aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-contrib <robot-contrib@yandex-team.com>2024-08-07 11:23:56 +0300
committerrobot-contrib <robot-contrib@yandex-team.com>2024-08-07 13:04:06 +0300
commit2137507f9ec8a5b7c48cc521943ffa038262a679 (patch)
tree1032db05350b9a3810833ce29ab3d238d34e256c
parenta159873112d46d9c8a1822e0e61857bb939803c2 (diff)
downloadydb-2137507f9ec8a5b7c48cc521943ffa038262a679.tar.gz
Update contrib/libs/c-ares to 1.33.0
023d295bf695dc8b9df70e1ee966dc423cdf62ca
-rw-r--r--contrib/libs/c-ares/CHANGES7
-rw-r--r--contrib/libs/c-ares/CHANGES.01218
-rw-r--r--contrib/libs/c-ares/INSTALL.md57
-rw-r--r--contrib/libs/c-ares/LICENSE.md2
-rw-r--r--contrib/libs/c-ares/NEWS21
-rw-r--r--contrib/libs/c-ares/README.cares15
-rw-r--r--contrib/libs/c-ares/README.md56
-rw-r--r--contrib/libs/c-ares/RELEASE-NOTES.md38
-rw-r--r--contrib/libs/c-ares/RELEASE-PROCEDURE.md81
-rw-r--r--contrib/libs/c-ares/include/ares.h77
-rw-r--r--contrib/libs/c-ares/include/ares_build-linux.h10
-rw-r--r--contrib/libs/c-ares/include/ares_dns_record.h95
-rw-r--r--contrib/libs/c-ares/include/ares_rules.h133
-rw-r--r--contrib/libs/c-ares/include/ares_version.h13
-rw-r--r--contrib/libs/c-ares/src/lib/ares__addrinfo2hostent.c70
-rw-r--r--contrib/libs/c-ares/src/lib/ares__addrinfo_localhost.c35
-rw-r--r--contrib/libs/c-ares/src/lib/ares__close_sockets.c111
-rw-r--r--contrib/libs/c-ares/src/lib/ares__hosts_file.c219
-rw-r--r--contrib/libs/c-ares/src/lib/ares__parse_into_addrinfo.c26
-rw-r--r--contrib/libs/c-ares/src/lib/ares__socket.c606
-rw-r--r--contrib/libs/c-ares/src/lib/ares__sortaddrinfo.c14
-rw-r--r--contrib/libs/c-ares/src/lib/ares_android.c33
-rw-r--r--contrib/libs/c-ares/src/lib/ares_cancel.c18
-rw-r--r--contrib/libs/c-ares/src/lib/ares_config-linux.h184
-rw-r--r--contrib/libs/c-ares/src/lib/ares_cookie.c459
-rw-r--r--contrib/libs/c-ares/src/lib/ares_data.c8
-rw-r--r--contrib/libs/c-ares/src/lib/ares_destroy.c34
-rw-r--r--contrib/libs/c-ares/src/lib/ares_event_win32.c601
-rw-r--r--contrib/libs/c-ares/src/lib/ares_free_hostent.c6
-rw-r--r--contrib/libs/c-ares/src/lib/ares_free_string.c3
-rw-r--r--contrib/libs/c-ares/src/lib/ares_freeaddrinfo.c5
-rw-r--r--contrib/libs/c-ares/src/lib/ares_getaddrinfo.c41
-rw-r--r--contrib/libs/c-ares/src/lib/ares_getenv.c2
-rw-r--r--contrib/libs/c-ares/src/lib/ares_getenv.h2
-rw-r--r--contrib/libs/c-ares/src/lib/ares_gethostbyaddr.c28
-rw-r--r--contrib/libs/c-ares/src/lib/ares_gethostbyname.c22
-rw-r--r--contrib/libs/c-ares/src/lib/ares_getnameinfo.c27
-rw-r--r--contrib/libs/c-ares/src/lib/ares_init.c77
-rw-r--r--contrib/libs/c-ares/src/lib/ares_library_init.c5
-rw-r--r--contrib/libs/c-ares/src/lib/ares_metrics.c261
-rw-r--r--contrib/libs/c-ares/src/lib/ares_options.c38
-rw-r--r--contrib/libs/c-ares/src/lib/ares_platform.c9
-rw-r--r--contrib/libs/c-ares/src/lib/ares_platform.h4
-rw-r--r--contrib/libs/c-ares/src/lib/ares_private.h343
-rw-r--r--contrib/libs/c-ares/src/lib/ares_process.c699
-rw-r--r--contrib/libs/c-ares/src/lib/ares_qcache.c110
-rw-r--r--contrib/libs/c-ares/src/lib/ares_query.c34
-rw-r--r--contrib/libs/c-ares/src/lib/ares_search.c42
-rw-r--r--contrib/libs/c-ares/src/lib/ares_send.c128
-rw-r--r--contrib/libs/c-ares/src/lib/ares_setup.h295
-rw-r--r--contrib/libs/c-ares/src/lib/ares_strerror.c4
-rw-r--r--contrib/libs/c-ares/src/lib/ares_sysconfig.c591
-rw-r--r--contrib/libs/c-ares/src/lib/ares_sysconfig_files.c20
-rw-r--r--contrib/libs/c-ares/src/lib/ares_sysconfig_mac.c108
-rw-r--r--contrib/libs/c-ares/src/lib/ares_sysconfig_win.c619
-rw-r--r--contrib/libs/c-ares/src/lib/ares_timeout.c70
-rw-r--r--contrib/libs/c-ares/src/lib/ares_update_servers.c151
-rw-r--r--contrib/libs/c-ares/src/lib/ares_version.c3
-rw-r--r--contrib/libs/c-ares/src/lib/config-win32.h30
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__array.c356
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__array.h223
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__htable.c (renamed from contrib/libs/c-ares/src/lib/ares__htable.c)10
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__htable.h (renamed from contrib/libs/c-ares/src/lib/ares__htable.h)0
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__htable_asvp.c (renamed from contrib/libs/c-ares/src/lib/ares__htable_asvp.c)14
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__htable_asvp.h (renamed from contrib/libs/c-ares/src/lib/ares__htable_asvp.h)0
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__htable_strvp.c (renamed from contrib/libs/c-ares/src/lib/ares__htable_strvp.c)2
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__htable_strvp.h (renamed from contrib/libs/c-ares/src/lib/ares__htable_strvp.h)2
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__htable_szvp.c (renamed from contrib/libs/c-ares/src/lib/ares__htable_szvp.c)8
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__htable_szvp.h (renamed from contrib/libs/c-ares/src/lib/ares__htable_szvp.h)0
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__htable_vpvp.c (renamed from contrib/libs/c-ares/src/lib/ares__htable_vpvp.c)10
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__htable_vpvp.h (renamed from contrib/libs/c-ares/src/lib/ares__htable_vpvp.h)0
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__llist.c (renamed from contrib/libs/c-ares/src/lib/ares__llist.c)42
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__llist.h (renamed from contrib/libs/c-ares/src/lib/ares__llist.h)15
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__slist.c (renamed from contrib/libs/c-ares/src/lib/ares__slist.c)12
-rw-r--r--contrib/libs/c-ares/src/lib/dsa/ares__slist.h (renamed from contrib/libs/c-ares/src/lib/ares__slist.h)0
-rw-r--r--contrib/libs/c-ares/src/lib/event/ares_event.h (renamed from contrib/libs/c-ares/src/lib/ares_event.h)2
-rw-r--r--contrib/libs/c-ares/src/lib/event/ares_event_configchg.c (renamed from contrib/libs/c-ares/src/lib/ares_event_configchg.c)227
-rw-r--r--contrib/libs/c-ares/src/lib/event/ares_event_epoll.c (renamed from contrib/libs/c-ares/src/lib/ares_event_epoll.c)28
-rw-r--r--contrib/libs/c-ares/src/lib/event/ares_event_kqueue.c (renamed from contrib/libs/c-ares/src/lib/ares_event_kqueue.c)11
-rw-r--r--contrib/libs/c-ares/src/lib/event/ares_event_poll.c (renamed from contrib/libs/c-ares/src/lib/ares_event_poll.c)8
-rw-r--r--contrib/libs/c-ares/src/lib/event/ares_event_select.c (renamed from contrib/libs/c-ares/src/lib/ares_event_select.c)13
-rw-r--r--contrib/libs/c-ares/src/lib/event/ares_event_thread.c (renamed from contrib/libs/c-ares/src/lib/ares_event_thread.c)185
-rw-r--r--contrib/libs/c-ares/src/lib/event/ares_event_wake_pipe.c (renamed from contrib/libs/c-ares/src/lib/ares_event_wake_pipe.c)16
-rw-r--r--contrib/libs/c-ares/src/lib/event/ares_event_win32.c976
-rw-r--r--contrib/libs/c-ares/src/lib/event/ares_event_win32.h (renamed from contrib/libs/c-ares/src/lib/ares_event_win32.h)58
-rw-r--r--contrib/libs/c-ares/src/lib/inet_net_pton.c26
-rw-r--r--contrib/libs/c-ares/src/lib/inet_ntop.c56
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_create_query.c (renamed from contrib/libs/c-ares/src/lib/ares_create_query.c)2
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_expand_name.c (renamed from contrib/libs/c-ares/src/lib/ares_expand_name.c)25
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_expand_string.c (renamed from contrib/libs/c-ares/src/lib/ares_expand_string.c)10
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_fds.c (renamed from contrib/libs/c-ares/src/lib/ares_fds.c)13
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_getsock.c (renamed from contrib/libs/c-ares/src/lib/ares_getsock.c)15
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_parse_a_reply.c (renamed from contrib/libs/c-ares/src/lib/ares_parse_a_reply.c)10
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_parse_aaaa_reply.c (renamed from contrib/libs/c-ares/src/lib/ares_parse_aaaa_reply.c)9
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_parse_caa_reply.c (renamed from contrib/libs/c-ares/src/lib/ares_parse_caa_reply.c)24
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_parse_mx_reply.c (renamed from contrib/libs/c-ares/src/lib/ares_parse_mx_reply.c)16
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_parse_naptr_reply.c (renamed from contrib/libs/c-ares/src/lib/ares_parse_naptr_reply.c)28
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_parse_ns_reply.c (renamed from contrib/libs/c-ares/src/lib/ares_parse_ns_reply.c)31
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_parse_ptr_reply.c (renamed from contrib/libs/c-ares/src/lib/ares_parse_ptr_reply.c)20
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_parse_soa_reply.c (renamed from contrib/libs/c-ares/src/lib/ares_parse_soa_reply.c)20
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_parse_srv_reply.c (renamed from contrib/libs/c-ares/src/lib/ares_parse_srv_reply.c)16
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_parse_txt_reply.c (renamed from contrib/libs/c-ares/src/lib/ares_parse_txt_reply.c)80
-rw-r--r--contrib/libs/c-ares/src/lib/legacy/ares_parse_uri_reply.c (renamed from contrib/libs/c-ares/src/lib/ares_parse_uri_reply.c)12
-rw-r--r--contrib/libs/c-ares/src/lib/record/ares_dns_mapping.c (renamed from contrib/libs/c-ares/src/lib/ares_dns_mapping.c)26
-rw-r--r--contrib/libs/c-ares/src/lib/record/ares_dns_multistring.c224
-rw-r--r--contrib/libs/c-ares/src/lib/record/ares_dns_multistring.h50
-rw-r--r--contrib/libs/c-ares/src/lib/record/ares_dns_name.c (renamed from contrib/libs/c-ares/src/lib/ares_dns_name.c)174
-rw-r--r--contrib/libs/c-ares/src/lib/record/ares_dns_parse.c (renamed from contrib/libs/c-ares/src/lib/ares_dns_parse.c)54
-rw-r--r--contrib/libs/c-ares/src/lib/record/ares_dns_private.h (renamed from contrib/libs/c-ares/src/lib/ares_dns_private.h)81
-rw-r--r--contrib/libs/c-ares/src/lib/record/ares_dns_record.c (renamed from contrib/libs/c-ares/src/lib/ares_dns_record.c)650
-rw-r--r--contrib/libs/c-ares/src/lib/record/ares_dns_write.c (renamed from contrib/libs/c-ares/src/lib/ares_dns_write.c)300
-rw-r--r--contrib/libs/c-ares/src/lib/setup_once.h469
-rw-r--r--contrib/libs/c-ares/src/lib/str/ares__buf.c (renamed from contrib/libs/c-ares/src/lib/ares__buf.c)203
-rw-r--r--contrib/libs/c-ares/src/lib/str/ares__buf.h (renamed from contrib/libs/c-ares/src/lib/ares__buf.h)36
-rw-r--r--contrib/libs/c-ares/src/lib/str/ares_str.c (renamed from contrib/libs/c-ares/src/lib/ares_str.c)14
-rw-r--r--contrib/libs/c-ares/src/lib/str/ares_str.h (renamed from contrib/libs/c-ares/src/lib/ares_str.h)16
-rw-r--r--contrib/libs/c-ares/src/lib/str/ares_strcasecmp.c (renamed from contrib/libs/c-ares/src/lib/ares_strcasecmp.c)10
-rw-r--r--contrib/libs/c-ares/src/lib/str/ares_strcasecmp.h (renamed from contrib/libs/c-ares/src/lib/ares_strcasecmp.h)2
-rw-r--r--contrib/libs/c-ares/src/lib/str/ares_strsplit.c (renamed from contrib/libs/c-ares/src/lib/ares_strsplit.c)21
-rw-r--r--contrib/libs/c-ares/src/lib/str/ares_strsplit.h (renamed from contrib/libs/c-ares/src/lib/ares_strsplit.h)2
-rw-r--r--contrib/libs/c-ares/src/lib/thirdparty/apple/README.md18
-rw-r--r--contrib/libs/c-ares/src/lib/thirdparty/apple/dnsinfo.h40
-rw-r--r--contrib/libs/c-ares/src/lib/util/ares__iface_ips.c (renamed from contrib/libs/c-ares/src/lib/ares__iface_ips.c)168
-rw-r--r--contrib/libs/c-ares/src/lib/util/ares__iface_ips.h (renamed from contrib/libs/c-ares/src/lib/ares__iface_ips.h)0
-rw-r--r--contrib/libs/c-ares/src/lib/util/ares__threads.c (renamed from contrib/libs/c-ares/src/lib/ares__threads.c)23
-rw-r--r--contrib/libs/c-ares/src/lib/util/ares__threads.h (renamed from contrib/libs/c-ares/src/lib/ares__threads.h)0
-rw-r--r--contrib/libs/c-ares/src/lib/util/ares__timeval.c (renamed from contrib/libs/c-ares/src/lib/ares__timeval.c)52
-rw-r--r--contrib/libs/c-ares/src/lib/util/ares_math.c (renamed from contrib/libs/c-ares/src/lib/ares_math.c)21
-rw-r--r--contrib/libs/c-ares/src/lib/util/ares_rand.c (renamed from contrib/libs/c-ares/src/lib/ares_rand.c)46
-rw-r--r--contrib/libs/c-ares/src/lib/windows_port.c4
-rw-r--r--contrib/libs/c-ares/ya.make99
131 files changed, 7468 insertions, 5984 deletions
diff --git a/contrib/libs/c-ares/CHANGES b/contrib/libs/c-ares/CHANGES
deleted file mode 100644
index f1426fda79..0000000000
--- a/contrib/libs/c-ares/CHANGES
+++ /dev/null
@@ -1,7 +0,0 @@
-This file no longer holds the changelog. Now you can generate it yourself
-like this:
-
- $ git log --pretty=fuller --no-color --date=short --decorate=full -1000 |
- ./git2changes.pl
-
-The older, manually edited, changelog is found in git named CHANGES.0
diff --git a/contrib/libs/c-ares/CHANGES.0 b/contrib/libs/c-ares/CHANGES.0
deleted file mode 100644
index 0da401eabe..0000000000
--- a/contrib/libs/c-ares/CHANGES.0
+++ /dev/null
@@ -1,1218 +0,0 @@
- Changelog for the c-ares project
-
-Version 1.7.5 (August 16, 2011)
-
-Fixed:
-
- o detection of semicolon comments in resolv.conf
- o avoid using system's inet_net_pton affected by the WLB-2008080064 advisory
- o replacement ares_inet_net_pton affected by the WLB-2008080064 advisory
- o replacement ares_inet_ntop affected by potential out of bounds write
- o added install target to Makefile.msvc
- o only fall back to AF_INET searches when looking for AF_UNSPEC addresses
- o fixed ares_parse_*_reply memory leaks
- o Use correct sizeof in ares_getnameinfo()
- o IPv6-on-windows: find DNS servers correctly
- o man pages: docs for the c-ares utility programs
- o getservbyport replacement for Win CE
- o config_sortlist: (win32) missing else
- o advance_tcp_send_queue: avoid NULL ptr dereference
- o configure: fix a bashism
- o ares_expand_name: Fix encoded length for indirect root
-
-Version 1.7.4 (December 9, 2010)
-
-Changed:
-
- o local-bind: Support binding to local interface/IPs, see
- ares_set_local_ip4, ares_set_local_ip6, ares_set_local_dev
-
-Fixed:
-
- o memory leak in ares_getnameinfo
- o add missing break that caused get_ares_servers to fail
- o ares_parse_a_reply: fix CNAME response parsing
- o init_by_options: don't copy an empty sortlist
- o Replaced uint32_t with unsigned int to fix broken builds
- on a couple of platforms
- o Fix lookup with HOSTALIASES set
- o adig: fix NAPTR parsing
- o compiler warning cleanups
-
-Version 1.7.3 (June 11, 2010)
-
-Fixed:
-
- o builds on Android
- o now includes all files necessary to build it (1.7.2 lacked a file)
-
-Version 1.7.2 (June 10, 2010)
-
-Changed:
-
- o Added ares_parse_mx_reply()
-
-Fixed:
-
- o ares_init: Last, not first instance of domain or search should win
- o improve alternative definition of bool
- o fix VS2010 compiler warnings
-
-
-Version 1.7.1 (Mar 23, 2010)
-
-* May 31, 2010 (Jakub Hrozek)
-- Use the last instance of domain/search, not the first one
-
-* March 23, 2010 (Daniel Stenberg)
-- We switched from CVS to git. See http://github.com/bagder/c-ares
-
-* March 5, 2010 (Daniel Stenberg)
-- Daniel Johnson provided fixes for building with the clang compiler.
-
-* March 5, 2010 (Yang Tse)
-- Added IPv6 name servers support. Implementation has been based on code,
- comments and feedback provided November and December of 2008 by Daniel
- Stenberg, Gregor Jasny, Phil Blundell and myself, December 2009 by Cedric
- Bail, and February 2010 by Jakub Hrozek on the c-ares mailing list. On
- March I reviewed all that, selected the best of each, and adjusted or
- extended parts of it to make the best fit.
-
- The external and visible result of all this is that two new functions are
- added to the external API, ares_get_servers() and ares_set_servers(), which
- becomes now the preferred way of getting and setting name servers for any
- ares channel as these support both IPv4 and IPv6 name servers.
-
- In order to not break ABI compatibility, ares_init_options() with option
- mask ARES_OPT_SERVERS and ares_save_options() may still be used in code
- which is intended to run on IPv4-only stacks. But remember that these
- functions do not support IPv6 name servers. This implies that if the user
- is capable of defining or providing an IPv6 name server, and the app is
- using ares_init_options() or ares_save_options() at some point to handle
- the name servers, the app will likely lose IPv6 name servers.
-
-* January 28, 2010 (Daniel Stenberg)
-- Tommie Gannert pointed out a silly bug in ares_process_fd() since it didn't
- check for broken connections like ares_process() did. Based on that, I
- merged the two functions into a single generic one with two front-ends.
-
-* December 29, 2009 (Yang Tse)
-- Laszlo Tamas Szabo adjusted Makefile.msvc compiler options so that where
- run-time error checks enabling compiler option /GZ was used it is replaced
- with equivalent /RTCsu for Visual Studio 2003 and newer versions. Option
- /GX is replaced with equivalent /EHsc for all versions. Also fixed socket
- data type for internal configure_socket function.
-
-* December 21, 2009 (Yang Tse)
-- Ingmar Runge noticed that Windows config-win32.h configuration file
- did not include a definition for HAVE_CLOSESOCKET which resulted in
- function close() being inappropriately used to close sockets.
-
-Version 1.7.0 (Nov 30, 2009)
-
-* November 26, 2009 (Yang Tse)
-- Larry Lansing fixed ares_parse_srv_reply to properly parse replies
- which might contain non-SRV answers, skipping over potential non-SRV
- ones such as CNAMEs.
-
-* November 23, 2009 (Yang Tse)
-- Changed naming convention for c-ares libraries built with MSVC, details
- and build instructions provided in README.msvc file.
-
-* November 22, 2009 (Yang Tse)
-- Jakub Hrozek fixed more function prototypes in man pages to sync them
- with the ones declared in ares.h
-
-- Jakub Hrozek renamed addrttl and addr6ttl structs to ares_addrttl and
- ares_addr6ttl in order to prevent name space pollution, along with
- necessary changes to code base and man pages.This change does not break
- ABI, there is no need to recompile existing applications. But existing
- applications using these structs with the old name will need source code
- adjustments when recompiled using c-ares 1.7.0.
-
-* November 21, 2009 (Yang Tse)
-- Added manifest stuff to Makefile.msvc.
-
-* November 20, 2009 (Yang Tse)
-- Fixed several function prototypes in man pages that were out of sync
- with the ones declared in ares.h. Added ares_free_data() along with
- man page. Updated ares_parse_srv_reply() and ares_parse_txt_reply()
- with changes from Jakub Hrozek making these now return linked lists
- instead of arrays, and merging the ares_free_data() adjustments.
-
-* November 10, 2009 (Yang Tse)
-- Updated MSVC 6.0 project files to match settings from Makefile.msvc.
-
-* November 9, 2009 (Yang Tse)
-- Makefile.msvc is now the reference method to build c-ares and sample
- programs with any MSVC compiler or MS Visual Studio version. If no
- option or target are specified it builds dynamic and static c-ares
- libraries in debug and release flavours and also builds all sample
- programs using each of the different c-ares libraries.
-
-* November 2, 2009 (Yang Tse)
-- Renamed c-ares setup.h to ares_setup.h
-
-* October 31, 2009 (Yang Tse)
-- Symbol hiding configure options are named now --enable-symbol-hiding
- and --disable-symbol-hiding in an attempt to make them less ambiguous.
-
-* October 30, 2009 (Yang Tse)
-- Many fixes for ares_parse_txt_reply()
-
-* October 29, 2009 (Daniel Stenberg)
-- Jakub Hrozek added ares_parse_txt_reply() for TXT parsing
-
-* October 29, 2009 (Yang Tse)
-- Updated MSVC 6.0 workspace and project files that allows building
- dynamic and static c-ares libraries in debug and release flavours.
- Additionally each of the three sample programs is built against
- each of the four possible c-ares libraries, generating all this
- a total number of 12 executables and 4 libraries.
-
-* October 28, 2009 (Yang Tse)
-- Initial step towards the ability to reduce c-ares exported symbols
- when built as a shared library based on the 'visibility' attribute
- for GNUC and Intel compilers and based on __global for Sun compilers,
- taking also in account __declspec function decoration for Win32 and
- Symbian DLL's.
-
-* October 27, 2009 (Yang Tse)
-- Fixed Pelles C Win32 target compilation issues.
-
-* October 23, 2009 (Yang Tse)
-- John Engelhart noticed an unreleased problem relative to a duplicate
- ARES_ECANCELLED error code value and missing error code description.
-
-* October 7, 2009 (Yang Tse)
-- Overhauled ares__get_hostent() Fixing out of bounds memory overwrite
- triggered with malformed /etc/hosts file. Improving parsing of /etc/hosts
- file. Validating requested address family. Ensuring that failures always
- return a NULL pointer. Adjusting header inclusions.
-
-* October 6, 2009 (Yang Tse)
-- Fix ssize_t redefinition errors on WIN64 reported by Alexey Simak.
-
-* September 29, 2009 (Yang Tse)
-- Make configure script also check if _REENTRANT definition is required to
- make errno available as a preprocessor macro.
-
-* September 7, 2009 (Yang Tse)
-- Add T_SRV portability check to ares_parse_srv_reply.c
-
-* 4 Sep 2009 (Daniel Stenberg)
-- Jakub Hrozek added ares_parse_srv_reply() for SRV parsing
-
-* 3 Aug 2009 (Daniel Stenberg)
-- Joshua Kwan fixed the init routine to fill in the defaults for stuff that
- fails to get inited by other means. This fixes a case of when the c-ares
- init fails when internet access is fone.
-
-- Timo Teras changed the reason code used in the resolve callback done when
- ares_cancel() is used, to be ARES_ECANCELLED instead of ARES_ETIMEOUT to
- better allow the callback to know what's happening.
-
-* 14 Jul 2009 (Guenter Knauf)
-- renamed generated config.h to ares_config.h to avoid any future clashes
- with config.h from other projects.
-
-* June 20 2009 (Yang Tse)
-- Refactor how libraries are checked for connect() function in configure
- script and check for connect() as it is done for other functions.
-
-* June 19 2009 (Yang Tse)
-- Make sclose() function-like macro definition used to close a socket,
- now solely based on HAVE_CLOSESOCKET and HAVE_CLOSESOCKET_CAMEL
- config file preprocessor definitions
-
-* June 18 2009 (Yang Tse)
-- Add CloseSocket camel case function check for configure script.
-
-* June 17 2009 (Yang Tse)
-- Check for socket() and closesocket() as it is done for other functions
- in configure script.
-
-* June 11 2009 (Yang Tse)
-- Modified buildconf so that when automake runs it copies missing files
- instead of symlinking them.
-
-* June 8 2009 (Yang Tse)
-- Removed buildconf.bat from release and daily snapshot archives. This
- file is only for CVS tree checkout builds.
-
-* May 26 2009 (Yang Tse)
-- Added --enable-curldebug configure option to enable and disable building
- with the low-level curl debug memory tracking 'feature' to allow decoupled
- setting from --enable-debug, allowing again to build c-ares independently
- out of the CVS tree.
-
- For the c-ares library option --enable-debug enables debug build features
- which are _not_ related with memory tracking. For the c-ares library when
- --enable-debug is given it does not enable the memory tracking feature. If
- you wish to enable the curl debug memory tracking you must use configure
- option --enable-curldebug explicitly to do so.
-
- Internally, definition of preprocessor symbol DEBUGBUILD restricts code
- which is only compiled for debug enabled builds. And symbol CURLDEBUG is
- used to differentiate code which is _only_ used for memory tracking.
-
- Make ares_init(), ares_dup() and ares_init_options() fail returning
- ARES_ENOTINITIALIZED if library initialization has not been performed
- calling ares_library_init().
-
-* May 20 2009 (Yang Tse)
-- Added ares_library_init() and ares_library_cleanup() man pages.
-
-* May 19 2009 (Yang Tse)
-- Introduced ares_library_init() and ares_library_cleanup() functions.
-
- This is an API and ABI break for Win32/64 systems. Non-Win32/64 build targets
- using c-ares 1.7.0 can still survive without calling these functions. Read all
- the details on ares_library_init(3) and ares_library_cleanup(3) man pages that
- are included.
-
- curl/libcurl 7.19.5 is fully compatible with c-ares 1.7.0 on all systems.
-
- In order to use c-ares 1.7.0 with curl/libcurl on Win32/64 systems it is
- required that curl/libcurl is 7.19.5 or newer. In other words, it is not
- possible on Win32/64 to use c-ares 1.7.0 with a curl/libcurl version less
- than 7.19.5
-
-* May 11 2009 (Daniel Stenberg)
-- Gregor Jasny made c-ares link with libtool 's -export-symbols-regex option to
- only expose functions starting with ares_.
-
-* May 7 2009 (Yang Tse)
-- Fix an m4 overquoting triggering a spurious 'AS_TR_CPP' symbol definition
- attempt in generated config.h
-
-* May 2 2009 (Yang Tse)
-- Use a build-time configured ares_socklen_t data type instead of socklen_t.
-
-* April 21 2009 (Yang Tse)
-- Moved potential inclusion of system's malloc.h and memory.h header files to
- setup_once.h. Inclusion of each header file is based on the definition of
- NEED_MALLOC_H and NEED_MEMORY_H respectively.
-
-* March 11 2009 (Yang Tse)
-- Japheth Cleaver fixed acountry.c replacing u_long with unsigned long.
-
-* February 20 2009 (Yang Tse)
-- Do not halt compilation when using VS2008 to build a Windows 2000 target.
-
-* February 3 2009 (Phil Blundell)
-- If the server returns garbage or nothing at all in response to an AAAA query,
- go on and ask for A records anyway.
-
-* January 31 2009 (Daniel Stenberg)
-- ares_gethostbyname() now accepts 'AF_UNSPEC' as a family for resolving
- either AF_INET6 or AF_INET. It works by accepting any of the looksups in the
- hosts file, and it resolves the AAAA field with a fallback to A.
-
-* January 14 2009 (Daniel Stenberg)
-- ares.h no longer uses the HAVE_STRUCT_IN6_ADDR define check, but instead it
- now declares the private struct ares_in6_addr for all systems instead of
- relying on one possibly not present in the system.
-
-* January 13 2009 (Phil Blundell)
-- ares__send_query() now varies the retry timeout pseudo-randomly to avoid
- packet storms when several queries were started at the same time.
-
-* January 11 2009 (Daniel Stenberg)
-- Phil Blundell added the internal function ares__expand_name_for_response()
- that is now used by the ares_parse_*_reply() functions instead of the
- ares_expand_name() simply to easier return ARES_EBADRESP for the cases where
- the name expansion fails as in responses that really isn't expected.
-
-Version 1.6.0 (Dec 9, 2008)
-
-* December 9 2008 (Gisle Vanem)
-
- Fixes for Win32 targets using the Watt-32 tcp/ip stack.
-
-* Dec 4 2008 (Daniel Stenberg)
-
- Gregor Jasny provided the patch that introduces ares_set_socket_callback(),
- and I edited it to also get duped by ares_dup().
-
-* Dec 3 2008 (Daniel Stenberg)
-
- API changes:
-
- I made sure the public ares_config struct looks like before and yet it
- supports the ROTATE option thanks to c-ares now storing the "optmask"
- internally. Thus we should be ABI compatible with the past release(s)
- now. My efforts mentioned below should not break backwards ABI compliance.
-
- Here's how I suggest we proceed with the API:
-
- ares_init() will be primary "channel creator" function.
-
- ares_init_options() will continue to work exactly like now and before. For
- starters, it will be the (only) way to set the existing options.
-
- ares_save_options() will continue to work like today, but will ONLY save
- options that you can set today (including ARES_OPT_ROTATE actually) but new
- options that we add may not be saved with this.
-
- Instead we introduce:
-
- ares_dup() that instead can make a new channel and clone the config used
- from an existing channel. It will then clone all config options, including
- future new things we add.
-
- ares_set_*() style functions that set (new) config options. As a start we
- simply add these for new functionality, but over time we can also introduce
- them for existing "struct ares_options" so that we can eventually deprecate
- the two ares_*_options() functions.
-
- ares_get_*() style functions for extracting info from a channel handle that
- should be used instead of ares_save_options().
-
-* Nov 26 2008 (Yang Tse)
-- Brad Spencer provided changes to allow buildconf to work on OS X.
-
-- Gerald Combs fixed a bug in ares_parse_ptr_reply() which would cause a
- buffer to shrink instead of expand if a reply contained 8 or more records.
-
-* Nov 25 2008 (Yang Tse)
-- In preparation for the upcoming IPv6 nameservers patch, the internal
- ares_addr union is now changed into an internal struct which also holds
- the address family.
-
-* Nov 19 2008 (Daniel Stenberg)
-- Brad Spencer brought the new function ares_gethostbyname_file() which simply
- resolves a host name from the given file, using the regular hosts syntax.
-
-* Nov 1 2008 (Daniel Stenberg)
-- Carlo Contavalli added support for the glibc "rotate" option, as documented
- in man resolv.conf:
-
- causes round robin selection of nameservers from among those listed. This
- has the effect of spreading the query load among all listed servers, rather
- than having all clients try the first listed server first every time.
-
- You can enable it with ARES_OPT_ROTATE
-
-* Oct 21 2008 (Yang Tse)
- Charles Hardin added handling of EINPROGRESS for UDP connects.
-
-* Oct 18 2008 (Daniel Stenberg)
- Charles Hardin made adig support a regular numerical dotted IP address for the
- -s option as well.
-
-* Oct 7 2008 (Yang Tse)
-- Added --enable-optimize configure option to enable and disable compiler
- optimizations to allow decoupled setting from --enable-debug.
-
-* Oct 2 2008 (Yang Tse)
-- Added --enable-warnings configure option to enable and disable strict
- compiler warnings to allow decoupled setting from --enable-debug.
-
-* Sep 17 2008 (Yang Tse)
-- Code reorganization to allow internal/private use of "nameser.h" to any
- system that lacks arpa/nameser.h or arpa/nameser_compat.h header files.
-
-* Sep 16 2008 (Yang Tse)
-- Code reorganization to allow internal/private use of ares_writev to any
- system that lacks the writev function.
-
-* Sep 15 2008 (Yang Tse)
-- Code reorganization to allow internal/private use of ares_strcasecmp to any
- system that lacks the strcasecmp function.
-
-- Improve configure detection of some string functions.
-
-* Sep 11 2008 (Yang Tse)
-- Code reorganization to allow internal/private use of ares_strdup to any
- system that lacks the strdup function.
-
-Version 1.5.3 (Aug 29, 2008)
-
-* Aug 25 2008 (Yang Tse)
-- Improvement by Brad House:
-
- This patch addresses an issue in which a response could be sent back to the
- source port of a client from a different address than the request was made to.
- This is one form of a DNS cache poisoning attack.
-
- The patch simply uses recvfrom() rather than recv() and validates that the
- address returned from recvfrom() matches the address of the server we have
- connected to. Only necessary on UDP sockets as they are connection-less, TCP
- is unaffected.
-
-- Fix by George Neill:
- Fixed compilation of acountry sample application failure on some systems.
-
-* Aug 4 2008 (Daniel Stenberg)
-- Fix by Tofu Linden:
-
- The symptom:
- * Users (usually, but not always) on 2-Wire routers and the Comcast service
- and a wired connection to their router would find that the second and
- subsequent DNS lookups from fresh processes using c-ares to resolve the same
- address would cause the process to never see a reply (it keeps polling for
- around 1m15s before giving up).
-
- The repro:
- * On such a machine (and yeah, it took us a lot of QA to find the systems
- that reproduce such a specific problem!), do 'ahost www.secondlife.com',
- then do it again. The first process's lookup will work, subsequent lookups
- will time-out and fail.
-
- The cause:
- * init_id_key() was calling randomize_key() *before* it initialized
- key->state, meaning that the randomness generated by randomize_key() is
- immediately overwritten with deterministic values. (/dev/urandom was also
- being read incorrectly in the c-ares version we were using, but this was
- fixed in a later version.)
- * This makes the stream of generated query-IDs from any new c-ares process
- be an identical and predictable sequence of IDs.
- * This makes the 2-Wire's default built-in DNS server detect these queries
- as probable-duplicates and (erroneously) not respond at all.
-
-
-* Aug 4 2008 (Yang Tse)
-- Autoconf 2.62 has changed the behaviour of the AC_AIX macro which we use.
- Prior versions of autoconf defined _ALL_SOURCE if _AIX was defined. 2.62
- version of AC_AIX defines _ALL_SOURCE and other four preprocessor symbols
- no matter if the system is AIX or not. To keep the traditional behaviour,
- and an uniform one across autoconf versions AC_AIX is replaced with our
- own internal macro CARES_CHECK_AIX_ALL_SOURCE.
-
-* Aug 1 2008 (Yang Tse)
-- Configure process now checks if the preprocessor _REENTRANT symbol is already
- defined. If it isn't currently defined a set of checks are performed to test
- if its definition is required to make visible to the compiler a set of *_r
- functions. Finally, if _REENTRANT is already defined or needed it takes care
- of making adjustments necessary to ensure that it is defined equally for the
- configure process tests and generated config file.
-
-* Jul 20 2008 (Yang Tse)
-- When recvfrom prototype uses a void pointer for arguments 2, 5 or 6 this will
- now cause the definition, as appropriate, of RECVFROM_TYPE_ARG2_IS_VOID,
- RECVFROM_TYPE_ARG5_IS_VOID or RECVFROM_TYPE_ARG6_IS_VOID.
-
-* Jul 17 2008 (Yang Tse)
-- RECVFROM_TYPE_ARG2, RECVFROM_TYPE_ARG5 and RECVFROM_TYPE_ARG6 are now defined
- to the data type pointed by its respective argument and not the pointer type.
-
-* Jul 16 2008 (Yang Tse)
-- Improved configure detection of number of arguments for getservbyport_r.
- Detection is now based on compilation checks instead of linker ones.
-
-- Configure process now checks availability of recvfrom() socket function and
- finds out its return type and the types of its arguments. Added definitions
- for non-configure systems config files, and introduced macro sreadfrom which
- will be used on udp sockets as a recvfrom() wrapper in the future.
-
-* Jul 15 2008 (Yang Tse)
-- Introduce definition of _REENTRANT symbol in setup.h to improve library
- usability. Previously the configure process only used the AC_SYS_LARGEFILE
- macro for debug builds, now it is also used for non-debug ones enabling the
- use of configure options --enable-largefile and --disable-largefile which
- might be needed for library compatibility. Remove checking the size of
- curl_off_t, it is no longer needed.
-
-* Jul 3 2008 (Daniel Stenberg)
-- Phil Blundell: If you ask ares_gethostbyname() to do an AF_INET6 lookup and
- the target host has only A records, it automatically falls back to an
- AF_INET lookup and gives you the A results. However, if the target host has
- a CNAME record, this behaviour is defeated since the original query does
- return some data even though ares_parse_aaa_reply() doesn't consider it
- relevant. Here's a small patch to make it behave the same with and without
- the CNAME.
-
-* Jul 2 2008 (Yang Tse)
-- Fallback to gettimeofday when monotonic clock is unavailable at run-time.
-
-* Jun 30 2008 (Daniel Stenberg)
-
-- As was pointed out to me by Andreas Schuldei, the MAXHOSTNAMELEN define is
- not posix or anything and thus c-ares failed to build on hurd (and possibly
- elsewhere). The define was also somewhat artificially used in the windows
- port. Now, I instead rewrote the use of gethostbyname to enlarge the host
- name buffer in case of need and totally avoid the use of the MAXHOSTNAMELEN
- define. I thus also removed the define from the namser.h file where it was
- once added for the windows build.
-
- I also fixed init_by_defaults() function to not leak memory in case if
- error.
-
-* Jun 9 2008 (Yang Tse)
-
-- Make libcares.pc generated file for pkg-config include information relative
- to the libraries needed for the static linking of c-ares.
-
-* May 30 2008 (Yang Tse)
-
-- Brad House fixed a missing header file inclusion in adig sample program.
-
-Version 1.5.2 (May 29, 2008)
-
-* May 13 2008 (Daniel Stenberg)
-
-- Introducing millisecond resolution support for the timeout option. See
- ares_init_options()'s ARES_OPT_TIMEOUTMS.
-
-* May 9 2008 (Yang Tse)
-
-- Use monotonic time source if available, for private function ares__tvnow()
-
-* May 7 2008 (Daniel Stenberg)
-
-- Sebastian made c-ares able to return all PTR-records when doing reverse
- lookups. It is not common practice to have multiple PTR-Records for a single
- IP, but its perfectly legal and some sites have those.
-
-- Doug Goldstein provided a configure patch: updates autoconf 2.13 usage to
- autoconf 2.57 usage (which is the version you have specified as the minimum
- version). It's a minor change but it does clean up some warnings with newer
- autoconf (specifically 2.62).
-
-* May 5 2008 (Yang Tse)
-
-- Improved parsing of resolver configuration files.
-
-* April 4 2008 (Daniel Stenberg)
-
-- Eino Tuominen improved the code when a file is used to seed the randomizer.
-
-- Alexey Simak made adig support NAPTR records
-
-- Alexey Simak fixed the VC dsp file by adding the missing source file
- ares_expand_string.c
-
-* December 11 2007 (Gisle Vanem)
-
-- Added another sample application; acountry.c which converts an
- IPv4-address(es) and/or host-name(s) to country-name and country-code.
- This uses the service of the DNSBL at countries.nerd.dk.
-
-* December 3 2007 (Daniel Stenberg)
-
-- Brad Spencer fixed the configure script to assume that there's no
- /dev/urandom when built cross-compiled as then the script cannot check for
- it.
-
-- Erik Kline cleaned up ares_gethostbyaddr.c:next_lookup() somewhat
-
-Version 1.5.1 (Nov 21, 2007)
-
-* November 21 2007 (Daniel Stenberg)
-
-- Robin Cornelius pointed out that ares_llist.h was missing in the release
- archive for 1.5.0
-
-Version 1.5.0 (Nov 21, 2007)
-
-* October 2 2007 (Daniel Stenberg)
-
-- ares_strerror() segfaulted if the input error number was out of the currently
- supported range.
-
-- Yang Tse: Avoid a segfault when generating a DNS "Transaction ID" in
- internal function init_id_key() under low memory conditions.
-
-* September 28 2007 (Daniel Stenberg)
-
-- Bumped version to 1.5.0 for next release and soname bumped to 2 due to ABI
- and API changes in the progress callback (and possibly more coming up from
- Steinar)
-
-* September 28 2007 (Steinar H. Gunderson)
-
-- Don't skip a server if it's the only one. (Bugfix from the Google tree.)
-
-- Made the query callbacks receive the number of timeouts that happened during
- the execution of a query, and updated documentation accordingly. (Patch from
- the Google tree.)
-
-- Support a few more socket options: ARES_OPT_SOCK_SNDBUF and
- ARES_OPT_SOCK_RCVBUF
-
-- Always register for TCP events even if there are no outstanding queries, as
- the other side could always close the connection, which is a valid event
- which should be responded to.
-
-* September 22 2007 (Daniel Stenberg)
-
-- Steinar H. Gunderson fixed: Correctly clear sockets from the fd_set on in
- several functions (write_tcp_data, read_tcp_data, read_udp_packets) so that
- if it fails and the socket is closed the following code doesn't try to use
- the file descriptor.
-
-- Steinar H. Gunderson modified c-ares to now also do to DNS retries even when
- TCP is used since there are several edge cases where it still makes sense.
-
-- Brad House provided a fix for ares_save_options():
-
- Apparently I overlooked something with the ares_save_options() where it
- would try to do a malloc(0) when no options of that type needed to be saved.
- On most platforms, this was fine because malloc(0) doesn't actually return
- NULL, but on AIX it does, so ares_save_options would return ARES_ENOMEM.
-
-* July 14 2007 (Daniel Stenberg)
-
-- Vlad Dinulescu fixed two outstanding valgrind reports:
-
- 1. In ares_query.c , in find_query_by_id we compare q->qid (which is a short
- int variable) with qid, which is declared as an int variable. Moreover,
- DNS_HEADER_SET_QID is used to set the value of qid, but DNS_HEADER_SET_QID
- sets only the first two bytes of qid. I think that qid should be declared as
- "unsigned short" in this function.
-
- 2. The same problem occurs in ares_process.c, process_answer() . query->qid
- (an unsigned short integer variable) is compared with id, which is an
- integer variable. Moreover, id is initialized from DNS_HEADER_QID which sets
- only the first two bytes of id. I think that the id variable should be
- declared as "unsigned short" in this function.
-
- Even after declaring these variables as "unsigned short", the valgrind
- errors are still there. Which brings us to the third problem.
-
- 3. The third problem is that Valgrind assumes that query->qid is not
- initialised correctly. And it does that because query->qid is set from
- DNS_HEADER_QID(qbuf); Valgrind says that qbuf has uninitialised bytes. And
- qbuf has uninitialised bytes because of channel->next_id . And next_id is
- set by ares_init.c:ares__generate_new_id() . I found that putting short r=0
- in this function (instead of short r) makes all Valgrind warnings go away.
- I have studied ares__rc4() too, and this is the offending line:
-
- buffer_ptr[counter] ^= state[xorIndex]; (ares_query.c:62)
-
- This is what triggers Valgrind.. buffer_ptr is uninitialised in this function,
- and by applying ^= on it, it remains uninitialised.
-
-Version 1.4.0 (June 8, 2007)
-
-* June 4 2007 (Daniel Stenberg)
-
-- James Bursa reported a major memory problem when resolving multi-IP names
- and I found and fixed the problem. It was added by Ashish Sharma's patch
- two days ago.
-
- When I then tried to verify multiple entries in /etc/hosts after my fix, I
- got another segfault and decided this code was not ripe for inclusion and I
- reverted the patch.
-
-* June 2 2007
-
-- Brad Spencer found and fixed three flaws in the code, found with the new
- gcc 4.2.0 warning: -Waddress
-
-- Brad House fixed VS2005 compiler warnings due to time_t being 64bit.
- He also made recent Microsoft compilers use _strdup() instead of strdup().
-
-- Brad House's man pages for ares_save_options() and ares_destroy_options()
- were added.
-
-- Ashish Sharma provided a patch for supporting multiple entries in the
- /etc/hosts file. Patch edited for coding style and functionality by me
- (Daniel).
-
-* May 30 2007
-
-- Shmulik Regev brought cryptographically secure transaction IDs:
-
- The c-ares library implementation uses a DNS "Transaction ID" field that is
- seeded with a pseudo random number (based on gettimeofday) which is
- incremented (++) between consecutive calls and is therefore rather
- predictable. In general, predictability of DNS Transaction ID is a well
- known security problem (e.g.
- http://bak.spc.org/dms/archive/dns_id_attack.txt) and makes a c-ares based
- implementation vulnerable to DNS poisoning. Credit goes to Amit Klein
- (Trusteer) for identifying this problem.
-
- The patch I wrote changes the implementation to use a more secure way of
- generating unique IDs. It starts by obtaining a key with reasonable entropy
- which is used with an RC4 stream to generate the cryptographically secure
- transaction IDs.
-
- Note that the key generation code (in ares_init:randomize_key) has two
- versions, the Windows specific one uses a cryptographically safe function
- provided (but undocumented :) by the operating system (described at
- http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx). The
- default implementation is a bit naive and uses the standard 'rand'
- function. Surely a better way to generate random keys exists for other
- platforms.
-
- The patch can be tested by using the adig utility and using the '-s' option.
-
-- Brad House added ares_save_options() and ares_destroy_options() that can be
- used to keep options for later re-usal when ares_init_options() is used.
-
- Problem: Calling ares_init() for each lookup can be unnecessarily resource
- intensive. On windows, it must LoadLibrary() or search the registry
- on each call to ares_init(). On unix, it must read and parse
- multiple files to obtain the necessary configuration information. In
- a single-threaded environment, it would make sense to only
- ares_init() once, but in a heavily multi-threaded environment, it is
- undesirable to ares_init() and ares_destroy() for each thread created
- and track that.
-
- Solution: Create ares_save_options() and ares_destroy_options() functions to
- retrieve and free options obtained from an initialized channel. The
- options populated can be used to pass back into ares_init_options(),
- it should populate all needed fields and not retrieve any information
- from the system. Probably wise to destroy the cache every minute or
- so to prevent the data from becoming stale.
-
-- Daniel S added ares_process_fd() to allow applications to ask for processing
- on specific sockets and thus avoiding select() and associated
- functions/macros. This function will be used by upcoming libcurl releases
- for this very reason. It also made me export the ares_socket_t type in the
- public ares.h header file, since ares_process_fd() uses that type for two of
- the arguments.
-
-* May 25 2007
-
-- Ravi Pratap fixed a flaw in the init_by_resolv_conf() function for windows
- that could cause it to return a bad return code.
-
-* April 16 2007
-
-- Yang Tse: Provide ares_getopt() command-line parser function as a source
- code helper function, not belonging to the actual c-ares library.
-
-* February 19 2007
-
-- Vlad Dinulescu added ares_parse_ns_reply().
-
-* February 13 2007
-
-- Yang Tse: Fix failure to get the search sequence of /etc/hosts and
- DNS from /etc/nsswitch.conf, /etc/host.conf or /etc/svc.conf when
- /etc/resolv.conf did not exist or was unable to read it.
-
-* November 22 2006
-
-- Install ares_dns.h too
-
-- Michael Wallner fixed this problem: When I set domains in the options
- struct, and there are domain/search entries in /etc/resolv.conf, the domains
- of the options struct will be overridden.
-
-* November 6 2006
-
-- Yang Tse removed a couple of potential zero size memory allocations.
-
-- Andreas Rieke fixed the line endings in the areslib.dsp file that I (Daniel)
- broke in the 1.3.2 release. We should switch to a system where that file is
- auto-generated. We could rip some code for that from curl...
-
-Version 1.3.2 (November 3, 2006)
-
-* October 12 2006
-
-- Prevent ares_getsock() to overflow if more than 16 sockets are used.
-
-* September 11 2006
-
-- Guilherme Balena Versiani: I noted a strange BUG in Win32 port
- (ares_init.c/get_iphlpapi_dns_info() function): when I disable the network
- by hand or disconnect the network cable in Windows 2000 or Windows XP, my
- application gets 127.0.0.1 as the only name server. The problem comes from
- 'GetNetworkParams' function, that returns the empty string "" as the only
- name server in that case. Moreover, the Windows implementation of
- inet_addr() returns INADDR_LOOPBACK instead of INADDR_NONE.
-
-* August 29 2006
-
-- Brad Spencer did
-
- o made ares_version.h use extern "C" for c++ compilers
- o fixed compiler warnings in ares_getnameinfo.c
- o fixed a buffer position init for TCP reads
-
-* August 3 2006
-
-- Ravi Pratap fixed ares_getsock() to actually return the proper bitmap and
- not always zero!
-
-Version 1.3.1 (June 24, 2006)
-
-* July 23, 2006
-
-- Gisle Vanem added getopt() to the ahost program. Currently accepts
- only [-t {a|aaaa}] to specify address family in ares_gethostbyname().
-
-* June 19, 2006
-
-- (wahern) Removed "big endian" DNS section and RR data integer parser
- macros from ares_dns.h, which break c-ares on my Sparc64. Bit-wise
- operations in C operate on logical values. And in any event the octets are
- already in big-endian (aka network) byte order so they're being reversed
- (thus the source of the breakage).
-
-* June 18, 2006
-
-- William Ahern handles EAGAIN/EWOULDBLOCK errors in most of the I/O calls
- from area_process.c.
-
- TODO: Handle one last EAGAIN for a UDP socket send(2) in
- ares__send_query().
-
-* May 10, 2006
-
-- Bram Matthys brought my attention to a libtool peculiarity where detecting
- things such as C++ compiler actually is a bad thing and since we don't need
- that detection I added a work-around, much inspired by a previous patch by
- Paolo Bonzini. This also shortens the configure script quite a lot.
-
-* May 3, 2006
-
-- Nick Mathewson added the ARES_OPT_SOCK_STATE_CB option that when set makes
- c-ares call a callback on socket state changes. A better way than the
- ares_getsock() to get full control over the socket state.
-
-* January 9, 2006
-
-- Alexander Lazic improved the getservbyport_r() configure check.
-
-* January 6, 2006
-
-- Alexander Lazic pointed out that the buildconf should use the ACLOCAL_FLAGS
- variable for easier controlling what it does and how it runs.
-
-* January 5, 2006
-
-- James Bursa fixed c-ares to find the hosts file on RISC OS, and made it
- build with newer gcc versions that no longer defines "riscos".
-
-* December 22
-
-- Daniel Stenberg added ares_getsock() that extracts the set of sockets to
- wait for action on. Similar to ares_fds() but not restricted to using
- select() for the waiting.
-
-* November 25
-
-- Yang Tse fixed some send() / recv() compiler warnings
-
-* September 18
-
-- Added constants that will be used by ares_getaddrinfo
-
-- Made ares_getnameinfo use the reentrant getservbyport (getservbyport_r) if it
- is available to ensure it works properly in a threaded environment.
-
-* September 10
-
-- configure fix for detecting a member in the sockaddr_in6 struct which failed
- on ipv6-enabled HP-UX 11.00
-
-Version 1.3.0 (August 29, 2005)
-
-* August 21
-
-- Alfredo Tupone provided a fix for the Windows code in get_iphlpapi_dns_info()
- when getting the DNS server etc.
-
-* June 19
-
-- Added some checks for the addrinfo structure.
-
-* June 2
-
-- William Ahern:
-
- Make UDP sockets non-blocking. I've confirmed that at least on Linux 2.4 a
- read event can come back from poll() on a valid SOCK_DGRAM socket but
- recv(2) will still block. This patch doesn't ignore EAGAIN in
- read_udp_packets(), though maybe it should. (This patch was edited by Daniel
- Stenberg and a new configure test was added (imported from curl's configure)
- to properly detect what non-blocking socket approach to use.)
-
- I'm not quite sure how this was happening, but I've been seeing PTR queries
- which seem to return empty responses. At least, they were empty when calling
- ares_expand_name() on the record. Here's a patch which guarantees to
- NUL-terminate the expanded name. The old behavior failed to NUL-terminate if
- len was 0, and this was causing strlen() to run past the end of the buffer
- after calling ares_expand_name() and getting ARES_SUCCESS as the return
- value. If q is not greater than *s then it's equal and *s is always
- allocated with at least one byte.
-
-* May 16
-
-- Added ares_getnameinfo which mimics the getnameinfo API (another feature
- that could use testing).
-
-* May 14
-
-- Added an inet_ntop function from BIND for systems that do not have it.
-
-* April 9
-
-- Made sortlist support IPv6 (this can probably use some testing).
-
-- Made sortlist support CIDR matching for IPv4.
-
-* April 8
-
-- Added preliminary IPv6 support to ares_gethostbyname. Currently, sortlist
- does not work with IPv6. Also provided an implementation of bitncmp from
- BIND for systems that do not supply this function. This will be used to add
- IPv6 support to sortlist.
-
-- Made ares_gethostbyaddr support IPv6 by specifying AF_INET6 as the family.
- The function can lookup IPv6 addresses both from files (/etc/hosts) and
- DNS lookups.
-
-* April 7
-
-- Tupone Alfredo fixed includes of arpa/nameser_compat.h to build fine on Mac
- OS X.
-
-* April 5
-
-- Dominick Meglio: Provided implementations of inet_net_pton and inet_pton
- from BIND for systems that do not include these functions.
-
-* March 11, 2005
-
-- Dominick Meglio added ares_parse_aaaa_reply.c and did various
- adjustments. The first little steps towards IPv6 support!
-
-* November 7
-
-- Fixed the VC project and makefile to use ares_cancel and ares_version
-
-* October 24
-
-- The released ares_version.h from 1.2.1 says 1.2.0 due to a maketgz flaw.
- This is now fixed.
-
-Version 1.2.1 (October 20, 2004)
-
-* September 29
-
-- Henrik Stoerner fix: got a report that Tru64 Unix (the unix from Digital
- when they made Alpha's) uses /etc/svc.conf for the purpose fixed below for
- other OSes. He made c-ares check for and understand it if present.
-
-- Now c-ares will use local host name lookup _before_ DNS resolving by default
- if nothing else is told.
-
-* September 26
-
-- Henrik Stoerner: found out that c-ares does not look at the /etc/host.conf
- file to determine the sequence in which to search /etc/hosts and DNS. So on
- systems where this order is defined by /etc/host.conf instead of a "lookup"
- entry in /etc/resolv.conf, c-ares will always default to looking in DNS
- first, and /etc/hosts second.
-
- c-ares now looks at
-
- 1) resolv.conf (for the "lookup" line);
- 2) nsswitch.fon (for the "hosts:" line);
- 3) host.conf (for the "order" line).
-
- First match wins.
-
-- Dominick Meglio patched: C-ares on Windows assumed that the HOSTS file is
- located in a static location. It assumed
- C:\Windows\System32\Drivers\Etc. This is a poor assumption to make. In fact,
- the location of the HOSTS file can be changed via a registry setting.
-
- There is a key called DatabasePath which specifies the path to the HOSTS
- file:
- http://www.microsoft.com/technet/itsolutions/network/deploy/depovg/tcpip2k.mspx
-
- The patch will make c-ares correctly consult the registry for the location
- of this file.
-
-* August 29
-
-- Gisle Vanem fixed the MSVC build files.
-
-* August 20
-
-- Gisle Vanem made c-ares build and work with his Watt-32 TCP/IP stack.
-
-* August 13
-
-- Harshal Pradhan made a minor syntax change in ares_init.c to make it build
- fine with MSVC 7.1
-
-* July 24
-
-- Made the lib get built static only if --enable-debug is used.
-
-- Gisle Vanem fixed:
-
- Basically in loops like handle_errors(), 'query->next' was assigned a local
- variable and then query was referenced after the memory was freed by
- next_server(). I've changed that so next_server() and end_query() returns
- the next query. So callers should use this ret-value.
-
- The next problem was that 'server->tcp_buffer_pos' had a random value at
- entry to 1st recv() (luckily causing Winsock to return ENOBUFS).
-
- I've also added a ares_writev() for Windows to streamline the code a bit
- more.
-
-* July 20
-- Fixed a few variable return types for some system calls. Made configure
- check for ssize_t to make it possible to use that when receiving the send()
- error code. This is necessary to prevent compiler warnings on some systems.
-
-- Made configure create config.h, and all source files now include setup.h that
- might include the proper config.h (or a handicrafted alternative).
-
-- Switched to 'ares_socket_t' type for sockets in ares, since Windows don't
- use 'int' for that.
-
-- automake-ified and libool-ified c-ares. Now it builds libcares as a shared
- lib on most platforms if wanted. (This bloated the size of the release
- archive with another 200K!)
-
-- Makefile.am now uses Makefile.inc for the c sources, h headers and man
- pages, to make it easier for other makefiles to use the exact same set of
- files.
-
-- Adjusted 'maketgz' to use the new automake magic when building distribution
- archives.
-
-- Anyone desires HTML and/or PDF versions of the man pages in the release
- archives?
-
-* July 3
-- Günter Knauf made c-ares build and run on Novell Netware.
-
-* July 1
-- Gisle Vanem provided Makefile.dj to build with djgpp, added a few more djgpp
- fixes and made ares not use 'errno' to provide further info on Windows.
-
-* June 30
-- Gisle Vanem made it build with djgpp and run fine with the Watt-32 stack.
-
-* June 10
-- Gisle Vanem's init patch for Windows:
-
- The init_by_resolv_conf() function fetches the DNS-server(s)
- from a series of registry branches.
-
- This can be wrong in the case where DHCP has assigned nameservers, but the
- user has overridden these servers with other preferred settings. Then it's
- wrong to use the DHCPNAMESERVER setting in registry.
-
- In the case of no global DHCP-assigned or fixed servers, but DNS server(s)
- per adapter, one has to query the adapter branches. But how can c-ares know
- which adapter is valid for use? AFAICS it can't. There could be one adapter
- that is down (e.g. a VPN adapter).
-
- So it's better to leave this to the IP Helper API (iphlapi) available in
- Win-98/2000 and later. My patch falls-back to the old way if not available.
-
-* June 8
-- James Bursa fixed an init issue for RISC OS.
-
-* May 11
-- Nico Stappenbelt reported that when processing domain and search lines in
- the resolv.conf file, the first entry encountered is processed and used as
- the search list. According to the manual pages for both Linux, Solaris and
- Tru64, the last entry of either a domain or a search field is used.
-
- This is now adjusted in the code
-
-Version 1.2.0 (April 13, 2004)
-
-* April 2, 2004
-- Updated various man pages to look nicer when converted to HTML on the web
- site.
-
-* April 1, 2004
-- Dirk Manske provided a new function that is now named ares_cancel(). It is
- used to cancel/cleanup a resolve/request made using ares functions on the
- given ares channel. It does not destroy/kill the ares channel itself.
-
-- Dominick Meglio cleaned up the formatting in several man pages.
-
-* March 30, 2004
-- Dominick Meglio's new ares_expand_string. A helper function when decoding
- incoming DNS packages.
-
-- Daniel Stenberg modified the Makefile.in to use a for loop for the man page
- installation to improve overview and make it easier to add man pages.
-
-Version 1.1.0 (March 11, 2004)
-
-* March 9, 2004
-- Gisle Vanem improved build on Windows.
-
-* February 25, 2004
-- Dan Fandrich found a flaw in the Feb 22 fix.
-
-- Added better configure --enable-debug logic (taken from the curl configure
- script). Added acinclude.m4 to the tarball.
-
-* February 23, 2004
-- Removed ares_free_errmem(), the function, the file and the man page. It was
- not used and it did nothing.
-
-- Fixed a lot of code that wasn't "64bit clean" and thus caused a lot of
- compiler warnings on picky compilers.
-
-* February 22, 2004
-- Dominick Meglio made ares init support multiple name servers in the
- NameServer key on Windows.
-
-* February 16, 2004
-- Modified ares_private.h to include libcurl's memory debug header if
- CURLDEBUG is set. This makes all the ares-functions supervised properly by
- the curl test suite. This also forced me to add inclusion of the
- ares_private.h header in a few more files that are using some kind of
- memory-related resources.
-
-- Made the makefile only build ahost and adig if 'make demos' is used.
-
-* February 10, 2004
-- Dirk Manske made ares_version.h installed with 'make install'
-
-* February 4, 2004
-- ares_free_errmem() is subject for removal, it is simply present for future
- purposes, and since we removed the extra parameter in strerror() it won't
- be used by c-ares!
-- configure --enable-debug now enables picky compiler options if gcc is used
-- fixed several compiler warnings --enable-debug showed and Joerg Mueller-Tolk
- reported
-
-Version 1.0.0 (February 3, 2004)
-
-* February 3, 2004
-- now we produce the libcares.a library instead of the previous libares.a
- since we are no longer compatible
-
-* February 2, 2004
-
-- ares_strerror() has one argument less. This is the first official
- modification of the existing provided ares API.
-
-* January 29, 2004
-
-- Dirk Manske fixed how the socket is set non-blocking.
-
-* January 4, 2004
-
-- Dominick Meglio made the private gettimeofday() become ares_gettimeofday()
- instead in order to not pollute the name space and risk colliding with
- other libraries' versions of this function.
-
-* October 24, 2003. Daniel Stenberg
-
- Added ares_version().
-
-Version 1.0-pre1 (8 October 2003)
-
-- James Bursa made it run on RISC OS
-
-- Dominick Meglio made it run fine on NT4
-
-- Duncan Wilcox made it work fine on Mac OS X
-
-- Daniel Stenberg adjusted the windows port
-
-- liren at vivisimo.com made the initial windows port
-
-* Imported the sources from ares 1.1.1
diff --git a/contrib/libs/c-ares/INSTALL.md b/contrib/libs/c-ares/INSTALL.md
index de766aad28..dc58ab8c04 100644
--- a/contrib/libs/c-ares/INSTALL.md
+++ b/contrib/libs/c-ares/INSTALL.md
@@ -1,5 +1,3 @@
-** This file is adapted from libcurl and not yet fully rewritten for c-ares! **
-
```
___ __ _ _ __ ___ ___
/ __| ___ / _` | '__/ _ \/ __|
@@ -44,7 +42,7 @@ unpacked the source archive):
You probably need to be root when doing the last command.
If you have checked out the sources from the git repository, read the
-[GIT-INFO](GIT_INFO) on how to proceed.
+[GIT-INFO](GIT-INFO) on how to proceed.
Get a full listing of all available configure options by invoking it like:
@@ -309,6 +307,16 @@ first to rebuild every single library your app uses as well as your
app using the debug multithreaded dynamic C runtime.
+### MSYS
+
+Building is supported for native windows via both AutoTools and CMake. When
+building with autotools, you can only build either a shared version or a static
+version (use `--disable-shared` or `--disable-static`). CMake can build both
+simultaneously.
+
+All of the MSYS environments are supported: `MINGW32`, `MINGW64`, `UCRT64`,
+`CLANG32`, `CLANG64`, `CLANGARM64`.
+
### MingW32
Make sure that MinGW32's bin dir is in the search path, for example:
@@ -341,6 +349,26 @@ add `-DCARES_STATICLIB` to your `CFLAGS`. Otherwise the linker will look for
dynamic import symbols.
+DOS
+---
+
+c-ares supports building as a 32bit protected mode application via
+[DJGPP](https://www.delorie.com/djgpp/). It is recommended to use a DJGPP
+cross compiler from [Andrew Wu](https://github.com/andrewwutw/build-djgpp)
+as building directly in a DOS environment can be difficult.
+
+It is required to also have [Watt-32](https://www.watt-32.net/) available
+built using the same compiler. It is recommended to build the latest `master`
+branch from [GitHub](https://github.com/sezero/watt32/tree/master).
+
+Finally, the `DJ_PREFIX` and `WATT_ROOT` environment variables must be set
+appropriately before calling `make Makefile.dj` to build c-ares.
+
+Please refer to our CI
+[GitHub Actions Workflow](https://github.com/c-ares/c-ares/blob/main/.github/workflows/djgpp.yml)
+for a full build example, including building the latest Watt-32 release.
+
+
IBM OS/2
--------
@@ -420,20 +448,25 @@ This is a probably incomplete list of known hardware and operating systems
that c-ares has been compiled for. If you know a system c-ares compiles and
runs on, that isn't listed, please let us know!
- - Alpha Tru64 v5.0 5.1
- - ARM Android 1.5, 2.1, 2.3
- - MIPS IRIX 6.2, 6.5
- - Power AIX 3.2.5, 4.2, 4.3.1, 4.3.2, 5.1, 5.2
- - i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4, 2.6
- - i386 Novell NetWare
- - i386 Windows 95, 98, ME, NT, 2000, XP, 2003
- - x86_64 Linux
+ - Linux (i686, x86_64, AARCH64, and more)
+ - MacOS 10.4+
+ - iOS
+ - Windows 8+ (i686, x86_64)
+ - Android (ARM, AARCH64, x86_64)
+ - FreeBSD
+ - NetBSD
+ - OpenBSD
+ - Solaris (SPARC, x86_64)
+ - AIX (POWER)
+ - Tru64 (Alpha)
+ - IRIX (MIPS)
+ - Novell NetWare (i386)
Useful URLs
===========
- c-ares: https://c-ares.org/
- - MingW: http://www.mingw.org/
- MinGW-w64: http://mingw-w64.sourceforge.net/
+ - MSYS2: https://msys2.org
- OpenWatcom: http://www.openwatcom.org/
diff --git a/contrib/libs/c-ares/LICENSE.md b/contrib/libs/c-ares/LICENSE.md
index e27bae933f..910ddded5c 100644
--- a/contrib/libs/c-ares/LICENSE.md
+++ b/contrib/libs/c-ares/LICENSE.md
@@ -1,5 +1,3 @@
-# c-ares license
-
MIT License
Copyright (c) 1998 Massachusetts Institute of Technology
diff --git a/contrib/libs/c-ares/NEWS b/contrib/libs/c-ares/NEWS
deleted file mode 100644
index 95a2eeea27..0000000000
--- a/contrib/libs/c-ares/NEWS
+++ /dev/null
@@ -1,21 +0,0 @@
-Major changes since:
-* see the CHANGES file
-
-Major changes in release 1.1.1:
-* ares should now compile as C++ code (no longer uses reserved word
- "class").
-* Added SRV support to adig test program.
-* Fixed a few error handling bugs in query processing.
-
-Major changes in release 1.1.0:
-* Added ares_free_string() function so that memory can be freed in the
- same layer as it is allocated, a desirable feature in some
- environments.
-* A few of the ares_dns.h macros are fixed to use the proper bitwise
- operator.
-* Fixed a couple of fenceposts fixed in ares_expand_name()'s
- bounds-checking.
-* In process_timeouts(), extract query->next before calling
- next_server() and possibly freeing the query structure.
-* Casted arguments to ctype macros casted to unsigned char, since not
- all char values are valid inputs to those macros according to ANSI.
diff --git a/contrib/libs/c-ares/README.cares b/contrib/libs/c-ares/README.cares
deleted file mode 100644
index ec809ab948..0000000000
--- a/contrib/libs/c-ares/README.cares
+++ /dev/null
@@ -1,15 +0,0 @@
-c-ares
-======
-
-This package is based on ares 1.1.1 (written by Greg Hudson). Daniel Stenberg
-decided to fork and release a separate project since the original ares author
-didn't want the improvements that were vital for our use of it.
-
-This package is dubbed 'c-ares' since Daniel wanted this for use within the
-curl project (hence the letter C) and it makes a nice pun. c-ares is not API
-compatible with ares: a new name makes that more obvious to the public.
-
-The original libares was distributed at
-ftp://athena-dist.mit.edu:pub/ATHENA/ares (which seems to not be alive
-anymore). A local copy of the original ares package is kept here:
-https://c-ares.org/download/ares-1.1.1.tar.gz
diff --git a/contrib/libs/c-ares/README.md b/contrib/libs/c-ares/README.md
index 5e022a85c1..c32d0677c8 100644
--- a/contrib/libs/c-ares/README.md
+++ b/contrib/libs/c-ares/README.md
@@ -2,12 +2,20 @@
[![Build Status](https://api.cirrus-ci.com/github/c-ares/c-ares.svg?branch=main)](https://cirrus-ci.com/github/c-ares/c-ares)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/aevgc5914tm72pvs/branch/main?svg=true)](https://ci.appveyor.com/project/c-ares/c-ares/branch/main)
-[![Coverage Status](https://coveralls.io/repos/github/c-ares/c-ares/badge.svg)](https://coveralls.io/github/c-ares/c-ares)
+[![Coverage Status](https://coveralls.io/repos/github/c-ares/c-ares/badge.svg?branch=main)](https://coveralls.io/github/c-ares/c-ares?branch=main)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/291/badge)](https://bestpractices.coreinfrastructure.org/projects/291)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/c-ares.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:c-ares)
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=c-ares_c-ares&metric=bugs)](https://sonarcloud.io/summary/new_code?id=c-ares_c-ares)
[![Coverity Scan Status](https://scan.coverity.com/projects/c-ares/badge.svg)](https://scan.coverity.com/projects/c-ares)
+- [Overview](#overview)
+- [Code](#code)
+- [Communication](#communication)
+- [Release Keys](#release-keys)
+ - [Verifying signatures](#verifying-signatures)
+- [Features](#features)
+ - [RFCs and Proposals](#supported-rfcs-and-proposals)
+
## Overview
[c-ares](https://c-ares.org) is a modern DNS (stub) resolver library, written in
C. It provides interfaces for asynchronous queries while trying to abstract the
@@ -39,7 +47,7 @@ best practices in regards to C coding standards.
The full source code and revision history is available in our
[GitHub repository](https://github.com/c-ares/c-ares). Our signed releases
-are available in the ['c-ares' release archives](https://c-ares.org/download/).
+are available in the [release archives](https://c-ares.org/download/).
See the [INSTALL.md](INSTALL.md) file for build information.
@@ -99,3 +107,47 @@ gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 27ED EAF2 2F3A BCEB 50DB 9A12 5CC9 08FD B71E 12C2
gpg: binary signature, digest algorithm SHA512, key algorithm rsa2048
```
+
+## Features
+### Supported RFCs and Proposals
+- [RFC1035](https://datatracker.ietf.org/doc/html/rfc7873).
+ Initial/Base DNS RFC
+- [RFC2671](https://datatracker.ietf.org/doc/html/rfc2671),
+ [RFC6891](https://datatracker.ietf.org/doc/html/rfc6891).
+ EDNS0 option (meta-RR)
+- [RFC3596](https://datatracker.ietf.org/doc/html/rfc3596).
+ IPv6 Address. `AAAA` Record.
+- [RFC2782](https://datatracker.ietf.org/doc/html/rfc2782).
+ Server Selection. `SRV` Record.
+- [RFC3403](https://datatracker.ietf.org/doc/html/rfc3403).
+ Naming Authority Pointer. `NAPTR` Record.
+- [RFC6698](https://datatracker.ietf.org/doc/html/rfc6698).
+ DNS-Based Authentication of Named Entities (DANE) Transport Layer Security (TLS) Protocol.
+ `TLSA` Record.
+- [RFC9460](https://datatracker.ietf.org/doc/html/rfc9460).
+ General Purpose Service Binding, Service Binding type for use with HTTPS.
+ `SVCB` and `HTTPS` Records.
+- [RFC7553](https://datatracker.ietf.org/doc/html/rfc7553).
+ Uniform Resource Identifier. `URI` Record.
+- [RFC6844](https://datatracker.ietf.org/doc/html/rfc6844).
+ Certification Authority Authorization. `CAA` Record.
+- [RFC2535](https://datatracker.ietf.org/doc/html/rfc2535),
+ [RFC2931](https://datatracker.ietf.org/doc/html/rfc2931).
+ `SIG0` Record. Only basic parser, not full implementation.
+- [RFC7873](https://datatracker.ietf.org/doc/html/rfc7873),
+ [RFC9018](https://datatracker.ietf.org/doc/html/rfc9018).
+ DNS Cookie off-path dns poisoning and amplification mitigation.
+- [draft-vixie-dnsext-dns0x20-00](https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00).
+ DNS 0x20 query name case randomization to prevent cache poisioning attacks.
+- [RFC7686](https://datatracker.ietf.org/doc/html/rfc7686).
+ Reject queries for `.onion` domain names with `NXDOMAIN`.
+- [RFC2606](https://datatracker.ietf.org/doc/html/rfc2606),
+ [RFC6761](https://datatracker.ietf.org/doc/html/rfc6761).
+ Special case treatment for `localhost`/`.localhost`.
+- [RFC2308](https://datatracker.ietf.org/doc/html/rfc2308),
+ [RFC9520](https://datatracker.ietf.org/doc/html/rfc9520).
+ Negative Caching of DNS Resolution Failures.
+- [RFC6724](https://datatracker.ietf.org/doc/html/rfc6724).
+ IPv6 address sorting as used by `ares_getaddrinfo()`.
+- [RFC7413](https://datatracker.ietf.org/doc/html/rfc7413).
+ TCP FastOpen (TFO) for 0-RTT TCP Connection Resumption.
diff --git a/contrib/libs/c-ares/RELEASE-NOTES.md b/contrib/libs/c-ares/RELEASE-NOTES.md
index 7d30a3d4e7..b072feb29f 100644
--- a/contrib/libs/c-ares/RELEASE-NOTES.md
+++ b/contrib/libs/c-ares/RELEASE-NOTES.md
@@ -1,33 +1,33 @@
-## c-ares version 1.30.0 - June 7 2024
+## c-ares version 1.33.0 - August 2 2024
-This is a maintenance and bugfix release.
+This is a feature and bugfix release.
Features:
-
-* Basic support for SIG RR record (RFC 2931 / RFC 2535) [PR #773](https://github.com/c-ares/c-ares/pull/773)
+* Add DNS cookie support (RFC7873 + RFC9018) to help prevent off-path cache
+ poisoning attacks. [PR #833](https://github.com/c-ares/c-ares/pull/833)
+* Implement TCP FastOpen (TFO) RFC7413, which will make TCP reconnects 0-RTT
+ on supported systems. [PR #840](https://github.com/c-ares/c-ares/pull/840)
Changes:
-
-* Validation that DNS strings can only consist of printable ascii characters
- otherwise will trigger a parse failure.
- [75de16c](https://github.com/c-ares/c-ares/commit/75de16c) and
- [40fb125](https://github.com/c-ares/c-ares/commit/40fb125)
-* Windows: use `GetTickCount64()` for a monotonic timer that does not wrap. [1dff8f6](https://github.com/c-ares/c-ares/commit/1dff8f6)
+* Reorganize source tree. [PR #822](https://github.com/c-ares/c-ares/pull/822)
+* Refactoring of connection handling to prevent code duplication.
+ [PR #839](https://github.com/c-ares/c-ares/pull/839)
+* New dynamic array data structure to prevent simple logic flaws in array
+ handling in various code paths.
+ [PR #841](https://github.com/c-ares/c-ares/pull/841)
Bugfixes:
+* `ares_destroy()` race condition during shutdown due to missing lock.
+ [PR #831](https://github.com/c-ares/c-ares/pull/831)
+* Android: Preserve thread name after attaching it to JVM.
+ [PR #838](https://github.com/c-ares/c-ares/pull/838)
+* Windows UWP (Store) support fix.
+ [PR #845](https://github.com/c-ares/c-ares/pull/845)
-* QueryCache: Fix issue where purging on server changes wasn't working. [a6c8fe6](https://github.com/c-ares/c-ares/commit/a6c8fe6)
-* Windows: Fix Y2K38 issue by creating our own `ares_timeval_t` datatype. [PR #772](https://github.com/c-ares/c-ares/pull/772)
-* Fix packaging issue affecting MacOS due to a missing header. [55afad6](https://github.com/c-ares/c-ares/commit/55afad6)
-* MacOS: Fix UBSAN warnings that are likely meaningless due to alignment issues
- in new MacOS config reader.
-* Android: arm 32bit build failure due to missing symbol. [d1722e6](https://github.com/c-ares/c-ares/commit/d1722e6)
Thanks go to these friendly people for their efforts and contributions for this
release:
* Brad House (@bradh352)
-* Daniel Stenberg (@bagder)
-
-
+* Yauheni Khnykin (@Hsilgos)
diff --git a/contrib/libs/c-ares/RELEASE-PROCEDURE.md b/contrib/libs/c-ares/RELEASE-PROCEDURE.md
index 1abc9a3822..c686a9f97b 100644
--- a/contrib/libs/c-ares/RELEASE-PROCEDURE.md
+++ b/contrib/libs/c-ares/RELEASE-PROCEDURE.md
@@ -4,49 +4,74 @@ c-ares release procedure - how to do a release
in the source code repo
-----------------------
-- edit `RELEASE-NOTES` to be accurate
-
+- edit `RELEASE-NOTES.md` to be accurate
- edit `configure.ac`'s `CARES_VERSION_INFO`, and `CMakeLists.txt`'s
`CARES_LIB_VERSIONINFO` set to the same value to denote the current shared
object versioning.
-
- edit `include/ares_version.h` and set `ARES_VERSION_*` definitions to reflect
the current version.
-
-- make sure all relevant changes are committed on the master branch
-
-- tag the git repo in this style: `git tag -a cares-1_14_0` -a annotates the
- tag and we use underscores instead of dots in the version number.
-
-- run "./maketgz 1.14.0" to build the release tarball. It is important that
- you run this on a machine with the correct set of autotools etc installed
- as this is what then will be shipped and used by most users on *nix like
- systems.
-
-- push the git commits and the new tag
-
-- gpg sign the tarball
-
-- upload the resulting files to https://c-ares.org/download/
+- All release tags need to be made off a release branch named `vX.Y`, where `X`
+ is the Major version number, and `Y` is the minor version number. We also
+ want to create an empty commit in the branch with a message, this ensures
+ when we tag a release from the branch, it gets tied to the branch itself and
+ not a commit which may be shared across this branch and `main`. Create the
+ branch like:
+```
+BRANCH=1.32
+git pull && \
+git checkout main && \
+git checkout -b v${BRANCH} main && \
+git commit --allow-empty -m "Created release branch v${BRANCH}" && \
+git push -u origin v${BRANCH}
+```
+- make sure all relevant changes are committed on the release branch
+- Create a signed tag for the release using a name of `vX.Y.Z` where `X` is the
+ Major version number, `Y` is the minor version number, and `Z` is the release.
+ This tag needs to be created from the release branch, for example:
+```
+BRANCH=1.32
+RELEASE=1.32.0
+git checkout v${BRANCH} && \
+git pull && \
+git tag -s v${RELEASE} -m 'c-ares release v${RELEASE}' v${BRANCH} && \
+git push origin --tags
+```
+- Create the release tarball using `make dist`, it is best to check out the
+ specific tag fresh and build from that:
+```
+RELEASE=1.32.0
+git clone --depth 1 --branch v${RELEASE} https://github.com/c-ares/c-ares c-ares-${RELEASE} && \
+cd c-ares-${RELEASE} && \
+autoreconf -fi && \
+./configure && \
+make && \
+make dist VERSION=${RELEASE}
+```
+- GPG sign the release with a detached signature. Valid signing keys are currently:
+ - Daniel Stenberg <daniel@haxx.se> - 27EDEAF22F3ABCEB50DB9A125CC908FDB71E12C2
+ - Brad House <brad@brad-house.com> - DA7D64E4C82C6294CB73A20E22E3D13B5411B7CA
+```
+gpg -ab c-ares-${RELEASE}.tar.gz
+```
+- Create a new release on GitHub using the `RELEASE-NOTES.md` as the body.
+ Upload the generated tarball and signature as an artifact.
in the c-ares-www repo
----------------------
-- edit `index.t` (version number and date),
-
-- edit `changelog.t` (add the new release in there)
-
+- edit `index.md`, change version and date in frontmatter
+- edit `changelog.md`, copy `RELEASE-NOTES.md` content
+- edit `download.md`, add new version and date in frontmatter
- commit all local changes
-
-- tag the repo with the same tag as used for the source repo
-
-- push the git commits and the new tag
+- push the git commits
inform
------
-- send an email to the c-ares mailing list. Insert the RELEASE-NOTES into the
+- send an email to the c-ares mailing list. Insert the RELEASE-NOTES.md into the
mail.
+- Create an announcement in the GitHub Discussions Announcements section:
+ https://github.com/c-ares/c-ares/discussions/categories/announcements
celebrate
---------
diff --git a/contrib/libs/c-ares/include/ares.h b/contrib/libs/c-ares/include/ares.h
index 46cdf9fa8e..adb2fe8419 100644
--- a/contrib/libs/c-ares/include/ares.h
+++ b/contrib/libs/c-ares/include/ares.h
@@ -30,18 +30,43 @@
#include "ares_version.h" /* c-ares version defines */
#include "ares_build.h" /* c-ares build definitions */
-#include "ares_rules.h" /* c-ares rules enforcement */
-/*
- * Define WIN32 when build target is Win32 API
- */
+#if defined(_WIN32)
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
+#endif
+
+#ifdef CARES_HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef CARES_HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+#ifdef CARES_HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && \
- !defined(__SYMBIAN32__)
-# define WIN32
+#ifdef CARES_HAVE_WINSOCK2_H
+# include <winsock2.h>
+/* To aid with linking against a static c-ares build, lets tell the microsoft
+ * compiler to pull in needed dependencies */
+# ifdef _MSC_VER
+# pragma comment(lib, "ws2_32")
+# pragma comment(lib, "advapi32")
+# pragma comment(lib, "iphlpapi")
+# endif
+#endif
+
+#ifdef CARES_HAVE_WS2TCPIP_H
+# include <ws2tcpip.h>
#endif
-#include <sys/types.h>
+#ifdef CARES_HAVE_WINDOWS_H
+# include <windows.h>
+#endif
/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
libc5-based Linux systems. Only include it on system that are known to
@@ -52,43 +77,26 @@
defined(__QNXNTO__) || defined(__MVS__) || defined(__HAIKU__)
# include <sys/select.h>
#endif
+
#if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
# include <sys/bsdskt.h>
#endif
-#if defined(WATT32)
+#if !defined(_WIN32)
# include <netinet/in.h>
-# include <sys/socket.h>
+#endif
+
+#ifdef WATT32
# include <tcp.h>
-#elif defined(_WIN32_WCE)
-# ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-# endif
-# include <windows.h>
-# include <winsock.h>
-#elif defined(WIN32)
-# ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-# endif
-# include <windows.h>
-# include <winsock2.h>
-# include <ws2tcpip.h>
-/* To aid with linking against a static c-ares build, lets tell the microsoft
- * compiler to pull in needed dependencies */
-# ifdef _MSC_VER
-# pragma comment(lib, "ws2_32")
-# pragma comment(lib, "advapi32")
-# pragma comment(lib, "iphlpapi")
-# endif
-#else
-# include <sys/socket.h>
-# include <netinet/in.h>
#endif
#if defined(ANDROID) || defined(__ANDROID__)
# include <jni.h>
#endif
+typedef CARES_TYPEOF_ARES_SOCKLEN_T ares_socklen_t;
+typedef CARES_TYPEOF_ARES_SSIZE_T ares_ssize_t;
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -230,6 +238,7 @@ typedef enum {
#define ARES_FLAG_NOCHECKRESP (1 << 7)
#define ARES_FLAG_EDNS (1 << 8)
#define ARES_FLAG_NO_DFLT_SVR (1 << 9)
+#define ARES_FLAG_DNS0x20 (1 << 10)
/* Option mask values */
#define ARES_OPT_FLAGS (1 << 0)
@@ -315,7 +324,7 @@ typedef enum {
*/
#ifndef ares_socket_typedef
-# ifdef WIN32
+# if defined(_WIN32) && !defined(WATT32)
typedef SOCKET ares_socket_t;
# define ARES_SOCKET_BAD INVALID_SOCKET
# else
diff --git a/contrib/libs/c-ares/include/ares_build-linux.h b/contrib/libs/c-ares/include/ares_build-linux.h
index bf3692fbbe..25bf2193b8 100644
--- a/contrib/libs/c-ares/include/ares_build-linux.h
+++ b/contrib/libs/c-ares/include/ares_build-linux.h
@@ -13,10 +13,10 @@
* for C-Ares */
#define CARES_HAVE_SYS_TYPES_H
#define CARES_HAVE_SYS_SOCKET_H
+#define CARES_HAVE_SYS_SELECT_H
/* #undef CARES_HAVE_WINDOWS_H */
/* #undef CARES_HAVE_WS2TCPIP_H */
/* #undef CARES_HAVE_WINSOCK2_H */
-/* #undef CARES_HAVE_WINDOWS_H */
#define CARES_HAVE_ARPA_NAMESER_H
#define CARES_HAVE_ARPA_NAMESER_COMPAT_H
@@ -28,6 +28,10 @@
# include <sys/socket.h>
#endif
+#ifdef CARES_HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+
#ifdef CARES_HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
@@ -40,8 +44,4 @@
# include <windows.h>
#endif
-
-typedef CARES_TYPEOF_ARES_SOCKLEN_T ares_socklen_t;
-typedef CARES_TYPEOF_ARES_SSIZE_T ares_ssize_t;
-
#endif /* __CARES_BUILD_H */
diff --git a/contrib/libs/c-ares/include/ares_dns_record.h b/contrib/libs/c-ares/include/ares_dns_record.h
index 5533929f65..2896eab24b 100644
--- a/contrib/libs/c-ares/include/ares_dns_record.h
+++ b/contrib/libs/c-ares/include/ares_dns_record.h
@@ -94,7 +94,7 @@ typedef enum {
ARES_OPCODE_IQUERY = 1, /*!< Inverse query. Obsolete. */
ARES_OPCODE_STATUS = 2, /*!< Name server status query */
ARES_OPCODE_NOTIFY = 4, /*!< Zone change notification (RFC 1996) */
- ARES_OPCODE_UPDATE = 5, /*!< Zone update message (RFC2136) */
+ ARES_OPCODE_UPDATE = 5 /*!< Zone update message (RFC2136) */
} ares_dns_opcode_t;
/*! DNS Header flags */
@@ -108,7 +108,7 @@ typedef enum {
ARES_FLAG_AD = 1 << 5, /*!< RFC 2065. Authentic Data bit indicates in a
* response that the data included has been verified by
* the server providing it */
- ARES_FLAG_CD = 1 << 6, /*!< RFC 2065. Checking Disabled bit indicates in a
+ ARES_FLAG_CD = 1 << 6 /*!< RFC 2065. Checking Disabled bit indicates in a
* query that non-verified data is acceptable to the
* resolver sending the query. */
} ares_dns_flags_t;
@@ -152,7 +152,7 @@ typedef enum {
ARES_RCODE_BADNAME = 20, /*!< RFC 2930. Duplicate Key Name */
ARES_RCODE_BADALG = 21, /*!< RFC 2930. Algorithm not supported */
ARES_RCODE_BADTRUNC = 22, /*!< RFC 8945. Bad Truncation */
- ARES_RCODE_BADCOOKIE = 23, /*!< RVC 7973. Bad/missing Server Cookie */
+ ARES_RCODE_BADCOOKIE = 23 /*!< RFC 7873. Bad/missing Server Cookie */
} ares_dns_rcode_t;
/*! Data types used */
@@ -171,6 +171,9 @@ typedef enum {
* length) */
ARES_DATATYPE_OPT = 10, /*!< Array of options. 16bit identifier, BIN
* data. */
+ ARES_DATATYPE_ABINP = 11 /*!< Array of binary data, likely printable.
+ * Guaranteed to have a NULL terminator for
+ * convenience (not included in length) */
} ares_dns_datatype_t;
/*! Keys used for all RR Types. We take the record type and multiply by 100
@@ -207,7 +210,7 @@ typedef enum {
ARES_RR_MX_PREFERENCE = (ARES_REC_TYPE_MX * 100) + 1,
/*! MX Record. Exchange, domain. Datatype: NAME */
ARES_RR_MX_EXCHANGE = (ARES_REC_TYPE_MX * 100) + 2,
- /*! TXT Record. Data. Datatype: BINP */
+ /*! TXT Record. Data. Datatype: ABINP */
ARES_RR_TXT_DATA = (ARES_REC_TYPE_TXT * 100) + 1,
/*! SIG Record. Type Covered. Datatype: U16 */
ARES_RR_SIG_TYPE_COVERED = (ARES_REC_TYPE_SIG * 100) + 1,
@@ -292,7 +295,7 @@ typedef enum {
/*! RAW Record. RR Type. Datatype: U16 */
ARES_RR_RAW_RR_TYPE = (ARES_REC_TYPE_RAW_RR * 100) + 1,
/*! RAW Record. RR Data. Datatype: BIN */
- ARES_RR_RAW_RR_DATA = (ARES_REC_TYPE_RAW_RR * 100) + 2,
+ ARES_RR_RAW_RR_DATA = (ARES_REC_TYPE_RAW_RR * 100) + 2
} ares_dns_rr_key_t;
/*! TLSA Record ARES_RR_TLSA_CERT_USAGE known values */
@@ -372,7 +375,7 @@ typedef enum {
/*! RFC 8145. Signaling Trust Anchor Knowledge in DNSSEC */
ARES_OPT_PARAM_EDNS_KEY_TAG = 14,
/*! RFC 8914. Extended ERROR code and message */
- ARES_OPT_PARAM_EXTENDED_DNS_ERROR = 15,
+ ARES_OPT_PARAM_EXTENDED_DNS_ERROR = 15
} ares_opt_param_t;
/*! Data type for option records for keys like ARES_RR_OPT_OPTIONS and
@@ -600,6 +603,15 @@ CARES_EXTERN void ares_dns_record_destroy(ares_dns_record_t *dnsrec);
CARES_EXTERN unsigned short
ares_dns_record_get_id(const ares_dns_record_t *dnsrec);
+/*! Overwrite the DNS query id
+ *
+ * \param[in] dnsrec Initialized record object
+ * \param[in] id DNS query id
+ * \return ARES_TRUE on success, ARES_FALSE on usage error
+ */
+CARES_EXTERN ares_bool_t ares_dns_record_set_id(ares_dns_record_t *dnsrec,
+ unsigned short id);
+
/*! Get the DNS Record Flags
*
* \param[in] dnsrec Initialized record object
@@ -863,6 +875,34 @@ CARES_EXTERN ares_status_t ares_dns_rr_set_bin(ares_dns_rr_t *dns_rr,
const unsigned char *val,
size_t len);
+/*! Add binary array value (ABINP) data for specified resource record and key.
+ * Can only be used on keys with datatype ARES_DATATYPE_ABINP. The value will
+ * Be added as the last element in the array.
+ *
+ * \param[in] dns_rr Pointer to resource record
+ * \param[in] key DNS Resource Record Key
+ * \param[in] val Pointer to binary data.
+ * \param[in] len Length of binary data
+ * \return ARES_SUCCESS on success
+ */
+CARES_EXTERN ares_status_t ares_dns_rr_add_abin(ares_dns_rr_t *dns_rr,
+ ares_dns_rr_key_t key,
+ const unsigned char *val,
+ size_t len);
+
+/*! Delete binary array value (ABINP) data for specified resource record and
+ * key by specified index. Can only be used on keys with datatype
+ * ARES_DATATYPE_ABINP. The value at the index will be deleted.
+ *
+ * \param[in] dns_rr Pointer to resource record
+ * \param[in] key DNS Resource Record Key
+ * \param[in] idx Index to delete
+ * \return ARES_SUCCESS on success
+ */
+CARES_EXTERN ares_status_t ares_dns_rr_del_abin(ares_dns_rr_t *dns_rr,
+ ares_dns_rr_key_t key,
+ size_t idx);
+
/*! Set the option for the RR
*
* \param[in] dns_rr Pointer to resource record
@@ -878,6 +918,17 @@ CARES_EXTERN ares_status_t ares_dns_rr_set_opt(ares_dns_rr_t *dns_rr,
const unsigned char *val,
size_t val_len);
+/*! Delete the option for the RR by id
+ *
+ * \param[in] dns_rr Pointer to resource record
+ * \param[in] key DNS Resource Record Key
+ * \param[in] opt Option record key id.
+ * \return ARES_SUCCESS if removed, ARES_ENOTFOUND if not found
+ */
+CARES_EXTERN ares_status_t ares_dns_rr_del_opt_byid(ares_dns_rr_t *dns_rr,
+ ares_dns_rr_key_t key,
+ unsigned short opt);
+
/*! Retrieve a pointer to the ipv4 address. Can only be used on keys with
* datatype ARES_DATATYPE_INADDR.
*
@@ -939,8 +990,9 @@ CARES_EXTERN unsigned int ares_dns_rr_get_u32(const ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key);
/*! Retrieve a pointer to the binary data. Can only be used on keys with
- * datatype ARES_DATATYPE_BIN or ARES_DATATYPE_BINP. If BINP, the data is
- * guaranteed to have a NULL terminator which is NOT included in the length.
+ * datatype ARES_DATATYPE_BIN, ARES_DATATYPE_BINP, or ARES_DATATYPE_ABINP.
+ * If BINP or ABINP, the data is guaranteed to have a NULL terminator which
+ * is NOT included in the length.
*
* \param[in] dns_rr Pointer to resource record
* \param[in] key DNS Resource Record Key
@@ -951,6 +1003,33 @@ CARES_EXTERN const unsigned char *
ares_dns_rr_get_bin(const ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
size_t *len);
+/*! Retrieve the count of the array of stored binary values. Can only be used on
+ * keys with datatype ARES_DATATYPE_ABINP.
+ *
+ * \param[in] dns_rr Pointer to resource record
+ * \param[in] key DNS Resource Record Key
+ * \return count of values
+ */
+CARES_EXTERN size_t ares_dns_rr_get_abin_cnt(const ares_dns_rr_t *dns_rr,
+ ares_dns_rr_key_t key);
+
+/*! Retrieve a pointer to the binary array data from the specified index. Can
+ * only be used on keys with datatype ARES_DATATYPE_ABINP. If ABINP, the data
+ * is guaranteed to have a NULL terminator which is NOT included in the length.
+ * If want all array membersconcatenated, may use ares_dns_rr_get_bin()
+ * instead.
+ *
+ * \param[in] dns_rr Pointer to resource record
+ * \param[in] key DNS Resource Record Key
+ * \param[in] idx Index of value to retrieve
+ * \param[out] len Length of binary data returned
+ * \return pointer binary data or NULL on error
+ */
+CARES_EXTERN const unsigned char *
+ ares_dns_rr_get_abin(const ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
+ size_t idx, size_t *len);
+
+
/*! Retrieve the number of options stored for the RR.
*
* \param[in] dns_rr Pointer to resource record
diff --git a/contrib/libs/c-ares/include/ares_rules.h b/contrib/libs/c-ares/include/ares_rules.h
deleted file mode 100644
index 450dc8ab2d..0000000000
--- a/contrib/libs/c-ares/include/ares_rules.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* MIT License
- *
- * Copyright (c) 2009 Daniel Stenberg
- *
- * 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
- */
-#ifndef __CARES_RULES_H
-#define __CARES_RULES_H
-
-/* ================================================================ */
-/* COMPILE TIME SANITY CHECKS */
-/* ================================================================ */
-
-/*
- * NOTE 1:
- * -------
- *
- * All checks done in this file are intentionally placed in a public
- * header file which is pulled by ares.h when an application is
- * being built using an already built c-ares library. Additionally
- * this file is also included and used when building the library.
- *
- * If compilation fails on this file it is certainly sure that the
- * problem is elsewhere. It could be a problem in the ares_build.h
- * header file, or simply that you are using different compilation
- * settings than those used to build the library.
- *
- * Nothing in this file is intended to be modified or adjusted by the
- * c-ares library user nor by the c-ares library builder.
- *
- * Do not deactivate any check, these are done to make sure that the
- * library is properly built and used.
- *
- * You can find further help on the c-ares development mailing list:
- * http://lists.haxx.se/listinfo/c-ares/
- *
- * NOTE 2
- * ------
- *
- * Some of the following compile time checks are based on the fact
- * that the dimension of a constant array can not be a negative one.
- * In this way if the compile time verification fails, the compilation
- * will fail issuing an error. The error description wording is compiler
- * dependent but it will be quite similar to one of the following:
- *
- * "negative subscript or subscript is too large"
- * "array must have at least one element"
- * "-1 is an illegal array size"
- * "size of array is negative"
- *
- * If you are building an application which tries to use an already
- * built c-ares library and you are getting this kind of errors on
- * this file, it is a clear indication that there is a mismatch between
- * how the library was built and how you are trying to use it for your
- * application. Your already compiled or binary library provider is the
- * only one who can give you the details you need to properly use it.
- */
-
-/*
- * Verify that some macros are actually defined.
- */
-
-#ifndef CARES_TYPEOF_ARES_SOCKLEN_T
-# error "CARES_TYPEOF_ARES_SOCKLEN_T definition is missing!"
-Error Compilation_aborted_CARES_TYPEOF_ARES_SOCKLEN_T_is_missing
-#endif
-
-/*
- * Macros private to this header file.
- */
-
-#define CareschkszEQ(t, s) sizeof(t) == s ? 1 : -1
-
-#define CareschkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1
-
- /*
- * Verify that the size previously defined and expected for
- * ares_socklen_t is actually the same as the one reported
- * by sizeof() at compile time.
- */
-
- typedef char __cares_rule_02__[CareschkszEQ(
- ares_socklen_t, sizeof(CARES_TYPEOF_ARES_SOCKLEN_T))];
-
-/*
- * Verify at compile time that the size of ares_socklen_t as reported
- * by sizeof() is greater or equal than the one reported for int for
- * the current compilation.
- */
-
-typedef char __cares_rule_03__[CareschkszGE(ares_socklen_t, int)];
-
-/* ================================================================ */
-/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */
-/* ================================================================ */
-
-/*
- * Get rid of macros private to this header file.
- */
-
-#undef CareschkszEQ
-#undef CareschkszGE
-
-/*
- * Get rid of macros not intended to exist beyond this point.
- */
-
-#undef CARES_PULL_WS2TCPIP_H
-#undef CARES_PULL_SYS_TYPES_H
-#undef CARES_PULL_SYS_SOCKET_H
-
-#undef CARES_TYPEOF_ARES_SOCKLEN_T
-
-#endif /* __CARES_RULES_H */
diff --git a/contrib/libs/c-ares/include/ares_version.h b/contrib/libs/c-ares/include/ares_version.h
index e791568e6b..fef66b7397 100644
--- a/contrib/libs/c-ares/include/ares_version.h
+++ b/contrib/libs/c-ares/include/ares_version.h
@@ -31,19 +31,14 @@
#define ARES_COPYRIGHT "2004 - 2024 Daniel Stenberg, <daniel@haxx.se>."
#define ARES_VERSION_MAJOR 1
-#define ARES_VERSION_MINOR 30
+#define ARES_VERSION_MINOR 33
#define ARES_VERSION_PATCH 0
#define ARES_VERSION \
((ARES_VERSION_MAJOR << 16) | (ARES_VERSION_MINOR << 8) | \
(ARES_VERSION_PATCH))
-#define ARES_VERSION_STR "1.30.0"
+#define ARES_VERSION_STR "1.33.0"
-#if (ARES_VERSION >= 0x010700)
-# define CARES_HAVE_ARES_LIBRARY_INIT 1
-# define CARES_HAVE_ARES_LIBRARY_CLEANUP 1
-#else
-# undef CARES_HAVE_ARES_LIBRARY_INIT
-# undef CARES_HAVE_ARES_LIBRARY_CLEANUP
-#endif
+#define CARES_HAVE_ARES_LIBRARY_INIT 1
+#define CARES_HAVE_ARES_LIBRARY_CLEANUP 1
#endif
diff --git a/contrib/libs/c-ares/src/lib/ares__addrinfo2hostent.c b/contrib/libs/c-ares/src/lib/ares__addrinfo2hostent.c
index 95717890c2..f7b6d1edd2 100644
--- a/contrib/libs/c-ares/src/lib/ares__addrinfo2hostent.c
+++ b/contrib/libs/c-ares/src/lib/ares__addrinfo2hostent.c
@@ -27,7 +27,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -39,8 +39,6 @@
# include <arpa/inet.h>
#endif
-#include "ares_nameser.h"
-
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
@@ -49,10 +47,6 @@
# include <limits.h>
#endif
-#include "ares.h"
-#include "ares_dns.h"
-#include "ares_inet_net_pton.h"
-#include "ares_private.h"
ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
struct hostent **host)
@@ -67,7 +61,7 @@ ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
size_t i;
if (ai == NULL || host == NULL) {
- return ARES_EBADQUERY;
+ return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Use the first node of the response as the family, since hostent can only
@@ -78,12 +72,12 @@ ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
}
if (family != AF_INET && family != AF_INET6) {
- return ARES_EBADQUERY;
+ return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */
}
*host = ares_malloc(sizeof(**host));
if (!(*host)) {
- goto enomem;
+ goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */
}
memset(*host, 0, sizeof(**host));
@@ -105,7 +99,7 @@ ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
aliases = ares_malloc((naliases + 1) * sizeof(char *));
if (!aliases) {
- goto enomem;
+ goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */
}
(*host)->h_aliases = aliases;
memset(aliases, 0, (naliases + 1) * sizeof(char *));
@@ -118,7 +112,7 @@ ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
}
aliases[alias] = ares_strdup(next_cname->alias);
if (!aliases[alias]) {
- goto enomem;
+ goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */
}
alias++;
}
@@ -127,7 +121,7 @@ ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
(*host)->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
if (!(*host)->h_addr_list) {
- goto enomem;
+ goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */
}
memset((*host)->h_addr_list, 0, (naddrs + 1) * sizeof(char *));
@@ -135,12 +129,12 @@ ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
if (ai->cnames) {
(*host)->h_name = ares_strdup(ai->cnames->name);
if ((*host)->h_name == NULL && ai->cnames->name) {
- goto enomem;
+ goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */
}
} else {
(*host)->h_name = ares_strdup(ai->name);
if ((*host)->h_name == NULL && ai->name) {
- goto enomem;
+ goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -157,7 +151,7 @@ ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
if (naddrs) {
addrs = ares_malloc(naddrs * (size_t)(*host)->h_length);
if (!addrs) {
- goto enomem;
+ goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */
}
i = 0;
@@ -167,16 +161,16 @@ ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
}
(*host)->h_addr_list[i] = addrs + (i * (size_t)(*host)->h_length);
if (family == AF_INET6) {
- memcpy(
- (*host)->h_addr_list[i],
- &(CARES_INADDR_CAST(struct sockaddr_in6 *, next->ai_addr)->sin6_addr),
- (size_t)(*host)->h_length);
+ memcpy((*host)->h_addr_list[i],
+ &(CARES_INADDR_CAST(const struct sockaddr_in6 *, next->ai_addr)
+ ->sin6_addr),
+ (size_t)(*host)->h_length);
}
if (family == AF_INET) {
- memcpy(
- (*host)->h_addr_list[i],
- &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
- (size_t)(*host)->h_length);
+ memcpy((*host)->h_addr_list[i],
+ &(CARES_INADDR_CAST(const struct sockaddr_in *, next->ai_addr)
+ ->sin_addr),
+ (size_t)(*host)->h_length);
}
++i;
}
@@ -194,10 +188,12 @@ ares_status_t ares__addrinfo2hostent(const struct ares_addrinfo *ai, int family,
return ARES_SUCCESS;
+/* LCOV_EXCL_START: OutOfMemory */
enomem:
ares_free_hostent(*host);
*host = NULL;
return ARES_ENOMEM;
+ /* LCOV_EXCL_STOP */
}
ares_status_t ares__addrinfo2addrttl(const struct ares_addrinfo *ai, int family,
@@ -211,23 +207,23 @@ ares_status_t ares__addrinfo2addrttl(const struct ares_addrinfo *ai, int family,
int cname_ttl = INT_MAX;
if (family != AF_INET && family != AF_INET6) {
- return ARES_EBADQUERY;
+ return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (ai == NULL || naddrttls == NULL) {
- return ARES_EBADQUERY;
+ return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (family == AF_INET && addrttls == NULL) {
- return ARES_EBADQUERY;
+ return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (family == AF_INET6 && addr6ttls == NULL) {
- return ARES_EBADQUERY;
+ return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (req_naddrttls == 0) {
- return ARES_EBADQUERY;
+ return ARES_EBADQUERY; /* LCOV_EXCL_LINE: DefensiveCoding */
}
*naddrttls = 0;
@@ -256,20 +252,20 @@ ares_status_t ares__addrinfo2addrttl(const struct ares_addrinfo *ai, int family,
addr6ttls[*naddrttls].ttl = next->ai_ttl;
}
- memcpy(
- &addr6ttls[*naddrttls].ip6addr,
- &(CARES_INADDR_CAST(struct sockaddr_in6 *, next->ai_addr)->sin6_addr),
- sizeof(struct ares_in6_addr));
+ memcpy(&addr6ttls[*naddrttls].ip6addr,
+ &(CARES_INADDR_CAST(const struct sockaddr_in6 *, next->ai_addr)
+ ->sin6_addr),
+ sizeof(struct ares_in6_addr));
} else {
if (next->ai_ttl > cname_ttl) {
addrttls[*naddrttls].ttl = cname_ttl;
} else {
addrttls[*naddrttls].ttl = next->ai_ttl;
}
- memcpy(
- &addrttls[*naddrttls].ipaddr,
- &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
- sizeof(struct in_addr));
+ memcpy(&addrttls[*naddrttls].ipaddr,
+ &(CARES_INADDR_CAST(const struct sockaddr_in *, next->ai_addr)
+ ->sin_addr),
+ sizeof(struct in_addr));
}
(*naddrttls)++;
}
diff --git a/contrib/libs/c-ares/src/lib/ares__addrinfo_localhost.c b/contrib/libs/c-ares/src/lib/ares__addrinfo_localhost.c
index baa9b37212..e98dd4e277 100644
--- a/contrib/libs/c-ares/src/lib/ares__addrinfo_localhost.c
+++ b/contrib/libs/c-ares/src/lib/ares__addrinfo_localhost.c
@@ -25,7 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -37,11 +37,10 @@
# include <arpa/inet.h>
#endif
-#if defined(_WIN32) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600
-# include <ws2ipdef.h>
-#endif
-
#if defined(USE_WINSOCK)
+# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600
+# include <ws2ipdef.h>
+# endif
# if defined(HAVE_IPHLPAPI_H)
# include <iphlpapi.h>
# endif
@@ -50,10 +49,6 @@
# endif
#endif
-#include "ares.h"
-#include "ares_inet_net_pton.h"
-#include "ares_private.h"
-
ares_status_t ares_append_ai_node(int aftype, unsigned short port,
unsigned int ttl, const void *adata,
struct ares_addrinfo_node **nodes)
@@ -62,7 +57,7 @@ ares_status_t ares_append_ai_node(int aftype, unsigned short port,
node = ares__append_addrinfo_node(nodes);
if (!node) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
memset(node, 0, sizeof(*node));
@@ -70,7 +65,7 @@ ares_status_t ares_append_ai_node(int aftype, unsigned short port,
if (aftype == AF_INET) {
struct sockaddr_in *sin = ares_malloc(sizeof(*sin));
if (!sin) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
memset(sin, 0, sizeof(*sin));
@@ -88,7 +83,7 @@ ares_status_t ares_append_ai_node(int aftype, unsigned short port,
if (aftype == AF_INET6) {
struct sockaddr_in6 *sin6 = ares_malloc(sizeof(*sin6));
if (!sin6) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
memset(sin6, 0, sizeof(*sin6));
@@ -117,7 +112,7 @@ static ares_status_t
ares_inet_pton(AF_INET6, "::1", &addr6);
status = ares_append_ai_node(AF_INET6, port, 0, &addr6, nodes);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -126,7 +121,7 @@ static ares_status_t
ares_inet_pton(AF_INET, "127.0.0.1", &addr4);
status = ares_append_ai_node(AF_INET, port, 0, &addr4, nodes);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -137,11 +132,11 @@ static ares_status_t
ares__system_loopback_addrs(int aftype, unsigned short port,
struct ares_addrinfo_node **nodes)
{
-#if defined(_WIN32) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 && \
+#if defined(USE_WINSOCK) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 && \
!defined(__WATCOMC__)
PMIB_UNICASTIPADDRESS_TABLE table;
unsigned int i;
- ares_status_t status;
+ ares_status_t status = ARES_ENOTFOUND;
*nodes = NULL;
@@ -209,13 +204,13 @@ ares_status_t ares__addrinfo_localhost(const char *name, unsigned short port,
case AF_INET6:
case AF_UNSPEC:
break;
- default:
- return ARES_EBADFAMILY;
+ default: /* LCOV_EXCL_LINE: DefensiveCoding */
+ return ARES_EBADFAMILY; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ai->name = ares_strdup(name);
if (!ai->name) {
- goto enomem;
+ goto enomem; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__system_loopback_addrs(hints->ai_family, port, &nodes);
@@ -228,9 +223,11 @@ ares_status_t ares__addrinfo_localhost(const char *name, unsigned short port,
return status;
+/* LCOV_EXCL_START: OutOfMemory */
enomem:
ares__freeaddrinfo_nodes(nodes);
ares_free(ai->name);
ai->name = NULL;
return ARES_ENOMEM;
+ /* LCOV_EXCL_STOP */
}
diff --git a/contrib/libs/c-ares/src/lib/ares__close_sockets.c b/contrib/libs/c-ares/src/lib/ares__close_sockets.c
index 03ba4abf89..27bbaacf0e 100644
--- a/contrib/libs/c-ares/src/lib/ares__close_sockets.c
+++ b/contrib/libs/c-ares/src/lib/ares__close_sockets.c
@@ -25,33 +25,33 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-
-#include "ares.h"
#include "ares_private.h"
#include <assert.h>
-static void ares__requeue_queries(struct server_connection *conn)
+static void ares__requeue_queries(ares_conn_t *conn,
+ ares_status_t requeue_status)
{
- struct query *query;
- ares_timeval_t now = ares__tvnow();
+ ares_query_t *query;
+ ares_timeval_t now;
+
+ ares__tvnow(&now);
while ((query = ares__llist_first_val(conn->queries_to_conn)) != NULL) {
- ares__requeue_query(query, &now);
+ ares__requeue_query(query, &now, requeue_status, ARES_TRUE);
}
}
-void ares__close_connection(struct server_connection *conn)
+void ares__close_connection(ares_conn_t *conn, ares_status_t requeue_status)
{
- struct server_state *server = conn->server;
- ares_channel_t *channel = server->channel;
+ ares_server_t *server = conn->server;
+ ares_channel_t *channel = server->channel;
/* Unlink */
ares__llist_node_claim(
ares__htable_asvp_get_direct(channel->connnode_by_socket, conn->fd));
ares__htable_asvp_remove(channel->connnode_by_socket, conn->fd);
- if (conn->is_tcp) {
+ if (conn->flags & ARES_CONN_FLAG_TCP) {
/* Reset any existing input and output buffer. */
ares__buf_consume(server->tcp_parser, ares__buf_len(server->tcp_parser));
ares__buf_consume(server->tcp_send, ares__buf_len(server->tcp_send));
@@ -59,7 +59,7 @@ void ares__close_connection(struct server_connection *conn)
}
/* Requeue queries to other connections */
- ares__requeue_queries(conn);
+ ares__requeue_queries(conn, requeue_status);
ares__llist_destroy(conn->queries_to_conn);
@@ -69,51 +69,68 @@ void ares__close_connection(struct server_connection *conn)
ares_free(conn);
}
-void ares__close_sockets(struct server_state *server)
+void ares__close_sockets(ares_server_t *server)
{
ares__llist_node_t *node;
while ((node = ares__llist_node_first(server->connections)) != NULL) {
- struct server_connection *conn = ares__llist_node_val(node);
- ares__close_connection(conn);
+ ares_conn_t *conn = ares__llist_node_val(node);
+ ares__close_connection(conn, ARES_SUCCESS);
}
}
-void ares__check_cleanup_conn(const ares_channel_t *channel,
- struct server_connection *conn)
+void ares__check_cleanup_conns(const ares_channel_t *channel)
{
- ares_bool_t do_cleanup = ARES_FALSE;
-
- if (channel == NULL || conn == NULL) {
- return;
- }
-
- if (ares__llist_len(conn->queries_to_conn)) {
- return;
- }
+ ares__slist_node_t *snode;
- /* If we are configured not to stay open, close it out */
- if (!(channel->flags & ARES_FLAG_STAYOPEN)) {
- do_cleanup = ARES_TRUE;
+ if (channel == NULL) {
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
- /* If the associated server has failures, close it out. Resetting the
- * connection (and specifically the source port number) can help resolve
- * situations where packets are being dropped.
- */
- if (conn->server->consec_failures > 0) {
- do_cleanup = ARES_TRUE;
+ /* Iterate across each server */
+ for (snode = ares__slist_node_first(channel->servers); snode != NULL;
+ snode = ares__slist_node_next(snode)) {
+ ares_server_t *server = ares__slist_node_val(snode);
+ ares__llist_node_t *cnode;
+
+ /* Iterate across each connection */
+ cnode = ares__llist_node_first(server->connections);
+ while (cnode != NULL) {
+ ares__llist_node_t *next = ares__llist_node_next(cnode);
+ ares_conn_t *conn = ares__llist_node_val(cnode);
+ ares_bool_t do_cleanup = ARES_FALSE;
+ cnode = next;
+
+ /* Has connections, not eligible */
+ if (ares__llist_len(conn->queries_to_conn)) {
+ continue;
+ }
+
+ /* If we are configured not to stay open, close it out */
+ if (!(channel->flags & ARES_FLAG_STAYOPEN)) {
+ do_cleanup = ARES_TRUE;
+ }
+
+ /* If the associated server has failures, close it out. Resetting the
+ * connection (and specifically the source port number) can help resolve
+ * situations where packets are being dropped.
+ */
+ if (conn->server->consec_failures > 0) {
+ do_cleanup = ARES_TRUE;
+ }
+
+ /* If the udp connection hit its max queries, always close it */
+ if (!(conn->flags & ARES_CONN_FLAG_TCP) && channel->udp_max_queries > 0 &&
+ conn->total_queries >= channel->udp_max_queries) {
+ do_cleanup = ARES_TRUE;
+ }
+
+ if (!do_cleanup) {
+ continue;
+ }
+
+ /* Clean it up */
+ ares__close_connection(conn, ARES_SUCCESS);
+ }
}
-
- /* If the udp connection hit its max queries, always close it */
- if (!conn->is_tcp && channel->udp_max_queries > 0 &&
- conn->total_queries >= channel->udp_max_queries) {
- do_cleanup = ARES_TRUE;
- }
-
- if (!do_cleanup) {
- return;
- }
-
- ares__close_connection(conn);
}
diff --git a/contrib/libs/c-ares/src/lib/ares__hosts_file.c b/contrib/libs/c-ares/src/lib/ares__hosts_file.c
index e279623de3..ae9c071d7a 100644
--- a/contrib/libs/c-ares/src/lib/ares__hosts_file.c
+++ b/contrib/libs/c-ares/src/lib/ares__hosts_file.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
@@ -105,7 +103,7 @@ const void *ares_dns_pton(const char *ipaddr, struct ares_addr *addr,
size_t ptr_len = 0;
if (ipaddr == NULL || addr == NULL || out_len == NULL) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
}
*out_len = 0;
@@ -150,7 +148,7 @@ static ares_bool_t ares__normalize_ipaddr(const char *ipaddr, char *out,
}
if (!ares_inet_ntop(data.family, addr, out, (ares_socklen_t)out_len)) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */
}
return ARES_TRUE;
@@ -315,8 +313,8 @@ static ares_status_t ares__hosts_file_add(ares_hosts_file_t *hosts,
if (matchtype != ARES_MATCH_NONE) {
status = ares__hosts_file_merge_entry(hosts, match, entry, matchtype);
if (status != ARES_SUCCESS) {
- ares__hosts_entry_destroy(entry);
- return status;
+ ares__hosts_entry_destroy(entry); /* LCOV_EXCL_LINE: DefensiveCoding */
+ return status; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* entry was invalidated above by merging */
entry = match;
@@ -617,7 +615,8 @@ static ares_bool_t ares__hosts_expired(const char *filename,
/* Expire every 60s if we can't get a time */
if (mod_ts == 0) {
- mod_ts = time(NULL) - 60;
+ mod_ts =
+ time(NULL) - 60; /* LCOV_EXCL_LINE: only on systems without stat() */
}
/* If filenames are different, its expired */
@@ -642,7 +641,7 @@ static ares_status_t ares__hosts_path(const ares_channel_t *channel,
if (channel->hosts_path) {
path_hosts = ares_strdup(channel->hosts_path);
if (!path_hosts) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -653,12 +652,12 @@ static ares_status_t ares__hosts_path(const ares_channel_t *channel,
path_hosts = ares_strdup(getenv("CARES_HOSTS"));
if (!path_hosts) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
if (!path_hosts) {
-#ifdef WIN32
+#if defined(USE_WINSOCK)
char PATH_HOSTS[MAX_PATH] = "";
char tmp[MAX_PATH];
HKEY hkeyHosts;
@@ -728,7 +727,7 @@ ares_status_t ares__hosts_search_ipaddr(ares_channel_t *channel,
}
if (channel->hf == NULL) {
- return ARES_ENOTFOUND;
+ return ARES_ENOTFOUND; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (!ares__normalize_ipaddr(ipaddr, addr, sizeof(addr))) {
@@ -757,7 +756,7 @@ ares_status_t ares__hosts_search_host(ares_channel_t *channel,
}
if (channel->hf == NULL) {
- return ARES_ENOTFOUND;
+ return ARES_ENOTFOUND; /* LCOV_EXCL_LINE: DefensiveCoding */
}
*entry = ares__htable_strvp_get_direct(channel->hf->hosthash, host);
@@ -768,124 +767,6 @@ ares_status_t ares__hosts_search_host(ares_channel_t *channel,
return ARES_SUCCESS;
}
-ares_status_t ares__hosts_entry_to_hostent(const ares_hosts_entry_t *entry,
- int family, struct hostent **hostent)
-{
- ares_status_t status;
- size_t naliases;
- ares__llist_node_t *node;
- size_t idx;
-
- *hostent = ares_malloc_zero(sizeof(**hostent));
- if (*hostent == NULL) {
- status = ARES_ENOMEM;
- goto fail;
- }
-
- (*hostent)->h_addrtype = (HOSTENT_ADDRTYPE_TYPE)family;
-
- /* Copy IP addresses that match the address family */
- idx = 0;
- for (node = ares__llist_node_first(entry->ips); node != NULL;
- node = ares__llist_node_next(node)) {
- struct ares_addr addr;
- const void *ptr = NULL;
- size_t ptr_len = 0;
- const char *ipaddr = ares__llist_node_val(node);
- char **temp = NULL;
-
- memset(&addr, 0, sizeof(addr));
-
- addr.family = family;
- ptr = ares_dns_pton(ipaddr, &addr, &ptr_len);
- if (ptr == NULL) {
- continue;
- }
-
- /* If family == AF_UNSPEC, then we want to inherit this for future
- * conversions as we can only support a single address class */
- if (family == AF_UNSPEC) {
- family = addr.family;
- (*hostent)->h_addrtype = (HOSTENT_ADDRTYPE_TYPE)addr.family;
- }
-
- temp = ares_realloc_zero((*hostent)->h_addr_list,
- (idx + 1) * sizeof(*(*hostent)->h_addr_list),
- (idx + 2) * sizeof(*(*hostent)->h_addr_list));
- if (temp == NULL) {
- status = ARES_ENOMEM;
- goto fail;
- }
-
- (*hostent)->h_addr_list = temp;
-
- (*hostent)->h_addr_list[idx] = ares_malloc(ptr_len);
- if ((*hostent)->h_addr_list[idx] == NULL) {
- status = ARES_ENOMEM;
- goto fail;
- }
-
- memcpy((*hostent)->h_addr_list[idx], ptr, ptr_len);
- idx++;
- (*hostent)->h_length = (HOSTENT_LENGTH_TYPE)ptr_len;
- }
-
- /* entry didn't match address class */
- if (idx == 0) {
- status = ARES_ENOTFOUND;
- goto fail;
- }
-
- /* Copy main hostname */
- (*hostent)->h_name = ares_strdup(ares__llist_first_val(entry->hosts));
- if ((*hostent)->h_name == NULL) {
- status = ARES_ENOMEM;
- goto fail;
- }
-
- /* Copy aliases */
- naliases = ares__llist_len(entry->hosts) - 1;
-
- /* Cap at 100, some people use https://github.com/StevenBlack/hosts and we
- * don't need 200k+ aliases */
- if (naliases > 100) {
- naliases = 100;
- }
-
- (*hostent)->h_aliases =
- ares_malloc_zero((naliases + 1) * sizeof(*(*hostent)->h_aliases));
- if ((*hostent)->h_aliases == NULL) {
- status = ARES_ENOMEM;
- goto fail;
- }
-
- /* Copy all entries to the alias except the first */
- idx = 0;
- node = ares__llist_node_first(entry->hosts);
- node = ares__llist_node_next(node);
- while (node != NULL) {
- (*hostent)->h_aliases[idx] = ares_strdup(ares__llist_node_val(node));
- if ((*hostent)->h_aliases[idx] == NULL) {
- status = ARES_ENOMEM;
- goto fail;
- }
- idx++;
-
- /* Break out if artificially capped */
- if (idx == naliases) {
- break;
- }
- node = ares__llist_node_next(node);
- }
-
- return ARES_SUCCESS;
-
-fail:
- ares_free_hostent(*hostent);
- *hostent = NULL;
- return status;
-}
-
static ares_status_t
ares__hosts_ai_append_cnames(const ares_hosts_entry_t *entry,
struct ares_addrinfo_cname **cnames_out)
@@ -909,25 +790,25 @@ static ares_status_t
* https://github.com/StevenBlack/hosts and we don't need 200k+ aliases */
cnt++;
if (cnt > 100) {
- break;
+ break; /* LCOV_EXCL_LINE: DefensiveCoding */
}
cname = ares__append_addrinfo_cname(&cnames);
if (cname == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
cname->alias = ares_strdup(host);
if (cname->alias == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
cname->name = ares_strdup(primaryhost);
if (cname->name == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
node = ares__llist_node_next(node);
@@ -937,22 +818,22 @@ static ares_status_t
if (cnames == NULL) {
cname = ares__append_addrinfo_cname(&cnames);
if (cname == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
cname->name = ares_strdup(primaryhost);
if (cname->name == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
status = ARES_SUCCESS;
done:
if (status != ARES_SUCCESS) {
- ares__freeaddrinfo_cnames(cnames);
- return status;
+ ares__freeaddrinfo_cnames(cnames); /* LCOV_EXCL_LINE: DefensiveCoding */
+ return status; /* LCOV_EXCL_LINE: DefensiveCoding */
}
*cnames_out = cnames;
@@ -975,14 +856,16 @@ ares_status_t ares__hosts_entry_to_addrinfo(const ares_hosts_entry_t *entry,
case AF_INET6:
case AF_UNSPEC:
break;
- default:
- return ARES_EBADFAMILY;
+ default: /* LCOV_EXCL_LINE: DefensiveCoding */
+ return ARES_EBADFAMILY; /* LCOV_EXCL_LINE: DefensiveCoding */
}
- ai->name = ares_strdup(name);
- if (ai->name == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ if (name != NULL) {
+ ai->name = ares_strdup(name);
+ if (ai->name == NULL) {
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
+ }
}
for (node = ares__llist_node_first(entry->ips); node != NULL;
@@ -1002,14 +885,14 @@ ares_status_t ares__hosts_entry_to_addrinfo(const ares_hosts_entry_t *entry,
status = ares_append_ai_node(addr.family, port, 0, ptr, &ainodes);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
}
if (want_cnames) {
status = ares__hosts_ai_append_cnames(entry, &cnames);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
}
@@ -1017,14 +900,48 @@ ares_status_t ares__hosts_entry_to_addrinfo(const ares_hosts_entry_t *entry,
done:
if (status != ARES_SUCCESS) {
+ /* LCOV_EXCL_START: defensive coding */
ares__freeaddrinfo_cnames(cnames);
ares__freeaddrinfo_nodes(ainodes);
ares_free(ai->name);
ai->name = NULL;
return status;
+ /* LCOV_EXCL_STOP */
}
ares__addrinfo_cat_cnames(&ai->cnames, cnames);
ares__addrinfo_cat_nodes(&ai->nodes, ainodes);
return status;
}
+
+ares_status_t ares__hosts_entry_to_hostent(const ares_hosts_entry_t *entry,
+ int family, struct hostent **hostent)
+{
+ ares_status_t status;
+ struct ares_addrinfo *ai = ares_malloc_zero(sizeof(*ai));
+
+ *hostent = NULL;
+
+ if (ai == NULL) {
+ return ARES_ENOMEM;
+ }
+
+ status = ares__hosts_entry_to_addrinfo(entry, NULL, family, 0, ARES_TRUE, ai);
+ if (status != ARES_SUCCESS) {
+ goto done;
+ }
+
+ status = ares__addrinfo2hostent(ai, family, hostent);
+ if (status != ARES_SUCCESS) {
+ goto done;
+ }
+
+done:
+ ares_freeaddrinfo(ai);
+ if (status != ARES_SUCCESS) {
+ ares_free_hostent(*hostent);
+ *hostent = NULL;
+ }
+
+ return status;
+}
diff --git a/contrib/libs/c-ares/src/lib/ares__parse_into_addrinfo.c b/contrib/libs/c-ares/src/lib/ares__parse_into_addrinfo.c
index 90e951c02f..65c94c0401 100644
--- a/contrib/libs/c-ares/src/lib/ares__parse_into_addrinfo.c
+++ b/contrib/libs/c-ares/src/lib/ares__parse_into_addrinfo.c
@@ -24,7 +24,7 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -44,8 +44,6 @@
# include <limits.h>
#endif
-#include "ares.h"
-#include "ares_private.h"
ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec,
ares_bool_t cname_only_is_enodata,
@@ -65,7 +63,7 @@ ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec,
/* Save question hostname */
status = ares_dns_record_query_get(dnsrec, 0, &hostname, NULL, NULL);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ancount = ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER);
@@ -107,19 +105,19 @@ ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec,
cname = ares__append_addrinfo_cname(&cnames);
if (cname == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
cname->ttl = (int)ares_dns_rr_get_ttl(rr);
cname->alias = ares_strdup(ares_dns_rr_get_name(rr));
if (cname->alias == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
cname->name = ares_strdup(hostname);
if (cname->name == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
} else if (rtype == ARES_REC_TYPE_A) {
got_a = ARES_TRUE;
@@ -127,7 +125,7 @@ ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec,
ares_append_ai_node(AF_INET, port, ares_dns_rr_get_ttl(rr),
ares_dns_rr_get_addr(rr, ARES_RR_A_ADDR), &nodes);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
} else if (rtype == ARES_REC_TYPE_AAAA) {
got_aaaa = ARES_TRUE;
@@ -135,7 +133,7 @@ ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec,
ares_dns_rr_get_addr6(rr, ARES_RR_AAAA_ADDR),
&nodes);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
} else {
continue;
@@ -153,8 +151,8 @@ ares_status_t ares__parse_into_addrinfo(const ares_dns_record_t *dnsrec,
ares_free(ai->name);
ai->name = ares_strdup(hostname);
if (ai->name == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
diff --git a/contrib/libs/c-ares/src/lib/ares__socket.c b/contrib/libs/c-ares/src/lib/ares__socket.c
index d3990e7660..345ab95ba1 100644
--- a/contrib/libs/c-ares/src/lib/ares__socket.c
+++ b/contrib/libs/c-ares/src/lib/ares__socket.c
@@ -24,7 +24,7 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_SYS_UIO_H
# include <sys/uio.h>
@@ -56,8 +56,77 @@
#include <fcntl.h>
#include <limits.h>
-#include "ares.h"
-#include "ares_private.h"
+#if defined(__linux__) && defined(MSG_FASTOPEN)
+# define TFO_SUPPORTED 1
+# define TFO_SKIP_CONNECT 0
+# define TFO_USE_SENDTO 0
+# define TFO_USE_CONNECTX 0
+# define TFO_CLIENT_SOCKOPT 0
+#elif defined(__FreeBSD__) && defined(TCP_FASTOPEN)
+# define TFO_SUPPORTED 1
+# define TFO_SKIP_CONNECT 1
+# define TFO_USE_SENDTO 1
+# define TFO_USE_CONNECTX 0
+# define TFO_CLIENT_SOCKOPT TCP_FASTOPEN
+#elif defined(__APPLE__) && defined(HAVE_CONNECTX)
+# define TFO_SUPPORTED 1
+# define TFO_SKIP_CONNECT 0
+# define TFO_USE_SENDTO 0
+# define TFO_USE_CONNECTX 1
+# undef TFO_CLIENT_SOCKOPT
+#else
+# define TFO_SUPPORTED 0
+#endif
+
+
+#ifndef HAVE_WRITEV
+/* Structure for scatter/gather I/O. */
+struct iovec {
+ void *iov_base; /* Pointer to data. */
+ size_t iov_len; /* Length of data. */
+};
+#endif
+
+
+/* Return 1 if the specified error number describes a readiness error, or 0
+ * otherwise. This is mostly for HP-UX, which could return EAGAIN or
+ * EWOULDBLOCK. See this man page
+ *
+ * http://devrsrc1.external.hp.com/STKS/cgi-bin/man2html?
+ * manpage=/usr/share/man/man2.Z/send.2
+ */
+ares_bool_t ares__socket_try_again(int errnum)
+{
+#if !defined EWOULDBLOCK && !defined EAGAIN
+# error "Neither EWOULDBLOCK nor EAGAIN defined"
+#endif
+
+#ifdef EWOULDBLOCK
+ if (errnum == EWOULDBLOCK) {
+ return ARES_TRUE;
+ }
+#endif
+
+#if defined EAGAIN && EAGAIN != EWOULDBLOCK
+ if (errnum == EAGAIN) {
+ return ARES_TRUE;
+ }
+#endif
+
+ return ARES_FALSE;
+}
+
+ares_ssize_t ares__socket_recv(ares_channel_t *channel, ares_socket_t s,
+ void *data, size_t data_len)
+{
+ if (channel->sock_funcs && channel->sock_funcs->arecvfrom) {
+ return channel->sock_funcs->arecvfrom(s, data, data_len, 0, 0, 0,
+ channel->sock_func_cb_data);
+ }
+
+ return (ares_ssize_t)recv((RECV_TYPE_ARG1)s, (RECV_TYPE_ARG2)data,
+ (RECV_TYPE_ARG3)data_len, (RECV_TYPE_ARG4)(0));
+}
ares_ssize_t ares__socket_recvfrom(ares_channel_t *channel, ares_socket_t s,
void *data, size_t data_len, int flags,
@@ -73,20 +142,142 @@ ares_ssize_t ares__socket_recvfrom(ares_channel_t *channel, ares_socket_t s,
return (ares_ssize_t)recvfrom(s, data, (RECVFROM_TYPE_ARG3)data_len, flags,
from, from_len);
#else
- return sread(s, data, data_len);
+ return ares__socket_recv(channel, s, data, data_len);
#endif
}
-ares_ssize_t ares__socket_recv(ares_channel_t *channel, ares_socket_t s,
- void *data, size_t data_len)
+/* Use like:
+ * struct sockaddr_storage sa_storage;
+ * ares_socklen_t salen = sizeof(sa_storage);
+ * struct sockaddr *sa = (struct sockaddr *)&sa_storage;
+ * ares__conn_set_sockaddr(conn, sa, &salen);
+ */
+static ares_status_t ares__conn_set_sockaddr(const ares_conn_t *conn,
+ struct sockaddr *sa,
+ ares_socklen_t *salen)
{
- if (channel->sock_funcs && channel->sock_funcs->arecvfrom) {
- return channel->sock_funcs->arecvfrom(s, data, data_len, 0, 0, 0,
- channel->sock_func_cb_data);
+ const ares_server_t *server = conn->server;
+ unsigned short port =
+ conn->flags & ARES_CONN_FLAG_TCP ? server->tcp_port : server->udp_port;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+
+ switch (server->addr.family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)(void *)sa;
+ if (*salen < (ares_socklen_t)sizeof(*sin)) {
+ return ARES_EFORMERR;
+ }
+ *salen = sizeof(*sin);
+ memset(sin, 0, sizeof(*sin));
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons(port);
+ memcpy(&sin->sin_addr, &server->addr.addr.addr4, sizeof(sin->sin_addr));
+ return ARES_SUCCESS;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)(void *)sa;
+ if (*salen < (ares_socklen_t)sizeof(*sin6)) {
+ return ARES_EFORMERR;
+ }
+ *salen = sizeof(*sin6);
+ memset(sin6, 0, sizeof(*sin6));
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = htons(port);
+ memcpy(&sin6->sin6_addr, &server->addr.addr.addr6,
+ sizeof(sin6->sin6_addr));
+#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
+ sin6->sin6_scope_id = server->ll_scope;
+#endif
+ return ARES_SUCCESS;
+ default:
+ break;
}
- /* sread() is a wrapper for read() or recv() depending on the system */
- return sread(s, data, data_len);
+ return ARES_EBADFAMILY;
+}
+
+static ares_status_t ares_conn_set_self_ip(ares_conn_t *conn, ares_bool_t early)
+{
+ struct sockaddr_storage sa_storage;
+ int rv;
+ ares_socklen_t len = sizeof(sa_storage);
+
+ /* We call this twice on TFO, if we already have the IP we can go ahead and
+ * skip processing */
+ if (!early && conn->self_ip.family != AF_UNSPEC) {
+ return ARES_SUCCESS;
+ }
+
+ memset(&sa_storage, 0, sizeof(sa_storage));
+
+ rv = getsockname(conn->fd, (struct sockaddr *)(void *)&sa_storage, &len);
+ if (rv != 0) {
+ /* During TCP FastOpen, we can't get the IP this early since connect()
+ * may not be called. That's ok, we'll try again later */
+ if (early && conn->flags & ARES_CONN_FLAG_TCP &&
+ conn->flags & ARES_CONN_FLAG_TFO) {
+ memset(&conn->self_ip, 0, sizeof(conn->self_ip));
+ return ARES_SUCCESS;
+ }
+ return ARES_ECONNREFUSED;
+ }
+
+ if (!ares_sockaddr_to_ares_addr(&conn->self_ip, NULL,
+ (struct sockaddr *)(void *)&sa_storage)) {
+ return ARES_ECONNREFUSED;
+ }
+
+ return ARES_SUCCESS;
+}
+
+ares_ssize_t ares__conn_write(ares_conn_t *conn, const void *data, size_t len)
+{
+ ares_channel_t *channel = conn->server->channel;
+ int flags = 0;
+
+#ifdef HAVE_MSG_NOSIGNAL
+ flags |= MSG_NOSIGNAL;
+#endif
+
+ if (channel->sock_funcs && channel->sock_funcs->asendv) {
+ struct iovec vec;
+ vec.iov_base = (void *)((size_t)data); /* Cast off const */
+ vec.iov_len = len;
+ return channel->sock_funcs->asendv(conn->fd, &vec, 1,
+ channel->sock_func_cb_data);
+ }
+
+ if (conn->flags & ARES_CONN_FLAG_TFO_INITIAL) {
+ conn->flags &= ~((unsigned int)ARES_CONN_FLAG_TFO_INITIAL);
+
+#if defined(TFO_USE_SENDTO) && TFO_USE_SENDTO
+ {
+ struct sockaddr_storage sa_storage;
+ ares_socklen_t salen = sizeof(sa_storage);
+ struct sockaddr *sa = (struct sockaddr *)&sa_storage;
+ ares_status_t status;
+ ares_ssize_t rv;
+
+ status = ares__conn_set_sockaddr(conn, sa, &salen);
+ if (status != ARES_SUCCESS) {
+ return status;
+ }
+
+ rv = (ares_ssize_t)sendto((SEND_TYPE_ARG1)conn->fd, (SEND_TYPE_ARG2)data,
+ (SEND_TYPE_ARG3)len, (SEND_TYPE_ARG4)flags, sa,
+ salen);
+
+ /* If using TFO, we might not have been able to get an IP earlier, since
+ * we hadn't informed the OS of the destination. When using sendto()
+ * now we have so we should be able to fetch it */
+ ares_conn_set_self_ip(conn, ARES_TRUE);
+ return rv;
+ }
+#endif
+ }
+
+ return (ares_ssize_t)send((SEND_TYPE_ARG1)conn->fd, (SEND_TYPE_ARG2)data,
+ (SEND_TYPE_ARG3)len, (SEND_TYPE_ARG4)flags);
}
/*
@@ -145,7 +336,7 @@ static int setsocknonblock(ares_socket_t sockfd, /* operate on this */
#endif
}
-#if defined(IPV6_V6ONLY) && defined(WIN32)
+#if defined(IPV6_V6ONLY) && defined(USE_WINSOCK)
/* It makes support for IPv4-mapped IPv6 addresses.
* Linux kernel, NetBSD, FreeBSD and Darwin: default is off;
* Windows Vista and later: default is on;
@@ -161,7 +352,7 @@ static void set_ipv6_v6only(ares_socket_t sockfd, int on)
# define set_ipv6_v6only(s, v)
#endif
-static int configure_socket(ares_socket_t s, struct server_state *server)
+static ares_status_t configure_socket(ares_conn_t *conn)
{
union {
struct sockaddr sa;
@@ -170,43 +361,53 @@ static int configure_socket(ares_socket_t s, struct server_state *server)
} local;
ares_socklen_t bindlen = 0;
+ ares_server_t *server = conn->server;
ares_channel_t *channel = server->channel;
/* do not set options for user-managed sockets */
if (channel->sock_funcs && channel->sock_funcs->asocket) {
- return 0;
+ return ARES_SUCCESS;
}
- (void)setsocknonblock(s, 1);
+ (void)setsocknonblock(conn->fd, 1);
#if defined(FD_CLOEXEC) && !defined(MSDOS)
/* Configure the socket fd as close-on-exec. */
- if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
- return -1; /* LCOV_EXCL_LINE */
+ if (fcntl(conn->fd, F_SETFD, FD_CLOEXEC) != 0) {
+ return ARES_ECONNREFUSED; /* LCOV_EXCL_LINE */
+ }
+#endif
+
+ /* No need to emit SIGPIPE on socket errors */
+#if defined(SO_NOSIGPIPE)
+ {
+ int opt = 1;
+ (void)setsockopt(conn->fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt,
+ sizeof(opt));
}
#endif
/* Set the socket's send and receive buffer sizes. */
- if ((channel->socket_send_buffer_size > 0) &&
- setsockopt(s, SOL_SOCKET, SO_SNDBUF,
+ if (channel->socket_send_buffer_size > 0 &&
+ setsockopt(conn->fd, SOL_SOCKET, SO_SNDBUF,
(void *)&channel->socket_send_buffer_size,
- sizeof(channel->socket_send_buffer_size)) == -1) {
- return -1;
+ sizeof(channel->socket_send_buffer_size)) != 0) {
+ return ARES_ECONNREFUSED; /* LCOV_EXCL_LINE: UntestablePath */
}
- if ((channel->socket_receive_buffer_size > 0) &&
- setsockopt(s, SOL_SOCKET, SO_RCVBUF,
+ if (channel->socket_receive_buffer_size > 0 &&
+ setsockopt(conn->fd, SOL_SOCKET, SO_RCVBUF,
(void *)&channel->socket_receive_buffer_size,
- sizeof(channel->socket_receive_buffer_size)) == -1) {
- return -1;
+ sizeof(channel->socket_receive_buffer_size)) != 0) {
+ return ARES_ECONNREFUSED; /* LCOV_EXCL_LINE: UntestablePath */
}
#ifdef SO_BINDTODEVICE
- if (channel->local_dev_name[0] &&
- setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, channel->local_dev_name,
- sizeof(channel->local_dev_name))) {
- /* Only root can do this, and usually not fatal if it doesn't work, so */
- /* just continue on. */
+ if (ares_strlen(channel->local_dev_name)) {
+ /* Only root can do this, and usually not fatal if it doesn't work, so
+ * just continue on. */
+ (void)setsockopt(conn->fd, SOL_SOCKET, SO_BINDTODEVICE,
+ channel->local_dev_name, sizeof(channel->local_dev_name));
}
#endif
@@ -226,130 +427,215 @@ static int configure_socket(ares_socket_t s, struct server_state *server)
bindlen = sizeof(local.sa6);
}
- if (bindlen && bind(s, &local.sa, bindlen) < 0) {
- return -1;
+ if (bindlen && bind(conn->fd, &local.sa, bindlen) < 0) {
+ return ARES_ECONNREFUSED;
}
if (server->addr.family == AF_INET6) {
- set_ipv6_v6only(s, 0);
- }
-
- return 0;
-}
-
-ares_status_t ares__open_connection(ares_channel_t *channel,
- struct server_state *server,
- ares_bool_t is_tcp)
-{
- ares_socket_t s;
- int opt;
- ares_socklen_t salen;
-
- union {
- struct sockaddr_in sa4;
- struct sockaddr_in6 sa6;
- } saddr;
- struct sockaddr *sa;
- struct server_connection *conn;
- ares__llist_node_t *node;
- int type = is_tcp ? SOCK_STREAM : SOCK_DGRAM;
-
- switch (server->addr.family) {
- case AF_INET:
- sa = (void *)&saddr.sa4;
- salen = sizeof(saddr.sa4);
- memset(sa, 0, (size_t)salen);
- saddr.sa4.sin_family = AF_INET;
- saddr.sa4.sin_port = htons(is_tcp ? server->tcp_port : server->udp_port);
- memcpy(&saddr.sa4.sin_addr, &server->addr.addr.addr4,
- sizeof(saddr.sa4.sin_addr));
- break;
- case AF_INET6:
- sa = (void *)&saddr.sa6;
- salen = sizeof(saddr.sa6);
- memset(sa, 0, (size_t)salen);
- saddr.sa6.sin6_family = AF_INET6;
- saddr.sa6.sin6_port = htons(is_tcp ? server->tcp_port : server->udp_port);
- memcpy(&saddr.sa6.sin6_addr, &server->addr.addr.addr6,
- sizeof(saddr.sa6.sin6_addr));
-#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
- saddr.sa6.sin6_scope_id = server->ll_scope;
-#endif
- break;
- default:
- return ARES_EBADFAMILY; /* LCOV_EXCL_LINE */
- }
-
- /* Acquire a socket. */
- s = ares__open_socket(channel, server->addr.family, type, 0);
- if (s == ARES_SOCKET_BAD) {
- return ARES_ECONNREFUSED;
+ set_ipv6_v6only(conn->fd, 0);
}
- /* Configure it. */
- if (configure_socket(s, server) < 0) {
- ares__close_socket(channel, s);
- return ARES_ECONNREFUSED;
- }
+ if (conn->flags & ARES_CONN_FLAG_TCP) {
+ int opt = 1;
#ifdef TCP_NODELAY
- if (is_tcp) {
/*
* Disable the Nagle algorithm (only relevant for TCP sockets, and thus not
* in configure_socket). In general, in DNS lookups we're pretty much
* interested in firing off a single request and then waiting for a reply,
* so batching isn't very interesting.
*/
- opt = 1;
- if ((!channel->sock_funcs || !channel->sock_funcs->asocket) &&
- setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *)&opt, sizeof(opt)) ==
- -1) {
- ares__close_socket(channel, s);
+ if (setsockopt(conn->fd, IPPROTO_TCP, TCP_NODELAY, (void *)&opt,
+ sizeof(opt)) != 0) {
return ARES_ECONNREFUSED;
}
- }
#endif
- if (channel->sock_config_cb) {
- int err = channel->sock_config_cb(s, type, channel->sock_config_cb_data);
- if (err < 0) {
- ares__close_socket(channel, s);
- return ARES_ECONNREFUSED;
+#if defined(TFO_CLIENT_SOCKOPT)
+ if (conn->flags & ARES_CONN_FLAG_TFO &&
+ setsockopt(conn->fd, IPPROTO_TCP, TFO_CLIENT_SOCKOPT, (void *)&opt,
+ sizeof(opt)) != 0) {
+ /* Disable TFO if flag can't be set. */
+ conn->flags &= ~((unsigned int)ARES_CONN_FLAG_TFO);
}
+#endif
}
- /* Connect to the server. */
- if (ares__connect_socket(channel, s, sa, salen) == -1) {
- int err = SOCKERRNO;
+ return ARES_SUCCESS;
+}
- if (err != EINPROGRESS && err != EWOULDBLOCK) {
- ares__close_socket(channel, s);
- return ARES_ECONNREFUSED;
+ares_bool_t ares_sockaddr_to_ares_addr(struct ares_addr *ares_addr,
+ unsigned short *port,
+ const struct sockaddr *sockaddr)
+{
+ if (sockaddr->sa_family == AF_INET) {
+ /* NOTE: memcpy sockaddr_in due to alignment issues found by UBSAN due to
+ * dnsinfo packing on MacOS */
+ struct sockaddr_in sockaddr_in;
+ memcpy(&sockaddr_in, sockaddr, sizeof(sockaddr_in));
+
+ ares_addr->family = AF_INET;
+ memcpy(&ares_addr->addr.addr4, &(sockaddr_in.sin_addr),
+ sizeof(ares_addr->addr.addr4));
+
+ if (port) {
+ *port = ntohs(sockaddr_in.sin_port);
}
+ return ARES_TRUE;
}
- if (channel->sock_create_cb) {
- int err = channel->sock_create_cb(s, type, channel->sock_create_cb_data);
- if (err < 0) {
- ares__close_socket(channel, s);
- return ARES_ECONNREFUSED;
+ if (sockaddr->sa_family == AF_INET6) {
+ /* NOTE: memcpy sockaddr_in6 due to alignment issues found by UBSAN due to
+ * dnsinfo packing on MacOS */
+ struct sockaddr_in6 sockaddr_in6;
+ memcpy(&sockaddr_in6, sockaddr, sizeof(sockaddr_in6));
+
+ ares_addr->family = AF_INET6;
+ memcpy(&ares_addr->addr.addr6, &(sockaddr_in6.sin6_addr),
+ sizeof(ares_addr->addr.addr6));
+ if (port) {
+ *port = ntohs(sockaddr_in6.sin6_port);
}
+ return ARES_TRUE;
}
+ return ARES_FALSE;
+}
+
+static ares_status_t ares__conn_connect(ares_conn_t *conn, struct sockaddr *sa,
+ ares_socklen_t salen)
+{
+ /* Normal non TCPFastOpen style connect */
+ if (!(conn->flags & ARES_CONN_FLAG_TFO)) {
+ return ares__connect_socket(conn->server->channel, conn->fd, sa, salen);
+ }
+
+ /* FreeBSD don't want any sort of connect() so skip */
+#if defined(TFO_SKIP_CONNECT) && TFO_SKIP_CONNECT
+ return ARES_SUCCESS;
+#elif defined(TFO_USE_CONNECTX) && TFO_USE_CONNECTX
+ {
+ int rv;
+ int err;
+
+ do {
+ sa_endpoints_t endpoints;
+ memset(&endpoints, 0, sizeof(endpoints));
+ endpoints.sae_dstaddr = sa;
+ endpoints.sae_dstaddrlen = salen;
+
+ rv = connectx(conn->fd, &endpoints, SAE_ASSOCID_ANY,
+ CONNECT_DATA_IDEMPOTENT | CONNECT_RESUME_ON_READ_WRITE,
+ NULL, 0, NULL, NULL);
+
+ err = SOCKERRNO;
+ if (rv == -1 && err != EINPROGRESS && err != EWOULDBLOCK) {
+ return ARES_ECONNREFUSED;
+ }
+
+ } while (rv == -1 && err == EINTR);
+ }
+ return ARES_SUCCESS;
+#elif defined(TFO_SUPPORTED) && TFO_SUPPORTED
+ return ares__connect_socket(conn->server->channel, conn->fd, sa, salen);
+#else
+ /* Shouldn't be possible */
+ return ARES_ECONNREFUSED;
+#endif
+}
+
+ares_status_t ares__open_connection(ares_conn_t **conn_out,
+ ares_channel_t *channel,
+ ares_server_t *server, ares_bool_t is_tcp)
+{
+ ares_status_t status;
+ struct sockaddr_storage sa_storage;
+ ares_socklen_t salen = sizeof(sa_storage);
+ struct sockaddr *sa = (struct sockaddr *)&sa_storage;
+ ares_conn_t *conn;
+ ares__llist_node_t *node = NULL;
+ int stype = is_tcp ? SOCK_STREAM : SOCK_DGRAM;
+
+ *conn_out = NULL;
+
conn = ares_malloc(sizeof(*conn));
if (conn == NULL) {
- ares__close_socket(channel, s);
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
+
memset(conn, 0, sizeof(*conn));
- conn->fd = s;
+ conn->fd = ARES_SOCKET_BAD;
conn->server = server;
conn->queries_to_conn = ares__llist_create(NULL);
- conn->is_tcp = is_tcp;
+ conn->flags = is_tcp ? ARES_CONN_FLAG_TCP : ARES_CONN_FLAG_NONE;
+
+ /* Enable TFO if the OS supports it and we were passed in data to send during
+ * the connect. It might be disabled later if an error is encountered. Make
+ * sure a user isn't overriding anything. */
+ if (conn->flags & ARES_CONN_FLAG_TCP && channel->sock_funcs == NULL &&
+ TFO_SUPPORTED) {
+ conn->flags |= ARES_CONN_FLAG_TFO;
+ }
+
if (conn->queries_to_conn == NULL) {
- ares__close_socket(channel, s);
- ares_free(conn);
- return ARES_ENOMEM;
+ /* LCOV_EXCL_START: OutOfMemory */
+ status = ARES_ENOMEM;
+ goto done;
+ /* LCOV_EXCL_STOP */
+ }
+
+ /* Convert into the struct sockaddr structure needed by the OS */
+ status = ares__conn_set_sockaddr(conn, sa, &salen);
+ if (status != ARES_SUCCESS) {
+ goto done;
+ }
+
+ /* Acquire a socket. */
+ conn->fd = ares__open_socket(channel, server->addr.family, stype, 0);
+ if (conn->fd == ARES_SOCKET_BAD) {
+ status = ARES_ECONNREFUSED;
+ goto done;
+ }
+
+ /* Configure it. */
+ status = configure_socket(conn);
+ if (status != ARES_SUCCESS) {
+ goto done;
+ }
+
+ if (channel->sock_config_cb) {
+ int err =
+ channel->sock_config_cb(conn->fd, stype, channel->sock_config_cb_data);
+ if (err < 0) {
+ status = ARES_ECONNREFUSED;
+ goto done;
+ }
+ }
+
+ /* Connect */
+ status = ares__conn_connect(conn, sa, salen);
+ if (status != ARES_SUCCESS) {
+ goto done;
+ }
+
+ if (channel->sock_create_cb) {
+ int err =
+ channel->sock_create_cb(conn->fd, stype, channel->sock_create_cb_data);
+ if (err < 0) {
+ status = ARES_ECONNREFUSED;
+ goto done;
+ }
+ }
+
+ /* Let the connection know we haven't written our first packet yet for TFO */
+ if (conn->flags & ARES_CONN_FLAG_TFO) {
+ conn->flags |= ARES_CONN_FLAG_TFO_INITIAL;
+ }
+
+ /* Need to store our own ip for DNS cookie support */
+ status = ares_conn_set_self_ip(conn, ARES_FALSE);
+ if (status != ARES_SUCCESS) {
+ goto done; /* LCOV_EXCL_LINE: UntestablePath */
}
/* TCP connections are thrown to the end as we don't spawn multiple TCP
@@ -361,29 +647,37 @@ ares_status_t ares__open_connection(ares_channel_t *channel,
node = ares__llist_insert_first(server->connections, conn);
}
if (node == NULL) {
- ares__close_socket(channel, s);
- ares__llist_destroy(conn->queries_to_conn);
- ares_free(conn);
- return ARES_ENOMEM;
+ /* LCOV_EXCL_START: OutOfMemory */
+ status = ARES_ENOMEM;
+ goto done;
+ /* LCOV_EXCL_STOP */
}
/* Register globally to quickly map event on file descriptor to connection
* node object */
- if (!ares__htable_asvp_insert(channel->connnode_by_socket, s, node)) {
- ares__close_socket(channel, s);
- ares__llist_destroy(conn->queries_to_conn);
- ares__llist_node_claim(node);
- ares_free(conn);
- return ARES_ENOMEM;
+ if (!ares__htable_asvp_insert(channel->connnode_by_socket, conn->fd, node)) {
+ /* LCOV_EXCL_START: OutOfMemory */
+ status = ARES_ENOMEM;
+ goto done;
+ /* LCOV_EXCL_STOP */
}
- SOCK_STATE_CALLBACK(channel, s, 1, 0);
+ SOCK_STATE_CALLBACK(channel, conn->fd, 1, is_tcp ? 1 : 0);
if (is_tcp) {
server->tcp_conn = conn;
}
- return ARES_SUCCESS;
+done:
+ if (status != ARES_SUCCESS) {
+ ares__llist_node_claim(node);
+ ares__llist_destroy(conn->queries_to_conn);
+ ares__close_socket(channel, conn->fd);
+ ares_free(conn);
+ } else {
+ *conn_out = conn;
+ }
+ return status;
}
ares_socket_t ares__open_socket(ares_channel_t *channel, int af, int type,
@@ -397,15 +691,31 @@ ares_socket_t ares__open_socket(ares_channel_t *channel, int af, int type,
return socket(af, type, protocol);
}
-int ares__connect_socket(ares_channel_t *channel, ares_socket_t sockfd,
- const struct sockaddr *addr, ares_socklen_t addrlen)
+ares_status_t ares__connect_socket(ares_channel_t *channel,
+ ares_socket_t sockfd,
+ const struct sockaddr *addr,
+ ares_socklen_t addrlen)
{
- if (channel->sock_funcs && channel->sock_funcs->aconnect) {
- return channel->sock_funcs->aconnect(sockfd, addr, addrlen,
+ int rv;
+ int err;
+
+ do {
+ if (channel->sock_funcs && channel->sock_funcs->aconnect) {
+ rv = channel->sock_funcs->aconnect(sockfd, addr, addrlen,
channel->sock_func_cb_data);
- }
+ } else {
+ rv = connect(sockfd, addr, addrlen);
+ }
+
+ err = SOCKERRNO;
+
+ if (rv == -1 && err != EINPROGRESS && err != EWOULDBLOCK) {
+ return ARES_ECONNREFUSED;
+ }
- return connect(sockfd, addr, addrlen);
+ } while (rv == -1 && err == EINTR);
+
+ return ARES_SUCCESS;
}
void ares__close_socket(ares_channel_t *channel, ares_socket_t s)
@@ -421,26 +731,6 @@ void ares__close_socket(ares_channel_t *channel, ares_socket_t s)
}
}
-#ifndef HAVE_WRITEV
-/* Structure for scatter/gather I/O. */
-struct iovec {
- void *iov_base; /* Pointer to data. */
- size_t iov_len; /* Length of data. */
-};
-#endif
-
-ares_ssize_t ares__socket_write(ares_channel_t *channel, ares_socket_t s,
- const void *data, size_t len)
-{
- if (channel->sock_funcs && channel->sock_funcs->asendv) {
- struct iovec vec;
- vec.iov_base = (void *)((size_t)data); /* Cast off const */
- vec.iov_len = len;
- return channel->sock_funcs->asendv(s, &vec, 1, channel->sock_func_cb_data);
- }
- return swrite(s, data, len);
-}
-
void ares_set_socket_callback(ares_channel_t *channel,
ares_sock_create_callback cb, void *data)
{
diff --git a/contrib/libs/c-ares/src/lib/ares__sortaddrinfo.c b/contrib/libs/c-ares/src/lib/ares__sortaddrinfo.c
index 155cc8caf4..1aab81ecf8 100644
--- a/contrib/libs/c-ares/src/lib/ares__sortaddrinfo.c
+++ b/contrib/libs/c-ares/src/lib/ares__sortaddrinfo.c
@@ -36,7 +36,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -51,9 +51,6 @@
#include <assert.h>
#include <limits.h>
-#include "ares.h"
-#include "ares_private.h"
-
struct addrinfo_sort_elem {
struct ares_addrinfo_node *ai;
ares_bool_t has_src_addr;
@@ -349,7 +346,6 @@ static int find_src_addr(ares_channel_t *channel, const struct sockaddr *addr,
struct sockaddr *src_addr)
{
ares_socket_t sock;
- int ret;
ares_socklen_t len;
switch (addr->sa_family) {
@@ -366,18 +362,14 @@ static int find_src_addr(ares_channel_t *channel, const struct sockaddr *addr,
sock = ares__open_socket(channel, addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
if (sock == ARES_SOCKET_BAD) {
- if (errno == EAFNOSUPPORT) {
+ if (SOCKERRNO == EAFNOSUPPORT) {
return 0;
} else {
return -1;
}
}
- do {
- ret = ares__connect_socket(channel, sock, addr, len);
- } while (ret == -1 && errno == EINTR);
-
- if (ret == -1) {
+ if (ares__connect_socket(channel, sock, addr, len) != ARES_SUCCESS) {
ares__close_socket(channel, sock);
return 0;
}
diff --git a/contrib/libs/c-ares/src/lib/ares_android.c b/contrib/libs/c-ares/src/lib/ares_android.c
index 778d4d1060..4c0ffa04f7 100644
--- a/contrib/libs/c-ares/src/lib/ares_android.c
+++ b/contrib/libs/c-ares/src/lib/ares_android.c
@@ -24,13 +24,9 @@
* SPDX-License-Identifier: MIT
*/
#if defined(ANDROID) || defined(__ANDROID__)
-
-# include <jni.h>
-
-# include "ares_setup.h"
-# include "ares.h"
-# include "ares_android.h"
# include "ares_private.h"
+# include <jni.h>
+# include <sys/prctl.h>
static JavaVM *android_jvm = NULL;
static jobject android_connectivity_manager = NULL;
@@ -85,6 +81,23 @@ static jmethodID jni_get_method_id(JNIEnv *env, jclass cls,
return mid;
}
+static int jvm_attach(JNIEnv **env)
+{
+ char name[17] = {0};
+
+ JavaVMAttachArgs args;
+
+ args.version = JNI_VERSION_1_6;
+ if (prctl(PR_GET_NAME, name) == 0) {
+ args.name = name;
+ } else {
+ args.name = NULL;
+ }
+ args.group = NULL;
+
+ return (*android_jvm)->AttachCurrentThread(android_jvm, env, &args);
+}
+
void ares_library_init_jvm(JavaVM *jvm)
{
android_jvm = jvm;
@@ -105,7 +118,7 @@ int ares_library_init_android(jobject connectivity_manager)
res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6);
if (res == JNI_EDETACHED) {
env = NULL;
- res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL);
+ res = jvm_attach(&env);
need_detatch = 1;
}
if (res != JNI_OK || env == NULL) {
@@ -238,7 +251,7 @@ void ares_library_cleanup_android(void)
res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6);
if (res == JNI_EDETACHED) {
env = NULL;
- res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL);
+ res = jvm_attach(&env);
need_detatch = 1;
}
if (res != JNI_OK || env == NULL) {
@@ -290,7 +303,7 @@ char **ares_get_android_server_list(size_t max_servers, size_t *num_servers)
res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6);
if (res == JNI_EDETACHED) {
env = NULL;
- res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL);
+ res = jvm_attach(&env);
need_detatch = 1;
}
if (res != JNI_OK || env == NULL) {
@@ -408,7 +421,7 @@ char *ares_get_android_search_domains_list(void)
res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6);
if (res == JNI_EDETACHED) {
env = NULL;
- res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL);
+ res = jvm_attach(&env);
need_detatch = 1;
}
if (res != JNI_OK || env == NULL) {
diff --git a/contrib/libs/c-ares/src/lib/ares_cancel.c b/contrib/libs/c-ares/src/lib/ares_cancel.c
index 5a9fb722cb..c29d8ef82f 100644
--- a/contrib/libs/c-ares/src/lib/ares_cancel.c
+++ b/contrib/libs/c-ares/src/lib/ares_cancel.c
@@ -24,10 +24,6 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include <assert.h>
-
-#include "ares.h"
#include "ares_private.h"
/*
@@ -57,35 +53,33 @@ void ares_cancel(ares_channel_t *channel)
/* Out of memory, this function doesn't return a result code though so we
* can't report to caller */
if (channel->all_queries == NULL) {
- channel->all_queries = list_copy;
- goto done;
+ channel->all_queries = list_copy; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
node = ares__llist_node_first(list_copy);
while (node != NULL) {
- struct query *query;
- struct server_connection *conn;
+ ares_query_t *query;
/* Cache next since this node is being deleted */
next = ares__llist_node_next(node);
query = ares__llist_node_claim(node);
- conn = query->conn;
query->node_all_queries = NULL;
/* NOTE: its possible this may enqueue new queries */
query->callback(query->arg, ARES_ECANCELLED, 0, NULL);
ares__free_query(query);
- /* See if the connection should be cleaned up */
- ares__check_cleanup_conn(channel, conn);
-
node = next;
}
ares__llist_destroy(list_copy);
}
+ /* See if the connections should be cleaned up */
+ ares__check_cleanup_conns(channel);
+
ares_queue_notify_empty(channel);
done:
diff --git a/contrib/libs/c-ares/src/lib/ares_config-linux.h b/contrib/libs/c-ares/src/lib/ares_config-linux.h
index ff485b0d38..d18434ea63 100644
--- a/contrib/libs/c-ares/src/lib/ares_config-linux.h
+++ b/contrib/libs/c-ares/src/lib/ares_config-linux.h
@@ -41,22 +41,22 @@
#define GETSERVBYNAME_R_ARGS 6
/* Define to 1 if you have AF_INET6. */
-#define HAVE_AF_INET6
+#define HAVE_AF_INET6 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
-#define HAVE_ARPA_INET_H
+#define HAVE_ARPA_INET_H 1
/* Define to 1 if you have the <arpa/nameser_compat.h> header file. */
-#define HAVE_ARPA_NAMESER_COMPAT_H
+#define HAVE_ARPA_NAMESER_COMPAT_H 1
/* Define to 1 if you have the <arpa/nameser.h> header file. */
-#define HAVE_ARPA_NAMESER_H
+#define HAVE_ARPA_NAMESER_H 1
/* Define to 1 if you have the <assert.h> header file. */
-#define HAVE_ASSERT_H
+#define HAVE_ASSERT_H 1
/* Define to 1 if you have the clock_gettime function and monotonic timer. */
-#define HAVE_CLOCK_GETTIME_MONOTONIC
+#define HAVE_CLOCK_GETTIME_MONOTONIC 1
/* Define to 1 if you have the closesocket function. */
/* #undef HAVE_CLOSESOCKET */
@@ -65,79 +65,82 @@
/* #undef HAVE_CLOSESOCKET_CAMEL */
/* Define to 1 if you have the connect function. */
-#define HAVE_CONNECT
+#define HAVE_CONNECT 1
+
+/* Define to 1 if you have the connectx function. */
+/* #undef HAVE_CONNECTX */
/* define if the compiler supports basic C++11 syntax */
/* #undef HAVE_CXX11 */
/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H
+#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H
+#define HAVE_ERRNO_H 1
/* Define to 1 if you have the <poll.h> header file. */
-#define HAVE_POLL_H
+#define HAVE_POLL_H 1
/* Define to 1 if you have the poll function. */
-#define HAVE_POLL
+#define HAVE_POLL 1
/* Define to 1 if you have the pipe function. */
-#define HAVE_PIPE
+#define HAVE_PIPE 1
/* Define to 1 if you have the pipe2 function. */
-#define HAVE_PIPE2
+#define HAVE_PIPE2 1
/* Define to 1 if you have the kqueue function. */
/* #undef HAVE_KQUEUE */
/* Define to 1 if you have the epoll{_create,ctl,wait} functions. */
-#define HAVE_EPOLL
+#define HAVE_EPOLL 1
/* Define to 1 if you have the fcntl function. */
-#define HAVE_FCNTL
+#define HAVE_FCNTL 1
/* Define to 1 if you have the <fcntl.h> header file. */
-#define HAVE_FCNTL_H
+#define HAVE_FCNTL_H 1
/* Define to 1 if you have a working fcntl O_NONBLOCK function. */
-#define HAVE_FCNTL_O_NONBLOCK
+#define HAVE_FCNTL_O_NONBLOCK 1
/* Define to 1 if you have the freeaddrinfo function. */
-#define HAVE_FREEADDRINFO
+#define HAVE_FREEADDRINFO 1
/* Define to 1 if you have a working getaddrinfo function. */
-#define HAVE_GETADDRINFO
+#define HAVE_GETADDRINFO 1
/* Define to 1 if the getaddrinfo function is threadsafe. */
/* #undef HAVE_GETADDRINFO_THREADSAFE */
/* Define to 1 if you have the getenv function. */
-#define HAVE_GETENV
+#define HAVE_GETENV 1
/* Define to 1 if you have the gethostname function. */
-#define HAVE_GETHOSTNAME
+#define HAVE_GETHOSTNAME 1
/* Define to 1 if you have the getnameinfo function. */
-#define HAVE_GETNAMEINFO
+#define HAVE_GETNAMEINFO 1
/* Define to 1 if you have the getrandom function. */
-#define HAVE_GETRANDOM
+#define HAVE_GETRANDOM 1
/* Define to 1 if you have the getservbyport_r function. */
-#define HAVE_GETSERVBYPORT_R
+#define HAVE_GETSERVBYPORT_R 1
/* Define to 1 if you have the getservbyname_r function. */
-#define HAVE_GETSERVBYNAME_R
+#define HAVE_GETSERVBYNAME_R 1
/* Define to 1 if you have the `gettimeofday' function. */
-#define HAVE_GETTIMEOFDAY
+#define HAVE_GETTIMEOFDAY 1
/* Define to 1 if you have the `if_indextoname' function. */
-#define HAVE_IF_INDEXTONAME
+#define HAVE_IF_INDEXTONAME 1
/* Define to 1 if you have the `if_nametoindex' function. */
-#define HAVE_IF_NAMETOINDEX
+#define HAVE_IF_NAMETOINDEX 1
/* Define to 1 if you have the `ConvertInterfaceIndexToLuid' function. */
/* #undef HAVE_CONVERTINTERFACEINDEXTOLUID */
@@ -145,20 +148,26 @@
/* Define to 1 if you have the `ConvertInterfaceLuidToNameA' function. */
/* #undef HAVE_CONVERTINTERFACELUIDTONAMEA */
+/* Define to 1 if you have the `NotifyIpInterfaceChange' function. */
+/* #undef HAVE_NOTIFYIPINTERFACECHANGE */
+
+/* Define to 1 if you have the `RegisterWaitForSingleObject' function. */
+/* #undef HAVE_REGISTERWAITFORSINGLEOBJECT */
+
/* Define to 1 if you have a IPv6 capable working inet_net_pton function. */
/* #undef HAVE_INET_NET_PTON */
/* Define to 1 if you have a IPv6 capable working inet_ntop function. */
-#define HAVE_INET_NTOP
+#define HAVE_INET_NTOP 1
/* Define to 1 if you have a IPv6 capable working inet_pton function. */
-#define HAVE_INET_PTON
+#define HAVE_INET_PTON 1
/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H
+#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the ioctl function. */
-#define HAVE_IOCTL
+#define HAVE_IOCTL 1
/* Define to 1 if you have the ioctlsocket function. */
/* #undef HAVE_IOCTLSOCKET */
@@ -174,10 +183,10 @@
/* #undef HAVE_IOCTLSOCKET_FIONBIO */
/* Define to 1 if you have a working ioctl FIONBIO function. */
-#define HAVE_IOCTL_FIONBIO
+#define HAVE_IOCTL_FIONBIO 1
/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */
-#define HAVE_IOCTL_SIOCGIFADDR
+#define HAVE_IOCTL_SIOCGIFADDR 1
/* Define to 1 if you have the `resolve' library (-lresolve). */
/* #undef HAVE_LIBRESOLV */
@@ -189,97 +198,97 @@
/* #undef HAVE_NETIOAPI_H */
/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H
+#define HAVE_LIMITS_H 1
/* Define to 1 if the compiler supports the 'long long' data type. */
-#define HAVE_LONGLONG
+#define HAVE_LONGLONG 1
/* Define to 1 if you have the malloc.h header file. */
-#define HAVE_MALLOC_H
+#define HAVE_MALLOC_H 1
/* Define to 1 if you have the memory.h header file. */
-#define HAVE_MEMORY_H
+#define HAVE_MEMORY_H 1
/* Define to 1 if you have the AvailabilityMacros.h header file. */
/* #undef HAVE_AVAILABILITYMACROS_H */
/* Define to 1 if you have the MSG_NOSIGNAL flag. */
-#define HAVE_MSG_NOSIGNAL
+#define HAVE_MSG_NOSIGNAL 1
/* Define to 1 if you have the <netdb.h> header file. */
-#define HAVE_NETDB_H
+#define HAVE_NETDB_H 1
/* Define to 1 if you have the <netinet/in.h> header file. */
-#define HAVE_NETINET_IN_H
+#define HAVE_NETINET_IN_H 1
/* Define to 1 if you have the <netinet6/in6.h> header file. */
/* #undef HAVE_NETINET6_IN6_H */
/* Define to 1 if you have the <netinet/tcp.h> header file. */
-#define HAVE_NETINET_TCP_H
+#define HAVE_NETINET_TCP_H 1
/* Define to 1 if you have the <net/if.h> header file. */
-#define HAVE_NET_IF_H
+#define HAVE_NET_IF_H 1
/* Define to 1 if you have PF_INET6. */
-#define HAVE_PF_INET6
+#define HAVE_PF_INET6 1
/* Define to 1 if you have the recv function. */
-#define HAVE_RECV
+#define HAVE_RECV 1
/* Define to 1 if you have the recvfrom function. */
-#define HAVE_RECVFROM
+#define HAVE_RECVFROM 1
/* Define to 1 if you have the send function. */
-#define HAVE_SEND
+#define HAVE_SEND 1
/* Define to 1 if you have the setsockopt function. */
-#define HAVE_SETSOCKOPT
+#define HAVE_SETSOCKOPT 1
/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */
/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */
/* Define to 1 if you have the <signal.h> header file. */
-#define HAVE_SIGNAL_H
+#define HAVE_SIGNAL_H 1
/* Define to 1 if your struct sockaddr_in6 has sin6_scope_id. */
-#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
+#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1
/* Define to 1 if you have the socket function. */
-#define HAVE_SOCKET
+#define HAVE_SOCKET 1
/* Define to 1 if you have the <socket.h> header file. */
/* #undef HAVE_SOCKET_H */
/* Define to 1 if you have the <stdbool.h> header file. */
-#define HAVE_STDBOOL_H
+#define HAVE_STDBOOL_H 1
/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H
+#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H
+#define HAVE_STDLIB_H 1
/* Define to 1 if you have the strcasecmp function. */
-#define HAVE_STRCASECMP
+#define HAVE_STRCASECMP 1
/* Define to 1 if you have the strcmpi function. */
/* #undef HAVE_STRCMPI */
/* Define to 1 if you have the strdup function. */
-#define HAVE_STRDUP
+#define HAVE_STRDUP 1
/* Define to 1 if you have the stricmp function. */
/* #undef HAVE_STRICMP */
/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H
+#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H
+#define HAVE_STRING_H 1
/* Define to 1 if you have the strncasecmp function. */
-#define HAVE_STRNCASECMP
+#define HAVE_STRNCASECMP 1
/* Define to 1 if you have the strncmpi function. */
/* #undef HAVE_STRNCMPI */
@@ -291,61 +300,61 @@
/* #undef HAVE_STROPTS_H */
/* Define to 1 if you have struct addrinfo. */
-#define HAVE_STRUCT_ADDRINFO
+#define HAVE_STRUCT_ADDRINFO 1
/* Define to 1 if you have struct in6_addr. */
-#define HAVE_STRUCT_IN6_ADDR
+#define HAVE_STRUCT_IN6_ADDR 1
/* Define to 1 if you have struct sockaddr_in6. */
-#define HAVE_STRUCT_SOCKADDR_IN6
+#define HAVE_STRUCT_SOCKADDR_IN6 1
/* if struct sockaddr_storage is defined */
-#define HAVE_STRUCT_SOCKADDR_STORAGE
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
/* Define to 1 if you have the timeval struct. */
-#define HAVE_STRUCT_TIMEVAL
+#define HAVE_STRUCT_TIMEVAL 1
/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#define HAVE_SYS_IOCTL_H
+#define HAVE_SYS_IOCTL_H 1
/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H
+#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/random.h> header file. */
-#define HAVE_SYS_RANDOM_H
+#define HAVE_SYS_RANDOM_H 1
/* Define to 1 if you have the <sys/event.h> header file. */
/* #undef HAVE_SYS_EVENT_H */
/* Define to 1 if you have the <sys/epoll.h> header file. */
-#define HAVE_SYS_EPOLL_H
+#define HAVE_SYS_EPOLL_H 1
/* Define to 1 if you have the <sys/select.h> header file. */
-#define HAVE_SYS_SELECT_H
+#define HAVE_SYS_SELECT_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
-#define HAVE_SYS_SOCKET_H
+#define HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H
+#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H
+#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H
+#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/uio.h> header file. */
-#define HAVE_SYS_UIO_H
+#define HAVE_SYS_UIO_H 1
/* Define to 1 if you have the <time.h> header file. */
-#define HAVE_TIME_H
+#define HAVE_TIME_H 1
/* Define to 1 if you have the <ifaddrs.h> header file. */
-#define HAVE_IFADDRS_H
+#define HAVE_IFADDRS_H 1
/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H
+#define HAVE_UNISTD_H 1
/* Define to 1 if you have the windows.h header file. */
/* #undef HAVE_WINDOWS_H */
@@ -369,7 +378,7 @@
/* #undef HAVE_NTDEF_H */
/* Define to 1 if you have the writev function. */
-#define HAVE_WRITEV
+#define HAVE_WRITEV 1
/* Define to 1 if you have the ws2tcpip.h header file. */
/* #undef HAVE_WS2TCPIP_H */
@@ -377,20 +386,14 @@
/* Define to 1 if you have the __system_property_get function */
/* #undef HAVE___SYSTEM_PROPERTY_GET */
-/* Define to 1 if you need the malloc.h header file even with stdlib.h */
-/* #undef NEED_MALLOC_H */
-
-/* Define to 1 if you need the memory.h header file even with stdlib.h */
-/* #undef NEED_MEMORY_H */
-
/* Define if have arc4random_buf() */
/* #undef HAVE_ARC4RANDOM_BUF */
/* Define if have getifaddrs() */
-#define HAVE_GETIFADDRS
+#define HAVE_GETIFADDRS 1
/* Define if have stat() */
-#define HAVE_STAT
+#define HAVE_STAT 1
/* a suitable file/device to read random data from */
#define CARES_RANDOM_FILE "/dev/urandom"
@@ -443,14 +446,11 @@
/* Define to the function return type for recv. */
#define RECV_TYPE_RETV ssize_t
-/* Define to the type qualifier of arg 2 for send. */
-#define SEND_QUAL_ARG2
-
/* Define to the type of arg 1 for send. */
#define SEND_TYPE_ARG1 int
/* Define to the type of arg 2 for send. */
-#define SEND_TYPE_ARG2 void *
+#define SEND_TYPE_ARG2 const void *
/* Define to the type of arg 3 for send. */
#define SEND_TYPE_ARG3 size_t
@@ -468,13 +468,13 @@
#undef WIN32_LEAN_AND_MEAN
/* Define to 1 if you have the pthread.h header file. */
-#define HAVE_PTHREAD_H
+#define HAVE_PTHREAD_H 1
/* Define to 1 if you have the pthread_np.h header file. */
/* #undef HAVE_PTHREAD_NP_H */
/* Define to 1 if threads are enabled */
-#define CARES_THREADS
+#define CARES_THREADS 1
/* Define to 1 if pthread_init() exists */
/* #undef HAVE_PTHREAD_INIT */
diff --git a/contrib/libs/c-ares/src/lib/ares_cookie.c b/contrib/libs/c-ares/src/lib/ares_cookie.c
new file mode 100644
index 0000000000..0680fe9ec7
--- /dev/null
+++ b/contrib/libs/c-ares/src/lib/ares_cookie.c
@@ -0,0 +1,459 @@
+/* MIT License
+ *
+ * Copyright (c) 2024 Brad House
+ *
+ * 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
+ */
+
+/* DNS cookies are a simple form of learned mutual authentication supported by
+ * most DNS server implementations these days and can help prevent DNS Cache
+ * Poisoning attacks for clients and DNS amplification attacks for servers.
+ *
+ * A good overview is here:
+ * https://www.dotmagazine.online/issues/digital-responsibility-and-sustainability/dns-cookies-transaction-mechanism
+ *
+ * RFCs used for implementation are
+ * [RFC7873](https://datatracker.ietf.org/doc/html/rfc7873) which is extended by
+ * [RFC9018](https://datatracker.ietf.org/doc/html/rfc9018).
+ *
+ * Though this could be used on TCP, the likelihood of it being useful is small
+ * and could cause some issues. TCP is better used as a fallback in case there
+ * are issues with DNS Cookie support in the upstream servers (e.g. AnyCast
+ * cluster issues).
+ *
+ * While most recursive DNS servers support DNS Cookies, public DNS servers like
+ * Google (8.8.8.8, 8.8.4.4) and CloudFlare (1.1.1.1, 1.0.0.1) don't seem to
+ * have this enabled yet for unknown reasons.
+ *
+ * The risk to having DNS Cookie support always enabled is nearly zero as there
+ * is built-in detection support and it will simply bypass using cookies if the
+ * remote server doesn't support it. The problem arises if a remote server
+ * supports DNS cookies, then stops supporting them (such as if an administrator
+ * reconfigured the server, or maybe there are different servers in a cluster
+ * with different configurations). We need to detect this behavior by tracking
+ * how much time has gone by since we received our last valid cookie reply, and
+ * if we exceed the threshold, reset all cookie parameters like we haven't
+ * attempted a request yet.
+ *
+ * ## Implementation Plan
+ *
+ * ### Constants:
+ * - `COOKIE_CLIENT_TIMEOUT`: 86400s (1 day)
+ * - How often to regenerate the per-server client cookie, even if our
+ * source ip address hasn't changed.
+ * - `COOKIE_UNSUPPORTED_TIMEOUT`: 300s (5 minutes)
+ * - If a server responds without a cookie in the reply, this is how long to
+ * wait before attempting to send a client cookie again.
+ * - `COOKIE_REGRESSION_TIMEOUT`: 120s (2 minutes)
+ * - If a server was once known to return cookies, and all of a sudden stops
+ * returning cookies (but the reply is otherwise valid), this is how long
+ * to continue to attempt to use cookies before giving up and resetting.
+ * Such an event would cause an outage for this duration, but since a
+ * cache poisoning attack should be dropping invalid replies we should be
+ * able to still get the valid reply and not assume it is a server
+ * regression just because we received replies without cookies.
+ * - `COOKIE_RESEND_MAX`: 3
+ * - Maximum times to resend a query to a server due to the server responding
+ * with `BAD_COOKIE`, after this, we switch to TCP.
+ *
+ * ### Per-server variables:
+ * - `cookie.state`: Known state of cookie support, enumeration.
+ * - `INITIAL` (0): Initial state, not yet determined. Used during startup.
+ * - `GENERATED` (1): Cookie has been generated and sent to a server, but no
+ * validated response yet.
+ * - `SUPPORTED` (2): Server has been determined to properly support cookies
+ * - `UNSUPPORTED` (3): Server has been determined to not support cookies
+ * - `cookie.client` : 8 byte randomly generated client cookie
+ * - `cookie.client_ts`: Timestamp client cookie was generated
+ * - `cookie.client_ip`: IP address client used to connect to server
+ * - `cookie.server`: 8 to 32 byte server cookie
+ * - `cookie.server_len`: length of server cookie
+ * - `cookie.unsupported_ts`: Timestamp of last attempt to use a cookies, but
+ * it was determined that the server didn't support them.
+ *
+ * ### Per-query variables:
+ * - `query.client_cookie`: Duplicate of `cookie.client` at the point in time
+ * the query is put on the wire. This should be available in the
+ * `ares_dns_record_t` for the request for verification purposes so we don't
+ * actually need to duplicate this, just naming it here for the ease of
+ * documentation below.
+ * - `query.cookie_try_count`: Number of tries to send a cookie but receive
+ * `BAD_COOKIE` responses. Used to know when we need to switch to TCP.
+ *
+ * ### Procedure:
+ * **NOTE**: These steps will all be done after obtaining a connection handle as
+ * some of these steps depend on determining the source ip address for the
+ * connection.
+ *
+ * 1. If the query is not using EDNS, then **skip any remaining processing**.
+ * 2. If using TCP, ensure there is no EDNS cookie opt (10) set (there may have
+ * been if this is a resend after upgrade to TCP), then **skip any remaining
+ * processing**.
+ * 3. If `cookie.state == SUPPORTED`, `cookie.unsupported_ts` is non-zero, and
+ * evaluates greater than `COOKIE_REGRESSION_TIMEOUT`, then clear all cookie
+ * settings, set `cookie.state = INITIAL`. Continue to next step (4)
+ * 4. If `cookie.state == UNSUPPORTED`
+ * - If `cookie.unsupported_ts` evaluates less than
+ * `COOKIE_UNSUPPORTED_TIMEOUT`
+ * - Ensure there is no EDNS cookie opt (10) set (shouldn't be unless
+ * requestor had put this themselves), then **skip any remaining
+ * processing** as we don't want to try to send cookies.
+ * - Otherwise:
+ * - clear all cookie settings, set `cookie.state = INITIAL`.
+ * - Continue to next step (5) which will send a new cookie.
+ * 5. If `cookie.state == INITIAL`:
+ * - randomly generate new `cookie.client`
+ * - set `cookie.client_ts` to the current timestamp.
+ * - set `cookie.state = GENERATED`.
+ * - set `cookie.client_ip` to the current source ip address.
+ * 6. If `cookie.state == GENERATED || cookie.state == SUPPORTED` and
+ * `cookie.client_ip` does not match the current source ip address:
+ * - clear `cookie.server`
+ * - randomly generate new `cookie.client`
+ * - set `cookie.client_ts` to the current timestamp.
+ * - set `cookie.client_ip` to the current source ip address.
+ * - do not change the `cookie.state`
+ * 7. If `cookie.state == SUPPORTED` and `cookie.client_ts` evaluation exceeds
+ * `COOKIE_CLIENT_TIMEOUT`:
+ * - clear `cookie.server`
+ * - randomly generate new `cookie.client`
+ * - set `cookie.client_ts` to the current timestamp.
+ * - set `cookie.client_ip` to the current source ip address.
+ * - do not change the `cookie.state`
+ * 8. Generate EDNS OPT record (10) for client cookie. The option value will be
+ * the `cookie.client` concatenated with the `cookie.server`. If there is no
+ * known server cookie, it will not be appended. Copy `cookie.client` to
+ * `query.client_cookie` to handle possible client cookie changes by other
+ * queries before a reply is received (technically this is in the cached
+ * `ares_dns_record_t` so no need to manually do this). Send request to
+ * server.
+ * 9. Evaluate response:
+ * 1. If invalid EDNS OPT cookie (10) length sent back in response (valid
+ * length is 16-40), or bad client cookie value (validate first 8 bytes
+ * against `query.client_cookie` not `cookie.client`), **drop response**
+ * as if it hadn't been received. This is likely a spoofing attack.
+ * Wait for valid response up to normal response timeout.
+ * 2. If a EDNS OPT cookie (10) server cookie is returned:
+ * - set `cookie.unsupported_ts` to zero and `cookie.state = SUPPORTED`.
+ * We can confirm this server supports cookies based on the existence
+ * of this record.
+ * - If a new EDNS OPT cookie (10) server cookie is in the response, and
+ * the `client.cookie` matches the `query.client_cookie` still (hasn't
+ * been rotated by some other parallel query), save it as
+ * `cookie.server`.
+ * 3. If dns response `rcode` is `BAD_COOKIE`:
+ * - Ensure a EDNS OPT cookie (10) is returned, otherwise **drop
+ * response**, this is completely invalid and likely an spoof of some
+ * sort.
+ * - Otherwise
+ * - Increment `query.cookie_try_count`
+ * - If `query.cookie_try_count >= COOKIE_RESEND_MAX`, set
+ * `query.using_tcp` to force the next attempt to use TCP.
+ * - **Requeue the query**, but do not increment the normal
+ * `try_count` as a `BAD_COOKIE` reply isn't a normal try failure.
+ * This should end up going all the way back to step 1 on the next
+ * attempt.
+ * 4. If EDNS OPT cookie (10) is **NOT** returned in the response:
+ * - If `cookie.state == SUPPORTED`
+ * - if `cookie.unsupported_ts` is zero, set to the current timestamp.
+ * - Drop the response, wait for a valid response to be returned
+ * - if `cookie.state == GENERATED`
+ * - clear all cookie settings
+ * - set `cookie.state = UNSUPPORTED`
+ * - set `cookie.unsupported_ts` to the current time
+ * - Accept response (state should be `UNSUPPORTED` if we're here)
+ */
+
+#include "ares_private.h"
+
+/* 1 day */
+#define COOKIE_CLIENT_TIMEOUT_MS (86400 * 1000)
+
+/* 5 minutes */
+#define COOKIE_UNSUPPORTED_TIMEOUT_MS (300 * 1000)
+
+/* 2 minutes */
+#define COOKIE_REGRESSION_TIMEOUT_MS (120 * 1000)
+
+#define COOKIE_RESEND_MAX 3
+
+static const unsigned char *
+ ares_dns_cookie_fetch(const ares_dns_record_t *dnsrec, size_t *len)
+{
+ const ares_dns_rr_t *rr = ares_dns_get_opt_rr_const(dnsrec);
+ const unsigned char *val = NULL;
+ *len = 0;
+
+ if (rr == NULL) {
+ return NULL;
+ }
+
+ if (!ares_dns_rr_get_opt_byid(rr, ARES_RR_OPT_OPTIONS, ARES_OPT_PARAM_COOKIE,
+ &val, len)) {
+ return NULL;
+ }
+
+ return val;
+}
+
+static ares_bool_t timeval_is_set(const ares_timeval_t *tv)
+{
+ if (tv->sec != 0 && tv->usec != 0) {
+ return ARES_TRUE;
+ }
+ return ARES_FALSE;
+}
+
+static ares_bool_t timeval_expired(const ares_timeval_t *tv,
+ const ares_timeval_t *now,
+ unsigned long millsecs)
+{
+ ares_int64_t tvdiff_ms;
+ ares_timeval_t tvdiff;
+ ares__timeval_diff(&tvdiff, tv, now);
+
+ tvdiff_ms = tvdiff.sec * 1000 + tvdiff.usec / 1000;
+ if (tvdiff_ms >= (ares_int64_t)millsecs) {
+ return ARES_TRUE;
+ }
+ return ARES_FALSE;
+}
+
+static void ares_cookie_clear(ares_cookie_t *cookie)
+{
+ memset(cookie, 0, sizeof(*cookie));
+ cookie->state = ARES_COOKIE_INITIAL;
+}
+
+static void ares_cookie_generate(ares_cookie_t *cookie, ares_conn_t *conn,
+ const ares_timeval_t *now)
+{
+ ares_channel_t *channel = conn->server->channel;
+
+ ares__rand_bytes(channel->rand_state, cookie->client, sizeof(cookie->client));
+ memcpy(&cookie->client_ts, now, sizeof(cookie->client_ts));
+ memcpy(&cookie->client_ip, &conn->self_ip, sizeof(cookie->client_ip));
+}
+
+static void ares_cookie_clear_server(ares_cookie_t *cookie)
+{
+ memset(cookie->server, 0, sizeof(cookie->server));
+ cookie->server_len = 0;
+}
+
+static ares_bool_t ares_addr_equal(const struct ares_addr *addr1,
+ const struct ares_addr *addr2)
+{
+ if (addr1->family != addr2->family) {
+ return ARES_FALSE;
+ }
+
+ switch (addr1->family) {
+ case AF_INET:
+ if (memcmp(&addr1->addr.addr4, &addr2->addr.addr4,
+ sizeof(addr1->addr.addr4)) == 0) {
+ return ARES_TRUE;
+ }
+ break;
+ case AF_INET6:
+ /* This structure is weird, and due to padding SonarCloud complains if
+ * you don't punch all the way down. At some point we should rework
+ * this structure */
+ if (memcmp(&addr1->addr.addr6._S6_un._S6_u8,
+ &addr2->addr.addr6._S6_un._S6_u8,
+ sizeof(addr1->addr.addr6._S6_un._S6_u8)) == 0) {
+ return ARES_TRUE;
+ }
+ break;
+ default:
+ break; /* LCOV_EXCL_LINE */
+ }
+
+ return ARES_FALSE;
+}
+
+ares_status_t ares_cookie_apply(ares_dns_record_t *dnsrec, ares_conn_t *conn,
+ const ares_timeval_t *now)
+{
+ ares_server_t *server = conn->server;
+ ares_cookie_t *cookie = &server->cookie;
+ ares_dns_rr_t *rr = ares_dns_get_opt_rr(dnsrec);
+ unsigned char c[40];
+ size_t c_len;
+
+ /* If there is no OPT record, then EDNS isn't supported, and therefore
+ * cookies can't be supported */
+ if (rr == NULL) {
+ return ARES_SUCCESS;
+ }
+
+ /* No cookies on TCP, make sure we remove one if one is present */
+ if (conn->flags & ARES_CONN_FLAG_TCP) {
+ ares_dns_rr_del_opt_byid(rr, ARES_RR_OPT_OPTIONS, ARES_OPT_PARAM_COOKIE);
+ return ARES_SUCCESS;
+ }
+
+ /* Look for regression */
+ if (cookie->state == ARES_COOKIE_SUPPORTED &&
+ timeval_is_set(&cookie->unsupported_ts) &&
+ timeval_expired(&cookie->unsupported_ts, now,
+ COOKIE_REGRESSION_TIMEOUT_MS)) {
+ ares_cookie_clear(cookie);
+ }
+
+ /* Handle unsupported state */
+ if (cookie->state == ARES_COOKIE_UNSUPPORTED) {
+ /* If timer hasn't expired, just delete any possible cookie and return */
+ if (!timeval_expired(&cookie->unsupported_ts, now,
+ COOKIE_REGRESSION_TIMEOUT_MS)) {
+ ares_dns_rr_del_opt_byid(rr, ARES_RR_OPT_OPTIONS, ARES_OPT_PARAM_COOKIE);
+ return ARES_SUCCESS;
+ }
+
+ /* We want to try to "learn" again */
+ ares_cookie_clear(cookie);
+ }
+
+ /* Generate a new cookie */
+ if (cookie->state == ARES_COOKIE_INITIAL) {
+ ares_cookie_generate(cookie, conn, now);
+ cookie->state = ARES_COOKIE_GENERATED;
+ }
+
+ /* Regenerate the cookie and clear the server cookie if the client ip has
+ * changed */
+ if ((cookie->state == ARES_COOKIE_GENERATED ||
+ cookie->state == ARES_COOKIE_SUPPORTED) &&
+ !ares_addr_equal(&conn->self_ip, &cookie->client_ip)) {
+ ares_cookie_clear_server(cookie);
+ ares_cookie_generate(cookie, conn, now);
+ }
+
+ /* If the client cookie has reached its maximum time, refresh it */
+ if (cookie->state == ARES_COOKIE_SUPPORTED &&
+ timeval_expired(&cookie->client_ts, now, COOKIE_CLIENT_TIMEOUT_MS)) {
+ ares_cookie_clear_server(cookie);
+ ares_cookie_generate(cookie, conn, now);
+ }
+
+ /* Generate the full cookie which is the client cookie concatenated with the
+ * server cookie (if there is one) and apply it. */
+ memcpy(c, cookie->client, sizeof(cookie->client));
+ if (cookie->server_len) {
+ memcpy(c + sizeof(cookie->client), cookie->server, cookie->server_len);
+ }
+ c_len = sizeof(cookie->client) + cookie->server_len;
+
+ return ares_dns_rr_set_opt(rr, ARES_RR_OPT_OPTIONS, ARES_OPT_PARAM_COOKIE, c,
+ c_len);
+}
+
+ares_status_t ares_cookie_validate(ares_query_t *query,
+ const ares_dns_record_t *dnsresp,
+ ares_conn_t *conn, const ares_timeval_t *now)
+{
+ ares_server_t *server = conn->server;
+ ares_cookie_t *cookie = &server->cookie;
+ const ares_dns_record_t *dnsreq = query->query;
+ const unsigned char *resp_cookie;
+ size_t resp_cookie_len;
+ const unsigned char *req_cookie;
+ size_t req_cookie_len;
+
+ resp_cookie = ares_dns_cookie_fetch(dnsresp, &resp_cookie_len);
+
+ /* Invalid cookie length, drop */
+ if (resp_cookie && (resp_cookie_len < 8 || resp_cookie_len > 40)) {
+ return ARES_EBADRESP;
+ }
+
+ req_cookie = ares_dns_cookie_fetch(dnsreq, &req_cookie_len);
+
+ /* Didn't request cookies, so we can stop evaluating */
+ if (req_cookie == NULL) {
+ return ARES_SUCCESS;
+ }
+
+ /* If 8-byte prefix for returned cookie doesn't match the requested cookie,
+ * drop for spoofing */
+ if (resp_cookie && memcmp(req_cookie, resp_cookie, 8) != 0) {
+ return ARES_EBADRESP;
+ }
+
+ if (resp_cookie && resp_cookie_len > 8) {
+ /* Make sure we record that we successfully received a cookie response */
+ cookie->state = ARES_COOKIE_SUPPORTED;
+ memset(&cookie->unsupported_ts, 0, sizeof(cookie->unsupported_ts));
+
+ /* If client cookie hasn't been rotated, save the returned server cookie */
+ if (memcmp(cookie->client, req_cookie, sizeof(cookie->client)) == 0) {
+ cookie->server_len = resp_cookie_len - 8;
+ memcpy(cookie->server, resp_cookie + 8, cookie->server_len);
+ }
+ }
+
+ if (ares_dns_record_get_rcode(dnsresp) == ARES_RCODE_BADCOOKIE) {
+ /* Illegal to return BADCOOKIE but no cookie, drop */
+ if (resp_cookie == NULL) {
+ return ARES_EBADRESP;
+ }
+
+ /* If we have too many attempts to send a cookie, we need to requeue as
+ * tcp */
+ query->cookie_try_count++;
+ if (query->cookie_try_count >= COOKIE_RESEND_MAX) {
+ query->using_tcp = ARES_TRUE;
+ }
+
+ /* Resend the request, hopefully it will work the next time as we should
+ * have recorded a server cookie */
+ ares__requeue_query(query, now, ARES_SUCCESS,
+ ARES_FALSE /* Don't increment try count */);
+
+ /* Parent needs to drop this response */
+ return ARES_EBADRESP;
+ }
+
+ /* We've got a response with a server cookie, and we've done all the
+ * evaluation we can, return success */
+ if (resp_cookie_len > 8) {
+ return ARES_SUCCESS;
+ }
+
+ if (cookie->state == ARES_COOKIE_SUPPORTED) {
+ /* If we're not currently tracking an error time yet, start */
+ if (!timeval_is_set(&cookie->unsupported_ts)) {
+ memcpy(&cookie->unsupported_ts, now, sizeof(cookie->unsupported_ts));
+ }
+ /* Drop it since we expected a cookie */
+ return ARES_EBADRESP;
+ }
+
+ if (cookie->state == ARES_COOKIE_GENERATED) {
+ ares_cookie_clear(cookie);
+ cookie->state = ARES_COOKIE_UNSUPPORTED;
+ memcpy(&cookie->unsupported_ts, now, sizeof(cookie->unsupported_ts));
+ }
+
+ /* Cookie state should be UNSUPPORTED if we're here */
+ return ARES_SUCCESS;
+}
diff --git a/contrib/libs/c-ares/src/lib/ares_data.c b/contrib/libs/c-ares/src/lib/ares_data.c
index e37088283b..d25c3fafff 100644
--- a/contrib/libs/c-ares/src/lib/ares_data.c
+++ b/contrib/libs/c-ares/src/lib/ares_data.c
@@ -24,14 +24,10 @@
* SPDX-License-Identifier: MIT
*/
-
-#include "ares_setup.h"
-
+#include "ares_private.h"
#include <stddef.h>
-
-#include "ares.h"
+#include <assert.h>
#include "ares_data.h"
-#include "ares_private.h"
/*
** ares_free_data() - c-ares external API function.
diff --git a/contrib/libs/c-ares/src/lib/ares_destroy.c b/contrib/libs/c-ares/src/lib/ares_destroy.c
index 672f8b0618..d75b5e227c 100644
--- a/contrib/libs/c-ares/src/lib/ares_destroy.c
+++ b/contrib/libs/c-ares/src/lib/ares_destroy.c
@@ -25,13 +25,9 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-
-#include <assert.h>
-
-#include "ares.h"
#include "ares_private.h"
-#include "ares_event.h"
+#include "event/ares_event.h"
+#include <assert.h>
void ares_destroy(ares_channel_t *channel)
{
@@ -42,7 +38,17 @@ void ares_destroy(ares_channel_t *channel)
return;
}
- /* Disable configuration change monitoring */
+ /* Mark as being shutdown */
+ ares__channel_lock(channel);
+ channel->sys_up = ARES_FALSE;
+ ares__channel_unlock(channel);
+
+ /* Disable configuration change monitoring. We can't hold a lock because
+ * some cleanup routines, such as on Windows, are synchronous operations.
+ * What we've observed is a system config change event was triggered right
+ * at shutdown time and it tries to take the channel lock and the destruction
+ * waits for that event to complete before it continues so we get a channel
+ * lock deadlock at shutdown if we hold a lock during this process. */
if (channel->optmask & ARES_OPT_EVENT_THREAD) {
ares_event_thread_t *e = channel->sock_state_cb_data;
if (e && e->configchg) {
@@ -51,21 +57,23 @@ void ares_destroy(ares_channel_t *channel)
}
}
- /* Wait for reinit thread to exit if there was one pending */
+ /* Wait for reinit thread to exit if there was one pending, can't be
+ * holding a lock as the thread may take locks. */
if (channel->reinit_thread != NULL) {
void *rv;
ares__thread_join(channel->reinit_thread, &rv);
channel->reinit_thread = NULL;
}
- /* Lock because callbacks will be triggered */
+ /* Lock because callbacks will be triggered, and any system-generated
+ * callbacks need to hold a channel lock. */
ares__channel_lock(channel);
/* Destroy all queries */
node = ares__llist_node_first(channel->all_queries);
while (node != NULL) {
ares__llist_node_t *next = ares__llist_node_next(node);
- struct query *query = ares__llist_node_claim(node);
+ ares_query_t *query = ares__llist_node_claim(node);
query->node_all_queries = NULL;
query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL);
@@ -126,10 +134,10 @@ void ares_destroy(ares_channel_t *channel)
ares_free(channel);
}
-void ares__destroy_server(struct server_state *server)
+void ares__destroy_server(ares_server_t *server)
{
if (server == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares__close_sockets(server);
@@ -144,7 +152,7 @@ void ares__destroy_servers_state(ares_channel_t *channel)
ares__slist_node_t *node;
while ((node = ares__slist_node_first(channel->servers)) != NULL) {
- struct server_state *server = ares__slist_node_claim(node);
+ ares_server_t *server = ares__slist_node_claim(node);
ares__destroy_server(server);
}
diff --git a/contrib/libs/c-ares/src/lib/ares_event_win32.c b/contrib/libs/c-ares/src/lib/ares_event_win32.c
deleted file mode 100644
index 718e865085..0000000000
--- a/contrib/libs/c-ares/src/lib/ares_event_win32.c
+++ /dev/null
@@ -1,601 +0,0 @@
-/* MIT License
- *
- * Copyright (c) 2024 Brad House
- *
- * 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"
-#include "ares_event.h"
-#include "ares_event_win32.h"
-#ifdef HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
-#ifdef _WIN32
-
-/* IMPLEMENTATION NOTES
- * ====================
- *
- * This implementation uses some undocumented functionality within Windows for
- * monitoring sockets. The Ancillary Function Driver (AFD) is the low level
- * implementation that Winsock2 sits on top of. Winsock2 unfortunately does
- * not expose the equivalent of epoll() or kqueue(), but it is possible to
- * access AFD directly and use along with IOCP to simulate the functionality.
- * We want to use IOCP if possible as it gives us the ability to monitor more
- * than just sockets (WSAPoll is not an option), and perform arbitrary callbacks
- * which means we can hook in non-socket related events.
- *
- * The information for this implementation was gathered from "wepoll" and
- * "libuv" which both use slight variants on this, but this implementation
- * doesn't directly follow either methodology.
- *
- * Initialization:
- * 1. Dynamically load the NtDeviceIoControlFile and NtCancelIoFileEx internal
- * symbols from ntdll.dll. These functions are used to submit the AFD POLL
- * request and to cancel a prior request, respectively.
- * 2. Create an IO Completion Port base handle via CreateIoCompletionPort()
- * that all socket events will be delivered through.
- * 3. Create a callback to be used to be able to interrupt waiting for IOCP
- * events, this may be called for allowing enqueuing of additional socket
- * events or removing socket events. PostQueuedCompletionStatus() is the
- * obvious choice. Use the same container structure as used with a Socket
- * but tagged indicating it is not as the CompletionKey (important!).
- *
- * Socket Add:
- * 1. Create/Allocate a container for holding metadata about a socket:
- * - SOCKET base_socket;
- * - SOCKET peer_socket;
- * - OVERLAPPED overlapped; -- Used by AFD POLL
- * - AFD_POLL_INFO afd_poll_info; -- Used by AFD POLL
- * 2. Call WSAIoctl(..., SIO_BASE_HANDLE, ...) to unwrap the SOCKET and get
- * the "base socket" we can use for polling. It appears this may fail so
- * we should call WSAIoctl(..., SIO_BSP_HANDLE_POLL, ...) as a fallback.
- * 3. The SOCKET handle we have is most likely not capable of supporting
- * OVERLAPPED, and we need to have a way to unbind a socket from IOCP
- * (which is done via a simple closesocket()) so we need to duplicate the
- * "base socket" using WSADuplicateSocketW() followed by
- * WSASocketW(..., WSA_FLAG_OVERLAPPED) to create this "peer socket" for
- * submitting AFD POLL requests.
- * 4. Bind to IOCP using CreateIoCompletionPort() referencing the "peer
- * socket" and the base IOCP handle from "Initialization". Use the
- * pointer to the socket container as the "CompletionKey" which will be
- * returned when an event occurs.
- * 5. Submit AFD POLL request (see "AFD POLL Request" section)
- *
- * Socket Delete:
- * 1. Call "AFD Poll Cancel" (see Section of same name)
- * 2. If a cancel was requested (not bypassed due to no events, etc), tag the
- * "container" for the socket as pending delete, and when the next IOCP
- * event for the socket is dequeued, cleanup.
- * 3. Otherwise, call closesocket(peer_socket) then free() the container
- * which will officially delete it.
- * NOTE: Deferring delete may be completely unnecessary. In theory closing
- * the peer_socket() should guarantee no additional events will be
- * delivered. But maybe if there's a pending event that hasn't been
- * read yet but already trigggered it would be an issue, so this is
- * "safer" unless we can prove its not necessary.
- *
- * Socket Modify:
- * 1. Call "AFD Poll Cancel" (see Section of same name)
- * 2. If a cancel was not enqueued because there is no pending request,
- * submit AFD POLL request (see "AFD POLL Request" section), otherwise
- * defer until next socket event.
- *
- * Event Wait:
- * 1. Call GetQueuedCompletionStatusEx() with the base IOCP handle, a
- * stack allocated array of OVERLAPPED_ENTRY's, and an appropriate
- * timeout.
- * 2. Iterate across returned events, the CompletionKey is a pointer to the
- * container registered with CreateIoCompletionPort() or
- * PostQueuedCompletionStatus()
- * 3. If object indicates it is pending delete, go ahead and
- * closesocket(peer_socket) and free() the container. Go to the next event.
- * 4. Submit AFD POLL Request (see "AFD POLL Request"). We must re-enable
- * the request each time we receive a response, it is not persistent.
- * 5. Notify of any events received as indicated in the AFD_POLL_INFO
- * Handles[0].Events (NOTE: check NumberOfHandles first, make sure it is
- * > 0, otherwise we might not have events such as if our last request
- * was cancelled).
- *
- * AFD Poll Request:
- * 1. Initialize the AFD_POLL_INFO structure:
- * Exclusive = TRUE; // Auto cancel duplicates for same socket
- * NumberOfHandles = 1;
- * Timeout.QuadPart = LLONG_MAX;
- * Handles[0].Handle = (HANDLE)base_socket;
- * Handles[0].Status = 0;
- * Handles[0].Events = ... set as appropriate AFD_POLL_RECEIVE, etc;
- * 2. Zero out the OVERLAPPED structure
- * 3. Create an IO_STATUS_BLOCK pointer (iosb) and set it to the address of
- * the OVERLAPPED "Internal" member.
- * 4. Set the "Status" member of IO_STATUS_BLOCK to STATUS_PENDING
- * 5. Call
- * NtDeviceIoControlFile((HANDLE)peer_socket, NULL, NULL, &overlapped,
- * iosb, IOCTL_AFD_POLL
- * &afd_poll_info, sizeof(afd_poll_info),
- * &afd_poll_info, sizeof(afd_poll_info));
- * NOTE: Its not clear to me if the IO_STATUS_BLOCK pointing to OVERLAPPED
- * is for efficiency or if its a requirement for AFD. This is what
- * libuv does, so I'm doing it here too.
- *
- * AFD Poll Cancel:
- * 1. Check to see if the IO_STATUS_BLOCK "Status" member for the socket
- * is still STATUS_PENDING, if not, no cancel request is necessary.
- * 2. Call
- * NtCancelIoFileEx((HANDLE)peer_socket, iosb, &temp_iosb);
- *
- *
- * References:
- * - https://github.com/piscisaureus/wepoll/
- * - https://github.com/libuv/libuv/
- */
-
-typedef struct {
- /* Dynamically loaded symbols */
- NtDeviceIoControlFile_t NtDeviceIoControlFile;
- NtCancelIoFileEx_t NtCancelIoFileEx;
-
- /* Implementation details */
- HANDLE iocp_handle;
-} ares_evsys_win32_t;
-
-typedef struct {
- /*! Pointer to parent event container */
- ares_event_t *event;
- /*! Socket passed in to monitor */
- SOCKET socket;
- /*! Base socket derived from provided socket */
- SOCKET base_socket;
- /*! New socket (duplicate base_socket handle) supporting OVERLAPPED operation
- */
- SOCKET peer_socket;
- /*! Structure for submitting AFD POLL requests (Internals!) */
- AFD_POLL_INFO afd_poll_info;
- /*! Overlapped structure submitted with AFD POLL requests and returned with
- * IOCP results */
- OVERLAPPED overlapped;
-} ares_evsys_win32_eventdata_t;
-
-static void ares_iocpevent_signal(const ares_event_t *event)
-{
- ares_event_thread_t *e = event->e;
- ares_evsys_win32_t *ew = e->ev_sys_data;
-
- if (e == NULL) {
- return;
- }
-
- PostQueuedCompletionStatus(ew->iocp_handle, 0, (ULONG_PTR)event->data, NULL);
-}
-
-static void ares_iocpevent_cb(ares_event_thread_t *e, ares_socket_t fd,
- void *data, ares_event_flags_t flags)
-{
- (void)e;
- (void)data;
- (void)fd;
- (void)flags;
-}
-
-static ares_event_t *ares_iocpevent_create(ares_event_thread_t *e)
-{
- ares_event_t *event = NULL;
- ares_status_t status;
-
- status =
- ares_event_update(&event, e, ARES_EVENT_FLAG_OTHER, ares_iocpevent_cb,
- ARES_SOCKET_BAD, NULL, NULL, ares_iocpevent_signal);
- if (status != ARES_SUCCESS) {
- return NULL;
- }
-
- return event;
-}
-
-static void ares_evsys_win32_destroy(ares_event_thread_t *e)
-{
- ares_evsys_win32_t *ew = NULL;
-
- if (e == NULL) {
- return;
- }
-
- ew = e->ev_sys_data;
- if (ew == NULL) {
- return;
- }
-
- if (ew->iocp_handle != NULL) {
- CloseHandle(ew->iocp_handle);
- }
-
- ares_free(ew);
- e->ev_sys_data = NULL;
-}
-
-static ares_bool_t ares_evsys_win32_init(ares_event_thread_t *e)
-{
- ares_evsys_win32_t *ew = NULL;
- HMODULE ntdll;
-
- ew = ares_malloc_zero(sizeof(*ew));
- if (ew == NULL) {
- return ARES_FALSE;
- }
-
- e->ev_sys_data = ew;
-
- /* All apps should have ntdll.dll already loaded, so just get a handle to
- * this */
- ntdll = GetModuleHandleA("ntdll.dll");
- if (ntdll == NULL) {
- goto fail;
- }
-
- /* Load Internal symbols not typically accessible */
- ew->NtDeviceIoControlFile = (NtDeviceIoControlFile_t)(void *)GetProcAddress(
- ntdll, "NtDeviceIoControlFile");
- ew->NtCancelIoFileEx =
- (NtCancelIoFileEx_t)(void *)GetProcAddress(ntdll, "NtCancelIoFileEx");
-
- if (ew->NtCancelIoFileEx == NULL || ew->NtDeviceIoControlFile == NULL) {
- goto fail;
- }
-
- ew->iocp_handle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
- if (ew->iocp_handle == NULL) {
- goto fail;
- }
-
- e->ev_signal = ares_iocpevent_create(e);
- if (e->ev_signal == NULL) {
- goto fail;
- }
-
- return ARES_TRUE;
-
-fail:
- ares_evsys_win32_destroy(e);
- return ARES_FALSE;
-}
-
-static ares_socket_t ares_evsys_win32_basesocket(ares_socket_t socket)
-{
- while (1) {
- DWORD bytes; /* Not used */
- ares_socket_t base_socket = ARES_SOCKET_BAD;
- int rv;
-
- rv = WSAIoctl(socket, SIO_BASE_HANDLE, NULL, 0, &base_socket,
- sizeof(base_socket), &bytes, NULL, NULL);
- if (rv != SOCKET_ERROR && base_socket != ARES_SOCKET_BAD) {
- socket = base_socket;
- break;
- }
-
- /* If we're here, an error occurred */
- if (GetLastError() == WSAENOTSOCK) {
- /* This is critical, exit */
- return ARES_SOCKET_BAD;
- }
-
- /* Work around known bug in Komodia based LSPs, use ARES_BSP_HANDLE_POLL
- * to retrieve the underlying socket to then loop and get the base socket:
- * https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls
- * https://www.komodia.com/newwiki/index.php?title=Komodia%27s_Redirector_bug_fixes#Version_2.2.2.6
- */
- base_socket = ARES_SOCKET_BAD;
- rv = WSAIoctl(socket, SIO_BSP_HANDLE_POLL, NULL, 0, &base_socket,
- sizeof(base_socket), &bytes, NULL, NULL);
-
- if (rv != SOCKET_ERROR && base_socket != ARES_SOCKET_BAD &&
- base_socket != socket) {
- socket = base_socket;
- continue; /* loop! */
- }
-
- return ARES_SOCKET_BAD;
- }
-
- return socket;
-}
-
-static ares_bool_t ares_evsys_win32_afd_enqueue(ares_event_t *event,
- ares_event_flags_t flags)
-{
- ares_event_thread_t *e = event->e;
- ares_evsys_win32_t *ew = e->ev_sys_data;
- ares_evsys_win32_eventdata_t *ed = event->data;
- NTSTATUS status;
- IO_STATUS_BLOCK *iosb_ptr;
-
- if (e == NULL || ed == NULL || ew == NULL) {
- return ARES_FALSE;
- }
-
- /* Enqueue AFD Poll */
- ed->afd_poll_info.Exclusive = TRUE;
- ed->afd_poll_info.NumberOfHandles = 1;
- ed->afd_poll_info.Timeout.QuadPart = LLONG_MAX;
- ed->afd_poll_info.Handles[0].Handle = (HANDLE)ed->base_socket;
- ed->afd_poll_info.Handles[0].Status = 0;
- ed->afd_poll_info.Handles[0].Events = 0;
-
- if (flags & ARES_EVENT_FLAG_READ) {
- ed->afd_poll_info.Handles[0].Events |=
- (AFD_POLL_RECEIVE | AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT |
- AFD_POLL_ABORT);
- }
- if (flags & ARES_EVENT_FLAG_WRITE) {
- ed->afd_poll_info.Handles[0].Events |=
- (AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL);
- }
- if (flags == 0) {
- ed->afd_poll_info.Handles[0].Events |= AFD_POLL_DISCONNECT;
- }
-
- memset(&ed->overlapped, 0, sizeof(ed->overlapped));
- iosb_ptr = (IO_STATUS_BLOCK *)&ed->overlapped.Internal;
- iosb_ptr->Status = STATUS_PENDING;
-
- status = ew->NtDeviceIoControlFile(
- (HANDLE)ed->peer_socket, NULL, NULL, &ed->overlapped, iosb_ptr,
- IOCTL_AFD_POLL, &ed->afd_poll_info, sizeof(ed->afd_poll_info),
- &ed->afd_poll_info, sizeof(ed->afd_poll_info));
- if (status != STATUS_SUCCESS && status != STATUS_PENDING) {
- printf("%s(): failed to perform IOCTL_AFD_POLL operation\n", __FUNCTION__);
- fflush(stdout);
- return ARES_FALSE;
- }
-
- return ARES_TRUE;
-}
-
-static ares_bool_t ares_evsys_win32_afd_cancel(ares_evsys_win32_eventdata_t *ed)
-{
- IO_STATUS_BLOCK *iosb_ptr;
- IO_STATUS_BLOCK cancel_iosb;
- ares_evsys_win32_t *ew;
- NTSTATUS status;
-
- /* Detached due to destroy */
- if (ed->event == NULL) {
- return ARES_FALSE;
- }
-
- iosb_ptr = (IO_STATUS_BLOCK *)&ed->overlapped.Internal;
- /* Not pending, nothing to do */
- if (iosb_ptr->Status != STATUS_PENDING) {
- return ARES_FALSE;
- }
-
- ew = ed->event->e->ev_sys_data;
- status =
- ew->NtCancelIoFileEx((HANDLE)ed->peer_socket, iosb_ptr, &cancel_iosb);
-
- /* NtCancelIoFileEx() may return STATUS_NOT_FOUND if the operation completed
- * just before calling NtCancelIoFileEx(), but we have not yet received the
- * notifiction (but it should be queued for the next IOCP event). */
- if (status == STATUS_SUCCESS || status == STATUS_NOT_FOUND) {
- return ARES_TRUE;
- }
-
- return ARES_FALSE;
-}
-
-static void ares_evsys_win32_eventdata_destroy(ares_evsys_win32_eventdata_t *ed)
-{
- if (ed == NULL) {
- return;
- }
-
- if (ed->peer_socket != ARES_SOCKET_BAD) {
- closesocket(ed->peer_socket);
- }
-
- ares_free(ed);
-}
-
-static ares_bool_t ares_evsys_win32_event_add(ares_event_t *event)
-{
- ares_event_thread_t *e = event->e;
- ares_evsys_win32_t *ew = e->ev_sys_data;
- ares_evsys_win32_eventdata_t *ed;
- WSAPROTOCOL_INFOW protocol_info;
-
- ed = ares_malloc_zero(sizeof(*ed));
- ed->event = event;
- ed->socket = event->fd;
- ed->base_socket = ARES_SOCKET_BAD;
- ed->peer_socket = ARES_SOCKET_BAD;
-
- /* Likely a signal event, not something we will directly handle. We create
- * the ares_evsys_win32_eventdata_t as the placeholder to use as the
- * IOCP Completion Key */
- if (ed->socket == ARES_SOCKET_BAD) {
- event->data = ed;
- return ARES_TRUE;
- }
-
- ed->base_socket = ares_evsys_win32_basesocket(ed->socket);
- if (ed->base_socket == ARES_SOCKET_BAD) {
- fprintf(stderr, "%s(): could not determine base socket for fd %d\n",
- __FUNCTION__, (int)event->fd);
- ares_evsys_win32_eventdata_destroy(ed);
- return ARES_FALSE;
- }
-
- /* Create a peer socket that supports OVERLAPPED so we can use IOCP on the
- * socket handle */
- if (WSADuplicateSocketW(ed->base_socket, GetCurrentProcessId(),
- &protocol_info) != 0) {
- fprintf(stderr,
- "%s(): could not retrieve protocol info for creating peer socket\n",
- __FUNCTION__);
- ares_evsys_win32_eventdata_destroy(ed);
- return ARES_FALSE;
- }
-
- ed->peer_socket =
- WSASocketW(protocol_info.iAddressFamily, protocol_info.iSocketType,
- protocol_info.iProtocol, &protocol_info, 0, WSA_FLAG_OVERLAPPED);
- if (ed->peer_socket == ARES_SOCKET_BAD) {
- fprintf(stderr, "%s(): could not create peer socket\n", __FUNCTION__);
- ares_evsys_win32_eventdata_destroy(ed);
- return ARES_FALSE;
- }
-
- SetHandleInformation((HANDLE)ed->peer_socket, HANDLE_FLAG_INHERIT, 0);
-
- if (CreateIoCompletionPort((HANDLE)ed->peer_socket, ew->iocp_handle,
- (ULONG_PTR)ed, 0) == NULL) {
- fprintf(stderr, "%s(): failed to bind peer socket to IOCP\n", __FUNCTION__);
- ares_evsys_win32_eventdata_destroy(ed);
- return ARES_FALSE;
- }
-
- event->data = ed;
-
- if (!ares_evsys_win32_afd_enqueue(event, event->flags)) {
- event->data = NULL;
- ares_evsys_win32_eventdata_destroy(ed);
- return ARES_FALSE;
- }
-
- return ARES_TRUE;
-}
-
-static void ares_evsys_win32_event_del(ares_event_t *event)
-{
- ares_evsys_win32_eventdata_t *ed = event->data;
- ares_event_thread_t *e = event->e;
-
- if (event->fd == ARES_SOCKET_BAD || !e->isup || ed == NULL ||
- !ares_evsys_win32_afd_cancel(ed)) {
- /* Didn't need to enqueue a cancellation, for one of these reasons:
- * - Not an IOCP socket
- * - This is during shutdown of the event thread, no more signals can be
- * delivered.
- * - It has been determined there is no AFD POLL queued currently for the
- * socket.
- */
- ares_evsys_win32_eventdata_destroy(ed);
- event->data = NULL;
- } else {
- /* Detach from event, so when the cancel event comes through,
- * it will clean up */
- ed->event = NULL;
- event->data = NULL;
- }
-}
-
-static void ares_evsys_win32_event_mod(ares_event_t *event,
- ares_event_flags_t new_flags)
-{
- ares_evsys_win32_eventdata_t *ed = event->data;
-
- /* Not for us */
- if (event->fd == ARES_SOCKET_BAD || ed == NULL) {
- return;
- }
-
- /* Try to cancel any current outstanding poll, if one is not running,
- * go ahead and queue it up */
- if (!ares_evsys_win32_afd_cancel(ed)) {
- ares_evsys_win32_afd_enqueue(event, new_flags);
- }
-}
-
-static size_t ares_evsys_win32_wait(ares_event_thread_t *e,
- unsigned long timeout_ms)
-{
- ares_evsys_win32_t *ew = e->ev_sys_data;
- OVERLAPPED_ENTRY entries[16];
- ULONG nentries = sizeof(entries) / sizeof(*entries);
- BOOL status;
- size_t i;
- size_t cnt = 0;
-
- status = GetQueuedCompletionStatusEx(
- ew->iocp_handle, entries, nentries, &nentries,
- (timeout_ms == 0) ? INFINITE : (DWORD)timeout_ms, FALSE);
-
- if (!status) {
- return 0;
- }
-
- for (i = 0; i < (size_t)nentries; i++) {
- ares_event_flags_t flags = 0;
- ares_evsys_win32_eventdata_t *ed =
- (ares_evsys_win32_eventdata_t *)entries[i].lpCompletionKey;
- ares_event_t *event = ed->event;
-
- if (ed->socket == ARES_SOCKET_BAD) {
- /* Some sort of signal event */
- flags = ARES_EVENT_FLAG_OTHER;
- } else {
- /* Process events */
- if (ed->afd_poll_info.NumberOfHandles > 0) {
- if (ed->afd_poll_info.Handles[0].Events &
- (AFD_POLL_RECEIVE | AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT |
- AFD_POLL_ABORT)) {
- flags |= ARES_EVENT_FLAG_READ;
- }
- if (ed->afd_poll_info.Handles[0].Events &
- (AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL)) {
- flags |= ARES_EVENT_FLAG_WRITE;
- }
-
- /* XXX: Handle ed->afd_poll_info.Handles[0].Events &
- * AFD_POLL_LOCAL_CLOSE */
- }
-
- if (event == NULL) {
- /* This means we need to cleanup the private event data as we've been
- * detached */
- ares_evsys_win32_eventdata_destroy(ed);
- } else {
- /* Re-enqueue so we can get more events on the socket */
- ares_evsys_win32_afd_enqueue(event, event->flags);
- }
- }
-
- if (event != NULL && flags != 0) {
- cnt++;
- event->cb(e, event->fd, event->data, flags);
- }
- }
-
- return cnt;
-}
-
-const ares_event_sys_t ares_evsys_win32 = { "win32",
- ares_evsys_win32_init,
- ares_evsys_win32_destroy,
- ares_evsys_win32_event_add,
- ares_evsys_win32_event_del,
- ares_evsys_win32_event_mod,
- ares_evsys_win32_wait };
-#endif
diff --git a/contrib/libs/c-ares/src/lib/ares_free_hostent.c b/contrib/libs/c-ares/src/lib/ares_free_hostent.c
index a088c1b15c..bf2037238b 100644
--- a/contrib/libs/c-ares/src/lib/ares_free_hostent.c
+++ b/contrib/libs/c-ares/src/lib/ares_free_hostent.c
@@ -24,16 +24,12 @@
*
* SPDX-License-Identifier: MIT
*/
-
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
-#include "ares.h"
-#include "ares_private.h" /* for memdebug */
-
void ares_free_hostent(struct hostent *host)
{
char **p;
diff --git a/contrib/libs/c-ares/src/lib/ares_free_string.c b/contrib/libs/c-ares/src/lib/ares_free_string.c
index 39773067bd..048ad5d2ae 100644
--- a/contrib/libs/c-ares/src/lib/ares_free_string.c
+++ b/contrib/libs/c-ares/src/lib/ares_free_string.c
@@ -25,9 +25,6 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-
-#include "ares.h"
#include "ares_private.h"
void ares_free_string(void *str)
diff --git a/contrib/libs/c-ares/src/lib/ares_freeaddrinfo.c b/contrib/libs/c-ares/src/lib/ares_freeaddrinfo.c
index 45d931a3f8..2a49f57531 100644
--- a/contrib/libs/c-ares/src/lib/ares_freeaddrinfo.c
+++ b/contrib/libs/c-ares/src/lib/ares_freeaddrinfo.c
@@ -25,15 +25,12 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
-#include "ares.h"
-#include "ares_private.h"
-
void ares__freeaddrinfo_cnames(struct ares_addrinfo_cname *head)
{
struct ares_addrinfo_cname *current;
diff --git a/contrib/libs/c-ares/src/lib/ares_getaddrinfo.c b/contrib/libs/c-ares/src/lib/ares_getaddrinfo.c
index cfc889c70a..f67acdec2f 100644
--- a/contrib/libs/c-ares/src/lib/ares_getaddrinfo.c
+++ b/contrib/libs/c-ares/src/lib/ares_getaddrinfo.c
@@ -26,7 +26,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_GETSERVBYNAME_R
# if !defined(GETSERVBYNAME_R_ARGS) || (GETSERVBYNAME_R_ARGS < 4) || \
@@ -56,14 +56,9 @@
# include <limits.h>
#endif
-#include "ares.h"
-#include "ares_private.h"
#include "ares_dns.h"
-#ifdef WATT32
-# undef WIN32
-#endif
-#ifdef WIN32
+#ifdef _WIN32
# include "ares_platform.h"
#endif
@@ -112,7 +107,7 @@ struct ares_addrinfo_cname *
struct ares_addrinfo_cname *last = *head;
if (tail == NULL) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
}
if (!last) {
@@ -152,7 +147,7 @@ struct ares_addrinfo_node *
struct ares_addrinfo_node *last = *head;
if (tail == NULL) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
}
if (!last) {
@@ -257,7 +252,7 @@ static ares_bool_t fake_addrinfo(const char *name, unsigned short port,
ares_bool_t valid = ARES_TRUE;
const char *p;
for (p = name; *p; p++) {
- if (!ISDIGIT(*p) && *p != '.') {
+ if (!ares__isdigit(*p) && *p != '.') {
valid = ARES_FALSE;
break;
} else if (*p == '.') {
@@ -277,8 +272,8 @@ static ares_bool_t fake_addrinfo(const char *name, unsigned short port,
if (result) {
status = ares_append_ai_node(AF_INET, port, 0, &addr4, &ai->nodes);
if (status != ARES_SUCCESS) {
- callback(arg, (int)status, 0, NULL);
- return ARES_TRUE;
+ callback(arg, (int)status, 0, NULL); /* LCOV_EXCL_LINE: OutOfMemory */
+ return ARES_TRUE; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
}
@@ -291,8 +286,8 @@ static ares_bool_t fake_addrinfo(const char *name, unsigned short port,
if (result) {
status = ares_append_ai_node(AF_INET6, port, 0, &addr6, &ai->nodes);
if (status != ARES_SUCCESS) {
- callback(arg, (int)status, 0, NULL);
- return ARES_TRUE;
+ callback(arg, (int)status, 0, NULL); /* LCOV_EXCL_LINE: OutOfMemory */
+ return ARES_TRUE; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
}
@@ -304,9 +299,11 @@ static ares_bool_t fake_addrinfo(const char *name, unsigned short port,
if (hints->ai_flags & ARES_AI_CANONNAME) {
cname = ares__append_addrinfo_cname(&ai->cnames);
if (!cname) {
+ /* LCOV_EXCL_START: OutOfMemory */
ares_freeaddrinfo(ai);
callback(arg, ARES_ENOMEM, 0, NULL);
return ARES_TRUE;
+ /* LCOV_EXCL_STOP */
}
/* Duplicate the name, to avoid a constness violation. */
@@ -371,7 +368,7 @@ ares_bool_t ares__is_localhost(const char *name)
size_t len;
if (name == NULL) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (strcmp(name, "localhost") == 0) {
@@ -415,7 +412,7 @@ static ares_status_t file_lookup(struct host_query *hquery)
hquery->ai);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
@@ -472,7 +469,7 @@ static void terminate_retries(const struct host_query *hquery,
unsigned short term_qid =
(qid == hquery->qid_a) ? hquery->qid_aaaa : hquery->qid_a;
const ares_channel_t *channel = hquery->channel;
- struct query *query = NULL;
+ ares_query_t *query = NULL;
/* No other outstanding queries, nothing to do */
if (!hquery->remaining) {
@@ -497,7 +494,7 @@ static void host_callback(void *arg, ares_status_t status, size_t timeouts,
if (status == ARES_SUCCESS) {
if (dnsrec == NULL) {
- addinfostatus = ARES_EBADRESP;
+ addinfostatus = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
} else {
addinfostatus =
ares__parse_into_addrinfo(dnsrec, ARES_TRUE, hquery->port, hquery->ai);
@@ -675,20 +672,20 @@ static ares_bool_t next_dns_lookup(struct host_query *hquery)
switch (hquery->hints.ai_family) {
case AF_INET:
hquery->remaining += 1;
- ares_query_dnsrec(hquery->channel, name, ARES_CLASS_IN, ARES_REC_TYPE_A,
+ ares_query_nolock(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_query_nolock(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,
+ ares_query_nolock(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_query_nolock(hquery->channel, name, ARES_CLASS_IN,
ARES_REC_TYPE_AAAA, host_callback, hquery,
&hquery->qid_aaaa);
break;
diff --git a/contrib/libs/c-ares/src/lib/ares_getenv.c b/contrib/libs/c-ares/src/lib/ares_getenv.c
index 08601a61e5..4f471673b9 100644
--- a/contrib/libs/c-ares/src/lib/ares_getenv.c
+++ b/contrib/libs/c-ares/src/lib/ares_getenv.c
@@ -25,7 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#include "ares_getenv.h"
#ifndef HAVE_GETENV
diff --git a/contrib/libs/c-ares/src/lib/ares_getenv.h b/contrib/libs/c-ares/src/lib/ares_getenv.h
index d8bd3a2195..490097fc8d 100644
--- a/contrib/libs/c-ares/src/lib/ares_getenv.h
+++ b/contrib/libs/c-ares/src/lib/ares_getenv.h
@@ -27,8 +27,6 @@
#ifndef HEADER_CARES_GETENV_H
#define HEADER_CARES_GETENV_H
-#include "ares_setup.h"
-
#ifndef HAVE_GETENV
extern char *ares_getenv(const char *name);
#endif
diff --git a/contrib/libs/c-ares/src/lib/ares_gethostbyaddr.c b/contrib/libs/c-ares/src/lib/ares_gethostbyaddr.c
index 453673260d..1db81ec2b4 100644
--- a/contrib/libs/c-ares/src/lib/ares_gethostbyaddr.c
+++ b/contrib/libs/c-ares/src/lib/ares_gethostbyaddr.c
@@ -25,7 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -38,15 +38,8 @@
#endif
#include "ares_nameser.h"
-
-#include "ares.h"
#include "ares_inet_net_pton.h"
#include "ares_platform.h"
-#include "ares_private.h"
-
-#ifdef WATT32
-# undef WIN32
-#endif
struct addr_query {
/* Arguments passed to ares_gethostbyaddr() */
@@ -68,9 +61,9 @@ static ares_status_t file_lookup(ares_channel_t *channel,
const struct ares_addr *addr,
struct hostent **host);
-static void ares_gethostbyaddr_int(ares_channel_t *channel, const void *addr,
- int addrlen, int family,
- ares_host_callback callback, void *arg)
+void ares_gethostbyaddr_nolock(ares_channel_t *channel, const void *addr,
+ int addrlen, int family,
+ ares_host_callback callback, void *arg)
{
struct addr_query *aquery;
@@ -92,9 +85,11 @@ static void ares_gethostbyaddr_int(ares_channel_t *channel, const void *addr,
}
aquery->lookups = ares_strdup(channel->lookups);
if (aquery->lookups == NULL) {
+ /* LCOV_EXCL_START: OutOfMemory */
ares_free(aquery);
callback(arg, ARES_ENOMEM, 0, NULL);
return;
+ /* LCOV_EXCL_STOP */
}
aquery->channel = channel;
if (family == AF_INET) {
@@ -118,7 +113,7 @@ void ares_gethostbyaddr(ares_channel_t *channel, const void *addr, int addrlen,
return;
}
ares__channel_lock(channel);
- ares_gethostbyaddr_int(channel, addr, addrlen, family, callback, arg);
+ ares_gethostbyaddr_nolock(channel, addr, addrlen, family, callback, arg);
ares__channel_unlock(channel);
}
@@ -134,11 +129,12 @@ static void next_lookup(struct addr_query *aquery)
case 'b':
name = ares_dns_addr_to_ptr(&aquery->addr);
if (name == NULL) {
- end_aquery(aquery, ARES_ENOMEM, NULL);
- return;
+ end_aquery(aquery, ARES_ENOMEM,
+ NULL); /* LCOV_EXCL_LINE: OutOfMemory */
+ return; /* LCOV_EXCL_LINE: OutOfMemory */
}
aquery->remaining_lookups = p + 1;
- ares_query_dnsrec(aquery->channel, name, ARES_CLASS_IN,
+ ares_query_nolock(aquery->channel, name, ARES_CLASS_IN,
ARES_REC_TYPE_PTR, addr_callback, aquery, NULL);
ares_free(name);
return;
@@ -227,7 +223,7 @@ static ares_status_t file_lookup(ares_channel_t *channel,
status = ares__hosts_entry_to_hostent(entry, addr->family, host);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
return ARES_SUCCESS;
diff --git a/contrib/libs/c-ares/src/lib/ares_gethostbyname.c b/contrib/libs/c-ares/src/lib/ares_gethostbyname.c
index 299c35b416..6db86e0eed 100644
--- a/contrib/libs/c-ares/src/lib/ares_gethostbyname.c
+++ b/contrib/libs/c-ares/src/lib/ares_gethostbyname.c
@@ -25,7 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -43,10 +43,8 @@
# include <strings.h>
#endif
-#include "ares.h"
#include "ares_inet_net_pton.h"
#include "ares_platform.h"
-#include "ares_private.h"
static void sort_addresses(const struct hostent *host,
const struct apattern *sortlist, size_t nsort);
@@ -102,13 +100,17 @@ static void ares_gethostbyname_callback(void *arg, int status, int timeouts,
void ares_gethostbyname(ares_channel_t *channel, const char *name, int family,
ares_host_callback callback, void *arg)
{
- const struct ares_addrinfo_hints hints = { ARES_AI_CANONNAME, family, 0, 0 };
- struct host_query *ghbn_arg;
+ struct ares_addrinfo_hints hints;
+ struct host_query *ghbn_arg;
if (!callback) {
return;
}
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = ARES_AI_CANONNAME;
+ hints.ai_family = family;
+
ghbn_arg = ares_malloc(sizeof(*ghbn_arg));
if (!ghbn_arg) {
callback(arg, ARES_ENOMEM, 0, NULL);
@@ -248,18 +250,18 @@ static ares_status_t ares__hostent_localhost(const char *name, int family,
ai = ares_malloc_zero(sizeof(*ai));
if (ai == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__addrinfo_localhost(name, 0, &hints, ai);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__addrinfo2hostent(ai, family, host_out);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
done:
@@ -298,7 +300,7 @@ static ares_status_t ares_gethostbyname_file_int(ares_channel_t *channel,
status = ares__hosts_entry_to_hostent(entry, family, host);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
done:
diff --git a/contrib/libs/c-ares/src/lib/ares_getnameinfo.c b/contrib/libs/c-ares/src/lib/ares_getnameinfo.c
index d4cf58ea51..622c1adb1c 100644
--- a/contrib/libs/c-ares/src/lib/ares_getnameinfo.c
+++ b/contrib/libs/c-ares/src/lib/ares_getnameinfo.c
@@ -23,7 +23,7 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_GETSERVBYPORT_R
# if !defined(GETSERVBYPORT_R_ARGS) || (GETSERVBYPORT_R_ARGS < 4) || \
@@ -51,9 +51,7 @@
# include <iphlpapi.h>
#endif
-#include "ares.h"
#include "ares_ipv6.h"
-#include "ares_private.h"
struct nameinfo_query {
ares_nameinfo_callback callback;
@@ -81,8 +79,8 @@ static void nameinfo_callback(void *arg, int status, int timeouts,
static char *lookup_service(unsigned short port, unsigned int flags, char *buf,
size_t buflen);
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
-static void append_scopeid(const struct sockaddr_in6 *addr6,
- unsigned int scopeid, char *buf, size_t buflen);
+static void append_scopeid(const struct sockaddr_in6 *addr6, unsigned int flags,
+ char *buf, size_t buflen);
#endif
static char *ares_striendstr(const char *s1, const char *s2);
@@ -100,11 +98,11 @@ static void ares_getnameinfo_int(ares_channel_t *channel,
/* Validate socket address family and length */
if (sa && sa->sa_family == AF_INET &&
salen >= (ares_socklen_t)sizeof(struct sockaddr_in)) {
- addr = CARES_INADDR_CAST(struct sockaddr_in *, sa);
+ addr = CARES_INADDR_CAST(const struct sockaddr_in *, sa);
port = addr->sin_port;
} else if (sa && sa->sa_family == AF_INET6 &&
salen >= (ares_socklen_t)sizeof(struct sockaddr_in6)) {
- addr6 = CARES_INADDR_CAST(struct sockaddr_in6 *, sa);
+ addr6 = CARES_INADDR_CAST(const struct sockaddr_in6 *, sa);
port = addr6->sin6_port;
} else {
callback(arg, ARES_ENOTIMP, 0, NULL, NULL);
@@ -173,14 +171,15 @@ static void ares_getnameinfo_int(ares_channel_t *channel,
if (sa->sa_family == AF_INET) {
niquery->family = AF_INET;
memcpy(&niquery->addr.addr4, addr, sizeof(niquery->addr.addr4));
- ares_gethostbyaddr(channel, &addr->sin_addr, sizeof(struct in_addr),
- AF_INET, nameinfo_callback, niquery);
+ ares_gethostbyaddr_nolock(channel, &addr->sin_addr,
+ sizeof(struct in_addr), AF_INET,
+ nameinfo_callback, niquery);
} else {
niquery->family = AF_INET6;
memcpy(&niquery->addr.addr6, addr6, sizeof(niquery->addr.addr6));
- ares_gethostbyaddr(channel, &addr6->sin6_addr,
- sizeof(struct ares_in6_addr), AF_INET6,
- nameinfo_callback, niquery);
+ ares_gethostbyaddr_nolock(channel, &addr6->sin6_addr,
+ sizeof(struct ares_in6_addr), AF_INET6,
+ nameinfo_callback, niquery);
}
}
}
@@ -411,8 +410,8 @@ static char *ares_striendstr(const char *s1, const char *s2)
c1 = c1_begin;
c2 = s2;
while (c2 < s2 + s2_len) {
- lo1 = TOLOWER(*c1);
- lo2 = TOLOWER(*c2);
+ lo1 = ares__tolower((unsigned char)*c1);
+ lo2 = ares__tolower((unsigned char)*c2);
if (lo1 != lo2) {
return NULL;
} else {
diff --git a/contrib/libs/c-ares/src/lib/ares_init.c b/contrib/libs/c-ares/src/lib/ares_init.c
index c8b4c34564..6dc5f4f935 100644
--- a/contrib/libs/c-ares/src/lib/ares_init.c
+++ b/contrib/libs/c-ares/src/lib/ares_init.c
@@ -25,7 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
@@ -61,16 +61,9 @@
# include <iphlpapi.h>
#endif
-#include "ares.h"
#include "ares_inet_net_pton.h"
#include "ares_platform.h"
-#include "ares_private.h"
-#include "ares_event.h"
-
-#ifdef WATT32
-# undef WIN32 /* Redefined in MingW/MSVC headers */
-#endif
-
+#include "event/ares_event.h"
int ares_init(ares_channel_t **channelptr)
{
@@ -79,8 +72,8 @@ int ares_init(ares_channel_t **channelptr)
static int ares_query_timeout_cmp_cb(const void *arg1, const void *arg2)
{
- const struct query *q1 = arg1;
- const struct query *q2 = arg2;
+ const ares_query_t *q1 = arg1;
+ const ares_query_t *q2 = arg2;
if (q1->timeout.sec > q2->timeout.sec) {
return 1;
@@ -101,8 +94,8 @@ static int ares_query_timeout_cmp_cb(const void *arg1, const void *arg2)
static int server_sort_cb(const void *data1, const void *data2)
{
- const struct server_state *s1 = data1;
- const struct server_state *s2 = data2;
+ const ares_server_t *s1 = data1;
+ const ares_server_t *s2 = data2;
if (s1->consec_failures < s2->consec_failures) {
return -1;
@@ -122,7 +115,7 @@ static int server_sort_cb(const void *data1, const void *data2)
static void server_destroy_cb(void *data)
{
if (data == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares__destroy_server(data);
}
@@ -167,7 +160,7 @@ static ares_status_t init_by_defaults(ares_channel_t *channel)
rc = ares__sconfig_append(&sconfig, &addr, 0, 0, NULL);
if (rc != ARES_SUCCESS) {
- goto error;
+ goto error; /* LCOV_EXCL_LINE: OutOfMemory */
}
rc = ares__servers_update(channel, sconfig, ARES_FALSE);
@@ -201,8 +194,8 @@ static ares_status_t init_by_defaults(ares_channel_t *channel)
hostname = ares_malloc(len);
if (!hostname) {
- rc = ARES_ENOMEM;
- goto error;
+ rc = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto error; /* LCOV_EXCL_LINE: OutOfMemory */
}
do {
@@ -214,8 +207,8 @@ static ares_status_t init_by_defaults(ares_channel_t *channel)
lenv *= 2;
p = ares_realloc(hostname, len);
if (!p) {
- rc = ARES_ENOMEM;
- goto error;
+ rc = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto error; /* LCOV_EXCL_LINE: OutOfMemory */
}
hostname = p;
continue;
@@ -233,13 +226,13 @@ static ares_status_t init_by_defaults(ares_channel_t *channel)
/* a dot was found */
channel->domains = ares_malloc(sizeof(char *));
if (!channel->domains) {
- rc = ARES_ENOMEM;
- goto error;
+ rc = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto error; /* LCOV_EXCL_LINE: OutOfMemory */
}
channel->domains[0] = ares_strdup(dot + 1);
if (!channel->domains[0]) {
- rc = ARES_ENOMEM;
- goto error;
+ rc = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto error; /* LCOV_EXCL_LINE: OutOfMemory */
}
channel->ndomains = 1;
}
@@ -253,7 +246,7 @@ static ares_status_t init_by_defaults(ares_channel_t *channel)
if (!channel->lookups) {
channel->lookups = ares_strdup("fb");
if (!channel->lookups) {
- rc = ARES_ENOMEM;
+ rc = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -287,6 +280,9 @@ int ares_init_options(ares_channel_t **channelptr,
return ARES_ENOMEM;
}
+ /* We are in a good state */
+ channel->sys_up = ARES_TRUE;
+
/* One option where zero is valid, so set default value here */
channel->ndots = 1;
@@ -351,12 +347,13 @@ int ares_init_options(ares_channel_t **channelptr,
goto done;
}
- if (channel->qcache_max_ttl > 0) {
- status = ares__qcache_create(channel->rand_state, channel->qcache_max_ttl,
- &channel->qcache);
- if (status != ARES_SUCCESS) {
- goto done;
- }
+ /* Go ahead and let it initialize the query cache even if the ttl is 0 and
+ * completely unused. This reduces the number of different code paths that
+ * might be followed even if there is a minor performance hit. */
+ status = ares__qcache_create(channel->rand_state, channel->qcache_max_ttl,
+ &channel->qcache);
+ if (status != ARES_SUCCESS) {
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
if (status == ARES_SUCCESS) {
@@ -384,7 +381,7 @@ int ares_init_options(ares_channel_t **channelptr,
status = ares_event_thread_init(channel);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: UntestablePath */
}
/* Initialize monitor for configuration changes. In some rare cases,
@@ -392,7 +389,7 @@ int ares_init_options(ares_channel_t **channelptr,
e = channel->sock_state_cb_data;
status = ares_event_configchg_init(&e->configchg, e);
if (status != ARES_SUCCESS && status != ARES_ENOTIMP) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: UntestablePath */
}
status = ARES_SUCCESS;
}
@@ -443,8 +440,9 @@ ares_status_t ares_reinit(ares_channel_t *channel)
ares__channel_lock(channel);
- /* If a reinit is already in process, lets not do it again */
- if (channel->reinit_pending) {
+ /* If a reinit is already in process, lets not do it again. Or if we are
+ * shutting down, skip. */
+ if (!channel->sys_up || channel->reinit_pending) {
ares__channel_unlock(channel);
return ARES_SUCCESS;
}
@@ -464,9 +462,11 @@ ares_status_t ares_reinit(ares_channel_t *channel)
status =
ares__thread_create(&channel->reinit_thread, ares_reinit_thread, channel);
if (status != ARES_SUCCESS) {
+ /* LCOV_EXCL_START: UntestablePath */
ares__channel_lock(channel);
channel->reinit_pending = ARES_FALSE;
ares__channel_unlock(channel);
+ /* LCOV_EXCL_STOP */
}
} else {
/* Threading support not available, call directly */
@@ -490,7 +490,6 @@ int ares_dup(ares_channel_t **dest, const ares_channel_t *src)
*dest = NULL; /* in case of failure return NULL explicitly */
- ares__channel_lock(src);
/* First get the options supported by the old ares_save_options() function,
which is most of them */
rc = (ares_status_t)ares_save_options(src, &opts, &optmask);
@@ -509,6 +508,7 @@ int ares_dup(ares_channel_t **dest, const ares_channel_t *src)
goto done;
}
+ ares__channel_lock(src);
/* Now clone the options that ares_save_options() doesn't support, but are
* user-provided */
(*dest)->sock_create_cb = src->sock_create_cb;
@@ -524,7 +524,7 @@ int ares_dup(ares_channel_t **dest, const ares_channel_t *src)
sizeof((*dest)->local_dev_name));
(*dest)->local_ip4 = src->local_ip4;
memcpy((*dest)->local_ip6, src->local_ip6, sizeof(src->local_ip6));
-
+ ares__channel_unlock(src);
/* Servers are a bit unique as ares_init_options() only allows ipv4 servers
* and not a port per server, but there are other user specified ways, that
@@ -539,24 +539,27 @@ int ares_dup(ares_channel_t **dest, const ares_channel_t *src)
if (optmask & ARES_OPT_SERVERS) {
char *csv = ares_get_servers_csv(src);
if (csv == NULL) {
+ /* LCOV_EXCL_START: OutOfMemory */
ares_destroy(*dest);
*dest = NULL;
rc = ARES_ENOMEM;
goto done;
+ /* LCOV_EXCL_STOP */
}
rc = (ares_status_t)ares_set_servers_ports_csv(*dest, csv);
ares_free_string(csv);
if (rc != ARES_SUCCESS) {
+ /* LCOV_EXCL_START: OutOfMemory */
ares_destroy(*dest);
*dest = NULL;
goto done;
+ /* LCOV_EXCL_STOP */
}
}
rc = ARES_SUCCESS;
done:
- ares__channel_unlock(src);
return (int)rc; /* everything went fine */
}
diff --git a/contrib/libs/c-ares/src/lib/ares_library_init.c b/contrib/libs/c-ares/src/lib/ares_library_init.c
index 5d8abf10a0..01d8ff1a44 100644
--- a/contrib/libs/c-ares/src/lib/ares_library_init.c
+++ b/contrib/libs/c-ares/src/lib/ares_library_init.c
@@ -25,9 +25,6 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-
-#include "ares.h"
#include "ares_private.h"
/* library-private global and unique instance vars */
@@ -55,7 +52,7 @@ static void *default_malloc(size_t size)
return malloc(size);
}
-#if defined(WIN32)
+#if defined(_WIN32)
/* We need indirections to handle Windows DLL rules. */
static void *default_realloc(void *p, size_t size)
{
diff --git a/contrib/libs/c-ares/src/lib/ares_metrics.c b/contrib/libs/c-ares/src/lib/ares_metrics.c
new file mode 100644
index 0000000000..aa0ea8c017
--- /dev/null
+++ b/contrib/libs/c-ares/src/lib/ares_metrics.c
@@ -0,0 +1,261 @@
+/* MIT License
+ *
+ * Copyright (c) 2024 Brad House
+ *
+ * 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
+ */
+
+
+/* IMPLEMENTATION NOTES
+ * ====================
+ *
+ * With very little effort we should be able to determine fairly proper timeouts
+ * we can use based on prior query history. We track in order to be able to
+ * auto-scale when network conditions change (e.g. maybe there is a provider
+ * failover and timings change due to that). Apple appears to do this within
+ * their system resolver in MacOS. Obviously we should have a minimum, maximum,
+ * and initial value to make sure the algorithm doesn't somehow go off the
+ * rails.
+ *
+ * Values:
+ * - Minimum Timeout: 250ms (approximate RTT half-way around the globe)
+ * - Maximum Timeout: 5000ms (Recommended timeout in RFC 1123), can be reduced
+ * by ARES_OPT_MAXTIMEOUTMS, but otherwise the bound specified by the option
+ * caps the retry timeout.
+ * - Initial Timeout: User-specified via configuration or ARES_OPT_TIMEOUTMS
+ * - Average latency multiplier: 5x (a local DNS server returning a cached value
+ * will be quicker than if it needs to recurse so we need to account for this)
+ * - Minimum Count for Average: 3. This is the minimum number of queries we
+ * need to form an average for the bucket.
+ *
+ * Per-server buckets for tracking latency over time (these are ephemeral
+ * meaning they don't persist once a channel is destroyed). We record both the
+ * current timespan for the bucket and the immediate preceding timespan in case
+ * of roll-overs we can still maintain recent metrics for calculations:
+ * - 1 minute
+ * - 15 minutes
+ * - 1 hr
+ * - 1 day
+ * - since inception
+ *
+ * Each bucket would contain:
+ * - timestamp (divided by interval)
+ * - minimum latency
+ * - maximum latency
+ * - total time
+ * - count
+ * NOTE: average latency is (total time / count), we will calculate this
+ * dynamically when needed
+ *
+ * Basic algorithm for calculating timeout to use would be:
+ * - Scan from most recent bucket to least recent
+ * - Check timestamp of bucket, if doesn't match current time, continue to next
+ * bucket
+ * - Check count of bucket, if its not at least the "Minimum Count for Average",
+ * check the previous bucket, otherwise continue to next bucket
+ * - If we reached the end with no bucket match, use "Initial Timeout"
+ * - If bucket is selected, take ("total time" / count) as Average latency,
+ * multiply by "Average Latency Multiplier", bound by "Minimum Timeout" and
+ * "Maximum Timeout"
+ * NOTE: The timeout calculated may not be the timeout used. If we are retrying
+ * the query on the same server another time, then it will use a larger value
+ *
+ * On each query reply where the response is legitimate (proper response or
+ * NXDOMAIN) and not something like a server error:
+ * - Cycle through each bucket in order
+ * - Check timestamp of bucket against current timestamp, if out of date
+ * overwrite previous entry with values, clear current values
+ * - Compare current minimum and maximum recorded latency against query time and
+ * adjust if necessary
+ * - Increment "count" by 1 and "total time" by the query time
+ *
+ * Other Notes:
+ * - This is always-on, the only user-configurable value is the initial
+ * timeout which will simply re-uses the current option.
+ * - Minimum and Maximum latencies for a bucket are currently unused but are
+ * there in case we find a need for them in the future.
+ */
+
+#include "ares_private.h"
+
+/*! Minimum timeout value. Chosen due to it being approximately RTT half-way
+ * around the world */
+#define MIN_TIMEOUT_MS 250
+
+/*! Multiplier to apply to average latency to come up with an initial timeout */
+#define AVG_TIMEOUT_MULTIPLIER 5
+
+/*! Upper timeout bounds, only used if channel->maxtimeout not set */
+#define MAX_TIMEOUT_MS 5000
+
+/*! Minimum queries required to form an average */
+#define MIN_COUNT_FOR_AVERAGE 3
+
+static time_t ares_metric_timestamp(ares_server_bucket_t bucket,
+ const ares_timeval_t *now,
+ ares_bool_t is_previous)
+{
+ time_t divisor = 1; /* Silence bogus MSVC warning by setting default value */
+
+ switch (bucket) {
+ case ARES_METRIC_1MINUTE:
+ divisor = 60;
+ break;
+ case ARES_METRIC_15MINUTES:
+ divisor = 15 * 60;
+ break;
+ case ARES_METRIC_1HOUR:
+ divisor = 60 * 60;
+ break;
+ case ARES_METRIC_1DAY:
+ divisor = 24 * 60 * 60;
+ break;
+ case ARES_METRIC_INCEPTION:
+ return is_previous ? 0 : 1;
+ case ARES_METRIC_COUNT:
+ return 0; /* Invalid! */
+ }
+
+ if (is_previous) {
+ if (divisor >= now->sec) {
+ return 0;
+ }
+ return (time_t)((now->sec - divisor) / divisor);
+ }
+
+ return (time_t)(now->sec / divisor);
+}
+
+void ares_metrics_record(const ares_query_t *query, ares_server_t *server,
+ ares_status_t status, const ares_dns_record_t *dnsrec)
+{
+ ares_timeval_t now;
+ ares_timeval_t tvdiff;
+ unsigned int query_ms;
+ ares_dns_rcode_t rcode;
+ ares_server_bucket_t i;
+
+ if (status != ARES_SUCCESS) {
+ return;
+ }
+
+ if (server == NULL) {
+ return;
+ }
+
+ ares__tvnow(&now);
+
+ rcode = ares_dns_record_get_rcode(dnsrec);
+ if (rcode != ARES_RCODE_NOERROR && rcode != ARES_RCODE_NXDOMAIN) {
+ return;
+ }
+
+ ares__timeval_diff(&tvdiff, &query->ts, &now);
+ query_ms = (unsigned int)(tvdiff.sec + (tvdiff.usec / 1000));
+ if (query_ms == 0) {
+ query_ms = 1;
+ }
+
+ /* Place in each bucket */
+ for (i = 0; i < ARES_METRIC_COUNT; i++) {
+ time_t ts = ares_metric_timestamp(i, &now, ARES_FALSE);
+
+ /* Copy metrics to prev and clear */
+ if (ts != server->metrics[i].ts) {
+ server->metrics[i].prev_ts = server->metrics[i].ts;
+ server->metrics[i].prev_total_ms = server->metrics[i].total_ms;
+ server->metrics[i].prev_total_count = server->metrics[i].total_count;
+ server->metrics[i].ts = ts;
+ server->metrics[i].latency_min_ms = 0;
+ server->metrics[i].latency_max_ms = 0;
+ server->metrics[i].total_ms = 0;
+ server->metrics[i].total_count = 0;
+ }
+
+ if (server->metrics[i].latency_min_ms == 0 ||
+ server->metrics[i].latency_min_ms > query_ms) {
+ server->metrics[i].latency_min_ms = query_ms;
+ }
+
+ if (query_ms > server->metrics[i].latency_max_ms) {
+ server->metrics[i].latency_min_ms = query_ms;
+ }
+
+ server->metrics[i].total_count++;
+ server->metrics[i].total_ms += (ares_uint64_t)query_ms;
+ }
+}
+
+size_t ares_metrics_server_timeout(const ares_server_t *server,
+ const ares_timeval_t *now)
+{
+ const ares_channel_t *channel = server->channel;
+ ares_server_bucket_t i;
+ size_t timeout_ms = 0;
+ size_t max_timeout_ms;
+
+ for (i = 0; i < ARES_METRIC_COUNT; i++) {
+ time_t ts = ares_metric_timestamp(i, now, ARES_FALSE);
+
+ /* This ts has been invalidated, see if we should use the previous
+ * time period */
+ if (ts != server->metrics[i].ts ||
+ server->metrics[i].total_count < MIN_COUNT_FOR_AVERAGE) {
+ time_t prev_ts = ares_metric_timestamp(i, now, ARES_TRUE);
+ if (prev_ts != server->metrics[i].prev_ts ||
+ server->metrics[i].prev_total_count < MIN_COUNT_FOR_AVERAGE) {
+ /* Move onto next bucket */
+ continue;
+ }
+ /* Calculate average time for previous bucket */
+ timeout_ms = (size_t)(server->metrics[i].prev_total_ms /
+ server->metrics[i].prev_total_count);
+ } else {
+ /* Calculate average time for current bucket*/
+ timeout_ms =
+ (size_t)(server->metrics[i].total_ms / server->metrics[i].total_count);
+ }
+
+ /* Multiply average by constant to get timeout value */
+ timeout_ms *= AVG_TIMEOUT_MULTIPLIER;
+ break;
+ }
+
+ /* If we're here, that means its the first query for the server, so we just
+ * use the initial default timeout */
+ if (timeout_ms == 0) {
+ timeout_ms = channel->timeout;
+ }
+
+ /* don't go below lower bounds */
+ if (timeout_ms < MIN_TIMEOUT_MS) {
+ timeout_ms = MIN_TIMEOUT_MS;
+ }
+
+ /* don't go above upper bounds */
+ max_timeout_ms = channel->maxtimeout ? channel->maxtimeout : MAX_TIMEOUT_MS;
+ if (timeout_ms > max_timeout_ms) {
+ timeout_ms = max_timeout_ms;
+ }
+
+ return timeout_ms;
+}
diff --git a/contrib/libs/c-ares/src/lib/ares_options.c b/contrib/libs/c-ares/src/lib/ares_options.c
index 6f50f2e498..9aeb4bad3d 100644
--- a/contrib/libs/c-ares/src/lib/ares_options.c
+++ b/contrib/libs/c-ares/src/lib/ares_options.c
@@ -25,16 +25,14 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
-#include "ares.h"
#include "ares_data.h"
#include "ares_inet_net_pton.h"
-#include "ares_private.h"
void ares_destroy_options(struct ares_options *options)
{
@@ -68,7 +66,7 @@ static struct in_addr *ares_save_opt_servers(const ares_channel_t *channel,
for (snode = ares__slist_node_first(channel->servers); snode != NULL;
snode = ares__slist_node_next(snode)) {
- const struct server_state *server = ares__slist_node_val(snode);
+ const ares_server_t *server = ares__slist_node_val(snode);
if (server->addr.family != AF_INET) {
continue;
@@ -249,7 +247,7 @@ static ares_status_t ares__init_options_servers(ares_channel_t *channel,
status = ares_in_addr_to_server_config_llist(servers, nservers, &slist);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__servers_update(channel, slist, ARES_TRUE);
@@ -266,12 +264,12 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
size_t i;
if (channel == NULL) {
- return ARES_ENODATA;
+ return ARES_ENODATA; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (options == NULL) {
if (optmask != 0) {
- return ARES_ENODATA;
+ return ARES_ENODATA; /* LCOV_EXCL_LINE: DefensiveCoding */
}
return ARES_SUCCESS;
}
@@ -389,13 +387,13 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
channel->domains =
ares_malloc_zero((size_t)options->ndomains * sizeof(char *));
if (!channel->domains) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
channel->ndomains = (size_t)options->ndomains;
for (i = 0; i < (size_t)options->ndomains; i++) {
channel->domains[i] = ares_strdup(options->domains[i]);
if (!channel->domains[i]) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
}
@@ -407,7 +405,7 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
} else {
channel->lookups = ares_strdup(options->lookups);
if (!channel->lookups) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
}
@@ -418,7 +416,7 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
channel->sortlist =
ares_malloc((size_t)options->nsort * sizeof(struct apattern));
if (!channel->sortlist) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
for (i = 0; i < (size_t)options->nsort; i++) {
channel->sortlist[i] = options->sortlist[i];
@@ -432,7 +430,7 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
} else {
channel->resolvconf_path = ares_strdup(options->resolvconf_path);
if (channel->resolvconf_path == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
}
@@ -444,7 +442,7 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
} else {
channel->hosts_path = ares_strdup(options->hosts_path);
if (channel->hosts_path == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
}
@@ -457,13 +455,15 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
}
}
+ /* As of c-ares 1.31.0, the Query Cache is on by default. The only way to
+ * disable it is to set options->qcache_max_ttl = 0 while specifying the
+ * ARES_OPT_QUERY_CACHE which will actually disable it completely. */
if (optmask & ARES_OPT_QUERY_CACHE) {
/* qcache_max_ttl is unsigned unlike the others */
- if (options->qcache_max_ttl == 0) {
- optmask &= ~(ARES_OPT_QUERY_CACHE);
- } else {
- channel->qcache_max_ttl = options->qcache_max_ttl;
- }
+ channel->qcache_max_ttl = options->qcache_max_ttl;
+ } else {
+ optmask |= ARES_OPT_QUERY_CACHE;
+ channel->qcache_max_ttl = 3600;
}
/* Initialize the ipv4 servers if provided */
@@ -475,7 +475,7 @@ ares_status_t ares__init_by_options(ares_channel_t *channel,
status = ares__init_options_servers(channel, options->servers,
(size_t)options->nservers);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
}
diff --git a/contrib/libs/c-ares/src/lib/ares_platform.c b/contrib/libs/c-ares/src/lib/ares_platform.c
index 58a5019871..8f0a1dbffb 100644
--- a/contrib/libs/c-ares/src/lib/ares_platform.c
+++ b/contrib/libs/c-ares/src/lib/ares_platform.c
@@ -25,13 +25,10 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-
-#include "ares.h"
-#include "ares_platform.h"
#include "ares_private.h"
+#include "ares_platform.h"
-#if defined(WIN32) && !defined(MSDOS)
+#if defined(_WIN32) && !defined(MSDOS)
# define V_PLATFORM_WIN32s 0
# define V_PLATFORM_WIN32_WINDOWS 1
@@ -78,7 +75,7 @@ win_platform ares__getplatform(void)
}
}
-#endif /* WIN32 && ! MSDOS */
+#endif /* _WIN32 && ! MSDOS */
#if defined(_WIN32_WCE)
diff --git a/contrib/libs/c-ares/src/lib/ares_platform.h b/contrib/libs/c-ares/src/lib/ares_platform.h
index 44b2c03644..768eaddddd 100644
--- a/contrib/libs/c-ares/src/lib/ares_platform.h
+++ b/contrib/libs/c-ares/src/lib/ares_platform.h
@@ -27,9 +27,7 @@
#ifndef HEADER_CARES_PLATFORM_H
#define HEADER_CARES_PLATFORM_H
-#include "ares_setup.h"
-
-#if defined(WIN32) && !defined(MSDOS)
+#if defined(_WIN32) && !defined(MSDOS)
typedef enum {
WIN_UNKNOWN,
diff --git a/contrib/libs/c-ares/src/lib/ares_private.h b/contrib/libs/c-ares/src/lib/ares_private.h
index 6d9fc11771..b85ecb5e14 100644
--- a/contrib/libs/c-ares/src/lib/ares_private.h
+++ b/contrib/libs/c-ares/src/lib/ares_private.h
@@ -27,23 +27,19 @@
#ifndef __ARES_PRIVATE_H
#define __ARES_PRIVATE_H
-/*
- * Define WIN32 when build target is Win32 API
+/* ============================================================================
+ * NOTE: All c-ares source files should include ares_private.h as the first
+ * header.
+ * ============================================================================
*/
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-# define WIN32
-#endif
+#include "ares_setup.h"
+#include "ares.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
-#ifdef WATT32
-# include <tcp.h>
-# include <sys/ioctl.h>
-#endif
-
#define DEFAULT_TIMEOUT 2000 /* milliseconds */
#define DEFAULT_TRIES 3
#ifndef INADDR_NONE
@@ -54,9 +50,9 @@
* warning: cast from 'const struct sockaddr *' to 'const struct sockaddr_in6 *'
* increases required alignment from 1 to 4 [-Wcast-align]
*/
-#define CARES_INADDR_CAST(type, var) ((type)((void *)var))
+#define CARES_INADDR_CAST(type, var) ((type)((const void *)var))
-#if defined(WIN32) && !defined(WATT32)
+#if defined(USE_WINSOCK)
# define WIN_NS_9X "System\\CurrentControlSet\\Services\\VxD\\MSTCP"
# define WIN_NS_NT_KEY "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
@@ -109,32 +105,34 @@ W32_FUNC const char *_w32_GetHostsFile(void);
struct ares_rand_state;
typedef struct ares_rand_state ares_rand_state;
-#include "ares__llist.h"
-#include "ares__slist.h"
-#include "ares__htable_strvp.h"
-#include "ares__htable_szvp.h"
-#include "ares__htable_asvp.h"
-#include "ares__htable_vpvp.h"
-#include "ares__buf.h"
-#include "ares_dns_private.h"
-#include "ares__iface_ips.h"
-#include "ares__threads.h"
+#include "dsa/ares__array.h"
+#include "dsa/ares__llist.h"
+#include "dsa/ares__slist.h"
+#include "dsa/ares__htable_strvp.h"
+#include "dsa/ares__htable_szvp.h"
+#include "dsa/ares__htable_asvp.h"
+#include "dsa/ares__htable_vpvp.h"
+#include "record/ares_dns_multistring.h"
+#include "str/ares__buf.h"
+#include "record/ares_dns_private.h"
+#include "util/ares__iface_ips.h"
+#include "util/ares__threads.h"
#ifndef HAVE_GETENV
# include "ares_getenv.h"
# define getenv(ptr) ares_getenv(ptr)
#endif
-#include "ares_str.h"
-#include "ares_strsplit.h"
+#include "str/ares_str.h"
+#include "str/ares_strsplit.h"
#ifndef HAVE_STRCASECMP
-# include "ares_strcasecmp.h"
+# include "str/ares_strcasecmp.h"
# define strcasecmp(p1, p2) ares_strcasecmp(p1, p2)
#endif
#ifndef HAVE_STRNCASECMP
-# include "ares_strcasecmp.h"
+# include "str/ares_strcasecmp.h"
# define strncasecmp(p1, p2, n) ares_strncasecmp(p1, p2, n)
#endif
@@ -153,18 +151,36 @@ typedef struct ares_rand_state ares_rand_state;
#define DEFAULT_SERVER_RETRY_CHANCE 10
#define DEFAULT_SERVER_RETRY_DELAY 5000
-struct query;
-
-struct server_state;
-
-struct server_connection {
- struct server_state *server;
- ares_socket_t fd;
- ares_bool_t is_tcp;
+struct ares_query;
+typedef struct ares_query ares_query_t;
+
+struct ares_server;
+typedef struct ares_server ares_server_t;
+
+struct ares_conn;
+typedef struct ares_conn ares_conn_t;
+
+typedef enum {
+ /*! No flags */
+ ARES_CONN_FLAG_NONE = 0,
+ /*! TCP connection, not UDP */
+ ARES_CONN_FLAG_TCP = 1 << 0,
+ /*! TCP Fast Open is enabled and being used if supported by the OS */
+ ARES_CONN_FLAG_TFO = 1 << 1,
+ /*! TCP Fast Open has not yet sent its first packet. Gets unset on first
+ * write to a connection */
+ ARES_CONN_FLAG_TFO_INITIAL = 1 << 2
+} ares_conn_flags_t;
+
+struct ares_conn {
+ ares_server_t *server;
+ ares_socket_t fd;
+ struct ares_addr self_ip;
+ ares_conn_flags_t flags;
/* total number of queries run on this connection since it was established */
- size_t total_queries;
+ size_t total_queries;
/* list of outstanding queries to this connection */
- ares__llist_t *queries_to_conn;
+ ares__llist_t *queries_to_conn;
};
#ifdef _MSC_VER
@@ -183,67 +199,128 @@ typedef struct {
unsigned int usec; /*!< Microseconds. Can't be negative. */
} ares_timeval_t;
-struct server_state {
+/*! Various buckets for grouping history */
+typedef enum {
+ ARES_METRIC_1MINUTE = 0, /*!< Bucket for tracking over the last minute */
+ ARES_METRIC_15MINUTES, /*!< Bucket for tracking over the last 15 minutes */
+ ARES_METRIC_1HOUR, /*!< Bucket for tracking over the last hour */
+ ARES_METRIC_1DAY, /*!< Bucket for tracking over the last day */
+ ARES_METRIC_INCEPTION, /*!< Bucket for tracking since inception */
+ ARES_METRIC_COUNT /*!< Count of buckets, not a real bucket */
+} ares_server_bucket_t;
+
+/*! Data metrics collected for each bucket */
+typedef struct {
+ time_t ts; /*!< Timestamp divided by bucket divisor */
+ unsigned int latency_min_ms; /*!< Minimum latency for queries */
+ unsigned int latency_max_ms; /*!< Maximum latency for queries */
+ ares_uint64_t total_ms; /*!< Cumulative query time for bucket */
+ ares_uint64_t total_count; /*!< Number of queries for bucket */
+
+ time_t prev_ts; /*!< Previous period bucket timestamp */
+ ares_uint64_t
+ prev_total_ms; /*!< Previous period bucket cumulative query time */
+ ares_uint64_t prev_total_count; /*!< Previous period bucket query count */
+} ares_server_metrics_t;
+
+typedef enum {
+ ARES_COOKIE_INITIAL = 0,
+ ARES_COOKIE_GENERATED = 1,
+ ARES_COOKIE_SUPPORTED = 2,
+ ARES_COOKIE_UNSUPPORTED = 3
+} ares_cookie_state_t;
+
+/*! Structure holding tracking data for RFC 7873/9018 DNS cookies.
+ * Implementation plan for this feature is here:
+ * https://github.com/c-ares/c-ares/issues/620
+ */
+typedef struct {
+ /*! starts at INITIAL, transitions as needed. */
+ ares_cookie_state_t state;
+ /*! randomly-generate client cookie */
+ unsigned char client[8];
+ /*! timestamp client cookie was generated, used for rotation purposes */
+ ares_timeval_t client_ts;
+ /*! IP address last used for client to connect to server. If this changes
+ * The client cookie gets invalidated */
+ struct ares_addr client_ip;
+ /*! Server Cookie last received, 8-32 bytes in length */
+ unsigned char server[32];
+ /*! Length of server cookie on file. */
+ size_t server_len;
+ /*! Timestamp of last attempt to use cookies, but it was determined that the
+ * server didn't support them */
+ ares_timeval_t unsupported_ts;
+} ares_cookie_t;
+
+struct ares_server {
/* Configuration */
- size_t idx; /* index for server in system configuration */
- struct ares_addr addr;
- unsigned short udp_port; /* host byte order */
- unsigned short tcp_port; /* host byte order */
- char ll_iface[64]; /* IPv6 Link Local Interface */
- unsigned int ll_scope; /* IPv6 Link Local Scope */
-
- size_t consec_failures; /* Consecutive query failure count
- * can be hard errors or timeouts
- */
- ares__llist_t *connections;
- struct server_connection *tcp_conn;
+ size_t idx; /* index for server in system configuration */
+ struct ares_addr addr;
+ unsigned short udp_port; /* host byte order */
+ unsigned short tcp_port; /* host byte order */
+ char ll_iface[64]; /* IPv6 Link Local Interface */
+ unsigned int ll_scope; /* IPv6 Link Local Scope */
+
+ size_t consec_failures; /* Consecutive query failure count
+ * can be hard errors or timeouts
+ */
+ ares__llist_t *connections;
+ ares_conn_t *tcp_conn;
/* The next time when we will retry this server if it has hit failures */
- ares_timeval_t next_retry_time;
+ ares_timeval_t next_retry_time;
/* TCP buffer since multiple responses can come back in one read, or partial
* in a read */
- ares__buf_t *tcp_parser;
+ ares__buf_t *tcp_parser;
/* TCP output queue */
- ares__buf_t *tcp_send;
+ ares__buf_t *tcp_send;
+
+ /*! Buckets for collecting metrics about the server */
+ ares_server_metrics_t metrics[ARES_METRIC_COUNT];
+
+ /*! RFC 7873/9018 DNS Cookies */
+ ares_cookie_t cookie;
/* Link back to owning channel */
- ares_channel_t *channel;
+ ares_channel_t *channel;
};
/* State to represent a DNS query */
-struct query {
+struct ares_query {
/* Query ID from qbuf, for faster lookup, and current timeout */
- unsigned short qid; /* host byte order */
- ares_timeval_t timeout;
- ares_channel_t *channel;
+ unsigned short qid; /* host byte order */
+ ares_timeval_t ts; /*!< Timestamp query was sent */
+ ares_timeval_t timeout;
+ ares_channel_t *channel;
/*
* Node object for each list entry the query belongs to in order to
* make removal operations O(1).
*/
- ares__slist_node_t *node_queries_by_timeout;
- ares__llist_node_t *node_queries_to_conn;
- ares__llist_node_t *node_all_queries;
+ ares__slist_node_t *node_queries_by_timeout;
+ ares__llist_node_t *node_queries_to_conn;
+ ares__llist_node_t *node_all_queries;
/* connection handle query is associated with */
- struct server_connection *conn;
+ ares_conn_t *conn;
- /* Arguments passed to ares_send() */
- unsigned char *qbuf;
- size_t qlen;
+ /* Query */
+ ares_dns_record_t *query;
- ares_callback_dnsrec callback;
- void *arg;
+ ares_callback_dnsrec callback;
+ void *arg;
/* Query status */
size_t try_count; /* Number of times we tried this query already. */
+ size_t cookie_try_count; /* Attempt count for cookie resends */
ares_bool_t using_tcp;
ares_status_t error_status;
- size_t timeouts; /* number of timeouts we saw for this request */
- ares_bool_t no_retries; /* do not perform any additional retries, this is set
- * when a query is to be canceled */
+ size_t timeouts; /* number of timeouts we saw for this request */
+ ares_bool_t no_retries; /* do not perform any additional retries, this is
+ * set when a query is to be canceled */
};
struct apattern {
@@ -361,6 +438,12 @@ struct ares_channeldata {
* exit. */
ares_bool_t reinit_pending;
ares__thread_t *reinit_thread;
+
+ /* Whether the system is up or not. This is mainly to prevent deadlocks
+ * and access violations during the cleanup process. Some things like
+ * system config changes might get triggered and we need a flag to make
+ * sure we don't take action. */
+ ares_bool_t sys_up;
};
/* Does the domain end in ".onion" or ".onion."? Case-insensitive. */
@@ -378,9 +461,11 @@ ares_bool_t ares__timedout(const ares_timeval_t *now,
const ares_timeval_t *check);
/* Returns one of the normal ares status codes like ARES_SUCCESS */
-ares_status_t ares__send_query(struct query *query, const ares_timeval_t *now);
-ares_status_t ares__requeue_query(struct query *query,
- const ares_timeval_t *now);
+ares_status_t ares__send_query(ares_query_t *query, const ares_timeval_t *now);
+ares_status_t ares__requeue_query(ares_query_t *query,
+ const ares_timeval_t *now,
+ ares_status_t status,
+ ares_bool_t inc_try_count);
/*! Retrieve a list of names to use for searching. The first successful
* query in the list wins. This function also uses the HOSTSALIASES file
@@ -408,38 +493,34 @@ void *ares__dnsrec_convert_arg(ares_callback callback, void *arg);
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);
+void ares__close_connection(ares_conn_t *conn, ares_status_t requeue_status);
+void ares__close_sockets(ares_server_t *server);
+void ares__check_cleanup_conns(const ares_channel_t *channel);
+void ares__free_query(ares_query_t *query);
ares_rand_state *ares__init_rand_state(void);
void ares__destroy_rand_state(ares_rand_state *state);
void ares__rand_bytes(ares_rand_state *state, unsigned char *buf, size_t len);
unsigned short ares__generate_new_id(ares_rand_state *state);
-ares_timeval_t ares__tvnow(void);
+void ares__tvnow(ares_timeval_t *now);
void ares__timeval_remaining(ares_timeval_t *remaining,
const ares_timeval_t *now,
const ares_timeval_t *tout);
-ares_status_t ares__expand_name_validated(const unsigned char *encoded,
- const unsigned char *abuf,
- size_t alen, char **s, size_t *enclen,
- ares_bool_t is_hostname);
-ares_status_t ares__expand_name_for_response(const unsigned char *encoded,
- const unsigned char *abuf,
- size_t alen, char **s,
- size_t *enclen,
- ares_bool_t is_hostname);
-ares_status_t ares_expand_string_ex(const unsigned char *encoded,
- const unsigned char *abuf, size_t alen,
- unsigned char **s, size_t *enclen);
-ares_status_t ares__init_servers_state(ares_channel_t *channel);
-ares_status_t ares__init_by_options(ares_channel_t *channel,
- const struct ares_options *options,
- int optmask);
-ares_status_t ares__init_by_sysconfig(ares_channel_t *channel);
+void ares__timeval_diff(ares_timeval_t *tvdiff, const ares_timeval_t *tvstart,
+ const ares_timeval_t *tvstop);
+ares_status_t ares__expand_name_validated(const unsigned char *encoded,
+ const unsigned char *abuf,
+ size_t alen, char **s, size_t *enclen,
+ ares_bool_t is_hostname);
+ares_status_t ares_expand_string_ex(const unsigned char *encoded,
+ const unsigned char *abuf, size_t alen,
+ unsigned char **s, size_t *enclen);
+ares_status_t ares__init_servers_state(ares_channel_t *channel);
+ares_status_t ares__init_by_options(ares_channel_t *channel,
+ const struct ares_options *options,
+ int optmask);
+ares_status_t ares__init_by_sysconfig(ares_channel_t *channel);
typedef struct {
ares__llist_t *sconfig;
@@ -465,6 +546,9 @@ ares_status_t ares__init_sysconfig_files(const ares_channel_t *channel,
#ifdef __APPLE__
ares_status_t ares__init_sysconfig_macos(ares_sysconfig_t *sysconfig);
#endif
+#ifdef USE_WINSOCK
+ares_status_t ares__init_sysconfig_windows(ares_sysconfig_t *sysconfig);
+#endif
ares_status_t ares__parse_sortlist(struct apattern **sortlist, size_t *nsort,
const char *str);
@@ -519,23 +603,28 @@ ares_status_t ares__addrinfo2addrttl(const struct ares_addrinfo *ai, int family,
ares_status_t ares__addrinfo_localhost(const char *name, unsigned short port,
const struct ares_addrinfo_hints *hints,
struct ares_addrinfo *ai);
-ares_status_t ares__open_connection(ares_channel_t *channel,
- struct server_state *server,
- ares_bool_t is_tcp);
+ares_status_t ares__open_connection(ares_conn_t **conn_out,
+ ares_channel_t *channel,
+ ares_server_t *server, ares_bool_t is_tcp);
+ares_bool_t ares_sockaddr_to_ares_addr(struct ares_addr *ares_addr,
+ unsigned short *port,
+ const struct sockaddr *sockaddr);
ares_socket_t ares__open_socket(ares_channel_t *channel, int af, int type,
int protocol);
-ares_ssize_t ares__socket_write(ares_channel_t *channel, ares_socket_t s,
- const void *data, size_t len);
+ares_bool_t ares__socket_try_again(int errnum);
+ares_ssize_t ares__conn_write(ares_conn_t *conn, const void *data, size_t len);
ares_ssize_t ares__socket_recvfrom(ares_channel_t *channel, ares_socket_t s,
void *data, size_t data_len, int flags,
struct sockaddr *from,
ares_socklen_t *from_len);
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);
-void ares__destroy_server(struct server_state *server);
+void ares__close_socket(ares_channel_t *channel, ares_socket_t s);
+ares_status_t ares__connect_socket(ares_channel_t *channel,
+ ares_socket_t sockfd,
+ const struct sockaddr *addr,
+ ares_socklen_t addrlen);
+void ares__destroy_server(ares_server_t *server);
ares_status_t ares__servers_update(ares_channel_t *channel,
ares__llist_t *server_list,
@@ -551,8 +640,8 @@ ares_status_t ares__sconfig_append_fromstr(ares__llist_t **sconfig,
ares_status_t ares_in_addr_to_server_config_llist(const struct in_addr *servers,
size_t nservers,
ares__llist_t **llist);
-ares_status_t ares_get_server_addr(const struct server_state *server,
- ares__buf_t *buf);
+ares_status_t ares_get_server_addr(const ares_server_t *server,
+ ares__buf_t *buf);
struct ares_hosts_entry;
typedef struct ares_hosts_entry ares_hosts_entry_t;
@@ -573,6 +662,26 @@ ares_status_t ares__hosts_entry_to_addrinfo(const ares_hosts_entry_t *entry,
ares_bool_t want_cnames,
struct ares_addrinfo *ai);
+/* Same as ares_query_dnsrec() except does not take a channel lock. Use this
+ * if a channel lock is already held */
+ares_status_t ares_query_nolock(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);
+
+/* Same as ares_send_dnsrec() except does not take a channel lock. Use this
+ * if a channel lock is already held */
+ares_status_t ares_send_nolock(ares_channel_t *channel,
+ const ares_dns_record_t *dnsrec,
+ ares_callback_dnsrec callback, void *arg,
+ unsigned short *qid);
+
+/* Same as ares_gethostbyaddr() except does not take a channel lock. Use this
+ * if a channel lock is already held */
+void ares_gethostbyaddr_nolock(ares_channel_t *channel, const void *addr,
+ int addrlen, int family,
+ ares_host_callback callback, void *arg);
/*! Parse a compressed DNS name as defined in RFC1035 starting at the current
* offset within the buffer.
@@ -622,13 +731,6 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
void ares_queue_notify_empty(ares_channel_t *channel);
-#define ARES_SWAP_BYTE(a, b) \
- do { \
- unsigned char swapByte = *(a); \
- *(a) = *(b); \
- *(b) = swapByte; \
- } while (0)
-
#define SOCK_STATE_CALLBACK(c, s, r, w) \
do { \
if ((c)->sock_state_cb) { \
@@ -645,6 +747,7 @@ ares_bool_t ares__subnet_match(const struct ares_addr *addr,
unsigned char netmask);
ares_bool_t ares__addr_is_linklocal(const struct ares_addr *addr);
+ares_bool_t ares__is_64bit(void);
size_t ares__round_up_pow2(size_t n);
size_t ares__log2(size_t n);
size_t ares__pow(size_t x, size_t y);
@@ -658,13 +761,25 @@ ares_status_t ares__qcache_create(ares_rand_state *rand_state,
void ares__qcache_flush(ares__qcache_t *cache);
ares_status_t ares_qcache_insert(ares_channel_t *channel,
const ares_timeval_t *now,
- const struct query *query,
+ const ares_query_t *query,
ares_dns_record_t *dnsrec);
ares_status_t ares_qcache_fetch(ares_channel_t *channel,
const ares_timeval_t *now,
const ares_dns_record_t *dnsrec,
const ares_dns_record_t **dnsrec_resp);
+void ares_metrics_record(const ares_query_t *query, ares_server_t *server,
+ ares_status_t status, const ares_dns_record_t *dnsrec);
+size_t ares_metrics_server_timeout(const ares_server_t *server,
+ const ares_timeval_t *now);
+
+ares_status_t ares_cookie_apply(ares_dns_record_t *dnsrec, ares_conn_t *conn,
+ const ares_timeval_t *now);
+ares_status_t ares_cookie_validate(ares_query_t *query,
+ const ares_dns_record_t *dnsresp,
+ ares_conn_t *conn,
+ const ares_timeval_t *now);
+
ares_status_t ares__channel_threading_init(ares_channel_t *channel);
void ares__channel_threading_destroy(ares_channel_t *channel);
void ares__channel_lock(const ares_channel_t *channel);
diff --git a/contrib/libs/c-ares/src/lib/ares_process.c b/contrib/libs/c-ares/src/lib/ares_process.c
index 0d8f3ca9ed..65ee673f6e 100644
--- a/contrib/libs/c-ares/src/lib/ares_process.c
+++ b/contrib/libs/c-ares/src/lib/ares_process.c
@@ -25,8 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-
+#include "ares_private.h"
#ifdef HAVE_STRINGS_H
# include <strings.h>
@@ -45,13 +44,8 @@
#include <fcntl.h>
#include <limits.h>
-#include "ares.h"
-#include "ares_private.h"
-#include "ares_nameser.h"
-#include "ares_dns.h"
static void timeadd(ares_timeval_t *now, size_t millisecs);
-static ares_bool_t try_again(int errnum);
static void write_tcp_data(ares_channel_t *channel, fd_set *write_fds,
ares_socket_t write_fd);
static void read_packets(ares_channel_t *channel, fd_set *read_fds,
@@ -60,21 +54,32 @@ static void process_timeouts(ares_channel_t *channel,
const ares_timeval_t *now);
static ares_status_t process_answer(ares_channel_t *channel,
const unsigned char *abuf, size_t alen,
- struct server_connection *conn,
- ares_bool_t tcp, const ares_timeval_t *now);
-static void handle_conn_error(struct server_connection *conn,
- ares_bool_t critical_failure);
-
-static ares_bool_t same_questions(const ares_dns_record_t *qrec,
- const ares_dns_record_t *arec);
-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 ares_dns_record_t *dnsrec);
+ ares_conn_t *conn, ares_bool_t tcp,
+ const ares_timeval_t *now);
+static void handle_conn_error(ares_conn_t *conn, ares_bool_t critical_failure,
+ ares_status_t failure_status);
+
+static ares_bool_t same_questions(const ares_query_t *query,
+ const ares_dns_record_t *arec);
+static ares_bool_t same_address(const struct sockaddr *sa,
+ const struct ares_addr *aa);
+static void end_query(ares_channel_t *channel, ares_server_t *server,
+ ares_query_t *query, ares_status_t status,
+ const ares_dns_record_t *dnsrec);
+
+static void ares__query_disassociate_from_conn(ares_query_t *query)
+{
+ /* If its not part of a connection, it can't be tracked for timeouts either */
+ ares__slist_node_destroy(query->node_queries_by_timeout);
+ ares__llist_node_destroy(query->node_queries_to_conn);
+ query->node_queries_by_timeout = NULL;
+ query->node_queries_to_conn = NULL;
+ query->conn = NULL;
+}
/* Invoke the server state callback after a success or failure */
-static void invoke_server_state_cb(const struct server_state *server,
- ares_bool_t success, int flags)
+static void invoke_server_state_cb(const ares_server_t *server,
+ ares_bool_t success, int flags)
{
const ares_channel_t *channel = server->channel;
ares__buf_t *buf;
@@ -87,19 +92,19 @@ static void invoke_server_state_cb(const struct server_state *server,
buf = ares__buf_create();
if (buf == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares_get_server_addr(server, buf);
if (status != ARES_SUCCESS) {
- ares__buf_destroy(buf);
- return;
+ ares__buf_destroy(buf); /* LCOV_EXCL_LINE: OutOfMemory */
+ return; /* LCOV_EXCL_LINE: OutOfMemory */
}
server_string = ares__buf_finish_str(buf, NULL);
buf = NULL;
if (server_string == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: OutOfMemory */
}
channel->server_state_cb(server_string, success, flags,
@@ -107,8 +112,8 @@ static void invoke_server_state_cb(const struct server_state *server,
ares_free(server_string);
}
-static void server_increment_failures(struct server_state *server,
- ares_bool_t used_tcp)
+static void server_increment_failures(ares_server_t *server,
+ ares_bool_t used_tcp)
{
ares__slist_node_t *node;
const ares_channel_t *channel = server->channel;
@@ -116,13 +121,13 @@ static void server_increment_failures(struct server_state *server,
node = ares__slist_node_find(channel->servers, server);
if (node == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
server->consec_failures++;
ares__slist_node_reinsert(node);
- next_retry_time = ares__tvnow();
+ ares__tvnow(&next_retry_time);
timeadd(&next_retry_time, channel->server_retry_delay);
server->next_retry_time = next_retry_time;
@@ -131,14 +136,14 @@ static void server_increment_failures(struct server_state *server,
: ARES_SERV_STATE_UDP);
}
-static void server_set_good(struct server_state *server, ares_bool_t used_tcp)
+static void server_set_good(ares_server_t *server, ares_bool_t used_tcp)
{
ares__slist_node_t *node;
const ares_channel_t *channel = server->channel;
node = ares__slist_node_find(channel->servers, server);
if (node == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (server->consec_failures > 0) {
@@ -195,17 +200,19 @@ static void processfds(ares_channel_t *channel, fd_set *read_fds,
ares_timeval_t now;
if (channel == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares__channel_lock(channel);
- now = ares__tvnow();
+ ares__tvnow(&now);
read_packets(channel, read_fds, read_fd, &now);
process_timeouts(channel, &now);
/* Write last as the other 2 operations might have triggered writes */
write_tcp_data(channel, write_fds, write_fd);
+ /* See if any connections should be cleaned up */
+ ares__check_cleanup_conns(channel);
ares__channel_unlock(channel);
}
@@ -228,34 +235,6 @@ void ares_process_fd(ares_channel_t *channel,
processfds(channel, NULL, read_fd, NULL, write_fd);
}
-/* Return 1 if the specified error number describes a readiness error, or 0
- * otherwise. This is mostly for HP-UX, which could return EAGAIN or
- * EWOULDBLOCK. See this man page
- *
- * http://devrsrc1.external.hp.com/STKS/cgi-bin/man2html?
- * manpage=/usr/share/man/man2.Z/send.2
- */
-static ares_bool_t try_again(int errnum)
-{
-#if !defined EWOULDBLOCK && !defined EAGAIN
-# error "Neither EWOULDBLOCK nor EAGAIN defined"
-#endif
-
-#ifdef EWOULDBLOCK
- if (errnum == EWOULDBLOCK) {
- return ARES_TRUE;
- }
-#endif
-
-#if defined EAGAIN && EAGAIN != EWOULDBLOCK
- if (errnum == EAGAIN) {
- return ARES_TRUE;
- }
-#endif
-
- return ARES_FALSE;
-}
-
/* If any TCP sockets select true for writing, write out queued data
* we have for them.
*/
@@ -271,7 +250,7 @@ static void write_tcp_data(ares_channel_t *channel, fd_set *write_fds,
for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) {
- struct server_state *server = ares__slist_node_val(node);
+ ares_server_t *server = ares__slist_node_val(node);
const unsigned char *data;
size_t data_len;
ares_ssize_t count;
@@ -302,10 +281,10 @@ static void write_tcp_data(ares_channel_t *channel, fd_set *write_fds,
}
data = ares__buf_peek(server->tcp_send, &data_len);
- count = ares__socket_write(channel, server->tcp_conn->fd, data, data_len);
+ count = ares__conn_write(server->tcp_conn, data, data_len);
if (count <= 0) {
- if (!try_again(SOCKERRNO)) {
- handle_conn_error(server->tcp_conn, ARES_TRUE);
+ if (!ares__socket_try_again(SOCKERRNO)) {
+ handle_conn_error(server->tcp_conn, ARES_TRUE, ARES_ECONNREFUSED);
}
continue;
}
@@ -324,21 +303,21 @@ static void write_tcp_data(ares_channel_t *channel, fd_set *write_fds,
* allocate a buffer if we finish reading the length word, and process
* a packet if we finish reading one.
*/
-static void read_tcp_data(ares_channel_t *channel,
- struct server_connection *conn,
- const ares_timeval_t *now)
+static void read_tcp_data(ares_channel_t *channel, ares_conn_t *conn,
+ const ares_timeval_t *now)
{
- ares_ssize_t count;
- struct server_state *server = conn->server;
+ ares_ssize_t count;
+ ares_server_t *server = conn->server;
/* Fetch buffer to store data we are reading */
- size_t ptr_len = 65535;
- unsigned char *ptr;
+ size_t ptr_len = 65535;
+ unsigned char *ptr;
ptr = ares__buf_append_start(server->tcp_parser, &ptr_len);
if (ptr == NULL) {
- handle_conn_error(conn, ARES_FALSE /* not critical to connection */);
+ handle_conn_error(conn, ARES_FALSE /* not critical to connection */,
+ ARES_SUCCESS);
return; /* bail out on malloc failure. TODO: make this
function return error codes */
}
@@ -347,8 +326,8 @@ static void read_tcp_data(ares_channel_t *channel,
count = ares__socket_recv(channel, conn->fd, ptr, ptr_len);
if (count <= 0) {
ares__buf_append_finish(server->tcp_parser, 0);
- if (!(count == -1 && try_again(SOCKERRNO))) {
- handle_conn_error(conn, ARES_TRUE);
+ if (!(count == -1 && ares__socket_try_again(SOCKERRNO))) {
+ handle_conn_error(conn, ARES_TRUE, ARES_ECONNREFUSED);
}
return;
}
@@ -380,7 +359,7 @@ static void read_tcp_data(ares_channel_t *channel,
/* Can't fail except for misuse */
data = ares__buf_tag_fetch(server->tcp_parser, &data_len);
- if (data == NULL) {
+ if (data == NULL || data_len < 2) {
ares__buf_tag_clear(server->tcp_parser);
break;
}
@@ -392,80 +371,57 @@ static void read_tcp_data(ares_channel_t *channel,
/* We finished reading this answer; process it */
status = process_answer(channel, data, data_len, conn, ARES_TRUE, now);
if (status != ARES_SUCCESS) {
- handle_conn_error(conn, ARES_TRUE);
+ handle_conn_error(conn, ARES_TRUE, status);
return;
}
/* Since we processed the answer, clear the tag so space can be reclaimed */
ares__buf_tag_clear(server->tcp_parser);
}
-
- ares__check_cleanup_conn(channel, conn);
-}
-
-static int socket_list_append(ares_socket_t **socketlist, ares_socket_t fd,
- size_t *alloc_cnt, size_t *num)
-{
- if (*num >= *alloc_cnt) {
- /* Grow by powers of 2 */
- size_t new_alloc = (*alloc_cnt) << 1;
- ares_socket_t *new_list =
- ares_realloc(socketlist, new_alloc * sizeof(*new_list));
- if (new_list == NULL) {
- return 0;
- }
- *alloc_cnt = new_alloc;
- *socketlist = new_list;
- }
-
- (*socketlist)[(*num)++] = fd;
- return 1;
}
static ares_socket_t *channel_socket_list(const ares_channel_t *channel,
size_t *num)
{
- size_t alloc_cnt = 1 << 4;
- ares_socket_t *out = ares_malloc(alloc_cnt * sizeof(*out));
ares__slist_node_t *snode;
+ ares__array_t *arr = ares__array_create(sizeof(ares_socket_t), NULL);
*num = 0;
- if (out == NULL) {
- return NULL;
+ if (arr == NULL) {
+ return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
}
for (snode = ares__slist_node_first(channel->servers); snode != NULL;
snode = ares__slist_node_next(snode)) {
- struct server_state *server = ares__slist_node_val(snode);
- ares__llist_node_t *node;
+ ares_server_t *server = ares__slist_node_val(snode);
+ ares__llist_node_t *node;
for (node = ares__llist_node_first(server->connections); node != NULL;
node = ares__llist_node_next(node)) {
- const struct server_connection *conn = ares__llist_node_val(node);
+ const ares_conn_t *conn = ares__llist_node_val(node);
+ ares_socket_t *sptr;
+ ares_status_t status;
if (conn->fd == ARES_SOCKET_BAD) {
continue;
}
- if (!socket_list_append(&out, conn->fd, &alloc_cnt, num)) {
- goto fail;
+ status = ares__array_insert_last((void **)&sptr, arr);
+ if (status != ARES_SUCCESS) {
+ ares__array_destroy(arr); /* LCOV_EXCL_LINE: OutOfMemory */
+ return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
}
+ *sptr = conn->fd;
}
}
- return out;
-
-fail:
- ares_free(out);
- *num = 0;
- return NULL;
+ return ares__array_finish(arr, num);
}
/* If any UDP sockets select true for reading, process them. */
-static void read_udp_packets_fd(ares_channel_t *channel,
- struct server_connection *conn,
- const ares_timeval_t *now)
+static void read_udp_packets_fd(ares_channel_t *channel, ares_conn_t *conn,
+ const ares_timeval_t *now)
{
ares_ssize_t read_len;
unsigned char buf[MAXENDSSZ + 1];
@@ -503,11 +459,11 @@ static void read_udp_packets_fd(ares_channel_t *channel,
* tcp */
continue;
} else if (read_len < 0) {
- if (try_again(SOCKERRNO)) {
+ if (ares__socket_try_again(SOCKERRNO)) {
break;
}
- handle_conn_error(conn, ARES_TRUE);
+ handle_conn_error(conn, ARES_TRUE, ARES_ECONNREFUSED);
return;
#ifdef HAVE_RECVFROM
} else if (!same_address(&from.sa, &conn->server->addr)) {
@@ -524,18 +480,16 @@ static void read_udp_packets_fd(ares_channel_t *channel,
/* Try to read again only if *we* set up the socket, otherwise it may be
* a blocking socket and would cause recvfrom to hang. */
} while (read_len >= 0 && channel->sock_funcs == NULL);
-
- ares__check_cleanup_conn(channel, conn);
}
static void read_packets(ares_channel_t *channel, fd_set *read_fds,
ares_socket_t read_fd, const ares_timeval_t *now)
{
- size_t i;
- ares_socket_t *socketlist = NULL;
- size_t num_sockets = 0;
- struct server_connection *conn = NULL;
- ares__llist_node_t *node = NULL;
+ size_t i;
+ ares_socket_t *socketlist = NULL;
+ size_t num_sockets = 0;
+ ares_conn_t *conn = NULL;
+ ares__llist_node_t *node = NULL;
if (!read_fds && (read_fd == ARES_SOCKET_BAD)) {
/* no possible action */
@@ -551,7 +505,7 @@ static void read_packets(ares_channel_t *channel, fd_set *read_fds,
conn = ares__llist_node_val(node);
- if (conn->is_tcp) {
+ if (conn->flags & ARES_CONN_FLAG_TCP) {
read_tcp_data(channel, conn, now);
} else {
read_udp_packets_fd(channel, conn, now);
@@ -585,7 +539,7 @@ static void read_packets(ares_channel_t *channel, fd_set *read_fds,
conn = ares__llist_node_val(node);
- if (conn->is_tcp) {
+ if (conn->flags & ARES_CONN_FLAG_TCP) {
read_tcp_data(channel, conn, now);
} else {
read_udp_packets_fd(channel, conn, now);
@@ -598,47 +552,42 @@ static void read_packets(ares_channel_t *channel, fd_set *read_fds,
/* If any queries have timed out, note the timeout and move them on. */
static void process_timeouts(ares_channel_t *channel, const ares_timeval_t *now)
{
- ares__slist_node_t *node =
- ares__slist_node_first(channel->queries_by_timeout);
- while (node != NULL) {
- struct query *query = ares__slist_node_val(node);
- /* Node might be removed, cache next */
- ares__slist_node_t *next = ares__slist_node_next(node);
- struct server_connection *conn;
+ ares__slist_node_t *node;
+
+ /* Just keep popping off the first as this list will re-sort as things come
+ * and go. We don't want to try to rely on 'next' as some operation might
+ * cause a cleanup of that pointer and would become invalid */
+ while ((node = ares__slist_node_first(channel->queries_by_timeout)) != NULL) {
+ ares_query_t *query = ares__slist_node_val(node);
+ ares_conn_t *conn;
+
/* Since this is sorted, as soon as we hit a query that isn't timed out,
* break */
if (!ares__timedout(now, &query->timeout)) {
break;
}
- query->error_status = ARES_ETIMEOUT;
query->timeouts++;
conn = query->conn;
server_increment_failures(conn->server, query->using_tcp);
- ares__requeue_query(query, now);
- ares__check_cleanup_conn(channel, conn);
-
- node = next;
+ ares__requeue_query(query, now, ARES_ETIMEOUT, ARES_TRUE);
}
}
-static ares_status_t rewrite_without_edns(ares_dns_record_t *qdnsrec,
- struct query *query)
+static ares_status_t rewrite_without_edns(ares_query_t *query)
{
- ares_status_t status;
- size_t i;
- ares_bool_t found_opt_rr = ARES_FALSE;
- unsigned char *msg = NULL;
- size_t msglen = 0;
+ ares_status_t status = ARES_SUCCESS;
+ size_t i;
+ ares_bool_t found_opt_rr = ARES_FALSE;
/* Find and remove the OPT RR record */
- for (i = 0; i < ares_dns_record_rr_cnt(qdnsrec, ARES_SECTION_ADDITIONAL);
+ for (i = 0; i < ares_dns_record_rr_cnt(query->query, ARES_SECTION_ADDITIONAL);
i++) {
const ares_dns_rr_t *rr;
- rr = ares_dns_record_rr_get(qdnsrec, ARES_SECTION_ADDITIONAL, i);
+ rr = ares_dns_record_rr_get(query->query, ARES_SECTION_ADDITIONAL, i);
if (ares_dns_rr_get_type(rr) == ARES_REC_TYPE_OPT) {
- ares_dns_record_rr_del(qdnsrec, ARES_SECTION_ADDITIONAL, i);
+ ares_dns_record_rr_del(query->query, ARES_SECTION_ADDITIONAL, i);
found_opt_rr = ARES_TRUE;
break;
}
@@ -649,16 +598,6 @@ static ares_status_t rewrite_without_edns(ares_dns_record_t *qdnsrec,
goto done;
}
- /* Rewrite the DNS message */
- status = ares_dns_write(qdnsrec, &msg, &msglen);
- if (status != ARES_SUCCESS) {
- goto done;
- }
-
- ares_free(query->qbuf);
- query->qbuf = msg;
- query->qlen = msglen;
-
done:
return status;
}
@@ -668,17 +607,16 @@ done:
* the connection to be terminated after this call. */
static ares_status_t process_answer(ares_channel_t *channel,
const unsigned char *abuf, size_t alen,
- struct server_connection *conn,
- ares_bool_t tcp, const ares_timeval_t *now)
+ ares_conn_t *conn, ares_bool_t tcp,
+ const ares_timeval_t *now)
{
- struct query *query;
+ ares_query_t *query;
/* Cache these as once ares__send_query() gets called, it may end up
* invalidating the connection all-together */
- struct server_state *server = conn->server;
- ares_dns_record_t *rdnsrec = NULL;
- ares_dns_record_t *qdnsrec = NULL;
- ares_status_t status;
- ares_bool_t is_cached = ARES_FALSE;
+ ares_server_t *server = conn->server;
+ ares_dns_record_t *rdnsrec = NULL;
+ ares_status_t status;
+ ares_bool_t is_cached = ARES_FALSE;
/* Parse the response */
status = ares_dns_parse(abuf, alen, 0, &rdnsrec);
@@ -699,21 +637,22 @@ static ares_status_t process_answer(ares_channel_t *channel,
goto cleanup;
}
- /* 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);
- goto cleanup;
- }
-
/* Both the query id and the questions must be the same. We will drop any
* replies that aren't for the same query as this is considered invalid. */
- if (!same_questions(qdnsrec, rdnsrec)) {
+ if (!same_questions(query, rdnsrec)) {
/* Possible qid conflict due to delayed response, that's ok */
status = ARES_SUCCESS;
goto cleanup;
}
+ /* Validate DNS cookie in response. This function may need to requeue the
+ * query. */
+ if (ares_cookie_validate(query, rdnsrec, conn, now) != ARES_SUCCESS) {
+ /* Drop response and return */
+ status = ARES_SUCCESS;
+ goto cleanup;
+ }
+
/* At this point we know we've received an answer for this query, so we should
* remove it from the connection's queue so we can possibly invalidate the
* connection. Delay cleaning up the connection though as we may enqueue
@@ -725,10 +664,11 @@ static ares_status_t process_answer(ares_channel_t *channel,
* protocol extension is not understood by the responder. We must retry the
* query without EDNS enabled. */
if (ares_dns_record_get_rcode(rdnsrec) == ARES_RCODE_FORMERR &&
- ares_dns_has_opt_rr(qdnsrec) && !ares_dns_has_opt_rr(rdnsrec)) {
- status = rewrite_without_edns(qdnsrec, query);
+ ares_dns_get_opt_rr_const(query->query) != NULL &&
+ ares_dns_get_opt_rr_const(rdnsrec) == NULL) {
+ status = rewrite_without_edns(query);
if (status != ARES_SUCCESS) {
- end_query(channel, query, status, NULL);
+ end_query(channel, server, query, status, NULL);
goto cleanup;
}
@@ -758,20 +698,20 @@ static ares_status_t process_answer(ares_channel_t *channel,
rcode == ARES_RCODE_REFUSED) {
switch (rcode) {
case ARES_RCODE_SERVFAIL:
- query->error_status = ARES_ESERVFAIL;
+ status = ARES_ESERVFAIL;
break;
case ARES_RCODE_NOTIMP:
- query->error_status = ARES_ENOTIMP;
+ status = ARES_ENOTIMP;
break;
case ARES_RCODE_REFUSED:
- query->error_status = ARES_EREFUSED;
+ status = ARES_EREFUSED;
break;
default:
break;
}
server_increment_failures(server, query->using_tcp);
- ares__requeue_query(query, now);
+ ares__requeue_query(query, now, status, ARES_TRUE);
/* Should any of these cause a connection termination?
* Maybe SERVER_FAILURE? */
@@ -787,7 +727,7 @@ static ares_status_t process_answer(ares_channel_t *channel,
}
server_set_good(server, query->using_tcp);
- end_query(channel, query, ARES_SUCCESS, rdnsrec);
+ end_query(channel, server, query, ARES_SUCCESS, rdnsrec);
status = ARES_SUCCESS;
@@ -797,32 +737,42 @@ cleanup:
ares_dns_record_destroy(rdnsrec);
}
- ares_dns_record_destroy(qdnsrec);
return status;
}
-static void handle_conn_error(struct server_connection *conn,
- ares_bool_t critical_failure)
+static void handle_conn_error(ares_conn_t *conn, ares_bool_t critical_failure,
+ ares_status_t failure_status)
{
- struct server_state *server = conn->server;
+ ares_server_t *server = conn->server;
/* Increment failures first before requeue so it is unlikely to requeue
* to the same server */
if (critical_failure) {
- server_increment_failures(server, conn->is_tcp);
+ server_increment_failures(
+ server, (conn->flags & ARES_CONN_FLAG_TCP) ? ARES_TRUE : ARES_FALSE);
}
/* This will requeue any connections automatically */
- ares__close_connection(conn);
+ ares__close_connection(conn, failure_status);
}
-ares_status_t ares__requeue_query(struct query *query,
- const ares_timeval_t *now)
+ares_status_t ares__requeue_query(ares_query_t *query,
+ const ares_timeval_t *now,
+ ares_status_t status,
+ ares_bool_t inc_try_count)
{
ares_channel_t *channel = query->channel;
size_t max_tries = ares__slist_len(channel->servers) * channel->tries;
- query->try_count++;
+ ares__query_disassociate_from_conn(query);
+
+ if (status != ARES_SUCCESS) {
+ query->error_status = status;
+ }
+
+ if (inc_try_count) {
+ query->try_count++;
+ }
if (query->try_count < max_tries && !query->no_retries) {
return ares__send_query(query, now);
@@ -833,14 +783,14 @@ ares_status_t ares__requeue_query(struct query *query,
query->error_status = ARES_ETIMEOUT;
}
- end_query(channel, query, query->error_status, NULL);
+ end_query(channel, NULL, query, query->error_status, NULL);
return ARES_ETIMEOUT;
}
/* Pick a random server from the list, we first get a random number in the
* range of the number of servers, then scan until we find that server in
* the list */
-static struct server_state *ares__random_server(ares_channel_t *channel)
+static ares_server_t *ares__random_server(ares_channel_t *channel)
{
unsigned char c;
size_t cnt;
@@ -884,16 +834,15 @@ static struct server_state *ares__random_server(ares_channel_t *channel)
* To resolve this, with some probability we select a failed server to retry
* instead.
*/
-static struct server_state *ares__failover_server(ares_channel_t *channel)
+static ares_server_t *ares__failover_server(ares_channel_t *channel)
{
- struct server_state *first_server = ares__slist_first_val(channel->servers);
- const struct server_state *last_server =
- ares__slist_last_val(channel->servers);
- unsigned short r;
+ ares_server_t *first_server = ares__slist_first_val(channel->servers);
+ const ares_server_t *last_server = ares__slist_last_val(channel->servers);
+ unsigned short r;
/* Defensive code against no servers being available on the channel. */
if (first_server == NULL) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* If no servers have failures, then prefer the first server in the list. */
@@ -916,11 +865,13 @@ static struct server_state *ares__failover_server(ares_channel_t *channel)
ares__rand_bytes(channel->rand_state, (unsigned char *)&r, sizeof(r));
if (r % channel->server_retry_chance == 0) {
/* Select a suitable failed server to retry. */
- ares_timeval_t now = ares__tvnow();
+ ares_timeval_t now;
ares__slist_node_t *node;
+
+ ares__tvnow(&now);
for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) {
- struct server_state *node_val = ares__slist_node_val(node);
+ ares_server_t *node_val = ares__slist_node_val(node);
if (node_val != NULL && node_val->consec_failures > 0 &&
ares__timedout(&now, &node_val->next_retry_time)) {
return node_val;
@@ -932,27 +883,18 @@ static struct server_state *ares__failover_server(ares_channel_t *channel)
return first_server;
}
-static ares_status_t ares__append_tcpbuf(struct server_state *server,
- const struct query *query)
-{
- ares_status_t status;
-
- status = ares__buf_append_be16(server->tcp_send, (unsigned short)query->qlen);
- if (status != ARES_SUCCESS) {
- return status;
- }
- return ares__buf_append(server->tcp_send, query->qbuf, query->qlen);
-}
-
-static size_t ares__calc_query_timeout(const struct query *query)
+static size_t ares__calc_query_timeout(const ares_query_t *query,
+ const ares_server_t *server,
+ const ares_timeval_t *now)
{
const ares_channel_t *channel = query->channel;
- size_t timeplus = channel->timeout;
+ size_t timeout = ares_metrics_server_timeout(server, now);
+ size_t timeplus = timeout;
size_t rounds;
size_t num_servers = ares__slist_len(channel->servers);
if (num_servers == 0) {
- return 0;
+ return 0; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* For each trip through the entire server list, we want to double the
@@ -986,159 +928,211 @@ static size_t ares__calc_query_timeout(const struct query *query)
/* We want explicitly guarantee that timeplus is greater or equal to timeout
* specified in channel options. */
- if (timeplus < channel->timeout) {
- timeplus = channel->timeout;
+ if (timeplus < timeout) {
+ timeplus = timeout;
}
return timeplus;
}
-ares_status_t ares__send_query(struct query *query, const ares_timeval_t *now)
+static ares_conn_t *ares__fetch_connection(const ares_channel_t *channel,
+ ares_server_t *server,
+ const ares_query_t *query)
{
- ares_channel_t *channel = query->channel;
- struct server_state *server;
- struct server_connection *conn;
- size_t timeplus;
- ares_status_t status;
- ares_bool_t new_connection = ARES_FALSE;
-
- query->conn = NULL;
+ ares__llist_node_t *node;
+ ares_conn_t *conn;
- /* Choose the server to send the query to */
- if (channel->rotate) {
- /* Pull random server */
- server = ares__random_server(channel);
- } else {
- /* Pull server with failover behavior */
- server = ares__failover_server(channel);
+ if (query->using_tcp) {
+ return server->tcp_conn;
}
- if (server == NULL) {
- end_query(channel, query, ARES_ENOSERVER /* ? */, NULL);
- return ARES_ENOSERVER;
+ /* Fetch existing UDP connection */
+ node = ares__llist_node_first(server->connections);
+ if (node == NULL) {
+ return NULL;
}
- if (query->using_tcp) {
- size_t prior_len = 0;
- /* Make sure the TCP socket for this server is set up and queue
- * a send request.
- */
- if (server->tcp_conn == NULL) {
- new_connection = ARES_TRUE;
- status = ares__open_connection(channel, server, ARES_TRUE);
- switch (status) {
- /* Good result, continue on */
- case ARES_SUCCESS:
- break;
+ conn = ares__llist_node_val(node);
+ /* Not UDP, skip */
+ if (conn->flags & ARES_CONN_FLAG_TCP) {
+ return NULL;
+ }
- /* These conditions are retryable as they are server-specific
- * error codes */
- case ARES_ECONNREFUSED:
- case ARES_EBADFAMILY:
- server_increment_failures(server, query->using_tcp);
- query->error_status = status;
- return ares__requeue_query(query, now);
+ /* Used too many times */
+ if (channel->udp_max_queries > 0 &&
+ conn->total_queries >= channel->udp_max_queries) {
+ return NULL;
+ }
- /* Anything else is not retryable, likely ENOMEM */
- default:
- end_query(channel, query, status, NULL);
- return status;
- }
- }
+ return conn;
+}
- conn = server->tcp_conn;
+static ares_status_t ares__conn_query_write(ares_conn_t *conn,
+ ares_query_t *query,
+ const ares_timeval_t *now)
+{
+ unsigned char *qbuf = NULL;
+ size_t qbuf_len = 0;
+ ares_ssize_t len;
+ ares_server_t *server = conn->server;
+ ares_channel_t *channel = server->channel;
+ ares_status_t status;
+
+ status = ares_cookie_apply(query->query, conn, now);
+ if (status != ARES_SUCCESS) {
+ return status;
+ }
- prior_len = ares__buf_len(server->tcp_send);
+ if (conn->flags & ARES_CONN_FLAG_TCP) {
+ size_t prior_len = ares__buf_len(server->tcp_send);
- status = ares__append_tcpbuf(server, query);
+ status = ares_dns_write_buf_tcp(query->query, server->tcp_send);
if (status != ARES_SUCCESS) {
- end_query(channel, query, status, NULL);
+ return status;
+ }
- /* Only safe to kill connection if it was new, otherwise it should be
- * cleaned up by another process later */
- if (new_connection) {
- ares__close_connection(conn);
+ if (conn->flags & ARES_CONN_FLAG_TFO_INITIAL) {
+ /* When using TFO, we need to put it on the wire immediately. */
+ size_t data_len;
+ const unsigned char *data = NULL;
+
+ data = ares__buf_peek(server->tcp_send, &data_len);
+ len = ares__conn_write(conn, data, data_len);
+ if (len <= 0) {
+ if (ares__socket_try_again(SOCKERRNO)) {
+ /* This means we must not have qualified for TFO, keep the data
+ * buffered, wait on write signal. */
+ return ARES_SUCCESS;
+ }
+
+ /* TCP TFO might delay failure. Reflect that here */
+ return ARES_ECONNREFUSED;
}
- return status;
+
+ /* Consume what was written */
+ ares__buf_consume(server->tcp_send, (size_t)len);
+ return ARES_SUCCESS;
}
if (prior_len == 0) {
SOCK_STATE_CALLBACK(channel, conn->fd, 1, 1);
}
- } else {
- ares__llist_node_t *node = ares__llist_node_first(server->connections);
-
- /* Don't use the found connection if we've gone over the maximum number
- * of queries. Also, skip over the TCP connection if it is the first in
- * the list */
- if (node != NULL) {
- conn = ares__llist_node_val(node);
- if (conn->is_tcp) {
- node = NULL;
- } else if (channel->udp_max_queries > 0 &&
- conn->total_queries >= channel->udp_max_queries) {
- node = NULL;
- }
+ return ARES_SUCCESS;
+ }
+
+ /* UDP Here */
+ status = ares_dns_write(query->query, &qbuf, &qbuf_len);
+ if (status != ARES_SUCCESS) {
+ return status;
+ }
+
+ len = ares__conn_write(conn, qbuf, qbuf_len);
+ ares_free(qbuf);
+
+ if (len == -1) {
+ if (ares__socket_try_again(SOCKERRNO)) {
+ return ARES_ESERVFAIL;
}
+ /* UDP is connection-less, but we might receive an ICMP unreachable which
+ * means we can't talk to the remote host at all and that will be
+ * reflected here */
+ return ARES_ECONNREFUSED;
+ }
- if (node == NULL) {
- new_connection = ARES_TRUE;
- status = ares__open_connection(channel, server, ARES_FALSE);
- switch (status) {
- /* Good result, continue on */
- case ARES_SUCCESS:
- break;
+ return ARES_SUCCESS;
+}
+
+ares_status_t ares__send_query(ares_query_t *query, const ares_timeval_t *now)
+{
+ ares_channel_t *channel = query->channel;
+ ares_server_t *server;
+ ares_conn_t *conn;
+ size_t timeplus;
+ ares_status_t status;
- /* These conditions are retryable as they are server-specific
- * error codes */
- case ARES_ECONNREFUSED:
- case ARES_EBADFAMILY:
- server_increment_failures(server, query->using_tcp);
- query->error_status = status;
- return ares__requeue_query(query, now);
+ /* Choose the server to send the query to */
+ if (channel->rotate) {
+ /* Pull random server */
+ server = ares__random_server(channel);
+ } else {
+ /* Pull server with failover behavior */
+ server = ares__failover_server(channel);
+ }
- /* Anything else is not retryable, likely ENOMEM */
- default:
- end_query(channel, query, status, NULL);
- return status;
- }
- node = ares__llist_node_first(server->connections);
+ if (server == NULL) {
+ end_query(channel, server, query, ARES_ENOSERVER /* ? */, NULL);
+ return ARES_ENOSERVER;
+ }
+
+ conn = ares__fetch_connection(channel, server, query);
+ if (conn == NULL) {
+ status = ares__open_connection(&conn, channel, server, query->using_tcp);
+ switch (status) {
+ /* Good result, continue on */
+ case ARES_SUCCESS:
+ break;
+
+ /* These conditions are retryable as they are server-specific
+ * error codes */
+ case ARES_ECONNREFUSED:
+ case ARES_EBADFAMILY:
+ server_increment_failures(server, query->using_tcp);
+ return ares__requeue_query(query, now, status, ARES_TRUE);
+
+ /* Anything else is not retryable, likely ENOMEM */
+ default:
+ end_query(channel, server, query, status, NULL);
+ return status;
}
+ }
- conn = ares__llist_node_val(node);
- if (ares__socket_write(channel, conn->fd, query->qbuf, query->qlen) == -1) {
- /* FIXME: Handle EAGAIN here since it likely can happen. */
- server_increment_failures(server, query->using_tcp);
- status = ares__requeue_query(query, now);
+ /* Write the query */
+ status = ares__conn_query_write(conn, query, now);
+ switch (status) {
+ /* Good result, continue on */
+ case ARES_SUCCESS:
+ break;
- /* Only safe to kill connection if it was new, otherwise it should be
- * cleaned up by another process later */
- if (new_connection) {
- ares__close_connection(conn);
+ case ARES_ENOMEM:
+ /* Not retryable */
+ end_query(channel, server, query, status, NULL);
+ return status;
+
+ /* These conditions are retryable as they are server-specific
+ * error codes */
+ case ARES_ECONNREFUSED:
+ case ARES_EBADFAMILY:
+ handle_conn_error(conn, ARES_TRUE, status);
+ status = ares__requeue_query(query, now, status, ARES_TRUE);
+ if (status == ARES_ETIMEOUT) {
+ status = ARES_ECONNREFUSED;
}
+ return status;
+ /* FIXME: Handle EAGAIN here since it likely can happen. Right now we
+ * just requeue to a different server/connection. */
+ default:
+ server_increment_failures(server, query->using_tcp);
+ status = ares__requeue_query(query, now, status, ARES_TRUE);
return status;
- }
}
- timeplus = ares__calc_query_timeout(query);
+ timeplus = ares__calc_query_timeout(query, server, now);
/* Keep track of queries bucketed by timeout, so we can process
* timeout events quickly.
*/
ares__slist_node_destroy(query->node_queries_by_timeout);
+ query->ts = *now;
query->timeout = *now;
timeadd(&query->timeout, timeplus);
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);
- /* Only safe to kill connection if it was new, otherwise it should be
- * cleaned up by another process later */
- if (new_connection) {
- ares__close_connection(conn);
- }
+ /* LCOV_EXCL_START: OutOfMemory */
+ end_query(channel, server, query, ARES_ENOMEM, NULL);
return ARES_ENOMEM;
+ /* LCOV_EXCL_STOP */
}
/* Keep track of queries bucketed by connection, so we can process errors
@@ -1148,13 +1142,10 @@ ares_status_t ares__send_query(struct query *query, const ares_timeval_t *now)
ares__llist_insert_last(conn->queries_to_conn, query);
if (query->node_queries_to_conn == NULL) {
- 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) {
- ares__close_connection(conn);
- }
+ /* LCOV_EXCL_START: OutOfMemory */
+ end_query(channel, server, query, ARES_ENOMEM, NULL);
return ARES_ENOMEM;
+ /* LCOV_EXCL_STOP */
}
query->conn = conn;
@@ -1162,11 +1153,13 @@ ares_status_t ares__send_query(struct query *query, const ares_timeval_t *now)
return ARES_SUCCESS;
}
-static ares_bool_t same_questions(const ares_dns_record_t *qrec,
+static ares_bool_t same_questions(const ares_query_t *query,
const ares_dns_record_t *arec)
{
- size_t i;
- ares_bool_t rv = ARES_FALSE;
+ size_t i;
+ ares_bool_t rv = ARES_FALSE;
+ const ares_dns_record_t *qrec = query->query;
+ const ares_channel_t *channel = query->channel;
if (ares_dns_record_query_cnt(qrec) != ares_dns_record_query_cnt(arec)) {
@@ -1192,9 +1185,26 @@ static ares_bool_t same_questions(const ares_dns_record_t *qrec,
aname == NULL) {
goto done;
}
- if (strcasecmp(qname, aname) != 0 || qtype != atype || qclass != aclass) {
+
+ if (qtype != atype || qclass != aclass) {
goto done;
}
+
+ if (channel->flags & ARES_FLAG_DNS0x20 && !query->using_tcp) {
+ /* NOTE: for DNS 0x20, part of the protection is to use a case-sensitive
+ * comparison of the DNS query name. This expects the upstream DNS
+ * server to preserve the case of the name in the response packet.
+ * https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00
+ */
+ if (strcmp(qname, aname) != 0) {
+ goto done;
+ }
+ } else {
+ /* without DNS0x20 use case-insensitive matching */
+ if (strcasecmp(qname, aname) != 0) {
+ goto done;
+ }
+ }
}
rv = ARES_TRUE;
@@ -1213,14 +1223,15 @@ static ares_bool_t same_address(const struct sockaddr *sa,
switch (aa->family) {
case AF_INET:
addr1 = &aa->addr.addr4;
- addr2 = &(CARES_INADDR_CAST(struct sockaddr_in *, sa))->sin_addr;
+ addr2 = &(CARES_INADDR_CAST(const struct sockaddr_in *, sa))->sin_addr;
if (memcmp(addr1, addr2, sizeof(aa->addr.addr4)) == 0) {
return ARES_TRUE; /* match */
}
break;
case AF_INET6:
addr1 = &aa->addr.addr6;
- addr2 = &(CARES_INADDR_CAST(struct sockaddr_in6 *, sa))->sin6_addr;
+ addr2 =
+ &(CARES_INADDR_CAST(const struct sockaddr_in6 *, sa))->sin6_addr;
if (memcmp(addr1, addr2, sizeof(aa->addr.addr6)) == 0) {
return ARES_TRUE; /* match */
}
@@ -1232,21 +1243,21 @@ static ares_bool_t same_address(const struct sockaddr *sa,
return ARES_FALSE; /* different */
}
-static void ares_detach_query(struct query *query)
+static void ares_detach_query(ares_query_t *query)
{
/* Remove the query from all the lists in which it is linked */
+ ares__query_disassociate_from_conn(query);
ares__htable_szvp_remove(query->channel->queries_by_qid, query->qid);
- ares__slist_node_destroy(query->node_queries_by_timeout);
- ares__llist_node_destroy(query->node_queries_to_conn);
ares__llist_node_destroy(query->node_all_queries);
- query->node_queries_by_timeout = NULL;
- query->node_queries_to_conn = NULL;
- query->node_all_queries = NULL;
+ query->node_all_queries = NULL;
}
-static void end_query(ares_channel_t *channel, struct query *query,
- ares_status_t status, const ares_dns_record_t *dnsrec)
+static void end_query(ares_channel_t *channel, ares_server_t *server,
+ ares_query_t *query, ares_status_t status,
+ const ares_dns_record_t *dnsrec)
{
+ ares_metrics_record(query, server, status, dnsrec);
+
/* Invoke the callback. */
query->callback(query->arg, status, query->timeouts, dnsrec);
ares__free_query(query);
@@ -1259,14 +1270,14 @@ static void end_query(ares_channel_t *channel, struct query *query,
ares_queue_notify_empty(channel);
}
-void ares__free_query(struct query *query)
+void ares__free_query(ares_query_t *query)
{
ares_detach_query(query);
/* Zero out some important stuff, to help catch bugs */
query->callback = NULL;
query->arg = NULL;
/* Deallocate the memory associated with the query */
- ares_free(query->qbuf);
+ ares_dns_record_destroy(query->query);
ares_free(query);
}
diff --git a/contrib/libs/c-ares/src/lib/ares_qcache.c b/contrib/libs/c-ares/src/lib/ares_qcache.c
index 087518d7b8..aee1328b51 100644
--- a/contrib/libs/c-ares/src/lib/ares_qcache.c
+++ b/contrib/libs/c-ares/src/lib/ares_qcache.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
struct ares__qcache {
@@ -48,7 +46,7 @@ static char *ares__qcache_calc_key(const ares_dns_record_t *dnsrec)
ares_dns_flags_t flags;
if (dnsrec == NULL || buf == NULL) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Format is OPCODE|FLAGS[|QTYPE1|QCLASS1|QNAME1]... */
@@ -56,12 +54,12 @@ static char *ares__qcache_calc_key(const ares_dns_record_t *dnsrec)
status = ares__buf_append_str(
buf, ares_dns_opcode_tostr(ares_dns_record_get_opcode(dnsrec)));
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append_byte(buf, '|');
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
flags = ares_dns_record_get_flags(dnsrec);
@@ -69,13 +67,13 @@ static char *ares__qcache_calc_key(const ares_dns_record_t *dnsrec)
if (flags & ARES_FLAG_RD) {
status = ares__buf_append_str(buf, "rd");
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
if (flags & ARES_FLAG_CD) {
status = ares__buf_append_str(buf, "cd");
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -87,32 +85,32 @@ static char *ares__qcache_calc_key(const ares_dns_record_t *dnsrec)
status = ares_dns_record_query_get(dnsrec, i, &name, &qtype, &qclass);
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: DefensiveCoding */
}
status = ares__buf_append_byte(buf, '|');
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append_str(buf, ares_dns_rec_type_tostr(qtype));
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append_byte(buf, '|');
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append_str(buf, ares_dns_class_tostr(qclass));
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append_byte(buf, '|');
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* On queries, a '.' may be appended to the name to indicate an explicit
@@ -125,15 +123,17 @@ static char *ares__qcache_calc_key(const ares_dns_record_t *dnsrec)
status = ares__buf_append(buf, (const unsigned char *)name, name_len);
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
return ares__buf_finish_str(buf, NULL);
+/* LCOV_EXCL_START: OutOfMemory */
fail:
ares__buf_destroy(buf);
return NULL;
+ /* LCOV_EXCL_STOP */
}
static void ares__qcache_expire(ares__qcache_t *cache,
@@ -194,7 +194,7 @@ static void ares__qcache_entry_destroy_cb(void *arg)
{
ares__qcache_entry_t *entry = arg;
if (entry == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares_free(entry->key);
@@ -211,21 +211,21 @@ ares_status_t ares__qcache_create(ares_rand_state *rand_state,
cache = ares_malloc_zero(sizeof(*cache));
if (cache == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
cache->cache = ares__htable_strvp_create(NULL);
if (cache->cache == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
cache->expire = ares__slist_create(rand_state, ares__qcache_entry_sort_cb,
ares__qcache_entry_destroy_cb);
if (cache->expire == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
cache->max_ttl = max_ttl;
@@ -299,37 +299,18 @@ static unsigned int ares__qcache_soa_minimum(ares_dns_record_t *dnsrec)
return 0;
}
-static char *ares__qcache_calc_key_frombuf(const unsigned char *qbuf,
- size_t qlen)
-{
- ares_status_t status;
- ares_dns_record_t *dnsrec = NULL;
- char *key = NULL;
-
- status = ares_dns_parse(qbuf, qlen, 0, &dnsrec);
- if (status != ARES_SUCCESS) {
- goto done;
- }
-
- key = ares__qcache_calc_key(dnsrec);
-
-done:
- ares_dns_record_destroy(dnsrec);
- return key;
-}
-
/* On success, takes ownership of dnsrec */
-static ares_status_t ares__qcache_insert(ares__qcache_t *qcache,
- ares_dns_record_t *dnsrec,
- const unsigned char *qbuf, size_t qlen,
- const ares_timeval_t *now)
+static ares_status_t ares__qcache_insert(ares__qcache_t *qcache,
+ ares_dns_record_t *qresp,
+ const ares_dns_record_t *qreq,
+ const ares_timeval_t *now)
{
ares__qcache_entry_t *entry;
unsigned int ttl;
- ares_dns_rcode_t rcode = ares_dns_record_get_rcode(dnsrec);
- ares_dns_flags_t flags = ares_dns_record_get_flags(dnsrec);
+ ares_dns_rcode_t rcode = ares_dns_record_get_rcode(qresp);
+ ares_dns_flags_t flags = ares_dns_record_get_flags(qresp);
- if (qcache == NULL || dnsrec == NULL) {
+ if (qcache == NULL || qresp == NULL) {
return ARES_EFORMERR;
}
@@ -345,9 +326,13 @@ static ares_status_t ares__qcache_insert(ares__qcache_t *qcache,
/* Look at SOA for NXDOMAIN for minimum */
if (rcode == ARES_RCODE_NXDOMAIN) {
- ttl = ares__qcache_soa_minimum(dnsrec);
+ ttl = ares__qcache_soa_minimum(qresp);
} else {
- ttl = ares__qcache_calc_minttl(dnsrec);
+ ttl = ares__qcache_calc_minttl(qresp);
+ }
+
+ if (ttl > qcache->max_ttl) {
+ ttl = qcache->max_ttl;
}
/* Don't cache something that is already expired */
@@ -355,16 +340,12 @@ static ares_status_t ares__qcache_insert(ares__qcache_t *qcache,
return ARES_EREFUSED;
}
- if (ttl > qcache->max_ttl) {
- ttl = qcache->max_ttl;
- }
-
entry = ares_malloc_zero(sizeof(*entry));
if (entry == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
- entry->dnsrec = dnsrec;
+ entry->dnsrec = qresp;
entry->expire_ts = now->sec + (time_t)ttl;
entry->insert_ts = now->sec;
@@ -372,21 +353,22 @@ static ares_status_t ares__qcache_insert(ares__qcache_t *qcache,
* request had, so we have to re-parse the request in order to generate the
* key for caching, but we'll only do this once we know for sure we really
* want to cache it */
- entry->key = ares__qcache_calc_key_frombuf(qbuf, qlen);
+ entry->key = ares__qcache_calc_key(qreq);
if (entry->key == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
if (!ares__htable_strvp_insert(qcache->cache, entry->key, entry)) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
if (ares__slist_insert(qcache->expire, entry) == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
return ARES_SUCCESS;
+/* LCOV_EXCL_START: OutOfMemory */
fail:
if (entry != NULL && entry->key != NULL) {
ares__htable_strvp_remove(qcache->cache, entry->key);
@@ -394,6 +376,7 @@ fail:
ares_free(entry);
}
return ARES_ENOMEM;
+ /* LCOV_EXCL_STOP */
}
ares_status_t ares_qcache_fetch(ares_channel_t *channel,
@@ -417,8 +400,8 @@ ares_status_t ares_qcache_fetch(ares_channel_t *channel,
key = ares__qcache_calc_key(dnsrec);
if (key == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
entry = ares__htable_strvp_get_direct(channel->qcache->cache, key);
@@ -439,9 +422,8 @@ done:
ares_status_t ares_qcache_insert(ares_channel_t *channel,
const ares_timeval_t *now,
- const struct query *query,
+ const ares_query_t *query,
ares_dns_record_t *dnsrec)
{
- return ares__qcache_insert(channel->qcache, dnsrec, query->qbuf, query->qlen,
- now);
+ return ares__qcache_insert(channel->qcache, dnsrec, query->query, now);
}
diff --git a/contrib/libs/c-ares/src/lib/ares_query.c b/contrib/libs/c-ares/src/lib/ares_query.c
index 0eea80e7fc..4d0861a5f5 100644
--- a/contrib/libs/c-ares/src/lib/ares_query.c
+++ b/contrib/libs/c-ares/src/lib/ares_query.c
@@ -25,18 +25,12 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
-#include "ares_nameser.h"
-
-#include "ares.h"
-#include "ares_dns.h"
-#include "ares_private.h"
-
typedef struct {
ares_callback_dnsrec callback;
void *arg;
@@ -64,11 +58,11 @@ static void ares_query_dnsrec_cb(void *arg, ares_status_t status,
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 ares_query_nolock(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;
@@ -76,11 +70,13 @@ static ares_status_t ares_query_int(ares_channel_t *channel, const char *name,
ares_query_dnsrec_arg_t *qquery = NULL;
if (channel == NULL || name == NULL || callback == NULL) {
+ /* LCOV_EXCL_START: DefensiveCoding */
status = ARES_EFORMERR;
if (callback != NULL) {
callback(arg, status, 0, NULL);
}
return status;
+ /* LCOV_EXCL_STOP */
}
if (!(channel->flags & ARES_FLAG_NORECURSE)) {
@@ -91,23 +87,25 @@ static ares_status_t ares_query_int(ares_channel_t *channel, const char *name,
&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;
+ callback(arg, status, 0, NULL); /* LCOV_EXCL_LINE: OutOfMemory */
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
qquery = ares_malloc(sizeof(*qquery));
if (qquery == NULL) {
+ /* LCOV_EXCL_START: OutOfMemory */
status = ARES_ENOMEM;
callback(arg, status, 0, NULL);
ares_dns_record_destroy(dnsrec);
return status;
+ /* LCOV_EXCL_STOP */
}
qquery->callback = callback;
qquery->arg = arg;
/* Send it off. qcallback will be called when we get an answer. */
- status = ares_send_dnsrec(channel, dnsrec, ares_query_dnsrec_cb, qquery, qid);
+ status = ares_send_nolock(channel, dnsrec, ares_query_dnsrec_cb, qquery, qid);
ares_dns_record_destroy(dnsrec);
return status;
@@ -126,7 +124,7 @@ ares_status_t ares_query_dnsrec(ares_channel_t *channel, const char *name,
}
ares__channel_lock(channel);
- status = ares_query_int(channel, name, dnsclass, type, callback, arg, qid);
+ status = ares_query_nolock(channel, name, dnsclass, type, callback, arg, qid);
ares__channel_unlock(channel);
return status;
}
@@ -142,8 +140,8 @@ void ares_query(ares_channel_t *channel, const char *name, int dnsclass,
carg = ares__dnsrec_convert_arg(callback, arg);
if (carg == NULL) {
- callback(arg, ARES_ENOMEM, 0, NULL, 0);
- return;
+ callback(arg, ARES_ENOMEM, 0, NULL, 0); /* LCOV_EXCL_LINE: OutOfMemory */
+ return; /* LCOV_EXCL_LINE: OutOfMemory */
}
ares_query_dnsrec(channel, name, (ares_dns_class_t)dnsclass,
diff --git a/contrib/libs/c-ares/src/lib/ares_search.c b/contrib/libs/c-ares/src/lib/ares_search.c
index 4fd909cd4f..ae98df39a8 100644
--- a/contrib/libs/c-ares/src/lib/ares_search.c
+++ b/contrib/libs/c-ares/src/lib/ares_search.c
@@ -25,16 +25,12 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
-#include "ares.h"
-#include "ares_private.h"
-#include "ares_dns.h"
-
struct search_query {
/* Arguments passed to ares_search_dnsrec() */
ares_channel_t *channel;
@@ -57,7 +53,7 @@ struct search_query {
static void squery_free(struct search_query *squery)
{
if (squery == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares__strsplit_free(squery->names, squery->names_cnt);
ares_dns_record_destroy(squery->dnsrec);
@@ -87,7 +83,7 @@ static ares_status_t ares_search_next(ares_channel_t *channel,
/* Misuse check */
if (squery->next_name_idx >= squery->names_cnt) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
status = ares_dns_record_query_set_name(
@@ -97,7 +93,7 @@ static ares_status_t ares_search_next(ares_channel_t *channel,
}
status =
- ares_send_dnsrec(channel, squery->dnsrec, search_callback, squery, NULL);
+ ares_send_nolock(channel, squery->dnsrec, search_callback, squery, NULL);
if (status != ARES_EFORMERR) {
*skip_cleanup = ARES_TRUE;
@@ -200,8 +196,8 @@ ares_status_t ares__search_name_list(const ares_channel_t *channel,
list_len = 1;
list = ares_malloc_zero(sizeof(*list) * list_len);
if (list == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
list[0] = alias;
alias = NULL;
@@ -215,12 +211,12 @@ ares_status_t ares__search_name_list(const ares_channel_t *channel,
list_len = 1;
list = ares_malloc_zero(sizeof(*list) * list_len);
if (list == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
list[0] = ares_strdup(name);
if (list[0] == NULL) {
- status = ARES_ENOMEM;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
} else {
status = ARES_SUCCESS;
}
@@ -322,8 +318,8 @@ static ares_status_t ares_search_int(ares_channel_t *channel,
*/
squery = ares_malloc_zero(sizeof(*squery));
if (squery == NULL) {
- status = ARES_ENOMEM;
- goto fail;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
squery->channel = channel;
@@ -331,8 +327,8 @@ static ares_status_t ares_search_int(ares_channel_t *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;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
squery->callback = callback;
@@ -456,7 +452,7 @@ ares_status_t ares_search_dnsrec(ares_channel_t *channel,
ares_status_t status;
if (channel == NULL || dnsrec == NULL || callback == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares__channel_lock(channel);
@@ -498,7 +494,7 @@ ares_status_t ares__lookup_hostaliases(const ares_channel_t *channel,
ares__llist_node_t *node;
if (channel == NULL || name == NULL || alias == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
*alias = NULL;
@@ -521,8 +517,8 @@ ares_status_t ares__lookup_hostaliases(const ares_channel_t *channel,
buf = ares__buf_create();
if (buf == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_load_file(hostaliases, buf);
@@ -581,8 +577,8 @@ ares_status_t ares__lookup_hostaliases(const ares_channel_t *channel,
*alias = ares_strdup(fqdn);
if (*alias == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Good! */
diff --git a/contrib/libs/c-ares/src/lib/ares_send.c b/contrib/libs/c-ares/src/lib/ares_send.c
index 8bbc6e758b..9441534404 100644
--- a/contrib/libs/c-ares/src/lib/ares_send.c
+++ b/contrib/libs/c-ares/src/lib/ares_send.c
@@ -25,18 +25,13 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
-
#include "ares_nameser.h"
-#include "ares.h"
-#include "ares_dns.h"
-#include "ares_private.h"
-
static unsigned short generate_unique_qid(ares_channel_t *channel)
{
unsigned short id;
@@ -48,18 +43,77 @@ static unsigned short generate_unique_qid(ares_channel_t *channel)
return id;
}
-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)
+/* https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00 */
+static ares_status_t ares_apply_dns0x20(ares_channel_t *channel,
+ ares_dns_record_t *dnsrec)
+{
+ ares_status_t status = ARES_SUCCESS;
+ const char *name = NULL;
+ char dns0x20name[256];
+ unsigned char randdata[256 / 8];
+ size_t len;
+ size_t remaining_bits;
+ size_t total_bits;
+ size_t i;
+
+ status = ares_dns_record_query_get(dnsrec, 0, &name, NULL, NULL);
+ if (status != ARES_SUCCESS) {
+ goto done;
+ }
+
+ len = ares_strlen(name);
+ if (len == 0 || len >= sizeof(dns0x20name)) {
+ status = ARES_EBADNAME;
+ goto done;
+ }
+
+ memset(dns0x20name, 0, sizeof(dns0x20name));
+
+ /* Fetch the minimum amount of random data we'd need for the string, which
+ * is 1 bit per byte */
+ total_bits = ((len + 7) / 8) * 8;
+ remaining_bits = total_bits;
+ ares__rand_bytes(channel->rand_state, randdata, total_bits / 8);
+
+ /* Randomly apply 0x20 to name */
+ for (i = 0; i < len; i++) {
+ size_t bit;
+
+ /* Only apply 0x20 to alpha characters */
+ if (!ares__isalpha(name[i])) {
+ dns0x20name[i] = name[i];
+ continue;
+ }
+
+ /* coin flip */
+ bit = total_bits - remaining_bits;
+ if (randdata[bit / 8] & (1 << (bit % 8))) {
+ dns0x20name[i] = name[i] | 0x20; /* Set 0x20 */
+ } else {
+ dns0x20name[i] = (char)(((unsigned char)name[i]) & 0xDF); /* Unset 0x20 */
+ }
+ remaining_bits--;
+ }
+
+ status = ares_dns_record_query_set_name(dnsrec, 0, dns0x20name);
+
+done:
+ return status;
+}
+
+ares_status_t ares_send_nolock(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;
- ares_timeval_t now = ares__tvnow();
+ ares_query_t *query;
+ ares_timeval_t now;
ares_status_t status;
unsigned short id = generate_unique_qid(channel);
const ares_dns_record_t *dnsrec_resp = NULL;
+ ares__tvnow(&now);
+
if (ares__slist_len(channel->servers) == 0) {
callback(arg, ARES_ENOSERVER, 0, NULL);
return ARES_ENOSERVER;
@@ -75,29 +129,40 @@ static ares_status_t ares_send_dnsrec_int(ares_channel_t *channel,
}
/* Allocate space for query and allocated fields. */
- query = ares_malloc(sizeof(struct query));
+ query = ares_malloc(sizeof(ares_query_t));
if (!query) {
- callback(arg, ARES_ENOMEM, 0, NULL);
- return ARES_ENOMEM;
+ callback(arg, ARES_ENOMEM, 0, NULL); /* LCOV_EXCL_LINE: OutOfMemory */
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
memset(query, 0, sizeof(*query));
- query->channel = channel;
+ query->channel = channel;
+ query->qid = id;
+ query->timeout.sec = 0;
+ query->timeout.usec = 0;
+ query->using_tcp =
+ (channel->flags & ARES_FLAG_USEVC) ? ARES_TRUE : ARES_FALSE;
- status = ares_dns_write(dnsrec, &query->qbuf, &query->qlen);
+ /* Duplicate Query */
+ status = ares_dns_record_duplicate_ex(&query->query, dnsrec);
if (status != ARES_SUCCESS) {
ares_free(query);
callback(arg, status, 0, NULL);
return status;
}
- query->qid = id;
- query->timeout.sec = 0;
- query->timeout.usec = 0;
-
- /* Ignore first 2 bytes, assign our own query id */
- query->qbuf[0] = (unsigned char)((id >> 8) & 0xFF);
- query->qbuf[1] = (unsigned char)(id & 0xFF);
+ ares_dns_record_set_id(query->query, id);
+
+ if (channel->flags & ARES_FLAG_DNS0x20 && !query->using_tcp) {
+ status = ares_apply_dns0x20(channel, query->query);
+ if (status != ARES_SUCCESS) {
+ /* LCOV_EXCL_START: OutOfMemory */
+ callback(arg, status, 0, NULL);
+ ares__free_query(query);
+ return status;
+ /* LCOV_EXCL_STOP */
+ }
+ }
/* Fill in query arguments. */
query->callback = callback;
@@ -106,9 +171,6 @@ static ares_status_t ares_send_dnsrec_int(ares_channel_t *channel,
/* Initialize query status. */
query->try_count = 0;
- packetsz = (channel->flags & ARES_FLAG_EDNS) ? channel->ednspsz : PACKETSZ;
- query->using_tcp =
- (channel->flags & ARES_FLAG_USEVC) || query->qlen > packetsz;
query->error_status = ARES_SUCCESS;
query->timeouts = 0;
@@ -121,18 +183,22 @@ static ares_status_t ares_send_dnsrec_int(ares_channel_t *channel,
query->node_all_queries =
ares__llist_insert_last(channel->all_queries, query);
if (query->node_all_queries == NULL) {
+ /* LCOV_EXCL_START: OutOfMemory */
callback(arg, ARES_ENOMEM, 0, NULL);
ares__free_query(query);
return ARES_ENOMEM;
+ /* LCOV_EXCL_STOP */
}
/* Keep track of queries bucketed by qid, so we can process DNS
* responses quickly.
*/
if (!ares__htable_szvp_insert(channel->queries_by_qid, query->qid, query)) {
+ /* LCOV_EXCL_START: OutOfMemory */
callback(arg, ARES_ENOMEM, 0, NULL);
ares__free_query(query);
return ARES_ENOMEM;
+ /* LCOV_EXCL_STOP */
}
/* Perform the first query action. */
@@ -152,12 +218,12 @@ ares_status_t ares_send_dnsrec(ares_channel_t *channel,
ares_status_t status;
if (channel == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares__channel_lock(channel);
- status = ares_send_dnsrec_int(channel, dnsrec, callback, arg, qid);
+ status = ares_send_nolock(channel, dnsrec, callback, arg, qid);
ares__channel_unlock(channel);
@@ -189,10 +255,12 @@ void ares_send(ares_channel_t *channel, const unsigned char *qbuf, int qlen,
carg = ares__dnsrec_convert_arg(callback, arg);
if (carg == NULL) {
+ /* LCOV_EXCL_START: OutOfMemory */
status = ARES_ENOMEM;
ares_dns_record_destroy(dnsrec);
callback(arg, (int)status, 0, NULL, 0);
return;
+ /* LCOV_EXCL_STOP */
}
ares_send_dnsrec(channel, dnsrec, ares__dnsrec_convert_cb, carg, NULL);
diff --git a/contrib/libs/c-ares/src/lib/ares_setup.h b/contrib/libs/c-ares/src/lib/ares_setup.h
index c506449dbd..d771e4e141 100644
--- a/contrib/libs/c-ares/src/lib/ares_setup.h
+++ b/contrib/libs/c-ares/src/lib/ares_setup.h
@@ -23,17 +23,17 @@
*
* SPDX-License-Identifier: MIT
*/
-#ifndef HEADER_CARES_SETUP_H
-#define HEADER_CARES_SETUP_H
-
-/*
- * Define WIN32 when build target is Win32 API
+#ifndef __ARES_SETUP_H
+#define __ARES_SETUP_H
+
+/* ============================================================================
+ * NOTE: This file is automatically included by ares_private.h and should not
+ * typically be included directly.
+ * All c-ares source files should include ares_private.h as the
+ * first header.
+ * ============================================================================
*/
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-# define WIN32
-#endif
-
/*
* Include configuration script results or hand-crafted
* configuration file for platforms which lack config tool.
@@ -42,62 +42,17 @@
#if defined(HAVE_CONFIG_H) && !defined(_MSC_VER)
# include "ares_config.h"
#else
-
-# ifdef WIN32
+# ifdef _WIN32
# include "config-win32.h"
# endif
-
#endif /* HAVE_CONFIG_H */
-/* ================================================================ */
-/* Definition of preprocessor macros/symbols which modify compiler */
-/* behaviour or generated code characteristics must be done here, */
-/* as appropriate, before any system header file is included. It is */
-/* also possible to have them defined in the config file included */
-/* before this point. As a result of all this we frown inclusion of */
-/* system header files in our config files, avoid this at any cost. */
-/* ================================================================ */
-
-/*
- * AIX 4.3 and newer needs _THREAD_SAFE defined to build
- * proper reentrant code. Others may also need it.
- */
-
-#ifdef NEED_THREAD_SAFE
-# ifndef _THREAD_SAFE
-# define _THREAD_SAFE
-# endif
-#endif
-
-/*
- * Tru64 needs _REENTRANT set for a few function prototypes and
- * things to appear in the system header files. Unixware needs it
- * to build proper reentrant code. Others may also need it.
- */
-
-#ifdef NEED_REENTRANT
-# ifndef _REENTRANT
-# define _REENTRANT
-# endif
-#endif
-
-/* ================================================================ */
-/* If you need to include a system header file for your platform, */
-/* please, do it beyond the point further indicated in this file. */
-/* ================================================================ */
-
/*
* c-ares external interface definitions are also used internally,
* and might also include required system header files to define them.
*/
-#include <ares_build.h>
-
-/*
- * Compile time sanity checks must also be done when building the library.
- */
-
-#include <ares_rules.h>
+#include "ares_build.h"
/* ================================================================= */
/* No system header file shall be included in this file before this */
@@ -115,6 +70,10 @@
* neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined.
*/
+#ifdef USE_WINSOCK
+# undef USE_WINSOCK
+#endif
+
#ifdef HAVE_WINDOWS_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
@@ -122,52 +81,56 @@
# include <windows.h>
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
+# define USE_WINSOCK 2
# ifdef HAVE_WS2TCPIP_H
# include <ws2tcpip.h>
# endif
# else
# ifdef HAVE_WINSOCK_H
# include <winsock.h>
+# define USE_WINSOCK 1
# endif
# endif
#endif
-/*
- * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else
- * define USE_WINSOCK to 1 if we have and use WINSOCK API, else
- * undefine USE_WINSOCK.
- */
-#ifdef USE_WINSOCK
-# undef USE_WINSOCK
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#ifdef HAVE_ERRNO_H
+# include <errno.h>
#endif
-#ifdef HAVE_WINSOCK2_H
-# define USE_WINSOCK 2
-#else
-# ifdef HAVE_WINSOCK_H
-# define USE_WINSOCK 1
-# endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
#endif
-/*
- * Work-arounds for systems without configure support
- */
+#ifdef HAVE_MALLOC_H
+# include <malloc.h>
+#endif
-#ifndef HAVE_CONFIG_H
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
-# if !defined(HAVE_SYS_TIME_H) && !defined(_MSC_VER) && !defined(__WATCOMC__)
-# define HAVE_SYS_TIME_H
-# endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
-# if !defined(HAVE_UNISTD_H) && !defined(_MSC_VER)
-# define HAVE_UNISTD_H 1
-# endif
+#ifdef HAVE_TIME_H
+# include <time.h>
+#endif
-# if !defined(HAVE_SYS_UIO_H) && !defined(WIN32) && !defined(MSDOS)
-# define HAVE_SYS_UIO_H
-# endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
-#endif /* HAVE_CONFIG_H */
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
/*
* Arg 2 type for gethostname in case it hasn't been defined in config file.
@@ -235,12 +198,170 @@
# endif
#endif
+
+#ifdef __hpux
+# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
+# ifdef _APP32_64BIT_OFF_T
+# define OLD_APP32_64BIT_OFF_T _APP32_64BIT_OFF_T
+# undef _APP32_64BIT_OFF_T
+# else
+# undef OLD_APP32_64BIT_OFF_T
+# endif
+# endif
+#endif
+
+#ifdef __hpux
+# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
+# ifdef OLD_APP32_64BIT_OFF_T
+# define _APP32_64BIT_OFF_T OLD_APP32_64BIT_OFF_T
+# undef OLD_APP32_64BIT_OFF_T
+# endif
+# endif
+#endif
+
+
+/*
+ * Definition of timeval struct for platforms that don't have it.
+ */
+
+#ifndef HAVE_STRUCT_TIMEVAL
+struct timeval {
+ long tv_sec;
+ long tv_usec;
+};
+#endif
+
+/*
+ * Function-like macro definition used to close a socket.
+ */
+
+#if defined(HAVE_CLOSESOCKET)
+# define sclose(x) closesocket((x))
+#elif defined(HAVE_CLOSESOCKET_CAMEL)
+# define sclose(x) CloseSocket((x))
+#elif defined(HAVE_CLOSE_S)
+# define sclose(x) close_s((x))
+#else
+# define sclose(x) close((x))
+#endif
+
/*
- * Include macros and defines that should only be processed once.
+ * Macro used to include code only in debug builds.
*/
-#ifndef __SETUP_ONCE_H
-# include "setup_once.h"
+#ifdef DEBUGBUILD
+# define DEBUGF(x) x
+#else
+# define DEBUGF(x) \
+ do { \
+ } while (0)
+#endif
+
+/*
+ * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno
+ * (or equivalent) on this platform to hide platform details to code using it.
+ */
+
+#ifdef USE_WINSOCK
+# define SOCKERRNO ((int)WSAGetLastError())
+# define SET_SOCKERRNO(x) (WSASetLastError((int)(x)))
+#else
+# define SOCKERRNO (errno)
+# define SET_SOCKERRNO(x) (errno = (x))
+#endif
+
+
+/*
+ * Macro ERRNO / SET_ERRNO() returns / sets the NOT *socket-related* errno
+ * (or equivalent) on this platform to hide platform details to code using it.
+ */
+
+#if defined(WIN32) && !defined(WATT32)
+# define ERRNO ((int)GetLastError())
+# define SET_ERRNO(x) (SetLastError((DWORD)(x)))
+#else
+# define ERRNO (errno)
+# define SET_ERRNO(x) (errno = (x))
+#endif
+
+
+/*
+ * Portable error number symbolic names defined to Winsock error codes.
+ */
+
+#ifdef USE_WINSOCK
+# undef EBADF /* override definition in errno.h */
+# define EBADF WSAEBADF
+# undef EINTR /* override definition in errno.h */
+# define EINTR WSAEINTR
+# undef EINVAL /* override definition in errno.h */
+# define EINVAL WSAEINVAL
+# undef EWOULDBLOCK /* override definition in errno.h */
+# define EWOULDBLOCK WSAEWOULDBLOCK
+# undef EINPROGRESS /* override definition in errno.h */
+# define EINPROGRESS WSAEINPROGRESS
+# undef EALREADY /* override definition in errno.h */
+# define EALREADY WSAEALREADY
+# undef ENOTSOCK /* override definition in errno.h */
+# define ENOTSOCK WSAENOTSOCK
+# undef EDESTADDRREQ /* override definition in errno.h */
+# define EDESTADDRREQ WSAEDESTADDRREQ
+# undef EMSGSIZE /* override definition in errno.h */
+# define EMSGSIZE WSAEMSGSIZE
+# undef EPROTOTYPE /* override definition in errno.h */
+# define EPROTOTYPE WSAEPROTOTYPE
+# undef ENOPROTOOPT /* override definition in errno.h */
+# define ENOPROTOOPT WSAENOPROTOOPT
+# undef EPROTONOSUPPORT /* override definition in errno.h */
+# define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+# define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+# undef EOPNOTSUPP /* override definition in errno.h */
+# define EOPNOTSUPP WSAEOPNOTSUPP
+# define EPFNOSUPPORT WSAEPFNOSUPPORT
+# undef EAFNOSUPPORT /* override definition in errno.h */
+# define EAFNOSUPPORT WSAEAFNOSUPPORT
+# undef EADDRINUSE /* override definition in errno.h */
+# define EADDRINUSE WSAEADDRINUSE
+# undef EADDRNOTAVAIL /* override definition in errno.h */
+# define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+# undef ENETDOWN /* override definition in errno.h */
+# define ENETDOWN WSAENETDOWN
+# undef ENETUNREACH /* override definition in errno.h */
+# define ENETUNREACH WSAENETUNREACH
+# undef ENETRESET /* override definition in errno.h */
+# define ENETRESET WSAENETRESET
+# undef ECONNABORTED /* override definition in errno.h */
+# define ECONNABORTED WSAECONNABORTED
+# undef ECONNRESET /* override definition in errno.h */
+# define ECONNRESET WSAECONNRESET
+# undef ENOBUFS /* override definition in errno.h */
+# define ENOBUFS WSAENOBUFS
+# undef EISCONN /* override definition in errno.h */
+# define EISCONN WSAEISCONN
+# undef ENOTCONN /* override definition in errno.h */
+# define ENOTCONN WSAENOTCONN
+# define ESHUTDOWN WSAESHUTDOWN
+# define ETOOMANYREFS WSAETOOMANYREFS
+# undef ETIMEDOUT /* override definition in errno.h */
+# define ETIMEDOUT WSAETIMEDOUT
+# undef ECONNREFUSED /* override definition in errno.h */
+# define ECONNREFUSED WSAECONNREFUSED
+# undef ELOOP /* override definition in errno.h */
+# define ELOOP WSAELOOP
+# ifndef ENAMETOOLONG /* possible previous definition in errno.h */
+# define ENAMETOOLONG WSAENAMETOOLONG
+# endif
+# define EHOSTDOWN WSAEHOSTDOWN
+# undef EHOSTUNREACH /* override definition in errno.h */
+# define EHOSTUNREACH WSAEHOSTUNREACH
+# ifndef ENOTEMPTY /* possible previous definition in errno.h */
+# define ENOTEMPTY WSAENOTEMPTY
+# endif
+# define EPROCLIM WSAEPROCLIM
+# define EUSERS WSAEUSERS
+# define EDQUOT WSAEDQUOT
+# define ESTALE WSAESTALE
+# define EREMOTE WSAEREMOTE
#endif
-#endif /* HEADER_CARES_SETUP_H */
+#endif /* __ARES_SETUP_H */
diff --git a/contrib/libs/c-ares/src/lib/ares_strerror.c b/contrib/libs/c-ares/src/lib/ares_strerror.c
index ae94f9619e..d9f6411620 100644
--- a/contrib/libs/c-ares/src/lib/ares_strerror.c
+++ b/contrib/libs/c-ares/src/lib/ares_strerror.c
@@ -25,9 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include <assert.h>
-#include "ares.h"
+#include "ares_private.h"
const char *ares_strerror(int code)
{
diff --git a/contrib/libs/c-ares/src/lib/ares_sysconfig.c b/contrib/libs/c-ares/src/lib/ares_sysconfig.c
index d56ee22e08..2cd3df2823 100644
--- a/contrib/libs/c-ares/src/lib/ares_sysconfig.c
+++ b/contrib/libs/c-ares/src/lib/ares_sysconfig.c
@@ -25,7 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
@@ -43,8 +43,6 @@
# include <arpa/inet.h>
#endif
-#include "ares_nameser.h"
-
#if defined(ANDROID) || defined(__ANDROID__)
# include <sys/system_properties.h>
# include "ares_android.h"
@@ -57,586 +55,9 @@
# include <resolv.h>
#endif
-#if defined(USE_WINSOCK)
-# if defined(HAVE_IPHLPAPI_H)
-# include <iphlpapi.h>
-# endif
-# if defined(HAVE_NETIOAPI_H)
-# include <netioapi.h>
-# endif
-#endif
-
-#include "ares.h"
#include "ares_inet_net_pton.h"
#include "ares_platform.h"
-#include "ares_private.h"
-
-#ifdef WATT32
-# undef WIN32 /* Redefined in MingW/MSVC headers */
-#endif
-
-
-#ifdef WIN32
-/*
- * get_REG_SZ()
- *
- * Given a 'hKey' handle to an open registry key and a 'leafKeyName' pointer
- * to the name of the registry leaf key to be queried, fetch it's string
- * value and return a pointer in *outptr to a newly allocated memory area
- * holding it as a null-terminated string.
- *
- * Returns 0 and nullifies *outptr upon inability to return a string value.
- *
- * Returns 1 and sets *outptr when returning a dynamically allocated string.
- *
- * Supported on Windows NT 3.5 and newer.
- */
-static ares_bool_t get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr)
-{
- DWORD size = 0;
- int res;
-
- *outptr = NULL;
-
- /* Find out size of string stored in registry */
- res = RegQueryValueExA(hKey, leafKeyName, 0, NULL, NULL, &size);
- if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size) {
- return ARES_FALSE;
- }
-
- /* Allocate buffer of indicated size plus one given that string
- might have been stored without null termination */
- *outptr = ares_malloc(size + 1);
- if (!*outptr) {
- return ARES_FALSE;
- }
-
- /* Get the value for real */
- res = RegQueryValueExA(hKey, leafKeyName, 0, NULL, (unsigned char *)*outptr,
- &size);
- if ((res != ERROR_SUCCESS) || (size == 1)) {
- ares_free(*outptr);
- *outptr = NULL;
- return ARES_FALSE;
- }
-
- /* Null terminate buffer always */
- *(*outptr + size) = '\0';
-
- return ARES_TRUE;
-}
-
-static void commanjoin(char **dst, const char * const src, const size_t len)
-{
- char *newbuf;
- size_t newsize;
-
- /* 1 for terminating 0 and 2 for , and terminating 0 */
- newsize = len + (*dst ? (ares_strlen(*dst) + 2) : 1);
- newbuf = ares_realloc(*dst, newsize);
- if (!newbuf) {
- return;
- }
- if (*dst == NULL) {
- *newbuf = '\0';
- }
- *dst = newbuf;
- if (ares_strlen(*dst) != 0) {
- strcat(*dst, ",");
- }
- strncat(*dst, src, len);
-}
-
-/*
- * commajoin()
- *
- * RTF code.
- */
-static void commajoin(char **dst, const char *src)
-{
- commanjoin(dst, src, ares_strlen(src));
-}
-/* A structure to hold the string form of IPv4 and IPv6 addresses so we can
- * sort them by a metric.
- */
-typedef struct {
- /* The metric we sort them by. */
- ULONG metric;
-
- /* Original index of the item, used as a secondary sort parameter to make
- * qsort() stable if the metrics are equal */
- size_t orig_idx;
-
- /* Room enough for the string form of any IPv4 or IPv6 address that
- * ares_inet_ntop() will create. Based on the existing c-ares practice.
- */
- char text[INET6_ADDRSTRLEN + 8 + 64]; /* [%s]:NNNNN%iface */
-} Address;
-
-/* Sort Address values \a left and \a right by metric, returning the usual
- * indicators for qsort().
- */
-static int compareAddresses(const void *arg1, const void *arg2)
-{
- const Address * const left = arg1;
- const Address * const right = arg2;
- /* Lower metric the more preferred */
- if (left->metric < right->metric) {
- return -1;
- }
- if (left->metric > right->metric) {
- return 1;
- }
- /* If metrics are equal, lower original index more preferred */
- if (left->orig_idx < right->orig_idx) {
- return -1;
- }
- if (left->orig_idx > right->orig_idx) {
- return 1;
- }
- return 0;
-}
-
-/* There can be multiple routes to "the Internet". And there can be different
- * DNS servers associated with each of the interfaces that offer those routes.
- * We have to assume that any DNS server can serve any request. But, some DNS
- * servers may only respond if requested over their associated interface. But
- * we also want to use "the preferred route to the Internet" whenever possible
- * (and not use DNS servers on a non-preferred route even by forcing request
- * to go out on the associated non-preferred interface). i.e. We want to use
- * the DNS servers associated with the same interface that we would use to
- * make a general request to anything else.
- *
- * But, Windows won't sort the DNS servers by the metrics associated with the
- * routes and interfaces _even_ though it obviously sends IP packets based on
- * those same routes and metrics. So, we must do it ourselves.
- *
- * So, we sort the DNS servers by the same metric values used to determine how
- * an outgoing IP packet will go, thus effectively using the DNS servers
- * associated with the interface that the DNS requests themselves will
- * travel. This gives us optimal routing and avoids issues where DNS servers
- * won't respond to requests that don't arrive via some specific subnetwork
- * (and thus some specific interface).
- *
- * This function computes the metric we use to sort. On the interface
- * identified by \a luid, it determines the best route to \a dest and combines
- * that route's metric with \a interfaceMetric to compute a metric for the
- * destination address on that interface. This metric can be used as a weight
- * to sort the DNS server addresses associated with each interface (lower is
- * better).
- *
- * Note that by restricting the route search to the specific interface with
- * which the DNS servers are associated, this function asks the question "What
- * is the metric for sending IP packets to this DNS server?" which allows us
- * to sort the DNS servers correctly.
- */
-static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */
- const SOCKADDR_INET * const dest,
- const ULONG interfaceMetric)
-{
- /* On this interface, get the best route to that destination. */
-# if defined(__WATCOMC__)
- /* OpenWatcom's builtin Windows SDK does not have a definition for
- * MIB_IPFORWARD_ROW2, and also does not allow the usage of SOCKADDR_INET
- * as a variable. Let's work around this by returning the worst possible
- * metric, but only when using the OpenWatcom compiler.
- * It may be worth investigating using a different version of the Windows
- * SDK with OpenWatcom in the future, though this may be fixed in OpenWatcom
- * 2.0.
- */
- return (ULONG)-1;
-# else
- MIB_IPFORWARD_ROW2 row;
- SOCKADDR_INET ignored;
- if (GetBestRoute2(/* The interface to use. The index is ignored since we are
- * passing a LUID.
- */
- luid, 0,
- /* No specific source address. */
- NULL,
- /* Our destination address. */
- dest,
- /* No options. */
- 0,
- /* The route row. */
- &row,
- /* The best source address, which we don't need. */
- &ignored) != NO_ERROR
- /* If the metric is "unused" (-1) or too large for us to add the two
- * metrics, use the worst possible, thus sorting this last.
- */
- || row.Metric == (ULONG)-1 ||
- row.Metric > ((ULONG)-1) - interfaceMetric) {
- /* Return the worst possible metric. */
- return (ULONG)-1;
- }
-
- /* Return the metric value from that row, plus the interface metric.
- *
- * See
- * http://msdn.microsoft.com/en-us/library/windows/desktop/aa814494(v=vs.85).aspx
- * which describes the combination as a "sum".
- */
- return row.Metric + interfaceMetric;
-# endif /* __WATCOMC__ */
-}
-
-/*
- * get_DNS_Windows()
- *
- * Locates DNS info using GetAdaptersAddresses() function from the Internet
- * Protocol Helper (IP Helper) API. When located, this returns a pointer
- * in *outptr to a newly allocated memory area holding a null-terminated
- * string with a space or comma separated list of DNS IP addresses.
- *
- * Returns 0 and nullifies *outptr upon inability to return DNSes string.
- *
- * Returns 1 and sets *outptr when returning a dynamically allocated string.
- *
- * Implementation supports Windows XP and newer.
- */
-# define IPAA_INITIAL_BUF_SZ 15 * 1024
-# define IPAA_MAX_TRIES 3
-
-static ares_bool_t get_DNS_Windows(char **outptr)
-{
- IP_ADAPTER_DNS_SERVER_ADDRESS *ipaDNSAddr;
- IP_ADAPTER_ADDRESSES *ipaa;
- IP_ADAPTER_ADDRESSES *newipaa;
- IP_ADAPTER_ADDRESSES *ipaaEntry;
- ULONG ReqBufsz = IPAA_INITIAL_BUF_SZ;
- ULONG Bufsz = IPAA_INITIAL_BUF_SZ;
- ULONG AddrFlags = 0;
- int trying = IPAA_MAX_TRIES;
- ULONG res;
-
- /* The capacity of addresses, in elements. */
- size_t addressesSize;
- /* The number of elements in addresses. */
- size_t addressesIndex = 0;
- /* The addresses we will sort. */
- Address *addresses;
-
- union {
- struct sockaddr *sa;
- struct sockaddr_in *sa4;
- struct sockaddr_in6 *sa6;
- } namesrvr;
-
- *outptr = NULL;
-
- ipaa = ares_malloc(Bufsz);
- if (!ipaa) {
- return ARES_FALSE;
- }
-
- /* Start with enough room for a few DNS server addresses and we'll grow it
- * as we encounter more.
- */
- addressesSize = 4;
- addresses = (Address *)ares_malloc(sizeof(Address) * addressesSize);
- if (addresses == NULL) {
- /* We need room for at least some addresses to function. */
- ares_free(ipaa);
- return ARES_FALSE;
- }
-
- /* Usually this call succeeds with initial buffer size */
- res = GetAdaptersAddresses(AF_UNSPEC, AddrFlags, NULL, ipaa, &ReqBufsz);
- if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS)) {
- goto done;
- }
-
- while ((res == ERROR_BUFFER_OVERFLOW) && (--trying)) {
- if (Bufsz < ReqBufsz) {
- newipaa = ares_realloc(ipaa, ReqBufsz);
- if (!newipaa) {
- goto done;
- }
- Bufsz = ReqBufsz;
- ipaa = newipaa;
- }
- res = GetAdaptersAddresses(AF_UNSPEC, AddrFlags, NULL, ipaa, &ReqBufsz);
- if (res == ERROR_SUCCESS) {
- break;
- }
- }
- if (res != ERROR_SUCCESS) {
- goto done;
- }
-
- for (ipaaEntry = ipaa; ipaaEntry; ipaaEntry = ipaaEntry->Next) {
- if (ipaaEntry->OperStatus != IfOperStatusUp) {
- continue;
- }
-
- /* For each interface, find any associated DNS servers as IPv4 or IPv6
- * addresses. For each found address, find the best route to that DNS
- * server address _on_ _that_ _interface_ (at this moment in time) and
- * compute the resulting total metric, just as Windows routing will do.
- * Then, sort all the addresses found by the metric.
- */
- for (ipaDNSAddr = ipaaEntry->FirstDnsServerAddress; ipaDNSAddr;
- ipaDNSAddr = ipaDNSAddr->Next) {
- char ipaddr[INET6_ADDRSTRLEN] = "";
- namesrvr.sa = ipaDNSAddr->Address.lpSockaddr;
-
- if (namesrvr.sa->sa_family == AF_INET) {
- if ((namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_ANY) ||
- (namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_NONE)) {
- continue;
- }
-
- /* Allocate room for another address, if necessary, else skip. */
- if (addressesIndex == addressesSize) {
- const size_t newSize = addressesSize + 4;
- Address * const newMem =
- (Address *)ares_realloc(addresses, sizeof(Address) * newSize);
- if (newMem == NULL) {
- continue;
- }
- addresses = newMem;
- addressesSize = newSize;
- }
-
- addresses[addressesIndex].metric = getBestRouteMetric(
- &ipaaEntry->Luid, (SOCKADDR_INET *)((void *)(namesrvr.sa)),
- ipaaEntry->Ipv4Metric);
-
- /* Record insertion index to make qsort stable */
- addresses[addressesIndex].orig_idx = addressesIndex;
-
- if (!ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr, ipaddr,
- sizeof(ipaddr))) {
- continue;
- }
- snprintf(addresses[addressesIndex].text,
- sizeof(addresses[addressesIndex].text), "[%s]:%u", ipaddr,
- ntohs(namesrvr.sa4->sin_port));
- ++addressesIndex;
- } else if (namesrvr.sa->sa_family == AF_INET6) {
- unsigned int ll_scope = 0;
- struct ares_addr addr;
-
- if (memcmp(&namesrvr.sa6->sin6_addr, &ares_in6addr_any,
- sizeof(namesrvr.sa6->sin6_addr)) == 0) {
- continue;
- }
-
- /* Allocate room for another address, if necessary, else skip. */
- if (addressesIndex == addressesSize) {
- const size_t newSize = addressesSize + 4;
- Address * const newMem =
- (Address *)ares_realloc(addresses, sizeof(Address) * newSize);
- if (newMem == NULL) {
- continue;
- }
- addresses = newMem;
- addressesSize = newSize;
- }
-
- /* See if its link-local */
- memset(&addr, 0, sizeof(addr));
- addr.family = AF_INET6;
- memcpy(&addr.addr.addr6, &namesrvr.sa6->sin6_addr, 16);
- if (ares__addr_is_linklocal(&addr)) {
- ll_scope = ipaaEntry->Ipv6IfIndex;
- }
-
- addresses[addressesIndex].metric = getBestRouteMetric(
- &ipaaEntry->Luid, (SOCKADDR_INET *)((void *)(namesrvr.sa)),
- ipaaEntry->Ipv6Metric);
-
- /* Record insertion index to make qsort stable */
- addresses[addressesIndex].orig_idx = addressesIndex;
-
- if (!ares_inet_ntop(AF_INET6, &namesrvr.sa6->sin6_addr, ipaddr,
- sizeof(ipaddr))) {
- continue;
- }
-
- if (ll_scope) {
- snprintf(addresses[addressesIndex].text,
- sizeof(addresses[addressesIndex].text), "[%s]:%u%%%u",
- ipaddr, ntohs(namesrvr.sa6->sin6_port), ll_scope);
- } else {
- snprintf(addresses[addressesIndex].text,
- sizeof(addresses[addressesIndex].text), "[%s]:%u", ipaddr,
- ntohs(namesrvr.sa6->sin6_port));
- }
- ++addressesIndex;
- } else {
- /* Skip non-IPv4/IPv6 addresses completely. */
- continue;
- }
- }
- }
-
- /* Sort all of the textual addresses by their metric (and original index if
- * metrics are equal). */
- qsort(addresses, addressesIndex, sizeof(*addresses), compareAddresses);
-
- /* Join them all into a single string, removing duplicates. */
- {
- size_t i;
- for (i = 0; i < addressesIndex; ++i) {
- size_t j;
- /* Look for this address text appearing previously in the results. */
- for (j = 0; j < i; ++j) {
- if (strcmp(addresses[j].text, addresses[i].text) == 0) {
- break;
- }
- }
- /* Iff we didn't emit this address already, emit it now. */
- if (j == i) {
- /* Add that to outptr (if we can). */
- commajoin(outptr, addresses[i].text);
- }
- }
- }
-
-done:
- ares_free(addresses);
-
- if (ipaa) {
- ares_free(ipaa);
- }
-
- if (!*outptr) {
- return ARES_FALSE;
- }
-
- return ARES_TRUE;
-}
-
-/*
- * get_SuffixList_Windows()
- *
- * Reads the "DNS Suffix Search List" from registry and writes the list items
- * whitespace separated to outptr. If the Search List is empty, the
- * "Primary Dns Suffix" is written to outptr.
- *
- * Returns 0 and nullifies *outptr upon inability to return the suffix list.
- *
- * Returns 1 and sets *outptr when returning a dynamically allocated string.
- *
- * Implementation supports Windows Server 2003 and newer
- */
-static ares_bool_t get_SuffixList_Windows(char **outptr)
-{
- HKEY hKey;
- HKEY hKeyEnum;
- char keyName[256];
- DWORD keyNameBuffSize;
- DWORD keyIdx = 0;
- char *p = NULL;
-
- *outptr = NULL;
-
- if (ares__getplatform() != WIN_NT) {
- return ARES_FALSE;
- }
-
- /* 1. Global DNS Suffix Search List */
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ, &hKey) ==
- ERROR_SUCCESS) {
- get_REG_SZ(hKey, SEARCHLIST_KEY, outptr);
- if (get_REG_SZ(hKey, DOMAIN_KEY, &p)) {
- commajoin(outptr, p);
- ares_free(p);
- p = NULL;
- }
- RegCloseKey(hKey);
- }
-
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NT_DNSCLIENT, 0, KEY_READ, &hKey) ==
- ERROR_SUCCESS) {
- if (get_REG_SZ(hKey, SEARCHLIST_KEY, &p)) {
- commajoin(outptr, p);
- ares_free(p);
- p = NULL;
- }
- RegCloseKey(hKey);
- }
-
- /* 2. Connection Specific Search List composed of:
- * a. Primary DNS Suffix */
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_DNSCLIENT, 0, KEY_READ, &hKey) ==
- ERROR_SUCCESS) {
- if (get_REG_SZ(hKey, PRIMARYDNSSUFFIX_KEY, &p)) {
- commajoin(outptr, p);
- ares_free(p);
- p = NULL;
- }
- RegCloseKey(hKey);
- }
-
- /* b. Interface SearchList, Domain, DhcpDomain */
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY "\\" INTERFACES_KEY, 0,
- KEY_READ, &hKey) == ERROR_SUCCESS) {
- for (;;) {
- keyNameBuffSize = sizeof(keyName);
- if (RegEnumKeyExA(hKey, keyIdx++, keyName, &keyNameBuffSize, 0, NULL,
- NULL, NULL) != ERROR_SUCCESS) {
- break;
- }
- if (RegOpenKeyExA(hKey, keyName, 0, KEY_QUERY_VALUE, &hKeyEnum) !=
- ERROR_SUCCESS) {
- continue;
- }
- /* p can be comma separated (SearchList) */
- if (get_REG_SZ(hKeyEnum, SEARCHLIST_KEY, &p)) {
- commajoin(outptr, p);
- ares_free(p);
- p = NULL;
- }
- if (get_REG_SZ(hKeyEnum, DOMAIN_KEY, &p)) {
- commajoin(outptr, p);
- ares_free(p);
- p = NULL;
- }
- if (get_REG_SZ(hKeyEnum, DHCPDOMAIN_KEY, &p)) {
- commajoin(outptr, p);
- ares_free(p);
- p = NULL;
- }
- RegCloseKey(hKeyEnum);
- }
- RegCloseKey(hKey);
- }
-
- return *outptr != NULL ? ARES_TRUE : ARES_FALSE;
-}
-
-static ares_status_t ares__init_sysconfig_windows(ares_sysconfig_t *sysconfig)
-{
- char *line = NULL;
- ares_status_t status = ARES_SUCCESS;
-
- if (get_DNS_Windows(&line)) {
- status = ares__sconfig_append_fromstr(&sysconfig->sconfig, line, ARES_TRUE);
- ares_free(line);
- if (status != ARES_SUCCESS) {
- goto done;
- }
- }
-
- if (get_SuffixList_Windows(&line)) {
- sysconfig->domains = ares__strsplit(line, ", ", &sysconfig->ndomains);
- ares_free(line);
- if (sysconfig->domains == NULL) {
- status = ARES_EFILE;
- }
- if (status != ARES_SUCCESS) {
- goto done;
- }
- }
-
-done:
- return status;
-}
-#endif
#if defined(__MVS__)
static ares_status_t ares__init_sysconfig_mvs(ares_sysconfig_t *sysconfig)
@@ -1012,7 +433,7 @@ static ares_status_t ares_sysconfig_apply(ares_channel_t *channel,
char **temp =
ares__strsplit_duplicate(sysconfig->domains, sysconfig->ndomains);
if (temp == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
ares__strsplit_free(channel->domains, channel->ndomains);
@@ -1023,7 +444,7 @@ static ares_status_t ares_sysconfig_apply(ares_channel_t *channel,
if (sysconfig->lookups && !(channel->optmask & ARES_OPT_LOOKUPS)) {
char *temp = ares_strdup(sysconfig->lookups);
if (temp == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
ares_free(channel->lookups);
@@ -1034,7 +455,7 @@ static ares_status_t ares_sysconfig_apply(ares_channel_t *channel,
struct apattern *temp =
ares_malloc(sizeof(*channel->sortlist) * sysconfig->nsortlist);
if (temp == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
memcpy(temp, sysconfig->sortlist,
sizeof(*channel->sortlist) * sysconfig->nsortlist);
@@ -1044,7 +465,7 @@ static ares_status_t ares_sysconfig_apply(ares_channel_t *channel,
channel->nsort = sysconfig->nsortlist;
}
- if (sysconfig->ndots && !(channel->optmask & ARES_OPT_NDOTS)) {
+ if (!(channel->optmask & ARES_OPT_NDOTS)) {
channel->ndots = sysconfig->ndots;
}
@@ -1074,7 +495,7 @@ ares_status_t ares__init_by_sysconfig(ares_channel_t *channel)
memset(&sysconfig, 0, sizeof(sysconfig));
-#ifdef _WIN32
+#if defined(USE_WINSOCK)
status = ares__init_sysconfig_windows(&sysconfig);
#elif defined(__MVS__)
status = ares__init_sysconfig_mvs(&sysconfig);
diff --git a/contrib/libs/c-ares/src/lib/ares_sysconfig_files.c b/contrib/libs/c-ares/src/lib/ares_sysconfig_files.c
index 5771a581db..7b8bdbe418 100644
--- a/contrib/libs/c-ares/src/lib/ares_sysconfig_files.c
+++ b/contrib/libs/c-ares/src/lib/ares_sysconfig_files.c
@@ -25,7 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
@@ -43,8 +43,6 @@
# include <arpa/inet.h>
#endif
-#include "ares_nameser.h"
-
#if defined(ANDROID) || defined(__ANDROID__)
# include <sys/system_properties.h>
# include "ares_android.h"
@@ -61,10 +59,8 @@
# include <iphlpapi.h>
#endif
-#include "ares.h"
#include "ares_inet_net_pton.h"
#include "ares_platform.h"
-#include "ares_private.h"
static unsigned char ip_natural_mask(const struct ares_addr *addr)
{
@@ -103,7 +99,7 @@ static ares_bool_t sortlist_append(struct apattern **sortlist, size_t *nsort,
newsort = ares_realloc(*sortlist, (*nsort + 1) * sizeof(*newsort));
if (newsort == NULL) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: OutOfMemory */
}
*sortlist = newsort;
@@ -223,7 +219,7 @@ ares_status_t ares__parse_sortlist(struct apattern **sortlist, size_t *nsort,
ares__llist_node_t *node = NULL;
if (sortlist == NULL || nsort == NULL || str == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (*sortlist != NULL) {
@@ -262,8 +258,8 @@ ares_status_t ares__parse_sortlist(struct apattern **sortlist, size_t *nsort,
}
if (!sortlist_append(sortlist, nsort, &pat)) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -371,7 +367,7 @@ static ares_status_t config_lookup(ares_sysconfig_t *sysconfig,
ares_free(sysconfig->lookups);
sysconfig->lookups = ares_strdup(lookupstr);
if (sysconfig->lookups == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -462,7 +458,7 @@ ares_status_t ares__sysconfig_set_options(ares_sysconfig_t *sysconfig,
status = process_option(sysconfig, valbuf);
/* Out of memory is the only fatal condition */
if (status == ARES_ENOMEM) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -484,7 +480,7 @@ ares_status_t ares__init_by_environment(ares_sysconfig_t *sysconfig)
if (localdomain) {
char *temp = ares_strdup(localdomain);
if (temp == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = config_search(sysconfig, temp, 1);
ares_free(temp);
diff --git a/contrib/libs/c-ares/src/lib/ares_sysconfig_mac.c b/contrib/libs/c-ares/src/lib/ares_sysconfig_mac.c
index 302bd0d344..38ac451ca5 100644
--- a/contrib/libs/c-ares/src/lib/ares_sysconfig_mac.c
+++ b/contrib/libs/c-ares/src/lib/ares_sysconfig_mac.c
@@ -45,16 +45,24 @@
* private header extracted from:
* https://opensource.apple.com/source/configd/configd-1109.140.1/dnsinfo/dnsinfo.h
*/
-# include "ares_setup.h"
+
+/* The apple header uses anonymous unions which came with C11 */
+# if defined(__clang__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wc11-extensions"
+# endif
+
+# include "ares_private.h"
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <dlfcn.h>
# include <arpa/inet.h>
# include "thirdparty/apple/dnsinfo.h"
-# include <SystemConfiguration/SCNetworkConfiguration.h>
-# include "ares.h"
-# include "ares_private.h"
+# include <AvailabilityMacros.h>
+# if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 /* MacOS 10.8 */
+# include <SystemConfiguration/SCNetworkConfiguration.h>
+# endif
typedef struct {
void *handle;
@@ -79,6 +87,13 @@ static ares_status_t dnsinfo_init(dnsinfo_t **dnsinfo_out)
{
dnsinfo_t *dnsinfo = NULL;
ares_status_t status = ARES_SUCCESS;
+ size_t i;
+ const char *searchlibs[] = {
+ "/usr/lib/libSystem.dylib",
+ "/System/Library/Frameworks/SystemConfiguration.framework/"
+ "SystemConfiguration",
+ NULL
+ };
if (dnsinfo_out == NULL) {
status = ARES_EFORMERR;
@@ -88,22 +103,34 @@ static ares_status_t dnsinfo_init(dnsinfo_t **dnsinfo_out)
*dnsinfo_out = NULL;
dnsinfo = ares_malloc_zero(sizeof(*dnsinfo));
-
if (dnsinfo == NULL) {
status = ARES_ENOMEM;
goto done;
}
- dnsinfo->handle = dlopen("/usr/lib/libSystem.dylib", RTLD_LAZY | RTLD_NOLOAD);
- if (dnsinfo->handle == NULL) {
- status = ARES_ESERVFAIL;
- goto done;
+ for (i = 0; searchlibs[i] != NULL; i++) {
+ dnsinfo->handle = dlopen(searchlibs[i], RTLD_LAZY /* | RTLD_NOLOAD */);
+ if (dnsinfo->handle == NULL) {
+ /* Fail, loop */
+ continue;
+ }
+
+ dnsinfo->dns_configuration_copy = (dns_config_t * (*)(void))
+ dlsym(dnsinfo->handle, "dns_configuration_copy");
+
+ dnsinfo->dns_configuration_free = (void (*)(dns_config_t *))dlsym(
+ dnsinfo->handle, "dns_configuration_free");
+
+ if (dnsinfo->dns_configuration_copy != NULL &&
+ dnsinfo->dns_configuration_free != NULL) {
+ break;
+ }
+
+ /* Fail, loop */
+ dlclose(dnsinfo->handle);
+ dnsinfo->handle = NULL;
}
- dnsinfo->dns_configuration_copy =
- dlsym(dnsinfo->handle, "dns_configuration_copy");
- dnsinfo->dns_configuration_free =
- dlsym(dnsinfo->handle, "dns_configuration_free");
if (dnsinfo->dns_configuration_copy == NULL ||
dnsinfo->dns_configuration_free == NULL) {
@@ -141,13 +168,19 @@ static ares_status_t read_resolver(const dns_resolver_t *resolver,
unsigned short port = 0;
ares_status_t status = ARES_SUCCESS;
+# if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 /* MacOS 10.8 */
/* XXX: resolver->domain is for domain-specific servers. When we implement
* this support, we'll want to use this. But for now, we're going to
- * skip any servers which set this since we can't properly route. */
+ * skip any servers which set this since we can't properly route.
+ * MacOS used to use this setting for a different purpose in the
+ * past however, so on versions of MacOS < 10.8 just ignore this
+ * completely. */
if (resolver->domain != NULL) {
return ARES_SUCCESS;
}
+# endif
+# if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 /* MacOS 10.8 */
/* Check to see if DNS server should be used, base this on if the server is
* reachable or can be reachable automatically if we send traffic that
* direction. */
@@ -156,6 +189,7 @@ static ares_status_t read_resolver(const dns_resolver_t *resolver,
kSCNetworkReachabilityFlagsConnectionOnTraffic))) {
return ARES_SUCCESS;
}
+# endif
/* NOTE: it doesn't look like resolver->flags is relevant */
@@ -219,7 +253,8 @@ static ares_status_t read_resolver(const dns_resolver_t *resolver,
* - resolver->timeout appears unused, always 0, so we ignore this
* - resolver->service_identifier doesn't appear relevant to us
* - resolver->cid also isn't relevant
- * - resolver->if_index we don't need, if_name is used instead.
+ * - resolver->if_name we won't use since it isn't available in MacOS 10.8
+ * or earlier, use resolver->if_index instead to then lookup the name.
*/
/* XXX: resolver->search_order appears like it might be relevant, we might
@@ -233,37 +268,24 @@ static ares_status_t read_resolver(const dns_resolver_t *resolver,
struct ares_addr addr;
unsigned short addrport;
const struct sockaddr *sockaddr;
+ char if_name_str[256] = "";
+ const char *if_name;
/* UBSAN alignment workaround to fetch memory address */
memcpy(&sockaddr, resolver->nameserver + i, sizeof(sockaddr));
- if (sockaddr->sa_family == AF_INET) {
- /* NOTE: memcpy sockaddr_in due to alignment issues found by UBSAN due to
- * dnsinfo packing */
- struct sockaddr_in addr_in;
- memcpy(&addr_in, sockaddr, sizeof(addr_in));
-
- addr.family = AF_INET;
- memcpy(&addr.addr.addr4, &(addr_in.sin_addr), sizeof(addr.addr.addr4));
- addrport = ntohs(addr_in.sin_port);
- } else if (sockaddr->sa_family == AF_INET6) {
- /* NOTE: memcpy sockaddr_in6 due to alignment issues found by UBSAN due to
- * dnsinfo packing */
- struct sockaddr_in6 addr_in6;
- memcpy(&addr_in6, sockaddr, sizeof(addr_in6));
-
- addr.family = AF_INET6;
- memcpy(&addr.addr.addr6, &(addr_in6.sin6_addr), sizeof(addr.addr.addr6));
- addrport = ntohs(addr_in6.sin6_port);
- } else {
+ if (!ares_sockaddr_to_ares_addr(&addr, &addrport, sockaddr)) {
continue;
}
if (addrport == 0) {
addrport = port;
}
- status = ares__sconfig_append(&sysconfig->sconfig, &addr, addrport,
- addrport, resolver->if_name);
+
+ if_name = ares__if_indextoname(resolver->if_index, if_name_str,
+ sizeof(if_name_str));
+ status = ares__sconfig_append(&sysconfig->sconfig, &addr, addrport,
+ addrport, if_name);
if (status != ARES_SUCCESS) {
return status;
}
@@ -280,7 +302,6 @@ static ares_status_t read_resolvers(dns_resolver_t **resolvers, int nresolvers,
for (i = 0; status == ARES_SUCCESS && i < nresolvers; i++) {
const dns_resolver_t *resolver_ptr;
- dns_resolver_t resolver;
/* UBSAN doesn't like that this is unaligned, lets use memcpy to get the
* address. Equivalent to:
@@ -288,10 +309,7 @@ static ares_status_t read_resolvers(dns_resolver_t **resolvers, int nresolvers,
*/
memcpy(&resolver_ptr, resolvers + i, sizeof(resolver_ptr));
- /* UBSAN. If the pointer is misaligned, try to use memcpy to get the data
- * into a new structure that is hopefully aligned properly */
- memcpy(&resolver, resolver_ptr, sizeof(resolver));
- status = read_resolver(&resolver, sysconfig);
+ status = read_resolver(resolver_ptr, sysconfig);
}
return status;
@@ -335,5 +353,13 @@ done:
return status;
}
+# if defined(__clang__)
+# pragma GCC diagnostic pop
+# endif
+
+#else
+
+/* Prevent compiler warnings due to empty translation unit */
+typedef int make_iso_compilers_happy;
#endif
diff --git a/contrib/libs/c-ares/src/lib/ares_sysconfig_win.c b/contrib/libs/c-ares/src/lib/ares_sysconfig_win.c
new file mode 100644
index 0000000000..ce2a261cec
--- /dev/null
+++ b/contrib/libs/c-ares/src/lib/ares_sysconfig_win.c
@@ -0,0 +1,619 @@
+/* MIT License
+ *
+ * Copyright (c) 1998 Massachusetts Institute of Technology
+ * Copyright (c) 2007 Daniel Stenberg
+ *
+ * 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_private.h"
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+#if defined(USE_WINSOCK)
+# if defined(HAVE_IPHLPAPI_H)
+# include <iphlpapi.h>
+# endif
+# if defined(HAVE_NETIOAPI_H)
+# include <netioapi.h>
+# endif
+#endif
+
+#include "ares_inet_net_pton.h"
+#include "ares_platform.h"
+
+#if defined(USE_WINSOCK)
+/*
+ * get_REG_SZ()
+ *
+ * Given a 'hKey' handle to an open registry key and a 'leafKeyName' pointer
+ * to the name of the registry leaf key to be queried, fetch it's string
+ * value and return a pointer in *outptr to a newly allocated memory area
+ * holding it as a null-terminated string.
+ *
+ * Returns 0 and nullifies *outptr upon inability to return a string value.
+ *
+ * Returns 1 and sets *outptr when returning a dynamically allocated string.
+ *
+ * Supported on Windows NT 3.5 and newer.
+ */
+static ares_bool_t get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr)
+{
+ DWORD size = 0;
+ int res;
+
+ *outptr = NULL;
+
+ /* Find out size of string stored in registry */
+ res = RegQueryValueExA(hKey, leafKeyName, 0, NULL, NULL, &size);
+ if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size) {
+ return ARES_FALSE;
+ }
+
+ /* Allocate buffer of indicated size plus one given that string
+ might have been stored without null termination */
+ *outptr = ares_malloc(size + 1);
+ if (!*outptr) {
+ return ARES_FALSE;
+ }
+
+ /* Get the value for real */
+ res = RegQueryValueExA(hKey, leafKeyName, 0, NULL, (unsigned char *)*outptr,
+ &size);
+ if ((res != ERROR_SUCCESS) || (size == 1)) {
+ ares_free(*outptr);
+ *outptr = NULL;
+ return ARES_FALSE;
+ }
+
+ /* Null terminate buffer always */
+ *(*outptr + size) = '\0';
+
+ return ARES_TRUE;
+}
+
+static void commanjoin(char **dst, const char * const src, const size_t len)
+{
+ char *newbuf;
+ size_t newsize;
+
+ /* 1 for terminating 0 and 2 for , and terminating 0 */
+ newsize = len + (*dst ? (ares_strlen(*dst) + 2) : 1);
+ newbuf = ares_realloc(*dst, newsize);
+ if (!newbuf) {
+ return;
+ }
+ if (*dst == NULL) {
+ *newbuf = '\0';
+ }
+ *dst = newbuf;
+ if (ares_strlen(*dst) != 0) {
+ strcat(*dst, ",");
+ }
+ strncat(*dst, src, len);
+}
+
+/*
+ * commajoin()
+ *
+ * RTF code.
+ */
+static void commajoin(char **dst, const char *src)
+{
+ commanjoin(dst, src, ares_strlen(src));
+}
+
+/* A structure to hold the string form of IPv4 and IPv6 addresses so we can
+ * sort them by a metric.
+ */
+typedef struct {
+ /* The metric we sort them by. */
+ ULONG metric;
+
+ /* Original index of the item, used as a secondary sort parameter to make
+ * qsort() stable if the metrics are equal */
+ size_t orig_idx;
+
+ /* Room enough for the string form of any IPv4 or IPv6 address that
+ * ares_inet_ntop() will create. Based on the existing c-ares practice.
+ */
+ char text[INET6_ADDRSTRLEN + 8 + 64]; /* [%s]:NNNNN%iface */
+} Address;
+
+/* Sort Address values \a left and \a right by metric, returning the usual
+ * indicators for qsort().
+ */
+static int compareAddresses(const void *arg1, const void *arg2)
+{
+ const Address * const left = arg1;
+ const Address * const right = arg2;
+ /* Lower metric the more preferred */
+ if (left->metric < right->metric) {
+ return -1;
+ }
+ if (left->metric > right->metric) {
+ return 1;
+ }
+ /* If metrics are equal, lower original index more preferred */
+ if (left->orig_idx < right->orig_idx) {
+ return -1;
+ }
+ if (left->orig_idx > right->orig_idx) {
+ return 1;
+ }
+ return 0;
+}
+
+/* There can be multiple routes to "the Internet". And there can be different
+ * DNS servers associated with each of the interfaces that offer those routes.
+ * We have to assume that any DNS server can serve any request. But, some DNS
+ * servers may only respond if requested over their associated interface. But
+ * we also want to use "the preferred route to the Internet" whenever possible
+ * (and not use DNS servers on a non-preferred route even by forcing request
+ * to go out on the associated non-preferred interface). i.e. We want to use
+ * the DNS servers associated with the same interface that we would use to
+ * make a general request to anything else.
+ *
+ * But, Windows won't sort the DNS servers by the metrics associated with the
+ * routes and interfaces _even_ though it obviously sends IP packets based on
+ * those same routes and metrics. So, we must do it ourselves.
+ *
+ * So, we sort the DNS servers by the same metric values used to determine how
+ * an outgoing IP packet will go, thus effectively using the DNS servers
+ * associated with the interface that the DNS requests themselves will
+ * travel. This gives us optimal routing and avoids issues where DNS servers
+ * won't respond to requests that don't arrive via some specific subnetwork
+ * (and thus some specific interface).
+ *
+ * This function computes the metric we use to sort. On the interface
+ * identified by \a luid, it determines the best route to \a dest and combines
+ * that route's metric with \a interfaceMetric to compute a metric for the
+ * destination address on that interface. This metric can be used as a weight
+ * to sort the DNS server addresses associated with each interface (lower is
+ * better).
+ *
+ * Note that by restricting the route search to the specific interface with
+ * which the DNS servers are associated, this function asks the question "What
+ * is the metric for sending IP packets to this DNS server?" which allows us
+ * to sort the DNS servers correctly.
+ */
+static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */
+ const SOCKADDR_INET * const dest,
+ const ULONG interfaceMetric)
+{
+ /* On this interface, get the best route to that destination. */
+# if defined(__WATCOMC__)
+ /* OpenWatcom's builtin Windows SDK does not have a definition for
+ * MIB_IPFORWARD_ROW2, and also does not allow the usage of SOCKADDR_INET
+ * as a variable. Let's work around this by returning the worst possible
+ * metric, but only when using the OpenWatcom compiler.
+ * It may be worth investigating using a different version of the Windows
+ * SDK with OpenWatcom in the future, though this may be fixed in OpenWatcom
+ * 2.0.
+ */
+ return (ULONG)-1;
+# else
+ MIB_IPFORWARD_ROW2 row;
+ SOCKADDR_INET ignored;
+ if (GetBestRoute2(/* The interface to use. The index is ignored since we are
+ * passing a LUID.
+ */
+ luid, 0,
+ /* No specific source address. */
+ NULL,
+ /* Our destination address. */
+ dest,
+ /* No options. */
+ 0,
+ /* The route row. */
+ &row,
+ /* The best source address, which we don't need. */
+ &ignored) != NO_ERROR
+ /* If the metric is "unused" (-1) or too large for us to add the two
+ * metrics, use the worst possible, thus sorting this last.
+ */
+ || row.Metric == (ULONG)-1 ||
+ row.Metric > ((ULONG)-1) - interfaceMetric) {
+ /* Return the worst possible metric. */
+ return (ULONG)-1;
+ }
+
+ /* Return the metric value from that row, plus the interface metric.
+ *
+ * See
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/aa814494(v=vs.85).aspx
+ * which describes the combination as a "sum".
+ */
+ return row.Metric + interfaceMetric;
+# endif /* __WATCOMC__ */
+}
+
+/*
+ * get_DNS_Windows()
+ *
+ * Locates DNS info using GetAdaptersAddresses() function from the Internet
+ * Protocol Helper (IP Helper) API. When located, this returns a pointer
+ * in *outptr to a newly allocated memory area holding a null-terminated
+ * string with a space or comma separated list of DNS IP addresses.
+ *
+ * Returns 0 and nullifies *outptr upon inability to return DNSes string.
+ *
+ * Returns 1 and sets *outptr when returning a dynamically allocated string.
+ *
+ * Implementation supports Windows XP and newer.
+ */
+# define IPAA_INITIAL_BUF_SZ 15 * 1024
+# define IPAA_MAX_TRIES 3
+
+static ares_bool_t get_DNS_Windows(char **outptr)
+{
+ IP_ADAPTER_DNS_SERVER_ADDRESS *ipaDNSAddr;
+ IP_ADAPTER_ADDRESSES *ipaa;
+ IP_ADAPTER_ADDRESSES *newipaa;
+ IP_ADAPTER_ADDRESSES *ipaaEntry;
+ ULONG ReqBufsz = IPAA_INITIAL_BUF_SZ;
+ ULONG Bufsz = IPAA_INITIAL_BUF_SZ;
+ ULONG AddrFlags = 0;
+ int trying = IPAA_MAX_TRIES;
+ ULONG res;
+
+ /* The capacity of addresses, in elements. */
+ size_t addressesSize;
+ /* The number of elements in addresses. */
+ size_t addressesIndex = 0;
+ /* The addresses we will sort. */
+ Address *addresses;
+
+ union {
+ struct sockaddr *sa;
+ struct sockaddr_in *sa4;
+ struct sockaddr_in6 *sa6;
+ } namesrvr;
+
+ *outptr = NULL;
+
+ ipaa = ares_malloc(Bufsz);
+ if (!ipaa) {
+ return ARES_FALSE;
+ }
+
+ /* Start with enough room for a few DNS server addresses and we'll grow it
+ * as we encounter more.
+ */
+ addressesSize = 4;
+ addresses = (Address *)ares_malloc(sizeof(Address) * addressesSize);
+ if (addresses == NULL) {
+ /* We need room for at least some addresses to function. */
+ ares_free(ipaa);
+ return ARES_FALSE;
+ }
+
+ /* Usually this call succeeds with initial buffer size */
+ res = GetAdaptersAddresses(AF_UNSPEC, AddrFlags, NULL, ipaa, &ReqBufsz);
+ if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS)) {
+ goto done;
+ }
+
+ while ((res == ERROR_BUFFER_OVERFLOW) && (--trying)) {
+ if (Bufsz < ReqBufsz) {
+ newipaa = ares_realloc(ipaa, ReqBufsz);
+ if (!newipaa) {
+ goto done;
+ }
+ Bufsz = ReqBufsz;
+ ipaa = newipaa;
+ }
+ res = GetAdaptersAddresses(AF_UNSPEC, AddrFlags, NULL, ipaa, &ReqBufsz);
+ if (res == ERROR_SUCCESS) {
+ break;
+ }
+ }
+ if (res != ERROR_SUCCESS) {
+ goto done;
+ }
+
+ for (ipaaEntry = ipaa; ipaaEntry; ipaaEntry = ipaaEntry->Next) {
+ if (ipaaEntry->OperStatus != IfOperStatusUp) {
+ continue;
+ }
+
+ /* For each interface, find any associated DNS servers as IPv4 or IPv6
+ * addresses. For each found address, find the best route to that DNS
+ * server address _on_ _that_ _interface_ (at this moment in time) and
+ * compute the resulting total metric, just as Windows routing will do.
+ * Then, sort all the addresses found by the metric.
+ */
+ for (ipaDNSAddr = ipaaEntry->FirstDnsServerAddress; ipaDNSAddr != NULL;
+ ipaDNSAddr = ipaDNSAddr->Next) {
+ char ipaddr[INET6_ADDRSTRLEN] = "";
+
+ namesrvr.sa = ipaDNSAddr->Address.lpSockaddr;
+
+ if (namesrvr.sa->sa_family == AF_INET) {
+ if ((namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_ANY) ||
+ (namesrvr.sa4->sin_addr.S_un.S_addr == INADDR_NONE)) {
+ continue;
+ }
+
+ /* Allocate room for another address, if necessary, else skip. */
+ if (addressesIndex == addressesSize) {
+ const size_t newSize = addressesSize + 4;
+ Address * const newMem =
+ (Address *)ares_realloc(addresses, sizeof(Address) * newSize);
+ if (newMem == NULL) {
+ continue;
+ }
+ addresses = newMem;
+ addressesSize = newSize;
+ }
+
+ addresses[addressesIndex].metric = getBestRouteMetric(
+ &ipaaEntry->Luid, (SOCKADDR_INET *)((void *)(namesrvr.sa)),
+ ipaaEntry->Ipv4Metric);
+
+ /* Record insertion index to make qsort stable */
+ addresses[addressesIndex].orig_idx = addressesIndex;
+
+ if (!ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr, ipaddr,
+ sizeof(ipaddr))) {
+ continue;
+ }
+ snprintf(addresses[addressesIndex].text,
+ sizeof(addresses[addressesIndex].text), "[%s]:%u", ipaddr,
+ ntohs(namesrvr.sa4->sin_port));
+ ++addressesIndex;
+ } else if (namesrvr.sa->sa_family == AF_INET6) {
+ unsigned int ll_scope = 0;
+ struct ares_addr addr;
+
+ if (memcmp(&namesrvr.sa6->sin6_addr, &ares_in6addr_any,
+ sizeof(namesrvr.sa6->sin6_addr)) == 0) {
+ continue;
+ }
+
+ /* Allocate room for another address, if necessary, else skip. */
+ if (addressesIndex == addressesSize) {
+ const size_t newSize = addressesSize + 4;
+ Address * const newMem =
+ (Address *)ares_realloc(addresses, sizeof(Address) * newSize);
+ if (newMem == NULL) {
+ continue;
+ }
+ addresses = newMem;
+ addressesSize = newSize;
+ }
+
+ /* See if its link-local */
+ memset(&addr, 0, sizeof(addr));
+ addr.family = AF_INET6;
+ memcpy(&addr.addr.addr6, &namesrvr.sa6->sin6_addr, 16);
+ if (ares__addr_is_linklocal(&addr)) {
+ ll_scope = ipaaEntry->Ipv6IfIndex;
+ }
+
+ addresses[addressesIndex].metric = getBestRouteMetric(
+ &ipaaEntry->Luid, (SOCKADDR_INET *)((void *)(namesrvr.sa)),
+ ipaaEntry->Ipv6Metric);
+
+ /* Record insertion index to make qsort stable */
+ addresses[addressesIndex].orig_idx = addressesIndex;
+
+ if (!ares_inet_ntop(AF_INET6, &namesrvr.sa6->sin6_addr, ipaddr,
+ sizeof(ipaddr))) {
+ continue;
+ }
+
+ if (ll_scope) {
+ snprintf(addresses[addressesIndex].text,
+ sizeof(addresses[addressesIndex].text), "[%s]:%u%%%u",
+ ipaddr, ntohs(namesrvr.sa6->sin6_port), ll_scope);
+ } else {
+ snprintf(addresses[addressesIndex].text,
+ sizeof(addresses[addressesIndex].text), "[%s]:%u", ipaddr,
+ ntohs(namesrvr.sa6->sin6_port));
+ }
+ ++addressesIndex;
+ } else {
+ /* Skip non-IPv4/IPv6 addresses completely. */
+ continue;
+ }
+ }
+ }
+
+ /* Sort all of the textual addresses by their metric (and original index if
+ * metrics are equal). */
+ qsort(addresses, addressesIndex, sizeof(*addresses), compareAddresses);
+
+ /* Join them all into a single string, removing duplicates. */
+ {
+ size_t i;
+ for (i = 0; i < addressesIndex; ++i) {
+ size_t j;
+ /* Look for this address text appearing previously in the results. */
+ for (j = 0; j < i; ++j) {
+ if (strcmp(addresses[j].text, addresses[i].text) == 0) {
+ break;
+ }
+ }
+ /* Iff we didn't emit this address already, emit it now. */
+ if (j == i) {
+ /* Add that to outptr (if we can). */
+ commajoin(outptr, addresses[i].text);
+ }
+ }
+ }
+
+done:
+ ares_free(addresses);
+
+ if (ipaa) {
+ ares_free(ipaa);
+ }
+
+ if (!*outptr) {
+ return ARES_FALSE;
+ }
+
+ return ARES_TRUE;
+}
+
+/*
+ * get_SuffixList_Windows()
+ *
+ * Reads the "DNS Suffix Search List" from registry and writes the list items
+ * whitespace separated to outptr. If the Search List is empty, the
+ * "Primary Dns Suffix" is written to outptr.
+ *
+ * Returns 0 and nullifies *outptr upon inability to return the suffix list.
+ *
+ * Returns 1 and sets *outptr when returning a dynamically allocated string.
+ *
+ * Implementation supports Windows Server 2003 and newer
+ */
+static ares_bool_t get_SuffixList_Windows(char **outptr)
+{
+ HKEY hKey;
+ HKEY hKeyEnum;
+ char keyName[256];
+ DWORD keyNameBuffSize;
+ DWORD keyIdx = 0;
+ char *p = NULL;
+
+ *outptr = NULL;
+
+ if (ares__getplatform() != WIN_NT) {
+ return ARES_FALSE;
+ }
+
+ /* 1. Global DNS Suffix Search List */
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ, &hKey) ==
+ ERROR_SUCCESS) {
+ get_REG_SZ(hKey, SEARCHLIST_KEY, outptr);
+ if (get_REG_SZ(hKey, DOMAIN_KEY, &p)) {
+ commajoin(outptr, p);
+ ares_free(p);
+ p = NULL;
+ }
+ RegCloseKey(hKey);
+ }
+
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NT_DNSCLIENT, 0, KEY_READ, &hKey) ==
+ ERROR_SUCCESS) {
+ if (get_REG_SZ(hKey, SEARCHLIST_KEY, &p)) {
+ commajoin(outptr, p);
+ ares_free(p);
+ p = NULL;
+ }
+ RegCloseKey(hKey);
+ }
+
+ /* 2. Connection Specific Search List composed of:
+ * a. Primary DNS Suffix */
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_DNSCLIENT, 0, KEY_READ, &hKey) ==
+ ERROR_SUCCESS) {
+ if (get_REG_SZ(hKey, PRIMARYDNSSUFFIX_KEY, &p)) {
+ commajoin(outptr, p);
+ ares_free(p);
+ p = NULL;
+ }
+ RegCloseKey(hKey);
+ }
+
+ /* b. Interface SearchList, Domain, DhcpDomain */
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY "\\" INTERFACES_KEY, 0,
+ KEY_READ, &hKey) == ERROR_SUCCESS) {
+ for (;;) {
+ keyNameBuffSize = sizeof(keyName);
+ if (RegEnumKeyExA(hKey, keyIdx++, keyName, &keyNameBuffSize, 0, NULL,
+ NULL, NULL) != ERROR_SUCCESS) {
+ break;
+ }
+ if (RegOpenKeyExA(hKey, keyName, 0, KEY_QUERY_VALUE, &hKeyEnum) !=
+ ERROR_SUCCESS) {
+ continue;
+ }
+ /* p can be comma separated (SearchList) */
+ if (get_REG_SZ(hKeyEnum, SEARCHLIST_KEY, &p)) {
+ commajoin(outptr, p);
+ ares_free(p);
+ p = NULL;
+ }
+ if (get_REG_SZ(hKeyEnum, DOMAIN_KEY, &p)) {
+ commajoin(outptr, p);
+ ares_free(p);
+ p = NULL;
+ }
+ if (get_REG_SZ(hKeyEnum, DHCPDOMAIN_KEY, &p)) {
+ commajoin(outptr, p);
+ ares_free(p);
+ p = NULL;
+ }
+ RegCloseKey(hKeyEnum);
+ }
+ RegCloseKey(hKey);
+ }
+
+ return *outptr != NULL ? ARES_TRUE : ARES_FALSE;
+}
+
+ares_status_t ares__init_sysconfig_windows(ares_sysconfig_t *sysconfig)
+{
+ char *line = NULL;
+ ares_status_t status = ARES_SUCCESS;
+
+ if (get_DNS_Windows(&line)) {
+ status = ares__sconfig_append_fromstr(&sysconfig->sconfig, line, ARES_TRUE);
+ ares_free(line);
+ if (status != ARES_SUCCESS) {
+ goto done;
+ }
+ }
+
+ if (get_SuffixList_Windows(&line)) {
+ sysconfig->domains = ares__strsplit(line, ", ", &sysconfig->ndomains);
+ ares_free(line);
+ if (sysconfig->domains == NULL) {
+ status = ARES_EFILE;
+ }
+ if (status != ARES_SUCCESS) {
+ goto done;
+ }
+ }
+
+done:
+ return status;
+}
+#endif
diff --git a/contrib/libs/c-ares/src/lib/ares_timeout.c b/contrib/libs/c-ares/src/lib/ares_timeout.c
index 3acc66a87f..5ed8b553a3 100644
--- a/contrib/libs/c-ares/src/lib/ares_timeout.c
+++ b/contrib/libs/c-ares/src/lib/ares_timeout.c
@@ -25,14 +25,12 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
-#include "ares.h"
-#include "ares_private.h"
void ares__timeval_remaining(ares_timeval_t *remaining,
const ares_timeval_t *now,
@@ -55,30 +53,42 @@ void ares__timeval_remaining(ares_timeval_t *remaining,
}
}
-static struct timeval ares_timeval_to_struct_timeval(const ares_timeval_t *atv)
+void ares__timeval_diff(ares_timeval_t *tvdiff, const ares_timeval_t *tvstart,
+ const ares_timeval_t *tvstop)
{
- struct timeval tv;
-
- tv.tv_sec = (time_t)atv->sec;
- tv.tv_usec = (int)atv->usec;
-
- return tv;
+ tvdiff->sec = tvstop->sec - tvstart->sec;
+ if (tvstop->usec > tvstart->usec) {
+ tvdiff->usec = tvstop->usec - tvstart->usec;
+ } else {
+ tvdiff->sec -= 1;
+ tvdiff->usec = tvstop->usec + 1000000 - tvstart->usec;
+ }
}
-static ares_timeval_t struct_timeval_to_ares_timeval(const struct timeval *tv)
+static void ares_timeval_to_struct_timeval(struct timeval *tv,
+ const ares_timeval_t *atv)
{
- ares_timeval_t atv;
+#ifdef USE_WINSOCK
+ tv->tv_sec = (long)atv->sec;
+#else
+ tv->tv_sec = (time_t)atv->sec;
+#endif
- atv.sec = (ares_int64_t)tv->tv_sec;
- atv.usec = (unsigned int)tv->tv_usec;
+ tv->tv_usec = (int)atv->usec;
+}
- return atv;
+static void struct_timeval_to_ares_timeval(ares_timeval_t *atv,
+ const struct timeval *tv)
+{
+ atv->sec = (ares_int64_t)tv->tv_sec;
+ atv->usec = (unsigned int)tv->tv_usec;
}
-struct timeval *ares_timeout(const ares_channel_t *channel,
- struct timeval *maxtv, struct timeval *tvbuf)
+static struct timeval *ares_timeout_int(const ares_channel_t *channel,
+ struct timeval *maxtv,
+ struct timeval *tvbuf)
{
- const struct query *query;
+ const ares_query_t *query;
ares__slist_node_t *node;
ares_timeval_t now;
ares_timeval_t atvbuf;
@@ -94,18 +104,18 @@ struct timeval *ares_timeout(const ares_channel_t *channel,
query = ares__slist_node_val(node);
- now = ares__tvnow();
+ ares__tvnow(&now);
ares__timeval_remaining(&atvbuf, &now, &query->timeout);
- *tvbuf = ares_timeval_to_struct_timeval(&atvbuf);
+ ares_timeval_to_struct_timeval(tvbuf, &atvbuf);
if (maxtv == NULL) {
return tvbuf;
}
/* Return the minimum time between maxtv and tvbuf */
- amaxtv = struct_timeval_to_ares_timeval(maxtv);
+ struct_timeval_to_ares_timeval(&amaxtv, maxtv);
if (atvbuf.sec > amaxtv.sec) {
return maxtv;
@@ -121,3 +131,21 @@ struct timeval *ares_timeout(const ares_channel_t *channel,
return tvbuf;
}
+
+struct timeval *ares_timeout(const ares_channel_t *channel,
+ struct timeval *maxtv, struct timeval *tvbuf)
+{
+ struct timeval *rv;
+
+ if (channel == NULL || tvbuf == NULL) {
+ return NULL;
+ }
+
+ ares__channel_lock(channel);
+
+ rv = ares_timeout_int(channel, maxtv, tvbuf);
+
+ ares__channel_unlock(channel);
+
+ return rv;
+}
diff --git a/contrib/libs/c-ares/src/lib/ares_update_servers.c b/contrib/libs/c-ares/src/lib/ares_update_servers.c
index 8075b1d1c0..639f79d815 100644
--- a/contrib/libs/c-ares/src/lib/ares_update_servers.c
+++ b/contrib/libs/c-ares/src/lib/ares_update_servers.c
@@ -25,7 +25,7 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
@@ -49,10 +49,8 @@
# endif
#endif
-#include "ares.h"
#include "ares_data.h"
#include "ares_inet_net_pton.h"
-#include "ares_private.h"
typedef struct {
struct ares_addr addr;
@@ -67,11 +65,11 @@ static ares_bool_t ares__addr_match(const struct ares_addr *addr1,
const struct ares_addr *addr2)
{
if (addr1 == NULL && addr2 == NULL) {
- return ARES_TRUE;
+ return ARES_TRUE; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (addr1 == NULL || addr2 == NULL) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (addr1->family != addr2->family) {
@@ -102,7 +100,7 @@ ares_bool_t ares__subnet_match(const struct ares_addr *addr,
size_t i;
if (addr == NULL || subnet == NULL) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (addr->family != subnet->family) {
@@ -115,7 +113,7 @@ ares_bool_t ares__subnet_match(const struct ares_addr *addr,
len = 4;
if (netmask > 32) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */
}
} else if (addr->family == AF_INET6) {
addr_ptr = (const unsigned char *)&addr->addr.addr6;
@@ -123,10 +121,10 @@ ares_bool_t ares__subnet_match(const struct ares_addr *addr,
len = 16;
if (netmask > 128) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */
}
} else {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */
}
for (i = 0; i < len && netmask > 0; i++) {
@@ -380,7 +378,7 @@ ares_status_t ares__sconfig_append(ares__llist_t **sconfig,
ares_status_t status;
if (sconfig == NULL || addr == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Silently skip blacklisted IPv6 servers. */
@@ -390,14 +388,14 @@ ares_status_t ares__sconfig_append(ares__llist_t **sconfig,
s = ares_malloc_zero(sizeof(*s));
if (s == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
if (*sconfig == NULL) {
*sconfig = ares__llist_create(ares_free);
if (*sconfig == NULL) {
- status = ARES_ENOMEM;
- goto fail;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -422,8 +420,8 @@ ares_status_t ares__sconfig_append(ares__llist_t **sconfig,
}
if (ares__llist_insert_last(*sconfig, s) == NULL) {
- status = ARES_ENOMEM;
- goto fail;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
return ARES_SUCCESS;
@@ -491,7 +489,7 @@ ares_status_t ares__sconfig_append_fromstr(ares__llist_t **sconfig,
status = ares__sconfig_append(sconfig, &s.addr, s.udp_port, s.tcp_port,
s.ll_iface);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -527,7 +525,7 @@ static ares__slist_node_t *ares__server_find(ares_channel_t *channel,
for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) {
- const struct server_state *server = ares__slist_node_val(node);
+ const ares_server_t *server = ares__slist_node_val(node);
if (!ares__addr_match(&server->addr, &s->addr)) {
continue;
@@ -581,11 +579,11 @@ static ares_status_t ares__server_create(ares_channel_t *channel,
const ares_sconfig_t *sconfig,
size_t idx)
{
- ares_status_t status;
- struct server_state *server = ares_malloc_zero(sizeof(*server));
+ ares_status_t status;
+ ares_server_t *server = ares_malloc_zero(sizeof(*server));
if (server == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
server->idx = idx;
@@ -612,39 +610,39 @@ static ares_status_t ares__server_create(ares_channel_t *channel,
server->tcp_parser = ares__buf_create();
if (server->tcp_parser == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
server->tcp_send = ares__buf_create();
if (server->tcp_send == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
server->connections = ares__llist_create(NULL);
if (server->connections == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
if (ares__slist_insert(channel->servers, server) == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ARES_SUCCESS;
done:
if (status != ARES_SUCCESS) {
- ares__destroy_server(server);
+ ares__destroy_server(server); /* LCOV_EXCL_LINE: OutOfMemory */
}
return status;
}
-static ares_bool_t ares__server_in_newconfig(const struct server_state *server,
- ares__llist_t *srvlist)
+static ares_bool_t ares__server_in_newconfig(const ares_server_t *server,
+ ares__llist_t *srvlist)
{
ares__llist_node_t *node;
const ares_channel_t *channel = server->channel;
@@ -678,8 +676,8 @@ static ares_bool_t ares__servers_remove_stale(ares_channel_t *channel,
ares__slist_node_t *snode = ares__slist_node_first(channel->servers);
while (snode != NULL) {
- ares__slist_node_t *snext = ares__slist_node_next(snode);
- const struct server_state *server = ares__slist_node_val(snode);
+ ares__slist_node_t *snext = ares__slist_node_next(snode);
+ const ares_server_t *server = ares__slist_node_val(snode);
if (!ares__server_in_newconfig(server, srvlist)) {
/* This will clean up all server state via the destruction callback and
* move any queries to new servers */
@@ -708,11 +706,9 @@ ares_status_t ares__servers_update(ares_channel_t *channel,
ares_bool_t list_changed = ARES_FALSE;
if (channel == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
- ares__channel_lock(channel);
-
/* NOTE: a NULL or zero entry server list is considered valid due to
* real-world people needing support for this for their test harnesses
*/
@@ -730,7 +726,7 @@ ares_status_t ares__servers_update(ares_channel_t *channel,
snode = ares__server_find(channel, sconfig);
if (snode != NULL) {
- struct server_state *server = ares__slist_node_val(snode);
+ ares_server_t *server = ares__slist_node_val(snode);
/* Copy over link-local settings. Its possible some of this data has
* changed, maybe ... */
@@ -781,7 +777,6 @@ ares_status_t ares__servers_update(ares_channel_t *channel,
status = ARES_SUCCESS;
done:
- ares__channel_unlock(channel);
return status;
}
@@ -796,7 +791,7 @@ static ares_status_t
s = ares__llist_create(ares_free);
if (s == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
for (node = servers; node != NULL; node = node->next) {
@@ -809,7 +804,7 @@ static ares_status_t
sconfig = ares_malloc_zero(sizeof(*sconfig));
if (sconfig == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
sconfig->addr.family = node->family;
@@ -822,17 +817,19 @@ static ares_status_t
}
if (ares__llist_insert_last(s, sconfig) == NULL) {
- ares_free(sconfig);
- goto fail;
+ ares_free(sconfig); /* LCOV_EXCL_LINE: OutOfMemory */
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
*llist = s;
return ARES_SUCCESS;
+/* LCOV_EXCL_START: OutOfMemory */
fail:
ares__llist_destroy(s);
return ARES_ENOMEM;
+ /* LCOV_EXCL_STOP */
}
static ares_status_t ares_addr_port_node_to_server_config_llist(
@@ -845,7 +842,7 @@ static ares_status_t ares_addr_port_node_to_server_config_llist(
s = ares__llist_create(ares_free);
if (s == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
for (node = servers; node != NULL; node = node->next) {
@@ -858,7 +855,7 @@ static ares_status_t ares_addr_port_node_to_server_config_llist(
sconfig = ares_malloc_zero(sizeof(*sconfig));
if (sconfig == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
sconfig->addr.family = node->family;
@@ -874,17 +871,19 @@ static ares_status_t ares_addr_port_node_to_server_config_llist(
sconfig->udp_port = (unsigned short)node->udp_port;
if (ares__llist_insert_last(s, sconfig) == NULL) {
- ares_free(sconfig);
- goto fail;
+ ares_free(sconfig); /* LCOV_EXCL_LINE: OutOfMemory */
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
*llist = s;
return ARES_SUCCESS;
+/* LCOV_EXCL_START: OutOfMemory */
fail:
ares__llist_destroy(s);
return ARES_ENOMEM;
+ /* LCOV_EXCL_STOP */
}
ares_status_t ares_in_addr_to_server_config_llist(const struct in_addr *servers,
@@ -898,7 +897,7 @@ ares_status_t ares_in_addr_to_server_config_llist(const struct in_addr *servers,
s = ares__llist_create(ares_free);
if (s == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
for (i = 0; servers != NULL && i < nservers; i++) {
@@ -906,7 +905,7 @@ ares_status_t ares_in_addr_to_server_config_llist(const struct in_addr *servers,
sconfig = ares_malloc_zero(sizeof(*sconfig));
if (sconfig == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
sconfig->addr.family = AF_INET;
@@ -914,21 +913,23 @@ ares_status_t ares_in_addr_to_server_config_llist(const struct in_addr *servers,
sizeof(sconfig->addr.addr.addr4));
if (ares__llist_insert_last(s, sconfig) == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
*llist = s;
return ARES_SUCCESS;
+/* LCOV_EXCL_START: OutOfMemory */
fail:
ares__llist_destroy(s);
return ARES_ENOMEM;
+ /* LCOV_EXCL_STOP */
}
/* Write out the details of a server to a buffer */
-ares_status_t ares_get_server_addr(const struct server_state *server,
- ares__buf_t *buf)
+ares_status_t ares_get_server_addr(const ares_server_t *server,
+ ares__buf_t *buf)
{
ares_status_t status;
char addr[INET6_ADDRSTRLEN];
@@ -937,7 +938,7 @@ ares_status_t ares_get_server_addr(const struct server_state *server,
if (server->addr.family == AF_INET6) {
status = ares__buf_append_byte(buf, '[');
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -945,37 +946,37 @@ ares_status_t ares_get_server_addr(const struct server_state *server,
status = ares__buf_append_str(buf, addr);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
if (server->addr.family == AF_INET6) {
status = ares__buf_append_byte(buf, ']');
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
/* :port */
status = ares__buf_append_byte(buf, ':');
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append_num_dec(buf, server->udp_port, 0);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* %iface */
if (ares_strlen(server->ll_iface)) {
status = ares__buf_append_byte(buf, '%');
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append_str(buf, server->ll_iface);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -999,7 +1000,7 @@ int ares_get_servers(const ares_channel_t *channel,
for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) {
- const struct server_state *server = ares__slist_node_val(node);
+ const ares_server_t *server = ares__slist_node_val(node);
/* Allocate storage for this server node appending it to the list */
srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_NODE);
@@ -1054,7 +1055,7 @@ int ares_get_servers_ports(const ares_channel_t *channel,
for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) {
- const struct server_state *server = ares__slist_node_val(node);
+ const ares_server_t *server = ares__slist_node_val(node);
/* Allocate storage for this server node appending it to the list */
srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_PORT_NODE);
@@ -1109,8 +1110,9 @@ int ares_set_servers(ares_channel_t *channel,
return (int)status;
}
- /* NOTE: lock is in ares__servers_update() */
+ ares__channel_lock(channel);
status = ares__servers_update(channel, slist, ARES_TRUE);
+ ares__channel_unlock(channel);
ares__llist_destroy(slist);
@@ -1132,8 +1134,9 @@ int ares_set_servers_ports(ares_channel_t *channel,
return (int)status;
}
- /* NOTE: lock is in ares__servers_update() */
+ ares__channel_lock(channel);
status = ares__servers_update(channel, slist, ARES_TRUE);
+ ares__channel_unlock(channel);
ares__llist_destroy(slist);
@@ -1151,11 +1154,12 @@ static ares_status_t set_servers_csv(ares_channel_t *channel, const char *_csv)
return ARES_ENODATA;
}
- /* NOTE: lock is in ares__servers_update() */
-
if (ares_strlen(_csv) == 0) {
/* blank all servers */
- return ares__servers_update(channel, NULL, ARES_TRUE);
+ ares__channel_lock(channel);
+ status = ares__servers_update(channel, NULL, ARES_TRUE);
+ ares__channel_unlock(channel);
+ return status;
}
status = ares__sconfig_append_fromstr(&slist, _csv, ARES_FALSE);
@@ -1164,8 +1168,9 @@ static ares_status_t set_servers_csv(ares_channel_t *channel, const char *_csv)
return status;
}
- /* NOTE: lock is in ares__servers_update() */
+ ares__channel_lock(channel);
status = ares__servers_update(channel, slist, ARES_TRUE);
+ ares__channel_unlock(channel);
ares__llist_destroy(slist);
@@ -1175,13 +1180,11 @@ static ares_status_t set_servers_csv(ares_channel_t *channel, const char *_csv)
/* We'll go ahead and honor ports anyhow */
int ares_set_servers_csv(ares_channel_t *channel, const char *_csv)
{
- /* NOTE: lock is in ares__servers_update() */
return (int)set_servers_csv(channel, _csv);
}
int ares_set_servers_ports_csv(ares_channel_t *channel, const char *_csv)
{
- /* NOTE: lock is in ares__servers_update() */
return (int)set_servers_csv(channel, _csv);
}
@@ -1195,24 +1198,24 @@ char *ares_get_servers_csv(const ares_channel_t *channel)
buf = ares__buf_create();
if (buf == NULL) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) {
- ares_status_t status;
- const struct server_state *server = ares__slist_node_val(node);
+ ares_status_t status;
+ const ares_server_t *server = ares__slist_node_val(node);
if (ares__buf_len(buf)) {
status = ares__buf_append_byte(buf, ',');
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
status = ares_get_server_addr(server, buf);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -1229,7 +1232,7 @@ void ares_set_server_state_callback(ares_channel_t *channel,
ares_server_state_callback cb, void *data)
{
if (channel == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
channel->server_state_cb = cb;
channel->server_state_cb_data = data;
diff --git a/contrib/libs/c-ares/src/lib/ares_version.c b/contrib/libs/c-ares/src/lib/ares_version.c
index ca15fa77dc..f50f65b0d6 100644
--- a/contrib/libs/c-ares/src/lib/ares_version.c
+++ b/contrib/libs/c-ares/src/lib/ares_version.c
@@ -24,8 +24,7 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
+#include "ares_private.h"
const char *ares_version(int *version)
{
diff --git a/contrib/libs/c-ares/src/lib/config-win32.h b/contrib/libs/c-ares/src/lib/config-win32.h
index 752e17afe6..003f3937e5 100644
--- a/contrib/libs/c-ares/src/lib/config-win32.h
+++ b/contrib/libs/c-ares/src/lib/config-win32.h
@@ -88,7 +88,7 @@
#define HAVE_IPHLPAPI_H 1
/* Define if you have <netioapi.h> header file */
-#ifndef __WATCOMC__
+#if !defined(__WATCOMC__) && !defined(WATT32)
# define HAVE_NETIOAPI_H 1
#endif
@@ -196,11 +196,8 @@
/* Define to the type of arg 1 for send. */
#define SEND_TYPE_ARG1 SOCKET
-/* Define to the type qualifier of arg 2 for send. */
-#define SEND_QUAL_ARG2 const
-
/* Define to the type of arg 2 for send. */
-#define SEND_TYPE_ARG2 char *
+#define SEND_TYPE_ARG2 const char *
/* Define to the type of arg 3 for send. */
#define SEND_TYPE_ARG3 int
@@ -213,21 +210,34 @@
/* Specifics for the Watt-32 tcp/ip stack. */
#ifdef WATT32
-# define SOCKET int
+# undef RECV_TYPE_ARG1
+# define RECV_TYPE_ARG1 int
+# undef SEND_TYPE_ARG1
+# define SEND_TYPE_ARG1 int
+# undef RECVFROM_TYPE_ARG1
+# define RECVFROM_TYPE_ARG1 int
# define NS_INADDRSZ 4
# define HAVE_ARPA_NAMESER_H 1
# define HAVE_ARPA_INET_H 1
# define HAVE_NETDB_H 1
# define HAVE_NETINET_IN_H 1
# define HAVE_SYS_SOCKET_H 1
+# define HAVE_SYS_IOCTL_H 1
# define HAVE_NETINET_TCP_H 1
# define HAVE_AF_INET6 1
# define HAVE_PF_INET6 1
# define HAVE_STRUCT_IN6_ADDR 1
# define HAVE_STRUCT_SOCKADDR_IN6 1
+# define HAVE_WRITEV 1
+# define HAVE_IF_NAMETOINDEX 1
+# define HAVE_IF_INDEXTONAME 1
+# define HAVE_GETSERVBYPORT_R 1
+# define GETSERVBYPORT_R_ARGS 6
# undef HAVE_WINSOCK_H
# undef HAVE_WINSOCK2_H
# undef HAVE_WS2TCPIP_H
+# undef HAVE_IPHLPAPI_H
+# undef HAVE_NETIOAPI_H
#endif
/* Threading support enabled */
@@ -348,7 +358,11 @@
# define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1
#endif
-#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) && !defined(__WATCOMC__)
+/* Define to 1 if you have the `RegisterWaitForSingleObject' function. */
+#define HAVE_REGISTERWAITFORSINGLEOBJECT 1
+
+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) && \
+ !defined(__WATCOMC__) && !defined(WATT32)
/* Define if you have if_nametoindex() */
# define HAVE_IF_NAMETOINDEX 1
/* Define if you have if_indextoname() */
@@ -357,6 +371,8 @@
# define HAVE_CONVERTINTERFACEINDEXTOLUID 1
/* Define to 1 if you have the `ConvertInterfaceLuidToNameA' function. */
# define HAVE_CONVERTINTERFACELUIDTONAMEA 1
+/* Define to 1 if you have the `NotifyIpInterfaceChange' function. */
+# define HAVE_NOTIFYIPINTERFACECHANGE 1
#endif
/* ---------------------------------------------------------------- */
diff --git a/contrib/libs/c-ares/src/lib/dsa/ares__array.c b/contrib/libs/c-ares/src/lib/dsa/ares__array.c
new file mode 100644
index 0000000000..0c724248bf
--- /dev/null
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__array.c
@@ -0,0 +1,356 @@
+/* MIT License
+ *
+ * Copyright (c) 2024 Brad House
+ *
+ * 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_private.h"
+#include "ares__array.h"
+
+#define ARES__ARRAY_MIN 4
+
+struct ares__array {
+ ares__array_destructor_t destruct;
+ void *arr;
+ size_t member_size;
+ size_t cnt;
+ size_t offset;
+ size_t alloc_cnt;
+};
+
+ares__array_t *ares__array_create(size_t member_size,
+ ares__array_destructor_t destruct)
+{
+ ares__array_t *arr;
+
+ if (member_size == 0) {
+ return NULL;
+ }
+
+ arr = ares_malloc_zero(sizeof(*arr));
+ if (arr == NULL) {
+ return NULL;
+ }
+
+ arr->member_size = member_size;
+ arr->destruct = destruct;
+ return arr;
+}
+
+size_t ares__array_len(const ares__array_t *arr)
+{
+ if (arr == NULL) {
+ return 0;
+ }
+ return arr->cnt;
+}
+
+void *ares__array_at(ares__array_t *arr, size_t idx)
+{
+ if (arr == NULL || idx >= arr->cnt) {
+ return NULL;
+ }
+ return (unsigned char *)arr->arr + ((idx + arr->offset) * arr->member_size);
+}
+
+const void *ares__array_at_const(const ares__array_t *arr, size_t idx)
+{
+ if (arr == NULL || idx >= arr->cnt) {
+ return NULL;
+ }
+ return (unsigned char *)arr->arr + ((idx + arr->offset) * arr->member_size);
+}
+
+ares_status_t ares__array_sort(ares__array_t *arr, ares__array_cmp_t cmp)
+{
+ if (arr == NULL || cmp == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ /* Nothing to sort */
+ if (arr->cnt < 2) {
+ return ARES_SUCCESS;
+ }
+
+ qsort((unsigned char *)arr->arr + (arr->offset * arr->member_size), arr->cnt,
+ arr->member_size, cmp);
+ return ARES_SUCCESS;
+}
+
+void ares__array_destroy(ares__array_t *arr)
+{
+ size_t i;
+
+ if (arr == NULL) {
+ return;
+ }
+
+ if (arr->destruct != NULL) {
+ for (i = 0; i < arr->cnt; i++) {
+ arr->destruct(ares__array_at(arr, i));
+ }
+ }
+
+ ares_free(arr->arr);
+ ares_free(arr);
+}
+
+/* NOTE: this function operates on actual indexes, NOT indexes using the
+ * arr->offset */
+static ares_status_t ares__array_move(ares__array_t *arr, size_t dest_idx,
+ size_t src_idx)
+{
+ void *dest_ptr;
+ const void *src_ptr;
+ size_t nmembers;
+
+ if (arr == NULL || dest_idx >= arr->alloc_cnt || src_idx >= arr->alloc_cnt) {
+ return ARES_EFORMERR;
+ }
+
+ /* Nothing to do */
+ if (dest_idx == src_idx) {
+ return ARES_SUCCESS;
+ }
+
+ dest_ptr = (unsigned char *)arr->arr + (dest_idx * arr->member_size);
+ src_ptr = (unsigned char *)arr->arr + (src_idx * arr->member_size);
+
+ /* Check to make sure shifting to the right won't overflow our allocation
+ * boundary */
+ if (dest_idx > src_idx && arr->cnt + (dest_idx - src_idx) > arr->alloc_cnt) {
+ return ARES_EFORMERR;
+ }
+ if (dest_idx < src_idx) {
+ nmembers = arr->cnt - dest_idx;
+ } else {
+ nmembers = arr->cnt - src_idx;
+ }
+
+ memmove(dest_ptr, src_ptr, nmembers * arr->member_size);
+
+ return ARES_SUCCESS;
+}
+
+void *ares__array_finish(ares__array_t *arr, size_t *num_members)
+{
+ void *ptr;
+
+ if (arr == NULL || num_members == NULL) {
+ return NULL;
+ }
+
+ /* Make sure we move data to beginning of allocation */
+ if (arr->offset != 0) {
+ if (ares__array_move(arr, 0, arr->offset) != ARES_SUCCESS) {
+ return NULL;
+ }
+ arr->offset = 0;
+ }
+
+ ptr = arr->arr;
+ *num_members = arr->cnt;
+ ares_free(arr);
+ return ptr;
+}
+
+ares_status_t ares__array_set_size(ares__array_t *arr, size_t size)
+{
+ void *temp;
+
+ if (arr == NULL || size == 0 || size < arr->cnt) {
+ return ARES_EFORMERR;
+ }
+
+ /* Always operate on powers of 2 */
+ size = ares__round_up_pow2(size);
+
+ if (size < ARES__ARRAY_MIN) {
+ size = ARES__ARRAY_MIN;
+ }
+
+ /* If our allocation size is already large enough, skip */
+ if (size <= arr->alloc_cnt) {
+ return ARES_SUCCESS;
+ }
+
+ temp = ares_realloc_zero(arr->arr, arr->alloc_cnt * arr->member_size,
+ size * arr->member_size);
+ if (temp == NULL) {
+ return ARES_ENOMEM;
+ }
+ arr->alloc_cnt = size;
+ arr->arr = temp;
+ return ARES_SUCCESS;
+}
+
+ares_status_t ares__array_insert_at(void **elem_ptr, ares__array_t *arr,
+ size_t idx)
+{
+ void *ptr;
+ ares_status_t status;
+
+ if (arr == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ /* Not >= since we are allowed to append to the end */
+ if (idx > arr->cnt) {
+ return ARES_EFORMERR;
+ }
+
+ /* Allocate more if needed */
+ status = ares__array_set_size(arr, arr->cnt + 1);
+ if (status != ARES_SUCCESS) {
+ return status;
+ }
+
+ /* Shift if we have memory but not enough room at the end */
+ if (arr->cnt + 1 + arr->offset > arr->alloc_cnt) {
+ status = ares__array_move(arr, 0, arr->offset);
+ if (status != ARES_SUCCESS) {
+ return status;
+ }
+ arr->offset = 0;
+ }
+
+ /* If we're inserting anywhere other than the end, we need to move some
+ * elements out of the way */
+ if (idx != arr->cnt) {
+ status = ares__array_move(arr, idx + arr->offset + 1, idx + arr->offset);
+ if (status != ARES_SUCCESS) {
+ return status;
+ }
+ }
+
+ /* Ok, we're guaranteed to have a gap where we need it, lets zero it out,
+ * and return it */
+ ptr = (unsigned char *)arr->arr + ((idx + arr->offset) * arr->member_size);
+ memset(ptr, 0, arr->member_size);
+ arr->cnt++;
+
+ if (elem_ptr) {
+ *elem_ptr = ptr;
+ }
+
+ return ARES_SUCCESS;
+}
+
+ares_status_t ares__array_insert_last(void **elem_ptr, ares__array_t *arr)
+{
+ return ares__array_insert_at(elem_ptr, arr, ares__array_len(arr));
+}
+
+ares_status_t ares__array_insert_first(void **elem_ptr, ares__array_t *arr)
+{
+ return ares__array_insert_at(elem_ptr, arr, 0);
+}
+
+void *ares__array_first(ares__array_t *arr)
+{
+ return ares__array_at(arr, 0);
+}
+
+void *ares__array_last(ares__array_t *arr)
+{
+ size_t cnt = ares__array_len(arr);
+ if (cnt == 0) {
+ return NULL;
+ }
+ return ares__array_at(arr, cnt - 1);
+}
+
+const void *ares__array_first_const(const ares__array_t *arr)
+{
+ return ares__array_at_const(arr, 0);
+}
+
+const void *ares__array_last_const(const ares__array_t *arr)
+{
+ size_t cnt = ares__array_len(arr);
+ if (cnt == 0) {
+ return NULL;
+ }
+ return ares__array_at_const(arr, cnt - 1);
+}
+
+ares_status_t ares__array_claim_at(void *dest, size_t dest_size,
+ ares__array_t *arr, size_t idx)
+{
+ ares_status_t status;
+
+ if (arr == NULL || idx >= arr->cnt) {
+ return ARES_EFORMERR;
+ }
+
+ if (dest != NULL && dest_size < arr->member_size) {
+ return ARES_EFORMERR;
+ }
+
+ if (dest) {
+ memcpy(dest, ares__array_at(arr, idx), arr->member_size);
+ }
+
+ if (idx == 0) {
+ /* Optimization, if first element, just increment offset, makes removing a
+ * lot from the start quick */
+ arr->offset++;
+ } else if (idx != arr->cnt - 1) {
+ /* Must shift entire array if removing an element from the middle. Does
+ * nothing if removing last element other than decrement count. */
+ status = ares__array_move(arr, idx + arr->offset, idx + arr->offset + 1);
+ if (status != ARES_SUCCESS) {
+ return status;
+ }
+ }
+
+ arr->cnt--;
+ return ARES_SUCCESS;
+}
+
+ares_status_t ares__array_remove_at(ares__array_t *arr, size_t idx)
+{
+ void *ptr = ares__array_at(arr, idx);
+ if (arr == NULL || ptr == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ if (arr->destruct != NULL) {
+ arr->destruct(ptr);
+ }
+
+ return ares__array_claim_at(NULL, 0, arr, idx);
+}
+
+ares_status_t ares__array_remove_first(ares__array_t *arr)
+{
+ return ares__array_remove_at(arr, 0);
+}
+
+ares_status_t ares__array_remove_last(ares__array_t *arr)
+{
+ size_t cnt = ares__array_len(arr);
+ if (cnt == 0) {
+ return ARES_EFORMERR;
+ }
+ return ares__array_remove_at(arr, cnt - 1);
+}
diff --git a/contrib/libs/c-ares/src/lib/dsa/ares__array.h b/contrib/libs/c-ares/src/lib/dsa/ares__array.h
new file mode 100644
index 0000000000..6fa1c0e15e
--- /dev/null
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__array.h
@@ -0,0 +1,223 @@
+/* MIT License
+ *
+ * Copyright (c) 2024 Brad House
+ *
+ * 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
+ */
+#ifndef __ARES__ARRAY_H
+#define __ARES__ARRAY_H
+
+/*! \addtogroup ares__array Array Data Structure
+ *
+ * This is an array with helpers. It is meant to have as little overhead
+ * as possible over direct array management by applications but to provide
+ * safety and some optimization features. It can also return the array in
+ * native form once all manipulation has been performed.
+ *
+ * @{
+ */
+
+struct ares__array;
+
+/*! Opaque data structure for array */
+typedef struct ares__array ares__array_t;
+
+/*! Callback to free user-defined member data
+ *
+ * \param[in] data pointer to member of array to be destroyed. The pointer
+ * itself must not be destroyed, just the data it contains.
+ */
+typedef void (*ares__array_destructor_t)(void *data);
+
+/*! Callback to compare two array elements used for sorting
+ *
+ * \param[in] data1 array member 1
+ * \param[in] data2 array member 2
+ * \return < 0 if data1 < data2, > 0 if data1 > data2, 0 if data1 == data2
+ */
+typedef int (*ares__array_cmp_t)(const void *data1, const void *data2);
+
+/*! Create an array object
+ *
+ * NOTE: members of the array are typically going to be an going to be a
+ * struct with compiler/ABI specific padding to ensure proper alignment.
+ * Care needs to be taken if using primitive types, especially floating
+ * point numbers which size may not indicate the required alignment.
+ * For example, a double may be 80 bits (10 bytes), but required
+ * alignment of 16 bytes. In such a case, a member_size of 16 would be
+ * required to be used.
+ *
+ * \param[in] destruct Optional. Destructor to call on a removed member
+ * \param[in] member_size Size of array member, usually determined using
+ * sizeof() for the member such as a struct.
+ *
+ * \return array object or NULL on out of memory
+ */
+ares__array_t *ares__array_create(size_t member_size,
+ ares__array_destructor_t destruct);
+
+
+/*! Request the array be at least the requested size. Useful if the desired
+ * array size is known prior to populating the array to prevent reallocations.
+ *
+ * \param[in] arr Initialized array object.
+ * \param[in] size Minimum number of members
+ * \return ARES_SUCCESS on success, ARES_EFORMERR on misuse,
+ * ARES_ENOMEM on out of memory */
+ares_status_t ares__array_set_size(ares__array_t *arr, size_t size);
+
+/*! Sort the array using the given comparison function. This is not
+ * persistent, any future elements inserted will not maintain this sort.
+ *
+ * \param[in] arr Initialized array object.
+ * \param[in] cb Sort callback
+ * \return ARES_SUCCESS on success
+ */
+ares_status_t ares__array_sort(ares__array_t *arr, ares__array_cmp_t cmp);
+
+/*! Destroy an array object. If a destructor is set, will be called on each
+ * member of the array.
+ *
+ * \param[in] arr Initialized array object.
+ */
+void ares__array_destroy(ares__array_t *arr);
+
+/*! Retrieve the array in the native format. This will also destroy the
+ * container. It is the responsibility of the caller to free the returned
+ * pointer and also any data within each array element.
+ *
+ * \param[in] arr Initialized array object
+ * \param[out] num_members the number of members in the returned array
+ * \return pointer to native array on success, NULL on failure.
+ */
+void *ares__array_finish(ares__array_t *arr, size_t *num_members);
+
+/*! Retrieve the number of members in the array
+ *
+ * \param[in] arr Initialized array object.
+ * \return numbrer of members
+ */
+size_t ares__array_len(const ares__array_t *arr);
+
+/*! Insert a new array member at the given index
+ *
+ * \param[out] elem_ptr Optional. Pointer to the returned array element.
+ * \param[in] arr Initialized array object.
+ * \param[in] idx Index in array to place new element, will shift any
+ * elements down that exist after this point.
+ * \return ARES_SUCCESS on success, ARES_EFORMERR on bad index,
+ * ARES_ENOMEM on out of memory.
+ */
+ares_status_t ares__array_insert_at(void **elem_ptr, ares__array_t *arr,
+ size_t idx);
+
+/*! Insert a new array member at the end of the array
+ *
+ * \param[out] elem_ptr Optional. Pointer to the returned array element.
+ * \param[in] arr Initialized array object.
+ * \return ARES_SUCCESS on success, ARES_ENOMEM on out of memory.
+ */
+ares_status_t ares__array_insert_last(void **elem_ptr, ares__array_t *arr);
+
+/*! Insert a new array member at the beginning of the array
+ *
+ * \param[out] elem_ptr Optional. Pointer to the returned array element.
+ * \param[in] arr Initialized array object.
+ * \return ARES_SUCCESS on success, ARES_ENOMEM on out of memory.
+ */
+ares_status_t ares__array_insert_first(void **elem_ptr, ares__array_t *arr);
+
+/*! Fetch a pointer to the given element in the array
+ * \param[in] array Initialized array object
+ * \param[in] idx Index to fetch
+ * \return pointer on success, NULL on failure */
+void *ares__array_at(ares__array_t *arr, size_t idx);
+
+/*! Fetch a pointer to the first element in the array
+ * \param[in] array Initialized array object
+ * \return pointer on success, NULL on failure */
+void *ares__array_first(ares__array_t *arr);
+
+/*! Fetch a pointer to the last element in the array
+ * \param[in] array Initialized array object
+ * \return pointer on success, NULL on failure */
+void *ares__array_last(ares__array_t *arr);
+
+/*! Fetch a constant pointer to the given element in the array
+ * \param[in] array Initialized array object
+ * \param[in] idx Index to fetch
+ * \return pointer on success, NULL on failure */
+const void *ares__array_at_const(const ares__array_t *arr, size_t idx);
+
+/*! Fetch a constant pointer to the first element in the array
+ * \param[in] array Initialized array object
+ * \return pointer on success, NULL on failure */
+const void *ares__array_first_const(const ares__array_t *arr);
+
+/*! Fetch a constant pointer to the last element in the array
+ * \param[in] array Initialized array object
+ * \return pointer on success, NULL on failure */
+const void *ares__array_last_const(const ares__array_t *arr);
+
+/*! Claim the data from the specified array index, copying it to the buffer
+ * provided by the caller. The index specified in the array will then be
+ * removed (without calling any possible destructor)
+ *
+ * \param[in,out] dest Optional. Buffer to hold array member. Pass NULL
+ * if not needed. This could leak memory if array
+ * member needs destructor if not provided.
+ * \param[in] dest_size Size of buffer provided, used as a sanity check.
+ * Must match member_size provided to
+ * ares__array_create() if dest_size specified.
+ * \param[in] arr Initialized array object
+ * \param[in] idx Index to claim
+ * \return ARES_SUCCESS on success, ARES_EFORMERR on usage failure.
+ */
+ares_status_t ares__array_claim_at(void *dest, size_t dest_size,
+ ares__array_t *arr, size_t idx);
+
+/*! Remove the member at the specified array index. The destructor will be
+ * called.
+ *
+ * \param[in] arr Initialized array object
+ * \param[in] idx Index to remove
+ * \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use
+ */
+ares_status_t ares__array_remove_at(ares__array_t *arr, size_t idx);
+
+/*! Remove the first member of the array.
+ *
+ * \param[in] arr Initialized array object
+ * \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use
+ */
+ares_status_t ares__array_remove_first(ares__array_t *arr);
+
+/*! Remove the last member of the array.
+ *
+ * \param[in] arr Initialized array object
+ * \return ARES_SUCCESS if removed, ARES_EFORMERR on invalid use
+ */
+ares_status_t ares__array_remove_last(ares__array_t *arr);
+
+/*! @} */
+
+#endif /* __ARES__ARRAY_H */
diff --git a/contrib/libs/c-ares/src/lib/ares__htable.c b/contrib/libs/c-ares/src/lib/dsa/ares__htable.c
index f09c9ea295..d608d60ce3 100644
--- a/contrib/libs/c-ares/src/lib/ares__htable.c
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__htable.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares__llist.h"
#include "ares__htable.h"
@@ -207,7 +205,7 @@ static ares_bool_t ares__htable_expand(ares__htable_t *htable)
* middle, we wouldn't be able to recover. */
buckets = ares_malloc_zero(sizeof(*buckets) * htable->size);
if (buckets == NULL) {
- goto done; /* LCOV_EXCL_LINE */
+ goto done; /* LCOV_EXCL_LINE */
}
/* The maximum number of new llists we'll need is the number of collisions
@@ -270,7 +268,7 @@ static ares_bool_t ares__htable_expand(ares__htable_t *htable)
if (buckets[idx] == NULL) {
/* Silence static analysis, this isn't possible but it doesn't know */
if (prealloc_llist == NULL || prealloc_llist_len == 0) {
- goto done; /* LCOV_EXCL_LINE */
+ goto done; /* LCOV_EXCL_LINE */
}
buckets[idx] = prealloc_llist[prealloc_llist_len - 1];
prealloc_llist_len--;
@@ -304,7 +302,7 @@ done:
/* On failure, we need to restore the htable size */
if (rv != ARES_TRUE) {
- htable->size = old_size; /* LCOV_EXCL_LINE */
+ htable->size = old_size; /* LCOV_EXCL_LINE */
}
return rv;
@@ -336,7 +334,7 @@ ares_bool_t ares__htable_insert(ares__htable_t *htable, void *bucket)
if (htable->num_keys + 1 >
(htable->size * ARES__HTABLE_EXPAND_PERCENT) / 100) {
if (!ares__htable_expand(htable)) {
- return ARES_FALSE; /* LCOV_EXCL_LINE */
+ return ARES_FALSE; /* LCOV_EXCL_LINE */
}
/* If we expanded, need to calculate a new index */
idx = HASH_IDX(htable, key);
diff --git a/contrib/libs/c-ares/src/lib/ares__htable.h b/contrib/libs/c-ares/src/lib/dsa/ares__htable.h
index d09c865977..d09c865977 100644
--- a/contrib/libs/c-ares/src/lib/ares__htable.h
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__htable.h
diff --git a/contrib/libs/c-ares/src/lib/ares__htable_asvp.c b/contrib/libs/c-ares/src/lib/dsa/ares__htable_asvp.c
index 3c1d2a336f..4b9267ff6c 100644
--- a/contrib/libs/c-ares/src/lib/ares__htable_asvp.c
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__htable_asvp.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares__htable.h"
#include "ares__htable_asvp.h"
@@ -121,7 +119,7 @@ ares_socket_t *ares__htable_asvp_keys(const ares__htable_asvp_t *htable,
size_t i;
if (htable == NULL || num == NULL) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
}
*num = 0;
@@ -133,8 +131,8 @@ ares_socket_t *ares__htable_asvp_keys(const ares__htable_asvp_t *htable,
out = ares_malloc_zero(sizeof(*out) * cnt);
if (out == NULL) {
- ares_free(buckets);
- return NULL;
+ ares_free(buckets); /* LCOV_EXCL_LINE: OutOfMemory */
+ return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
}
for (i = 0; i < cnt; i++) {
@@ -157,7 +155,7 @@ ares_bool_t ares__htable_asvp_insert(ares__htable_asvp_t *htable,
bucket = ares_malloc(sizeof(*bucket));
if (bucket == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
bucket->parent = htable;
@@ -165,14 +163,14 @@ ares_bool_t ares__htable_asvp_insert(ares__htable_asvp_t *htable,
bucket->val = val;
if (!ares__htable_insert(htable->hash, bucket)) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
return ARES_TRUE;
fail:
if (bucket) {
- ares_free(bucket);
+ ares_free(bucket); /* LCOV_EXCL_LINE: OutOfMemory */
}
return ARES_FALSE;
}
diff --git a/contrib/libs/c-ares/src/lib/ares__htable_asvp.h b/contrib/libs/c-ares/src/lib/dsa/ares__htable_asvp.h
index 49a766d023..49a766d023 100644
--- a/contrib/libs/c-ares/src/lib/ares__htable_asvp.h
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__htable_asvp.h
diff --git a/contrib/libs/c-ares/src/lib/ares__htable_strvp.c b/contrib/libs/c-ares/src/lib/dsa/ares__htable_strvp.c
index bfae4c3622..d73a1928a7 100644
--- a/contrib/libs/c-ares/src/lib/ares__htable_strvp.c
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__htable_strvp.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares__htable.h"
#include "ares__htable_strvp.h"
diff --git a/contrib/libs/c-ares/src/lib/ares__htable_strvp.h b/contrib/libs/c-ares/src/lib/dsa/ares__htable_strvp.h
index 25dd2b9077..878c71869a 100644
--- a/contrib/libs/c-ares/src/lib/ares__htable_strvp.h
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__htable_strvp.h
@@ -115,4 +115,4 @@ size_t ares__htable_strvp_num_keys(const ares__htable_strvp_t *htable);
/*! @} */
-#endif /* __ARES__HTABLE_STVP_H */
+#endif /* __ARES__HTABLE_STRVP_H */
diff --git a/contrib/libs/c-ares/src/lib/ares__htable_szvp.c b/contrib/libs/c-ares/src/lib/dsa/ares__htable_szvp.c
index 2ff64784bc..b3e88d8b9a 100644
--- a/contrib/libs/c-ares/src/lib/ares__htable_szvp.c
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__htable_szvp.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares__htable.h"
#include "ares__htable_szvp.h"
@@ -123,7 +121,7 @@ ares_bool_t ares__htable_szvp_insert(ares__htable_szvp_t *htable, size_t key,
bucket = ares_malloc(sizeof(*bucket));
if (bucket == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
bucket->parent = htable;
@@ -131,14 +129,14 @@ ares_bool_t ares__htable_szvp_insert(ares__htable_szvp_t *htable, size_t key,
bucket->val = val;
if (!ares__htable_insert(htable->hash, bucket)) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
return ARES_TRUE;
fail:
if (bucket) {
- ares_free(bucket);
+ ares_free(bucket); /* LCOV_EXCL_LINE: OutOfMemory */
}
return ARES_FALSE;
}
diff --git a/contrib/libs/c-ares/src/lib/ares__htable_szvp.h b/contrib/libs/c-ares/src/lib/dsa/ares__htable_szvp.h
index 62b1776be9..62b1776be9 100644
--- a/contrib/libs/c-ares/src/lib/ares__htable_szvp.h
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__htable_szvp.h
diff --git a/contrib/libs/c-ares/src/lib/ares__htable_vpvp.c b/contrib/libs/c-ares/src/lib/dsa/ares__htable_vpvp.c
index 3558fa5a9b..9042c48dd7 100644
--- a/contrib/libs/c-ares/src/lib/ares__htable_vpvp.c
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__htable_vpvp.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares__htable.h"
#include "ares__htable_vpvp.h"
@@ -44,7 +42,7 @@ typedef struct {
void ares__htable_vpvp_destroy(ares__htable_vpvp_t *htable)
{
if (htable == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares__htable_destroy(htable->hash);
@@ -93,13 +91,13 @@ ares__htable_vpvp_t *
{
ares__htable_vpvp_t *htable = ares_malloc(sizeof(*htable));
if (htable == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
htable->hash =
ares__htable_create(hash_func, bucket_key, bucket_free, key_eq);
if (htable->hash == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
htable->free_key = key_free;
@@ -107,12 +105,14 @@ ares__htable_vpvp_t *
return htable;
+/* LCOV_EXCL_START: OutOfMemory */
fail:
if (htable) {
ares__htable_destroy(htable->hash);
ares_free(htable);
}
return NULL;
+ /* LCOV_EXCL_STOP */
}
ares_bool_t ares__htable_vpvp_insert(ares__htable_vpvp_t *htable, void *key,
diff --git a/contrib/libs/c-ares/src/lib/ares__htable_vpvp.h b/contrib/libs/c-ares/src/lib/dsa/ares__htable_vpvp.h
index 1e0c750d86..1e0c750d86 100644
--- a/contrib/libs/c-ares/src/lib/ares__htable_vpvp.h
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__htable_vpvp.h
diff --git a/contrib/libs/c-ares/src/lib/ares__llist.c b/contrib/libs/c-ares/src/lib/dsa/ares__llist.c
index d175da2bd3..96936c1abe 100644
--- a/contrib/libs/c-ares/src/lib/ares__llist.c
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__llist.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares__llist.h"
@@ -77,7 +75,7 @@ static void ares__llist_attach_at(ares__llist_t *list,
ares__llist_node_t *node)
{
if (list == NULL || node == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
node->parent = list;
@@ -127,7 +125,7 @@ static ares__llist_node_t *ares__llist_insert_at(ares__llist_t *list,
ares__llist_node_t *node = NULL;
if (list == NULL || val == NULL) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
}
node = ares_malloc_zero(sizeof(*node));
@@ -186,6 +184,26 @@ ares__llist_node_t *ares__llist_node_first(ares__llist_t *list)
return list->head;
}
+ares__llist_node_t *ares__llist_node_idx(ares__llist_t *list, size_t idx)
+{
+ ares__llist_node_t *node;
+ size_t cnt;
+
+ if (list == NULL) {
+ return NULL;
+ }
+ if (idx >= list->cnt) {
+ return NULL;
+ }
+
+ node = list->head;
+ for (cnt = 0; node != NULL && cnt < idx; cnt++) {
+ node = node->next;
+ }
+
+ return node;
+}
+
ares__llist_node_t *ares__llist_node_last(ares__llist_t *list)
{
if (list == NULL) {
@@ -250,7 +268,7 @@ static void ares__llist_node_detach(ares__llist_node_t *node)
ares__llist_t *list;
if (node == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
list = node->parent;
@@ -323,7 +341,7 @@ void ares__llist_node_replace(ares__llist_node_t *node, void *val)
node->data = val;
}
-void ares__llist_destroy(ares__llist_t *list)
+void ares__llist_clear(ares__llist_t *list)
{
ares__llist_node_t *node;
@@ -334,6 +352,14 @@ void ares__llist_destroy(ares__llist_t *list)
while ((node = ares__llist_node_first(list)) != NULL) {
ares__llist_node_destroy(node);
}
+}
+
+void ares__llist_destroy(ares__llist_t *list)
+{
+ if (list == NULL) {
+ return;
+ }
+ ares__llist_clear(list);
ares_free(list);
}
@@ -341,7 +367,7 @@ void ares__llist_node_move_parent_last(ares__llist_node_t *node,
ares__llist_t *new_parent)
{
if (node == NULL || new_parent == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares__llist_node_detach(node);
@@ -352,7 +378,7 @@ void ares__llist_node_move_parent_first(ares__llist_node_t *node,
ares__llist_t *new_parent)
{
if (node == NULL || new_parent == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares__llist_node_detach(node);
diff --git a/contrib/libs/c-ares/src/lib/ares__llist.h b/contrib/libs/c-ares/src/lib/dsa/ares__llist.h
index 7d57bdab3b..213f54134b 100644
--- a/contrib/libs/c-ares/src/lib/ares__llist.h
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__llist.h
@@ -122,6 +122,14 @@ ares__llist_node_t *ares__llist_node_first(ares__llist_t *list);
*/
ares__llist_node_t *ares__llist_node_last(ares__llist_t *list);
+/*! Obtain a node based on its index. This is an O(n) operation.
+ *
+ * \param[in] list Initialized list object
+ * \param[in] idx Index of node to retrieve
+ * \return node at index or NULL if invalid index
+ */
+ares__llist_node_t *ares__llist_node_idx(ares__llist_t *list, size_t idx);
+
/*! Obtain next node in respect to specified node
*
* \param[in] node Node referenced
@@ -136,6 +144,7 @@ ares__llist_node_t *ares__llist_node_next(ares__llist_node_t *node);
*/
ares__llist_node_t *ares__llist_node_prev(ares__llist_node_t *node);
+
/*! Obtain value from node
*
* \param[in] node Node referenced
@@ -150,6 +159,12 @@ void *ares__llist_node_val(ares__llist_node_t *node);
*/
size_t ares__llist_len(const ares__llist_t *list);
+/*! Clear all entries in the list, but don't destroy the list object.
+ *
+ * \param[in] list Initialized list object
+ */
+void ares__llist_clear(ares__llist_t *list);
+
/*! Obtain list object from referenced node
*
* \param[in] node Node referenced
diff --git a/contrib/libs/c-ares/src/lib/ares__slist.c b/contrib/libs/c-ares/src/lib/dsa/ares__slist.c
index 5b80984355..f0e3f8b14a 100644
--- a/contrib/libs/c-ares/src/lib/ares__slist.c
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__slist.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares__slist.h"
@@ -206,7 +204,7 @@ ares__slist_node_t *ares__slist_insert(ares__slist_t *list, void *val)
node = ares_malloc_zero(sizeof(*node));
if (node == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
node->data = val;
@@ -218,12 +216,12 @@ ares__slist_node_t *ares__slist_insert(ares__slist_t *list, void *val)
/* Allocate array of next and prev nodes for linking each level */
node->next = ares_malloc_zero(sizeof(*node->next) * node->levels);
if (node->next == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
node->prev = ares_malloc_zero(sizeof(*node->prev) * node->levels);
if (node->prev == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* If the number of levels is greater than we currently support in the slist,
@@ -233,7 +231,7 @@ ares__slist_node_t *ares__slist_insert(ares__slist_t *list, void *val)
ares_realloc_zero(list->head, sizeof(*list->head) * list->levels,
sizeof(*list->head) * node->levels);
if (ptr == NULL) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
list->head = ptr;
@@ -246,6 +244,7 @@ ares__slist_node_t *ares__slist_insert(ares__slist_t *list, void *val)
return node;
+/* LCOV_EXCL_START: OutOfMemory */
fail:
if (node) {
ares_free(node->prev);
@@ -253,6 +252,7 @@ fail:
ares_free(node);
}
return NULL;
+ /* LCOV_EXCL_STOP */
}
static void ares__slist_node_pop(ares__slist_node_t *node)
diff --git a/contrib/libs/c-ares/src/lib/ares__slist.h b/contrib/libs/c-ares/src/lib/dsa/ares__slist.h
index 26af88fa78..26af88fa78 100644
--- a/contrib/libs/c-ares/src/lib/ares__slist.h
+++ b/contrib/libs/c-ares/src/lib/dsa/ares__slist.h
diff --git a/contrib/libs/c-ares/src/lib/ares_event.h b/contrib/libs/c-ares/src/lib/event/ares_event.h
index f5d044d2a6..317731fc42 100644
--- a/contrib/libs/c-ares/src/lib/ares_event.h
+++ b/contrib/libs/c-ares/src/lib/event/ares_event.h
@@ -26,8 +26,6 @@
#ifndef __ARES__EVENT_H
#define __ARES__EVENT_H
-#include "ares_setup.h"
-
struct ares_event;
typedef struct ares_event ares_event_t;
diff --git a/contrib/libs/c-ares/src/lib/ares_event_configchg.c b/contrib/libs/c-ares/src/lib/event/ares_event_configchg.c
index c7bc9ffd58..030c76c69c 100644
--- a/contrib/libs/c-ares/src/lib/ares_event_configchg.c
+++ b/contrib/libs/c-ares/src/lib/event/ares_event_configchg.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares_event.h"
@@ -54,7 +52,7 @@ struct ares_event_configchg {
void ares_event_configchg_destroy(ares_event_configchg_t *configchg)
{
if (configchg == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Tell event system to stop monitoring for changes. This will cause the
@@ -67,7 +65,7 @@ static void ares_event_configchg_free(void *data)
{
ares_event_configchg_t *configchg = data;
if (configchg == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (configchg->inotify_fd >= 0) {
@@ -142,22 +140,22 @@ ares_status_t ares_event_configchg_init(ares_event_configchg_t **configchg,
c = ares_malloc_zero(sizeof(*c));
if (c == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
c->e = e;
c->inotify_fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
if (c->inotify_fd == -1) {
- status = ARES_ESERVFAIL;
- goto done;
+ status = ARES_ESERVFAIL; /* LCOV_EXCL_LINE: UntestablePath */
+ goto done; /* LCOV_EXCL_LINE: UntestablePath */
}
/* We need to monitor /etc/resolv.conf, /etc/nsswitch.conf */
if (inotify_add_watch(c->inotify_fd, "/etc",
IN_CREATE | IN_MODIFY | IN_MOVED_TO | IN_ONLYDIR) ==
-1) {
- status = ARES_ESERVFAIL;
- goto done;
+ status = ARES_ESERVFAIL; /* LCOV_EXCL_LINE: UntestablePath */
+ goto done; /* LCOV_EXCL_LINE: UntestablePath */
}
status =
@@ -173,7 +171,7 @@ done:
return status;
}
-#elif defined(_WIN32)
+#elif defined(USE_WINSOCK)
# include <winsock2.h>
# include <iphlpapi.h>
@@ -182,31 +180,68 @@ done:
struct ares_event_configchg {
HANDLE ifchg_hnd;
+ HKEY regip4;
+ HANDLE regip4_event;
+ HANDLE regip4_wait;
+ HKEY regip6;
+ HANDLE regip6_event;
+ HANDLE regip6_wait;
ares_event_thread_t *e;
};
void ares_event_configchg_destroy(ares_event_configchg_t *configchg)
{
-# ifdef __WATCOMC__
- /* Not supported */
-# else
if (configchg == NULL) {
return;
}
+# ifdef HAVE_NOTIFYIPINTERFACECHANGE
if (configchg->ifchg_hnd != NULL) {
CancelMibChangeNotify2(configchg->ifchg_hnd);
configchg->ifchg_hnd = NULL;
}
+# endif
+
+# ifdef HAVE_REGISTERWAITFORSINGLEOBJECT
+ if (configchg->regip4_wait != NULL) {
+ UnregisterWait(configchg->regip4_wait);
+ configchg->regip4_wait = NULL;
+ }
- ares_free(configchg);
+ if (configchg->regip6_wait != NULL) {
+ UnregisterWait(configchg->regip6_wait);
+ configchg->regip6_wait = NULL;
+ }
+
+ if (configchg->regip4 != NULL) {
+ RegCloseKey(configchg->regip4);
+ configchg->regip4 = NULL;
+ }
+
+ if (configchg->regip6 != NULL) {
+ RegCloseKey(configchg->regip6);
+ configchg->regip6 = NULL;
+ }
+
+ if (configchg->regip4_event != NULL) {
+ CloseHandle(configchg->regip4_event);
+ configchg->regip4_event = NULL;
+ }
+
+ if (configchg->regip6_event != NULL) {
+ CloseHandle(configchg->regip6_event);
+ configchg->regip6_event = NULL;
+ }
# endif
+
+ ares_free(configchg);
}
-# ifndef __WATCOMC__
-static void ares_event_configchg_cb(PVOID CallerContext,
- PMIB_IPINTERFACE_ROW Row,
- MIB_NOTIFICATION_TYPE NotificationType)
+
+# ifdef HAVE_NOTIFYIPINTERFACECHANGE
+static void NETIOAPI_API_
+ ares_event_configchg_ip_cb(PVOID CallerContext, PMIB_IPINTERFACE_ROW Row,
+ MIB_NOTIFICATION_TYPE NotificationType)
{
ares_event_configchg_t *configchg = CallerContext;
(void)Row;
@@ -215,43 +250,130 @@ static void ares_event_configchg_cb(PVOID CallerContext,
}
# endif
+static ares_bool_t
+ ares_event_configchg_regnotify(ares_event_configchg_t *configchg)
+{
+# ifdef HAVE_REGISTERWAITFORSINGLEOBJECT
+# if defined(__WATCOMC__) && !defined(REG_NOTIFY_THREAD_AGNOSTIC)
+# define REG_NOTIFY_THREAD_AGNOSTIC 0x10000000L
+# endif
+ DWORD flags = REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET |
+ REG_NOTIFY_THREAD_AGNOSTIC;
+
+ if (RegNotifyChangeKeyValue(configchg->regip4, TRUE, flags,
+ configchg->regip4_event, TRUE) != ERROR_SUCCESS) {
+ return ARES_FALSE;
+ }
+
+ if (RegNotifyChangeKeyValue(configchg->regip6, TRUE, flags,
+ configchg->regip6_event, TRUE) != ERROR_SUCCESS) {
+ return ARES_FALSE;
+ }
+# else
+ (void)configchg;
+# endif
+ return ARES_TRUE;
+}
+
+static VOID CALLBACK ares_event_configchg_reg_cb(PVOID lpParameter,
+ BOOLEAN TimerOrWaitFired)
+{
+ ares_event_configchg_t *configchg = lpParameter;
+ (void)TimerOrWaitFired;
+
+ ares_reinit(configchg->e->channel);
+
+ /* Re-arm, as its single-shot. However, we don't know which one needs to
+ * be re-armed, so we just do both */
+ ares_event_configchg_regnotify(configchg);
+}
ares_status_t ares_event_configchg_init(ares_event_configchg_t **configchg,
ares_event_thread_t *e)
{
-# ifdef __WATCOMC__
- return ARES_ENOTIMP;
-# else
- ares_status_t status = ARES_SUCCESS;
+ ares_status_t status = ARES_SUCCESS;
+ ares_event_configchg_t *c = NULL;
- *configchg = ares_malloc_zero(sizeof(**configchg));
- if (*configchg == NULL) {
+ c = ares_malloc_zero(sizeof(**configchg));
+ if (c == NULL) {
return ARES_ENOMEM;
}
- (*configchg)->e = e;
+ c->e = e;
+# ifdef HAVE_NOTIFYIPINTERFACECHANGE
/* NOTE: If a user goes into the control panel and changes the network
* adapter DNS addresses manually, this will NOT trigger a notification.
* We've also tried listening on NotifyUnicastIpAddressChange(), but
* that didn't get triggered either.
*/
+ if (NotifyIpInterfaceChange(AF_UNSPEC, ares_event_configchg_ip_cb, c, FALSE,
+ &c->ifchg_hnd) != NO_ERROR) {
+ status = ARES_ESERVFAIL;
+ goto done;
+ }
+# endif
+
+# ifdef HAVE_REGISTERWAITFORSINGLEOBJECT
+ /* Monitor HKLM\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters\Interfaces
+ * and HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
+ * for changes via RegNotifyChangeKeyValue() */
+ if (RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces",
+ 0, KEY_NOTIFY, &c->regip4) != ERROR_SUCCESS) {
+ status = ARES_ESERVFAIL;
+ goto done;
+ }
+
+ if (RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Services\\Tcpip6\\Parameters\\Interfaces",
+ 0, KEY_NOTIFY, &c->regip6) != ERROR_SUCCESS) {
+ status = ARES_ESERVFAIL;
+ goto done;
+ }
+
+ c->regip4_event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (c->regip4_event == NULL) {
+ status = ARES_ESERVFAIL;
+ goto done;
+ }
+
+ c->regip6_event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (c->regip6_event == NULL) {
+ status = ARES_ESERVFAIL;
+ goto done;
+ }
+
+ if (!RegisterWaitForSingleObject(&c->regip4_wait, c->regip4_event,
+ ares_event_configchg_reg_cb, c, INFINITE,
+ WT_EXECUTEDEFAULT)) {
+ status = ARES_ESERVFAIL;
+ goto done;
+ }
+
+ if (!RegisterWaitForSingleObject(&c->regip6_wait, c->regip6_event,
+ ares_event_configchg_reg_cb, c, INFINITE,
+ WT_EXECUTEDEFAULT)) {
+ status = ARES_ESERVFAIL;
+ goto done;
+ }
+# endif
- if (NotifyIpInterfaceChange(
- AF_UNSPEC, (PIPINTERFACE_CHANGE_CALLBACK)ares_event_configchg_cb,
- *configchg, FALSE, &(*configchg)->ifchg_hnd) != NO_ERROR) {
+ if (!ares_event_configchg_regnotify(c)) {
status = ARES_ESERVFAIL;
goto done;
}
done:
if (status != ARES_SUCCESS) {
- ares_event_configchg_destroy(*configchg);
- *configchg = NULL;
+ ares_event_configchg_destroy(c);
+ } else {
+ *configchg = c;
}
return status;
-# endif
}
#elif defined(__APPLE__)
@@ -260,6 +382,7 @@ done:
# include <unistd.h>
# include <notify.h>
# include <dlfcn.h>
+# include <fcntl.h>
struct ares_event_configchg {
int fd;
@@ -333,6 +456,13 @@ ares_status_t ares_event_configchg_init(ares_event_configchg_t **configchg,
const char *(*pdns_configuration_notify_key)(void) = NULL;
const char *notify_key = NULL;
int flags;
+ size_t i;
+ const char *searchlibs[] = {
+ "/usr/lib/libSystem.dylib",
+ "/System/Library/Frameworks/SystemConfiguration.framework/"
+ "SystemConfiguration",
+ NULL
+ };
*configchg = ares_malloc_zero(sizeof(**configchg));
if (*configchg == NULL) {
@@ -340,13 +470,23 @@ ares_status_t ares_event_configchg_init(ares_event_configchg_t **configchg,
}
/* Load symbol as it isn't normally public */
- handle = dlopen("/usr/lib/libSystem.dylib", RTLD_LAZY | RTLD_NOLOAD);
- if (handle == NULL) {
- status = ARES_ESERVFAIL;
- goto done;
- }
+ for (i = 0; searchlibs[i] != NULL; i++) {
+ handle = dlopen(searchlibs[i], RTLD_LAZY);
+ if (handle == NULL) {
+ /* Fail, loop! */
+ continue;
+ }
- pdns_configuration_notify_key = dlsym(handle, "dns_configuration_notify_key");
+ pdns_configuration_notify_key =
+ (const char *(*)(void))dlsym(handle, "dns_configuration_notify_key");
+ if (pdns_configuration_notify_key != NULL) {
+ break;
+ }
+
+ /* Fail, loop! */
+ dlclose(handle);
+ handle = NULL;
+ }
if (pdns_configuration_notify_key == NULL) {
status = ARES_ESERVFAIL;
@@ -388,7 +528,7 @@ done:
return status;
}
-#elif defined(HAVE_STAT)
+#elif defined(HAVE_STAT) && !defined(_WIN32)
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
@@ -415,9 +555,14 @@ static ares_status_t config_change_check(ares__htable_strvp_t *filestat,
const char *resolvconf_path)
{
size_t i;
- const char *configfiles[] = { resolvconf_path, "/etc/nsswitch.conf",
- "/etc/netsvc.conf", "/etc/svc.conf", NULL };
- ares_bool_t changed = ARES_FALSE;
+ const char *configfiles[5];
+ ares_bool_t changed = ARES_FALSE;
+
+ configfiles[0] = resolvconf_path;
+ configfiles[1] = "/etc/nsswitch.conf";
+ configfiles[2] = "/etc/netsvc.conf";
+ configfiles[3] = "/etc/svc.conf";
+ configfiles[4] = NULL;
for (i = 0; configfiles[i] != NULL; i++) {
fileinfo_t *fi = ares__htable_strvp_get_direct(filestat, configfiles[i]);
diff --git a/contrib/libs/c-ares/src/lib/ares_event_epoll.c b/contrib/libs/c-ares/src/lib/event/ares_event_epoll.c
index 78cbbc368c..5eb25cccc9 100644
--- a/contrib/libs/c-ares/src/lib/ares_event_epoll.c
+++ b/contrib/libs/c-ares/src/lib/event/ares_event_epoll.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares_event.h"
@@ -46,12 +44,12 @@ static void ares_evsys_epoll_destroy(ares_event_thread_t *e)
ares_evsys_epoll_t *ep = NULL;
if (e == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ep = e->ev_sys_data;
if (ep == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (ep->epoll_fd != -1) {
@@ -68,25 +66,21 @@ static ares_bool_t ares_evsys_epoll_init(ares_event_thread_t *e)
ep = ares_malloc_zero(sizeof(*ep));
if (ep == NULL) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: OutOfMemory */
}
e->ev_sys_data = ep;
- ep->epoll_fd = epoll_create1(0);
+ ep->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (ep->epoll_fd == -1) {
- ares_evsys_epoll_destroy(e);
- return ARES_FALSE;
+ ares_evsys_epoll_destroy(e); /* LCOV_EXCL_LINE: UntestablePath */
+ return ARES_FALSE; /* LCOV_EXCL_LINE: UntestablePath */
}
-# ifdef FD_CLOEXEC
- fcntl(ep->epoll_fd, F_SETFD, FD_CLOEXEC);
-# endif
-
e->ev_signal = ares_pipeevent_create(e);
if (e->ev_signal == NULL) {
- ares_evsys_epoll_destroy(e);
- return ARES_FALSE;
+ ares_evsys_epoll_destroy(e); /* LCOV_EXCL_LINE: UntestablePath */
+ return ARES_FALSE; /* LCOV_EXCL_LINE: UntestablePath */
}
return ARES_TRUE;
@@ -108,7 +102,7 @@ static ares_bool_t ares_evsys_epoll_event_add(ares_event_t *event)
epev.events |= EPOLLOUT;
}
if (epoll_ctl(ep->epoll_fd, EPOLL_CTL_ADD, event->fd, &epev) != 0) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: UntestablePath */
}
return ARES_TRUE;
}
@@ -158,7 +152,7 @@ static size_t ares_evsys_epoll_wait(ares_event_thread_t *e,
rv = epoll_wait(ep->epoll_fd, events, (int)nevents,
(timeout_ms == 0) ? -1 : (int)timeout_ms);
if (rv < 0) {
- return 0;
+ return 0; /* LCOV_EXCL_LINE: UntestablePath */
}
nevents = (size_t)rv;
@@ -170,7 +164,7 @@ static size_t ares_evsys_epoll_wait(ares_event_thread_t *e,
ev = ares__htable_asvp_get_direct(e->ev_sock_handles,
(ares_socket_t)events[i].data.fd);
if (ev == NULL || ev->cb == NULL) {
- continue;
+ continue; /* LCOV_EXCL_LINE: DefensiveCoding */
}
cnt++;
diff --git a/contrib/libs/c-ares/src/lib/ares_event_kqueue.c b/contrib/libs/c-ares/src/lib/event/ares_event_kqueue.c
index 7e2c60abf5..1c35c14f16 100644
--- a/contrib/libs/c-ares/src/lib/ares_event_kqueue.c
+++ b/contrib/libs/c-ares/src/lib/event/ares_event_kqueue.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares_event.h"
@@ -95,7 +93,7 @@ static ares_bool_t ares_evsys_kqueue_init(ares_event_thread_t *e)
kq->nchanges_alloc = 8;
kq->changelist =
- ares_malloc_zero(sizeof(*kq->changelist) * kq->nchanges_alloc);
+ ares_malloc_zero(kq->nchanges_alloc * sizeof(*kq->changelist));
if (kq->changelist == NULL) {
ares_evsys_kqueue_destroy(e);
return ARES_FALSE;
@@ -125,8 +123,9 @@ static void ares_evsys_kqueue_enqueue(ares_evsys_kqueue_t *kq, int fd,
if (kq->nchanges > kq->nchanges_alloc) {
kq->nchanges_alloc <<= 1;
- kq->changelist = ares_realloc_zero(kq->changelist, kq->nchanges_alloc >> 1,
- kq->nchanges_alloc);
+ kq->changelist = ares_realloc_zero(
+ kq->changelist, (kq->nchanges_alloc >> 1) * sizeof(*kq->changelist),
+ kq->nchanges_alloc * sizeof(*kq->changelist));
}
EV_SET(&kq->changelist[idx], fd, filter, flags, 0, 0, 0);
@@ -197,7 +196,7 @@ static size_t ares_evsys_kqueue_wait(ares_event_thread_t *e,
size_t cnt = 0;
if (timeout_ms != 0) {
- ts.tv_sec = timeout_ms / 1000;
+ ts.tv_sec = (time_t)timeout_ms / 1000;
ts.tv_nsec = (timeout_ms % 1000) * 1000 * 1000;
timeout = &ts;
}
diff --git a/contrib/libs/c-ares/src/lib/ares_event_poll.c b/contrib/libs/c-ares/src/lib/event/ares_event_poll.c
index a06c6e3fc4..42ffd912e9 100644
--- a/contrib/libs/c-ares/src/lib/ares_event_poll.c
+++ b/contrib/libs/c-ares/src/lib/event/ares_event_poll.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares_event.h"
#ifdef HAVE_POLL_H
@@ -37,7 +35,7 @@ static ares_bool_t ares_evsys_poll_init(ares_event_thread_t *e)
{
e->ev_signal = ares_pipeevent_create(e);
if (e->ev_signal == NULL) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: UntestablePath */
}
return ARES_TRUE;
}
@@ -78,7 +76,7 @@ static size_t ares_evsys_poll_wait(ares_event_thread_t *e,
if (fdlist != NULL && num_fds) {
pollfd = ares_malloc_zero(sizeof(*pollfd) * num_fds);
if (pollfd == NULL) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
for (i = 0; i < num_fds; i++) {
const ares_event_t *ev =
@@ -111,7 +109,7 @@ static size_t ares_evsys_poll_wait(ares_event_thread_t *e,
ev = ares__htable_asvp_get_direct(e->ev_sock_handles, pollfd[i].fd);
if (ev == NULL || ev->cb == NULL) {
- continue;
+ continue; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (pollfd[i].revents & (POLLERR | POLLHUP | POLLIN)) {
diff --git a/contrib/libs/c-ares/src/lib/ares_event_select.c b/contrib/libs/c-ares/src/lib/event/ares_event_select.c
index 57a4271ea7..e1266ea990 100644
--- a/contrib/libs/c-ares/src/lib/ares_event_select.c
+++ b/contrib/libs/c-ares/src/lib/event/ares_event_select.c
@@ -29,8 +29,6 @@
* anyhow */
#define FD_SETSIZE 4096
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares_event.h"
#ifdef HAVE_SYS_SELECT_H
@@ -45,7 +43,7 @@ static ares_bool_t ares_evsys_select_init(ares_event_thread_t *e)
{
e->ev_signal = ares_pipeevent_create(e);
if (e->ev_signal == NULL) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: UntestablePath */
}
return ARES_TRUE;
}
@@ -83,12 +81,14 @@ static size_t ares_evsys_select_wait(ares_event_thread_t *e,
size_t i;
fd_set read_fds;
fd_set write_fds;
+ fd_set except_fds;
int nfds = 0;
struct timeval tv;
struct timeval *tout = NULL;
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
+ FD_ZERO(&except_fds);
for (i = 0; i < num_fds; i++) {
const ares_event_t *ev =
@@ -99,6 +99,7 @@ static size_t ares_evsys_select_wait(ares_event_thread_t *e,
if (ev->flags & ARES_EVENT_FLAG_WRITE) {
FD_SET(ev->fd, &write_fds);
}
+ FD_SET(ev->fd, &except_fds);
if (ev->fd + 1 > nfds) {
nfds = ev->fd + 1;
}
@@ -110,7 +111,7 @@ static size_t ares_evsys_select_wait(ares_event_thread_t *e,
tout = &tv;
}
- rv = select(nfds, &read_fds, &write_fds, NULL, tout);
+ rv = select(nfds, &read_fds, &write_fds, &except_fds, tout);
if (rv > 0) {
for (i = 0; i < num_fds; i++) {
ares_event_t *ev;
@@ -118,10 +119,10 @@ static size_t ares_evsys_select_wait(ares_event_thread_t *e,
ev = ares__htable_asvp_get_direct(e->ev_sock_handles, fdlist[i]);
if (ev == NULL || ev->cb == NULL) {
- continue;
+ continue; /* LCOV_EXCL_LINE: DefensiveCoding */
}
- if (FD_ISSET(fdlist[i], &read_fds)) {
+ if (FD_ISSET(fdlist[i], &read_fds) || FD_ISSET(fdlist[i], &except_fds)) {
flags |= ARES_EVENT_FLAG_READ;
}
diff --git a/contrib/libs/c-ares/src/lib/ares_event_thread.c b/contrib/libs/c-ares/src/lib/event/ares_event_thread.c
index d9d904f29b..8b332e9b01 100644
--- a/contrib/libs/c-ares/src/lib/ares_event_thread.c
+++ b/contrib/libs/c-ares/src/lib/event/ares_event_thread.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares_event.h"
@@ -32,7 +30,7 @@ static void ares_event_destroy_cb(void *arg)
{
ares_event_t *event = arg;
if (event == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Unregister from the event thread if it was registered with one */
@@ -49,6 +47,23 @@ static void ares_event_destroy_cb(void *arg)
ares_free(event);
}
+static void ares_event_signal(const ares_event_t *event)
+{
+ if (event == NULL || event->signal_cb == NULL) {
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
+ }
+ event->signal_cb(event);
+}
+
+static void ares_event_thread_wake(const ares_event_thread_t *e)
+{
+ if (e == NULL) {
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
+ }
+
+ ares_event_signal(e->ev_signal);
+}
+
/* See if a pending update already exists. We don't want to enqueue multiple
* updates for the same event handle. Right now this is O(n) based on number
* of updates already enqueued. In the future, it might make sense to make
@@ -88,9 +103,10 @@ ares_status_t ares_event_update(ares_event_t **event, ares_event_thread_t *e,
ares_event_signal_cb_t signal_cb)
{
ares_event_t *ev = NULL;
+ ares_status_t status;
if (e == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Callback must be specified if not a removal event. */
@@ -118,18 +134,22 @@ ares_status_t ares_event_update(ares_event_t **event, ares_event_thread_t *e,
/* That's all the validation we can really do */
+ ares__thread_mutex_lock(e->mutex);
+
/* See if we have a queued update already */
ev = ares_event_update_find(e, fd, data);
if (ev == NULL) {
/* Allocate a new one */
ev = ares_malloc_zero(sizeof(*ev));
if (ev == NULL) {
- return ARES_ENOMEM;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
if (ares__llist_insert_last(e->ev_updates, ev) == NULL) {
- ares_free(ev);
- return ARES_ENOMEM;
+ ares_free(ev); /* LCOV_EXCL_LINE: OutOfMemory */
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -152,24 +172,17 @@ ares_status_t ares_event_update(ares_event_t **event, ares_event_thread_t *e,
*event = ev;
}
- return ARES_SUCCESS;
-}
+ status = ARES_SUCCESS;
-static void ares_event_signal(const ares_event_t *event)
-{
- if (event == NULL || event->signal_cb == NULL) {
- return;
+done:
+ if (status == ARES_SUCCESS) {
+ /* Wake event thread if successful so it can pull the updates */
+ ares_event_thread_wake(e);
}
- event->signal_cb(event);
-}
-static void ares_event_thread_wake(const ares_event_thread_t *e)
-{
- if (e == NULL) {
- return;
- }
+ ares__thread_mutex_unlock(e->mutex);
- ares_event_signal(e->ev_signal);
+ return status;
}
static void ares_event_thread_process_fd(ares_event_thread_t *e,
@@ -197,15 +210,10 @@ static void ares_event_thread_sockstate_cb(void *data, ares_socket_t socket_fd,
flags |= ARES_EVENT_FLAG_WRITE;
}
- /* Update channel fd */
- ares__thread_mutex_lock(e->mutex);
+ /* Update channel fd. This function will lock e->mutex and also wake the
+ * event thread to process the update */
ares_event_update(NULL, e, flags, ares_event_thread_process_fd, socket_fd,
NULL, NULL, NULL);
-
- /* Wake the event thread so it properly enqueues any updates */
- ares_event_thread_wake(e);
-
- ares__thread_mutex_unlock(e->mutex);
}
static void ares_event_process_updates(ares_event_thread_t *e)
@@ -264,6 +272,35 @@ static void ares_event_process_updates(ares_event_thread_t *e)
}
}
+static void ares_event_thread_cleanup(ares_event_thread_t *e)
+{
+ /* Manually free any updates that weren't processed */
+ if (e->ev_updates != NULL) {
+ ares__llist_node_t *node;
+
+ while ((node = ares__llist_node_first(e->ev_updates)) != NULL) {
+ ares_event_destroy_cb(ares__llist_node_claim(node));
+ }
+ ares__llist_destroy(e->ev_updates);
+ e->ev_updates = NULL;
+ }
+
+ if (e->ev_sock_handles != NULL) {
+ ares__htable_asvp_destroy(e->ev_sock_handles);
+ e->ev_sock_handles = NULL;
+ }
+
+ if (e->ev_cust_handles != NULL) {
+ ares__htable_vpvp_destroy(e->ev_cust_handles);
+ e->ev_cust_handles = NULL;
+ }
+
+ if (e->ev_sys != NULL && e->ev_sys->destroy != NULL) {
+ e->ev_sys->destroy(e);
+ e->ev_sys = NULL;
+ }
+}
+
static void *ares_event_thread(void *arg)
{
ares_event_thread_t *e = arg;
@@ -274,16 +311,19 @@ static void *ares_event_thread(void *arg)
const struct timeval *tvout;
unsigned long timeout_ms = 0; /* 0 = unlimited */
+ ares_event_process_updates(e);
+
+ /* Don't hold a mutex while waiting on events or calling into anything
+ * that might require a c-ares channel lock since a callback could be
+ * triggered cross-thread */
+ ares__thread_mutex_unlock(e->mutex);
+
tvout = ares_timeout(e->channel, NULL, &tv);
if (tvout != NULL) {
timeout_ms =
(unsigned long)((tvout->tv_sec * 1000) + (tvout->tv_usec / 1000) + 1);
}
- ares_event_process_updates(e);
-
- /* Don't hold a mutex while waiting on events */
- ares__thread_mutex_unlock(e->mutex);
e->ev_sys->wait(e, timeout_ms);
/* Each iteration should do timeout processing */
@@ -295,14 +335,16 @@ static void *ares_event_thread(void *arg)
ares__thread_mutex_lock(e->mutex);
}
+ /* Lets cleanup while we're in the thread itself */
+ ares_event_thread_cleanup(e);
+
ares__thread_mutex_unlock(e->mutex);
+
return NULL;
}
static void ares_event_thread_destroy_int(ares_event_thread_t *e)
{
- ares__llist_node_t *node;
-
/* Wake thread and tell it to shutdown if it exists */
ares__thread_mutex_lock(e->mutex);
if (e->isup) {
@@ -313,26 +355,14 @@ static void ares_event_thread_destroy_int(ares_event_thread_t *e)
/* Wait for thread to shutdown */
if (e->thread) {
- ares__thread_join(e->thread, NULL);
+ void *rv = NULL;
+ ares__thread_join(e->thread, &rv);
e->thread = NULL;
}
- /* Manually free any updates that weren't processed */
- while ((node = ares__llist_node_first(e->ev_updates)) != NULL) {
- ares_event_destroy_cb(ares__llist_node_claim(node));
- }
- ares__llist_destroy(e->ev_updates);
- e->ev_updates = NULL;
-
- ares__htable_asvp_destroy(e->ev_sock_handles);
- e->ev_sock_handles = NULL;
-
- ares__htable_vpvp_destroy(e->ev_cust_handles);
- e->ev_cust_handles = NULL;
-
- if (e->ev_sys && e->ev_sys->destroy) {
- e->ev_sys->destroy(e);
- }
+ /* If the event thread ever got to the point of starting, this is a no-op
+ * as it runs this same cleanup when it shuts down */
+ ares_event_thread_cleanup(e);
ares__thread_mutex_destroy(e->mutex);
e->mutex = NULL;
@@ -345,17 +375,19 @@ void ares_event_thread_destroy(ares_channel_t *channel)
ares_event_thread_t *e = channel->sock_state_cb_data;
if (e == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares_event_thread_destroy_int(e);
+ channel->sock_state_cb_data = NULL;
+ channel->sock_state_cb = NULL;
}
static const ares_event_sys_t *ares_event_fetch_sys(ares_evsys_t evsys)
{
switch (evsys) {
case ARES_EVSYS_WIN32:
-#if defined(_WIN32)
+#if defined(USE_WINSOCK)
return &ares_evsys_win32;
#else
return NULL;
@@ -391,22 +423,23 @@ static const ares_event_sys_t *ares_event_fetch_sys(ares_evsys_t evsys)
/* case ARES_EVSYS_DEFAULT: */
default:
-#if defined(_WIN32)
- return &ares_evsys_win32;
+ break;
+ }
+
+ /* default */
+#if defined(USE_WINSOCK)
+ return &ares_evsys_win32;
#elif defined(HAVE_KQUEUE)
- return &ares_evsys_kqueue;
+ return &ares_evsys_kqueue;
#elif defined(HAVE_EPOLL)
- return &ares_evsys_epoll;
+ return &ares_evsys_epoll;
#elif defined(HAVE_POLL)
- return &ares_evsys_poll;
+ return &ares_evsys_poll;
#elif defined(HAVE_PIPE)
- return &ares_evsys_select;
+ return &ares_evsys_select;
#else
- break;
-#endif
- }
-
return NULL;
+#endif
}
ares_status_t ares_event_thread_init(ares_channel_t *channel)
@@ -415,49 +448,51 @@ ares_status_t ares_event_thread_init(ares_channel_t *channel)
e = ares_malloc_zero(sizeof(*e));
if (e == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
e->mutex = ares__thread_mutex_create();
if (e->mutex == NULL) {
- ares_event_thread_destroy_int(e);
- return ARES_ENOMEM;
+ ares_event_thread_destroy_int(e); /* LCOV_EXCL_LINE: OutOfMemory */
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
e->ev_updates = ares__llist_create(NULL);
if (e->ev_updates == NULL) {
- ares_event_thread_destroy_int(e);
- return ARES_ENOMEM;
+ ares_event_thread_destroy_int(e); /* LCOV_EXCL_LINE: OutOfMemory */
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
e->ev_sock_handles = ares__htable_asvp_create(ares_event_destroy_cb);
if (e->ev_sock_handles == NULL) {
- ares_event_thread_destroy_int(e);
- return ARES_ENOMEM;
+ ares_event_thread_destroy_int(e); /* LCOV_EXCL_LINE: OutOfMemory */
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
e->ev_cust_handles = ares__htable_vpvp_create(NULL, ares_event_destroy_cb);
if (e->ev_cust_handles == NULL) {
- ares_event_thread_destroy_int(e);
- return ARES_ENOMEM;
+ ares_event_thread_destroy_int(e); /* LCOV_EXCL_LINE: OutOfMemory */
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
e->channel = channel;
e->isup = ARES_TRUE;
e->ev_sys = ares_event_fetch_sys(channel->evsys);
if (e->ev_sys == NULL) {
- ares_event_thread_destroy_int(e);
- return ARES_ENOTIMP;
+ ares_event_thread_destroy_int(e); /* LCOV_EXCL_LINE: UntestablePath */
+ return ARES_ENOTIMP; /* LCOV_EXCL_LINE: UntestablePath */
}
channel->sock_state_cb = ares_event_thread_sockstate_cb;
channel->sock_state_cb_data = e;
if (!e->ev_sys->init(e)) {
+ /* LCOV_EXCL_START: UntestablePath */
ares_event_thread_destroy_int(e);
channel->sock_state_cb = NULL;
channel->sock_state_cb_data = NULL;
return ARES_ESERVFAIL;
+ /* LCOV_EXCL_STOP */
}
/* Before starting the thread, process any possible events the initialization
@@ -469,10 +504,12 @@ ares_status_t ares_event_thread_init(ares_channel_t *channel)
/* Start thread */
if (ares__thread_create(&e->thread, ares_event_thread, e) != ARES_SUCCESS) {
+ /* LCOV_EXCL_START: UntestablePath */
ares_event_thread_destroy_int(e);
channel->sock_state_cb = NULL;
channel->sock_state_cb_data = NULL;
return ARES_ESERVFAIL;
+ /* LCOV_EXCL_STOP */
}
return ARES_SUCCESS;
diff --git a/contrib/libs/c-ares/src/lib/ares_event_wake_pipe.c b/contrib/libs/c-ares/src/lib/event/ares_event_wake_pipe.c
index a2cd6f609a..282d013dc6 100644
--- a/contrib/libs/c-ares/src/lib/ares_event_wake_pipe.c
+++ b/contrib/libs/c-ares/src/lib/event/ares_event_wake_pipe.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares_event.h"
#ifdef HAVE_UNISTD_H
@@ -60,7 +58,7 @@ static ares_pipeevent_t *ares_pipeevent_init(void)
{
ares_pipeevent_t *p = ares_malloc_zero(sizeof(*p));
if (p == NULL) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
}
p->filedes[0] = -1;
@@ -68,8 +66,8 @@ static ares_pipeevent_t *ares_pipeevent_init(void)
# ifdef HAVE_PIPE2
if (pipe2(p->filedes, O_NONBLOCK | O_CLOEXEC) != 0) {
- ares_pipeevent_destroy(p);
- return NULL;
+ ares_pipeevent_destroy(p); /* LCOV_EXCL_LINE: UntestablePath */
+ return NULL; /* LCOV_EXCL_LINE: UntestablePath */
}
# else
if (pipe(p->filedes) != 0) {
@@ -113,7 +111,7 @@ static void ares_pipeevent_signal(const ares_event_t *e)
const ares_pipeevent_t *p;
if (e == NULL || e->data == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
p = e->data;
@@ -131,7 +129,7 @@ static void ares_pipeevent_cb(ares_event_thread_t *e, ares_socket_t fd,
(void)flags;
if (data == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
p = data;
@@ -156,8 +154,8 @@ ares_event_t *ares_pipeevent_create(ares_event_thread_t *e)
p->filedes[0], p, ares_pipeevent_destroy_cb,
ares_pipeevent_signal);
if (status != ARES_SUCCESS) {
- ares_pipeevent_destroy(p);
- return NULL;
+ ares_pipeevent_destroy(p); /* LCOV_EXCL_LINE: DefensiveCoding */
+ return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
}
return event;
diff --git a/contrib/libs/c-ares/src/lib/event/ares_event_win32.c b/contrib/libs/c-ares/src/lib/event/ares_event_win32.c
new file mode 100644
index 0000000000..0b7e535bbb
--- /dev/null
+++ b/contrib/libs/c-ares/src/lib/event/ares_event_win32.c
@@ -0,0 +1,976 @@
+/* MIT License
+ *
+ * Copyright (c) 2024 Brad House
+ *
+ * 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
+ */
+
+/* Uses an anonymous union */
+#if defined(__clang__) || defined(__GNUC__)
+# pragma GCC diagnostic push
+# if defined(__clang__)
+# pragma GCC diagnostic ignored "-Wc11-extensions"
+# else
+# pragma GCC diagnostic ignored "-Wpedantic"
+# endif
+#endif
+
+#include "ares_private.h"
+#include "ares_event.h"
+#include "ares_event_win32.h"
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#if defined(USE_WINSOCK)
+
+/* IMPLEMENTATION NOTES
+ * ====================
+ *
+ * This implementation uses some undocumented functionality within Windows for
+ * monitoring sockets. The Ancillary Function Driver (AFD) is the low level
+ * implementation that Winsock2 sits on top of. Winsock2 unfortunately does
+ * not expose the equivalent of epoll() or kqueue(), but it is possible to
+ * access AFD directly and use along with IOCP to simulate the functionality.
+ * We want to use IOCP if possible as it gives us the ability to monitor more
+ * than just sockets (WSAPoll is not an option), and perform arbitrary callbacks
+ * which means we can hook in non-socket related events.
+ *
+ * The information for this implementation was gathered from "wepoll" and
+ * "libuv" which both use slight variants on this. We originally went with
+ * an implementation methodology more similar to "libuv", but we had a few
+ * user reports of crashes during shutdown and memory leaks due to some
+ * events not being delivered for cleanup of closed sockets.
+ *
+ * Initialization:
+ * 1. Dynamically load the NtDeviceIoControlFile, NtCreateFile, and
+ * NtCancelIoFileEx internal symbols from ntdll.dll. (Don't believe
+ * Microsoft's documentation for NtCancelIoFileEx as it documents an
+ * invalid prototype). These functions are to open a reference to the
+ * Ancillary Function Driver (AFD), and to submit and cancel POLL
+ * requests.
+ * 2. Create an IO Completion Port base handle via CreateIoCompletionPort()
+ * that all socket events will be delivered through.
+ * 3. Create a list of AFD Handles and track the number of poll requests
+ * per AFD handle. When we exceed a pre-determined limit of poll requests
+ * for a handle (128), we will automatically create a new handle. The
+ * reason behind this is NtCancelIoFileEx uses a horrible algorithm for
+ * issuing cancellations. See:
+ * https://github.com/python-trio/trio/issues/52#issuecomment-548215128
+ * 4. Create a callback to be used to be able to interrupt waiting for IOCP
+ * events, this may be called for allowing enqueuing of additional socket
+ * events or removing socket events. PostQueuedCompletionStatus() is the
+ * obvious choice. We can use the same container format, the event
+ * delivered won't have an OVERLAPPED pointer so we can differentiate from
+ * socket events. Use the container as the completion key.
+ *
+ * Socket Add:
+ * 1. Create/Allocate a container for holding metadata about a socket
+ * including:
+ * - SOCKET base_socket;
+ * - IO_STATUS_BLOCK iosb; -- Used by AFD POLL, returned as OVERLAPPED
+ * - AFD_POLL_INFO afd_poll_info; -- Used by AFD POLL
+ * - afd list node -- for tracking which AFD handle a POLL request was
+ * submitted to.
+ * 2. Call WSAIoctl(..., SIO_BASE_HANDLE, ...) to unwrap the SOCKET and get
+ * the "base socket" we can use for polling. It appears this may fail so
+ * we should call WSAIoctl(..., SIO_BSP_HANDLE_POLL, ...) as a fallback.
+ * 3. Submit AFD POLL request (see "AFD POLL Request" section)
+ * 4. Record a mapping between the "IO Status Block" and the socket container
+ * so when events are delivered we can dereference.
+ *
+ * Socket Delete:
+ * 1. Call
+ * NtCancelIoFileEx(afd, iosb, &temp_iosb);
+ * to cancel any pending operations.
+ * 2. Tag the socket container as being queued for deletion
+ * 3. Wait for an event to be delivered for the socket (cancel isn't
+ * immediate, it delivers an event to know its complete). Delete only once
+ * that event has been delivered. If we don't do this we could try to
+ * access free()'d memory at a later point.
+ *
+ * Socket Modify:
+ * 1. Call
+ * NtCancelIoFileEx(afd, iosb, &temp_iosb)
+ * to cancel any pending operation.
+ * 2. When the event comes through that the cancel is complete, enqueue
+ * another "AFD Poll Request" for the desired events.
+ *
+ * Event Wait:
+ * 1. Call GetQueuedCompletionStatusEx() with the base IOCP handle, a
+ * stack allocated array of OVERLAPPED_ENTRY's, and an appropriate
+ * timeout.
+ * 2. Iterate across returned events, if the lpOverlapped is NULL, then the
+ * the CompletionKey is a pointer to the container registered via
+ * PostQueuedCompletionStatus(), otherwise it is the "IO Status Block"
+ * registered with the "AFD Poll Request" which needs to be dereferenced
+ * to the "socket container".
+ * 3. If it is a "socket container", disassociate it from the afd list node
+ * it was previously submitted to.
+ * 4. If it is a "socket container" check to see if we are cleaning up, if so,
+ * clean it up.
+ * 5. If it is a "socket container" that is still valid, Submit an
+ * AFD POLL Request (see "AFD POLL Request"). We must re-enable the request
+ * each time we receive a response, it is not persistent.
+ * 6. Notify of any events received as indicated in the AFD_POLL_INFO
+ * Handles[0].Events (NOTE: check NumberOfHandles > 0, and the status in
+ * the IO_STATUS_BLOCK. If we received an AFD_POLL_LOCAL_CLOSE, clean up
+ * the connection like the integrator requested it to be cleaned up.
+ *
+ * AFD Poll Request:
+ * 1. Find an afd poll handle in the list that has fewer pending requests than
+ * the limit.
+ * 2. If an afd poll handle was not associated (e.g. due to all being over
+ * limit), create a new afd poll handle by calling NtCreateFile()
+ * with path \Device\Afd , then add the AFD handle to the IO Completion
+ * Port. We can leave the completion key as blank since events for
+ * multiple sockets will be delivered through this and we need to
+ * differentiate via the OVERLAPPED member returned. Add the new AFD
+ * handle to the list of handles.
+ * 3. Initialize the AFD_POLL_INFO structure:
+ * Exclusive = FALSE; // allow multiple requests
+ * NumberOfHandles = 1;
+ * Timeout.QuadPart = LLONG_MAX;
+ * Handles[0].Handle = (HANDLE)base_socket;
+ * Handles[0].Status = 0;
+ * Handles[0].Events = AFD_POLL_LOCAL_CLOSE + additional events to wait for
+ * such as AFD_POLL_RECEIVE, etc;
+ * 4. Zero out the IO_STATUS_BLOCK structures
+ * 5. Set the "Status" member of IO_STATUS_BLOCK to STATUS_PENDING
+ * 6. Call
+ * NtDeviceIoControlFile(afd, NULL, NULL, &iosb,
+ * &iosb, IOCTL_AFD_POLL
+ * &afd_poll_info, sizeof(afd_poll_info),
+ * &afd_poll_info, sizeof(afd_poll_info));
+ *
+ *
+ * References:
+ * - https://github.com/piscisaureus/wepoll/
+ * - https://github.com/libuv/libuv/
+ */
+
+/* Cap the number of outstanding AFD poll requests per AFD handle due to known
+ * slowdowns with large lists and NtCancelIoFileEx() */
+# define AFD_POLL_PER_HANDLE 128
+
+# include <stdarg.h>
+
+/* # define CARES_DEBUG 1 */
+
+# ifdef __GNUC__
+# define CARES_PRINTF_LIKE(fmt, args) \
+ __attribute__((format(printf, fmt, args)))
+# else
+# define CARES_PRINTF_LIKE(fmt, args)
+# endif
+
+static void CARES_DEBUG_LOG(const char *fmt, ...) CARES_PRINTF_LIKE(1, 2);
+
+static void CARES_DEBUG_LOG(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+# ifdef CARES_DEBUG
+ vfprintf(stderr, fmt, ap);
+ fflush(stderr);
+# endif
+ va_end(ap);
+}
+
+typedef struct {
+ /* Dynamically loaded symbols */
+ NtCreateFile_t NtCreateFile;
+ NtDeviceIoControlFile_t NtDeviceIoControlFile;
+ NtCancelIoFileEx_t NtCancelIoFileEx;
+
+ /* Implementation details */
+ ares__slist_t *afd_handles;
+ HANDLE iocp_handle;
+
+ /* IO_STATUS_BLOCK * -> ares_evsys_win32_eventdata_t * mapping. There is
+ * no completion key passed to IOCP with this method so we have to look
+ * up based on the lpOverlapped returned (which is mapped to IO_STATUS_BLOCK)
+ */
+ ares__htable_vpvp_t *sockets;
+
+ /* Flag about whether or not we are shutting down */
+ ares_bool_t is_shutdown;
+} ares_evsys_win32_t;
+
+typedef enum {
+ POLL_STATUS_NONE = 0,
+ POLL_STATUS_PENDING = 1,
+ POLL_STATUS_CANCEL = 2,
+ POLL_STATUS_DESTROY = 3
+} poll_status_t;
+
+typedef struct {
+ /*! Pointer to parent event container */
+ ares_event_t *event;
+ /*! Socket passed in to monitor */
+ SOCKET socket;
+ /*! Base socket derived from provided socket */
+ SOCKET base_socket;
+ /*! Structure for submitting AFD POLL requests (Internals!) */
+ AFD_POLL_INFO afd_poll_info;
+ /*! Status of current polling operation */
+ poll_status_t poll_status;
+ /*! IO Status Block structure submitted with AFD POLL requests and returned
+ * with IOCP results as lpOverlapped (even though its a different structure)
+ */
+ IO_STATUS_BLOCK iosb;
+ /*! AFD handle node an outstanding poll request is associated with */
+ ares__slist_node_t *afd_handle_node;
+ /* Lock is only for PostQueuedCompletionStatus() to prevent multiple
+ * signals. Tracking via POLL_STATUS_PENDING/POLL_STATUS_NONE */
+ ares__thread_mutex_t *lock;
+} ares_evsys_win32_eventdata_t;
+
+static size_t ares_evsys_win32_wait(ares_event_thread_t *e,
+ unsigned long timeout_ms);
+
+static void ares_iocpevent_signal(const ares_event_t *event)
+{
+ ares_event_thread_t *e = event->e;
+ ares_evsys_win32_t *ew = e->ev_sys_data;
+ ares_evsys_win32_eventdata_t *ed = event->data;
+ ares_bool_t queue_event = ARES_FALSE;
+
+ ares__thread_mutex_lock(ed->lock);
+ if (ed->poll_status != POLL_STATUS_PENDING) {
+ ed->poll_status = POLL_STATUS_PENDING;
+ queue_event = ARES_TRUE;
+ }
+ ares__thread_mutex_unlock(ed->lock);
+
+ if (!queue_event) {
+ return;
+ }
+
+ PostQueuedCompletionStatus(ew->iocp_handle, 0, (ULONG_PTR)event->data, NULL);
+}
+
+static void ares_iocpevent_cb(ares_event_thread_t *e, ares_socket_t fd,
+ void *data, ares_event_flags_t flags)
+{
+ ares_evsys_win32_eventdata_t *ed = data;
+ (void)e;
+ (void)fd;
+ (void)flags;
+ ares__thread_mutex_lock(ed->lock);
+ ed->poll_status = POLL_STATUS_NONE;
+ ares__thread_mutex_unlock(ed->lock);
+}
+
+static ares_event_t *ares_iocpevent_create(ares_event_thread_t *e)
+{
+ ares_event_t *event = NULL;
+ ares_status_t status;
+
+ status =
+ ares_event_update(&event, e, ARES_EVENT_FLAG_OTHER, ares_iocpevent_cb,
+ ARES_SOCKET_BAD, NULL, NULL, ares_iocpevent_signal);
+ if (status != ARES_SUCCESS) {
+ return NULL;
+ }
+
+ return event;
+}
+
+static void ares_evsys_win32_destroy(ares_event_thread_t *e)
+{
+ ares_evsys_win32_t *ew = NULL;
+
+ if (e == NULL) {
+ return;
+ }
+
+ CARES_DEBUG_LOG("** Win32 Event Destroy\n");
+
+ ew = e->ev_sys_data;
+ if (ew == NULL) {
+ return;
+ }
+
+ ew->is_shutdown = ARES_TRUE;
+ CARES_DEBUG_LOG(" ** waiting on %lu remaining sockets to be destroyed\n",
+ (unsigned long)ares__htable_vpvp_num_keys(ew->sockets));
+ while (ares__htable_vpvp_num_keys(ew->sockets)) {
+ ares_evsys_win32_wait(e, 0);
+ }
+ CARES_DEBUG_LOG(" ** all sockets cleaned up\n");
+
+
+ if (ew->iocp_handle != NULL) {
+ CloseHandle(ew->iocp_handle);
+ }
+
+ ares__slist_destroy(ew->afd_handles);
+
+ ares__htable_vpvp_destroy(ew->sockets);
+
+ ares_free(ew);
+ e->ev_sys_data = NULL;
+}
+
+typedef struct {
+ size_t poll_cnt;
+ HANDLE afd_handle;
+} ares_afd_handle_t;
+
+static void ares_afd_handle_destroy(void *arg)
+{
+ ares_afd_handle_t *hnd = arg;
+ if (hnd != NULL && hnd->afd_handle != NULL) {
+ CloseHandle(hnd->afd_handle);
+ }
+ ares_free(hnd);
+}
+
+static int ares_afd_handle_cmp(const void *data1, const void *data2)
+{
+ const ares_afd_handle_t *hnd1 = data1;
+ const ares_afd_handle_t *hnd2 = data2;
+
+ if (hnd1->poll_cnt > hnd2->poll_cnt) {
+ return 1;
+ }
+ if (hnd1->poll_cnt < hnd2->poll_cnt) {
+ return -1;
+ }
+ return 0;
+}
+
+static void fill_object_attributes(OBJECT_ATTRIBUTES *attr,
+ UNICODE_STRING *name, ULONG attributes)
+{
+ memset(attr, 0, sizeof(*attr));
+ attr->Length = sizeof(*attr);
+ attr->ObjectName = name;
+ attr->Attributes = attributes;
+}
+
+# define UNICODE_STRING_CONSTANT(s) \
+ { (sizeof(s) - 1) * sizeof(wchar_t), sizeof(s) * sizeof(wchar_t), L##s }
+
+static ares__slist_node_t *ares_afd_handle_create(ares_evsys_win32_t *ew)
+{
+ UNICODE_STRING afd_device_name = UNICODE_STRING_CONSTANT("\\Device\\Afd");
+ OBJECT_ATTRIBUTES afd_attributes;
+ NTSTATUS status;
+ IO_STATUS_BLOCK iosb;
+ ares_afd_handle_t *afd = ares_malloc_zero(sizeof(*afd));
+ ares__slist_node_t *node = NULL;
+ if (afd == NULL) {
+ goto fail;
+ }
+
+ /* Open a handle to the AFD subsystem */
+ fill_object_attributes(&afd_attributes, &afd_device_name, 0);
+ memset(&iosb, 0, sizeof(iosb));
+ iosb.Status = STATUS_PENDING;
+ status = ew->NtCreateFile(&afd->afd_handle, SYNCHRONIZE, &afd_attributes,
+ &iosb, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_OPEN, 0, NULL, 0);
+ if (status != STATUS_SUCCESS) {
+ CARES_DEBUG_LOG("** Failed to create AFD endpoint\n");
+ goto fail;
+ }
+
+ if (CreateIoCompletionPort(afd->afd_handle, ew->iocp_handle,
+ 0 /* CompletionKey */, 0) == NULL) {
+ goto fail;
+ }
+
+ if (!SetFileCompletionNotificationModes(afd->afd_handle,
+ FILE_SKIP_SET_EVENT_ON_HANDLE)) {
+ goto fail;
+ }
+
+ node = ares__slist_insert(ew->afd_handles, afd);
+ if (node == NULL) {
+ goto fail;
+ }
+
+ return node;
+
+fail:
+
+ ares_afd_handle_destroy(afd);
+ return NULL;
+}
+
+/* Fetch the lowest poll count entry, but if it exceeds the limit, create a
+ * new one and return that */
+static ares__slist_node_t *ares_afd_handle_fetch(ares_evsys_win32_t *ew)
+{
+ ares__slist_node_t *node = ares__slist_node_first(ew->afd_handles);
+ ares_afd_handle_t *afd = ares__slist_node_val(node);
+
+ if (afd != NULL && afd->poll_cnt < AFD_POLL_PER_HANDLE) {
+ return node;
+ }
+
+ return ares_afd_handle_create(ew);
+}
+
+static ares_bool_t ares_evsys_win32_init(ares_event_thread_t *e)
+{
+ ares_evsys_win32_t *ew = NULL;
+ HMODULE ntdll;
+
+ CARES_DEBUG_LOG("** Win32 Event Init\n");
+
+ ew = ares_malloc_zero(sizeof(*ew));
+ if (ew == NULL) {
+ return ARES_FALSE;
+ }
+
+ e->ev_sys_data = ew;
+
+ /* All apps should have ntdll.dll already loaded, so just get a handle to
+ * this */
+ ntdll = GetModuleHandleA("ntdll.dll");
+ if (ntdll == NULL) {
+ goto fail;
+ }
+
+# ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wpedantic"
+/* Without the (void *) cast we get:
+ * warning: cast between incompatible function types from 'FARPROC' {aka 'long
+ * long int (*)()'} to 'NTSTATUS (*)(...)'} [-Wcast-function-type] but with it
+ * we get: warning: ISO C forbids conversion of function pointer to object
+ * pointer type [-Wpedantic] look unsolvable short of killing the warning.
+ */
+# endif
+
+ /* Load Internal symbols not typically accessible */
+ ew->NtCreateFile =
+ (NtCreateFile_t)(void *)GetProcAddress(ntdll, "NtCreateFile");
+ ew->NtDeviceIoControlFile = (NtDeviceIoControlFile_t)(void *)GetProcAddress(
+ ntdll, "NtDeviceIoControlFile");
+ ew->NtCancelIoFileEx =
+ (NtCancelIoFileEx_t)(void *)GetProcAddress(ntdll, "NtCancelIoFileEx");
+
+# ifdef __GNUC__
+# pragma GCC diagnostic pop
+# endif
+
+ if (ew->NtCreateFile == NULL || ew->NtCancelIoFileEx == NULL ||
+ ew->NtDeviceIoControlFile == NULL) {
+ goto fail;
+ }
+
+ ew->iocp_handle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
+ if (ew->iocp_handle == NULL) {
+ goto fail;
+ }
+
+ ew->afd_handles = ares__slist_create(
+ e->channel->rand_state, ares_afd_handle_cmp, ares_afd_handle_destroy);
+ if (ew->afd_handles == NULL) {
+ goto fail;
+ }
+
+ /* Create at least the first afd handle, so we know of any critical system
+ * issues during startup */
+ if (ares_afd_handle_create(ew) == NULL) {
+ goto fail;
+ }
+
+ e->ev_signal = ares_iocpevent_create(e);
+ if (e->ev_signal == NULL) {
+ goto fail;
+ }
+
+ ew->sockets = ares__htable_vpvp_create(NULL, NULL);
+ if (ew->sockets == NULL) {
+ goto fail;
+ }
+
+ return ARES_TRUE;
+
+fail:
+ ares_evsys_win32_destroy(e);
+ return ARES_FALSE;
+}
+
+static ares_socket_t ares_evsys_win32_basesocket(ares_socket_t socket)
+{
+ while (1) {
+ DWORD bytes; /* Not used */
+ ares_socket_t base_socket = ARES_SOCKET_BAD;
+ int rv;
+
+ rv = WSAIoctl(socket, SIO_BASE_HANDLE, NULL, 0, &base_socket,
+ sizeof(base_socket), &bytes, NULL, NULL);
+ if (rv != SOCKET_ERROR && base_socket != ARES_SOCKET_BAD) {
+ socket = base_socket;
+ break;
+ }
+
+ /* If we're here, an error occurred */
+ if (GetLastError() == WSAENOTSOCK) {
+ /* This is critical, exit */
+ return ARES_SOCKET_BAD;
+ }
+
+ /* Work around known bug in Komodia based LSPs, use ARES_BSP_HANDLE_POLL
+ * to retrieve the underlying socket to then loop and get the base socket:
+ * https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls
+ * https://www.komodia.com/newwiki/index.php?title=Komodia%27s_Redirector_bug_fixes#Version_2.2.2.6
+ */
+ base_socket = ARES_SOCKET_BAD;
+ rv = WSAIoctl(socket, SIO_BSP_HANDLE_POLL, NULL, 0, &base_socket,
+ sizeof(base_socket), &bytes, NULL, NULL);
+
+ if (rv != SOCKET_ERROR && base_socket != ARES_SOCKET_BAD &&
+ base_socket != socket) {
+ socket = base_socket;
+ continue; /* loop! */
+ }
+
+ return ARES_SOCKET_BAD;
+ }
+
+ return socket;
+}
+
+static ares_bool_t ares_evsys_win32_afd_enqueue(ares_event_t *event,
+ ares_event_flags_t flags)
+{
+ ares_event_thread_t *e = event->e;
+ ares_evsys_win32_t *ew = e->ev_sys_data;
+ ares_evsys_win32_eventdata_t *ed = event->data;
+ ares_afd_handle_t *afd;
+ NTSTATUS status;
+
+ if (e == NULL || ed == NULL || ew == NULL) {
+ return ARES_FALSE;
+ }
+
+ /* Misuse */
+ if (ed->poll_status != POLL_STATUS_NONE) {
+ return ARES_FALSE;
+ }
+
+ ed->afd_handle_node = ares_afd_handle_fetch(ew);
+ /* System resource issue? */
+ if (ed->afd_handle_node == NULL) {
+ return ARES_FALSE;
+ }
+
+ afd = ares__slist_node_val(ed->afd_handle_node);
+
+ /* Enqueue AFD Poll */
+ ed->afd_poll_info.Exclusive = FALSE;
+ ed->afd_poll_info.NumberOfHandles = 1;
+ ed->afd_poll_info.Timeout.QuadPart = LLONG_MAX;
+ ed->afd_poll_info.Handles[0].Handle = (HANDLE)ed->base_socket;
+ ed->afd_poll_info.Handles[0].Status = 0;
+ ed->afd_poll_info.Handles[0].Events = AFD_POLL_LOCAL_CLOSE;
+
+ if (flags & ARES_EVENT_FLAG_READ) {
+ ed->afd_poll_info.Handles[0].Events |=
+ (AFD_POLL_RECEIVE | AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT |
+ AFD_POLL_ABORT);
+ }
+ if (flags & ARES_EVENT_FLAG_WRITE) {
+ ed->afd_poll_info.Handles[0].Events |=
+ (AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL);
+ }
+ if (flags == 0) {
+ ed->afd_poll_info.Handles[0].Events |= AFD_POLL_DISCONNECT;
+ }
+
+ memset(&ed->iosb, 0, sizeof(ed->iosb));
+ ed->iosb.Status = STATUS_PENDING;
+
+ status = ew->NtDeviceIoControlFile(
+ afd->afd_handle, NULL, NULL, &ed->iosb, &ed->iosb, IOCTL_AFD_POLL,
+ &ed->afd_poll_info, sizeof(ed->afd_poll_info), &ed->afd_poll_info,
+ sizeof(ed->afd_poll_info));
+ if (status != STATUS_SUCCESS && status != STATUS_PENDING) {
+ CARES_DEBUG_LOG("** afd_enqueue ed=%p FAILED\n", (void *)ed);
+ ed->afd_handle_node = NULL;
+ return ARES_FALSE;
+ }
+
+ /* Record that we submitted a poll request to this handle and tell it to
+ * re-sort the node since we changed its sort value */
+ afd->poll_cnt++;
+ ares__slist_node_reinsert(ed->afd_handle_node);
+
+ ed->poll_status = POLL_STATUS_PENDING;
+ CARES_DEBUG_LOG("++ afd_enqueue ed=%p flags=%X\n", (void *)ed,
+ (unsigned int)flags);
+ return ARES_TRUE;
+}
+
+static ares_bool_t ares_evsys_win32_afd_cancel(ares_evsys_win32_eventdata_t *ed)
+{
+ IO_STATUS_BLOCK cancel_iosb;
+ ares_evsys_win32_t *ew;
+ NTSTATUS status;
+ ares_afd_handle_t *afd;
+
+ ew = ed->event->e->ev_sys_data;
+
+ /* Misuse */
+ if (ed->poll_status != POLL_STATUS_PENDING) {
+ return ARES_FALSE;
+ }
+
+ afd = ares__slist_node_val(ed->afd_handle_node);
+
+ /* Misuse */
+ if (afd == NULL) {
+ return ARES_FALSE;
+ }
+
+ ed->poll_status = POLL_STATUS_CANCEL;
+
+ /* Not pending, nothing to do. Most likely that means there is a pending
+ * event that hasn't yet been delivered otherwise it would be re-armed
+ * already */
+ if (ed->iosb.Status != STATUS_PENDING) {
+ CARES_DEBUG_LOG("** cancel not needed for ed=%p\n", (void *)ed);
+ return ARES_FALSE;
+ }
+
+ status = ew->NtCancelIoFileEx(afd->afd_handle, &ed->iosb, &cancel_iosb);
+
+ CARES_DEBUG_LOG("** Enqueued cancel for ed=%p, status = %lX\n", (void *)ed,
+ status);
+
+ /* NtCancelIoFileEx() may return STATUS_NOT_FOUND if the operation completed
+ * just before calling NtCancelIoFileEx(), but we have not yet received the
+ * notifiction (but it should be queued for the next IOCP event). */
+ if (status == STATUS_SUCCESS || status == STATUS_NOT_FOUND) {
+ return ARES_TRUE;
+ }
+
+ return ARES_FALSE;
+}
+
+static void ares_evsys_win32_eventdata_destroy(ares_evsys_win32_t *ew,
+ ares_evsys_win32_eventdata_t *ed)
+{
+ if (ew == NULL || ed == NULL) {
+ return;
+ }
+ CARES_DEBUG_LOG("-- deleting ed=%p (%s)\n", (void *)ed,
+ (ed->socket == ARES_SOCKET_BAD) ? "data" : "socket");
+ /* These type of handles are deferred destroy. Update tracking. */
+ if (ed->socket != ARES_SOCKET_BAD) {
+ ares__htable_vpvp_remove(ew->sockets, &ed->iosb);
+ }
+
+ ares__thread_mutex_destroy(ed->lock);
+
+ if (ed->event != NULL) {
+ ed->event->data = NULL;
+ }
+
+ ares_free(ed);
+}
+
+static ares_bool_t ares_evsys_win32_event_add(ares_event_t *event)
+{
+ ares_event_thread_t *e = event->e;
+ ares_evsys_win32_t *ew = e->ev_sys_data;
+ ares_evsys_win32_eventdata_t *ed;
+ ares_bool_t rc = ARES_FALSE;
+
+ ed = ares_malloc_zero(sizeof(*ed));
+ ed->event = event;
+ ed->socket = event->fd;
+ ed->base_socket = ARES_SOCKET_BAD;
+ event->data = ed;
+
+ CARES_DEBUG_LOG("++ add ed=%p (%s) flags=%X\n", (void *)ed,
+ (ed->socket == ARES_SOCKET_BAD) ? "data" : "socket",
+ (unsigned int)event->flags);
+
+ /* Likely a signal event, not something we will directly handle. We create
+ * the ares_evsys_win32_eventdata_t as the placeholder to use as the
+ * IOCP Completion Key */
+ if (ed->socket == ARES_SOCKET_BAD) {
+ ed->lock = ares__thread_mutex_create();
+ if (ed->lock == NULL) {
+ goto done;
+ }
+ rc = ARES_TRUE;
+ goto done;
+ }
+
+ ed->base_socket = ares_evsys_win32_basesocket(ed->socket);
+ if (ed->base_socket == ARES_SOCKET_BAD) {
+ goto done;
+ }
+
+ if (!ares__htable_vpvp_insert(ew->sockets, &ed->iosb, ed)) {
+ goto done;
+ }
+
+ if (!ares_evsys_win32_afd_enqueue(event, event->flags)) {
+ goto done;
+ }
+
+ rc = ARES_TRUE;
+
+done:
+ if (!rc) {
+ ares_evsys_win32_eventdata_destroy(ew, ed);
+ event->data = NULL;
+ }
+ return rc;
+}
+
+static void ares_evsys_win32_event_del(ares_event_t *event)
+{
+ ares_evsys_win32_eventdata_t *ed = event->data;
+
+ /* Already cleaned up, likely a LOCAL_CLOSE */
+ if (ed == NULL) {
+ return;
+ }
+
+ CARES_DEBUG_LOG("-- DELETE requested for ed=%p (%s)\n", (void *)ed,
+ (ed->socket != ARES_SOCKET_BAD) ? "socket" : "data");
+
+ /*
+ * Cancel pending AFD Poll operation.
+ */
+ if (ed->socket != ARES_SOCKET_BAD) {
+ ares_evsys_win32_afd_cancel(ed);
+ ed->poll_status = POLL_STATUS_DESTROY;
+ ed->event = NULL;
+ } else {
+ ares_evsys_win32_eventdata_destroy(event->e->ev_sys_data, ed);
+ }
+
+ event->data = NULL;
+}
+
+static void ares_evsys_win32_event_mod(ares_event_t *event,
+ ares_event_flags_t new_flags)
+{
+ ares_evsys_win32_eventdata_t *ed = event->data;
+
+ /* Not for us */
+ if (event->fd == ARES_SOCKET_BAD || ed == NULL) {
+ return;
+ }
+
+ CARES_DEBUG_LOG("** mod ed=%p new_flags=%X\n", (void *)ed,
+ (unsigned int)new_flags);
+
+ /* All we need to do is cancel the pending operation. When the event gets
+ * delivered for the cancellation, it will automatically re-enqueue a new
+ * event */
+ ares_evsys_win32_afd_cancel(ed);
+}
+
+static ares_bool_t ares_evsys_win32_process_other_event(
+ ares_evsys_win32_t *ew, ares_evsys_win32_eventdata_t *ed, size_t i)
+{
+ ares_event_t *event;
+
+ /* NOTE: do NOT dereference 'ed' if during shutdown as this could be an
+ * invalid pointer if the signal handle was cleaned up, but there was still a
+ * pending event! */
+
+ if (ew->is_shutdown) {
+ CARES_DEBUG_LOG("\t\t** i=%lu, skip non-socket handle during shutdown\n",
+ (unsigned long)i);
+ return ARES_FALSE;
+ }
+
+ event = ed->event;
+ CARES_DEBUG_LOG("\t\t** i=%lu, ed=%p (data)\n", (unsigned long)i, (void *)ed);
+
+ event->cb(event->e, event->fd, event->data, ARES_EVENT_FLAG_OTHER);
+ return ARES_TRUE;
+}
+
+static ares_bool_t ares_evsys_win32_process_socket_event(
+ ares_evsys_win32_t *ew, ares_evsys_win32_eventdata_t *ed, size_t i)
+{
+ ares_event_flags_t flags = 0;
+ ares_event_t *event = NULL;
+ ares_afd_handle_t *afd = NULL;
+
+ /* Shouldn't be possible */
+ if (ed == NULL) {
+ CARES_DEBUG_LOG("\t\t** i=%lu, Invalid handle.\n", (unsigned long)i);
+ return ARES_FALSE;
+ }
+
+ event = ed->event;
+
+ CARES_DEBUG_LOG("\t\t** i=%lu, ed=%p (socket)\n", (unsigned long)i,
+ (void *)ed);
+
+ /* Process events */
+ if (ed->poll_status == POLL_STATUS_PENDING &&
+ ed->iosb.Status == STATUS_SUCCESS &&
+ ed->afd_poll_info.NumberOfHandles > 0) {
+ if (ed->afd_poll_info.Handles[0].Events &
+ (AFD_POLL_RECEIVE | AFD_POLL_DISCONNECT | AFD_POLL_ACCEPT |
+ AFD_POLL_ABORT)) {
+ flags |= ARES_EVENT_FLAG_READ;
+ }
+ if (ed->afd_poll_info.Handles[0].Events &
+ (AFD_POLL_SEND | AFD_POLL_CONNECT_FAIL)) {
+ flags |= ARES_EVENT_FLAG_WRITE;
+ }
+ if (ed->afd_poll_info.Handles[0].Events & AFD_POLL_LOCAL_CLOSE) {
+ CARES_DEBUG_LOG("\t\t** ed=%p LOCAL CLOSE\n", (void *)ed);
+ ed->poll_status = POLL_STATUS_DESTROY;
+ }
+ }
+
+ CARES_DEBUG_LOG("\t\t** ed=%p, iosb status=%lX, poll_status=%d, flags=%X\n",
+ (void *)ed, (unsigned long)ed->iosb.Status,
+ (int)ed->poll_status, (unsigned int)flags);
+
+ /* Decrement poll count for AFD handle then resort, also disassociate
+ * with socket */
+ afd = ares__slist_node_val(ed->afd_handle_node);
+ afd->poll_cnt--;
+ ares__slist_node_reinsert(ed->afd_handle_node);
+ ed->afd_handle_node = NULL;
+
+ /* Pending destroy, go ahead and kill it */
+ if (ed->poll_status == POLL_STATUS_DESTROY) {
+ ares_evsys_win32_eventdata_destroy(ew, ed);
+ return ARES_FALSE;
+ }
+
+ ed->poll_status = POLL_STATUS_NONE;
+
+ /* Mask flags against current desired flags. We could have an event
+ * queued that is outdated. */
+ flags &= event->flags;
+
+ /* Don't actually do anything with the event that was delivered as we are
+ * in a shutdown/cleanup process. Mostly just handling the delayed
+ * destruction of sockets */
+ if (ew->is_shutdown) {
+ return ARES_FALSE;
+ }
+
+ /* Re-enqueue so we can get more events on the socket, we either
+ * received a real event, or a cancellation notice. Both cases we
+ * re-queue using the current configured event flags.
+ *
+ * If we can't re-enqueue, that likely means the socket has been
+ * closed, so we want to kill our reference to it
+ */
+ if (!ares_evsys_win32_afd_enqueue(event, event->flags)) {
+ ares_evsys_win32_eventdata_destroy(ew, ed);
+ return ARES_FALSE;
+ }
+
+ /* No events we recognize to deliver */
+ if (flags == 0) {
+ return ARES_FALSE;
+ }
+
+ event->cb(event->e, event->fd, event->data, flags);
+ return ARES_TRUE;
+}
+
+static size_t ares_evsys_win32_wait(ares_event_thread_t *e,
+ unsigned long timeout_ms)
+{
+ ares_evsys_win32_t *ew = e->ev_sys_data;
+ OVERLAPPED_ENTRY entries[16];
+ ULONG maxentries = sizeof(entries) / sizeof(*entries);
+ ULONG nentries;
+ BOOL status;
+ size_t i;
+ size_t cnt = 0;
+ DWORD tout = (timeout_ms == 0) ? INFINITE : (DWORD)timeout_ms;
+
+ CARES_DEBUG_LOG("** Wait Enter\n");
+ /* Process in a loop for as long as it fills the entire entries buffer, and
+ * on subsequent attempts, ensure the timeout is 0 */
+ do {
+ nentries = maxentries;
+ status = GetQueuedCompletionStatusEx(ew->iocp_handle, entries, nentries,
+ &nentries, tout, FALSE);
+
+ /* Next loop around, we want to return instantly if there are no events to
+ * be processed */
+ tout = 0;
+
+ if (!status) {
+ break;
+ }
+
+ CARES_DEBUG_LOG("\t** GetQueuedCompletionStatusEx returned %lu entries\n",
+ (unsigned long)nentries);
+ for (i = 0; i < (size_t)nentries; i++) {
+ ares_evsys_win32_eventdata_t *ed = NULL;
+ ares_bool_t rc;
+
+ /* For things triggered via PostQueuedCompletionStatus() we have an
+ * lpCompletionKey we can just use. Otherwise we need to dereference the
+ * pointer returned in lpOverlapped to determine the referenced
+ * socket */
+ if (entries[i].lpCompletionKey) {
+ ed = (ares_evsys_win32_eventdata_t *)entries[i].lpCompletionKey;
+ rc = ares_evsys_win32_process_other_event(ew, ed, i);
+ } else {
+ ed = ares__htable_vpvp_get_direct(ew->sockets, entries[i].lpOverlapped);
+ rc = ares_evsys_win32_process_socket_event(ew, ed, i);
+ }
+
+ /* We processed actual events */
+ if (rc) {
+ cnt++;
+ }
+ }
+ } while (nentries == maxentries);
+
+ CARES_DEBUG_LOG("** Wait Exit\n");
+
+ return cnt;
+}
+
+const ares_event_sys_t ares_evsys_win32 = { "win32",
+ ares_evsys_win32_init,
+ ares_evsys_win32_destroy,
+ ares_evsys_win32_event_add,
+ ares_evsys_win32_event_del,
+ ares_evsys_win32_event_mod,
+ ares_evsys_win32_wait };
+#endif
+
+#if defined(__clang__) || defined(__GNUC__)
+# pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/c-ares/src/lib/ares_event_win32.h b/contrib/libs/c-ares/src/lib/event/ares_event_win32.h
index 99cd5c90f3..5d0274cd85 100644
--- a/contrib/libs/c-ares/src/lib/ares_event_win32.h
+++ b/contrib/libs/c-ares/src/lib/event/ares_event_win32.h
@@ -67,17 +67,53 @@ typedef VOID(NTAPI *PIO_APC_ROUTINE)(PVOID ApcContext,
# define STATUS_CANCELLED ((NTSTATUS)0xC0000120L)
# define STATUS_NOT_FOUND ((NTSTATUS)0xC0000225L)
+typedef struct _UNICODE_STRING {
+ USHORT Length;
+ USHORT MaximumLength;
+ LPCWSTR Buffer;
+} UNICODE_STRING, *PUNICODE_STRING;
+
+typedef struct _OBJECT_ATTRIBUTES {
+ ULONG Length;
+ HANDLE RootDirectory;
+ PUNICODE_STRING ObjectName;
+ ULONG Attributes;
+ PVOID SecurityDescriptor;
+ PVOID SecurityQualityOfService;
+} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
+
+# ifndef FILE_OPEN
+# define FILE_OPEN 0x00000001UL
+# endif
+
/* Not sure what headers might have these */
# define IOCTL_AFD_POLL 0x00012024
-# define AFD_POLL_RECEIVE 0x0001
-# define AFD_POLL_RECEIVE_EXPEDITED 0x0002
-# define AFD_POLL_SEND 0x0004
-# define AFD_POLL_DISCONNECT 0x0008
-# define AFD_POLL_ABORT 0x0010
-# define AFD_POLL_LOCAL_CLOSE 0x0020
-# define AFD_POLL_ACCEPT 0x0080
-# define AFD_POLL_CONNECT_FAIL 0x0100
+# define AFD_POLL_RECEIVE_BIT 0
+# define AFD_POLL_RECEIVE (1 << AFD_POLL_RECEIVE_BIT)
+# define AFD_POLL_RECEIVE_EXPEDITED_BIT 1
+# define AFD_POLL_RECEIVE_EXPEDITED (1 << AFD_POLL_RECEIVE_EXPEDITED_BIT)
+# define AFD_POLL_SEND_BIT 2
+# define AFD_POLL_SEND (1 << AFD_POLL_SEND_BIT)
+# define AFD_POLL_DISCONNECT_BIT 3
+# define AFD_POLL_DISCONNECT (1 << AFD_POLL_DISCONNECT_BIT)
+# define AFD_POLL_ABORT_BIT 4
+# define AFD_POLL_ABORT (1 << AFD_POLL_ABORT_BIT)
+# define AFD_POLL_LOCAL_CLOSE_BIT 5
+# define AFD_POLL_LOCAL_CLOSE (1 << AFD_POLL_LOCAL_CLOSE_BIT)
+# define AFD_POLL_CONNECT_BIT 6
+# define AFD_POLL_CONNECT (1 << AFD_POLL_CONNECT_BIT)
+# define AFD_POLL_ACCEPT_BIT 7
+# define AFD_POLL_ACCEPT (1 << AFD_POLL_ACCEPT_BIT)
+# define AFD_POLL_CONNECT_FAIL_BIT 8
+# define AFD_POLL_CONNECT_FAIL (1 << AFD_POLL_CONNECT_FAIL_BIT)
+# define AFD_POLL_QOS_BIT 9
+# define AFD_POLL_QOS (1 << AFD_POLL_QOS_BIT)
+# define AFD_POLL_GROUP_QOS_BIT 10
+# define AFD_POLL_GROUP_QOS (1 << AFD_POLL_GROUP_QOS_BIT)
+
+# define AFD_NUM_POLL_EVENTS 11
+# define AFD_POLL_ALL ((1 << AFD_NUM_POLL_EVENTS) - 1)
typedef struct _AFD_POLL_HANDLE_INFO {
HANDLE Handle;
@@ -101,6 +137,12 @@ typedef NTSTATUS(NTAPI *NtDeviceIoControlFile_t)(
PIO_STATUS_BLOCK IoStatusBlock, ULONG IoControlCode, PVOID InputBuffer,
ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength);
+typedef NTSTATUS(NTAPI *NtCreateFile_t)(
+ PHANDLE FileHandle, ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock,
+ PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess,
+ ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength);
+
/* On UWP/Windows Store, these definitions aren't there for some reason */
# ifndef SIO_BSP_HANDLE_POLL
# define SIO_BSP_HANDLE_POLL 0x4800001D
diff --git a/contrib/libs/c-ares/src/lib/inet_net_pton.c b/contrib/libs/c-ares/src/lib/inet_net_pton.c
index 19429f205d..5356778c47 100644
--- a/contrib/libs/c-ares/src/lib/inet_net_pton.c
+++ b/contrib/libs/c-ares/src/lib/inet_net_pton.c
@@ -18,7 +18,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -29,11 +29,8 @@
#include "ares_nameser.h"
-#include "ares.h"
#include "ares_ipv6.h"
#include "ares_inet_net_pton.h"
-#include "ares_private.h"
-
const struct ares_in6_addr ares_in6addr_any = { { { 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0 } } };
@@ -72,17 +69,17 @@ static int ares_inet_net_pton_ipv4(const char *src, unsigned char *dst,
const unsigned char *odst = dst;
ch = *src++;
- if (ch == '0' && (src[0] == 'x' || src[0] == 'X') && ISASCII(src[1]) &&
- ISXDIGIT(src[1])) {
+ if (ch == '0' && (src[0] == 'x' || src[0] == 'X') && ares__isascii(src[1]) &&
+ ares__isxdigit(src[1])) {
/* Hexadecimal: Eat nybble string. */
if (!size) {
goto emsgsize;
}
dirty = 0;
src++; /* skip x or X. */
- while ((ch = *src++) != '\0' && ISASCII(ch) && ISXDIGIT(ch)) {
- if (ISUPPER(ch)) {
- ch = tolower(ch);
+ while ((ch = *src++) != '\0' && ares__isascii(ch) && ares__isxdigit(ch)) {
+ if (ares__isupper(ch)) {
+ ch = ares__tolower((unsigned char)ch);
}
n = (int)(strchr(xdigits, ch) - xdigits);
if (dirty == 0) {
@@ -104,7 +101,7 @@ static int ares_inet_net_pton_ipv4(const char *src, unsigned char *dst,
}
*dst++ = (unsigned char)(tmp << 4);
}
- } else if (ISASCII(ch) && ISDIGIT(ch)) {
+ } else if (ares__isascii(ch) && ares__isdigit(ch)) {
/* Decimal: eat dotted digit string. */
for (;;) {
tmp = 0;
@@ -115,7 +112,7 @@ static int ares_inet_net_pton_ipv4(const char *src, unsigned char *dst,
if (tmp > 255) {
goto enoent;
}
- } while ((ch = *src++) != '\0' && ISASCII(ch) && ISDIGIT(ch));
+ } while ((ch = *src++) != '\0' && ares__isascii(ch) && ares__isdigit(ch));
if (!size--) {
goto emsgsize;
}
@@ -127,7 +124,7 @@ static int ares_inet_net_pton_ipv4(const char *src, unsigned char *dst,
goto enoent;
}
ch = *src++;
- if (!ISASCII(ch) || !ISDIGIT(ch)) {
+ if (!ares__isascii(ch) || !ares__isdigit(ch)) {
goto enoent;
}
}
@@ -136,7 +133,8 @@ static int ares_inet_net_pton_ipv4(const char *src, unsigned char *dst,
}
bits = -1;
- if (ch == '/' && ISASCII(src[0]) && ISDIGIT(src[0]) && dst > odst) {
+ if (ch == '/' && ares__isascii(src[0]) && ares__isdigit(src[0]) &&
+ dst > odst) {
/* CIDR width specifier. Nothing can follow it. */
ch = *src++; /* Skip over the /. */
bits = 0;
@@ -147,7 +145,7 @@ static int ares_inet_net_pton_ipv4(const char *src, unsigned char *dst,
if (bits > 32) {
goto enoent;
}
- } while ((ch = *src++) != '\0' && ISASCII(ch) && ISDIGIT(ch));
+ } while ((ch = *src++) != '\0' && ares__isascii(ch) && ares__isdigit(ch));
if (ch != '\0') {
goto enoent;
}
diff --git a/contrib/libs/c-ares/src/lib/inet_ntop.c b/contrib/libs/c-ares/src/lib/inet_ntop.c
index 622befa995..6f96b92ccc 100644
--- a/contrib/libs/c-ares/src/lib/inet_ntop.c
+++ b/contrib/libs/c-ares/src/lib/inet_ntop.c
@@ -17,7 +17,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -27,12 +27,7 @@
#endif
#include "ares_nameser.h"
-
-#include "ares.h"
#include "ares_ipv6.h"
-#include "ares_private.h"
-
-#ifndef HAVE_INET_NTOP
/*
* WARNING: Don't even consider trying to compile this on a system where
@@ -60,14 +55,14 @@ const char *ares_inet_ntop(int af, const void *src, char *dst,
{
switch (af) {
case AF_INET:
- return (inet_ntop4(src, dst, (size_t)size));
+ return inet_ntop4(src, dst, (size_t)size);
case AF_INET6:
- return (inet_ntop6(src, dst, (size_t)size));
+ return inet_ntop6(src, dst, (size_t)size);
default:
- SET_ERRNO(EAFNOSUPPORT);
- return (NULL);
+ break;
}
- /* NOTREACHED */
+ SET_ERRNO(EAFNOSUPPORT);
+ return NULL;
}
/* const char *
@@ -86,13 +81,18 @@ static const char *inet_ntop4(const unsigned char *src, char *dst, size_t size)
static const char fmt[] = "%u.%u.%u.%u";
char tmp[sizeof("255.255.255.255")];
+ if (size < sizeof(tmp)) {
+ SET_ERRNO(ENOSPC);
+ return NULL;
+ }
+
if ((size_t)snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]) >=
size) {
SET_ERRNO(ENOSPC);
- return (NULL);
+ return NULL;
}
ares_strcpy(dst, tmp, size);
- return (dst);
+ return dst;
}
/* const char *
@@ -114,11 +114,12 @@ static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size)
char *tp;
struct {
- int base, len;
+ ares_ssize_t base;
+ size_t len;
} best, cur;
unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
- int i;
+ size_t i;
/*
* Preprocess:
@@ -136,7 +137,8 @@ static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size)
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
if (words[i] == 0) {
if (cur.base == -1) {
- cur.base = i, cur.len = 1;
+ cur.base = (ares_ssize_t)i;
+ cur.len = 1;
} else {
cur.len++;
}
@@ -164,8 +166,9 @@ static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size)
tp = tmp;
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
/* Are we inside the best run of 0x00's? */
- if (best.base != -1 && i >= best.base && i < (best.base + best.len)) {
- if (i == best.base) {
+ if (best.base != -1 && i >= (size_t)best.base &&
+ i < ((size_t)best.base + best.len)) {
+ if (i == (size_t)best.base) {
*tp++ = ':';
}
continue;
@@ -188,7 +191,7 @@ static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size)
}
/* Was it a trailing run of 0x00's? */
if (best.base != -1 &&
- (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) {
+ ((size_t)best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) {
*tp++ = ':';
}
*tp++ = '\0';
@@ -198,19 +201,8 @@ static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size)
*/
if ((size_t)(tp - tmp) > size) {
SET_ERRNO(ENOSPC);
- return (NULL);
+ return NULL;
}
ares_strcpy(dst, tmp, size);
- return (dst);
-}
-
-#else /* HAVE_INET_NTOP */
-
-const char *ares_inet_ntop(int af, const void *src, char *dst,
- ares_socklen_t size)
-{
- /* just relay this to the underlying function */
- return inet_ntop(af, src, dst, size);
+ return dst;
}
-
-#endif /* HAVE_INET_NTOP */
diff --git a/contrib/libs/c-ares/src/lib/ares_create_query.c b/contrib/libs/c-ares/src/lib/legacy/ares_create_query.c
index a2f2caac6e..f71a71c951 100644
--- a/contrib/libs/c-ares/src/lib/ares_create_query.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_create_query.c
@@ -24,8 +24,6 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
static int ares_create_query_int(const char *name, int dnsclass, int type,
diff --git a/contrib/libs/c-ares/src/lib/ares_expand_name.c b/contrib/libs/c-ares/src/lib/legacy/ares_expand_name.c
index 280490b86a..63bd645166 100644
--- a/contrib/libs/c-ares/src/lib/ares_expand_name.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_expand_name.c
@@ -25,7 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -33,9 +33,6 @@
#include "ares_nameser.h"
-#include "ares.h"
-#include "ares_private.h" /* for the memdebug */
-
ares_status_t ares__expand_name_validated(const unsigned char *encoded,
const unsigned char *abuf,
size_t alen, char **s, size_t *enclen,
@@ -91,8 +88,8 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
size_t enclen_temp = 0;
ares_status_t status;
- if (alen < 0) {
- return ARES_EBADRESP;
+ if (encoded == NULL || abuf == NULL || alen <= 0 || enclen == NULL) {
+ return ARES_EBADNAME;
}
status = ares__expand_name_validated(encoded, abuf, (size_t)alen, s,
@@ -100,19 +97,3 @@ int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
*enclen = (long)enclen_temp;
return (int)status;
}
-
-/* Like ares_expand_name_validated but returns EBADRESP in case of invalid
- * input. */
-ares_status_t ares__expand_name_for_response(const unsigned char *encoded,
- const unsigned char *abuf,
- size_t alen, char **s,
- size_t *enclen,
- ares_bool_t is_hostname)
-{
- ares_status_t status =
- ares__expand_name_validated(encoded, abuf, alen, s, enclen, is_hostname);
- if (status == ARES_EBADNAME) {
- status = ARES_EBADRESP;
- }
- return status;
-}
diff --git a/contrib/libs/c-ares/src/lib/ares_expand_string.c b/contrib/libs/c-ares/src/lib/legacy/ares_expand_string.c
index be7034e271..b3e99daa54 100644
--- a/contrib/libs/c-ares/src/lib/ares_expand_string.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_expand_string.c
@@ -25,7 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -33,9 +33,6 @@
#include "ares_nameser.h"
-#include "ares.h"
-#include "ares_private.h" /* for the memdebug */
-
/* Simply decodes a length-encoded character string. The first byte of the
* input is the length of the string to be returned and the bytes thereafter
* are the characters of the string. The returned result will be NULL
@@ -77,8 +74,7 @@ ares_status_t ares_expand_string_ex(const unsigned char *encoded,
}
start_len = ares__buf_len(buf);
- status =
- ares__buf_parse_dns_binstr(buf, ares__buf_len(buf), s, &len, ARES_FALSE);
+ status = ares__buf_parse_dns_binstr(buf, ares__buf_len(buf), s, &len);
/* hrm, no way to pass back 'len' with the prototype */
if (status != ARES_SUCCESS) {
goto done;
@@ -100,7 +96,7 @@ int ares_expand_string(const unsigned char *encoded, const unsigned char *abuf,
ares_status_t status;
size_t temp_enclen = 0;
- if (alen < 0) {
+ if (encoded == NULL || abuf == NULL || alen <= 0 || enclen == NULL) {
return ARES_EBADRESP;
}
diff --git a/contrib/libs/c-ares/src/lib/ares_fds.c b/contrib/libs/c-ares/src/lib/legacy/ares_fds.c
index e39823304a..3aedd2c90e 100644
--- a/contrib/libs/c-ares/src/lib/ares_fds.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_fds.c
@@ -25,9 +25,6 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-
-#include "ares.h"
#include "ares_private.h"
int ares_fds(const ares_channel_t *channel, fd_set *read_fds, fd_set *write_fds)
@@ -48,14 +45,14 @@ int ares_fds(const ares_channel_t *channel, fd_set *read_fds, fd_set *write_fds)
nfds = 0;
for (snode = ares__slist_node_first(channel->servers); snode != NULL;
snode = ares__slist_node_next(snode)) {
- struct server_state *server = ares__slist_node_val(snode);
- ares__llist_node_t *node;
+ ares_server_t *server = ares__slist_node_val(snode);
+ ares__llist_node_t *node;
for (node = ares__llist_node_first(server->connections); node != NULL;
node = ares__llist_node_next(node)) {
- const struct server_connection *conn = ares__llist_node_val(node);
+ const ares_conn_t *conn = ares__llist_node_val(node);
- if (!active_queries && !conn->is_tcp) {
+ if (!active_queries && !(conn->flags & ARES_CONN_FLAG_TCP)) {
continue;
}
@@ -72,7 +69,7 @@ int ares_fds(const ares_channel_t *channel, fd_set *read_fds, fd_set *write_fds)
}
/* TCP only wait on write if we have buffered data */
- if (conn->is_tcp && ares__buf_len(server->tcp_send)) {
+ if (conn->flags & ARES_CONN_FLAG_TCP && ares__buf_len(server->tcp_send)) {
FD_SET(conn->fd, write_fds);
}
}
diff --git a/contrib/libs/c-ares/src/lib/ares_getsock.c b/contrib/libs/c-ares/src/lib/legacy/ares_getsock.c
index b64c075572..8c8476fa95 100644
--- a/contrib/libs/c-ares/src/lib/ares_getsock.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_getsock.c
@@ -24,9 +24,6 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-
-#include "ares.h"
#include "ares_private.h"
int ares_getsock(const ares_channel_t *channel, ares_socket_t *socks,
@@ -50,12 +47,12 @@ int ares_getsock(const ares_channel_t *channel, ares_socket_t *socks,
for (snode = ares__slist_node_first(channel->servers); snode != NULL;
snode = ares__slist_node_next(snode)) {
- struct server_state *server = ares__slist_node_val(snode);
- ares__llist_node_t *node;
+ ares_server_t *server = ares__slist_node_val(snode);
+ ares__llist_node_t *node;
for (node = ares__llist_node_first(server->connections); node != NULL;
node = ares__llist_node_next(node)) {
- const struct server_connection *conn = ares__llist_node_val(node);
+ const ares_conn_t *conn = ares__llist_node_val(node);
if (sockindex >= (size_t)numsocks || sockindex >= ARES_GETSOCK_MAXNUM) {
break;
@@ -64,17 +61,17 @@ int ares_getsock(const ares_channel_t *channel, ares_socket_t *socks,
/* We only need to register interest in UDP sockets if we have
* outstanding queries.
*/
- if (!active_queries && !conn->is_tcp) {
+ if (!active_queries && !(conn->flags & ARES_CONN_FLAG_TCP)) {
continue;
}
socks[sockindex] = conn->fd;
- if (active_queries || conn->is_tcp) {
+ if (active_queries || conn->flags & ARES_CONN_FLAG_TCP) {
bitmap |= ARES_GETSOCK_READABLE(setbits, sockindex);
}
- if (conn->is_tcp && ares__buf_len(server->tcp_send)) {
+ if (conn->flags & ARES_CONN_FLAG_TCP && ares__buf_len(server->tcp_send)) {
/* then the tcp socket is also writable! */
bitmap |= ARES_GETSOCK_WRITABLE(setbits, sockindex);
}
diff --git a/contrib/libs/c-ares/src/lib/ares_parse_a_reply.c b/contrib/libs/c-ares/src/lib/legacy/ares_parse_a_reply.c
index da841f0da9..0981b90eea 100644
--- a/contrib/libs/c-ares/src/lib/ares_parse_a_reply.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_parse_a_reply.c
@@ -25,7 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -37,8 +37,6 @@
# include <arpa/inet.h>
#endif
-#include "ares_nameser.h"
-
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
@@ -47,10 +45,6 @@
# include <limits.h>
#endif
-#include "ares.h"
-#include "ares_dns.h"
-#include "ares_private.h"
-
int ares_parse_a_reply(const unsigned char *abuf, int alen,
struct hostent **host, struct ares_addrttl *addrttls,
int *naddrttls)
@@ -85,7 +79,7 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
if (host != NULL) {
status = ares__addrinfo2hostent(&ai, AF_INET, host);
if (status != ARES_SUCCESS && status != ARES_ENODATA) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: DefensiveCoding */
}
}
diff --git a/contrib/libs/c-ares/src/lib/ares_parse_aaaa_reply.c b/contrib/libs/c-ares/src/lib/legacy/ares_parse_aaaa_reply.c
index b3eba166be..3f6932643b 100644
--- a/contrib/libs/c-ares/src/lib/ares_parse_aaaa_reply.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_parse_aaaa_reply.c
@@ -26,7 +26,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -38,8 +38,6 @@
# include <arpa/inet.h>
#endif
-#include "ares_nameser.h"
-
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
@@ -48,10 +46,7 @@
# include <limits.h>
#endif
-#include "ares.h"
-#include "ares_dns.h"
#include "ares_inet_net_pton.h"
-#include "ares_private.h"
int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
struct hostent **host, struct ares_addr6ttl *addrttls,
@@ -87,7 +82,7 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
if (host != NULL) {
status = ares__addrinfo2hostent(&ai, AF_INET6, host);
if (status != ARES_SUCCESS && status != ARES_ENODATA) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: DefensiveCoding */
}
}
diff --git a/contrib/libs/c-ares/src/lib/ares_parse_caa_reply.c b/contrib/libs/c-ares/src/lib/legacy/ares_parse_caa_reply.c
index 6c30305ee1..f74358f456 100644
--- a/contrib/libs/c-ares/src/lib/ares_parse_caa_reply.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_parse_caa_reply.c
@@ -24,10 +24,8 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
-#include "ares_data.h"
#include "ares_private.h"
+#include "ares_data.h"
int ares_parse_caa_reply(const unsigned char *abuf, int alen_int,
struct ares_caa_reply **caa_out)
@@ -66,8 +64,8 @@ int ares_parse_caa_reply(const unsigned char *abuf, int alen_int,
if (rr == NULL) {
/* Shouldn't be possible */
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* XXX: Why do we allow Chaos class? */
@@ -84,8 +82,8 @@ int ares_parse_caa_reply(const unsigned char *abuf, int alen_int,
/* Allocate storage for this CAA answer appending it to the list */
caa_curr = ares_malloc_data(ARES_DATATYPE_CAA_REPLY);
if (caa_curr == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Link in the record */
@@ -100,8 +98,8 @@ int ares_parse_caa_reply(const unsigned char *abuf, int alen_int,
caa_curr->property =
(unsigned char *)ares_strdup(ares_dns_rr_get_str(rr, ARES_RR_CAA_TAG));
if (caa_curr->property == NULL) {
- status = ARES_ENOMEM;
- break;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ break; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* RFC6844 says this can only be ascii, so not sure why we're recording a
* length */
@@ -109,15 +107,15 @@ int ares_parse_caa_reply(const unsigned char *abuf, int alen_int,
ptr = ares_dns_rr_get_bin(rr, ARES_RR_CAA_VALUE, &ptr_len);
if (ptr == NULL) {
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Wants NULL termination for some reason */
caa_curr->value = ares_malloc(ptr_len + 1);
if (caa_curr->value == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
memcpy(caa_curr->value, ptr, ptr_len);
caa_curr->value[ptr_len] = 0;
diff --git a/contrib/libs/c-ares/src/lib/ares_parse_mx_reply.c b/contrib/libs/c-ares/src/lib/legacy/ares_parse_mx_reply.c
index db7155d2e8..480074f670 100644
--- a/contrib/libs/c-ares/src/lib/ares_parse_mx_reply.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_parse_mx_reply.c
@@ -24,10 +24,8 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
-#include "ares_data.h"
#include "ares_private.h"
+#include "ares_data.h"
int ares_parse_mx_reply(const unsigned char *abuf, int alen_int,
struct ares_mx_reply **mx_out)
@@ -64,8 +62,8 @@ int ares_parse_mx_reply(const unsigned char *abuf, int alen_int,
if (rr == NULL) {
/* Shouldn't be possible */
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN ||
@@ -76,8 +74,8 @@ int ares_parse_mx_reply(const unsigned char *abuf, int alen_int,
/* Allocate storage for this MX answer appending it to the list */
mx_curr = ares_malloc_data(ARES_DATATYPE_MX_REPLY);
if (mx_curr == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Link in the record */
@@ -92,8 +90,8 @@ int ares_parse_mx_reply(const unsigned char *abuf, int alen_int,
mx_curr->host = ares_strdup(ares_dns_rr_get_str(rr, ARES_RR_MX_EXCHANGE));
if (mx_curr->host == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
diff --git a/contrib/libs/c-ares/src/lib/ares_parse_naptr_reply.c b/contrib/libs/c-ares/src/lib/legacy/ares_parse_naptr_reply.c
index 1a304ccdd3..c00ce71066 100644
--- a/contrib/libs/c-ares/src/lib/ares_parse_naptr_reply.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_parse_naptr_reply.c
@@ -23,10 +23,8 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
-#include "ares_data.h"
#include "ares_private.h"
+#include "ares_data.h"
int ares_parse_naptr_reply(const unsigned char *abuf, int alen_int,
struct ares_naptr_reply **naptr_out)
@@ -63,8 +61,8 @@ int ares_parse_naptr_reply(const unsigned char *abuf, int alen_int,
if (rr == NULL) {
/* Shouldn't be possible */
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN ||
@@ -75,8 +73,8 @@ int ares_parse_naptr_reply(const unsigned char *abuf, int alen_int,
/* Allocate storage for this NAPTR answer appending it to the list */
naptr_curr = ares_malloc_data(ARES_DATATYPE_NAPTR_REPLY);
if (naptr_curr == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Link in the record */
@@ -94,28 +92,28 @@ int ares_parse_naptr_reply(const unsigned char *abuf, int alen_int,
naptr_curr->flags = (unsigned char *)ares_strdup(
ares_dns_rr_get_str(rr, ARES_RR_NAPTR_FLAGS));
if (naptr_curr->flags == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* XXX: Why is this unsigned char * ? */
naptr_curr->service = (unsigned char *)ares_strdup(
ares_dns_rr_get_str(rr, ARES_RR_NAPTR_SERVICES));
if (naptr_curr->service == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* XXX: Why is this unsigned char * ? */
naptr_curr->regexp = (unsigned char *)ares_strdup(
ares_dns_rr_get_str(rr, ARES_RR_NAPTR_REGEXP));
if (naptr_curr->regexp == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
naptr_curr->replacement =
ares_strdup(ares_dns_rr_get_str(rr, ARES_RR_NAPTR_REPLACEMENT));
if (naptr_curr->replacement == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
diff --git a/contrib/libs/c-ares/src/lib/ares_parse_ns_reply.c b/contrib/libs/c-ares/src/lib/legacy/ares_parse_ns_reply.c
index 18fda82f41..fc9ab9219d 100644
--- a/contrib/libs/c-ares/src/lib/ares_parse_ns_reply.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_parse_ns_reply.c
@@ -24,7 +24,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -36,9 +36,6 @@
# include <arpa/inet.h>
#endif
-#include "ares.h"
-#include "ares_private.h"
-
int ares_parse_ns_reply(const unsigned char *abuf, int alen_int,
struct hostent **host)
{
@@ -73,16 +70,16 @@ int ares_parse_ns_reply(const unsigned char *abuf, int alen_int,
/* Response structure */
hostent = ares_malloc(sizeof(*hostent));
if (hostent == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
memset(hostent, 0, sizeof(*hostent));
hostent->h_addr_list = ares_malloc(sizeof(*hostent->h_addr_list));
if (hostent->h_addr_list == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
hostent->h_addr_list[0] = NULL;
hostent->h_addrtype = AF_INET;
@@ -91,19 +88,19 @@ int ares_parse_ns_reply(const unsigned char *abuf, int alen_int,
/* Fill in hostname */
status = ares_dns_record_query_get(dnsrec, 0, &hostname, NULL, NULL);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
hostent->h_name = ares_strdup(hostname);
if (hostent->h_name == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Preallocate the maximum number + 1 */
hostent->h_aliases = ares_malloc((ancount + 1) * sizeof(*hostent->h_aliases));
if (hostent->h_aliases == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
memset(hostent->h_aliases, 0, (ancount + 1) * sizeof(*hostent->h_aliases));
@@ -113,8 +110,8 @@ int ares_parse_ns_reply(const unsigned char *abuf, int alen_int,
if (rr == NULL) {
/* Shouldn't be possible */
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN ||
@@ -124,8 +121,8 @@ int ares_parse_ns_reply(const unsigned char *abuf, int alen_int,
hostname = ares_dns_rr_get_str(rr, ARES_RR_NS_NSDNAME);
if (hostname == NULL) {
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
hostent->h_aliases[nscount] = ares_strdup(hostname);
diff --git a/contrib/libs/c-ares/src/lib/ares_parse_ptr_reply.c b/contrib/libs/c-ares/src/lib/legacy/ares_parse_ptr_reply.c
index 6ee20f722e..56a7b5f94e 100644
--- a/contrib/libs/c-ares/src/lib/ares_parse_ptr_reply.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_parse_ptr_reply.c
@@ -24,7 +24,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -33,8 +33,6 @@
# include <netdb.h>
#endif
-#include "ares.h"
-#include "ares_private.h"
ares_status_t ares_parse_ptr_reply_dnsrec(const ares_dns_record_t *dnsrec,
const void *addr, int addrlen,
@@ -105,8 +103,8 @@ ares_status_t ares_parse_ptr_reply_dnsrec(const ares_dns_record_t *dnsrec,
if (rr == NULL) {
/* Shouldn't be possible */
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN) {
@@ -117,8 +115,8 @@ ares_status_t ares_parse_ptr_reply_dnsrec(const ares_dns_record_t *dnsrec,
if (ares_dns_rr_get_type(rr) == ARES_REC_TYPE_CNAME) {
ptrname = ares_dns_rr_get_str(rr, ARES_RR_CNAME_CNAME);
if (ptrname == NULL) {
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
}
@@ -145,8 +143,8 @@ ares_status_t ares_parse_ptr_reply_dnsrec(const ares_dns_record_t *dnsrec,
/* Save most recent PTR record as the hostname */
hostname = ares_dns_rr_get_str(rr, ARES_RR_PTR_DNAME);
if (hostname == NULL) {
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Append as an alias */
@@ -168,8 +166,8 @@ ares_status_t ares_parse_ptr_reply_dnsrec(const ares_dns_record_t *dnsrec,
/* Fill in hostname */
hostent->h_name = ares_strdup(hostname);
if (hostent->h_name == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
done:
diff --git a/contrib/libs/c-ares/src/lib/ares_parse_soa_reply.c b/contrib/libs/c-ares/src/lib/legacy/ares_parse_soa_reply.c
index 2777dbcb0b..46b40dedc4 100644
--- a/contrib/libs/c-ares/src/lib/ares_parse_soa_reply.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_parse_soa_reply.c
@@ -24,10 +24,8 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
-#include "ares_data.h"
#include "ares_private.h"
+#include "ares_data.h"
int ares_parse_soa_reply(const unsigned char *abuf, int alen_int,
struct ares_soa_reply **soa_out)
@@ -62,8 +60,8 @@ int ares_parse_soa_reply(const unsigned char *abuf, int alen_int,
if (rr == NULL) {
/* Shouldn't be possible */
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN ||
@@ -74,8 +72,8 @@ int ares_parse_soa_reply(const unsigned char *abuf, int alen_int,
/* allocate result struct */
soa = ares_malloc_data(ARES_DATATYPE_SOA_REPLY);
if (soa == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
soa->serial = ares_dns_rr_get_u32(rr, ARES_RR_SOA_SERIAL);
@@ -85,13 +83,13 @@ int ares_parse_soa_reply(const unsigned char *abuf, int alen_int,
soa->minttl = ares_dns_rr_get_u32(rr, ARES_RR_SOA_MINIMUM);
soa->nsname = ares_strdup(ares_dns_rr_get_str(rr, ARES_RR_SOA_MNAME));
if (soa->nsname == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
soa->hostmaster = ares_strdup(ares_dns_rr_get_str(rr, ARES_RR_SOA_RNAME));
if (soa->hostmaster == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
break;
}
diff --git a/contrib/libs/c-ares/src/lib/ares_parse_srv_reply.c b/contrib/libs/c-ares/src/lib/legacy/ares_parse_srv_reply.c
index f27bcce733..3f9fd95ebf 100644
--- a/contrib/libs/c-ares/src/lib/ares_parse_srv_reply.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_parse_srv_reply.c
@@ -24,10 +24,8 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
-#include "ares_data.h"
#include "ares_private.h"
+#include "ares_data.h"
int ares_parse_srv_reply(const unsigned char *abuf, int alen_int,
struct ares_srv_reply **srv_out)
@@ -64,8 +62,8 @@ int ares_parse_srv_reply(const unsigned char *abuf, int alen_int,
if (rr == NULL) {
/* Shouldn't be possible */
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN ||
@@ -76,8 +74,8 @@ int ares_parse_srv_reply(const unsigned char *abuf, int alen_int,
/* Allocate storage for this SRV answer appending it to the list */
srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_REPLY);
if (srv_curr == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Link in the record */
@@ -96,8 +94,8 @@ int ares_parse_srv_reply(const unsigned char *abuf, int alen_int,
srv_curr->host = ares_strdup(ares_dns_rr_get_str(rr, ARES_RR_SRV_TARGET));
if (srv_curr->host == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
diff --git a/contrib/libs/c-ares/src/lib/ares_parse_txt_reply.c b/contrib/libs/c-ares/src/lib/legacy/ares_parse_txt_reply.c
index 85c3644b8c..71ee084111 100644
--- a/contrib/libs/c-ares/src/lib/ares_parse_txt_reply.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_parse_txt_reply.c
@@ -24,10 +24,8 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
-#include "ares_data.h"
#include "ares_private.h"
+#include "ares_data.h"
static int ares__parse_txt_reply(const unsigned char *abuf, size_t alen,
ares_bool_t ex, void **txt_out)
@@ -54,13 +52,14 @@ static int ares__parse_txt_reply(const unsigned char *abuf, size_t alen,
for (i = 0; i < ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER); i++) {
const ares_dns_rr_t *rr =
ares_dns_record_rr_get(dnsrec, ARES_SECTION_ANSWER, i);
- const unsigned char *ptr;
- size_t ptr_len;
+ size_t j;
+ size_t cnt;
+
if (rr == NULL) {
/* Shouldn't be possible */
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* XXX: Why Chaos? */
@@ -70,37 +69,44 @@ static int ares__parse_txt_reply(const unsigned char *abuf, size_t alen,
continue;
}
- /* Allocate storage for this TXT answer appending it to the list */
- txt_curr =
- ares_malloc_data(ex ? ARES_DATATYPE_TXT_EXT : ARES_DATATYPE_TXT_REPLY);
- if (txt_curr == NULL) {
- status = ARES_ENOMEM;
- goto done;
- }
-
- /* Link in the record */
- if (txt_last) {
- txt_last->next = txt_curr;
- } else {
- txt_head = txt_curr;
- }
- txt_last = txt_curr;
-
- /* These days, records are joined, always tag as start */
- if (ex) {
- txt_curr->record_start = 1;
- }
-
- ptr = ares_dns_rr_get_bin(rr, ARES_RR_TXT_DATA, &ptr_len);
-
- txt_curr->txt = ares_malloc(ptr_len + 1);
- if (txt_curr->txt == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ cnt = ares_dns_rr_get_abin_cnt(rr, ARES_RR_TXT_DATA);
+
+ for (j = 0; j < cnt; j++) {
+ const unsigned char *ptr;
+ size_t ptr_len;
+
+ /* Allocate storage for this TXT answer appending it to the list */
+ txt_curr =
+ ares_malloc_data(ex ? ARES_DATATYPE_TXT_EXT : ARES_DATATYPE_TXT_REPLY);
+ if (txt_curr == NULL) {
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
+ }
+
+ /* Link in the record */
+ if (txt_last) {
+ txt_last->next = txt_curr;
+ } else {
+ txt_head = txt_curr;
+ }
+ txt_last = txt_curr;
+
+ /* Tag start on first for each TXT record */
+ if (ex && j == 0) {
+ txt_curr->record_start = 1;
+ }
+
+ ptr = ares_dns_rr_get_abin(rr, ARES_RR_TXT_DATA, j, &ptr_len);
+
+ txt_curr->txt = ares_malloc(ptr_len + 1);
+ if (txt_curr->txt == NULL) {
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
+ }
+ memcpy(txt_curr->txt, ptr, ptr_len);
+ txt_curr->txt[ptr_len] = 0;
+ txt_curr->length = ptr_len;
}
- memcpy(txt_curr->txt, ptr, ptr_len);
- txt_curr->txt[ptr_len] = 0;
- txt_curr->length = ptr_len;
}
done:
diff --git a/contrib/libs/c-ares/src/lib/ares_parse_uri_reply.c b/contrib/libs/c-ares/src/lib/legacy/ares_parse_uri_reply.c
index bff7023f78..317e204d5d 100644
--- a/contrib/libs/c-ares/src/lib/ares_parse_uri_reply.c
+++ b/contrib/libs/c-ares/src/lib/legacy/ares_parse_uri_reply.c
@@ -24,10 +24,8 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
-#include "ares_data.h"
#include "ares_private.h"
+#include "ares_data.h"
int ares_parse_uri_reply(const unsigned char *abuf, int alen_int,
struct ares_uri_reply **uri_out)
@@ -64,8 +62,8 @@ int ares_parse_uri_reply(const unsigned char *abuf, int alen_int,
if (rr == NULL) {
/* Shouldn't be possible */
- status = ARES_EBADRESP;
- goto done;
+ status = ARES_EBADRESP; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN ||
@@ -76,8 +74,8 @@ int ares_parse_uri_reply(const unsigned char *abuf, int alen_int,
/* Allocate storage for this URI answer appending it to the list */
uri_curr = ares_malloc_data(ARES_DATATYPE_URI_REPLY);
if (uri_curr == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Link in the record */
diff --git a/contrib/libs/c-ares/src/lib/ares_dns_mapping.c b/contrib/libs/c-ares/src/lib/record/ares_dns_mapping.c
index 6c4362f000..738d2f3795 100644
--- a/contrib/libs/c-ares/src/lib/ares_dns_mapping.c
+++ b/contrib/libs/c-ares/src/lib/record/ares_dns_mapping.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
ares_bool_t ares_dns_opcode_isvalid(ares_dns_opcode_t opcode)
@@ -518,9 +516,11 @@ ares_dns_datatype_t ares_dns_rr_key_datatype(ares_dns_rr_key_t key)
return ARES_DATATYPE_U8;
case ARES_RR_CAA_VALUE:
- case ARES_RR_TXT_DATA:
return ARES_DATATYPE_BINP;
+ case ARES_RR_TXT_DATA:
+ return ARES_DATATYPE_ABINP;
+
case ARES_RR_SIG_SIGNATURE:
case ARES_RR_TLSA_DATA:
case ARES_RR_RAW_RR_DATA:
@@ -548,18 +548,14 @@ static const ares_dns_rr_key_t rr_hinfo_keys[] = { ARES_RR_HINFO_CPU,
ARES_RR_HINFO_OS };
static const ares_dns_rr_key_t rr_mx_keys[] = { ARES_RR_MX_PREFERENCE,
ARES_RR_MX_EXCHANGE };
-static const ares_dns_rr_key_t rr_sig_keys[] = { ARES_RR_SIG_TYPE_COVERED,
- ARES_RR_SIG_ALGORITHM,
- ARES_RR_SIG_LABELS,
- ARES_RR_SIG_ORIGINAL_TTL,
- ARES_RR_SIG_EXPIRATION,
- ARES_RR_SIG_INCEPTION,
- ARES_RR_SIG_KEY_TAG,
- ARES_RR_SIG_SIGNERS_NAME,
- ARES_RR_SIG_SIGNATURE };
-static const ares_dns_rr_key_t rr_txt_keys[] = { ARES_RR_TXT_DATA };
-static const ares_dns_rr_key_t rr_aaaa_keys[] = { ARES_RR_AAAA_ADDR };
-static const ares_dns_rr_key_t rr_srv_keys[] = {
+static const ares_dns_rr_key_t rr_sig_keys[] = {
+ ARES_RR_SIG_TYPE_COVERED, ARES_RR_SIG_ALGORITHM, ARES_RR_SIG_LABELS,
+ ARES_RR_SIG_ORIGINAL_TTL, ARES_RR_SIG_EXPIRATION, ARES_RR_SIG_INCEPTION,
+ ARES_RR_SIG_KEY_TAG, ARES_RR_SIG_SIGNERS_NAME, ARES_RR_SIG_SIGNATURE
+};
+static const ares_dns_rr_key_t rr_txt_keys[] = { ARES_RR_TXT_DATA };
+static const ares_dns_rr_key_t rr_aaaa_keys[] = { ARES_RR_AAAA_ADDR };
+static const ares_dns_rr_key_t rr_srv_keys[] = {
ARES_RR_SRV_PRIORITY, ARES_RR_SRV_WEIGHT, ARES_RR_SRV_PORT, ARES_RR_SRV_TARGET
};
static const ares_dns_rr_key_t rr_naptr_keys[] = {
diff --git a/contrib/libs/c-ares/src/lib/record/ares_dns_multistring.c b/contrib/libs/c-ares/src/lib/record/ares_dns_multistring.c
new file mode 100644
index 0000000000..bff5afb9f2
--- /dev/null
+++ b/contrib/libs/c-ares/src/lib/record/ares_dns_multistring.c
@@ -0,0 +1,224 @@
+/* MIT License
+ *
+ * Copyright (c) 2024 Brad House
+ *
+ * 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_private.h"
+#include "ares_dns_private.h"
+
+typedef struct {
+ unsigned char *data;
+ size_t len;
+} multistring_data_t;
+
+struct ares__dns_multistring {
+ /*! whether or not cached concatenated string is valid */
+ ares_bool_t cache_invalidated;
+ /*! combined/concatenated string cache */
+ unsigned char *cache_str;
+ /*! length of combined/concatenated string */
+ size_t cache_str_len;
+ /*! Data making up strings */
+ ares__array_t *strs; /*!< multistring_data_t type */
+};
+
+static void ares__dns_multistring_free_cb(void *arg)
+{
+ multistring_data_t *data = arg;
+ if (data == NULL) {
+ return;
+ }
+ ares_free(data->data);
+}
+
+ares__dns_multistring_t *ares__dns_multistring_create(void)
+{
+ ares__dns_multistring_t *strs = ares_malloc_zero(sizeof(*strs));
+ if (strs == NULL) {
+ return NULL;
+ }
+
+ strs->strs = ares__array_create(sizeof(multistring_data_t),
+ ares__dns_multistring_free_cb);
+ if (strs->strs == NULL) {
+ ares_free(strs);
+ return NULL;
+ }
+
+ return strs;
+}
+
+void ares__dns_multistring_clear(ares__dns_multistring_t *strs)
+{
+ if (strs == NULL) {
+ return;
+ }
+
+ while (ares__array_len(strs->strs)) {
+ ares__array_remove_last(strs->strs);
+ }
+}
+
+void ares__dns_multistring_destroy(ares__dns_multistring_t *strs)
+{
+ if (strs == NULL) {
+ return;
+ }
+ ares__dns_multistring_clear(strs);
+ ares__array_destroy(strs->strs);
+ ares_free(strs->cache_str);
+ ares_free(strs);
+}
+
+ares_status_t ares__dns_multistring_replace_own(ares__dns_multistring_t *strs,
+ size_t idx, unsigned char *str,
+ size_t len)
+{
+ multistring_data_t *data;
+
+ if (strs == NULL || str == NULL || len == 0) {
+ return ARES_EFORMERR;
+ }
+
+ strs->cache_invalidated = ARES_TRUE;
+
+ data = ares__array_at(strs->strs, idx);
+ if (data == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ ares_free(data->data);
+ data->data = str;
+ data->len = len;
+ return ARES_SUCCESS;
+}
+
+ares_status_t ares__dns_multistring_del(ares__dns_multistring_t *strs,
+ size_t idx)
+{
+ if (strs == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ strs->cache_invalidated = ARES_TRUE;
+
+ return ares__array_remove_at(strs->strs, idx);
+}
+
+ares_status_t ares__dns_multistring_add_own(ares__dns_multistring_t *strs,
+ unsigned char *str, size_t len)
+{
+ multistring_data_t *data;
+ ares_status_t status;
+
+ if (strs == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ strs->cache_invalidated = ARES_TRUE;
+
+ /* NOTE: its ok to have an empty string added */
+ if (str == NULL && len != 0) {
+ return ARES_EFORMERR;
+ }
+
+ status = ares__array_insert_last((void **)&data, strs->strs);
+ if (status != ARES_SUCCESS) {
+ return status;
+ }
+
+ data->data = str;
+ data->len = len;
+
+ return ARES_SUCCESS;
+}
+
+size_t ares__dns_multistring_cnt(const ares__dns_multistring_t *strs)
+{
+ if (strs == NULL) {
+ return 0;
+ }
+ return ares__array_len(strs->strs);
+}
+
+const unsigned char *
+ ares__dns_multistring_get(const ares__dns_multistring_t *strs, size_t idx,
+ size_t *len)
+{
+ const multistring_data_t *data;
+
+ if (strs == NULL || len == NULL) {
+ return NULL;
+ }
+
+ data = ares__array_at_const(strs->strs, idx);
+ if (data == NULL) {
+ return NULL;
+ }
+
+ *len = data->len;
+ return data->data;
+}
+
+const unsigned char *
+ ares__dns_multistring_get_combined(ares__dns_multistring_t *strs, size_t *len)
+{
+ ares__buf_t *buf = NULL;
+ size_t i;
+
+ if (strs == NULL || len == NULL) {
+ return NULL;
+ }
+
+ *len = 0;
+
+ /* Return cache if possible */
+ if (!strs->cache_invalidated) {
+ *len = strs->cache_str_len;
+ return strs->cache_str;
+ }
+
+ /* Clear cache */
+ ares_free(strs->cache_str);
+ strs->cache_str = NULL;
+ strs->cache_str_len = 0;
+
+ buf = ares__buf_create();
+
+ for (i = 0; i < ares__array_len(strs->strs); i++) {
+ const multistring_data_t *data = ares__array_at_const(strs->strs, i);
+ if (data == NULL ||
+ ares__buf_append(buf, data->data, data->len) != ARES_SUCCESS) {
+ ares__buf_destroy(buf);
+ return NULL;
+ }
+ }
+
+ strs->cache_str =
+ (unsigned char *)ares__buf_finish_str(buf, &strs->cache_str_len);
+ if (strs->cache_str != NULL) {
+ strs->cache_invalidated = ARES_FALSE;
+ }
+ *len = strs->cache_str_len;
+ return strs->cache_str;
+}
diff --git a/contrib/libs/c-ares/src/lib/record/ares_dns_multistring.h b/contrib/libs/c-ares/src/lib/record/ares_dns_multistring.h
new file mode 100644
index 0000000000..d9aa7ae378
--- /dev/null
+++ b/contrib/libs/c-ares/src/lib/record/ares_dns_multistring.h
@@ -0,0 +1,50 @@
+/* MIT License
+ *
+ * Copyright (c) 2024 Brad House
+ *
+ * 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
+ */
+#ifndef __ARES_DNS_MULTISTRING_H
+#define __ARES_DNS_MULTISTRING_H
+
+struct ares__dns_multistring;
+typedef struct ares__dns_multistring ares__dns_multistring_t;
+
+ares__dns_multistring_t *ares__dns_multistring_create(void);
+void ares__dns_multistring_clear(ares__dns_multistring_t *strs);
+void ares__dns_multistring_destroy(ares__dns_multistring_t *strs);
+ares_status_t ares__dns_multistring_replace_own(ares__dns_multistring_t *strs,
+ size_t idx, unsigned char *str,
+ size_t len);
+ares_status_t ares__dns_multistring_del(ares__dns_multistring_t *strs,
+ size_t idx);
+ares_status_t ares__dns_multistring_add_own(ares__dns_multistring_t *strs,
+ unsigned char *str, size_t len);
+size_t ares__dns_multistring_cnt(const ares__dns_multistring_t *strs);
+const unsigned char *
+ ares__dns_multistring_get(const ares__dns_multistring_t *strs, size_t idx,
+ size_t *len);
+const unsigned char *
+ ares__dns_multistring_get_combined(ares__dns_multistring_t *strs,
+ size_t *len);
+
+#endif
diff --git a/contrib/libs/c-ares/src/lib/ares_dns_name.c b/contrib/libs/c-ares/src/lib/record/ares_dns_name.c
index 85e26cd25b..a437553b0f 100644
--- a/contrib/libs/c-ares/src/lib/ares_dns_name.c
+++ b/contrib/libs/c-ares/src/lib/record/ares_dns_name.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
typedef struct {
@@ -37,7 +35,7 @@ static void ares__nameoffset_free(void *arg)
{
ares_nameoffset_t *off = arg;
if (off == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares_free(off->name);
ares_free(off);
@@ -51,20 +49,20 @@ static ares_status_t ares__nameoffset_create(ares__llist_t **list,
if (list == NULL || name == NULL || ares_strlen(name) == 0 ||
ares_strlen(name) > 255) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (*list == NULL) {
*list = ares__llist_create(ares__nameoffset_free);
}
if (*list == NULL) {
- status = ARES_ENOMEM;
- goto fail;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
off = ares_malloc_zero(sizeof(*off));
if (off == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
off->name = ares_strdup(name);
@@ -72,15 +70,17 @@ static ares_status_t ares__nameoffset_create(ares__llist_t **list,
off->idx = idx;
if (ares__llist_insert_last(*list, off) == NULL) {
- status = ARES_ENOMEM;
- goto fail;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
return ARES_SUCCESS;
+/* LCOV_EXCL_START: OutOfMemory */
fail:
ares__nameoffset_free(off);
return status;
+ /* LCOV_EXCL_STOP */
}
static const ares_nameoffset_t *ares__nameoffset_find(ares__llist_t *list,
@@ -111,7 +111,10 @@ static const ares_nameoffset_t *ares__nameoffset_find(ares__llist_t *list,
prefix_len = name_len - val->name_len;
- if (strcasecmp(val->name, name + prefix_len) != 0) {
+ /* Due to DNS 0x20, lets not inadvertently mangle things, use case-sensitive
+ * matching instead of case-insensitive. This may result in slightly
+ * larger DNS queries overall. */
+ if (strcmp(val->name, name + prefix_len) != 0) {
continue;
}
@@ -128,72 +131,62 @@ static const ares_nameoffset_t *ares__nameoffset_find(ares__llist_t *list,
return longest_match;
}
-typedef struct {
- ares__buf_t **label;
- size_t num;
-} ares_dns_labels_t;
-
-static void ares_dns_labels_free(ares_dns_labels_t *labels)
+static void ares_dns_labels_free_cb(void *arg)
{
- size_t i;
-
- if (labels == NULL) {
+ ares__buf_t **buf = arg;
+ if (buf == NULL) {
return;
}
- for (i = 0; i < labels->num; i++) {
- ares__buf_destroy(labels->label[i]);
- labels->label[i] = NULL;
- }
- ares_free(labels->label);
- labels->label = NULL;
- labels->num = 0;
+ ares__buf_destroy(*buf);
}
-static ares__buf_t *ares_dns_labels_add(ares_dns_labels_t *labels)
+static ares__buf_t *ares_dns_labels_add(ares__array_t *labels)
{
- void *temp;
+ ares__buf_t **buf;
if (labels == NULL) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
}
- temp = ares_realloc_zero(labels->label, sizeof(*labels->label) * labels->num,
- sizeof(*labels->label) * (labels->num + 1));
- if (temp == NULL) {
+ if (ares__array_insert_last((void **)&buf, labels) != ARES_SUCCESS) {
return NULL;
}
- labels->label = temp;
-
- labels->label[labels->num] = ares__buf_create();
- if (labels->label[labels->num] == NULL) {
+ *buf = ares__buf_create();
+ if (*buf == NULL) {
+ ares__array_remove_last(labels);
return NULL;
}
- labels->num++;
- return labels->label[labels->num - 1];
+ return *buf;
}
-static const ares__buf_t *
- ares_dns_labels_get_last(const ares_dns_labels_t *labels)
+static ares__buf_t *ares_dns_labels_get_last(ares__array_t *labels)
{
- if (labels == NULL || labels->num == 0) {
+ ares__buf_t **buf = ares__array_last(labels);
+
+ if (buf == NULL) {
return NULL;
}
- return labels->label[labels->num - 1];
+ return *buf;
}
-static void ares_dns_name_labels_del_last(ares_dns_labels_t *labels)
+static ares__buf_t *ares_dns_labels_get_at(ares__array_t *labels, size_t idx)
{
- if (labels == NULL || labels->num == 0) {
- return;
+ ares__buf_t **buf = ares__array_at(labels, idx);
+
+ if (buf == NULL) {
+ return NULL;
}
- ares__buf_destroy(labels->label[labels->num - 1]);
- labels->label[labels->num - 1] = NULL;
- labels->num--;
+ return *buf;
+}
+
+static void ares_dns_name_labels_del_last(ares__array_t *labels)
+{
+ ares__array_remove_last(labels);
}
static ares_status_t ares_parse_dns_name_escape(ares__buf_t *namebuf,
@@ -209,7 +202,7 @@ static ares_status_t ares_parse_dns_name_escape(ares__buf_t *namebuf,
}
/* If next character is a digit, read 2 more digits */
- if (isdigit(c)) {
+ if (ares__isdigit(c)) {
size_t i;
unsigned int val = 0;
@@ -221,7 +214,7 @@ static ares_status_t ares_parse_dns_name_escape(ares__buf_t *namebuf,
return ARES_EBADNAME;
}
- if (!isdigit(c)) {
+ if (!ares__isdigit(c)) {
return ARES_EBADNAME;
}
val *= 10;
@@ -248,9 +241,9 @@ static ares_status_t ares_parse_dns_name_escape(ares__buf_t *namebuf,
return ares__buf_append_byte(label, c);
}
-static ares_status_t ares_split_dns_name(ares_dns_labels_t *labels,
- ares_bool_t validate_hostname,
- const char *name)
+static ares_status_t ares_split_dns_name(ares__array_t *labels,
+ ares_bool_t validate_hostname,
+ const char *name)
{
ares_status_t status;
ares__buf_t *label = NULL;
@@ -260,29 +253,29 @@ static ares_status_t ares_split_dns_name(ares_dns_labels_t *labels,
unsigned char c;
if (name == NULL || labels == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Put name into a buffer for parsing */
namebuf = ares__buf_create();
if (namebuf == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
if (*name != '\0') {
status =
ares__buf_append(namebuf, (const unsigned char *)name, ares_strlen(name));
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
/* Start with 1 label */
label = ares_dns_labels_add(labels);
if (label == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
while (ares__buf_fetch_bytes(namebuf, &c, 1) == ARES_SUCCESS) {
@@ -290,8 +283,8 @@ static ares_status_t ares_split_dns_name(ares_dns_labels_t *labels,
if (c == '.') {
label = ares_dns_labels_add(labels);
if (label == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
continue;
}
@@ -313,7 +306,7 @@ static ares_status_t ares_split_dns_name(ares_dns_labels_t *labels,
status = ares__buf_append_byte(label, c);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -324,14 +317,15 @@ static ares_status_t ares_split_dns_name(ares_dns_labels_t *labels,
/* If someone passed in "." there could have been 2 blank labels, check for
* that */
- if (labels->num == 1 &&
+ if (ares__array_len(labels) == 1 &&
ares__buf_len(ares_dns_labels_get_last(labels)) == 0) {
ares_dns_name_labels_del_last(labels);
}
/* Scan to make sure label lengths are valid */
- for (i = 0; i < labels->num; i++) {
- size_t len = ares__buf_len(labels->label[i]);
+ for (i = 0; i < ares__array_len(labels); i++) {
+ const ares__buf_t *buf = ares_dns_labels_get_at(labels, i);
+ size_t len = ares__buf_len(buf);
/* No 0-length labels, and no labels over 63 bytes */
if (len == 0 || len > 63) {
status = ARES_EBADNAME;
@@ -341,7 +335,8 @@ static ares_status_t ares_split_dns_name(ares_dns_labels_t *labels,
}
/* Can't exceed maximum (unescaped) length */
- if (labels->num && total_len + labels->num - 1 > 255) {
+ if (ares__array_len(labels) &&
+ total_len + ares__array_len(labels) - 1 > 255) {
status = ARES_EBADNAME;
goto done;
}
@@ -350,9 +345,6 @@ static ares_status_t ares_split_dns_name(ares_dns_labels_t *labels,
done:
ares__buf_destroy(namebuf);
- if (status != ARES_SUCCESS) {
- ares_dns_labels_free(labels);
- }
return status;
}
@@ -363,16 +355,19 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
const ares_nameoffset_t *off = NULL;
size_t name_len;
size_t orig_name_len;
- size_t pos = ares__buf_len(buf);
- ares_dns_labels_t labels;
+ size_t pos = ares__buf_len(buf);
+ ares__array_t *labels = NULL;
char name_copy[512];
ares_status_t status;
if (buf == NULL || name == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
- memset(&labels, 0, sizeof(labels));
+ labels = ares__array_create(sizeof(ares__buf_t *), ares_dns_labels_free_cb);
+ if (labels == NULL) {
+ return ARES_ENOMEM;
+ }
/* NOTE: due to possible escaping, name_copy buffer is > 256 to allow for
* this */
@@ -393,23 +388,24 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
if (off == NULL || off->name_len != orig_name_len) {
size_t i;
- status = ares_split_dns_name(&labels, validate_hostname, name_copy);
+ status = ares_split_dns_name(labels, validate_hostname, name_copy);
if (status != ARES_SUCCESS) {
goto done;
}
- for (i = 0; i < labels.num; i++) {
- size_t len = 0;
- const unsigned char *ptr = ares__buf_peek(labels.label[i], &len);
+ for (i = 0; i < ares__array_len(labels); i++) {
+ size_t len = 0;
+ const ares__buf_t *lbuf = ares_dns_labels_get_at(labels, i);
+ const unsigned char *ptr = ares__buf_peek(lbuf, &len);
status = ares__buf_append_byte(buf, (unsigned char)(len & 0xFF));
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append(buf, ptr, len);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -417,7 +413,7 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
if (off == NULL) {
status = ares__buf_append_byte(buf, 0);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
}
@@ -428,7 +424,7 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
(unsigned short)0xC000 | (unsigned short)(off->idx & 0x3FFF);
status = ares__buf_append_be16(buf, u16);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -438,14 +434,14 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
name_len > 0) {
status = ares__nameoffset_create(list, name /* not truncated copy! */, pos);
if (status != ARES_SUCCESS) {
- goto done;
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
status = ARES_SUCCESS;
done:
- ares_dns_labels_free(&labels);
+ ares__array_destroy(labels);
return status;
}
@@ -509,7 +505,7 @@ static ares_status_t ares__fetch_dnsname_into_buf(ares__buf_t *buf,
status = ares__buf_append(dest, escape, sizeof(escape));
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
continue;
@@ -519,13 +515,13 @@ static ares_status_t ares__fetch_dnsname_into_buf(ares__buf_t *buf,
if (is_reservedch(c)) {
status = ares__buf_append_byte(dest, '\\');
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
status = ares__buf_append_byte(dest, c);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -641,7 +637,7 @@ ares_status_t ares__dns_name_parse(ares__buf_t *buf, char **name,
if (ares__buf_len(namebuf) != 0 && name != NULL) {
status = ares__buf_append_byte(namebuf, '.');
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -660,8 +656,8 @@ ares_status_t ares__dns_name_parse(ares__buf_t *buf, char **name,
if (name != NULL) {
*name = ares__buf_finish_str(namebuf, NULL);
if (*name == NULL) {
- status = ARES_ENOMEM;
- goto fail;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
diff --git a/contrib/libs/c-ares/src/lib/ares_dns_parse.c b/contrib/libs/c-ares/src/lib/record/ares_dns_parse.c
index 8b771ee1fa..57cb0f714e 100644
--- a/contrib/libs/c-ares/src/lib/ares_dns_parse.c
+++ b/contrib/libs/c-ares/src/lib/record/ares_dns_parse.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include <limits.h>
#ifdef HAVE_STDINT_H
@@ -62,14 +60,16 @@ static ares_status_t ares_dns_parse_and_set_dns_name(ares__buf_t *buf,
return ARES_SUCCESS;
}
-static ares_status_t ares_dns_parse_and_set_dns_str(
- ares__buf_t *buf, size_t max_len, ares_bool_t allow_multiple,
- ares_dns_rr_t *rr, ares_dns_rr_key_t key, ares_bool_t blank_allowed)
+static ares_status_t ares_dns_parse_and_set_dns_str(ares__buf_t *buf,
+ size_t max_len,
+ ares_dns_rr_t *rr,
+ ares_dns_rr_key_t key,
+ ares_bool_t blank_allowed)
{
ares_status_t status;
char *str = NULL;
- status = ares__buf_parse_dns_str(buf, max_len, &str, allow_multiple);
+ status = ares__buf_parse_dns_str(buf, max_len, &str);
if (status != ARES_SUCCESS) {
return status;
}
@@ -88,23 +88,21 @@ static ares_status_t ares_dns_parse_and_set_dns_str(
}
static ares_status_t
- ares_dns_parse_and_set_dns_binstr(ares__buf_t *buf, size_t max_len,
- ares_bool_t allow_multiple,
- ares_dns_rr_t *rr, ares_dns_rr_key_t key)
+ ares_dns_parse_and_set_dns_abin(ares__buf_t *buf, size_t max_len,
+ ares_dns_rr_t *rr, ares_dns_rr_key_t key,
+ ares_bool_t validate_printable)
{
- ares_status_t status;
- unsigned char *bin = NULL;
- size_t bin_len = 0;
+ ares_status_t status;
+ ares__dns_multistring_t *strs = NULL;
- status =
- ares__buf_parse_dns_binstr(buf, max_len, &bin, &bin_len, allow_multiple);
+ status = ares__buf_parse_dns_abinstr(buf, max_len, &strs, validate_printable);
if (status != ARES_SUCCESS) {
return status;
}
- status = ares_dns_rr_set_bin_own(rr, key, bin, bin_len);
+ status = ares_dns_rr_set_abin_own(rr, key, strs);
if (status != ARES_SUCCESS) {
- ares_free(bin);
+ ares__dns_multistring_destroy(strs);
return status;
}
return ARES_SUCCESS;
@@ -257,7 +255,7 @@ static ares_status_t ares_dns_parse_rr_hinfo(ares__buf_t *buf,
/* CPU */
status = ares_dns_parse_and_set_dns_str(
- buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), ARES_FALSE, rr,
+ buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
ARES_RR_HINFO_CPU, ARES_TRUE);
if (status != ARES_SUCCESS) {
return status;
@@ -265,7 +263,7 @@ static ares_status_t ares_dns_parse_rr_hinfo(ares__buf_t *buf,
/* OS */
status = ares_dns_parse_and_set_dns_str(
- buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), ARES_FALSE, rr,
+ buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
ARES_RR_HINFO_OS, ARES_TRUE);
return status;
@@ -292,8 +290,8 @@ static ares_status_t ares_dns_parse_rr_mx(ares__buf_t *buf, ares_dns_rr_t *rr,
static ares_status_t ares_dns_parse_rr_txt(ares__buf_t *buf, ares_dns_rr_t *rr,
size_t rdlength)
{
- return ares_dns_parse_and_set_dns_binstr(buf, rdlength, ARES_TRUE, rr,
- ARES_RR_TXT_DATA);
+ return ares_dns_parse_and_set_dns_abin(buf, rdlength, rr, ARES_RR_TXT_DATA,
+ ARES_FALSE);
}
static ares_status_t ares_dns_parse_rr_sig(ares__buf_t *buf, ares_dns_rr_t *rr,
@@ -430,7 +428,7 @@ static ares_status_t ares_dns_parse_rr_naptr(ares__buf_t *buf,
/* FLAGS */
status = ares_dns_parse_and_set_dns_str(
- buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), ARES_FALSE, rr,
+ buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
ARES_RR_NAPTR_FLAGS, ARES_TRUE);
if (status != ARES_SUCCESS) {
return status;
@@ -438,7 +436,7 @@ static ares_status_t ares_dns_parse_rr_naptr(ares__buf_t *buf,
/* SERVICES */
status = ares_dns_parse_and_set_dns_str(
- buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), ARES_FALSE, rr,
+ buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
ARES_RR_NAPTR_SERVICES, ARES_TRUE);
if (status != ARES_SUCCESS) {
return status;
@@ -446,7 +444,7 @@ static ares_status_t ares_dns_parse_rr_naptr(ares__buf_t *buf,
/* REGEXP */
status = ares_dns_parse_and_set_dns_str(
- buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), ARES_FALSE, rr,
+ buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
ARES_RR_NAPTR_REGEXP, ARES_TRUE);
if (status != ARES_SUCCESS) {
return status;
@@ -731,7 +729,7 @@ static ares_status_t ares_dns_parse_rr_caa(ares__buf_t *buf, ares_dns_rr_t *rr,
/* Tag */
status = ares_dns_parse_and_set_dns_str(
- buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), ARES_FALSE, rr,
+ buf, ares_dns_rr_remaining_len(buf, orig_len, rdlength), rr,
ARES_RR_CAA_TAG, ARES_FALSE);
if (status != ARES_SUCCESS) {
return status;
@@ -925,7 +923,7 @@ static ares_status_t ares_dns_parse_header(ares__buf_t *buf, unsigned int flags,
status =
ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_ANSWER, *ancount);
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -933,7 +931,7 @@ static ares_status_t ares_dns_parse_header(ares__buf_t *buf, unsigned int flags,
status =
ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_AUTHORITY, *nscount);
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -941,7 +939,7 @@ static ares_status_t ares_dns_parse_header(ares__buf_t *buf, unsigned int flags,
status =
ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_ADDITIONAL, *arcount);
if (status != ARES_SUCCESS) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -1216,7 +1214,7 @@ static ares_status_t ares_dns_parse_buf(ares__buf_t *buf, unsigned int flags,
unsigned short i;
if (buf == NULL || dnsrec == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Maximum DNS packet size is 64k, even over TCP */
diff --git a/contrib/libs/c-ares/src/lib/ares_dns_private.h b/contrib/libs/c-ares/src/lib/record/ares_dns_private.h
index e8e783d559..5b86fed51f 100644
--- a/contrib/libs/c-ares/src/lib/ares_dns_private.h
+++ b/contrib/libs/c-ares/src/lib/record/ares_dns_private.h
@@ -26,6 +26,8 @@
#ifndef __ARES_DNS_PRIVATE_H
#define __ARES_DNS_PRIVATE_H
+ares_status_t ares_dns_record_duplicate_ex(ares_dns_record_t **dest,
+ const ares_dns_record_t *src);
ares_bool_t ares_dns_rec_type_allow_name_compression(ares_dns_rec_type_t type);
ares_bool_t ares_dns_opcode_isvalid(ares_dns_opcode_t opcode);
ares_bool_t ares_dns_rcode_isvalid(ares_dns_rcode_t rcode);
@@ -36,20 +38,32 @@ ares_bool_t ares_dns_class_isvalid(ares_dns_class_t qclass,
ares_dns_rec_type_t type,
ares_bool_t is_query);
ares_bool_t ares_dns_section_isvalid(ares_dns_section_t sect);
-ares_status_t ares_dns_rr_set_str_own(ares_dns_rr_t *dns_rr,
- ares_dns_rr_key_t key, char *val);
-ares_status_t ares_dns_rr_set_bin_own(ares_dns_rr_t *dns_rr,
- ares_dns_rr_key_t key, unsigned char *val,
- size_t len);
-ares_status_t ares_dns_rr_set_opt_own(ares_dns_rr_t *dns_rr,
- ares_dns_rr_key_t key, unsigned short opt,
- unsigned char *val, size_t val_len);
-ares_status_t ares_dns_record_rr_prealloc(ares_dns_record_t *dnsrec,
- ares_dns_section_t sect, size_t cnt);
-ares_bool_t ares_dns_has_opt_rr(const ares_dns_record_t *rec);
+ares_status_t ares_dns_rr_set_str_own(ares_dns_rr_t *dns_rr,
+ ares_dns_rr_key_t key, char *val);
+ares_status_t ares_dns_rr_set_bin_own(ares_dns_rr_t *dns_rr,
+ ares_dns_rr_key_t key, unsigned char *val,
+ size_t len);
+ares_status_t ares_dns_rr_set_abin_own(ares_dns_rr_t *dns_rr,
+ ares_dns_rr_key_t key,
+ ares__dns_multistring_t *strs);
+ares_status_t ares_dns_rr_set_opt_own(ares_dns_rr_t *dns_rr,
+ ares_dns_rr_key_t key, unsigned short opt,
+ unsigned char *val, size_t val_len);
+ares_status_t ares_dns_record_rr_prealloc(ares_dns_record_t *dnsrec,
+ ares_dns_section_t sect, size_t cnt);
+ares_dns_rr_t *ares_dns_get_opt_rr(ares_dns_record_t *rec);
+const ares_dns_rr_t *ares_dns_get_opt_rr_const(const ares_dns_record_t *rec);
void ares_dns_record_write_ttl_decrement(ares_dns_record_t *dnsrec,
unsigned int ttl_decrement);
+/* Same as ares_dns_write() but appends to an existing buffer object */
+ares_status_t ares_dns_write_buf(const ares_dns_record_t *dnsrec,
+ ares__buf_t *buf);
+
+/* Same as ares_dns_write_buf(), but prepends a 16bit length */
+ares_status_t ares_dns_write_buf_tcp(const ares_dns_record_t *dnsrec,
+ ares__buf_t *buf);
+
/*! Create a DNS record object for a query. The arguments are the same as
* those for ares_create_query().
*
@@ -120,8 +134,7 @@ typedef struct {
} ares__dns_mx_t;
typedef struct {
- char *data;
- size_t data_len;
+ ares__dns_multistring_t *strs;
} ares__dns_txt_t;
typedef struct {
@@ -164,18 +177,11 @@ typedef struct {
} ares__dns_optval_t;
typedef struct {
- ares__dns_optval_t *optval; /*!< Attribute/value pairs */
- size_t cnt; /*!< Count of Attribute/Value pairs */
- size_t alloc; /*!< Allocated count of attribute/value
- * pairs */
-} ares__dns_options_t;
-
-typedef struct {
- unsigned short udp_size; /*!< taken from class */
- unsigned char version; /*!< taken from bits 8-16 of ttl */
- unsigned short flags; /*!< Flags, remaining 16 bits, though only
- * 1 currently defined */
- ares__dns_options_t *options; /*!< Attribute/Value pairs */
+ unsigned short udp_size; /*!< taken from class */
+ unsigned char version; /*!< taken from bits 8-16 of ttl */
+ unsigned short flags; /*!< Flags, remaining 16 bits, though only
+ * 1 currently defined */
+ ares__array_t *options; /*!< Type is ares__dns_optval_t */
} ares__dns_opt_t;
typedef struct {
@@ -187,9 +193,9 @@ typedef struct {
} ares__dns_tlsa_t;
typedef struct {
- unsigned short priority;
- char *target;
- ares__dns_options_t *params;
+ unsigned short priority;
+ char *target;
+ ares__array_t *params; /*!< Type is ares__dns_optval_t */
} ares__dns_svcb_t;
typedef struct {
@@ -258,21 +264,10 @@ struct ares_dns_record {
* the ttl of any resource records by
* this amount. Used for cache */
- ares_dns_qd_t *qd;
- size_t qdcount;
- size_t qdalloc;
-
- ares_dns_rr_t *an;
- size_t ancount;
- size_t analloc;
-
- ares_dns_rr_t *ns;
- size_t nscount;
- size_t nsalloc;
-
- ares_dns_rr_t *ar;
- size_t arcount;
- size_t aralloc;
+ ares__array_t *qd; /*!< Type is ares_dns_qd_t */
+ ares__array_t *an; /*!< Type is ares_dns_rr_t */
+ ares__array_t *ns; /*!< Type is ares_dns_rr_t */
+ ares__array_t *ar; /*!< Type is ares_dns_rr_t */
};
#endif
diff --git a/contrib/libs/c-ares/src/lib/ares_dns_record.c b/contrib/libs/c-ares/src/lib/record/ares_dns_record.c
index e6b7bf7fe1..1470494909 100644
--- a/contrib/libs/c-ares/src/lib/ares_dns_record.c
+++ b/contrib/libs/c-ares/src/lib/record/ares_dns_record.c
@@ -23,14 +23,31 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include <limits.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
+static void ares__dns_rr_free(ares_dns_rr_t *rr);
+
+static void ares_dns_qd_free_cb(void *arg)
+{
+ ares_dns_qd_t *qd = arg;
+ if (qd == NULL) {
+ return;
+ }
+ ares_free(qd->name);
+}
+
+static void ares_dns_rr_free_cb(void *arg)
+{
+ ares_dns_rr_t *rr = arg;
+ if (rr == NULL) {
+ return;
+ }
+ ares__dns_rr_free(rr);
+}
ares_status_t ares_dns_record_create(ares_dns_record_t **dnsrec,
unsigned short id, unsigned short flags,
@@ -57,6 +74,22 @@ ares_status_t ares_dns_record_create(ares_dns_record_t **dnsrec,
(*dnsrec)->flags = flags;
(*dnsrec)->opcode = opcode;
(*dnsrec)->rcode = rcode;
+ (*dnsrec)->qd =
+ ares__array_create(sizeof(ares_dns_qd_t), ares_dns_qd_free_cb);
+ (*dnsrec)->an =
+ ares__array_create(sizeof(ares_dns_rr_t), ares_dns_rr_free_cb);
+ (*dnsrec)->ns =
+ ares__array_create(sizeof(ares_dns_rr_t), ares_dns_rr_free_cb);
+ (*dnsrec)->ar =
+ ares__array_create(sizeof(ares_dns_rr_t), ares_dns_rr_free_cb);
+
+ if ((*dnsrec)->qd == NULL || (*dnsrec)->an == NULL || (*dnsrec)->ns == NULL ||
+ (*dnsrec)->ar == NULL) {
+ ares_dns_record_destroy(*dnsrec);
+ *dnsrec = NULL;
+ return ARES_ENOMEM;
+ }
+
return ARES_SUCCESS;
}
@@ -68,6 +101,15 @@ unsigned short ares_dns_record_get_id(const ares_dns_record_t *dnsrec)
return dnsrec->id;
}
+ares_bool_t ares_dns_record_set_id(ares_dns_record_t *dnsrec, unsigned short id)
+{
+ if (dnsrec == NULL) {
+ return ARES_FALSE;
+ }
+ dnsrec->id = id;
+ return ARES_TRUE;
+}
+
unsigned short ares_dns_record_get_flags(const ares_dns_record_t *dnsrec)
{
if (dnsrec == NULL) {
@@ -92,21 +134,6 @@ ares_dns_rcode_t ares_dns_record_get_rcode(const ares_dns_record_t *dnsrec)
return dnsrec->rcode;
}
-static void ares__dns_options_free(ares__dns_options_t *options)
-{
- size_t i;
-
- if (options == NULL) {
- return;
- }
-
- for (i = 0; i < options->cnt; i++) {
- ares_free(options->optval[i].val);
- }
- ares_free(options->optval);
- ares_free(options);
-}
-
static void ares__dns_rr_free(ares_dns_rr_t *rr)
{
ares_free(rr->name);
@@ -145,7 +172,7 @@ static void ares__dns_rr_free(ares_dns_rr_t *rr)
break;
case ARES_REC_TYPE_TXT:
- ares_free(rr->r.txt.data);
+ ares__dns_multistring_destroy(rr->r.txt.strs);
break;
case ARES_REC_TYPE_SIG:
@@ -165,7 +192,7 @@ static void ares__dns_rr_free(ares_dns_rr_t *rr)
break;
case ARES_REC_TYPE_OPT:
- ares__dns_options_free(rr->r.opt.options);
+ ares__array_destroy(rr->r.opt.options);
break;
case ARES_REC_TYPE_TLSA:
@@ -174,12 +201,12 @@ static void ares__dns_rr_free(ares_dns_rr_t *rr)
case ARES_REC_TYPE_SVCB:
ares_free(rr->r.svcb.target);
- ares__dns_options_free(rr->r.svcb.params);
+ ares__array_destroy(rr->r.svcb.params);
break;
case ARES_REC_TYPE_HTTPS:
ares_free(rr->r.https.target);
- ares__dns_options_free(rr->r.https.params);
+ ares__array_destroy(rr->r.https.params);
break;
case ARES_REC_TYPE_URI:
@@ -199,35 +226,21 @@ static void ares__dns_rr_free(ares_dns_rr_t *rr)
void ares_dns_record_destroy(ares_dns_record_t *dnsrec)
{
- size_t i;
-
if (dnsrec == NULL) {
return;
}
/* Free questions */
- for (i = 0; i < dnsrec->qdcount; i++) {
- ares_free(dnsrec->qd[i].name);
- }
- ares_free(dnsrec->qd);
+ ares__array_destroy(dnsrec->qd);
/* Free answers */
- for (i = 0; i < dnsrec->ancount; i++) {
- ares__dns_rr_free(&dnsrec->an[i]);
- }
- ares_free(dnsrec->an);
+ ares__array_destroy(dnsrec->an);
/* Free authority */
- for (i = 0; i < dnsrec->nscount; i++) {
- ares__dns_rr_free(&dnsrec->ns[i]);
- }
- ares_free(dnsrec->ns);
+ ares__array_destroy(dnsrec->ns);
/* Free additional */
- for (i = 0; i < dnsrec->arcount; i++) {
- ares__dns_rr_free(&dnsrec->ar[i]);
- }
- ares_free(dnsrec->ar);
+ ares__array_destroy(dnsrec->ar);
ares_free(dnsrec);
}
@@ -237,7 +250,7 @@ size_t ares_dns_record_query_cnt(const ares_dns_record_t *dnsrec)
if (dnsrec == NULL) {
return 0;
}
- return dnsrec->qdcount;
+ return ares__array_len(dnsrec->qd);
}
ares_status_t ares_dns_record_query_add(ares_dns_record_t *dnsrec,
@@ -245,8 +258,9 @@ 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_dns_qd_t *temp = NULL;
size_t idx;
+ ares_dns_qd_t *qd;
+ ares_status_t status;
if (dnsrec == NULL || name == NULL ||
!ares_dns_rec_type_isvalid(qtype, ARES_TRUE) ||
@@ -254,46 +268,39 @@ ares_status_t ares_dns_record_query_add(ares_dns_record_t *dnsrec,
return ARES_EFORMERR;
}
- if (dnsrec->qdcount >= dnsrec->qdalloc) {
- size_t alloc_cnt = ares__round_up_pow2(dnsrec->qdcount + 1);
-
- temp = ares_realloc_zero(dnsrec->qd, sizeof(*temp) * (dnsrec->qdalloc),
- sizeof(*temp) * alloc_cnt);
- if (temp == NULL) {
- return ARES_ENOMEM;
- }
-
- dnsrec->qdalloc = alloc_cnt;
- dnsrec->qd = temp;
+ idx = ares__array_len(dnsrec->qd);
+ status = ares__array_insert_last((void **)&qd, dnsrec->qd);
+ if (status != ARES_SUCCESS) {
+ return status;
}
- idx = dnsrec->qdcount;
-
- dnsrec->qd[idx].name = ares_strdup(name);
- if (dnsrec->qd[idx].name == NULL) {
- /* No need to clean up anything */
+ qd->name = ares_strdup(name);
+ if (qd->name == NULL) {
+ ares__array_remove_at(dnsrec->qd, idx);
return ARES_ENOMEM;
}
-
- dnsrec->qd[idx].qtype = qtype;
- dnsrec->qd[idx].qclass = qclass;
- dnsrec->qdcount++;
+ qd->qtype = qtype;
+ qd->qclass = qclass;
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;
+ char *orig_name = NULL;
+ ares_dns_qd_t *qd;
- if (dnsrec == NULL || idx >= dnsrec->qdcount || name == NULL) {
+ if (dnsrec == NULL || idx >= ares__array_len(dnsrec->qd) || 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;
+
+ qd = ares__array_at(dnsrec->qd, idx);
+
+ orig_name = qd->name;
+ qd->name = ares_strdup(name);
+ if (qd->name == NULL) {
+ qd->name = orig_name; /* LCOV_EXCL_LINE: OutOfMemory */
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
ares_free(orig_name);
@@ -304,12 +311,15 @@ 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_qd_t *qd;
+
+ if (dnsrec == NULL || idx >= ares__array_len(dnsrec->qd) ||
!ares_dns_rec_type_isvalid(qtype, ARES_TRUE)) {
return ARES_EFORMERR;
}
- dnsrec->qd[idx].qtype = qtype;
+ qd = ares__array_at(dnsrec->qd, idx);
+ qd->qtype = qtype;
return ARES_SUCCESS;
}
@@ -319,20 +329,22 @@ ares_status_t ares_dns_record_query_get(const ares_dns_record_t *dnsrec,
ares_dns_rec_type_t *qtype,
ares_dns_class_t *qclass)
{
- if (dnsrec == NULL || idx >= dnsrec->qdcount) {
+ const ares_dns_qd_t *qd;
+ if (dnsrec == NULL || idx >= ares__array_len(dnsrec->qd)) {
return ARES_EFORMERR;
}
+ qd = ares__array_at(dnsrec->qd, idx);
if (name != NULL) {
- *name = dnsrec->qd[idx].name;
+ *name = qd->name;
}
if (qtype != NULL) {
- *qtype = dnsrec->qd[idx].qtype;
+ *qtype = qd->qtype;
}
if (qclass != NULL) {
- *qclass = dnsrec->qd[idx].qclass;
+ *qclass = qd->qclass;
}
return ARES_SUCCESS;
@@ -347,59 +359,42 @@ size_t ares_dns_record_rr_cnt(const ares_dns_record_t *dnsrec,
switch (sect) {
case ARES_SECTION_ANSWER:
- return dnsrec->ancount;
+ return ares__array_len(dnsrec->an);
case ARES_SECTION_AUTHORITY:
- return dnsrec->nscount;
+ return ares__array_len(dnsrec->ns);
case ARES_SECTION_ADDITIONAL:
- return dnsrec->arcount;
+ return ares__array_len(dnsrec->ar);
}
- return 0;
+ return 0; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares_status_t ares_dns_record_rr_prealloc(ares_dns_record_t *dnsrec,
ares_dns_section_t sect, size_t cnt)
{
- ares_dns_rr_t **rr_ptr = NULL;
- size_t *rr_alloc = NULL;
- ares_dns_rr_t *temp = NULL;
+ ares__array_t *arr = NULL;
- if (dnsrec == NULL || cnt == 0 || !ares_dns_section_isvalid(sect)) {
+ if (dnsrec == NULL || !ares_dns_section_isvalid(sect)) {
return ARES_EFORMERR;
}
switch (sect) {
case ARES_SECTION_ANSWER:
- rr_ptr = &dnsrec->an;
- rr_alloc = &dnsrec->analloc;
+ arr = dnsrec->an;
break;
case ARES_SECTION_AUTHORITY:
- rr_ptr = &dnsrec->ns;
- rr_alloc = &dnsrec->nsalloc;
+ arr = dnsrec->ns;
break;
case ARES_SECTION_ADDITIONAL:
- rr_ptr = &dnsrec->ar;
- rr_alloc = &dnsrec->aralloc;
+ arr = dnsrec->ar;
break;
}
- /* Round up cnt to a power of 2 */
- cnt = ares__round_up_pow2(cnt);
-
- /* Already have that */
- if (cnt <= *rr_alloc) {
- return ARES_SUCCESS;
- }
-
- temp = ares_realloc_zero(*rr_ptr, sizeof(*temp) * (*rr_alloc),
- sizeof(*temp) * cnt);
- if (temp == NULL) {
- return ARES_ENOMEM;
+ if (cnt < ares__array_len(arr)) {
+ return ARES_EFORMERR;
}
- *rr_alloc = cnt;
- *rr_ptr = temp;
- return ARES_SUCCESS;
+ return ares__array_set_size(arr, cnt);
}
ares_status_t ares_dns_record_rr_add(ares_dns_rr_t **rr_out,
@@ -408,11 +403,10 @@ ares_status_t ares_dns_record_rr_add(ares_dns_rr_t **rr_out,
ares_dns_rec_type_t type,
ares_dns_class_t rclass, unsigned int ttl)
{
- ares_dns_rr_t **rr_ptr = NULL;
- ares_dns_rr_t *rr = NULL;
- size_t *rr_len = NULL;
- ares_status_t status;
- size_t idx;
+ ares_dns_rr_t *rr = NULL;
+ ares__array_t *arr = NULL;
+ ares_status_t status;
+ size_t idx;
if (dnsrec == NULL || name == NULL || rr_out == NULL ||
!ares_dns_section_isvalid(sect) ||
@@ -425,30 +419,25 @@ ares_status_t ares_dns_record_rr_add(ares_dns_rr_t **rr_out,
switch (sect) {
case ARES_SECTION_ANSWER:
- rr_ptr = &dnsrec->an;
- rr_len = &dnsrec->ancount;
+ arr = dnsrec->an;
break;
case ARES_SECTION_AUTHORITY:
- rr_ptr = &dnsrec->ns;
- rr_len = &dnsrec->nscount;
+ arr = dnsrec->ns;
break;
case ARES_SECTION_ADDITIONAL:
- rr_ptr = &dnsrec->ar;
- rr_len = &dnsrec->arcount;
+ arr = dnsrec->ar;
break;
}
- status = ares_dns_record_rr_prealloc(dnsrec, sect, *rr_len + 1);
+ idx = ares__array_len(arr);
+ status = ares__array_insert_last((void **)&rr, arr);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
- idx = *rr_len;
- rr = &(*rr_ptr)[idx];
-
rr->name = ares_strdup(name);
if (rr->name == NULL) {
- /* No need to clean up anything */
+ ares__array_remove_at(arr, idx);
return ARES_ENOMEM;
}
@@ -456,7 +445,6 @@ ares_status_t ares_dns_record_rr_add(ares_dns_rr_t **rr_out,
rr->type = type;
rr->rclass = rclass;
rr->ttl = ttl;
- (*rr_len)++;
*rr_out = rr;
@@ -466,9 +454,7 @@ ares_status_t ares_dns_record_rr_add(ares_dns_rr_t **rr_out,
ares_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec,
ares_dns_section_t sect, size_t idx)
{
- ares_dns_rr_t *rr_ptr = NULL;
- size_t *rr_len = NULL;
- size_t cnt_after;
+ ares__array_t *arr = NULL;
if (dnsrec == NULL || !ares_dns_section_isvalid(sect)) {
return ARES_EFORMERR;
@@ -476,40 +462,23 @@ ares_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec,
switch (sect) {
case ARES_SECTION_ANSWER:
- rr_ptr = dnsrec->an;
- rr_len = &dnsrec->ancount;
+ arr = dnsrec->an;
break;
case ARES_SECTION_AUTHORITY:
- rr_ptr = dnsrec->ns;
- rr_len = &dnsrec->nscount;
+ arr = dnsrec->ns;
break;
case ARES_SECTION_ADDITIONAL:
- rr_ptr = dnsrec->ar;
- rr_len = &dnsrec->arcount;
+ arr = dnsrec->ar;
break;
}
- if (idx >= *rr_len) {
- return ARES_EFORMERR;
- }
-
- ares__dns_rr_free(&rr_ptr[idx]);
-
- cnt_after = *rr_len - idx - 1;
-
- if (cnt_after) {
- memmove(&rr_ptr[idx], &rr_ptr[idx + 1], sizeof(*rr_ptr) * cnt_after);
- }
-
- (*rr_len)--;
- return ARES_SUCCESS;
+ return ares__array_remove_at(arr, idx);
}
ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec,
ares_dns_section_t sect, size_t idx)
{
- ares_dns_rr_t *rr_ptr = NULL;
- size_t rr_len = 0;
+ ares__array_t *arr = NULL;
if (dnsrec == NULL || !ares_dns_section_isvalid(sect)) {
return NULL;
@@ -517,24 +486,17 @@ ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec,
switch (sect) {
case ARES_SECTION_ANSWER:
- rr_ptr = dnsrec->an;
- rr_len = dnsrec->ancount;
+ arr = dnsrec->an;
break;
case ARES_SECTION_AUTHORITY:
- rr_ptr = dnsrec->ns;
- rr_len = dnsrec->nscount;
+ arr = dnsrec->ns;
break;
case ARES_SECTION_ADDITIONAL:
- rr_ptr = dnsrec->ar;
- rr_len = dnsrec->arcount;
+ arr = dnsrec->ar;
break;
}
- if (idx >= rr_len) {
- return NULL;
- }
-
- return &rr_ptr[idx];
+ return ares__array_at(arr, idx);
}
const ares_dns_rr_t *
@@ -580,7 +542,7 @@ static void *ares_dns_rr_data_ptr(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
size_t **lenptr)
{
if (dns_rr == NULL || dns_rr->type != ares_dns_rr_key_to_rec_type(key)) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
}
switch (key) {
@@ -664,11 +626,7 @@ static void *ares_dns_rr_data_ptr(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
return &dns_rr->r.sig.signature;
case ARES_RR_TXT_DATA:
- if (lenptr == NULL) {
- return NULL;
- }
- *lenptr = &dns_rr->r.txt.data_len;
- return &dns_rr->r.txt.data;
+ return &dns_rr->r.txt.strs;
case ARES_RR_SRV_PRIORITY:
return &dns_rr->r.srv.priority;
@@ -883,26 +841,138 @@ const unsigned char *ares_dns_rr_get_bin(const ares_dns_rr_t *dns_rr,
size_t const *bin_len = NULL;
if ((ares_dns_rr_key_datatype(key) != ARES_DATATYPE_BIN &&
- ares_dns_rr_key_datatype(key) != ARES_DATATYPE_BINP) ||
+ ares_dns_rr_key_datatype(key) != ARES_DATATYPE_BINP &&
+ ares_dns_rr_key_datatype(key) != ARES_DATATYPE_ABINP) ||
len == NULL) {
return NULL;
}
+ /* Array of strings, return concatenated version */
+ if (ares_dns_rr_key_datatype(key) == ARES_DATATYPE_ABINP) {
+ ares__dns_multistring_t * const *strs =
+ ares_dns_rr_data_ptr_const(dns_rr, key, NULL);
+
+ if (strs == NULL) {
+ return NULL;
+ }
+
+ return ares__dns_multistring_get_combined(*strs, len);
+ }
+
+ /* Not a multi-string, just straight binary data */
bin = ares_dns_rr_data_ptr_const(dns_rr, key, &bin_len);
if (bin == NULL) {
- return 0;
+ return NULL;
}
/* Shouldn't be possible */
if (bin_len == NULL) {
return NULL;
}
-
*len = *bin_len;
return *bin;
}
+size_t ares_dns_rr_get_abin_cnt(const ares_dns_rr_t *dns_rr,
+ ares_dns_rr_key_t key)
+{
+ ares__dns_multistring_t * const *strs;
+
+ if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_ABINP) {
+ return 0;
+ }
+
+ strs = ares_dns_rr_data_ptr_const(dns_rr, key, NULL);
+ if (strs == NULL) {
+ return 0;
+ }
+
+ return ares__dns_multistring_cnt(*strs);
+}
+
+const unsigned char *ares_dns_rr_get_abin(const ares_dns_rr_t *dns_rr,
+ ares_dns_rr_key_t key, size_t idx,
+ size_t *len)
+{
+ ares__dns_multistring_t * const *strs;
+
+ if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_ABINP) {
+ return NULL;
+ }
+
+ strs = ares_dns_rr_data_ptr_const(dns_rr, key, NULL);
+ if (strs == NULL) {
+ return NULL;
+ }
+
+ return ares__dns_multistring_get(*strs, idx, len);
+}
+
+ares_status_t ares_dns_rr_del_abin(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
+ size_t idx)
+{
+ ares__dns_multistring_t **strs;
+
+ if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_ABINP) {
+ return ARES_EFORMERR;
+ }
+
+ strs = ares_dns_rr_data_ptr(dns_rr, key, NULL);
+ if (strs == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ return ares__dns_multistring_del(*strs, idx);
+}
+
+ares_status_t ares_dns_rr_add_abin(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
+ const unsigned char *val, size_t len)
+{
+ ares_status_t status;
+ ares_dns_datatype_t datatype = ares_dns_rr_key_datatype(key);
+ ares_bool_t is_nullterm =
+ (datatype == ARES_DATATYPE_ABINP) ? ARES_TRUE : ARES_FALSE;
+ size_t alloclen = is_nullterm ? len + 1 : len;
+ unsigned char *temp;
+ ares__dns_multistring_t **strs;
+
+ if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_ABINP) {
+ return ARES_EFORMERR;
+ }
+
+ strs = ares_dns_rr_data_ptr(dns_rr, key, NULL);
+ if (strs == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ if (*strs == NULL) {
+ *strs = ares__dns_multistring_create();
+ if (*strs == NULL) {
+ return ARES_ENOMEM;
+ }
+ }
+
+ temp = ares_malloc(alloclen);
+ if (temp == NULL) {
+ return ARES_ENOMEM;
+ }
+
+ memcpy(temp, val, len);
+
+ /* NULL-term ABINP */
+ if (is_nullterm) {
+ temp[len] = 0;
+ }
+
+ status = ares__dns_multistring_add_own(*strs, temp, len);
+ if (status != ARES_SUCCESS) {
+ ares_free(temp);
+ }
+
+ return status;
+}
+
const char *ares_dns_rr_get_str(const ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key)
{
@@ -924,7 +994,7 @@ const char *ares_dns_rr_get_str(const ares_dns_rr_t *dns_rr,
size_t ares_dns_rr_get_opt_cnt(const ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key)
{
- ares__dns_options_t * const *opts;
+ ares__array_t * const *opts;
if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_OPT) {
return 0;
@@ -935,14 +1005,15 @@ size_t ares_dns_rr_get_opt_cnt(const ares_dns_rr_t *dns_rr,
return 0;
}
- return (*opts)->cnt;
+ return ares__array_len(*opts);
}
unsigned short ares_dns_rr_get_opt(const ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key, size_t idx,
const unsigned char **val, size_t *val_len)
{
- ares__dns_options_t * const *opts;
+ ares__array_t * const *opts;
+ const ares__dns_optval_t *opt;
if (val) {
*val = NULL;
@@ -960,26 +1031,29 @@ unsigned short ares_dns_rr_get_opt(const ares_dns_rr_t *dns_rr,
return 65535;
}
- if (idx >= (*opts)->cnt) {
+ opt = ares__array_at(*opts, idx);
+ if (opt == NULL) {
return 65535;
}
if (val) {
- *val = (*opts)->optval[idx].val;
+ *val = opt->val;
}
if (val_len) {
- *val_len = (*opts)->optval[idx].val_len;
+ *val_len = opt->val_len;
}
- return (*opts)->optval[idx].opt;
+ return opt->opt;
}
ares_bool_t ares_dns_rr_get_opt_byid(const ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key, unsigned short opt,
const unsigned char **val, size_t *val_len)
{
- ares__dns_options_t * const *opts;
- size_t i;
+ ares__array_t * const *opts;
+ size_t i;
+ size_t cnt;
+ const ares__dns_optval_t *optptr = NULL;
if (val) {
*val = NULL;
@@ -997,21 +1071,26 @@ ares_bool_t ares_dns_rr_get_opt_byid(const ares_dns_rr_t *dns_rr,
return ARES_FALSE;
}
- for (i = 0; i < (*opts)->cnt; i++) {
- if ((*opts)->optval[i].opt == opt) {
+ cnt = ares__array_len(*opts);
+ for (i = 0; i < cnt; i++) {
+ optptr = ares__array_at(*opts, i);
+ if (optptr == NULL) {
+ return ARES_FALSE;
+ }
+ if (optptr->opt == opt) {
break;
}
}
- if (i >= (*opts)->cnt) {
+ if (i >= cnt || optptr == NULL) {
return ARES_FALSE;
}
if (val) {
- *val = (*opts)->optval[i].val;
+ *val = optptr->val;
}
if (val_len) {
- *val_len = (*opts)->optval[i].val_len;
+ *val_len = optptr->val_len;
}
return ARES_TRUE;
}
@@ -1115,10 +1194,30 @@ ares_status_t ares_dns_rr_set_bin_own(ares_dns_rr_t *dns_rr,
size_t *bin_len = NULL;
if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_BIN &&
- ares_dns_rr_key_datatype(key) != ARES_DATATYPE_BINP) {
+ ares_dns_rr_key_datatype(key) != ARES_DATATYPE_BINP &&
+ ares_dns_rr_key_datatype(key) != ARES_DATATYPE_ABINP) {
return ARES_EFORMERR;
}
+ if (ares_dns_rr_key_datatype(key) == ARES_DATATYPE_ABINP) {
+ ares__dns_multistring_t **strs = ares_dns_rr_data_ptr(dns_rr, key, NULL);
+ if (strs == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ if (*strs == NULL) {
+ *strs = ares__dns_multistring_create();
+ if (*strs == NULL) {
+ return ARES_ENOMEM;
+ }
+ }
+
+ /* Clear all existing entries as this is an override */
+ ares__dns_multistring_clear(*strs);
+
+ return ares__dns_multistring_add_own(*strs, val, len);
+ }
+
bin = ares_dns_rr_data_ptr(dns_rr, key, &bin_len);
if (bin == NULL || bin_len == NULL) {
return ARES_EFORMERR;
@@ -1138,7 +1237,11 @@ ares_status_t ares_dns_rr_set_bin(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
{
ares_status_t status;
ares_dns_datatype_t datatype = ares_dns_rr_key_datatype(key);
- size_t alloclen = (datatype == ARES_DATATYPE_BINP) ? len + 1 : len;
+ ares_bool_t is_nullterm =
+ (datatype == ARES_DATATYPE_BINP || datatype == ARES_DATATYPE_ABINP)
+ ? ARES_TRUE
+ : ARES_FALSE;
+ size_t alloclen = is_nullterm ? len + 1 : len;
unsigned char *temp = ares_malloc(alloclen);
if (temp == NULL) {
@@ -1148,7 +1251,7 @@ ares_status_t ares_dns_rr_set_bin(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
memcpy(temp, val, len);
/* NULL-term BINP */
- if (datatype == ARES_DATATYPE_BINP) {
+ if (is_nullterm) {
temp[len] = 0;
}
@@ -1204,12 +1307,47 @@ ares_status_t ares_dns_rr_set_str(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
return status;
}
+ares_status_t ares_dns_rr_set_abin_own(ares_dns_rr_t *dns_rr,
+ ares_dns_rr_key_t key,
+ ares__dns_multistring_t *strs)
+{
+ ares__dns_multistring_t **strs_ptr;
+
+ if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_ABINP) {
+ return ARES_EFORMERR;
+ }
+
+ strs_ptr = ares_dns_rr_data_ptr(dns_rr, key, NULL);
+ if (strs_ptr == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ if (*strs_ptr != NULL) {
+ ares__dns_multistring_destroy(*strs_ptr);
+ }
+ *strs_ptr = strs;
+
+ return ARES_SUCCESS;
+}
+
+static void ares__dns_opt_free_cb(void *arg)
+{
+ ares__dns_optval_t *opt = arg;
+ if (opt == NULL) {
+ return;
+ }
+ ares_free(opt->val);
+}
+
ares_status_t ares_dns_rr_set_opt_own(ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key, unsigned short opt,
unsigned char *val, size_t val_len)
{
- ares__dns_options_t **options;
- size_t idx;
+ ares__array_t **options;
+ ares__dns_optval_t *optptr = NULL;
+ size_t idx;
+ size_t cnt;
+ ares_status_t status;
if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_OPT) {
return ARES_EFORMERR;
@@ -1221,54 +1359,39 @@ ares_status_t ares_dns_rr_set_opt_own(ares_dns_rr_t *dns_rr,
}
if (*options == NULL) {
- *options = ares_malloc_zero(sizeof(**options));
+ *options =
+ ares__array_create(sizeof(ares__dns_optval_t), ares__dns_opt_free_cb);
}
if (*options == NULL) {
return ARES_ENOMEM;
}
- for (idx = 0; idx < (*options)->cnt; idx++) {
- if ((*options)->optval[idx].opt == opt) {
+ cnt = ares__array_len(*options);
+ for (idx = 0; idx < cnt; idx++) {
+ optptr = ares__array_at(*options, idx);
+ if (optptr == NULL) {
+ return ARES_EFORMERR;
+ }
+ if (optptr->opt == opt) {
break;
}
}
/* Duplicate entry, replace */
- if (idx != (*options)->cnt) {
+ if (idx != cnt && optptr != NULL) {
goto done;
}
- idx = (*options)->cnt;
-
- /* Expand by powers of 2 */
- if (idx >= (*options)->alloc) {
- size_t alloc_size = (*options)->alloc;
- void *temp;
-
- if (alloc_size == 0) {
- alloc_size = 1;
- } else {
- alloc_size <<= 1;
- }
-
- temp = ares_realloc_zero((*options)->optval,
- (*options)->alloc * sizeof(*(*options)->optval),
- alloc_size * sizeof(*(*options)->optval));
- if (temp == NULL) {
- return ARES_ENOMEM;
- }
-
- (*options)->optval = temp;
- (*options)->alloc = alloc_size;
+ status = ares__array_insert_last((void **)&optptr, *options);
+ if (status != ARES_SUCCESS) {
+ return status;
}
- (*options)->cnt++;
-
done:
- ares_free((*options)->optval[idx].val);
- (*options)->optval[idx].opt = opt;
- (*options)->optval[idx].val = val;
- (*options)->optval[idx].val_len = val_len;
+ ares_free(optptr->val);
+ optptr->opt = opt;
+ optptr->val = val;
+ optptr->val_len = val_len;
return ARES_SUCCESS;
}
@@ -1297,6 +1420,43 @@ ares_status_t ares_dns_rr_set_opt(ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key,
return status;
}
+ares_status_t ares_dns_rr_del_opt_byid(ares_dns_rr_t *dns_rr,
+ ares_dns_rr_key_t key,
+ unsigned short opt)
+{
+ ares__array_t **options;
+ const ares__dns_optval_t *optptr;
+ size_t idx;
+ size_t cnt;
+
+ if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_OPT) {
+ return ARES_EFORMERR;
+ }
+
+ options = ares_dns_rr_data_ptr(dns_rr, key, NULL);
+ if (options == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ /* No options */
+ if (*options == NULL) {
+ return ARES_SUCCESS;
+ }
+
+ cnt = ares__array_len(*options);
+ for (idx = 0; idx < cnt; idx++) {
+ optptr = ares__array_at_const(*options, idx);
+ if (optptr == NULL) {
+ return ARES_ENOTFOUND;
+ }
+ if (optptr->opt == opt) {
+ return ares__array_remove_at(*options, idx);
+ }
+ }
+
+ return ARES_ENOTFOUND;
+}
+
char *ares_dns_addr_to_ptr(const struct ares_addr *addr)
{
ares__buf_t *buf = NULL;
@@ -1369,8 +1529,20 @@ fail:
return NULL;
}
-/* search for an OPT RR in the response */
-ares_bool_t ares_dns_has_opt_rr(const ares_dns_record_t *rec)
+ares_dns_rr_t *ares_dns_get_opt_rr(ares_dns_record_t *rec)
+{
+ size_t i;
+ for (i = 0; i < ares_dns_record_rr_cnt(rec, ARES_SECTION_ADDITIONAL); i++) {
+ ares_dns_rr_t *rr = ares_dns_record_rr_get(rec, ARES_SECTION_ADDITIONAL, i);
+
+ if (ares_dns_rr_get_type(rr) == ARES_REC_TYPE_OPT) {
+ return rr;
+ }
+ }
+ return NULL;
+}
+
+const ares_dns_rr_t *ares_dns_get_opt_rr_const(const ares_dns_record_t *rec)
{
size_t i;
for (i = 0; i < ares_dns_record_rr_cnt(rec, ARES_SECTION_ADDITIONAL); i++) {
@@ -1378,10 +1550,10 @@ ares_bool_t ares_dns_has_opt_rr(const ares_dns_record_t *rec)
ares_dns_record_rr_get_const(rec, ARES_SECTION_ADDITIONAL, i);
if (ares_dns_rr_get_type(rr) == ARES_REC_TYPE_OPT) {
- return ARES_TRUE;
+ return rr;
}
}
- return ARES_FALSE;
+ return NULL;
}
/* Construct a DNS record for a name with given class and type. Used internally
@@ -1460,26 +1632,34 @@ done:
return status;
}
-ares_dns_record_t *ares_dns_record_duplicate(const ares_dns_record_t *dnsrec)
+ares_status_t ares_dns_record_duplicate_ex(ares_dns_record_t **dest,
+ const ares_dns_record_t *src)
{
- unsigned char *data = NULL;
- size_t data_len = 0;
- ares_dns_record_t *out = NULL;
- ares_status_t status;
+ unsigned char *data = NULL;
+ size_t data_len = 0;
+ ares_status_t status;
- if (dnsrec == NULL) {
- return NULL;
+ if (dest == NULL || src == NULL) {
+ return ARES_EFORMERR;
}
- status = ares_dns_write(dnsrec, &data, &data_len);
+ *dest = NULL;
+
+ status = ares_dns_write(src, &data, &data_len);
if (status != ARES_SUCCESS) {
- return NULL;
+ return status;
}
- status = ares_dns_parse(data, data_len, 0, &out);
+ status = ares_dns_parse(data, data_len, 0, dest);
ares_free(data);
- if (status != ARES_SUCCESS) {
- return NULL;
- }
- return out;
+
+ return status;
+}
+
+ares_dns_record_t *ares_dns_record_duplicate(const ares_dns_record_t *dnsrec)
+{
+ ares_dns_record_t *dest = NULL;
+
+ ares_dns_record_duplicate_ex(&dest, dnsrec);
+ return dest;
}
diff --git a/contrib/libs/c-ares/src/lib/ares_dns_write.c b/contrib/libs/c-ares/src/lib/record/ares_dns_write.c
index 1643f08103..8a3addd9f0 100644
--- a/contrib/libs/c-ares/src/lib/ares_dns_write.c
+++ b/contrib/libs/c-ares/src/lib/record/ares_dns_write.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include <limits.h>
#ifdef HAVE_STDINT_H
@@ -44,7 +42,7 @@ static ares_status_t ares_dns_write_header(const ares_dns_record_t *dnsrec,
/* ID */
status = ares__buf_append_be16(buf, dnsrec->id);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Flags */
@@ -93,7 +91,7 @@ static ares_status_t ares_dns_write_header(const ares_dns_record_t *dnsrec,
}
/* RCODE */
- if (dnsrec->rcode > 15 && !ares_dns_has_opt_rr(dnsrec)) {
+ if (dnsrec->rcode > 15 && ares_dns_get_opt_rr_const(dnsrec) == NULL) {
/* Must have OPT RR in order to write extended error codes */
rcode = ARES_RCODE_SERVFAIL;
} else {
@@ -103,31 +101,35 @@ static ares_status_t ares_dns_write_header(const ares_dns_record_t *dnsrec,
status = ares__buf_append_be16(buf, u16);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* QDCOUNT */
- status = ares__buf_append_be16(buf, (unsigned short)dnsrec->qdcount);
+ status = ares__buf_append_be16(
+ buf, (unsigned short)ares_dns_record_query_cnt(dnsrec));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* ANCOUNT */
- status = ares__buf_append_be16(buf, (unsigned short)dnsrec->ancount);
+ status = ares__buf_append_be16(
+ buf, (unsigned short)ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* NSCOUNT */
- status = ares__buf_append_be16(buf, (unsigned short)dnsrec->nscount);
+ status = ares__buf_append_be16(buf, (unsigned short)ares_dns_record_rr_cnt(
+ dnsrec, ARES_SECTION_AUTHORITY));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* ARCOUNT */
- status = ares__buf_append_be16(buf, (unsigned short)dnsrec->arcount);
+ status = ares__buf_append_be16(buf, (unsigned short)ares_dns_record_rr_cnt(
+ dnsrec, ARES_SECTION_ADDITIONAL));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
return ARES_SUCCESS;
@@ -159,13 +161,13 @@ static ares_status_t ares_dns_write_questions(const ares_dns_record_t *dnsrec,
/* Type */
status = ares__buf_append_be16(buf, (unsigned short)qtype);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Class */
status = ares__buf_append_be16(buf, (unsigned short)qclass);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -182,7 +184,7 @@ static ares_status_t ares_dns_write_rr_name(ares__buf_t *buf,
name = ares_dns_rr_get_str(rr, key);
if (name == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
return ares__dns_name_write(buf, namelist, validate_hostname, name);
@@ -198,7 +200,7 @@ static ares_status_t ares_dns_write_rr_str(ares__buf_t *buf,
str = ares_dns_rr_get_str(rr, key);
if (str == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
len = ares_strlen(str);
@@ -209,7 +211,7 @@ static ares_status_t ares_dns_write_rr_str(ares__buf_t *buf,
/* Write 1 byte length */
status = ares__buf_append_byte(buf, (unsigned char)(len & 0xFF));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
if (len == 0) {
@@ -220,20 +222,14 @@ static ares_status_t ares_dns_write_rr_str(ares__buf_t *buf,
return ares__buf_append(buf, (const unsigned char *)str, len);
}
-static ares_status_t ares_dns_write_rr_binstrs(ares__buf_t *buf,
- const ares_dns_rr_t *rr,
- ares_dns_rr_key_t key)
+static ares_status_t ares_dns_write_binstr(ares__buf_t *buf,
+ const unsigned char *bin,
+ size_t bin_len)
{
- const unsigned char *bin;
const unsigned char *ptr;
- size_t bin_len;
size_t ptr_len;
ares_status_t status;
- bin = ares_dns_rr_get_bin(rr, key, &bin_len);
- if (bin == NULL) {
- return ARES_EFORMERR;
- }
/* split into possible multiple 255-byte or less length strings */
ptr = bin;
ptr_len = bin_len;
@@ -246,14 +242,14 @@ static ares_status_t ares_dns_write_rr_binstrs(ares__buf_t *buf,
/* Length */
status = ares__buf_append_byte(buf, (unsigned char)(len & 0xFF));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* String */
if (len) {
status = ares__buf_append(buf, ptr, len);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -264,12 +260,39 @@ static ares_status_t ares_dns_write_rr_binstrs(ares__buf_t *buf,
return ARES_SUCCESS;
}
+static ares_status_t ares_dns_write_rr_abin(ares__buf_t *buf,
+ const ares_dns_rr_t *rr,
+ ares_dns_rr_key_t key)
+{
+ ares_status_t status = ARES_EFORMERR;
+ size_t i;
+ size_t cnt = ares_dns_rr_get_abin_cnt(rr, key);
+
+ if (cnt == 0) {
+ return ARES_EFORMERR;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ const unsigned char *bin;
+ size_t bin_len;
+
+ bin = ares_dns_rr_get_abin(rr, key, i, &bin_len);
+
+ status = ares_dns_write_binstr(buf, bin, bin_len);
+ if (status != ARES_SUCCESS) {
+ break;
+ }
+ }
+
+ return status;
+}
+
static ares_status_t ares_dns_write_rr_be32(ares__buf_t *buf,
const ares_dns_rr_t *rr,
ares_dns_rr_key_t key)
{
if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_U32) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
return ares__buf_append_be32(buf, ares_dns_rr_get_u32(rr, key));
}
@@ -279,7 +302,7 @@ static ares_status_t ares_dns_write_rr_be16(ares__buf_t *buf,
ares_dns_rr_key_t key)
{
if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_U16) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
return ares__buf_append_be16(buf, ares_dns_rr_get_u16(rr, key));
}
@@ -289,7 +312,7 @@ static ares_status_t ares_dns_write_rr_u8(ares__buf_t *buf,
ares_dns_rr_key_t key)
{
if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_U8) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
return ares__buf_append_byte(buf, ares_dns_rr_get_u8(rr, key));
}
@@ -303,7 +326,7 @@ static ares_status_t ares_dns_write_rr_a(ares__buf_t *buf,
addr = ares_dns_rr_get_addr(rr, ARES_RR_A_ADDR);
if (addr == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
return ares__buf_append(buf, (const unsigned char *)addr, sizeof(*addr));
@@ -348,25 +371,25 @@ static ares_status_t ares_dns_write_rr_soa(ares__buf_t *buf,
/* SERIAL */
status = ares_dns_write_rr_be32(buf, rr, ARES_RR_SOA_SERIAL);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* REFRESH */
status = ares_dns_write_rr_be32(buf, rr, ARES_RR_SOA_REFRESH);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* RETRY */
status = ares_dns_write_rr_be32(buf, rr, ARES_RR_SOA_RETRY);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* EXPIRE */
status = ares_dns_write_rr_be32(buf, rr, ARES_RR_SOA_EXPIRE);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* MINIMUM */
@@ -408,7 +431,7 @@ static ares_status_t ares_dns_write_rr_mx(ares__buf_t *buf,
/* PREFERENCE */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_MX_PREFERENCE);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* EXCHANGE */
@@ -421,7 +444,7 @@ static ares_status_t ares_dns_write_rr_txt(ares__buf_t *buf,
ares__llist_t **namelist)
{
(void)namelist;
- return ares_dns_write_rr_binstrs(buf, rr, ARES_RR_TXT_DATA);
+ return ares_dns_write_rr_abin(buf, rr, ARES_RR_TXT_DATA);
}
static ares_status_t ares_dns_write_rr_sig(ares__buf_t *buf,
@@ -437,43 +460,43 @@ static ares_status_t ares_dns_write_rr_sig(ares__buf_t *buf,
/* TYPE COVERED */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_SIG_TYPE_COVERED);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* ALGORITHM */
status = ares_dns_write_rr_u8(buf, rr, ARES_RR_SIG_ALGORITHM);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* LABELS */
status = ares_dns_write_rr_u8(buf, rr, ARES_RR_SIG_LABELS);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* ORIGINAL TTL */
status = ares_dns_write_rr_be32(buf, rr, ARES_RR_SIG_ORIGINAL_TTL);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* EXPIRATION */
status = ares_dns_write_rr_be32(buf, rr, ARES_RR_SIG_EXPIRATION);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* INCEPTION */
status = ares_dns_write_rr_be32(buf, rr, ARES_RR_SIG_INCEPTION);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* KEY TAG */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_SIG_KEY_TAG);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* SIGNERS NAME */
@@ -501,7 +524,7 @@ static ares_status_t ares_dns_write_rr_aaaa(ares__buf_t *buf,
addr = ares_dns_rr_get_addr6(rr, ARES_RR_AAAA_ADDR);
if (addr == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
return ares__buf_append(buf, (const unsigned char *)addr, sizeof(*addr));
@@ -516,19 +539,19 @@ static ares_status_t ares_dns_write_rr_srv(ares__buf_t *buf,
/* PRIORITY */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_SRV_PRIORITY);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* WEIGHT */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_SRV_WEIGHT);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* PORT */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_SRV_PORT);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* TARGET */
@@ -545,31 +568,31 @@ static ares_status_t ares_dns_write_rr_naptr(ares__buf_t *buf,
/* ORDER */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_NAPTR_ORDER);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* PREFERENCE */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_NAPTR_PREFERENCE);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* FLAGS */
status = ares_dns_write_rr_str(buf, rr, ARES_RR_NAPTR_FLAGS);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* SERVICES */
status = ares_dns_write_rr_str(buf, rr, ARES_RR_NAPTR_SERVICES);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* REGEXP */
status = ares_dns_write_rr_str(buf, rr, ARES_RR_NAPTR_REGEXP);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* REPLACEMENT */
@@ -589,6 +612,12 @@ static ares_status_t ares_dns_write_rr_opt(ares__buf_t *buf,
(void)namelist;
+ /* Coverity reports on this even though its not possible when taken
+ * into context */
+ if (len == 0) {
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
+ }
+
/* We need to go back and overwrite the class and ttl that were emitted as
* the OPT record overloads them for its own use (yes, very strange!) */
status = ares__buf_set_length(buf, len - 2 /* RDLENGTH */
@@ -601,7 +630,7 @@ static ares_status_t ares_dns_write_rr_opt(ares__buf_t *buf,
/* Class -> UDP Size */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_OPT_UDP_SIZE);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* TTL -> rcode (u8) << 24 | version (u8) << 16 | flags (u16) */
@@ -611,7 +640,7 @@ static ares_status_t ares_dns_write_rr_opt(ares__buf_t *buf,
status = ares__buf_append_be32(buf, ttl);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Now go back to real end */
@@ -631,20 +660,20 @@ static ares_status_t ares_dns_write_rr_opt(ares__buf_t *buf,
/* BE16 option */
status = ares__buf_append_be16(buf, opt);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* BE16 length */
status = ares__buf_append_be16(buf, (unsigned short)(val_len & 0xFFFF));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Value */
if (val && val_len) {
status = ares__buf_append(buf, val, val_len);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
}
@@ -665,19 +694,19 @@ static ares_status_t ares_dns_write_rr_tlsa(ares__buf_t *buf,
/* CERT_USAGE */
status = ares_dns_write_rr_u8(buf, rr, ARES_RR_TLSA_CERT_USAGE);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* SELECTOR */
status = ares_dns_write_rr_u8(buf, rr, ARES_RR_TLSA_SELECTOR);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* MATCH */
status = ares_dns_write_rr_u8(buf, rr, ARES_RR_TLSA_MATCH);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* DATA -- binary, rest of buffer, required to be non-zero length */
@@ -699,7 +728,7 @@ static ares_status_t ares_dns_write_rr_svcb(ares__buf_t *buf,
/* PRIORITY */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_SVCB_PRIORITY);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* TARGET */
@@ -720,20 +749,20 @@ static ares_status_t ares_dns_write_rr_svcb(ares__buf_t *buf,
/* BE16 option */
status = ares__buf_append_be16(buf, opt);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* BE16 length */
status = ares__buf_append_be16(buf, (unsigned short)(val_len & 0xFFFF));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Value */
if (val && val_len) {
status = ares__buf_append(buf, val, val_len);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
}
@@ -750,7 +779,7 @@ static ares_status_t ares_dns_write_rr_https(ares__buf_t *buf,
/* PRIORITY */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_HTTPS_PRIORITY);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* TARGET */
@@ -771,20 +800,20 @@ static ares_status_t ares_dns_write_rr_https(ares__buf_t *buf,
/* BE16 option */
status = ares__buf_append_be16(buf, opt);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* BE16 length */
status = ares__buf_append_be16(buf, (unsigned short)(val_len & 0xFFFF));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Value */
if (val && val_len) {
status = ares__buf_append(buf, val, val_len);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
}
@@ -803,13 +832,13 @@ static ares_status_t ares_dns_write_rr_uri(ares__buf_t *buf,
/* PRIORITY */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_URI_PRIORITY);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* WEIGHT */
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_URI_WEIGHT);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* TARGET -- not in DNS string format, rest of buffer, required to be
@@ -836,13 +865,13 @@ static ares_status_t ares_dns_write_rr_caa(ares__buf_t *buf,
/* CRITICAL */
status = ares_dns_write_rr_u8(buf, rr, ARES_RR_CAA_CRITICAL);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Tag */
status = ares_dns_write_rr_str(buf, rr, ARES_RR_CAA_TAG);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Value - binary! (remaining buffer */
@@ -865,6 +894,12 @@ static ares_status_t ares_dns_write_rr_raw_rr(ares__buf_t *buf,
(void)namelist;
+ /* Coverity reports on this even though its not possible when taken
+ * into context */
+ if (len == 0) {
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
+ }
+
/* We need to go back and overwrite the type that was emitted by the parent
* function */
status = ares__buf_set_length(buf, len - 2 /* RDLENGTH */
@@ -877,7 +912,7 @@ static ares_status_t ares_dns_write_rr_raw_rr(ares__buf_t *buf,
status = ares_dns_write_rr_be16(buf, rr, ARES_RR_RAW_RR_TYPE);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Now go back to real end */
@@ -919,7 +954,7 @@ static ares_status_t ares_dns_write_rr(const ares_dns_record_t *dnsrec,
rr = ares_dns_record_rr_get_const(dnsrec, section, i);
if (rr == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
type = ares_dns_rr_get_type(rr);
@@ -938,14 +973,14 @@ static ares_status_t ares_dns_write_rr(const ares_dns_record_t *dnsrec,
/* Type */
status = ares__buf_append_be16(buf, (unsigned short)type);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Class */
status =
ares__buf_append_be16(buf, (unsigned short)ares_dns_rr_get_class(rr));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* TTL */
@@ -957,14 +992,14 @@ static ares_status_t ares_dns_write_rr(const ares_dns_record_t *dnsrec,
}
status = ares__buf_append_be32(buf, ttl);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Length */
pos_len = ares__buf_len(buf); /* Save to write real length later */
status = ares__buf_append_be16(buf, 0);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* Data */
@@ -1047,7 +1082,7 @@ static ares_status_t ares_dns_write_rr(const ares_dns_record_t *dnsrec,
status = ares__buf_append_be16(buf, (unsigned short)(rdlength & 0xFFFF));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_set_length(buf, end_length);
@@ -1059,52 +1094,121 @@ static ares_status_t ares_dns_write_rr(const ares_dns_record_t *dnsrec,
return ARES_SUCCESS;
}
-ares_status_t ares_dns_write(const ares_dns_record_t *dnsrec,
- unsigned char **buf, size_t *buf_len)
+ares_status_t ares_dns_write_buf(const ares_dns_record_t *dnsrec,
+ ares__buf_t *buf)
{
- ares__buf_t *b = NULL;
- ares_status_t status;
ares__llist_t *namelist = NULL;
+ size_t orig_len;
+ ares_status_t status;
- if (buf == NULL || buf_len == NULL || dnsrec == NULL) {
+ if (dnsrec == NULL || buf == NULL) {
return ARES_EFORMERR;
}
- *buf = NULL;
- *buf_len = 0;
+ orig_len = ares__buf_len(buf);
- b = ares__buf_create();
- if (b == NULL) {
- return ARES_ENOMEM;
+ status = ares_dns_write_header(dnsrec, buf);
+ if (status != ARES_SUCCESS) {
+ goto done;
}
- status = ares_dns_write_header(dnsrec, b);
+ status = ares_dns_write_questions(dnsrec, &namelist, buf);
if (status != ARES_SUCCESS) {
goto done;
}
- status = ares_dns_write_questions(dnsrec, &namelist, b);
+ status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_ANSWER, buf);
if (status != ARES_SUCCESS) {
goto done;
}
- status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_ANSWER, b);
+ status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_AUTHORITY, buf);
if (status != ARES_SUCCESS) {
goto done;
}
- status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_AUTHORITY, b);
+ status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_ADDITIONAL, buf);
if (status != ARES_SUCCESS) {
goto done;
}
- status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_ADDITIONAL, b);
+done:
+ ares__llist_destroy(namelist);
if (status != ARES_SUCCESS) {
+ ares__buf_set_length(buf, orig_len);
+ }
+
+ return status;
+}
+
+ares_status_t ares_dns_write_buf_tcp(const ares_dns_record_t *dnsrec,
+ ares__buf_t *buf)
+{
+ ares_status_t status;
+ size_t orig_len;
+ size_t msg_len;
+ size_t len;
+
+ if (dnsrec == NULL || buf == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ orig_len = ares__buf_len(buf);
+
+ /* Write placeholder for length */
+ status = ares__buf_append_be16(buf, 0);
+ if (status != ARES_SUCCESS) {
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
+ }
+
+ /* Write message */
+ status = ares_dns_write_buf(dnsrec, buf);
+ if (status != ARES_SUCCESS) {
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
+ }
+
+ len = ares__buf_len(buf);
+ msg_len = len - orig_len - 2;
+ if (msg_len > 65535) {
+ status = ARES_EBADQUERY;
goto done;
}
+ /* Now we need to overwrite the length, so we jump back to the original
+ * message length, overwrite the section and jump back */
+ ares__buf_set_length(buf, orig_len);
+ status = ares__buf_append_be16(buf, (unsigned short)(msg_len & 0xFFFF));
+ if (status != ARES_SUCCESS) {
+ goto done; /* LCOV_EXCL_LINE: UntestablePath */
+ }
+ ares__buf_set_length(buf, len);
+
done:
- ares__llist_destroy(namelist);
+ if (status != ARES_SUCCESS) {
+ ares__buf_set_length(buf, orig_len);
+ }
+ return status;
+}
+
+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;
+
+ if (buf == NULL || buf_len == NULL || dnsrec == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ *buf = NULL;
+ *buf_len = 0;
+
+ b = ares__buf_create();
+ if (b == NULL) {
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ }
+
+ status = ares_dns_write_buf(dnsrec, b);
if (status != ARES_SUCCESS) {
ares__buf_destroy(b);
diff --git a/contrib/libs/c-ares/src/lib/setup_once.h b/contrib/libs/c-ares/src/lib/setup_once.h
deleted file mode 100644
index 38527ec442..0000000000
--- a/contrib/libs/c-ares/src/lib/setup_once.h
+++ /dev/null
@@ -1,469 +0,0 @@
-/* MIT License
- *
- * Copyright (c) 2004 Daniel Stenberg
- *
- * 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
- */
-#ifndef __SETUP_ONCE_H
-#define __SETUP_ONCE_H
-
-
-/********************************************************************
- * NOTICE *
- * ======== *
- * *
- * Content of header files lib/setup_once.h and ares/setup_once.h *
- * must be kept in sync. Modify the other one if you change this. *
- * *
- ********************************************************************/
-
-
-/*
- * Inclusion of common header files.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
-
-#ifdef HAVE_ERRNO_H
-# include <errno.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef NEED_MALLOC_H
-# include <malloc.h>
-#endif
-
-#ifdef NEED_MEMORY_H
-# include <memory.h>
-#endif
-
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-
-#ifdef HAVE_TIME_H
-# include <time.h>
-#endif
-
-#ifdef WIN32
-# include <io.h>
-# include <fcntl.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#ifdef __hpux
-# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
-# ifdef _APP32_64BIT_OFF_T
-# define OLD_APP32_64BIT_OFF_T _APP32_64BIT_OFF_T
-# undef _APP32_64BIT_OFF_T
-# else
-# undef OLD_APP32_64BIT_OFF_T
-# endif
-# endif
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-
-#ifdef __hpux
-# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL)
-# ifdef OLD_APP32_64BIT_OFF_T
-# define _APP32_64BIT_OFF_T OLD_APP32_64BIT_OFF_T
-# undef OLD_APP32_64BIT_OFF_T
-# endif
-# endif
-#endif
-
-
-/*
- * Definition of timeval struct for platforms that don't have it.
- */
-
-#ifndef HAVE_STRUCT_TIMEVAL
-struct timeval {
- long tv_sec;
- long tv_usec;
-};
-#endif
-
-
-/*
- * If we have the MSG_NOSIGNAL define, make sure we use
- * it as the fourth argument of function send()
- */
-
-#if defined(HAVE_MSG_NOSIGNAL) && defined(MSG_NOSIGNAL)
-# define SEND_4TH_ARG MSG_NOSIGNAL
-#else
-# define SEND_4TH_ARG 0
-#endif
-
-
-#if defined(__minix)
-/* Minix doesn't support recv on TCP sockets */
-# define sread(x, y, z) \
- (ares_ssize_t) \
- read((RECV_TYPE_ARG1)(x), (RECV_TYPE_ARG2)(y), (RECV_TYPE_ARG3)(z))
-
-#elif defined(HAVE_RECV)
-/*
- * The definitions for the return type and arguments types
- * of functions recv() and send() belong and come from the
- * configuration file. Do not define them in any other place.
- *
- * HAVE_RECV is defined if you have a function named recv()
- * which is used to read incoming data from sockets. If your
- * function has another name then don't define HAVE_RECV.
- *
- * If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2,
- * RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also
- * be defined.
- *
- * HAVE_SEND is defined if you have a function named send()
- * which is used to write outgoing data on a connected socket.
- * If yours has another name then don't define HAVE_SEND.
- *
- * If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_QUAL_ARG2,
- * SEND_TYPE_ARG2, SEND_TYPE_ARG3, SEND_TYPE_ARG4 and
- * SEND_TYPE_RETV must also be defined.
- */
-
-# if !defined(RECV_TYPE_ARG1) || !defined(RECV_TYPE_ARG2) || \
- !defined(RECV_TYPE_ARG3) || !defined(RECV_TYPE_ARG4) || \
- !defined(RECV_TYPE_RETV)
-/* */
-Error Missing_definition_of_return_and_arguments_types_of_recv
-/* */
-# else
-# define sread(x, y, z) \
- (ares_ssize_t) recv((RECV_TYPE_ARG1)(x), (RECV_TYPE_ARG2)(y), \
- (RECV_TYPE_ARG3)(z), (RECV_TYPE_ARG4)(0))
-# endif
-#else /* HAVE_RECV */
-# ifndef sread
-/* */
-Error Missing_definition_of_macro_sread
-/* */
-# endif
-#endif /* HAVE_RECV */
-
-
-#if defined(__minix)
-/* Minix doesn't support send on TCP sockets */
-# define swrite(x, y, z) \
- (ares_ssize_t) \
- write((SEND_TYPE_ARG1)(x), (SEND_TYPE_ARG2)(y), (SEND_TYPE_ARG3)(z))
-
-#elif defined(HAVE_SEND)
-# if !defined(SEND_TYPE_ARG1) || !defined(SEND_QUAL_ARG2) || \
- !defined(SEND_TYPE_ARG2) || !defined(SEND_TYPE_ARG3) || \
- !defined(SEND_TYPE_ARG4) || !defined(SEND_TYPE_RETV)
- /* */
- Error Missing_definition_of_return_and_arguments_types_of_send
-/* */
-# else
-# define swrite(x, y, z) \
- (ares_ssize_t) send((SEND_TYPE_ARG1)(x), (SEND_TYPE_ARG2)(y), \
- (SEND_TYPE_ARG3)(z), (SEND_TYPE_ARG4)(SEND_4TH_ARG))
-# endif
-#else /* HAVE_SEND */
-# ifndef swrite
- /* */
- Error Missing_definition_of_macro_swrite
-/* */
-# endif
-#endif /* HAVE_SEND */
-
-
-#if 0
-# if defined(HAVE_RECVFROM)
-/*
- * Currently recvfrom is only used on udp sockets.
- */
-# if !defined(RECVFROM_TYPE_ARG1) || !defined(RECVFROM_TYPE_ARG2) || \
- !defined(RECVFROM_TYPE_ARG3) || !defined(RECVFROM_TYPE_ARG4) || \
- !defined(RECVFROM_TYPE_ARG5) || !defined(RECVFROM_TYPE_ARG6) || \
- !defined(RECVFROM_TYPE_RETV)
- /* */
- Error Missing_definition_of_return_and_arguments_types_of_recvfrom
- /* */
-# else
-# define sreadfrom(s, b, bl, f, fl) \
- (ares_ssize_t) \
- recvfrom((RECVFROM_TYPE_ARG1)(s), (RECVFROM_TYPE_ARG2 *)(b), \
- (RECVFROM_TYPE_ARG3)(bl), (RECVFROM_TYPE_ARG4)(0), \
- (RECVFROM_TYPE_ARG5 *)(f), (RECVFROM_TYPE_ARG6 *)(fl))
-# endif
-# else /* HAVE_RECVFROM */
-# ifndef sreadfrom
- /* */
- Error Missing_definition_of_macro_sreadfrom
- /* */
-# endif
-# endif /* HAVE_RECVFROM */
-
-
-# ifdef RECVFROM_TYPE_ARG6_IS_VOID
-# define RECVFROM_ARG6_T int
-# else
-# define RECVFROM_ARG6_T RECVFROM_TYPE_ARG6
-# endif
-#endif /* if 0 */
-
-
-/*
- * Function-like macro definition used to close a socket.
- */
-
-#if defined(HAVE_CLOSESOCKET)
-# define sclose(x) closesocket((x))
-#elif defined(HAVE_CLOSESOCKET_CAMEL)
-# define sclose(x) CloseSocket((x))
-#elif defined(HAVE_CLOSE_S)
-# define sclose(x) close_s((x))
-#else
-# define sclose(x) close((x))
-#endif
-
-
-/*
- * Uppercase macro versions of ANSI/ISO is*() functions/macros which
- * avoid negative number inputs with argument byte codes > 127.
- */
-
-#define ISSPACE(x) (isspace((int)((unsigned char)x)))
-#define ISDIGIT(x) (isdigit((int)((unsigned char)x)))
-#define ISALNUM(x) (isalnum((int)((unsigned char)x)))
-#define ISXDIGIT(x) (isxdigit((int)((unsigned char)x)))
-#define ISGRAPH(x) (isgraph((int)((unsigned char)x)))
-#define ISALPHA(x) (isalpha((int)((unsigned char)x)))
-#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) (((unsigned char)x) <= 127 ? 1 : 0)
-
-#define ISBLANK(x) \
- (int)((((unsigned char)x) == ' ') || (((unsigned char)x) == '\t'))
-
-#define TOLOWER(x) (tolower((int)((unsigned char)x)))
-
-
-/*
- * Macro WHILE_FALSE may be used to build single-iteration do-while loops,
- * avoiding compiler warnings. Mostly intended for other macro definitions.
- */
-
-#define WHILE_FALSE while (0)
-
-#if defined(_MSC_VER) && !defined(__POCC__)
-# undef WHILE_FALSE
-# if (_MSC_VER < 1500)
-# define WHILE_FALSE while (1, 0)
-# else
-# define WHILE_FALSE \
- __pragma(warning(push)) __pragma(warning(disable : 4127)) while (0) \
- __pragma(warning(pop))
-# endif
-#endif
-
-
-/*
- * Macro used to include code only in debug builds.
- */
-
-#ifdef DEBUGBUILD
-# define DEBUGF(x) x
-#else
-# define DEBUGF(x) \
- do { \
- } \
- WHILE_FALSE
-#endif
-
-
-/*
- * Macro used to include assertion code only in debug builds.
- */
-
-#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H)
-# define DEBUGASSERT(x) assert(x)
-#else
-# define DEBUGASSERT(x) \
- do { \
- } \
- WHILE_FALSE
-#endif
-
-
-/*
- * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno
- * (or equivalent) on this platform to hide platform details to code using it.
- */
-
-#ifdef USE_WINSOCK
-# define SOCKERRNO ((int)WSAGetLastError())
-# define SET_SOCKERRNO(x) (WSASetLastError((int)(x)))
-#else
-# define SOCKERRNO (errno)
-# define SET_SOCKERRNO(x) (errno = (x))
-#endif
-
-
-/*
- * Macro ERRNO / SET_ERRNO() returns / sets the NOT *socket-related* errno
- * (or equivalent) on this platform to hide platform details to code using it.
- */
-
-#if defined(WIN32) && !defined(WATT32)
-# define ERRNO ((int)GetLastError())
-# define SET_ERRNO(x) (SetLastError((DWORD)(x)))
-#else
-# define ERRNO (errno)
-# define SET_ERRNO(x) (errno = (x))
-#endif
-
-
-/*
- * Portable error number symbolic names defined to Winsock error codes.
- */
-
-#ifdef USE_WINSOCK
-# undef EBADF /* override definition in errno.h */
-# define EBADF WSAEBADF
-# undef EINTR /* override definition in errno.h */
-# define EINTR WSAEINTR
-# undef EINVAL /* override definition in errno.h */
-# define EINVAL WSAEINVAL
-# undef EWOULDBLOCK /* override definition in errno.h */
-# define EWOULDBLOCK WSAEWOULDBLOCK
-# undef EINPROGRESS /* override definition in errno.h */
-# define EINPROGRESS WSAEINPROGRESS
-# undef EALREADY /* override definition in errno.h */
-# define EALREADY WSAEALREADY
-# undef ENOTSOCK /* override definition in errno.h */
-# define ENOTSOCK WSAENOTSOCK
-# undef EDESTADDRREQ /* override definition in errno.h */
-# define EDESTADDRREQ WSAEDESTADDRREQ
-# undef EMSGSIZE /* override definition in errno.h */
-# define EMSGSIZE WSAEMSGSIZE
-# undef EPROTOTYPE /* override definition in errno.h */
-# define EPROTOTYPE WSAEPROTOTYPE
-# undef ENOPROTOOPT /* override definition in errno.h */
-# define ENOPROTOOPT WSAENOPROTOOPT
-# undef EPROTONOSUPPORT /* override definition in errno.h */
-# define EPROTONOSUPPORT WSAEPROTONOSUPPORT
-# define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
-# undef EOPNOTSUPP /* override definition in errno.h */
-# define EOPNOTSUPP WSAEOPNOTSUPP
-# define EPFNOSUPPORT WSAEPFNOSUPPORT
-# undef EAFNOSUPPORT /* override definition in errno.h */
-# define EAFNOSUPPORT WSAEAFNOSUPPORT
-# undef EADDRINUSE /* override definition in errno.h */
-# define EADDRINUSE WSAEADDRINUSE
-# undef EADDRNOTAVAIL /* override definition in errno.h */
-# define EADDRNOTAVAIL WSAEADDRNOTAVAIL
-# undef ENETDOWN /* override definition in errno.h */
-# define ENETDOWN WSAENETDOWN
-# undef ENETUNREACH /* override definition in errno.h */
-# define ENETUNREACH WSAENETUNREACH
-# undef ENETRESET /* override definition in errno.h */
-# define ENETRESET WSAENETRESET
-# undef ECONNABORTED /* override definition in errno.h */
-# define ECONNABORTED WSAECONNABORTED
-# undef ECONNRESET /* override definition in errno.h */
-# define ECONNRESET WSAECONNRESET
-# undef ENOBUFS /* override definition in errno.h */
-# define ENOBUFS WSAENOBUFS
-# undef EISCONN /* override definition in errno.h */
-# define EISCONN WSAEISCONN
-# undef ENOTCONN /* override definition in errno.h */
-# define ENOTCONN WSAENOTCONN
-# define ESHUTDOWN WSAESHUTDOWN
-# define ETOOMANYREFS WSAETOOMANYREFS
-# undef ETIMEDOUT /* override definition in errno.h */
-# define ETIMEDOUT WSAETIMEDOUT
-# undef ECONNREFUSED /* override definition in errno.h */
-# define ECONNREFUSED WSAECONNREFUSED
-# undef ELOOP /* override definition in errno.h */
-# define ELOOP WSAELOOP
-# ifndef ENAMETOOLONG /* possible previous definition in errno.h */
-# define ENAMETOOLONG WSAENAMETOOLONG
-# endif
-# define EHOSTDOWN WSAEHOSTDOWN
-# undef EHOSTUNREACH /* override definition in errno.h */
-# define EHOSTUNREACH WSAEHOSTUNREACH
-# ifndef ENOTEMPTY /* possible previous definition in errno.h */
-# define ENOTEMPTY WSAENOTEMPTY
-# endif
-# define EPROCLIM WSAEPROCLIM
-# define EUSERS WSAEUSERS
-# define EDQUOT WSAEDQUOT
-# define ESTALE WSAESTALE
-# define EREMOTE WSAEREMOTE
-#endif
-
-
-/*
- * Actually use __32_getpwuid() on 64-bit VMS builds for getpwuid()
- */
-
-#if defined(__VMS) && defined(__INITIAL_POINTER_SIZE) && \
- (__INITIAL_POINTER_SIZE == 64)
-# define getpwuid __32_getpwuid
-#endif
-
-
-/*
- * Macro argv_item_t hides platform details to code using it.
- */
-
-#ifdef __VMS
-# define argv_item_t __char_ptr32
-#else
-# define argv_item_t char *
-#endif
-
-
-/*
- * We use this ZERO_NULL to avoid picky compiler warnings,
- * when assigning a NULL pointer to a function pointer var.
- */
-
-#define ZERO_NULL 0
-
-
-#endif /* __SETUP_ONCE_H */
diff --git a/contrib/libs/c-ares/src/lib/ares__buf.c b/contrib/libs/c-ares/src/lib/str/ares__buf.c
index 2203662fab..b855260ab3 100644
--- a/contrib/libs/c-ares/src/lib/ares__buf.c
+++ b/contrib/libs/c-ares/src/lib/str/ares__buf.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include "ares__buf.h"
#include <limits.h>
@@ -87,7 +85,7 @@ void ares__buf_destroy(ares__buf_t *buf)
static ares_bool_t ares__buf_is_const(const ares__buf_t *buf)
{
if (buf == NULL) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (buf->data != NULL && buf->alloc_buf == NULL) {
@@ -107,7 +105,7 @@ void ares__buf_reclaim(ares__buf_t *buf)
}
if (ares__buf_is_const(buf)) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Silence coverity. All lengths are zero so would bail out later but
@@ -135,8 +133,6 @@ void ares__buf_reclaim(ares__buf_t *buf)
if (buf->tag_offset != SIZE_MAX) {
buf->tag_offset -= prefix_size;
}
-
- return;
}
static ares_status_t ares__buf_ensure_space(ares__buf_t *buf,
@@ -151,7 +147,7 @@ static ares_status_t ares__buf_ensure_space(ares__buf_t *buf,
}
if (ares__buf_is_const(buf)) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* When calling ares__buf_finish_str() we end up adding a null terminator,
@@ -201,14 +197,14 @@ static ares_status_t ares__buf_ensure_space(ares__buf_t *buf,
ares_status_t ares__buf_set_length(ares__buf_t *buf, size_t len)
{
if (buf == NULL || ares__buf_is_const(buf)) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (len >= buf->alloc_buf_len - buf->offset) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
- buf->data_len = len;
+ buf->data_len = len + buf->offset;
return ARES_SUCCESS;
}
@@ -231,9 +227,9 @@ ares_status_t ares__buf_append(ares__buf_t *buf, const unsigned char *data,
return ARES_SUCCESS;
}
-ares_status_t ares__buf_append_byte(ares__buf_t *buf, unsigned char byte)
+ares_status_t ares__buf_append_byte(ares__buf_t *buf, unsigned char b)
{
- return ares__buf_append(buf, &byte, 1);
+ return ares__buf_append(buf, &b, 1);
}
ares_status_t ares__buf_append_be16(ares__buf_t *buf, unsigned short u16)
@@ -242,12 +238,12 @@ ares_status_t ares__buf_append_be16(ares__buf_t *buf, unsigned short u16)
status = ares__buf_append_byte(buf, (unsigned char)((u16 >> 8) & 0xff));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append_byte(buf, (unsigned char)(u16 & 0xff));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
return ARES_SUCCESS;
@@ -259,22 +255,22 @@ ares_status_t ares__buf_append_be32(ares__buf_t *buf, unsigned int u32)
status = ares__buf_append_byte(buf, ((unsigned char)(u32 >> 24) & 0xff));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append_byte(buf, ((unsigned char)(u32 >> 16) & 0xff));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append_byte(buf, ((unsigned char)(u32 >> 8) & 0xff));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append_byte(buf, ((unsigned char)u32 & 0xff));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
return ARES_SUCCESS;
@@ -319,7 +315,7 @@ unsigned char *ares__buf_finish_bin(ares__buf_t *buf, size_t *len)
/* We don't want to return NULL except on failure, may be zero-length */
if (buf->alloc_buf == NULL &&
ares__buf_ensure_space(buf, 1) != ARES_SUCCESS) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
}
ptr = buf->alloc_buf;
*len = buf->data_len;
@@ -540,7 +536,7 @@ ares_status_t ares__buf_fetch_bytes_dup(ares__buf_t *buf, size_t len,
*bytes = ares_malloc(null_term ? len + 1 : len);
if (*bytes == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
memcpy(*bytes, ptr, len);
@@ -561,7 +557,7 @@ ares_status_t ares__buf_fetch_str_dup(ares__buf_t *buf, size_t len, char **str)
*str = ares_malloc(len + 1);
if (*str == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
memcpy(*str, ptr, len);
@@ -787,7 +783,7 @@ ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims,
ares_bool_t first = ARES_TRUE;
if (buf == NULL || delims == NULL || delims_len == 0 || list == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
*list = ares__llist_create(ares__buf_destroy_cb);
@@ -825,7 +821,7 @@ ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims,
/* Shouldn't be possible */
if (ptr == NULL) {
- status = ARES_EFORMERR;
+ status = ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
goto done;
}
@@ -841,7 +837,7 @@ ares_status_t ares__buf_split(ares__buf_t *buf, const unsigned char *delims,
}
if (flags & ARES_BUF_SPLIT_RTRIM) {
- while (len && ares__is_whitespace(ptr[len - 1], ARES_TRUE)) {
+ while (len > 0 && ares__is_whitespace(ptr[len - 1], ARES_TRUE)) {
len--;
}
}
@@ -934,20 +930,20 @@ ares_status_t ares__buf_set_position(ares__buf_t *buf, size_t idx)
}
if (idx > buf->data_len) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
buf->offset = idx;
return ARES_SUCCESS;
}
-static ares_status_t ares__buf_parse_dns_binstr_int(
- ares__buf_t *buf, size_t remaining_len, unsigned char **bin, size_t *bin_len,
- ares_bool_t allow_multiple, ares_bool_t validate_printable)
+ares_status_t ares__buf_parse_dns_abinstr(ares__buf_t *buf,
+ size_t remaining_len,
+ ares__dns_multistring_t **strs,
+ ares_bool_t validate_printable)
{
unsigned char len;
- ares_status_t status;
- ares__buf_t *binbuf = NULL;
+ ares_status_t status = ARES_EBADRESP;
size_t orig_len = ares__buf_len(buf);
if (buf == NULL) {
@@ -958,15 +954,17 @@ static ares_status_t ares__buf_parse_dns_binstr_int(
return ARES_EBADRESP;
}
- binbuf = ares__buf_create();
- if (binbuf == NULL) {
- return ARES_ENOMEM;
+ if (strs != NULL) {
+ *strs = ares__dns_multistring_create();
+ if (*strs == NULL) {
+ return ARES_ENOMEM;
+ }
}
while (orig_len - ares__buf_len(buf) < remaining_len) {
status = ares__buf_fetch_bytes(buf, &len, 1);
if (status != ARES_SUCCESS) {
- break;
+ break; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (len) {
@@ -981,22 +979,88 @@ static ares_status_t ares__buf_parse_dns_binstr_int(
}
}
- if (bin != NULL) {
- status = ares__buf_fetch_bytes_into_buf(buf, binbuf, len);
+ if (strs != NULL) {
+ unsigned char *data = NULL;
+ status = ares__buf_fetch_bytes_dup(buf, len, ARES_TRUE, &data);
+ if (status != ARES_SUCCESS) {
+ break;
+ }
+ status = ares__dns_multistring_add_own(*strs, data, len);
+ if (status != ARES_SUCCESS) {
+ ares_free(data);
+ break;
+ }
} else {
status = ares__buf_consume(buf, len);
+ if (status != ARES_SUCCESS) {
+ break;
+ }
}
- if (status != ARES_SUCCESS) {
- break;
+ }
+ }
+
+ if (status != ARES_SUCCESS && strs != NULL) {
+ ares__dns_multistring_destroy(*strs);
+ *strs = NULL;
+ }
+
+ return status;
+}
+
+static ares_status_t
+ ares__buf_parse_dns_binstr_int(ares__buf_t *buf, size_t remaining_len,
+ unsigned char **bin, size_t *bin_len,
+ ares_bool_t validate_printable)
+{
+ unsigned char len;
+ ares_status_t status = ARES_EBADRESP;
+ ares__buf_t *binbuf = NULL;
+
+ if (buf == NULL) {
+ return ARES_EFORMERR;
+ }
+
+ if (remaining_len == 0) {
+ return ARES_EBADRESP;
+ }
+
+ binbuf = ares__buf_create();
+ if (binbuf == NULL) {
+ return ARES_ENOMEM;
+ }
+
+ status = ares__buf_fetch_bytes(buf, &len, 1);
+ if (status != ARES_SUCCESS) {
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
+ }
+
+ remaining_len--;
+
+ if (len > remaining_len) {
+ status = ARES_EBADRESP;
+ goto done;
+ }
+
+ if (len) {
+ /* When used by the _str() parser, it really needs to be validated to
+ * be a valid printable ascii string. Do that here */
+ if (validate_printable && ares__buf_len(buf) >= len) {
+ size_t mylen;
+ const char *data = (const char *)ares__buf_peek(buf, &mylen);
+ if (!ares__str_isprint(data, len)) {
+ status = ARES_EBADSTR;
+ goto done;
}
}
- if (!allow_multiple) {
- break;
+ if (bin != NULL) {
+ status = ares__buf_fetch_bytes_into_buf(buf, binbuf, len);
+ } else {
+ status = ares__buf_consume(buf, len);
}
}
-
+done:
if (status != ARES_SUCCESS) {
ares__buf_destroy(binbuf);
} else {
@@ -1014,20 +1078,19 @@ static ares_status_t ares__buf_parse_dns_binstr_int(
}
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)
+ unsigned char **bin, size_t *bin_len)
{
return ares__buf_parse_dns_binstr_int(buf, remaining_len, bin, bin_len,
- allow_multiple, ARES_FALSE);
+ ARES_FALSE);
}
ares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, size_t remaining_len,
- char **str, ares_bool_t allow_multiple)
+ char **str)
{
size_t len;
- return ares__buf_parse_dns_binstr_int(
- buf, remaining_len, (unsigned char **)str, &len, allow_multiple, ARES_TRUE);
+ return ares__buf_parse_dns_binstr_int(buf, remaining_len,
+ (unsigned char **)str, &len, ARES_TRUE);
}
ares_status_t ares__buf_append_num_dec(ares__buf_t *buf, size_t num, size_t len)
@@ -1049,13 +1112,13 @@ ares_status_t ares__buf_append_num_dec(ares__buf_t *buf, size_t num, size_t len)
/* Silence coverity. Shouldn't be possible since we calculate it above */
if (mod == 0) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
digit /= mod;
status = ares__buf_append_byte(buf, '0' + (unsigned char)(digit & 0xFF));
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
return ARES_SUCCESS;
@@ -1074,7 +1137,7 @@ ares_status_t ares__buf_append_num_hex(ares__buf_t *buf, size_t num, size_t len)
ares_status_t status;
status = ares__buf_append_byte(buf, hexbytes[(num >> ((i - 1) * 4)) & 0xF]);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
return ARES_SUCCESS;
@@ -1095,13 +1158,13 @@ static ares_status_t ares__buf_hexdump_line(ares__buf_t *buf, size_t idx,
/* Address */
status = ares__buf_append_num_hex(buf, idx, 6);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
/* | */
status = ares__buf_append_str(buf, " | ");
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
for (i = 0; i < 16; i++) {
@@ -1111,19 +1174,19 @@ static ares_status_t ares__buf_hexdump_line(ares__buf_t *buf, size_t idx,
status = ares__buf_append_num_hex(buf, data[i], 2);
}
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append_byte(buf, ' ');
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
/* | */
status = ares__buf_append_str(buf, " | ");
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
for (i = 0; i < 16; i++) {
@@ -1132,7 +1195,7 @@ static ares_status_t ares__buf_hexdump_line(ares__buf_t *buf, size_t idx,
}
status = ares__buf_append_byte(buf, ares__isprint(data[i]) ? data[i] : '.');
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -1149,7 +1212,7 @@ ares_status_t ares__buf_hexdump(ares__buf_t *buf, const unsigned char *data,
ares_status_t status;
status = ares__buf_hexdump_line(buf, i, data + i, len - i);
if (status != ARES_SUCCESS) {
- return status;
+ return status; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -1166,7 +1229,7 @@ ares_status_t ares__buf_load_file(const char *filename, ares__buf_t *buf)
ares_status_t status;
if (filename == NULL || buf == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
fp = fopen(filename, "rb");
@@ -1188,39 +1251,39 @@ ares_status_t ares__buf_load_file(const char *filename, ares__buf_t *buf)
/* Get length portably, fstat() is POSIX, not C */
if (fseek(fp, 0, SEEK_END) != 0) {
- status = ARES_EFILE;
- goto done;
+ status = ARES_EFILE; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ftell_len = ftell(fp);
if (ftell_len < 0) {
- status = ARES_EFILE;
- goto done;
+ status = ARES_EFILE; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
len = (size_t)ftell_len;
if (fseek(fp, 0, SEEK_SET) != 0) {
- status = ARES_EFILE;
- goto done;
+ status = ARES_EFILE; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
if (len == 0) {
- status = ARES_SUCCESS;
- goto done;
+ status = ARES_SUCCESS; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Read entire data into buffer */
ptr_len = len;
ptr = ares__buf_append_start(buf, &ptr_len);
if (ptr == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
ptr_len = fread(ptr, 1, len, fp);
if (ptr_len != len) {
- status = ARES_EFILE;
- goto done;
+ status = ARES_EFILE; /* LCOV_EXCL_LINE: DefensiveCoding */
+ goto done; /* LCOV_EXCL_LINE: DefensiveCoding */
}
ares__buf_append_finish(buf, len);
diff --git a/contrib/libs/c-ares/src/lib/ares__buf.h b/contrib/libs/c-ares/src/lib/str/ares__buf.h
index 4298814f7b..cb887aa27e 100644
--- a/contrib/libs/c-ares/src/lib/ares__buf.h
+++ b/contrib/libs/c-ares/src/lib/str/ares__buf.h
@@ -85,10 +85,10 @@ ares_status_t ares__buf_append(ares__buf_t *buf, const unsigned char *data,
/*! Append a single byte to the dynamic buffer object
*
* \param[in] buf Initialized buffer object
- * \param[in] byte Single byte to append to buffer object.
+ * \param[in] b Single byte to append to buffer object.
* \return ARES_SUCCESS or one of the c-ares error codes
*/
-ares_status_t ares__buf_append_byte(ares__buf_t *buf, unsigned char byte);
+ares_status_t ares__buf_append_byte(ares__buf_t *buf, unsigned char b);
/*! Append a null-terminated string to the dynamic buffer object
*
@@ -554,13 +554,31 @@ size_t ares__buf_get_position(const ares__buf_t *buf);
* \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
- * strings back to back, and will concatenate in
- * the returned str.
* \return ARES_SUCCESS on success
*/
ares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, size_t remaining_len,
- char **name, ares_bool_t allow_multiple);
+ char **name);
+
+/*! Parse an array of character strings as defined in RFC1035, as binary,
+ * however, for convenience this does guarantee a NULL terminator (that is
+ * not included in the length for each value).
+ *
+ * \param[in] buf initialized buffer object
+ * \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] strs Pointer passed by reference to be filled in
+ * with
+ * the array of values.
+ * \param[out] validate_printable Validate the strings contain only printable
+ * data.
+ * \return ARES_SUCCESS on success
+ */
+ares_status_t ares__buf_parse_dns_abinstr(ares__buf_t *buf,
+ size_t remaining_len,
+ ares__dns_multistring_t **strs,
+ ares_bool_t validate_printable);
/*! Parse a character-string as defined in RFC1035, as binary, however for
* convenience this does guarantee a NULL terminator (that is not included
@@ -574,14 +592,10 @@ ares_status_t ares__buf_parse_dns_str(ares__buf_t *buf, size_t remaining_len,
* allocated string of the parsed that must be
* ares_free()'d by the caller.
* \param[out] bin_len Length of returned string.
- * \param[in] allow_multiple ARES_TRUE if it should attempt to parse multiple
- * strings back to back, and will concatenate in
- * the returned str.
* \return ARES_SUCCESS on success
*/
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);
+ unsigned char **bin, size_t *bin_len);
/*! Load data from specified file path into provided buffer. The entire file
* is loaded into memory.
diff --git a/contrib/libs/c-ares/src/lib/ares_str.c b/contrib/libs/c-ares/src/lib/str/ares_str.c
index 44a5e452fb..ade61041eb 100644
--- a/contrib/libs/c-ares/src/lib/ares_str.c
+++ b/contrib/libs/c-ares/src/lib/str/ares_str.c
@@ -25,10 +25,8 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares_str.h"
-#include "ares.h"
#include "ares_private.h"
+#include "ares_str.h"
#ifdef HAVE_STDINT_H
# include <stdint.h>
@@ -56,7 +54,7 @@ char *ares_strdup(const char *s1)
/* Don't see how this is possible */
if (len == SIZE_MAX) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
}
out = ares_malloc(len + 1);
@@ -77,7 +75,7 @@ size_t ares_strcpy(char *dest, const char *src, size_t dest_size)
size_t len = 0;
if (dest == NULL || dest_size == 0) {
- return 0;
+ return 0; /* LCOV_EXCL_LINE: DefensiveCoding */
}
len = ares_strlen(src);
@@ -116,7 +114,7 @@ void ares__str_rtrim(char *str)
size_t i;
if (str == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
len = ares_strlen(str);
@@ -134,7 +132,7 @@ void ares__str_ltrim(char *str)
size_t len;
if (str == NULL) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
for (i = 0; str[i] != 0 && ares__isspace(str[i]); i++) {
@@ -262,7 +260,7 @@ ares_bool_t ares__is_hostname(const char *str)
size_t i;
if (str == NULL) {
- return ARES_FALSE;
+ return ARES_FALSE; /* LCOV_EXCL_LINE: DefensiveCoding */
}
for (i = 0; str[i] != 0; i++) {
diff --git a/contrib/libs/c-ares/src/lib/ares_str.h b/contrib/libs/c-ares/src/lib/str/ares_str.h
index 526a927a62..440758c21b 100644
--- a/contrib/libs/c-ares/src/lib/ares_str.h
+++ b/contrib/libs/c-ares/src/lib/str/ares_str.h
@@ -27,9 +27,6 @@
#ifndef __ARES_STR_H
#define __ARES_STR_H
-#include "ares_setup.h"
-#include "ares.h"
-
char *ares_strdup(const char *s1);
size_t ares_strlen(const char *str);
@@ -75,5 +72,18 @@ ares_bool_t ares__is_hostname(const char *str);
*/
ares_bool_t ares__str_isprint(const char *str, size_t len);
+/* We only care about ASCII rules */
+#define ares__isascii(x) (((unsigned char)x) <= 127)
+#define ares__isdigit(x) \
+ (((unsigned char)x) >= '0' && ((unsigned char)x) <= '9')
+#define ares__isxdigit(x) \
+ (ares__isdigit(x) || \
+ (((unsigned char)x) >= 'a' && ((unsigned char)x) <= 'f') || \
+ (((unsigned char)x) >= 'A' && ((unsigned char)x) <= 'F'))
+#define ares__isupper(x) \
+ (((unsigned char)x) >= 'A' && ((unsigned char)x) <= 'Z')
+#define ares__islower(x) \
+ (((unsigned char)x) >= 'a' && ((unsigned char)x) <= 'z')
+#define ares__isalpha(x) (ares__islower(x) || ares__isupper(x))
#endif /* __ARES_STR_H */
diff --git a/contrib/libs/c-ares/src/lib/ares_strcasecmp.c b/contrib/libs/c-ares/src/lib/str/ares_strcasecmp.c
index b91cbbe154..76b835fd8e 100644
--- a/contrib/libs/c-ares/src/lib/ares_strcasecmp.c
+++ b/contrib/libs/c-ares/src/lib/str/ares_strcasecmp.c
@@ -25,7 +25,7 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
+#include "ares_private.h"
#include "ares_strcasecmp.h"
#ifndef HAVE_STRCASECMP
@@ -39,8 +39,8 @@ int ares_strcasecmp(const char *a, const char *b)
size_t i;
for (i = 0; i < (size_t)-1; i++) {
- int c1 = ISUPPER(a[i]) ? tolower(a[i]) : a[i];
- int c2 = ISUPPER(b[i]) ? tolower(b[i]) : b[i];
+ int c1 = ares__tolower(a[i]);
+ int c2 = ares__tolower(b[i]);
if (c1 != c2) {
return c1 - c2;
}
@@ -64,8 +64,8 @@ int ares_strncasecmp(const char *a, const char *b, size_t n)
size_t i;
for (i = 0; i < n; i++) {
- int c1 = ISUPPER(a[i]) ? tolower(a[i]) : a[i];
- int c2 = ISUPPER(b[i]) ? tolower(b[i]) : b[i];
+ int c1 = ares__tolower(a[i]);
+ int c2 = ares__tolower(b[i]);
if (c1 != c2) {
return c1 - c2;
}
diff --git a/contrib/libs/c-ares/src/lib/ares_strcasecmp.h b/contrib/libs/c-ares/src/lib/str/ares_strcasecmp.h
index 31a66be717..a8097d2219 100644
--- a/contrib/libs/c-ares/src/lib/ares_strcasecmp.h
+++ b/contrib/libs/c-ares/src/lib/str/ares_strcasecmp.h
@@ -27,8 +27,6 @@
#ifndef HEADER_CARES_STRCASECMP_H
#define HEADER_CARES_STRCASECMP_H
-#include "ares_setup.h"
-
#ifndef HAVE_STRCASECMP
extern int ares_strcasecmp(const char *a, const char *b);
#endif
diff --git a/contrib/libs/c-ares/src/lib/ares_strsplit.c b/contrib/libs/c-ares/src/lib/str/ares_strsplit.c
index 395bf1ebb9..dee307d779 100644
--- a/contrib/libs/c-ares/src/lib/ares_strsplit.c
+++ b/contrib/libs/c-ares/src/lib/str/ares_strsplit.c
@@ -23,13 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-
-#if defined(__MVS__)
-# include <strings.h>
-#endif
-
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
void ares__strsplit_free(char **elms, size_t num_elm)
@@ -52,19 +45,19 @@ char **ares__strsplit_duplicate(char **elms, size_t num_elm)
char **out;
if (elms == NULL || num_elm == 0) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
}
out = ares_malloc_zero(sizeof(*elms) * num_elm);
if (out == NULL) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
}
for (i = 0; i < num_elm; i++) {
out[i] = ares_strdup(elms[i]);
if (out[i] == NULL) {
- ares__strsplit_free(out, num_elm);
- return NULL;
+ ares__strsplit_free(out, num_elm); /* LCOV_EXCL_LINE: OutOfMemory */
+ return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
}
}
@@ -82,7 +75,7 @@ char **ares__strsplit(const char *in, const char *delms, size_t *num_elm)
size_t idx = 0;
if (in == NULL || delms == NULL || num_elm == NULL) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
}
*num_elm = 0;
@@ -108,8 +101,8 @@ char **ares__strsplit(const char *in, const char *delms, size_t *num_elm)
out = ares_malloc_zero(cnt * sizeof(*out));
if (out == NULL) {
- status = ARES_ENOMEM;
- goto done;
+ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
+ goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
for (node = ares__llist_node_first(llist); node != NULL;
diff --git a/contrib/libs/c-ares/src/lib/ares_strsplit.h b/contrib/libs/c-ares/src/lib/str/ares_strsplit.h
index af650eee53..ee997804f0 100644
--- a/contrib/libs/c-ares/src/lib/ares_strsplit.h
+++ b/contrib/libs/c-ares/src/lib/str/ares_strsplit.h
@@ -26,8 +26,6 @@
#ifndef HEADER_CARES_STRSPLIT_H
#define HEADER_CARES_STRSPLIT_H
-#include "ares_setup.h"
-
/* Split a string on delms skipping empty or duplicate elements.
*
* param in String to split.
diff --git a/contrib/libs/c-ares/src/lib/thirdparty/apple/README.md b/contrib/libs/c-ares/src/lib/thirdparty/apple/README.md
index e0915f4a43..8cef22ed7e 100644
--- a/contrib/libs/c-ares/src/lib/thirdparty/apple/README.md
+++ b/contrib/libs/c-ares/src/lib/thirdparty/apple/README.md
@@ -1,4 +1,18 @@
The `dnsinfo.h` header was extracted from Apple's OpenSource repository:
-[https://opensource.apple.com/source/configd/configd-1109.140.1/dnsinfo/dnsinfo.h](https://opensource.apple.com/source/configd/configd-1109.140.1/dnsinfo/dnsinfo.h)
+[https://opensource.apple.com/source/configd/configd-453.19/dnsinfo/dnsinfo.h](https://opensource.apple.com/source/configd/configd-453.19/dnsinfo/dnsinfo.h)
-This is needed to call into `dns_configuration_copy()` and `dns_configuration_free()`.
+We then had to make a few edits to this file:
+1. Add `AvailabilityMacros.h` header file
+2. conditionalize `reach_flags` in `dns_resolver_t` on MacOS 10.8 or higher, in
+ order to maintain compatibility with the last MacOS PPC release, 10.6.
+3. conditionalize `_dns_configuration_ack()` on MacOS 10.8 or higher.
+4. Update parameter list to `(void)` for both `dns_configuration_notify_key()`
+ and `dns_configuration_copy()` to sidestep compiler warnings in this old
+ header.
+
+We had tried initially to use the latest 1109.140.1 which only worked on
+MacOS 11+, then downgraded to 963.50.8 for MacOS 10.8+ support, then finally
+to 453.19 with additional patches.
+
+This is needed to call into `dns_configuration_copy()` and
+`dns_configuration_free()`.
diff --git a/contrib/libs/c-ares/src/lib/thirdparty/apple/dnsinfo.h b/contrib/libs/c-ares/src/lib/thirdparty/apple/dnsinfo.h
index d5a0e70e2f..d92a1d8030 100644
--- a/contrib/libs/c-ares/src/lib/thirdparty/apple/dnsinfo.h
+++ b/contrib/libs/c-ares/src/lib/thirdparty/apple/dnsinfo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2006, 2008, 2009, 2011-2013, 2015-2018 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2006, 2008, 2009, 2011 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
@@ -28,14 +28,15 @@
* These routines provide access to the systems DNS configuration
*/
-#include <os/availability.h>
+#include <Availability.h>
#include <sys/cdefs.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include <AvailabilityMacros.h>
-#define DNSINFO_VERSION 20170629
+#define DNSINFO_VERSION 20111104
#define DEFAULT_SEARCH_ORDER 200000 /* search order for the "default" resolver domain name */
@@ -72,23 +73,17 @@ typedef struct {
DNS_VAR(uint32_t, search_order); /* search_order */
DNS_VAR(uint32_t, if_index);
DNS_VAR(uint32_t, flags);
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 /* MacOS 10.8 */
+ DNS_VAR(uint32_t, reserved[6]);
+#else
DNS_VAR(uint32_t, reach_flags); /* SCNetworkReachabilityFlags */
- DNS_VAR(uint32_t, service_identifier);
- DNS_PTR(char *, cid); /* configuration identifer */
- DNS_PTR(char *, if_name); /* if_index interface name */
+ DNS_VAR(uint32_t, reserved[5]);
+#endif
} dns_resolver_t;
#pragma pack()
-#define DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS 0x0002 /* always requesting for A dns records in queries */
-#define DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS 0x0004 /* always requesting for AAAA dns records in queries */
-
-#define DNS_RESOLVER_FLAGS_REQUEST_ALL_RECORDS \
- (DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS | DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS)
-
-#define DNS_RESOLVER_FLAGS_SCOPED 0x1000 /* configuration is for scoped questions */
-#define DNS_RESOLVER_FLAGS_SERVICE_SPECIFIC 0x2000 /* configuration is service-specific */
-#define DNS_RESOLVER_FLAGS_SUPPLEMENTAL 0x4000 /* supplemental match configuration */
+#define DNS_RESOLVER_FLAGS_SCOPED 1 /* configuration is for scoped questions */
#pragma pack(4)
@@ -97,10 +92,7 @@ typedef struct {
DNS_PTR(dns_resolver_t **, resolver);
DNS_VAR(int32_t, n_scoped_resolver); /* "scoped" resolver configurations */
DNS_PTR(dns_resolver_t **, scoped_resolver);
- DNS_VAR(uint64_t, generation);
- DNS_VAR(int32_t, n_service_specific_resolver);
- DNS_PTR(dns_resolver_t **, service_specific_resolver);
- DNS_VAR(uint32_t, version);
+ DNS_VAR(uint32_t, reserved[5]);
} dns_config_t;
#pragma pack()
@@ -111,17 +103,19 @@ __BEGIN_DECLS
* DNS configuration access APIs
*/
const char *
-dns_configuration_notify_key (void) API_AVAILABLE(macos(10.4), ios(2.0));
+dns_configuration_notify_key (void) __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
dns_config_t *
-dns_configuration_copy (void) API_AVAILABLE(macos(10.4), ios(2.0));
+dns_configuration_copy (void) __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
void
-dns_configuration_free (dns_config_t *config) API_AVAILABLE(macos(10.4), ios(2.0));
+dns_configuration_free (dns_config_t *config) __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_2_0);
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
void
_dns_configuration_ack (dns_config_t *config,
- const char *bundle_id) API_AVAILABLE(macos(10.8), ios(6.0));
+ const char *bundle_id) __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_6_0);
+#endif
__END_DECLS
diff --git a/contrib/libs/c-ares/src/lib/ares__iface_ips.c b/contrib/libs/c-ares/src/lib/util/ares__iface_ips.c
index b252a7ab49..56dc257904 100644
--- a/contrib/libs/c-ares/src/lib/ares__iface_ips.c
+++ b/contrib/libs/c-ares/src/lib/util/ares__iface_ips.c
@@ -23,8 +23,7 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-
+#include "ares_private.h"
#ifdef USE_WINSOCK
# include <winsock2.h>
@@ -55,9 +54,10 @@
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
-#include "ares.h"
-#include "ares_private.h"
static ares_status_t ares__iface_ips_enumerate(ares__iface_ips_t *ips,
const char *name);
@@ -71,51 +71,43 @@ typedef struct {
} ares__iface_ip_t;
struct ares__iface_ips {
- ares__iface_ip_t *ips;
- size_t cnt;
- size_t alloc_size;
+ ares__array_t *ips; /*!< Type is ares__iface_ip_t */
ares__iface_ip_flags_t enum_flags;
};
+static void ares__iface_ip_free_cb(void *arg)
+{
+ ares__iface_ip_t *ip = arg;
+ if (ip == NULL) {
+ return;
+ }
+ ares_free(ip->name);
+}
+
static ares__iface_ips_t *ares__iface_ips_alloc(ares__iface_ip_flags_t flags)
{
ares__iface_ips_t *ips = ares_malloc_zero(sizeof(*ips));
if (ips == NULL) {
- return NULL;
+ return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
}
- /* Prealloc 4 entries */
- ips->alloc_size = 4;
- ips->ips = ares_malloc_zero(ips->alloc_size * sizeof(*ips->ips));
+ ips->enum_flags = flags;
+ ips->ips =
+ ares__array_create(sizeof(ares__iface_ip_t), ares__iface_ip_free_cb);
if (ips->ips == NULL) {
- ares_free(ips);
- return NULL;
+ ares_free(ips); /* LCOV_EXCL_LINE: OutOfMemory */
+ return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
}
- ips->enum_flags = flags;
return ips;
}
-static void ares__iface_ip_destroy(ares__iface_ip_t *ip)
-{
- if (ip == NULL) {
- return;
- }
- ares_free(ip->name);
- memset(ip, 0, sizeof(*ip));
-}
-
void ares__iface_ips_destroy(ares__iface_ips_t *ips)
{
- size_t i;
-
if (ips == NULL) {
return;
}
- for (i = 0; i < ips->cnt; i++) {
- ares__iface_ip_destroy(&ips->ips[i]);
- }
- ares_free(ips->ips);
+ ares__array_destroy(ips->ips);
ares_free(ips);
}
@@ -130,14 +122,16 @@ ares_status_t ares__iface_ips(ares__iface_ips_t **ips,
*ips = ares__iface_ips_alloc(flags);
if (*ips == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__iface_ips_enumerate(*ips, name);
if (status != ARES_SUCCESS) {
+ /* LCOV_EXCL_START: UntestablePath */
ares__iface_ips_destroy(*ips);
*ips = NULL;
return status;
+ /* LCOV_EXCL_STOP */
}
return ARES_SUCCESS;
@@ -148,10 +142,11 @@ static ares_status_t
const char *name, const struct ares_addr *addr,
unsigned char netmask, unsigned int ll_scope)
{
- size_t idx;
+ ares__iface_ip_t *ip;
+ ares_status_t status;
if (ips == NULL || name == NULL || addr == NULL) {
- return ARES_EFORMERR;
+ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
}
/* Don't want loopback */
@@ -195,31 +190,21 @@ static ares_status_t
}
}
- /* Allocate more ips */
- if (ips->cnt + 1 > ips->alloc_size) {
- void *temp;
- size_t alloc_size;
-
- alloc_size = ares__round_up_pow2(ips->alloc_size + 1);
- temp = ares_realloc_zero(ips->ips, ips->alloc_size * sizeof(*ips->ips),
- alloc_size * sizeof(*ips->ips));
- if (temp == NULL) {
- return ARES_ENOMEM;
- }
- ips->ips = temp;
- ips->alloc_size = alloc_size;
+ status = ares__array_insert_last((void **)&ip, ips->ips);
+ if (status != ARES_SUCCESS) {
+ return status;
}
- /* Add */
- idx = ips->cnt++;
-
- ips->ips[idx].flags = flags;
- ips->ips[idx].netmask = netmask;
- ips->ips[idx].ll_scope = ll_scope;
- memcpy(&ips->ips[idx].addr, addr, sizeof(*addr));
- ips->ips[idx].name = ares_strdup(name);
- if (ips->ips[idx].name == NULL) {
- return ARES_ENOMEM;
+ ip->flags = flags;
+ ip->netmask = netmask;
+ if (flags & ARES_IFACE_IP_LINKLOCAL) {
+ ip->ll_scope = ll_scope;
+ }
+ memcpy(&ip->addr, addr, sizeof(*addr));
+ ip->name = ares_strdup(name);
+ if (ip->name == NULL) {
+ ares__array_remove_last(ips->ips);
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
return ARES_SUCCESS;
@@ -230,51 +215,91 @@ size_t ares__iface_ips_cnt(const ares__iface_ips_t *ips)
if (ips == NULL) {
return 0;
}
- return ips->cnt;
+ return ares__array_len(ips->ips);
}
const char *ares__iface_ips_get_name(const ares__iface_ips_t *ips, size_t idx)
{
- if (ips == NULL || idx >= ips->cnt) {
+ const ares__iface_ip_t *ip;
+
+ if (ips == NULL) {
+ return NULL;
+ }
+
+ ip = ares__array_at_const(ips->ips, idx);
+ if (ip == NULL) {
return NULL;
}
- return ips->ips[idx].name;
+
+ return ip->name;
}
const struct ares_addr *ares__iface_ips_get_addr(const ares__iface_ips_t *ips,
size_t idx)
{
- if (ips == NULL || idx >= ips->cnt) {
+ const ares__iface_ip_t *ip;
+
+ if (ips == NULL) {
return NULL;
}
- return &ips->ips[idx].addr;
+
+ ip = ares__array_at_const(ips->ips, idx);
+ if (ip == NULL) {
+ return NULL;
+ }
+
+ return &ip->addr;
}
ares__iface_ip_flags_t ares__iface_ips_get_flags(const ares__iface_ips_t *ips,
size_t idx)
{
- if (ips == NULL || idx >= ips->cnt) {
+ const ares__iface_ip_t *ip;
+
+ if (ips == NULL) {
return 0;
}
- return ips->ips[idx].flags;
+
+ ip = ares__array_at_const(ips->ips, idx);
+ if (ip == NULL) {
+ return 0;
+ }
+
+ return ip->flags;
}
unsigned char ares__iface_ips_get_netmask(const ares__iface_ips_t *ips,
size_t idx)
{
- if (ips == NULL || idx >= ips->cnt) {
+ const ares__iface_ip_t *ip;
+
+ if (ips == NULL) {
return 0;
}
- return ips->ips[idx].netmask;
+
+ ip = ares__array_at_const(ips->ips, idx);
+ if (ip == NULL) {
+ return 0;
+ }
+
+ return ip->netmask;
}
unsigned int ares__iface_ips_get_ll_scope(const ares__iface_ips_t *ips,
size_t idx)
{
- if (ips == NULL || idx >= ips->cnt) {
+ const ares__iface_ip_t *ip;
+
+ if (ips == NULL) {
+ return 0;
+ }
+
+ ip = ares__array_at_const(ips->ips, idx);
+ if (ip == NULL) {
return 0;
}
- return ips->ips[idx].ll_scope;
+
+ return ip->ll_scope;
}
@@ -490,7 +515,7 @@ static ares_status_t ares__iface_ips_enumerate(ares__iface_ips_t *ips,
}
/* Name mismatch */
- if (strcasecmp(ifa->ifa_name, name) != 0) {
+ if (name != NULL && strcasecmp(ifa->ifa_name, name) != 0) {
continue;
}
@@ -522,6 +547,9 @@ static ares_status_t ares__iface_ips_enumerate(ares__iface_ips_t *ips,
unsigned int ares__if_nametoindex(const char *name)
{
#ifdef HAVE_IF_NAMETOINDEX
+ if (name == NULL) {
+ return 0;
+ }
return if_nametoindex(name);
#else
ares_status_t status;
@@ -529,6 +557,10 @@ unsigned int ares__if_nametoindex(const char *name)
size_t i;
unsigned int index = 0;
+ if (name == NULL) {
+ return 0;
+ }
+
status =
ares__iface_ips(&ips, ARES_IFACE_IP_V6 | ARES_IFACE_IP_LINKLOCAL, name);
if (status != ARES_SUCCESS) {
@@ -562,7 +594,7 @@ const char *ares__if_indextoname(unsigned int index, char *name,
size_t i;
const char *ptr = NULL;
- if (name_len < IF_NAMESIZE) {
+ if (name == NULL || name_len < IF_NAMESIZE) {
goto done;
}
diff --git a/contrib/libs/c-ares/src/lib/ares__iface_ips.h b/contrib/libs/c-ares/src/lib/util/ares__iface_ips.h
index 61ff736a79..61ff736a79 100644
--- a/contrib/libs/c-ares/src/lib/ares__iface_ips.h
+++ b/contrib/libs/c-ares/src/lib/util/ares__iface_ips.h
diff --git a/contrib/libs/c-ares/src/lib/ares__threads.c b/contrib/libs/c-ares/src/lib/util/ares__threads.c
index 53c81d41b2..b47544451d 100644
--- a/contrib/libs/c-ares/src/lib/ares__threads.c
+++ b/contrib/libs/c-ares/src/lib/util/ares__threads.c
@@ -23,8 +23,6 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#ifdef CARES_THREADS
@@ -226,25 +224,27 @@ ares__thread_mutex_t *ares__thread_mutex_create(void)
}
if (pthread_mutexattr_init(&attr) != 0) {
- ares_free(mut);
- return NULL;
+ ares_free(mut); /* LCOV_EXCL_LINE: UntestablePath */
+ return NULL; /* LCOV_EXCL_LINE: UntestablePath */
}
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: UntestablePath */
}
if (pthread_mutex_init(&mut->mutex, &attr) != 0) {
- goto fail;
+ goto fail; /* LCOV_EXCL_LINE: UntestablePath */
}
pthread_mutexattr_destroy(&attr);
return mut;
+/* LCOV_EXCL_START: UntestablePath */
fail:
pthread_mutexattr_destroy(&attr);
ares_free(mut);
return NULL;
+ /* LCOV_EXCL_STOP */
}
void ares__thread_mutex_destroy(ares__thread_mutex_t *mut)
@@ -379,11 +379,11 @@ ares_status_t ares__thread_create(ares__thread_t **thread,
thr = ares_malloc_zero(sizeof(*thr));
if (thr == NULL) {
- return ARES_ENOMEM;
+ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
}
if (pthread_create(&thr->thread, NULL, func, arg) != 0) {
- ares_free(thr);
- return ARES_ESERVFAIL;
+ ares_free(thr); /* LCOV_EXCL_LINE: UntestablePath */
+ return ARES_ESERVFAIL; /* LCOV_EXCL_LINE: UntestablePath */
}
*thread = thr;
@@ -562,7 +562,7 @@ ares_status_t ares_queue_wait_empty(ares_channel_t *channel, int timeout_ms)
}
if (timeout_ms >= 0) {
- tout = ares__tvnow();
+ ares__tvnow(&tout);
tout.sec += (ares_int64_t)(timeout_ms / 1000);
tout.usec += (unsigned int)(timeout_ms % 1000) * 1000;
}
@@ -573,9 +573,10 @@ ares_status_t ares_queue_wait_empty(ares_channel_t *channel, int timeout_ms)
ares__thread_cond_wait(channel->cond_empty, channel->lock);
} else {
ares_timeval_t tv_remaining;
- ares_timeval_t tv_now = ares__tvnow();
+ ares_timeval_t tv_now;
unsigned long tms;
+ ares__tvnow(&tv_now);
ares__timeval_remaining(&tv_remaining, &tv_now, &tout);
tms =
(unsigned long)((tv_remaining.sec * 1000) + (tv_remaining.usec / 1000));
diff --git a/contrib/libs/c-ares/src/lib/ares__threads.h b/contrib/libs/c-ares/src/lib/util/ares__threads.h
index 108354dfc1..108354dfc1 100644
--- a/contrib/libs/c-ares/src/lib/ares__threads.h
+++ b/contrib/libs/c-ares/src/lib/util/ares__threads.h
diff --git a/contrib/libs/c-ares/src/lib/ares__timeval.c b/contrib/libs/c-ares/src/lib/util/ares__timeval.c
index fae5ad7e87..e3a989dca8 100644
--- a/contrib/libs/c-ares/src/lib/ares__timeval.c
+++ b/contrib/libs/c-ares/src/lib/util/ares__timeval.c
@@ -24,62 +24,68 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
-#if defined(WIN32) && !defined(MSDOS)
+#if defined(_WIN32) && !defined(MSDOS)
-ares_timeval_t ares__tvnow(void)
+void ares__tvnow(ares_timeval_t *now)
{
- /* GetTickCount64() is available on Windows Vista and higher */
- ares_timeval_t now;
- ULONGLONG milliseconds = GetTickCount64();
+ /* QueryPerformanceCounters() has been around since Windows 2000, though
+ * significant fixes were made in later versions. Documentation states
+ * 1 microsecond or better resolution with a rollover not less than 100 years.
+ * This differs from GetTickCount{64}() which has a resolution between 10 and
+ * 16 ms. */
+ LARGE_INTEGER freq;
+ LARGE_INTEGER current;
- now.sec = (ares_int64_t)milliseconds / 1000;
- now.usec = (unsigned int)(milliseconds % 1000) * 1000;
- return now;
+ /* Not sure how long it takes to get the frequency, I see it recommended to
+ * cache it */
+ QueryPerformanceFrequency(&freq);
+ QueryPerformanceCounter(&current);
+
+ now->sec = current.QuadPart / freq.QuadPart;
+ /* We want to prevent overflows so we get the remainder, then multiply to
+ * microseconds before dividing */
+ now->usec = (unsigned int)(((current.QuadPart % freq.QuadPart) * 1000000) /
+ freq.QuadPart);
}
#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC)
-ares_timeval_t ares__tvnow(void)
+void ares__tvnow(ares_timeval_t *now)
{
/* clock_gettime() is guaranteed to be increased monotonically when the
* monotonic clock is queried. Time starting point is unspecified, it
* could be the system start-up time, the Epoch, or something else,
* in any case the time starting point does not change once that the
* system has started up. */
- ares_timeval_t now;
struct timespec tsnow;
if (clock_gettime(CLOCK_MONOTONIC, &tsnow) == 0) {
- now.sec = (ares_int64_t)tsnow.tv_sec;
- now.usec = (unsigned int)(tsnow.tv_nsec / 1000);
+ now->sec = (ares_int64_t)tsnow.tv_sec;
+ now->usec = (unsigned int)(tsnow.tv_nsec / 1000);
} else {
+ /* LCOV_EXCL_START: FallbackCode */
struct timeval tv;
(void)gettimeofday(&tv, NULL);
- now.sec = (ares_int64_t)tv.tv_sec;
- now.usec = (unsigned int)tv.tv_usec;
+ now->sec = (ares_int64_t)tv.tv_sec;
+ now->usec = (unsigned int)tv.tv_usec;
+ /* LCOV_EXCL_STOP */
}
- return now;
}
#elif defined(HAVE_GETTIMEOFDAY)
-ares_timeval_t ares__tvnow(void)
+void ares__tvnow(ares_timeval_t *now)
{
/* gettimeofday() is not granted to be increased monotonically, due to
* clock drifting and external source time synchronization it can jump
* forward or backward in time. */
- ares_timeval_t now;
struct timeval tv;
(void)gettimeofday(&tv, NULL);
- now.sec = (ares_int64_t)tv.tv_sec;
- now.usec = (unsigned int)tv.tv_usec;
-
- return now;
+ now->sec = (ares_int64_t)tv.tv_sec;
+ now->usec = (unsigned int)tv.tv_usec;
}
#else
diff --git a/contrib/libs/c-ares/src/lib/ares_math.c b/contrib/libs/c-ares/src/lib/util/ares_math.c
index eaefd6c5de..45999bdeab 100644
--- a/contrib/libs/c-ares/src/lib/ares_math.c
+++ b/contrib/libs/c-ares/src/lib/util/ares_math.c
@@ -23,8 +23,7 @@
*
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
+
#include "ares_private.h"
/* Uses public domain code snippets from
@@ -57,9 +56,23 @@ static ares_int64_t ares__round_up_pow2_u64(ares_int64_t n)
return n;
}
+ares_bool_t ares__is_64bit(void)
+{
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable : 4127)
+#endif
+
+ return (sizeof(size_t) == 4) ? ARES_FALSE : ARES_TRUE;
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+}
+
size_t ares__round_up_pow2(size_t n)
{
- if (sizeof(size_t) > 4) {
+ if (ares__is_64bit()) {
return (size_t)ares__round_up_pow2_u64((ares_int64_t)n);
}
@@ -79,7 +92,7 @@ size_t ares__log2(size_t n)
56, 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5
};
- if (sizeof(size_t) == 4) {
+ if (!ares__is_64bit()) {
return tab32[(n * 0x077CB531) >> 27];
}
diff --git a/contrib/libs/c-ares/src/lib/ares_rand.c b/contrib/libs/c-ares/src/lib/util/ares_rand.c
index bf3a695c9c..c57bb706e6 100644
--- a/contrib/libs/c-ares/src/lib/ares_rand.c
+++ b/contrib/libs/c-ares/src/lib/util/ares_rand.c
@@ -24,8 +24,6 @@
* SPDX-License-Identifier: MIT
*/
-#include "ares_setup.h"
-#include "ares.h"
#include "ares_private.h"
#include <stdlib.h>
@@ -43,7 +41,7 @@
typedef enum {
ARES_RAND_OS = 1 << 0, /* OS-provided such as RtlGenRandom or arc4random */
ARES_RAND_FILE = 1 << 1, /* OS file-backed random number generator */
- ARES_RAND_RC4 = 1 << 2, /* Internal RC4 based PRNG */
+ ARES_RAND_RC4 = 1 << 2 /* Internal RC4 based PRNG */
} ares_rand_backend;
#define ARES_RC4_KEY_LEN 32 /* 256 bits */
@@ -56,17 +54,20 @@ typedef struct ares_rand_rc4 {
static unsigned int ares_u32_from_ptr(void *addr)
{
- if (sizeof(void *) == 8) {
+ /* LCOV_EXCL_START: FallbackCode */
+ if (ares__is_64bit()) {
return (unsigned int)((((ares_uint64_t)addr >> 32) & 0xFFFFFFFF) |
((ares_uint64_t)addr & 0xFFFFFFFF));
}
return (unsigned int)((size_t)addr & 0xFFFFFFFF);
+ /* LCOV_EXCL_STOP */
}
/* initialize an rc4 key as the last possible fallback. */
static void ares_rc4_generate_key(ares_rand_rc4 *rc4_state, unsigned char *key,
size_t key_len)
{
+ /* LCOV_EXCL_START: FallbackCode */
size_t i;
size_t len = 0;
unsigned int data;
@@ -88,7 +89,7 @@ static void ares_rc4_generate_key(ares_rand_rc4 *rc4_state, unsigned char *key,
memcpy(key + len, &data, sizeof(data));
len += sizeof(data);
- tv = ares__tvnow();
+ ares__tvnow(&tv);
data = (unsigned int)((tv.sec | tv.usec) & 0xFFFFFFFF);
memcpy(key + len, &data, sizeof(data));
len += sizeof(data);
@@ -99,10 +100,19 @@ static void ares_rc4_generate_key(ares_rand_rc4 *rc4_state, unsigned char *key,
for (i = len; i < key_len; i++) {
key[i] = (unsigned char)(rand() % 256); /* LCOV_EXCL_LINE */
}
+ /* LCOV_EXCL_STOP */
}
+#define ARES_SWAP_BYTE(a, b) \
+ do { \
+ unsigned char swapByte = *(a); \
+ *(a) = *(b); \
+ *(b) = swapByte; \
+ } while (0)
+
static void ares_rc4_init(ares_rand_rc4 *rc4_state)
{
+ /* LCOV_EXCL_START: FallbackCode */
unsigned char key[ARES_RC4_KEY_LEN];
size_t i;
size_t j;
@@ -120,6 +130,7 @@ static void ares_rc4_init(ares_rand_rc4 *rc4_state)
rc4_state->i = 0;
rc4_state->j = 0;
+ /* LCOV_EXCL_STOP */
}
/* Just outputs the key schedule, no need to XOR with any data since we have
@@ -127,6 +138,7 @@ static void ares_rc4_init(ares_rand_rc4 *rc4_state)
static void ares_rc4_prng(ares_rand_rc4 *rc4_state, unsigned char *buf,
size_t len)
{
+ /* LCOV_EXCL_START: FallbackCode */
unsigned char *S = rc4_state->S;
size_t i = rc4_state->i;
size_t j = rc4_state->j;
@@ -142,6 +154,7 @@ static void ares_rc4_prng(ares_rand_rc4 *rc4_state, unsigned char *buf,
rc4_state->i = i;
rc4_state->j = j;
+ /* LCOV_EXCL_STOP */
}
struct ares_rand_state {
@@ -187,6 +200,7 @@ static ares_bool_t ares__init_rand_engine(ares_rand_state *state)
#endif
#if defined(CARES_RANDOM_FILE)
+ /* LCOV_EXCL_START: FallbackCode */
if (!(state->bad_backends & ARES_RAND_FILE)) {
state->type = ARES_RAND_FILE;
state->state.rand_file = fopen(CARES_RANDOM_FILE, "rb");
@@ -195,14 +209,18 @@ static ares_bool_t ares__init_rand_engine(ares_rand_state *state)
return ARES_TRUE;
}
}
+ /* LCOV_EXCL_STOP */
+
/* Fall-Thru on failure to RC4 */
#endif
+ /* LCOV_EXCL_START: FallbackCode */
state->type = ARES_RAND_RC4;
ares_rc4_init(&state->state.rc4);
+ /* LCOV_EXCL_STOP */
/* Currently cannot fail */
- return ARES_TRUE;
+ return ARES_TRUE; /* LCOV_EXCL_LINE: UntestablePath */
}
ares_rand_state *ares__init_rand_state(void)
@@ -215,8 +233,8 @@ ares_rand_state *ares__init_rand_state(void)
}
if (!ares__init_rand_engine(state)) {
- ares_free(state);
- return NULL;
+ ares_free(state); /* LCOV_EXCL_LINE: UntestablePath */
+ return NULL; /* LCOV_EXCL_LINE: UntestablePath */
}
return state;
@@ -225,24 +243,28 @@ ares_rand_state *ares__init_rand_state(void)
static void ares__clear_rand_state(ares_rand_state *state)
{
if (!state) {
- return;
+ return; /* LCOV_EXCL_LINE: DefensiveCoding */
}
switch (state->type) {
case ARES_RAND_OS:
break;
+ /* LCOV_EXCL_START: FallbackCode */
case ARES_RAND_FILE:
fclose(state->state.rand_file);
break;
case ARES_RAND_RC4:
break;
+ /* LCOV_EXCL_STOP */
}
}
static void ares__reinit_rand(ares_rand_state *state)
{
+ /* LCOV_EXCL_START: UntestablePath */
ares__clear_rand_state(state);
ares__init_rand_engine(state);
+ /* LCOV_EXCL_STOP */
}
void ares__destroy_rand_state(ares_rand_state *state)
@@ -296,6 +318,8 @@ static void ares__rand_bytes_fetch(ares_rand_state *state, unsigned char *buf,
break;
#endif
+ /* LCOV_EXCL_START: FallbackCode */
+
case ARES_RAND_FILE:
while (1) {
size_t rv = fread(buf + bytes_read, 1, len - bytes_read,
@@ -314,11 +338,13 @@ static void ares__rand_bytes_fetch(ares_rand_state *state, unsigned char *buf,
case ARES_RAND_RC4:
ares_rc4_prng(&state->state.rc4, buf, len);
return;
+
+ /* LCOV_EXCL_STOP */
}
/* If we didn't return before we got here, that means we had a critical rand
* failure and need to reinitialized */
- ares__reinit_rand(state);
+ ares__reinit_rand(state); /* LCOV_EXCL_LINE: UntestablePath */
}
}
diff --git a/contrib/libs/c-ares/src/lib/windows_port.c b/contrib/libs/c-ares/src/lib/windows_port.c
index d5f0ad3abf..22f0dc020a 100644
--- a/contrib/libs/c-ares/src/lib/windows_port.c
+++ b/contrib/libs/c-ares/src/lib/windows_port.c
@@ -6,12 +6,12 @@
* SPDX-License-Identifier: MIT
*
*/
-#include "ares_setup.h"
+#include "ares_private.h"
/* only do the following on windows
*/
-#if (defined(WIN32) || defined(WATT32)) && !defined(MSDOS)
+#if defined(_WIN32) && !defined(MSDOS)
# ifdef __WATCOMC__
/*
diff --git a/contrib/libs/c-ares/ya.make b/contrib/libs/c-ares/ya.make
index 7850b67185..864edf40a5 100644
--- a/contrib/libs/c-ares/ya.make
+++ b/contrib/libs/c-ares/ya.make
@@ -12,9 +12,9 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-VERSION(1.30.0)
+VERSION(1.33.0)
-ORIGINAL_SOURCE(https://github.com/c-ares/c-ares/archive/v1.30.0.tar.gz)
+ORIGINAL_SOURCE(https://github.com/c-ares/c-ares/archive/v1.33.0.tar.gz)
PEERDIR(
contrib/libs/libc_compat
@@ -50,43 +50,16 @@ ENDIF()
SRCS(
src/lib/ares__addrinfo2hostent.c
src/lib/ares__addrinfo_localhost.c
- src/lib/ares__buf.c
src/lib/ares__close_sockets.c
src/lib/ares__hosts_file.c
- src/lib/ares__htable.c
- src/lib/ares__htable_asvp.c
- src/lib/ares__htable_strvp.c
- src/lib/ares__htable_szvp.c
- src/lib/ares__htable_vpvp.c
- src/lib/ares__iface_ips.c
- src/lib/ares__llist.c
src/lib/ares__parse_into_addrinfo.c
- src/lib/ares__slist.c
src/lib/ares__socket.c
src/lib/ares__sortaddrinfo.c
- src/lib/ares__threads.c
- src/lib/ares__timeval.c
src/lib/ares_android.c
src/lib/ares_cancel.c
- src/lib/ares_create_query.c
+ src/lib/ares_cookie.c
src/lib/ares_data.c
src/lib/ares_destroy.c
- src/lib/ares_dns_mapping.c
- src/lib/ares_dns_name.c
- src/lib/ares_dns_parse.c
- src/lib/ares_dns_record.c
- src/lib/ares_dns_write.c
- src/lib/ares_event_configchg.c
- src/lib/ares_event_epoll.c
- src/lib/ares_event_kqueue.c
- src/lib/ares_event_poll.c
- src/lib/ares_event_select.c
- src/lib/ares_event_thread.c
- src/lib/ares_event_wake_pipe.c
- src/lib/ares_event_win32.c
- src/lib/ares_expand_name.c
- src/lib/ares_expand_string.c
- src/lib/ares_fds.c
src/lib/ares_free_hostent.c
src/lib/ares_free_string.c
src/lib/ares_freeaddrinfo.c
@@ -95,42 +68,74 @@ SRCS(
src/lib/ares_gethostbyaddr.c
src/lib/ares_gethostbyname.c
src/lib/ares_getnameinfo.c
- src/lib/ares_getsock.c
src/lib/ares_init.c
src/lib/ares_library_init.c
- src/lib/ares_math.c
+ src/lib/ares_metrics.c
src/lib/ares_options.c
- src/lib/ares_parse_a_reply.c
- src/lib/ares_parse_aaaa_reply.c
- src/lib/ares_parse_caa_reply.c
- src/lib/ares_parse_mx_reply.c
- src/lib/ares_parse_naptr_reply.c
- src/lib/ares_parse_ns_reply.c
- src/lib/ares_parse_ptr_reply.c
- src/lib/ares_parse_soa_reply.c
- src/lib/ares_parse_srv_reply.c
- src/lib/ares_parse_txt_reply.c
- src/lib/ares_parse_uri_reply.c
src/lib/ares_platform.c
src/lib/ares_process.c
src/lib/ares_qcache.c
src/lib/ares_query.c
- src/lib/ares_rand.c
src/lib/ares_search.c
src/lib/ares_send.c
- src/lib/ares_str.c
- src/lib/ares_strcasecmp.c
src/lib/ares_strerror.c
- src/lib/ares_strsplit.c
src/lib/ares_sysconfig.c
src/lib/ares_sysconfig_files.c
src/lib/ares_sysconfig_mac.c
+ src/lib/ares_sysconfig_win.c
src/lib/ares_timeout.c
src/lib/ares_update_servers.c
src/lib/ares_version.c
src/lib/atomic.cpp
+ src/lib/dsa/ares__array.c
+ src/lib/dsa/ares__htable.c
+ src/lib/dsa/ares__htable_asvp.c
+ src/lib/dsa/ares__htable_strvp.c
+ src/lib/dsa/ares__htable_szvp.c
+ src/lib/dsa/ares__htable_vpvp.c
+ src/lib/dsa/ares__llist.c
+ src/lib/dsa/ares__slist.c
+ src/lib/event/ares_event_configchg.c
+ src/lib/event/ares_event_epoll.c
+ src/lib/event/ares_event_kqueue.c
+ src/lib/event/ares_event_poll.c
+ src/lib/event/ares_event_select.c
+ src/lib/event/ares_event_thread.c
+ src/lib/event/ares_event_wake_pipe.c
+ src/lib/event/ares_event_win32.c
src/lib/inet_net_pton.c
src/lib/inet_ntop.c
+ src/lib/legacy/ares_create_query.c
+ src/lib/legacy/ares_expand_name.c
+ src/lib/legacy/ares_expand_string.c
+ src/lib/legacy/ares_fds.c
+ src/lib/legacy/ares_getsock.c
+ src/lib/legacy/ares_parse_a_reply.c
+ src/lib/legacy/ares_parse_aaaa_reply.c
+ src/lib/legacy/ares_parse_caa_reply.c
+ src/lib/legacy/ares_parse_mx_reply.c
+ src/lib/legacy/ares_parse_naptr_reply.c
+ src/lib/legacy/ares_parse_ns_reply.c
+ src/lib/legacy/ares_parse_ptr_reply.c
+ src/lib/legacy/ares_parse_soa_reply.c
+ src/lib/legacy/ares_parse_srv_reply.c
+ src/lib/legacy/ares_parse_txt_reply.c
+ src/lib/legacy/ares_parse_uri_reply.c
+ src/lib/record/ares_dns_mapping.c
+ src/lib/record/ares_dns_multistring.c
+ src/lib/record/ares_dns_name.c
+ src/lib/record/ares_dns_parse.c
+ src/lib/record/ares_dns_record.c
+ src/lib/record/ares_dns_write.c
+ src/lib/str/ares__buf.c
+ src/lib/str/ares_str.c
+ src/lib/str/ares_strcasecmp.c
+ src/lib/str/ares_strsplit.c
+ src/lib/util/ares__iface_ips.c
+ src/lib/util/ares__threads.c
+ src/lib/util/ares__timeval.c
+ src/lib/util/ares_math.c
+ src/lib/util/ares_rand.c
src/lib/windows_port.c
)