diff --git a/deps/cares/CHANGES b/deps/cares/CHANGES index 24a68a89849b67..ae56d4f24bc3d9 100644 --- a/deps/cares/CHANGES +++ b/deps/cares/CHANGES @@ -1,5 +1,250 @@ Changelog for the c-ares project. Generated with git2changes.pl +Version 1.28.1 (30 Mar 2024) + +GitHub (30 Mar 2024) +- [Brad House brought this change] + + release prep for 1.28.1 (#739) + +Brad House (30 Mar 2024) +- ares_search() and ares_getaddrinfo() resolution fails if no search domains + + Due to an error in creating the list of domains to search, if no search + domains were configured, resolution would fail. + + Fixes Issue: #737 + Fix By: Brad House (@bradh352) + +- typo + +Version 1.28.0 (28 Mar 2024) + +GitHub (28 Mar 2024) +- [Brad House brought this change] + + Allow configuration value for NDots to be zero (#735) + + As per Issue #734 some people use `ndots:0` in their configuration which + is allowed by the system resolver but not by c-ares. Add support for + `ndots:0` and add a test case to validate this behavior. + + Fixes Issue: #734 + Fix By: Brad House (@bradh352) + +Brad House (27 Mar 2024) +- typo + +GitHub (27 Mar 2024) +- [Brad House brought this change] + + 1.28.0 release prep (#733) + +Brad House (27 Mar 2024) +- CMake: don't overwrite global required libraries/definitions/includes + + When chain building c-ares, global settings were being unset which + could lead to build problems. + + Fixes Issue: #729 + Fix By: Brad House (@bradh352) + +- remove tests that have been disabled forever + +- clang-format + +- ares_search_dnsrec() takes a const + +- sonarcloud: clean up some minor codesmells + +GitHub (26 Mar 2024) +- [Brad House brought this change] + + mark deprecated functions as such (#732) + + Multiple functions have been deprecated over the years, annotate them + with attribute deprecated. + + When possible show a message about their replacements. + + This is a continuation/completion of PR #706 + + Fix By: Cristian Rodríguez (@crrodriguez) + +Brad House (26 Mar 2024) +- silence clang static analyzer + +- silence coverity + +- coverity: fix mostly bogus warnings + +- fix missing doc + +GitHub (25 Mar 2024) +- [Brad House brought this change] + + Rework internals to pass around `ares_dns_record_t` instead of binary data (#730) + + c-ares has historically passed around raw dns packets in binary form. + Now that we have a new parser, and messages are already parsed + internally, lets pass around that parsed message rather than requiring + multiple parse attempts on the same message. Also add a new + `ares_send_dnsrec()` and `ares_query_dnsrec()` similar to + `ares_search_dnsrec()` added with PR #719 that can return the pointer to + the `ares_dns_record_t` to the caller enqueuing queries and rework + `ares_search_dnsrec()` to use `ares_send_dnsrec()` internally. + + Fix By: Brad House (@bradh352) + +Brad House (23 Mar 2024) +- tests: mockserver is local, shorten timeouts to make test cases run faster to use less CI resources + +- appveyor: disable UWP builds until MSVC version is updated in base image + +GitHub (21 Mar 2024) +- [Faraz brought this change] + + Include netinet6/in6.h (#728) + + On some platforms, "netinet6/in6.h" is not included by "netinet/in.h" + and needs to be included separately. + + Fix By: Faraz (@farazrbx) + +- [Oliver Welsh brought this change] + + Add function ares_search_dnrec() to search for records using the new DNS record parser (#719) + + This PR adds a new function `ares_search_dnsrec()` to search for records + using the new DNS record parser. + + The function takes an arbitrary DNS record object to search (that must + represent a query for a single name). The function takes a new callback + type, `ares_callback_dnsrec`, that is invoked with a parsed DNS record + object rather than the raw buffer(+length). + + The original motivation for this change is to provide support for + [draft-kaplan-enum-sip-routing-04](https://datatracker.ietf.org/doc/html/draft-kaplan-enum-sip-routing-04); + when routing phone calls using an ENUM server, it can be useful to + include identifying source information in an OPT RR options value, to + help select the appropriate route for the call. The new function allows + for more customisable searches like this. + + **Summary of code changes** + + A new function `ares_search_dnsrec()` has been added and exposed. + Moreover, the entire `ares_search_int()` internal code flow has been + refactored to use parsed DNS record objects and the new DNS record + parser. The DNS record object is passed through the `search_query` + structure by encoding/decoding to/from a buffer (if multiple search + domains are used). A helper function `ares_dns_write_query_altname()` is + used to re-write the DNS record object with a new query name (used to + append search domains). + + `ares_search()` is now a wrapper around the new internal code, where the + DNS record object is created based on the name, class and type + parameters. + + The new function uses a new callback type, `ares_callback_dnsrec`. This + is invoked with a parsed DNS record object. For now, we convert from + `ares_callback` to this new type using `ares__dnsrec_convert_cb()`. + + Some functions that are common to both `ares_query()` and + `ares_search()` have been refactored using the new DNS record parser. + See `ares_dns_record_create_query()` and + `ares_dns_query_reply_tostatus()`. + + **Testing** + + A new FV has been added to test the new function, which searches for a + DNS record containing an OPT RR with custom options value. + + As part of this, I needed to enhance the mock DNS server to expect + request text (and assert that it matches actual request text). This is + because the FV needs to check that the request contains the correct OPT + RR. + + **Documentation** + + The man page docs have been updated to describe the new feature. + + **Futures** + + In the future, a new variant of `ares_send()` could be introduced in the + same vein (`ares_send_dnsrec()`). This could be used by + `ares_search_dnsrec()`. Moreover, we could migrate internal code to use + `ares_callback_dnsrec` as the default callback. + + This will help to make the new DNS record parser the norm in C-Ares. + + --------- + + Co-authored-by: Oliver Welsh (@oliverwelsh) + +- [Brad House brought this change] + + Replace configuration file parsers with memory-safe parser (#725) + + Rewrite configuration parsers using new memory safe parsing functions. + After CVE-2024-25629 its obvious that we need to prioritize again on + getting all the hand written parsers with direct pointer manipulation + replaced. They're just not safe and hard to audit. It was yet another + example of 20+yr old code having a memory safety issue just now coming + to light. + + Though these parsers are definitely less efficient, they're written with + memory safety in mind, and any performance difference is going to be + meaningless for something that only happens once a while. + + Fix By: Brad House (@bradh352) + +Brad House (12 Mar 2024) +- skip ubsan/asan on debian arm64 due to the compiler getting killed + +- ares_init potential memory leak + + If initializing using default settings fails, there may be a memory leak of + search domains that were set by system configuration. + + Fixes Issue: #724 + Fix By: Brad House (@bradh352) + +GitHub (12 Mar 2024) +- [Faraz Fallahi brought this change] + + simple implementation for isascii where stdlib isascii is not available (#721) + + Some platforms don't have the isascii() function. Implement as a macro. + + Fix By: Faraz Fallahi (@fffaraz) + +Brad House (11 Mar 2024) +- Doxygen: fix typos + + Fix reported typos in doxygen-style comments. + + Fixes Issue: #722 + Credit: @dzalyalov88 + +- CI: update freebsd image + +- CMake: Fix Chain building if CMAKE runtime paths not set + + This fixes issues created by #708 + + Fix By: Brad House (@bradh352) + +- silence benign warnings + +- Remove acountry completely from code, including manpage + + Since acountry cannot be restored due to nerd.dk being decommissioned, + we should completely remove the manpage and source. This also + will resolve issue #718. + + Fixes Issue: #718 + Fix By: Brad House (@bradh352) + Version 1.27.0 (22 Feb 2024) GitHub (22 Feb 2024) @@ -6100,127 +6345,3 @@ Yang Tse (10 Mar 2013) Daniel Stenberg (9 Mar 2013) - ares.h: there is no ares_free_soa function - -Yang Tse (9 Mar 2013) -- Makefile.am: empty AM_LDFLAGS definition for automake 1.7 compatibility - -- ares_inet_ntop.3: s/socklen_t/ares_socklen_t - -- configure: use XC_LIBTOOL for portability across libtool versions - -- xc-lt-iface.m4: provide XC_LIBTOOL macro - -- Makefile.am: use AM_CPPFLAGS instead of INCLUDES - -- inet_ntop.c: s/socklen_t/ares_socklen_t - -- inet_ntop.c: s/socklen_t/ares_socklen_t for portability - -Daniel Stenberg (19 Feb 2013) -- ares.h: s/socklen_t/ares_socklen_t for portability - -- ares_inet_ntop.3: 4th argument is socklen_t! - -- spell inet correctly! - -- ares_inet_pton/ntop: cleanup - - Make sure that the symbols are always exported and present in c-ares. - - Make the headers prefixed with 'ares'. - - Removed the inet_ntop.h version as it no longer features any content. - -- ares_inet_ntop/ares_inet_pton: added man pages - -Yang Tse (15 Feb 2013) -- [Gisle Vanem brought this change] - - curl_setup_once.h: definition of HAVE_CLOSE_S defines sclose() to close_s() - -- [Gisle Vanem brought this change] - - config-dos.h: define HAVE_CLOSE_S for MSDOS/Watt-32 - -- [Gisle Vanem brought this change] - - config-dos.h: define strerror() to strerror_s_() for High-C - -Daniel Stenberg (13 Feb 2013) -- ares_get_datatype: removed unused function - - it was also wrongly named as internal functions require two underscores - -- ares__bitncmp: use two underscores for private functions - - It used a single one previously making it look like a public one - -- ares__generate_new_id: moved to ares_query.c - - ... and ares__rc4 is turned into a local static function. - -- ares__swap_lists: make private and static - - ... since there's only one user, make it static within ares_process.c - -Yang Tse (13 Feb 2013) -- Makefile.msvc: add four VS version strings - -Daniel Stenberg (13 Feb 2013) -- ares_expand_name.3: clarify how to free the data - -Yang Tse (30 Jan 2013) -- zz40-xc-ovr.m4: fix 'wc' detection - follow-up 2 - - - Fix a pair of single quotes to double quotes. - - URL: http://curl.haxx.se/mail/lib-2013-01/0355.html - Reported by: Tor Arntsen - -- zz40-xc-ovr.m4: fix 'wc' detection - follow-up - - - Take into account that 'wc' may return leading spaces and/or tabs. - - - Set initial IFS to space, tab and newline. - -- zz40-xc-ovr.m4: fix 'wc' detection - - - Take into account that 'wc' may return leading spaces. - - - Set internationalization behavior variables. - - Tor Arntsen analyzed and reported the issue. - - URL: http://curl.haxx.se/mail/lib-2013-01/0351.html - -- zz40-xc-ovr.m4: check another three basic utilities - -- zz40-xc-ovr.m4: 1.0 interface stabilization - - - Stabilization results in 4 public interface m4 macros: - XC_CONFIGURE_PREAMBLE - XC_CONFIGURE_PREAMBLE_VER_MAJOR - XC_CONFIGURE_PREAMBLE_VER_MINOR - XC_CHECK_PATH_SEPARATOR - - Avoid one level of internal indirection - - Update comments - - Drop XC_OVR_ZZ40 macro - -- zz40-xc-ovr.m4: emit witness message in configure BODY - - This avoids witness message in output when running configure --help, - while sending the message to config.log for other configure runs. - -- zz40-xc-ovr.m4: truly do version conditional overriding - - - version conditional overriding - - catch unexpanded XC macros - - fix double words in comments - -- zz40-xc-ovr.m4: fix variable assignment of subshell output bashism - - Tor Arntsen analyzed and reported the issue. - - URL: http://curl.haxx.se/mail/lib-2013-01/0306.html - -- zz40-xc-ovr.m4: reinstate strict AC_REQUIRE macro dependencies diff --git a/deps/cares/CMakeLists.txt b/deps/cares/CMakeLists.txt index e951cafd7b4068..2718ce52b73ff6 100644 --- a/deps/cares/CMakeLists.txt +++ b/deps/cares/CMakeLists.txt @@ -12,10 +12,10 @@ INCLUDE (CheckCSourceCompiles) INCLUDE (CheckStructHasMember) INCLUDE (CheckLibraryExists) -PROJECT (c-ares LANGUAGES C VERSION "1.27.0" ) +PROJECT (c-ares LANGUAGES C VERSION "1.28.1" ) # Set this version before release -SET (CARES_VERSION "1.27.0") +SET (CARES_VERSION "1.28.1") INCLUDE (GNUInstallDirs) # include this *AFTER* PROJECT(), otherwise paths are wrong. @@ -30,7 +30,7 @@ INCLUDE (GNUInstallDirs) # include this *AFTER* PROJECT(), otherwise paths are w # For example, a version of 4:0:2 would generate output such as: # libname.so -> libname.so.2 # libname.so.2 -> libname.so.2.2.0 -SET (CARES_LIB_VERSIONINFO "14:0:12") +SET (CARES_LIB_VERSIONINFO "15:1:13") OPTION (CARES_STATIC "Build as a static library" OFF) @@ -98,7 +98,7 @@ IF (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) SET (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}") SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") SET (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") - SET (PACKAGE_DIRECTORY ${PROJECT_BINARY_DIR}/package) + SET (CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") ENDIF () # Destinations for installing different kinds of targets (pass to install command). @@ -113,11 +113,10 @@ SET (TARGETS_INST_DEST # CHECK_LIBRARY_EXISTS can't be used as it will return true if the function # is found in a different required/dependent library. MACRO (CARES_FUNCTION_IN_LIBRARY func lib var) - - SET (_ORIG_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}") + SET (_ORIG_FIL_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}") SET (CMAKE_REQUIRED_LIBRARIES ) CHECK_FUNCTION_EXISTS ("${func}" "_CARES_FUNC_IN_LIB_GLOBAL_${func}") - SET (CMAKE_REQUIRED_LIBRARIES "${_ORIG_CMAKE_REQUIRED_LIBRARIES}") + SET (CMAKE_REQUIRED_LIBRARIES "${_ORIG_FIL_CMAKE_REQUIRED_LIBRARIES}") IF ("${_CARES_FUNC_IN_LIB_GLOBAL_${func}}") SET (${var} FALSE) @@ -207,6 +206,7 @@ CHECK_INCLUDE_FILES (malloc.h HAVE_MALLOC_H) CHECK_INCLUDE_FILES (memory.h HAVE_MEMORY_H) CHECK_INCLUDE_FILES (netdb.h HAVE_NETDB_H) CHECK_INCLUDE_FILES (netinet/in.h HAVE_NETINET_IN_H) +CHECK_INCLUDE_FILES (netinet6/in6.h HAVE_NETINET6_IN6_H) # On old MacOS SDK versions, you must include sys/socket.h before net/if.h IF (HAVE_SYS_SOCKET_H) CHECK_INCLUDE_FILES ("sys/socket.h;net/if.h" HAVE_NET_IF_H) @@ -303,7 +303,11 @@ ENDIF () # headers, libraries, and definitions for the detection to work properly # CMAKE_REQUIRED_DEFINITIONS, CMAKE_REQUIRED_LIBRARIES, and # CMAKE_EXTRA_INCLUDE_FILES. When we're done with the detection, we'll -# unset them. +# restore them to their original values (otherwise a parent project +# that tries to set these won't be maintained, see Issue #729) +SET (ORIG_CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEEFINITIONS}) +SET (ORIG_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) +SET (ORIG_CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES}) SET (CMAKE_REQUIRED_DEFINITIONS ${SYSFLAGS}) LIST (APPEND CMAKE_REQUIRED_LIBRARIES ${CARES_DEPENDENT_LIBS}) @@ -323,6 +327,7 @@ CARES_EXTRAINCLUDE_IFSET (HAVE_NETDB_H netdb.h) CARES_EXTRAINCLUDE_IFSET (HAVE_NET_IF_H net/if.h) CARES_EXTRAINCLUDE_IFSET (HAVE_IFADDRS_H ifaddrs.h) CARES_EXTRAINCLUDE_IFSET (HAVE_NETINET_IN_H netinet/in.h) +CARES_EXTRAINCLUDE_IFSET (HAVE_NETINET6_IN6_H netinet6/in6.h) CARES_EXTRAINCLUDE_IFSET (HAVE_NETINET_TCP_H netinet/tcp.h) CARES_EXTRAINCLUDE_IFSET (HAVE_SIGNAL_H signal.h) CARES_EXTRAINCLUDE_IFSET (HAVE_STDLIB_H stdlib.h) @@ -458,10 +463,10 @@ CHECK_SYMBOL_EXISTS (epoll_create1 "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_EPOLL) # from libc. We need to perform a link test instead of a header/symbol test. CHECK_FUNCTION_EXISTS (__system_property_get HAVE___SYSTEM_PROPERTY_GET) -# Unset temporary data -SET (CMAKE_EXTRA_INCLUDE_FILES) -SET (CMAKE_REQUIRED_DEFINITIONS) -SET (CMAKE_REQUIRED_LIBRARIES) +# Restore original values (as per Issue #729) +SET (CMAKE_REQUIRED_DEFINITIONS ${ORIG_CMAKE_REQUIRED_DEEFINITIONS}) +SET (CMAKE_REQUIRED_LIBRARIES ${ORIG_CMAKE_REQUIRED_LIBRARIES}) +SET (CMAKE_EXTRA_INCLUDE_FILES ${ORIG_CMAKE_EXTRA_INCLUDE_FILES}) ################################################################################ diff --git a/deps/cares/Makefile.in b/deps/cares/Makefile.in index d1c663d5488366..928cdc217ee6de 100644 --- a/deps/cares/Makefile.in +++ b/deps/cares/Makefile.in @@ -364,6 +364,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ diff --git a/deps/cares/Makefile.msvc b/deps/cares/Makefile.msvc index c89454ec155d94..f6e8f4e71f2e6f 100644 --- a/deps/cares/Makefile.msvc +++ b/deps/cares/Makefile.msvc @@ -229,7 +229,7 @@ LINK_CMD_EXE_DBG = $(LINK_CMD_EXE) /debug $(PDBTYPE_CONSOLIDATE) CARES_TARGET = $(STA_LIB_REL).lib CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DCARES_STATICLIB CARES_LFLAGS = -SPROG_CFLAGS = /DCARES_STATICLIB +SPROG_CFLAGS = /DCARES_STATICLIB /DCARES_NO_DEPRECATED SPROG_LFLAGS = /libpath:$(CARES_OUTDIR) $(EX_LIBS_REL) $(STA_LIB_REL).lib CARES_LINK = $(LINK_CMD_LIB) SPROG_LINK = $(LINK_CMD_EXE_REL) @@ -240,7 +240,7 @@ CC_CMD = $(CC_CMD_REL) CARES_TARGET = $(STA_LIB_DBG).lib CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DCARES_STATICLIB /DDEBUGBUILD CARES_LFLAGS = -SPROG_CFLAGS = /DCARES_STATICLIB +SPROG_CFLAGS = /DCARES_STATICLIB /DCARES_NO_DEPRECATED SPROG_LFLAGS = /libpath:$(CARES_OUTDIR) $(EX_LIBS_DBG) $(STA_LIB_DBG).lib CARES_LINK = $(LINK_CMD_LIB) SPROG_LINK = $(LINK_CMD_EXE_DBG) @@ -251,7 +251,7 @@ CC_CMD = $(CC_CMD_DBG) CARES_TARGET = $(DYN_LIB_REL).dll CARES_CFLAGS = /DCARES_BUILDING_LIBRARY CARES_LFLAGS = /release $(EX_LIBS_REL) /implib:$(CARES_OUTDIR)\$(IMP_LIB_REL).lib $(PDB_NONE) -SPROG_CFLAGS = +SPROG_CFLAGS = /DCARES_NO_DEPRECATED SPROG_LFLAGS = /libpath:$(CARES_OUTDIR) $(EX_LIBS_REL) $(IMP_LIB_REL).lib CARES_LINK = $(LINK_CMD_DLL) SPROG_LINK = $(LINK_CMD_EXE_REL) @@ -264,7 +264,7 @@ RC_CMD = $(RC_CMD_REL) CARES_TARGET = $(DYN_LIB_DBG).dll CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DDEBUGBUILD CARES_LFLAGS = /debug $(EX_LIBS_DBG) /implib:$(CARES_OUTDIR)\$(IMP_LIB_DBG).lib /pdb:$(CARES_OUTDIR)\$(DYN_LIB_DBG).pdb $(PDBTYPE_CONSOLIDATE) -SPROG_CFLAGS = +SPROG_CFLAGS = /DCARES_NO_DEPRECATED SPROG_LFLAGS = /libpath:$(CARES_OUTDIR) $(EX_LIBS_DBG) $(IMP_LIB_DBG).lib CARES_LINK = $(LINK_CMD_DLL) SPROG_LINK = $(LINK_CMD_EXE_DBG) diff --git a/deps/cares/RELEASE-NOTES.md b/deps/cares/RELEASE-NOTES.md index 0fdcbc6b968488..3a9b9dd9c35fa1 100644 --- a/deps/cares/RELEASE-NOTES.md +++ b/deps/cares/RELEASE-NOTES.md @@ -1,40 +1,49 @@ -## c-ares version 1.27.0 - Feb 23 2024 +## c-ares version 1.28.1 - Mar 30 2024 -This is a security, feature, and bugfix release. +This release contains a fix for a single significant regression introduced +in c-ares 1.28.0. -Security: +* `ares_search()` and `ares_getaddrinfo()` resolution fails if no search domains + are specified. [Issue #737](https://github.com/c-ares/c-ares/issues/737) -* Moderate. CVE-2024-25629. Reading malformatted `/etc/resolv.conf`, - `/etc/nsswitch.conf` or the `HOSTALIASES` file could result in a crash. - [GHSA-mg26-v6qh-x48q](https://github.com/c-ares/c-ares/security/advisories/GHSA-mg26-v6qh-x48q) + +## c-ares version 1.28.0 - Mar 29 2024 + +This is a feature and bugfix release. Features: -* New function `ares_queue_active_queries()` to retrieve number of in-flight - queries. [PR #712](https://github.com/c-ares/c-ares/pull/712) -* New function `ares_queue_wait_empty()` to wait for the number of in-flight - queries to reach zero. [PR #710](https://github.com/c-ares/c-ares/pull/710) -* New `ARES_FLAG_NO_DEFLT_SVR` for `ares_init_options()` to return a failure if - no DNS servers can be found rather than attempting to use `127.0.0.1`. This - also introduces a new ares status code of `ARES_ENOSERVER`. [PR #713](https://github.com/c-ares/c-ares/pull/713) +* Emit warnings when deprecated c-ares functions are used. This can be + disabled by passing a compiler definition of `CARES_NO_DEPRECATED`. [PR #732](https://github.com/c-ares/c-ares/pull/732) +* Add function `ares_search_dnsrec()` to search for records using the new DNS + record data structures. [PR #719](https://github.com/c-ares/c-ares/pull/719) +* Rework internals to pass around `ares_dns_record_t` instead of binary data, + this introduces new public functions of `ares_query_dnsrec()` and + `ares_send_dnsrec()`. [PR #730](https://github.com/c-ares/c-ares/pull/730) Changes: -* EDNS Packet size should be 1232 as per DNS Flag Day. [PR #705](https://github.com/c-ares/c-ares/pull/705) +* tests: when performing simulated queries, reduce timeouts to make tests run + faster +* Replace configuration file parsers with memory-safe parser. [PR #725](https://github.com/c-ares/c-ares/pull/725) +* Remove `acountry` completely, the manpage might still get installed otherwise. [Issue #718](https://github.com/c-ares/c-ares/pull/718) Bugfixes: -* Windows DNS suffix search list memory leak. [PR #711](https://github.com/c-ares/c-ares/pull/711) -* Fix warning due to ignoring return code of `write()`. [PR #709](https://github.com/c-ares/c-ares/pull/709) -* CMake: don't override target output locations if not top-level. [Issue #708](https://github.com/c-ares/c-ares/issues/708) -* Fix building c-ares without thread support. [PR #700](https://github.com/c-ares/c-ares/pull/700) +* CMake: don't overwrite global required libraries/definitions/includes which + could cause build errors for projects chain building c-ares. [Issue #729](https://github.com/c-ares/c-ares/issues/729) +* On some platforms, `netinet6/in6.h` is not included by `netinet/in.h` + and needs to be included separately. [PR #728](https://github.com/c-ares/c-ares/pull/728) +* Fix a potential memory leak in `ares_init()`. [Issue #724](https://github.com/c-ares/c-ares/issues/724) +* Some platforms don't have the `isascii()` function. Implement as a macro. [PR #721](https://github.com/c-ares/c-ares/pull/721) +* CMake: Fix Chain building if CMAKE runtime paths not set +* NDots configuration should allow a value of zero. [PR #735](https://github.com/c-ares/c-ares/pull/735) Thanks go to these friendly people for their efforts and contributions for this release: -* Anthony Alayo (@anthonyalayo) * Brad House (@bradh352) -* Cheng Zhao (@zcbenz) * Cristian Rodríguez (@crrodriguez) * Daniel Stenberg (@bagder) +* Faraz (@farazrbx) +* Faraz Fallahi (@fffaraz) * Oliver Welsh (@oliverwelsh) -* Vojtěch Vobr (@vojtechvobr) diff --git a/deps/cares/aminclude_static.am b/deps/cares/aminclude_static.am index e3fc636c7b51a4..6fa817a8346703 100644 --- a/deps/cares/aminclude_static.am +++ b/deps/cares/aminclude_static.am @@ -1,6 +1,6 @@ # aminclude_static.am generated automatically by Autoconf -# from AX_AM_MACROS_STATIC on Fri Feb 23 08:24:27 CET 2024 +# from AX_AM_MACROS_STATIC on Sat Mar 30 16:17:17 CET 2024 # Code coverage diff --git a/deps/cares/configure b/deps/cares/configure index ac3c7b55db0565..656164f46e3ad8 100755 --- a/deps/cares/configure +++ b/deps/cares/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for c-ares 1.27.0. +# Generated by GNU Autoconf 2.71 for c-ares 1.28.1. # # Report bugs to . # @@ -621,8 +621,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='c-ares' PACKAGE_TARNAME='c-ares' -PACKAGE_VERSION='1.27.0' -PACKAGE_STRING='c-ares 1.27.0' +PACKAGE_VERSION='1.28.1' +PACKAGE_STRING='c-ares 1.28.1' PACKAGE_BUGREPORT='c-ares mailing list: http://lists.haxx.se/listinfo/c-ares' PACKAGE_URL='' @@ -1420,7 +1420,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures c-ares 1.27.0 to adapt to many kinds of systems. +\`configure' configures c-ares 1.28.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1491,7 +1491,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of c-ares 1.27.0:";; + short | recursive ) echo "Configuration of c-ares 1.28.1:";; esac cat <<\_ACEOF @@ -1627,7 +1627,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -c-ares configure 1.27.0 +c-ares configure 1.28.1 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2251,7 +2251,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by c-ares $as_me 1.27.0, which was +It was created by c-ares $as_me 1.28.1, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3225,7 +3225,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu -CARES_VERSION_INFO="14:0:12" +CARES_VERSION_INFO="15:1:13" @@ -5907,7 +5907,7 @@ fi # Define the identity of the package. PACKAGE='c-ares' - VERSION='1.27.0' + VERSION='1.28.1' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -21681,6 +21681,31 @@ if test "x$ac_cv_header_netinet_in_h" = xyes then : printf "%s\n" "#define HAVE_NETINET_IN_H 1" >>confdefs.h +fi +ac_fn_c_check_header_compile "$LINENO" "netinet6/in6.h" "ac_cv_header_netinet6_in6_h" " +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_ARPA_NAMESER_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif + + +" +if test "x$ac_cv_header_netinet6_in6_h" = xyes +then : + printf "%s\n" "#define HAVE_NETINET6_IN6_H 1" >>confdefs.h + fi ac_fn_c_check_header_compile "$LINENO" "netinet/tcp.h" "ac_cv_header_netinet_tcp_h" " #ifdef HAVE_SYS_TYPES_H @@ -25931,7 +25956,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by c-ares $as_me 1.27.0, which was +This file was extended by c-ares $as_me 1.28.1, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -25999,7 +26024,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -c-ares config.status 1.27.0 +c-ares config.status 1.28.1 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/deps/cares/configure.ac b/deps/cares/configure.ac index 1a3ba8c3fc4c49..4d263a7f309017 100644 --- a/deps/cares/configure.ac +++ b/deps/cares/configure.ac @@ -2,10 +2,10 @@ dnl Copyright (C) The c-ares project and its contributors dnl SPDX-License-Identifier: MIT AC_PREREQ([2.69]) -AC_INIT([c-ares], [1.27.0], +AC_INIT([c-ares], [1.28.1], [c-ares mailing list: http://lists.haxx.se/listinfo/c-ares]) -CARES_VERSION_INFO="14:0:12" +CARES_VERSION_INFO="15:1:13" dnl This flag accepts an argument of the form current[:revision[:age]]. So, dnl passing -version-info 3:12:1 sets current to 3, revision to 12, and age to dnl 1. @@ -436,6 +436,7 @@ AC_CHECK_HEADERS( netioapi.h \ netdb.h \ netinet/in.h \ + netinet6/in6.h \ netinet/tcp.h \ net/if.h \ ifaddrs.h \ diff --git a/deps/cares/docs/Makefile.in b/deps/cares/docs/Makefile.in index 4f5bb62409c7ab..8cb46878fa59ee 100644 --- a/deps/cares/docs/Makefile.in +++ b/deps/cares/docs/Makefile.in @@ -263,6 +263,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ @@ -357,18 +358,22 @@ MANPAGES = ares_cancel.3 \ ares_dns_rcode_tostr.3 \ ares_dns_record.3 \ ares_dns_record_create.3 \ + ares_dns_record_duplicate.3 \ ares_dns_record_get_flags.3 \ ares_dns_record_get_id.3 \ ares_dns_record_get_opcode.3 \ ares_dns_record_get_rcode.3 \ ares_dns_record_destroy.3 \ ares_dns_record_query_add.3 \ + ares_dns_record_query_set_name.3 \ + ares_dns_record_query_set_type.3 \ ares_dns_record_query_cnt.3 \ ares_dns_record_query_get.3 \ ares_dns_record_rr_add.3 \ ares_dns_record_rr_cnt.3 \ ares_dns_record_rr_del.3 \ ares_dns_record_rr_get.3 \ + ares_dns_record_rr_get_const.3 \ ares_dns_rec_type_fromstr.3 \ ares_dns_rec_type_t.3 \ ares_dns_rr.3 \ @@ -442,10 +447,16 @@ MANPAGES = ares_cancel.3 \ ares_parse_uri_reply.3 \ ares_process.3 \ ares_query.3 \ + ares_query_dnsrec.3 \ + ares_queue.3 \ + ares_queue_active_queries.3 \ + ares_queue_wait_empty.3 \ ares_reinit.3 \ ares_save_options.3 \ ares_search.3 \ + ares_search_dnsrec.3 \ ares_send.3 \ + ares_send_dnsrec.3 \ ares_set_local_dev.3 \ ares_set_local_ip4.3 \ ares_set_local_ip6.3 \ diff --git a/deps/cares/docs/Makefile.inc b/deps/cares/docs/Makefile.inc index 3645a7fcddc58b..882bf2280446d5 100644 --- a/deps/cares/docs/Makefile.inc +++ b/deps/cares/docs/Makefile.inc @@ -20,18 +20,22 @@ MANPAGES = ares_cancel.3 \ ares_dns_rcode_tostr.3 \ ares_dns_record.3 \ ares_dns_record_create.3 \ + ares_dns_record_duplicate.3 \ ares_dns_record_get_flags.3 \ ares_dns_record_get_id.3 \ ares_dns_record_get_opcode.3 \ ares_dns_record_get_rcode.3 \ ares_dns_record_destroy.3 \ ares_dns_record_query_add.3 \ + ares_dns_record_query_set_name.3 \ + ares_dns_record_query_set_type.3 \ ares_dns_record_query_cnt.3 \ ares_dns_record_query_get.3 \ ares_dns_record_rr_add.3 \ ares_dns_record_rr_cnt.3 \ ares_dns_record_rr_del.3 \ ares_dns_record_rr_get.3 \ + ares_dns_record_rr_get_const.3 \ ares_dns_rec_type_fromstr.3 \ ares_dns_rec_type_t.3 \ ares_dns_rr.3 \ @@ -105,13 +109,16 @@ MANPAGES = ares_cancel.3 \ ares_parse_uri_reply.3 \ ares_process.3 \ ares_query.3 \ + ares_query_dnsrec.3 \ ares_queue.3 \ ares_queue_active_queries.3 \ ares_queue_wait_empty.3 \ ares_reinit.3 \ ares_save_options.3 \ ares_search.3 \ + ares_search_dnsrec.3 \ ares_send.3 \ + ares_send_dnsrec.3 \ ares_set_local_dev.3 \ ares_set_local_ip4.3 \ ares_set_local_ip6.3 \ diff --git a/deps/cares/docs/adig.1 b/deps/cares/docs/adig.1 index 48b491b593b73c..59923790587ddd 100644 --- a/deps/cares/docs/adig.1 +++ b/deps/cares/docs/adig.1 @@ -64,4 +64,4 @@ Report bugs to the c-ares mailing list: \fBhttps://lists.haxx.se/listinfo/c-ares\fR .SH "SEE ALSO" .PP -acountry(1), ahost(1). +ahost(1). diff --git a/deps/cares/docs/ahost.1 b/deps/cares/docs/ahost.1 index 5feed981ab62c1..e17057273f8285 100644 --- a/deps/cares/docs/ahost.1 +++ b/deps/cares/docs/ahost.1 @@ -47,4 +47,4 @@ Report bugs to the c-ares mailing list: \fBhttps://lists.haxx.se/listinfo/c-ares\fR .SH "SEE ALSO" .PP -acountry(1), adig(1) +adig(1) diff --git a/deps/cares/docs/ares_dns_record.3 b/deps/cares/docs/ares_dns_record.3 index fe23b5eece60e5..01ce7601aa3199 100644 --- a/deps/cares/docs/ares_dns_record.3 +++ b/deps/cares/docs/ares_dns_record.3 @@ -19,7 +19,7 @@ ares_status_t ares_dns_parse(const unsigned char *buf, size_t buf_len, unsigned int flags, ares_dns_record_t **dnsrec); -ares_status_t ares_dns_write(ares_dns_record_t *dnsrec, +ares_status_t ares_dns_write(const ares_dns_record_t *dnsrec, unsigned char **buf, size_t *buf_len); ares_status_t ares_dns_record_create(ares_dns_record_t **dnsrec, @@ -28,6 +28,8 @@ ares_status_t ares_dns_record_create(ares_dns_record_t **dnsrec, ares_dns_opcode_t opcode, ares_dns_rcode_t rcode); +ares_dns_record_t *ares_dns_record_duplicate(const ares_dns_record_t *dnsrec); + unsigned short ares_dns_record_get_id(const ares_dns_record_t *dnsrec); unsigned short ares_dns_record_get_flags(const ares_dns_record_t *dnsrec); @@ -41,6 +43,14 @@ ares_status_t ares_dns_record_query_add(ares_dns_record_t *dnsrec, ares_dns_rec_type_t qtype, ares_dns_class_t qclass); +ares_status_t ares_dns_record_query_set_name(ares_dns_record_t *dnsrec, + size_t idx, + const char *name); + +ares_status_t ares_dns_record_query_set_type(ares_dns_record_t *dnsrec, + size_t idx, + ares_dns_rec_type_t qtype); + size_t ares_dns_record_query_cnt(const ares_dns_record_t *dnsrec); ares_status_t ares_dns_record_query_get(const ares_dns_record_t *dnsrec, @@ -67,7 +77,7 @@ on requests, and some may only be valid on responses: .B ARES_REC_TYPE_SOA - Start of authority zone .br -.B ARES_REC_TYPE_PTR +.B ARES_REC_TYPE_PTR - Domain name pointer .br .B ARES_REC_TYPE_HINFO @@ -317,6 +327,13 @@ is meant mostly for responses and is passed in the .IR rcode parameter and is typically \fPARES_RCODE_NOERROR\fP. +The \fIares_dns_record_duplicate(3)\fP function duplicates an existing DNS +record structure. This may be useful if needing to save a result as retrieved +from \fIares_send_dnsrec(3)\fP or \fIares_search_dnsrec(3)\fP. The structure +to be duplicated is passed in the +.IR dnsrec +parameter, and the duplicated copy is returned, or NULL on error such as +out of memory. The \fIares_dns_record_get_id(3)\fP function is used to retrieve the DNS message id from the DNS record provided in the @@ -350,6 +367,29 @@ parameter and the question class (typically \fIARES_CLASS_IN\fP) in the .IR qclass parameter. +The \fIares_dns_record_query_set_name(3)\fP function is used to modify the +question name in the DNS record provided in the +.IR dnsrec +parameter. The index of the query, which must be less than +\fIares_dns_record_query_cnt(3)\fP, is provided in the +.IR idx +parameter. The new domain name is provided in the +.IR name +parameter. Care should be taken as this will cause invalidation of any +\fIname\fP pointer retrieved from \fIares_dns_Record_query_get(3)\fP. This +function is useful if sending multiple similar queries without re-creating +the entire DNS query. + +The \fIares_dns_record_query_set_type(3)\fP function is used to modify the +question type in the DNS record provided in the +.IR dnsrec +parameter. The index of the query, which must be less than +\fIares_dns_record_query_cnt(3)\fP, is provided in the +.IR idx +parameter. The new query type is provided in the +.IR qtype +parameter. + The \fIares_dns_record_query_cnt(3)\fP function is used to retrieve the number of DNS questions in the DNS record provided in the .IR dnsrec @@ -363,7 +403,8 @@ parameter. The index provided in the parameter must be less than the value returned from \fIares_dns_record_query_cnt(3)\fP. The DNS question name will be returned in the variable pointed to by the .IR name -parameter, this may be provided as NULL if the name is not needed. +parameter, this may be provided as NULL if the name is not needed. This pointer +will be invalided by any call to \fIares_dns_record_query_set_name(3)\fP. The DNS question type will be returned in the variable pointed to by the .IR qtype parameter, this may be provided as NULL if the type is not needed. diff --git a/deps/cares/docs/ares_dns_record_duplicate.3 b/deps/cares/docs/ares_dns_record_duplicate.3 new file mode 100644 index 00000000000000..4acc581d29789c --- /dev/null +++ b/deps/cares/docs/ares_dns_record_duplicate.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_dns_record.3 diff --git a/deps/cares/docs/ares_dns_record_query_set_name.3 b/deps/cares/docs/ares_dns_record_query_set_name.3 new file mode 100644 index 00000000000000..4acc581d29789c --- /dev/null +++ b/deps/cares/docs/ares_dns_record_query_set_name.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_dns_record.3 diff --git a/deps/cares/docs/ares_dns_record_query_set_type.3 b/deps/cares/docs/ares_dns_record_query_set_type.3 new file mode 100644 index 00000000000000..4acc581d29789c --- /dev/null +++ b/deps/cares/docs/ares_dns_record_query_set_type.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_dns_record.3 diff --git a/deps/cares/docs/ares_dns_record_rr_get_const.3 b/deps/cares/docs/ares_dns_record_rr_get_const.3 new file mode 100644 index 00000000000000..b93e4cd4e37fa8 --- /dev/null +++ b/deps/cares/docs/ares_dns_record_rr_get_const.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_dns_rr.3 diff --git a/deps/cares/docs/ares_dns_rr.3 b/deps/cares/docs/ares_dns_rr.3 index 2999d18e3aa6bb..290859e838e7ef 100644 --- a/deps/cares/docs/ares_dns_rr.3 +++ b/deps/cares/docs/ares_dns_rr.3 @@ -4,14 +4,15 @@ .TH ARES_DNS_RR 3 "12 November 2023" .SH NAME ares_dns_record_rr_add, ares_dns_record_rr_cnt, ares_dns_record_rr_del, -ares_dns_record_rr_get, ares_dns_rr_get_addr, ares_dns_rr_get_addr6, -ares_dns_rr_get_bin, ares_dns_rr_get_class, ares_dns_rr_get_name, -ares_dns_rr_get_opt, ares_dns_rr_get_opt_byid, ares_dns_rr_get_opt_cnt, -ares_dns_rr_get_str, ares_dns_rr_get_ttl, ares_dns_rr_get_type, -ares_dns_rr_get_u16, ares_dns_rr_get_u32, ares_dns_rr_get_u8, ares_dns_rr_key_t, -ares_dns_rr_set_addr, ares_dns_rr_set_addr6, ares_dns_rr_set_bin, -ares_dns_rr_set_opt, ares_dns_rr_set_str, ares_dns_rr_set_u16, -ares_dns_rr_set_u32, ares_dns_rr_set_u8, ares_dns_section_t, ares_tlsa_match_t, +ares_dns_record_rr_get, ares_dns_record_rr_get_const, ares_dns_rr_get_addr, +ares_dns_rr_get_addr6, ares_dns_rr_get_bin, ares_dns_rr_get_class, +ares_dns_rr_get_name, ares_dns_rr_get_opt, ares_dns_rr_get_opt_byid, +ares_dns_rr_get_opt_cnt, ares_dns_rr_get_str, ares_dns_rr_get_ttl, +ares_dns_rr_get_type, ares_dns_rr_get_u16, ares_dns_rr_get_u32, +ares_dns_rr_get_u8, ares_dns_rr_key_t, ares_dns_rr_set_addr, +ares_dns_rr_set_addr6, ares_dns_rr_set_bin, ares_dns_rr_set_opt, +ares_dns_rr_set_str, ares_dns_rr_set_u16, ares_dns_rr_set_u32, +ares_dns_rr_set_u8, ares_dns_section_t, ares_tlsa_match_t, ares_tlsa_selector_t, ares_tlsa_usage_t \- DNS Resource Record creating, reading, and writing functions. .SH SYNOPSIS @@ -33,6 +34,10 @@ ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec, ares_dns_section_t sect, size_t idx); +const ares_dns_rr_t *ares_dns_record_rr_get_const(const ares_dns_record_t *dnsrec, + ares_dns_section_t sect, + size_t idx); + ares_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec, ares_dns_section_t sect, size_t idx); @@ -357,14 +362,17 @@ parameter, and the Time To Live (TTL) in the parameter. -The \fIares_dns_record_rr_get(3)\fP function is used to retrieve the resource -record pointer from the DNS record provided in the +The \fIares_dns_record_rr_get(3)\fP and \fIares_dns_record_rr_get_const(3)\fP +functions are used to retrieve the resource record pointer from the DNS record +provided in the .IR dnsrec parameter, for the resource record section provided in the .IR sect parameter, for the specified index in the .IR idx -parameter. The index must be less than \fIares_dns_record_rr_cnt(3)\fP. +parameter. The index must be less than \fIares_dns_record_rr_cnt(3)\fP. The +former returns a writable pointer to the resource record, while the latter +returns a read-only pointer to the resource record. The \fIares_dns_record_rr_del(3)\fP is used to delete a resource record from @@ -615,8 +623,8 @@ prescribed datatype values and in general can't fail except for misuse cases, in which a 0 (or NULL) may be returned, however 0 can also be a valid return value for most of these functions. -\fIares_dns_record_rr_get(3)\fP will return the requested resource record -pointer or NULL on failure (misuse). +\fIares_dns_record_rr_get(3)\fP and \fIares_dns_record_rr_get_const(3)\fP will +return the requested resource record pointer or NULL on failure (misuse). \fIares_dns_rr_get_opt_byid(3)\fP will return ARES_TRUE if the option was found, otherwise ARES_FALSE if not found (or misuse). diff --git a/deps/cares/docs/ares_init_options.3 b/deps/cares/docs/ares_init_options.3 index 000cc1d9a592b5..72889b5b4874ef 100644 --- a/deps/cares/docs/ares_init_options.3 +++ b/deps/cares/docs/ares_init_options.3 @@ -158,7 +158,7 @@ before giving up. The default is three tries. The number of dots which must be present in a domain name for it to be queried for "as is" prior to querying for it with the default domain extensions appended. The default value is 1 unless set otherwise by -resolv.conf or the RES_OPTIONS environment variable. +resolv.conf or the RES_OPTIONS environment variable. Valid range is 0-15. .TP 18 .B ARES_OPT_MAXTIMEOUTMS .B int \fImaxtimeout\fP; diff --git a/deps/cares/docs/ares_query.3 b/deps/cares/docs/ares_query.3 index 00e44f52594d90..24decf7009441b 100644 --- a/deps/cares/docs/ares_query.3 +++ b/deps/cares/docs/ares_query.3 @@ -9,19 +9,32 @@ ares_query \- Initiate a single-question DNS query .nf #include -typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, - int \fItimeouts\fP, unsigned char *\fIabuf\fP, - int \fIalen\fP) +typedef void (*ares_callback_dnsrec)(void *arg, ares_status_t status, + size_t timeouts, + const ares_dns_record_t *dnsrec); + +ares_status_t ares_query_dnsrec(ares_channel_t *channel, + const char *name, + ares_dns_class_t dnsclass, + ares_dns_rec_type_t type, + ares_callback_dnsrec callback, + void *arg, + unsigned short *qid); + +typedef void (*ares_callback)(void *arg, int status, + int timeouts, unsigned char *abuf, + int alen); + +void ares_query(ares_channel_t *channel, const char *name, + int dnsclass, int type, + ares_callback callback, void *arg); -void ares_query(ares_channel_t *\fIchannel\fP, const char *\fIname\fP, - int \fIdnsclass\fP, int \fItype\fP, - ares_callback \fIcallback\fP, void *\fIarg\fP) .fi + .SH DESCRIPTION -The -.B ares_query -function initiates a single-question DNS query on the name service -channel identified by + +The \fBares_query_dnsrec(3)\fP and \fBares_query(3)\fP functions initiate a +single-question DNS query on the name service channel identified by .IR channel . The parameter .I name @@ -31,27 +44,27 @@ a label must be escaped with a backslash. The parameters .I dnsclass and .I type -give the class and type of the query using the values defined in -.BR . +give the class and type of the query. + +\fBares_query_dnsrec(3)\fP uses the ares \fBares_dns_class_t\fP and +\fBares_dns_rec_type_t\fP defined types. However, \fBares_query(3)\fP uses +the values defined in \fB\fP. + When the query is complete or has failed, the ares library will invoke .IR callback . -Completion or failure of the query may happen immediately, or may -happen during a later call to -.BR ares_process (3) -or -.BR ares_destroy (3). -.PP +Completion or failure of the query may happen immediately (even before the +return of the function call), or may happen during a later call to +\fBares_process(3)\fP or \fBares_destroy(3)\fP. + If this is called from a thread other than which the main program event loop is running, care needs to be taken to ensure any file descriptor lists are updated immediately within the eventloop. When the associated callback is called, it is called with a channel lock so care must be taken to ensure any processing is minimal to prevent DNS channel stalls. -.PP + The callback argument .I arg -is copied from the -.B ares_query -argument +is copied from the \fBares_query_dnsrec(3)\fP or \fBares_query(3)\fP argument .IR arg . The callback argument .I status @@ -73,9 +86,7 @@ The query completed but the server claims to have experienced a failure. (This code can only occur if the .B ARES_FLAG_NOCHECKRESP flag was specified at channel initialization time; otherwise, such -responses are ignored at the -.BR ares_send (3) -level.) +responses are ignored at the \fBares_send_dnsrec(3)\fP level.) .TP 19 .B ARES_ENOTFOUND The query completed but the queried-for domain name was not found. @@ -85,18 +96,14 @@ The query completed but the server does not implement the operation requested by the query. (This code can only occur if the .B ARES_FLAG_NOCHECKRESP flag was specified at channel initialization time; otherwise, such -responses are ignored at the -.BR ares_send (3) -level.) +responses are ignored at the \fBares_send_dnsrec(3)\fP level.) .TP 19 .B ARES_EREFUSED The query completed but the server refused the query. (This code can only occur if the .B ARES_FLAG_NOCHECKRESP flag was specified at channel initialization time; otherwise, such -responses are ignored at the -.BR ares_send (3) -level.) +responses are ignored at the \fBares_send_dnsrec(3)\fP level.) .TP 19 .B ARES_EBADNAME The query name @@ -126,23 +133,26 @@ is being destroyed; the query will not be completed. The query will not be completed because no DNS servers were configured on the channel. .PP + The callback argument .I timeouts reports how many times a query timed out during the execution of the given request. -.PP + If the query completed (even if there was something wrong with it, as indicated by some of the above error codes), the callback argument +.I dnsrec +or .I abuf -points to a result buffer of length -.IR alen . -If the query did not complete, -.I abuf -will be NULL and -.I alen -will be 0. +will be non-NULL, otherwise they will be NULL. + +.SH AVAILABILITY +\fBares_query_dnsrec(3)\fP was introduced in c-ares 1.28.0. + .SH SEE ALSO -.BR ares_process (3) +.BR ares_process (3), +.BR ares_dns_record (3) + .SH AUTHOR Greg Hudson, MIT Information Systems .br diff --git a/deps/cares/docs/ares_query_dnsrec.3 b/deps/cares/docs/ares_query_dnsrec.3 new file mode 100644 index 00000000000000..b178e987646055 --- /dev/null +++ b/deps/cares/docs/ares_query_dnsrec.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_query.3 diff --git a/deps/cares/docs/ares_queue.3 b/deps/cares/docs/ares_queue.3 new file mode 100644 index 00000000000000..1212e8d3f8c3cc --- /dev/null +++ b/deps/cares/docs/ares_queue.3 @@ -0,0 +1,53 @@ +.\" +.\" SPDX-License-Identifier: MIT +.\" +.TH ARES_QUEUE 3 "16 February 2024" +.SH NAME +ares_queue_wait_empty, ares_queue_active_queries \- Functions for checking the +c-ares queue status +.SH SYNOPSIS +.nf +#include + +size_t ares_queue_active_queries(ares_channel_t *channel); + +ares_status_t ares_queue_wait_empty(ares_channel_t *channel, + int timeout_ms); +.fi +.SH DESCRIPTION +The \fBares_queue_active_queries(3)\fP function retrieves the total number of +active queries pending answers from servers. Some c-ares requests may spawn +multiple queries, such as \fIares_getaddrinfo(3)\fP when using \fIAF_UNSPEC\fP, +which will be reflected in this number. The \fBchannel\fP parameter must be set +to an initialized channel. + +The \fBares_queue_wait_empty(3)\fP function blocks until notified that there are +no longer any queries in queue, or the specified timeout has expired. The +\fBchannel\fP parameter must be set to an initialized channel. The +\fBtimeout_ms\fP parameter is the number of milliseconds to wait for the queue +to be empty or -1 for Infinite. + +.SH RETURN VALUES +\fIares_queue_active_queries(3)\fP returns the active query count. + +\fIares_queue_wait_empty(3)\fP can return any of the following values: +.TP 14 +.B ARES_ENOTIMP +if not built with threading support +.TP 14 +.B ARES_ETIMEOUT +if requested timeout expired +.TP 14 +.B ARES_SUCCESS +when queue is empty. +.TP 14 + +.SH AVAILABILITY +This function was first introduced in c-ares version 1.27.0, and requires the +c-ares library to be built with threading support. + +.SH SEE ALSO +.BR ares_init_options (3), +.BR ares_threadsafety (3) +.SH AUTHOR +Copyright (C) 2024 The c-ares project and its members. diff --git a/deps/cares/docs/ares_queue_active_queries.3 b/deps/cares/docs/ares_queue_active_queries.3 new file mode 100644 index 00000000000000..c16c69ddcb9e02 --- /dev/null +++ b/deps/cares/docs/ares_queue_active_queries.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2024 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_queue.3 diff --git a/deps/cares/docs/ares_queue_wait_empty.3 b/deps/cares/docs/ares_queue_wait_empty.3 new file mode 100644 index 00000000000000..c16c69ddcb9e02 --- /dev/null +++ b/deps/cares/docs/ares_queue_wait_empty.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2024 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_queue.3 diff --git a/deps/cares/docs/ares_search.3 b/deps/cares/docs/ares_search.3 index 08246d349d02fd..1a324b0ff47db5 100644 --- a/deps/cares/docs/ares_search.3 +++ b/deps/cares/docs/ares_search.3 @@ -9,13 +9,23 @@ ares_search \- Initiate a DNS query with domain search .nf #include +typedef void (*ares_callback_dnsrec)(void *\fIarg\fP, + ares_status_t \fIstatus\fP, + size_t \fItimeouts\fP, + const ares_dns_record_t *\fIdnsrec\fP); + +void ares_search_dnsrec(ares_channel_t *\fIchannel\fP, + const ares_dns_record_t *\fIdnsrec\fP, + ares_callback_dnsrec \fIcallback\fP, void *\fIarg\fP); + typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, int \fItimeouts\fP, unsigned char *\fIabuf\fP, - int \fIalen\fP) + int \fIalen\fP); void ares_search(ares_channel_t *\fIchannel\fP, const char *\fIname\fP, int \fIdnsclass\fP, int \fItype\fP, - ares_callback \fIcallback\fP, void *\fIarg\fP) + ares_callback \fIcallback\fP, void *\fIarg\fP); + .fi .SH DESCRIPTION The @@ -142,9 +152,34 @@ will usually be NULL and will usually be 0, but in some cases an unsuccessful query result may be placed in .IR abuf . + +The \fIares_search_dnsrec(3)\fP function behaves identically to +\fIares_search(3)\fP, but takes an initialized and filled DNS record object to +use for queries as the second argument +.I dnsrec +instead of a name, class and type. This object is used as the base for the +queries and must itself represent a valid query for a single name. Note that +the search domains will only be appended to the name in the question section; +RRs on the DNS record object will not be affected. Moreover, the +.I callback +argument is of type \fIares_callback_dnsrec\fP. This callback behaves +identically to \fIares_callback\fP, but is invoked with a parsed DNS record +object +.I dnsrec +rather than a raw buffer with length. Note that this object is read-only. + +The \fIares_search_dnsrec(3)\fP function returns an \fIares_status_t\fP response +code. This may be useful to know that the query was enqueued properly. The +response code does not reflect the result of the query, just the result of the +enqueuing of the query. + +.SH AVAILABILITY +\fBares_search_dnsrec(3)\fP was introduced in c-ares 1.28.0. + .SH SEE ALSO .BR ares_process (3), .BR ares_dns_record (3) + .SH AUTHOR Greg Hudson, MIT Information Systems .br diff --git a/deps/cares/docs/ares_search_dnsrec.3 b/deps/cares/docs/ares_search_dnsrec.3 new file mode 100644 index 00000000000000..86c2317c071144 --- /dev/null +++ b/deps/cares/docs/ares_search_dnsrec.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_search.3 diff --git a/deps/cares/docs/ares_send.3 b/deps/cares/docs/ares_send.3 index 1fe1c0273e7379..010bb2579174bd 100644 --- a/deps/cares/docs/ares_send.3 +++ b/deps/cares/docs/ares_send.3 @@ -9,46 +9,78 @@ ares_send \- Initiate a DNS query .nf #include -typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP, - int \fItimeouts\fP, unsigned char *\fIabuf\fP, - int \fIalen\fP) +typedef void (*ares_callback_dnsrec)(void *arg, ares_status_t status, + size_t timeouts, + const ares_dns_record_t *dnsrec); + +ares_status_t ares_send_dnsrec(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, + void *arg, unsigned short *qid); + +typedef void (*ares_callback)(void *arg, int status, + int timeouts, unsigned char *abuf, + int alen); + +void ares_send(ares_channel_t *channel, const unsigned char *qbuf, + int qlen, ares_callback callback, void *arg); -void ares_send(ares_channel_t *\fIchannel\fP, const unsigned char *\fIqbuf\fP, - int \fIqlen\fP, ares_callback \fIcallback\fP, void *\fIarg\fP) .fi .SH DESCRIPTION -The -.B ares_send -function initiates a DNS query on the name service channel identified -by -.IR channel . -The parameters -.I qbuf +The \fIares_send_dnsrec(3)\fP function initiates a DNS query formatted using the +\fIares_dns_record_t *\fP data structure created via +\fIares_dns_record_create(3)\fP in the +.IR dnsrec +parameter. The supplied callback in the +.IR callback +parameter also returns the response using a +\fIares_dns_record_t *\fP data structure. + +The \fIares_send(3)\fP function similarly initiates a DNS query, but instead uses +raw binary buffers with fully formatted DNS messages passed in the request via the +.IR qbuf and -.I qlen -give the DNS query, which should already have been formatted according -to the DNS protocol. When the query is complete or has failed, the -ares library will invoke -.IR callback . -Completion or failure of the query may happen immediately, or may -happen later as network events are processed. -.PP +.IR qlen +parameters. The supplied callback in the +.IR callback +parameter also returns the raw binary DNS response in the +.IR abuf +and +.IR alen +parameters. This method should be considered deprecated in favor of +\fIares_send_dnsrec(3)\fP. + +Both functions take an initialized ares channel identified by +.IR channel . + +The \fIares_send_dnsrec(3)\fP also can be supplied an optional output parameter of +.IR qid +to populate the query id as it was placed on the wire. + +The \fIares_send_dnsrec(3)\fP function returns an \fIares_status_t\fP response +code. This may be useful to know that the query was enqueued properly. The +response code does not reflect the result of the query, just the result of the +enqueuing of the query. + +Completion or failure of the query may happen immediately (even before the +function returning), or may happen later as network events are processed. + When the associated callback is called, it is called with a channel lock so care must be taken to ensure any processing is minimal to prevent DNS channel stalls. The callback may be triggered from a different thread than the one which -called \fIares_send(3)\fP. +called \fIares_send_dnsrec(3)\fP or \fIares_send(3)\fP. For integrators running their own event loops and not using \fBARES_OPT_EVENT_THREAD\fP, care needs to be taken to ensure any file descriptor lists are updated immediately within the eventloop when notified. -.PP + The callback argument -.I arg -is copied from the -.B ares_send -argument -.IR arg . +.IR arg +is copied from the \fIares_send_dnsrec(3)\fP or \fIares_send(3)\fP +.IR arg +parameter. + The callback argument .I status indicates whether the query succeeded and, if not, how it failed. It @@ -82,43 +114,44 @@ is being destroyed; the query will not be completed. The query will not be completed because no DNS servers were configured on the channel. .PP + The callback argument .I timeouts reports how many times a query timed out during the execution of the given request. -.PP + If the query completed, the callback argument -.I abuf -points to a result buffer of length -.IR alen . -If the query did not complete, -.I abuf -will be NULL and -.I alen -will be 0. -.PP +.IR dnsrec +for \fIares_send_dnsrec(3)\fP or +.IR abuf +and +.IR alen +for \fIares_send(3)\fP will be non-NULL. + Unless the flag .B ARES_FLAG_NOCHECKRESP -was set at channel initialization time, -.B ares_send -will normally ignore responses whose questions do not match the -questions in -.IR qbuf , -as well as responses with reply codes of +was set at channel initialization time, \fIares_send_dnsrec(3)\fP and +\fIares_send(3)\fP will normally ignore responses whose questions do not match +the supplied questions, as well as responses with reply codes of .BR SERVFAIL , .BR NOTIMP , and .BR REFUSED . Unlike other query functions in the ares library, however, -.B ares_send -does not inspect the header of the reply packet to determine the error -status, so a callback status of +\fIares_send_dnsrec(3)\fP and \fIares_send(3)\fP do not inspect the header of +the reply packet to determine the error status, so a callback status of .B ARES_SUCCESS -does not reflect as much about the response as for other query -functions. +does not reflect as much about the response as for other query functions. + +.SH AVAILABILITY +\fBares_send_dnsrec(3)\fP was introduced in c-ares 1.28.0. + .SH SEE ALSO +.BR ares_dns_record_create (3), .BR ares_process (3), +.BR ares_search (3), .BR ares_dns_record (3) + .SH AUTHOR Greg Hudson, MIT Information Systems .br diff --git a/deps/cares/docs/ares_send_dnsrec.3 b/deps/cares/docs/ares_send_dnsrec.3 new file mode 100644 index 00000000000000..f5596f5cf049bc --- /dev/null +++ b/deps/cares/docs/ares_send_dnsrec.3 @@ -0,0 +1,3 @@ +.\" Copyright (C) 2023 The c-ares project and its contributors. +.\" SPDX-License-Identifier: MIT +.so man3/ares_send.3 diff --git a/deps/cares/include/Makefile.in b/deps/cares/include/Makefile.in index cf8cb55170cc8b..6e06995bfc5a3b 100644 --- a/deps/cares/include/Makefile.in +++ b/deps/cares/include/Makefile.in @@ -274,6 +274,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ diff --git a/deps/cares/include/ares.h b/deps/cares/include/ares.h index acbd6583074a56..bc17230e47262f 100644 --- a/deps/cares/include/ares.h +++ b/deps/cares/include/ares.h @@ -119,6 +119,37 @@ extern "C" { # endif #endif +#ifdef __GNUC__ +# define CARES_GCC_VERSION \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#else +# define CARES_GCC_VERSION 0 +#endif + +#ifndef __has_attribute +# define __has_attribute(x) 0 +#endif + +#ifdef CARES_NO_DEPRECATED +# define CARES_DEPRECATED +# define CARES_DEPRECATED_FOR(f) +#else +# if CARES_GCC_VERSION >= 30200 || __has_attribute(__deprecated__) +# define CARES_DEPRECATED __attribute__((__deprecated__)) +# else +# define CARES_DEPRECATED +# endif + +# if CARES_GCC_VERSION >= 40500 || defined(__clang__) +# define CARES_DEPRECATED_FOR(f) \ + __attribute__((deprecated("Use " #f " instead"))) +# elif defined(_MSC_VER) +# define CARES_DEPRECATED_FOR(f) __declspec(deprecated("Use " #f " instead")) +# else +# define CARES_DEPRECATED_FOR(f) CARES_DEPRECATED +# endif +#endif + typedef enum { ARES_SUCCESS = 0, @@ -352,29 +383,57 @@ typedef struct ares_channeldata *ares_channel; /* Current main channel typedef */ typedef struct ares_channeldata ares_channel_t; +/* + * NOTE: before c-ares 1.7.0 we would most often use the system in6_addr + * struct below when ares itself was built, but many apps would use this + * private version since the header checked a HAVE_* define for it. Starting + * with 1.7.0 we always declare and use our own to stop relying on the + * system's one. + */ +struct ares_in6_addr { + union { + unsigned char _S6_u8[16]; + } _S6_un; +}; + +struct ares_addr { + int family; + + union { + struct in_addr addr4; + struct ares_in6_addr addr6; + } addr; +}; + +/* DNS record parser, writer, and helpers */ +#include "ares_dns_record.h" -typedef void (*ares_callback)(void *arg, int status, int timeouts, +typedef void (*ares_callback)(void *arg, int status, int timeouts, unsigned char *abuf, int alen); -typedef void (*ares_host_callback)(void *arg, int status, int timeouts, +typedef void (*ares_callback_dnsrec)(void *arg, ares_status_t status, + size_t timeouts, + const ares_dns_record_t *dnsrec); + +typedef void (*ares_host_callback)(void *arg, int status, int timeouts, struct hostent *hostent); -typedef void (*ares_nameinfo_callback)(void *arg, int status, int timeouts, +typedef void (*ares_nameinfo_callback)(void *arg, int status, int timeouts, char *node, char *service); -typedef int (*ares_sock_create_callback)(ares_socket_t socket_fd, int type, +typedef int (*ares_sock_create_callback)(ares_socket_t socket_fd, int type, void *data); -typedef int (*ares_sock_config_callback)(ares_socket_t socket_fd, int type, +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, +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, void *(*amalloc)(size_t size), - void (*afree)(void *ptr), + void (*afree)(void *ptr), void *(*arealloc)(void *ptr, size_t size)); @@ -384,13 +443,14 @@ CARES_EXTERN int ares_library_init_android(jobject connectivity_manager); CARES_EXTERN int ares_library_android_initialized(void); #endif -CARES_EXTERN int ares_library_initialized(void); +CARES_EXTERN int ares_library_initialized(void); -CARES_EXTERN void ares_library_cleanup(void); +CARES_EXTERN void ares_library_cleanup(void); -CARES_EXTERN const char *ares_version(int *version); +CARES_EXTERN const char *ares_version(int *version); -CARES_EXTERN int ares_init(ares_channel_t **channelptr); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_init_options) int ares_init( + ares_channel_t **channelptr); CARES_EXTERN int ares_init_options(ares_channel_t **channelptr, const struct ares_options *options, @@ -453,7 +513,7 @@ struct iovec; struct ares_socket_functions { ares_socket_t (*asocket)(int, int, int, void *); - int (*aclose)(ares_socket_t, void *); + int (*aclose)(ares_socket_t, void *); int (*aconnect)(ares_socket_t, const struct sockaddr *, ares_socklen_t, void *); ares_ssize_t (*arecvfrom)(ares_socket_t, void *, size_t, int, @@ -462,24 +522,76 @@ struct ares_socket_functions { }; CARES_EXTERN void - ares_set_socket_functions(ares_channel_t *channel, - const struct ares_socket_functions *funcs, - void *user_data); + ares_set_socket_functions(ares_channel_t *channel, + const struct ares_socket_functions *funcs, + void *user_data); + +CARES_EXTERN CARES_DEPRECATED_FOR(ares_send_dnsrec) void ares_send( + ares_channel_t *channel, const unsigned char *qbuf, int qlen, + ares_callback callback, void *arg); -CARES_EXTERN void ares_send(ares_channel_t *channel, const unsigned char *qbuf, - int qlen, ares_callback callback, void *arg); +/*! Send a DNS query as an ares_dns_record_t with a callback containing the + * parsed DNS record. + * + * \param[in] channel Pointer to channel on which queries will be sent. + * \param[in] dnsrec DNS Record to send + * \param[in] callback Callback function invoked on completion or failure of + * the query sequence. + * \param[in] arg Additional argument passed to the callback function. + * \param[out] qid Query ID + * \return One of the c-ares status codes. + */ +CARES_EXTERN ares_status_t ares_send_dnsrec(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, + void *arg, unsigned short *qid); -CARES_EXTERN void ares_query(ares_channel_t *channel, const char *name, - int dnsclass, int type, ares_callback callback, - void *arg); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_query_dnsrec) void ares_query( + ares_channel_t *channel, const char *name, int dnsclass, int type, + ares_callback callback, void *arg); -CARES_EXTERN void ares_search(ares_channel_t *channel, const char *name, - int dnsclass, int type, ares_callback callback, - void *arg); +/*! Perform a DNS query with a callback containing the parsed DNS record. + * + * \param[in] channel Pointer to channel on which queries will be sent. + * \param[in] name Query name + * \param[in] dnsclass DNS Class + * \param[in] type DNS Record Type + * \param[in] callback Callback function invoked on completion or failure of + * the query sequence. + * \param[in] arg Additional argument passed to the callback function. + * \param[out] qid Query ID + * \return One of the c-ares status codes. + */ +CARES_EXTERN ares_status_t ares_query_dnsrec(ares_channel_t *channel, + const char *name, + ares_dns_class_t dnsclass, + ares_dns_rec_type_t type, + ares_callback_dnsrec callback, + void *arg, unsigned short *qid); + +CARES_EXTERN CARES_DEPRECATED_FOR(ares_search_dnsrec) void ares_search( + ares_channel_t *channel, const char *name, int dnsclass, int type, + ares_callback callback, void *arg); + +/*! Search for a complete DNS message. + * + * \param[in] channel Pointer to channel on which queries will be sent. + * \param[in] dnsrec Pointer to initialized and filled DNS record object. + * \param[in] callback Callback function invoked on completion or failure of + * the query sequence. + * \param[in] arg Additional argument passed to the callback function. + * \return One of the c-ares status codes. In all cases, except + * ARES_EFORMERR due to misuse, this error code will also be sent + * to the provided callback. + */ +CARES_EXTERN ares_status_t ares_search_dnsrec(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, + void *arg); -CARES_EXTERN void ares_gethostbyname(ares_channel_t *channel, const char *name, - int family, ares_host_callback callback, - void *arg); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_getaddrinfo) void ares_gethostbyname( + ares_channel_t *channel, const char *name, int family, + ares_host_callback callback, void *arg); CARES_EXTERN int ares_gethostbyname_file(ares_channel_t *channel, const char *name, int family, @@ -494,61 +606,42 @@ CARES_EXTERN void ares_getnameinfo(ares_channel_t *channel, ares_socklen_t salen, int flags, ares_nameinfo_callback callback, void *arg); -CARES_EXTERN int ares_fds(ares_channel_t *channel, fd_set *read_fds, - fd_set *write_fds); +CARES_EXTERN CARES_DEPRECATED_FOR( + ARES_OPT_EVENT_THREAD or + ARES_OPT_SOCK_STATE_CB) int ares_fds(ares_channel_t *channel, + fd_set *read_fds, fd_set *write_fds); -CARES_EXTERN int ares_getsock(ares_channel_t *channel, ares_socket_t *socks, - int numsocks); +CARES_EXTERN CARES_DEPRECATED_FOR( + ARES_OPT_EVENT_THREAD or + ARES_OPT_SOCK_STATE_CB) int ares_getsock(ares_channel_t *channel, + ares_socket_t *socks, int numsocks); CARES_EXTERN struct timeval *ares_timeout(ares_channel_t *channel, struct timeval *maxtv, struct timeval *tv); -CARES_EXTERN void ares_process(ares_channel_t *channel, fd_set *read_fds, - fd_set *write_fds); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_process_fd) void ares_process( + ares_channel_t *channel, fd_set *read_fds, fd_set *write_fds); CARES_EXTERN void ares_process_fd(ares_channel_t *channel, ares_socket_t read_fd, ares_socket_t write_fd); -CARES_EXTERN int ares_create_query(const char *name, int dnsclass, int type, - unsigned short id, int rd, - unsigned char **buf, int *buflen, - int max_udp_size); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_record_create) int ares_create_query( + const char *name, int dnsclass, int type, unsigned short id, int rd, + unsigned char **buf, int *buflen, int max_udp_size); -CARES_EXTERN int ares_mkquery(const char *name, int dnsclass, int type, - unsigned short id, int rd, unsigned char **buf, - int *buflen); - -CARES_EXTERN int ares_expand_name(const unsigned char *encoded, - const unsigned char *abuf, int alen, char **s, - long *enclen); - -CARES_EXTERN int ares_expand_string(const unsigned char *encoded, - const unsigned char *abuf, int alen, - unsigned char **s, long *enclen); - -/* - * NOTE: before c-ares 1.7.0 we would most often use the system in6_addr - * struct below when ares itself was built, but many apps would use this - * private version since the header checked a HAVE_* define for it. Starting - * with 1.7.0 we always declare and use our own to stop relying on the - * system's one. - */ -struct ares_in6_addr { - union { - unsigned char _S6_u8[16]; - } _S6_un; -}; +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_record_create) int ares_mkquery( + const char *name, int dnsclass, int type, unsigned short id, int rd, + unsigned char **buf, int *buflen); -struct ares_addr { - int family; +CARES_EXTERN int ares_expand_name(const unsigned char *encoded, + const unsigned char *abuf, int alen, char **s, + long *enclen); - union { - struct in_addr addr4; - struct ares_in6_addr addr6; - } addr; -}; +CARES_EXTERN int ares_expand_string(const unsigned char *encoded, + const unsigned char *abuf, int alen, + unsigned char **s, long *enclen); struct ares_addrttl { struct in_addr ipaddr; @@ -675,52 +768,50 @@ struct ares_addrinfo_hints { ** so written. */ -CARES_EXTERN int ares_parse_a_reply(const unsigned char *abuf, int alen, - struct hostent **host, - struct ares_addrttl *addrttls, - int *naddrttls); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_a_reply( + const unsigned char *abuf, int alen, struct hostent **host, + struct ares_addrttl *addrttls, int *naddrttls); -CARES_EXTERN int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, - struct hostent **host, - struct ares_addr6ttl *addrttls, - int *naddrttls); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_aaaa_reply( + const unsigned char *abuf, int alen, struct hostent **host, + struct ares_addr6ttl *addrttls, int *naddrttls); -CARES_EXTERN int ares_parse_caa_reply(const unsigned char *abuf, int alen, - struct ares_caa_reply **caa_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_caa_reply( + const unsigned char *abuf, int alen, struct ares_caa_reply **caa_out); -CARES_EXTERN int ares_parse_ptr_reply(const unsigned char *abuf, int alen, - const void *addr, int addrlen, int family, - struct hostent **host); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_ptr_reply( + const unsigned char *abuf, int alen, const void *addr, int addrlen, + int family, struct hostent **host); -CARES_EXTERN int ares_parse_ns_reply(const unsigned char *abuf, int alen, - struct hostent **host); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_ns_reply( + const unsigned char *abuf, int alen, struct hostent **host); -CARES_EXTERN int ares_parse_srv_reply(const unsigned char *abuf, int alen, - struct ares_srv_reply **srv_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_srv_reply( + const unsigned char *abuf, int alen, struct ares_srv_reply **srv_out); -CARES_EXTERN int ares_parse_mx_reply(const unsigned char *abuf, int alen, - struct ares_mx_reply **mx_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_mx_reply( + const unsigned char *abuf, int alen, struct ares_mx_reply **mx_out); -CARES_EXTERN int ares_parse_txt_reply(const unsigned char *abuf, int alen, - struct ares_txt_reply **txt_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_txt_reply( + const unsigned char *abuf, int alen, struct ares_txt_reply **txt_out); -CARES_EXTERN int ares_parse_txt_reply_ext(const unsigned char *abuf, int alen, - struct ares_txt_ext **txt_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_txt_reply_ext( + const unsigned char *abuf, int alen, struct ares_txt_ext **txt_out); -CARES_EXTERN int ares_parse_naptr_reply(const unsigned char *abuf, int alen, - struct ares_naptr_reply **naptr_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_naptr_reply( + const unsigned char *abuf, int alen, struct ares_naptr_reply **naptr_out); -CARES_EXTERN int ares_parse_soa_reply(const unsigned char *abuf, int alen, - struct ares_soa_reply **soa_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_soa_reply( + const unsigned char *abuf, int alen, struct ares_soa_reply **soa_out); -CARES_EXTERN int ares_parse_uri_reply(const unsigned char *abuf, int alen, - struct ares_uri_reply **uri_out); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_uri_reply( + const unsigned char *abuf, int alen, struct ares_uri_reply **uri_out); -CARES_EXTERN void ares_free_string(void *str); +CARES_EXTERN void ares_free_string(void *str); -CARES_EXTERN void ares_free_hostent(struct hostent *host); +CARES_EXTERN void ares_free_hostent(struct hostent *host); -CARES_EXTERN void ares_free_data(void *dataptr); +CARES_EXTERN void ares_free_data(void *dataptr); CARES_EXTERN const char *ares_strerror(int code); @@ -747,23 +838,26 @@ struct ares_addr_port_node { int tcp_port; }; -CARES_EXTERN int ares_set_servers(ares_channel_t *channel, - const struct ares_addr_node *servers); -CARES_EXTERN int - ares_set_servers_ports(ares_channel_t *channel, - const struct ares_addr_port_node *servers); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_set_servers_csv) int ares_set_servers( + ares_channel_t *channel, const struct ares_addr_node *servers); + +CARES_EXTERN + CARES_DEPRECATED_FOR(ares_set_servers_ports_csv) int ares_set_servers_ports( + ares_channel_t *channel, const struct ares_addr_port_node *servers); /* Incoming string format: host[:port][,host[:port]]... */ -CARES_EXTERN int ares_set_servers_csv(ares_channel_t *channel, - const char *servers); -CARES_EXTERN int ares_set_servers_ports_csv(ares_channel_t *channel, - const char *servers); -CARES_EXTERN char *ares_get_servers_csv(ares_channel_t *channel); +CARES_EXTERN int ares_set_servers_csv(ares_channel_t *channel, + const char *servers); +CARES_EXTERN int ares_set_servers_ports_csv(ares_channel_t *channel, + const char *servers); +CARES_EXTERN char *ares_get_servers_csv(ares_channel_t *channel); -CARES_EXTERN int ares_get_servers(ares_channel_t *channel, - struct ares_addr_node **servers); -CARES_EXTERN int ares_get_servers_ports(ares_channel_t *channel, - struct ares_addr_port_node **servers); +CARES_EXTERN CARES_DEPRECATED_FOR(ares_get_servers_csv) int ares_get_servers( + ares_channel_t *channel, struct ares_addr_node **servers); + +CARES_EXTERN + CARES_DEPRECATED_FOR(ares_get_servers_ports_csv) int ares_get_servers_ports( + ares_channel_t *channel, struct ares_addr_port_node **servers); CARES_EXTERN const char *ares_inet_ntop(int af, const void *src, char *dst, ares_socklen_t size); @@ -803,7 +897,4 @@ CARES_EXTERN size_t ares_queue_active_queries(ares_channel_t *channel); } #endif -/* DNS record parser, writer, and helpers */ -#include "ares_dns_record.h" - #endif /* ARES__H */ diff --git a/deps/cares/include/ares_dns_record.h b/deps/cares/include/ares_dns_record.h index 3f802aefa3231e..8d09bd0a464254 100644 --- a/deps/cares/include/ares_dns_record.h +++ b/deps/cares/include/ares_dns_record.h @@ -393,11 +393,11 @@ typedef enum { /*! Parse Additional from RFC 1035 that allow name compression as RAW */ ARES_DNS_PARSE_AR_BASE_RAW = 1 << 2, /*! Parse Answers from later RFCs (no name compression) RAW */ - ARES_DNS_PARSE_AN_EXT_RAW = 1 << 3, + ARES_DNS_PARSE_AN_EXT_RAW = 1 << 3, /*! Parse Authority from later RFCs (no name compression) as RAW */ - ARES_DNS_PARSE_NS_EXT_RAW = 1 << 4, - /*< Parse Additional from later RFCs (no name compression) as RAW */ - ARES_DNS_PARSE_AR_EXT_RAW = 1 << 5 + ARES_DNS_PARSE_NS_EXT_RAW = 1 << 4, + /*! Parse Additional from later RFCs (no name compression) as RAW */ + ARES_DNS_PARSE_AR_EXT_RAW = 1 << 5 } ares_dns_parse_flags_t; /*! String representation of DNS Record Type @@ -468,7 +468,7 @@ CARES_EXTERN const char *ares_dns_rcode_tostr(ares_dns_rcode_t rcode); * \param[in] ipaddr ASCII string form of the ip address * \param[in,out] addr Must set "family" member to one of AF_UNSPEC, * AF_INET, AF_INET6 on input. - * \param[out] ptr_len Length of binary form address + * \param[out] out_len Length of binary form address * \return Pointer to start of binary address or NULL on error. */ CARES_EXTERN const void *ares_dns_pton(const char *ipaddr, @@ -619,6 +619,32 @@ CARES_EXTERN ares_status_t ares_dns_record_query_add(ares_dns_record_t *dnsrec, ares_dns_rec_type_t qtype, ares_dns_class_t qclass); +/*! Replace the question name with a new name. This may be used when performing + * a search with aliases. + * + * Note that this will invalidate the name pointer returned from + * ares_dns_record_query_get(). + * + * \param[in] dnsrec Initialized record object + * \param[in] idx Index of question (typically 0) + * \param[in] name Name to use as replacement. + * \return ARES_SUCCESS on success + */ +CARES_EXTERN ares_status_t ares_dns_record_query_set_name( + ares_dns_record_t *dnsrec, size_t idx, const char *name); + + +/*! Replace the question type with a different type. This may be used when + * needing to query more than one address class (e.g. A and AAAA) + * + * \param[in] dnsrec Initialized record object + * \param[in] idx Index of question (typically 0) + * \param[in] qtype Record Type to use as replacement. + * \return ARES_SUCCESS on success + */ +CARES_EXTERN ares_status_t ares_dns_record_query_set_type( + ares_dns_record_t *dnsrec, size_t idx, ares_dns_rec_type_t qtype); + /*! Get the count of queries in the DNS Record * * \param[in] dnsrec Initialized record object @@ -631,6 +657,8 @@ CARES_EXTERN size_t ares_dns_record_query_cnt(const ares_dns_record_t *dnsrec); * \param[in] dnsrec Initialized record object * \param[in] idx Index of query * \param[out] name Optional. Returns name, may pass NULL if not desired. + * This pointer will be invalided by any call to + * ares_dns_record_query_set_name(). * \param[out] qtype Optional. Returns record type, may pass NULL. * \param[out] qclass Optional. Returns class, may pass NULL. * \return ARES_SUCCESS on success @@ -667,17 +695,28 @@ CARES_EXTERN ares_status_t ares_dns_record_rr_add( const char *name, ares_dns_rec_type_t type, ares_dns_class_t rclass, unsigned int ttl); -/*! Fetch a resource record based on the section and index. +/*! Fetch a writable resource record based on the section and index. * * \param[in] dnsrec Initialized record object * \param[in] sect Section for resource record * \param[in] idx Index of resource record in section - * \return NULL on misuse, otherwise a pointer to the resource record + * \return NULL on misuse, otherwise a writable pointer to the resource record */ CARES_EXTERN ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec, ares_dns_section_t sect, size_t idx); +/*! Fetch a non-writeable resource record based on the section and index. + * + * \param[in] dnsrec Initialized record object + * \param[in] sect Section for resource record + * \param[in] idx Index of resource record in section + * \return NULL on misuse, otherwise a const pointer to the resource record + */ +CARES_EXTERN const ares_dns_rr_t * + ares_dns_record_rr_get_const(const ares_dns_record_t *dnsrec, + ares_dns_section_t sect, size_t idx); + /*! Remove the resource record based on the section and index * @@ -686,9 +725,9 @@ CARES_EXTERN ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec, * \param[in] idx Index of resource record in section * \return ARES_SUCCESS on success, otherwise an error code. */ -CARES_EXTERN ares_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec, - ares_dns_section_t sect, - size_t idx); +CARES_EXTERN ares_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec, + ares_dns_section_t sect, + size_t idx); /*! Retrieve the resource record Name/Hostname @@ -696,7 +735,7 @@ CARES_EXTERN ares_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec, * \param[in] rr Pointer to resource record * \return Name */ -CARES_EXTERN const char *ares_dns_rr_get_name(const ares_dns_rr_t *rr); +CARES_EXTERN const char *ares_dns_rr_get_name(const ares_dns_rr_t *rr); /*! Retrieve the resource record type * @@ -959,8 +998,19 @@ CARES_EXTERN ares_status_t ares_dns_parse(const unsigned char *buf, * \param[out] buf_len Length of returned buffer containing DNS message. * \return ARES_SUCCESS on success */ -CARES_EXTERN ares_status_t ares_dns_write(ares_dns_record_t *dnsrec, +CARES_EXTERN ares_status_t ares_dns_write(const ares_dns_record_t *dnsrec, unsigned char **buf, size_t *buf_len); + + +/*! Duplicate a complete DNS message. This does not copy internal members + * (such as the ttl decrement capability). + * + * \param[in] dnsrec Pointer to initialized and filled DNS record object. + * \return duplicted DNS record object, or NULL on out of memory. + */ +CARES_EXTERN ares_dns_record_t * + ares_dns_record_duplicate(const ares_dns_record_t *dnsrec); + /*! @} */ #ifdef __cplusplus diff --git a/deps/cares/include/ares_version.h b/deps/cares/include/ares_version.h index 44dbdef161ac35..0e94a98be8f280 100644 --- a/deps/cares/include/ares_version.h +++ b/deps/cares/include/ares_version.h @@ -31,12 +31,12 @@ #define ARES_COPYRIGHT "2004 - 2024 Daniel Stenberg, ." #define ARES_VERSION_MAJOR 1 -#define ARES_VERSION_MINOR 27 -#define ARES_VERSION_PATCH 0 +#define ARES_VERSION_MINOR 28 +#define ARES_VERSION_PATCH 1 #define ARES_VERSION \ ((ARES_VERSION_MAJOR << 16) | (ARES_VERSION_MINOR << 8) | \ (ARES_VERSION_PATCH)) -#define ARES_VERSION_STR "1.27.0" +#define ARES_VERSION_STR "1.28.1" #if (ARES_VERSION >= 0x010700) # define CARES_HAVE_ARES_LIBRARY_INIT 1 diff --git a/deps/cares/src/Makefile.in b/deps/cares/src/Makefile.in index 040373fe95a247..f657ef0d43e7b9 100644 --- a/deps/cares/src/Makefile.in +++ b/deps/cares/src/Makefile.in @@ -285,6 +285,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ diff --git a/deps/cares/src/lib/CMakeLists.txt b/deps/cares/src/lib/CMakeLists.txt index 015e57f8193ebd..de73f712f1d1ce 100644 --- a/deps/cares/src/lib/CMakeLists.txt +++ b/deps/cares/src/lib/CMakeLists.txt @@ -31,7 +31,6 @@ IF (CARES_SHARED) EXPORT_NAME cares OUTPUT_NAME cares COMPILE_PDB_NAME cares - COMPILE_PDB_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} SOVERSION ${CARES_LIB_VERSION_MAJOR} VERSION "${CARES_LIB_VERSION_MAJOR}.${CARES_LIB_VERSION_MINOR}.${CARES_LIB_VERSION_RELEASE}" C_STANDARD 90 @@ -65,11 +64,13 @@ IF (CARES_SHARED) COMPONENT Library ${TARGETS_INST_DEST} ) - INSTALL(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/cares.pdb - DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT Library - OPTIONAL - ) + IF (MSVC) + INSTALL(FILES $ + DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT Library + OPTIONAL + ) + ENDIF () ENDIF () SET (STATIC_SUFFIX "_static") @@ -88,7 +89,6 @@ IF (CARES_STATIC) EXPORT_NAME cares${STATIC_SUFFIX} OUTPUT_NAME cares${STATIC_SUFFIX} COMPILE_PDB_NAME cares${STATIC_SUFFIX} - COMPILE_PDB_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} C_STANDARD 90 ) @@ -116,11 +116,6 @@ IF (CARES_STATIC) INSTALL (TARGETS ${LIBNAME} EXPORT ${PROJECT_NAME}-targets COMPONENT Devel ${TARGETS_INST_DEST} ) - INSTALL(FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/cares${STATIC_SUFFIX}.pdb - DESTINATION ${CMAKE_INSTALL_BINDIR} - COMPONENT Library - OPTIONAL - ) ENDIF () # For chain building: add alias targets that look like import libs that would be returned by find_package(c-ares). diff --git a/deps/cares/src/lib/Makefile.in b/deps/cares/src/lib/Makefile.in index c516cba2cf46d2..0060295c21e8ef 100644 --- a/deps/cares/src/lib/Makefile.in +++ b/deps/cares/src/lib/Makefile.in @@ -15,7 +15,7 @@ @SET_MAKE@ # aminclude_static.am generated automatically by Autoconf -# from AX_AM_MACROS_STATIC on Fri Jan 26 17:16:19 CET 2024 +# from AX_AM_MACROS_STATIC on Sat Mar 30 16:15:43 CET 2024 # Copyright (C) The c-ares project and its contributors # SPDX-License-Identifier: MIT @@ -169,14 +169,14 @@ am__objects_1 = libcares_la-ares__addrinfo2hostent.lo \ libcares_la-ares__htable_szvp.lo \ libcares_la-ares__iface_ips.lo libcares_la-ares__llist.lo \ libcares_la-ares__parse_into_addrinfo.lo \ - libcares_la-ares__read_line.lo libcares_la-ares__slist.lo \ - libcares_la-ares__socket.lo libcares_la-ares__sortaddrinfo.lo \ - libcares_la-ares__threads.lo libcares_la-ares__timeval.lo \ - libcares_la-ares_android.lo libcares_la-ares_cancel.lo \ - libcares_la-ares_data.lo libcares_la-ares_destroy.lo \ - libcares_la-ares_dns_mapping.lo libcares_la-ares_dns_name.lo \ - libcares_la-ares_dns_parse.lo libcares_la-ares_dns_record.lo \ - libcares_la-ares_dns_write.lo libcares_la-ares_event_epoll.lo \ + libcares_la-ares__slist.lo libcares_la-ares__socket.lo \ + libcares_la-ares__sortaddrinfo.lo libcares_la-ares__threads.lo \ + libcares_la-ares__timeval.lo libcares_la-ares_android.lo \ + libcares_la-ares_cancel.lo libcares_la-ares_data.lo \ + libcares_la-ares_destroy.lo libcares_la-ares_dns_mapping.lo \ + libcares_la-ares_dns_name.lo libcares_la-ares_dns_parse.lo \ + libcares_la-ares_dns_record.lo libcares_la-ares_dns_write.lo \ + libcares_la-ares_event_epoll.lo \ libcares_la-ares_event_kqueue.lo \ libcares_la-ares_event_poll.lo \ libcares_la-ares_event_select.lo \ @@ -193,9 +193,8 @@ am__objects_1 = libcares_la-ares__addrinfo2hostent.lo \ libcares_la-ares_gethostbyname.lo \ libcares_la-ares_getnameinfo.lo libcares_la-ares_getsock.lo \ libcares_la-ares_init.lo libcares_la-ares_library_init.lo \ - libcares_la-ares_math.lo libcares_la-ares_mkquery.lo \ - libcares_la-ares_create_query.lo libcares_la-ares_options.lo \ - libcares_la-ares_parse_a_reply.lo \ + libcares_la-ares_math.lo libcares_la-ares_create_query.lo \ + libcares_la-ares_options.lo libcares_la-ares_parse_a_reply.lo \ libcares_la-ares_parse_aaaa_reply.lo \ libcares_la-ares_parse_caa_reply.lo \ libcares_la-ares_parse_mx_reply.lo \ @@ -254,7 +253,6 @@ am__depfiles_remade = \ ./$(DEPDIR)/libcares_la-ares__iface_ips.Plo \ ./$(DEPDIR)/libcares_la-ares__llist.Plo \ ./$(DEPDIR)/libcares_la-ares__parse_into_addrinfo.Plo \ - ./$(DEPDIR)/libcares_la-ares__read_line.Plo \ ./$(DEPDIR)/libcares_la-ares__slist.Plo \ ./$(DEPDIR)/libcares_la-ares__socket.Plo \ ./$(DEPDIR)/libcares_la-ares__sortaddrinfo.Plo \ @@ -292,7 +290,6 @@ am__depfiles_remade = \ ./$(DEPDIR)/libcares_la-ares_init.Plo \ ./$(DEPDIR)/libcares_la-ares_library_init.Plo \ ./$(DEPDIR)/libcares_la-ares_math.Plo \ - ./$(DEPDIR)/libcares_la-ares_mkquery.Plo \ ./$(DEPDIR)/libcares_la-ares_options.Plo \ ./$(DEPDIR)/libcares_la-ares_parse_a_reply.Plo \ ./$(DEPDIR)/libcares_la-ares_parse_aaaa_reply.Plo \ @@ -505,6 +502,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ @@ -628,7 +626,6 @@ CSOURCES = ares__addrinfo2hostent.c \ ares__iface_ips.c \ ares__llist.c \ ares__parse_into_addrinfo.c \ - ares__read_line.c \ ares__slist.c \ ares__socket.c \ ares__sortaddrinfo.c \ @@ -665,7 +662,6 @@ CSOURCES = ares__addrinfo2hostent.c \ ares_init.c \ ares_library_init.c \ ares_math.c \ - ares_mkquery.c \ ares_create_query.c \ ares_options.c \ ares_parse_a_reply.c \ @@ -834,7 +830,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__iface_ips.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__llist.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__parse_into_addrinfo.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__read_line.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__slist.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__socket.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares__sortaddrinfo.Plo@am__quote@ # am--include-marker @@ -872,7 +867,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_init.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_library_init.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_math.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_mkquery.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_options.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_parse_a_reply.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcares_la-ares_parse_aaaa_reply.Plo@am__quote@ # am--include-marker @@ -1019,13 +1013,6 @@ libcares_la-ares__parse_into_addrinfo.lo: ares__parse_into_addrinfo.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -c -o libcares_la-ares__parse_into_addrinfo.lo `test -f 'ares__parse_into_addrinfo.c' || echo '$(srcdir)/'`ares__parse_into_addrinfo.c -libcares_la-ares__read_line.lo: ares__read_line.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -MT libcares_la-ares__read_line.lo -MD -MP -MF $(DEPDIR)/libcares_la-ares__read_line.Tpo -c -o libcares_la-ares__read_line.lo `test -f 'ares__read_line.c' || echo '$(srcdir)/'`ares__read_line.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcares_la-ares__read_line.Tpo $(DEPDIR)/libcares_la-ares__read_line.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ares__read_line.c' object='libcares_la-ares__read_line.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -c -o libcares_la-ares__read_line.lo `test -f 'ares__read_line.c' || echo '$(srcdir)/'`ares__read_line.c - libcares_la-ares__slist.lo: ares__slist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -MT libcares_la-ares__slist.lo -MD -MP -MF $(DEPDIR)/libcares_la-ares__slist.Tpo -c -o libcares_la-ares__slist.lo `test -f 'ares__slist.c' || echo '$(srcdir)/'`ares__slist.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcares_la-ares__slist.Tpo $(DEPDIR)/libcares_la-ares__slist.Plo @@ -1278,13 +1265,6 @@ libcares_la-ares_math.lo: ares_math.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -c -o libcares_la-ares_math.lo `test -f 'ares_math.c' || echo '$(srcdir)/'`ares_math.c -libcares_la-ares_mkquery.lo: ares_mkquery.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -MT libcares_la-ares_mkquery.lo -MD -MP -MF $(DEPDIR)/libcares_la-ares_mkquery.Tpo -c -o libcares_la-ares_mkquery.lo `test -f 'ares_mkquery.c' || echo '$(srcdir)/'`ares_mkquery.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcares_la-ares_mkquery.Tpo $(DEPDIR)/libcares_la-ares_mkquery.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ares_mkquery.c' object='libcares_la-ares_mkquery.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -c -o libcares_la-ares_mkquery.lo `test -f 'ares_mkquery.c' || echo '$(srcdir)/'`ares_mkquery.c - libcares_la-ares_create_query.lo: ares_create_query.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcares_la_CPPFLAGS) $(CPPFLAGS) $(libcares_la_CFLAGS) $(CFLAGS) -MT libcares_la-ares_create_query.lo -MD -MP -MF $(DEPDIR)/libcares_la-ares_create_query.Tpo -c -o libcares_la-ares_create_query.lo `test -f 'ares_create_query.c' || echo '$(srcdir)/'`ares_create_query.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcares_la-ares_create_query.Tpo $(DEPDIR)/libcares_la-ares_create_query.Plo @@ -1728,7 +1708,6 @@ distclean: distclean-recursive -rm -f ./$(DEPDIR)/libcares_la-ares__iface_ips.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__llist.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__parse_into_addrinfo.Plo - -rm -f ./$(DEPDIR)/libcares_la-ares__read_line.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__slist.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__socket.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__sortaddrinfo.Plo @@ -1766,7 +1745,6 @@ distclean: distclean-recursive -rm -f ./$(DEPDIR)/libcares_la-ares_init.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_library_init.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_math.Plo - -rm -f ./$(DEPDIR)/libcares_la-ares_mkquery.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_options.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_parse_a_reply.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_parse_aaaa_reply.Plo @@ -1855,7 +1833,6 @@ maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/libcares_la-ares__iface_ips.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__llist.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__parse_into_addrinfo.Plo - -rm -f ./$(DEPDIR)/libcares_la-ares__read_line.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__slist.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__socket.Plo -rm -f ./$(DEPDIR)/libcares_la-ares__sortaddrinfo.Plo @@ -1893,7 +1870,6 @@ maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/libcares_la-ares_init.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_library_init.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_math.Plo - -rm -f ./$(DEPDIR)/libcares_la-ares_mkquery.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_options.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_parse_a_reply.Plo -rm -f ./$(DEPDIR)/libcares_la-ares_parse_aaaa_reply.Plo diff --git a/deps/cares/src/lib/Makefile.inc b/deps/cares/src/lib/Makefile.inc index 29a65fd35b1dd0..38f7a115fe3598 100644 --- a/deps/cares/src/lib/Makefile.inc +++ b/deps/cares/src/lib/Makefile.inc @@ -13,7 +13,6 @@ CSOURCES = ares__addrinfo2hostent.c \ ares__iface_ips.c \ ares__llist.c \ ares__parse_into_addrinfo.c \ - ares__read_line.c \ ares__slist.c \ ares__socket.c \ ares__sortaddrinfo.c \ @@ -50,7 +49,6 @@ CSOURCES = ares__addrinfo2hostent.c \ ares_init.c \ ares_library_init.c \ ares_math.c \ - ares_mkquery.c \ ares_create_query.c \ ares_options.c \ ares_parse_a_reply.c \ diff --git a/deps/cares/src/lib/ares__buf.c b/deps/cares/src/lib/ares__buf.c index 8f9f32d71867ff..0663383df9e42e 100644 --- a/deps/cares/src/lib/ares__buf.c +++ b/deps/cares/src/lib/ares__buf.c @@ -45,47 +45,6 @@ struct ares__buf { * SIZE_MAX if not set. */ }; -ares_bool_t ares__isprint(int ch) -{ - if (ch >= 0x20 && ch <= 0x7E) { - return ARES_TRUE; - } - return ARES_FALSE; -} - -/* Character set allowed by hostnames. This is to include the normal - * domain name character set plus: - * - underscores which are used in SRV records. - * - Forward slashes such as are used for classless in-addr.arpa - * delegation (CNAMEs) - * - Asterisks may be used for wildcard domains in CNAMEs as seen in the - * real world. - * While RFC 2181 section 11 does state not to do validation, - * that applies to servers, not clients. Vulnerabilities have been - * reported when this validation is not performed. Security is more - * important than edge-case compatibility (which is probably invalid - * anyhow). */ -ares_bool_t ares__is_hostnamech(int ch) -{ - /* [A-Za-z0-9-*._/] - * Don't use isalnum() as it is locale-specific - */ - if (ch >= 'A' && ch <= 'Z') { - return ARES_TRUE; - } - if (ch >= 'a' && ch <= 'z') { - return ARES_TRUE; - } - if (ch >= '0' && ch <= '9') { - return ARES_TRUE; - } - if (ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '*') { - return ARES_TRUE; - } - - return ARES_FALSE; -} - ares__buf_t *ares__buf_create(void) { ares__buf_t *buf = ares_malloc_zero(sizeof(*buf)); @@ -630,6 +589,24 @@ ares_status_t ares__buf_fetch_bytes_into_buf(ares__buf_t *buf, return ares__buf_consume(buf, len); } +static ares_bool_t ares__is_whitespace(unsigned char c, + ares_bool_t include_linefeed) +{ + switch (c) { + case '\r': + case '\t': + case ' ': + case '\v': + case '\f': + return ARES_TRUE; + case '\n': + return include_linefeed; + default: + break; + } + return ARES_FALSE; +} + size_t ares__buf_consume_whitespace(ares__buf_t *buf, ares_bool_t include_linefeed) { @@ -642,24 +619,11 @@ size_t ares__buf_consume_whitespace(ares__buf_t *buf, } for (i = 0; i < remaining_len; i++) { - switch (ptr[i]) { - case '\r': - case '\t': - case ' ': - case '\v': - case '\f': - break; - case '\n': - if (!include_linefeed) { - goto done; - } - break; - default: - goto done; + if (!ares__is_whitespace(ptr[i], include_linefeed)) { + break; } } -done: if (i > 0) { ares__buf_consume(buf, i); } @@ -677,20 +641,11 @@ size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf) } for (i = 0; i < remaining_len; i++) { - switch (ptr[i]) { - case '\r': - case '\t': - case ' ': - case '\v': - case '\f': - case '\n': - goto done; - default: - break; + if (ares__is_whitespace(ptr[i], ARES_TRUE)) { + break; } } -done: if (i > 0) { ares__buf_consume(buf, i); } @@ -826,7 +781,7 @@ static ares_bool_t ares__buf_split_isduplicate(ares__llist_t *list, ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, size_t delims_len, ares__buf_split_t flags, - ares__llist_t **list) + size_t max_sections, ares__llist_t **list) { ares_status_t status = ARES_SUCCESS; ares_bool_t first = ARES_TRUE; @@ -842,20 +797,57 @@ ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, } while (ares__buf_len(buf)) { - size_t len; + size_t len = 0; + const unsigned char *ptr; + + if (first) { + /* No delimiter yet, just tag the start */ + ares__buf_tag(buf); + } else { + if (flags & ARES_BUF_SPLIT_DONT_CONSUME_DELIMS) { + /* tag then eat delimiter so its first byte in buffer */ + ares__buf_tag(buf); + ares__buf_consume(buf, 1); + } else { + /* throw away delimiter */ + ares__buf_consume(buf, 1); + ares__buf_tag(buf); + } + } + + if (max_sections && ares__llist_len(*list) >= max_sections - 1) { + ares__buf_consume(buf, ares__buf_len(buf)); + } else { + ares__buf_consume_until_charset(buf, delims, delims_len, ARES_FALSE); + } - ares__buf_tag(buf); + ptr = ares__buf_tag_fetch(buf, &len); - len = ares__buf_consume_until_charset(buf, delims, delims_len, ARES_FALSE); + /* Shouldn't be possible */ + if (ptr == NULL) { + status = ARES_EFORMERR; + goto done; + } + + if (flags & ARES_BUF_SPLIT_LTRIM) { + size_t i; + for (i = 0; i < len; i++) { + if (!ares__is_whitespace(ptr[i], ARES_TRUE)) { + break; + } + } + ptr += i; + len -= i; + } - /* Don't treat a delimiter as part of the length */ - if (!first && len && flags & ARES_BUF_SPLIT_DONT_CONSUME_DELIMS) { - len--; + if (flags & ARES_BUF_SPLIT_RTRIM) { + while (len && ares__is_whitespace(ptr[len - 1], ARES_TRUE)) { + len--; + } } if (len != 0 || flags & ARES_BUF_SPLIT_ALLOW_BLANK) { - const unsigned char *ptr = ares__buf_tag_fetch(buf, &len); - ares__buf_t *data; + ares__buf_t *data; if (!(flags & ARES_BUF_SPLIT_NO_DUPLICATES) || !ares__buf_split_isduplicate(*list, ptr, len, flags)) { @@ -880,12 +872,6 @@ ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, } } - if (!(flags & ARES_BUF_SPLIT_DONT_CONSUME_DELIMS) && - ares__buf_len(buf) != 0) { - /* Consume delimiter */ - ares__buf_consume(buf, 1); - } - first = ARES_FALSE; } @@ -1150,3 +1136,80 @@ ares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data, return ARES_SUCCESS; } + +ares_status_t ares__buf_load_file(const char *filename, ares__buf_t *buf) +{ + FILE *fp = NULL; + unsigned char *ptr = NULL; + size_t len = 0; + size_t ptr_len = 0; + long ftell_len = 0; + ares_status_t status; + + if (filename == NULL || buf == NULL) { + return ARES_EFORMERR; + } + + fp = fopen(filename, "rb"); + if (fp == NULL) { + int error = ERRNO; + switch (error) { + case ENOENT: + case ESRCH: + status = ARES_ENOTFOUND; + goto done; + default: + DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, + strerror(error))); + DEBUGF(fprintf(stderr, "Error opening file: %s\n", filename)); + status = ARES_EFILE; + goto done; + } + } + + /* Get length portably, fstat() is POSIX, not C */ + if (fseek(fp, 0, SEEK_END) != 0) { + status = ARES_EFILE; + goto done; + } + + ftell_len = ftell(fp); + if (ftell_len < 0) { + status = ARES_EFILE; + goto done; + } + len = (size_t)ftell_len; + + if (fseek(fp, 0, SEEK_SET) != 0) { + status = ARES_EFILE; + goto done; + } + + if (len == 0) { + status = ARES_SUCCESS; + goto done; + } + + /* Read entire data into buffer */ + ptr_len = len; + ptr = ares__buf_append_start(buf, &ptr_len); + if (ptr == NULL) { + status = ARES_ENOMEM; + goto done; + } + + ptr_len = fread(ptr, 1, len, fp); + if (ptr_len != len) { + status = ARES_EFILE; + goto done; + } + + ares__buf_append_finish(buf, len); + status = ARES_SUCCESS; + +done: + if (fp != NULL) { + fclose(fp); + } + return status; +} diff --git a/deps/cares/src/lib/ares__buf.h b/deps/cares/src/lib/ares__buf.h index 52054a0b33c658..4298814f7b4396 100644 --- a/deps/cares/src/lib/ares__buf.h +++ b/deps/cares/src/lib/ares__buf.h @@ -177,7 +177,7 @@ void ares__buf_append_finish(ares__buf_t *buf, size_t len); * * \param[in] buf Initialized buffer object. * \param[in] data Data to hex dump - * \param[in] data_len Length of data to hexdump + * \param[in] len Length of data to hexdump * \return ARES_SUCCESS on success. */ ares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data, @@ -373,7 +373,8 @@ size_t ares__buf_consume_whitespace(ares__buf_t *buf, size_t ares__buf_consume_nonwhitespace(ares__buf_t *buf); -/*! Consume until a character in the character set provided is reached +/*! Consume until a character in the character set provided is reached. Does + * not include the character from the charset at the end. * * \param[in] buf Initialized buffer object * \param[in] charset character set @@ -414,7 +415,9 @@ typedef enum { /*! No flags */ ARES_BUF_SPLIT_NONE = 0, /*! The delimiter will be the first character in the buffer, except the - * first buffer since the start doesn't have a delimiter + * first buffer since the start doesn't have a delimiter. This option is + * incompatible with ARES_BUF_SPLIT_LTRIM since the delimiter is always + * the first character. */ ARES_BUF_SPLIT_DONT_CONSUME_DELIMS = 1 << 0, /*! Allow blank sections, by default blank sections are not emitted. If using @@ -424,7 +427,13 @@ typedef enum { /*! Remove duplicate entries */ ARES_BUF_SPLIT_NO_DUPLICATES = 1 << 2, /*! Perform case-insensitive matching when comparing values */ - ARES_BUF_SPLIT_CASE_INSENSITIVE = 1 << 3 + ARES_BUF_SPLIT_CASE_INSENSITIVE = 1 << 3, + /*! Trim leading whitespace from buffer */ + ARES_BUF_SPLIT_LTRIM = 1 << 4, + /*! Trim trailing whitespace from buffer */ + ARES_BUF_SPLIT_RTRIM = 1 << 5, + /*! Trim leading and trailing whitespace from buffer */ + ARES_BUF_SPLIT_TRIM = (ARES_BUF_SPLIT_LTRIM | ARES_BUF_SPLIT_RTRIM) } ares__buf_split_t; /*! Split the provided buffer into multiple sub-buffers stored in the variable @@ -435,6 +444,12 @@ typedef enum { * \param[in] delims Possible delimiters * \param[in] delims_len Length of possible delimiters * \param[in] flags One more more flags + * \param[in] max_sections Maximum number of sections. Use 0 for + * unlimited. Useful for splitting key/value + * pairs where the delimiter may be a valid + * character in the value. A value of 1 would + * have little usefulness and would effectively + * ignore the delimiter itself. * \param[out] list Result. Depending on flags, this may be a * valid list with no elements. Use * ares__llist_destroy() to free the memory which @@ -444,7 +459,7 @@ typedef enum { */ ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims, size_t delims_len, ares__buf_split_t flags, - ares__llist_t **list); + size_t max_sections, ares__llist_t **list); /*! Check the unprocessed buffer to see if it begins with the sequence of @@ -536,7 +551,7 @@ size_t ares__buf_get_position(const ares__buf_t *buf); * \param[in] remaining_len maximum length that should be used for parsing * the string, this is often less than the remaining * buffer and is based on the RR record length. - * \param[out] str Pointer passed by reference to be filled in with + * \param[out] name Pointer passed by reference to be filled in with * allocated string of the parsed that must be * ares_free()'d by the caller. * \param[in] allow_multiple ARES_TRUE if it should attempt to parse multiple @@ -567,6 +582,18 @@ ares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, size_t remaining_len, ares_status_t ares__buf_parse_dns_binstr(ares__buf_t *buf, size_t remaining_len, unsigned char **bin, size_t *bin_len, ares_bool_t allow_multiple); + +/*! Load data from specified file path into provided buffer. The entire file + * is loaded into memory. + * + * \param[in] filename complete path to file + * \param[in,out] buf Initialized (non-const) buffer object to load data + * into + * \return ARES_ENOTFOUND if file not found, ARES_EFILE if issues reading + * file, ARES_ENOMEM if out of memory, ARES_SUCCESS on success. + */ +ares_status_t ares__buf_load_file(const char *filename, ares__buf_t *buf); + /*! @} */ #endif /* __ARES__BUF_H */ diff --git a/deps/cares/src/lib/ares__hosts_file.c b/deps/cares/src/lib/ares__hosts_file.c index c6fe63a429d269..e279623de37e64 100644 --- a/deps/cares/src/lib/ares__hosts_file.c +++ b/deps/cares/src/lib/ares__hosts_file.c @@ -98,95 +98,6 @@ struct ares_hosts_entry { ares__llist_t *hosts; }; -static ares_status_t ares__read_file_into_buf(const char *filename, - ares__buf_t *buf) -{ - FILE *fp = NULL; - unsigned char *ptr = NULL; - size_t len = 0; - size_t ptr_len = 0; - long ftell_len = 0; - ares_status_t status; - - if (filename == NULL || buf == NULL) { - return ARES_EFORMERR; - } - - fp = fopen(filename, "rb"); - if (fp == NULL) { - int error = ERRNO; - switch (error) { - case ENOENT: - case ESRCH: - status = ARES_ENOTFOUND; - goto done; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, - strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", filename)); - status = ARES_EFILE; - goto done; - } - } - - /* Get length portably, fstat() is POSIX, not C */ - if (fseek(fp, 0, SEEK_END) != 0) { - status = ARES_EFILE; - goto done; - } - - ftell_len = ftell(fp); - if (ftell_len < 0) { - status = ARES_EFILE; - goto done; - } - len = (size_t)ftell_len; - - if (fseek(fp, 0, SEEK_SET) != 0) { - status = ARES_EFILE; - goto done; - } - - if (len == 0) { - status = ARES_SUCCESS; - goto done; - } - - /* Read entire data into buffer */ - ptr_len = len; - ptr = ares__buf_append_start(buf, &ptr_len); - if (ptr == NULL) { - status = ARES_ENOMEM; - goto done; - } - - ptr_len = fread(ptr, 1, len, fp); - if (ptr_len != len) { - status = ARES_EFILE; - goto done; - } - - ares__buf_append_finish(buf, len); - status = ARES_SUCCESS; - -done: - if (fp != NULL) { - fclose(fp); - } - return status; -} - -static ares_bool_t ares__is_hostname(const char *str) -{ - size_t i; - for (i = 0; str[i] != 0; i++) { - if (!ares__is_hostnamech(str[i])) { - return ARES_FALSE; - } - } - return ARES_TRUE; -} - const void *ares_dns_pton(const char *ipaddr, struct ares_addr *addr, size_t *out_len) { @@ -605,7 +516,7 @@ static ares_status_t ares__parse_hosts(const char *filename, goto done; } - status = ares__read_file_into_buf(filename, buf); + status = ares__buf_load_file(filename, buf); if (status != ARES_SUCCESS) { goto done; } diff --git a/deps/cares/src/lib/ares__htable.h b/deps/cares/src/lib/ares__htable.h index fd1c0a2366022f..d09c865977cdae 100644 --- a/deps/cares/src/lib/ares__htable.h +++ b/deps/cares/src/lib/ares__htable.h @@ -58,21 +58,21 @@ typedef struct ares__htable ares__htable_t; * but otherwise will not change between calls. * \return hash */ -typedef unsigned int (*ares__htable_hashfunc_t)(const void *key, +typedef unsigned int (*ares__htable_hashfunc_t)(const void *key, unsigned int seed); /*! Callback to free the bucket * * \param[in] bucket user provided bucket */ -typedef void (*ares__htable_bucket_free_t)(void *bucket); +typedef void (*ares__htable_bucket_free_t)(void *bucket); /*! Callback to extract the key from the user-provided bucket * * \param[in] bucket user provided bucket * \return pointer to key held in bucket */ -typedef const void *(*ares__htable_bucket_key_t)(const void *bucket); +typedef const void *(*ares__htable_bucket_key_t)(const void *bucket); /*! Callback to compare two keys for equality * @@ -80,15 +80,15 @@ typedef const void *(*ares__htable_bucket_key_t)(const void *bucket); * \param[in] key2 second key * \return ARES_TRUE if equal, ARES_FALSE if not */ -typedef ares_bool_t (*ares__htable_key_eq_t)(const void *key1, +typedef ares_bool_t (*ares__htable_key_eq_t)(const void *key1, const void *key2); /*! Destroy the initialized hashtable * - * \param[in] initialized hashtable + * \param[in] htable initialized hashtable */ -void ares__htable_destroy(ares__htable_t *htable); +void ares__htable_destroy(ares__htable_t *htable); /*! Create a new hashtable * diff --git a/deps/cares/src/lib/ares__htable_asvp.h b/deps/cares/src/lib/ares__htable_asvp.h index ee253455b2690c..49a766d023091e 100644 --- a/deps/cares/src/lib/ares__htable_asvp.h +++ b/deps/cares/src/lib/ares__htable_asvp.h @@ -51,7 +51,7 @@ typedef struct ares__htable_asvp ares__htable_asvp_t; * * \param[in] val user-supplied value */ -typedef void (*ares__htable_asvp_val_free_t)(void *val); +typedef void (*ares__htable_asvp_val_free_t)(void *val); /*! Destroy hashtable * @@ -71,7 +71,7 @@ ares__htable_asvp_t * /*! Retrieve an array of keys from the hashtable. * * \param[in] htable Initialized hashtable - * \param[out] num_keys Count of returned keys + * \param[out] num Count of returned keys * \return Array of keys in the hashtable. Must be free'd with ares_free(). */ ares_socket_t *ares__htable_asvp_keys(const ares__htable_asvp_t *htable, diff --git a/deps/cares/src/lib/ares__htable_strvp.h b/deps/cares/src/lib/ares__htable_strvp.h index 80d375c06804a5..25dd2b90777d8d 100644 --- a/deps/cares/src/lib/ares__htable_strvp.h +++ b/deps/cares/src/lib/ares__htable_strvp.h @@ -49,7 +49,7 @@ typedef struct ares__htable_strvp ares__htable_strvp_t; * * \param[in] val user-supplied value */ -typedef void (*ares__htable_strvp_val_free_t)(void *val); +typedef void (*ares__htable_strvp_val_free_t)(void *val); /*! Destroy hashtable * diff --git a/deps/cares/src/lib/ares__htable_szvp.h b/deps/cares/src/lib/ares__htable_szvp.h index 9857afe79604d3..62b1776be92b5b 100644 --- a/deps/cares/src/lib/ares__htable_szvp.h +++ b/deps/cares/src/lib/ares__htable_szvp.h @@ -49,7 +49,7 @@ typedef struct ares__htable_szvp ares__htable_szvp_t; * * \param[in] val user-supplied value */ -typedef void (*ares__htable_szvp_val_free_t)(void *val); +typedef void (*ares__htable_szvp_val_free_t)(void *val); /*! Destroy hashtable * diff --git a/deps/cares/src/lib/ares__llist.h b/deps/cares/src/lib/ares__llist.h index bd18bb9ec1d54c..7d57bdab3b077c 100644 --- a/deps/cares/src/lib/ares__llist.h +++ b/deps/cares/src/lib/ares__llist.h @@ -52,7 +52,7 @@ typedef struct ares__llist_node ares__llist_node_t; * * \param[in] data user supplied data */ -typedef void (*ares__llist_destructor_t)(void *data); +typedef void (*ares__llist_destructor_t)(void *data); /*! Create a linked list object * @@ -201,8 +201,8 @@ void ares__llist_destroy(ares__llist_t *list); /*! Detach node from the current list and re-attach it to the new list as the * last entry. * - * \param[in] node node to move - * \param[in] parent new list + * \param[in] node node to move + * \param[in] new_parent new list */ void ares__llist_node_move_parent_last(ares__llist_node_t *node, ares__llist_t *new_parent); @@ -210,8 +210,8 @@ void ares__llist_node_move_parent_last(ares__llist_node_t *node, /*! Detach node from the current list and re-attach it to the new list as the * first entry. * - * \param[in] node node to move - * \param[in] parent new list + * \param[in] node node to move + * \param[in] new_parent new list */ void ares__llist_node_move_parent_first(ares__llist_node_t *node, ares__llist_t *new_parent); diff --git a/deps/cares/src/lib/ares__parse_into_addrinfo.c b/deps/cares/src/lib/ares__parse_into_addrinfo.c index a5ce0c594fc3be..90e951c02f3f6d 100644 --- a/deps/cares/src/lib/ares__parse_into_addrinfo.c +++ b/deps/cares/src/lib/ares__parse_into_addrinfo.c @@ -47,13 +47,12 @@ #include "ares.h" #include "ares_private.h" -ares_status_t ares__parse_into_addrinfo(const unsigned char *abuf, size_t alen, +ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec, ares_bool_t cname_only_is_enodata, unsigned short port, struct ares_addrinfo *ai) { ares_status_t status; - ares_dns_record_t *dnsrec = NULL; size_t i; size_t ancount; const char *hostname = NULL; @@ -63,11 +62,6 @@ ares_status_t ares__parse_into_addrinfo(const unsigned char *abuf, size_t alen, struct ares_addrinfo_cname *cnames = NULL; struct ares_addrinfo_node *nodes = NULL; - status = ares_dns_parse(abuf, alen, 0, &dnsrec); - if (status != ARES_SUCCESS) { - goto done; - } - /* Save question hostname */ status = ares_dns_record_query_get(dnsrec, 0, &hostname, NULL, NULL); if (status != ARES_SUCCESS) { @@ -83,7 +77,7 @@ ares_status_t ares__parse_into_addrinfo(const unsigned char *abuf, size_t alen, for (i = 0; i < ancount; i++) { ares_dns_rec_type_t rtype; const ares_dns_rr_t *rr = - ares_dns_record_rr_get(dnsrec, ARES_SECTION_ANSWER, i); + ares_dns_record_rr_get_const(dnsrec, ARES_SECTION_ANSWER, i); if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN) { continue; @@ -177,7 +171,6 @@ ares_status_t ares__parse_into_addrinfo(const unsigned char *abuf, size_t alen, done: ares__freeaddrinfo_cnames(cnames); ares__freeaddrinfo_nodes(nodes); - ares_dns_record_destroy(dnsrec); /* compatibility */ if (status == ARES_EBADNAME) { diff --git a/deps/cares/src/lib/ares__read_line.c b/deps/cares/src/lib/ares__read_line.c deleted file mode 100644 index 018f55e8b2681f..00000000000000 --- a/deps/cares/src/lib/ares__read_line.c +++ /dev/null @@ -1,90 +0,0 @@ -/* MIT License - * - * Copyright (c) 1998 Massachusetts Institute of Technology - * Copyright (c) The c-ares project and its contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * SPDX-License-Identifier: MIT - */ - -#include "ares_setup.h" - -#include "ares.h" -#include "ares_private.h" - -/* This is an internal function. Its contract is to read a line from - * a file into a dynamically allocated buffer, zeroing the trailing - * newline if there is one. The calling routine may call - * ares__read_line multiple times with the same buf and bufsize - * pointers; *buf will be reallocated and *bufsize adjusted as - * appropriate. The initial value of *buf should be NULL. After the - * calling routine is done reading lines, it should free *buf. - */ -ares_status_t ares__read_line(FILE *fp, char **buf, size_t *bufsize) -{ - char *newbuf; - size_t offset = 0; - size_t len; - - if (*buf == NULL) { - *buf = ares_malloc(128); - if (!*buf) { - return ARES_ENOMEM; - } - *bufsize = 128; - } - - for (;;) { - int bytestoread = (int)(*bufsize - offset); - - if (!fgets(*buf + offset, bytestoread, fp)) { - return (offset != 0) ? 0 : (ferror(fp)) ? ARES_EFILE : ARES_EOF; - } - len = offset + ares_strlen(*buf + offset); - - /* Probably means there was an embedded NULL as the first character in - * the line, throw away line */ - if (len == 0) { - offset = 0; - continue; - } - - if ((*buf)[len - 1] == '\n') { - (*buf)[len - 1] = 0; - break; - } - offset = len; - if (len < *bufsize - 1) { - continue; - } - - /* Allocate more space. */ - newbuf = ares_realloc(*buf, *bufsize * 2); - if (!newbuf) { - ares_free(*buf); - *buf = NULL; - return ARES_ENOMEM; - } - *buf = newbuf; - *bufsize *= 2; - } - return ARES_SUCCESS; -} diff --git a/deps/cares/src/lib/ares__slist.h b/deps/cares/src/lib/ares__slist.h index 04cd50806ebc2d..26af88fa782499 100644 --- a/deps/cares/src/lib/ares__slist.h +++ b/deps/cares/src/lib/ares__slist.h @@ -63,7 +63,7 @@ typedef struct ares__slist_node ares__slist_node_t; * * \param[in] data User-defined data to destroy */ -typedef void (*ares__slist_destructor_t)(void *data); +typedef void (*ares__slist_destructor_t)(void *data); /*! SkipList comparison function * @@ -71,7 +71,7 @@ typedef void (*ares__slist_destructor_t)(void *data); * \param[in] data2 Second user-defined data object * \return < 0 if data1 < data1, > 0 if data1 > data2, 0 if data1 == data2 */ -typedef int (*ares__slist_cmp_t)(const void *data1, const void *data2); +typedef int (*ares__slist_cmp_t)(const void *data1, const void *data2); /*! Create SkipList * diff --git a/deps/cares/src/lib/ares__threads.c b/deps/cares/src/lib/ares__threads.c index 028790aead5abe..f6de8c698e373d 100644 --- a/deps/cares/src/lib/ares__threads.c +++ b/deps/cares/src/lib/ares__threads.c @@ -138,9 +138,9 @@ struct ares__thread { HANDLE thread; DWORD id; - void *(*func)(void *arg); - void *arg; - void *rv; + void *(*func)(void *arg); + void *arg; + void *rv; }; /* Wrap for pthread compatibility */ @@ -335,8 +335,8 @@ static void ares__timespec_timeout(struct timespec *ts, unsigned long add_ms) # error cannot determine current system time # endif - ts->tv_sec += add_ms / 1000; - ts->tv_nsec += (add_ms % 1000) * 1000000; + ts->tv_sec += (time_t)(add_ms / 1000); + ts->tv_nsec += (long)((add_ms % 1000) * 1000000); /* Normalize if needed */ if (ts->tv_nsec >= 1000000000) { diff --git a/deps/cares/src/lib/ares__threads.h b/deps/cares/src/lib/ares__threads.h index 39764296478a07..108354dfc1e17f 100644 --- a/deps/cares/src/lib/ares__threads.h +++ b/deps/cares/src/lib/ares__threads.h @@ -52,9 +52,9 @@ ares_status_t ares__thread_cond_timedwait(ares__thread_cond_t *cond, struct ares__thread; typedef struct ares__thread ares__thread_t; -typedef void *(*ares__thread_func_t)(void *arg); -ares_status_t ares__thread_create(ares__thread_t **thread, - ares__thread_func_t func, void *arg); +typedef void *(*ares__thread_func_t)(void *arg); +ares_status_t ares__thread_create(ares__thread_t **thread, + ares__thread_func_t func, void *arg); ares_status_t ares__thread_join(ares__thread_t *thread, void **rv); #endif diff --git a/deps/cares/src/lib/ares_cancel.c b/deps/cares/src/lib/ares_cancel.c index 0ee6124dd71440..5a9fb722cb7778 100644 --- a/deps/cares/src/lib/ares_cancel.c +++ b/deps/cares/src/lib/ares_cancel.c @@ -74,7 +74,7 @@ void ares_cancel(ares_channel_t *channel) query->node_all_queries = NULL; /* NOTE: its possible this may enqueue new queries */ - query->callback(query->arg, ARES_ECANCELLED, 0, NULL, 0); + query->callback(query->arg, ARES_ECANCELLED, 0, NULL); ares__free_query(query); /* See if the connection should be cleaned up */ diff --git a/deps/cares/src/lib/ares_config.h.cmake b/deps/cares/src/lib/ares_config.h.cmake index 01dcccaa17c2b4..10a1b7a971604b 100644 --- a/deps/cares/src/lib/ares_config.h.cmake +++ b/deps/cares/src/lib/ares_config.h.cmake @@ -212,6 +212,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETINET_IN_H +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETINET6_IN6_H + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETINET_TCP_H diff --git a/deps/cares/src/lib/ares_config.h.in b/deps/cares/src/lib/ares_config.h.in index 4e07e58473a009..f486b6b4f000b9 100644 --- a/deps/cares/src/lib/ares_config.h.in +++ b/deps/cares/src/lib/ares_config.h.in @@ -186,6 +186,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET6_IN6_H + /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H diff --git a/deps/cares/src/lib/ares_create_query.c b/deps/cares/src/lib/ares_create_query.c index f66b0ff6e0693d..a2f2caac6e95d9 100644 --- a/deps/cares/src/lib/ares_create_query.c +++ b/deps/cares/src/lib/ares_create_query.c @@ -28,13 +28,15 @@ #include "ares.h" #include "ares_private.h" -int ares_create_query(const char *name, int dnsclass, int type, - unsigned short id, int rd, unsigned char **bufp, - int *buflenp, int max_udp_size) +static int ares_create_query_int(const char *name, int dnsclass, int type, + unsigned short id, int rd, + unsigned char **bufp, int *buflenp, + int max_udp_size) { ares_status_t status; ares_dns_record_t *dnsrec = NULL; size_t len; + ares_dns_flags_t rd_flag = rd ? ARES_FLAG_RD : 0; if (name == NULL || bufp == NULL || buflenp == NULL) { status = ARES_EFORMERR; @@ -44,56 +46,13 @@ int ares_create_query(const char *name, int dnsclass, int type, *bufp = NULL; *buflenp = 0; - /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */ - if (ares__is_onion_domain(name)) { - status = ARES_ENOTFOUND; - goto done; - } - - status = ares_dns_record_create(&dnsrec, id, rd ? ARES_FLAG_RD : 0, - ARES_OPCODE_QUERY, ARES_RCODE_NOERROR); + status = ares_dns_record_create_query( + &dnsrec, name, (ares_dns_class_t)dnsclass, (ares_dns_rec_type_t)type, id, + rd_flag, (size_t)max_udp_size); if (status != ARES_SUCCESS) { goto done; } - status = ares_dns_record_query_add(dnsrec, name, (ares_dns_rec_type_t)type, - (ares_dns_class_t)dnsclass); - if (status != ARES_SUCCESS) { - goto done; - } - - /* max_udp_size > 0 indicates EDNS, so send OPT RR as an additional record */ - if (max_udp_size > 0) { - ares_dns_rr_t *rr = NULL; - - status = ares_dns_record_rr_add(&rr, dnsrec, ARES_SECTION_ADDITIONAL, "", - ARES_REC_TYPE_OPT, ARES_CLASS_IN, 0); - if (status != ARES_SUCCESS) { - goto done; - } - - if (max_udp_size > 65535) { - status = ARES_EFORMERR; - goto done; - } - - status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_UDP_SIZE, - (unsigned short)max_udp_size); - if (status != ARES_SUCCESS) { - goto done; - } - - status = ares_dns_rr_set_u8(rr, ARES_RR_OPT_VERSION, 0); - if (status != ARES_SUCCESS) { - goto done; - } - - status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_FLAGS, 0); - if (status != ARES_SUCCESS) { - goto done; - } - } - status = ares_dns_write(dnsrec, bufp, &len); if (status != ARES_SUCCESS) { goto done; @@ -105,3 +64,17 @@ int ares_create_query(const char *name, int dnsclass, int type, ares_dns_record_destroy(dnsrec); return (int)status; } + +int ares_create_query(const char *name, int dnsclass, int type, + unsigned short id, int rd, unsigned char **bufp, + int *buflenp, int max_udp_size) +{ + return ares_create_query_int(name, dnsclass, type, id, rd, bufp, buflenp, + max_udp_size); +} + +int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id, + int rd, unsigned char **buf, int *buflen) +{ + return ares_create_query_int(name, dnsclass, type, id, rd, buf, buflen, 0); +} diff --git a/deps/cares/src/lib/ares_destroy.c b/deps/cares/src/lib/ares_destroy.c index 145084577f7fba..6965b601e76e07 100644 --- a/deps/cares/src/lib/ares_destroy.c +++ b/deps/cares/src/lib/ares_destroy.c @@ -51,7 +51,7 @@ void ares_destroy(ares_channel_t *channel) struct query *query = ares__llist_node_claim(node); query->node_all_queries = NULL; - query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL, 0); + query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL); ares__free_query(query); node = next; diff --git a/deps/cares/src/lib/ares_dns_mapping.c b/deps/cares/src/lib/ares_dns_mapping.c index 55f1af7939c32f..2b463fe83128a7 100644 --- a/deps/cares/src/lib/ares_dns_mapping.c +++ b/deps/cares/src/lib/ares_dns_mapping.c @@ -883,3 +883,37 @@ const char *ares_dns_rcode_tostr(ares_dns_rcode_t rcode) return "UNKNOWN"; } + +/* Convert an rcode and ancount from a query reply into an ares_status_t + * value. Used internally by ares_search() and ares_query(). + */ +ares_status_t ares_dns_query_reply_tostatus(ares_dns_rcode_t rcode, + size_t ancount) +{ + ares_status_t status = ARES_SUCCESS; + + switch (rcode) { + case ARES_RCODE_NOERROR: + status = (ancount > 0) ? ARES_SUCCESS : ARES_ENODATA; + break; + case ARES_RCODE_FORMERR: + status = ARES_EFORMERR; + break; + case ARES_RCODE_SERVFAIL: + status = ARES_ESERVFAIL; + break; + case ARES_RCODE_NXDOMAIN: + status = ARES_ENOTFOUND; + break; + case ARES_RCODE_NOTIMP: + status = ARES_ENOTIMP; + break; + case ARES_RCODE_REFUSED: + status = ARES_EREFUSED; + break; + default: + break; + } + + return status; +} diff --git a/deps/cares/src/lib/ares_dns_private.h b/deps/cares/src/lib/ares_dns_private.h index 91635e74cd8010..3af4b3c9926e42 100644 --- a/deps/cares/src/lib/ares_dns_private.h +++ b/deps/cares/src/lib/ares_dns_private.h @@ -49,6 +49,33 @@ ares_bool_t ares_dns_has_opt_rr(const ares_dns_record_t *rec); void ares_dns_record_write_ttl_decrement(ares_dns_record_t *dnsrec, unsigned int ttl_decrement); +/*! Create a DNS record object for a query. The arguments are the same as + * those for ares_create_query(). + * + * \param[out] dnsrec DNS record object to create. + * \param[in] name NUL-terminated name for the query. + * \param[in] dnsclass Class for the query. + * \param[in] type Type for the query. + * \param[in] id Identifier for the query. + * \param[in] flags Flags for the query. + * \param[in] max_udp_size Maximum size of a UDP packet for EDNS. + * \return ARES_SUCCESS on success, otherwise an error code. + */ +ares_status_t + ares_dns_record_create_query(ares_dns_record_t **dnsrec, const char *name, + ares_dns_class_t dnsclass, + ares_dns_rec_type_t type, unsigned short id, + ares_dns_flags_t flags, size_t max_udp_size); + +/*! Convert the RCODE and ANCOUNT from a DNS query reply into a status code. + * + * \param[in] rcode The RCODE from the reply. + * \param[in] ancount The ANCOUNT from the reply. + * \return An appropriate status code. + */ +ares_status_t ares_dns_query_reply_tostatus(ares_dns_rcode_t rcode, + size_t ancount); + struct ares_dns_qd { char *name; ares_dns_rec_type_t qtype; diff --git a/deps/cares/src/lib/ares_dns_record.c b/deps/cares/src/lib/ares_dns_record.c index 30219003e24a57..ec7f7e734302de 100644 --- a/deps/cares/src/lib/ares_dns_record.c +++ b/deps/cares/src/lib/ares_dns_record.c @@ -276,6 +276,39 @@ ares_status_t ares_dns_record_query_add(ares_dns_record_t *dnsrec, return ARES_SUCCESS; } +ares_status_t ares_dns_record_query_set_name(ares_dns_record_t *dnsrec, + size_t idx, const char *name) +{ + char *orig_name = NULL; + + if (dnsrec == NULL || idx >= dnsrec->qdcount || name == NULL) { + return ARES_EFORMERR; + } + orig_name = dnsrec->qd[idx].name; + dnsrec->qd[idx].name = ares_strdup(name); + if (dnsrec->qd[idx].name == NULL) { + dnsrec->qd[idx].name = orig_name; + return ARES_ENOMEM; + } + + ares_free(orig_name); + return ARES_SUCCESS; +} + +ares_status_t ares_dns_record_query_set_type(ares_dns_record_t *dnsrec, + size_t idx, + ares_dns_rec_type_t qtype) +{ + if (dnsrec == NULL || idx >= dnsrec->qdcount || + !ares_dns_rec_type_isvalid(qtype, ARES_TRUE)) { + return ARES_EFORMERR; + } + + dnsrec->qd[idx].qtype = qtype; + + return ARES_SUCCESS; +} + ares_status_t ares_dns_record_query_get(const ares_dns_record_t *dnsrec, size_t idx, const char **name, ares_dns_rec_type_t *qtype, @@ -499,7 +532,7 @@ ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec, return &rr_ptr[idx]; } -static const ares_dns_rr_t * +const ares_dns_rr_t * ares_dns_record_rr_get_const(const ares_dns_record_t *dnsrec, ares_dns_section_t sect, size_t idx) { @@ -1314,3 +1347,103 @@ ares_bool_t ares_dns_has_opt_rr(const ares_dns_record_t *rec) } return ARES_FALSE; } + +/* Construct a DNS record for a name with given class and type. Used internally + * by ares_search() and ares_create_query(). + */ +ares_status_t + ares_dns_record_create_query(ares_dns_record_t **dnsrec, const char *name, + ares_dns_class_t dnsclass, + ares_dns_rec_type_t type, unsigned short id, + ares_dns_flags_t flags, size_t max_udp_size) +{ + ares_status_t status; + ares_dns_rr_t *rr = NULL; + + if (dnsrec == NULL) { + return ARES_EFORMERR; + } + + *dnsrec = NULL; + + /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN */ + if (ares__is_onion_domain(name)) { + status = ARES_ENOTFOUND; + goto done; + } + + status = ares_dns_record_create(dnsrec, id, (unsigned short)flags, + ARES_OPCODE_QUERY, ARES_RCODE_NOERROR); + if (status != ARES_SUCCESS) { + goto done; + } + + status = ares_dns_record_query_add(*dnsrec, name, type, dnsclass); + if (status != ARES_SUCCESS) { + goto done; + } + + /* max_udp_size > 0 indicates EDNS, so send OPT RR as an additional record */ + if (max_udp_size > 0) { + /* max_udp_size must fit into a 16 bit unsigned integer field on the OPT + * RR, so check here that it fits + */ + if (max_udp_size > 65535) { + status = ARES_EFORMERR; + goto done; + } + + status = ares_dns_record_rr_add(&rr, *dnsrec, ARES_SECTION_ADDITIONAL, "", + ARES_REC_TYPE_OPT, ARES_CLASS_IN, 0); + if (status != ARES_SUCCESS) { + goto done; + } + + status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_UDP_SIZE, + (unsigned short)max_udp_size); + if (status != ARES_SUCCESS) { + goto done; + } + + status = ares_dns_rr_set_u8(rr, ARES_RR_OPT_VERSION, 0); + if (status != ARES_SUCCESS) { + goto done; + } + + status = ares_dns_rr_set_u16(rr, ARES_RR_OPT_FLAGS, 0); + if (status != ARES_SUCCESS) { + goto done; + } + } + +done: + if (status != ARES_SUCCESS) { + ares_dns_record_destroy(*dnsrec); + *dnsrec = NULL; + } + return status; +} + +ares_dns_record_t *ares_dns_record_duplicate(const ares_dns_record_t *dnsrec) +{ + unsigned char *data = NULL; + size_t data_len = 0; + ares_dns_record_t *out = NULL; + ares_status_t status; + + if (dnsrec == NULL) { + return NULL; + } + + status = ares_dns_write(dnsrec, &data, &data_len); + if (status != ARES_SUCCESS) { + return NULL; + } + + status = ares_dns_parse(data, data_len, 0, &out); + ares_free(data); + if (status != ARES_SUCCESS) { + return NULL; + } + return out; +} diff --git a/deps/cares/src/lib/ares_dns_write.c b/deps/cares/src/lib/ares_dns_write.c index 2e99c5ba88aee7..b49ec07bcb9b6b 100644 --- a/deps/cares/src/lib/ares_dns_write.c +++ b/deps/cares/src/lib/ares_dns_write.c @@ -831,10 +831,10 @@ static ares_status_t ares_dns_write_rr_raw_rr(ares__buf_t *buf, return ares__buf_append(buf, data, data_len); } -static ares_status_t ares_dns_write_rr(ares_dns_record_t *dnsrec, - ares__llist_t **namelist, - ares_dns_section_t section, - ares__buf_t *buf) +static ares_status_t ares_dns_write_rr(const ares_dns_record_t *dnsrec, + ares__llist_t **namelist, + ares_dns_section_t section, + ares__buf_t *buf) { size_t i; @@ -849,7 +849,7 @@ static ares_status_t ares_dns_write_rr(ares_dns_record_t *dnsrec, size_t end_length; unsigned int ttl; - rr = ares_dns_record_rr_get(dnsrec, section, i); + rr = ares_dns_record_rr_get_const(dnsrec, section, i); if (rr == NULL) { return ARES_EFORMERR; } @@ -988,8 +988,8 @@ static ares_status_t ares_dns_write_rr(ares_dns_record_t *dnsrec, return ARES_SUCCESS; } -ares_status_t ares_dns_write(ares_dns_record_t *dnsrec, unsigned char **buf, - size_t *buf_len) +ares_status_t ares_dns_write(const ares_dns_record_t *dnsrec, + unsigned char **buf, size_t *buf_len) { ares__buf_t *b = NULL; ares_status_t status; diff --git a/deps/cares/src/lib/ares_event.h b/deps/cares/src/lib/ares_event.h index 9d01d75f372afe..23e9637924ba07 100644 --- a/deps/cares/src/lib/ares_event.h +++ b/deps/cares/src/lib/ares_event.h @@ -72,11 +72,11 @@ struct ares_event { typedef struct { const char *name; ares_bool_t (*init)(ares_event_thread_t *e); - void (*destroy)(ares_event_thread_t *e); + void (*destroy)(ares_event_thread_t *e); ares_bool_t (*event_add)(ares_event_t *event); - void (*event_del)(ares_event_t *event); - void (*event_mod)(ares_event_t *event, ares_event_flags_t new_flags); - size_t (*wait)(ares_event_thread_t *e, unsigned long timeout_ms); + void (*event_del)(ares_event_t *event); + void (*event_mod)(ares_event_t *event, ares_event_flags_t new_flags); + size_t (*wait)(ares_event_thread_t *e, unsigned long timeout_ms); } ares_event_sys_t; struct ares_event_thread { diff --git a/deps/cares/src/lib/ares_event_poll.c b/deps/cares/src/lib/ares_event_poll.c index c16b2824663544..33b1d6dfd58ec7 100644 --- a/deps/cares/src/lib/ares_event_poll.c +++ b/deps/cares/src/lib/ares_event_poll.c @@ -75,8 +75,11 @@ static size_t ares_evsys_poll_wait(ares_event_thread_t *e, size_t cnt = 0; size_t i; - if (num_fds) { + if (fdlist != NULL && num_fds) { pollfd = ares_malloc_zero(sizeof(*pollfd) * num_fds); + if (pollfd == NULL) { + goto done; + } for (i = 0; i < num_fds; i++) { const ares_event_t *ev = ares__htable_asvp_get_direct(e->ev_handles, fdlist[i]); @@ -96,7 +99,7 @@ static size_t ares_evsys_poll_wait(ares_event_thread_t *e, goto done; } - for (i = 0; i < num_fds; i++) { + for (i = 0; pollfd != NULL && i < num_fds; i++) { ares_event_t *ev; ares_event_flags_t flags = 0; diff --git a/deps/cares/src/lib/ares_getaddrinfo.c b/deps/cares/src/lib/ares_getaddrinfo.c index eaa4b422c06e9e..cfc889c70a84e2 100644 --- a/deps/cares/src/lib/ares_getaddrinfo.c +++ b/deps/cares/src/lib/ares_getaddrinfo.c @@ -79,15 +79,20 @@ struct host_query { char *lookups; /* Duplicate memory from channel because of ares_reinit() */ const char *remaining_lookups; /* types of lookup we need to perform ("fb" by default, file and dns respectively) */ - char **domains; /* duplicate from channel for ares_reinit() safety */ - size_t ndomains; - struct ares_addrinfo *ai; /* store results between lookups */ - unsigned short qid_a; /* qid for A request */ - unsigned short qid_aaaa; /* qid for AAAA request */ - size_t remaining; /* number of DNS answers waiting for */ - ares_ssize_t next_domain; /* next search domain to try */ - size_t - nodata_cnt; /* Track nodata responses to possibly override final result */ + + /* Search order for names */ + char **names; + size_t names_cnt; + size_t next_name_idx; /* next name index being attempted */ + + struct ares_addrinfo *ai; /* store results between lookups */ + unsigned short qid_a; /* qid for A request */ + unsigned short qid_aaaa; /* qid for AAAA request */ + + size_t remaining; /* number of DNS answers waiting for */ + + /* Track nodata responses to possibly override final result */ + size_t nodata_cnt; }; static const struct ares_addrinfo_hints default_hints = { @@ -98,10 +103,6 @@ static const struct ares_addrinfo_hints default_hints = { }; /* forward declarations */ -static void host_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen); -static ares_bool_t as_is_first(const struct host_query *hquery); -static ares_bool_t as_is_only(const struct host_query *hquery); static ares_bool_t next_dns_lookup(struct host_query *hquery); struct ares_addrinfo_cname * @@ -324,6 +325,17 @@ static ares_bool_t fake_addrinfo(const char *name, unsigned short port, return ARES_TRUE; } +static void hquery_free(struct host_query *hquery, ares_bool_t cleanup_ai) +{ + if (cleanup_ai) { + ares_freeaddrinfo(hquery->ai); + } + ares__strsplit_free(hquery->names, hquery->names_cnt); + ares_free(hquery->name); + ares_free(hquery->lookups); + ares_free(hquery); +} + static void end_hquery(struct host_query *hquery, ares_status_t status) { struct ares_addrinfo_node sentinel; @@ -349,10 +361,7 @@ static void end_hquery(struct host_query *hquery, ares_status_t status) } hquery->callback(hquery->arg, (int)status, (int)hquery->timeouts, hquery->ai); - ares__strsplit_free(hquery->domains, hquery->ndomains); - ares_free(hquery->lookups); - ares_free(hquery->name); - ares_free(hquery); + hquery_free(hquery, ARES_FALSE); } ares_bool_t ares__is_localhost(const char *name) @@ -478,25 +487,23 @@ static void terminate_retries(const struct host_query *hquery, query->no_retries = ARES_TRUE; } -static void host_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen) +static void host_callback(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec) { struct host_query *hquery = (struct host_query *)arg; ares_status_t addinfostatus = ARES_SUCCESS; - unsigned short qid = 0; - hquery->timeouts += (size_t)timeouts; + hquery->timeouts += timeouts; hquery->remaining--; if (status == ARES_SUCCESS) { - if (alen < 0) { + if (dnsrec == NULL) { addinfostatus = ARES_EBADRESP; } else { - addinfostatus = ares__parse_into_addrinfo(abuf, (size_t)alen, ARES_TRUE, - hquery->port, hquery->ai); + addinfostatus = + ares__parse_into_addrinfo(dnsrec, ARES_TRUE, hquery->port, hquery->ai); } - if (addinfostatus == ARES_SUCCESS && alen >= HFIXEDSZ) { - qid = DNS_HEADER_QID(abuf); /* Converts to host byte order */ - terminate_retries(hquery, qid); + if (addinfostatus == ARES_SUCCESS) { + terminate_retries(hquery, ares_dns_record_get_id(dnsrec)); } } @@ -505,7 +512,7 @@ static void host_callback(void *arg, int status, int timeouts, /* must make sure we don't do next_lookup() on destroy or cancel, * and return the appropriate status. We won't return a partial * result in this case. */ - end_hquery(hquery, (ares_status_t)status); + end_hquery(hquery, status); } else if (addinfostatus != ARES_SUCCESS && addinfostatus != ARES_ENODATA) { /* error in parsing result e.g. no memory */ if (addinfostatus == ARES_EBADRESP && hquery->ai->nodes) { @@ -523,10 +530,9 @@ static void host_callback(void *arg, int status, int timeouts, if (status == ARES_ENODATA || addinfostatus == ARES_ENODATA) { hquery->nodata_cnt++; } - next_lookup(hquery, - hquery->nodata_cnt ? ARES_ENODATA : (ares_status_t)status); + next_lookup(hquery, hquery->nodata_cnt ? ARES_ENODATA : status); } else { - end_hquery(hquery, (ares_status_t)status); + end_hquery(hquery, status); } } @@ -542,7 +548,6 @@ static void ares_getaddrinfo_int(ares_channel_t *channel, const char *name, unsigned short port = 0; int family; struct ares_addrinfo *ai; - char *alias_name = NULL; ares_status_t status; if (!hints) { @@ -563,25 +568,12 @@ static void ares_getaddrinfo_int(ares_channel_t *channel, const char *name, return; } - /* perform HOSTALIAS resolution (technically this function does some other - * things we are going to ignore) */ - status = ares__single_domain(channel, name, &alias_name); - if (status != ARES_SUCCESS) { - callback(arg, (int)status, 0, NULL); - return; - } - - if (alias_name) { - name = alias_name; - } - if (service) { if (hints->ai_flags & ARES_AI_NUMERICSERV) { unsigned long val; errno = 0; val = strtoul(service, NULL, 0); if ((val == 0 && errno != 0) || val > 65535) { - ares_free(alias_name); callback(arg, ARES_ESERVICE, 0, NULL); return; } @@ -593,7 +585,6 @@ static void ares_getaddrinfo_int(ares_channel_t *channel, const char *name, errno = 0; val = strtoul(service, NULL, 0); if ((val == 0 && errno != 0) || val > 65535) { - ares_free(alias_name); callback(arg, ARES_ESERVICE, 0, NULL); return; } @@ -604,66 +595,53 @@ static void ares_getaddrinfo_int(ares_channel_t *channel, const char *name, ai = ares_malloc_zero(sizeof(*ai)); if (!ai) { - ares_free(alias_name); callback(arg, ARES_ENOMEM, 0, NULL); return; } if (fake_addrinfo(name, port, hints, ai, callback, arg)) { - ares_free(alias_name); return; } /* Allocate and fill in the host query structure. */ hquery = ares_malloc_zero(sizeof(*hquery)); if (!hquery) { - ares_free(alias_name); ares_freeaddrinfo(ai); callback(arg, ARES_ENOMEM, 0, NULL); return; } - memset(hquery, 0, sizeof(*hquery)); - hquery->name = ares_strdup(name); - ares_free(alias_name); - if (!hquery->name) { - ares_free(hquery); - ares_freeaddrinfo(ai); + + hquery->port = port; + hquery->channel = channel; + hquery->hints = *hints; + hquery->sent_family = -1; /* nothing is sent yet */ + hquery->callback = callback; + hquery->arg = arg; + hquery->ai = ai; + hquery->name = ares_strdup(name); + if (hquery->name == NULL) { + hquery_free(hquery, ARES_TRUE); callback(arg, ARES_ENOMEM, 0, NULL); return; } - hquery->lookups = ares_strdup(channel->lookups); - if (!hquery->lookups) { - ares_free(hquery->name); - ares_free(hquery); - ares_freeaddrinfo(ai); - callback(arg, ARES_ENOMEM, 0, NULL); + + status = + ares__search_name_list(channel, name, &hquery->names, &hquery->names_cnt); + if (status != ARES_SUCCESS) { + hquery_free(hquery, ARES_TRUE); + callback(arg, (int)status, 0, NULL); return; } + hquery->next_name_idx = 0; - if (channel->ndomains) { - /* Duplicate for ares_reinit() safety */ - hquery->domains = - ares__strsplit_duplicate(channel->domains, channel->ndomains); - if (hquery->domains == NULL) { - ares_free(hquery->lookups); - ares_free(hquery->name); - ares_free(hquery); - ares_freeaddrinfo(ai); - callback(arg, ARES_ENOMEM, 0, NULL); - return; - } - hquery->ndomains = channel->ndomains; - } - hquery->port = port; - hquery->channel = channel; - hquery->hints = *hints; - hquery->sent_family = -1; /* nothing is sent yet */ - hquery->callback = callback; - hquery->arg = arg; + hquery->lookups = ares_strdup(channel->lookups); + if (hquery->lookups == NULL) { + hquery_free(hquery, ARES_TRUE); + callback(arg, ARES_ENOMEM, 0, NULL); + return; + } hquery->remaining_lookups = hquery->lookups; - hquery->ai = ai; - hquery->next_domain = -1; /* Start performing lookups according to channel->lookups. */ next_lookup(hquery, ARES_ECONNREFUSED /* initial error code */); @@ -684,93 +662,39 @@ void ares_getaddrinfo(ares_channel_t *channel, const char *name, static ares_bool_t next_dns_lookup(struct host_query *hquery) { - char *s = NULL; - ares_bool_t is_s_allocated = ARES_FALSE; - ares_status_t 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 && (size_t)hquery->next_domain == hquery->ndomains) { - if (!as_is_first(hquery)) { - s = hquery->name; - } - hquery->next_domain++; - } - - if (!s && (size_t)hquery->next_domain < hquery->ndomains && - !as_is_only(hquery)) { - status = ares__cat_domain(hquery->name, - hquery->domains[hquery->next_domain++], &s); - if (status == ARES_SUCCESS) { - is_s_allocated = ARES_TRUE; - } - } + const char *name = NULL; - if (s) { - /* NOTE: hquery may be invalidated during the call to ares_query_qid(), - * so should not be referenced after this point */ - switch (hquery->hints.ai_family) { - case AF_INET: - hquery->remaining += 1; - ares_query_qid(hquery->channel, s, C_IN, T_A, host_callback, hquery, - &hquery->qid_a); - break; - case AF_INET6: - hquery->remaining += 1; - ares_query_qid(hquery->channel, s, C_IN, T_AAAA, host_callback, hquery, - &hquery->qid_aaaa); - break; - case AF_UNSPEC: - hquery->remaining += 2; - ares_query_qid(hquery->channel, s, C_IN, T_A, host_callback, hquery, - &hquery->qid_a); - ares_query_qid(hquery->channel, s, C_IN, T_AAAA, host_callback, hquery, - &hquery->qid_aaaa); - break; - default: - break; - } - if (is_s_allocated) { - ares_free(s); - } - return ARES_TRUE; - } else { - assert(!hquery->ai->nodes); + if (hquery->next_name_idx >= hquery->names_cnt) { return ARES_FALSE; } -} -static ares_bool_t as_is_first(const struct host_query *hquery) -{ - const char *p; - size_t ndots = 0; - for (p = hquery->name; p && *p; p++) { - if (*p == '.') { - ndots++; - } - } - if (as_is_only(hquery)) { - /* prevent ARES_EBADNAME for valid FQDN, where ndots < channel->ndots */ - return ARES_TRUE; - } - return ndots >= hquery->channel->ndots ? ARES_TRUE : ARES_FALSE; -} + name = hquery->names[hquery->next_name_idx++]; -static ares_bool_t as_is_only(const struct host_query *hquery) -{ - size_t nname = ares_strlen(hquery->name); - if (hquery->channel->flags & ARES_FLAG_NOSEARCH) { - return ARES_TRUE; - } - if (hquery->name != NULL && nname && hquery->name[nname - 1] == '.') { - return ARES_TRUE; + /* NOTE: hquery may be invalidated during the call to ares_query_qid(), + * so should not be referenced after this point */ + switch (hquery->hints.ai_family) { + case AF_INET: + hquery->remaining += 1; + ares_query_dnsrec(hquery->channel, name, ARES_CLASS_IN, ARES_REC_TYPE_A, + host_callback, hquery, &hquery->qid_a); + break; + case AF_INET6: + hquery->remaining += 1; + ares_query_dnsrec(hquery->channel, name, ARES_CLASS_IN, + ARES_REC_TYPE_AAAA, host_callback, hquery, + &hquery->qid_aaaa); + break; + case AF_UNSPEC: + hquery->remaining += 2; + ares_query_dnsrec(hquery->channel, name, ARES_CLASS_IN, ARES_REC_TYPE_A, + host_callback, hquery, &hquery->qid_a); + ares_query_dnsrec(hquery->channel, name, ARES_CLASS_IN, + ARES_REC_TYPE_AAAA, host_callback, hquery, + &hquery->qid_aaaa); + break; + default: + break; } - return ARES_FALSE; + + return ARES_TRUE; } diff --git a/deps/cares/src/lib/ares_gethostbyaddr.c b/deps/cares/src/lib/ares_gethostbyaddr.c index ab54706ba96889..453673260dcee5 100644 --- a/deps/cares/src/lib/ares_gethostbyaddr.c +++ b/deps/cares/src/lib/ares_gethostbyaddr.c @@ -59,11 +59,11 @@ struct addr_query { size_t timeouts; }; -static void next_lookup(struct addr_query *aquery); -static void addr_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen); -static void end_aquery(struct addr_query *aquery, ares_status_t status, - struct hostent *host); +static void next_lookup(struct addr_query *aquery); +static void addr_callback(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec); +static void end_aquery(struct addr_query *aquery, ares_status_t status, + struct hostent *host); static ares_status_t file_lookup(ares_channel_t *channel, const struct ares_addr *addr, struct hostent **host); @@ -138,7 +138,8 @@ static void next_lookup(struct addr_query *aquery) return; } aquery->remaining_lookups = p + 1; - ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback, aquery); + ares_query_dnsrec(aquery->channel, name, ARES_CLASS_IN, + ARES_REC_TYPE_PTR, addr_callback, aquery, NULL); ares_free(name); return; case 'f': @@ -159,27 +160,27 @@ static void next_lookup(struct addr_query *aquery) end_aquery(aquery, ARES_ENOTFOUND, NULL); } -static void addr_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen) +static void addr_callback(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec) { struct addr_query *aquery = (struct addr_query *)arg; struct hostent *host; size_t addrlen; - aquery->timeouts += (size_t)timeouts; + aquery->timeouts += timeouts; if (status == ARES_SUCCESS) { if (aquery->addr.family == AF_INET) { addrlen = sizeof(aquery->addr.addr.addr4); - status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addr.addr4, - (int)addrlen, AF_INET, &host); + status = ares_parse_ptr_reply_dnsrec(dnsrec, &aquery->addr.addr.addr4, + (int)addrlen, AF_INET, &host); } else { addrlen = sizeof(aquery->addr.addr.addr6); - status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addr.addr6, - (int)addrlen, AF_INET6, &host); + status = ares_parse_ptr_reply_dnsrec(dnsrec, &aquery->addr.addr.addr6, + (int)addrlen, AF_INET6, &host); } - end_aquery(aquery, (ares_status_t)status, host); + end_aquery(aquery, status, host); } else if (status == ARES_EDESTRUCTION || status == ARES_ECANCELLED) { - end_aquery(aquery, (ares_status_t)status, NULL); + end_aquery(aquery, status, NULL); } else { next_lookup(aquery); } diff --git a/deps/cares/src/lib/ares_init.c b/deps/cares/src/lib/ares_init.c index bae7c72fe2cf67..28a509ea48a5af 100644 --- a/deps/cares/src/lib/ares_init.c +++ b/deps/cares/src/lib/ares_init.c @@ -152,10 +152,6 @@ static ares_status_t init_by_defaults(ares_channel_t *channel) channel->tries = DEFAULT_TRIES; } - if (channel->ndots == 0) { - channel->ndots = 1; - } - if (ares__slist_len(channel->servers) == 0) { /* Add a default local named server to the channel unless configured not * to (in which case return an error). @@ -261,31 +257,6 @@ static ares_status_t init_by_defaults(ares_channel_t *channel) } error: - if (rc) { - if (channel->domains && channel->domains[0]) { - ares_free(channel->domains[0]); - } - if (channel->domains) { - ares_free(channel->domains); - channel->domains = NULL; - } - - if (channel->lookups) { - ares_free(channel->lookups); - channel->lookups = NULL; - } - - if (channel->resolvconf_path) { - ares_free(channel->resolvconf_path); - channel->resolvconf_path = NULL; - } - - if (channel->hosts_path) { - ares_free(channel->hosts_path); - channel->hosts_path = NULL; - } - } - if (hostname) { ares_free(hostname); } @@ -309,6 +280,9 @@ int ares_init_options(ares_channel_t **channelptr, return ARES_ENOMEM; } + /* One option where zero is valid, so set default value here */ + channel->ndots = 1; + status = ares__channel_threading_init(channel); if (status != ARES_SUCCESS) { goto done; diff --git a/deps/cares/src/lib/ares_ipv6.h b/deps/cares/src/lib/ares_ipv6.h index be8cbe989396c2..28d7851ff3f051 100644 --- a/deps/cares/src/lib/ares_ipv6.h +++ b/deps/cares/src/lib/ares_ipv6.h @@ -27,6 +27,10 @@ #ifndef ARES_IPV6_H #define ARES_IPV6_H +#ifdef HAVE_NETINET6_IN6_H +# include +#endif + #ifndef HAVE_PF_INET6 # define PF_INET6 AF_INET6 #endif diff --git a/deps/cares/src/lib/ares_library_init.c b/deps/cares/src/lib/ares_library_init.c index 5cd39dc244ba4b..2767f1f93c77e4 100644 --- a/deps/cares/src/lib/ares_library_init.c +++ b/deps/cares/src/lib/ares_library_init.c @@ -72,7 +72,7 @@ static void default_free(void *p) #endif void *(*ares_malloc)(size_t size) = default_malloc; void *(*ares_realloc)(void *ptr, size_t size) = default_realloc; -void (*ares_free)(void *ptr) = default_free; +void (*ares_free)(void *ptr) = default_free; void *ares_malloc_zero(size_t size) { @@ -114,7 +114,7 @@ int ares_library_init(int flags) } int ares_library_init_mem(int flags, void *(*amalloc)(size_t size), - void (*afree)(void *ptr), + void (*afree)(void *ptr), void *(*arealloc)(void *ptr, size_t size)) { if (amalloc) { diff --git a/deps/cares/src/lib/ares_mkquery.c b/deps/cares/src/lib/ares_mkquery.c deleted file mode 100644 index da1898e74cd951..00000000000000 --- a/deps/cares/src/lib/ares_mkquery.c +++ /dev/null @@ -1,35 +0,0 @@ -/* MIT License - * - * Copyright (c) 1998 Massachusetts Institute of Technology - * Copyright (c) The c-ares project and its contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * SPDX-License-Identifier: MIT - */ - -#include "ares_setup.h" -#include "ares.h" - -int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id, - int rd, unsigned char **buf, int *buflen) -{ - return ares_create_query(name, dnsclass, type, id, rd, buf, buflen, 0); -} diff --git a/deps/cares/src/lib/ares_options.c b/deps/cares/src/lib/ares_options.c index 342d2ea1bec968..adc3e062ac437e 100644 --- a/deps/cares/src/lib/ares_options.c +++ b/deps/cares/src/lib/ares_options.c @@ -316,7 +316,7 @@ ares_status_t ares__init_by_options(ares_channel_t *channel, } if (optmask & ARES_OPT_NDOTS) { - if (options->ndots <= 0) { + if (options->ndots < 0) { optmask &= ~(ARES_OPT_NDOTS); } else { channel->ndots = (size_t)options->ndots; diff --git a/deps/cares/src/lib/ares_parse_a_reply.c b/deps/cares/src/lib/ares_parse_a_reply.c index f576575fe4b2fd..da841f0da9af36 100644 --- a/deps/cares/src/lib/ares_parse_a_reply.c +++ b/deps/cares/src/lib/ares_parse_a_reply.c @@ -59,6 +59,7 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, char *question_hostname = NULL; ares_status_t status; size_t req_naddrttls = 0; + ares_dns_record_t *dnsrec = NULL; if (alen < 0) { return ARES_EBADRESP; @@ -71,7 +72,12 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, memset(&ai, 0, sizeof(ai)); - status = ares__parse_into_addrinfo(abuf, (size_t)alen, 0, 0, &ai); + status = ares_dns_parse(abuf, (size_t)alen, 0, &dnsrec); + if (status != ARES_SUCCESS) { + goto fail; + } + + status = ares__parse_into_addrinfo(dnsrec, 0, 0, &ai); if (status != ARES_SUCCESS && status != ARES_ENODATA) { goto fail; } @@ -96,6 +102,11 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen, ares__freeaddrinfo_nodes(ai.nodes); ares_free(ai.name); ares_free(question_hostname); + ares_dns_record_destroy(dnsrec); + + if (status == ARES_EBADNAME) { + status = ARES_EBADRESP; + } return (int)status; } diff --git a/deps/cares/src/lib/ares_parse_aaaa_reply.c b/deps/cares/src/lib/ares_parse_aaaa_reply.c index cef4ad7f80948f..b3eba166be6ad6 100644 --- a/deps/cares/src/lib/ares_parse_aaaa_reply.c +++ b/deps/cares/src/lib/ares_parse_aaaa_reply.c @@ -61,6 +61,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, char *question_hostname = NULL; ares_status_t status; size_t req_naddrttls = 0; + ares_dns_record_t *dnsrec = NULL; if (alen < 0) { return ARES_EBADRESP; @@ -73,7 +74,12 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, memset(&ai, 0, sizeof(ai)); - status = ares__parse_into_addrinfo(abuf, (size_t)alen, 0, 0, &ai); + status = ares_dns_parse(abuf, (size_t)alen, 0, &dnsrec); + if (status != ARES_SUCCESS) { + goto fail; + } + + status = ares__parse_into_addrinfo(dnsrec, 0, 0, &ai); if (status != ARES_SUCCESS && status != ARES_ENODATA) { goto fail; } @@ -97,6 +103,11 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, ares__freeaddrinfo_nodes(ai.nodes); ares_free(question_hostname); ares_free(ai.name); + ares_dns_record_destroy(dnsrec); + + if (status == ARES_EBADNAME) { + status = ARES_EBADRESP; + } return (int)status; } diff --git a/deps/cares/src/lib/ares_parse_ptr_reply.c b/deps/cares/src/lib/ares_parse_ptr_reply.c index d8a29f272251cf..6ee20f722e3d01 100644 --- a/deps/cares/src/lib/ares_parse_ptr_reply.c +++ b/deps/cares/src/lib/ares_parse_ptr_reply.c @@ -36,33 +36,20 @@ #include "ares.h" #include "ares_private.h" -int ares_parse_ptr_reply(const unsigned char *abuf, int alen_int, - const void *addr, int addrlen, int family, - struct hostent **host) +ares_status_t ares_parse_ptr_reply_dnsrec(const ares_dns_record_t *dnsrec, + const void *addr, int addrlen, + int family, struct hostent **host) { - ares_status_t status; - size_t alen; - size_t ptrcount = 0; - struct hostent *hostent = NULL; - const char *hostname = NULL; - const char *ptrname = NULL; - ares_dns_record_t *dnsrec = NULL; - size_t i; - size_t ancount; + ares_status_t status; + size_t ptrcount = 0; + struct hostent *hostent = NULL; + const char *hostname = NULL; + const char *ptrname = NULL; + size_t i; + size_t ancount; *host = NULL; - if (alen_int < 0) { - return ARES_EBADRESP; - } - - alen = (size_t)alen_int; - - status = ares_dns_parse(abuf, alen, 0, &dnsrec); - if (status != ARES_SUCCESS) { - goto done; - } - /* Fetch name from query as we will use it to compare later on. Old code * did this check, so we'll retain it. */ status = ares_dns_record_query_get(dnsrec, 0, &ptrname, NULL, NULL); @@ -114,7 +101,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen_int, /* Cycle through answers */ for (i = 0; i < ancount; i++) { const ares_dns_rr_t *rr = - ares_dns_record_rr_get(dnsrec, ARES_SECTION_ANSWER, i); + ares_dns_record_rr_get_const(dnsrec, ARES_SECTION_ANSWER, i); if (rr == NULL) { /* Shouldn't be possible */ @@ -195,6 +182,34 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen_int, } else { *host = hostent; } + return status; +} + +int ares_parse_ptr_reply(const unsigned char *abuf, int alen_int, + const void *addr, int addrlen, int family, + struct hostent **host) +{ + size_t alen; + ares_dns_record_t *dnsrec = NULL; + ares_status_t status; + + if (alen_int < 0) { + return ARES_EBADRESP; + } + + alen = (size_t)alen_int; + + status = ares_dns_parse(abuf, alen, 0, &dnsrec); + if (status != ARES_SUCCESS) { + goto done; + } + + status = ares_parse_ptr_reply_dnsrec(dnsrec, addr, addrlen, family, host); + +done: ares_dns_record_destroy(dnsrec); + if (status == ARES_EBADNAME) { + status = ARES_EBADRESP; + } return (int)status; } diff --git a/deps/cares/src/lib/ares_private.h b/deps/cares/src/lib/ares_private.h index fd321b911c4a1c..6a9e04af2eb633 100644 --- a/deps/cares/src/lib/ares_private.h +++ b/deps/cares/src/lib/ares_private.h @@ -209,7 +209,7 @@ struct query { unsigned char *qbuf; size_t qlen; - ares_callback callback; + ares_callback_dnsrec callback; void *arg; /* Query status */ @@ -318,12 +318,12 @@ struct ares_channeldata { }; /* Does the domain end in ".onion" or ".onion."? Case-insensitive. */ -ares_bool_t ares__is_onion_domain(const char *name); +ares_bool_t ares__is_onion_domain(const char *name); /* Memory management functions */ -extern void *(*ares_malloc)(size_t size); -extern void *(*ares_realloc)(void *ptr, size_t size); -extern void (*ares_free)(void *ptr); +extern void *(*ares_malloc)(size_t size); +extern void *(*ares_realloc)(void *ptr, size_t size); +extern void (*ares_free)(void *ptr); void *ares_malloc_zero(size_t size); void *ares_realloc_zero(void *ptr, size_t orig_size, size_t new_size); @@ -335,23 +335,37 @@ ares_bool_t ares__timedout(const struct timeval *now, ares_status_t ares__send_query(struct query *query, struct timeval *now); ares_status_t ares__requeue_query(struct query *query, struct timeval *now); -/* Identical to ares_query, but returns a normal ares return code like - * ARES_SUCCESS, and can be passed the qid by reference which will be - * filled in on ARES_SUCCESS */ -ares_status_t ares_query_qid(ares_channel_t *channel, const char *name, - int dnsclass, int type, ares_callback callback, - void *arg, unsigned short *qid); -/* Identical to ares_send() except returns normal ares return codes like - * ARES_SUCCESS */ -ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, - size_t qlen, ares_callback callback, void *arg, - unsigned short *qid); -void ares__close_connection(struct server_connection *conn); -void ares__close_sockets(struct server_state *server); -void ares__check_cleanup_conn(const ares_channel_t *channel, - struct server_connection *conn); -ares_status_t ares__read_line(FILE *fp, char **buf, size_t *bufsize); -void ares__free_query(struct query *query); +/*! Retrieve a list of names to use for searching. The first successful + * query in the list wins. This function also uses the HOSTSALIASES file + * as well as uses channel configuration to determine the search order. + * + * \param[in] channel initialized ares channel + * \param[in] name initial name being searched + * \param[out] names array of names to attempt, use ares__strsplit_free() + * when no longer needed. + * \param[out] names_len number of names in array + * \return ARES_SUCCESS on success, otherwise one of the other error codes. + */ +ares_status_t ares__search_name_list(const ares_channel_t *channel, + const char *name, char ***names, + size_t *names_len); + +/*! Function to create callback arg for converting from ares_callback_dnsrec + * to ares_calback */ +void *ares__dnsrec_convert_arg(ares_callback callback, void *arg); + +/*! Callback function used to convert from the ares_callback_dnsrec prototype to + * the ares_callback prototype, by writing the result and passing that to + * the inner callback. + */ +void ares__dnsrec_convert_cb(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec); + +void ares__close_connection(struct server_connection *conn); +void ares__close_sockets(struct server_state *server); +void ares__check_cleanup_conn(const ares_channel_t *channel, + struct server_connection *conn); +void ares__free_query(struct query *query); ares_rand_state *ares__init_rand_state(void); void ares__destroy_rand_state(ares_rand_state *state); @@ -391,6 +405,7 @@ typedef struct { size_t tries; ares_bool_t rotate; size_t timeout_ms; + ares_bool_t usevc; } ares_sysconfig_t; ares_status_t ares__init_by_environment(ares_sysconfig_t *sysconfig); @@ -401,8 +416,13 @@ ares_status_t ares__parse_sortlist(struct apattern **sortlist, size_t *nsort, const char *str); void ares__destroy_servers_state(ares_channel_t *channel); -ares_status_t ares__single_domain(const ares_channel_t *channel, - const char *name, char **s); + +/* Returns ARES_SUCCESS if alias found, alias is set. Returns ARES_ENOTFOUND + * if not alias found. Returns other errors on critical failure like + * ARES_ENOMEM */ +ares_status_t ares__lookup_hostaliases(const ares_channel_t *channel, + const char *name, char **alias); + ares_status_t ares__cat_domain(const char *name, const char *domain, char **s); ares_status_t ares__sortaddrinfo(ares_channel_t *channel, struct ares_addrinfo_node *ai_node); @@ -427,10 +447,13 @@ ares_status_t ares_append_ai_node(int aftype, unsigned short port, void ares__addrinfo_cat_cnames(struct ares_addrinfo_cname **head, struct ares_addrinfo_cname *tail); -ares_status_t ares__parse_into_addrinfo(const unsigned char *abuf, size_t alen, +ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec, ares_bool_t cname_only_is_enodata, unsigned short port, struct ares_addrinfo *ai); +ares_status_t ares_parse_ptr_reply_dnsrec(const ares_dns_record_t *dnsrec, + const void *addr, int addrlen, + int family, struct hostent **host); ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family, struct hostent **host); @@ -456,10 +479,9 @@ ares_ssize_t ares__socket_recvfrom(ares_channel_t *channel, ares_socket_t s, ares_ssize_t ares__socket_recv(ares_channel_t *channel, ares_socket_t s, void *data, size_t data_len); void ares__close_socket(ares_channel, ares_socket_t); -int ares__connect_socket(ares_channel_t *channel, ares_socket_t sockfd, - const struct sockaddr *addr, ares_socklen_t addrlen); -ares_bool_t ares__is_hostnamech(int ch); -void ares__destroy_server(struct server_state *server); +int ares__connect_socket(ares_channel_t *channel, ares_socket_t sockfd, + const struct sockaddr *addr, ares_socklen_t addrlen); +void ares__destroy_server(struct server_state *server); ares_status_t ares__servers_update(ares_channel_t *channel, ares__llist_t *server_list, @@ -494,7 +516,6 @@ ares_status_t ares__hosts_entry_to_addrinfo(const ares_hosts_entry_t *entry, unsigned short port, ares_bool_t want_cnames, struct ares_addrinfo *ai); -ares_bool_t ares__isprint(int ch); /*! Parse a compressed DNS name as defined in RFC1035 starting at the current @@ -560,7 +581,7 @@ void ares_queue_notify_empty(ares_channel_t *channel); } while (0) #define ARES_CONFIG_CHECK(x) \ - (x && x->lookups && ares__slist_len(x->servers) > 0 && x->ndots > 0 && \ + (x && x->lookups && ares__slist_len(x->servers) > 0 && \ x->timeout > 0 && x->tries > 0) ares_bool_t ares__subnet_match(const struct ares_addr *addr, @@ -583,10 +604,10 @@ ares_status_t ares_qcache_insert(ares_channel_t *channel, const struct timeval *now, const struct query *query, ares_dns_record_t *dnsrec); -ares_status_t ares_qcache_fetch(ares_channel_t *channel, - const struct timeval *now, - const unsigned char *qbuf, size_t qlen, - unsigned char **abuf, size_t *alen); +ares_status_t ares_qcache_fetch(ares_channel_t *channel, + const struct timeval *now, + const ares_dns_record_t *dnsrec, + const ares_dns_record_t **dnsrec_resp); ares_status_t ares__channel_threading_init(ares_channel_t *channel); void ares__channel_threading_destroy(ares_channel_t *channel); diff --git a/deps/cares/src/lib/ares_process.c b/deps/cares/src/lib/ares_process.c index bd84d09e134805..b9705ae882b9ff 100644 --- a/deps/cares/src/lib/ares_process.c +++ b/deps/cares/src/lib/ares_process.c @@ -68,8 +68,7 @@ static ares_bool_t same_questions(const ares_dns_record_t *qrec, static ares_bool_t same_address(const struct sockaddr *sa, const struct ares_addr *aa); static void end_query(ares_channel_t *channel, struct query *query, - ares_status_t status, const unsigned char *abuf, - size_t alen); + ares_status_t status, const ares_dns_record_t *dnsrec); static void server_increment_failures(struct server_state *server) { @@ -625,6 +624,7 @@ static ares_status_t process_answer(ares_channel_t *channel, ares_dns_record_t *rdnsrec = NULL; ares_dns_record_t *qdnsrec = NULL; ares_status_t status; + ares_bool_t is_cached = ARES_FALSE; /* Parse the response */ status = ares_dns_parse(abuf, alen, 0, &rdnsrec); @@ -648,7 +648,7 @@ static ares_status_t process_answer(ares_channel_t *channel, /* Parse the question we sent as we use it to compare */ status = ares_dns_parse(query->qbuf, query->qlen, 0, &qdnsrec); if (status != ARES_SUCCESS) { - end_query(channel, query, status, NULL, 0); + end_query(channel, query, status, NULL); goto cleanup; } @@ -674,7 +674,7 @@ static ares_status_t process_answer(ares_channel_t *channel, ares_dns_has_opt_rr(qdnsrec) && !ares_dns_has_opt_rr(rdnsrec)) { status = rewrite_without_edns(qdnsrec, query); if (status != ARES_SUCCESS) { - end_query(channel, query, status, NULL, 0); + end_query(channel, query, status, NULL); goto cleanup; } @@ -729,16 +729,20 @@ static ares_status_t process_answer(ares_channel_t *channel, /* If cache insertion was successful, it took ownership. We ignore * other cache insertion failures. */ if (ares_qcache_insert(channel, now, query, rdnsrec) == ARES_SUCCESS) { - rdnsrec = NULL; + is_cached = ARES_TRUE; } server_set_good(server); - end_query(channel, query, ARES_SUCCESS, abuf, alen); + end_query(channel, query, ARES_SUCCESS, rdnsrec); status = ARES_SUCCESS; cleanup: - ares_dns_record_destroy(rdnsrec); + /* Don't cleanup the cached pointer to the dns response */ + if (!is_cached) { + ares_dns_record_destroy(rdnsrec); + } + ares_dns_record_destroy(qdnsrec); return status; } @@ -774,7 +778,7 @@ ares_status_t ares__requeue_query(struct query *query, struct timeval *now) query->error_status = ARES_ETIMEOUT; } - end_query(channel, query, query->error_status, NULL, 0); + end_query(channel, query, query->error_status, NULL); return ARES_ETIMEOUT; } @@ -893,7 +897,7 @@ ares_status_t ares__send_query(struct query *query, struct timeval *now) } if (server == NULL) { - end_query(channel, query, ARES_ENOSERVER /* ? */, NULL, 0); + end_query(channel, query, ARES_ENOSERVER /* ? */, NULL); return ARES_ENOSERVER; } @@ -920,7 +924,7 @@ ares_status_t ares__send_query(struct query *query, struct timeval *now) /* Anything else is not retryable, likely ENOMEM */ default: - end_query(channel, query, status, NULL, 0); + end_query(channel, query, status, NULL); return status; } } @@ -931,7 +935,7 @@ ares_status_t ares__send_query(struct query *query, struct timeval *now) status = ares__append_tcpbuf(server, query); if (status != ARES_SUCCESS) { - end_query(channel, query, status, NULL, 0); + end_query(channel, query, status, NULL); /* Only safe to kill connection if it was new, otherwise it should be * cleaned up by another process later */ @@ -979,7 +983,7 @@ ares_status_t ares__send_query(struct query *query, struct timeval *now) /* Anything else is not retryable, likely ENOMEM */ default: - end_query(channel, query, status, NULL, 0); + end_query(channel, query, status, NULL); return status; } node = ares__llist_node_first(server->connections); @@ -1011,7 +1015,7 @@ ares_status_t ares__send_query(struct query *query, struct timeval *now) query->node_queries_by_timeout = ares__slist_insert(channel->queries_by_timeout, query); if (!query->node_queries_by_timeout) { - end_query(channel, query, ARES_ENOMEM, NULL, 0); + end_query(channel, query, ARES_ENOMEM, NULL); /* Only safe to kill connection if it was new, otherwise it should be * cleaned up by another process later */ if (new_connection) { @@ -1027,7 +1031,7 @@ ares_status_t ares__send_query(struct query *query, struct timeval *now) ares__llist_insert_last(conn->queries_to_conn, query); if (query->node_queries_to_conn == NULL) { - end_query(channel, query, ARES_ENOMEM, NULL, 0); + end_query(channel, query, ARES_ENOMEM, NULL); /* Only safe to kill connection if it was new, otherwise it should be * cleaned up by another process later */ if (new_connection) { @@ -1124,14 +1128,10 @@ static void ares_detach_query(struct query *query) } static void end_query(ares_channel_t *channel, struct query *query, - ares_status_t status, const unsigned char *abuf, - size_t alen) + ares_status_t status, const ares_dns_record_t *dnsrec) { /* Invoke the callback. */ - query->callback(query->arg, (int)status, (int)query->timeouts, - /* due to prior design flaws, abuf isn't meant to be modified, - * but bad prototypes, ugh. Lets cast off constfor compat. */ - (unsigned char *)((void *)((size_t)abuf)), (int)alen); + query->callback(query->arg, status, query->timeouts, dnsrec); ares__free_query(query); /* Check and notify if no other queries are enqueued on the channel. This diff --git a/deps/cares/src/lib/ares_qcache.c b/deps/cares/src/lib/ares_qcache.c index bab8781850789a..2af1125a0d299f 100644 --- a/deps/cares/src/lib/ares_qcache.c +++ b/deps/cares/src/lib/ares_qcache.c @@ -81,6 +81,7 @@ static char *ares__qcache_calc_key(const ares_dns_record_t *dnsrec) for (i = 0; i < ares_dns_record_query_cnt(dnsrec); i++) { const char *name; + size_t name_len; ares_dns_rec_type_t qtype; ares_dns_class_t qclass; @@ -114,7 +115,15 @@ static char *ares__qcache_calc_key(const ares_dns_record_t *dnsrec) goto fail; } - status = ares__buf_append_str(buf, name); + /* On queries, a '.' may be appended to the name to indicate an explicit + * name lookup without performing a search. Strip this since its not part + * of a cached response. */ + name_len = ares_strlen(name); + if (name_len && name[name_len - 1] == '.') { + name_len--; + } + + status = ares__buf_append(buf, (const unsigned char *)name, name_len); if (status != ARES_SUCCESS) { goto fail; } @@ -384,20 +393,24 @@ static ares_status_t ares__qcache_insert(ares__qcache_t *qcache, return ARES_ENOMEM; } -static ares_status_t ares__qcache_fetch(ares__qcache_t *qcache, - const ares_dns_record_t *dnsrec, - const struct timeval *now, - unsigned char **buf, size_t *buf_len) +ares_status_t ares_qcache_fetch(ares_channel_t *channel, + const struct timeval *now, + const ares_dns_record_t *dnsrec, + const ares_dns_record_t **dnsrec_resp) { char *key = NULL; ares__qcache_entry_t *entry; - ares_status_t status; + ares_status_t status = ARES_SUCCESS; - if (qcache == NULL || dnsrec == NULL) { + if (channel == NULL || dnsrec == NULL || dnsrec_resp == NULL) { return ARES_EFORMERR; } - ares__qcache_expire(qcache, now); + if (channel->qcache == NULL) { + return ARES_ENOTFOUND; + } + + ares__qcache_expire(channel->qcache, now); key = ares__qcache_calc_key(dnsrec); if (key == NULL) { @@ -405,7 +418,7 @@ static ares_status_t ares__qcache_fetch(ares__qcache_t *qcache, goto done; } - entry = ares__htable_strvp_get_direct(qcache->cache, key); + entry = ares__htable_strvp_get_direct(channel->qcache->cache, key); if (entry == NULL) { status = ARES_ENOTFOUND; goto done; @@ -414,7 +427,7 @@ static ares_status_t ares__qcache_fetch(ares__qcache_t *qcache, ares_dns_record_write_ttl_decrement( entry->dnsrec, (unsigned int)(now->tv_sec - entry->insert_ts)); - status = ares_dns_write(entry->dnsrec, buf, buf_len); + *dnsrec_resp = entry->dnsrec; done: ares_free(key); @@ -429,27 +442,3 @@ ares_status_t ares_qcache_insert(ares_channel_t *channel, return ares__qcache_insert(channel->qcache, dnsrec, query->qbuf, query->qlen, now); } - -ares_status_t ares_qcache_fetch(ares_channel_t *channel, - const struct timeval *now, - const unsigned char *qbuf, size_t qlen, - unsigned char **abuf, size_t *alen) -{ - ares_status_t status; - ares_dns_record_t *dnsrec = NULL; - - if (channel->qcache == NULL) { - return ARES_ENOTFOUND; - } - - status = ares_dns_parse(qbuf, qlen, 0, &dnsrec); - if (status != ARES_SUCCESS) { - goto done; - } - - status = ares__qcache_fetch(channel->qcache, dnsrec, now, abuf, alen); - -done: - ares_dns_record_destroy(dnsrec); - return status; -} diff --git a/deps/cares/src/lib/ares_query.c b/deps/cares/src/lib/ares_query.c index 098e6789471809..0eea80e7fc1e59 100644 --- a/deps/cares/src/lib/ares_query.c +++ b/deps/cares/src/lib/ares_query.c @@ -37,103 +37,116 @@ #include "ares_dns.h" #include "ares_private.h" -struct qquery { - ares_callback callback; - void *arg; -}; +typedef struct { + ares_callback_dnsrec callback; + void *arg; +} ares_query_dnsrec_arg_t; -static void qcallback(void *arg, int status, int timeouts, unsigned char *abuf, - int alen); - -ares_status_t ares_query_qid(ares_channel_t *channel, const char *name, - int dnsclass, int type, ares_callback callback, - void *arg, unsigned short *qid) +static void ares_query_dnsrec_cb(void *arg, ares_status_t status, + size_t timeouts, + const ares_dns_record_t *dnsrec) { - struct qquery *qquery; - unsigned char *qbuf; - int qlen; - int rd; - ares_status_t status; - - /* Compose the query. */ - rd = !(channel->flags & ARES_FLAG_NORECURSE); - status = (ares_status_t)ares_create_query( - name, dnsclass, type, 0, rd, &qbuf, &qlen, - (channel->flags & ARES_FLAG_EDNS) ? (int)channel->ednspsz : 0); + ares_query_dnsrec_arg_t *qquery = arg; + if (status != ARES_SUCCESS) { - if (qbuf != NULL) { - ares_free(qbuf); + qquery->callback(qquery->arg, status, timeouts, dnsrec); + } else { + size_t ancount; + ares_dns_rcode_t rcode; + /* Pull the response code and answer count from the packet and convert any + * errors. + */ + rcode = ares_dns_record_get_rcode(dnsrec); + ancount = ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); + status = ares_dns_query_reply_tostatus(rcode, ancount); + qquery->callback(qquery->arg, status, timeouts, dnsrec); + } + ares_free(qquery); +} + +static ares_status_t ares_query_int(ares_channel_t *channel, const char *name, + ares_dns_class_t dnsclass, + ares_dns_rec_type_t type, + ares_callback_dnsrec callback, void *arg, + unsigned short *qid) +{ + ares_status_t status; + ares_dns_record_t *dnsrec = NULL; + ares_dns_flags_t flags = 0; + ares_query_dnsrec_arg_t *qquery = NULL; + + if (channel == NULL || name == NULL || callback == NULL) { + status = ARES_EFORMERR; + if (callback != NULL) { + callback(arg, status, 0, NULL); } - callback(arg, (int)status, 0, NULL, 0); return status; } - /* Allocate and fill in the query structure. */ - qquery = ares_malloc(sizeof(struct qquery)); - if (!qquery) { - ares_free_string(qbuf); - callback(arg, ARES_ENOMEM, 0, NULL, 0); - return ARES_ENOMEM; + if (!(channel->flags & ARES_FLAG_NORECURSE)) { + flags |= ARES_FLAG_RD; } + + status = ares_dns_record_create_query( + &dnsrec, name, dnsclass, type, 0, flags, + (size_t)(channel->flags & ARES_FLAG_EDNS) ? channel->ednspsz : 0); + if (status != ARES_SUCCESS) { + callback(arg, status, 0, NULL); + return status; + } + + qquery = ares_malloc(sizeof(*qquery)); + if (qquery == NULL) { + status = ARES_ENOMEM; + callback(arg, status, 0, NULL); + ares_dns_record_destroy(dnsrec); + return status; + } + qquery->callback = callback; qquery->arg = arg; /* Send it off. qcallback will be called when we get an answer. */ - status = ares_send_ex(channel, qbuf, (size_t)qlen, qcallback, qquery, qid); - ares_free_string(qbuf); + status = ares_send_dnsrec(channel, dnsrec, ares_query_dnsrec_cb, qquery, qid); + ares_dns_record_destroy(dnsrec); return status; } -void ares_query(ares_channel_t *channel, const char *name, int dnsclass, - int type, ares_callback callback, void *arg) +ares_status_t ares_query_dnsrec(ares_channel_t *channel, const char *name, + ares_dns_class_t dnsclass, + ares_dns_rec_type_t type, + ares_callback_dnsrec callback, void *arg, + unsigned short *qid) { + ares_status_t status; + if (channel == NULL) { - return; + return ARES_EFORMERR; } + ares__channel_lock(channel); - ares_query_qid(channel, name, dnsclass, type, callback, arg, NULL); + status = ares_query_int(channel, name, dnsclass, type, callback, arg, qid); ares__channel_unlock(channel); + return status; } -static void qcallback(void *arg, int status, int timeouts, unsigned char *abuf, - int alen) +void ares_query(ares_channel_t *channel, const char *name, int dnsclass, + int type, ares_callback callback, void *arg) { - struct qquery *qquery = (struct qquery *)arg; - size_t ancount; - int rcode; + void *carg = NULL; - if (status != ARES_SUCCESS) { - qquery->callback(qquery->arg, status, timeouts, abuf, alen); - } else { - /* Pull the response code and answer count from the packet. */ - rcode = DNS_HEADER_RCODE(abuf); - ancount = DNS_HEADER_ANCOUNT(abuf); - - /* Convert errors. */ - switch (rcode) { - case NOERROR: - status = (ancount > 0) ? ARES_SUCCESS : ARES_ENODATA; - break; - case FORMERR: - status = ARES_EFORMERR; - break; - case SERVFAIL: - status = ARES_ESERVFAIL; - break; - case NXDOMAIN: - status = ARES_ENOTFOUND; - break; - case NOTIMP: - status = ARES_ENOTIMP; - break; - case REFUSED: - status = ARES_EREFUSED; - break; - default: - break; - } - qquery->callback(qquery->arg, status, timeouts, abuf, alen); + if (channel == NULL) { + return; } - ares_free(qquery); + + carg = ares__dnsrec_convert_arg(callback, arg); + if (carg == NULL) { + callback(arg, ARES_ENOMEM, 0, NULL, 0); + return; + } + + ares_query_dnsrec(channel, name, (ares_dns_class_t)dnsclass, + (ares_dns_rec_type_t)type, ares__dnsrec_convert_cb, carg, + NULL); } diff --git a/deps/cares/src/lib/ares_search.c b/deps/cares/src/lib/ares_search.c index 429c7e1db0de26..4fd909cd4f8b9f 100644 --- a/deps/cares/src/lib/ares_search.c +++ b/deps/cares/src/lib/ares_search.c @@ -33,209 +33,437 @@ #include "ares.h" #include "ares_private.h" +#include "ares_dns.h" struct search_query { - /* Arguments passed to ares_search */ - ares_channel_t *channel; - char *name; /* copied into an allocated buffer */ - int dnsclass; - int type; - ares_callback callback; - void *arg; - char **domains; /* duplicate for ares_reinit() safety */ - size_t ndomains; - - int status_as_is; /* error status from trying as-is */ - size_t next_domain; /* next search domain to try */ - ares_bool_t trying_as_is; /* current query is for name as-is */ - size_t timeouts; /* number of timeouts we saw for this request */ + /* Arguments passed to ares_search_dnsrec() */ + ares_channel_t *channel; + ares_callback_dnsrec callback; + void *arg; + + /* Duplicate of DNS record passed to ares_search_dnsrec() */ + ares_dns_record_t *dnsrec; + + /* Search order for names */ + char **names; + size_t names_cnt; + + /* State tracking progress through the search query */ + size_t next_name_idx; /* next name index being attempted */ + size_t timeouts; /* number of timeouts we saw for this request */ ares_bool_t ever_got_nodata; /* did we ever get ARES_ENODATA along the way? */ }; -static void search_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen); +static void squery_free(struct search_query *squery) +{ + if (squery == NULL) { + return; + } + ares__strsplit_free(squery->names, squery->names_cnt); + ares_dns_record_destroy(squery->dnsrec); + ares_free(squery); +} + +/* End a search query by invoking the user callback and freeing the + * search_query structure. + */ static void end_squery(struct search_query *squery, ares_status_t status, - unsigned char *abuf, size_t alen); + const ares_dns_record_t *dnsrec) +{ + squery->callback(squery->arg, status, squery->timeouts, dnsrec); + squery_free(squery); +} + +static void search_callback(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec); -static void ares_search_int(ares_channel_t *channel, const char *name, - int dnsclass, int type, ares_callback callback, - void *arg) +static ares_status_t ares_search_next(ares_channel_t *channel, + struct search_query *squery, + ares_bool_t *skip_cleanup) { - struct search_query *squery; - char *s; - const char *p; - ares_status_t status; - size_t ndots; + ares_status_t status; - /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */ - if (ares__is_onion_domain(name)) { - callback(arg, ARES_ENOTFOUND, 0, NULL, 0); - return; + *skip_cleanup = ARES_FALSE; + + /* Misuse check */ + if (squery->next_name_idx >= squery->names_cnt) { + return ARES_EFORMERR; } - /* 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_dns_record_query_set_name( + squery->dnsrec, 0, squery->names[squery->next_name_idx++]); if (status != ARES_SUCCESS) { - callback(arg, (int)status, 0, NULL, 0); + return status; + } + + status = + ares_send_dnsrec(channel, squery->dnsrec, search_callback, squery, NULL); + + if (status != ARES_EFORMERR) { + *skip_cleanup = ARES_TRUE; + } + + return status; +} + +static void search_callback(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec) +{ + struct search_query *squery = (struct search_query *)arg; + ares_channel_t *channel = squery->channel; + ares_dns_rcode_t rcode; + size_t ancount; + ares_status_t mystatus; + ares_bool_t skip_cleanup = ARES_FALSE; + + squery->timeouts += timeouts; + + if (status != ARES_SUCCESS) { + end_squery(squery, status, dnsrec); return; } - if (s) { - ares_query(channel, s, dnsclass, type, callback, arg); - ares_free(s); + + rcode = ares_dns_record_get_rcode(dnsrec); + ancount = ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); + mystatus = ares_dns_query_reply_tostatus(rcode, ancount); + + if (mystatus != ARES_ENODATA && mystatus != ARES_ESERVFAIL && + mystatus != ARES_ENOTFOUND) { + end_squery(squery, mystatus, dnsrec); return; } - /* Allocate a search_query structure to hold the state necessary for - * doing multiple lookups. + /* If we ever get ARES_ENODATA along the way, record that; if the search + * should run to the very end and we got at least one ARES_ENODATA, + * then callers like ares_gethostbyname() may want to try a T_A search + * even if the last domain we queried for T_AAAA resource records + * returned ARES_ENOTFOUND. */ - squery = ares_malloc_zero(sizeof(*squery)); - if (!squery) { - callback(arg, ARES_ENOMEM, 0, NULL, 0); + if (mystatus == ARES_ENODATA) { + squery->ever_got_nodata = ARES_TRUE; + } + + if (squery->next_name_idx < squery->names_cnt) { + mystatus = ares_search_next(channel, squery, &skip_cleanup); + if (mystatus != ARES_SUCCESS && !skip_cleanup) { + end_squery(squery, mystatus, NULL); + } return; } - squery->channel = channel; - squery->name = ares_strdup(name); - if (!squery->name) { - ares_free(squery); - callback(arg, ARES_ENOMEM, 0, NULL, 0); + + + /* We have no more domains to search, return an appropriate response. */ + if (mystatus == ARES_ENOTFOUND && squery->ever_got_nodata) { + end_squery(squery, ARES_ENODATA, NULL); return; } - /* Duplicate domains for safety during ares_reinit() */ - if (channel->ndomains) { - squery->domains = - ares__strsplit_duplicate(channel->domains, channel->ndomains); - if (squery->domains == NULL) { - ares_free(squery->name); - ares_free(squery); - callback(arg, ARES_ENOMEM, 0, NULL, 0); - return; + end_squery(squery, mystatus, NULL); +} + +/* Determine if the domain should be looked up as-is, or if it is eligible + * for search by appending domains */ +static ares_bool_t ares__search_eligible(const ares_channel_t *channel, + const char *name) +{ + size_t len = ares_strlen(name); + + /* Name ends in '.', cannot search */ + if (len && name[len - 1] == '.') { + return ARES_FALSE; + } + + if (channel->flags & ARES_FLAG_NOSEARCH) { + return ARES_FALSE; + } + + return ARES_TRUE; +} + +ares_status_t ares__search_name_list(const ares_channel_t *channel, + const char *name, char ***names, + size_t *names_len) +{ + ares_status_t status; + char **list = NULL; + size_t list_len = 0; + char *alias = NULL; + size_t ndots = 0; + size_t idx = 0; + const char *p; + size_t i; + + /* Perform HOSTALIASES resolution */ + status = ares__lookup_hostaliases(channel, name, &alias); + if (status == ARES_SUCCESS) { + /* If hostalias succeeds, there is no searching, it is used as-is */ + list_len = 1; + list = ares_malloc_zero(sizeof(*list) * list_len); + if (list == NULL) { + status = ARES_ENOMEM; + goto done; } - squery->ndomains = channel->ndomains; + list[0] = alias; + alias = NULL; + goto done; + } else if (status != ARES_ENOTFOUND) { + goto done; } - squery->dnsclass = dnsclass; - squery->type = type; - squery->status_as_is = -1; - squery->callback = callback; - squery->arg = arg; - squery->timeouts = 0; - squery->ever_got_nodata = ARES_FALSE; + /* See if searching is eligible at all, if not, look up as-is only */ + if (!ares__search_eligible(channel, name)) { + list_len = 1; + list = ares_malloc_zero(sizeof(*list) * list_len); + if (list == NULL) { + status = ARES_ENOMEM; + goto done; + } + list[0] = ares_strdup(name); + if (list[0] == NULL) { + status = ARES_ENOMEM; + } else { + status = ARES_SUCCESS; + } + goto done; + } - /* Count the number of dots in name. */ + /* Count the number of dots in name */ ndots = 0; - for (p = name; *p; p++) { + for (p = name; *p != 0; p++) { if (*p == '.') { ndots++; } } - /* If ndots is at least the channel ndots threshold (usually 1), - * then we try the name as-is first. Otherwise, we try the name - * as-is last. - */ - if (ndots >= channel->ndots || squery->ndomains == 0) { - /* Try the name as-is first. */ - squery->next_domain = 0; - squery->trying_as_is = ARES_TRUE; - ares_query(channel, name, dnsclass, type, search_callback, squery); - } else { - /* Try the name as-is last; start with the first search domain. */ - squery->next_domain = 1; - squery->trying_as_is = ARES_FALSE; - status = ares__cat_domain(name, squery->domains[0], &s); - if (status == ARES_SUCCESS) { - ares_query(channel, s, dnsclass, type, search_callback, squery); - ares_free(s); - } else { - /* failed, free the malloc()ed memory */ - ares_free(squery->name); - ares_free(squery); - callback(arg, (int)status, 0, NULL, 0); + /* Allocate an entry for each search domain, plus one for as-is */ + list_len = channel->ndomains + 1; + list = ares_malloc_zero(sizeof(*list) * list_len); + if (list == NULL) { + status = ARES_ENOMEM; + goto done; + } + + /* Set status here, its possible there are no search domains at all, so + * status may be ARES_ENOTFOUND from ares__lookup_hostaliases(). */ + status = ARES_SUCCESS; + + /* Try as-is first */ + if (ndots >= channel->ndots) { + list[idx] = ares_strdup(name); + if (list[idx] == NULL) { + status = ARES_ENOMEM; + goto done; + } + idx++; + } + + /* Append each search suffix to the name */ + for (i = 0; i < channel->ndomains; i++) { + status = ares__cat_domain(name, channel->domains[i], &list[idx]); + if (status != ARES_SUCCESS) { + goto done; } + idx++; } + + /* Try as-is last */ + if (ndots < channel->ndots) { + list[idx] = ares_strdup(name); + if (list[idx] == NULL) { + status = ARES_ENOMEM; + goto done; + } + idx++; + } + + +done: + if (status == ARES_SUCCESS) { + *names = list; + *names_len = list_len; + } else { + ares__strsplit_free(list, list_len); + } + + ares_free(alias); + return status; } -void ares_search(ares_channel_t *channel, const char *name, int dnsclass, - int type, ares_callback callback, void *arg) +static ares_status_t ares_search_int(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, void *arg) { - if (channel == NULL) { - return; + struct search_query *squery = NULL; + const char *name; + ares_status_t status = ARES_SUCCESS; + ares_bool_t skip_cleanup = ARES_FALSE; + + /* Extract the name for the search. Note that searches are only supported for + * DNS records containing a single query. + */ + if (ares_dns_record_query_cnt(dnsrec) != 1) { + status = ARES_EBADQUERY; + goto fail; } - ares__channel_lock(channel); - ares_search_int(channel, name, dnsclass, type, callback, arg); - ares__channel_unlock(channel); + + status = ares_dns_record_query_get(dnsrec, 0, &name, NULL, NULL); + if (status != ARES_SUCCESS) { + goto fail; + } + + /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */ + if (ares__is_onion_domain(name)) { + status = ARES_ENOTFOUND; + goto fail; + } + + /* Allocate a search_query structure to hold the state necessary for + * doing multiple lookups. + */ + squery = ares_malloc_zero(sizeof(*squery)); + if (squery == NULL) { + status = ARES_ENOMEM; + goto fail; + } + + squery->channel = channel; + + /* Duplicate DNS record since, name will need to be rewritten */ + squery->dnsrec = ares_dns_record_duplicate(dnsrec); + if (squery->dnsrec == NULL) { + status = ARES_ENOMEM; + goto fail; + } + + squery->callback = callback; + squery->arg = arg; + squery->timeouts = 0; + squery->ever_got_nodata = ARES_FALSE; + + status = + ares__search_name_list(channel, name, &squery->names, &squery->names_cnt); + if (status != ARES_SUCCESS) { + goto fail; + } + + status = ares_search_next(channel, squery, &skip_cleanup); + if (status != ARES_SUCCESS) { + goto fail; + } + + return status; + +fail: + if (!skip_cleanup) { + squery_free(squery); + callback(arg, status, 0, NULL); + } + return status; } -static void search_callback(void *arg, int status, int timeouts, - unsigned char *abuf, int alen) +/* Callback argument structure passed to ares__dnsrec_convert_cb(). */ +typedef struct { + ares_callback callback; + void *arg; +} dnsrec_convert_arg_t; + +/*! Function to create callback arg for converting from ares_callback_dnsrec + * to ares_calback */ +void *ares__dnsrec_convert_arg(ares_callback callback, void *arg) { - struct search_query *squery = (struct search_query *)arg; - ares_channel_t *channel = squery->channel; - char *s; + dnsrec_convert_arg_t *carg = ares_malloc_zero(sizeof(*carg)); + if (carg == NULL) { + return NULL; + } + carg->callback = callback; + carg->arg = arg; + return carg; +} - squery->timeouts += (size_t)timeouts; +/*! Callback function used to convert from the ares_callback_dnsrec prototype to + * the ares_callback prototype, by writing the result and passing that to + * the inner callback. + */ +void ares__dnsrec_convert_cb(void *arg, ares_status_t status, size_t timeouts, + const ares_dns_record_t *dnsrec) +{ + dnsrec_convert_arg_t *carg = arg; + unsigned char *abuf = NULL; + size_t alen = 0; - /* Stop searching unless we got a non-fatal error. */ - if (status != ARES_ENODATA && status != ARES_ESERVFAIL && - status != ARES_ENOTFOUND) { - end_squery(squery, (ares_status_t)status, abuf, (size_t)alen); - } else { - /* Save the status if we were trying as-is. */ - if (squery->trying_as_is) { - squery->status_as_is = status; + if (dnsrec != NULL) { + ares_status_t mystatus = ares_dns_write(dnsrec, &abuf, &alen); + if (mystatus != ARES_SUCCESS) { + status = mystatus; } + } - /* - * If we ever get ARES_ENODATA along the way, record that; if the search - * should run to the very end and we got at least one ARES_ENODATA, - * then callers like ares_gethostbyname() may want to try a T_A search - * even if the last domain we queried for T_AAAA resource records - * returned ARES_ENOTFOUND. - */ - if (status == ARES_ENODATA) { - squery->ever_got_nodata = ARES_TRUE; - } + carg->callback(carg->arg, (int)status, (int)timeouts, abuf, (int)alen); - if (squery->next_domain < squery->ndomains) { - ares_status_t mystatus; - /* Try the next domain. */ - mystatus = ares__cat_domain(squery->name, - squery->domains[squery->next_domain], &s); - if (mystatus != ARES_SUCCESS) { - end_squery(squery, mystatus, NULL, 0); - } else { - squery->trying_as_is = ARES_FALSE; - squery->next_domain++; - ares_query(channel, s, squery->dnsclass, squery->type, search_callback, - squery); - ares_free(s); - } - } else if (squery->status_as_is == -1) { - /* Try the name as-is at the end. */ - squery->trying_as_is = ARES_TRUE; - ares_query(channel, squery->name, squery->dnsclass, squery->type, - search_callback, squery); - } else { - if (squery->status_as_is == ARES_ENOTFOUND && squery->ever_got_nodata) { - end_squery(squery, ARES_ENODATA, NULL, 0); - } else { - end_squery(squery, (ares_status_t)squery->status_as_is, NULL, 0); - } - } + ares_free(abuf); + ares_free(carg); +} + +/* Search for a DNS name with given class and type. Wrapper around + * ares_search_int() where the DNS record to search is first constructed. + */ +void ares_search(ares_channel_t *channel, const char *name, int dnsclass, + int type, ares_callback callback, void *arg) +{ + ares_status_t status; + ares_dns_record_t *dnsrec = NULL; + size_t max_udp_size; + ares_dns_flags_t rd_flag; + void *carg = NULL; + if (channel == NULL || name == NULL) { + return; + } + + /* For now, ares_search_int() uses the ares_callback prototype. We need to + * wrap the callback passed to this function in ares__dnsrec_convert_cb, to + * convert from ares_callback_dnsrec to ares_callback. Allocate the convert + * arg structure here. + */ + carg = ares__dnsrec_convert_arg(callback, arg); + if (carg == NULL) { + callback(arg, ARES_ENOMEM, 0, NULL, 0); + return; + } + + rd_flag = !(channel->flags & ARES_FLAG_NORECURSE) ? ARES_FLAG_RD : 0; + max_udp_size = (channel->flags & ARES_FLAG_EDNS) ? channel->ednspsz : 0; + status = ares_dns_record_create_query( + &dnsrec, name, (ares_dns_class_t)dnsclass, (ares_dns_rec_type_t)type, 0, + rd_flag, max_udp_size); + if (status != ARES_SUCCESS) { + callback(arg, (int)status, 0, NULL, 0); + ares_free(carg); + return; } + + ares__channel_lock(channel); + ares_search_int(channel, dnsrec, ares__dnsrec_convert_cb, carg); + ares__channel_unlock(channel); + + ares_dns_record_destroy(dnsrec); } -static void end_squery(struct search_query *squery, ares_status_t status, - unsigned char *abuf, size_t alen) +/* Search for a DNS record. Wrapper around ares_search_int(). */ +ares_status_t ares_search_dnsrec(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, void *arg) { - squery->callback(squery->arg, (int)status, (int)squery->timeouts, abuf, - (int)alen); - ares__strsplit_free(squery->domains, squery->ndomains); - ares_free(squery->name); - ares_free(squery); + ares_status_t status; + + if (channel == NULL || dnsrec == NULL || callback == NULL) { + return ARES_EFORMERR; + } + + ares__channel_lock(channel); + status = ares_search_int(channel, dnsrec, callback, arg); + ares__channel_unlock(channel); + + return status; } /* Concatenate two domains. */ @@ -260,89 +488,113 @@ ares_status_t ares__cat_domain(const char *name, const char *domain, char **s) return ARES_SUCCESS; } -/* Determine if this name only yields one query. If it does, set *s to - * the string we should query, in an allocated buffer. If not, set *s - * to NULL. - */ -ares_status_t ares__single_domain(const ares_channel_t *channel, - const char *name, char **s) +ares_status_t ares__lookup_hostaliases(const ares_channel_t *channel, + const char *name, char **alias) { - size_t len = ares_strlen(name); - const char *hostaliases; - FILE *fp; - char *line = NULL; - ares_status_t status; - size_t linesize; - const char *p; - const char *q; - int error; + ares_status_t status = ARES_SUCCESS; + const char *hostaliases = NULL; + ares__buf_t *buf = NULL; + ares__llist_t *lines = NULL; + ares__llist_node_t *node; + + if (channel == NULL || name == NULL || alias == NULL) { + return ARES_EFORMERR; + } + + *alias = NULL; + + /* Configuration says to not perform alias lookup */ + if (channel->flags & ARES_FLAG_NOALIASES) { + return ARES_ENOTFOUND; + } + + /* If a domain has a '.', its not allowed to perform an alias lookup */ + if (strchr(name, '.') != NULL) { + return ARES_ENOTFOUND; + } - /* If the name contains a trailing dot, then the single query is the name - * sans the trailing dot. + hostaliases = getenv("HOSTALIASES"); + if (hostaliases == NULL) { + status = ARES_ENOTFOUND; + goto done; + } + + buf = ares__buf_create(); + if (buf == NULL) { + status = ARES_ENOMEM; + goto done; + } + + status = ares__buf_load_file(hostaliases, buf); + if (status != ARES_SUCCESS) { + goto done; + } + + /* The HOSTALIASES file is structured as one alias per line. The first + * field in the line is the simple hostname with no periods, followed by + * whitespace, then the full domain name, e.g.: + * + * c-ares www.c-ares.org + * curl www.curl.se */ - if ((len > 0) && (name[len - 1] == '.')) { - *s = ares_strdup(name); - return (*s) ? ARES_SUCCESS : ARES_ENOMEM; - } - - if (!(channel->flags & ARES_FLAG_NOALIASES) && !strchr(name, '.')) { - /* The name might be a host alias. */ - hostaliases = getenv("HOSTALIASES"); - if (hostaliases) { - fp = fopen(hostaliases, "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == - ARES_SUCCESS) { - if (strncasecmp(line, name, len) != 0 || !ISSPACE(line[len])) { - continue; - } - p = line + len; - while (ISSPACE(*p)) { - p++; - } - if (*p) { - q = p + 1; - while (*q && !ISSPACE(*q)) { - q++; - } - *s = ares_malloc((size_t)(q - p + 1)); - if (*s) { - memcpy(*s, p, (size_t)(q - p)); - (*s)[q - p] = 0; - } - ares_free(line); - fclose(fp); - return (*s) ? ARES_SUCCESS : ARES_ENOMEM; - } - } - ares_free(line); - fclose(fp); - if (status != ARES_SUCCESS && status != ARES_EOF) { - return status; - } - } else { - error = ERRNO; - switch (error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, - strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", hostaliases)); - *s = NULL; - return ARES_EFILE; - } - } - } + + status = ares__buf_split(buf, (const unsigned char *)"\n", 1, + ARES_BUF_SPLIT_TRIM, 0, &lines); + if (status != ARES_SUCCESS) { + goto done; } - if (channel->flags & ARES_FLAG_NOSEARCH || channel->ndomains == 0) { - /* No domain search to do; just try the name as-is. */ - *s = ares_strdup(name); - return (*s) ? ARES_SUCCESS : ARES_ENOMEM; + for (node = ares__llist_node_first(lines); node != NULL; + node = ares__llist_node_next(node)) { + ares__buf_t *line = ares__llist_node_val(node); + char hostname[64] = ""; + char fqdn[256] = ""; + + /* Pull off hostname */ + ares__buf_tag(line); + ares__buf_consume_nonwhitespace(line); + if (ares__buf_tag_fetch_string(line, hostname, sizeof(hostname)) != + ARES_SUCCESS) { + continue; + } + + /* Match hostname */ + if (strcasecmp(hostname, name) != 0) { + continue; + } + + /* consume whitespace */ + ares__buf_consume_whitespace(line, ARES_TRUE); + + /* pull off fqdn */ + ares__buf_tag(line); + ares__buf_consume_nonwhitespace(line); + if (ares__buf_tag_fetch_string(line, fqdn, sizeof(fqdn)) != ARES_SUCCESS || + ares_strlen(fqdn) == 0) { + continue; + } + + /* Validate characterset */ + if (!ares__is_hostname(fqdn)) { + continue; + } + + *alias = ares_strdup(fqdn); + if (*alias == NULL) { + status = ARES_ENOMEM; + goto done; + } + + /* Good! */ + status = ARES_SUCCESS; + goto done; } - *s = NULL; - return ARES_SUCCESS; + status = ARES_ENOTFOUND; + +done: + ares__buf_destroy(buf); + ares__llist_destroy(lines); + + return status; } diff --git a/deps/cares/src/lib/ares_send.c b/deps/cares/src/lib/ares_send.c index 6cefdb6a36a87e..54f2b504d50cac 100644 --- a/deps/cares/src/lib/ares_send.c +++ b/deps/cares/src/lib/ares_send.c @@ -48,52 +48,47 @@ static unsigned short generate_unique_qid(ares_channel_t *channel) return id; } -ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, - size_t qlen, ares_callback callback, void *arg, - unsigned short *qid) +static ares_status_t ares_send_dnsrec_int(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, + void *arg, unsigned short *qid) { - struct query *query; - size_t packetsz; - struct timeval now = ares__tvnow(); - ares_status_t status; - unsigned short id = generate_unique_qid(channel); - unsigned char *abuf = NULL; - size_t alen = 0; + struct query *query; + size_t packetsz; + struct timeval now = ares__tvnow(); + ares_status_t status; + unsigned short id = generate_unique_qid(channel); + const ares_dns_record_t *dnsrec_resp = NULL; - /* Verify that the query is at least long enough to hold the header. */ - if (qlen < HFIXEDSZ || qlen >= (1 << 16)) { - callback(arg, ARES_EBADQUERY, 0, NULL, 0); - return ARES_EBADQUERY; - } if (ares__slist_len(channel->servers) == 0) { - callback(arg, ARES_ENOSERVER, 0, NULL, 0); + callback(arg, ARES_ENOSERVER, 0, NULL); return ARES_ENOSERVER; } /* Check query cache */ - status = ares_qcache_fetch(channel, &now, qbuf, qlen, &abuf, &alen); + status = ares_qcache_fetch(channel, &now, dnsrec, &dnsrec_resp); if (status != ARES_ENOTFOUND) { /* ARES_SUCCESS means we retrieved the cache, anything else is a critical * failure, all result in termination */ - callback(arg, (int)status, 0, abuf, (int)alen); - ares_free(abuf); + callback(arg, status, 0, dnsrec_resp); return status; } /* Allocate space for query and allocated fields. */ query = ares_malloc(sizeof(struct query)); if (!query) { - callback(arg, ARES_ENOMEM, 0, NULL, 0); + callback(arg, ARES_ENOMEM, 0, NULL); return ARES_ENOMEM; } memset(query, 0, sizeof(*query)); query->channel = channel; - query->qbuf = ares_malloc(qlen); - if (!query->qbuf) { + + status = ares_dns_write(dnsrec, &query->qbuf, &query->qlen); + if (status != ARES_SUCCESS) { ares_free(query); - callback(arg, ARES_ENOMEM, 0, NULL, 0); - return ARES_ENOMEM; + callback(arg, status, 0, NULL); + return status; } query->qid = id; @@ -103,8 +98,6 @@ ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, /* Ignore first 2 bytes, assign our own query id */ query->qbuf[0] = (unsigned char)((id >> 8) & 0xFF); query->qbuf[1] = (unsigned char)(id & 0xFF); - memcpy(query->qbuf + 2, qbuf + 2, qlen - 2); - query->qlen = qlen; /* Fill in query arguments. */ query->callback = callback; @@ -114,7 +107,8 @@ ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, query->try_count = 0; packetsz = (channel->flags & ARES_FLAG_EDNS) ? channel->ednspsz : PACKETSZ; - query->using_tcp = (channel->flags & ARES_FLAG_USEVC) || qlen > packetsz; + query->using_tcp = + (channel->flags & ARES_FLAG_USEVC) || query->qlen > packetsz; query->error_status = ARES_SUCCESS; query->timeouts = 0; @@ -127,7 +121,7 @@ ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, query->node_all_queries = ares__llist_insert_last(channel->all_queries, query); if (query->node_all_queries == NULL) { - callback(arg, ARES_ENOMEM, 0, NULL, 0); + callback(arg, ARES_ENOMEM, 0, NULL); ares__free_query(query); return ARES_ENOMEM; } @@ -136,7 +130,7 @@ ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, * responses quickly. */ if (!ares__htable_szvp_insert(channel->queries_by_qid, query->qid, query)) { - callback(arg, ARES_ENOMEM, 0, NULL, 0); + callback(arg, ARES_ENOMEM, 0, NULL); ares__free_query(query); return ARES_ENOMEM; } @@ -150,18 +144,60 @@ ares_status_t ares_send_ex(ares_channel_t *channel, const unsigned char *qbuf, return status; } +ares_status_t ares_send_dnsrec(ares_channel_t *channel, + const ares_dns_record_t *dnsrec, + ares_callback_dnsrec callback, void *arg, + unsigned short *qid) +{ + ares_status_t status; + + if (channel == NULL) { + return ARES_EFORMERR; + } + + ares__channel_lock(channel); + + status = ares_send_dnsrec_int(channel, dnsrec, callback, arg, qid); + + ares__channel_unlock(channel); + + return status; +} + void ares_send(ares_channel_t *channel, const unsigned char *qbuf, int qlen, ares_callback callback, void *arg) { + ares_dns_record_t *dnsrec = NULL; + ares_status_t status; + void *carg = NULL; + if (channel == NULL) { return; } - ares__channel_lock(channel); + /* Verify that the query is at least long enough to hold the header. */ + if (qlen < HFIXEDSZ || qlen >= (1 << 16)) { + callback(arg, ARES_EBADQUERY, 0, NULL, 0); + return; + } - ares_send_ex(channel, qbuf, (size_t)qlen, callback, arg, NULL); + status = ares_dns_parse(qbuf, (size_t)qlen, 0, &dnsrec); + if (status != ARES_SUCCESS) { + callback(arg, (int)status, 0, NULL, 0); + return; + } - ares__channel_unlock(channel); + carg = ares__dnsrec_convert_arg(callback, arg); + if (carg == NULL) { + status = ARES_ENOMEM; + ares_dns_record_destroy(dnsrec); + callback(arg, (int)status, 0, NULL, 0); + return; + } + + ares_send_dnsrec(channel, dnsrec, ares__dnsrec_convert_cb, carg, NULL); + + ares_dns_record_destroy(dnsrec); } size_t ares_queue_active_queries(ares_channel_t *channel) diff --git a/deps/cares/src/lib/ares_str.c b/deps/cares/src/lib/ares_str.c index 80660136dac8e1..5f25cfeaff041e 100644 --- a/deps/cares/src/lib/ares_str.c +++ b/deps/cares/src/lib/ares_str.c @@ -110,6 +110,54 @@ ares_bool_t ares_str_isnum(const char *str) return ARES_TRUE; } +void ares__str_rtrim(char *str) +{ + size_t len; + size_t i; + + if (str == NULL) { + return; + } + + len = ares_strlen(str); + for (i = len; i > 0; i--) { + if (!ares__isspace(str[i - 1])) { + break; + } + } + str[i] = 0; +} + +void ares__str_ltrim(char *str) +{ + size_t i; + size_t len; + + if (str == NULL) { + return; + } + + for (i = 0; str[i] != 0 && ares__isspace(str[i]); i++) { + /* Do nothing */ + } + + if (i == 0) { + return; + } + + len = ares_strlen(str); + if (i != len) { + memmove(str, str + i, len - i); + } + str[len - i] = 0; +} + +void ares__str_trim(char *str) +{ + ares__str_ltrim(str); + ares__str_rtrim(str); +} + /* tolower() is locale-specific. Use a lookup table fast conversion that only * operates on ASCII */ static const unsigned char ares__tolower_lookup[] = { @@ -151,3 +199,71 @@ ares_bool_t ares__memeq_ci(const unsigned char *ptr, const unsigned char *val, } return ARES_TRUE; } + +ares_bool_t ares__isspace(int ch) +{ + switch (ch) { + case '\r': + case '\t': + case ' ': + case '\v': + case '\f': + case '\n': + return ARES_TRUE; + default: + break; + } + return ARES_FALSE; +} + +ares_bool_t ares__isprint(int ch) +{ + if (ch >= 0x20 && ch <= 0x7E) { + return ARES_TRUE; + } + return ARES_FALSE; +} + +/* Character set allowed by hostnames. This is to include the normal + * domain name character set plus: + * - underscores which are used in SRV records. + * - Forward slashes such as are used for classless in-addr.arpa + * delegation (CNAMEs) + * - Asterisks may be used for wildcard domains in CNAMEs as seen in the + * real world. + * While RFC 2181 section 11 does state not to do validation, + * that applies to servers, not clients. Vulnerabilities have been + * reported when this validation is not performed. Security is more + * important than edge-case compatibility (which is probably invalid + * anyhow). */ +ares_bool_t ares__is_hostnamech(int ch) +{ + /* [A-Za-z0-9-*._/] + * Don't use isalnum() as it is locale-specific + */ + if (ch >= 'A' && ch <= 'Z') { + return ARES_TRUE; + } + if (ch >= 'a' && ch <= 'z') { + return ARES_TRUE; + } + if (ch >= '0' && ch <= '9') { + return ARES_TRUE; + } + if (ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '*') { + return ARES_TRUE; + } + + return ARES_FALSE; +} + +ares_bool_t ares__is_hostname(const char *str) +{ + size_t i; + for (i = 0; str[i] != 0; i++) { + if (!ares__is_hostnamech(str[i])) { + return ARES_FALSE; + } + } + return ARES_TRUE; +} diff --git a/deps/cares/src/lib/ares_str.h b/deps/cares/src/lib/ares_str.h index 2bf32d0d253da7..8d869073d8153c 100644 --- a/deps/cares/src/lib/ares_str.h +++ b/deps/cares/src/lib/ares_str.h @@ -24,8 +24,8 @@ * * SPDX-License-Identifier: MIT */ -#ifndef HEADER_CARES_STRDUP_H -#define HEADER_CARES_STRDUP_H +#ifndef __ARES_STR_H +#define __ARES_STR_H #include "ares_setup.h" #include "ares.h" @@ -48,8 +48,19 @@ size_t ares_strcpy(char *dest, const char *src, size_t dest_size); ares_bool_t ares_str_isnum(const char *str); +void ares__str_ltrim(char *str); +void ares__str_rtrim(char *str); +void ares__str_trim(char *str); + unsigned char ares__tolower(unsigned char c); ares_bool_t ares__memeq_ci(const unsigned char *ptr, const unsigned char *val, size_t len); -#endif /* HEADER_CARES_STRDUP_H */ +ares_bool_t ares__isspace(int ch); +ares_bool_t ares__isprint(int ch); +ares_bool_t ares__is_hostnamech(int ch); + +ares_bool_t ares__is_hostname(const char *str); + + +#endif /* __ARES_STR_H */ diff --git a/deps/cares/src/lib/ares_strsplit.c b/deps/cares/src/lib/ares_strsplit.c index 5ec615c76482ed..395bf1ebb9a5ec 100644 --- a/deps/cares/src/lib/ares_strsplit.c +++ b/deps/cares/src/lib/ares_strsplit.c @@ -94,7 +94,7 @@ char **ares__strsplit(const char *in, const char *delms, size_t *num_elm) status = ares__buf_split( buf, (const unsigned char *)delms, ares_strlen(delms), - ARES_BUF_SPLIT_NO_DUPLICATES | ARES_BUF_SPLIT_CASE_INSENSITIVE, &llist); + ARES_BUF_SPLIT_NO_DUPLICATES | ARES_BUF_SPLIT_CASE_INSENSITIVE, 0, &llist); if (status != ARES_SUCCESS) { goto done; } diff --git a/deps/cares/src/lib/ares_sysconfig.c b/deps/cares/src/lib/ares_sysconfig.c index 825008b7b8a543..474534512af191 100644 --- a/deps/cares/src/lib/ares_sysconfig.c +++ b/deps/cares/src/lib/ares_sysconfig.c @@ -954,7 +954,7 @@ static ares_status_t ares__init_sysconfig_libresolv(ares_sysconfig_t *sysconfig) } } - if (res.ndots > 0) { + if (res.ndots >= 0) { sysconfig->ndots = (size_t)res.ndots; } if (res.retry > 0) { @@ -1059,6 +1059,10 @@ static ares_status_t ares_sysconfig_apply(ares_channel_t *channel, channel->rotate = sysconfig->rotate; } + if (sysconfig->usevc) { + channel->flags |= ARES_FLAG_USEVC; + } + return ARES_SUCCESS; } diff --git a/deps/cares/src/lib/ares_sysconfig_files.c b/deps/cares/src/lib/ares_sysconfig_files.c index 9802c7e54a5419..557888bc740a39 100644 --- a/deps/cares/src/lib/ares_sysconfig_files.c +++ b/deps/cares/src/lib/ares_sysconfig_files.c @@ -134,7 +134,7 @@ static ares_status_t parse_sort(ares__buf_t *buf, struct apattern *pat) ares__buf_tag(buf); /* Consume ip address */ - if (ares__buf_consume_charset(buf, ip_charset, sizeof(ip_charset)) == 0) { + if (ares__buf_consume_charset(buf, ip_charset, sizeof(ip_charset) - 1) == 0) { return ARES_EBADSTR; } @@ -162,8 +162,8 @@ static ares_status_t parse_sort(ares__buf_t *buf, struct apattern *pat) ares__buf_tag(buf); /* Consume mask */ - if (ares__buf_consume_charset(buf, ipv4_charset, sizeof(ipv4_charset)) == - 0) { + if (ares__buf_consume_charset(buf, ipv4_charset, + sizeof(ipv4_charset) - 1) == 0) { return ARES_EBADSTR; } @@ -241,7 +241,7 @@ ares_status_t ares__parse_sortlist(struct apattern **sortlist, size_t *nsort, /* Split on space or semicolon */ status = ares__buf_split(buf, (const unsigned char *)" ;", 2, - ARES_BUF_SPLIT_NONE, &list); + ARES_BUF_SPLIT_NONE, 0, &list); if (status != ARES_SUCCESS) { goto done; } @@ -282,7 +282,8 @@ ares_status_t ares__parse_sortlist(struct apattern **sortlist, size_t *nsort, return status; } -static ares_status_t config_search(ares_sysconfig_t *sysconfig, const char *str) +static ares_status_t config_search(ares_sysconfig_t *sysconfig, const char *str, + size_t max_domains) { if (sysconfig->domains && sysconfig->ndomains > 0) { /* if we already have some domains present, free them first */ @@ -296,410 +297,515 @@ static ares_status_t config_search(ares_sysconfig_t *sysconfig, const char *str) return ARES_ENOMEM; } + /* Truncate if necessary */ + if (max_domains && sysconfig->ndomains > max_domains) { + size_t i; + for (i = max_domains; i < sysconfig->ndomains; i++) { + ares_free(sysconfig->domains[i]); + sysconfig->domains[i] = NULL; + } + sysconfig->ndomains = max_domains; + } + return ARES_SUCCESS; } -static ares_status_t config_domain(ares_sysconfig_t *sysconfig, char *str) +static ares_status_t buf_fetch_string(ares__buf_t *buf, char *str, + size_t str_len) { - char *q; - - /* Set a single search domain. */ - q = str; - while (*q && !ISSPACE(*q)) { - q++; - } - *q = '\0'; + ares_status_t status; + ares__buf_tag(buf); + ares__buf_consume(buf, ares__buf_len(buf)); - return config_search(sysconfig, str); + status = ares__buf_tag_fetch_string(buf, str, str_len); + return status; } -static ares_status_t config_lookup(ares_sysconfig_t *sysconfig, const char *str, - const char *bindch, const char *altbindch, - const char *filech) +static ares_status_t config_lookup(ares_sysconfig_t *sysconfig, + ares__buf_t *buf, const char *separators) { - char lookups[3]; - char *l; - const char *p; - ares_bool_t found; - - if (altbindch == NULL) { - altbindch = bindch; + ares_status_t status; + char lookupstr[32]; + size_t lookupstr_cnt = 0; + ares__llist_t *lookups = NULL; + ares__llist_node_t *node; + size_t separators_len = ares_strlen(separators); + + status = ares__buf_split(buf, (const unsigned char *)separators, + separators_len, ARES_BUF_SPLIT_TRIM, 0, &lookups); + if (status != ARES_SUCCESS) { + goto done; } - /* Set the lookup order. Only the first letter of each work - * is relevant, and it has to be "b" for DNS or "f" for the - * host file. Ignore everything else. - */ - l = lookups; - p = str; - found = ARES_FALSE; - while (*p) { - if ((*p == *bindch || *p == *altbindch || *p == *filech) && - l < lookups + 2) { - if (*p == *bindch || *p == *altbindch) { - *l++ = 'b'; - } else { - *l++ = 'f'; - } - found = ARES_TRUE; + memset(lookupstr, 0, sizeof(lookupstr)); + + for (node = ares__llist_node_first(lookups); node != NULL; + node = ares__llist_node_next(node)) { + char value[128]; + char ch; + ares__buf_t *valbuf = ares__llist_node_val(node); + + status = buf_fetch_string(valbuf, value, sizeof(value)); + if (status != ARES_SUCCESS) { + continue; } - while (*p && !ISSPACE(*p) && (*p != ',')) { - p++; + + if (strcasecmp(value, "dns") == 0 || strcasecmp(value, "bind") == 0 || + strcasecmp(value, "resolv") == 0 || strcasecmp(value, "resolve") == 0) { + ch = 'b'; + } else if (strcasecmp(value, "files") == 0 || + strcasecmp(value, "file") == 0 || + strcasecmp(value, "local") == 0) { + ch = 'f'; + } else { + continue; } - while (*p && (ISSPACE(*p) || (*p == ','))) { - p++; + + /* Look for a duplicate and ignore */ + if (memchr(lookupstr, ch, lookupstr_cnt) == NULL) { + lookupstr[lookupstr_cnt++] = ch; } } - if (!found) { - return ARES_ENOTINITIALIZED; + + if (lookupstr_cnt) { + ares_free(sysconfig->lookups); + sysconfig->lookups = ares_strdup(lookupstr); + if (sysconfig->lookups == NULL) { + return ARES_ENOMEM; + } } - *l = '\0'; - ares_free(sysconfig->lookups); - sysconfig->lookups = ares_strdup(lookups); - if (sysconfig->lookups == NULL) { - return ARES_ENOMEM; + status = ARES_SUCCESS; + +done: + if (status != ARES_ENOMEM) { + status = ARES_SUCCESS; } - return ARES_SUCCESS; + ares__llist_destroy(lookups); + return status; } -static const char *try_option(const char *p, const char *q, const char *opt) +static ares_status_t process_option(ares_sysconfig_t *sysconfig, + ares__buf_t *option) { - size_t len = ares_strlen(opt); - return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL; + ares__llist_t *kv = NULL; + char key[32] = ""; + char val[32] = ""; + unsigned int valint = 0; + ares_status_t status; + + /* Split on : */ + status = ares__buf_split(option, (const unsigned char *)":", 1, + ARES_BUF_SPLIT_TRIM, 2, &kv); + if (status != ARES_SUCCESS) { + goto done; + } + + status = buf_fetch_string(ares__llist_first_val(kv), key, sizeof(key)); + if (status != ARES_SUCCESS) { + goto done; + } + if (ares__llist_len(kv) == 2) { + status = buf_fetch_string(ares__llist_last_val(kv), val, sizeof(val)); + if (status != ARES_SUCCESS) { + goto done; + } + valint = (unsigned int)strtoul(val, NULL, 10); + } + + if (strcmp(key, "ndots") == 0) { + sysconfig->ndots = valint; + } else if (strcmp(key, "retrans") == 0 || strcmp(key, "timeout") == 0) { + if (valint == 0) { + return ARES_EFORMERR; + } + sysconfig->timeout_ms = valint * 1000; + } else if (strcmp(key, "retry") == 0 || strcmp(key, "attempts") == 0) { + if (valint == 0) { + return ARES_EFORMERR; + } + sysconfig->tries = valint; + } else if (strcmp(key, "rotate") == 0) { + sysconfig->rotate = ARES_TRUE; + } else if (strcmp(key, "use-vc") == 0 || strcmp(key, "usevc") == 0) { + sysconfig->usevc = ARES_TRUE; + } + +done: + ares__llist_destroy(kv); + return status; } static ares_status_t set_options(ares_sysconfig_t *sysconfig, const char *str) { - const char *p; - const char *q; - const char *val; + ares__buf_t *buf = NULL; + ares__llist_t *options = NULL; + ares_status_t status; + ares__llist_node_t *node; - if (str == NULL) { - return ARES_SUCCESS; + buf = ares__buf_create_const((const unsigned char *)str, ares_strlen(str)); + if (buf == NULL) { + return ARES_ENOMEM; } - p = str; - while (*p) { - q = p; - while (*q && !ISSPACE(*q)) { - q++; - } - val = try_option(p, q, "ndots:"); - if (val) { - sysconfig->ndots = strtoul(val, NULL, 10); - } + status = ares__buf_split(buf, (const unsigned char *)" \t", 2, + ARES_BUF_SPLIT_TRIM, 0, &options); + if (status != ARES_SUCCESS) { + goto done; + } - // Outdated option. - val = try_option(p, q, "retrans:"); - if (val) { - sysconfig->timeout_ms = strtoul(val, NULL, 10); - } + for (node = ares__llist_node_first(options); node != NULL; + node = ares__llist_node_next(node)) { + ares__buf_t *valbuf = ares__llist_node_val(node); - val = try_option(p, q, "timeout:"); - if (val) { - sysconfig->timeout_ms = strtoul(val, NULL, 10) * 1000; + status = process_option(sysconfig, valbuf); + /* Out of memory is the only fatal condition */ + if (status == ARES_ENOMEM) { + goto done; } + } - // Outdated option. - val = try_option(p, q, "retry:"); - if (val) { - sysconfig->tries = strtoul(val, NULL, 10); - } + status = ARES_SUCCESS; - val = try_option(p, q, "attempts:"); - if (val) { - sysconfig->tries = strtoul(val, NULL, 10); - } +done: + ares__llist_destroy(options); + ares__buf_destroy(buf); + return status; +} - val = try_option(p, q, "rotate"); - if (val) { - sysconfig->rotate = ARES_TRUE; +ares_status_t ares__init_by_environment(ares_sysconfig_t *sysconfig) +{ + const char *localdomain; + const char *res_options; + ares_status_t status; + + localdomain = getenv("LOCALDOMAIN"); + if (localdomain) { + char *temp = ares_strdup(localdomain); + if (temp == NULL) { + return ARES_ENOMEM; } + status = config_search(sysconfig, temp, 1); + ares_free(temp); + if (status != ARES_SUCCESS) { + return status; + } + } - p = q; - while (ISSPACE(*p)) { - p++; + res_options = getenv("RES_OPTIONS"); + if (res_options) { + status = set_options(sysconfig, res_options); + if (status != ARES_SUCCESS) { + return status; } } return ARES_SUCCESS; } -static char *try_config(char *s, const char *opt, char scc) +/* Configuration Files: + * /etc/resolv.conf + * - All Unix-like systems + * - Comments start with ; or # + * - Lines have a keyword followed by a value that is interpreted specific + * to the keyword: + * - Keywords: + * - nameserver - IP address of nameserver with optional port (using a : + * prefix). If using an ipv6 address and specifying a port, the ipv6 + * address must be encapsulated in brackets. For link-local ipv6 + * addresses, the interface can also be specified with a % prefix. e.g.: + * "nameserver [fe80::1]:1234%iface" + * This keyword may be specified multiple times. + * - search - whitespace separated list of domains + * - domain - obsolete, same as search except only a single domain + * - lookup / hostresorder - local, bind, file, files + * - sortlist - whitespace separated ip-address/netmask pairs + * - options - options controlling resolver variables + * - ndots:n - set ndots option + * - timeout:n (retrans:n) - timeout per query attempt in seconds + * - attempts:n (retry:n) - number of times resolver will send query + * - rotate - round-robin selection of name servers + * - use-vc / usevc - force tcp + * /etc/nsswitch.conf + * - Modern Linux, FreeBSD, HP-UX, Solaris + * - Search order set via: + * "hosts: files dns mdns4_minimal mdns4" + * - files is /etc/hosts + * - dns is dns + * - mdns4_minimal does mdns only if ending in .local + * - mdns4 does not limit to domains ending in .local + * /etc/netsvc.conf + * - AIX + * - Search order set via: + * "hosts = local , bind" + * - bind is dns + * - local is /etc/hosts + * /etc/svc.conf + * - Tru64 + * - Same format as /etc/netsvc.conf + * /etc/host.conf + * - Early FreeBSD, Early Linux + * - Not worth supporting, format varied based on system, FreeBSD used + * just a line per search order, Linux used "order " and a comma + * delimited list of "bind" and "hosts" + */ + + +/* This function will only return ARES_SUCCESS or ARES_ENOMEM. Any other + * conditions are ignored. Users may mess up config files, but we want to + * process anything we can. */ +static ares_status_t parse_resolvconf_line(ares_sysconfig_t *sysconfig, + ares__buf_t *line) { - size_t len; - char *p; - char *q; + char option[32]; + char value[512]; + ares_status_t status = ARES_SUCCESS; - if (!s || !opt) { - /* no line or no option */ - return NULL; /* LCOV_EXCL_LINE */ + /* Ignore lines beginning with a comment */ + if (ares__buf_begins_with(line, (const unsigned char *)"#", 1) || + ares__buf_begins_with(line, (const unsigned char *)";", 1)) { + return ARES_SUCCESS; } - /* Hash '#' character is always used as primary comment char, additionally - a not-NUL secondary comment char will be considered when specified. */ + ares__buf_tag(line); - /* trim line comment */ - p = s; - if (scc) { - while (*p && (*p != '#') && (*p != scc)) { - p++; - } - } else { - while (*p && (*p != '#')) { - p++; - } + /* Shouldn't be possible, but if it happens, ignore the line. */ + if (ares__buf_consume_nonwhitespace(line) == 0) { + return ARES_SUCCESS; } - *p = '\0'; - /* trim trailing whitespace */ - q = p - 1; - while ((q >= s) && ISSPACE(*q)) { - q--; + status = ares__buf_tag_fetch_string(line, option, sizeof(option)); + if (status != ARES_SUCCESS) { + return ARES_SUCCESS; } - *++q = '\0'; - /* skip leading whitespace */ - p = s; - while (*p && ISSPACE(*p)) { - p++; - } + ares__buf_consume_whitespace(line, ARES_TRUE); - if (!*p) { - /* empty line */ - return NULL; + status = buf_fetch_string(line, value, sizeof(value)); + if (status != ARES_SUCCESS) { + return ARES_SUCCESS; } - if ((len = ares_strlen(opt)) == 0) { - /* empty option */ - return NULL; /* LCOV_EXCL_LINE */ + ares__str_trim(value); + if (*value == 0) { + return ARES_SUCCESS; } - if (strncmp(p, opt, len) != 0) { - /* line and option do not match */ - return NULL; + /* At this point we have a string option and a string value, both trimmed + * of leading and trailing whitespace. Lets try to evaluate them */ + if (strcmp(option, "domain") == 0) { + /* Domain is legacy, don't overwrite an existing config set by search */ + if (sysconfig->domains == NULL) { + status = config_search(sysconfig, value, 1); + } + } else if (strcmp(option, "lookup") == 0 || + strcmp(option, "hostresorder") == 0) { + ares__buf_tag_rollback(line); + status = config_lookup(sysconfig, line, " \t"); + } else if (strcmp(option, "search") == 0) { + status = config_search(sysconfig, value, 0); + } else if (strcmp(option, "nameserver") == 0) { + status = + ares__sconfig_append_fromstr(&sysconfig->sconfig, value, ARES_TRUE); + } else if (strcmp(option, "sortlist") == 0) { + /* Ignore all failures except ENOMEM. If the sysadmin set a bad + * sortlist, just ignore the sortlist, don't cause an inoperable + * channel */ + status = + ares__parse_sortlist(&sysconfig->sortlist, &sysconfig->nsortlist, value); + if (status != ARES_ENOMEM) { + status = ARES_SUCCESS; + } + } else if (strcmp(option, "options") == 0) { + status = set_options(sysconfig, value); } - /* skip over given option name */ - p += len; + return status; +} + +/* This function will only return ARES_SUCCESS or ARES_ENOMEM. Any other + * conditions are ignored. Users may mess up config files, but we want to + * process anything we can. */ +static ares_status_t parse_nsswitch_line(ares_sysconfig_t *sysconfig, + ares__buf_t *line) +{ + char option[32]; + ares__buf_t *buf; + ares_status_t status = ARES_SUCCESS; + ares__llist_t *sects = NULL; - if (!*p) { - /* no option value */ - return NULL; /* LCOV_EXCL_LINE */ + /* Ignore lines beginning with a comment */ + if (ares__buf_begins_with(line, (const unsigned char *)"#", 1)) { + return ARES_SUCCESS; } - if ((opt[len - 1] != ':') && (opt[len - 1] != '=') && !ISSPACE(*p)) { - /* whitespace between option name and value is mandatory - for given option names which do not end with ':' or '=' */ - return NULL; + /* database : values (space delimited) */ + status = ares__buf_split(line, (const unsigned char *)":", 1, + ARES_BUF_SPLIT_TRIM, 2, §s); + + if (status != ARES_SUCCESS || ares__llist_len(sects) != 2) { + goto done; } - /* skip over whitespace */ - while (*p && ISSPACE(*p)) { - p++; + buf = ares__llist_first_val(sects); + status = buf_fetch_string(buf, option, sizeof(option)); + if (status != ARES_SUCCESS) { + goto done; } - if (!*p) { - /* no option value */ - return NULL; + /* Only support "hosts:" */ + if (strcmp(option, "hosts") != 0) { + goto done; } - /* return pointer to option value */ - return p; + /* Values are space separated */ + buf = ares__llist_last_val(sects); + status = config_lookup(sysconfig, buf, " \t"); + +done: + ares__llist_destroy(sects); + if (status != ARES_ENOMEM) { + status = ARES_SUCCESS; + } + return status; } -ares_status_t ares__init_by_environment(ares_sysconfig_t *sysconfig) +/* This function will only return ARES_SUCCESS or ARES_ENOMEM. Any other + * conditions are ignored. Users may mess up config files, but we want to + * process anything we can. */ +static ares_status_t parse_svcconf_line(ares_sysconfig_t *sysconfig, + ares__buf_t *line) { - const char *localdomain; - const char *res_options; - ares_status_t status; + char option[32]; + ares__buf_t *buf; + ares_status_t status = ARES_SUCCESS; + ares__llist_t *sects = NULL; - localdomain = getenv("LOCALDOMAIN"); - if (localdomain) { - char *temp = ares_strdup(localdomain); - if (temp == NULL) { - return ARES_ENOMEM; - } - status = config_domain(sysconfig, temp); - ares_free(temp); - if (status != ARES_SUCCESS) { - return status; - } + /* Ignore lines beginning with a comment */ + if (ares__buf_begins_with(line, (const unsigned char *)"#", 1)) { + return ARES_SUCCESS; } - res_options = getenv("RES_OPTIONS"); - if (res_options) { - status = set_options(sysconfig, res_options); - if (status != ARES_SUCCESS) { - return status; - } + /* database = values (comma delimited)*/ + status = ares__buf_split(line, (const unsigned char *)"=", 1, + ARES_BUF_SPLIT_TRIM, 2, §s); + + if (status != ARES_SUCCESS || ares__llist_len(sects) != 2) { + goto done; } - return ARES_SUCCESS; + buf = ares__llist_first_val(sects); + status = buf_fetch_string(buf, option, sizeof(option)); + if (status != ARES_SUCCESS) { + goto done; + } + + /* Only support "hosts=" */ + if (strcmp(option, "hosts") != 0) { + goto done; + } + + /* Values are comma separated */ + buf = ares__llist_last_val(sects); + status = config_lookup(sysconfig, buf, ","); + +done: + ares__llist_destroy(sects); + if (status != ARES_ENOMEM) { + status = ARES_SUCCESS; + } + return status; } -ares_status_t ares__init_sysconfig_files(const ares_channel_t *channel, - ares_sysconfig_t *sysconfig) +typedef ares_status_t (*line_callback_t)(ares_sysconfig_t *sysconfig, + ares__buf_t *line); + +/* Should only return: + * ARES_ENOTFOUND - file not found + * ARES_EFILE - error reading file (perms) + * ARES_ENOMEM - out of memory + * ARES_SUCCESS - file processed, doesn't necessarily mean it was a good + * file, but we're not erroring out if we can't parse + * something (or anything at all) */ +static ares_status_t process_config_lines(const char *filename, + ares_sysconfig_t *sysconfig, + line_callback_t cb) { - char *p; - FILE *fp = NULL; - char *line = NULL; - size_t linesize = 0; - int error; - const char *resolvconf_path; - ares_status_t status = ARES_SUCCESS; + ares_status_t status = ARES_SUCCESS; + ares__llist_node_t *node; + ares__llist_t *lines = NULL; + ares__buf_t *buf = NULL; - /* Support path for resolvconf filename set by ares_init_options */ - if (channel->resolvconf_path) { - resolvconf_path = channel->resolvconf_path; - } else { - resolvconf_path = PATH_RESOLV_CONF; - } - - fp = fopen(resolvconf_path, "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { - if ((p = try_config(line, "domain", ';'))) { - status = config_domain(sysconfig, p); - } else if ((p = try_config(line, "lookup", ';'))) { - status = config_lookup(sysconfig, p, "bind", NULL, "file"); - } else if ((p = try_config(line, "search", ';'))) { - status = config_search(sysconfig, p); - } else if ((p = try_config(line, "nameserver", ';'))) { - status = - ares__sconfig_append_fromstr(&sysconfig->sconfig, p, ARES_TRUE); - } else if ((p = try_config(line, "sortlist", ';'))) { - /* Ignore all failures except ENOMEM. If the sysadmin set a bad - * sortlist, just ignore the sortlist, don't cause an inoperable - * channel */ - status = - ares__parse_sortlist(&sysconfig->sortlist, &sysconfig->nsortlist, p); - if (status != ARES_ENOMEM) { - status = ARES_SUCCESS; - } - } else if ((p = try_config(line, "options", ';'))) { - status = set_options(sysconfig, p); - } else { - status = ARES_SUCCESS; - } - if (status != ARES_SUCCESS) { - fclose(fp); - goto done; - } - } - fclose(fp); + buf = ares__buf_create(); + if (buf == NULL) { + status = ARES_ENOMEM; + goto done; + } - if (status != ARES_EOF) { - goto done; - } - } else { - error = ERRNO; - switch (error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, - strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF)); - status = ARES_EFILE; - goto done; - } + status = ares__buf_load_file(filename, buf); + if (status != ARES_SUCCESS) { + goto done; } + status = ares__buf_split(buf, (const unsigned char *)"\n", 1, + ARES_BUF_SPLIT_TRIM, 0, &lines); + if (status != ARES_SUCCESS) { + goto done; + } - /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */ - fp = fopen("/etc/nsswitch.conf", "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { - if ((p = try_config(line, "hosts:", '\0'))) { - (void)config_lookup(sysconfig, p, "dns", "resolve", "files"); - } - } - fclose(fp); - if (status != ARES_EOF) { + for (node = ares__llist_node_first(lines); node != NULL; + node = ares__llist_node_next(node)) { + ares__buf_t *line = ares__llist_node_val(node); + + status = cb(sysconfig, line); + if (status != ARES_SUCCESS) { goto done; } - } else { - error = ERRNO; - switch (error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, - strerror(error))); - DEBUGF( - fprintf(stderr, "Error opening file: %s\n", "/etc/nsswitch.conf")); - break; - } - /* ignore error, maybe we will get luck in next if clause */ } +done: + ares__buf_destroy(buf); + ares__llist_destroy(lines); - /* Linux / GNU libc 2.x and possibly others have host.conf */ - fp = fopen("/etc/host.conf", "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { - if ((p = try_config(line, "order", '\0'))) { - /* ignore errors */ - (void)config_lookup(sysconfig, p, "bind", NULL, "hosts"); - } - } - fclose(fp); - if (status != ARES_EOF) { - goto done; - } - } else { - error = ERRNO; - switch (error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, - strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/host.conf")); - break; - } + return status; +} + +ares_status_t ares__init_sysconfig_files(const ares_channel_t *channel, + ares_sysconfig_t *sysconfig) +{ + ares_status_t status = ARES_SUCCESS; + + /* Resolv.conf */ + status = process_config_lines((channel->resolvconf_path != NULL) + ? channel->resolvconf_path + : PATH_RESOLV_CONF, + sysconfig, parse_resolvconf_line); + if (status != ARES_SUCCESS && status != ARES_ENOTFOUND) { + goto done; + } - /* ignore error, maybe we will get luck in next if clause */ + /* Nsswitch.conf */ + status = + process_config_lines("/etc/nsswitch.conf", sysconfig, parse_nsswitch_line); + if (status != ARES_SUCCESS && status != ARES_ENOTFOUND) { + goto done; } + /* netsvc.conf */ + status = + process_config_lines("/etc/netsvc.conf", sysconfig, parse_svcconf_line); + if (status != ARES_SUCCESS && status != ARES_ENOTFOUND) { + goto done; + } - /* Tru64 uses /etc/svc.conf */ - fp = fopen("/etc/svc.conf", "r"); - if (fp) { - while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) { - if ((p = try_config(line, "hosts=", '\0'))) { - /* ignore errors */ - (void)config_lookup(sysconfig, p, "bind", NULL, "local"); - } - } - fclose(fp); - if (status != ARES_EOF) { - goto done; - } - } else { - error = ERRNO; - switch (error) { - case ENOENT: - case ESRCH: - break; - default: - DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error, - strerror(error))); - DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf")); - break; - } - /* ignore error */ + /* svc.conf */ + status = process_config_lines("/etc/svc.conf", sysconfig, parse_svcconf_line); + if (status != ARES_SUCCESS && status != ARES_ENOTFOUND) { + goto done; } status = ARES_SUCCESS; done: - ares_free(line); - return status; } diff --git a/deps/cares/src/lib/ares_update_servers.c b/deps/cares/src/lib/ares_update_servers.c index dd24fbfdd4675c..fce791476327c3 100644 --- a/deps/cares/src/lib/ares_update_servers.c +++ b/deps/cares/src/lib/ares_update_servers.c @@ -266,8 +266,8 @@ static ares_status_t parse_nameserver(ares__buf_t *buf, ares_sconfig_t *sconfig) } else { /* IPv6 */ const unsigned char ipv6_charset[] = "ABCDEFabcdef0123456789.:"; - if (ares__buf_consume_charset(buf, ipv6_charset, sizeof(ipv6_charset)) == - 0) { + if (ares__buf_consume_charset(buf, ipv6_charset, + sizeof(ipv6_charset) - 1) == 0) { return ARES_EBADSTR; } } @@ -318,8 +318,8 @@ static ares_status_t parse_nameserver(ares__buf_t *buf, ares_sconfig_t *sconfig) ares__buf_tag(buf); - if (ares__buf_consume_charset(buf, iface_charset, sizeof(iface_charset)) == - 0) { + if (ares__buf_consume_charset(buf, iface_charset, + sizeof(iface_charset) - 1) == 0) { return ARES_EBADSTR; } @@ -463,7 +463,7 @@ ares_status_t ares__sconfig_append_fromstr(ares__llist_t **sconfig, } status = ares__buf_split(buf, (const unsigned char *)" ,", 2, - ARES_BUF_SPLIT_NONE, &list); + ARES_BUF_SPLIT_NONE, 0, &list); if (status != ARES_SUCCESS) { goto done; } @@ -1080,7 +1080,7 @@ static ares_status_t set_servers_csv(ares_channel_t *channel, const char *_csv) if (ares_strlen(_csv) == 0) { /* blank all servers */ - return (ares_status_t)ares_set_servers_ports(channel, NULL); + return ares__servers_update(channel, NULL, ARES_TRUE); } status = ares__sconfig_append_fromstr(&slist, _csv, ARES_FALSE); diff --git a/deps/cares/src/lib/setup_once.h b/deps/cares/src/lib/setup_once.h index 8341b348e7a9e0..a6168c9aed5365 100644 --- a/deps/cares/src/lib/setup_once.h +++ b/deps/cares/src/lib/setup_once.h @@ -274,7 +274,7 @@ Error Missing_definition_of_macro_sread #define ISPRINT(x) (isprint((int)((unsigned char)x))) #define ISUPPER(x) (isupper((int)((unsigned char)x))) #define ISLOWER(x) (islower((int)((unsigned char)x))) -#define ISASCII(x) (isascii((int)((unsigned char)x))) +#define ISASCII(x) (((unsigned char)x) <= 127 ? 1 : 0) #define ISBLANK(x) \ (int)((((unsigned char)x) == ' ') || (((unsigned char)x) == '\t')) diff --git a/deps/cares/src/tools/CMakeLists.txt b/deps/cares/src/tools/CMakeLists.txt index 13aefe135e9105..fb795a91741aaf 100644 --- a/deps/cares/src/tools/CMakeLists.txt +++ b/deps/cares/src/tools/CMakeLists.txt @@ -19,7 +19,7 @@ IF (CARES_BUILD_TOOLS) C_STANDARD 90 ) - TARGET_COMPILE_DEFINITIONS (ahost PRIVATE HAVE_CONFIG_H=1) + TARGET_COMPILE_DEFINITIONS (ahost PRIVATE HAVE_CONFIG_H=1 CARES_NO_DEPRECATED) TARGET_LINK_LIBRARIES (ahost PRIVATE ${PROJECT_NAME}) IF (CARES_INSTALL) INSTALL (TARGETS ahost COMPONENT Tools ${TARGETS_INST_DEST}) @@ -40,7 +40,7 @@ IF (CARES_BUILD_TOOLS) C_STANDARD 90 ) - TARGET_COMPILE_DEFINITIONS (adig PRIVATE HAVE_CONFIG_H=1) + TARGET_COMPILE_DEFINITIONS (adig PRIVATE HAVE_CONFIG_H=1 CARES_NO_DEPRECATED) TARGET_LINK_LIBRARIES (adig PRIVATE ${PROJECT_NAME}) IF (CARES_INSTALL) INSTALL (TARGETS adig COMPONENT Tools ${TARGETS_INST_DEST}) diff --git a/deps/cares/src/tools/Makefile.am b/deps/cares/src/tools/Makefile.am index 729658d79a76da..ba7a672f89faf5 100644 --- a/deps/cares/src/tools/Makefile.am +++ b/deps/cares/src/tools/Makefile.am @@ -15,7 +15,8 @@ noinst_PROGRAMS =$(PROGS) AM_CPPFLAGS += -I$(top_builddir)/include \ -I$(top_builddir)/src/lib \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/src/lib + -I$(top_srcdir)/src/lib \ + -DCARES_NO_DEPRECATED include Makefile.inc diff --git a/deps/cares/src/tools/Makefile.in b/deps/cares/src/tools/Makefile.in index f0602fe172fdbb..0b7a310baaab5d 100644 --- a/deps/cares/src/tools/Makefile.in +++ b/deps/cares/src/tools/Makefile.in @@ -228,7 +228,7 @@ AM_CFLAGS = @AM_CFLAGS@ # might possibly already be installed in the system. AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_builddir)/include \ -I$(top_builddir)/src/lib -I$(top_srcdir)/include \ - -I$(top_srcdir)/src/lib + -I$(top_srcdir)/src/lib -DCARES_NO_DEPRECATED AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ @@ -310,6 +310,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@