diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/libs/c-ares | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/c-ares')
41 files changed, 4312 insertions, 4312 deletions
diff --git a/contrib/libs/c-ares/CHANGES b/contrib/libs/c-ares/CHANGES index f6652caaa0..8b910b7737 100644 --- a/contrib/libs/c-ares/CHANGES +++ b/contrib/libs/c-ares/CHANGES @@ -1,559 +1,559 @@ Changelog for the c-ares project. Generated with git2changes.pl -Version 1.16.1 (11 May 2020) - -Brad House (11 May 2020) -- c-ares 1.16.1 release prep - -- update travis to use xcode11.4 - -- Prevent possible double-free in ares_getaddrinfo() if ares_destroy() is called - - In the event that ares_destroy() is called prior to ares_getaddrinfo() completing, - it would result in an invalid read and double-free due to calling end_hquery() twice. - - Reported By: Jann Horn @ Google Project Zero - -GitHub (30 Apr 2020) -- [shelley vohr brought this change] - - fix: windows UNICODE incompatibilities with ares_getaddrinfo (#328) - - Fixes the following compatibility issues: - * Use RegQueryValueExA instead of RegQueryValueEx - * Use ExpandEnvironmentStringsA instead of ExpandEnvironmentStrings - * Use RegOpenKeyExA instead of RegOpenKeyExA - * Use GetWindowsDirectoryA instead of GetWindowsDirectoryA - - Fix By: Shelley Vohr (@codebytere) - Closes: #327 - -Brad House (13 Apr 2020) -- travis: CloudFlare does not allow T_ANY requests, so live tests that use it fail. Disable. - -- travis: bump macos image to the latest - -- cast-align warnings are false for struct sockaddr, silence - - Create a macro to silence false cast-align warnings when casting - struct sockaddr * to struct sockaddr_in * and struct sockaddr_in6 *. - - Fix By: Brad House (@bradh352) - -- MacOS: Enable libresolv support for retrieving DNS servers like iOS does. - -GitHub (10 Apr 2020) -- [Dmitry Igrishin brought this change] - - CMake: Populate the INCLUDE_DIRECTORIES property of installed targets (#323) - - Populate the INCLUDE_DIRECTORIES property of installed targets - - Fix By: Dmitry Igrishin (@dmitigr) - -Brad House (10 Apr 2020) -- travis: make valgrind use cmake for tests - -- dont try to use libtool to run valgrind - -- valgrind requires libtool installed to wrap tests - -- scan build 7 - -- fix travis live test - -- add debug for travis - -- try without sudo - -- attempt to modernize travis build environment - -GitHub (6 Apr 2020) -- [Teemu R brought this change] - - Allow TXT records on CHAOS qclass (#321) - - Some DNS servers intentionally "misuse" the obsoleted CHAOS (CH) qclass to provide things like `version.bind`, `version.server`, `authors.bind`, `hostname.bind` and `id.server`. - - C-ares was not allowing such use cases. - - Fix By: Teemu R. (@rytilahti) - -Brad House (5 Apr 2020) -- Remove warnings from ares_getaddrinfo.3 man page - - As reported in #319, non-standard macros of .IN were used. - Replace with .RS/.RE. - - Fixes: #319 - Fix By: Brad House (@bradh352) - -- ares_getaddrinfo man page render better for man2html - -- update man pages to render better for man2html - -Version 1.16.0 (12 Mar 2020) - -Brad House (12 Mar 2020) -- 1.16.0 release notes draft - -- attempt to fix double-free introduced in e0517f9 - -GitHub (12 Mar 2020) -- [David Drysdale brought this change] - - test: fuzzer input triggering double free (#315) - - OSS-Fuzz has reported a double-free with the fuzzer input file - included here; run with: - ./test/aresfuzz test/fuzzinput/clusterfuzz-5637790584012800 - - Bisecting the failure points to commit e0517f97d988 ("Parse SOA records - from ns_t_any response (#103)") - -- [Brad House brought this change] - - CMake: Install Manpages (#314) - - CMake wasn't installing manpages. - - Fixes #297 - Fix By: Brad House (@bradh352) - -- [Brad House brought this change] - - Enable cmake tests for AppVeyor (#313) - - Tests require linking against the static library on Windows otherwise the symbols are not exported for internals being tested. - - Fix By: Brad House (@bradh352) - -Brad House (11 Mar 2020) -- Add AppVeyor badge - -- bump c-ares version to 1.16.0. test AppVeyor integration. - -GitHub (11 Mar 2020) -- [Brad House brought this change] - - replace all usages of inet_addr() with ares_inet_pton() which is more proper (#312) - - Replace usage of inet_addr() with ares_inet_pton() which is more appropriate and fixes issues with legitimate addresses like 255.255.255.0. IPv6 already used this. - - Fixes #309 - Fix By: Brad House (@bradh352) - -- [Brad House brought this change] - - CMake: Generate WinPDB files during build (#311) - - Build and Install PDB (Windows Debug Symbol) files if supported by underlying system. - - Also update AppVeyor to test cmake builds. - - Fixes #245 - Fix By: Piotr Pietraszkiewicz (@ppietrasa) and Brad House (@bradh352) - -- [Brad House brought this change] - - CMake: Rework library function checking (#310) - - CHECK_LIBRARY_EXISTS(), while it takes a function name, does not actually verify the function exists in the library being evaluated. Instead, if the function is found in any dependent library, and the referenced library also exists, it returns true. This is not desirable. - - Wrap with a Macro to change the behavior. - - Fixes: #307 - Fix By: Brad House (@bradh352) - -- [Dron Rathore brought this change] - - Parse SOA records from ns_t_any response (#103) - - Added the capability of parsing SOA record from a response buffer of ns_t_any type query, this implementation doesn't interfere with existing T_SOA query's response as that too is treated as a list of records. The function returns ARES_EBADRESP if no SOA record is found(as per RFC). - - The basic idea of sticking to RFC that a ns_t_any too should return an SOA record is something open for discussion but I have kept the functionality intact as it was previously i.e the function returns ARES_EBADRESP if it doesn't find a SOA record regardless of which response it is parsing i.e. T_SOA or T_ANY. - - Note that asking for T_ANY is generally a bad idea: - - https://blog.cloudflare.com/what-happened-next-the-deprecation-of-any/ - - https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any - - Bug: #102 - Fix By: Dron Rathore (@DronRathore) - -- [Stephen Bryant brought this change] - - Added CPack functionality for generating RPM or DEB packages (#283) - - Added CPack functionality for generating RPM or DEB packages - - ie: run `cpack -G RPM` (or "DEB") after building with CMake. - - The current configuration creates 3 separate packages for the shared library, - the development files and the tools. - - Fix By: Stephen Bryant (@bf-bryants) - -- [tjwalton brought this change] - - ares_gethostbyname: Return ENODATA if no valid A or AAAA record found (#304) - - ares_gethostbyname() was returning ESUCCESS when no A or AAAA record was found but a CNAME pointing nowhere was present. ENODATA should be returned instead, however the hosts pointer will still be present to provide the alias list. - - * Return ENODATA if no valid A or AAAA record found - * Fix and update test ParseAReplyNoData. - * Add test for new ENODATA behaviour in ares_gethostbyname. - - Fixes Bug #303 - Fix By: @tjwalton - -- [Michal Rostecki brought this change] - - test: Separate live tests from SetServers* tests (#299) - - Before this change, SetServers, SetServersPorts and SetServersCSV - contained test cases trying to make DNS queries with the google.com - hostname, which requires Internet connectivity. Tests with that - requirement should be defined in the ares-test-live.cc file and contain - "Live" prefix to filter them out with `--gtest_filter=-*.Live*` on - machines without Internet connectivity. - - Fix By: Michal Rostecki (@mrostecki) - -- [Adam Majer brought this change] - - Only count valid addresses when response parsing (#302) - - When ares_parse_a_reply or ares_parse_aaaa_reply is called in case - where another AAAA and A responses exist, the resulting ares_addrttl - count is invalid and the structure points to gibberish. - - This is a regression since 1.15. - - Issue: https://github.com/c-ares/c-ares/issues/300 - Fix By: Adam Majer (@AdamMajer) - -Brad House (24 Dec 2019) -- [Kyle Edwards brought this change] - - CMake: Provide c-ares version in package export file (#296) - - The CMake package export file should provide version information. - - Fix By: Kyle Edwards (@KyleFromKitware) - -- [Ben Noordhuis brought this change] - - Accept invalid /etc/resolv.conf lookup values, ability to build container tests (#274) - - * Add CARES_BUILD_CONTAINER_TESTS CMake option to add ability to build the Linux-only containerized tests. - * Accept invalid /etc/resolv.conf lookup values - - Before this commit invalid `lookup` values resulted in c-ares not using - any lookups without any clear indication why. After this commit it uses - the default "fb". - - Fix By: Ben Noordhuis (@bnoordhuis) - -- [Christian Ammer brought this change] - - Parallel A and AAAA lookups in `ares_getaddrinfo` (#290) - - A and AAAA lookups for ares_getaddrinfo() are now performed in parallel. - - For this change `ares_search` was removed from `ares_getaddrinfo`. - Instead `ares_query` in combination with `next_dns_lookup` are - doing the suffix search. - - Adding support for `.onion` addresses which are tested by - `TEST_F(DefaultChannelTest, GetAddrinfoOnionDomain)` - - Fix By: Christian Ammer (@ChristianAmmer) - -- [Vy Nguyen brought this change] - - Move variables into the block where it is used to avoid unused-vars (#281) - - Warning uncovered with [-Werror, -Wunused-variables] - - Fix By: Vy Nguyen (@oontvoo) - -- [Vy Nguyen brought this change] - - Rename local macros to avoid conflicting with system ones and remove unsed variables. (Otherwise code will break once compiled with [-Werror,-Wmacro-redefined,-Wunused-variable] ) (#280) - - Fix new getaddrinfo code to not redefine macros on some systems. - - Fix By: Vy Nguyen (@oontvoo) - -- [Egor Pugin brought this change] - - [ares_getenv] Return NULL in all cases. (#279) - - if ares_getenv is defined, it must return a value on all platforms. - - Fix By: Egor Pugin (@egorpugin) - -- [Abhishek Arya brought this change] - - Add OSS-Fuzz fuzzing badge (#278) - - Adds based on instructions at - https://google.github.io/oss-fuzz/getting-started/new-project-guide/#status-badge - - Patch By: Abhishek Arya (@inferno-chromium) - -- [Peter Eisentraut brought this change] - - ares_init_options.3: Fix layout (#275) - - 7e6af8e inserted the documentation of resolvconf_path in the middle of - the item for ednspsz, leading to broken layout. Fix that. - - Fix By: Peter Eisentraut (@petere) - -- [Gregor Jasny brought this change] - - manpages: Fix typos detected by lintian (#269) - - - Fix By: Gregor Jasny (@gjasny) - -- [lifenjoiner brought this change] - - keep command line usage up to date (#256) - - adig and ahost built-in help did not match args taken. - - Fix-By: @lifenjoiner - -- [Dan Noé brought this change] - - ares-test.cc: Handle nullptr in AddrInfo ostream. (#268) - - The const AddrInfo& argument to operator<< overload for AddrInfo can be - a nullptr unique_ptr. Handle this explicitly by printing {nullptr} if - the rest of the function cannot be safely executed. - - Fix-by: Dan Noé <dpn@google.com> - -- [Dan Noé brought this change] - - Add missing limits.h include from ares_getaddrinfo.c (#267) - - This files references INT_MAX, but does not include limits.h. This can - cause a build failure on some platforms. Include limits.h if we have it. - - Fix-by: Dan Noé <dpn@google.com> - -- [Andrew Selivanov brought this change] - - fix fuzzer docs and add missing getaddrinfo docs (#265) - - There is a fix for a bit outdated clang fuzzer docs and ares_getaddrinfo docs. - - Fix By: Andrew Selivanov (@ki11roy) - -- [Andrew Selivanov brought this change] - - Fix leak and crash in ares_parse_a/aaaa_reply (#264) - - * fix leak if naddress of particular type found - * fix segfault when wanted ttls count lesser than count of result records - * add fuzzer input files that trigger problems (from #263) - - Reported-By: David Drysdale (@daviddrysdale) - Fix-By: Andrew Selivanov (@ki11roy) - -- [Andrew Selivanov brought this change] - - fix segfault when parsing wrong type of record (#262) - - Fixes segfault when trying to ares_parse_aaaa with AF_INET and vise versa. - - Fix By: Andrew Selivanov (@ki11roy) - -- work around mingw compile failure - -- c++ requires explicit casts - -- support EnvValue on Windows by implementing setenv/unsetenv - -- [Andrew Selivanov brought this change] - - getaddrinfo enhancements (#257) - - * Service support has been added to getaddrinfo. - * ares_parse_a/aaaa_record now share code with the addrinfo parser. - * Private ares_addrinfo structure with useful extensions such as ttls (including cname ttls), - as well as the ability to list multiple cnames in chain of lookups - - Work By: Andrew Selivanov @ki11roy - -- [Andrew Selivanov brought this change] - - fix ares__sortaddrinfo, use wrappers for sock_funcs (#258) - - Some socket functions weren't exposed for use by other areas of the library. Expose - those and make use of them in ares__sortaddrinfo(). - - Fix By: Andrew Selivanov (@ki11roy) - -- Fix c89 compilation support broken by .onion rejection changes - - Move .onion check lower after all variables have been declared. - - Bug: #246 - -- [kedixa brought this change] - - getaddrinfo: callback must be called on bad domain (#249) - - Due to an order of incrementing the remaining queries and calling ares_query, on a bad domain - the registered callback wouldn't be called. - - Bug: #248 - Fixed-By: @kedixa - -- [Darrin W. Cullop brought this change] - - Windows ARM/ARM64 requires AdvApi32 (#252) - - Fix link issues caused by missing library that appears to only be required on ARM (though - docs don't list this restriction). Doesn't hurt to require it everywhere. - - Bug: #251 - Fixed-By: Darrin Cullop (@dwcullop) - -- [kedixa brought this change] - - getaddrinfo: avoid infinite loop in case of NXDOMAIN(#240) (#242) - - There are two possible causes for infinite loops fo NXDOMAIN, based on how many dots are in the domain name (one for < ARES_OPT_NDOTS and one for >= ARES_OPT_NDOTS), where it will repeat the same query over and over as the hquery->next_domain doesn't increment. - - Fix By: @kedixa - -- Portability fix for ares__sortaddrinfo() - - replace uint32_t with unsigned int and socklen_t with ares_socklen_t - - By: Brad House - -- [Khaidi Chu brought this change] - - fix: init bufp before reject .onion to make it can be free correctly (#241) - - When querying a .onion domain, it returns directly without setting bufp to NULL. A subsequent free() that occurs can cause a segmentation fault. - - Fix By: Khaidi Chu (@XadillaX) - -- [Andrew Selivanov brought this change] - - Add ares__sortaddrinfo() to support getaddrinfo() sorted results (#239) - - This is a port of RFC 6724 compliant sorting function from Android Bionic project: - https://android.googlesource.com/platform/bionic/+/e919b116d35aa7deb24ddece69c491e24c3b0d6f/libc/netbsd/net/getaddrinfo.c - - The latest version is essentially the same, except two additional parameters to test connection with (mark/uid): - https://android.googlesource.com/platform/bionic/+/master/libc/dns/net/getaddrinfo.c - - Please note that even that version has some restrictions. It doesn't support some rules from RFC 6724: - - Rule 3 (Avoid deprecated addresses) - Rule 4 (Prefer home addresses) - Rule 7 (Prefer native transport) - - Submitted By: Andrew Selivanov (@ki11roy) - -- [Christian Ammer brought this change] - - Increase portability of `ares-test-mock-ai.cc` (#235) - - * using portable ares_inet_pton and updated includes in ares-test-mock-ai - * forgot to remove deleted ares-test-ai.cc in Makefile.inc - - Fix By: Christian Ammer (@ChristianAmmer) - -- [Fabrice Fontaine brought this change] - - m4/xc-cc-check.m4: use XC_CHECK_BUILD_FLAGS (#236) - - Use XC_CHECK_BUILD_FLAGS instead of XC_CHECK_USER_FLAGS. - Otherwise it complains of CPPFLAGS in CFLAGS. - [Retrieved from: - https://git.buildroot.net/buildroot/tree/package/c-ares/0001-use_check_build_instead_of_check_user.patch] - - Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar> - Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com> - Submitted by: Fabrice Fontaine - -- [Christian Ammer brought this change] - - Bugfix for `ares_getaddrinfo` and additional unit tests (#234) - - This PullRequest fixes a bug in the function add_to_addrinfo which task is to add new addrinfo items to the ai_next linked list. Also additional unit tests for testing ares_getaddrinfo will be added: - - Additional mock server test classes (ares-test-mock-ai.cc): - MockTCPChannelTestAI - MockExtraOptsTestAI - MockNoCheckRespChannelTestAI - MockEDNSChannelTestAI - RotateMultiMockTestAI - NoRotateMultiMockTestAI - - Additional live tests (ares-test-live-ai.cc): - LiveGetHostByNameV4 - LiveGetHostByNameV6 - LiveGetHostByNameV4AndV6 - - Fix By: Christian Ammer (@ChristianAmmer) - -- [Christian Ammer brought this change] - - Remaining queries counter fix, additional unit tests for `ares_getaddrinfo` (#233) - - Remaining queries counter fix, added tests (ParallelLookups, - SearchDomains, SearchDomainsServFailOnAAAA). Removed unnecessary - if and commented code in test. - - Fix By: Christian Ammer (@ChristianAmmer) - -- [Christian Ammer brought this change] - - Add initial implementation for ares_getaddrinfo (#112) - - Initial implementation for ares_getaddrinfo(). It is NOT compliant with RFC6724, though - it is expected to come closer to conformance prior to the next release. - - Features not supported include sorted addresses and honoring of service and hints - parameters. - - Implementation by: Christian Ammer (@ChristianAmmer) - -- [Ben Noordhuis brought this change] - - test: fix bad expectation in ipv6 localhost test (#227) - - The LiveGetLocalhostByAddrV6 test expected to see "localhost" in the - result when doing an address-to-name lookup for ::1 but on my system - that resolves to "ip6-loopback" because of this stanza in /etc/hosts: - - $ grep ^::1 /etc/hosts - ::1 ip6-localhost ip6-loopback - - Fix By: Ben Noordhuis (@bnoordhuis) - Bug: #85 - -- [Ben Noordhuis brought this change] - - ares_version.h: bump version (#230) - - Version change not committed from maketgz.sh - - Bug: #229 - -Daniel Stenberg (24 Oct 2018) -- ares_library_init_android.3: minor syntax edits, fixed AVAILABILITY - +Version 1.16.1 (11 May 2020) + +Brad House (11 May 2020) +- c-ares 1.16.1 release prep + +- update travis to use xcode11.4 + +- Prevent possible double-free in ares_getaddrinfo() if ares_destroy() is called + + In the event that ares_destroy() is called prior to ares_getaddrinfo() completing, + it would result in an invalid read and double-free due to calling end_hquery() twice. + + Reported By: Jann Horn @ Google Project Zero + +GitHub (30 Apr 2020) +- [shelley vohr brought this change] + + fix: windows UNICODE incompatibilities with ares_getaddrinfo (#328) + + Fixes the following compatibility issues: + * Use RegQueryValueExA instead of RegQueryValueEx + * Use ExpandEnvironmentStringsA instead of ExpandEnvironmentStrings + * Use RegOpenKeyExA instead of RegOpenKeyExA + * Use GetWindowsDirectoryA instead of GetWindowsDirectoryA + + Fix By: Shelley Vohr (@codebytere) + Closes: #327 + +Brad House (13 Apr 2020) +- travis: CloudFlare does not allow T_ANY requests, so live tests that use it fail. Disable. + +- travis: bump macos image to the latest + +- cast-align warnings are false for struct sockaddr, silence + + Create a macro to silence false cast-align warnings when casting + struct sockaddr * to struct sockaddr_in * and struct sockaddr_in6 *. + + Fix By: Brad House (@bradh352) + +- MacOS: Enable libresolv support for retrieving DNS servers like iOS does. + +GitHub (10 Apr 2020) +- [Dmitry Igrishin brought this change] + + CMake: Populate the INCLUDE_DIRECTORIES property of installed targets (#323) + + Populate the INCLUDE_DIRECTORIES property of installed targets + + Fix By: Dmitry Igrishin (@dmitigr) + +Brad House (10 Apr 2020) +- travis: make valgrind use cmake for tests + +- dont try to use libtool to run valgrind + +- valgrind requires libtool installed to wrap tests + +- scan build 7 + +- fix travis live test + +- add debug for travis + +- try without sudo + +- attempt to modernize travis build environment + +GitHub (6 Apr 2020) +- [Teemu R brought this change] + + Allow TXT records on CHAOS qclass (#321) + + Some DNS servers intentionally "misuse" the obsoleted CHAOS (CH) qclass to provide things like `version.bind`, `version.server`, `authors.bind`, `hostname.bind` and `id.server`. + + C-ares was not allowing such use cases. + + Fix By: Teemu R. (@rytilahti) + +Brad House (5 Apr 2020) +- Remove warnings from ares_getaddrinfo.3 man page + + As reported in #319, non-standard macros of .IN were used. + Replace with .RS/.RE. + + Fixes: #319 + Fix By: Brad House (@bradh352) + +- ares_getaddrinfo man page render better for man2html + +- update man pages to render better for man2html + +Version 1.16.0 (12 Mar 2020) + +Brad House (12 Mar 2020) +- 1.16.0 release notes draft + +- attempt to fix double-free introduced in e0517f9 + +GitHub (12 Mar 2020) +- [David Drysdale brought this change] + + test: fuzzer input triggering double free (#315) + + OSS-Fuzz has reported a double-free with the fuzzer input file + included here; run with: + ./test/aresfuzz test/fuzzinput/clusterfuzz-5637790584012800 + + Bisecting the failure points to commit e0517f97d988 ("Parse SOA records + from ns_t_any response (#103)") + +- [Brad House brought this change] + + CMake: Install Manpages (#314) + + CMake wasn't installing manpages. + + Fixes #297 + Fix By: Brad House (@bradh352) + +- [Brad House brought this change] + + Enable cmake tests for AppVeyor (#313) + + Tests require linking against the static library on Windows otherwise the symbols are not exported for internals being tested. + + Fix By: Brad House (@bradh352) + +Brad House (11 Mar 2020) +- Add AppVeyor badge + +- bump c-ares version to 1.16.0. test AppVeyor integration. + +GitHub (11 Mar 2020) +- [Brad House brought this change] + + replace all usages of inet_addr() with ares_inet_pton() which is more proper (#312) + + Replace usage of inet_addr() with ares_inet_pton() which is more appropriate and fixes issues with legitimate addresses like 255.255.255.0. IPv6 already used this. + + Fixes #309 + Fix By: Brad House (@bradh352) + +- [Brad House brought this change] + + CMake: Generate WinPDB files during build (#311) + + Build and Install PDB (Windows Debug Symbol) files if supported by underlying system. + + Also update AppVeyor to test cmake builds. + + Fixes #245 + Fix By: Piotr Pietraszkiewicz (@ppietrasa) and Brad House (@bradh352) + +- [Brad House brought this change] + + CMake: Rework library function checking (#310) + + CHECK_LIBRARY_EXISTS(), while it takes a function name, does not actually verify the function exists in the library being evaluated. Instead, if the function is found in any dependent library, and the referenced library also exists, it returns true. This is not desirable. + + Wrap with a Macro to change the behavior. + + Fixes: #307 + Fix By: Brad House (@bradh352) + +- [Dron Rathore brought this change] + + Parse SOA records from ns_t_any response (#103) + + Added the capability of parsing SOA record from a response buffer of ns_t_any type query, this implementation doesn't interfere with existing T_SOA query's response as that too is treated as a list of records. The function returns ARES_EBADRESP if no SOA record is found(as per RFC). + + The basic idea of sticking to RFC that a ns_t_any too should return an SOA record is something open for discussion but I have kept the functionality intact as it was previously i.e the function returns ARES_EBADRESP if it doesn't find a SOA record regardless of which response it is parsing i.e. T_SOA or T_ANY. + + Note that asking for T_ANY is generally a bad idea: + - https://blog.cloudflare.com/what-happened-next-the-deprecation-of-any/ + - https://tools.ietf.org/html/draft-ietf-dnsop-refuse-any + + Bug: #102 + Fix By: Dron Rathore (@DronRathore) + +- [Stephen Bryant brought this change] + + Added CPack functionality for generating RPM or DEB packages (#283) + + Added CPack functionality for generating RPM or DEB packages + + ie: run `cpack -G RPM` (or "DEB") after building with CMake. + + The current configuration creates 3 separate packages for the shared library, + the development files and the tools. + + Fix By: Stephen Bryant (@bf-bryants) + +- [tjwalton brought this change] + + ares_gethostbyname: Return ENODATA if no valid A or AAAA record found (#304) + + ares_gethostbyname() was returning ESUCCESS when no A or AAAA record was found but a CNAME pointing nowhere was present. ENODATA should be returned instead, however the hosts pointer will still be present to provide the alias list. + + * Return ENODATA if no valid A or AAAA record found + * Fix and update test ParseAReplyNoData. + * Add test for new ENODATA behaviour in ares_gethostbyname. + + Fixes Bug #303 + Fix By: @tjwalton + +- [Michal Rostecki brought this change] + + test: Separate live tests from SetServers* tests (#299) + + Before this change, SetServers, SetServersPorts and SetServersCSV + contained test cases trying to make DNS queries with the google.com + hostname, which requires Internet connectivity. Tests with that + requirement should be defined in the ares-test-live.cc file and contain + "Live" prefix to filter them out with `--gtest_filter=-*.Live*` on + machines without Internet connectivity. + + Fix By: Michal Rostecki (@mrostecki) + +- [Adam Majer brought this change] + + Only count valid addresses when response parsing (#302) + + When ares_parse_a_reply or ares_parse_aaaa_reply is called in case + where another AAAA and A responses exist, the resulting ares_addrttl + count is invalid and the structure points to gibberish. + + This is a regression since 1.15. + + Issue: https://github.com/c-ares/c-ares/issues/300 + Fix By: Adam Majer (@AdamMajer) + +Brad House (24 Dec 2019) +- [Kyle Edwards brought this change] + + CMake: Provide c-ares version in package export file (#296) + + The CMake package export file should provide version information. + + Fix By: Kyle Edwards (@KyleFromKitware) + +- [Ben Noordhuis brought this change] + + Accept invalid /etc/resolv.conf lookup values, ability to build container tests (#274) + + * Add CARES_BUILD_CONTAINER_TESTS CMake option to add ability to build the Linux-only containerized tests. + * Accept invalid /etc/resolv.conf lookup values + + Before this commit invalid `lookup` values resulted in c-ares not using + any lookups without any clear indication why. After this commit it uses + the default "fb". + + Fix By: Ben Noordhuis (@bnoordhuis) + +- [Christian Ammer brought this change] + + Parallel A and AAAA lookups in `ares_getaddrinfo` (#290) + + A and AAAA lookups for ares_getaddrinfo() are now performed in parallel. + + For this change `ares_search` was removed from `ares_getaddrinfo`. + Instead `ares_query` in combination with `next_dns_lookup` are + doing the suffix search. + + Adding support for `.onion` addresses which are tested by + `TEST_F(DefaultChannelTest, GetAddrinfoOnionDomain)` + + Fix By: Christian Ammer (@ChristianAmmer) + +- [Vy Nguyen brought this change] + + Move variables into the block where it is used to avoid unused-vars (#281) + + Warning uncovered with [-Werror, -Wunused-variables] + + Fix By: Vy Nguyen (@oontvoo) + +- [Vy Nguyen brought this change] + + Rename local macros to avoid conflicting with system ones and remove unsed variables. (Otherwise code will break once compiled with [-Werror,-Wmacro-redefined,-Wunused-variable] ) (#280) + + Fix new getaddrinfo code to not redefine macros on some systems. + + Fix By: Vy Nguyen (@oontvoo) + +- [Egor Pugin brought this change] + + [ares_getenv] Return NULL in all cases. (#279) + + if ares_getenv is defined, it must return a value on all platforms. + + Fix By: Egor Pugin (@egorpugin) + +- [Abhishek Arya brought this change] + + Add OSS-Fuzz fuzzing badge (#278) + + Adds based on instructions at + https://google.github.io/oss-fuzz/getting-started/new-project-guide/#status-badge + + Patch By: Abhishek Arya (@inferno-chromium) + +- [Peter Eisentraut brought this change] + + ares_init_options.3: Fix layout (#275) + + 7e6af8e inserted the documentation of resolvconf_path in the middle of + the item for ednspsz, leading to broken layout. Fix that. + + Fix By: Peter Eisentraut (@petere) + +- [Gregor Jasny brought this change] + + manpages: Fix typos detected by lintian (#269) + + + Fix By: Gregor Jasny (@gjasny) + +- [lifenjoiner brought this change] + + keep command line usage up to date (#256) + + adig and ahost built-in help did not match args taken. + + Fix-By: @lifenjoiner + +- [Dan Noé brought this change] + + ares-test.cc: Handle nullptr in AddrInfo ostream. (#268) + + The const AddrInfo& argument to operator<< overload for AddrInfo can be + a nullptr unique_ptr. Handle this explicitly by printing {nullptr} if + the rest of the function cannot be safely executed. + + Fix-by: Dan Noé <dpn@google.com> + +- [Dan Noé brought this change] + + Add missing limits.h include from ares_getaddrinfo.c (#267) + + This files references INT_MAX, but does not include limits.h. This can + cause a build failure on some platforms. Include limits.h if we have it. + + Fix-by: Dan Noé <dpn@google.com> + +- [Andrew Selivanov brought this change] + + fix fuzzer docs and add missing getaddrinfo docs (#265) + + There is a fix for a bit outdated clang fuzzer docs and ares_getaddrinfo docs. + + Fix By: Andrew Selivanov (@ki11roy) + +- [Andrew Selivanov brought this change] + + Fix leak and crash in ares_parse_a/aaaa_reply (#264) + + * fix leak if naddress of particular type found + * fix segfault when wanted ttls count lesser than count of result records + * add fuzzer input files that trigger problems (from #263) + + Reported-By: David Drysdale (@daviddrysdale) + Fix-By: Andrew Selivanov (@ki11roy) + +- [Andrew Selivanov brought this change] + + fix segfault when parsing wrong type of record (#262) + + Fixes segfault when trying to ares_parse_aaaa with AF_INET and vise versa. + + Fix By: Andrew Selivanov (@ki11roy) + +- work around mingw compile failure + +- c++ requires explicit casts + +- support EnvValue on Windows by implementing setenv/unsetenv + +- [Andrew Selivanov brought this change] + + getaddrinfo enhancements (#257) + + * Service support has been added to getaddrinfo. + * ares_parse_a/aaaa_record now share code with the addrinfo parser. + * Private ares_addrinfo structure with useful extensions such as ttls (including cname ttls), + as well as the ability to list multiple cnames in chain of lookups + + Work By: Andrew Selivanov @ki11roy + +- [Andrew Selivanov brought this change] + + fix ares__sortaddrinfo, use wrappers for sock_funcs (#258) + + Some socket functions weren't exposed for use by other areas of the library. Expose + those and make use of them in ares__sortaddrinfo(). + + Fix By: Andrew Selivanov (@ki11roy) + +- Fix c89 compilation support broken by .onion rejection changes + + Move .onion check lower after all variables have been declared. + + Bug: #246 + +- [kedixa brought this change] + + getaddrinfo: callback must be called on bad domain (#249) + + Due to an order of incrementing the remaining queries and calling ares_query, on a bad domain + the registered callback wouldn't be called. + + Bug: #248 + Fixed-By: @kedixa + +- [Darrin W. Cullop brought this change] + + Windows ARM/ARM64 requires AdvApi32 (#252) + + Fix link issues caused by missing library that appears to only be required on ARM (though + docs don't list this restriction). Doesn't hurt to require it everywhere. + + Bug: #251 + Fixed-By: Darrin Cullop (@dwcullop) + +- [kedixa brought this change] + + getaddrinfo: avoid infinite loop in case of NXDOMAIN(#240) (#242) + + There are two possible causes for infinite loops fo NXDOMAIN, based on how many dots are in the domain name (one for < ARES_OPT_NDOTS and one for >= ARES_OPT_NDOTS), where it will repeat the same query over and over as the hquery->next_domain doesn't increment. + + Fix By: @kedixa + +- Portability fix for ares__sortaddrinfo() + + replace uint32_t with unsigned int and socklen_t with ares_socklen_t + + By: Brad House + +- [Khaidi Chu brought this change] + + fix: init bufp before reject .onion to make it can be free correctly (#241) + + When querying a .onion domain, it returns directly without setting bufp to NULL. A subsequent free() that occurs can cause a segmentation fault. + + Fix By: Khaidi Chu (@XadillaX) + +- [Andrew Selivanov brought this change] + + Add ares__sortaddrinfo() to support getaddrinfo() sorted results (#239) + + This is a port of RFC 6724 compliant sorting function from Android Bionic project: + https://android.googlesource.com/platform/bionic/+/e919b116d35aa7deb24ddece69c491e24c3b0d6f/libc/netbsd/net/getaddrinfo.c + + The latest version is essentially the same, except two additional parameters to test connection with (mark/uid): + https://android.googlesource.com/platform/bionic/+/master/libc/dns/net/getaddrinfo.c + + Please note that even that version has some restrictions. It doesn't support some rules from RFC 6724: + + Rule 3 (Avoid deprecated addresses) + Rule 4 (Prefer home addresses) + Rule 7 (Prefer native transport) + + Submitted By: Andrew Selivanov (@ki11roy) + +- [Christian Ammer brought this change] + + Increase portability of `ares-test-mock-ai.cc` (#235) + + * using portable ares_inet_pton and updated includes in ares-test-mock-ai + * forgot to remove deleted ares-test-ai.cc in Makefile.inc + + Fix By: Christian Ammer (@ChristianAmmer) + +- [Fabrice Fontaine brought this change] + + m4/xc-cc-check.m4: use XC_CHECK_BUILD_FLAGS (#236) + + Use XC_CHECK_BUILD_FLAGS instead of XC_CHECK_USER_FLAGS. + Otherwise it complains of CPPFLAGS in CFLAGS. + [Retrieved from: + https://git.buildroot.net/buildroot/tree/package/c-ares/0001-use_check_build_instead_of_check_user.patch] + + Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar> + Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com> + Submitted by: Fabrice Fontaine + +- [Christian Ammer brought this change] + + Bugfix for `ares_getaddrinfo` and additional unit tests (#234) + + This PullRequest fixes a bug in the function add_to_addrinfo which task is to add new addrinfo items to the ai_next linked list. Also additional unit tests for testing ares_getaddrinfo will be added: + + Additional mock server test classes (ares-test-mock-ai.cc): + MockTCPChannelTestAI + MockExtraOptsTestAI + MockNoCheckRespChannelTestAI + MockEDNSChannelTestAI + RotateMultiMockTestAI + NoRotateMultiMockTestAI + + Additional live tests (ares-test-live-ai.cc): + LiveGetHostByNameV4 + LiveGetHostByNameV6 + LiveGetHostByNameV4AndV6 + + Fix By: Christian Ammer (@ChristianAmmer) + +- [Christian Ammer brought this change] + + Remaining queries counter fix, additional unit tests for `ares_getaddrinfo` (#233) + + Remaining queries counter fix, added tests (ParallelLookups, + SearchDomains, SearchDomainsServFailOnAAAA). Removed unnecessary + if and commented code in test. + + Fix By: Christian Ammer (@ChristianAmmer) + +- [Christian Ammer brought this change] + + Add initial implementation for ares_getaddrinfo (#112) + + Initial implementation for ares_getaddrinfo(). It is NOT compliant with RFC6724, though + it is expected to come closer to conformance prior to the next release. + + Features not supported include sorted addresses and honoring of service and hints + parameters. + + Implementation by: Christian Ammer (@ChristianAmmer) + +- [Ben Noordhuis brought this change] + + test: fix bad expectation in ipv6 localhost test (#227) + + The LiveGetLocalhostByAddrV6 test expected to see "localhost" in the + result when doing an address-to-name lookup for ::1 but on my system + that resolves to "ip6-loopback" because of this stanza in /etc/hosts: + + $ grep ^::1 /etc/hosts + ::1 ip6-localhost ip6-loopback + + Fix By: Ben Noordhuis (@bnoordhuis) + Bug: #85 + +- [Ben Noordhuis brought this change] + + ares_version.h: bump version (#230) + + Version change not committed from maketgz.sh + + Bug: #229 + +Daniel Stenberg (24 Oct 2018) +- ares_library_init_android.3: minor syntax edits, fixed AVAILABILITY + Version 1.15.0 (23 Oct 2018) Brad House (23 Oct 2018) diff --git a/contrib/libs/c-ares/README.md b/contrib/libs/c-ares/README.md index 148338f9e1..ef78c8e65b 100644 --- a/contrib/libs/c-ares/README.md +++ b/contrib/libs/c-ares/README.md @@ -2,10 +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/aevgc5914tm72pvs/branch/master?svg=true)](https://ci.appveyor.com/project/c-ares/c-ares/branch/master) +[![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) +[![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/contrib/libs/c-ares/RELEASE-NOTES b/contrib/libs/c-ares/RELEASE-NOTES index 7a9d75fe78..5caf0bb7ef 100644 --- a/contrib/libs/c-ares/RELEASE-NOTES +++ b/contrib/libs/c-ares/RELEASE-NOTES @@ -1,30 +1,30 @@ -c-ares version 1.16.1 - -Security: - o Prevent possible use-after-free and double-free in ares_getaddrinfo() if - ares_destroy() is called prior to ares_getaddrinfo() completing. Reported - by Jann Horn at Google Project Zero. +c-ares version 1.16.1 +Security: + o Prevent possible use-after-free and double-free in ares_getaddrinfo() if + ares_destroy() is called prior to ares_getaddrinfo() completing. Reported + by Jann Horn at Google Project Zero. + Changes: - o Allow TXT records on CHAOS qclass. Used for retriving things like - version.bind, version.server, authoris.bind, hostname.bind, and id.server. - [3] + o Allow TXT records on CHAOS qclass. Used for retriving things like + version.bind, version.server, authoris.bind, hostname.bind, and id.server. + [3] Bug fixes: - o Fix Windows Unicode incompatibilities with ares_getaddrinfo() [1] - o Silence false cast-align compiler warnings due to valid casts of - struct sockaddr to struct sockaddr_in and struct sockaddr_in6. - o MacOS should use libresolv for retrieving DNS servers, like iOS - o CMake build system should populate the INCLUDE_DIRECTORIES property of - installed targets [2] - o Correct macros in use for the ares_getaddrinfo.3 man page + o Fix Windows Unicode incompatibilities with ares_getaddrinfo() [1] + o Silence false cast-align compiler warnings due to valid casts of + struct sockaddr to struct sockaddr_in and struct sockaddr_in6. + o MacOS should use libresolv for retrieving DNS servers, like iOS + o CMake build system should populate the INCLUDE_DIRECTORIES property of + installed targets [2] + o Correct macros in use for the ares_getaddrinfo.3 man page Thanks go to these friendly people for their efforts and contributions: - Brad House (@bradh352), Daniel Stenberg (@bagder), Dmitry Igrishin (@dmitigr), - Jann Horn, Shelly Vohr, Teemu R (@rytilahti) - (6 contributors) + Brad House (@bradh352), Daniel Stenberg (@bagder), Dmitry Igrishin (@dmitigr), + Jann Horn, Shelly Vohr, Teemu R (@rytilahti) + (6 contributors) References to bug reports and discussions on issues: - [1] = https://github.com/c-ares/c-ares/pull/328 - [2] = https://github.com/c-ares/c-ares/pull/323 - [3] = https://github.com/c-ares/c-ares/pull/321 + [1] = https://github.com/c-ares/c-ares/pull/328 + [2] = https://github.com/c-ares/c-ares/pull/323 + [3] = https://github.com/c-ares/c-ares/pull/321 diff --git a/contrib/libs/c-ares/acountry.c b/contrib/libs/c-ares/acountry.c index c486824434..68f66fa16d 100644 --- a/contrib/libs/c-ares/acountry.c +++ b/contrib/libs/c-ares/acountry.c @@ -69,12 +69,12 @@ #define INADDR_NONE 0xffffffff #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)) - -static const char *usage = "acountry [-?hdv] {host|addr} ...\n"; +/* 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)) + +static const char *usage = "acountry [-?hdv] {host|addr} ...\n"; static const char nerd_fmt[] = "%u.%u.%u.%u.zz.countries.nerd.dk"; static const char *nerd_ver1 = nerd_fmt + 14; /* .countries.nerd.dk */ static const char *nerd_ver2 = nerd_fmt + 11; /* .zz.countries.nerd.dk */ @@ -238,7 +238,7 @@ static void callback(void *arg, int status, int timeouts, struct hostent *host) if (!cname) printf("Failed to get CNAME for %s\n", name); else - find_country_from_cname(cname, *(CARES_INADDR_CAST(struct in_addr *, host->h_addr))); + find_country_from_cname(cname, *(CARES_INADDR_CAST(struct in_addr *, host->h_addr))); } /* diff --git a/contrib/libs/c-ares/adig.c b/contrib/libs/c-ares/adig.c index 2d5cb8c876..2e97c0db3f 100644 --- a/contrib/libs/c-ares/adig.c +++ b/contrib/libs/c-ares/adig.c @@ -795,8 +795,8 @@ static const char *class_name(int dnsclass) static void usage(void) { - fprintf(stderr, "usage: adig [-h] [-d] [-f flag] [-s server] [-c class] " - "[-t type] [-T|U port] name ...\n"); + fprintf(stderr, "usage: adig [-h] [-d] [-f flag] [-s server] [-c class] " + "[-t type] [-T|U port] name ...\n"); exit(1); } diff --git a/contrib/libs/c-ares/ahost.c b/contrib/libs/c-ares/ahost.c index 89a7c14fcb..5748de9ae3 100644 --- a/contrib/libs/c-ares/ahost.c +++ b/contrib/libs/c-ares/ahost.c @@ -201,6 +201,6 @@ static void callback(void *arg, int status, int timeouts, struct hostent *host) static void usage(void) { - fprintf(stderr, "usage: ahost [-h] [-d] [-s {domain}] [-t {a|aaaa|u}] {host|addr} ...\n"); + fprintf(stderr, "usage: ahost [-h] [-d] [-s {domain}] [-t {a|aaaa|u}] {host|addr} ...\n"); exit(1); } diff --git a/contrib/libs/c-ares/ares.h b/contrib/libs/c-ares/ares.h index 3f8a6954d0..05abaa8fc2 100644 --- a/contrib/libs/c-ares/ares.h +++ b/contrib/libs/c-ares/ares.h @@ -135,9 +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 */ - +/* 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) @@ -197,8 +197,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) +#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) @@ -288,8 +288,8 @@ struct hostent; struct timeval; struct sockaddr; struct ares_channeldata; -struct ares_addrinfo; -struct ares_addrinfo_hints; +struct ares_addrinfo; +struct ares_addrinfo_hints; typedef struct ares_channeldata *ares_channel; @@ -318,11 +318,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); - +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, @@ -386,15 +386,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); - +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 @@ -591,44 +591,44 @@ struct ares_soa_reply { }; /* - * 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; -}; - -/* + * 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. ** Also, if addrttls is nonnull, put up to *naddrttls IPv4 addresses along with diff --git a/contrib/libs/c-ares/ares__close_sockets.c b/contrib/libs/c-ares/ares__close_sockets.c index 0477174e3e..b06668d2b7 100644 --- a/contrib/libs/c-ares/ares__close_sockets.c +++ b/contrib/libs/c-ares/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__close_socket(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__close_socket(channel, server->udp_socket); + ares__close_socket(channel, server->udp_socket); server->udp_socket = ARES_SOCKET_BAD; } } diff --git a/contrib/libs/c-ares/ares__get_hostent.c b/contrib/libs/c-ares/ares__get_hostent.c index 367f39037b..67203e5a25 100644 --- a/contrib/libs/c-ares/ares__get_hostent.c +++ b/contrib/libs/c-ares/ares__get_hostent.c @@ -138,7 +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)) { - if (ares_inet_pton(AF_INET, txtaddr, &addr.addrV4) > 0) + if (ares_inet_pton(AF_INET, txtaddr, &addr.addrV4) > 0) { /* Actual network address family and length. */ addr.family = AF_INET; diff --git a/contrib/libs/c-ares/ares__parse_into_addrinfo.c b/contrib/libs/c-ares/ares__parse_into_addrinfo.c index b0801632b4..51e88d0134 100644 --- a/contrib/libs/c-ares/ares__parse_into_addrinfo.c +++ b/contrib/libs/c-ares/ares__parse_into_addrinfo.c @@ -1,266 +1,266 @@ -/* Copyright (C) 2019 by Andrew Selivanov - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without - * fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting - * documentation, and that the name of M.I.T. not be used in - * advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" - * without express or implied warranty. - */ - -#include "ares_setup.h" - -#ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> -#endif -#ifdef HAVE_NETDB_H -# include <netdb.h> -#endif -#ifdef HAVE_ARPA_INET_H -# include <arpa/inet.h> -#endif -#ifdef HAVE_ARPA_NAMESER_H -# include <arpa/nameser.h> -#else -# include "nameser.h" -#endif -#ifdef HAVE_ARPA_NAMESER_COMPAT_H -# include <arpa/nameser_compat.h> -#endif - -#ifdef HAVE_STRINGS_H -# include <strings.h> -#endif - -#ifdef HAVE_LIMITS_H -# include <limits.h> -#endif - -#include "ares.h" -#include "ares_dns.h" -#include "ares_private.h" - -int ares__parse_into_addrinfo2(const unsigned char *abuf, - int alen, - char **question_hostname, - struct ares_addrinfo *ai) -{ - unsigned int qdcount, ancount; - int status, i, rr_type, rr_class, rr_len, rr_ttl; - int got_a = 0, got_aaaa = 0, got_cname = 0; - long len; - const unsigned char *aptr; - char *hostname, *rr_name = NULL, *rr_data; - struct ares_addrinfo_cname *cname, *cnames = NULL; - struct ares_addrinfo_node *node, *nodes = NULL; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - - *question_hostname = NULL; - - /* Give up if abuf doesn't have room for a header. */ - if (alen < HFIXEDSZ) - return ARES_EBADRESP; - - /* Fetch the question and answer count from the header. */ - qdcount = DNS_HEADER_QDCOUNT(abuf); - ancount = DNS_HEADER_ANCOUNT(abuf); - if (qdcount != 1) - return ARES_EBADRESP; - - - /* Expand the name from the question, and skip past the question. */ - aptr = abuf + HFIXEDSZ; - status = ares__expand_name_for_response(aptr, abuf, alen, question_hostname, &len); - if (status != ARES_SUCCESS) - return status; - if (aptr + len + QFIXEDSZ > abuf + alen) - { - return ARES_EBADRESP; - } - - hostname = *question_hostname; - - aptr += len + QFIXEDSZ; - - /* Examine each answer resource record (RR) in turn. */ - for (i = 0; i < (int)ancount; i++) - { - /* Decode the RR up to the data field. */ - status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len); - if (status != ARES_SUCCESS) - { - rr_name = NULL; - goto failed_stat; - } - - aptr += len; - if (aptr + RRFIXEDSZ > abuf + alen) - { - status = ARES_EBADRESP; - goto failed_stat; - } - rr_type = DNS_RR_TYPE(aptr); - rr_class = DNS_RR_CLASS(aptr); - rr_len = DNS_RR_LEN(aptr); - rr_ttl = DNS_RR_TTL(aptr); - aptr += RRFIXEDSZ; - if (aptr + rr_len > abuf + alen) - { - status = ARES_EBADRESP; - goto failed_stat; - } - - if (rr_class == C_IN && rr_type == T_A - && rr_len == sizeof(struct in_addr) - && strcasecmp(rr_name, hostname) == 0) - { - got_a = 1; - if (aptr + sizeof(struct in_addr) > abuf + alen) - { /* LCOV_EXCL_START: already checked above */ - status = ARES_EBADRESP; - goto failed_stat; - } /* LCOV_EXCL_STOP */ - - node = ares__append_addrinfo_node(&nodes); - if (!node) - { - status = ARES_ENOMEM; - goto failed_stat; - } - - sin = ares_malloc(sizeof(struct sockaddr_in)); - if (!sin) - { - status = ARES_ENOMEM; - goto failed_stat; - } - memset(sin, 0, sizeof(struct sockaddr_in)); - memcpy(&sin->sin_addr.s_addr, aptr, sizeof(struct in_addr)); - sin->sin_family = AF_INET; - - node->ai_addr = (struct sockaddr *)sin; - node->ai_family = AF_INET; - node->ai_addrlen = sizeof(struct sockaddr_in); - - node->ai_ttl = rr_ttl; - - status = ARES_SUCCESS; - } - else if (rr_class == C_IN && rr_type == T_AAAA - && rr_len == sizeof(struct ares_in6_addr) - && strcasecmp(rr_name, hostname) == 0) - { - got_aaaa = 1; - if (aptr + sizeof(struct ares_in6_addr) > abuf + alen) - { /* LCOV_EXCL_START: already checked above */ - status = ARES_EBADRESP; - goto failed_stat; - } /* LCOV_EXCL_STOP */ - - node = ares__append_addrinfo_node(&nodes); - if (!node) - { - status = ARES_ENOMEM; - goto failed_stat; - } - - sin6 = ares_malloc(sizeof(struct sockaddr_in6)); - if (!sin6) - { - status = ARES_ENOMEM; - goto failed_stat; - } - - memset(sin6, 0, sizeof(struct sockaddr_in6)); - memcpy(&sin6->sin6_addr.s6_addr, aptr, sizeof(struct ares_in6_addr)); - sin6->sin6_family = AF_INET6; - - node->ai_addr = (struct sockaddr *)sin6; - node->ai_family = AF_INET6; - node->ai_addrlen = sizeof(struct sockaddr_in6); - - node->ai_ttl = rr_ttl; - - status = ARES_SUCCESS; - } - - if (rr_class == C_IN && rr_type == T_CNAME) - { - got_cname = 1; - status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data, - &len); - if (status != ARES_SUCCESS) - { - goto failed_stat; - } - - /* Decode the RR data and replace the hostname with it. */ - /* SA: Seems wrong as it introduses order dependency. */ - hostname = rr_data; - - cname = ares__append_addrinfo_cname(&cnames); - if (!cname) - { - status = ARES_ENOMEM; - ares_free(rr_data); - goto failed_stat; - } - cname->ttl = rr_ttl; - cname->alias = rr_name; - cname->name = rr_data; - } - else - { - ares_free(rr_name); - } - - - aptr += rr_len; - if (aptr > abuf + alen) - { /* LCOV_EXCL_START: already checked above */ - status = ARES_EBADRESP; - goto failed_stat; - } /* LCOV_EXCL_STOP */ - } - - if (status == ARES_SUCCESS) - { - ares__addrinfo_cat_nodes(&ai->nodes, nodes); - if (got_cname) - { - ares__addrinfo_cat_cnames(&ai->cnames, cnames); - return status; - } - else if (got_a == 0 && got_aaaa == 0) - { - /* the check for naliases to be zero is to make sure CNAME responses - don't get caught here */ - status = ARES_ENODATA; - } - } - - return status; - -failed_stat: - ares_free(rr_name); - ares__freeaddrinfo_cnames(cnames); - ares__freeaddrinfo_nodes(nodes); - return status; -} - -int ares__parse_into_addrinfo(const unsigned char *abuf, - int alen, - struct ares_addrinfo *ai) -{ - int status; - char *question_hostname; - status = ares__parse_into_addrinfo2(abuf, alen, &question_hostname, ai); - ares_free(question_hostname); - return status; -} +/* Copyright (C) 2019 by Andrew Selivanov + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +# include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +# include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +# include <arpa/nameser.h> +#else +# include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +# include <arpa/nameser_compat.h> +#endif + +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif + +#include "ares.h" +#include "ares_dns.h" +#include "ares_private.h" + +int ares__parse_into_addrinfo2(const unsigned char *abuf, + int alen, + char **question_hostname, + struct ares_addrinfo *ai) +{ + unsigned int qdcount, ancount; + int status, i, rr_type, rr_class, rr_len, rr_ttl; + int got_a = 0, got_aaaa = 0, got_cname = 0; + long len; + const unsigned char *aptr; + char *hostname, *rr_name = NULL, *rr_data; + struct ares_addrinfo_cname *cname, *cnames = NULL; + struct ares_addrinfo_node *node, *nodes = NULL; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + + *question_hostname = NULL; + + /* Give up if abuf doesn't have room for a header. */ + if (alen < HFIXEDSZ) + return ARES_EBADRESP; + + /* Fetch the question and answer count from the header. */ + qdcount = DNS_HEADER_QDCOUNT(abuf); + ancount = DNS_HEADER_ANCOUNT(abuf); + if (qdcount != 1) + return ARES_EBADRESP; + + + /* Expand the name from the question, and skip past the question. */ + aptr = abuf + HFIXEDSZ; + status = ares__expand_name_for_response(aptr, abuf, alen, question_hostname, &len); + if (status != ARES_SUCCESS) + return status; + if (aptr + len + QFIXEDSZ > abuf + alen) + { + return ARES_EBADRESP; + } + + hostname = *question_hostname; + + aptr += len + QFIXEDSZ; + + /* Examine each answer resource record (RR) in turn. */ + for (i = 0; i < (int)ancount; i++) + { + /* Decode the RR up to the data field. */ + status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len); + if (status != ARES_SUCCESS) + { + rr_name = NULL; + goto failed_stat; + } + + aptr += len; + if (aptr + RRFIXEDSZ > abuf + alen) + { + status = ARES_EBADRESP; + goto failed_stat; + } + rr_type = DNS_RR_TYPE(aptr); + rr_class = DNS_RR_CLASS(aptr); + rr_len = DNS_RR_LEN(aptr); + rr_ttl = DNS_RR_TTL(aptr); + aptr += RRFIXEDSZ; + if (aptr + rr_len > abuf + alen) + { + status = ARES_EBADRESP; + goto failed_stat; + } + + if (rr_class == C_IN && rr_type == T_A + && rr_len == sizeof(struct in_addr) + && strcasecmp(rr_name, hostname) == 0) + { + got_a = 1; + if (aptr + sizeof(struct in_addr) > abuf + alen) + { /* LCOV_EXCL_START: already checked above */ + status = ARES_EBADRESP; + goto failed_stat; + } /* LCOV_EXCL_STOP */ + + node = ares__append_addrinfo_node(&nodes); + if (!node) + { + status = ARES_ENOMEM; + goto failed_stat; + } + + sin = ares_malloc(sizeof(struct sockaddr_in)); + if (!sin) + { + status = ARES_ENOMEM; + goto failed_stat; + } + memset(sin, 0, sizeof(struct sockaddr_in)); + memcpy(&sin->sin_addr.s_addr, aptr, sizeof(struct in_addr)); + sin->sin_family = AF_INET; + + node->ai_addr = (struct sockaddr *)sin; + node->ai_family = AF_INET; + node->ai_addrlen = sizeof(struct sockaddr_in); + + node->ai_ttl = rr_ttl; + + status = ARES_SUCCESS; + } + else if (rr_class == C_IN && rr_type == T_AAAA + && rr_len == sizeof(struct ares_in6_addr) + && strcasecmp(rr_name, hostname) == 0) + { + got_aaaa = 1; + if (aptr + sizeof(struct ares_in6_addr) > abuf + alen) + { /* LCOV_EXCL_START: already checked above */ + status = ARES_EBADRESP; + goto failed_stat; + } /* LCOV_EXCL_STOP */ + + node = ares__append_addrinfo_node(&nodes); + if (!node) + { + status = ARES_ENOMEM; + goto failed_stat; + } + + sin6 = ares_malloc(sizeof(struct sockaddr_in6)); + if (!sin6) + { + status = ARES_ENOMEM; + goto failed_stat; + } + + memset(sin6, 0, sizeof(struct sockaddr_in6)); + memcpy(&sin6->sin6_addr.s6_addr, aptr, sizeof(struct ares_in6_addr)); + sin6->sin6_family = AF_INET6; + + node->ai_addr = (struct sockaddr *)sin6; + node->ai_family = AF_INET6; + node->ai_addrlen = sizeof(struct sockaddr_in6); + + node->ai_ttl = rr_ttl; + + status = ARES_SUCCESS; + } + + if (rr_class == C_IN && rr_type == T_CNAME) + { + got_cname = 1; + status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data, + &len); + if (status != ARES_SUCCESS) + { + goto failed_stat; + } + + /* Decode the RR data and replace the hostname with it. */ + /* SA: Seems wrong as it introduses order dependency. */ + hostname = rr_data; + + cname = ares__append_addrinfo_cname(&cnames); + if (!cname) + { + status = ARES_ENOMEM; + ares_free(rr_data); + goto failed_stat; + } + cname->ttl = rr_ttl; + cname->alias = rr_name; + cname->name = rr_data; + } + else + { + ares_free(rr_name); + } + + + aptr += rr_len; + if (aptr > abuf + alen) + { /* LCOV_EXCL_START: already checked above */ + status = ARES_EBADRESP; + goto failed_stat; + } /* LCOV_EXCL_STOP */ + } + + if (status == ARES_SUCCESS) + { + ares__addrinfo_cat_nodes(&ai->nodes, nodes); + if (got_cname) + { + ares__addrinfo_cat_cnames(&ai->cnames, cnames); + return status; + } + else if (got_a == 0 && got_aaaa == 0) + { + /* the check for naliases to be zero is to make sure CNAME responses + don't get caught here */ + status = ARES_ENODATA; + } + } + + return status; + +failed_stat: + ares_free(rr_name); + ares__freeaddrinfo_cnames(cnames); + ares__freeaddrinfo_nodes(nodes); + return status; +} + +int ares__parse_into_addrinfo(const unsigned char *abuf, + int alen, + struct ares_addrinfo *ai) +{ + int status; + char *question_hostname; + status = ares__parse_into_addrinfo2(abuf, alen, &question_hostname, ai); + ares_free(question_hostname); + return status; +} diff --git a/contrib/libs/c-ares/ares__readaddrinfo.c b/contrib/libs/c-ares/ares__readaddrinfo.c index dd3abe2e9f..9ee8d7f0c4 100644 --- a/contrib/libs/c-ares/ares__readaddrinfo.c +++ b/contrib/libs/c-ares/ares__readaddrinfo.c @@ -1,260 +1,260 @@ -/* Copyright (C) 2019 by Andrew Selivanov - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without - * fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting - * documentation, and that the name of M.I.T. not be used in - * advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" - * without express or implied warranty. - */ - -#include "ares_setup.h" - -#ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> -#endif -#ifdef HAVE_NETDB_H -# include <netdb.h> -#endif -#ifdef HAVE_ARPA_INET_H -# include <arpa/inet.h> -#endif - -#include "ares.h" -#include "ares_inet_net_pton.h" -#include "ares_nowarn.h" -#include "ares_private.h" - -#define MAX_ALIASES 40 - -int ares__readaddrinfo(FILE *fp, - const char *name, - unsigned short port, - const struct ares_addrinfo_hints *hints, - struct ares_addrinfo *ai) -{ - char *line = NULL, *p, *q; - char *txtaddr, *txthost, *txtalias; - char *aliases[MAX_ALIASES]; - unsigned int i, alias_count; - int status; - size_t linesize; - ares_sockaddr addr; - struct ares_addrinfo_cname *cname = NULL, *cnames = NULL; - struct ares_addrinfo_node *node = NULL, *nodes = NULL; - int match_with_alias, match_with_canonical; - int want_cname = hints->ai_flags & ARES_AI_CANONNAME; - - /* Validate family */ - switch (hints->ai_family) { - case AF_INET: - case AF_INET6: - case AF_UNSPEC: - break; - default: - return ARES_EBADFAMILY; - } - - - while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) - { - match_with_alias = 0; - match_with_canonical = 0; - alias_count = 0; - /* Trim line comment. */ - p = line; - while (*p && (*p != '#')) - p++; - *p = '\0'; - - /* Trim trailing whitespace. */ - q = p - 1; - while ((q >= line) && ISSPACE(*q)) - q--; - *++q = '\0'; - - /* Skip leading whitespace. */ - p = line; - while (*p && ISSPACE(*p)) - p++; - if (!*p) - /* Ignore line if empty. */ - continue; - - /* Pointer to start of IPv4 or IPv6 address part. */ - txtaddr = p; - - /* Advance past address part. */ - while (*p && !ISSPACE(*p)) - p++; - if (!*p) - /* Ignore line if reached end of line. */ - continue; - - /* Null terminate address part. */ - *p = '\0'; - - /* Advance to host name */ - p++; - while (*p && ISSPACE(*p)) - p++; - if (!*p) - /* Ignore line if reached end of line. */ - continue; /* LCOV_EXCL_LINE: trailing whitespace already stripped */ - - /* Pointer to start of host name. */ - txthost = p; - - /* Advance past host name. */ - while (*p && !ISSPACE(*p)) - p++; - - /* Pointer to start of first alias. */ - txtalias = NULL; - if (*p) - { - q = p + 1; - while (*q && ISSPACE(*q)) - q++; - if (*q) - txtalias = q; - } - - /* Null terminate host name. */ - *p = '\0'; - - /* Find out if host name matches with canonical host name. */ - if (strcasecmp(txthost, name) == 0) - { - match_with_canonical = 1; - } - - /* Find out if host name matches with one of the aliases. */ - while (txtalias) - { - p = txtalias; - while (*p && !ISSPACE(*p)) - p++; - q = p; - while (*q && ISSPACE(*q)) - q++; - *p = '\0'; - if (strcasecmp(txtalias, name) == 0) - { - match_with_alias = 1; - if (!want_cname) - break; - } - if (alias_count < MAX_ALIASES) - { - aliases[alias_count++] = txtalias; - } - txtalias = *q ? q : NULL; - } - - /* Try next line if host does not match. */ - if (!match_with_alias && !match_with_canonical) - { - continue; - } - - /* - * Convert address string to network address for the requested families. - * Actual address family possible values are AF_INET and AF_INET6 only. - */ - if ((hints->ai_family == AF_INET) || (hints->ai_family == AF_UNSPEC)) - { - addr.sa4.sin_port = htons(port); - if (ares_inet_pton(AF_INET, txtaddr, &addr.sa4.sin_addr) > 0) - { - node = ares__append_addrinfo_node(&nodes); - if(!node) - { - goto enomem; - } - - node->ai_family = addr.sa.sa_family = AF_INET; - node->ai_addrlen = sizeof(sizeof(addr.sa4)); - node->ai_addr = ares_malloc(sizeof(addr.sa4)); - if (!node->ai_addr) - { - goto enomem; - } - memcpy(node->ai_addr, &addr.sa4, sizeof(addr.sa4)); - } - } - if ((hints->ai_family == AF_INET6) || (hints->ai_family == AF_UNSPEC)) - { - addr.sa6.sin6_port = htons(port); - if (ares_inet_pton(AF_INET6, txtaddr, &addr.sa6.sin6_addr) > 0) - { - node = ares__append_addrinfo_node(&nodes); - if (!node) - { - goto enomem; - } - - node->ai_family = addr.sa.sa_family = AF_INET6; - node->ai_addrlen = sizeof(sizeof(addr.sa6)); - node->ai_addr = ares_malloc(sizeof(addr.sa6)); - if (!node->ai_addr) - { - goto enomem; - } - memcpy(node->ai_addr, &addr.sa6, sizeof(addr.sa6)); - } - } - if (!node) - /* Ignore line if invalid address string for the requested family. */ - continue; - - if (want_cname) - { - for (i = 0; i < alias_count; ++i) - { - cname = ares__append_addrinfo_cname(&cnames); - if (!cname) - { - goto enomem; - } - cname->alias = ares_strdup(aliases[i]); - cname->name = ares_strdup(txthost); - } - /* No aliases, cname only. */ - if(!alias_count) - { - cname = ares__append_addrinfo_cname(&cnames); - if (!cname) - { - goto enomem; - } - cname->name = ares_strdup(txthost); - } - } - } - - /* Last read failed. */ - if (status == ARES_ENOMEM) - { - goto enomem; - } - - /* Free line buffer. */ - ares_free(line); - - ares__addrinfo_cat_cnames(&ai->cnames, cnames); - ares__addrinfo_cat_nodes(&ai->nodes, nodes); - - return node ? ARES_SUCCESS : ARES_ENOTFOUND; - -enomem: - ares_free(line); - ares__freeaddrinfo_cnames(cnames); - ares__freeaddrinfo_nodes(nodes); - return ARES_ENOMEM; -} +/* Copyright (C) 2019 by Andrew Selivanov + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +# include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +# include <arpa/inet.h> +#endif + +#include "ares.h" +#include "ares_inet_net_pton.h" +#include "ares_nowarn.h" +#include "ares_private.h" + +#define MAX_ALIASES 40 + +int ares__readaddrinfo(FILE *fp, + const char *name, + unsigned short port, + const struct ares_addrinfo_hints *hints, + struct ares_addrinfo *ai) +{ + char *line = NULL, *p, *q; + char *txtaddr, *txthost, *txtalias; + char *aliases[MAX_ALIASES]; + unsigned int i, alias_count; + int status; + size_t linesize; + ares_sockaddr addr; + struct ares_addrinfo_cname *cname = NULL, *cnames = NULL; + struct ares_addrinfo_node *node = NULL, *nodes = NULL; + int match_with_alias, match_with_canonical; + int want_cname = hints->ai_flags & ARES_AI_CANONNAME; + + /* Validate family */ + switch (hints->ai_family) { + case AF_INET: + case AF_INET6: + case AF_UNSPEC: + break; + default: + return ARES_EBADFAMILY; + } + + + while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) + { + match_with_alias = 0; + match_with_canonical = 0; + alias_count = 0; + /* Trim line comment. */ + p = line; + while (*p && (*p != '#')) + p++; + *p = '\0'; + + /* Trim trailing whitespace. */ + q = p - 1; + while ((q >= line) && ISSPACE(*q)) + q--; + *++q = '\0'; + + /* Skip leading whitespace. */ + p = line; + while (*p && ISSPACE(*p)) + p++; + if (!*p) + /* Ignore line if empty. */ + continue; + + /* Pointer to start of IPv4 or IPv6 address part. */ + txtaddr = p; + + /* Advance past address part. */ + while (*p && !ISSPACE(*p)) + p++; + if (!*p) + /* Ignore line if reached end of line. */ + continue; + + /* Null terminate address part. */ + *p = '\0'; + + /* Advance to host name */ + p++; + while (*p && ISSPACE(*p)) + p++; + if (!*p) + /* Ignore line if reached end of line. */ + continue; /* LCOV_EXCL_LINE: trailing whitespace already stripped */ + + /* Pointer to start of host name. */ + txthost = p; + + /* Advance past host name. */ + while (*p && !ISSPACE(*p)) + p++; + + /* Pointer to start of first alias. */ + txtalias = NULL; + if (*p) + { + q = p + 1; + while (*q && ISSPACE(*q)) + q++; + if (*q) + txtalias = q; + } + + /* Null terminate host name. */ + *p = '\0'; + + /* Find out if host name matches with canonical host name. */ + if (strcasecmp(txthost, name) == 0) + { + match_with_canonical = 1; + } + + /* Find out if host name matches with one of the aliases. */ + while (txtalias) + { + p = txtalias; + while (*p && !ISSPACE(*p)) + p++; + q = p; + while (*q && ISSPACE(*q)) + q++; + *p = '\0'; + if (strcasecmp(txtalias, name) == 0) + { + match_with_alias = 1; + if (!want_cname) + break; + } + if (alias_count < MAX_ALIASES) + { + aliases[alias_count++] = txtalias; + } + txtalias = *q ? q : NULL; + } + + /* Try next line if host does not match. */ + if (!match_with_alias && !match_with_canonical) + { + continue; + } + + /* + * Convert address string to network address for the requested families. + * Actual address family possible values are AF_INET and AF_INET6 only. + */ + if ((hints->ai_family == AF_INET) || (hints->ai_family == AF_UNSPEC)) + { + addr.sa4.sin_port = htons(port); + if (ares_inet_pton(AF_INET, txtaddr, &addr.sa4.sin_addr) > 0) + { + node = ares__append_addrinfo_node(&nodes); + if(!node) + { + goto enomem; + } + + node->ai_family = addr.sa.sa_family = AF_INET; + node->ai_addrlen = sizeof(sizeof(addr.sa4)); + node->ai_addr = ares_malloc(sizeof(addr.sa4)); + if (!node->ai_addr) + { + goto enomem; + } + memcpy(node->ai_addr, &addr.sa4, sizeof(addr.sa4)); + } + } + if ((hints->ai_family == AF_INET6) || (hints->ai_family == AF_UNSPEC)) + { + addr.sa6.sin6_port = htons(port); + if (ares_inet_pton(AF_INET6, txtaddr, &addr.sa6.sin6_addr) > 0) + { + node = ares__append_addrinfo_node(&nodes); + if (!node) + { + goto enomem; + } + + node->ai_family = addr.sa.sa_family = AF_INET6; + node->ai_addrlen = sizeof(sizeof(addr.sa6)); + node->ai_addr = ares_malloc(sizeof(addr.sa6)); + if (!node->ai_addr) + { + goto enomem; + } + memcpy(node->ai_addr, &addr.sa6, sizeof(addr.sa6)); + } + } + if (!node) + /* Ignore line if invalid address string for the requested family. */ + continue; + + if (want_cname) + { + for (i = 0; i < alias_count; ++i) + { + cname = ares__append_addrinfo_cname(&cnames); + if (!cname) + { + goto enomem; + } + cname->alias = ares_strdup(aliases[i]); + cname->name = ares_strdup(txthost); + } + /* No aliases, cname only. */ + if(!alias_count) + { + cname = ares__append_addrinfo_cname(&cnames); + if (!cname) + { + goto enomem; + } + cname->name = ares_strdup(txthost); + } + } + } + + /* Last read failed. */ + if (status == ARES_ENOMEM) + { + goto enomem; + } + + /* Free line buffer. */ + ares_free(line); + + ares__addrinfo_cat_cnames(&ai->cnames, cnames); + ares__addrinfo_cat_nodes(&ai->nodes, nodes); + + return node ? ARES_SUCCESS : ARES_ENOTFOUND; + +enomem: + ares_free(line); + ares__freeaddrinfo_cnames(cnames); + ares__freeaddrinfo_nodes(nodes); + return ARES_ENOMEM; +} diff --git a/contrib/libs/c-ares/ares__sortaddrinfo.c b/contrib/libs/c-ares/ares__sortaddrinfo.c index c0e2ea1528..b740860a6a 100644 --- a/contrib/libs/c-ares/ares__sortaddrinfo.c +++ b/contrib/libs/c-ares/ares__sortaddrinfo.c @@ -1,495 +1,495 @@ -/* - * 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) -{ - int sock; - int ret; - ares_socklen_t len; - - switch (addr->sa_family) - { - case AF_INET: - len = sizeof(struct sockaddr_in); - break; - case AF_INET6: - len = sizeof(struct sockaddr_in6); - break; - default: - /* No known usable source address for non-INET families. */ - return 0; - } - - sock = ares__open_socket(channel, addr->sa_family, SOCK_DGRAM, IPPROTO_UDP); - if (sock == -1) - { - if (errno == EAFNOSUPPORT) - { - return 0; - } - else - { - return -1; - } - } - - do - { - ret = ares__connect_socket(channel, sock, addr, len); - } - while (ret == -1 && errno == EINTR); - - if (ret == -1) - { - ares__close_socket(channel, sock); - return 0; - } - - if (getsockname(sock, src_addr, &len) == -1) - { - ares__close_socket(channel, sock); - return -1; - } - ares__close_socket(channel, sock); - return 1; -} - -/* - * Sort the linked list starting at sentinel->ai_next in RFC6724 order. - * Will leave the list unchanged if an error occurs. - */ -int ares__sortaddrinfo(ares_channel channel, struct ares_addrinfo_node *list_sentinel) -{ - struct ares_addrinfo_node *cur; - int nelem = 0, i; - int has_src_addr; - struct addrinfo_sort_elem *elems; - - cur = list_sentinel->ai_next; - while (cur) - { - ++nelem; - cur = cur->ai_next; - } - elems = (struct addrinfo_sort_elem *)ares_malloc( - nelem * sizeof(struct addrinfo_sort_elem)); - if (!elems) - { - return ARES_ENOMEM; - } - - /* - * Convert the linked list to an array that also contains the candidate - * source address for each destination address. - */ - for (i = 0, cur = list_sentinel->ai_next; i < nelem; ++i, cur = cur->ai_next) - { - assert(cur != NULL); - elems[i].ai = cur; - elems[i].original_order = i; - has_src_addr = find_src_addr(channel, cur->ai_addr, &elems[i].src_addr.sa); - if (has_src_addr == -1) - { - ares_free(elems); - return ARES_ENOTFOUND; - } - elems[i].has_src_addr = has_src_addr; - } - - /* Sort the addresses, and rearrange the linked list so it matches the sorted - * order. */ - qsort((void *)elems, nelem, sizeof(struct addrinfo_sort_elem), - rfc6724_compare); - - list_sentinel->ai_next = elems[0].ai; - for (i = 0; i < nelem - 1; ++i) - { - elems[i].ai->ai_next = elems[i + 1].ai; - } - elems[nelem - 1].ai->ai_next = NULL; - - ares_free(elems); - return ARES_SUCCESS; -} +/* + * 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) +{ + int sock; + int ret; + ares_socklen_t len; + + switch (addr->sa_family) + { + case AF_INET: + len = sizeof(struct sockaddr_in); + break; + case AF_INET6: + len = sizeof(struct sockaddr_in6); + break; + default: + /* No known usable source address for non-INET families. */ + return 0; + } + + sock = ares__open_socket(channel, addr->sa_family, SOCK_DGRAM, IPPROTO_UDP); + if (sock == -1) + { + if (errno == EAFNOSUPPORT) + { + return 0; + } + else + { + return -1; + } + } + + do + { + ret = ares__connect_socket(channel, sock, addr, len); + } + while (ret == -1 && errno == EINTR); + + if (ret == -1) + { + ares__close_socket(channel, sock); + return 0; + } + + if (getsockname(sock, src_addr, &len) == -1) + { + ares__close_socket(channel, sock); + return -1; + } + ares__close_socket(channel, sock); + return 1; +} + +/* + * Sort the linked list starting at sentinel->ai_next in RFC6724 order. + * Will leave the list unchanged if an error occurs. + */ +int ares__sortaddrinfo(ares_channel channel, struct ares_addrinfo_node *list_sentinel) +{ + struct ares_addrinfo_node *cur; + int nelem = 0, i; + int has_src_addr; + struct addrinfo_sort_elem *elems; + + cur = list_sentinel->ai_next; + while (cur) + { + ++nelem; + cur = cur->ai_next; + } + elems = (struct addrinfo_sort_elem *)ares_malloc( + nelem * sizeof(struct addrinfo_sort_elem)); + if (!elems) + { + return ARES_ENOMEM; + } + + /* + * Convert the linked list to an array that also contains the candidate + * source address for each destination address. + */ + for (i = 0, cur = list_sentinel->ai_next; i < nelem; ++i, cur = cur->ai_next) + { + assert(cur != NULL); + elems[i].ai = cur; + elems[i].original_order = i; + has_src_addr = find_src_addr(channel, cur->ai_addr, &elems[i].src_addr.sa); + if (has_src_addr == -1) + { + ares_free(elems); + return ARES_ENOTFOUND; + } + elems[i].has_src_addr = has_src_addr; + } + + /* Sort the addresses, and rearrange the linked list so it matches the sorted + * order. */ + qsort((void *)elems, nelem, sizeof(struct addrinfo_sort_elem), + rfc6724_compare); + + list_sentinel->ai_next = elems[0].ai; + for (i = 0; i < nelem - 1; ++i) + { + elems[i].ai->ai_next = elems[i + 1].ai; + } + elems[nelem - 1].ai->ai_next = NULL; + + ares_free(elems); + return ARES_SUCCESS; +} diff --git a/contrib/libs/c-ares/ares_freeaddrinfo.c b/contrib/libs/c-ares/ares_freeaddrinfo.c index 128f5daec4..bcbbc66d94 100644 --- a/contrib/libs/c-ares/ares_freeaddrinfo.c +++ b/contrib/libs/c-ares/ares_freeaddrinfo.c @@ -1,57 +1,57 @@ - -/* Copyright 1998 by the Massachusetts Institute of Technology. - * Copyright (C) 2019 by Andrew Selivanov - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without - * fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting - * documentation, and that the name of M.I.T. not be used in - * advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" - * without express or implied warranty. - */ - -#include "ares_setup.h" - -#ifdef HAVE_NETDB_H -# include <netdb.h> -#endif - -#include "ares.h" -#include "ares_private.h" - -void ares__freeaddrinfo_cnames(struct ares_addrinfo_cname *head) -{ - struct ares_addrinfo_cname *current; - while (head) - { - current = head; - head = head->next; - ares_free(current->alias); - ares_free(current->name); - ares_free(current); - } -} - -void ares__freeaddrinfo_nodes(struct ares_addrinfo_node *head) -{ - struct ares_addrinfo_node *current; - while (head) - { - current = head; - head = head->ai_next; - ares_free(current->ai_addr); - ares_free(current); - } -} - -void ares_freeaddrinfo(struct ares_addrinfo *ai) -{ - ares__freeaddrinfo_cnames(ai->cnames); - ares__freeaddrinfo_nodes(ai->nodes); - ares_free(ai); -} + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2019 by Andrew Selivanov + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_NETDB_H +# include <netdb.h> +#endif + +#include "ares.h" +#include "ares_private.h" + +void ares__freeaddrinfo_cnames(struct ares_addrinfo_cname *head) +{ + struct ares_addrinfo_cname *current; + while (head) + { + current = head; + head = head->next; + ares_free(current->alias); + ares_free(current->name); + ares_free(current); + } +} + +void ares__freeaddrinfo_nodes(struct ares_addrinfo_node *head) +{ + struct ares_addrinfo_node *current; + while (head) + { + current = head; + head = head->ai_next; + ares_free(current->ai_addr); + ares_free(current); + } +} + +void ares_freeaddrinfo(struct ares_addrinfo *ai) +{ + ares__freeaddrinfo_cnames(ai->cnames); + ares__freeaddrinfo_nodes(ai->nodes); + ares_free(ai); +} diff --git a/contrib/libs/c-ares/ares_getaddrinfo.c b/contrib/libs/c-ares/ares_getaddrinfo.c index be168068b1..d257e75673 100644 --- a/contrib/libs/c-ares/ares_getaddrinfo.c +++ b/contrib/libs/c-ares/ares_getaddrinfo.c @@ -1,765 +1,765 @@ - -/* Copyright 1998, 2011, 2013 by the Massachusetts Institute of Technology. - * Copyright (C) 2017 - 2018 by Christian Ammer - * Copyright (C) 2019 by Andrew Selivanov - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without - * fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting - * documentation, and that the name of M.I.T. not be used in - * advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" - * without express or implied warranty. - */ - -#include "ares_setup.h" - -#ifdef HAVE_GETSERVBYNAME_R -# if !defined(GETSERVBYNAME_R_ARGS) || \ - (GETSERVBYNAME_R_ARGS < 4) || (GETSERVBYNAME_R_ARGS > 6) -# error "you MUST specifiy a valid number of arguments for getservbyname_r" -# endif -#endif - -#ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> -#endif -#ifdef HAVE_NETDB_H -# include <netdb.h> -#endif -#ifdef HAVE_ARPA_INET_H -# include <arpa/inet.h> -#endif -#ifdef HAVE_ARPA_NAMESER_H -# include <arpa/nameser.h> -#else -# include "nameser.h" -#endif -#ifdef HAVE_ARPA_NAMESER_COMPAT_H -# include <arpa/nameser_compat.h> -#endif - -#ifdef HAVE_STRINGS_H -#include <strings.h> -#endif -#include <assert.h> - -#ifdef HAVE_LIMITS_H -#include <limits.h> -#endif - -#include "ares.h" -#include "bitncmp.h" -#include "ares_private.h" - -#ifdef WATT32 -#undef WIN32 -#endif -#ifdef WIN32 -# include "ares_platform.h" -#endif - -struct host_query -{ - ares_channel channel; - char *name; - unsigned short port; /* in host order */ - ares_addrinfo_callback callback; - void *arg; - struct ares_addrinfo_hints hints; - int sent_family; /* this family is what was is being used */ - int timeouts; /* number of timeouts we saw for this request */ - const char *remaining_lookups; /* types of lookup we need to perform ("fb" by - default, file and dns respectively) */ - struct ares_addrinfo *ai; /* store results between lookups */ - int remaining; /* number of DNS answers waiting for */ - int next_domain; /* next search domain to try */ -}; - -static const struct ares_addrinfo_hints default_hints = { - 0, /* ai_flags */ - AF_UNSPEC, /* ai_family */ - 0, /* ai_socktype */ - 0, /* ai_protocol */ -}; - -static const struct ares_addrinfo_cname empty_addrinfo_cname = { - INT_MAX, /* ttl */ - NULL, /* alias */ - NULL, /* name */ - NULL, /* next */ -}; - -static const struct ares_addrinfo_node empty_addrinfo_node = { - 0, /* ai_ttl */ - 0, /* ai_flags */ - 0, /* ai_family */ - 0, /* ai_socktype */ - 0, /* ai_protocol */ - 0, /* ai_addrlen */ - NULL, /* ai_addr */ - NULL /* ai_next */ -}; - -static const struct ares_addrinfo empty_addrinfo = { - NULL, /* cnames */ - NULL /* nodes */ -}; - -/* forward declarations */ -static void host_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen); -static int as_is_first(const struct host_query *hquery); -static int next_dns_lookup(struct host_query *hquery); - -struct ares_addrinfo_cname *ares__malloc_addrinfo_cname() -{ - struct ares_addrinfo_cname *cname = ares_malloc(sizeof(struct ares_addrinfo_cname)); - if (!cname) - return NULL; - - *cname = empty_addrinfo_cname; - return cname; -} - -struct ares_addrinfo_cname *ares__append_addrinfo_cname(struct ares_addrinfo_cname **head) -{ - struct ares_addrinfo_cname *tail = ares__malloc_addrinfo_cname(); - struct ares_addrinfo_cname *last = *head; - if (!last) - { - *head = tail; - return tail; - } - - while (last->next) - { - last = last->next; - } - - last->next = tail; - return tail; -} - -void ares__addrinfo_cat_cnames(struct ares_addrinfo_cname **head, - struct ares_addrinfo_cname *tail) -{ - struct ares_addrinfo_cname *last = *head; - if (!last) - { - *head = tail; - return; - } - - while (last->next) - { - last = last->next; - } - - last->next = tail; -} - -struct ares_addrinfo *ares__malloc_addrinfo() -{ - struct ares_addrinfo *ai = ares_malloc(sizeof(struct ares_addrinfo)); - if (!ai) - return NULL; - - *ai = empty_addrinfo; - return ai; -} - -struct ares_addrinfo_node *ares__malloc_addrinfo_node() -{ - struct ares_addrinfo_node *node = - ares_malloc(sizeof(struct ares_addrinfo_node)); - if (!node) - return NULL; - - *node = empty_addrinfo_node; - return node; -} - -/* Allocate new addrinfo and append to the tail. */ -struct ares_addrinfo_node *ares__append_addrinfo_node(struct ares_addrinfo_node **head) -{ - struct ares_addrinfo_node *tail = ares__malloc_addrinfo_node(); - struct ares_addrinfo_node *last = *head; - if (!last) - { - *head = tail; - return tail; - } - - while (last->ai_next) - { - last = last->ai_next; - } - - last->ai_next = tail; - return tail; -} - -void ares__addrinfo_cat_nodes(struct ares_addrinfo_node **head, - struct ares_addrinfo_node *tail) -{ - struct ares_addrinfo_node *last = *head; - if (!last) - { - *head = tail; - return; - } - - while (last->ai_next) - { - last = last->ai_next; - } - - last->ai_next = tail; -} - -/* Resolve service name into port number given in host byte order. - * If not resolved, return 0. - */ -static unsigned short lookup_service(const char *service, int flags) -{ - const char *proto; - struct servent *sep; -#ifdef HAVE_GETSERVBYNAME_R - struct servent se; - char tmpbuf[4096]; -#endif - - if (service) - { - if (flags & ARES_NI_UDP) - proto = "udp"; - else if (flags & ARES_NI_SCTP) - proto = "sctp"; - else if (flags & ARES_NI_DCCP) - proto = "dccp"; - else - proto = "tcp"; -#ifdef HAVE_GETSERVBYNAME_R - memset(&se, 0, sizeof(se)); - sep = &se; - memset(tmpbuf, 0, sizeof(tmpbuf)); -#if GETSERVBYNAME_R_ARGS == 6 - if (getservbyname_r(service, proto, &se, (void *)tmpbuf, sizeof(tmpbuf), - &sep) != 0) - sep = NULL; /* LCOV_EXCL_LINE: buffer large so this never fails */ -#elif GETSERVBYNAME_R_ARGS == 5 - sep = - getservbyname_r(service, proto, &se, (void *)tmpbuf, sizeof(tmpbuf)); -#elif GETSERVBYNAME_R_ARGS == 4 - if (getservbyname_r(service, proto, &se, (void *)tmpbuf) != 0) - sep = NULL; -#else - /* Lets just hope the OS uses TLS! */ - sep = getservbyname(service, proto); -#endif -#else - /* Lets just hope the OS uses TLS! */ -#if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) - sep = getservbyname(service, (char *)proto); -#else - sep = getservbyname(service, proto); -#endif -#endif - return (sep ? ntohs((unsigned short)sep->s_port) : 0); - } - return 0; -} - -/* If the name looks like an IP address or an error occured, - * fake up a host entry, end the query immediately, and return true. - * Otherwise return false. - */ -static int fake_addrinfo(const char *name, - unsigned short port, - const struct ares_addrinfo_hints *hints, - struct ares_addrinfo *ai, - ares_addrinfo_callback callback, - void *arg) -{ - struct ares_addrinfo_cname *cname; - struct ares_addrinfo_node *node; - ares_sockaddr addr; - size_t addrlen; - int result = 0; - int family = hints->ai_family; - if (family == AF_INET || family == AF_INET6 || family == AF_UNSPEC) - { - /* It only looks like an IP address if it's all numbers and dots. */ - int numdots = 0, valid = 1; - const char *p; - for (p = name; *p; p++) - { - if (!ISDIGIT(*p) && *p != '.') - { - valid = 0; - break; - } - else if (*p == '.') - { - numdots++; - } - } - - memset(&addr, 0, sizeof(addr)); - - /* if we don't have 3 dots, it is illegal - * (although inet_pton doesn't think so). - */ - if (numdots != 3 || !valid) - result = 0; - else - result = - (ares_inet_pton(AF_INET, name, &addr.sa4.sin_addr) < 1 ? 0 : 1); - - if (result) - { - family = addr.sa.sa_family = AF_INET; - addr.sa4.sin_port = htons(port); - addrlen = sizeof(addr.sa4); - } - } - - if (family == AF_INET6 || family == AF_UNSPEC) - { - result = - (ares_inet_pton(AF_INET6, name, &addr.sa6.sin6_addr) < 1 ? 0 : 1); - addr.sa6.sin6_family = AF_INET6; - addr.sa6.sin6_port = htons(port); - addrlen = sizeof(addr.sa6); - } - - if (!result) - return 0; - - node = ares__malloc_addrinfo_node(); - if (!node) - { - ares_freeaddrinfo(ai); - callback(arg, ARES_ENOMEM, 0, NULL); - return 1; - } - - ai->nodes = node; - - node->ai_addr = ares_malloc(addrlen); - if (!node->ai_addr) - { - ares_freeaddrinfo(ai); - callback(arg, ARES_ENOMEM, 0, NULL); - return 1; - } - - node->ai_addrlen = (unsigned int)addrlen; - node->ai_family = addr.sa.sa_family; - if (addr.sa.sa_family == AF_INET) - memcpy(node->ai_addr, &addr.sa4, sizeof(addr.sa4)); - else - memcpy(node->ai_addr, &addr.sa6, sizeof(addr.sa6)); - - if (hints->ai_flags & ARES_AI_CANONNAME) - { - cname = ares__append_addrinfo_cname(&ai->cnames); - if (!cname) - { - ares_freeaddrinfo(ai); - callback(arg, ARES_ENOMEM, 0, NULL); - return 1; - } - - /* Duplicate the name, to avoid a constness violation. */ - cname->name = ares_strdup(name); - if (!cname->name) - { - ares_freeaddrinfo(ai); - callback(arg, ARES_ENOMEM, 0, NULL); - return 1; - } - } - - callback(arg, ARES_SUCCESS, 0, ai); - return 1; -} - -static void end_hquery(struct host_query *hquery, int status) -{ - struct ares_addrinfo_node sentinel; - struct ares_addrinfo_node *next; - if (status == ARES_SUCCESS) - { - if (!(hquery->hints.ai_flags & ARES_AI_NOSORT)) - { - sentinel.ai_next = hquery->ai->nodes; - ares__sortaddrinfo(hquery->channel, &sentinel); - hquery->ai->nodes = sentinel.ai_next; - } - next = hquery->ai->nodes; - /* Set port into each address (resolved separately). */ - while (next) - { - if (next->ai_family == AF_INET) - { - (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); - } - else if (status == ARES_EDESTRUCTION) - { - end_hquery(hquery, status); - return; - } - - if (!hquery->remaining) - { - if (addinfostatus != ARES_SUCCESS) - { - /* error in parsing result e.g. no memory */ - end_hquery(hquery, addinfostatus); - } - else if (hquery->ai->nodes) - { - /* at least one query ended with ARES_SUCCESS */ - end_hquery(hquery, ARES_SUCCESS); - } - else if (status == ARES_ENOTFOUND) - { - next_lookup(hquery, status); - } - else - { - end_hquery(hquery, status); - } - } - - /* at this point we keep on waiting for the next query to finish */ -} - -void ares_getaddrinfo(ares_channel channel, - const char* name, const char* service, - const struct ares_addrinfo_hints* hints, - ares_addrinfo_callback callback, void* arg) -{ - struct host_query *hquery; - unsigned short port = 0; - int family; - struct ares_addrinfo *ai; - - if (!hints) - { - hints = &default_hints; - } - - family = hints->ai_family; - - /* Right now we only know how to look up Internet addresses - and unspec means try both basically. */ - if (family != AF_INET && - family != AF_INET6 && - family != AF_UNSPEC) - { - callback(arg, ARES_ENOTIMP, 0, NULL); - return; - } - - if (ares__is_onion_domain(name)) - { - callback(arg, ARES_ENOTFOUND, 0, NULL); - return; - } - - if (service) - { - if (hints->ai_flags & ARES_AI_NUMERICSERV) - { - port = (unsigned short)strtoul(service, NULL, 0); - if (!port) - { - callback(arg, ARES_ESERVICE, 0, NULL); - return; - } - } - else - { - port = lookup_service(service, 0); - if (!port) - { - port = (unsigned short)strtoul(service, NULL, 0); - if (!port) - { - callback(arg, ARES_ESERVICE, 0, NULL); - return; - } - } - } - } - - ai = ares__malloc_addrinfo(); - if (!ai) - { - callback(arg, ARES_ENOMEM, 0, NULL); - return; - } - - if (fake_addrinfo(name, port, hints, ai, callback, arg)) - { - return; - } - - /* Allocate and fill in the host query structure. */ - hquery = ares_malloc(sizeof(struct host_query)); - if (!hquery) - { - ares_freeaddrinfo(ai); - callback(arg, ARES_ENOMEM, 0, NULL); - return; - } - - hquery->name = ares_strdup(name); - if (!hquery->name) - { - ares_free(hquery); - ares_freeaddrinfo(ai); - callback(arg, ARES_ENOMEM, 0, NULL); - return; - } - - hquery->port = port; - hquery->channel = channel; - hquery->hints = *hints; - hquery->sent_family = -1; /* nothing is sent yet */ - hquery->callback = callback; - hquery->arg = arg; - hquery->remaining_lookups = channel->lookups; - hquery->timeouts = 0; - hquery->ai = ai; - hquery->next_domain = -1; - hquery->remaining = 0; - - /* Start performing lookups according to channel->lookups. */ - next_lookup(hquery, ARES_ECONNREFUSED /* initial error code */); -} - -static int next_dns_lookup(struct host_query *hquery) -{ - char *s = NULL; - int is_s_allocated = 0; - int status; - - /* if next_domain == -1 and as_is_first is true, try hquery->name */ - if (hquery->next_domain == -1) - { - if (as_is_first(hquery)) - { - s = hquery->name; - } - hquery->next_domain = 0; - } - - /* if as_is_first is false, try hquery->name at last */ - if (!s && hquery->next_domain == hquery->channel->ndomains) { - if (!as_is_first(hquery)) - { - s = hquery->name; - } - hquery->next_domain++; - } - - if (!s && hquery->next_domain < hquery->channel->ndomains) - { - status = ares__cat_domain( - hquery->name, - hquery->channel->domains[hquery->next_domain++], - &s); - if (status == ARES_SUCCESS) - { - is_s_allocated = 1; - } - } - - if (s) - { - switch (hquery->hints.ai_family) - { - case AF_INET: - hquery->remaining += 1; - ares_query(hquery->channel, s, C_IN, T_A, host_callback, hquery); - break; - case AF_INET6: - hquery->remaining += 1; - ares_query(hquery->channel, s, C_IN, T_AAAA, host_callback, hquery); - break; - case AF_UNSPEC: - hquery->remaining += 2; - ares_query(hquery->channel, s, C_IN, T_A, host_callback, hquery); - ares_query(hquery->channel, s, C_IN, T_AAAA, host_callback, hquery); - break; - default: break; - } - if (is_s_allocated) - { - ares_free(s); - } - return 1; - } - else - { - assert(!hquery->ai->nodes); - return 0; - } -} - -static int as_is_first(const struct host_query* hquery) -{ - char* p; - int ndots = 0; - for (p = hquery->name; *p; p++) - { - if (*p == '.') - { - ndots++; - } - } - return ndots >= hquery->channel->ndots; -} + +/* Copyright 1998, 2011, 2013 by the Massachusetts Institute of Technology. + * Copyright (C) 2017 - 2018 by Christian Ammer + * Copyright (C) 2019 by Andrew Selivanov + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_GETSERVBYNAME_R +# if !defined(GETSERVBYNAME_R_ARGS) || \ + (GETSERVBYNAME_R_ARGS < 4) || (GETSERVBYNAME_R_ARGS > 6) +# error "you MUST specifiy a valid number of arguments for getservbyname_r" +# endif +#endif + +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +# include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +# include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +# include <arpa/nameser.h> +#else +# include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +# include <arpa/nameser_compat.h> +#endif + +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#include <assert.h> + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +#include "ares.h" +#include "bitncmp.h" +#include "ares_private.h" + +#ifdef WATT32 +#undef WIN32 +#endif +#ifdef WIN32 +# include "ares_platform.h" +#endif + +struct host_query +{ + ares_channel channel; + char *name; + unsigned short port; /* in host order */ + ares_addrinfo_callback callback; + void *arg; + struct ares_addrinfo_hints hints; + int sent_family; /* this family is what was is being used */ + int timeouts; /* number of timeouts we saw for this request */ + const char *remaining_lookups; /* types of lookup we need to perform ("fb" by + default, file and dns respectively) */ + struct ares_addrinfo *ai; /* store results between lookups */ + int remaining; /* number of DNS answers waiting for */ + int next_domain; /* next search domain to try */ +}; + +static const struct ares_addrinfo_hints default_hints = { + 0, /* ai_flags */ + AF_UNSPEC, /* ai_family */ + 0, /* ai_socktype */ + 0, /* ai_protocol */ +}; + +static const struct ares_addrinfo_cname empty_addrinfo_cname = { + INT_MAX, /* ttl */ + NULL, /* alias */ + NULL, /* name */ + NULL, /* next */ +}; + +static const struct ares_addrinfo_node empty_addrinfo_node = { + 0, /* ai_ttl */ + 0, /* ai_flags */ + 0, /* ai_family */ + 0, /* ai_socktype */ + 0, /* ai_protocol */ + 0, /* ai_addrlen */ + NULL, /* ai_addr */ + NULL /* ai_next */ +}; + +static const struct ares_addrinfo empty_addrinfo = { + NULL, /* cnames */ + NULL /* nodes */ +}; + +/* forward declarations */ +static void host_callback(void *arg, int status, int timeouts, + unsigned char *abuf, int alen); +static int as_is_first(const struct host_query *hquery); +static int next_dns_lookup(struct host_query *hquery); + +struct ares_addrinfo_cname *ares__malloc_addrinfo_cname() +{ + struct ares_addrinfo_cname *cname = ares_malloc(sizeof(struct ares_addrinfo_cname)); + if (!cname) + return NULL; + + *cname = empty_addrinfo_cname; + return cname; +} + +struct ares_addrinfo_cname *ares__append_addrinfo_cname(struct ares_addrinfo_cname **head) +{ + struct ares_addrinfo_cname *tail = ares__malloc_addrinfo_cname(); + struct ares_addrinfo_cname *last = *head; + if (!last) + { + *head = tail; + return tail; + } + + while (last->next) + { + last = last->next; + } + + last->next = tail; + return tail; +} + +void ares__addrinfo_cat_cnames(struct ares_addrinfo_cname **head, + struct ares_addrinfo_cname *tail) +{ + struct ares_addrinfo_cname *last = *head; + if (!last) + { + *head = tail; + return; + } + + while (last->next) + { + last = last->next; + } + + last->next = tail; +} + +struct ares_addrinfo *ares__malloc_addrinfo() +{ + struct ares_addrinfo *ai = ares_malloc(sizeof(struct ares_addrinfo)); + if (!ai) + return NULL; + + *ai = empty_addrinfo; + return ai; +} + +struct ares_addrinfo_node *ares__malloc_addrinfo_node() +{ + struct ares_addrinfo_node *node = + ares_malloc(sizeof(struct ares_addrinfo_node)); + if (!node) + return NULL; + + *node = empty_addrinfo_node; + return node; +} + +/* Allocate new addrinfo and append to the tail. */ +struct ares_addrinfo_node *ares__append_addrinfo_node(struct ares_addrinfo_node **head) +{ + struct ares_addrinfo_node *tail = ares__malloc_addrinfo_node(); + struct ares_addrinfo_node *last = *head; + if (!last) + { + *head = tail; + return tail; + } + + while (last->ai_next) + { + last = last->ai_next; + } + + last->ai_next = tail; + return tail; +} + +void ares__addrinfo_cat_nodes(struct ares_addrinfo_node **head, + struct ares_addrinfo_node *tail) +{ + struct ares_addrinfo_node *last = *head; + if (!last) + { + *head = tail; + return; + } + + while (last->ai_next) + { + last = last->ai_next; + } + + last->ai_next = tail; +} + +/* Resolve service name into port number given in host byte order. + * If not resolved, return 0. + */ +static unsigned short lookup_service(const char *service, int flags) +{ + const char *proto; + struct servent *sep; +#ifdef HAVE_GETSERVBYNAME_R + struct servent se; + char tmpbuf[4096]; +#endif + + if (service) + { + if (flags & ARES_NI_UDP) + proto = "udp"; + else if (flags & ARES_NI_SCTP) + proto = "sctp"; + else if (flags & ARES_NI_DCCP) + proto = "dccp"; + else + proto = "tcp"; +#ifdef HAVE_GETSERVBYNAME_R + memset(&se, 0, sizeof(se)); + sep = &se; + memset(tmpbuf, 0, sizeof(tmpbuf)); +#if GETSERVBYNAME_R_ARGS == 6 + if (getservbyname_r(service, proto, &se, (void *)tmpbuf, sizeof(tmpbuf), + &sep) != 0) + sep = NULL; /* LCOV_EXCL_LINE: buffer large so this never fails */ +#elif GETSERVBYNAME_R_ARGS == 5 + sep = + getservbyname_r(service, proto, &se, (void *)tmpbuf, sizeof(tmpbuf)); +#elif GETSERVBYNAME_R_ARGS == 4 + if (getservbyname_r(service, proto, &se, (void *)tmpbuf) != 0) + sep = NULL; +#else + /* Lets just hope the OS uses TLS! */ + sep = getservbyname(service, proto); +#endif +#else + /* Lets just hope the OS uses TLS! */ +#if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) + sep = getservbyname(service, (char *)proto); +#else + sep = getservbyname(service, proto); +#endif +#endif + return (sep ? ntohs((unsigned short)sep->s_port) : 0); + } + return 0; +} + +/* If the name looks like an IP address or an error occured, + * fake up a host entry, end the query immediately, and return true. + * Otherwise return false. + */ +static int fake_addrinfo(const char *name, + unsigned short port, + const struct ares_addrinfo_hints *hints, + struct ares_addrinfo *ai, + ares_addrinfo_callback callback, + void *arg) +{ + struct ares_addrinfo_cname *cname; + struct ares_addrinfo_node *node; + ares_sockaddr addr; + size_t addrlen; + int result = 0; + int family = hints->ai_family; + if (family == AF_INET || family == AF_INET6 || family == AF_UNSPEC) + { + /* It only looks like an IP address if it's all numbers and dots. */ + int numdots = 0, valid = 1; + const char *p; + for (p = name; *p; p++) + { + if (!ISDIGIT(*p) && *p != '.') + { + valid = 0; + break; + } + else if (*p == '.') + { + numdots++; + } + } + + memset(&addr, 0, sizeof(addr)); + + /* if we don't have 3 dots, it is illegal + * (although inet_pton doesn't think so). + */ + if (numdots != 3 || !valid) + result = 0; + else + result = + (ares_inet_pton(AF_INET, name, &addr.sa4.sin_addr) < 1 ? 0 : 1); + + if (result) + { + family = addr.sa.sa_family = AF_INET; + addr.sa4.sin_port = htons(port); + addrlen = sizeof(addr.sa4); + } + } + + if (family == AF_INET6 || family == AF_UNSPEC) + { + result = + (ares_inet_pton(AF_INET6, name, &addr.sa6.sin6_addr) < 1 ? 0 : 1); + addr.sa6.sin6_family = AF_INET6; + addr.sa6.sin6_port = htons(port); + addrlen = sizeof(addr.sa6); + } + + if (!result) + return 0; + + node = ares__malloc_addrinfo_node(); + if (!node) + { + ares_freeaddrinfo(ai); + callback(arg, ARES_ENOMEM, 0, NULL); + return 1; + } + + ai->nodes = node; + + node->ai_addr = ares_malloc(addrlen); + if (!node->ai_addr) + { + ares_freeaddrinfo(ai); + callback(arg, ARES_ENOMEM, 0, NULL); + return 1; + } + + node->ai_addrlen = (unsigned int)addrlen; + node->ai_family = addr.sa.sa_family; + if (addr.sa.sa_family == AF_INET) + memcpy(node->ai_addr, &addr.sa4, sizeof(addr.sa4)); + else + memcpy(node->ai_addr, &addr.sa6, sizeof(addr.sa6)); + + if (hints->ai_flags & ARES_AI_CANONNAME) + { + cname = ares__append_addrinfo_cname(&ai->cnames); + if (!cname) + { + ares_freeaddrinfo(ai); + callback(arg, ARES_ENOMEM, 0, NULL); + return 1; + } + + /* Duplicate the name, to avoid a constness violation. */ + cname->name = ares_strdup(name); + if (!cname->name) + { + ares_freeaddrinfo(ai); + callback(arg, ARES_ENOMEM, 0, NULL); + return 1; + } + } + + callback(arg, ARES_SUCCESS, 0, ai); + return 1; +} + +static void end_hquery(struct host_query *hquery, int status) +{ + struct ares_addrinfo_node sentinel; + struct ares_addrinfo_node *next; + if (status == ARES_SUCCESS) + { + if (!(hquery->hints.ai_flags & ARES_AI_NOSORT)) + { + sentinel.ai_next = hquery->ai->nodes; + ares__sortaddrinfo(hquery->channel, &sentinel); + hquery->ai->nodes = sentinel.ai_next; + } + next = hquery->ai->nodes; + /* Set port into each address (resolved separately). */ + while (next) + { + if (next->ai_family == AF_INET) + { + (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); + } + else if (status == ARES_EDESTRUCTION) + { + end_hquery(hquery, status); + return; + } + + if (!hquery->remaining) + { + if (addinfostatus != ARES_SUCCESS) + { + /* error in parsing result e.g. no memory */ + end_hquery(hquery, addinfostatus); + } + else if (hquery->ai->nodes) + { + /* at least one query ended with ARES_SUCCESS */ + end_hquery(hquery, ARES_SUCCESS); + } + else if (status == ARES_ENOTFOUND) + { + next_lookup(hquery, status); + } + else + { + end_hquery(hquery, status); + } + } + + /* at this point we keep on waiting for the next query to finish */ +} + +void ares_getaddrinfo(ares_channel channel, + const char* name, const char* service, + const struct ares_addrinfo_hints* hints, + ares_addrinfo_callback callback, void* arg) +{ + struct host_query *hquery; + unsigned short port = 0; + int family; + struct ares_addrinfo *ai; + + if (!hints) + { + hints = &default_hints; + } + + family = hints->ai_family; + + /* Right now we only know how to look up Internet addresses + and unspec means try both basically. */ + if (family != AF_INET && + family != AF_INET6 && + family != AF_UNSPEC) + { + callback(arg, ARES_ENOTIMP, 0, NULL); + return; + } + + if (ares__is_onion_domain(name)) + { + callback(arg, ARES_ENOTFOUND, 0, NULL); + return; + } + + if (service) + { + if (hints->ai_flags & ARES_AI_NUMERICSERV) + { + port = (unsigned short)strtoul(service, NULL, 0); + if (!port) + { + callback(arg, ARES_ESERVICE, 0, NULL); + return; + } + } + else + { + port = lookup_service(service, 0); + if (!port) + { + port = (unsigned short)strtoul(service, NULL, 0); + if (!port) + { + callback(arg, ARES_ESERVICE, 0, NULL); + return; + } + } + } + } + + ai = ares__malloc_addrinfo(); + if (!ai) + { + callback(arg, ARES_ENOMEM, 0, NULL); + return; + } + + if (fake_addrinfo(name, port, hints, ai, callback, arg)) + { + return; + } + + /* Allocate and fill in the host query structure. */ + hquery = ares_malloc(sizeof(struct host_query)); + if (!hquery) + { + ares_freeaddrinfo(ai); + callback(arg, ARES_ENOMEM, 0, NULL); + return; + } + + hquery->name = ares_strdup(name); + if (!hquery->name) + { + ares_free(hquery); + ares_freeaddrinfo(ai); + callback(arg, ARES_ENOMEM, 0, NULL); + return; + } + + hquery->port = port; + hquery->channel = channel; + hquery->hints = *hints; + hquery->sent_family = -1; /* nothing is sent yet */ + hquery->callback = callback; + hquery->arg = arg; + hquery->remaining_lookups = channel->lookups; + hquery->timeouts = 0; + hquery->ai = ai; + hquery->next_domain = -1; + hquery->remaining = 0; + + /* Start performing lookups according to channel->lookups. */ + next_lookup(hquery, ARES_ECONNREFUSED /* initial error code */); +} + +static int next_dns_lookup(struct host_query *hquery) +{ + char *s = NULL; + int is_s_allocated = 0; + int status; + + /* if next_domain == -1 and as_is_first is true, try hquery->name */ + if (hquery->next_domain == -1) + { + if (as_is_first(hquery)) + { + s = hquery->name; + } + hquery->next_domain = 0; + } + + /* if as_is_first is false, try hquery->name at last */ + if (!s && hquery->next_domain == hquery->channel->ndomains) { + if (!as_is_first(hquery)) + { + s = hquery->name; + } + hquery->next_domain++; + } + + if (!s && hquery->next_domain < hquery->channel->ndomains) + { + status = ares__cat_domain( + hquery->name, + hquery->channel->domains[hquery->next_domain++], + &s); + if (status == ARES_SUCCESS) + { + is_s_allocated = 1; + } + } + + if (s) + { + switch (hquery->hints.ai_family) + { + case AF_INET: + hquery->remaining += 1; + ares_query(hquery->channel, s, C_IN, T_A, host_callback, hquery); + break; + case AF_INET6: + hquery->remaining += 1; + ares_query(hquery->channel, s, C_IN, T_AAAA, host_callback, hquery); + break; + case AF_UNSPEC: + hquery->remaining += 2; + ares_query(hquery->channel, s, C_IN, T_A, host_callback, hquery); + ares_query(hquery->channel, s, C_IN, T_AAAA, host_callback, hquery); + break; + default: break; + } + if (is_s_allocated) + { + ares_free(s); + } + return 1; + } + else + { + assert(!hquery->ai->nodes); + return 0; + } +} + +static int as_is_first(const struct host_query* hquery) +{ + char* p; + int ndots = 0; + for (p = hquery->name; *p; p++) + { + if (*p == '.') + { + ndots++; + } + } + return ndots >= hquery->channel->ndots; +} diff --git a/contrib/libs/c-ares/ares_gethostbyname.c b/contrib/libs/c-ares/ares_gethostbyname.c index ecd03e7931..527b0b60e8 100644 --- a/contrib/libs/c-ares/ares_gethostbyname.c +++ b/contrib/libs/c-ares/ares_gethostbyname.c @@ -211,13 +211,13 @@ static void host_callback(void *arg, int status, int timeouts, if (host && channel->nsort) sort6_addresses(host, channel->sortlist, channel->nsort); } - if (status == ARES_SUCCESS && host && host->h_addr_list[0] == NULL) - { - /* The query returned something but had no A/AAAA record - (even after potentially retrying AAAA with A) - so we should treat this as an error */ - status = ARES_ENODATA; - } + 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 || @@ -274,12 +274,12 @@ static int fake_hostent(const char *name, int family, } /* if we don't have 3 dots, it is illegal - * (although inet_pton doesn't think so). + * (although inet_pton doesn't think so). */ if (numdots != 3 || !valid) result = 0; else - result = (ares_inet_pton(AF_INET, name, &in) < 1 ? 0 : 1); + result = (ares_inet_pton(AF_INET, name, &in) < 1 ? 0 : 1); if (result) family = AF_INET; @@ -390,11 +390,11 @@ static int file_lookup(const char *name, int family, struct hostent **host) return ARES_ENOTFOUND; #endif - /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */ - if (ares__is_onion_domain(name)) - return ARES_ENOTFOUND; - - + /* 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/contrib/libs/c-ares/ares_getnameinfo.c b/contrib/libs/c-ares/ares_getnameinfo.c index 53f91ca845..ca90788a70 100644 --- a/contrib/libs/c-ares/ares_getnameinfo.c +++ b/contrib/libs/c-ares/ares_getnameinfo.c @@ -92,13 +92,13 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, if ((sa->sa_family == AF_INET) && (salen == sizeof(struct sockaddr_in))) { - addr = CARES_INADDR_CAST(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 = CARES_INADDR_CAST(struct sockaddr_in6 *, sa); + addr6 = CARES_INADDR_CAST(struct sockaddr_in6 *, sa); port = addr6->sin6_port; } else diff --git a/contrib/libs/c-ares/ares_init.c b/contrib/libs/c-ares/ares_init.c index e06265c6a2..efa6a4470d 100644 --- a/contrib/libs/c-ares/ares_init.c +++ b/contrib/libs/c-ares/ares_init.c @@ -1599,8 +1599,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]=""; + 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) { @@ -2038,7 +2038,7 @@ static int config_lookup(ares_channel channel, const char *str, { char lookups[3], *l; const char *vqualifier p; - int found; + int found; if (altbindch == NULL) altbindch = bindch; @@ -2049,21 +2049,21 @@ static int config_lookup(ares_channel channel, const char *str, */ l = lookups; p = str; - found = 0; + 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; + found = 1; } while (*p && !ISSPACE(*p) && (*p != ',')) p++; while (*p && (ISSPACE(*p) || (*p == ','))) p++; } - if (!found) - return ARES_ENOTINITIALIZED; + if (!found) + return ARES_ENOTINITIALIZED; *l = '\0'; channel->lookups = ares_strdup(lookups); return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM; @@ -2311,7 +2311,7 @@ static int set_search(ares_channel channel, const char *str) channel->ndomains = -1; } /* LCOV_EXCL_STOP */ - channel->domains = ares_strsplit(str, ", ", 1, &cnt); + channel->domains = ares_strsplit(str, ", ", 1, &cnt); channel->ndomains = (int)cnt; if (channel->domains == NULL || channel->ndomains == 0) { channel->domains = NULL; @@ -2449,9 +2449,9 @@ static int ip_addr(const char *ipbuf, ares_ssize_t len, struct in_addr *addr) if (len > 15) return -1; - if (ares_inet_pton(AF_INET, ipbuf, addr) < 1) + if (ares_inet_pton(AF_INET, ipbuf, addr) < 1) return -1; - + return 0; } diff --git a/contrib/libs/c-ares/ares_ipv6.h b/contrib/libs/c-ares/ares_ipv6.h index fdbc21fe8f..84622e2052 100644 --- a/contrib/libs/c-ares/ares_ipv6.h +++ b/contrib/libs/c-ares/ares_ipv6.h @@ -32,13 +32,13 @@ struct sockaddr_in6 }; #endif -typedef union -{ - struct sockaddr sa; - struct sockaddr_in sa4; - struct sockaddr_in6 sa6; -} ares_sockaddr; - +typedef union +{ + struct sockaddr sa; + struct sockaddr_in sa4; + struct sockaddr_in6 sa6; +} ares_sockaddr; + #ifndef HAVE_STRUCT_ADDRINFO struct addrinfo { diff --git a/contrib/libs/c-ares/ares_parse_a_reply.c b/contrib/libs/c-ares/ares_parse_a_reply.c index d8a9e9b578..0ede897bf0 100644 --- a/contrib/libs/c-ares/ares_parse_a_reply.c +++ b/contrib/libs/c-ares/ares_parse_a_reply.c @@ -1,6 +1,6 @@ /* Copyright 1998 by the Massachusetts Institute of Technology. - * Copyright (C) 2019 by Andrew Selivanov + * Copyright (C) 2019 by Andrew Selivanov * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without @@ -51,164 +51,164 @@ 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) + 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) { - ares_free(question_hostname); - - if (naddrttls) - { - *naddrttls = 0; - } - - return status; + goto enomem; } - hostent = ares_malloc(sizeof(struct hostent)); - if (!hostent) + next = ai.nodes; + while (next) { - goto enomem; - } - - next = ai.nodes; - while (next) - { - if (next->ai_family == AF_INET) + if (next->ai_family == AF_INET) { - ++naddrs; + ++naddrs; } - next = next->ai_next; + next = next->ai_next; } - - next_cname = ai.cnames; - while (next_cname) + + next_cname = ai.cnames; + while (next_cname) { - if(next_cname->alias) - ++naliases; - next_cname = next_cname->next; + if(next_cname->alias) + ++naliases; + next_cname = next_cname->next; } - aliases = ares_malloc((naliases + 1) * sizeof(char *)); - if (!aliases) - { - goto enomem; - } + aliases = ares_malloc((naliases + 1) * sizeof(char *)); + if (!aliases) + { + goto enomem; + } - if (naliases) + if (naliases) { - next_cname = ai.cnames; - while (next_cname) + next_cname = ai.cnames; + while (next_cname) { - if(next_cname->alias) - aliases[alias++] = strdup(next_cname->alias); - if(next_cname->ttl < cname_ttl) - cname_ttl = next_cname->ttl; - next_cname = next_cname->next; + if(next_cname->alias) + aliases[alias++] = strdup(next_cname->alias); + if(next_cname->ttl < cname_ttl) + cname_ttl = next_cname->ttl; + next_cname = next_cname->next; } - } + } - aliases[alias] = NULL; + aliases[alias] = NULL; - hostent->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *)); - if (!hostent->h_addr_list) - { - goto enomem; - } + 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; - } + for (i = 0; i < naddrs + 1; ++i) + { + hostent->h_addr_list[i] = NULL; + } - if (ai.cnames) - { - hostent->h_name = strdup(ai.cnames->name); - ares_free(question_hostname); + if (ai.cnames) + { + hostent->h_name = strdup(ai.cnames->name); + ares_free(question_hostname); } - else + else + { + hostent->h_name = question_hostname; + } + + hostent->h_aliases = aliases; + hostent->h_addrtype = AF_INET; + hostent->h_length = sizeof(struct in_addr); + + if (naddrs) { - 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) + addrs = ares_malloc(naddrs * sizeof(struct in_addr)); + if (!addrs) { - goto enomem; + goto enomem; } - - i = 0; - next = ai.nodes; - while (next) + + i = 0; + next = ai.nodes; + while (next) { - if (next->ai_family == AF_INET) + 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) + 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)); + 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; + ++i; } - next = next->ai_next; - } - if (i == 0) - { - ares_free(addrs); + next = next->ai_next; } - } - - if (host) - { - *host = hostent; - } - else + if (i == 0) + { + ares_free(addrs); + } + } + + if (host) { - ares_free_hostent(hostent); + *host = hostent; } - - if (naddrttls) - { - *naddrttls = naddrs; - } - - ares__freeaddrinfo_cnames(ai.cnames); - ares__freeaddrinfo_nodes(ai.nodes); - return ARES_SUCCESS; - -enomem: - ares_free(aliases); - ares_free(hostent); - ares__freeaddrinfo_cnames(ai.cnames); - ares__freeaddrinfo_nodes(ai.nodes); - ares_free(question_hostname); - return ARES_ENOMEM; + else + { + ares_free_hostent(hostent); + } + + if (naddrttls) + { + *naddrttls = naddrs; + } + + ares__freeaddrinfo_cnames(ai.cnames); + ares__freeaddrinfo_nodes(ai.nodes); + return ARES_SUCCESS; + +enomem: + ares_free(aliases); + ares_free(hostent); + ares__freeaddrinfo_cnames(ai.cnames); + ares__freeaddrinfo_nodes(ai.nodes); + ares_free(question_hostname); + return ARES_ENOMEM; } diff --git a/contrib/libs/c-ares/ares_parse_aaaa_reply.c b/contrib/libs/c-ares/ares_parse_aaaa_reply.c index 0d39bfa826..7d30f57372 100644 --- a/contrib/libs/c-ares/ares_parse_aaaa_reply.c +++ b/contrib/libs/c-ares/ares_parse_aaaa_reply.c @@ -1,7 +1,7 @@ /* Copyright 1998 by the Massachusetts Institute of Technology. * Copyright 2005 Dominick Meglio - * Copyright (C) 2019 by Andrew Selivanov + * Copyright (C) 2019 by Andrew Selivanov * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without @@ -53,165 +53,165 @@ 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) + 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) { - ares_free(question_hostname); - - if (naddrttls) - { - *naddrttls = 0; - } - - return status; + goto enomem; } - hostent = ares_malloc(sizeof(struct hostent)); - if (!hostent) + next = ai.nodes; + while (next) { - goto enomem; - } - - next = ai.nodes; - while (next) - { - if(next->ai_family == AF_INET6) + if(next->ai_family == AF_INET6) { - ++naddrs; + ++naddrs; } - next = next->ai_next; + next = next->ai_next; } - - next_cname = ai.cnames; - while (next_cname) + + next_cname = ai.cnames; + while (next_cname) { - if(next_cname->alias) - ++naliases; - next_cname = next_cname->next; + if(next_cname->alias) + ++naliases; + next_cname = next_cname->next; } - aliases = ares_malloc((naliases + 1) * sizeof(char *)); - if (!aliases) + aliases = ares_malloc((naliases + 1) * sizeof(char *)); + if (!aliases) { - goto enomem; - } + goto enomem; + } - if (naliases) - { - next_cname = ai.cnames; - while (next_cname) + if (naliases) + { + next_cname = ai.cnames; + while (next_cname) { - if(next_cname->alias) - aliases[alias++] = strdup(next_cname->alias); - if(next_cname->ttl < cname_ttl) - cname_ttl = next_cname->ttl; - next_cname = next_cname->next; + if(next_cname->alias) + aliases[alias++] = strdup(next_cname->alias); + if(next_cname->ttl < cname_ttl) + cname_ttl = next_cname->ttl; + next_cname = next_cname->next; } - } + } - aliases[alias] = NULL; + aliases[alias] = NULL; - hostent->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *)); - if (!hostent->h_addr_list) - { - goto enomem; - } + 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; - } + for (i = 0; i < naddrs + 1; ++i) + { + hostent->h_addr_list[i] = NULL; + } - if (ai.cnames) - { - hostent->h_name = strdup(ai.cnames->name); - ares_free(question_hostname); + if (ai.cnames) + { + hostent->h_name = strdup(ai.cnames->name); + ares_free(question_hostname); } - else + 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) { - 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) + addrs = ares_malloc(naddrs * sizeof(struct ares_in6_addr)); + if (!addrs) { - goto enomem; + goto enomem; } - - i = 0; - next = ai.nodes; - while (next) + + i = 0; + next = ai.nodes; + while (next) { - if(next->ai_family == AF_INET6) + 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) + 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)); + 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; + ++i; } - next = next->ai_next; - } - - if (i == 0) - { - ares_free(addrs); + next = next->ai_next; } + + if (i == 0) + { + ares_free(addrs); + } } - - if (host) - { - *host = hostent; - } - else + + if (host) { - ares_free_hostent(hostent); + *host = hostent; } - - if (naddrttls) - { - *naddrttls = naddrs; - } - - ares__freeaddrinfo_cnames(ai.cnames); - ares__freeaddrinfo_nodes(ai.nodes); - return ARES_SUCCESS; - -enomem: - ares_free(aliases); - ares_free(hostent); - ares__freeaddrinfo_cnames(ai.cnames); - ares__freeaddrinfo_nodes(ai.nodes); - ares_free(question_hostname); - return ARES_ENOMEM; + else + { + ares_free_hostent(hostent); + } + + if (naddrttls) + { + *naddrttls = naddrs; + } + + ares__freeaddrinfo_cnames(ai.cnames); + ares__freeaddrinfo_nodes(ai.nodes); + return ARES_SUCCESS; + +enomem: + ares_free(aliases); + ares_free(hostent); + ares__freeaddrinfo_cnames(ai.cnames); + ares__freeaddrinfo_nodes(ai.nodes); + ares_free(question_hostname); + return ARES_ENOMEM; } diff --git a/contrib/libs/c-ares/ares_parse_soa_reply.c b/contrib/libs/c-ares/ares_parse_soa_reply.c index 8b84a368db..473b3542a8 100644 --- a/contrib/libs/c-ares/ares_parse_soa_reply.c +++ b/contrib/libs/c-ares/ares_parse_soa_reply.c @@ -48,8 +48,8 @@ ares_parse_soa_reply(const unsigned char *abuf, int alen, long len; char *qname = NULL, *rr_name = NULL; struct ares_soa_reply *soa = NULL; - int qdcount, ancount, qclass; - int status, i, rr_type, rr_class, rr_len; + int qdcount, ancount, qclass; + int status, i, rr_type, rr_class, rr_len; int ttl; if (alen < HFIXEDSZ) @@ -58,12 +58,12 @@ ares_parse_soa_reply(const unsigned char *abuf, int alen, /* parse message header */ qdcount = DNS_HEADER_QDCOUNT(abuf); ancount = DNS_HEADER_ANCOUNT(abuf); - - if (qdcount != 1) - return ARES_EBADRESP; - if (ancount == 0) + + if (qdcount != 1) return ARES_EBADRESP; - + if (ancount == 0) + return ARES_EBADRESP; + aptr = abuf + HFIXEDSZ; /* query name */ @@ -72,113 +72,113 @@ ares_parse_soa_reply(const unsigned char *abuf, int alen, goto failed_stat; aptr += len; - qclass = DNS_QUESTION_TYPE(aptr); - + 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) + /* 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); - if (status != ARES_SUCCESS) - { - ares_free(rr_name); - goto failed_stat; - } - - aptr += len; - if ( aptr + RRFIXEDSZ > abuf + alen ) + /* examine all the records, break and return if found soa */ + for (i = 0; i < ancount; i++) + { + rr_name = NULL; + status = ares__expand_name_for_response (aptr, abuf, alen, &rr_name, &len); + if (status != ARES_SUCCESS) + { + ares_free(rr_name); + goto failed_stat; + } + + aptr += len; + if ( aptr + RRFIXEDSZ > abuf + alen ) { - ares_free(rr_name); - status = ARES_EBADRESP; + 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 ); - ttl = DNS_RR_TTL(aptr); - aptr += RRFIXEDSZ; - if (aptr + rr_len > abuf + alen) - { - ares_free(rr_name); - status = ARES_EBADRESP; - goto failed_stat; - } - if ( rr_class == C_IN && rr_type == T_SOA ) - { - /* allocate result struct */ - soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY); - if (!soa) - { - ares_free(rr_name); - status = ARES_ENOMEM; - goto failed_stat; - } - - /* nsname */ - status = ares__expand_name_for_response(aptr, abuf, alen, &soa->nsname, - &len); - if (status != ARES_SUCCESS) - { - ares_free(rr_name); - goto failed_stat; - } - aptr += len; - - /* hostmaster */ - status = ares__expand_name_for_response(aptr, abuf, alen, - &soa->hostmaster, &len); - if (status != ARES_SUCCESS) - { - 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); - soa->ttl = ttl; - - 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; + rr_type = DNS_RR_TYPE( aptr ); + rr_class = DNS_RR_CLASS( aptr ); + rr_len = DNS_RR_LEN( aptr ); + ttl = DNS_RR_TTL(aptr); + aptr += RRFIXEDSZ; + if (aptr + rr_len > abuf + alen) + { + ares_free(rr_name); + status = ARES_EBADRESP; + goto failed_stat; + } + if ( rr_class == C_IN && rr_type == T_SOA ) + { + /* allocate result struct */ + soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY); + if (!soa) + { + ares_free(rr_name); + status = ARES_ENOMEM; + goto failed_stat; + } + + /* nsname */ + status = ares__expand_name_for_response(aptr, abuf, alen, &soa->nsname, + &len); + if (status != ARES_SUCCESS) + { + ares_free(rr_name); + goto failed_stat; + } + aptr += len; + + /* hostmaster */ + status = ares__expand_name_for_response(aptr, abuf, alen, + &soa->hostmaster, &len); + if (status != ARES_SUCCESS) + { + 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); + soa->ttl = ttl; + + 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 (soa) + ares_free_data(soa); if (qname) ares_free(qname); return status; diff --git a/contrib/libs/c-ares/ares_parse_txt_reply.c b/contrib/libs/c-ares/ares_parse_txt_reply.c index c685dfd052..ef7a1da7fe 100644 --- a/contrib/libs/c-ares/ares_parse_txt_reply.c +++ b/contrib/libs/c-ares/ares_parse_txt_reply.c @@ -114,7 +114,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_class == C_CHAOS) && 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/contrib/libs/c-ares/ares_private.h b/contrib/libs/c-ares/ares_private.h index 3312ed1932..e34c1d5ce9 100644 --- a/contrib/libs/c-ares/ares_private.h +++ b/contrib/libs/c-ares/ares_private.h @@ -50,11 +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)) - +/* 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" @@ -363,51 +363,51 @@ int ares__expand_name_for_response(const unsigned char *encoded, char **s, long *enclen); void ares__init_servers_state(ares_channel channel); void ares__destroy_servers_state(ares_channel channel); -int ares__parse_qtype_reply(const unsigned char* abuf, int alen, int* qtype); -int ares__single_domain(ares_channel channel, const char *name, char **s); -int ares__cat_domain(const char *name, const char *domain, char **s); -int ares__sortaddrinfo(ares_channel channel, struct ares_addrinfo_node *ai_node); -int ares__readaddrinfo(FILE *fp, const char *name, unsigned short port, - const struct ares_addrinfo_hints *hints, - struct ares_addrinfo *ai); - -struct ares_addrinfo *ares__malloc_addrinfo(void); - -struct ares_addrinfo_node *ares__malloc_addrinfo_node(void); -void ares__freeaddrinfo_nodes(struct ares_addrinfo_node *ai_node); - -struct ares_addrinfo_node *ares__append_addrinfo_node(struct ares_addrinfo_node **ai_node); -void ares__addrinfo_cat_nodes(struct ares_addrinfo_node **head, - struct ares_addrinfo_node *tail); - -struct ares_addrinfo_cname *ares__malloc_addrinfo_cname(void); -void ares__freeaddrinfo_cnames(struct ares_addrinfo_cname *ai_cname); - -struct ares_addrinfo_cname *ares__append_addrinfo_cname(struct ares_addrinfo_cname **ai_cname); - -void ares__addrinfo_cat_cnames(struct ares_addrinfo_cname **head, - struct ares_addrinfo_cname *tail); - -int ares__parse_into_addrinfo(const unsigned char *abuf, - int alen, - struct ares_addrinfo *ai); - -int ares__parse_into_addrinfo2(const unsigned char *abuf, - int alen, - char **question_hostname, - struct ares_addrinfo *ai); - +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 -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); +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; } diff --git a/contrib/libs/c-ares/ares_process.c b/contrib/libs/c-ares/ares_process.c index 25095d0f05..0795f5b4c4 100644 --- a/contrib/libs/c-ares/ares_process.c +++ b/contrib/libs/c-ares/ares_process.c @@ -1104,14 +1104,14 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) } /* Acquire a socket. */ - s = ares__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__close_socket(channel, s); + ares__close_socket(channel, s); return -1; } @@ -1128,7 +1128,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__close_socket(channel, s); + ares__close_socket(channel, s); return -1; } #endif @@ -1139,19 +1139,19 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) channel->sock_config_cb_data); if (err < 0) { - ares__close_socket(channel, s); + ares__close_socket(channel, s); return err; } } /* Connect to the server. */ - if (ares__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__close_socket(channel, s); + ares__close_socket(channel, s); return -1; } } @@ -1162,7 +1162,7 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) channel->sock_create_cb_data); if (err < 0) { - ares__close_socket(channel, s); + ares__close_socket(channel, s); return err; } } @@ -1217,14 +1217,14 @@ static int open_udp_socket(ares_channel channel, struct server_state *server) } /* Acquire a socket. */ - s = ares__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__close_socket(channel, s); + ares__close_socket(channel, s); return -1; } @@ -1234,19 +1234,19 @@ static int open_udp_socket(ares_channel channel, struct server_state *server) channel->sock_config_cb_data); if (err < 0) { - ares__close_socket(channel, s); + ares__close_socket(channel, s); return err; } } /* Connect to the server. */ - if (ares__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__close_socket(channel, s); + ares__close_socket(channel, s); return -1; } } @@ -1257,7 +1257,7 @@ static int open_udp_socket(ares_channel channel, struct server_state *server) channel->sock_create_cb_data); if (err < 0) { - ares__close_socket(channel, s); + ares__close_socket(channel, s); return err; } } @@ -1358,13 +1358,13 @@ static int same_address(struct sockaddr *sa, struct ares_addr *aa) { case AF_INET: addr1 = &aa->addrV4; - addr2 = &(CARES_INADDR_CAST(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 = &(CARES_INADDR_CAST(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; @@ -1461,35 +1461,35 @@ void ares__free_query(struct query *query) ares_free(query); } -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) +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); else sclose(s); diff --git a/contrib/libs/c-ares/ares_search.c b/contrib/libs/c-ares/ares_search.c index c4b0424f5b..f33e77f92b 100644 --- a/contrib/libs/c-ares/ares_search.c +++ b/contrib/libs/c-ares/ares_search.c @@ -62,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 = ares__single_domain(channel, name, &s); + status = ares__single_domain(channel, name, &s); if (status != ARES_SUCCESS) { callback(arg, status, 0, NULL, 0); @@ -124,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 = ares__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); @@ -172,7 +172,7 @@ static void search_callback(void *arg, int status, int timeouts, if (squery->next_domain < channel->ndomains) { /* Try the next domain. */ - status = ares__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); @@ -211,7 +211,7 @@ static void end_squery(struct search_query *squery, int status, } /* Concatenate two domains. */ -int ares__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); @@ -230,7 +230,7 @@ int ares__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. */ -int ares__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/contrib/libs/c-ares/ares_version.h b/contrib/libs/c-ares/ares_version.h index c041d574de..1a3871c12b 100644 --- a/contrib/libs/c-ares/ares_version.h +++ b/contrib/libs/c-ares/ares_version.h @@ -3,15 +3,15 @@ #define ARES__VERSION_H /* This is the global package copyright */ -#define ARES_COPYRIGHT "2004 - 2020 Daniel Stenberg, <daniel@haxx.se>." +#define ARES_COPYRIGHT "2004 - 2020 Daniel Stenberg, <daniel@haxx.se>." #define ARES_VERSION_MAJOR 1 -#define ARES_VERSION_MINOR 16 -#define ARES_VERSION_PATCH 1 +#define ARES_VERSION_MINOR 16 +#define ARES_VERSION_PATCH 1 #define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\ (ARES_VERSION_MINOR<<8)|\ (ARES_VERSION_PATCH)) -#define ARES_VERSION_STR "1.16.1" +#define ARES_VERSION_STR "1.16.1" #if (ARES_VERSION >= 0x010700) # define CARES_HAVE_ARES_LIBRARY_INIT 1 diff --git a/contrib/libs/c-ares/test/ares-test-ai.h b/contrib/libs/c-ares/test/ares-test-ai.h index 7cf27e3306..22555d4e8c 100644 --- a/contrib/libs/c-ares/test/ares-test-ai.h +++ b/contrib/libs/c-ares/test/ares-test-ai.h @@ -1,57 +1,57 @@ -#ifndef ARES_TEST_AI_H -#define ARES_TEST_AI_H - -#include <utility> -#include "gtest/gtest.h" -#include "gmock/gmock.h" -#include "ares-test.h" - -namespace ares { -namespace test { - -class MockChannelTestAI - : public MockChannelOptsTest, - public ::testing::WithParamInterface< std::pair<int, bool> > { - public: - MockChannelTestAI() : MockChannelOptsTest(1, GetParam().first, GetParam().second, nullptr, 0) {} -}; - -class MockUDPChannelTestAI - : public MockChannelOptsTest, - public ::testing::WithParamInterface<int> { - public: - MockUDPChannelTestAI() : MockChannelOptsTest(1, GetParam(), false, nullptr, 0) {} -}; - -class MockTCPChannelTestAI - : public MockChannelOptsTest, - public ::testing::WithParamInterface<int> { - public: - MockTCPChannelTestAI() : MockChannelOptsTest(1, GetParam(), true, nullptr, 0) {} -}; - - -// Test fixture that uses a default channel. -class DefaultChannelTestAI : public LibraryTest { - public: - DefaultChannelTestAI() : channel_(nullptr) { - EXPECT_EQ(ARES_SUCCESS, ares_init(&channel_)); - EXPECT_NE(nullptr, channel_); - } - - ~DefaultChannelTestAI() { - ares_destroy(channel_); - channel_ = nullptr; - } - - // Process all pending work on ares-owned file descriptors. - void Process(); - - protected: - ares_channel channel_; -}; - -} -} - -#endif +#ifndef ARES_TEST_AI_H +#define ARES_TEST_AI_H + +#include <utility> +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "ares-test.h" + +namespace ares { +namespace test { + +class MockChannelTestAI + : public MockChannelOptsTest, + public ::testing::WithParamInterface< std::pair<int, bool> > { + public: + MockChannelTestAI() : MockChannelOptsTest(1, GetParam().first, GetParam().second, nullptr, 0) {} +}; + +class MockUDPChannelTestAI + : public MockChannelOptsTest, + public ::testing::WithParamInterface<int> { + public: + MockUDPChannelTestAI() : MockChannelOptsTest(1, GetParam(), false, nullptr, 0) {} +}; + +class MockTCPChannelTestAI + : public MockChannelOptsTest, + public ::testing::WithParamInterface<int> { + public: + MockTCPChannelTestAI() : MockChannelOptsTest(1, GetParam(), true, nullptr, 0) {} +}; + + +// Test fixture that uses a default channel. +class DefaultChannelTestAI : public LibraryTest { + public: + DefaultChannelTestAI() : channel_(nullptr) { + EXPECT_EQ(ARES_SUCCESS, ares_init(&channel_)); + EXPECT_NE(nullptr, channel_); + } + + ~DefaultChannelTestAI() { + ares_destroy(channel_); + channel_ = nullptr; + } + + // Process all pending work on ares-owned file descriptors. + void Process(); + + protected: + ares_channel channel_; +}; + +} +} + +#endif diff --git a/contrib/libs/c-ares/test/ares-test-init.cc b/contrib/libs/c-ares/test/ares-test-init.cc index 842b0e15ac..58fa02d48c 100644 --- a/contrib/libs/c-ares/test/ares-test-init.cc +++ b/contrib/libs/c-ares/test/ares-test-init.cc @@ -495,24 +495,24 @@ CONTAINED_TEST_F(LibraryTest, ContainerSvcConfInit, return HasFailure(); } -NameContentList malformedresolvconflookup = { - {"/etc/resolv.conf", "nameserver 1.2.3.4\n" - "lookup garbage\n"}}; // malformed line -CONTAINED_TEST_F(LibraryTest, ContainerMalformedResolvConfLookup, - "myhostname", "mydomainname.org", malformedresolvconflookup) { - ares_channel channel = nullptr; - EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); - - struct ares_options opts; - int optmask = 0; - ares_save_options(channel, &opts, &optmask); - EXPECT_EQ(std::string("fb"), std::string(opts.lookups)); - ares_destroy_options(&opts); - - ares_destroy(channel); - return HasFailure(); -} - +NameContentList malformedresolvconflookup = { + {"/etc/resolv.conf", "nameserver 1.2.3.4\n" + "lookup garbage\n"}}; // malformed line +CONTAINED_TEST_F(LibraryTest, ContainerMalformedResolvConfLookup, + "myhostname", "mydomainname.org", malformedresolvconflookup) { + ares_channel channel = nullptr; + EXPECT_EQ(ARES_SUCCESS, ares_init(&channel)); + + struct ares_options opts; + int optmask = 0; + ares_save_options(channel, &opts, &optmask); + EXPECT_EQ(std::string("fb"), std::string(opts.lookups)); + ares_destroy_options(&opts); + + ares_destroy(channel); + return HasFailure(); +} + // Failures when expected config filenames are inaccessible. class MakeUnreadable { public: diff --git a/contrib/libs/c-ares/test/ares-test-internal.cc b/contrib/libs/c-ares/test/ares-test-internal.cc index 96d4edece5..cda8d96356 100644 --- a/contrib/libs/c-ares/test/ares-test-internal.cc +++ b/contrib/libs/c-ares/test/ares-test-internal.cc @@ -356,107 +356,107 @@ TEST_F(LibraryTest, GetHostentAllocFail) { fclose(fp); } -TEST_F(DefaultChannelTest, GetAddrInfoHostsPositive) { - TempFile hostsfile("1.2.3.4 example.com \n" - " 2.3.4.5\tgoogle.com www.google.com\twww2.google.com\n" - "#comment\n" - "4.5.6.7\n" - "1.3.5.7 \n" - "::1 ipv6.com"); - EnvValue with_env("CARES_HOSTS", hostsfile.filename()); - struct ares_addrinfo_hints hints = {}; - AddrInfoResult result = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_CANONNAME | ARES_AI_ENVHOSTS | ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "example.com", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - std::stringstream ss; - ss << result.ai_; - EXPECT_EQ("{example.com addr=[1.2.3.4]}", ss.str()); -} - -TEST_F(DefaultChannelTest, GetAddrInfoHostsSpaces) { - TempFile hostsfile("1.2.3.4 example.com \n" - " 2.3.4.5\tgoogle.com www.google.com\twww2.google.com\n" - "#comment\n" - "4.5.6.7\n" - "1.3.5.7 \n" - "::1 ipv6.com"); - EnvValue with_env("CARES_HOSTS", hostsfile.filename()); - struct ares_addrinfo_hints hints = {}; - AddrInfoResult result = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_CANONNAME | ARES_AI_ENVHOSTS | ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "google.com", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - std::stringstream ss; - ss << result.ai_; - EXPECT_EQ("{www.google.com->google.com, www2.google.com->google.com addr=[2.3.4.5]}", ss.str()); -} - -TEST_F(DefaultChannelTest, GetAddrInfoHostsByALias) { - TempFile hostsfile("1.2.3.4 example.com \n" - " 2.3.4.5\tgoogle.com www.google.com\twww2.google.com\n" - "#comment\n" - "4.5.6.7\n" - "1.3.5.7 \n" - "::1 ipv6.com"); - EnvValue with_env("CARES_HOSTS", hostsfile.filename()); - struct ares_addrinfo_hints hints = {}; - AddrInfoResult result = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_CANONNAME | ARES_AI_ENVHOSTS | ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www2.google.com", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - std::stringstream ss; - ss << result.ai_; - EXPECT_EQ("{www.google.com->google.com, www2.google.com->google.com addr=[2.3.4.5]}", ss.str()); -} - -TEST_F(DefaultChannelTest, GetAddrInfoHostsIPV6) { - TempFile hostsfile("1.2.3.4 example.com \n" - " 2.3.4.5\tgoogle.com www.google.com\twww2.google.com\n" - "#comment\n" - "4.5.6.7\n" - "1.3.5.7 \n" - "::1 ipv6.com"); - EnvValue with_env("CARES_HOSTS", hostsfile.filename()); - struct ares_addrinfo_hints hints = {}; - AddrInfoResult result = {}; - hints.ai_family = AF_INET6; - hints.ai_flags = ARES_AI_CANONNAME | ARES_AI_ENVHOSTS | ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "ipv6.com", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - std::stringstream ss; - ss << result.ai_; - EXPECT_EQ("{ipv6.com addr=[[0000:0000:0000:0000:0000:0000:0000:0001]]}", ss.str()); -} - -TEST_F(LibraryTest, GetAddrInfoAllocFail) { - TempFile hostsfile("1.2.3.4 example.com alias1 alias2\n"); - struct ares_addrinfo_hints hints; - unsigned short port = 80; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - - FILE *fp = fopen(hostsfile.filename(), "r"); - ASSERT_NE(nullptr, fp); - - for (int ii = 1; ii <= 3; ii++) { - rewind(fp); - ClearFails(); - SetAllocFail(ii); - struct ares_addrinfo ai; - EXPECT_EQ(ARES_ENOMEM, ares__readaddrinfo(fp, "example.com", port, &hints, &ai)) << ii; - } - fclose(fp); -} - +TEST_F(DefaultChannelTest, GetAddrInfoHostsPositive) { + TempFile hostsfile("1.2.3.4 example.com \n" + " 2.3.4.5\tgoogle.com www.google.com\twww2.google.com\n" + "#comment\n" + "4.5.6.7\n" + "1.3.5.7 \n" + "::1 ipv6.com"); + EnvValue with_env("CARES_HOSTS", hostsfile.filename()); + struct ares_addrinfo_hints hints = {}; + AddrInfoResult result = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_CANONNAME | ARES_AI_ENVHOSTS | ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "example.com", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + std::stringstream ss; + ss << result.ai_; + EXPECT_EQ("{example.com addr=[1.2.3.4]}", ss.str()); +} + +TEST_F(DefaultChannelTest, GetAddrInfoHostsSpaces) { + TempFile hostsfile("1.2.3.4 example.com \n" + " 2.3.4.5\tgoogle.com www.google.com\twww2.google.com\n" + "#comment\n" + "4.5.6.7\n" + "1.3.5.7 \n" + "::1 ipv6.com"); + EnvValue with_env("CARES_HOSTS", hostsfile.filename()); + struct ares_addrinfo_hints hints = {}; + AddrInfoResult result = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_CANONNAME | ARES_AI_ENVHOSTS | ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "google.com", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + std::stringstream ss; + ss << result.ai_; + EXPECT_EQ("{www.google.com->google.com, www2.google.com->google.com addr=[2.3.4.5]}", ss.str()); +} + +TEST_F(DefaultChannelTest, GetAddrInfoHostsByALias) { + TempFile hostsfile("1.2.3.4 example.com \n" + " 2.3.4.5\tgoogle.com www.google.com\twww2.google.com\n" + "#comment\n" + "4.5.6.7\n" + "1.3.5.7 \n" + "::1 ipv6.com"); + EnvValue with_env("CARES_HOSTS", hostsfile.filename()); + struct ares_addrinfo_hints hints = {}; + AddrInfoResult result = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_CANONNAME | ARES_AI_ENVHOSTS | ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www2.google.com", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + std::stringstream ss; + ss << result.ai_; + EXPECT_EQ("{www.google.com->google.com, www2.google.com->google.com addr=[2.3.4.5]}", ss.str()); +} + +TEST_F(DefaultChannelTest, GetAddrInfoHostsIPV6) { + TempFile hostsfile("1.2.3.4 example.com \n" + " 2.3.4.5\tgoogle.com www.google.com\twww2.google.com\n" + "#comment\n" + "4.5.6.7\n" + "1.3.5.7 \n" + "::1 ipv6.com"); + EnvValue with_env("CARES_HOSTS", hostsfile.filename()); + struct ares_addrinfo_hints hints = {}; + AddrInfoResult result = {}; + hints.ai_family = AF_INET6; + hints.ai_flags = ARES_AI_CANONNAME | ARES_AI_ENVHOSTS | ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "ipv6.com", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + std::stringstream ss; + ss << result.ai_; + EXPECT_EQ("{ipv6.com addr=[[0000:0000:0000:0000:0000:0000:0000:0001]]}", ss.str()); +} + +TEST_F(LibraryTest, GetAddrInfoAllocFail) { + TempFile hostsfile("1.2.3.4 example.com alias1 alias2\n"); + struct ares_addrinfo_hints hints; + unsigned short port = 80; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + + FILE *fp = fopen(hostsfile.filename(), "r"); + ASSERT_NE(nullptr, fp); + + for (int ii = 1; ii <= 3; ii++) { + rewind(fp); + ClearFails(); + SetAllocFail(ii); + struct ares_addrinfo ai; + EXPECT_EQ(ARES_ENOMEM, ares__readaddrinfo(fp, "example.com", port, &hints, &ai)) << ii; + } + fclose(fp); +} + TEST(Misc, OnionDomain) { EXPECT_EQ(0, ares__is_onion_domain("onion.no")); EXPECT_EQ(0, ares__is_onion_domain(".onion.no")); @@ -484,23 +484,23 @@ TEST_F(LibraryTest, Striendstr) { const char *str = "plugh"; EXPECT_NE(nullptr, ares_striendstr(str, str)); } -extern "C" int ares__single_domain(ares_channel, const char*, char**); +extern "C" int ares__single_domain(ares_channel, const char*, char**); TEST_F(DefaultChannelTest, SingleDomain) { TempFile aliases("www www.google.com\n"); EnvValue with_env("HOSTALIASES", aliases.filename()); SetAllocSizeFail(128); char *ptr = nullptr; - EXPECT_EQ(ARES_ENOMEM, ares__single_domain(channel_, "www", &ptr)); + EXPECT_EQ(ARES_ENOMEM, ares__single_domain(channel_, "www", &ptr)); channel_->flags |= ARES_FLAG_NOSEARCH|ARES_FLAG_NOALIASES; - EXPECT_EQ(ARES_SUCCESS, ares__single_domain(channel_, "www", &ptr)); + EXPECT_EQ(ARES_SUCCESS, ares__single_domain(channel_, "www", &ptr)); EXPECT_EQ("www", std::string(ptr)); ares_free(ptr); ptr = nullptr; SetAllocFail(1); - EXPECT_EQ(ARES_ENOMEM, ares__single_domain(channel_, "www", &ptr)); + EXPECT_EQ(ARES_ENOMEM, ares__single_domain(channel_, "www", &ptr)); EXPECT_EQ(nullptr, ptr); } #endif diff --git a/contrib/libs/c-ares/test/ares-test-live.cc b/contrib/libs/c-ares/test/ares-test-live.cc index 5510163e95..7d27cbc9d4 100644 --- a/contrib/libs/c-ares/test/ares-test-live.cc +++ b/contrib/libs/c-ares/test/ares-test-live.cc @@ -18,70 +18,70 @@ unsigned char gdns_addr4[4] = {0x08, 0x08, 0x08, 0x08}; unsigned char gdns_addr6[16] = {0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88}; -MATCHER_P(IncludesAtLeastNumAddresses, n, "") { - if(!arg) - return false; - int cnt = 0; - for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) - cnt++; - return cnt >= n; -} - -MATCHER_P(OnlyIncludesAddrType, addrtype, "") { - if(!arg) - return false; - for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) - if (ai->ai_family != addrtype) - return false; - return true; -} - -MATCHER_P(IncludesAddrType, addrtype, "") { - if(!arg) - return false; - for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) - if (ai->ai_family == addrtype) - return true; - return false; -} - -//VIRT_NONVIRT_TEST_F(DefaultChannelTest, LiveGetAddrInfoV4) { - //struct ares_addrinfo_hints hints = {}; - //hints.ai_family = AF_INET; - //AddrInfoResult result; - //ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - //Process(); - //EXPECT_TRUE(result.done_); - //EXPECT_EQ(ARES_SUCCESS, result.status_); - //EXPECT_THAT(result.ai_, IncludesAtLeastNumAddresses(1)); - //EXPECT_THAT(result.ai_, OnlyIncludesAddrType(AF_INET)); -//} - -//VIRT_NONVIRT_TEST_F(DefaultChannelTest, LiveGetAddrInfoV6) { - //struct ares_addrinfo_hints hints = {}; - //hints.ai_family = AF_INET6; - //AddrInfoResult result; - //ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - //Process(); - //EXPECT_TRUE(result.done_); - //EXPECT_EQ(ARES_SUCCESS, result.status_); - //EXPECT_THAT(result.ai_, IncludesAtLeastNumAddresses(1)); - //EXPECT_THAT(result.ai_, OnlyIncludesAddrType(AF_INET6)); -//} - -//VIRT_NONVIRT_TEST_F(DefaultChannelTest, LiveGetAddrInfoUnspec) { - //struct ares_addrinfo_hints hints = {}; - //hints.ai_family = AF_UNSPEC; - //AddrInfoResult result; - //ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - //Process(); - //EXPECT_TRUE(result.done_); - //EXPECT_EQ(ARES_SUCCESS, result.status_); - //EXPECT_THAT(result.ai_, IncludesAtLeastNumAddresses(2)); - //EXPECT_THAT(result.ai_, IncludesAddrType(AF_INET6)); - //EXPECT_THAT(result.ai_, IncludesAddrType(AF_INET)); -//} - +MATCHER_P(IncludesAtLeastNumAddresses, n, "") { + if(!arg) + return false; + int cnt = 0; + for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) + cnt++; + return cnt >= n; +} + +MATCHER_P(OnlyIncludesAddrType, addrtype, "") { + if(!arg) + return false; + for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) + if (ai->ai_family != addrtype) + return false; + return true; +} + +MATCHER_P(IncludesAddrType, addrtype, "") { + if(!arg) + return false; + for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) + if (ai->ai_family == addrtype) + return true; + return false; +} + +//VIRT_NONVIRT_TEST_F(DefaultChannelTest, LiveGetAddrInfoV4) { + //struct ares_addrinfo_hints hints = {}; + //hints.ai_family = AF_INET; + //AddrInfoResult result; + //ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + //Process(); + //EXPECT_TRUE(result.done_); + //EXPECT_EQ(ARES_SUCCESS, result.status_); + //EXPECT_THAT(result.ai_, IncludesAtLeastNumAddresses(1)); + //EXPECT_THAT(result.ai_, OnlyIncludesAddrType(AF_INET)); +//} + +//VIRT_NONVIRT_TEST_F(DefaultChannelTest, LiveGetAddrInfoV6) { + //struct ares_addrinfo_hints hints = {}; + //hints.ai_family = AF_INET6; + //AddrInfoResult result; + //ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + //Process(); + //EXPECT_TRUE(result.done_); + //EXPECT_EQ(ARES_SUCCESS, result.status_); + //EXPECT_THAT(result.ai_, IncludesAtLeastNumAddresses(1)); + //EXPECT_THAT(result.ai_, OnlyIncludesAddrType(AF_INET6)); +//} + +//VIRT_NONVIRT_TEST_F(DefaultChannelTest, LiveGetAddrInfoUnspec) { + //struct ares_addrinfo_hints hints = {}; + //hints.ai_family = AF_UNSPEC; + //AddrInfoResult result; + //ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + //Process(); + //EXPECT_TRUE(result.done_); + //EXPECT_EQ(ARES_SUCCESS, result.status_); + //EXPECT_THAT(result.ai_, IncludesAtLeastNumAddresses(2)); + //EXPECT_THAT(result.ai_, IncludesAddrType(AF_INET6)); + //EXPECT_THAT(result.ai_, IncludesAddrType(AF_INET)); +//} + VIRT_NONVIRT_TEST_F(DefaultChannelTest, DISABLED_LiveGetHostByNameV4) { HostResult result; ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result); @@ -214,11 +214,11 @@ TEST_P(DefaultChannelModeTest, LiveGetLocalhostByAddrV4) { EXPECT_EQ(ARES_SUCCESS, result.status_); EXPECT_LT(0, (int)result.host_.addrs_.size()); EXPECT_EQ(AF_INET, result.host_.addrtype_); - // oddly, travis does not resolve to localhost, but a random hostname starting with travis-job - if (result.host_.name_.find("travis-job") == std::string::npos) { - EXPECT_NE(std::string::npos, - result.host_.name_.find("localhost")); - } + // oddly, travis does not resolve to localhost, but a random hostname starting with travis-job + if (result.host_.name_.find("travis-job") == std::string::npos) { + EXPECT_NE(std::string::npos, + result.host_.name_.find("localhost")); + } } } @@ -234,9 +234,9 @@ TEST_P(DefaultChannelModeTest, LiveGetLocalhostByAddrV6) { EXPECT_EQ(ARES_SUCCESS, result.status_); EXPECT_LT(0, (int)result.host_.addrs_.size()); EXPECT_EQ(AF_INET6, result.host_.addrtype_); - const std::string& name = result.host_.name_; - EXPECT_TRUE(std::string::npos != name.find("localhost") || - std::string::npos != name.find("ip6-loopback")); + const std::string& name = result.host_.name_; + EXPECT_TRUE(std::string::npos != name.find("localhost") || + std::string::npos != name.find("ip6-loopback")); } } @@ -696,54 +696,54 @@ TEST_F(DefaultChannelTest, VerifySocketFunctionCallback) { } -TEST_F(DefaultChannelTest, LiveSetServers) { - struct ares_addr_node server1; - struct ares_addr_node server2; - server1.next = &server2; - server1.family = AF_INET; - server1.addr.addr4.s_addr = htonl(0x01020304); - server2.next = nullptr; - server2.family = AF_INET; - server2.addr.addr4.s_addr = htonl(0x02030405); - - // Change not allowed while request is pending - HostResult result; - ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result); - EXPECT_EQ(ARES_ENOTIMP, ares_set_servers(channel_, &server1)); - ares_cancel(channel_); -} - -TEST_F(DefaultChannelTest, LiveSetServersPorts) { - struct ares_addr_port_node server1; - struct ares_addr_port_node server2; - server1.next = &server2; - server1.family = AF_INET; - server1.addr.addr4.s_addr = htonl(0x01020304); - server1.udp_port = 111; - server1.tcp_port = 111; - server2.next = nullptr; - server2.family = AF_INET; - server2.addr.addr4.s_addr = htonl(0x02030405); - server2.udp_port = 0; - server2.tcp_port = 0;; - EXPECT_EQ(ARES_ENODATA, ares_set_servers_ports(nullptr, &server1)); - - // Change not allowed while request is pending - HostResult result; - ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result); - EXPECT_EQ(ARES_ENOTIMP, ares_set_servers_ports(channel_, &server1)); - ares_cancel(channel_); -} - -TEST_F(DefaultChannelTest, LiveSetServersCSV) { - // Change not allowed while request is pending - HostResult result; - ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result); - EXPECT_EQ(ARES_ENOTIMP, ares_set_servers_csv(channel_, "1.2.3.4,2.3.4.5")); - EXPECT_EQ(ARES_ENOTIMP, ares_set_servers_ports_csv(channel_, "1.2.3.4:56,2.3.4.5:67")); - ares_cancel(channel_); -} - - +TEST_F(DefaultChannelTest, LiveSetServers) { + struct ares_addr_node server1; + struct ares_addr_node server2; + server1.next = &server2; + server1.family = AF_INET; + server1.addr.addr4.s_addr = htonl(0x01020304); + server2.next = nullptr; + server2.family = AF_INET; + server2.addr.addr4.s_addr = htonl(0x02030405); + + // Change not allowed while request is pending + HostResult result; + ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result); + EXPECT_EQ(ARES_ENOTIMP, ares_set_servers(channel_, &server1)); + ares_cancel(channel_); +} + +TEST_F(DefaultChannelTest, LiveSetServersPorts) { + struct ares_addr_port_node server1; + struct ares_addr_port_node server2; + server1.next = &server2; + server1.family = AF_INET; + server1.addr.addr4.s_addr = htonl(0x01020304); + server1.udp_port = 111; + server1.tcp_port = 111; + server2.next = nullptr; + server2.family = AF_INET; + server2.addr.addr4.s_addr = htonl(0x02030405); + server2.udp_port = 0; + server2.tcp_port = 0;; + EXPECT_EQ(ARES_ENODATA, ares_set_servers_ports(nullptr, &server1)); + + // Change not allowed while request is pending + HostResult result; + ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result); + EXPECT_EQ(ARES_ENOTIMP, ares_set_servers_ports(channel_, &server1)); + ares_cancel(channel_); +} + +TEST_F(DefaultChannelTest, LiveSetServersCSV) { + // Change not allowed while request is pending + HostResult result; + ares_gethostbyname(channel_, "www.google.com.", AF_INET, HostCallback, &result); + EXPECT_EQ(ARES_ENOTIMP, ares_set_servers_csv(channel_, "1.2.3.4,2.3.4.5")); + EXPECT_EQ(ARES_ENOTIMP, ares_set_servers_ports_csv(channel_, "1.2.3.4:56,2.3.4.5:67")); + ares_cancel(channel_); +} + + } // namespace test } // namespace ares diff --git a/contrib/libs/c-ares/test/ares-test-misc.cc b/contrib/libs/c-ares/test/ares-test-misc.cc index 6fc28a8f97..c79f67ba1f 100644 --- a/contrib/libs/c-ares/test/ares-test-misc.cc +++ b/contrib/libs/c-ares/test/ares-test-misc.cc @@ -277,15 +277,15 @@ TEST_F(DefaultChannelTest, HostByNameFileOnionDomain) { ares_gethostbyname_file(channel_, "dontleak.onion", AF_INET, &h)); } -TEST_F(DefaultChannelTest, GetAddrinfoOnionDomain) { - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_UNSPEC; - ares_getaddrinfo(channel_, "dontleak.onion", NULL, &hints, AddrInfoCallback, &result); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_ENOTFOUND, result.status_); -} - +TEST_F(DefaultChannelTest, GetAddrinfoOnionDomain) { + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_UNSPEC; + ares_getaddrinfo(channel_, "dontleak.onion", NULL, &hints, AddrInfoCallback, &result); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_ENOTFOUND, result.status_); +} + // Interesting question: should tacking on a search domain let the query // through? It seems safer to reject it because "supersecret.onion.search" // still leaks information about the query to malicious resolvers. diff --git a/contrib/libs/c-ares/test/ares-test-mock-ai.cc b/contrib/libs/c-ares/test/ares-test-mock-ai.cc index d0df867fef..700333b826 100644 --- a/contrib/libs/c-ares/test/ares-test-mock-ai.cc +++ b/contrib/libs/c-ares/test/ares-test-mock-ai.cc @@ -1,723 +1,723 @@ -#include "ares-test-ai.h" -#include "dns-proto.h" - -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif - -#include <sstream> -#include <vector> - -using testing::InvokeWithoutArgs; -using testing::DoAll; - -namespace ares { -namespace test { - -MATCHER_P(IncludesNumAddresses, n, "") { - if(!arg) - return false; - int cnt = 0; - for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) - cnt++; - return n == cnt; -} - -MATCHER_P(IncludesV4Address, address, "") { - if(!arg) - return false; - in_addr addressnum = {}; - if (!ares_inet_pton(AF_INET, address, &addressnum)) - return false; // wrong number format? - for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family != AF_INET) - continue; - if (reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_addr.s_addr == - addressnum.s_addr) - return true; // found - } - return false; -} - -MATCHER_P(IncludesV6Address, address, "") { - if(!arg) - return false; - in6_addr addressnum = {}; - if (!ares_inet_pton(AF_INET6, address, &addressnum)) { - return false; // wrong number format? - } - for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family != AF_INET6) - continue; - if (!memcmp( - reinterpret_cast<sockaddr_in6*>(ai->ai_addr)->sin6_addr.s6_addr, - addressnum.s6_addr, sizeof(addressnum.s6_addr))) - return true; // found - } - return false; -} - -// UDP only so mock server doesn't get confused by concatenated requests -TEST_P(MockUDPChannelTestAI, GetAddrInfoParallelLookups) { - DNSPacket rsp1; - rsp1.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)) - .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5})); - ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp1)); - DNSPacket rsp2; - rsp2.set_response().set_aa() - .add_question(new DNSQuestion("www.example.com", ns_t_a)) - .add_answer(new DNSARR("www.example.com", 100, {1, 2, 3, 4})); - ON_CALL(server_, OnRequest("www.example.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp2)); - - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - AddrInfoResult result1; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result1); - AddrInfoResult result2; - ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result2); - AddrInfoResult result3; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result3); - Process(); - - EXPECT_TRUE(result1.done_); - EXPECT_EQ(result1.status_, ARES_SUCCESS); - EXPECT_THAT(result1.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result1.ai_, IncludesV4Address("2.3.4.5")); - - EXPECT_TRUE(result2.done_); - EXPECT_EQ(result2.status_, ARES_SUCCESS); - EXPECT_THAT(result2.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result2.ai_, IncludesV4Address("1.2.3.4")); - - EXPECT_TRUE(result3.done_); - EXPECT_EQ(result3.status_, ARES_SUCCESS); - EXPECT_THAT(result3.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result3.ai_, IncludesV4Address("2.3.4.5")); -} - -// UDP to TCP specific test -TEST_P(MockUDPChannelTestAI, TruncationRetry) { - DNSPacket rsptruncated; - rsptruncated.set_response().set_aa().set_tc() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - DNSPacket rspok; - rspok.set_response() - .add_question(new DNSQuestion("www.google.com", ns_t_a)) - .add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4})); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rsptruncated)) - .WillOnce(SetReply(&server_, &rspok)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(result.status_, ARES_SUCCESS); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4")); -} - -// TCP only to prevent retries -TEST_P(MockTCPChannelTestAI, MalformedResponse) { - std::vector<byte> one = {0x01}; - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReplyData(&server_, one)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_ETIMEOUT, result.status_); -} - -TEST_P(MockTCPChannelTestAI, FormErrResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_formerr); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_EFORMERR, result.status_); -} - -TEST_P(MockTCPChannelTestAI, ServFailResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_servfail); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - // ARES_FLAG_NOCHECKRESP not set, so SERVFAIL consumed - EXPECT_EQ(ARES_ECONNREFUSED, result.status_); -} - -TEST_P(MockTCPChannelTestAI, NotImplResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_notimpl); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - // ARES_FLAG_NOCHECKRESP not set, so NOTIMPL consumed - EXPECT_EQ(ARES_ECONNREFUSED, result.status_); -} - -TEST_P(MockTCPChannelTestAI, RefusedResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_refused); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - // ARES_FLAG_NOCHECKRESP not set, so REFUSED consumed - EXPECT_EQ(ARES_ECONNREFUSED, result.status_); -} - -TEST_P(MockTCPChannelTestAI, YXDomainResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_yxdomain); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_ENODATA, result.status_); -} - -class MockExtraOptsTestAI - : public MockChannelOptsTest, - public ::testing::WithParamInterface< std::pair<int, bool> > { - public: - MockExtraOptsTestAI() - : MockChannelOptsTest(1, GetParam().first, GetParam().second, - FillOptions(&opts_), - ARES_OPT_SOCK_SNDBUF|ARES_OPT_SOCK_RCVBUF) {} - static struct ares_options* FillOptions(struct ares_options * opts) { - memset(opts, 0, sizeof(struct ares_options)); - // Set a few options that affect socket communications - opts->socket_send_buffer_size = 514; - opts->socket_receive_buffer_size = 514; - return opts; - } - private: - struct ares_options opts_; -}; - -TEST_P(MockExtraOptsTestAI, SimpleQuery) { - ares_set_local_ip4(channel_, 0x7F000001); - byte addr6[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; - ares_set_local_ip6(channel_, addr6); - ares_set_local_dev(channel_, "dummy"); - - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)) - .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5})); - ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_SUCCESS, result.status_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); -} - -class MockFlagsChannelOptsTestAI - : public MockChannelOptsTest, - public ::testing::WithParamInterface< std::pair<int, bool> > { - public: - MockFlagsChannelOptsTestAI(int flags) - : MockChannelOptsTest(1, GetParam().first, GetParam().second, - FillOptions(&opts_, flags), ARES_OPT_FLAGS) {} - static struct ares_options* FillOptions(struct ares_options * opts, int flags) { - memset(opts, 0, sizeof(struct ares_options)); - opts->flags = flags; - return opts; - } - private: - struct ares_options opts_; -}; - -class MockNoCheckRespChannelTestAI : public MockFlagsChannelOptsTestAI { - public: - MockNoCheckRespChannelTestAI() : MockFlagsChannelOptsTestAI(ARES_FLAG_NOCHECKRESP) {} -}; - -TEST_P(MockNoCheckRespChannelTestAI, ServFailResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_servfail); - ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_ESERVFAIL, result.status_); -} - -TEST_P(MockNoCheckRespChannelTestAI, NotImplResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_notimpl); - ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_ENOTIMP, result.status_); -} - -TEST_P(MockNoCheckRespChannelTestAI, RefusedResponse) { - DNSPacket rsp; - rsp.set_response().set_aa() - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - rsp.set_rcode(ns_r_refused); - ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_EREFUSED, result.status_); -} - -TEST_P(MockChannelTestAI, FamilyV6) { - DNSPacket rsp6; - rsp6.set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_aaaa)) - .add_answer(new DNSAaaaRR("example.com", 100, - {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03})); - ON_CALL(server_, OnRequest("example.com", ns_t_aaaa)) - .WillByDefault(SetReply(&server_, &rsp6)); - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET6; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "example.com.", NULL, &hints, - AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303")); -} - -TEST_P(MockChannelTestAI, FamilyV4) { - DNSPacket rsp4; - rsp4.set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_a)) - .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5})); - ON_CALL(server_, OnRequest("example.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp4)); - AddrInfoResult result = {}; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "example.com.", NULL, &hints, - AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); -} - -TEST_P(MockChannelTestAI, FamilyV4_MultipleAddresses) { - DNSPacket rsp4; - rsp4.set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_a)) - .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5})) - .add_answer(new DNSARR("example.com", 100, {7, 8, 9, 0})); - ON_CALL(server_, OnRequest("example.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp4)); - AddrInfoResult result = {}; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "example.com.", NULL, &hints, - AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - std::stringstream ss; - ss << result.ai_; - EXPECT_EQ("{addr=[2.3.4.5], addr=[7.8.9.0]}", ss.str()); -} - -TEST_P(MockChannelTestAI, FamilyUnspecified) { - DNSPacket rsp6; - rsp6.set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_aaaa)) - .add_answer(new DNSAaaaRR("example.com", 100, - {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03})); - ON_CALL(server_, OnRequest("example.com", ns_t_aaaa)) - .WillByDefault(SetReply(&server_, &rsp6)); - DNSPacket rsp4; - rsp4.set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_a)) - .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5})); - ON_CALL(server_, OnRequest("example.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp4)); - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_UNSPEC; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "example.com.", NULL, &hints, - AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(2)); - EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); - EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303")); -} - -class MockEDNSChannelTestAI : public MockFlagsChannelOptsTestAI { - public: - MockEDNSChannelTestAI() : MockFlagsChannelOptsTestAI(ARES_FLAG_EDNS) {} -}; - -TEST_P(MockEDNSChannelTestAI, RetryWithoutEDNS) { - DNSPacket rspfail; - rspfail.set_response().set_aa().set_rcode(ns_r_servfail) - .add_question(new DNSQuestion("www.google.com", ns_t_a)); - DNSPacket rspok; - rspok.set_response() - .add_question(new DNSQuestion("www.google.com", ns_t_a)) - .add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4})); - EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) - .WillOnce(SetReply(&server_, &rspfail)) - .WillOnce(SetReply(&server_, &rspok)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4")); -} - -TEST_P(MockChannelTestAI, SearchDomains) { - DNSPacket nofirst; - nofirst.set_response().set_aa().set_rcode(ns_r_nxdomain) - .add_question(new DNSQuestion("www.first.com", ns_t_a)); - ON_CALL(server_, OnRequest("www.first.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &nofirst)); - DNSPacket nosecond; - nosecond.set_response().set_aa().set_rcode(ns_r_nxdomain) - .add_question(new DNSQuestion("www.second.org", ns_t_a)); - ON_CALL(server_, OnRequest("www.second.org", ns_t_a)) - .WillByDefault(SetReply(&server_, &nosecond)); - DNSPacket yesthird; - yesthird.set_response().set_aa() - .add_question(new DNSQuestion("www.third.gov", ns_t_a)) - .add_answer(new DNSARR("www.third.gov", 0x0200, {2, 3, 4, 5})); - ON_CALL(server_, OnRequest("www.third.gov", ns_t_a)) - .WillByDefault(SetReply(&server_, &yesthird)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); -} - -TEST_P(MockChannelTestAI, SearchDomainsServFailOnAAAA) { - DNSPacket nofirst; - nofirst.set_response().set_aa().set_rcode(ns_r_nxdomain) - .add_question(new DNSQuestion("www.first.com", ns_t_aaaa)); - ON_CALL(server_, OnRequest("www.first.com", ns_t_aaaa)) - .WillByDefault(SetReply(&server_, &nofirst)); - DNSPacket nofirst4; - nofirst4.set_response().set_aa().set_rcode(ns_r_nxdomain) - .add_question(new DNSQuestion("www.first.com", ns_t_a)); - ON_CALL(server_, OnRequest("www.first.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &nofirst4)); - - DNSPacket nosecond; - nosecond.set_response().set_aa().set_rcode(ns_r_nxdomain) - .add_question(new DNSQuestion("www.second.org", ns_t_aaaa)); - ON_CALL(server_, OnRequest("www.second.org", ns_t_aaaa)) - .WillByDefault(SetReply(&server_, &nosecond)); - DNSPacket yessecond4; - yessecond4.set_response().set_aa() - .add_question(new DNSQuestion("www.second.org", ns_t_a)) - .add_answer(new DNSARR("www.second.org", 0x0200, {2, 3, 4, 5})); - ON_CALL(server_, OnRequest("www.second.org", ns_t_a)) - .WillByDefault(SetReply(&server_, &yessecond4)); - - DNSPacket failthird; - failthird.set_response().set_aa().set_rcode(ns_r_servfail) - .add_question(new DNSQuestion("www.third.gov", ns_t_aaaa)); - ON_CALL(server_, OnRequest("www.third.gov", ns_t_aaaa)) - .WillByDefault(SetReply(&server_, &failthird)); - DNSPacket failthird4; - failthird4.set_response().set_aa().set_rcode(ns_r_servfail) - .add_question(new DNSQuestion("www.third.gov", ns_t_a)); - ON_CALL(server_, OnRequest("www.third.gov", ns_t_a)) - .WillByDefault(SetReply(&server_, &failthird4)); - - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_UNSPEC; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); -} - -class MockMultiServerChannelTestAI - : public MockChannelOptsTest, - public ::testing::WithParamInterface< std::pair<int, bool> > { - public: - MockMultiServerChannelTestAI(bool rotate) - : MockChannelOptsTest(3, GetParam().first, GetParam().second, nullptr, rotate ? ARES_OPT_ROTATE : ARES_OPT_NOROTATE) {} - void CheckExample() { - AddrInfoResult result; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(result.status_, ARES_SUCCESS); - EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); - EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); - } -}; - -class RotateMultiMockTestAI : public MockMultiServerChannelTestAI { - public: - RotateMultiMockTestAI() : MockMultiServerChannelTestAI(true) {} -}; - -class NoRotateMultiMockTestAI : public MockMultiServerChannelTestAI { - public: - NoRotateMultiMockTestAI() : MockMultiServerChannelTestAI(false) {} -}; - - -TEST_P(RotateMultiMockTestAI, ThirdServer) { - struct ares_options opts = {0}; - int optmask = 0; - EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel_, &opts, &optmask)); - EXPECT_EQ(0, (optmask & ARES_OPT_NOROTATE)); - ares_destroy_options(&opts); - - DNSPacket servfailrsp; - servfailrsp.set_response().set_aa().set_rcode(ns_r_servfail) - .add_question(new DNSQuestion("www.example.com", ns_t_a)); - DNSPacket notimplrsp; - notimplrsp.set_response().set_aa().set_rcode(ns_r_notimpl) - .add_question(new DNSQuestion("www.example.com", ns_t_a)); - DNSPacket okrsp; - okrsp.set_response().set_aa() - .add_question(new DNSQuestion("www.example.com", ns_t_a)) - .add_answer(new DNSARR("www.example.com", 100, {2,3,4,5})); - - EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); - EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); - EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[2].get(), &okrsp)); - CheckExample(); - - // Second time around, starts from server [1]. - EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[1].get(), &servfailrsp)); - EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[2].get(), ¬implrsp)); - EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[0].get(), &okrsp)); - CheckExample(); - - // Third time around, starts from server [2]. - EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[2].get(), &servfailrsp)); - EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[0].get(), ¬implrsp)); - EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[1].get(), &okrsp)); - CheckExample(); -} - -TEST_P(NoRotateMultiMockTestAI, ThirdServer) { - struct ares_options opts = {0}; - int optmask = 0; - EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel_, &opts, &optmask)); - EXPECT_EQ(ARES_OPT_NOROTATE, (optmask & ARES_OPT_NOROTATE)); - ares_destroy_options(&opts); - - DNSPacket servfailrsp; - servfailrsp.set_response().set_aa().set_rcode(ns_r_servfail) - .add_question(new DNSQuestion("www.example.com", ns_t_a)); - DNSPacket notimplrsp; - notimplrsp.set_response().set_aa().set_rcode(ns_r_notimpl) - .add_question(new DNSQuestion("www.example.com", ns_t_a)); - DNSPacket okrsp; - okrsp.set_response().set_aa() - .add_question(new DNSQuestion("www.example.com", ns_t_a)) - .add_answer(new DNSARR("www.example.com", 100, {2,3,4,5})); - - EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); - EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); - EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[2].get(), &okrsp)); - CheckExample(); - - // Second time around, still starts from server [0]. - EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); - EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); - EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[2].get(), &okrsp)); - CheckExample(); - - // Third time around, still starts from server [0]. - EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); - EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); - EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) - .WillOnce(SetReply(servers_[2].get(), &okrsp)); - CheckExample(); -} - -TEST_P(MockChannelTestAI, FamilyV4ServiceName) { - DNSPacket rsp4; - rsp4.set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_a)) - .add_answer(new DNSARR("example.com", 100, {1, 1, 1, 1})) - .add_answer(new DNSARR("example.com", 100, {2, 2, 2, 2})); - ON_CALL(server_, OnRequest("example.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &rsp4)); - AddrInfoResult result = {}; - struct ares_addrinfo_hints hints = {}; - hints.ai_family = AF_INET; - hints.ai_flags = ARES_AI_NOSORT; - ares_getaddrinfo(channel_, "example.com", "http", &hints, AddrInfoCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - std::stringstream ss; - ss << result.ai_; - EXPECT_EQ("{addr=[1.1.1.1:80], addr=[2.2.2.2:80]}", ss.str()); -} - -// force-tcp does currently not work, possibly test DNS server swallows -// bytes from second query -//INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockChannelTestAI, -// ::testing::ValuesIn(ares::test::families_modes)); -//const std::vector<std::pair<int, bool>> both_families_udponly = { -// std::make_pair<int, bool>(AF_INET, false), -// std::make_pair<int, bool>(AF_INET6, false) -//}; -INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockChannelTestAI, - ::testing::Values(std::make_pair<int, bool>(AF_INET, false))); - -INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockUDPChannelTestAI, - ::testing::ValuesIn(ares::test::families)); - -INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockTCPChannelTestAI, - ::testing::ValuesIn(ares::test::families)); - -INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockExtraOptsTestAI, - ::testing::ValuesIn(ares::test::families_modes)); - -INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockNoCheckRespChannelTestAI, - ::testing::ValuesIn(ares::test::families_modes)); - -INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockEDNSChannelTestAI, - ::testing::ValuesIn(ares::test::families_modes)); - -INSTANTIATE_TEST_CASE_P(TransportModesAI, RotateMultiMockTestAI, - ::testing::ValuesIn(ares::test::families_modes)); - -INSTANTIATE_TEST_CASE_P(TransportModesAI, NoRotateMultiMockTestAI, - ::testing::ValuesIn(ares::test::families_modes)); - - -} // namespace test -} // namespace ares +#include "ares-test-ai.h" +#include "dns-proto.h" + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#include <sstream> +#include <vector> + +using testing::InvokeWithoutArgs; +using testing::DoAll; + +namespace ares { +namespace test { + +MATCHER_P(IncludesNumAddresses, n, "") { + if(!arg) + return false; + int cnt = 0; + for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) + cnt++; + return n == cnt; +} + +MATCHER_P(IncludesV4Address, address, "") { + if(!arg) + return false; + in_addr addressnum = {}; + if (!ares_inet_pton(AF_INET, address, &addressnum)) + return false; // wrong number format? + for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) { + if (ai->ai_family != AF_INET) + continue; + if (reinterpret_cast<sockaddr_in*>(ai->ai_addr)->sin_addr.s_addr == + addressnum.s_addr) + return true; // found + } + return false; +} + +MATCHER_P(IncludesV6Address, address, "") { + if(!arg) + return false; + in6_addr addressnum = {}; + if (!ares_inet_pton(AF_INET6, address, &addressnum)) { + return false; // wrong number format? + } + for (const ares_addrinfo_node* ai = arg->nodes; ai != NULL; ai = ai->ai_next) { + if (ai->ai_family != AF_INET6) + continue; + if (!memcmp( + reinterpret_cast<sockaddr_in6*>(ai->ai_addr)->sin6_addr.s6_addr, + addressnum.s6_addr, sizeof(addressnum.s6_addr))) + return true; // found + } + return false; +} + +// UDP only so mock server doesn't get confused by concatenated requests +TEST_P(MockUDPChannelTestAI, GetAddrInfoParallelLookups) { + DNSPacket rsp1; + rsp1.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)) + .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5})); + ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp1)); + DNSPacket rsp2; + rsp2.set_response().set_aa() + .add_question(new DNSQuestion("www.example.com", ns_t_a)) + .add_answer(new DNSARR("www.example.com", 100, {1, 2, 3, 4})); + ON_CALL(server_, OnRequest("www.example.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp2)); + + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + AddrInfoResult result1; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result1); + AddrInfoResult result2; + ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result2); + AddrInfoResult result3; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result3); + Process(); + + EXPECT_TRUE(result1.done_); + EXPECT_EQ(result1.status_, ARES_SUCCESS); + EXPECT_THAT(result1.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result1.ai_, IncludesV4Address("2.3.4.5")); + + EXPECT_TRUE(result2.done_); + EXPECT_EQ(result2.status_, ARES_SUCCESS); + EXPECT_THAT(result2.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result2.ai_, IncludesV4Address("1.2.3.4")); + + EXPECT_TRUE(result3.done_); + EXPECT_EQ(result3.status_, ARES_SUCCESS); + EXPECT_THAT(result3.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result3.ai_, IncludesV4Address("2.3.4.5")); +} + +// UDP to TCP specific test +TEST_P(MockUDPChannelTestAI, TruncationRetry) { + DNSPacket rsptruncated; + rsptruncated.set_response().set_aa().set_tc() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + DNSPacket rspok; + rspok.set_response() + .add_question(new DNSQuestion("www.google.com", ns_t_a)) + .add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4})); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rsptruncated)) + .WillOnce(SetReply(&server_, &rspok)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(result.status_, ARES_SUCCESS); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4")); +} + +// TCP only to prevent retries +TEST_P(MockTCPChannelTestAI, MalformedResponse) { + std::vector<byte> one = {0x01}; + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReplyData(&server_, one)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_ETIMEOUT, result.status_); +} + +TEST_P(MockTCPChannelTestAI, FormErrResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_formerr); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_EFORMERR, result.status_); +} + +TEST_P(MockTCPChannelTestAI, ServFailResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_servfail); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + // ARES_FLAG_NOCHECKRESP not set, so SERVFAIL consumed + EXPECT_EQ(ARES_ECONNREFUSED, result.status_); +} + +TEST_P(MockTCPChannelTestAI, NotImplResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_notimpl); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + // ARES_FLAG_NOCHECKRESP not set, so NOTIMPL consumed + EXPECT_EQ(ARES_ECONNREFUSED, result.status_); +} + +TEST_P(MockTCPChannelTestAI, RefusedResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_refused); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + // ARES_FLAG_NOCHECKRESP not set, so REFUSED consumed + EXPECT_EQ(ARES_ECONNREFUSED, result.status_); +} + +TEST_P(MockTCPChannelTestAI, YXDomainResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_yxdomain); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_ENODATA, result.status_); +} + +class MockExtraOptsTestAI + : public MockChannelOptsTest, + public ::testing::WithParamInterface< std::pair<int, bool> > { + public: + MockExtraOptsTestAI() + : MockChannelOptsTest(1, GetParam().first, GetParam().second, + FillOptions(&opts_), + ARES_OPT_SOCK_SNDBUF|ARES_OPT_SOCK_RCVBUF) {} + static struct ares_options* FillOptions(struct ares_options * opts) { + memset(opts, 0, sizeof(struct ares_options)); + // Set a few options that affect socket communications + opts->socket_send_buffer_size = 514; + opts->socket_receive_buffer_size = 514; + return opts; + } + private: + struct ares_options opts_; +}; + +TEST_P(MockExtraOptsTestAI, SimpleQuery) { + ares_set_local_ip4(channel_, 0x7F000001); + byte addr6[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + ares_set_local_ip6(channel_, addr6); + ares_set_local_dev(channel_, "dummy"); + + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)) + .add_answer(new DNSARR("www.google.com", 100, {2, 3, 4, 5})); + ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_SUCCESS, result.status_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); +} + +class MockFlagsChannelOptsTestAI + : public MockChannelOptsTest, + public ::testing::WithParamInterface< std::pair<int, bool> > { + public: + MockFlagsChannelOptsTestAI(int flags) + : MockChannelOptsTest(1, GetParam().first, GetParam().second, + FillOptions(&opts_, flags), ARES_OPT_FLAGS) {} + static struct ares_options* FillOptions(struct ares_options * opts, int flags) { + memset(opts, 0, sizeof(struct ares_options)); + opts->flags = flags; + return opts; + } + private: + struct ares_options opts_; +}; + +class MockNoCheckRespChannelTestAI : public MockFlagsChannelOptsTestAI { + public: + MockNoCheckRespChannelTestAI() : MockFlagsChannelOptsTestAI(ARES_FLAG_NOCHECKRESP) {} +}; + +TEST_P(MockNoCheckRespChannelTestAI, ServFailResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_servfail); + ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_ESERVFAIL, result.status_); +} + +TEST_P(MockNoCheckRespChannelTestAI, NotImplResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_notimpl); + ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_ENOTIMP, result.status_); +} + +TEST_P(MockNoCheckRespChannelTestAI, RefusedResponse) { + DNSPacket rsp; + rsp.set_response().set_aa() + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + rsp.set_rcode(ns_r_refused); + ON_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_EREFUSED, result.status_); +} + +TEST_P(MockChannelTestAI, FamilyV6) { + DNSPacket rsp6; + rsp6.set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_aaaa)) + .add_answer(new DNSAaaaRR("example.com", 100, + {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03})); + ON_CALL(server_, OnRequest("example.com", ns_t_aaaa)) + .WillByDefault(SetReply(&server_, &rsp6)); + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET6; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "example.com.", NULL, &hints, + AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303")); +} + +TEST_P(MockChannelTestAI, FamilyV4) { + DNSPacket rsp4; + rsp4.set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_a)) + .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5})); + ON_CALL(server_, OnRequest("example.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp4)); + AddrInfoResult result = {}; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "example.com.", NULL, &hints, + AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); +} + +TEST_P(MockChannelTestAI, FamilyV4_MultipleAddresses) { + DNSPacket rsp4; + rsp4.set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_a)) + .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5})) + .add_answer(new DNSARR("example.com", 100, {7, 8, 9, 0})); + ON_CALL(server_, OnRequest("example.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp4)); + AddrInfoResult result = {}; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "example.com.", NULL, &hints, + AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + std::stringstream ss; + ss << result.ai_; + EXPECT_EQ("{addr=[2.3.4.5], addr=[7.8.9.0]}", ss.str()); +} + +TEST_P(MockChannelTestAI, FamilyUnspecified) { + DNSPacket rsp6; + rsp6.set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_aaaa)) + .add_answer(new DNSAaaaRR("example.com", 100, + {0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03})); + ON_CALL(server_, OnRequest("example.com", ns_t_aaaa)) + .WillByDefault(SetReply(&server_, &rsp6)); + DNSPacket rsp4; + rsp4.set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_a)) + .add_answer(new DNSARR("example.com", 100, {2, 3, 4, 5})); + ON_CALL(server_, OnRequest("example.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp4)); + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_UNSPEC; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "example.com.", NULL, &hints, + AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(2)); + EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); + EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303")); +} + +class MockEDNSChannelTestAI : public MockFlagsChannelOptsTestAI { + public: + MockEDNSChannelTestAI() : MockFlagsChannelOptsTestAI(ARES_FLAG_EDNS) {} +}; + +TEST_P(MockEDNSChannelTestAI, RetryWithoutEDNS) { + DNSPacket rspfail; + rspfail.set_response().set_aa().set_rcode(ns_r_servfail) + .add_question(new DNSQuestion("www.google.com", ns_t_a)); + DNSPacket rspok; + rspok.set_response() + .add_question(new DNSQuestion("www.google.com", ns_t_a)) + .add_answer(new DNSARR("www.google.com", 100, {1, 2, 3, 4})); + EXPECT_CALL(server_, OnRequest("www.google.com", ns_t_a)) + .WillOnce(SetReply(&server_, &rspfail)) + .WillOnce(SetReply(&server_, &rspok)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.google.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("1.2.3.4")); +} + +TEST_P(MockChannelTestAI, SearchDomains) { + DNSPacket nofirst; + nofirst.set_response().set_aa().set_rcode(ns_r_nxdomain) + .add_question(new DNSQuestion("www.first.com", ns_t_a)); + ON_CALL(server_, OnRequest("www.first.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &nofirst)); + DNSPacket nosecond; + nosecond.set_response().set_aa().set_rcode(ns_r_nxdomain) + .add_question(new DNSQuestion("www.second.org", ns_t_a)); + ON_CALL(server_, OnRequest("www.second.org", ns_t_a)) + .WillByDefault(SetReply(&server_, &nosecond)); + DNSPacket yesthird; + yesthird.set_response().set_aa() + .add_question(new DNSQuestion("www.third.gov", ns_t_a)) + .add_answer(new DNSARR("www.third.gov", 0x0200, {2, 3, 4, 5})); + ON_CALL(server_, OnRequest("www.third.gov", ns_t_a)) + .WillByDefault(SetReply(&server_, &yesthird)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); +} + +TEST_P(MockChannelTestAI, SearchDomainsServFailOnAAAA) { + DNSPacket nofirst; + nofirst.set_response().set_aa().set_rcode(ns_r_nxdomain) + .add_question(new DNSQuestion("www.first.com", ns_t_aaaa)); + ON_CALL(server_, OnRequest("www.first.com", ns_t_aaaa)) + .WillByDefault(SetReply(&server_, &nofirst)); + DNSPacket nofirst4; + nofirst4.set_response().set_aa().set_rcode(ns_r_nxdomain) + .add_question(new DNSQuestion("www.first.com", ns_t_a)); + ON_CALL(server_, OnRequest("www.first.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &nofirst4)); + + DNSPacket nosecond; + nosecond.set_response().set_aa().set_rcode(ns_r_nxdomain) + .add_question(new DNSQuestion("www.second.org", ns_t_aaaa)); + ON_CALL(server_, OnRequest("www.second.org", ns_t_aaaa)) + .WillByDefault(SetReply(&server_, &nosecond)); + DNSPacket yessecond4; + yessecond4.set_response().set_aa() + .add_question(new DNSQuestion("www.second.org", ns_t_a)) + .add_answer(new DNSARR("www.second.org", 0x0200, {2, 3, 4, 5})); + ON_CALL(server_, OnRequest("www.second.org", ns_t_a)) + .WillByDefault(SetReply(&server_, &yessecond4)); + + DNSPacket failthird; + failthird.set_response().set_aa().set_rcode(ns_r_servfail) + .add_question(new DNSQuestion("www.third.gov", ns_t_aaaa)); + ON_CALL(server_, OnRequest("www.third.gov", ns_t_aaaa)) + .WillByDefault(SetReply(&server_, &failthird)); + DNSPacket failthird4; + failthird4.set_response().set_aa().set_rcode(ns_r_servfail) + .add_question(new DNSQuestion("www.third.gov", ns_t_a)); + ON_CALL(server_, OnRequest("www.third.gov", ns_t_a)) + .WillByDefault(SetReply(&server_, &failthird4)); + + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_UNSPEC; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); +} + +class MockMultiServerChannelTestAI + : public MockChannelOptsTest, + public ::testing::WithParamInterface< std::pair<int, bool> > { + public: + MockMultiServerChannelTestAI(bool rotate) + : MockChannelOptsTest(3, GetParam().first, GetParam().second, nullptr, rotate ? ARES_OPT_ROTATE : ARES_OPT_NOROTATE) {} + void CheckExample() { + AddrInfoResult result; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "www.example.com.", NULL, &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(result.status_, ARES_SUCCESS); + EXPECT_THAT(result.ai_, IncludesNumAddresses(1)); + EXPECT_THAT(result.ai_, IncludesV4Address("2.3.4.5")); + } +}; + +class RotateMultiMockTestAI : public MockMultiServerChannelTestAI { + public: + RotateMultiMockTestAI() : MockMultiServerChannelTestAI(true) {} +}; + +class NoRotateMultiMockTestAI : public MockMultiServerChannelTestAI { + public: + NoRotateMultiMockTestAI() : MockMultiServerChannelTestAI(false) {} +}; + + +TEST_P(RotateMultiMockTestAI, ThirdServer) { + struct ares_options opts = {0}; + int optmask = 0; + EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel_, &opts, &optmask)); + EXPECT_EQ(0, (optmask & ARES_OPT_NOROTATE)); + ares_destroy_options(&opts); + + DNSPacket servfailrsp; + servfailrsp.set_response().set_aa().set_rcode(ns_r_servfail) + .add_question(new DNSQuestion("www.example.com", ns_t_a)); + DNSPacket notimplrsp; + notimplrsp.set_response().set_aa().set_rcode(ns_r_notimpl) + .add_question(new DNSQuestion("www.example.com", ns_t_a)); + DNSPacket okrsp; + okrsp.set_response().set_aa() + .add_question(new DNSQuestion("www.example.com", ns_t_a)) + .add_answer(new DNSARR("www.example.com", 100, {2,3,4,5})); + + EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); + EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); + EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[2].get(), &okrsp)); + CheckExample(); + + // Second time around, starts from server [1]. + EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[1].get(), &servfailrsp)); + EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[2].get(), ¬implrsp)); + EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[0].get(), &okrsp)); + CheckExample(); + + // Third time around, starts from server [2]. + EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[2].get(), &servfailrsp)); + EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[0].get(), ¬implrsp)); + EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[1].get(), &okrsp)); + CheckExample(); +} + +TEST_P(NoRotateMultiMockTestAI, ThirdServer) { + struct ares_options opts = {0}; + int optmask = 0; + EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel_, &opts, &optmask)); + EXPECT_EQ(ARES_OPT_NOROTATE, (optmask & ARES_OPT_NOROTATE)); + ares_destroy_options(&opts); + + DNSPacket servfailrsp; + servfailrsp.set_response().set_aa().set_rcode(ns_r_servfail) + .add_question(new DNSQuestion("www.example.com", ns_t_a)); + DNSPacket notimplrsp; + notimplrsp.set_response().set_aa().set_rcode(ns_r_notimpl) + .add_question(new DNSQuestion("www.example.com", ns_t_a)); + DNSPacket okrsp; + okrsp.set_response().set_aa() + .add_question(new DNSQuestion("www.example.com", ns_t_a)) + .add_answer(new DNSARR("www.example.com", 100, {2,3,4,5})); + + EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); + EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); + EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[2].get(), &okrsp)); + CheckExample(); + + // Second time around, still starts from server [0]. + EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); + EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); + EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[2].get(), &okrsp)); + CheckExample(); + + // Third time around, still starts from server [0]. + EXPECT_CALL(*servers_[0], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[0].get(), &servfailrsp)); + EXPECT_CALL(*servers_[1], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[1].get(), ¬implrsp)); + EXPECT_CALL(*servers_[2], OnRequest("www.example.com", ns_t_a)) + .WillOnce(SetReply(servers_[2].get(), &okrsp)); + CheckExample(); +} + +TEST_P(MockChannelTestAI, FamilyV4ServiceName) { + DNSPacket rsp4; + rsp4.set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_a)) + .add_answer(new DNSARR("example.com", 100, {1, 1, 1, 1})) + .add_answer(new DNSARR("example.com", 100, {2, 2, 2, 2})); + ON_CALL(server_, OnRequest("example.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &rsp4)); + AddrInfoResult result = {}; + struct ares_addrinfo_hints hints = {}; + hints.ai_family = AF_INET; + hints.ai_flags = ARES_AI_NOSORT; + ares_getaddrinfo(channel_, "example.com", "http", &hints, AddrInfoCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + std::stringstream ss; + ss << result.ai_; + EXPECT_EQ("{addr=[1.1.1.1:80], addr=[2.2.2.2:80]}", ss.str()); +} + +// force-tcp does currently not work, possibly test DNS server swallows +// bytes from second query +//INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockChannelTestAI, +// ::testing::ValuesIn(ares::test::families_modes)); +//const std::vector<std::pair<int, bool>> both_families_udponly = { +// std::make_pair<int, bool>(AF_INET, false), +// std::make_pair<int, bool>(AF_INET6, false) +//}; +INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockChannelTestAI, + ::testing::Values(std::make_pair<int, bool>(AF_INET, false))); + +INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockUDPChannelTestAI, + ::testing::ValuesIn(ares::test::families)); + +INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockTCPChannelTestAI, + ::testing::ValuesIn(ares::test::families)); + +INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockExtraOptsTestAI, + ::testing::ValuesIn(ares::test::families_modes)); + +INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockNoCheckRespChannelTestAI, + ::testing::ValuesIn(ares::test::families_modes)); + +INSTANTIATE_TEST_CASE_P(AddressFamiliesAI, MockEDNSChannelTestAI, + ::testing::ValuesIn(ares::test::families_modes)); + +INSTANTIATE_TEST_CASE_P(TransportModesAI, RotateMultiMockTestAI, + ::testing::ValuesIn(ares::test::families_modes)); + +INSTANTIATE_TEST_CASE_P(TransportModesAI, NoRotateMultiMockTestAI, + ::testing::ValuesIn(ares::test::families_modes)); + + +} // namespace test +} // namespace ares diff --git a/contrib/libs/c-ares/test/ares-test-mock.cc b/contrib/libs/c-ares/test/ares-test-mock.cc index 80e9fc02b0..99a3c6a2bf 100644 --- a/contrib/libs/c-ares/test/ares-test-mock.cc +++ b/contrib/libs/c-ares/test/ares-test-mock.cc @@ -51,7 +51,7 @@ TEST_P(MockChannelTest, Basic) { } // UDP only so mock server doesn't get confused by concatenated requests -TEST_P(MockUDPChannelTest, GetHostByNameParallelLookups) { +TEST_P(MockUDPChannelTest, GetHostByNameParallelLookups) { DNSPacket rsp1; rsp1.set_response().set_aa() .add_question(new DNSQuestion("www.google.com", ns_t_a)) @@ -936,21 +936,21 @@ TEST_P(MockChannelTest, GetHostByNameDestroyRelative) { EXPECT_EQ(0, result.timeouts_); } -TEST_P(MockChannelTest, GetHostByNameCNAMENoData) { - DNSPacket response; - response.set_response().set_aa() - .add_question(new DNSQuestion("cname.first.com", ns_t_a)) - .add_answer(new DNSCnameRR("cname.first.com", 100, "a.first.com")); - ON_CALL(server_, OnRequest("cname.first.com", ns_t_a)) - .WillByDefault(SetReply(&server_, &response)); - - HostResult result; - ares_gethostbyname(channel_, "cname.first.com", AF_INET, HostCallback, &result); - Process(); - EXPECT_TRUE(result.done_); - EXPECT_EQ(ARES_ENODATA, result.status_); -} - +TEST_P(MockChannelTest, GetHostByNameCNAMENoData) { + DNSPacket response; + response.set_response().set_aa() + .add_question(new DNSQuestion("cname.first.com", ns_t_a)) + .add_answer(new DNSCnameRR("cname.first.com", 100, "a.first.com")); + ON_CALL(server_, OnRequest("cname.first.com", ns_t_a)) + .WillByDefault(SetReply(&server_, &response)); + + HostResult result; + ares_gethostbyname(channel_, "cname.first.com", AF_INET, HostCallback, &result); + Process(); + EXPECT_TRUE(result.done_); + EXPECT_EQ(ARES_ENODATA, result.status_); +} + TEST_P(MockChannelTest, GetHostByAddrDestroy) { unsigned char gdns_addr4[4] = {0x08, 0x08, 0x08, 0x08}; HostResult result; diff --git a/contrib/libs/c-ares/test/ares-test-parse-a.cc b/contrib/libs/c-ares/test/ares-test-parse-a.cc index 7f6a987c13..6cdaba58ac 100644 --- a/contrib/libs/c-ares/test/ares-test-parse-a.cc +++ b/contrib/libs/c-ares/test/ares-test-parse-a.cc @@ -11,14 +11,14 @@ TEST_F(LibraryTest, ParseAReplyOK) { DNSPacket pkt; pkt.set_qid(0x1234).set_response().set_aa() .add_question(new DNSQuestion("example.com", ns_t_a)) - .add_answer(new DNSARR("example.com", 0x01020304, {2,3,4,5})) - .add_answer(new DNSAaaaRR("example.com", 0x01020304, {0,0,0,0,0,0,0,0,0,0,0,0,2,3,4,5})); + .add_answer(new DNSARR("example.com", 0x01020304, {2,3,4,5})) + .add_answer(new DNSAaaaRR("example.com", 0x01020304, {0,0,0,0,0,0,0,0,0,0,0,0,2,3,4,5})); std::vector<byte> data = { 0x12, 0x34, // qid 0x84, // response + query + AA + not-TC + not-RD 0x00, // not-RA + not-Z + not-AD + not-CD + rc=NoError 0x00, 0x01, // num questions - 0x00, 0x02, // num answer RRs + 0x00, 0x02, // num answer RRs 0x00, 0x00, // num authority RRs 0x00, 0x00, // num additional RRs // Question @@ -36,15 +36,15 @@ TEST_F(LibraryTest, ParseAReplyOK) { 0x01, 0x02, 0x03, 0x04, // TTL 0x00, 0x04, // rdata length 0x02, 0x03, 0x04, 0x05, - // Answer 2 - 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', - 0x03, 'c', 'o', 'm', - 0x00, - 0x00, 0x1c, // RR type - 0x00, 0x01, // class IN - 0x01, 0x02, 0x03, 0x04, // TTL - 0x00, 0x10, // rdata length - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x04, 0x05, + // Answer 2 + 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', + 0x03, 'c', 'o', 'm', + 0x00, + 0x00, 0x1c, // RR type + 0x00, 0x01, // class IN + 0x01, 0x02, 0x03, 0x04, // TTL + 0x00, 0x10, // rdata length + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x04, 0x05, }; EXPECT_EQ(data, pkt.data()); struct hostent *host = nullptr; @@ -78,7 +78,7 @@ TEST_F(LibraryTest, ParseMalformedAReply) { 0x84, // [2] response + query + AA + not-TC + not-RD 0x00, // [3] not-RA + not-Z + not-AD + not-CD + rc=NoError 0x00, 0x01, // [4:6) num questions - 0x00, 0x02, // [6:8) num answer RRs + 0x00, 0x02, // [6:8) num answer RRs 0x00, 0x00, // [8:10) num authority RRs 0x00, 0x00, // [10:12) num additional RRs // Question @@ -131,16 +131,16 @@ TEST_F(LibraryTest, ParseAReplyNoData) { // Again but with a CNAME. pkt.add_answer(new DNSCnameRR("example.com", 200, "c.example.com")); - data = pkt.data(); - // Expect success as per https://github.com/c-ares/c-ares/commit/2c63440127feed70ccefb148b8f938a2df6c15f8 - EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(), + data = pkt.data(); + // Expect success as per https://github.com/c-ares/c-ares/commit/2c63440127feed70ccefb148b8f938a2df6c15f8 + EXPECT_EQ(ARES_SUCCESS, ares_parse_a_reply(data.data(), data.size(), &host, info, &count)); EXPECT_EQ(0, count); - EXPECT_NE(nullptr, host); - std::stringstream ss; - ss << HostEnt(host); - EXPECT_EQ("{'c.example.com' aliases=[example.com] addrs=[]}", ss.str()); - ares_free_hostent(host); + EXPECT_NE(nullptr, host); + std::stringstream ss; + ss << HostEnt(host); + EXPECT_EQ("{'c.example.com' aliases=[example.com] addrs=[]}", ss.str()); + ares_free_hostent(host); } TEST_F(LibraryTest, ParseAReplyVariantA) { diff --git a/contrib/libs/c-ares/test/ares-test-parse-aaaa.cc b/contrib/libs/c-ares/test/ares-test-parse-aaaa.cc index 1314c837a6..371438fca3 100644 --- a/contrib/libs/c-ares/test/ares-test-parse-aaaa.cc +++ b/contrib/libs/c-ares/test/ares-test-parse-aaaa.cc @@ -13,8 +13,8 @@ TEST_F(LibraryTest, ParseAaaaReplyOK) { .add_question(new DNSQuestion("example.com", ns_t_aaaa)) .add_answer(new DNSAaaaRR("example.com", 100, {0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, - 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04})) - .add_answer(new DNSARR("example.com", 0x01020304, {2,3,4,5})); + 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04})) + .add_answer(new DNSARR("example.com", 0x01020304, {2,3,4,5})); std::vector<byte> data = pkt.data(); struct hostent *host = nullptr; struct ares_addr6ttl info[5]; diff --git a/contrib/libs/c-ares/test/ares-test-parse-soa-any.cc b/contrib/libs/c-ares/test/ares-test-parse-soa-any.cc index 804c6a0060..2e2c3f9db4 100644 --- a/contrib/libs/c-ares/test/ares-test-parse-soa-any.cc +++ b/contrib/libs/c-ares/test/ares-test-parse-soa-any.cc @@ -1,111 +1,111 @@ -#include "ares-test.h" -#include "dns-proto.h" - -#include <sstream> -#include <vector> - -namespace ares { -namespace test { - -TEST_F(LibraryTest, ParseSoaAnyReplyOK) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_any))\ - .add_answer(new DNSARR("example.com", 0x01020304, {2,3,4,5})) - .add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")) - .add_answer(new DNSMxRR("example.com", 100, 200, "mx2.example.com")) - .add_answer(new DNSSoaRR("example.com", 100, - "soa1.example.com", "fred.example.com", - 1, 2, 3, 4, 5)); - std::vector<byte> data = pkt.data(); - - struct ares_soa_reply* soa = nullptr; - EXPECT_EQ(ARES_SUCCESS, ares_parse_soa_reply(data.data(), data.size(), &soa)); - ASSERT_NE(nullptr, soa); - EXPECT_EQ("soa1.example.com", std::string(soa->nsname)); - EXPECT_EQ("fred.example.com", std::string(soa->hostmaster)); - EXPECT_EQ(1, soa->serial); - EXPECT_EQ(2, soa->refresh); - EXPECT_EQ(3, soa->retry); - EXPECT_EQ(4, soa->expire); - EXPECT_EQ(5, soa->minttl); - ares_free_data(soa); -} - -TEST_F(LibraryTest, ParseSoaAnyReplyErrors) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_any)) - .add_answer(new DNSSoaRR("example.com", 100, - "soa1.example.com", "fred.example.com", - 1, 2, 3, 4, 5)); - std::vector<byte> data; - struct ares_soa_reply* soa = nullptr; - - // No question. - pkt.questions_.clear(); - data = pkt.data(); - EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), data.size(), &soa)); - pkt.add_question(new DNSQuestion("example.com", ns_t_any)); - -#ifdef DISABLED - // Question != answer - pkt.questions_.clear(); - pkt.add_question(new DNSQuestion("Axample.com", ns_t_any)); - data = pkt.data(); - EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), data.size(), &soa)); - pkt.questions_.clear(); - pkt.add_question(new DNSQuestion("example.com", ns_t_any)); -#endif - - // Two questions - pkt.add_question(new DNSQuestion("example.com", ns_t_any)); - data = pkt.data(); - EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), data.size(), &soa)); - pkt.questions_.clear(); - pkt.add_question(new DNSQuestion("example.com", ns_t_any)); - - // Wrong sort of answer. - pkt.answers_.clear(); - pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); - data = pkt.data(); - EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), data.size(), &soa)); - pkt.answers_.clear(); - pkt.add_answer(new DNSSoaRR("example.com", 100, - "soa1.example.com", "fred.example.com", - 1, 2, 3, 4, 5)); - - // No answer. - pkt.answers_.clear(); - data = pkt.data(); - EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), data.size(), &soa)); - pkt.add_answer(new DNSSoaRR("example.com", 100, - "soa1.example.com", "fred.example.com", - 1, 2, 3, 4, 5)); - - // Truncated packets. - data = pkt.data(); - for (size_t len = 1; len < data.size(); len++) { - EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), len, &soa)); - } -} - -TEST_F(LibraryTest, ParseSoaAnyReplyAllocFail) { - DNSPacket pkt; - pkt.set_qid(0x1234).set_response().set_aa() - .add_question(new DNSQuestion("example.com", ns_t_any)) - .add_answer(new DNSSoaRR("example.com", 100, - "soa1.example.com", "fred.example.com", - 1, 2, 3, 4, 5)); - std::vector<byte> data = pkt.data(); - struct ares_soa_reply* soa = nullptr; - - for (int ii = 1; ii <= 5; ii++) { - ClearFails(); - SetAllocFail(ii); - EXPECT_EQ(ARES_ENOMEM, ares_parse_soa_reply(data.data(), data.size(), &soa)) << ii; - } -} - -} // namespace test -} // namespace ares +#include "ares-test.h" +#include "dns-proto.h" + +#include <sstream> +#include <vector> + +namespace ares { +namespace test { + +TEST_F(LibraryTest, ParseSoaAnyReplyOK) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_any))\ + .add_answer(new DNSARR("example.com", 0x01020304, {2,3,4,5})) + .add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")) + .add_answer(new DNSMxRR("example.com", 100, 200, "mx2.example.com")) + .add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + std::vector<byte> data = pkt.data(); + + struct ares_soa_reply* soa = nullptr; + EXPECT_EQ(ARES_SUCCESS, ares_parse_soa_reply(data.data(), data.size(), &soa)); + ASSERT_NE(nullptr, soa); + EXPECT_EQ("soa1.example.com", std::string(soa->nsname)); + EXPECT_EQ("fred.example.com", std::string(soa->hostmaster)); + EXPECT_EQ(1, soa->serial); + EXPECT_EQ(2, soa->refresh); + EXPECT_EQ(3, soa->retry); + EXPECT_EQ(4, soa->expire); + EXPECT_EQ(5, soa->minttl); + ares_free_data(soa); +} + +TEST_F(LibraryTest, ParseSoaAnyReplyErrors) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_any)) + .add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + std::vector<byte> data; + struct ares_soa_reply* soa = nullptr; + + // No question. + pkt.questions_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.add_question(new DNSQuestion("example.com", ns_t_any)); + +#ifdef DISABLED + // Question != answer + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("Axample.com", ns_t_any)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", ns_t_any)); +#endif + + // Two questions + pkt.add_question(new DNSQuestion("example.com", ns_t_any)); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.questions_.clear(); + pkt.add_question(new DNSQuestion("example.com", ns_t_any)); + + // Wrong sort of answer. + pkt.answers_.clear(); + pkt.add_answer(new DNSMxRR("example.com", 100, 100, "mx1.example.com")); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.answers_.clear(); + pkt.add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + + // No answer. + pkt.answers_.clear(); + data = pkt.data(); + EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), data.size(), &soa)); + pkt.add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + + // Truncated packets. + data = pkt.data(); + for (size_t len = 1; len < data.size(); len++) { + EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), len, &soa)); + } +} + +TEST_F(LibraryTest, ParseSoaAnyReplyAllocFail) { + DNSPacket pkt; + pkt.set_qid(0x1234).set_response().set_aa() + .add_question(new DNSQuestion("example.com", ns_t_any)) + .add_answer(new DNSSoaRR("example.com", 100, + "soa1.example.com", "fred.example.com", + 1, 2, 3, 4, 5)); + std::vector<byte> data = pkt.data(); + struct ares_soa_reply* soa = nullptr; + + for (int ii = 1; ii <= 5; ii++) { + ClearFails(); + SetAllocFail(ii); + EXPECT_EQ(ARES_ENOMEM, ares_parse_soa_reply(data.data(), data.size(), &soa)) << ii; + } +} + +} // namespace test +} // namespace ares diff --git a/contrib/libs/c-ares/test/ares-test-parse-soa.cc b/contrib/libs/c-ares/test/ares-test-parse-soa.cc index c0ffaaed50..3ef95ec7f1 100644 --- a/contrib/libs/c-ares/test/ares-test-parse-soa.cc +++ b/contrib/libs/c-ares/test/ares-test-parse-soa.cc @@ -50,7 +50,7 @@ TEST_F(LibraryTest, ParseSoaReplyErrors) { pkt.questions_.clear(); pkt.add_question(new DNSQuestion("Axample.com", ns_t_soa)); data = pkt.data(); - EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), data.size(), &soa)); + EXPECT_EQ(ARES_EBADRESP, ares_parse_soa_reply(data.data(), data.size(), &soa)); pkt.questions_.clear(); pkt.add_question(new DNSQuestion("example.com", ns_t_soa)); #endif diff --git a/contrib/libs/c-ares/test/ares-test.cc b/contrib/libs/c-ares/test/ares-test.cc index ec4b460549..8c85b4ef93 100644 --- a/contrib/libs/c-ares/test/ares-test.cc +++ b/contrib/libs/c-ares/test/ares-test.cc @@ -1,5 +1,5 @@ #include "ares-test.h" -#include "ares-test-ai.h" +#include "ares-test-ai.h" #include "dns-proto.h" // Include ares internal files for DNS protocol details @@ -565,79 +565,79 @@ void HostCallback(void *data, int status, int timeouts, if (verbose) std::cerr << "HostCallback(" << *result << ")" << std::endl; } -std::ostream& operator<<(std::ostream& os, const AddrInfoResult& result) { - os << '{'; - if (result.done_ && result.ai_) { - os << StatusToString(result.status_) << " " << result.ai_; - } else { - os << "(incomplete)"; - } - os << '}'; - return os; -} - -std::ostream& operator<<(std::ostream& os, const AddrInfo& ai) { - os << '{'; - if (ai == nullptr) { - os << "nullptr}"; - return os; - } - - struct ares_addrinfo_cname *next_cname = ai->cnames; - while(next_cname) { - if(next_cname->alias) { - os << next_cname->alias << "->"; - } - if(next_cname->name) { - os << next_cname->name; - } - if((next_cname = next_cname->next)) - os << ", "; - else - os << " "; - } - - struct ares_addrinfo_node *next = ai->nodes; - while(next) { - //if(next->ai_canonname) { - //os << "'" << next->ai_canonname << "' "; - //} - unsigned short port = 0; - os << "addr=["; - if(next->ai_family == AF_INET) { - sockaddr_in* sin = (sockaddr_in*)next->ai_addr; - port = ntohs(sin->sin_port); - os << AddressToString(&sin->sin_addr, 4); - } - else if (next->ai_family == AF_INET6) { - sockaddr_in6* sin = (sockaddr_in6*)next->ai_addr; - port = ntohs(sin->sin6_port); - os << "[" << AddressToString(&sin->sin6_addr, 16) << "]"; - } - else - os << "unknown family"; - if(port) { - os << ":" << port; - } - os << "]"; - if((next = next->ai_next)) - os << ", "; - } - os << '}'; - return os; -} - -void AddrInfoCallback(void *data, int status, int timeouts, - struct ares_addrinfo *ai) { - EXPECT_NE(nullptr, data); - AddrInfoResult* result = reinterpret_cast<AddrInfoResult*>(data); - result->done_ = true; - result->status_ = status; - result->timeouts_= timeouts; - result->ai_ = AddrInfo(ai); - if (verbose) std::cerr << "AddrInfoCallback(" << *result << ")" << std::endl; -} - +std::ostream& operator<<(std::ostream& os, const AddrInfoResult& result) { + os << '{'; + if (result.done_ && result.ai_) { + os << StatusToString(result.status_) << " " << result.ai_; + } else { + os << "(incomplete)"; + } + os << '}'; + return os; +} + +std::ostream& operator<<(std::ostream& os, const AddrInfo& ai) { + os << '{'; + if (ai == nullptr) { + os << "nullptr}"; + return os; + } + + struct ares_addrinfo_cname *next_cname = ai->cnames; + while(next_cname) { + if(next_cname->alias) { + os << next_cname->alias << "->"; + } + if(next_cname->name) { + os << next_cname->name; + } + if((next_cname = next_cname->next)) + os << ", "; + else + os << " "; + } + + struct ares_addrinfo_node *next = ai->nodes; + while(next) { + //if(next->ai_canonname) { + //os << "'" << next->ai_canonname << "' "; + //} + unsigned short port = 0; + os << "addr=["; + if(next->ai_family == AF_INET) { + sockaddr_in* sin = (sockaddr_in*)next->ai_addr; + port = ntohs(sin->sin_port); + os << AddressToString(&sin->sin_addr, 4); + } + else if (next->ai_family == AF_INET6) { + sockaddr_in6* sin = (sockaddr_in6*)next->ai_addr; + port = ntohs(sin->sin6_port); + os << "[" << AddressToString(&sin->sin6_addr, 16) << "]"; + } + else + os << "unknown family"; + if(port) { + os << ":" << port; + } + os << "]"; + if((next = next->ai_next)) + os << ", "; + } + os << '}'; + return os; +} + +void AddrInfoCallback(void *data, int status, int timeouts, + struct ares_addrinfo *ai) { + EXPECT_NE(nullptr, data); + AddrInfoResult* result = reinterpret_cast<AddrInfoResult*>(data); + result->done_ = true; + result->status_ = status; + result->timeouts_= timeouts; + result->ai_ = AddrInfo(ai); + if (verbose) std::cerr << "AddrInfoCallback(" << *result << ")" << std::endl; +} + std::ostream& operator<<(std::ostream& os, const SearchResult& result) { os << '{'; if (result.done_) { diff --git a/contrib/libs/c-ares/test/ares-test.h b/contrib/libs/c-ares/test/ares-test.h index fd3bc31c27..541e29a87d 100644 --- a/contrib/libs/c-ares/test/ares-test.h +++ b/contrib/libs/c-ares/test/ares-test.h @@ -276,30 +276,30 @@ struct NameInfoResult { }; std::ostream& operator<<(std::ostream& os, const NameInfoResult& result); -struct AddrInfoDeleter { - void operator() (ares_addrinfo *ptr) { - if (ptr) ares_freeaddrinfo(ptr); - } -}; - -// C++ wrapper for struct ares_addrinfo. -using AddrInfo = std::unique_ptr<ares_addrinfo, AddrInfoDeleter>; - -std::ostream& operator<<(std::ostream& os, const AddrInfo& result); - -// Structure that describes the result of an ares_addrinfo_callback invocation. -struct AddrInfoResult { - AddrInfoResult() : done_(false), status_(-1), timeouts_(0) {} - // Whether the callback has been invoked. - bool done_; - // Explicitly provided result information. - int status_; - int timeouts_; - // Contents of the ares_addrinfo structure, if provided. - AddrInfo ai_; -}; -std::ostream& operator<<(std::ostream& os, const AddrInfoResult& result); - +struct AddrInfoDeleter { + void operator() (ares_addrinfo *ptr) { + if (ptr) ares_freeaddrinfo(ptr); + } +}; + +// C++ wrapper for struct ares_addrinfo. +using AddrInfo = std::unique_ptr<ares_addrinfo, AddrInfoDeleter>; + +std::ostream& operator<<(std::ostream& os, const AddrInfo& result); + +// Structure that describes the result of an ares_addrinfo_callback invocation. +struct AddrInfoResult { + AddrInfoResult() : done_(false), status_(-1), timeouts_(0) {} + // Whether the callback has been invoked. + bool done_; + // Explicitly provided result information. + int status_; + int timeouts_; + // Contents of the ares_addrinfo structure, if provided. + AddrInfo ai_; +}; +std::ostream& operator<<(std::ostream& os, const AddrInfoResult& result); + // Standard implementation of ares callbacks that fill out the corresponding // structures. void HostCallback(void *data, int status, int timeouts, @@ -308,8 +308,8 @@ void SearchCallback(void *data, int status, int timeouts, unsigned char *abuf, int alen); void NameInfoCallback(void *data, int status, int timeouts, char *node, char *service); -void AddrInfoCallback(void *data, int status, int timeouts, - struct ares_addrinfo *res); +void AddrInfoCallback(void *data, int status, int timeouts, + struct ares_addrinfo *res); // Retrieve the name servers used by a channel. std::vector<std::string> GetNameServers(ares_channel channel); @@ -345,40 +345,40 @@ class TempFile : public TransientFile { const char* filename() const { return filename_.c_str(); } }; -#ifdef _WIN32 -extern "C" { - -static int setenv(const char *name, const char *value, int overwrite) -{ - char *buffer; - size_t buf_size; - - if (name == NULL) - return -1; - - if (value == NULL) - value = ""; /* For unset */ - - if (!overwrite && getenv(name) != NULL) { - return -1; - } - - buf_size = strlen(name) + strlen(value) + 1 /* = */ + 1 /* NULL */; - buffer = (char *)malloc(buf_size); - _snprintf(buffer, buf_size, "%s=%s", name, value); - _putenv(buffer); - free(buffer); - return 0; -} - -static int unsetenv(const char *name) -{ - return setenv(name, NULL, 1); -} - -} /* extern "C" */ -#endif - +#ifdef _WIN32 +extern "C" { + +static int setenv(const char *name, const char *value, int overwrite) +{ + char *buffer; + size_t buf_size; + + if (name == NULL) + return -1; + + if (value == NULL) + value = ""; /* For unset */ + + if (!overwrite && getenv(name) != NULL) { + return -1; + } + + buf_size = strlen(name) + strlen(value) + 1 /* = */ + 1 /* NULL */; + buffer = (char *)malloc(buf_size); + _snprintf(buffer, buf_size, "%s=%s", name, value); + _putenv(buffer); + free(buffer); + return 0; +} + +static int unsetenv(const char *name) +{ + return setenv(name, NULL, 1); +} + +} /* extern "C" */ +#endif + // RAII class for a temporary environment variable value. class EnvValue { public: diff --git a/contrib/libs/c-ares/test/ya.make b/contrib/libs/c-ares/test/ya.make index ef42eab230..5eb7f6c6bf 100644 --- a/contrib/libs/c-ares/test/ya.make +++ b/contrib/libs/c-ares/test/ya.make @@ -38,7 +38,7 @@ SRCS( ares-test-internal.cc ares-test-live.cc ares-test-misc.cc - ares-test-mock-ai.cc + ares-test-mock-ai.cc ares-test-mock.cc ares-test-ns.cc ares-test-parse-a.cc @@ -47,7 +47,7 @@ SRCS( ares-test-parse-naptr.cc ares-test-parse-ns.cc ares-test-parse-ptr.cc - ares-test-parse-soa-any.cc + ares-test-parse-soa-any.cc ares-test-parse-soa.cc ares-test-parse-srv.cc ares-test-parse-txt.cc diff --git a/contrib/libs/c-ares/ya.make b/contrib/libs/c-ares/ya.make index bd35762e44..7c1a7d13e8 100644 --- a/contrib/libs/c-ares/ya.make +++ b/contrib/libs/c-ares/ya.make @@ -7,7 +7,7 @@ OWNER( g:cpp-contrib ) -VERSION(1.16.1) +VERSION(1.16.1) ORIGINAL_SOURCE(https://c-ares.haxx.se/download/c-ares-1.16.1.tar.gz) @@ -51,10 +51,10 @@ ENDIF() SRCS( ares__close_sockets.c ares__get_hostent.c - ares__parse_into_addrinfo.c + ares__parse_into_addrinfo.c ares__read_line.c - ares__readaddrinfo.c - ares__sortaddrinfo.c + ares__readaddrinfo.c + ares__sortaddrinfo.c ares__timeval.c ares_android.c ares_cancel.c @@ -66,8 +66,8 @@ SRCS( ares_fds.c ares_free_hostent.c ares_free_string.c - ares_freeaddrinfo.c - ares_getaddrinfo.c + ares_freeaddrinfo.c + ares_getaddrinfo.c ares_getenv.c ares_gethostbyaddr.c ares_gethostbyname.c |