deps: update c-ares to v1.33.0

PR-URL: https://github.com/nodejs/node/pull/54198
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
This commit is contained in:
Node.js GitHub Bot 2024-08-11 12:07:05 -04:00 committed by GitHub
parent 746213ec7a
commit bc5ebe44f9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
120 changed files with 4943 additions and 2729 deletions

View file

@ -12,7 +12,7 @@ INCLUDE (CheckCSourceCompiles)
INCLUDE (CheckStructHasMember) INCLUDE (CheckStructHasMember)
INCLUDE (CheckLibraryExists) INCLUDE (CheckLibraryExists)
PROJECT (c-ares LANGUAGES C VERSION "1.32.3" ) PROJECT (c-ares LANGUAGES C VERSION "1.33.0" )
# Set this version before release # Set this version before release
SET (CARES_VERSION "${PROJECT_VERSION}") SET (CARES_VERSION "${PROJECT_VERSION}")
@ -30,7 +30,7 @@ INCLUDE (GNUInstallDirs) # include this *AFTER* PROJECT(), otherwise paths are w
# For example, a version of 4:0:2 would generate output such as: # For example, a version of 4:0:2 would generate output such as:
# libname.so -> libname.so.2 # libname.so -> libname.so.2
# libname.so.2 -> libname.so.2.2.0 # libname.so.2 -> libname.so.2.2.0
SET (CARES_LIB_VERSIONINFO "19:3:17") SET (CARES_LIB_VERSIONINFO "20:0:18")
OPTION (CARES_STATIC "Build as a static library" OFF) OPTION (CARES_STATIC "Build as a static library" OFF)
@ -42,6 +42,7 @@ OPTION (CARES_BUILD_CONTAINER_TESTS "Build and run container tests (implies CARE
OPTION (CARES_BUILD_TOOLS "Build tools" ON) OPTION (CARES_BUILD_TOOLS "Build tools" ON)
OPTION (CARES_SYMBOL_HIDING "Hide private symbols in shared libraries" OFF) OPTION (CARES_SYMBOL_HIDING "Hide private symbols in shared libraries" OFF)
OPTION (CARES_THREADS "Build with thread-safety support" ON) OPTION (CARES_THREADS "Build with thread-safety support" ON)
OPTION (CARES_COVERAGE "Build for code coverage" OFF)
SET (CARES_RANDOM_FILE "/dev/urandom" CACHE STRING "Suitable File / Device Path for entropy, such as /dev/urandom") SET (CARES_RANDOM_FILE "/dev/urandom" CACHE STRING "Suitable File / Device Path for entropy, such as /dev/urandom")
@ -265,7 +266,7 @@ IF (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "Linux") ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "Linux")
LIST (APPEND SYSFLAGS -D_GNU_SOURCE -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700) LIST (APPEND SYSFLAGS -D_GNU_SOURCE -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700)
ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "SunOS") ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
LIST (APPEND SYSFLAGS -D__EXTENSIONS__ -D_REENTRANT -D_XOPEN_SOURCE=700) LIST (APPEND SYSFLAGS -D__EXTENSIONS__ -D_REENTRANT -D_XOPEN_SOURCE=600)
ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "AIX") ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "AIX")
LIST (APPEND SYSFLAGS -D_ALL_SOURCE -D_XOPEN_SOURCE=700 -D_USE_IRS) LIST (APPEND SYSFLAGS -D_ALL_SOURCE -D_XOPEN_SOURCE=700 -D_USE_IRS)
ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
@ -409,6 +410,7 @@ CHECK_STRUCT_HAS_MEMBER("struct sockaddr_in6" sin6_scope_id "${CMAKE_EXTRA_INCLU
CHECK_SYMBOL_EXISTS (closesocket "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CLOSESOCKET) CHECK_SYMBOL_EXISTS (closesocket "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CLOSESOCKET)
CHECK_SYMBOL_EXISTS (CloseSocket "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CLOSESOCKET_CAMEL) CHECK_SYMBOL_EXISTS (CloseSocket "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CLOSESOCKET_CAMEL)
CHECK_SYMBOL_EXISTS (connect "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CONNECT) CHECK_SYMBOL_EXISTS (connect "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CONNECT)
CHECK_SYMBOL_EXISTS (connectx "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CONNECTX)
CHECK_SYMBOL_EXISTS (fcntl "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_FCNTL) CHECK_SYMBOL_EXISTS (fcntl "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_FCNTL)
CHECK_SYMBOL_EXISTS (freeaddrinfo "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_FREEADDRINFO) CHECK_SYMBOL_EXISTS (freeaddrinfo "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_FREEADDRINFO)
CHECK_SYMBOL_EXISTS (getaddrinfo "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETADDRINFO) CHECK_SYMBOL_EXISTS (getaddrinfo "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETADDRINFO)
@ -423,6 +425,10 @@ CHECK_SYMBOL_EXISTS (if_indextoname "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_IF_INDE
CHECK_SYMBOL_EXISTS (if_nametoindex "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_IF_NAMETOINDEX) CHECK_SYMBOL_EXISTS (if_nametoindex "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_IF_NAMETOINDEX)
CHECK_SYMBOL_EXISTS (ConvertInterfaceIndexToLuid "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CONVERTINTERFACEINDEXTOLUID) CHECK_SYMBOL_EXISTS (ConvertInterfaceIndexToLuid "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CONVERTINTERFACEINDEXTOLUID)
CHECK_SYMBOL_EXISTS (ConvertInterfaceLuidToNameA "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CONVERTINTERFACELUIDTONAMEA) CHECK_SYMBOL_EXISTS (ConvertInterfaceLuidToNameA "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CONVERTINTERFACELUIDTONAMEA)
CHECK_SYMBOL_EXISTS (NotifyIpInterfaceChange "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_NOTIFYIPINTERFACECHANGE)
CHECK_SYMBOL_EXISTS (RegisterWaitForSingleObject "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_REGISTERWAITFORSINGLEOBJECT)
CHECK_SYMBOL_EXISTS (inet_net_pton "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_INET_NET_PTON) CHECK_SYMBOL_EXISTS (inet_net_pton "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_INET_NET_PTON)
IF (NOT WIN32) IF (NOT WIN32)
# Disabled on Windows, because these functions are only really supported on Windows # Disabled on Windows, because these functions are only really supported on Windows
@ -682,6 +688,27 @@ IF (HAVE_ARPA_NAMESER_COMPAT_H)
SET (CARES_HAVE_ARPA_NAMESER_COMPAT_H 1) SET (CARES_HAVE_ARPA_NAMESER_COMPAT_H 1)
ENDIF() ENDIF()
# Coverage
IF (CARES_COVERAGE)
# set compiler flags
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs")
# find required tools
FIND_PROGRAM(LCOV lcov REQUIRED)
FIND_PROGRAM(GENHTML genhtml REQUIRED)
# add coverage target
ADD_CUSTOM_TARGET(coverage
# gather data
COMMAND ${LCOV} --directory . --capture --output-file coverage.info
# generate report
COMMAND ${GENHTML} --demangle-cpp -o coverage coverage.info
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
ENDIF()
# TRANSFORM_MAKEFILE_INC # TRANSFORM_MAKEFILE_INC
# #
# This function consumes the "Makefile.inc" autotools file, and converts it into # This function consumes the "Makefile.inc" autotools file, and converts it into
@ -729,6 +756,8 @@ IF (CARES_BUILD_TESTS OR CARES_BUILD_CONTAINER_TESTS)
ENDIF () ENDIF ()
# Export targets # Export targets
IF (CARES_INSTALL) IF (CARES_INSTALL)
SET (CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") SET (CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")

View file

@ -1,5 +1,3 @@
# c-ares license
MIT License MIT License
Copyright (c) 1998 Massachusetts Institute of Technology Copyright (c) 1998 Massachusetts Institute of Technology

View file

@ -97,7 +97,19 @@ all: $(ARESBUILDH) $(OBJ_BASE) $(TARGETS) $(DEMOS) .SYMBOLIC
$(OBJ_BASE): $(OBJ_BASE):
-$(MD) $^@ -$(MD) $^@
-$(MD) $^@\stat -$(MD) $^@\stat
-$(MD) $^@\stat\dsa
-$(MD) $^@\stat\event
-$(MD) $^@\stat\legacy
-$(MD) $^@\stat\record
-$(MD) $^@\stat\str
-$(MD) $^@\stat\util
-$(MD) $^@\dyn -$(MD) $^@\dyn
-$(MD) $^@\dyn\dsa
-$(MD) $^@\dyn\event
-$(MD) $^@\dyn\legacy
-$(MD) $^@\dyn\record
-$(MD) $^@\dyn\str
-$(MD) $^@\dyn\util
-$(MD) $^@\tools -$(MD) $^@\tools
$(ARESBUILDH): .EXISTSONLY $(ARESBUILDH): .EXISTSONLY
@ -129,7 +141,19 @@ vclean realclean: clean .SYMBOLIC
-$(RM) $(TARGETS) $(LIBNAME).map -$(RM) $(TARGETS) $(LIBNAME).map
-$(RM) $(DEMOS) $(DEMOS:.exe=.map) -$(RM) $(DEMOS) $(DEMOS:.exe=.map)
-$(RD) $(OBJ_BASE)\stat -$(RD) $(OBJ_BASE)\stat
-$(RD) $(OBJ_BASE)\stat\dsa
-$(RD) $(OBJ_BASE)\stat\event
-$(RD) $(OBJ_BASE)\stat\legacy
-$(RD) $(OBJ_BASE)\stat\record
-$(RD) $(OBJ_BASE)\stat\str
-$(RD) $(OBJ_BASE)\stat\util
-$(RD) $(OBJ_BASE)\dyn -$(RD) $(OBJ_BASE)\dyn
-$(RD) $(OBJ_BASE)\dyn\dsa
-$(RD) $(OBJ_BASE)\dyn\event
-$(RD) $(OBJ_BASE)\dyn\legacy
-$(RD) $(OBJ_BASE)\dyn\record
-$(RD) $(OBJ_BASE)\dyn\str
-$(RD) $(OBJ_BASE)\dyn\util
-$(RD) $(OBJ_BASE)\tools -$(RD) $(OBJ_BASE)\tools
-$(RD) $(OBJ_BASE) -$(RD) $(OBJ_BASE)
@ -144,10 +168,58 @@ $(RESOURCE): src\lib\cares.rc .AUTODEPEND
.c{$(OBJ_BASE)\dyn}.obj: .c{$(OBJ_BASE)\dyn}.obj:
$(CC) $(CFLAGS) -bd .\src\lib\$^& -fo=$^@ $(CC) $(CFLAGS) -bd .\src\lib\$^& -fo=$^@
.ERASE
{dsa}.c{$(OBJ_BASE)\dyn\dsa}.obj:
$(CC) $(CFLAGS) -bd .\src\lib\dsa\$^& -fo=$^@
.ERASE
{event}.c{$(OBJ_BASE)\dyn\event}.obj:
$(CC) $(CFLAGS) -bd .\src\lib\event\$^& -fo=$^@
.ERASE
{legacy}.c{$(OBJ_BASE)\dyn\legacy}.obj:
$(CC) $(CFLAGS) -bd .\src\lib\legacy\$^& -fo=$^@
.ERASE
{record}.c{$(OBJ_BASE)\dyn\record}.obj:
$(CC) $(CFLAGS) -bd .\src\lib\record\$^& -fo=$^@
.ERASE
{str}.c{$(OBJ_BASE)\dyn\str}.obj:
$(CC) $(CFLAGS) -bd .\src\lib\str\$^& -fo=$^@
.ERASE
{util}.c{$(OBJ_BASE)\dyn\util}.obj:
$(CC) $(CFLAGS) -bd .\src\lib\util\$^& -fo=$^@
.ERASE .ERASE
.c{$(OBJ_BASE)\stat}.obj: .c{$(OBJ_BASE)\stat}.obj:
$(CC) $(CFLAGS) -DCARES_STATICLIB .\src\lib\$^& -fo=$^@ $(CC) $(CFLAGS) -DCARES_STATICLIB .\src\lib\$^& -fo=$^@
.ERASE
{dsa}.c{$(OBJ_BASE)\stat\dsa}.obj:
$(CC) $(CFLAGS) -DCARES_STATICLIB .\src\lib\dsa\$^& -fo=$^@
.ERASE
{event}.c{$(OBJ_BASE)\stat\event}.obj:
$(CC) $(CFLAGS) -DCARES_STATICLIB .\src\lib\event\$^& -fo=$^@
.ERASE
{legacy}.c{$(OBJ_BASE)\stat\legacy}.obj:
$(CC) $(CFLAGS) -DCARES_STATICLIB .\src\lib\legacy\$^& -fo=$^@
.ERASE
{record}.c{$(OBJ_BASE)\stat\record}.obj:
$(CC) $(CFLAGS) -DCARES_STATICLIB .\src\lib\record\$^& -fo=$^@
.ERASE
{str}.c{$(OBJ_BASE)\stat\str}.obj:
$(CC) $(CFLAGS) -DCARES_STATICLIB .\src\lib\str\$^& -fo=$^@
.ERASE
{util}.c{$(OBJ_BASE)\stat\util}.obj:
$(CC) $(CFLAGS) -DCARES_STATICLIB .\src\lib\util\$^& -fo=$^@
$(LINK_ARG): $(__MAKEFILES__) $(LINK_ARG): $(__MAKEFILES__)
%create $^@ %create $^@
@%append $^@ system nt dll @%append $^@ system nt dll

View file

@ -22,7 +22,7 @@
AUTOMAKE_OPTIONS = foreign nostdinc 1.9.6 AUTOMAKE_OPTIONS = foreign nostdinc 1.9.6
ACLOCAL_AMFLAGS = -I m4 --install ACLOCAL_AMFLAGS = -I m4 --install
MSVCFILES = msvc_ver.inc buildconf.bat MSVCFILES = buildconf.bat
# adig and ahost are just sample programs and thus not mentioned with the # adig and ahost are just sample programs and thus not mentioned with the
# regular sources and headers # regular sources and headers

View file

@ -5,8 +5,14 @@
# #
include src/lib/Makefile.inc include src/lib/Makefile.inc
CSOURCES := $(addprefix src/lib/, $(CSOURCES)) OBJ_DIR = djgpp
CSOURCES := $(filter-out src/lib/windows_port.c, $(CSOURCES)) OBJECTS = $(addprefix $(OBJ_DIR)/, \
$(CSOURCES:.c=.o))
CSRC = $(addprefix src/lib/, $(CSOURCES))
#CSRC := $(filter-out src/lib/windows_port.c, $(CSOURCES))
OBJ_SUBDIRS = $(OBJ_DIR)/dsa $(OBJ_DIR)/event $(OBJ_DIR)/legacy $(OBJ_DIR)/record $(OBJ_DIR)/str $(OBJ_DIR)/util
VPATH = src/lib src/tools VPATH = src/lib src/tools
@ -17,8 +23,6 @@ VPATH = src/lib src/tools
WATT32_ROOT = $(realpath $(WATT_ROOT)) WATT32_ROOT = $(realpath $(WATT_ROOT))
WATT32_LIB = $(WATT32_ROOT)/lib/libwatt.a WATT32_LIB = $(WATT32_ROOT)/lib/libwatt.a
OBJ_DIR = djgpp
CFLAGS = -g -O2 -I./include -I./src/lib \ CFLAGS = -g -O2 -I./include -I./src/lib \
-I$(WATT32_ROOT)/inc \ -I$(WATT32_ROOT)/inc \
-Wall \ -Wall \
@ -82,9 +86,6 @@ else
CC = gcc CC = gcc
endif endif
OBJECTS = $(addprefix $(OBJ_DIR)/, \
$(notdir $(CSOURCES:.c=.o)))
GENERATED = src/lib/ares_config.h \ GENERATED = src/lib/ares_config.h \
include/ares_build.h include/ares_build.h
@ -92,7 +93,7 @@ TARGETS = libcares.a adig.exe ahost.exe
.SECONDARY: $(OBJ_DIR)/ares_getopt.o .SECONDARY: $(OBJ_DIR)/ares_getopt.o
all: $(OBJ_DIR) $(GENERATED) $(TARGETS) all: $(OBJ_DIR) $(OBJ_SUBDIRS) $(GENERATED) $(TARGETS)
@echo Welcome to c-ares. @echo Welcome to c-ares.
libcares.a: $(OBJECTS) libcares.a: $(OBJECTS)
@ -111,15 +112,19 @@ include/ares_build.h: include/ares_build.h.dist
# #
clean: clean:
- rm -f depend.dj $(GENERATED) $(OBJ_DIR)/*.o - rm -f depend.dj $(GENERATED) $(OBJ_DIR)/*.o
- rmdir $(OBJ_DIR) - rmdir $(OBJ_SUBDIRS)
# Clean everything # Clean everything
# #
realclean vclean: clean realclean vclean: clean
- rm -f $(TARGETS) $(TARGETS:.exe=.map) - rm -f $(TARGETS) $(TARGETS:.exe=.map)
$(OBJ_DIR): .PHONY: obj_subdirs $(OBJ_SUBDIRS)
- mkdir $@
obj_subdirs: $(OBJ_SUBDIRS)
$(OBJ_SUBDIRS):
mkdir $@
$(OBJ_DIR)/%.o: %.c $(OBJ_DIR)/%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $< $(CC) $(CFLAGS) -o $@ -c $<
@ -138,7 +143,7 @@ DEP_REPLACE = sed -e 's@\(.*\)\.o: @\n$$(OBJ_DIR)\/\1.o: @' \
# a foreign 'curl_config.h' is making trouble. # a foreign 'curl_config.h' is making trouble.
# #
depend: $(GENERATED) Makefile.dj depend: $(GENERATED) Makefile.dj
$(CC) -MM $(CFLAGS) $(CSOURCES) | $(DEP_REPLACE) > depend.dj $(CC) -MM $(CFLAGS) $(CSRC) | $(DEP_REPLACE) > depend.dj
-include depend.dj -include depend.dj

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.5 from Makefile.am. # Makefile.in generated by automake 1.17 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2021 Free Software Foundation, Inc. # Copyright (C) 1994-2024 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -91,6 +91,8 @@ am__make_running_with_option = \
test $$has_opt = yes test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
am__rm_f = rm -f $(am__rm_f_notfound)
am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@ pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@
@ -194,10 +196,9 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \ am__uninstall_files_from_dir = { \
test -z "$$files" \ { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \
$(am__cd) "$$dir" && rm -f $$files; }; \
} }
am__installdirs = "$(DESTDIR)$(pkgconfigdir)" am__installdirs = "$(DESTDIR)$(pkgconfigdir)"
DATA = $(pkgconfig_DATA) DATA = $(pkgconfig_DATA)
@ -238,8 +239,8 @@ distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir) top_distdir = $(distdir)
am__remove_distdir = \ am__remove_distdir = \
if test -d "$(distdir)"; then \ if test -d "$(distdir)"; then \
find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ find "$(distdir)" -type d ! -perm -700 -exec chmod u+rwx {} ';' \
&& rm -rf "$(distdir)" \ ; rm -rf "$(distdir)" \
|| { sleep 5 && rm -rf "$(distdir)"; }; \ || { sleep 5 && rm -rf "$(distdir)"; }; \
else :; fi else :; fi
am__post_remove_distdir = $(am__remove_distdir) am__post_remove_distdir = $(am__remove_distdir)
@ -269,14 +270,16 @@ am__relativize = \
done; \ done; \
reldir="$$dir2" reldir="$$dir2"
DIST_ARCHIVES = $(distdir).tar.gz DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best GZIP_ENV = -9
DIST_TARGETS = dist-gzip DIST_TARGETS = dist-gzip
# Exists only to be overridden by the user if desired. # Exists only to be overridden by the user if desired.
AM_DISTCHECK_DVI_TARGET = dvi AM_DISTCHECK_DVI_TARGET = dvi
distuninstallcheck_listfiles = find . -type f -print distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
distcleancheck_listfiles = find . -type f -print distcleancheck_listfiles = \
find . \( -type f -a \! \
\( -name .nfs* -o -name .smb* -o -name .__afs* \) \) -print
ACLOCAL = @ACLOCAL@ ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@ AMTAR = @AMTAR@
AM_CFLAGS = @AM_CFLAGS@ AM_CFLAGS = @AM_CFLAGS@
@ -387,8 +390,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@ am__include = @am__include@
am__leading_dot = @am__leading_dot@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@ am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@ am__tar = @am__tar@
am__untar = @am__untar@ am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
ax_pthread_config = @ax_pthread_config@ ax_pthread_config = @ax_pthread_config@
bindir = @bindir@ bindir = @bindir@
build = @build@ build = @build@
@ -435,7 +440,7 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@ top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = foreign nostdinc 1.9.6 AUTOMAKE_OPTIONS = foreign nostdinc 1.9.6
ACLOCAL_AMFLAGS = -I m4 --install ACLOCAL_AMFLAGS = -I m4 --install
MSVCFILES = msvc_ver.inc buildconf.bat MSVCFILES = buildconf.bat
# adig and ahost are just sample programs and thus not mentioned with the # adig and ahost are just sample programs and thus not mentioned with the
# regular sources and headers # regular sources and headers
@ -634,7 +639,7 @@ distdir: $(BUILT_SOURCES)
distdir-am: $(DISTFILES) distdir-am: $(DISTFILES)
$(am__remove_distdir) $(am__remove_distdir)
test -d "$(distdir)" || mkdir "$(distdir)" $(AM_V_at)$(MKDIR_P) "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \ list='$(DISTFILES)'; \
@ -748,7 +753,7 @@ dist dist-all:
distcheck: dist distcheck: dist
case '$(DIST_ARCHIVES)' in \ case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \ *.tar.gz*) \
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ eval GZIP= gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \ *.tar.bz2*) \
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lz*) \ *.tar.lz*) \
@ -758,7 +763,7 @@ distcheck: dist
*.tar.Z*) \ *.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \ *.shar.gz*) \
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ eval GZIP= gzip -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \ *.zip*) \
unzip $(distdir).zip ;;\ unzip $(distdir).zip ;;\
*.tar.zst*) \ *.tar.zst*) \
@ -859,12 +864,12 @@ install-strip:
mostlyclean-generic: mostlyclean-generic:
clean-generic: clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) -$(am__rm_f) $(CLEANFILES)
distclean-generic: distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -$(am__rm_f) $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
-test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) -$(am__rm_f) $(DISTCLEANFILES)
maintainer-clean-generic: maintainer-clean-generic:
@echo "This command is intended for maintainers to use" @echo "This command is intended for maintainers to use"
@ -973,3 +978,10 @@ dist-hook:
# Tell versions [3.59,3.63) of GNU make to not export all variables. # Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded. # Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT: .NOEXPORT:
# Tell GNU make to disable its built-in pattern rules.
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%

View file

@ -75,11 +75,6 @@ RTLIBD = /MTd
USE_WATT32 = 0 USE_WATT32 = 0
!ENDIF !ENDIF
# --------------------------------------------------------
# Detect compiler version.
# --------------------------------------------------------
!INCLUDE .\msvc_ver.inc
# ---------------------------------------------------- # ----------------------------------------------------
# Verify that current subdir is the c-ares source one # Verify that current subdir is the c-ares source one
# ---------------------------------------------------- # ----------------------------------------------------
@ -190,30 +185,13 @@ EX_LIBS_REL = ws2_32.lib advapi32.lib kernel32.lib iphlpapi.lib
EX_LIBS_DBG = ws2_32.lib advapi32.lib kernel32.lib iphlpapi.lib EX_LIBS_DBG = ws2_32.lib advapi32.lib kernel32.lib iphlpapi.lib
!ENDIF !ENDIF
# -------------------------------------------------
# Switches that depend on ancient compiler versions
# -------------------------------------------------
!IF $(CC_VERS_NUM) == 60
PDB_NONE = /pdb:none
PDBTYPE_CONSOLIDATE = /pdbtype:consolidate
!ELSE
!UNDEF PDB_NONE
!UNDEF PDBTYPE_CONSOLIDATE
!ENDIF
!IF $(CC_VERS_NUM) <= 70
RT_ERROR_CHECKING = /GZ
!ELSE
RT_ERROR_CHECKING = /RTCsu
!ENDIF
# ---------------------------- # ----------------------------
# Assorted commands and flags # Assorted commands and flags
# ---------------------------- # ----------------------------
CC_CMD_REL = cl.exe /nologo $(RTLIB) /DNDEBUG /O2 CC_CMD_REL = cl.exe /nologo $(RTLIB) /DNDEBUG /O2
CC_CMD_DBG = cl.exe /nologo $(RTLIBD) /D_DEBUG /Od /Zi $(RT_ERROR_CHECKING) CC_CMD_DBG = cl.exe /nologo $(RTLIBD) /D_DEBUG /Od /Zi /RTCsu
CC_CFLAGS = $(CFLAGS) /D_REENTRANT /I.\src\lib /I.\include /W3 /EHsc /FD CC_CFLAGS = $(CFLAGS) /D_REENTRANT /I.\src\lib /I.\include /W3 /EHsc /FD
RC_CMD_REL = rc.exe /l 0x409 /d "NDEBUG" RC_CMD_REL = rc.exe /l 0x409 /d "NDEBUG"
@ -223,8 +201,8 @@ LINK_CMD_LIB = link.exe /lib /nologo
LINK_CMD_DLL = link.exe /dll /nologo /incremental:no /fixed:no LINK_CMD_DLL = link.exe /dll /nologo /incremental:no /fixed:no
LINK_CMD_EXE = link.exe /nologo /incremental:no /fixed:no /subsystem:console LINK_CMD_EXE = link.exe /nologo /incremental:no /fixed:no /subsystem:console
LINK_CMD_EXE_REL = $(LINK_CMD_EXE) /release $(PDB_NONE) LINK_CMD_EXE_REL = $(LINK_CMD_EXE) /release
LINK_CMD_EXE_DBG = $(LINK_CMD_EXE) /debug $(PDBTYPE_CONSOLIDATE) LINK_CMD_EXE_DBG = $(LINK_CMD_EXE) /debug
# --------------------------------- # ---------------------------------
# Configuration dependent settings # Configuration dependent settings
@ -255,7 +233,7 @@ CC_CMD = $(CC_CMD_DBG)
!IF "$(CFG)" == "dll-release" !IF "$(CFG)" == "dll-release"
CARES_TARGET = $(DYN_LIB_REL).dll CARES_TARGET = $(DYN_LIB_REL).dll
CARES_CFLAGS = /DCARES_BUILDING_LIBRARY CARES_CFLAGS = /DCARES_BUILDING_LIBRARY
CARES_LFLAGS = /release $(EX_LIBS_REL) /implib:$(CARES_OUTDIR)\$(IMP_LIB_REL).lib $(PDB_NONE) CARES_LFLAGS = /release $(EX_LIBS_REL) /implib:$(CARES_OUTDIR)\$(IMP_LIB_REL).lib
SPROG_CFLAGS = /DCARES_NO_DEPRECATED SPROG_CFLAGS = /DCARES_NO_DEPRECATED
SPROG_LFLAGS = /libpath:$(CARES_OUTDIR) $(EX_LIBS_REL) $(IMP_LIB_REL).lib SPROG_LFLAGS = /libpath:$(CARES_OUTDIR) $(EX_LIBS_REL) $(IMP_LIB_REL).lib
CARES_LINK = $(LINK_CMD_DLL) CARES_LINK = $(LINK_CMD_DLL)
@ -268,7 +246,7 @@ RC_CMD = $(RC_CMD_REL)
!IF "$(CFG)" == "dll-debug" !IF "$(CFG)" == "dll-debug"
CARES_TARGET = $(DYN_LIB_DBG).dll CARES_TARGET = $(DYN_LIB_DBG).dll
CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DDEBUGBUILD CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DDEBUGBUILD
CARES_LFLAGS = /debug $(EX_LIBS_DBG) /implib:$(CARES_OUTDIR)\$(IMP_LIB_DBG).lib /pdb:$(CARES_OUTDIR)\$(DYN_LIB_DBG).pdb $(PDBTYPE_CONSOLIDATE) CARES_LFLAGS = /debug $(EX_LIBS_DBG) /implib:$(CARES_OUTDIR)\$(IMP_LIB_DBG).lib /pdb:$(CARES_OUTDIR)\$(DYN_LIB_DBG).pdb
SPROG_CFLAGS = /DCARES_NO_DEPRECATED SPROG_CFLAGS = /DCARES_NO_DEPRECATED
SPROG_LFLAGS = /libpath:$(CARES_OUTDIR) $(EX_LIBS_DBG) $(IMP_LIB_DBG).lib SPROG_LFLAGS = /libpath:$(CARES_OUTDIR) $(EX_LIBS_DBG) $(IMP_LIB_DBG).lib
CARES_LINK = $(LINK_CMD_DLL) CARES_LINK = $(LINK_CMD_DLL)
@ -299,6 +277,7 @@ RC_CMD = $(RC_CMD_DBG)
!ERROR Problem generating CARES_OBJS list. !ERROR Problem generating CARES_OBJS list.
!ENDIF !ENDIF
CARES_OBJS = $(CARES_OBJS:.c=.obj) CARES_OBJS = $(CARES_OBJS:.c=.obj)
CARES_OBJS = $(CARES_OBJS:/=\)
!IF "$(USE_RES_FILE)" == "TRUE" !IF "$(USE_RES_FILE)" == "TRUE"
CARES_OBJS = $(CARES_OBJS) $(CARES_OBJDIR)\cares.res CARES_OBJS = $(CARES_OBJS) $(CARES_OBJDIR)\cares.res
!ENDIF !ENDIF
@ -341,20 +320,38 @@ PROG3_OBJS = $(PROG3_OBJS) $(PROG3_OBJDIR)\ahost.obj
{$(SRCDIR)\src\lib}.c{$(CARES_OBJDIR)}.obj: {$(SRCDIR)\src\lib}.c{$(CARES_OBJDIR)}.obj:
$(CC_CMD) $(CC_CFLAGS) $(CARES_CFLAGS) /Fo$@ /Fd$(@D)\ /c $< $(CC_CMD) $(CC_CFLAGS) $(CARES_CFLAGS) /Fo$@ /Fd$(@D)\ /c $<
{$(SRCDIR)\src\lib\dsa}.c{$(CARES_OBJDIR)\dsa}.obj:
$(CC_CMD) $(CC_CFLAGS) $(CARES_CFLAGS) /Fo$@ /Fd$(@D)\ /c $<
{$(SRCDIR)\src\lib\event}.c{$(CARES_OBJDIR)\event}.obj:
$(CC_CMD) $(CC_CFLAGS) $(CARES_CFLAGS) /Fo$@ /Fd$(@D)\ /c $<
{$(SRCDIR)\src\lib\legacy}.c{$(CARES_OBJDIR)\legacy}.obj:
$(CC_CMD) $(CC_CFLAGS) $(CARES_CFLAGS) /Fo$@ /Fd$(@D)\ /c $<
{$(SRCDIR)\src\lib\record}.c{$(CARES_OBJDIR)\record}.obj:
$(CC_CMD) $(CC_CFLAGS) $(CARES_CFLAGS) /Fo$@ /Fd$(@D)\ /c $<
{$(SRCDIR)\src\lib\str}.c{$(CARES_OBJDIR)\str}.obj:
$(CC_CMD) $(CC_CFLAGS) $(CARES_CFLAGS) /Fo$@ /Fd$(@D)\ /c $<
{$(SRCDIR)\src\lib\util}.c{$(CARES_OBJDIR)\util}.obj:
$(CC_CMD) $(CC_CFLAGS) $(CARES_CFLAGS) /Fo$@ /Fd$(@D)\ /c $<
{$(SRCDIR)\src\tools}.c{$(PROG2_OBJDIR)}.obj: {$(SRCDIR)\src\tools}.c{$(PROG2_OBJDIR)}.obj:
$(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$@ /Fd$(@D)\ /c $< $(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$@ /Fd$(PROG2_OBJDIR)\ /c $<
{$(SRCDIR)\src\tools}.c{$(PROG3_OBJDIR)}.obj: {$(SRCDIR)\src\tools}.c{$(PROG3_OBJDIR)}.obj:
$(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$@ /Fd$(@D)\ /c $< $(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$@ /Fd$(PROG3_OBJDIR)\ /c $<
# Hack Alert! we reference ../lib/ files in the Makefile.inc for tools as they # Hack Alert! we reference ../lib/str files in the Makefile.inc for tools as they
# share some files with the library itself. We need to hack around that here. # share some files with the library itself. We need to hack around that here.
{$(SRCDIR)\src\lib}.c{$(PROG2_OBJDIR)\..\lib}.obj: {$(SRCDIR)\src\lib\str}.c{$(PROG2_OBJDIR)\..\lib\str}.obj:
$(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$(PROG2_OBJDIR)\$(@F) /Fd$(PROG2_OBJDIR)\ /c $< $(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$(PROG2_OBJDIR)\str\$(@F) /Fd$(PROG2_OBJDIR)\str\ /c $<
{$(SRCDIR)\src\lib}.c{$(PROG3_OBJDIR)\..\lib}.obj: {$(SRCDIR)\src\lib\str}.c{$(PROG3_OBJDIR)\..\lib\str}.obj:
$(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$(PROG3_OBJDIR)\$(@F) /Fd$(PROG3_OBJDIR)\ /c $< $(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$(PROG3_OBJDIR)\str\$(@F) /Fd$(PROG3_OBJDIR)\str\ /c $<
# ------------------------------------------------------------- # # ------------------------------------------------------------- #
# ------------------------------------------------------------- # # ------------------------------------------------------------- #
@ -419,16 +416,32 @@ $(PROG3_OUTDIR): $(PROG3_DIR)
$(CARES_OBJDIR): $(CARES_OUTDIR) $(CARES_OBJDIR): $(CARES_OUTDIR)
@if not exist $(CARES_OBJDIR) mkdir $(CARES_OBJDIR) @if not exist $(CARES_OBJDIR) mkdir $(CARES_OBJDIR)
@if not exist $(CARES_OBJDIR)\dsa mkdir $(CARES_OBJDIR)\dsa
@if not exist $(CARES_OBJDIR)\event mkdir $(CARES_OBJDIR)\event
@if not exist $(CARES_OBJDIR)\legacy mkdir $(CARES_OBJDIR)\legacy
@if not exist $(CARES_OBJDIR)\record mkdir $(CARES_OBJDIR)\record
@if not exist $(CARES_OBJDIR)\str mkdir $(CARES_OBJDIR)\str
@if not exist $(CARES_OBJDIR)\util mkdir $(CARES_OBJDIR)\util
$(PROG2_OBJDIR): $(PROG2_OUTDIR) $(PROG2_OBJDIR): $(PROG2_OUTDIR)
@if not exist $(PROG2_OBJDIR) mkdir $(PROG2_OBJDIR) @if not exist $(PROG2_OBJDIR) mkdir $(PROG2_OBJDIR)
@if not exist $(PROG2_OBJDIR)\str mkdir $(PROG2_OBJDIR)\str
$(PROG3_OBJDIR): $(PROG3_OUTDIR) $(PROG3_OBJDIR): $(PROG3_OUTDIR)
@if not exist $(PROG3_OBJDIR) mkdir $(PROG3_OBJDIR) @if not exist $(PROG3_OBJDIR) mkdir $(PROG3_OBJDIR)
@if not exist $(PROG3_OBJDIR)\str mkdir $(PROG3_OBJDIR)\str
clean: clean:
@-RMDIR /S /Q $(CARES_OBJDIR)\dsa >NUL 2>&1
@-RMDIR /S /Q $(CARES_OBJDIR)\event >NUL 2>&1
@-RMDIR /S /Q $(CARES_OBJDIR)\legacy >NUL 2>&1
@-RMDIR /S /Q $(CARES_OBJDIR)\record >NUL 2>&1
@-RMDIR /S /Q $(CARES_OBJDIR)\str >NUL 2>&1
@-RMDIR /S /Q $(CARES_OBJDIR)\util >NUL 2>&1
@-RMDIR /S /Q $(CARES_OUTDIR) >NUL 2>&1 @-RMDIR /S /Q $(CARES_OUTDIR) >NUL 2>&1
@-RMDIR /S /Q $(PROG2_OBJDIR)\str >NUL 2>&1
@-RMDIR /S /Q $(PROG2_OUTDIR) >NUL 2>&1 @-RMDIR /S /Q $(PROG2_OUTDIR) >NUL 2>&1
@-RMDIR /S /Q $(PROG3_OBJDIR)\str >NUL 2>&1
@-RMDIR /S /Q $(PROG3_OUTDIR) >NUL 2>&1 @-RMDIR /S /Q $(PROG3_OUTDIR) >NUL 2>&1
install: install:

52
deps/cares/README.md vendored
View file

@ -8,6 +8,14 @@
[![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) [![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) [![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 ## Overview
[c-ares](https://c-ares.org) is a modern DNS (stub) resolver library, written in [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 C. It provides interfaces for asynchronous queries while trying to abstract the
@ -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 Primary key fingerprint: 27ED EAF2 2F3A BCEB 50DB 9A12 5CC9 08FD B71E 12C2
gpg: binary signature, digest algorithm SHA512, key algorithm rsa2048 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.

View file

@ -1,98 +1,33 @@
## c-ares version 1.32.3 - July 24 2024 ## c-ares version 1.33.0 - August 2 2024
This is a bugfix release.
Changes:
* Prevent complex recursion during query requeuing and connection cleanup for
stability. [e8b32b8](https://github.com/c-ares/c-ares/commit/e8b32b8)
* Better propagate error codes on requeue situations.
[a9bc0a2](https://github.com/c-ares/c-ares/commit/a9bc0a2)
* Try to prevent SIGPIPE from being generated and delivered to integrations.
[de01baa](https://github.com/c-ares/c-ares/commit/de01baa)
Bugfixes:
* Missing manpage for `ares_dns_record_set_id()`
[aa462b3](https://github.com/c-ares/c-ares/commit/aa462b3)
* Memory leak in `ares__hosts_entry_to_hostent()` due to allocation strategy.
[PR #824](https://github.com/c-ares/c-ares/pull/824)
* UDP write failure detected via ICMP unreachable should trigger faster
failover. [PR #821](https://github.com/c-ares/c-ares/pull/821)
* Fix pycares test case regression due to wrong error code being returned.
Regression from 1.31.0. [PR #820](https://github.com/c-ares/c-ares/pull/820)
* Fix possible Windows crash during `ares_destroy()` when using event threads.
[5609bd4](https://github.com/c-ares/c-ares/commit/5609bd4)
* `ARES_OPT_MAXTIMEOUTMS` wasn't being honored in all cases.
[a649c60](https://github.com/c-ares/c-ares/commit/a649c60)
## c-ares version 1.32.2 - July 15 2024
This is a bugfix release.
Bugfixes:
* Windows: rework EventThread AFD code for better stability.
[PR #811](https://github.com/c-ares/c-ares/pull/811)
* Windows: If an IP address was detected to have changed, it could lead to a
crash due to a bad pointer. Regression introduced in 1.31.0.
[59e3a1f4](https://github.com/c-ares/c-ares/commit/59e3a1f4)
* Windows: use `QueryPerformanceCounters()` instead of `GetTickCount64()` for
better time accuracy (~15ms -> ~1us).
* Windows 32bit config change callback needs to be tagged as `stdcall` otherwise
could result in a crash.
[5c2bab35](https://github.com/c-ares/c-ares/commit/5c2bab35)
* Tests that need accurate timing should not depend on internal symbols as there
are C++ equivalents in `std::chrono`.
[PR #809](https://github.com/c-ares/c-ares/pull/809)
* Kqueue (MacOS, \*BSD): If the open socket count exceeded 8 (unlikely), it
would try to allocate a new buffer that was too small.
[5aad7981](https://github.com/c-ares/c-ares/commit/5aad7981)
## c-ares version 1.32.1 - July 7 2024
This is a bugfix release.
Bugfixes:
* Channel lock needs to be recursive to ensure calls into c-ares functions can
be made from callbacks otherwise deadlocks will occur. This regression was
introduced in 1.32.0.
## c-ares version 1.32.0 - July 4 2024
This is a feature and bugfix release. This is a feature and bugfix release.
Features: Features:
* Add DNS cookie support (RFC7873 + RFC9018) to help prevent off-path cache
* Add support for DNS 0x20 to help prevent cache poisoning attacks, enabled poisoning attacks. [PR #833](https://github.com/c-ares/c-ares/pull/833)
by specifying `ARES_FLAG_DNS0x20`. Disabled by default. [PR #800](https://github.com/c-ares/c-ares/pull/800) * Implement TCP FastOpen (TFO) RFC7413, which will make TCP reconnects 0-RTT
* Rework query timeout logic to automatically adjust timeouts based on network on supported systems. [PR #840](https://github.com/c-ares/c-ares/pull/840)
conditions. The timeout specified now is only used as a hint until there
is enough history to calculate a more valid timeout. [PR #794](https://github.com/c-ares/c-ares/pull/794)
Changes: Changes:
* Reorganize source tree. [PR #822](https://github.com/c-ares/c-ares/pull/822)
* DNS RR TXT strings should not be automatically concatenated as there are use * Refactoring of connection handling to prevent code duplication.
cases outside of RFC 7208. In order to maintain ABI compliance, the ability [PR #839](https://github.com/c-ares/c-ares/pull/839)
to retrieve TXT strings concatenated is retained as well as a new API to * New dynamic array data structure to prevent simple logic flaws in array
retrieve the individual strings. This restores behavior from c-ares 1.20.0. handling in various code paths.
[PR #801](https://github.com/c-ares/c-ares/pull/801) [PR #841](https://github.com/c-ares/c-ares/pull/841)
* Clean up header inclusion logic to make hacking on code easier. [PR #797](https://github.com/c-ares/c-ares/pull/797)
* GCC/Clang: Enable even more strict warnings to catch more coding flaws. [253bdee](https://github.com/c-ares/c-ares/commit/253bdee)
* MSVC: Enable `/W4` warning level. [PR #792](https://github.com/c-ares/c-ares/pull/792)
Bugfixes: 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)
* Tests: Fix thread race condition in test cases for EventThread. [PR #803](https://github.com/c-ares/c-ares/pull/803)
* Windows: Fix building with UNICODE. [PR #802](https://github.com/c-ares/c-ares/pull/802)
* Thread Saftey: `ares_timeout()` was missing lock. [74a64e4](https://github.com/c-ares/c-ares/commit/74a64e4)
* Fix building with DJGPP (32bit protected mode DOS). [PR #789](https://github.com/c-ares/c-ares/pull/789)
Thanks go to these friendly people for their efforts and contributions for this Thanks go to these friendly people for their efforts and contributions for this
release: release:
* Brad House (@bradh352) * Brad House (@bradh352)
* Cheng (@zcbenz) * Yauheni Khnykin (@Hsilgos)

415
deps/cares/aclocal.m4 vendored
View file

@ -1,6 +1,6 @@
# generated automatically by aclocal 1.16.5 -*- Autoconf -*- # generated automatically by aclocal 1.17 -*- Autoconf -*-
# Copyright (C) 1996-2021 Free Software Foundation, Inc. # Copyright (C) 1996-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -20,7 +20,7 @@ You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely. If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])]) To do so, use the procedure documented by the package, typically 'autoreconf'.])])
# Copyright (C) 2002-2021 Free Software Foundation, Inc. # Copyright (C) 2002-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -32,10 +32,10 @@ To do so, use the procedure documented by the package, typically 'autoreconf'.])
# generated from the m4 files accompanying Automake X.Y. # generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.) # (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION], AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.16' [am__api_version='1.17'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro. dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.16.5], [], m4_if([$1], [1.17], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
]) ])
@ -51,14 +51,14 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.16.5])dnl [AM_AUTOMAKE_VERSION([1.17])dnl
m4_ifndef([AC_AUTOCONF_VERSION], m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*- # AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2021 Free Software Foundation, Inc. # Copyright (C) 2001-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -110,7 +110,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
# AM_COND_IF -*- Autoconf -*- # AM_COND_IF -*- Autoconf -*-
# Copyright (C) 2008-2021 Free Software Foundation, Inc. # Copyright (C) 2008-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -147,7 +147,7 @@ fi[]dnl
# AM_CONDITIONAL -*- Autoconf -*- # AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2021 Free Software Foundation, Inc. # Copyright (C) 1997-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -178,7 +178,7 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]]) Usually this means the macro was only invoked conditionally.]])
fi])]) fi])])
# Copyright (C) 1999-2021 Free Software Foundation, Inc. # Copyright (C) 1999-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -310,7 +310,7 @@ AC_CACHE_CHECK([dependency style of $depcc],
# icc doesn't choke on unknown options, it will just issue warnings # icc doesn't choke on unknown options, it will just issue warnings
# or remarks (even with -Werror). So we grep stderr for any message # or remarks (even with -Werror). So we grep stderr for any message
# that says an option was ignored or not supported. # that says an option was ignored or not supported.
# When given -MP, icc 7.0 and 7.1 complain thusly: # When given -MP, icc 7.0 and 7.1 complain thus:
# icc: Command line warning: ignoring option '-M'; no argument required # icc: Command line warning: ignoring option '-M'; no argument required
# The diagnosis changed in icc 8.0: # The diagnosis changed in icc 8.0:
# icc: Command line remark: option '-MP' not supported # icc: Command line remark: option '-MP' not supported
@ -369,7 +369,7 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
# Generate code to set up dependency tracking. -*- Autoconf -*- # Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999-2021 Free Software Foundation, Inc. # Copyright (C) 1999-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -437,7 +437,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
# Do all the work for Automake. -*- Autoconf -*- # Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996-2021 Free Software Foundation, Inc. # Copyright (C) 1996-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -571,7 +571,7 @@ if test -z "$CSCOPE"; then
fi fi
AC_SUBST([CSCOPE]) AC_SUBST([CSCOPE])
AC_REQUIRE([AM_SILENT_RULES])dnl AC_REQUIRE([_AM_SILENT_RULES])dnl
dnl The testsuite driver may need to know about EXEEXT, so add the dnl The testsuite driver may need to know about EXEEXT, so add the
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
@ -579,47 +579,9 @@ AC_CONFIG_COMMANDS_PRE(dnl
[m4_provide_if([_AM_COMPILER_EXEEXT], [m4_provide_if([_AM_COMPILER_EXEEXT],
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
# POSIX will say in a future version that running "rm -f" with no argument AC_REQUIRE([_AM_PROG_RM_F])
# is OK; and we want to be able to make that assumption in our Makefile AC_REQUIRE([_AM_PROG_XARGS_N])
# recipes. So use an aggressive probe to check that the usage we want is
# actually supported "in the wild" to an acceptable degree.
# See automake bug#10828.
# To make any issue more visible, cause the running configure to be aborted
# by default if the 'rm' program in use doesn't match our expectations; the
# user can still override this though.
if rm -f && rm -fr && rm -rf; then : OK; else
cat >&2 <<'END'
Oops!
Your 'rm' program seems unable to run without file operands specified
on the command line, even when the '-f' option is present. This is contrary
to the behaviour of most rm programs out there, and not conforming with
the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
Please tell bug-automake@gnu.org about your system, including the value
of your $PATH and any error possibly output before this message. This
can help us improve future automake versions.
END
if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
echo 'Configuration will proceed anyway, since you have set the' >&2
echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
echo >&2
else
cat >&2 <<'END'
Aborting the configuration process, to ensure you take notice of the issue.
You can download and install GNU coreutils to get an 'rm' implementation
that behaves properly: <https://www.gnu.org/software/coreutils/>.
If you want to complete the configuration process using your problematic
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
to "yes", and re-run configure.
END
AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
fi
fi
dnl The trailing newline in this macro's definition is deliberate, for dnl The trailing newline in this macro's definition is deliberate, for
dnl backward compatibility and to allow trailing 'dnl'-style comments dnl backward compatibility and to allow trailing 'dnl'-style comments
dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
@ -652,7 +614,7 @@ for _am_header in $config_headers :; do
done done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001-2021 Free Software Foundation, Inc. # Copyright (C) 2001-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -673,7 +635,7 @@ if test x"${install_sh+set}" != xset; then
fi fi
AC_SUBST([install_sh])]) AC_SUBST([install_sh])])
# Copyright (C) 2003-2021 Free Software Foundation, Inc. # Copyright (C) 2003-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -695,7 +657,7 @@ AC_SUBST([am__leading_dot])])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering # From Jim Meyering
# Copyright (C) 1996-2021 Free Software Foundation, Inc. # Copyright (C) 1996-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -730,7 +692,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
# Check to see how 'make' treats includes. -*- Autoconf -*- # Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001-2021 Free Software Foundation, Inc. # Copyright (C) 2001-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -773,7 +735,7 @@ AC_SUBST([am__quote])])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997-2021 Free Software Foundation, Inc. # Copyright (C) 1997-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -807,7 +769,7 @@ fi
# Helper functions for option handling. -*- Autoconf -*- # Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001-2021 Free Software Foundation, Inc. # Copyright (C) 2001-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -836,7 +798,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION], AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Copyright (C) 1999-2021 Free Software Foundation, Inc. # Copyright (C) 1999-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -883,7 +845,23 @@ AC_LANG_POP([C])])
# For backward compatibility. # For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
# Copyright (C) 2001-2021 Free Software Foundation, Inc. # Copyright (C) 2022-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_PROG_RM_F
# ---------------
# Check whether 'rm -f' without any arguments works.
# https://bugs.gnu.org/10828
AC_DEFUN([_AM_PROG_RM_F],
[am__rm_f_notfound=
AS_IF([(rm -f && rm -fr && rm -rf) 2>/dev/null], [], [am__rm_f_notfound='""'])
AC_SUBST(am__rm_f_notfound)
])
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -902,16 +880,169 @@ AC_DEFUN([AM_RUN_LOG],
# Check to make sure that the build environment is sane. -*- Autoconf -*- # Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996-2021 Free Software Foundation, Inc. # Copyright (C) 1996-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved. # with or without modifications, as long as this notice is preserved.
# _AM_SLEEP_FRACTIONAL_SECONDS
# ----------------------------
AC_DEFUN([_AM_SLEEP_FRACTIONAL_SECONDS], [dnl
AC_CACHE_CHECK([whether sleep supports fractional seconds],
am_cv_sleep_fractional_seconds, [dnl
AS_IF([sleep 0.001 2>/dev/null], [am_cv_sleep_fractional_seconds=yes],
[am_cv_sleep_fractional_seconds=no])
])])
# _AM_FILESYSTEM_TIMESTAMP_RESOLUTION
# -----------------------------------
# Determine the filesystem's resolution for file modification
# timestamps. The coarsest we know of is FAT, with a resolution
# of only two seconds, even with the most recent "exFAT" extensions.
# The finest (e.g. ext4 with large inodes, XFS, ZFS) is one
# nanosecond, matching clock_gettime. However, it is probably not
# possible to delay execution of a shell script for less than one
# millisecond, due to process creation overhead and scheduling
# granularity, so we don't check for anything finer than that. (See below.)
AC_DEFUN([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION], [dnl
AC_REQUIRE([_AM_SLEEP_FRACTIONAL_SECONDS])
AC_CACHE_CHECK([filesystem timestamp resolution],
am_cv_filesystem_timestamp_resolution, [dnl
# Default to the worst case.
am_cv_filesystem_timestamp_resolution=2
# Only try to go finer than 1 sec if sleep can do it.
# Don't try 1 sec, because if 0.01 sec and 0.1 sec don't work,
# - 1 sec is not much of a win compared to 2 sec, and
# - it takes 2 seconds to perform the test whether 1 sec works.
#
# Instead, just use the default 2s on platforms that have 1s resolution,
# accept the extra 1s delay when using $sleep in the Automake tests, in
# exchange for not incurring the 2s delay for running the test for all
# packages.
#
am_try_resolutions=
if test "$am_cv_sleep_fractional_seconds" = yes; then
# Even a millisecond often causes a bunch of false positives,
# so just try a hundredth of a second. The time saved between .001 and
# .01 is not terribly consequential.
am_try_resolutions="0.01 0.1 $am_try_resolutions"
fi
# In order to catch current-generation FAT out, we must *modify* files
# that already exist; the *creation* timestamp is finer. Use names
# that make ls -t sort them differently when they have equal
# timestamps than when they have distinct timestamps, keeping
# in mind that ls -t prints the *newest* file first.
rm -f conftest.ts?
: > conftest.ts1
: > conftest.ts2
: > conftest.ts3
# Make sure ls -t actually works. Do 'set' in a subshell so we don't
# clobber the current shell's arguments. (Outer-level square brackets
# are removed by m4; they're present so that m4 does not expand
# <dollar><star>; be careful, easy to get confused.)
if (
set X `[ls -t conftest.ts[12]]` &&
{
test "$[]*" != "X conftest.ts1 conftest.ts2" ||
test "$[]*" != "X conftest.ts2 conftest.ts1";
}
); then :; else
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
_AS_ECHO_UNQUOTED(
["Bad output from ls -t: \"`[ls -t conftest.ts[12]]`\""],
[AS_MESSAGE_LOG_FD])
AC_MSG_FAILURE([ls -t produces unexpected output.
Make sure there is not a broken ls alias in your environment.])
fi
for am_try_res in $am_try_resolutions; do
# Any one fine-grained sleep might happen to cross the boundary
# between two values of a coarser actual resolution, but if we do
# two fine-grained sleeps in a row, at least one of them will fall
# entirely within a coarse interval.
echo alpha > conftest.ts1
sleep $am_try_res
echo beta > conftest.ts2
sleep $am_try_res
echo gamma > conftest.ts3
# We assume that 'ls -t' will make use of high-resolution
# timestamps if the operating system supports them at all.
if (set X `ls -t conftest.ts?` &&
test "$[]2" = conftest.ts3 &&
test "$[]3" = conftest.ts2 &&
test "$[]4" = conftest.ts1); then
#
# Ok, ls -t worked. If we're at a resolution of 1 second, we're done,
# because we don't need to test make.
make_ok=true
if test $am_try_res != 1; then
# But if we've succeeded so far with a subsecond resolution, we
# have one more thing to check: make. It can happen that
# everything else supports the subsecond mtimes, but make doesn't;
# notably on macOS, which ships make 3.81 from 2006 (the last one
# released under GPLv2). https://bugs.gnu.org/68808
#
# We test $MAKE if it is defined in the environment, else "make".
# It might get overridden later, but our hope is that in practice
# it does not matter: it is the system "make" which is (by far)
# the most likely to be broken, whereas if the user overrides it,
# probably they did so with a better, or at least not worse, make.
# https://lists.gnu.org/archive/html/automake/2024-06/msg00051.html
#
# Create a Makefile (real tab character here):
rm -f conftest.mk
echo 'conftest.ts1: conftest.ts2' >conftest.mk
echo ' touch conftest.ts2' >>conftest.mk
#
# Now, running
# touch conftest.ts1; touch conftest.ts2; make
# should touch ts1 because ts2 is newer. This could happen by luck,
# but most often, it will fail if make's support is insufficient. So
# test for several consecutive successes.
#
# (We reuse conftest.ts[12] because we still want to modify existing
# files, not create new ones, per above.)
n=0
make=${MAKE-make}
until test $n -eq 3; do
echo one > conftest.ts1
sleep $am_try_res
echo two > conftest.ts2 # ts2 should now be newer than ts1
if $make -f conftest.mk | grep 'up to date' >/dev/null; then
make_ok=false
break # out of $n loop
fi
n=`expr $n + 1`
done
fi
#
if $make_ok; then
# Everything we know to check worked out, so call this resolution good.
am_cv_filesystem_timestamp_resolution=$am_try_res
break # out of $am_try_res loop
fi
# Otherwise, we'll go on to check the next resolution.
fi
done
rm -f conftest.ts?
# (end _am_filesystem_timestamp_resolution)
])])
# AM_SANITY_CHECK # AM_SANITY_CHECK
# --------------- # ---------------
AC_DEFUN([AM_SANITY_CHECK], AC_DEFUN([AM_SANITY_CHECK],
[AC_MSG_CHECKING([whether build environment is sane]) [AC_REQUIRE([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION])
# This check should not be cached, as it may vary across builds of
# different projects.
AC_MSG_CHECKING([whether build environment is sane])
# Reject unsafe characters in $srcdir or the absolute working directory # Reject unsafe characters in $srcdir or the absolute working directory
# name. Accept space and tab only in the latter. # name. Accept space and tab only in the latter.
am_lf=' am_lf='
@ -930,49 +1061,40 @@ esac
# symlink; some systems play weird games with the mod time of symlinks # symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing # (eg FreeBSD returns the mod time of the symlink's containing
# directory). # directory).
if ( am_build_env_is_sane=no
am_has_slept=no am_has_slept=no
for am_try in 1 2; do rm -f conftest.file
echo "timestamp, slept: $am_has_slept" > conftest.file for am_try in 1 2; do
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` echo "timestamp, slept: $am_has_slept" > conftest.file
if test "$[*]" = "X"; then if (
# -L didn't work. set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
set X `ls -t "$srcdir/configure" conftest.file` if test "$[]*" = "X"; then
fi # -L didn't work.
if test "$[*]" != "X $srcdir/configure conftest.file" \ set X `ls -t "$srcdir/configure" conftest.file`
&& test "$[*]" != "X conftest.file $srcdir/configure"; then fi
test "$[]2" = conftest.file
); then
am_build_env_is_sane=yes
break
fi
# Just in case.
sleep "$am_cv_filesystem_timestamp_resolution"
am_has_slept=yes
done
# If neither matched, then we have a broken ls. This can happen AC_MSG_RESULT([$am_build_env_is_sane])
# if, for instance, CONFIG_SHELL is bash and it inherits a if test "$am_build_env_is_sane" = no; then
# broken ls alias from the environment. This has actually AC_MSG_ERROR([newly created file is older than distributed files!
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
if test "$[2]" = conftest.file || test $am_try -eq 2; then
break
fi
# Just in case.
sleep 1
am_has_slept=yes
done
test "$[2]" = conftest.file
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock]) Check your system clock])
fi fi
AC_MSG_RESULT([yes])
# If we didn't sleep, we still need to ensure time stamps of config.status and # If we didn't sleep, we still need to ensure time stamps of config.status and
# generated files are strictly newer. # generated files are strictly newer.
am_sleep_pid= am_sleep_pid=
if grep 'slept: no' conftest.file >/dev/null 2>&1; then AS_IF([test -e conftest.file || grep 'slept: no' conftest.file >/dev/null 2>&1],, [dnl
( sleep 1 ) & ( sleep "$am_cv_filesystem_timestamp_resolution" ) &
am_sleep_pid=$! am_sleep_pid=$!
fi ])
AC_CONFIG_COMMANDS_PRE( AC_CONFIG_COMMANDS_PRE(
[AC_MSG_CHECKING([that generated files are newer than configure]) [AC_MSG_CHECKING([that generated files are newer than configure])
if test -n "$am_sleep_pid"; then if test -n "$am_sleep_pid"; then
@ -983,18 +1105,18 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file rm -f conftest.file
]) ])
# Copyright (C) 2009-2021 Free Software Foundation, Inc. # Copyright (C) 2009-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved. # with or without modifications, as long as this notice is preserved.
# AM_SILENT_RULES([DEFAULT]) # _AM_SILENT_RULES
# -------------------------- # ----------------
# Enable less verbose build rules; with the default set to DEFAULT # Enable less verbose build rules support.
# ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([_AM_SILENT_RULES],
AC_DEFUN([AM_SILENT_RULES], [AM_DEFAULT_VERBOSITY=1
[AC_ARG_ENABLE([silent-rules], [dnl AC_ARG_ENABLE([silent-rules], [dnl
AS_HELP_STRING( AS_HELP_STRING(
[--enable-silent-rules], [--enable-silent-rules],
[less verbose build output (undo: "make V=1")]) [less verbose build output (undo: "make V=1")])
@ -1002,11 +1124,6 @@ AS_HELP_STRING(
[--disable-silent-rules], [--disable-silent-rules],
[verbose build output (undo: "make V=0")])dnl [verbose build output (undo: "make V=0")])dnl
]) ])
case $enable_silent_rules in @%:@ (((
yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
esac
dnl dnl
dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
dnl do not support nested variable expansions. dnl do not support nested variable expansions.
@ -1025,14 +1142,6 @@ am__doit:
else else
am_cv_make_support_nested_variables=no am_cv_make_support_nested_variables=no
fi]) fi])
if test $am_cv_make_support_nested_variables = yes; then
dnl Using '$V' instead of '$(V)' breaks IRIX make.
AM_V='$(V)'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
AM_V=$AM_DEFAULT_VERBOSITY
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
AC_SUBST([AM_V])dnl AC_SUBST([AM_V])dnl
AM_SUBST_NOTMAKE([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl
AC_SUBST([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_V])dnl
@ -1041,9 +1150,33 @@ AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
AM_BACKSLASH='\' AM_BACKSLASH='\'
AC_SUBST([AM_BACKSLASH])dnl AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
dnl Delay evaluation of AM_DEFAULT_VERBOSITY to the end to allow multiple calls
dnl to AM_SILENT_RULES to change the default value.
AC_CONFIG_COMMANDS_PRE([dnl
case $enable_silent_rules in @%:@ (((
yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
esac
if test $am_cv_make_support_nested_variables = yes; then
dnl Using '$V' instead of '$(V)' breaks IRIX make.
AM_V='$(V)'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
AM_V=$AM_DEFAULT_VERBOSITY
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
])dnl
]) ])
# Copyright (C) 2001-2021 Free Software Foundation, Inc. # AM_SILENT_RULES([DEFAULT])
# --------------------------
# Set the default verbosity level to DEFAULT ("yes" being less verbose, "no" or
# empty being verbose).
AC_DEFUN([AM_SILENT_RULES],
[AC_REQUIRE([_AM_SILENT_RULES])
AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1])])
# Copyright (C) 2001-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1071,7 +1204,7 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])]) AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006-2021 Free Software Foundation, Inc. # Copyright (C) 2006-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1090,7 +1223,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*- # Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004-2021 Free Software Foundation, Inc. # Copyright (C) 2004-2024 Free Software Foundation, Inc.
# #
# This file is free software; the Free Software Foundation # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1136,15 +1269,19 @@ m4_if([$1], [v7],
am_uid=`id -u || echo unknown` am_uid=`id -u || echo unknown`
am_gid=`id -g || echo unknown` am_gid=`id -g || echo unknown`
AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
if test $am_uid -le $am_max_uid; then if test x$am_uid = xunknown; then
AC_MSG_RESULT([yes]) AC_MSG_WARN([ancient id detected; assuming current UID is ok, but dist-ustar might not work])
elif test $am_uid -le $am_max_uid; then
AC_MSG_RESULT([yes])
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
_am_tools=none _am_tools=none
fi fi
AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
if test $am_gid -le $am_max_gid; then if test x$gm_gid = xunknown; then
AC_MSG_RESULT([yes]) AC_MSG_WARN([ancient id detected; assuming current GID is ok, but dist-ustar might not work])
elif test $am_gid -le $am_max_gid; then
AC_MSG_RESULT([yes])
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
_am_tools=none _am_tools=none
@ -1221,6 +1358,26 @@ AC_SUBST([am__tar])
AC_SUBST([am__untar]) AC_SUBST([am__untar])
]) # _AM_PROG_TAR ]) # _AM_PROG_TAR
# Copyright (C) 2022-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_PROG_XARGS_N
# ----------------
# Check whether 'xargs -n' works. It should work everywhere, so the fallback
# is not optimized at all as we never expect to use it.
AC_DEFUN([_AM_PROG_XARGS_N],
[AC_CACHE_CHECK([xargs -n works], am_cv_xargs_n_works, [dnl
AS_IF([test "`echo 1 2 3 | xargs -n2 echo`" = "1 2
3"], [am_cv_xargs_n_works=yes], [am_cv_xargs_n_works=no])])
AS_IF([test "$am_cv_xargs_n_works" = yes], [am__xargs_n='xargs -n'], [dnl
am__xargs_n='am__xargs_n () { shift; sed "s/ /\\n/g" | while read am__xargs_n_arg; do "$@" "$am__xargs_n_arg"; done; }'
])dnl
AC_SUBST(am__xargs_n)
])
m4_include([m4/ax_ac_append_to_file.m4]) m4_include([m4/ax_ac_append_to_file.m4])
m4_include([m4/ax_ac_print_to_file.m4]) m4_include([m4/ax_ac_print_to_file.m4])
m4_include([m4/ax_add_am_macro_static.m4]) m4_include([m4/ax_add_am_macro_static.m4])

View file

@ -1,6 +1,6 @@
# aminclude_static.am generated automatically by Autoconf # aminclude_static.am generated automatically by Autoconf
# from AX_AM_MACROS_STATIC on Wed Jul 24 05:40:58 EDT 2024 # from AX_AM_MACROS_STATIC on Fri Aug 2 08:48:39 EDT 2024
# Code coverage # Code coverage

133
deps/cares/cares.gyp vendored
View file

@ -8,60 +8,18 @@
'include/ares_version.h', 'include/ares_version.h',
'src/lib/ares__addrinfo2hostent.c', 'src/lib/ares__addrinfo2hostent.c',
'src/lib/ares__addrinfo_localhost.c', 'src/lib/ares__addrinfo_localhost.c',
'src/lib/ares__buf.c',
'src/lib/ares__buf.h',
'src/lib/ares__close_sockets.c', 'src/lib/ares__close_sockets.c',
'src/lib/ares__hosts_file.c', 'src/lib/ares__hosts_file.c',
'src/lib/ares__htable.c',
'src/lib/ares__htable.h',
'src/lib/ares__htable_asvp.c',
'src/lib/ares__htable_asvp.h',
'src/lib/ares__htable_strvp.c',
'src/lib/ares__htable_strvp.h',
'src/lib/ares__htable_szvp.c',
'src/lib/ares__htable_szvp.h',
'src/lib/ares__htable_vpvp.c',
'src/lib/ares__htable_vpvp.h',
'src/lib/ares__iface_ips.c',
'src/lib/ares__iface_ips.h',
'src/lib/ares__llist.c',
'src/lib/ares__llist.h',
'src/lib/ares__parse_into_addrinfo.c', 'src/lib/ares__parse_into_addrinfo.c',
'src/lib/ares__slist.c',
'src/lib/ares__slist.h',
'src/lib/ares__socket.c', 'src/lib/ares__socket.c',
'src/lib/ares__sortaddrinfo.c', 'src/lib/ares__sortaddrinfo.c',
'src/lib/ares__threads.c',
'src/lib/ares__threads.h',
'src/lib/ares__timeval.c',
'src/lib/ares_android.c', 'src/lib/ares_android.c',
'src/lib/ares_android.h', 'src/lib/ares_android.h',
'src/lib/ares_cancel.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_data.c',
'src/lib/ares_data.h', 'src/lib/ares_data.h',
'src/lib/ares_destroy.c', 'src/lib/ares_destroy.c',
'src/lib/ares_dns_mapping.c',
'src/lib/ares_dns_multistring.c',
'src/lib/ares_dns_multistring.h',
'src/lib/ares_dns_name.c',
'src/lib/ares_dns_parse.c',
'src/lib/ares_dns_record.c',
'src/lib/ares_dns_private.h',
'src/lib/ares_dns_write.c',
'src/lib/ares_event_configchg.c',
'src/lib/ares_event.h',
'src/lib/ares_event_win32.h',
'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_hostent.c',
'src/lib/ares_free_string.c', 'src/lib/ares_free_string.c',
'src/lib/ares_freeaddrinfo.c', 'src/lib/ares_freeaddrinfo.c',
@ -71,49 +29,94 @@
'src/lib/ares_gethostbyaddr.c', 'src/lib/ares_gethostbyaddr.c',
'src/lib/ares_gethostbyname.c', 'src/lib/ares_gethostbyname.c',
'src/lib/ares_getnameinfo.c', 'src/lib/ares_getnameinfo.c',
'src/lib/ares_getsock.c',
'src/lib/ares_inet_net_pton.h', 'src/lib/ares_inet_net_pton.h',
'src/lib/ares_init.c', 'src/lib/ares_init.c',
'src/lib/ares_library_init.c',
'src/lib/ares_ipv6.h', 'src/lib/ares_ipv6.h',
'src/lib/ares_math.c', 'src/lib/ares_library_init.c',
'src/lib/ares_metrics.c', 'src/lib/ares_metrics.c',
'src/lib/ares_options.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_platform.c',
'src/lib/ares_platform.h', 'src/lib/ares_platform.h',
'src/lib/ares_private.h', 'src/lib/ares_private.h',
'src/lib/ares_process.c', 'src/lib/ares_process.c',
'src/lib/ares_qcache.c', 'src/lib/ares_qcache.c',
'src/lib/ares_query.c', 'src/lib/ares_query.c',
'src/lib/ares_rand.c',
'src/lib/ares_search.c', 'src/lib/ares_search.c',
'src/lib/ares_send.c', 'src/lib/ares_send.c',
'src/lib/ares_setup.h', 'src/lib/ares_setup.h',
'src/lib/ares_strcasecmp.c',
'src/lib/ares_strcasecmp.h',
'src/lib/ares_str.c',
'src/lib/ares_str.h',
'src/lib/ares_strerror.c', 'src/lib/ares_strerror.c',
'src/lib/ares_strsplit.c',
'src/lib/ares_strsplit.h',
'src/lib/ares_sysconfig.c', 'src/lib/ares_sysconfig.c',
'src/lib/ares_sysconfig_files.c', 'src/lib/ares_sysconfig_files.c',
'src/lib/ares_timeout.c', 'src/lib/ares_timeout.c',
'src/lib/ares_update_servers.c', 'src/lib/ares_update_servers.c',
'src/lib/ares_version.c', 'src/lib/ares_version.c',
'src/lib/dsa/ares__array.c',
'src/lib/dsa/ares__array.h',
'src/lib/dsa/ares__htable.c',
'src/lib/dsa/ares__htable.h',
'src/lib/dsa/ares__htable_asvp.c',
'src/lib/dsa/ares__htable_asvp.h',
'src/lib/dsa/ares__htable_strvp.c',
'src/lib/dsa/ares__htable_strvp.h',
'src/lib/dsa/ares__htable_szvp.c',
'src/lib/dsa/ares__htable_szvp.h',
'src/lib/dsa/ares__htable_vpvp.c',
'src/lib/dsa/ares__htable_vpvp.h',
'src/lib/dsa/ares__llist.c',
'src/lib/dsa/ares__llist.h',
'src/lib/dsa/ares__slist.c',
'src/lib/dsa/ares__slist.h',
'src/lib/event/ares_event.h',
'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/event/ares_event_win32.h',
'src/lib/inet_net_pton.c', 'src/lib/inet_net_pton.c',
'src/lib/inet_ntop.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_multistring.h',
'src/lib/record/ares_dns_name.c',
'src/lib/record/ares_dns_parse.c',
'src/lib/record/ares_dns_private.h',
'src/lib/record/ares_dns_record.c',
'src/lib/record/ares_dns_write.c',
'src/lib/str/ares__buf.c',
'src/lib/str/ares__buf.h',
'src/lib/str/ares_str.c',
'src/lib/str/ares_str.h',
'src/lib/str/ares_strcasecmp.c',
'src/lib/str/ares_strcasecmp.h',
'src/lib/str/ares_strsplit.c',
'src/lib/str/ares_strsplit.h',
'src/lib/util/ares__iface_ips.c',
'src/lib/util/ares__iface_ips.h',
'src/lib/util/ares__threads.c',
'src/lib/util/ares__threads.h',
'src/lib/util/ares__timeval.c',
'src/lib/util/ares_math.c',
'src/lib/util/ares_rand.c',
'src/tools/ares_getopt.c', 'src/tools/ares_getopt.c',
'src/tools/ares_getopt.h', 'src/tools/ares_getopt.h',
], ],
@ -160,7 +163,7 @@
{ {
'target_name': 'cares', 'target_name': 'cares',
'type': '<(library)', 'type': '<(library)',
'include_dirs': [ 'include' ], 'include_dirs': [ 'include', 'src/lib' ],
'direct_dependent_settings': { 'direct_dependent_settings': {
'include_dirs': [ 'include' ], 'include_dirs': [ 'include' ],
'cflags': [ '-Wno-error=deprecated-declarations' ], 'cflags': [ '-Wno-error=deprecated-declarations' ],

574
deps/cares/configure vendored
View file

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.72 for c-ares 1.32.3. # Generated by GNU Autoconf 2.72 for c-ares 1.33.0.
# #
# Report bugs to <c-ares mailing list: http://lists.haxx.se/listinfo/c-ares>. # Report bugs to <c-ares mailing list: http://lists.haxx.se/listinfo/c-ares>.
# #
@ -614,8 +614,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='c-ares' PACKAGE_NAME='c-ares'
PACKAGE_TARNAME='c-ares' PACKAGE_TARNAME='c-ares'
PACKAGE_VERSION='1.32.3' PACKAGE_VERSION='1.33.0'
PACKAGE_STRING='c-ares 1.32.3' PACKAGE_STRING='c-ares 1.33.0'
PACKAGE_BUGREPORT='c-ares mailing list: http://lists.haxx.se/listinfo/c-ares' PACKAGE_BUGREPORT='c-ares mailing list: http://lists.haxx.se/listinfo/c-ares'
PACKAGE_URL='' PACKAGE_URL=''
@ -729,6 +729,8 @@ LIBTOOL
OBJDUMP OBJDUMP
DLLTOOL DLLTOOL
AS AS
am__xargs_n
am__rm_f_notfound
AM_BACKSLASH AM_BACKSLASH
AM_DEFAULT_VERBOSITY AM_DEFAULT_VERBOSITY
AM_DEFAULT_V AM_DEFAULT_V
@ -1415,7 +1417,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
'configure' configures c-ares 1.32.3 to adapt to many kinds of systems. 'configure' configures c-ares 1.33.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1486,7 +1488,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of c-ares 1.32.3:";; short | recursive ) echo "Configuration of c-ares 1.33.0:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1623,7 +1625,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
c-ares configure 1.32.3 c-ares configure 1.33.0
generated by GNU Autoconf 2.72 generated by GNU Autoconf 2.72
Copyright (C) 2023 Free Software Foundation, Inc. Copyright (C) 2023 Free Software Foundation, Inc.
@ -2267,7 +2269,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by c-ares $as_me 1.32.3, which was It was created by c-ares $as_me 1.33.0, which was
generated by GNU Autoconf 2.72. Invocation command line was generated by GNU Autoconf 2.72. Invocation command line was
$ $0$ac_configure_args_raw $ $0$ac_configure_args_raw
@ -3259,7 +3261,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
CARES_VERSION_INFO="19:3:17" CARES_VERSION_INFO="20:0:18"
@ -5421,7 +5423,7 @@ printf "%s\n" "#define HAVE_CXX14 1" >>confdefs.h
fi fi
am__api_version='1.16' am__api_version='1.17'
# Find a good install program. We prefer a C program (faster), # Find a good install program. We prefer a C program (faster),
@ -5523,6 +5525,165 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether sleep supports fractional seconds" >&5
printf %s "checking whether sleep supports fractional seconds... " >&6; }
if test ${am_cv_sleep_fractional_seconds+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if sleep 0.001 2>/dev/null
then :
am_cv_sleep_fractional_seconds=yes
else case e in #(
e) am_cv_sleep_fractional_seconds=no ;;
esac
fi
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_sleep_fractional_seconds" >&5
printf "%s\n" "$am_cv_sleep_fractional_seconds" >&6; }
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking filesystem timestamp resolution" >&5
printf %s "checking filesystem timestamp resolution... " >&6; }
if test ${am_cv_filesystem_timestamp_resolution+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) # Default to the worst case.
am_cv_filesystem_timestamp_resolution=2
# Only try to go finer than 1 sec if sleep can do it.
# Don't try 1 sec, because if 0.01 sec and 0.1 sec don't work,
# - 1 sec is not much of a win compared to 2 sec, and
# - it takes 2 seconds to perform the test whether 1 sec works.
#
# Instead, just use the default 2s on platforms that have 1s resolution,
# accept the extra 1s delay when using $sleep in the Automake tests, in
# exchange for not incurring the 2s delay for running the test for all
# packages.
#
am_try_resolutions=
if test "$am_cv_sleep_fractional_seconds" = yes; then
# Even a millisecond often causes a bunch of false positives,
# so just try a hundredth of a second. The time saved between .001 and
# .01 is not terribly consequential.
am_try_resolutions="0.01 0.1 $am_try_resolutions"
fi
# In order to catch current-generation FAT out, we must *modify* files
# that already exist; the *creation* timestamp is finer. Use names
# that make ls -t sort them differently when they have equal
# timestamps than when they have distinct timestamps, keeping
# in mind that ls -t prints the *newest* file first.
rm -f conftest.ts?
: > conftest.ts1
: > conftest.ts2
: > conftest.ts3
# Make sure ls -t actually works. Do 'set' in a subshell so we don't
# clobber the current shell's arguments. (Outer-level square brackets
# are removed by m4; they're present so that m4 does not expand
# <dollar><star>; be careful, easy to get confused.)
if (
set X `ls -t conftest.ts[12]` &&
{
test "$*" != "X conftest.ts1 conftest.ts2" ||
test "$*" != "X conftest.ts2 conftest.ts1";
}
); then :; else
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
printf "%s\n" ""Bad output from ls -t: \"`ls -t conftest.ts[12]`\""" >&5
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
as_fn_error $? "ls -t produces unexpected output.
Make sure there is not a broken ls alias in your environment.
See 'config.log' for more details" "$LINENO" 5; }
fi
for am_try_res in $am_try_resolutions; do
# Any one fine-grained sleep might happen to cross the boundary
# between two values of a coarser actual resolution, but if we do
# two fine-grained sleeps in a row, at least one of them will fall
# entirely within a coarse interval.
echo alpha > conftest.ts1
sleep $am_try_res
echo beta > conftest.ts2
sleep $am_try_res
echo gamma > conftest.ts3
# We assume that 'ls -t' will make use of high-resolution
# timestamps if the operating system supports them at all.
if (set X `ls -t conftest.ts?` &&
test "$2" = conftest.ts3 &&
test "$3" = conftest.ts2 &&
test "$4" = conftest.ts1); then
#
# Ok, ls -t worked. If we're at a resolution of 1 second, we're done,
# because we don't need to test make.
make_ok=true
if test $am_try_res != 1; then
# But if we've succeeded so far with a subsecond resolution, we
# have one more thing to check: make. It can happen that
# everything else supports the subsecond mtimes, but make doesn't;
# notably on macOS, which ships make 3.81 from 2006 (the last one
# released under GPLv2). https://bugs.gnu.org/68808
#
# We test $MAKE if it is defined in the environment, else "make".
# It might get overridden later, but our hope is that in practice
# it does not matter: it is the system "make" which is (by far)
# the most likely to be broken, whereas if the user overrides it,
# probably they did so with a better, or at least not worse, make.
# https://lists.gnu.org/archive/html/automake/2024-06/msg00051.html
#
# Create a Makefile (real tab character here):
rm -f conftest.mk
echo 'conftest.ts1: conftest.ts2' >conftest.mk
echo ' touch conftest.ts2' >>conftest.mk
#
# Now, running
# touch conftest.ts1; touch conftest.ts2; make
# should touch ts1 because ts2 is newer. This could happen by luck,
# but most often, it will fail if make's support is insufficient. So
# test for several consecutive successes.
#
# (We reuse conftest.ts[12] because we still want to modify existing
# files, not create new ones, per above.)
n=0
make=${MAKE-make}
until test $n -eq 3; do
echo one > conftest.ts1
sleep $am_try_res
echo two > conftest.ts2 # ts2 should now be newer than ts1
if $make -f conftest.mk | grep 'up to date' >/dev/null; then
make_ok=false
break # out of $n loop
fi
n=`expr $n + 1`
done
fi
#
if $make_ok; then
# Everything we know to check worked out, so call this resolution good.
am_cv_filesystem_timestamp_resolution=$am_try_res
break # out of $am_try_res loop
fi
# Otherwise, we'll go on to check the next resolution.
fi
done
rm -f conftest.ts?
# (end _am_filesystem_timestamp_resolution)
;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_filesystem_timestamp_resolution" >&5
printf "%s\n" "$am_cv_filesystem_timestamp_resolution" >&6; }
# This check should not be cached, as it may vary across builds of
# different projects.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
printf %s "checking whether build environment is sane... " >&6; } printf %s "checking whether build environment is sane... " >&6; }
# Reject unsafe characters in $srcdir or the absolute working directory # Reject unsafe characters in $srcdir or the absolute working directory
@ -5543,49 +5704,45 @@ esac
# symlink; some systems play weird games with the mod time of symlinks # symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing # (eg FreeBSD returns the mod time of the symlink's containing
# directory). # directory).
if ( am_build_env_is_sane=no
am_has_slept=no am_has_slept=no
for am_try in 1 2; do rm -f conftest.file
echo "timestamp, slept: $am_has_slept" > conftest.file for am_try in 1 2; do
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` echo "timestamp, slept: $am_has_slept" > conftest.file
if test "$*" = "X"; then if (
# -L didn't work. set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
set X `ls -t "$srcdir/configure" conftest.file` if test "$*" = "X"; then
fi # -L didn't work.
if test "$*" != "X $srcdir/configure conftest.file" \ set X `ls -t "$srcdir/configure" conftest.file`
&& test "$*" != "X conftest.file $srcdir/configure"; then fi
test "$2" = conftest.file
); then
am_build_env_is_sane=yes
break
fi
# Just in case.
sleep "$am_cv_filesystem_timestamp_resolution"
am_has_slept=yes
done
# If neither matched, then we have a broken ls. This can happen { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_build_env_is_sane" >&5
# if, for instance, CONFIG_SHELL is bash and it inherits a printf "%s\n" "$am_build_env_is_sane" >&6; }
# broken ls alias from the environment. This has actually if test "$am_build_env_is_sane" = no; then
# happened. Such a system could not be considered "sane". as_fn_error $? "newly created file is older than distributed files!
as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
alias in your environment" "$LINENO" 5
fi
if test "$2" = conftest.file || test $am_try -eq 2; then
break
fi
# Just in case.
sleep 1
am_has_slept=yes
done
test "$2" = conftest.file
)
then
# Ok.
:
else
as_fn_error $? "newly created file is older than distributed files!
Check your system clock" "$LINENO" 5 Check your system clock" "$LINENO" 5
fi fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
# If we didn't sleep, we still need to ensure time stamps of config.status and # If we didn't sleep, we still need to ensure time stamps of config.status and
# generated files are strictly newer. # generated files are strictly newer.
am_sleep_pid= am_sleep_pid=
if grep 'slept: no' conftest.file >/dev/null 2>&1; then if test -e conftest.file || grep 'slept: no' conftest.file >/dev/null 2>&1
( sleep 1 ) & then :
else case e in #(
e) ( sleep "$am_cv_filesystem_timestamp_resolution" ) &
am_sleep_pid=$! am_sleep_pid=$!
;;
esac
fi fi
rm -f conftest.file rm -f conftest.file
@ -5935,17 +6092,13 @@ else
fi fi
AM_DEFAULT_VERBOSITY=1
# Check whether --enable-silent-rules was given. # Check whether --enable-silent-rules was given.
if test ${enable_silent_rules+y} if test ${enable_silent_rules+y}
then : then :
enableval=$enable_silent_rules; enableval=$enable_silent_rules;
fi fi
case $enable_silent_rules in # (((
yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
*) AM_DEFAULT_VERBOSITY=1;;
esac
am_make=${MAKE-make} am_make=${MAKE-make}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
printf %s "checking whether $am_make supports nested variables... " >&6; } printf %s "checking whether $am_make supports nested variables... " >&6; }
@ -5968,15 +6121,45 @@ esac
fi fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
printf "%s\n" "$am_cv_make_support_nested_variables" >&6; } printf "%s\n" "$am_cv_make_support_nested_variables" >&6; }
if test $am_cv_make_support_nested_variables = yes; then
AM_V='$(V)'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
AM_V=$AM_DEFAULT_VERBOSITY
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
AM_BACKSLASH='\' AM_BACKSLASH='\'
am__rm_f_notfound=
if (rm -f && rm -fr && rm -rf) 2>/dev/null
then :
else case e in #(
e) am__rm_f_notfound='""' ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking xargs -n works" >&5
printf %s "checking xargs -n works... " >&6; }
if test ${am_cv_xargs_n_works+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if test "`echo 1 2 3 | xargs -n2 echo`" = "1 2
3"
then :
am_cv_xargs_n_works=yes
else case e in #(
e) am_cv_xargs_n_works=no ;;
esac
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_xargs_n_works" >&5
printf "%s\n" "$am_cv_xargs_n_works" >&6; }
if test "$am_cv_xargs_n_works" = yes
then :
am__xargs_n='xargs -n'
else case e in #(
e) am__xargs_n='am__xargs_n () { shift; sed "s/ /\\n/g" | while read am__xargs_n_arg; do "" "$am__xargs_n_arg"; done; }'
;;
esac
fi
if test "`cd $srcdir && pwd`" != "`pwd`"; then if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I." # is not polluted with repeated "-I."
@ -5999,7 +6182,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='c-ares' PACKAGE='c-ares'
VERSION='1.32.3' VERSION='1.33.0'
printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@ -6140,7 +6323,7 @@ else case e in #(
# icc doesn't choke on unknown options, it will just issue warnings # icc doesn't choke on unknown options, it will just issue warnings
# or remarks (even with -Werror). So we grep stderr for any message # or remarks (even with -Werror). So we grep stderr for any message
# that says an option was ignored or not supported. # that says an option was ignored or not supported.
# When given -MP, icc 7.0 and 7.1 complain thusly: # When given -MP, icc 7.0 and 7.1 complain thus:
# icc: Command line warning: ignoring option '-M'; no argument required # icc: Command line warning: ignoring option '-M'; no argument required
# The diagnosis changed in icc 8.0: # The diagnosis changed in icc 8.0:
# icc: Command line remark: option '-MP' not supported # icc: Command line remark: option '-MP' not supported
@ -6270,7 +6453,7 @@ else case e in #(
# icc doesn't choke on unknown options, it will just issue warnings # icc doesn't choke on unknown options, it will just issue warnings
# or remarks (even with -Werror). So we grep stderr for any message # or remarks (even with -Werror). So we grep stderr for any message
# that says an option was ignored or not supported. # that says an option was ignored or not supported.
# When given -MP, icc 7.0 and 7.1 complain thusly: # When given -MP, icc 7.0 and 7.1 complain thus:
# icc: Command line warning: ignoring option '-M'; no argument required # icc: Command line warning: ignoring option '-M'; no argument required
# The diagnosis changed in icc 8.0: # The diagnosis changed in icc 8.0:
# icc: Command line remark: option '-MP' not supported # icc: Command line remark: option '-MP' not supported
@ -6320,47 +6503,9 @@ fi
# POSIX will say in a future version that running "rm -f" with no argument
# is OK; and we want to be able to make that assumption in our Makefile
# recipes. So use an aggressive probe to check that the usage we want is
# actually supported "in the wild" to an acceptable degree.
# See automake bug#10828.
# To make any issue more visible, cause the running configure to be aborted
# by default if the 'rm' program in use doesn't match our expectations; the
# user can still override this though.
if rm -f && rm -fr && rm -rf; then : OK; else
cat >&2 <<'END'
Oops!
Your 'rm' program seems unable to run without file operands specified
on the command line, even when the '-f' option is present. This is contrary
to the behaviour of most rm programs out there, and not conforming with
the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
Please tell bug-automake@gnu.org about your system, including the value
of your $PATH and any error possibly output before this message. This
can help us improve future automake versions.
END
if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
echo 'Configuration will proceed anyway, since you have set the' >&2
echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
echo >&2
else
cat >&2 <<'END'
Aborting the configuration process, to ensure you take notice of the issue.
You can download and install GNU coreutils to get an 'rm' implementation
that behaves properly: <https://www.gnu.org/software/coreutils/>.
If you want to complete the configuration process using your problematic
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
to "yes", and re-run configure.
END
as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
fi
fi
case `pwd` in case `pwd` in
*\ * | *\ *) *\ * | *\ *)
@ -19498,48 +19643,8 @@ fi
MAINT=$MAINTAINER_MODE_TRUE MAINT=$MAINTAINER_MODE_TRUE
# Check whether --enable-silent-rules was given.
if test ${enable_silent_rules+y}
then :
enableval=$enable_silent_rules;
fi
case $enable_silent_rules in # (((
yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
*) AM_DEFAULT_VERBOSITY=0;;
esac
am_make=${MAKE-make}
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
printf %s "checking whether $am_make supports nested variables... " >&6; }
if test ${am_cv_make_support_nested_variables+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) if printf "%s\n" 'TRUE=$(BAR$(V))
BAR0=false
BAR1=true
V=1
am__doit:
@$(TRUE)
.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
am_cv_make_support_nested_variables=yes
else
am_cv_make_support_nested_variables=no
fi ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
printf "%s\n" "$am_cv_make_support_nested_variables" >&6; }
if test $am_cv_make_support_nested_variables = yes; then
AM_V='$(V)'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
AM_V=$AM_DEFAULT_VERBOSITY
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
AM_BACKSLASH='\'
AM_DEFAULT_VERBOSITY=0
@ -20682,7 +20787,7 @@ fi
if test "$enable_warnings" = "yes"; then if test "$enable_warnings" = "yes"; then
for flag in -std=c90 -Wall -Wextra -Waggregate-return -Wcast-align -Wcast-qual -Wconversion -Wdeclaration-after-statement -Wdouble-promotion -Wfloat-equal -Wformat-security -Winit-self -Wjump-misses-init -Wlogical-op -Wmissing-braces -Wmissing-declarations -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-prototypes -Wnested-externs -Wno-coverage-mismatch -Wold-style-definition -Wpacked -Wpedantic -Wpointer-arith -Wredundant-decls -Wshadow -Wsign-conversion -Wstrict-overflow -Wstrict-prototypes -Wtrampolines -Wundef -Wunreachable-code -Wunused -Wvariadic-macros -Wvla -Wwrite-strings -Werror=implicit-int -Werror=implicit-function-declaration -Werror=partial-availability -Wno-long-long ; do for flag in -Wall -Wextra -Waggregate-return -Wcast-align -Wcast-qual -Wconversion -Wdeclaration-after-statement -Wdouble-promotion -Wfloat-equal -Wformat-security -Winit-self -Wjump-misses-init -Wlogical-op -Wmissing-braces -Wmissing-declarations -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-prototypes -Wnested-externs -Wno-coverage-mismatch -Wold-style-definition -Wpacked -Wpedantic -Wpointer-arith -Wredundant-decls -Wshadow -Wsign-conversion -Wstrict-overflow -Wstrict-prototypes -Wtrampolines -Wundef -Wunreachable-code -Wunused -Wvariadic-macros -Wvla -Wwrite-strings -Werror=implicit-int -Werror=implicit-function-declaration -Werror=partial-availability -Wno-long-long ; do
as_CACHEVAR=`printf "%s\n" "ax_cv_check_cflags_-Werror_$flag" | sed "$as_sed_sh"` as_CACHEVAR=`printf "%s\n" "ax_cv_check_cflags_-Werror_$flag" | sed "$as_sed_sh"`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5
printf %s "checking whether C compiler accepts $flag... " >&6; } printf %s "checking whether C compiler accepts $flag... " >&6; }
@ -20751,6 +20856,155 @@ fi
done done
case $host_os in
*android*)
for flag in -std=c99; do
as_CACHEVAR=`printf "%s\n" "ax_cv_check_cflags_-Werror_$flag" | sed "$as_sed_sh"`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5
printf %s "checking whether C compiler accepts $flag... " >&6; }
if eval test \${$as_CACHEVAR+y}
then :
printf %s "(cached) " >&6
else case e in #(
e)
ax_check_save_flags=$CFLAGS
CFLAGS="$CFLAGS -Werror $flag"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
eval "$as_CACHEVAR=yes"
else case e in #(
e) eval "$as_CACHEVAR=no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$ax_check_save_flags ;;
esac
fi
eval ac_res=\$$as_CACHEVAR
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
if test x"`eval 'as_val=${'$as_CACHEVAR'};printf "%s\n" "$as_val"'`" = xyes
then :
if test ${AM_CFLAGS+y}
then :
case " $AM_CFLAGS " in
*" $flag "*)
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : AM_CFLAGS already contains \$flag"; } >&5
(: AM_CFLAGS already contains $flag) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
;;
*)
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : AM_CFLAGS=\"\$AM_CFLAGS \$flag\""; } >&5
(: AM_CFLAGS="$AM_CFLAGS $flag") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
AM_CFLAGS="$AM_CFLAGS $flag"
;;
esac
else case e in #(
e) AM_CFLAGS="$flag" ;;
esac
fi
else case e in #(
e) : ;;
esac
fi
done
;;
*)
for flag in -std=c90; do
as_CACHEVAR=`printf "%s\n" "ax_cv_check_cflags_-Werror_$flag" | sed "$as_sed_sh"`
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts $flag" >&5
printf %s "checking whether C compiler accepts $flag... " >&6; }
if eval test \${$as_CACHEVAR+y}
then :
printf %s "(cached) " >&6
else case e in #(
e)
ax_check_save_flags=$CFLAGS
CFLAGS="$CFLAGS -Werror $flag"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main (void)
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
eval "$as_CACHEVAR=yes"
else case e in #(
e) eval "$as_CACHEVAR=no" ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
CFLAGS=$ax_check_save_flags ;;
esac
fi
eval ac_res=\$$as_CACHEVAR
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
printf "%s\n" "$ac_res" >&6; }
if test x"`eval 'as_val=${'$as_CACHEVAR'};printf "%s\n" "$as_val"'`" = xyes
then :
if test ${AM_CFLAGS+y}
then :
case " $AM_CFLAGS " in
*" $flag "*)
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : AM_CFLAGS already contains \$flag"; } >&5
(: AM_CFLAGS already contains $flag) 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
;;
*)
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: : AM_CFLAGS=\"\$AM_CFLAGS \$flag\""; } >&5
(: AM_CFLAGS="$AM_CFLAGS $flag") 2>&5
ac_status=$?
printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
AM_CFLAGS="$AM_CFLAGS $flag"
;;
esac
else case e in #(
e) AM_CFLAGS="$flag" ;;
esac
fi
else case e in #(
e) : ;;
esac
fi
done
;;
esac
fi fi
if test "$ax_cv_c_compiler_vendor" = "intel"; then if test "$ax_cv_c_compiler_vendor" = "intel"; then
@ -22622,6 +22876,14 @@ then :
printf "%s\n" "#define HAVE_CONNECT 1" >>confdefs.h printf "%s\n" "#define HAVE_CONNECT 1" >>confdefs.h
fi
ac_fn_check_decl "$LINENO" "connectx" "ac_cv_have_decl_connectx" "$cares_all_includes
" "$ac_c_undeclared_builtin_options" "CFLAGS"
if test "x$ac_cv_have_decl_connectx" = xyes
then :
printf "%s\n" "#define HAVE_CONNECTX 1" >>confdefs.h
fi fi
ac_fn_check_decl "$LINENO" "closesocket" "ac_cv_have_decl_closesocket" "$cares_all_includes ac_fn_check_decl "$LINENO" "closesocket" "ac_cv_have_decl_closesocket" "$cares_all_includes
" "$ac_c_undeclared_builtin_options" "CFLAGS" " "$ac_c_undeclared_builtin_options" "CFLAGS"
@ -22910,6 +23172,22 @@ then :
printf "%s\n" "#define HAVE_CONVERTINTERFACELUIDTONAMEA 1" >>confdefs.h printf "%s\n" "#define HAVE_CONVERTINTERFACELUIDTONAMEA 1" >>confdefs.h
fi
ac_fn_check_decl "$LINENO" "NotifyIpInterfaceChange" "ac_cv_have_decl_NotifyIpInterfaceChange" "$cares_all_includes
" "$ac_c_undeclared_builtin_options" "CFLAGS"
if test "x$ac_cv_have_decl_NotifyIpInterfaceChange" = xyes
then :
printf "%s\n" "#define HAVE_NOTIFYIPINTERFACECHANGE 1" >>confdefs.h
fi
ac_fn_check_decl "$LINENO" "RegisterWaitForSingleObject" "ac_cv_have_decl_RegisterWaitForSingleObject" "$cares_all_includes
" "$ac_c_undeclared_builtin_options" "CFLAGS"
if test "x$ac_cv_have_decl_RegisterWaitForSingleObject" = xyes
then :
printf "%s\n" "#define HAVE_REGISTERWAITFORSINGLEOBJECT 1" >>confdefs.h
fi fi
ac_fn_check_decl "$LINENO" "__system_property_get" "ac_cv_have_decl___system_property_get" "$cares_all_includes ac_fn_check_decl "$LINENO" "__system_property_get" "ac_cv_have_decl___system_property_get" "$cares_all_includes
" "$ac_c_undeclared_builtin_options" "CFLAGS" " "$ac_c_undeclared_builtin_options" "CFLAGS"
@ -25912,6 +26190,18 @@ if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. as_fn_error $? "conditional \"am__fastdepCXX\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5 Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi fi
case $enable_silent_rules in # (((
yes) AM_DEFAULT_VERBOSITY=0;;
no) AM_DEFAULT_VERBOSITY=1;;
esac
if test $am_cv_make_support_nested_variables = yes; then
AM_V='$(V)'
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
else
AM_V=$AM_DEFAULT_VERBOSITY
AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
if test -n "$EXEEXT"; then if test -n "$EXEEXT"; then
am__EXEEXT_TRUE= am__EXEEXT_TRUE=
am__EXEEXT_FALSE='#' am__EXEEXT_FALSE='#'
@ -26339,7 +26629,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by c-ares $as_me 1.32.3, which was This file was extended by c-ares $as_me 1.33.0, which was
generated by GNU Autoconf 2.72. Invocation command line was generated by GNU Autoconf 2.72. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -26407,7 +26697,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped' ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\ ac_cs_version="\\
c-ares config.status 1.32.3 c-ares config.status 1.33.0
configured by $0, generated by GNU Autoconf 2.72, configured by $0, generated by GNU Autoconf 2.72,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View file

@ -2,10 +2,10 @@ dnl Copyright (C) The c-ares project and its contributors
dnl SPDX-License-Identifier: MIT dnl SPDX-License-Identifier: MIT
AC_PREREQ([2.69]) AC_PREREQ([2.69])
AC_INIT([c-ares], [1.32.3], AC_INIT([c-ares], [1.33.0],
[c-ares mailing list: http://lists.haxx.se/listinfo/c-ares]) [c-ares mailing list: http://lists.haxx.se/listinfo/c-ares])
CARES_VERSION_INFO="19:3:17" CARES_VERSION_INFO="20:0:18"
dnl This flag accepts an argument of the form current[:revision[:age]]. So, dnl This flag accepts an argument of the form current[:revision[:age]]. So,
dnl passing -version-info 3:12:1 sets current to 3, revision to 12, and age to dnl passing -version-info 3:12:1 sets current to 3, revision to 12, and age to
dnl 1. dnl 1.
@ -245,8 +245,18 @@ AC_SUBST(CARES_SYMBOL_HIDING_CFLAG)
if test "$enable_warnings" = "yes"; then if test "$enable_warnings" = "yes"; then
AX_APPEND_COMPILE_FLAGS([-std=c90 -Wall -Wextra -Waggregate-return -Wcast-align -Wcast-qual -Wconversion -Wdeclaration-after-statement -Wdouble-promotion -Wfloat-equal -Wformat-security -Winit-self -Wjump-misses-init -Wlogical-op -Wmissing-braces -Wmissing-declarations -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-prototypes -Wnested-externs -Wno-coverage-mismatch -Wold-style-definition -Wpacked -Wpedantic -Wpointer-arith -Wredundant-decls -Wshadow -Wsign-conversion -Wstrict-overflow -Wstrict-prototypes -Wtrampolines -Wundef -Wunreachable-code -Wunused -Wvariadic-macros -Wvla -Wwrite-strings -Werror=implicit-int -Werror=implicit-function-declaration -Werror=partial-availability -Wno-long-long ], AX_APPEND_COMPILE_FLAGS([-Wall -Wextra -Waggregate-return -Wcast-align -Wcast-qual -Wconversion -Wdeclaration-after-statement -Wdouble-promotion -Wfloat-equal -Wformat-security -Winit-self -Wjump-misses-init -Wlogical-op -Wmissing-braces -Wmissing-declarations -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-prototypes -Wnested-externs -Wno-coverage-mismatch -Wold-style-definition -Wpacked -Wpedantic -Wpointer-arith -Wredundant-decls -Wshadow -Wsign-conversion -Wstrict-overflow -Wstrict-prototypes -Wtrampolines -Wundef -Wunreachable-code -Wunused -Wvariadic-macros -Wvla -Wwrite-strings -Werror=implicit-int -Werror=implicit-function-declaration -Werror=partial-availability -Wno-long-long ],
[AM_CFLAGS], [-Werror]) [AM_CFLAGS], [-Werror])
dnl Android requires c99, all others should use c90
case $host_os in
*android*)
AX_APPEND_COMPILE_FLAGS([-std=c99], [AM_CFLAGS], [-Werror])
;;
*)
AX_APPEND_COMPILE_FLAGS([-std=c90], [AM_CFLAGS], [-Werror])
;;
esac
fi fi
if test "$ax_cv_c_compiler_vendor" = "intel"; then if test "$ax_cv_c_compiler_vendor" = "intel"; then
@ -538,6 +548,7 @@ AC_CHECK_DECL(send, [AC_DEFINE([HAVE_SEND], 1, [Define t
AC_CHECK_DECL(getnameinfo, [AC_DEFINE([HAVE_GETNAMEINFO], 1, [Define to 1 if you have `getnameinfo`] )], [], $cares_all_includes) AC_CHECK_DECL(getnameinfo, [AC_DEFINE([HAVE_GETNAMEINFO], 1, [Define to 1 if you have `getnameinfo`] )], [], $cares_all_includes)
AC_CHECK_DECL(gethostname, [AC_DEFINE([HAVE_GETHOSTNAME], 1, [Define to 1 if you have `gethostname`] )], [], $cares_all_includes) AC_CHECK_DECL(gethostname, [AC_DEFINE([HAVE_GETHOSTNAME], 1, [Define to 1 if you have `gethostname`] )], [], $cares_all_includes)
AC_CHECK_DECL(connect, [AC_DEFINE([HAVE_CONNECT], 1, [Define to 1 if you have `connect`] )], [], $cares_all_includes) AC_CHECK_DECL(connect, [AC_DEFINE([HAVE_CONNECT], 1, [Define to 1 if you have `connect`] )], [], $cares_all_includes)
AC_CHECK_DECL(connectx, [AC_DEFINE([HAVE_CONNECTX], 1, [Define to 1 if you have `connectx`] )], [], $cares_all_includes)
AC_CHECK_DECL(closesocket, [AC_DEFINE([HAVE_CLOSESOCKET], 1, [Define to 1 if you have `closesocket`] )], [], $cares_all_includes) AC_CHECK_DECL(closesocket, [AC_DEFINE([HAVE_CLOSESOCKET], 1, [Define to 1 if you have `closesocket`] )], [], $cares_all_includes)
AC_CHECK_DECL(CloseSocket, [AC_DEFINE([HAVE_CLOSESOCKET_CAMEL], 1, [Define to 1 if you have `CloseSocket`] )], [], $cares_all_includes) AC_CHECK_DECL(CloseSocket, [AC_DEFINE([HAVE_CLOSESOCKET_CAMEL], 1, [Define to 1 if you have `CloseSocket`] )], [], $cares_all_includes)
AC_CHECK_DECL(fcntl, [AC_DEFINE([HAVE_FCNTL], 1, [Define to 1 if you have `fcntl`] )], [], $cares_all_includes) AC_CHECK_DECL(fcntl, [AC_DEFINE([HAVE_FCNTL], 1, [Define to 1 if you have `fcntl`] )], [], $cares_all_includes)
@ -574,6 +585,8 @@ AC_CHECK_DECL(kqueue, [AC_DEFINE([HAVE_KQUEUE], 1, [Define t
AC_CHECK_DECL(epoll_create1, [AC_DEFINE([HAVE_EPOLL], 1, [Define to 1 if you have `epoll_{create1,ctl,wait}`])], [], $cares_all_includes) AC_CHECK_DECL(epoll_create1, [AC_DEFINE([HAVE_EPOLL], 1, [Define to 1 if you have `epoll_{create1,ctl,wait}`])], [], $cares_all_includes)
AC_CHECK_DECL(ConvertInterfaceIndexToLuid, [AC_DEFINE([HAVE_CONVERTINTERFACEINDEXTOLUID], 1, [Define to 1 if you have `ConvertInterfaceIndexToLuid`])], [], $cares_all_includes) AC_CHECK_DECL(ConvertInterfaceIndexToLuid, [AC_DEFINE([HAVE_CONVERTINTERFACEINDEXTOLUID], 1, [Define to 1 if you have `ConvertInterfaceIndexToLuid`])], [], $cares_all_includes)
AC_CHECK_DECL(ConvertInterfaceLuidToNameA, [AC_DEFINE([HAVE_CONVERTINTERFACELUIDTONAMEA], 1, [Define to 1 if you have `ConvertInterfaceLuidToNameA`])], [], $cares_all_includes) AC_CHECK_DECL(ConvertInterfaceLuidToNameA, [AC_DEFINE([HAVE_CONVERTINTERFACELUIDTONAMEA], 1, [Define to 1 if you have `ConvertInterfaceLuidToNameA`])], [], $cares_all_includes)
AC_CHECK_DECL(NotifyIpInterfaceChange, [AC_DEFINE([HAVE_NOTIFYIPINTERFACECHANGE], 1, [Define to 1 if you have `NotifyIpInterfaceChange`] )], [], $cares_all_includes)
AC_CHECK_DECL(RegisterWaitForSingleObject, [AC_DEFINE([HAVE_REGISTERWAITFORSINGLEOBJECT], 1, [Define to 1 if you have `RegisterWaitForSingleObject`])], [], $cares_all_includes)
AC_CHECK_DECL(__system_property_get, [AC_DEFINE([HAVE___SYSTEM_PROPERTY_GET], 1, [Define to 1 if you have `__system_property_get`] )], [], $cares_all_includes) AC_CHECK_DECL(__system_property_get, [AC_DEFINE([HAVE___SYSTEM_PROPERTY_GET], 1, [Define to 1 if you have `__system_property_get`] )], [], $cares_all_includes)

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.5 from Makefile.am. # Makefile.in generated by automake 1.17 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2021 Free Software Foundation, Inc. # Copyright (C) 1994-2024 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -72,6 +72,8 @@ am__make_running_with_option = \
test $$has_opt = yes test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
am__rm_f = rm -f $(am__rm_f_notfound)
am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@ pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@
@ -166,10 +168,9 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \ am__uninstall_files_from_dir = { \
test -z "$$files" \ { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \
$(am__cd) "$$dir" && rm -f $$files; }; \
} }
man3dir = $(mandir)/man3 man3dir = $(mandir)/man3
am__installdirs = "$(DESTDIR)$(man3dir)" am__installdirs = "$(DESTDIR)$(man3dir)"
@ -288,8 +289,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@ am__include = @am__include@
am__leading_dot = @am__leading_dot@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@ am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@ am__tar = @am__tar@
am__untar = @am__untar@ am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
ax_pthread_config = @ax_pthread_config@ ax_pthread_config = @ax_pthread_config@
bindir = @bindir@ bindir = @bindir@
build = @build@ build = @build@
@ -638,8 +641,8 @@ mostlyclean-generic:
clean-generic: clean-generic:
distclean-generic: distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -$(am__rm_f) $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic: maintainer-clean-generic:
@echo "This command is intended for maintainers to use" @echo "This command is intended for maintainers to use"
@ -733,3 +736,10 @@ uninstall-man: uninstall-man3
# Tell versions [3.59,3.63) of GNU make to not export all variables. # Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded. # Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT: .NOEXPORT:
# Tell GNU make to disable its built-in pattern rules.
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%

View file

@ -96,6 +96,10 @@ ares_status_t ares_dns_rr_set_opt(ares_dns_rr_t *dns_rr,
const unsigned char *val, const unsigned char *val,
size_t val_len); size_t val_len);
ares_status_t ares_dns_rr_del_opt_byid(ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key,
unsigned short opt);
const struct in_addr *ares_dns_rr_get_addr(const ares_dns_rr_t *dns_rr, const struct in_addr *ares_dns_rr_get_addr(const ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key); ares_dns_rr_key_t key);
@ -553,7 +557,7 @@ parameter, and the index to remove is provided in the
parameter. parameter.
The \fIares_dns_rr_set_opt(3)\fP function is used to set option/parameter keys and The \fIares_dns_rr_set_opt(3)\fP function is used to set option/parameter keys and
values for the resource record when the datatype if \fIARES_DATATYPE_OPT\fP. The values for the resource record when the datatype is \fIARES_DATATYPE_OPT\fP. The
resource record to be modified is provided in the resource record to be modified is provided in the
.IR dns_rr .IR dns_rr
parameter. They key/parameter is provided in the parameter. They key/parameter is provided in the
@ -568,6 +572,18 @@ enumerations. The value for the option is always provided in binary form in
with length provided in with length provided in
.IR val_len. .IR val_len.
The \fIares_dns_rr_del_opt_byid(3)\fP function is used to delete option/parameter
keys and values for the resource record when the datatype is
\fIARES_DATATYPE_OPT\fP. The resource record to be modified is provided in the
.IR dns_rr
parameter. They key/parameter is provided in the
.IR key
parameter. The option/parameter value specific to the resource record is provided
in the
.IR opt
parameter. This function returns \fIARES_SUCCESS\fP if the record is successfully
removed, or \fIARES_ENOTFOUND\fP if the record could not be found.
The \fIares_dns_rr_get_addr(3)\fP function is used to retrieve the IPv4 address The \fIares_dns_rr_get_addr(3)\fP function is used to retrieve the IPv4 address
from the resource record when the datatype is \fIARES_DATATYPE_INADDR\fP. The from the resource record when the datatype is \fIARES_DATATYPE_INADDR\fP. The
resource record is provided in the resource record is provided in the
@ -635,7 +651,7 @@ parameter and the key/parameter to retrieve is provided in the
.IR key .IR key
parameter. parameter.
The \fIares_dns_rr_get_abin(3)\fP function is used to retrive binary data from The \fIares_dns_rr_get_abin(3)\fP function is used to retrieve binary data from
the resource record array when the datatype is \fIARES_DATATYPE_ABINP\fP. the resource record array when the datatype is \fIARES_DATATYPE_ABINP\fP.
The resource record is provided in the The resource record is provided in the
.IR dns_rr .IR dns_rr

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.5 from Makefile.am. # Makefile.in generated by automake 1.17 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2021 Free Software Foundation, Inc. # Copyright (C) 1994-2024 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -70,6 +70,8 @@ am__make_running_with_option = \
test $$has_opt = yes test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
am__rm_f = rm -f $(am__rm_f_notfound)
am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@ pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@
@ -162,10 +164,9 @@ am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \ am__uninstall_files_from_dir = { \
test -z "$$files" \ { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \
$(am__cd) "$$dir" && rm -f $$files; }; \
} }
am__installdirs = "$(DESTDIR)$(includedir)" am__installdirs = "$(DESTDIR)$(includedir)"
HEADERS = $(include_HEADERS) HEADERS = $(include_HEADERS)
@ -299,8 +300,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@ am__include = @am__include@
am__leading_dot = @am__leading_dot@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@ am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@ am__tar = @am__tar@
am__untar = @am__untar@ am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
ax_pthread_config = @ax_pthread_config@ ax_pthread_config = @ax_pthread_config@
bindir = @bindir@ bindir = @bindir@
build = @build@ build = @build@
@ -393,8 +396,8 @@ ares_build.h: stamp-h2
@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h2 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h2
stamp-h2: $(srcdir)/ares_build.h.in $(top_builddir)/config.status stamp-h2: $(srcdir)/ares_build.h.in $(top_builddir)/config.status
@rm -f stamp-h2 $(AM_V_at)rm -f stamp-h2
cd $(top_builddir) && $(SHELL) ./config.status include/ares_build.h $(AM_V_GEN)cd $(top_builddir) && $(SHELL) ./config.status include/ares_build.h
distclean-hdr: distclean-hdr:
-rm -f ares_build.h stamp-h2 -rm -f ares_build.h stamp-h2
@ -541,8 +544,8 @@ mostlyclean-generic:
clean-generic: clean-generic:
distclean-generic: distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -$(am__rm_f) $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic: maintainer-clean-generic:
@echo "This command is intended for maintainers to use" @echo "This command is intended for maintainers to use"
@ -635,3 +638,10 @@ uninstall-am: uninstall-includeHEADERS
# Tell versions [3.59,3.63) of GNU make to not export all variables. # Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded. # Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT: .NOEXPORT:
# Tell GNU make to disable its built-in pattern rules.
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%

View file

@ -95,7 +95,7 @@
#endif #endif
typedef CARES_TYPEOF_ARES_SOCKLEN_T ares_socklen_t; typedef CARES_TYPEOF_ARES_SOCKLEN_T ares_socklen_t;
typedef CARES_TYPEOF_ARES_SSIZE_T ares_ssize_t; typedef CARES_TYPEOF_ARES_SSIZE_T ares_ssize_t;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View file

@ -152,28 +152,28 @@ typedef enum {
ARES_RCODE_BADNAME = 20, /*!< RFC 2930. Duplicate Key Name */ ARES_RCODE_BADNAME = 20, /*!< RFC 2930. Duplicate Key Name */
ARES_RCODE_BADALG = 21, /*!< RFC 2930. Algorithm not supported */ ARES_RCODE_BADALG = 21, /*!< RFC 2930. Algorithm not supported */
ARES_RCODE_BADTRUNC = 22, /*!< RFC 8945. Bad Truncation */ 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; } ares_dns_rcode_t;
/*! Data types used */ /*! Data types used */
typedef enum { typedef enum {
ARES_DATATYPE_INADDR = 1, /*!< struct in_addr * type */ ARES_DATATYPE_INADDR = 1, /*!< struct in_addr * type */
ARES_DATATYPE_INADDR6 = 2, /*!< struct ares_in6_addr * type */ ARES_DATATYPE_INADDR6 = 2, /*!< struct ares_in6_addr * type */
ARES_DATATYPE_U8 = 3, /*!< 8bit unsigned integer */ ARES_DATATYPE_U8 = 3, /*!< 8bit unsigned integer */
ARES_DATATYPE_U16 = 4, /*!< 16bit unsigned integer */ ARES_DATATYPE_U16 = 4, /*!< 16bit unsigned integer */
ARES_DATATYPE_U32 = 5, /*!< 32bit unsigned integer */ ARES_DATATYPE_U32 = 5, /*!< 32bit unsigned integer */
ARES_DATATYPE_NAME = 6, /*!< Null-terminated string of a domain name */ ARES_DATATYPE_NAME = 6, /*!< Null-terminated string of a domain name */
ARES_DATATYPE_STR = 7, /*!< Null-terminated string */ ARES_DATATYPE_STR = 7, /*!< Null-terminated string */
ARES_DATATYPE_BIN = 8, /*!< Binary data */ ARES_DATATYPE_BIN = 8, /*!< Binary data */
ARES_DATATYPE_BINP = 9, /*!< Officially defined as binary data, but likely ARES_DATATYPE_BINP = 9, /*!< Officially defined as binary data, but likely
* printable. Guaranteed to have a NULL * printable. Guaranteed to have a NULL
* terminator for convenience (not included in * terminator for convenience (not included in
* length) */ * length) */
ARES_DATATYPE_OPT = 10, /*!< Array of options. 16bit identifier, BIN ARES_DATATYPE_OPT = 10, /*!< Array of options. 16bit identifier, BIN
* data. */ * data. */
ARES_DATATYPE_ABINP = 11 /*!< Array of binary data, likely printable. ARES_DATATYPE_ABINP = 11 /*!< Array of binary data, likely printable.
* Guaranteed to have a NULL terminator for * Guaranteed to have a NULL terminator for
* convenience (not included in length) */ * convenience (not included in length) */
} ares_dns_datatype_t; } ares_dns_datatype_t;
/*! Keys used for all RR Types. We take the record type and multiply by 100 /*! Keys used for all RR Types. We take the record type and multiply by 100
@ -609,8 +609,8 @@ CARES_EXTERN unsigned short
* \param[in] id DNS query id * \param[in] id DNS query id
* \return ARES_TRUE on success, ARES_FALSE on usage error * \return ARES_TRUE on success, ARES_FALSE on usage error
*/ */
CARES_EXTERN ares_bool_t CARES_EXTERN ares_bool_t ares_dns_record_set_id(ares_dns_record_t *dnsrec,
ares_dns_record_set_id(ares_dns_record_t *dnsrec, unsigned short id); unsigned short id);
/*! Get the DNS Record Flags /*! Get the DNS Record Flags
* *
@ -885,10 +885,10 @@ CARES_EXTERN ares_status_t ares_dns_rr_set_bin(ares_dns_rr_t *dns_rr,
* \param[in] len Length of binary data * \param[in] len Length of binary data
* \return ARES_SUCCESS on success * \return ARES_SUCCESS on success
*/ */
CARES_EXTERN ares_status_t ares_dns_rr_add_abin(ares_dns_rr_t *dns_rr, CARES_EXTERN ares_status_t ares_dns_rr_add_abin(ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key, ares_dns_rr_key_t key,
const unsigned char *val, const unsigned char *val,
size_t len); size_t len);
/*! Delete binary array value (ABINP) data for specified resource record and /*! Delete binary array value (ABINP) data for specified resource record and
* key by specified index. Can only be used on keys with datatype * key by specified index. Can only be used on keys with datatype
@ -899,9 +899,9 @@ CARES_EXTERN ares_status_t ares_dns_rr_add_abin(ares_dns_rr_t *dns_rr,
* \param[in] idx Index to delete * \param[in] idx Index to delete
* \return ARES_SUCCESS on success * \return ARES_SUCCESS on success
*/ */
CARES_EXTERN ares_status_t ares_dns_rr_del_abin(ares_dns_rr_t *dns_rr, CARES_EXTERN ares_status_t ares_dns_rr_del_abin(ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key, ares_dns_rr_key_t key,
size_t idx); size_t idx);
/*! Set the option for the RR /*! Set the option for the RR
* *
@ -918,6 +918,17 @@ CARES_EXTERN ares_status_t ares_dns_rr_set_opt(ares_dns_rr_t *dns_rr,
const unsigned char *val, const unsigned char *val,
size_t val_len); 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 /*! Retrieve a pointer to the ipv4 address. Can only be used on keys with
* datatype ARES_DATATYPE_INADDR. * datatype ARES_DATATYPE_INADDR.
* *
@ -1000,7 +1011,7 @@ CARES_EXTERN const unsigned char *
* \return count of values * \return count of values
*/ */
CARES_EXTERN size_t ares_dns_rr_get_abin_cnt(const ares_dns_rr_t *dns_rr, CARES_EXTERN size_t ares_dns_rr_get_abin_cnt(const ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key); ares_dns_rr_key_t key);
/*! Retrieve a pointer to the binary array data from the specified index. Can /*! 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 * only be used on keys with datatype ARES_DATATYPE_ABINP. If ABINP, the data
@ -1014,8 +1025,9 @@ CARES_EXTERN size_t ares_dns_rr_get_abin_cnt(const ares_dns_rr_t *dns_rr,
* \param[out] len Length of binary data returned * \param[out] len Length of binary data returned
* \return pointer binary data or NULL on error * \return pointer binary data or NULL on error
*/ */
CARES_EXTERN const unsigned char *ares_dns_rr_get_abin( CARES_EXTERN const unsigned char *
const ares_dns_rr_t *dns_rr, ares_dns_rr_key_t key, size_t idx, size_t *len); 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. /*! Retrieve the number of options stored for the RR.

View file

@ -31,12 +31,12 @@
#define ARES_COPYRIGHT "2004 - 2024 Daniel Stenberg, <daniel@haxx.se>." #define ARES_COPYRIGHT "2004 - 2024 Daniel Stenberg, <daniel@haxx.se>."
#define ARES_VERSION_MAJOR 1 #define ARES_VERSION_MAJOR 1
#define ARES_VERSION_MINOR 32 #define ARES_VERSION_MINOR 33
#define ARES_VERSION_PATCH 3 #define ARES_VERSION_PATCH 0
#define ARES_VERSION \ #define ARES_VERSION \
((ARES_VERSION_MAJOR << 16) | (ARES_VERSION_MINOR << 8) | \ ((ARES_VERSION_MAJOR << 16) | (ARES_VERSION_MINOR << 8) | \
(ARES_VERSION_PATCH)) (ARES_VERSION_PATCH))
#define ARES_VERSION_STR "1.32.3" #define ARES_VERSION_STR "1.33.0"
#define CARES_HAVE_ARES_LIBRARY_INIT 1 #define CARES_HAVE_ARES_LIBRARY_INIT 1
#define CARES_HAVE_ARES_LIBRARY_CLEANUP 1 #define CARES_HAVE_ARES_LIBRARY_CLEANUP 1

View file

@ -1,26 +0,0 @@
# Copyright (C) The c-ares project and its contributors
# SPDX-License-Identifier: MIT
# -----------------------------------------------
# Detect NMAKE version deducing old MSVC versions
# -----------------------------------------------
!IFNDEF _NMAKE_VER
! MESSAGE Macro _NMAKE_VER not defined.
! MESSAGE Use MSVC's NMAKE to process this makefile.
! ERROR See previous message.
!ENDIF
!IF "$(_NMAKE_VER)" == "6.00.8168.0"
CC_VERS_NUM = 60
!ELSEIF "$(_NMAKE_VER)" == "6.00.9782.0"
CC_VERS_NUM = 60
!ELSEIF "$(_NMAKE_VER)" == "7.00.8882"
CC_VERS_NUM = 70
!ELSEIF "$(_NMAKE_VER)" == "7.00.9466"
CC_VERS_NUM = 70
!ELSEIF "$(_NMAKE_VER)" == "7.00.9955"
CC_VERS_NUM = 70
!ELSE
# Pick an arbitrary bigger number for all later versions
CC_VERS_NUM = 199
!ENDIF

View file

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.5 from Makefile.am. # Makefile.in generated by automake 1.17 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2021 Free Software Foundation, Inc. # Copyright (C) 1994-2024 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -69,6 +69,8 @@ am__make_running_with_option = \
test $$has_opt = yes test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
am__rm_f = rm -f $(am__rm_f_notfound)
am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@ pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@
@ -310,8 +312,10 @@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@ am__include = @am__include@
am__leading_dot = @am__leading_dot@ am__leading_dot = @am__leading_dot@
am__quote = @am__quote@ am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@ am__tar = @am__tar@
am__untar = @am__untar@ am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
ax_pthread_config = @ax_pthread_config@ ax_pthread_config = @ax_pthread_config@
bindir = @bindir@ bindir = @bindir@
build = @build@ build = @build@
@ -585,8 +589,8 @@ mostlyclean-generic:
clean-generic: clean-generic:
distclean-generic: distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -$(am__rm_f) $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic: maintainer-clean-generic:
@echo "This command is intended for maintainers to use" @echo "This command is intended for maintainers to use"
@ -678,3 +682,10 @@ uninstall-am:
# Tell versions [3.59,3.63) of GNU make to not export all variables. # Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded. # Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT: .NOEXPORT:
# Tell GNU make to disable its built-in pattern rules.
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%

File diff suppressed because it is too large Load diff

View file

@ -3,43 +3,16 @@
CSOURCES = ares__addrinfo2hostent.c \ CSOURCES = ares__addrinfo2hostent.c \
ares__addrinfo_localhost.c \ ares__addrinfo_localhost.c \
ares__buf.c \
ares__close_sockets.c \ ares__close_sockets.c \
ares__hosts_file.c \ ares__hosts_file.c \
ares__htable.c \
ares__htable_asvp.c \
ares__htable_strvp.c \
ares__htable_szvp.c \
ares__htable_vpvp.c \
ares__iface_ips.c \
ares__llist.c \
ares__parse_into_addrinfo.c \ ares__parse_into_addrinfo.c \
ares__slist.c \
ares__socket.c \ ares__socket.c \
ares__sortaddrinfo.c \ ares__sortaddrinfo.c \
ares__threads.c \
ares__timeval.c \
ares_android.c \ ares_android.c \
ares_cancel.c \ ares_cancel.c \
ares_cookie.c \
ares_data.c \ ares_data.c \
ares_destroy.c \ ares_destroy.c \
ares_dns_mapping.c \
ares_dns_multistring.c \
ares_dns_name.c \
ares_dns_parse.c \
ares_dns_record.c \
ares_dns_write.c \
ares_event_configchg.c \
ares_event_epoll.c \
ares_event_kqueue.c \
ares_event_poll.c \
ares_event_select.c \
ares_event_thread.c \
ares_event_wake_pipe.c \
ares_event_win32.c \
ares_expand_name.c \
ares_expand_string.c \
ares_fds.c \
ares_free_hostent.c \ ares_free_hostent.c \
ares_free_string.c \ ares_free_string.c \
ares_freeaddrinfo.c \ ares_freeaddrinfo.c \
@ -48,35 +21,17 @@ CSOURCES = ares__addrinfo2hostent.c \
ares_gethostbyaddr.c \ ares_gethostbyaddr.c \
ares_gethostbyname.c \ ares_gethostbyname.c \
ares_getnameinfo.c \ ares_getnameinfo.c \
ares_getsock.c \
ares_init.c \ ares_init.c \
ares_library_init.c \ ares_library_init.c \
ares_math.c \
ares_metrics.c \ ares_metrics.c \
ares_create_query.c \
ares_options.c \ ares_options.c \
ares_parse_a_reply.c \
ares_parse_aaaa_reply.c \
ares_parse_caa_reply.c \
ares_parse_mx_reply.c \
ares_parse_naptr_reply.c \
ares_parse_ns_reply.c \
ares_parse_ptr_reply.c \
ares_parse_soa_reply.c \
ares_parse_srv_reply.c \
ares_parse_txt_reply.c \
ares_parse_uri_reply.c \
ares_platform.c \ ares_platform.c \
ares_process.c \ ares_process.c \
ares_qcache.c \ ares_qcache.c \
ares_query.c \ ares_query.c \
ares_rand.c \
ares_search.c \ ares_search.c \
ares_send.c \ ares_send.c \
ares_strcasecmp.c \
ares_str.c \
ares_strerror.c \ ares_strerror.c \
ares_strsplit.c \
ares_sysconfig.c \ ares_sysconfig.c \
ares_sysconfig_files.c \ ares_sysconfig_files.c \
ares_sysconfig_mac.c \ ares_sysconfig_mac.c \
@ -86,32 +41,80 @@ CSOURCES = ares__addrinfo2hostent.c \
ares_version.c \ ares_version.c \
inet_net_pton.c \ inet_net_pton.c \
inet_ntop.c \ inet_ntop.c \
windows_port.c windows_port.c \
dsa/ares__array.c \
dsa/ares__htable.c \
dsa/ares__htable_asvp.c \
dsa/ares__htable_strvp.c \
dsa/ares__htable_szvp.c \
dsa/ares__htable_vpvp.c \
dsa/ares__llist.c \
dsa/ares__slist.c \
event/ares_event_configchg.c \
event/ares_event_epoll.c \
event/ares_event_kqueue.c \
event/ares_event_poll.c \
event/ares_event_select.c \
event/ares_event_thread.c \
event/ares_event_wake_pipe.c \
event/ares_event_win32.c \
legacy/ares_create_query.c \
legacy/ares_expand_name.c \
legacy/ares_expand_string.c \
legacy/ares_fds.c \
legacy/ares_getsock.c \
legacy/ares_parse_a_reply.c \
legacy/ares_parse_aaaa_reply.c \
legacy/ares_parse_caa_reply.c \
legacy/ares_parse_mx_reply.c \
legacy/ares_parse_naptr_reply.c \
legacy/ares_parse_ns_reply.c \
legacy/ares_parse_ptr_reply.c \
legacy/ares_parse_soa_reply.c \
legacy/ares_parse_srv_reply.c \
legacy/ares_parse_txt_reply.c \
legacy/ares_parse_uri_reply.c \
record/ares_dns_mapping.c \
record/ares_dns_multistring.c \
record/ares_dns_name.c \
record/ares_dns_parse.c \
record/ares_dns_record.c \
record/ares_dns_write.c \
str/ares__buf.c \
str/ares_strcasecmp.c \
str/ares_str.c \
str/ares_strsplit.c \
util/ares__iface_ips.c \
util/ares__threads.c \
util/ares__timeval.c \
util/ares_math.c \
util/ares_rand.c
HHEADERS = ares__buf.h \ HHEADERS = ares_android.h \
ares__htable.h \
ares__htable_asvp.h \
ares__htable_strvp.h \
ares__htable_szvp.h \
ares__htable_vpvp.h \
ares__iface_ips.h \
ares__llist.h \
ares__slist.h \
ares__threads.h \
ares_android.h \
ares_data.h \ ares_data.h \
ares_dns_multistring.h \
ares_dns_private.h \
ares_event.h \
ares_event_win32.h \
ares_getenv.h \ ares_getenv.h \
ares_inet_net_pton.h \ ares_inet_net_pton.h \
ares_ipv6.h \ ares_ipv6.h \
ares_platform.h \ ares_platform.h \
ares_private.h \ ares_private.h \
ares_strcasecmp.h \
ares_str.h \
ares_strsplit.h \
ares_setup.h \ ares_setup.h \
dsa/ares__array.h \
dsa/ares__htable.h \
dsa/ares__htable_asvp.h \
dsa/ares__htable_strvp.h \
dsa/ares__htable_szvp.h \
dsa/ares__htable_vpvp.h \
dsa/ares__llist.h \
dsa/ares__slist.h \
event/ares_event.h \
event/ares_event_win32.h \
record/ares_dns_multistring.h \
record/ares_dns_private.h \
str/ares__buf.h \
str/ares_strcasecmp.h \
str/ares_str.h \
str/ares_strsplit.h \
util/ares__iface_ips.h \
util/ares__threads.h \
thirdparty/apple/dnsinfo.h thirdparty/apple/dnsinfo.h

View file

@ -161,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); (*host)->h_addr_list[i] = addrs + (i * (size_t)(*host)->h_length);
if (family == AF_INET6) { if (family == AF_INET6) {
memcpy( memcpy((*host)->h_addr_list[i],
(*host)->h_addr_list[i], &(CARES_INADDR_CAST(const struct sockaddr_in6 *, next->ai_addr)
&(CARES_INADDR_CAST(const struct sockaddr_in6 *, next->ai_addr)->sin6_addr), ->sin6_addr),
(size_t)(*host)->h_length); (size_t)(*host)->h_length);
} }
if (family == AF_INET) { if (family == AF_INET) {
memcpy( memcpy((*host)->h_addr_list[i],
(*host)->h_addr_list[i], &(CARES_INADDR_CAST(const struct sockaddr_in *, next->ai_addr)
&(CARES_INADDR_CAST(const struct sockaddr_in *, next->ai_addr)->sin_addr), ->sin_addr),
(size_t)(*host)->h_length); (size_t)(*host)->h_length);
} }
++i; ++i;
} }
@ -252,20 +252,20 @@ ares_status_t ares__addrinfo2addrttl(const struct ares_addrinfo *ai, int family,
addr6ttls[*naddrttls].ttl = next->ai_ttl; addr6ttls[*naddrttls].ttl = next->ai_ttl;
} }
memcpy( memcpy(&addr6ttls[*naddrttls].ip6addr,
&addr6ttls[*naddrttls].ip6addr, &(CARES_INADDR_CAST(const struct sockaddr_in6 *, next->ai_addr)
&(CARES_INADDR_CAST(const struct sockaddr_in6 *, next->ai_addr)->sin6_addr), ->sin6_addr),
sizeof(struct ares_in6_addr)); sizeof(struct ares_in6_addr));
} else { } else {
if (next->ai_ttl > cname_ttl) { if (next->ai_ttl > cname_ttl) {
addrttls[*naddrttls].ttl = cname_ttl; addrttls[*naddrttls].ttl = cname_ttl;
} else { } else {
addrttls[*naddrttls].ttl = next->ai_ttl; addrttls[*naddrttls].ttl = next->ai_ttl;
} }
memcpy( memcpy(&addrttls[*naddrttls].ipaddr,
&addrttls[*naddrttls].ipaddr, &(CARES_INADDR_CAST(const struct sockaddr_in *, next->ai_addr)
&(CARES_INADDR_CAST(const struct sockaddr_in *, next->ai_addr)->sin_addr), ->sin_addr),
sizeof(struct in_addr)); sizeof(struct in_addr));
} }
(*naddrttls)++; (*naddrttls)++;
} }

View file

@ -28,31 +28,30 @@
#include "ares_private.h" #include "ares_private.h"
#include <assert.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) ares_status_t requeue_status)
{ {
struct query *query; ares_query_t *query;
ares_timeval_t now; ares_timeval_t now;
ares__tvnow(&now); ares__tvnow(&now);
while ((query = ares__llist_first_val(conn->queries_to_conn)) != NULL) { while ((query = ares__llist_first_val(conn->queries_to_conn)) != NULL) {
ares__requeue_query(query, &now, requeue_status); 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)
ares_status_t requeue_status)
{ {
struct server_state *server = conn->server; ares_server_t *server = conn->server;
ares_channel_t *channel = server->channel; ares_channel_t *channel = server->channel;
/* Unlink */ /* Unlink */
ares__llist_node_claim( ares__llist_node_claim(
ares__htable_asvp_get_direct(channel->connnode_by_socket, conn->fd)); ares__htable_asvp_get_direct(channel->connnode_by_socket, conn->fd));
ares__htable_asvp_remove(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. */ /* Reset any existing input and output buffer. */
ares__buf_consume(server->tcp_parser, ares__buf_len(server->tcp_parser)); ares__buf_consume(server->tcp_parser, ares__buf_len(server->tcp_parser));
ares__buf_consume(server->tcp_send, ares__buf_len(server->tcp_send)); ares__buf_consume(server->tcp_send, ares__buf_len(server->tcp_send));
@ -70,12 +69,12 @@ void ares__close_connection(struct server_connection *conn,
ares_free(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; ares__llist_node_t *node;
while ((node = ares__llist_node_first(server->connections)) != NULL) { while ((node = ares__llist_node_first(server->connections)) != NULL) {
struct server_connection *conn = ares__llist_node_val(node); ares_conn_t *conn = ares__llist_node_val(node);
ares__close_connection(conn, ARES_SUCCESS); ares__close_connection(conn, ARES_SUCCESS);
} }
} }
@ -91,17 +90,16 @@ void ares__check_cleanup_conns(const ares_channel_t *channel)
/* Iterate across each server */ /* Iterate across each server */
for (snode = ares__slist_node_first(channel->servers); snode != NULL; for (snode = ares__slist_node_first(channel->servers); snode != NULL;
snode = ares__slist_node_next(snode)) { snode = ares__slist_node_next(snode)) {
ares_server_t *server = ares__slist_node_val(snode);
struct server_state *server = ares__slist_node_val(snode); ares__llist_node_t *cnode;
ares__llist_node_t *cnode;
/* Iterate across each connection */ /* Iterate across each connection */
cnode = ares__llist_node_first(server->connections); cnode = ares__llist_node_first(server->connections);
while (cnode != NULL) { while (cnode != NULL) {
ares__llist_node_t *next = ares__llist_node_next(cnode); ares__llist_node_t *next = ares__llist_node_next(cnode);
struct server_connection *conn = ares__llist_node_val(cnode); ares_conn_t *conn = ares__llist_node_val(cnode);
ares_bool_t do_cleanup = ARES_FALSE; ares_bool_t do_cleanup = ARES_FALSE;
cnode = next; cnode = next;
/* Has connections, not eligible */ /* Has connections, not eligible */
if (ares__llist_len(conn->queries_to_conn)) { if (ares__llist_len(conn->queries_to_conn)) {
@ -122,7 +120,7 @@ void ares__check_cleanup_conns(const ares_channel_t *channel)
} }
/* If the udp connection hit its max queries, always close it */ /* If the udp connection hit its max queries, always close it */
if (!conn->is_tcp && channel->udp_max_queries > 0 && if (!(conn->flags & ARES_CONN_FLAG_TCP) && channel->udp_max_queries > 0 &&
conn->total_queries >= channel->udp_max_queries) { conn->total_queries >= channel->udp_max_queries) {
do_cleanup = ARES_TRUE; do_cleanup = ARES_TRUE;
} }

View file

@ -56,6 +56,77 @@
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.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 TCP_FASTOPEN_CONNECT
#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, ares_ssize_t ares__socket_recvfrom(ares_channel_t *channel, ares_socket_t s,
void *data, size_t data_len, int flags, void *data, size_t data_len, int flags,
@ -71,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, return (ares_ssize_t)recvfrom(s, data, (RECVFROM_TYPE_ARG3)data_len, flags,
from, from_len); from, from_len);
#else #else
return sread(s, data, data_len); return ares__socket_recv(channel, s, data, data_len);
#endif #endif
} }
ares_ssize_t ares__socket_recv(ares_channel_t *channel, ares_socket_t s, /* Use like:
void *data, size_t data_len) * 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) { const ares_server_t *server = conn->server;
return channel->sock_funcs->arecvfrom(s, data, data_len, 0, 0, 0, unsigned short port =
channel->sock_func_cb_data); 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 ARES_EBADFAMILY;
return sread(s, data, data_len); }
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);
} }
/* /*
@ -159,7 +352,7 @@ static void set_ipv6_v6only(ares_socket_t sockfd, int on)
# define set_ipv6_v6only(s, v) # define set_ipv6_v6only(s, v)
#endif #endif
static int configure_socket(ares_socket_t s, struct server_state *server) static ares_status_t configure_socket(ares_conn_t *conn)
{ {
union { union {
struct sockaddr sa; struct sockaddr sa;
@ -168,19 +361,20 @@ static int configure_socket(ares_socket_t s, struct server_state *server)
} local; } local;
ares_socklen_t bindlen = 0; ares_socklen_t bindlen = 0;
ares_server_t *server = conn->server;
ares_channel_t *channel = server->channel; ares_channel_t *channel = server->channel;
/* do not set options for user-managed sockets */ /* do not set options for user-managed sockets */
if (channel->sock_funcs && channel->sock_funcs->asocket) { 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) #if defined(FD_CLOEXEC) && !defined(MSDOS)
/* Configure the socket fd as close-on-exec. */ /* Configure the socket fd as close-on-exec. */
if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) { if (fcntl(conn->fd, F_SETFD, FD_CLOEXEC) != 0) {
return -1; /* LCOV_EXCL_LINE */ return ARES_ECONNREFUSED; /* LCOV_EXCL_LINE */
} }
#endif #endif
@ -188,31 +382,32 @@ static int configure_socket(ares_socket_t s, struct server_state *server)
#if defined(SO_NOSIGPIPE) #if defined(SO_NOSIGPIPE)
{ {
int opt = 1; int opt = 1;
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt, sizeof(opt)); (void)setsockopt(conn->fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt,
sizeof(opt));
} }
#endif #endif
/* Set the socket's send and receive buffer sizes. */ /* Set the socket's send and receive buffer sizes. */
if ((channel->socket_send_buffer_size > 0) && if (channel->socket_send_buffer_size > 0 &&
setsockopt(s, SOL_SOCKET, SO_SNDBUF, setsockopt(conn->fd, SOL_SOCKET, SO_SNDBUF,
(void *)&channel->socket_send_buffer_size, (void *)&channel->socket_send_buffer_size,
sizeof(channel->socket_send_buffer_size)) == -1) { sizeof(channel->socket_send_buffer_size)) != 0) {
return -1; /* LCOV_EXCL_LINE: UntestablePath */ return ARES_ECONNREFUSED; /* LCOV_EXCL_LINE: UntestablePath */
} }
if ((channel->socket_receive_buffer_size > 0) && if (channel->socket_receive_buffer_size > 0 &&
setsockopt(s, SOL_SOCKET, SO_RCVBUF, setsockopt(conn->fd, SOL_SOCKET, SO_RCVBUF,
(void *)&channel->socket_receive_buffer_size, (void *)&channel->socket_receive_buffer_size,
sizeof(channel->socket_receive_buffer_size)) == -1) { sizeof(channel->socket_receive_buffer_size)) != 0) {
return -1; /* LCOV_EXCL_LINE: UntestablePath */ return ARES_ECONNREFUSED; /* LCOV_EXCL_LINE: UntestablePath */
} }
#ifdef SO_BINDTODEVICE #ifdef SO_BINDTODEVICE
if (channel->local_dev_name[0] && if (ares_strlen(channel->local_dev_name)) {
setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, channel->local_dev_name, /* Only root can do this, and usually not fatal if it doesn't work, so
sizeof(channel->local_dev_name))) { * just continue on. */
/* Only root can do this, and usually not fatal if it doesn't work, so */ (void)setsockopt(conn->fd, SOL_SOCKET, SO_BINDTODEVICE,
/* just continue on. */ channel->local_dev_name, sizeof(channel->local_dev_name));
} }
#endif #endif
@ -232,134 +427,217 @@ static int configure_socket(ares_socket_t s, struct server_state *server)
bindlen = sizeof(local.sa6); bindlen = sizeof(local.sa6);
} }
if (bindlen && bind(s, &local.sa, bindlen) < 0) { if (bindlen && bind(conn->fd, &local.sa, bindlen) < 0) {
return -1; return ARES_ECONNREFUSED;
} }
if (server->addr.family == AF_INET6) { if (server->addr.family == AF_INET6) {
set_ipv6_v6only(s, 0); set_ipv6_v6only(conn->fd, 0);
} }
return 0; if (conn->flags & ARES_CONN_FLAG_TCP) {
} int opt = 1;
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;
}
/* Configure it. */
if (configure_socket(s, server) < 0) {
ares__close_socket(channel, s);
return ARES_ECONNREFUSED;
}
#ifdef TCP_NODELAY #ifdef TCP_NODELAY
if (is_tcp) {
/* /*
* Disable the Nagle algorithm (only relevant for TCP sockets, and thus not * Disable the Nagle algorithm (only relevant for TCP sockets, and thus not
* in configure_socket). In general, in DNS lookups we're pretty much * 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, * interested in firing off a single request and then waiting for a reply,
* so batching isn't very interesting. * so batching isn't very interesting.
*/ */
opt = 1; if (setsockopt(conn->fd, IPPROTO_TCP, TCP_NODELAY, (void *)&opt,
if ((!channel->sock_funcs || !channel->sock_funcs->asocket) && sizeof(opt)) != 0) {
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *)&opt, sizeof(opt)) == return ARES_ECONNREFUSED;
-1) {
ares__close_socket(channel, s); /* LCOV_EXCL_LINE: UntestablePath */
return ARES_ECONNREFUSED; /* LCOV_EXCL_LINE: UntestablePath */
} }
}
#endif #endif
if (channel->sock_config_cb) { #if defined(TFO_CLIENT_SOCKOPT)
int err = channel->sock_config_cb(s, type, channel->sock_config_cb_data); if (conn->flags & ARES_CONN_FLAG_TFO &&
if (err < 0) { setsockopt(conn->fd, IPPROTO_TCP, TFO_CLIENT_SOCKOPT, (void *)&opt,
ares__close_socket(channel, s); sizeof(opt)) != 0) {
return ARES_ECONNREFUSED; /* Disable TFO if flag can't be set. */
conn->flags &= ~((unsigned int)ARES_CONN_FLAG_TFO);
} }
#endif
} }
/* Connect to the server. */ return ARES_SUCCESS;
if (ares__connect_socket(channel, s, sa, salen) == -1) { }
int err = SOCKERRNO;
if (err != EINPROGRESS && err != EWOULDBLOCK) { ares_bool_t ares_sockaddr_to_ares_addr(struct ares_addr *ares_addr,
ares__close_socket(channel, s); unsigned short *port,
return ARES_ECONNREFUSED; 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) { if (sockaddr->sa_family == AF_INET6) {
int err = channel->sock_create_cb(s, type, channel->sock_create_cb_data); /* NOTE: memcpy sockaddr_in6 due to alignment issues found by UBSAN due to
if (err < 0) { * dnsinfo packing on MacOS */
ares__close_socket(channel, s); struct sockaddr_in6 sockaddr_in6;
return ARES_ECONNREFUSED; 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)); conn = ares_malloc(sizeof(*conn));
if (conn == NULL) { if (conn == NULL) {
ares__close_socket(channel, s); /* LCOV_EXCL_LINE: OutOfMemory */ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
} }
memset(conn, 0, sizeof(*conn)); memset(conn, 0, sizeof(*conn));
conn->fd = s; conn->fd = ARES_SOCKET_BAD;
conn->server = server; conn->server = server;
conn->queries_to_conn = ares__llist_create(NULL); 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) { if (conn->queries_to_conn == NULL) {
/* LCOV_EXCL_START: OutOfMemory */ /* LCOV_EXCL_START: OutOfMemory */
ares__close_socket(channel, s); status = ARES_ENOMEM;
ares_free(conn); goto done;
return ARES_ENOMEM;
/* LCOV_EXCL_STOP */ /* 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 /* TCP connections are thrown to the end as we don't spawn multiple TCP
* connections. UDP connections are put on front where the newest connection * connections. UDP connections are put on front where the newest connection
* can be quickly pulled */ * can be quickly pulled */
@ -370,32 +648,36 @@ ares_status_t ares__open_connection(ares_channel_t *channel,
} }
if (node == NULL) { if (node == NULL) {
/* LCOV_EXCL_START: OutOfMemory */ /* LCOV_EXCL_START: OutOfMemory */
ares__close_socket(channel, s); status = ARES_ENOMEM;
ares__llist_destroy(conn->queries_to_conn); goto done;
ares_free(conn);
return ARES_ENOMEM;
/* LCOV_EXCL_STOP */ /* LCOV_EXCL_STOP */
} }
/* Register globally to quickly map event on file descriptor to connection /* Register globally to quickly map event on file descriptor to connection
* node object */ * node object */
if (!ares__htable_asvp_insert(channel->connnode_by_socket, s, node)) { if (!ares__htable_asvp_insert(channel->connnode_by_socket, conn->fd, node)) {
/* LCOV_EXCL_START: OutOfMemory */ /* LCOV_EXCL_START: OutOfMemory */
ares__close_socket(channel, s); status = ARES_ENOMEM;
ares__llist_destroy(conn->queries_to_conn); goto done;
ares__llist_node_claim(node);
ares_free(conn);
return ARES_ENOMEM;
/* LCOV_EXCL_STOP */ /* LCOV_EXCL_STOP */
} }
SOCK_STATE_CALLBACK(channel, s, 1, 0); SOCK_STATE_CALLBACK(channel, conn->fd, 1, is_tcp ? 1 : 0);
if (is_tcp) { if (is_tcp) {
server->tcp_conn = conn; 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, ares_socket_t ares__open_socket(ares_channel_t *channel, int af, int type,
@ -409,15 +691,31 @@ ares_socket_t ares__open_socket(ares_channel_t *channel, int af, int type,
return socket(af, type, protocol); return socket(af, type, protocol);
} }
int ares__connect_socket(ares_channel_t *channel, ares_socket_t sockfd, ares_status_t ares__connect_socket(ares_channel_t *channel,
const struct sockaddr *addr, ares_socklen_t addrlen) ares_socket_t sockfd,
const struct sockaddr *addr,
ares_socklen_t addrlen)
{ {
if (channel->sock_funcs && channel->sock_funcs->aconnect) { int rv;
return channel->sock_funcs->aconnect(sockfd, addr, addrlen, int err;
channel->sock_func_cb_data);
}
return connect(sockfd, addr, addrlen); 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;
}
} while (rv == -1 && err == EINTR);
return ARES_SUCCESS;
} }
void ares__close_socket(ares_channel_t *channel, ares_socket_t s) void ares__close_socket(ares_channel_t *channel, ares_socket_t s)
@ -433,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, void ares_set_socket_callback(ares_channel_t *channel,
ares_sock_create_callback cb, void *data) ares_sock_create_callback cb, void *data)
{ {

View file

@ -51,7 +51,6 @@
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
struct addrinfo_sort_elem { struct addrinfo_sort_elem {
struct ares_addrinfo_node *ai; struct ares_addrinfo_node *ai;
ares_bool_t has_src_addr; ares_bool_t has_src_addr;
@ -347,7 +346,6 @@ static int find_src_addr(ares_channel_t *channel, const struct sockaddr *addr,
struct sockaddr *src_addr) struct sockaddr *src_addr)
{ {
ares_socket_t sock; ares_socket_t sock;
int ret;
ares_socklen_t len; ares_socklen_t len;
switch (addr->sa_family) { switch (addr->sa_family) {
@ -364,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); sock = ares__open_socket(channel, addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
if (sock == ARES_SOCKET_BAD) { if (sock == ARES_SOCKET_BAD) {
if (errno == EAFNOSUPPORT) { if (SOCKERRNO == EAFNOSUPPORT) {
return 0; return 0;
} else { } else {
return -1; return -1;
} }
} }
do { if (ares__connect_socket(channel, sock, addr, len) != ARES_SUCCESS) {
ret = ares__connect_socket(channel, sock, addr, len);
} while (ret == -1 && errno == EINTR);
if (ret == -1) {
ares__close_socket(channel, sock); ares__close_socket(channel, sock);
return 0; return 0;
} }

View file

@ -26,6 +26,7 @@
#if defined(ANDROID) || defined(__ANDROID__) #if defined(ANDROID) || defined(__ANDROID__)
# include "ares_private.h" # include "ares_private.h"
# include <jni.h> # include <jni.h>
# include <sys/prctl.h>
static JavaVM *android_jvm = NULL; static JavaVM *android_jvm = NULL;
static jobject android_connectivity_manager = NULL; static jobject android_connectivity_manager = NULL;
@ -80,6 +81,23 @@ static jmethodID jni_get_method_id(JNIEnv *env, jclass cls,
return mid; 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) void ares_library_init_jvm(JavaVM *jvm)
{ {
android_jvm = jvm; android_jvm = jvm;
@ -100,7 +118,7 @@ int ares_library_init_android(jobject connectivity_manager)
res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6); res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6);
if (res == JNI_EDETACHED) { if (res == JNI_EDETACHED) {
env = NULL; env = NULL;
res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL); res = jvm_attach(&env);
need_detatch = 1; need_detatch = 1;
} }
if (res != JNI_OK || env == NULL) { if (res != JNI_OK || env == NULL) {
@ -233,7 +251,7 @@ void ares_library_cleanup_android(void)
res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6); res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6);
if (res == JNI_EDETACHED) { if (res == JNI_EDETACHED) {
env = NULL; env = NULL;
res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL); res = jvm_attach(&env);
need_detatch = 1; need_detatch = 1;
} }
if (res != JNI_OK || env == NULL) { if (res != JNI_OK || env == NULL) {
@ -285,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); res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6);
if (res == JNI_EDETACHED) { if (res == JNI_EDETACHED) {
env = NULL; env = NULL;
res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL); res = jvm_attach(&env);
need_detatch = 1; need_detatch = 1;
} }
if (res != JNI_OK || env == NULL) { if (res != JNI_OK || env == NULL) {
@ -403,7 +421,7 @@ char *ares_get_android_search_domains_list(void)
res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6); res = (*android_jvm)->GetEnv(android_jvm, (void **)&env, JNI_VERSION_1_6);
if (res == JNI_EDETACHED) { if (res == JNI_EDETACHED) {
env = NULL; env = NULL;
res = (*android_jvm)->AttachCurrentThread(android_jvm, &env, NULL); res = jvm_attach(&env);
need_detatch = 1; need_detatch = 1;
} }
if (res != JNI_OK || env == NULL) { if (res != JNI_OK || env == NULL) {

View file

@ -59,7 +59,7 @@ void ares_cancel(ares_channel_t *channel)
node = ares__llist_node_first(list_copy); node = ares__llist_node_first(list_copy);
while (node != NULL) { while (node != NULL) {
struct query *query; ares_query_t *query;
/* Cache next since this node is being deleted */ /* Cache next since this node is being deleted */
next = ares__llist_node_next(node); next = ares__llist_node_next(node);

View file

@ -67,6 +67,9 @@
/* Define to 1 if you have the connect function. */ /* Define to 1 if you have the connect function. */
#cmakedefine HAVE_CONNECT 1 #cmakedefine HAVE_CONNECT 1
/* Define to 1 if you have the connectx function. */
#cmakedefine HAVE_CONNECTX 1
/* define if the compiler supports basic C++11 syntax */ /* define if the compiler supports basic C++11 syntax */
#cmakedefine HAVE_CXX11 1 #cmakedefine HAVE_CXX11 1
@ -145,6 +148,12 @@
/* Define to 1 if you have the `ConvertInterfaceLuidToNameA' function. */ /* Define to 1 if you have the `ConvertInterfaceLuidToNameA' function. */
#cmakedefine HAVE_CONVERTINTERFACELUIDTONAMEA 1 #cmakedefine HAVE_CONVERTINTERFACELUIDTONAMEA 1
/* Define to 1 if you have the `NotifyIpInterfaceChange' function. */
#cmakedefine HAVE_NOTIFYIPINTERFACECHANGE 1
/* Define to 1 if you have the `RegisterWaitForSingleObject' function. */
#cmakedefine HAVE_REGISTERWAITFORSINGLEOBJECT 1
/* Define to 1 if you have a IPv6 capable working inet_net_pton function. */ /* Define to 1 if you have a IPv6 capable working inet_net_pton function. */
#cmakedefine HAVE_INET_NET_PTON 1 #cmakedefine HAVE_INET_NET_PTON 1

View file

@ -75,6 +75,9 @@
/* Define to 1 if you have `connect` */ /* Define to 1 if you have `connect` */
#undef HAVE_CONNECT #undef HAVE_CONNECT
/* Define to 1 if you have `connectx` */
#undef HAVE_CONNECTX
/* Define to 1 if you have `ConvertInterfaceIndexToLuid` */ /* Define to 1 if you have `ConvertInterfaceIndexToLuid` */
#undef HAVE_CONVERTINTERFACEINDEXTOLUID #undef HAVE_CONVERTINTERFACEINDEXTOLUID
@ -201,6 +204,9 @@
/* Define to 1 if you have the <net/if.h> header file. */ /* Define to 1 if you have the <net/if.h> header file. */
#undef HAVE_NET_IF_H #undef HAVE_NET_IF_H
/* Define to 1 if you have `NotifyIpInterfaceChange` */
#undef HAVE_NOTIFYIPINTERFACECHANGE
/* Define to 1 if you have the <ntdef.h> header file. */ /* Define to 1 if you have the <ntdef.h> header file. */
#undef HAVE_NTDEF_H #undef HAVE_NTDEF_H
@ -237,6 +243,9 @@
/* Define to 1 if you have `recvfrom` */ /* Define to 1 if you have `recvfrom` */
#undef HAVE_RECVFROM #undef HAVE_RECVFROM
/* Define to 1 if you have `RegisterWaitForSingleObject` */
#undef HAVE_REGISTERWAITFORSINGLEOBJECT
/* Define to 1 if you have `send` */ /* Define to 1 if you have `send` */
#undef HAVE_SEND #undef HAVE_SEND

459
deps/cares/src/lib/ares_cookie.c vendored Normal file
View file

@ -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;
}

View file

@ -26,7 +26,7 @@
*/ */
#include "ares_private.h" #include "ares_private.h"
#include "ares_event.h" #include "event/ares_event.h"
#include <assert.h> #include <assert.h>
void ares_destroy(ares_channel_t *channel) void ares_destroy(ares_channel_t *channel)
@ -73,7 +73,7 @@ void ares_destroy(ares_channel_t *channel)
node = ares__llist_node_first(channel->all_queries); node = ares__llist_node_first(channel->all_queries);
while (node != NULL) { while (node != NULL) {
ares__llist_node_t *next = ares__llist_node_next(node); 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->node_all_queries = NULL;
query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL); query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL);
@ -134,7 +134,7 @@ void ares_destroy(ares_channel_t *channel)
ares_free(channel); ares_free(channel);
} }
void ares__destroy_server(struct server_state *server) void ares__destroy_server(ares_server_t *server)
{ {
if (server == NULL) { if (server == NULL) {
return; /* LCOV_EXCL_LINE: DefensiveCoding */ return; /* LCOV_EXCL_LINE: DefensiveCoding */
@ -152,7 +152,7 @@ void ares__destroy_servers_state(ares_channel_t *channel)
ares__slist_node_t *node; ares__slist_node_t *node;
while ((node = ares__slist_node_first(channel->servers)) != NULL) { 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); ares__destroy_server(server);
} }

View file

@ -252,7 +252,7 @@ static ares_bool_t fake_addrinfo(const char *name, unsigned short port,
ares_bool_t valid = ARES_TRUE; ares_bool_t valid = ARES_TRUE;
const char *p; const char *p;
for (p = name; *p; p++) { for (p = name; *p; p++) {
if (!isdigit(*p) && *p != '.') { if (!ares__isdigit(*p) && *p != '.') {
valid = ARES_FALSE; valid = ARES_FALSE;
break; break;
} else if (*p == '.') { } else if (*p == '.') {
@ -469,7 +469,7 @@ static void terminate_retries(const struct host_query *hquery,
unsigned short term_qid = unsigned short term_qid =
(qid == hquery->qid_a) ? hquery->qid_aaaa : hquery->qid_a; (qid == hquery->qid_a) ? hquery->qid_aaaa : hquery->qid_a;
const ares_channel_t *channel = hquery->channel; const ares_channel_t *channel = hquery->channel;
struct query *query = NULL; ares_query_t *query = NULL;
/* No other outstanding queries, nothing to do */ /* No other outstanding queries, nothing to do */
if (!hquery->remaining) { if (!hquery->remaining) {

View file

@ -63,7 +63,7 @@
#include "ares_inet_net_pton.h" #include "ares_inet_net_pton.h"
#include "ares_platform.h" #include "ares_platform.h"
#include "ares_event.h" #include "event/ares_event.h"
int ares_init(ares_channel_t **channelptr) int ares_init(ares_channel_t **channelptr)
{ {
@ -72,8 +72,8 @@ int ares_init(ares_channel_t **channelptr)
static int ares_query_timeout_cmp_cb(const void *arg1, const void *arg2) static int ares_query_timeout_cmp_cb(const void *arg1, const void *arg2)
{ {
const struct query *q1 = arg1; const ares_query_t *q1 = arg1;
const struct query *q2 = arg2; const ares_query_t *q2 = arg2;
if (q1->timeout.sec > q2->timeout.sec) { if (q1->timeout.sec > q2->timeout.sec) {
return 1; return 1;
@ -94,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) static int server_sort_cb(const void *data1, const void *data2)
{ {
const struct server_state *s1 = data1; const ares_server_t *s1 = data1;
const struct server_state *s2 = data2; const ares_server_t *s2 = data2;
if (s1->consec_failures < s2->consec_failures) { if (s1->consec_failures < s2->consec_failures) {
return -1; return -1;

View file

@ -145,7 +145,7 @@ static time_t ares_metric_timestamp(ares_server_bucket_t bucket,
return (time_t)(now->sec / divisor); return (time_t)(now->sec / divisor);
} }
void ares_metrics_record(const struct query *query, struct server_state *server, void ares_metrics_record(const ares_query_t *query, ares_server_t *server,
ares_status_t status, const ares_dns_record_t *dnsrec) ares_status_t status, const ares_dns_record_t *dnsrec)
{ {
ares_timeval_t now; ares_timeval_t now;
@ -205,8 +205,8 @@ void ares_metrics_record(const struct query *query, struct server_state *server,
} }
} }
size_t ares_metrics_server_timeout(const struct server_state *server, size_t ares_metrics_server_timeout(const ares_server_t *server,
const ares_timeval_t *now) const ares_timeval_t *now)
{ {
const ares_channel_t *channel = server->channel; const ares_channel_t *channel = server->channel;
ares_server_bucket_t i; ares_server_bucket_t i;
@ -252,7 +252,7 @@ size_t ares_metrics_server_timeout(const struct server_state *server,
} }
/* don't go above upper bounds */ /* don't go above upper bounds */
max_timeout_ms = channel->maxtimeout?channel->maxtimeout:MAX_TIMEOUT_MS; max_timeout_ms = channel->maxtimeout ? channel->maxtimeout : MAX_TIMEOUT_MS;
if (timeout_ms > max_timeout_ms) { if (timeout_ms > max_timeout_ms) {
timeout_ms = max_timeout_ms; timeout_ms = max_timeout_ms;
} }

View file

@ -66,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; for (snode = ares__slist_node_first(channel->servers); snode != NULL;
snode = ares__slist_node_next(snode)) { 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) { if (server->addr.family != AF_INET) {
continue; continue;

View file

@ -105,33 +105,34 @@ W32_FUNC const char *_w32_GetHostsFile(void);
struct ares_rand_state; struct ares_rand_state;
typedef struct ares_rand_state ares_rand_state; typedef struct ares_rand_state ares_rand_state;
#include "ares__llist.h" #include "dsa/ares__array.h"
#include "ares__slist.h" #include "dsa/ares__llist.h"
#include "ares__htable_strvp.h" #include "dsa/ares__slist.h"
#include "ares__htable_szvp.h" #include "dsa/ares__htable_strvp.h"
#include "ares__htable_asvp.h" #include "dsa/ares__htable_szvp.h"
#include "ares__htable_vpvp.h" #include "dsa/ares__htable_asvp.h"
#include "ares_dns_multistring.h" #include "dsa/ares__htable_vpvp.h"
#include "ares__buf.h" #include "record/ares_dns_multistring.h"
#include "ares_dns_private.h" #include "str/ares__buf.h"
#include "ares__iface_ips.h" #include "record/ares_dns_private.h"
#include "ares__threads.h" #include "util/ares__iface_ips.h"
#include "util/ares__threads.h"
#ifndef HAVE_GETENV #ifndef HAVE_GETENV
# include "ares_getenv.h" # include "ares_getenv.h"
# define getenv(ptr) ares_getenv(ptr) # define getenv(ptr) ares_getenv(ptr)
#endif #endif
#include "ares_str.h" #include "str/ares_str.h"
#include "ares_strsplit.h" #include "str/ares_strsplit.h"
#ifndef HAVE_STRCASECMP #ifndef HAVE_STRCASECMP
# include "ares_strcasecmp.h" # include "str/ares_strcasecmp.h"
# define strcasecmp(p1, p2) ares_strcasecmp(p1, p2) # define strcasecmp(p1, p2) ares_strcasecmp(p1, p2)
#endif #endif
#ifndef HAVE_STRNCASECMP #ifndef HAVE_STRNCASECMP
# include "ares_strcasecmp.h" # include "str/ares_strcasecmp.h"
# define strncasecmp(p1, p2, n) ares_strncasecmp(p1, p2, n) # define strncasecmp(p1, p2, n) ares_strncasecmp(p1, p2, n)
#endif #endif
@ -150,18 +151,36 @@ typedef struct ares_rand_state ares_rand_state;
#define DEFAULT_SERVER_RETRY_CHANCE 10 #define DEFAULT_SERVER_RETRY_CHANCE 10
#define DEFAULT_SERVER_RETRY_DELAY 5000 #define DEFAULT_SERVER_RETRY_DELAY 5000
struct query; struct ares_query;
typedef struct ares_query ares_query_t;
struct server_state; struct ares_server;
typedef struct ares_server ares_server_t;
struct server_connection { struct ares_conn;
struct server_state *server; typedef struct ares_conn ares_conn_t;
ares_socket_t fd;
ares_bool_t is_tcp; 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 */ /* 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 */ /* list of outstanding queries to this connection */
ares__llist_t *queries_to_conn; ares__llist_t *queries_to_conn;
}; };
#ifdef _MSC_VER #ifdef _MSC_VER
@ -204,70 +223,104 @@ typedef struct {
ares_uint64_t prev_total_count; /*!< Previous period bucket query count */ ares_uint64_t prev_total_count; /*!< Previous period bucket query count */
} ares_server_metrics_t; } ares_server_metrics_t;
struct server_state { typedef enum {
/* Configuration */ ARES_COOKIE_INITIAL = 0,
size_t idx; /* index for server in system configuration */ ARES_COOKIE_GENERATED = 1,
struct ares_addr addr; ARES_COOKIE_SUPPORTED = 2,
unsigned short udp_port; /* host byte order */ ARES_COOKIE_UNSUPPORTED = 3
unsigned short tcp_port; /* host byte order */ } ares_cookie_state_t;
char ll_iface[64]; /* IPv6 Link Local Interface */
unsigned int ll_scope; /* IPv6 Link Local Scope */
size_t consec_failures; /* Consecutive query failure count /*! Structure holding tracking data for RFC 7873/9018 DNS cookies.
* can be hard errors or timeouts * Implementation plan for this feature is here:
*/ * https://github.com/c-ares/c-ares/issues/620
ares__llist_t *connections; */
struct server_connection *tcp_conn; 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;
ares_conn_t *tcp_conn;
/* The next time when we will retry this server if it has hit failures */ /* 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 /* TCP buffer since multiple responses can come back in one read, or partial
* in a read */ * in a read */
ares__buf_t *tcp_parser; ares__buf_t *tcp_parser;
/* TCP output queue */ /* TCP output queue */
ares__buf_t *tcp_send; ares__buf_t *tcp_send;
/*! Buckets for collecting metrics about the server */ /*! Buckets for collecting metrics about the server */
ares_server_metrics_t metrics[ARES_METRIC_COUNT]; ares_server_metrics_t metrics[ARES_METRIC_COUNT];
/*! RFC 7873/9018 DNS Cookies */
ares_cookie_t cookie;
/* Link back to owning channel */ /* Link back to owning channel */
ares_channel_t *channel; ares_channel_t *channel;
}; };
/* State to represent a DNS query */ /* State to represent a DNS query */
struct query { struct ares_query {
/* Query ID from qbuf, for faster lookup, and current timeout */ /* Query ID from qbuf, for faster lookup, and current timeout */
unsigned short qid; /* host byte order */ unsigned short qid; /* host byte order */
ares_timeval_t ts; /*!< Timestamp query was sent */ ares_timeval_t ts; /*!< Timestamp query was sent */
ares_timeval_t timeout; ares_timeval_t timeout;
ares_channel_t *channel; ares_channel_t *channel;
/* /*
* Node object for each list entry the query belongs to in order to * Node object for each list entry the query belongs to in order to
* make removal operations O(1). * make removal operations O(1).
*/ */
ares__slist_node_t *node_queries_by_timeout; ares__slist_node_t *node_queries_by_timeout;
ares__llist_node_t *node_queries_to_conn; ares__llist_node_t *node_queries_to_conn;
ares__llist_node_t *node_all_queries; ares__llist_node_t *node_all_queries;
/* connection handle query is associated with */ /* connection handle query is associated with */
struct server_connection *conn; ares_conn_t *conn;
/* Query */ /* Query */
ares_dns_record_t *query; ares_dns_record_t *query;
ares_callback_dnsrec callback; ares_callback_dnsrec callback;
void *arg; void *arg;
/* Query status */ /* Query status */
size_t try_count; /* Number of times we tried this query already. */ 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_bool_t using_tcp;
ares_status_t error_status; ares_status_t error_status;
size_t timeouts; /* number of timeouts we saw for this request */ 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 ares_bool_t no_retries; /* do not perform any additional retries, this is
* when a query is to be canceled */ * set when a query is to be canceled */
}; };
struct apattern { struct apattern {
@ -408,10 +461,11 @@ ares_bool_t ares__timedout(const ares_timeval_t *now,
const ares_timeval_t *check); const ares_timeval_t *check);
/* Returns one of the normal ares status codes like ARES_SUCCESS */ /* 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__send_query(ares_query_t *query, const ares_timeval_t *now);
ares_status_t ares__requeue_query(struct query *query, ares_status_t ares__requeue_query(ares_query_t *query,
const ares_timeval_t *now, const ares_timeval_t *now,
ares_status_t status); ares_status_t status,
ares_bool_t inc_try_count);
/*! Retrieve a list of names to use for searching. The first successful /*! Retrieve a list of names to use for searching. The first successful
* query in the list wins. This function also uses the HOSTSALIASES file * query in the list wins. This function also uses the HOSTSALIASES file
@ -439,11 +493,10 @@ void *ares__dnsrec_convert_arg(ares_callback callback, void *arg);
void ares__dnsrec_convert_cb(void *arg, ares_status_t status, size_t timeouts, void ares__dnsrec_convert_cb(void *arg, ares_status_t status, size_t timeouts,
const ares_dns_record_t *dnsrec); const ares_dns_record_t *dnsrec);
void ares__close_connection(struct server_connection *conn, void ares__close_connection(ares_conn_t *conn, ares_status_t requeue_status);
ares_status_t requeue_status); void ares__close_sockets(ares_server_t *server);
void ares__close_sockets(struct server_state *server);
void ares__check_cleanup_conns(const ares_channel_t *channel); void ares__check_cleanup_conns(const ares_channel_t *channel);
void ares__free_query(struct query *query); void ares__free_query(ares_query_t *query);
ares_rand_state *ares__init_rand_state(void); ares_rand_state *ares__init_rand_state(void);
void ares__destroy_rand_state(ares_rand_state *state); void ares__destroy_rand_state(ares_rand_state *state);
@ -550,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, ares_status_t ares__addrinfo_localhost(const char *name, unsigned short port,
const struct ares_addrinfo_hints *hints, const struct ares_addrinfo_hints *hints,
struct ares_addrinfo *ai); struct ares_addrinfo *ai);
ares_status_t ares__open_connection(ares_channel_t *channel, ares_status_t ares__open_connection(ares_conn_t **conn_out,
struct server_state *server, ares_channel_t *channel,
ares_bool_t is_tcp); 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, ares_socket_t ares__open_socket(ares_channel_t *channel, int af, int type,
int protocol); int protocol);
ares_ssize_t ares__socket_write(ares_channel_t *channel, ares_socket_t s, ares_bool_t ares__socket_try_again(int errnum);
const void *data, size_t len); 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, ares_ssize_t ares__socket_recvfrom(ares_channel_t *channel, ares_socket_t s,
void *data, size_t data_len, int flags, void *data, size_t data_len, int flags,
struct sockaddr *from, struct sockaddr *from,
ares_socklen_t *from_len); ares_socklen_t *from_len);
ares_ssize_t ares__socket_recv(ares_channel_t *channel, ares_socket_t s, ares_ssize_t ares__socket_recv(ares_channel_t *channel, ares_socket_t s,
void *data, size_t data_len); void *data, size_t data_len);
void ares__close_socket(ares_channel, ares_socket_t); void ares__close_socket(ares_channel_t *channel, ares_socket_t s);
int ares__connect_socket(ares_channel_t *channel, ares_socket_t sockfd, ares_status_t ares__connect_socket(ares_channel_t *channel,
const struct sockaddr *addr, ares_socklen_t addrlen); ares_socket_t sockfd,
void ares__destroy_server(struct server_state *server); 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_status_t ares__servers_update(ares_channel_t *channel,
ares__llist_t *server_list, ares__llist_t *server_list,
@ -582,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, ares_status_t ares_in_addr_to_server_config_llist(const struct in_addr *servers,
size_t nservers, size_t nservers,
ares__llist_t **llist); ares__llist_t **llist);
ares_status_t ares_get_server_addr(const struct server_state *server, ares_status_t ares_get_server_addr(const ares_server_t *server,
ares__buf_t *buf); ares__buf_t *buf);
struct ares_hosts_entry; struct ares_hosts_entry;
typedef struct ares_hosts_entry ares_hosts_entry_t; typedef struct ares_hosts_entry ares_hosts_entry_t;
@ -616,8 +674,8 @@ ares_status_t ares_query_nolock(ares_channel_t *channel, const char *name,
* if a channel lock is already held */ * if a channel lock is already held */
ares_status_t ares_send_nolock(ares_channel_t *channel, ares_status_t ares_send_nolock(ares_channel_t *channel,
const ares_dns_record_t *dnsrec, const ares_dns_record_t *dnsrec,
ares_callback_dnsrec callback, ares_callback_dnsrec callback, void *arg,
void *arg, unsigned short *qid); unsigned short *qid);
/* Same as ares_gethostbyaddr() except does not take a channel lock. Use this /* Same as ares_gethostbyaddr() except does not take a channel lock. Use this
* if a channel lock is already held */ * if a channel lock is already held */
@ -703,17 +761,24 @@ ares_status_t ares__qcache_create(ares_rand_state *rand_state,
void ares__qcache_flush(ares__qcache_t *cache); void ares__qcache_flush(ares__qcache_t *cache);
ares_status_t ares_qcache_insert(ares_channel_t *channel, ares_status_t ares_qcache_insert(ares_channel_t *channel,
const ares_timeval_t *now, const ares_timeval_t *now,
const struct query *query, const ares_query_t *query,
ares_dns_record_t *dnsrec); ares_dns_record_t *dnsrec);
ares_status_t ares_qcache_fetch(ares_channel_t *channel, ares_status_t ares_qcache_fetch(ares_channel_t *channel,
const ares_timeval_t *now, const ares_timeval_t *now,
const ares_dns_record_t *dnsrec, const ares_dns_record_t *dnsrec,
const ares_dns_record_t **dnsrec_resp); const ares_dns_record_t **dnsrec_resp);
void ares_metrics_record(const struct query *query, struct server_state *server, void ares_metrics_record(const ares_query_t *query, ares_server_t *server,
ares_status_t status, const ares_dns_record_t *dnsrec); ares_status_t status, const ares_dns_record_t *dnsrec);
size_t ares_metrics_server_timeout(const struct server_state *server, size_t ares_metrics_server_timeout(const ares_server_t *server,
const ares_timeval_t *now); 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); ares_status_t ares__channel_threading_init(ares_channel_t *channel);
void ares__channel_threading_destroy(ares_channel_t *channel); void ares__channel_threading_destroy(ares_channel_t *channel);

View file

@ -46,7 +46,6 @@
static void timeadd(ares_timeval_t *now, size_t millisecs); 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, static void write_tcp_data(ares_channel_t *channel, fd_set *write_fds,
ares_socket_t write_fd); ares_socket_t write_fd);
static void read_packets(ares_channel_t *channel, fd_set *read_fds, static void read_packets(ares_channel_t *channel, fd_set *read_fds,
@ -55,22 +54,20 @@ static void process_timeouts(ares_channel_t *channel,
const ares_timeval_t *now); const ares_timeval_t *now);
static ares_status_t process_answer(ares_channel_t *channel, static ares_status_t process_answer(ares_channel_t *channel,
const unsigned char *abuf, size_t alen, const unsigned char *abuf, size_t alen,
struct server_connection *conn, ares_conn_t *conn, ares_bool_t tcp,
ares_bool_t tcp, const ares_timeval_t *now); const ares_timeval_t *now);
static void handle_conn_error(struct server_connection *conn, static void handle_conn_error(ares_conn_t *conn, ares_bool_t critical_failure,
ares_bool_t critical_failure, ares_status_t failure_status);
ares_status_t failure_status);
static ares_bool_t same_questions(const struct query *query, static ares_bool_t same_questions(const ares_query_t *query,
const ares_dns_record_t *arec); const ares_dns_record_t *arec);
static ares_bool_t same_address(const struct sockaddr *sa, static ares_bool_t same_address(const struct sockaddr *sa,
const struct ares_addr *aa); const struct ares_addr *aa);
static void end_query(ares_channel_t *channel, struct server_state *server, static void end_query(ares_channel_t *channel, ares_server_t *server,
struct query *query, ares_status_t status, ares_query_t *query, ares_status_t status,
const ares_dns_record_t *dnsrec); const ares_dns_record_t *dnsrec);
static void ares__query_disassociate_from_conn(ares_query_t *query)
static void ares__query_disassociate_from_conn(struct query *query)
{ {
/* If its not part of a connection, it can't be tracked for timeouts either */ /* 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__slist_node_destroy(query->node_queries_by_timeout);
@ -81,7 +78,7 @@ static void ares__query_disassociate_from_conn(struct query *query)
} }
/* Invoke the server state callback after a success or failure */ /* Invoke the server state callback after a success or failure */
static void invoke_server_state_cb(const struct server_state *server, static void invoke_server_state_cb(const ares_server_t *server,
ares_bool_t success, int flags) ares_bool_t success, int flags)
{ {
const ares_channel_t *channel = server->channel; const ares_channel_t *channel = server->channel;
@ -115,8 +112,8 @@ static void invoke_server_state_cb(const struct server_state *server,
ares_free(server_string); ares_free(server_string);
} }
static void server_increment_failures(struct server_state *server, static void server_increment_failures(ares_server_t *server,
ares_bool_t used_tcp) ares_bool_t used_tcp)
{ {
ares__slist_node_t *node; ares__slist_node_t *node;
const ares_channel_t *channel = server->channel; const ares_channel_t *channel = server->channel;
@ -139,7 +136,7 @@ static void server_increment_failures(struct server_state *server,
: ARES_SERV_STATE_UDP); : 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; ares__slist_node_t *node;
const ares_channel_t *channel = server->channel; const ares_channel_t *channel = server->channel;
@ -238,34 +235,6 @@ void ares_process_fd(ares_channel_t *channel,
processfds(channel, NULL, read_fd, NULL, write_fd); 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 /* If any TCP sockets select true for writing, write out queued data
* we have for them. * we have for them.
*/ */
@ -281,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; for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) { 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; const unsigned char *data;
size_t data_len; size_t data_len;
ares_ssize_t count; ares_ssize_t count;
@ -312,9 +281,9 @@ static void write_tcp_data(ares_channel_t *channel, fd_set *write_fds,
} }
data = ares__buf_peek(server->tcp_send, &data_len); 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 (count <= 0) {
if (!try_again(SOCKERRNO)) { if (!ares__socket_try_again(SOCKERRNO)) {
handle_conn_error(server->tcp_conn, ARES_TRUE, ARES_ECONNREFUSED); handle_conn_error(server->tcp_conn, ARES_TRUE, ARES_ECONNREFUSED);
} }
continue; continue;
@ -334,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 * allocate a buffer if we finish reading the length word, and process
* a packet if we finish reading one. * a packet if we finish reading one.
*/ */
static void read_tcp_data(ares_channel_t *channel, static void read_tcp_data(ares_channel_t *channel, ares_conn_t *conn,
struct server_connection *conn, const ares_timeval_t *now)
const ares_timeval_t *now)
{ {
ares_ssize_t count; ares_ssize_t count;
struct server_state *server = conn->server; ares_server_t *server = conn->server;
/* Fetch buffer to store data we are reading */ /* Fetch buffer to store data we are reading */
size_t ptr_len = 65535; size_t ptr_len = 65535;
unsigned char *ptr; unsigned char *ptr;
ptr = ares__buf_append_start(server->tcp_parser, &ptr_len); ptr = ares__buf_append_start(server->tcp_parser, &ptr_len);
if (ptr == NULL) { if (ptr == NULL) {
handle_conn_error(conn, ARES_FALSE /* not critical to connection */, ARES_SUCCESS); handle_conn_error(conn, ARES_FALSE /* not critical to connection */,
ARES_SUCCESS);
return; /* bail out on malloc failure. TODO: make this return; /* bail out on malloc failure. TODO: make this
function return error codes */ function return error codes */
} }
@ -357,7 +326,7 @@ static void read_tcp_data(ares_channel_t *channel,
count = ares__socket_recv(channel, conn->fd, ptr, ptr_len); count = ares__socket_recv(channel, conn->fd, ptr, ptr_len);
if (count <= 0) { if (count <= 0) {
ares__buf_append_finish(server->tcp_parser, 0); ares__buf_append_finish(server->tcp_parser, 0);
if (!(count == -1 && try_again(SOCKERRNO))) { if (!(count == -1 && ares__socket_try_again(SOCKERRNO))) {
handle_conn_error(conn, ARES_TRUE, ARES_ECONNREFUSED); handle_conn_error(conn, ARES_TRUE, ARES_ECONNREFUSED);
} }
return; return;
@ -411,69 +380,48 @@ static void read_tcp_data(ares_channel_t *channel,
} }
} }
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; /* LCOV_EXCL_LINE: OutOfMemory */
}
*alloc_cnt = new_alloc;
*socketlist = new_list;
}
(*socketlist)[(*num)++] = fd;
return 1;
}
static ares_socket_t *channel_socket_list(const ares_channel_t *channel, static ares_socket_t *channel_socket_list(const ares_channel_t *channel,
size_t *num) 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__slist_node_t *snode;
ares__array_t *arr = ares__array_create(sizeof(ares_socket_t), NULL);
*num = 0; *num = 0;
if (out == NULL) { if (arr == NULL) {
return NULL; /* LCOV_EXCL_LINE: OutOfMemory */ return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
} }
for (snode = ares__slist_node_first(channel->servers); snode != NULL; for (snode = ares__slist_node_first(channel->servers); snode != NULL;
snode = ares__slist_node_next(snode)) { snode = ares__slist_node_next(snode)) {
struct server_state *server = ares__slist_node_val(snode); ares_server_t *server = ares__slist_node_val(snode);
ares__llist_node_t *node; ares__llist_node_t *node;
for (node = ares__llist_node_first(server->connections); node != NULL; for (node = ares__llist_node_first(server->connections); node != NULL;
node = ares__llist_node_next(node)) { 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) { if (conn->fd == ARES_SOCKET_BAD) {
continue; continue;
} }
if (!socket_list_append(&out, conn->fd, &alloc_cnt, num)) { status = ares__array_insert_last((void **)&sptr, arr);
goto fail; /* LCOV_EXCL_LINE: OutOfMemory */ if (status != ARES_SUCCESS) {
ares__array_destroy(arr); /* LCOV_EXCL_LINE: OutOfMemory */
return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
} }
*sptr = conn->fd;
} }
} }
return out; return ares__array_finish(arr, num);
fail:
ares_free(out);
*num = 0;
return NULL;
} }
/* If any UDP sockets select true for reading, process them. */ /* If any UDP sockets select true for reading, process them. */
static void read_udp_packets_fd(ares_channel_t *channel, static void read_udp_packets_fd(ares_channel_t *channel, ares_conn_t *conn,
struct server_connection *conn, const ares_timeval_t *now)
const ares_timeval_t *now)
{ {
ares_ssize_t read_len; ares_ssize_t read_len;
unsigned char buf[MAXENDSSZ + 1]; unsigned char buf[MAXENDSSZ + 1];
@ -511,7 +459,7 @@ static void read_udp_packets_fd(ares_channel_t *channel,
* tcp */ * tcp */
continue; continue;
} else if (read_len < 0) { } else if (read_len < 0) {
if (try_again(SOCKERRNO)) { if (ares__socket_try_again(SOCKERRNO)) {
break; break;
} }
@ -537,11 +485,11 @@ static void read_udp_packets_fd(ares_channel_t *channel,
static void read_packets(ares_channel_t *channel, fd_set *read_fds, static void read_packets(ares_channel_t *channel, fd_set *read_fds,
ares_socket_t read_fd, const ares_timeval_t *now) ares_socket_t read_fd, const ares_timeval_t *now)
{ {
size_t i; size_t i;
ares_socket_t *socketlist = NULL; ares_socket_t *socketlist = NULL;
size_t num_sockets = 0; size_t num_sockets = 0;
struct server_connection *conn = NULL; ares_conn_t *conn = NULL;
ares__llist_node_t *node = NULL; ares__llist_node_t *node = NULL;
if (!read_fds && (read_fd == ARES_SOCKET_BAD)) { if (!read_fds && (read_fd == ARES_SOCKET_BAD)) {
/* no possible action */ /* no possible action */
@ -557,7 +505,7 @@ static void read_packets(ares_channel_t *channel, fd_set *read_fds,
conn = ares__llist_node_val(node); conn = ares__llist_node_val(node);
if (conn->is_tcp) { if (conn->flags & ARES_CONN_FLAG_TCP) {
read_tcp_data(channel, conn, now); read_tcp_data(channel, conn, now);
} else { } else {
read_udp_packets_fd(channel, conn, now); read_udp_packets_fd(channel, conn, now);
@ -591,7 +539,7 @@ static void read_packets(ares_channel_t *channel, fd_set *read_fds,
conn = ares__llist_node_val(node); conn = ares__llist_node_val(node);
if (conn->is_tcp) { if (conn->flags & ARES_CONN_FLAG_TCP) {
read_tcp_data(channel, conn, now); read_tcp_data(channel, conn, now);
} else { } else {
read_udp_packets_fd(channel, conn, now); read_udp_packets_fd(channel, conn, now);
@ -610,8 +558,8 @@ static void process_timeouts(ares_channel_t *channel, const ares_timeval_t *now)
* and go. We don't want to try to rely on 'next' as some operation might * 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 */ * cause a cleanup of that pointer and would become invalid */
while ((node = ares__slist_node_first(channel->queries_by_timeout)) != NULL) { while ((node = ares__slist_node_first(channel->queries_by_timeout)) != NULL) {
struct query *query = ares__slist_node_val(node); ares_query_t *query = ares__slist_node_val(node);
struct server_connection *conn; ares_conn_t *conn;
/* Since this is sorted, as soon as we hit a query that isn't timed out, /* Since this is sorted, as soon as we hit a query that isn't timed out,
* break */ * break */
@ -623,15 +571,15 @@ static void process_timeouts(ares_channel_t *channel, const ares_timeval_t *now)
conn = query->conn; conn = query->conn;
server_increment_failures(conn->server, query->using_tcp); server_increment_failures(conn->server, query->using_tcp);
ares__requeue_query(query, now, ARES_ETIMEOUT); ares__requeue_query(query, now, ARES_ETIMEOUT, ARES_TRUE);
} }
} }
static ares_status_t rewrite_without_edns(struct query *query) static ares_status_t rewrite_without_edns(ares_query_t *query)
{ {
ares_status_t status = ARES_SUCCESS; ares_status_t status = ARES_SUCCESS;
size_t i; size_t i;
ares_bool_t found_opt_rr = ARES_FALSE; ares_bool_t found_opt_rr = ARES_FALSE;
/* Find and remove the OPT RR record */ /* Find and remove the OPT RR record */
for (i = 0; i < ares_dns_record_rr_cnt(query->query, ARES_SECTION_ADDITIONAL); for (i = 0; i < ares_dns_record_rr_cnt(query->query, ARES_SECTION_ADDITIONAL);
@ -659,16 +607,16 @@ done:
* the connection to be terminated after this call. */ * the connection to be terminated after this call. */
static ares_status_t process_answer(ares_channel_t *channel, static ares_status_t process_answer(ares_channel_t *channel,
const unsigned char *abuf, size_t alen, const unsigned char *abuf, size_t alen,
struct server_connection *conn, ares_conn_t *conn, ares_bool_t tcp,
ares_bool_t tcp, const ares_timeval_t *now) 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 /* Cache these as once ares__send_query() gets called, it may end up
* invalidating the connection all-together */ * invalidating the connection all-together */
struct server_state *server = conn->server; ares_server_t *server = conn->server;
ares_dns_record_t *rdnsrec = NULL; ares_dns_record_t *rdnsrec = NULL;
ares_status_t status; ares_status_t status;
ares_bool_t is_cached = ARES_FALSE; ares_bool_t is_cached = ARES_FALSE;
/* Parse the response */ /* Parse the response */
status = ares_dns_parse(abuf, alen, 0, &rdnsrec); status = ares_dns_parse(abuf, alen, 0, &rdnsrec);
@ -697,6 +645,14 @@ static ares_status_t process_answer(ares_channel_t *channel,
goto cleanup; 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 /* 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 * remove it from the connection's queue so we can possibly invalidate the
* connection. Delay cleaning up the connection though as we may enqueue * connection. Delay cleaning up the connection though as we may enqueue
@ -708,7 +664,8 @@ static ares_status_t process_answer(ares_channel_t *channel,
* protocol extension is not understood by the responder. We must retry the * protocol extension is not understood by the responder. We must retry the
* query without EDNS enabled. */ * query without EDNS enabled. */
if (ares_dns_record_get_rcode(rdnsrec) == ARES_RCODE_FORMERR && if (ares_dns_record_get_rcode(rdnsrec) == ARES_RCODE_FORMERR &&
ares_dns_has_opt_rr(query->query) && !ares_dns_has_opt_rr(rdnsrec)) { ares_dns_get_opt_rr_const(query->query) != NULL &&
ares_dns_get_opt_rr_const(rdnsrec) == NULL) {
status = rewrite_without_edns(query); status = rewrite_without_edns(query);
if (status != ARES_SUCCESS) { if (status != ARES_SUCCESS) {
end_query(channel, server, query, status, NULL); end_query(channel, server, query, status, NULL);
@ -754,7 +711,7 @@ static ares_status_t process_answer(ares_channel_t *channel,
} }
server_increment_failures(server, query->using_tcp); server_increment_failures(server, query->using_tcp);
ares__requeue_query(query, now, status); ares__requeue_query(query, now, status, ARES_TRUE);
/* Should any of these cause a connection termination? /* Should any of these cause a connection termination?
* Maybe SERVER_FAILURE? */ * Maybe SERVER_FAILURE? */
@ -783,25 +740,26 @@ cleanup:
return status; return status;
} }
static void handle_conn_error(struct server_connection *conn, static void handle_conn_error(ares_conn_t *conn, ares_bool_t critical_failure,
ares_bool_t critical_failure, ares_status_t failure_status)
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 /* Increment failures first before requeue so it is unlikely to requeue
* to the same server */ * to the same server */
if (critical_failure) { 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 */ /* This will requeue any connections automatically */
ares__close_connection(conn, failure_status); ares__close_connection(conn, failure_status);
} }
ares_status_t ares__requeue_query(struct query *query, ares_status_t ares__requeue_query(ares_query_t *query,
const ares_timeval_t *now, const ares_timeval_t *now,
ares_status_t status) ares_status_t status,
ares_bool_t inc_try_count)
{ {
ares_channel_t *channel = query->channel; ares_channel_t *channel = query->channel;
size_t max_tries = ares__slist_len(channel->servers) * channel->tries; size_t max_tries = ares__slist_len(channel->servers) * channel->tries;
@ -812,7 +770,10 @@ ares_status_t ares__requeue_query(struct query *query,
query->error_status = status; query->error_status = status;
} }
query->try_count++; if (inc_try_count) {
query->try_count++;
}
if (query->try_count < max_tries && !query->no_retries) { if (query->try_count < max_tries && !query->no_retries) {
return ares__send_query(query, now); return ares__send_query(query, now);
} }
@ -829,7 +790,7 @@ ares_status_t ares__requeue_query(struct query *query,
/* Pick a random server from the list, we first get a random number in the /* 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 * range of the number of servers, then scan until we find that server in
* the list */ * 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; unsigned char c;
size_t cnt; size_t cnt;
@ -873,12 +834,11 @@ static struct server_state *ares__random_server(ares_channel_t *channel)
* To resolve this, with some probability we select a failed server to retry * To resolve this, with some probability we select a failed server to retry
* instead. * 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); ares_server_t *first_server = ares__slist_first_val(channel->servers);
const struct server_state *last_server = const ares_server_t *last_server = ares__slist_last_val(channel->servers);
ares__slist_last_val(channel->servers); unsigned short r;
unsigned short r;
/* Defensive code against no servers being available on the channel. */ /* Defensive code against no servers being available on the channel. */
if (first_server == NULL) { if (first_server == NULL) {
@ -911,7 +871,7 @@ static struct server_state *ares__failover_server(ares_channel_t *channel)
ares__tvnow(&now); ares__tvnow(&now);
for (node = ares__slist_node_first(channel->servers); node != NULL; for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) { 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 && if (node_val != NULL && node_val->consec_failures > 0 &&
ares__timedout(&now, &node_val->next_retry_time)) { ares__timedout(&now, &node_val->next_retry_time)) {
return node_val; return node_val;
@ -923,65 +883,9 @@ static struct server_state *ares__failover_server(ares_channel_t *channel)
return first_server; return first_server;
} }
static ares_status_t ares__append_tcpbuf(struct server_state *server, static size_t ares__calc_query_timeout(const ares_query_t *query,
const struct query *query) const ares_server_t *server,
{ const ares_timeval_t *now)
ares_status_t status;
unsigned char *qbuf = NULL;
size_t qbuf_len = 0;
status = ares_dns_write(query->query, &qbuf, &qbuf_len);
if (status != ARES_SUCCESS) {
goto done;
}
status = ares__buf_append_be16(server->tcp_send, (unsigned short)qbuf_len);
if (status != ARES_SUCCESS) {
goto done; /* LCOV_EXCL_LINE: OutOfMemory */
}
status = ares__buf_append(server->tcp_send, qbuf, qbuf_len);
done:
ares_free(qbuf);
return status;
}
static ares_status_t ares__write_udpbuf(ares_channel_t *channel,
ares_socket_t fd,
const struct query *query)
{
ares_status_t status;
unsigned char *qbuf = NULL;
size_t qbuf_len = 0;
status = ares_dns_write(query->query, &qbuf, &qbuf_len);
if (status != ARES_SUCCESS) {
goto done;
}
if (ares__socket_write(channel, fd, qbuf, qbuf_len) == -1) {
if (try_again(SOCKERRNO)) {
status = ARES_ESERVFAIL;
} else {
/* 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 */
status = ARES_ECONNREFUSED;
}
} else {
status = ARES_SUCCESS;
}
done:
ares_free(qbuf);
return status;
}
static size_t ares__calc_query_timeout(const struct query *query,
const struct server_state *server,
const ares_timeval_t *now)
{ {
const ares_channel_t *channel = query->channel; const ares_channel_t *channel = query->channel;
size_t timeout = ares_metrics_server_timeout(server, now); size_t timeout = ares_metrics_server_timeout(server, now);
@ -1031,14 +935,121 @@ static size_t ares__calc_query_timeout(const struct query *query,
return timeplus; 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; ares__llist_node_t *node;
struct server_state *server; ares_conn_t *conn;
struct server_connection *conn;
size_t timeplus; if (query->using_tcp) {
ares_status_t status; return server->tcp_conn;
ares_bool_t new_connection = ARES_FALSE; }
/* Fetch existing UDP connection */
node = ares__llist_node_first(server->connections);
if (node == NULL) {
return NULL;
}
conn = ares__llist_node_val(node);
/* Not UDP, skip */
if (conn->flags & ARES_CONN_FLAG_TCP) {
return NULL;
}
/* Used too many times */
if (channel->udp_max_queries > 0 &&
conn->total_queries >= channel->udp_max_queries) {
return NULL;
}
return 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;
}
if (conn->flags & ARES_CONN_FLAG_TCP) {
size_t prior_len = ares__buf_len(server->tcp_send);
status = ares_dns_write_buf_tcp(query->query, server->tcp_send);
if (status != ARES_SUCCESS) {
return status;
}
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;
}
/* 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);
}
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;
}
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;
/* Choose the server to send the query to */ /* Choose the server to send the query to */
if (channel->rotate) { if (channel->rotate) {
@ -1054,129 +1065,59 @@ ares_status_t ares__send_query(struct query *query, const ares_timeval_t *now)
return ARES_ENOSERVER; return ARES_ENOSERVER;
} }
if (query->using_tcp) { conn = ares__fetch_connection(channel, server, query);
size_t prior_len = 0; if (conn == NULL) {
/* Make sure the TCP socket for this server is set up and queue status = ares__open_connection(&conn, channel, server, query->using_tcp);
* a send request. switch (status) {
*/ /* Good result, continue on */
if (server->tcp_conn == NULL) { case ARES_SUCCESS:
new_connection = ARES_TRUE; break;
status = ares__open_connection(channel, server, ARES_TRUE);
switch (status) {
/* Good result, continue on */
case ARES_SUCCESS:
break;
/* These conditions are retryable as they are server-specific /* These conditions are retryable as they are server-specific
* error codes */ * error codes */
case ARES_ECONNREFUSED: case ARES_ECONNREFUSED:
case ARES_EBADFAMILY: case ARES_EBADFAMILY:
server_increment_failures(server, query->using_tcp); server_increment_failures(server, query->using_tcp);
return ares__requeue_query(query, now, status); return ares__requeue_query(query, now, status, ARES_TRUE);
/* Anything else is not retryable, likely ENOMEM */ /* Anything else is not retryable, likely ENOMEM */
default: default:
end_query(channel, server, query, status, NULL);
return status;
}
}
conn = server->tcp_conn;
prior_len = ares__buf_len(server->tcp_send);
status = ares__append_tcpbuf(server, query);
if (status != ARES_SUCCESS) {
end_query(channel, server, query, status, 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, status);
}
return status;
}
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;
}
}
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;
/* 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);
/* Anything else is not retryable, likely ENOMEM */
default:
end_query(channel, server, query, status, NULL);
return status;
}
node = ares__llist_node_first(server->connections);
}
conn = ares__llist_node_val(node);
status = ares__write_udpbuf(channel, conn->fd, query);
if (status != ARES_SUCCESS) {
if (status == ARES_ENOMEM) {
/* Not retryable */
end_query(channel, server, query, status, NULL); end_query(channel, server, query, status, NULL);
return status; return status;
}
if (status == ARES_ECONNREFUSED) {
handle_conn_error(conn, ARES_TRUE, status);
/* This query wasn't yet bound to the connection, need to manually
* requeue it and return an appropriate error */
status = ares__requeue_query(query, now, status);
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. */
server_increment_failures(server, query->using_tcp);
status = ares__requeue_query(query, now, 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, status);
}
return status;
} }
} }
/* Write the query */
status = ares__conn_query_write(conn, query, now);
switch (status) {
/* Good result, continue on */
case ARES_SUCCESS:
break;
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, server, now); timeplus = ares__calc_query_timeout(query, server, now);
/* Keep track of queries bucketed by timeout, so we can process /* Keep track of queries bucketed by timeout, so we can process
* timeout events quickly. * timeout events quickly.
@ -1190,11 +1131,6 @@ ares_status_t ares__send_query(struct query *query, const ares_timeval_t *now)
if (!query->node_queries_by_timeout) { if (!query->node_queries_by_timeout) {
/* LCOV_EXCL_START: OutOfMemory */ /* LCOV_EXCL_START: OutOfMemory */
end_query(channel, server, query, ARES_ENOMEM, NULL); end_query(channel, server, 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, ARES_SUCCESS);
}
return ARES_ENOMEM; return ARES_ENOMEM;
/* LCOV_EXCL_STOP */ /* LCOV_EXCL_STOP */
} }
@ -1208,11 +1144,6 @@ ares_status_t ares__send_query(struct query *query, const ares_timeval_t *now)
if (query->node_queries_to_conn == NULL) { if (query->node_queries_to_conn == NULL) {
/* LCOV_EXCL_START: OutOfMemory */ /* LCOV_EXCL_START: OutOfMemory */
end_query(channel, server, query, ARES_ENOMEM, NULL); end_query(channel, server, 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, ARES_SUCCESS);
}
return ARES_ENOMEM; return ARES_ENOMEM;
/* LCOV_EXCL_STOP */ /* LCOV_EXCL_STOP */
} }
@ -1222,7 +1153,7 @@ ares_status_t ares__send_query(struct query *query, const ares_timeval_t *now)
return ARES_SUCCESS; return ARES_SUCCESS;
} }
static ares_bool_t same_questions(const struct query *query, static ares_bool_t same_questions(const ares_query_t *query,
const ares_dns_record_t *arec) const ares_dns_record_t *arec)
{ {
size_t i; size_t i;
@ -1299,7 +1230,8 @@ static ares_bool_t same_address(const struct sockaddr *sa,
break; break;
case AF_INET6: case AF_INET6:
addr1 = &aa->addr.addr6; addr1 = &aa->addr.addr6;
addr2 = &(CARES_INADDR_CAST(const 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) { if (memcmp(addr1, addr2, sizeof(aa->addr.addr6)) == 0) {
return ARES_TRUE; /* match */ return ARES_TRUE; /* match */
} }
@ -1311,17 +1243,17 @@ static ares_bool_t same_address(const struct sockaddr *sa,
return ARES_FALSE; /* different */ 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 */ /* Remove the query from all the lists in which it is linked */
ares__query_disassociate_from_conn(query); ares__query_disassociate_from_conn(query);
ares__htable_szvp_remove(query->channel->queries_by_qid, query->qid); ares__htable_szvp_remove(query->channel->queries_by_qid, query->qid);
ares__llist_node_destroy(query->node_all_queries); ares__llist_node_destroy(query->node_all_queries);
query->node_all_queries = NULL; query->node_all_queries = NULL;
} }
static void end_query(ares_channel_t *channel, struct server_state *server, static void end_query(ares_channel_t *channel, ares_server_t *server,
struct query *query, ares_status_t status, ares_query_t *query, ares_status_t status,
const ares_dns_record_t *dnsrec) const ares_dns_record_t *dnsrec)
{ {
ares_metrics_record(query, server, status, dnsrec); ares_metrics_record(query, server, status, dnsrec);
@ -1338,7 +1270,7 @@ static void end_query(ares_channel_t *channel, struct server_state *server,
ares_queue_notify_empty(channel); ares_queue_notify_empty(channel);
} }
void ares__free_query(struct query *query) void ares__free_query(ares_query_t *query)
{ {
ares_detach_query(query); ares_detach_query(query);
/* Zero out some important stuff, to help catch bugs */ /* Zero out some important stuff, to help catch bugs */

View file

@ -300,10 +300,10 @@ static unsigned int ares__qcache_soa_minimum(ares_dns_record_t *dnsrec)
} }
/* On success, takes ownership of dnsrec */ /* On success, takes ownership of dnsrec */
static ares_status_t ares__qcache_insert(ares__qcache_t *qcache, static ares_status_t ares__qcache_insert(ares__qcache_t *qcache,
ares_dns_record_t *qresp, ares_dns_record_t *qresp,
const ares_dns_record_t *qreq, const ares_dns_record_t *qreq,
const ares_timeval_t *now) const ares_timeval_t *now)
{ {
ares__qcache_entry_t *entry; ares__qcache_entry_t *entry;
unsigned int ttl; unsigned int ttl;
@ -422,9 +422,8 @@ done:
ares_status_t ares_qcache_insert(ares_channel_t *channel, ares_status_t ares_qcache_insert(ares_channel_t *channel,
const ares_timeval_t *now, const ares_timeval_t *now,
const struct query *query, const ares_query_t *query,
ares_dns_record_t *dnsrec) ares_dns_record_t *dnsrec)
{ {
return ares__qcache_insert(channel->qcache, dnsrec, query->query, return ares__qcache_insert(channel->qcache, dnsrec, query->query, now);
now);
} }

View file

@ -43,13 +43,12 @@ static unsigned short generate_unique_qid(ares_channel_t *channel)
return id; return id;
} }
/* https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00 */ /* https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00 */
static ares_status_t ares_apply_dns0x20(ares_channel_t *channel, static ares_status_t ares_apply_dns0x20(ares_channel_t *channel,
ares_dns_record_t *dnsrec) ares_dns_record_t *dnsrec)
{ {
ares_status_t status = ARES_SUCCESS; ares_status_t status = ARES_SUCCESS;
const char *name = NULL; const char *name = NULL;
char dns0x20name[256]; char dns0x20name[256];
unsigned char randdata[256 / 8]; unsigned char randdata[256 / 8];
size_t len; size_t len;
@ -72,16 +71,16 @@ static ares_status_t ares_apply_dns0x20(ares_channel_t *channel,
/* Fetch the minimum amount of random data we'd need for the string, which /* Fetch the minimum amount of random data we'd need for the string, which
* is 1 bit per byte */ * is 1 bit per byte */
total_bits = ((len + 7) / 8) * 8; total_bits = ((len + 7) / 8) * 8;
remaining_bits = total_bits; remaining_bits = total_bits;
ares__rand_bytes(channel->rand_state, randdata, total_bits / 8); ares__rand_bytes(channel->rand_state, randdata, total_bits / 8);
/* Randomly apply 0x20 to name */ /* Randomly apply 0x20 to name */
for (i=0; i<len; i++) { for (i = 0; i < len; i++) {
size_t bit; size_t bit;
/* Only apply 0x20 to alpha characters */ /* Only apply 0x20 to alpha characters */
if (!isalpha(name[i])) { if (!ares__isalpha(name[i])) {
dns0x20name[i] = name[i]; dns0x20name[i] = name[i];
continue; continue;
} }
@ -89,7 +88,7 @@ static ares_status_t ares_apply_dns0x20(ares_channel_t *channel,
/* coin flip */ /* coin flip */
bit = total_bits - remaining_bits; bit = total_bits - remaining_bits;
if (randdata[bit / 8] & (1 << (bit % 8))) { if (randdata[bit / 8] & (1 << (bit % 8))) {
dns0x20name[i] = name[i] | 0x20; /* Set 0x20 */ dns0x20name[i] = name[i] | 0x20; /* Set 0x20 */
} else { } else {
dns0x20name[i] = (char)(((unsigned char)name[i]) & 0xDF); /* Unset 0x20 */ dns0x20name[i] = (char)(((unsigned char)name[i]) & 0xDF); /* Unset 0x20 */
} }
@ -102,13 +101,12 @@ done:
return status; return status;
} }
ares_status_t ares_send_nolock(ares_channel_t *channel, ares_status_t ares_send_nolock(ares_channel_t *channel,
const ares_dns_record_t *dnsrec, const ares_dns_record_t *dnsrec,
ares_callback_dnsrec callback, ares_callback_dnsrec callback, void *arg,
void *arg, unsigned short *qid) unsigned short *qid)
{ {
struct query *query; ares_query_t *query;
ares_timeval_t now; ares_timeval_t now;
ares_status_t status; ares_status_t status;
unsigned short id = generate_unique_qid(channel); unsigned short id = generate_unique_qid(channel);
@ -131,7 +129,7 @@ ares_status_t ares_send_nolock(ares_channel_t *channel,
} }
/* Allocate space for query and allocated fields. */ /* Allocate space for query and allocated fields. */
query = ares_malloc(sizeof(struct query)); query = ares_malloc(sizeof(ares_query_t));
if (!query) { if (!query) {
callback(arg, ARES_ENOMEM, 0, NULL); /* LCOV_EXCL_LINE: OutOfMemory */ callback(arg, ARES_ENOMEM, 0, NULL); /* LCOV_EXCL_LINE: OutOfMemory */
return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
@ -142,7 +140,8 @@ ares_status_t ares_send_nolock(ares_channel_t *channel,
query->qid = id; query->qid = id;
query->timeout.sec = 0; query->timeout.sec = 0;
query->timeout.usec = 0; query->timeout.usec = 0;
query->using_tcp = (channel->flags & ARES_FLAG_USEVC)?ARES_TRUE:ARES_FALSE; query->using_tcp =
(channel->flags & ARES_FLAG_USEVC) ? ARES_TRUE : ARES_FALSE;
/* Duplicate Query */ /* Duplicate Query */
status = ares_dns_record_duplicate_ex(&query->query, dnsrec); status = ares_dns_record_duplicate_ex(&query->query, dnsrec);

View file

@ -231,95 +231,6 @@ struct timeval {
}; };
#endif #endif
/*
* If we have the MSG_NOSIGNAL define, make sure we use
* it as the fourth argument of function send()
*/
#ifdef HAVE_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_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_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 */
/* /*
* Function-like macro definition used to close a socket. * Function-like macro definition used to close a socket.
*/ */
@ -343,7 +254,7 @@ Error Missing_definition_of_macro_sread
#else #else
# define DEBUGF(x) \ # define DEBUGF(x) \
do { \ do { \
} while(0) } while (0)
#endif #endif
/* /*

View file

@ -115,11 +115,11 @@ static ares_status_t dnsinfo_init(dnsinfo_t **dnsinfo_out)
continue; continue;
} }
dnsinfo->dns_configuration_copy = (dns_config_t *(*)(void)) dnsinfo->dns_configuration_copy = (dns_config_t * (*)(void))
dlsym(dnsinfo->handle, "dns_configuration_copy"); dlsym(dnsinfo->handle, "dns_configuration_copy");
dnsinfo->dns_configuration_free = (void (*)(dns_config_t *)) dnsinfo->dns_configuration_free = (void (*)(dns_config_t *))dlsym(
dlsym(dnsinfo->handle, "dns_configuration_free"); dnsinfo->handle, "dns_configuration_free");
if (dnsinfo->dns_configuration_copy != NULL && if (dnsinfo->dns_configuration_copy != NULL &&
dnsinfo->dns_configuration_free != NULL) { dnsinfo->dns_configuration_free != NULL) {
@ -274,25 +274,7 @@ static ares_status_t read_resolver(const dns_resolver_t *resolver,
/* UBSAN alignment workaround to fetch memory address */ /* UBSAN alignment workaround to fetch memory address */
memcpy(&sockaddr, resolver->nameserver + i, sizeof(sockaddr)); memcpy(&sockaddr, resolver->nameserver + i, sizeof(sockaddr));
if (sockaddr->sa_family == AF_INET) { if (!ares_sockaddr_to_ares_addr(&addr, &addrport, sockaddr)) {
/* 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 {
continue; continue;
} }

View file

@ -65,7 +65,8 @@ void ares__timeval_diff(ares_timeval_t *tvdiff, const ares_timeval_t *tvstart,
} }
} }
static void ares_timeval_to_struct_timeval(struct timeval *tv, const ares_timeval_t *atv) static void ares_timeval_to_struct_timeval(struct timeval *tv,
const ares_timeval_t *atv)
{ {
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
tv->tv_sec = (long)atv->sec; tv->tv_sec = (long)atv->sec;
@ -76,17 +77,18 @@ static void ares_timeval_to_struct_timeval(struct timeval *tv, const ares_timeva
tv->tv_usec = (int)atv->usec; tv->tv_usec = (int)atv->usec;
} }
static void struct_timeval_to_ares_timeval(ares_timeval_t *atv, const struct timeval *tv) static void struct_timeval_to_ares_timeval(ares_timeval_t *atv,
const struct timeval *tv)
{ {
atv->sec = (ares_int64_t)tv->tv_sec; atv->sec = (ares_int64_t)tv->tv_sec;
atv->usec = (unsigned int)tv->tv_usec; atv->usec = (unsigned int)tv->tv_usec;
} }
static struct timeval *ares_timeout_int(const ares_channel_t *channel, static struct timeval *ares_timeout_int(const ares_channel_t *channel,
struct timeval *maxtv, struct timeval *maxtv,
struct timeval *tvbuf) struct timeval *tvbuf)
{ {
const struct query *query; const ares_query_t *query;
ares__slist_node_t *node; ares__slist_node_t *node;
ares_timeval_t now; ares_timeval_t now;
ares_timeval_t atvbuf; ares_timeval_t atvbuf;
@ -135,8 +137,9 @@ struct timeval *ares_timeout(const ares_channel_t *channel,
{ {
struct timeval *rv; struct timeval *rv;
if (channel == NULL || tvbuf == NULL) if (channel == NULL || tvbuf == NULL) {
return NULL; return NULL;
}
ares__channel_lock(channel); ares__channel_lock(channel);

View file

@ -525,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; for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) { 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)) { if (!ares__addr_match(&server->addr, &s->addr)) {
continue; continue;
@ -579,8 +579,8 @@ static ares_status_t ares__server_create(ares_channel_t *channel,
const ares_sconfig_t *sconfig, const ares_sconfig_t *sconfig,
size_t idx) size_t idx)
{ {
ares_status_t status; ares_status_t status;
struct server_state *server = ares_malloc_zero(sizeof(*server)); ares_server_t *server = ares_malloc_zero(sizeof(*server));
if (server == NULL) { if (server == NULL) {
return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
@ -641,8 +641,8 @@ done:
return status; return status;
} }
static ares_bool_t ares__server_in_newconfig(const struct server_state *server, static ares_bool_t ares__server_in_newconfig(const ares_server_t *server,
ares__llist_t *srvlist) ares__llist_t *srvlist)
{ {
ares__llist_node_t *node; ares__llist_node_t *node;
const ares_channel_t *channel = server->channel; const ares_channel_t *channel = server->channel;
@ -676,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); ares__slist_node_t *snode = ares__slist_node_first(channel->servers);
while (snode != NULL) { while (snode != NULL) {
ares__slist_node_t *snext = ares__slist_node_next(snode); ares__slist_node_t *snext = 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 (!ares__server_in_newconfig(server, srvlist)) { if (!ares__server_in_newconfig(server, srvlist)) {
/* This will clean up all server state via the destruction callback and /* This will clean up all server state via the destruction callback and
* move any queries to new servers */ * move any queries to new servers */
@ -726,7 +726,7 @@ ares_status_t ares__servers_update(ares_channel_t *channel,
snode = ares__server_find(channel, sconfig); snode = ares__server_find(channel, sconfig);
if (snode != NULL) { 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 /* Copy over link-local settings. Its possible some of this data has
* changed, maybe ... */ * changed, maybe ... */
@ -928,8 +928,8 @@ fail:
} }
/* Write out the details of a server to a buffer */ /* Write out the details of a server to a buffer */
ares_status_t ares_get_server_addr(const struct server_state *server, ares_status_t ares_get_server_addr(const ares_server_t *server,
ares__buf_t *buf) ares__buf_t *buf)
{ {
ares_status_t status; ares_status_t status;
char addr[INET6_ADDRSTRLEN]; char addr[INET6_ADDRSTRLEN];
@ -1000,7 +1000,7 @@ int ares_get_servers(const ares_channel_t *channel,
for (node = ares__slist_node_first(channel->servers); node != NULL; for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) { 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 */ /* Allocate storage for this server node appending it to the list */
srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_NODE); srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_NODE);
@ -1055,7 +1055,7 @@ int ares_get_servers_ports(const ares_channel_t *channel,
for (node = ares__slist_node_first(channel->servers); node != NULL; for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) { 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 */ /* Allocate storage for this server node appending it to the list */
srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_PORT_NODE); srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_PORT_NODE);
@ -1203,8 +1203,8 @@ char *ares_get_servers_csv(const ares_channel_t *channel)
for (node = ares__slist_node_first(channel->servers); node != NULL; for (node = ares__slist_node_first(channel->servers); node != NULL;
node = ares__slist_node_next(node)) { node = ares__slist_node_next(node)) {
ares_status_t status; ares_status_t status;
const struct server_state *server = ares__slist_node_val(node); const ares_server_t *server = ares__slist_node_val(node);
if (ares__buf_len(buf)) { if (ares__buf_len(buf)) {
status = ares__buf_append_byte(buf, ','); status = ares__buf_append_byte(buf, ',');

View file

@ -352,6 +352,9 @@
# define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1 # define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1
#endif #endif
/* Define to 1 if you have the `RegisterWaitForSingleObject' function. */
#define HAVE_REGISTERWAITFORSINGLEOBJECT 1
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) && \ #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) && \
!defined(__WATCOMC__) && !defined(WATT32) !defined(__WATCOMC__) && !defined(WATT32)
/* Define if you have if_nametoindex() */ /* Define if you have if_nametoindex() */
@ -362,6 +365,8 @@
# define HAVE_CONVERTINTERFACEINDEXTOLUID 1 # define HAVE_CONVERTINTERFACEINDEXTOLUID 1
/* Define to 1 if you have the `ConvertInterfaceLuidToNameA' function. */ /* Define to 1 if you have the `ConvertInterfaceLuidToNameA' function. */
# define HAVE_CONVERTINTERFACELUIDTONAMEA 1 # define HAVE_CONVERTINTERFACELUIDTONAMEA 1
/* Define to 1 if you have the `NotifyIpInterfaceChange' function. */
# define HAVE_NOTIFYIPINTERFACECHANGE 1
#endif #endif
/* ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- */

356
deps/cares/src/lib/dsa/ares__array.c vendored Normal file
View file

@ -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);
}

223
deps/cares/src/lib/dsa/ares__array.h vendored Normal file
View file

@ -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 */

View file

@ -195,13 +195,14 @@ void ares_event_configchg_destroy(ares_event_configchg_t *configchg)
return; return;
} }
# ifndef __WATCOMC__ # ifdef HAVE_NOTIFYIPINTERFACECHANGE
if (configchg->ifchg_hnd != NULL) { if (configchg->ifchg_hnd != NULL) {
CancelMibChangeNotify2(configchg->ifchg_hnd); CancelMibChangeNotify2(configchg->ifchg_hnd);
configchg->ifchg_hnd = NULL; configchg->ifchg_hnd = NULL;
} }
# endif # endif
# ifdef HAVE_REGISTERWAITFORSINGLEOBJECT
if (configchg->regip4_wait != NULL) { if (configchg->regip4_wait != NULL) {
UnregisterWait(configchg->regip4_wait); UnregisterWait(configchg->regip4_wait);
configchg->regip4_wait = NULL; configchg->regip4_wait = NULL;
@ -231,15 +232,15 @@ void ares_event_configchg_destroy(ares_event_configchg_t *configchg)
CloseHandle(configchg->regip6_event); CloseHandle(configchg->regip6_event);
configchg->regip6_event = NULL; configchg->regip6_event = NULL;
} }
# endif
ares_free(configchg); ares_free(configchg);
} }
# ifndef __WATCOMC__ # ifdef HAVE_NOTIFYIPINTERFACECHANGE
static void NETIOAPI_API_ static void NETIOAPI_API_
ares_event_configchg_ip_cb(PVOID CallerContext, ares_event_configchg_ip_cb(PVOID CallerContext, PMIB_IPINTERFACE_ROW Row,
PMIB_IPINTERFACE_ROW Row,
MIB_NOTIFICATION_TYPE NotificationType) MIB_NOTIFICATION_TYPE NotificationType)
{ {
ares_event_configchg_t *configchg = CallerContext; ares_event_configchg_t *configchg = CallerContext;
@ -252,9 +253,10 @@ static void NETIOAPI_API_
static ares_bool_t static ares_bool_t
ares_event_configchg_regnotify(ares_event_configchg_t *configchg) ares_event_configchg_regnotify(ares_event_configchg_t *configchg)
{ {
# if defined(__WATCOMC__) && !defined(REG_NOTIFY_THREAD_AGNOSTIC) # ifdef HAVE_REGISTERWAITFORSINGLEOBJECT
# define REG_NOTIFY_THREAD_AGNOSTIC 0x10000000L # if defined(__WATCOMC__) && !defined(REG_NOTIFY_THREAD_AGNOSTIC)
# endif # define REG_NOTIFY_THREAD_AGNOSTIC 0x10000000L
# endif
DWORD flags = REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET | DWORD flags = REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET |
REG_NOTIFY_THREAD_AGNOSTIC; REG_NOTIFY_THREAD_AGNOSTIC;
@ -267,7 +269,9 @@ static ares_bool_t
configchg->regip6_event, TRUE) != ERROR_SUCCESS) { configchg->regip6_event, TRUE) != ERROR_SUCCESS) {
return ARES_FALSE; return ARES_FALSE;
} }
# else
(void)configchg;
# endif
return ARES_TRUE; return ARES_TRUE;
} }
@ -297,27 +301,27 @@ ares_status_t ares_event_configchg_init(ares_event_configchg_t **configchg,
c->e = e; c->e = e;
# ifndef __WATCOMC__ # ifdef HAVE_NOTIFYIPINTERFACECHANGE
/* NOTE: If a user goes into the control panel and changes the network /* NOTE: If a user goes into the control panel and changes the network
* adapter DNS addresses manually, this will NOT trigger a notification. * adapter DNS addresses manually, this will NOT trigger a notification.
* We've also tried listening on NotifyUnicastIpAddressChange(), but * We've also tried listening on NotifyUnicastIpAddressChange(), but
* that didn't get triggered either. * that didn't get triggered either.
*/ */
if (NotifyIpInterfaceChange( if (NotifyIpInterfaceChange(AF_UNSPEC, ares_event_configchg_ip_cb, c, FALSE,
AF_UNSPEC, ares_event_configchg_ip_cb, &c->ifchg_hnd) != NO_ERROR) {
c, FALSE, &c->ifchg_hnd) != NO_ERROR) {
status = ARES_ESERVFAIL; status = ARES_ESERVFAIL;
goto done; goto done;
} }
# endif # endif
# ifdef HAVE_REGISTERWAITFORSINGLEOBJECT
/* Monitor HKLM\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters\Interfaces /* Monitor HKLM\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters\Interfaces
* and HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces * and HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces
* for changes via RegNotifyChangeKeyValue() */ * for changes via RegNotifyChangeKeyValue() */
if (RegOpenKeyExW( if (RegOpenKeyExW(
HKEY_LOCAL_MACHINE, HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces", 0, L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces",
KEY_NOTIFY, &c->regip4) != ERROR_SUCCESS) { 0, KEY_NOTIFY, &c->regip4) != ERROR_SUCCESS) {
status = ARES_ESERVFAIL; status = ARES_ESERVFAIL;
goto done; goto done;
} }
@ -355,6 +359,7 @@ ares_status_t ares_event_configchg_init(ares_event_configchg_t **configchg,
status = ARES_ESERVFAIL; status = ARES_ESERVFAIL;
goto done; goto done;
} }
# endif
if (!ares_event_configchg_regnotify(c)) { if (!ares_event_configchg_regnotify(c)) {
status = ARES_ESERVFAIL; status = ARES_ESERVFAIL;
@ -472,8 +477,8 @@ ares_status_t ares_event_configchg_init(ares_event_configchg_t **configchg,
continue; continue;
} }
pdns_configuration_notify_key = (const char *(*)(void)) pdns_configuration_notify_key =
dlsym(handle, "dns_configuration_notify_key"); (const char *(*)(void))dlsym(handle, "dns_configuration_notify_key");
if (pdns_configuration_notify_key != NULL) { if (pdns_configuration_notify_key != NULL) {
break; break;
} }
@ -551,7 +556,7 @@ static ares_status_t config_change_check(ares__htable_strvp_t *filestat,
{ {
size_t i; size_t i;
const char *configfiles[5]; const char *configfiles[5];
ares_bool_t changed = ARES_FALSE; ares_bool_t changed = ARES_FALSE;
configfiles[0] = resolvconf_path; configfiles[0] = resolvconf_path;
configfiles[1] = "/etc/nsswitch.conf"; configfiles[1] = "/etc/nsswitch.conf";

View file

@ -123,11 +123,9 @@ static void ares_evsys_kqueue_enqueue(ares_evsys_kqueue_t *kq, int fd,
if (kq->nchanges > kq->nchanges_alloc) { if (kq->nchanges > kq->nchanges_alloc) {
kq->nchanges_alloc <<= 1; kq->nchanges_alloc <<= 1;
kq->changelist = ares_realloc_zero( kq->changelist = ares_realloc_zero(
kq->changelist, kq->changelist, (kq->nchanges_alloc >> 1) * sizeof(*kq->changelist),
(kq->nchanges_alloc >> 1) * sizeof(*kq->changelist), kq->nchanges_alloc * sizeof(*kq->changelist));
kq->nchanges_alloc * sizeof(*kq->changelist)
);
} }
EV_SET(&kq->changelist[idx], fd, filter, flags, 0, 0, 0); EV_SET(&kq->changelist[idx], fd, filter, flags, 0, 0, 0);
@ -198,7 +196,7 @@ static size_t ares_evsys_kqueue_wait(ares_event_thread_t *e,
size_t cnt = 0; size_t cnt = 0;
if (timeout_ms != 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; ts.tv_nsec = (timeout_ms % 1000) * 1000 * 1000;
timeout = &ts; timeout = &ts;
} }

View file

@ -47,6 +47,23 @@ static void ares_event_destroy_cb(void *arg)
ares_free(event); 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 /* 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 * 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 * of updates already enqueued. In the future, it might make sense to make
@ -86,6 +103,7 @@ ares_status_t ares_event_update(ares_event_t **event, ares_event_thread_t *e,
ares_event_signal_cb_t signal_cb) ares_event_signal_cb_t signal_cb)
{ {
ares_event_t *ev = NULL; ares_event_t *ev = NULL;
ares_status_t status;
if (e == NULL) { if (e == NULL) {
return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
@ -116,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 */ /* That's all the validation we can really do */
ares__thread_mutex_lock(e->mutex);
/* See if we have a queued update already */ /* See if we have a queued update already */
ev = ares_event_update_find(e, fd, data); ev = ares_event_update_find(e, fd, data);
if (ev == NULL) { if (ev == NULL) {
/* Allocate a new one */ /* Allocate a new one */
ev = ares_malloc_zero(sizeof(*ev)); ev = ares_malloc_zero(sizeof(*ev));
if (ev == NULL) { if (ev == NULL) {
return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
goto done; /* LCOV_EXCL_LINE: OutOfMemory */
} }
if (ares__llist_insert_last(e->ev_updates, ev) == NULL) { if (ares__llist_insert_last(e->ev_updates, ev) == NULL) {
ares_free(ev); /* LCOV_EXCL_LINE: OutOfMemory */ ares_free(ev); /* LCOV_EXCL_LINE: OutOfMemory */
return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */ status = ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
goto done; /* LCOV_EXCL_LINE: OutOfMemory */
} }
} }
@ -150,24 +172,17 @@ ares_status_t ares_event_update(ares_event_t **event, ares_event_thread_t *e,
*event = ev; *event = ev;
} }
return ARES_SUCCESS; status = ARES_SUCCESS;
}
static void ares_event_signal(const ares_event_t *event) done:
{ if (status == ARES_SUCCESS) {
if (event == NULL || event->signal_cb == NULL) { /* Wake event thread if successful so it can pull the updates */
return; /* LCOV_EXCL_LINE: DefensiveCoding */ 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; /* LCOV_EXCL_LINE: DefensiveCoding */
} }
ares_event_signal(e->ev_signal); ares__thread_mutex_unlock(e->mutex);
return status;
} }
static void ares_event_thread_process_fd(ares_event_thread_t *e, static void ares_event_thread_process_fd(ares_event_thread_t *e,
@ -195,15 +210,10 @@ static void ares_event_thread_sockstate_cb(void *data, ares_socket_t socket_fd,
flags |= ARES_EVENT_FLAG_WRITE; flags |= ARES_EVENT_FLAG_WRITE;
} }
/* Update channel fd */ /* Update channel fd. This function will lock e->mutex and also wake the
ares__thread_mutex_lock(e->mutex); * event thread to process the update */
ares_event_update(NULL, e, flags, ares_event_thread_process_fd, socket_fd, ares_event_update(NULL, e, flags, ares_event_thread_process_fd, socket_fd,
NULL, NULL, NULL); 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) static void ares_event_process_updates(ares_event_thread_t *e)
@ -370,7 +380,7 @@ void ares_event_thread_destroy(ares_channel_t *channel)
ares_event_thread_destroy_int(e); ares_event_thread_destroy_int(e);
channel->sock_state_cb_data = NULL; channel->sock_state_cb_data = NULL;
channel->sock_state_cb = NULL; channel->sock_state_cb = NULL;
} }
static const ares_event_sys_t *ares_event_fetch_sys(ares_evsys_t evsys) static const ares_event_sys_t *ares_event_fetch_sys(ares_evsys_t evsys)

View file

@ -25,9 +25,13 @@
*/ */
/* Uses an anonymous union */ /* Uses an anonymous union */
#if defined(__clang__) #if defined(__clang__) || defined(__GNUC__)
# pragma GCC diagnostic push # pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wc11-extensions" # if defined(__clang__)
# pragma GCC diagnostic ignored "-Wc11-extensions"
# else
# pragma GCC diagnostic ignored "-Wpedantic"
# endif
#endif #endif
#include "ares_private.h" #include "ares_private.h"
@ -967,6 +971,6 @@ const ares_event_sys_t ares_evsys_win32 = { "win32",
ares_evsys_win32_wait }; ares_evsys_win32_wait };
#endif #endif
#if defined(__clang__) #if defined(__clang__) || defined(__GNUC__)
# pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif #endif

View file

@ -32,11 +32,6 @@
#include "ares_ipv6.h" #include "ares_ipv6.h"
#include "ares_inet_net_pton.h" #include "ares_inet_net_pton.h"
#define ISDIGIT(x) (isdigit((int)((unsigned char)x)))
#define ISXDIGIT(x) (isxdigit((int)((unsigned char)x)))
#define ISASCII(x) (((unsigned char)x) <= 127 ? 1 : 0)
#define ISUPPER(x) (isupper((int)((unsigned char)x)))
const struct ares_in6_addr ares_in6addr_any = { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, const struct ares_in6_addr ares_in6addr_any = { { { 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0 } } }; 0, 0, 0, 0, 0, 0, 0 } } };
@ -74,16 +69,16 @@ static int ares_inet_net_pton_ipv4(const char *src, unsigned char *dst,
const unsigned char *odst = dst; const unsigned char *odst = dst;
ch = *src++; ch = *src++;
if (ch == '0' && (src[0] == 'x' || src[0] == 'X') && ISASCII(src[1]) && if (ch == '0' && (src[0] == 'x' || src[0] == 'X') && ares__isascii(src[1]) &&
ISXDIGIT(src[1])) { ares__isxdigit(src[1])) {
/* Hexadecimal: Eat nybble string. */ /* Hexadecimal: Eat nybble string. */
if (!size) { if (!size) {
goto emsgsize; goto emsgsize;
} }
dirty = 0; dirty = 0;
src++; /* skip x or X. */ src++; /* skip x or X. */
while ((ch = *src++) != '\0' && ISASCII(ch) && ISXDIGIT(ch)) { while ((ch = *src++) != '\0' && ares__isascii(ch) && ares__isxdigit(ch)) {
if (ISUPPER(ch)) { if (ares__isupper(ch)) {
ch = ares__tolower((unsigned char)ch); ch = ares__tolower((unsigned char)ch);
} }
n = (int)(strchr(xdigits, ch) - xdigits); n = (int)(strchr(xdigits, ch) - xdigits);
@ -106,7 +101,7 @@ static int ares_inet_net_pton_ipv4(const char *src, unsigned char *dst,
} }
*dst++ = (unsigned char)(tmp << 4); *dst++ = (unsigned char)(tmp << 4);
} }
} else if (ISASCII(ch) && ISDIGIT(ch)) { } else if (ares__isascii(ch) && ares__isdigit(ch)) {
/* Decimal: eat dotted digit string. */ /* Decimal: eat dotted digit string. */
for (;;) { for (;;) {
tmp = 0; tmp = 0;
@ -117,7 +112,7 @@ static int ares_inet_net_pton_ipv4(const char *src, unsigned char *dst,
if (tmp > 255) { if (tmp > 255) {
goto enoent; goto enoent;
} }
} while ((ch = *src++) != '\0' && ISASCII(ch) && ISDIGIT(ch)); } while ((ch = *src++) != '\0' && ares__isascii(ch) && ares__isdigit(ch));
if (!size--) { if (!size--) {
goto emsgsize; goto emsgsize;
} }
@ -129,7 +124,7 @@ static int ares_inet_net_pton_ipv4(const char *src, unsigned char *dst,
goto enoent; goto enoent;
} }
ch = *src++; ch = *src++;
if (!ISASCII(ch) || !ISDIGIT(ch)) { if (!ares__isascii(ch) || !ares__isdigit(ch)) {
goto enoent; goto enoent;
} }
} }
@ -138,7 +133,8 @@ static int ares_inet_net_pton_ipv4(const char *src, unsigned char *dst,
} }
bits = -1; 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. */ /* CIDR width specifier. Nothing can follow it. */
ch = *src++; /* Skip over the /. */ ch = *src++; /* Skip over the /. */
bits = 0; bits = 0;
@ -149,7 +145,7 @@ static int ares_inet_net_pton_ipv4(const char *src, unsigned char *dst,
if (bits > 32) { if (bits > 32) {
goto enoent; goto enoent;
} }
} while ((ch = *src++) != '\0' && ISASCII(ch) && ISDIGIT(ch)); } while ((ch = *src++) != '\0' && ares__isascii(ch) && ares__isdigit(ch));
if (ch != '\0') { if (ch != '\0') {
goto enoent; goto enoent;
} }

View file

@ -138,7 +138,7 @@ static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size)
if (words[i] == 0) { if (words[i] == 0) {
if (cur.base == -1) { if (cur.base == -1) {
cur.base = (ares_ssize_t)i; cur.base = (ares_ssize_t)i;
cur.len = 1; cur.len = 1;
} else { } else {
cur.len++; cur.len++;
} }
@ -166,7 +166,8 @@ static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size)
tp = tmp; tp = tmp;
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
/* Are we inside the best run of 0x00's? */ /* Are we inside the best run of 0x00's? */
if (best.base != -1 && i >= (size_t)best.base && i < ((size_t)best.base + best.len)) { if (best.base != -1 && i >= (size_t)best.base &&
i < ((size_t)best.base + best.len)) {
if (i == (size_t)best.base) { if (i == (size_t)best.base) {
*tp++ = ':'; *tp++ = ':';
} }
@ -205,4 +206,3 @@ static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size)
ares_strcpy(dst, tmp, size); ares_strcpy(dst, tmp, size);
return dst; return dst;
} }

View file

@ -74,8 +74,7 @@ ares_status_t ares_expand_string_ex(const unsigned char *encoded,
} }
start_len = ares__buf_len(buf); start_len = ares__buf_len(buf);
status = status = ares__buf_parse_dns_binstr(buf, ares__buf_len(buf), s, &len);
ares__buf_parse_dns_binstr(buf, ares__buf_len(buf), s, &len);
/* hrm, no way to pass back 'len' with the prototype */ /* hrm, no way to pass back 'len' with the prototype */
if (status != ARES_SUCCESS) { if (status != ARES_SUCCESS) {
goto done; goto done;

View file

@ -45,14 +45,14 @@ int ares_fds(const ares_channel_t *channel, fd_set *read_fds, fd_set *write_fds)
nfds = 0; nfds = 0;
for (snode = ares__slist_node_first(channel->servers); snode != NULL; for (snode = ares__slist_node_first(channel->servers); snode != NULL;
snode = ares__slist_node_next(snode)) { snode = ares__slist_node_next(snode)) {
struct server_state *server = ares__slist_node_val(snode); ares_server_t *server = ares__slist_node_val(snode);
ares__llist_node_t *node; ares__llist_node_t *node;
for (node = ares__llist_node_first(server->connections); node != NULL; for (node = ares__llist_node_first(server->connections); node != NULL;
node = ares__llist_node_next(node)) { 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; continue;
} }
@ -69,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 */ /* 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); FD_SET(conn->fd, write_fds);
} }
} }

View file

@ -47,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; for (snode = ares__slist_node_first(channel->servers); snode != NULL;
snode = ares__slist_node_next(snode)) { snode = ares__slist_node_next(snode)) {
struct server_state *server = ares__slist_node_val(snode); ares_server_t *server = ares__slist_node_val(snode);
ares__llist_node_t *node; ares__llist_node_t *node;
for (node = ares__llist_node_first(server->connections); node != NULL; for (node = ares__llist_node_first(server->connections); node != NULL;
node = ares__llist_node_next(node)) { 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) { if (sockindex >= (size_t)numsocks || sockindex >= ARES_GETSOCK_MAXNUM) {
break; break;
@ -61,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 /* We only need to register interest in UDP sockets if we have
* outstanding queries. * outstanding queries.
*/ */
if (!active_queries && !conn->is_tcp) { if (!active_queries && !(conn->flags & ARES_CONN_FLAG_TCP)) {
continue; continue;
} }
socks[sockindex] = conn->fd; 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); 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! */ /* then the tcp socket is also writable! */
bitmap |= ARES_GETSOCK_WRITABLE(setbits, sockindex); bitmap |= ARES_GETSOCK_WRITABLE(setbits, sockindex);
} }

View file

@ -71,7 +71,7 @@ static int ares__parse_txt_reply(const unsigned char *abuf, size_t alen,
cnt = ares_dns_rr_get_abin_cnt(rr, ARES_RR_TXT_DATA); cnt = ares_dns_rr_get_abin_cnt(rr, ARES_RR_TXT_DATA);
for (j=0; j<cnt; j++) { for (j = 0; j < cnt; j++) {
const unsigned char *ptr; const unsigned char *ptr;
size_t ptr_len; size_t ptr_len;

View file

@ -33,35 +33,50 @@ typedef struct {
struct ares__dns_multistring { struct ares__dns_multistring {
/*! whether or not cached concatenated string is valid */ /*! whether or not cached concatenated string is valid */
ares_bool_t cache_invalidated; ares_bool_t cache_invalidated;
/*! combined/concatenated string cache */ /*! combined/concatenated string cache */
unsigned char *cache_str; unsigned char *cache_str;
/*! length of combined/concatenated string */ /*! length of combined/concatenated string */
size_t cache_str_len; size_t cache_str_len;
/*! Data making up strings */ /*! Data making up strings */
multistring_data_t *strs; ares__array_t *strs; /*!< multistring_data_t type */
size_t cnt;
size_t alloc;
}; };
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 *ares__dns_multistring_create(void)
{ {
return ares_malloc_zero(sizeof(ares__dns_multistring_t)); 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) void ares__dns_multistring_clear(ares__dns_multistring_t *strs)
{ {
size_t i;
if (strs == NULL) { if (strs == NULL) {
return; return;
} }
for (i = 0; i < strs->cnt; i++) { while (ares__array_len(strs->strs)) {
ares_free(strs->strs[i].data); ares__array_remove_last(strs->strs);
memset(&strs->strs[i], 0, sizeof(strs->strs[i]));
} }
strs->cnt = 0;
} }
void ares__dns_multistring_destroy(ares__dns_multistring_t *strs) void ares__dns_multistring_destroy(ares__dns_multistring_t *strs)
@ -70,7 +85,7 @@ void ares__dns_multistring_destroy(ares__dns_multistring_t *strs)
return; return;
} }
ares__dns_multistring_clear(strs); ares__dns_multistring_clear(strs);
ares_free(strs->strs); ares__array_destroy(strs->strs);
ares_free(strs->cache_str); ares_free(strs->cache_str);
ares_free(strs); ares_free(strs);
} }
@ -79,43 +94,43 @@ ares_status_t ares__dns_multistring_replace_own(ares__dns_multistring_t *strs,
size_t idx, unsigned char *str, size_t idx, unsigned char *str,
size_t len) size_t len)
{ {
if (strs == NULL || str == NULL || len == 0 || idx >= strs->cnt) { multistring_data_t *data;
if (strs == NULL || str == NULL || len == 0) {
return ARES_EFORMERR; return ARES_EFORMERR;
} }
strs->cache_invalidated = ARES_TRUE; strs->cache_invalidated = ARES_TRUE;
ares_free(strs->strs[idx].data);
strs->strs[idx].data = str; data = ares__array_at(strs->strs, idx);
strs->strs[idx].len = len; if (data == NULL) {
return ARES_EFORMERR;
}
ares_free(data->data);
data->data = str;
data->len = len;
return ARES_SUCCESS; return ARES_SUCCESS;
} }
ares_status_t ares__dns_multistring_del(ares__dns_multistring_t *strs, ares_status_t ares__dns_multistring_del(ares__dns_multistring_t *strs,
size_t idx) size_t idx)
{ {
size_t move_cnt; if (strs == NULL) {
if (strs == NULL || idx >= strs->cnt) {
return ARES_EFORMERR; return ARES_EFORMERR;
} }
strs->cache_invalidated = ARES_TRUE; strs->cache_invalidated = ARES_TRUE;
ares_free(strs->strs[idx].data); return ares__array_remove_at(strs->strs, idx);
move_cnt = strs->cnt - idx - 1;
if (move_cnt) {
memmove(&strs->strs[idx], &strs->strs[idx + 1],
sizeof(*strs->strs) * move_cnt);
}
strs->cnt--;
return ARES_SUCCESS;
} }
ares_status_t ares__dns_multistring_add_own(ares__dns_multistring_t *strs, ares_status_t ares__dns_multistring_add_own(ares__dns_multistring_t *strs,
unsigned char *str, size_t len) unsigned char *str, size_t len)
{ {
multistring_data_t *data;
ares_status_t status;
if (strs == NULL) { if (strs == NULL) {
return ARES_EFORMERR; return ARES_EFORMERR;
} }
@ -127,20 +142,13 @@ ares_status_t ares__dns_multistring_add_own(ares__dns_multistring_t *strs,
return ARES_EFORMERR; return ARES_EFORMERR;
} }
if (strs->alloc < strs->cnt + 1) { status = ares__array_insert_last((void **)&data, strs->strs);
size_t newalloc = (strs->alloc == 0) ? 1 : (strs->alloc << 1); if (status != ARES_SUCCESS) {
void *ptr = ares_realloc_zero(strs->strs, strs->alloc * sizeof(*strs->strs), return status;
(newalloc) * sizeof(*strs->strs));
if (ptr == NULL) {
return ARES_ENOMEM;
}
strs->strs = ptr;
strs->alloc = newalloc;
} }
strs->strs[strs->cnt].data = str; data->data = str;
strs->strs[strs->cnt].len = len; data->len = len;
strs->cnt++;
return ARES_SUCCESS; return ARES_SUCCESS;
} }
@ -150,18 +158,26 @@ size_t ares__dns_multistring_cnt(const ares__dns_multistring_t *strs)
if (strs == NULL) { if (strs == NULL) {
return 0; return 0;
} }
return strs->cnt; return ares__array_len(strs->strs);
} }
const unsigned char *ares__dns_multistring_get( const unsigned char *
const ares__dns_multistring_t *strs, size_t idx, size_t *len) ares__dns_multistring_get(const ares__dns_multistring_t *strs, size_t idx,
size_t *len)
{ {
if (strs == NULL || idx >= strs->cnt || len == NULL) { const multistring_data_t *data;
if (strs == NULL || len == NULL) {
return NULL; return NULL;
} }
*len = strs->strs[idx].len; data = ares__array_at_const(strs->strs, idx);
return strs->strs[idx].data; if (data == NULL) {
return NULL;
}
*len = data->len;
return data->data;
} }
const unsigned char * const unsigned char *
@ -189,9 +205,10 @@ const unsigned char *
buf = ares__buf_create(); buf = ares__buf_create();
for (i = 0; i < strs->cnt; i++) { for (i = 0; i < ares__array_len(strs->strs); i++) {
if (ares__buf_append(buf, strs->strs[i].data, strs->strs[i].len) != const multistring_data_t *data = ares__array_at_const(strs->strs, i);
ARES_SUCCESS) { if (data == NULL ||
ares__buf_append(buf, data->data, data->len) != ARES_SUCCESS) {
ares__buf_destroy(buf); ares__buf_destroy(buf);
return NULL; return NULL;
} }

View file

@ -40,8 +40,9 @@ ares_status_t ares__dns_multistring_del(ares__dns_multistring_t *strs,
ares_status_t ares__dns_multistring_add_own(ares__dns_multistring_t *strs, ares_status_t ares__dns_multistring_add_own(ares__dns_multistring_t *strs,
unsigned char *str, size_t len); unsigned char *str, size_t len);
size_t ares__dns_multistring_cnt(const ares__dns_multistring_t *strs); size_t ares__dns_multistring_cnt(const ares__dns_multistring_t *strs);
const unsigned char *ares__dns_multistring_get( const unsigned char *
const ares__dns_multistring_t *strs, size_t idx, size_t *len); ares__dns_multistring_get(const ares__dns_multistring_t *strs, size_t idx,
size_t *len);
const unsigned char * const unsigned char *
ares__dns_multistring_get_combined(ares__dns_multistring_t *strs, ares__dns_multistring_get_combined(ares__dns_multistring_t *strs,
size_t *len); size_t *len);

View file

@ -131,72 +131,62 @@ static const ares_nameoffset_t *ares__nameoffset_find(ares__llist_t *list,
return longest_match; return longest_match;
} }
typedef struct { static void ares_dns_labels_free_cb(void *arg)
ares__buf_t **label;
size_t num;
} ares_dns_labels_t;
static void ares_dns_labels_free(ares_dns_labels_t *labels)
{ {
size_t i; ares__buf_t **buf = arg;
if (buf == NULL) {
if (labels == NULL) { return;
return; /* LCOV_EXCL_LINE: DefensiveCoding */
} }
for (i = 0; i < labels->num; i++) { ares__buf_destroy(*buf);
ares__buf_destroy(labels->label[i]);
labels->label[i] = NULL;
}
ares_free(labels->label);
labels->label = NULL;
labels->num = 0;
} }
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) { if (labels == NULL) {
return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */ return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
} }
temp = ares_realloc_zero(labels->label, sizeof(*labels->label) * labels->num, if (ares__array_insert_last((void **)&buf, labels) != ARES_SUCCESS) {
sizeof(*labels->label) * (labels->num + 1)); return NULL;
if (temp == NULL) {
return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
} }
labels->label = temp; *buf = ares__buf_create();
if (*buf == NULL) {
labels->label[labels->num] = ares__buf_create(); ares__array_remove_last(labels);
if (labels->label[labels->num] == NULL) { return NULL;
return NULL; /* LCOV_EXCL_LINE: OutOfMemory */
} }
labels->num++; return *buf;
return labels->label[labels->num - 1];
} }
static const ares__buf_t * static ares__buf_t *ares_dns_labels_get_last(ares__array_t *labels)
ares_dns_labels_get_last(const ares_dns_labels_t *labels)
{ {
if (labels == NULL || labels->num == 0) { ares__buf_t **buf = ares__array_last(labels);
return NULL; /* LCOV_EXCL_LINE: DefensiveCoding */
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) { ares__buf_t **buf = ares__array_at(labels, idx);
return; /* LCOV_EXCL_LINE: DefensiveCoding */
if (buf == NULL) {
return NULL;
} }
ares__buf_destroy(labels->label[labels->num - 1]); return *buf;
labels->label[labels->num - 1] = NULL; }
labels->num--;
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, static ares_status_t ares_parse_dns_name_escape(ares__buf_t *namebuf,
@ -212,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 next character is a digit, read 2 more digits */
if (isdigit(c)) { if (ares__isdigit(c)) {
size_t i; size_t i;
unsigned int val = 0; unsigned int val = 0;
@ -224,7 +214,7 @@ static ares_status_t ares_parse_dns_name_escape(ares__buf_t *namebuf,
return ARES_EBADNAME; return ARES_EBADNAME;
} }
if (!isdigit(c)) { if (!ares__isdigit(c)) {
return ARES_EBADNAME; return ARES_EBADNAME;
} }
val *= 10; val *= 10;
@ -251,9 +241,9 @@ static ares_status_t ares_parse_dns_name_escape(ares__buf_t *namebuf,
return ares__buf_append_byte(label, c); return ares__buf_append_byte(label, c);
} }
static ares_status_t ares_split_dns_name(ares_dns_labels_t *labels, static ares_status_t ares_split_dns_name(ares__array_t *labels,
ares_bool_t validate_hostname, ares_bool_t validate_hostname,
const char *name) const char *name)
{ {
ares_status_t status; ares_status_t status;
ares__buf_t *label = NULL; ares__buf_t *label = NULL;
@ -327,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 /* If someone passed in "." there could have been 2 blank labels, check for
* that */ * that */
if (labels->num == 1 && if (ares__array_len(labels) == 1 &&
ares__buf_len(ares_dns_labels_get_last(labels)) == 0) { ares__buf_len(ares_dns_labels_get_last(labels)) == 0) {
ares_dns_name_labels_del_last(labels); ares_dns_name_labels_del_last(labels);
} }
/* Scan to make sure label lengths are valid */ /* Scan to make sure label lengths are valid */
for (i = 0; i < labels->num; i++) { for (i = 0; i < ares__array_len(labels); i++) {
size_t len = ares__buf_len(labels->label[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 */ /* No 0-length labels, and no labels over 63 bytes */
if (len == 0 || len > 63) { if (len == 0 || len > 63) {
status = ARES_EBADNAME; status = ARES_EBADNAME;
@ -344,7 +335,8 @@ static ares_status_t ares_split_dns_name(ares_dns_labels_t *labels,
} }
/* Can't exceed maximum (unescaped) length */ /* 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; status = ARES_EBADNAME;
goto done; goto done;
} }
@ -353,9 +345,6 @@ static ares_status_t ares_split_dns_name(ares_dns_labels_t *labels,
done: done:
ares__buf_destroy(namebuf); ares__buf_destroy(namebuf);
if (status != ARES_SUCCESS) {
ares_dns_labels_free(labels);
}
return status; return status;
} }
@ -366,8 +355,8 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
const ares_nameoffset_t *off = NULL; const ares_nameoffset_t *off = NULL;
size_t name_len; size_t name_len;
size_t orig_name_len; size_t orig_name_len;
size_t pos = ares__buf_len(buf); size_t pos = ares__buf_len(buf);
ares_dns_labels_t labels; ares__array_t *labels = NULL;
char name_copy[512]; char name_copy[512];
ares_status_t status; ares_status_t status;
@ -375,7 +364,10 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */ 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 /* NOTE: due to possible escaping, name_copy buffer is > 256 to allow for
* this */ * this */
@ -396,14 +388,15 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
if (off == NULL || off->name_len != orig_name_len) { if (off == NULL || off->name_len != orig_name_len) {
size_t i; 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) { if (status != ARES_SUCCESS) {
goto done; goto done;
} }
for (i = 0; i < labels.num; i++) { for (i = 0; i < ares__array_len(labels); i++) {
size_t len = 0; size_t len = 0;
const unsigned char *ptr = ares__buf_peek(labels.label[i], &len); 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)); status = ares__buf_append_byte(buf, (unsigned char)(len & 0xFF));
if (status != ARES_SUCCESS) { if (status != ARES_SUCCESS) {
@ -448,7 +441,7 @@ ares_status_t ares__dns_name_write(ares__buf_t *buf, ares__llist_t **list,
status = ARES_SUCCESS; status = ARES_SUCCESS;
done: done:
ares_dns_labels_free(&labels); ares__array_destroy(labels);
return status; return status;
} }

View file

@ -26,7 +26,7 @@
#ifndef __ARES_DNS_PRIVATE_H #ifndef __ARES_DNS_PRIVATE_H
#define __ARES_DNS_PRIVATE_H #define __ARES_DNS_PRIVATE_H
ares_status_t ares_dns_record_duplicate_ex(ares_dns_record_t **dest, ares_status_t ares_dns_record_duplicate_ex(ares_dns_record_t **dest,
const ares_dns_record_t *src); 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_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_opcode_isvalid(ares_dns_opcode_t opcode);
@ -38,23 +38,32 @@ ares_bool_t ares_dns_class_isvalid(ares_dns_class_t qclass,
ares_dns_rec_type_t type, ares_dns_rec_type_t type,
ares_bool_t is_query); ares_bool_t is_query);
ares_bool_t ares_dns_section_isvalid(ares_dns_section_t sect); 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_status_t ares_dns_rr_set_str_own(ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key, char *val); ares_dns_rr_key_t key, char *val);
ares_status_t ares_dns_rr_set_bin_own(ares_dns_rr_t *dns_rr, ares_status_t ares_dns_rr_set_bin_own(ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key, unsigned char *val, ares_dns_rr_key_t key, unsigned char *val,
size_t len); size_t len);
ares_status_t ares_dns_rr_set_abin_own(ares_dns_rr_t *dns_rr, ares_status_t ares_dns_rr_set_abin_own(ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key, ares_dns_rr_key_t key,
ares__dns_multistring_t *strs); ares__dns_multistring_t *strs);
ares_status_t ares_dns_rr_set_opt_own(ares_dns_rr_t *dns_rr, ares_status_t ares_dns_rr_set_opt_own(ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key, unsigned short opt, ares_dns_rr_key_t key, unsigned short opt,
unsigned char *val, size_t val_len); unsigned char *val, size_t val_len);
ares_status_t ares_dns_record_rr_prealloc(ares_dns_record_t *dnsrec, ares_status_t ares_dns_record_rr_prealloc(ares_dns_record_t *dnsrec,
ares_dns_section_t sect, size_t cnt); ares_dns_section_t sect, size_t cnt);
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);
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, void ares_dns_record_write_ttl_decrement(ares_dns_record_t *dnsrec,
unsigned int ttl_decrement); 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 /*! Create a DNS record object for a query. The arguments are the same as
* those for ares_create_query(). * those for ares_create_query().
* *
@ -168,18 +177,11 @@ typedef struct {
} ares__dns_optval_t; } ares__dns_optval_t;
typedef struct { typedef struct {
ares__dns_optval_t *optval; /*!< Attribute/value pairs */ unsigned short udp_size; /*!< taken from class */
size_t cnt; /*!< Count of Attribute/Value pairs */ unsigned char version; /*!< taken from bits 8-16 of ttl */
size_t alloc; /*!< Allocated count of attribute/value unsigned short flags; /*!< Flags, remaining 16 bits, though only
* pairs */ * 1 currently defined */
} ares__dns_options_t; ares__array_t *options; /*!< Type is ares__dns_optval_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 */
} ares__dns_opt_t; } ares__dns_opt_t;
typedef struct { typedef struct {
@ -191,9 +193,9 @@ typedef struct {
} ares__dns_tlsa_t; } ares__dns_tlsa_t;
typedef struct { typedef struct {
unsigned short priority; unsigned short priority;
char *target; char *target;
ares__dns_options_t *params; ares__array_t *params; /*!< Type is ares__dns_optval_t */
} ares__dns_svcb_t; } ares__dns_svcb_t;
typedef struct { typedef struct {
@ -262,21 +264,10 @@ struct ares_dns_record {
* the ttl of any resource records by * the ttl of any resource records by
* this amount. Used for cache */ * this amount. Used for cache */
ares_dns_qd_t *qd; ares__array_t *qd; /*!< Type is ares_dns_qd_t */
size_t qdcount; ares__array_t *an; /*!< Type is ares_dns_rr_t */
size_t qdalloc; ares__array_t *ns; /*!< Type is ares_dns_rr_t */
ares__array_t *ar; /*!< Type is ares_dns_rr_t */
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;
}; };
#endif #endif

View file

@ -29,6 +29,25 @@
# include <stdint.h> # include <stdint.h>
#endif #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, ares_status_t ares_dns_record_create(ares_dns_record_t **dnsrec,
unsigned short id, unsigned short flags, unsigned short id, unsigned short flags,
@ -55,6 +74,22 @@ ares_status_t ares_dns_record_create(ares_dns_record_t **dnsrec,
(*dnsrec)->flags = flags; (*dnsrec)->flags = flags;
(*dnsrec)->opcode = opcode; (*dnsrec)->opcode = opcode;
(*dnsrec)->rcode = rcode; (*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; return ARES_SUCCESS;
} }
@ -99,21 +134,6 @@ ares_dns_rcode_t ares_dns_record_get_rcode(const ares_dns_record_t *dnsrec)
return dnsrec->rcode; 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) static void ares__dns_rr_free(ares_dns_rr_t *rr)
{ {
ares_free(rr->name); ares_free(rr->name);
@ -172,7 +192,7 @@ static void ares__dns_rr_free(ares_dns_rr_t *rr)
break; break;
case ARES_REC_TYPE_OPT: case ARES_REC_TYPE_OPT:
ares__dns_options_free(rr->r.opt.options); ares__array_destroy(rr->r.opt.options);
break; break;
case ARES_REC_TYPE_TLSA: case ARES_REC_TYPE_TLSA:
@ -181,12 +201,12 @@ static void ares__dns_rr_free(ares_dns_rr_t *rr)
case ARES_REC_TYPE_SVCB: case ARES_REC_TYPE_SVCB:
ares_free(rr->r.svcb.target); ares_free(rr->r.svcb.target);
ares__dns_options_free(rr->r.svcb.params); ares__array_destroy(rr->r.svcb.params);
break; break;
case ARES_REC_TYPE_HTTPS: case ARES_REC_TYPE_HTTPS:
ares_free(rr->r.https.target); ares_free(rr->r.https.target);
ares__dns_options_free(rr->r.https.params); ares__array_destroy(rr->r.https.params);
break; break;
case ARES_REC_TYPE_URI: case ARES_REC_TYPE_URI:
@ -206,35 +226,21 @@ static void ares__dns_rr_free(ares_dns_rr_t *rr)
void ares_dns_record_destroy(ares_dns_record_t *dnsrec) void ares_dns_record_destroy(ares_dns_record_t *dnsrec)
{ {
size_t i;
if (dnsrec == NULL) { if (dnsrec == NULL) {
return; return;
} }
/* Free questions */ /* Free questions */
for (i = 0; i < dnsrec->qdcount; i++) { ares__array_destroy(dnsrec->qd);
ares_free(dnsrec->qd[i].name);
}
ares_free(dnsrec->qd);
/* Free answers */ /* Free answers */
for (i = 0; i < dnsrec->ancount; i++) { ares__array_destroy(dnsrec->an);
ares__dns_rr_free(&dnsrec->an[i]);
}
ares_free(dnsrec->an);
/* Free authority */ /* Free authority */
for (i = 0; i < dnsrec->nscount; i++) { ares__array_destroy(dnsrec->ns);
ares__dns_rr_free(&dnsrec->ns[i]);
}
ares_free(dnsrec->ns);
/* Free additional */ /* Free additional */
for (i = 0; i < dnsrec->arcount; i++) { ares__array_destroy(dnsrec->ar);
ares__dns_rr_free(&dnsrec->ar[i]);
}
ares_free(dnsrec->ar);
ares_free(dnsrec); ares_free(dnsrec);
} }
@ -244,7 +250,7 @@ size_t ares_dns_record_query_cnt(const ares_dns_record_t *dnsrec)
if (dnsrec == NULL) { if (dnsrec == NULL) {
return 0; return 0;
} }
return dnsrec->qdcount; return ares__array_len(dnsrec->qd);
} }
ares_status_t ares_dns_record_query_add(ares_dns_record_t *dnsrec, ares_status_t ares_dns_record_query_add(ares_dns_record_t *dnsrec,
@ -252,8 +258,9 @@ ares_status_t ares_dns_record_query_add(ares_dns_record_t *dnsrec,
ares_dns_rec_type_t qtype, ares_dns_rec_type_t qtype,
ares_dns_class_t qclass) ares_dns_class_t qclass)
{ {
ares_dns_qd_t *temp = NULL;
size_t idx; size_t idx;
ares_dns_qd_t *qd;
ares_status_t status;
if (dnsrec == NULL || name == NULL || if (dnsrec == NULL || name == NULL ||
!ares_dns_rec_type_isvalid(qtype, ARES_TRUE) || !ares_dns_rec_type_isvalid(qtype, ARES_TRUE) ||
@ -261,47 +268,39 @@ ares_status_t ares_dns_record_query_add(ares_dns_record_t *dnsrec,
return ARES_EFORMERR; return ARES_EFORMERR;
} }
if (dnsrec->qdcount >= dnsrec->qdalloc) { idx = ares__array_len(dnsrec->qd);
size_t alloc_cnt = ares__round_up_pow2(dnsrec->qdcount + 1); status = ares__array_insert_last((void **)&qd, dnsrec->qd);
if (status != ARES_SUCCESS) {
temp = ares_realloc_zero(dnsrec->qd, sizeof(*temp) * (dnsrec->qdalloc), return status;
sizeof(*temp) * alloc_cnt);
if (temp == NULL) {
return ARES_ENOMEM;
}
dnsrec->qdalloc = alloc_cnt;
dnsrec->qd = temp;
} }
idx = dnsrec->qdcount; qd->name = ares_strdup(name);
if (qd->name == NULL) {
dnsrec->qd[idx].name = ares_strdup(name); ares__array_remove_at(dnsrec->qd, idx);
if (dnsrec->qd[idx].name == NULL) {
/* No need to clean up anything */
return ARES_ENOMEM; return ARES_ENOMEM;
} }
qd->qtype = qtype;
dnsrec->qd[idx].qtype = qtype; qd->qclass = qclass;
dnsrec->qd[idx].qclass = qclass;
dnsrec->qdcount++;
return ARES_SUCCESS; return ARES_SUCCESS;
} }
ares_status_t ares_dns_record_query_set_name(ares_dns_record_t *dnsrec, ares_status_t ares_dns_record_query_set_name(ares_dns_record_t *dnsrec,
size_t idx, const char *name) 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; return ARES_EFORMERR;
} }
orig_name = dnsrec->qd[idx].name; qd = ares__array_at(dnsrec->qd, idx);
dnsrec->qd[idx].name = ares_strdup(name);
if (dnsrec->qd[idx].name == NULL) { orig_name = qd->name;
dnsrec->qd[idx].name = orig_name; /* LCOV_EXCL_LINE: OutOfMemory */ qd->name = ares_strdup(name);
return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */ if (qd->name == NULL) {
qd->name = orig_name; /* LCOV_EXCL_LINE: OutOfMemory */
return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
} }
ares_free(orig_name); ares_free(orig_name);
@ -312,12 +311,15 @@ ares_status_t ares_dns_record_query_set_type(ares_dns_record_t *dnsrec,
size_t idx, size_t idx,
ares_dns_rec_type_t qtype) 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)) { !ares_dns_rec_type_isvalid(qtype, ARES_TRUE)) {
return ARES_EFORMERR; return ARES_EFORMERR;
} }
dnsrec->qd[idx].qtype = qtype; qd = ares__array_at(dnsrec->qd, idx);
qd->qtype = qtype;
return ARES_SUCCESS; return ARES_SUCCESS;
} }
@ -327,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_rec_type_t *qtype,
ares_dns_class_t *qclass) 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; return ARES_EFORMERR;
} }
qd = ares__array_at(dnsrec->qd, idx);
if (name != NULL) { if (name != NULL) {
*name = dnsrec->qd[idx].name; *name = qd->name;
} }
if (qtype != NULL) { if (qtype != NULL) {
*qtype = dnsrec->qd[idx].qtype; *qtype = qd->qtype;
} }
if (qclass != NULL) { if (qclass != NULL) {
*qclass = dnsrec->qd[idx].qclass; *qclass = qd->qclass;
} }
return ARES_SUCCESS; return ARES_SUCCESS;
@ -355,11 +359,11 @@ size_t ares_dns_record_rr_cnt(const ares_dns_record_t *dnsrec,
switch (sect) { switch (sect) {
case ARES_SECTION_ANSWER: case ARES_SECTION_ANSWER:
return dnsrec->ancount; return ares__array_len(dnsrec->an);
case ARES_SECTION_AUTHORITY: case ARES_SECTION_AUTHORITY:
return dnsrec->nscount; return ares__array_len(dnsrec->ns);
case ARES_SECTION_ADDITIONAL: case ARES_SECTION_ADDITIONAL:
return dnsrec->arcount; return ares__array_len(dnsrec->ar);
} }
return 0; /* LCOV_EXCL_LINE: DefensiveCoding */ return 0; /* LCOV_EXCL_LINE: DefensiveCoding */
@ -368,46 +372,29 @@ size_t ares_dns_record_rr_cnt(const ares_dns_record_t *dnsrec,
ares_status_t ares_dns_record_rr_prealloc(ares_dns_record_t *dnsrec, ares_status_t ares_dns_record_rr_prealloc(ares_dns_record_t *dnsrec,
ares_dns_section_t sect, size_t cnt) ares_dns_section_t sect, size_t cnt)
{ {
ares_dns_rr_t **rr_ptr = NULL; ares__array_t *arr = NULL;
size_t *rr_alloc = NULL;
ares_dns_rr_t *temp = NULL;
if (dnsrec == NULL || cnt == 0 || !ares_dns_section_isvalid(sect)) { if (dnsrec == NULL || !ares_dns_section_isvalid(sect)) {
return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */ return ARES_EFORMERR;
} }
switch (sect) { switch (sect) {
case ARES_SECTION_ANSWER: case ARES_SECTION_ANSWER:
rr_ptr = &dnsrec->an; arr = dnsrec->an;
rr_alloc = &dnsrec->analloc;
break; break;
case ARES_SECTION_AUTHORITY: case ARES_SECTION_AUTHORITY:
rr_ptr = &dnsrec->ns; arr = dnsrec->ns;
rr_alloc = &dnsrec->nsalloc;
break; break;
case ARES_SECTION_ADDITIONAL: case ARES_SECTION_ADDITIONAL:
rr_ptr = &dnsrec->ar; arr = dnsrec->ar;
rr_alloc = &dnsrec->aralloc;
break; break;
} }
/* Round up cnt to a power of 2 */ if (cnt < ares__array_len(arr)) {
cnt = ares__round_up_pow2(cnt); return ARES_EFORMERR;
/* Already have that */
if (cnt <= *rr_alloc) {
return ARES_SUCCESS;
} }
temp = ares_realloc_zero(*rr_ptr, sizeof(*temp) * (*rr_alloc), return ares__array_set_size(arr, cnt);
sizeof(*temp) * cnt);
if (temp == NULL) {
return ARES_ENOMEM;
}
*rr_alloc = cnt;
*rr_ptr = temp;
return ARES_SUCCESS;
} }
ares_status_t ares_dns_record_rr_add(ares_dns_rr_t **rr_out, ares_status_t ares_dns_record_rr_add(ares_dns_rr_t **rr_out,
@ -416,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_rec_type_t type,
ares_dns_class_t rclass, unsigned int ttl) ares_dns_class_t rclass, unsigned int ttl)
{ {
ares_dns_rr_t **rr_ptr = NULL; ares_dns_rr_t *rr = NULL;
ares_dns_rr_t *rr = NULL; ares__array_t *arr = NULL;
size_t *rr_len = NULL; ares_status_t status;
ares_status_t status; size_t idx;
size_t idx;
if (dnsrec == NULL || name == NULL || rr_out == NULL || if (dnsrec == NULL || name == NULL || rr_out == NULL ||
!ares_dns_section_isvalid(sect) || !ares_dns_section_isvalid(sect) ||
@ -433,30 +419,25 @@ ares_status_t ares_dns_record_rr_add(ares_dns_rr_t **rr_out,
switch (sect) { switch (sect) {
case ARES_SECTION_ANSWER: case ARES_SECTION_ANSWER:
rr_ptr = &dnsrec->an; arr = dnsrec->an;
rr_len = &dnsrec->ancount;
break; break;
case ARES_SECTION_AUTHORITY: case ARES_SECTION_AUTHORITY:
rr_ptr = &dnsrec->ns; arr = dnsrec->ns;
rr_len = &dnsrec->nscount;
break; break;
case ARES_SECTION_ADDITIONAL: case ARES_SECTION_ADDITIONAL:
rr_ptr = &dnsrec->ar; arr = dnsrec->ar;
rr_len = &dnsrec->arcount;
break; 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) { if (status != ARES_SUCCESS) {
return status; /* LCOV_EXCL_LINE: OutOfMemory */ return status; /* LCOV_EXCL_LINE: OutOfMemory */
} }
idx = *rr_len;
rr = &(*rr_ptr)[idx];
rr->name = ares_strdup(name); rr->name = ares_strdup(name);
if (rr->name == NULL) { if (rr->name == NULL) {
/* No need to clean up anything */ ares__array_remove_at(arr, idx);
return ARES_ENOMEM; return ARES_ENOMEM;
} }
@ -464,7 +445,6 @@ ares_status_t ares_dns_record_rr_add(ares_dns_rr_t **rr_out,
rr->type = type; rr->type = type;
rr->rclass = rclass; rr->rclass = rclass;
rr->ttl = ttl; rr->ttl = ttl;
(*rr_len)++;
*rr_out = rr; *rr_out = rr;
@ -474,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_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec,
ares_dns_section_t sect, size_t idx) ares_dns_section_t sect, size_t idx)
{ {
ares_dns_rr_t *rr_ptr = NULL; ares__array_t *arr = NULL;
size_t *rr_len = NULL;
size_t cnt_after;
if (dnsrec == NULL || !ares_dns_section_isvalid(sect)) { if (dnsrec == NULL || !ares_dns_section_isvalid(sect)) {
return ARES_EFORMERR; return ARES_EFORMERR;
@ -484,40 +462,23 @@ ares_status_t ares_dns_record_rr_del(ares_dns_record_t *dnsrec,
switch (sect) { switch (sect) {
case ARES_SECTION_ANSWER: case ARES_SECTION_ANSWER:
rr_ptr = dnsrec->an; arr = dnsrec->an;
rr_len = &dnsrec->ancount;
break; break;
case ARES_SECTION_AUTHORITY: case ARES_SECTION_AUTHORITY:
rr_ptr = dnsrec->ns; arr = dnsrec->ns;
rr_len = &dnsrec->nscount;
break; break;
case ARES_SECTION_ADDITIONAL: case ARES_SECTION_ADDITIONAL:
rr_ptr = dnsrec->ar; arr = dnsrec->ar;
rr_len = &dnsrec->arcount;
break; break;
} }
if (idx >= *rr_len) { return ares__array_remove_at(arr, idx);
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;
} }
ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec, ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec,
ares_dns_section_t sect, size_t idx) ares_dns_section_t sect, size_t idx)
{ {
ares_dns_rr_t *rr_ptr = NULL; ares__array_t *arr = NULL;
size_t rr_len = 0;
if (dnsrec == NULL || !ares_dns_section_isvalid(sect)) { if (dnsrec == NULL || !ares_dns_section_isvalid(sect)) {
return NULL; return NULL;
@ -525,24 +486,17 @@ ares_dns_rr_t *ares_dns_record_rr_get(ares_dns_record_t *dnsrec,
switch (sect) { switch (sect) {
case ARES_SECTION_ANSWER: case ARES_SECTION_ANSWER:
rr_ptr = dnsrec->an; arr = dnsrec->an;
rr_len = dnsrec->ancount;
break; break;
case ARES_SECTION_AUTHORITY: case ARES_SECTION_AUTHORITY:
rr_ptr = dnsrec->ns; arr = dnsrec->ns;
rr_len = dnsrec->nscount;
break; break;
case ARES_SECTION_ADDITIONAL: case ARES_SECTION_ADDITIONAL:
rr_ptr = dnsrec->ar; arr = dnsrec->ar;
rr_len = dnsrec->arcount;
break; break;
} }
if (idx >= rr_len) { return ares__array_at(arr, idx);
return NULL;
}
return &rr_ptr[idx];
} }
const ares_dns_rr_t * const ares_dns_rr_t *
@ -1040,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, size_t ares_dns_rr_get_opt_cnt(const ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key) 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) { if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_OPT) {
return 0; return 0;
@ -1051,14 +1005,15 @@ size_t ares_dns_rr_get_opt_cnt(const ares_dns_rr_t *dns_rr,
return 0; return 0;
} }
return (*opts)->cnt; return ares__array_len(*opts);
} }
unsigned short ares_dns_rr_get_opt(const ares_dns_rr_t *dns_rr, unsigned short ares_dns_rr_get_opt(const ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key, size_t idx, ares_dns_rr_key_t key, size_t idx,
const unsigned char **val, size_t *val_len) 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) { if (val) {
*val = NULL; *val = NULL;
@ -1076,26 +1031,29 @@ unsigned short ares_dns_rr_get_opt(const ares_dns_rr_t *dns_rr,
return 65535; return 65535;
} }
if (idx >= (*opts)->cnt) { opt = ares__array_at(*opts, idx);
if (opt == NULL) {
return 65535; return 65535;
} }
if (val) { if (val) {
*val = (*opts)->optval[idx].val; *val = opt->val;
} }
if (val_len) { 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_bool_t ares_dns_rr_get_opt_byid(const ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key, unsigned short opt, ares_dns_rr_key_t key, unsigned short opt,
const unsigned char **val, size_t *val_len) const unsigned char **val, size_t *val_len)
{ {
ares__dns_options_t * const *opts; ares__array_t * const *opts;
size_t i; size_t i;
size_t cnt;
const ares__dns_optval_t *optptr = NULL;
if (val) { if (val) {
*val = NULL; *val = NULL;
@ -1113,21 +1071,26 @@ ares_bool_t ares_dns_rr_get_opt_byid(const ares_dns_rr_t *dns_rr,
return ARES_FALSE; return ARES_FALSE;
} }
for (i = 0; i < (*opts)->cnt; i++) { cnt = ares__array_len(*opts);
if ((*opts)->optval[i].opt == opt) { for (i = 0; i < cnt; i++) {
optptr = ares__array_at(*opts, i);
if (optptr == NULL) {
return ARES_FALSE;
}
if (optptr->opt == opt) {
break; break;
} }
} }
if (i >= (*opts)->cnt) { if (i >= cnt || optptr == NULL) {
return ARES_FALSE; return ARES_FALSE;
} }
if (val) { if (val) {
*val = (*opts)->optval[i].val; *val = optptr->val;
} }
if (val_len) { if (val_len) {
*val_len = (*opts)->optval[i].val_len; *val_len = optptr->val_len;
} }
return ARES_TRUE; return ARES_TRUE;
} }
@ -1367,12 +1330,24 @@ ares_status_t ares_dns_rr_set_abin_own(ares_dns_rr_t *dns_rr,
return ARES_SUCCESS; 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_status_t ares_dns_rr_set_opt_own(ares_dns_rr_t *dns_rr,
ares_dns_rr_key_t key, unsigned short opt, ares_dns_rr_key_t key, unsigned short opt,
unsigned char *val, size_t val_len) unsigned char *val, size_t val_len)
{ {
ares__dns_options_t **options; ares__array_t **options;
size_t idx; 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) { if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_OPT) {
return ARES_EFORMERR; return ARES_EFORMERR;
@ -1384,54 +1359,39 @@ ares_status_t ares_dns_rr_set_opt_own(ares_dns_rr_t *dns_rr,
} }
if (*options == NULL) { 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) { if (*options == NULL) {
return ARES_ENOMEM; return ARES_ENOMEM;
} }
for (idx = 0; idx < (*options)->cnt; idx++) { cnt = ares__array_len(*options);
if ((*options)->optval[idx].opt == opt) { for (idx = 0; idx < cnt; idx++) {
optptr = ares__array_at(*options, idx);
if (optptr == NULL) {
return ARES_EFORMERR;
}
if (optptr->opt == opt) {
break; break;
} }
} }
/* Duplicate entry, replace */ /* Duplicate entry, replace */
if (idx != (*options)->cnt) { if (idx != cnt && optptr != NULL) {
goto done; goto done;
} }
idx = (*options)->cnt; status = ares__array_insert_last((void **)&optptr, *options);
if (status != ARES_SUCCESS) {
/* Expand by powers of 2 */ return status;
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;
} }
(*options)->cnt++;
done: done:
ares_free((*options)->optval[idx].val); ares_free(optptr->val);
(*options)->optval[idx].opt = opt; optptr->opt = opt;
(*options)->optval[idx].val = val; optptr->val = val;
(*options)->optval[idx].val_len = val_len; optptr->val_len = val_len;
return ARES_SUCCESS; return ARES_SUCCESS;
} }
@ -1460,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; 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) char *ares_dns_addr_to_ptr(const struct ares_addr *addr)
{ {
ares__buf_t *buf = NULL; ares__buf_t *buf = NULL;
@ -1532,8 +1529,20 @@ fail:
return NULL; return NULL;
} }
/* search for an OPT RR in the response */ ares_dns_rr_t *ares_dns_get_opt_rr(ares_dns_record_t *rec)
ares_bool_t ares_dns_has_opt_rr(const 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; size_t i;
for (i = 0; i < ares_dns_record_rr_cnt(rec, ARES_SECTION_ADDITIONAL); i++) { for (i = 0; i < ares_dns_record_rr_cnt(rec, ARES_SECTION_ADDITIONAL); i++) {
@ -1541,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); ares_dns_record_rr_get_const(rec, ARES_SECTION_ADDITIONAL, i);
if (ares_dns_rr_get_type(rr) == ARES_REC_TYPE_OPT) { 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 /* Construct a DNS record for a name with given class and type. Used internally
@ -1623,12 +1632,12 @@ done:
return status; return status;
} }
ares_status_t ares_dns_record_duplicate_ex(ares_dns_record_t **dest, ares_status_t ares_dns_record_duplicate_ex(ares_dns_record_t **dest,
const ares_dns_record_t *src) const ares_dns_record_t *src)
{ {
unsigned char *data = NULL; unsigned char *data = NULL;
size_t data_len = 0; size_t data_len = 0;
ares_status_t status; ares_status_t status;
if (dest == NULL || src == NULL) { if (dest == NULL || src == NULL) {
return ARES_EFORMERR; return ARES_EFORMERR;

View file

@ -91,7 +91,7 @@ static ares_status_t ares_dns_write_header(const ares_dns_record_t *dnsrec,
} }
/* RCODE */ /* 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 */ /* Must have OPT RR in order to write extended error codes */
rcode = ARES_RCODE_SERVFAIL; rcode = ARES_RCODE_SERVFAIL;
} else { } else {
@ -105,25 +105,29 @@ static ares_status_t ares_dns_write_header(const ares_dns_record_t *dnsrec,
} }
/* QDCOUNT */ /* 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) { if (status != ARES_SUCCESS) {
return status; /* LCOV_EXCL_LINE: OutOfMemory */ return status; /* LCOV_EXCL_LINE: OutOfMemory */
} }
/* ANCOUNT */ /* 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) { if (status != ARES_SUCCESS) {
return status; /* LCOV_EXCL_LINE: OutOfMemory */ return status; /* LCOV_EXCL_LINE: OutOfMemory */
} }
/* NSCOUNT */ /* 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) { if (status != ARES_SUCCESS) {
return status; /* LCOV_EXCL_LINE: OutOfMemory */ return status; /* LCOV_EXCL_LINE: OutOfMemory */
} }
/* ARCOUNT */ /* 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) { if (status != ARES_SUCCESS) {
return status; /* LCOV_EXCL_LINE: OutOfMemory */ return status; /* LCOV_EXCL_LINE: OutOfMemory */
} }
@ -1090,12 +1094,107 @@ static ares_status_t ares_dns_write_rr(const ares_dns_record_t *dnsrec,
return ARES_SUCCESS; return ARES_SUCCESS;
} }
ares_status_t ares_dns_write_buf(const ares_dns_record_t *dnsrec,
ares__buf_t *buf)
{
ares__llist_t *namelist = NULL;
size_t orig_len;
ares_status_t status;
if (dnsrec == NULL || buf == NULL) {
return ARES_EFORMERR;
}
orig_len = ares__buf_len(buf);
status = ares_dns_write_header(dnsrec, buf);
if (status != ARES_SUCCESS) {
goto done;
}
status = ares_dns_write_questions(dnsrec, &namelist, buf);
if (status != ARES_SUCCESS) {
goto done;
}
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_AUTHORITY, buf);
if (status != ARES_SUCCESS) {
goto done;
}
status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_ADDITIONAL, buf);
if (status != ARES_SUCCESS) {
goto done;
}
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:
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, ares_status_t ares_dns_write(const ares_dns_record_t *dnsrec,
unsigned char **buf, size_t *buf_len) unsigned char **buf, size_t *buf_len)
{ {
ares__buf_t *b = NULL; ares__buf_t *b = NULL;
ares_status_t status; ares_status_t status;
ares__llist_t *namelist = NULL;
if (buf == NULL || buf_len == NULL || dnsrec == NULL) { if (buf == NULL || buf_len == NULL || dnsrec == NULL) {
return ARES_EFORMERR; return ARES_EFORMERR;
@ -1109,33 +1208,7 @@ ares_status_t ares_dns_write(const ares_dns_record_t *dnsrec,
return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */ return ARES_ENOMEM; /* LCOV_EXCL_LINE: OutOfMemory */
} }
status = ares_dns_write_header(dnsrec, b); status = ares_dns_write_buf(dnsrec, b);
if (status != ARES_SUCCESS) {
goto done;
}
status = ares_dns_write_questions(dnsrec, &namelist, b);
if (status != ARES_SUCCESS) {
goto done;
}
status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_ANSWER, b);
if (status != ARES_SUCCESS) {
goto done;
}
status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_AUTHORITY, b);
if (status != ARES_SUCCESS) {
goto done;
}
status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_ADDITIONAL, b);
if (status != ARES_SUCCESS) {
goto done;
}
done:
ares__llist_destroy(namelist);
if (status != ARES_SUCCESS) { if (status != ARES_SUCCESS) {
ares__buf_destroy(b); ares__buf_destroy(b);

View file

@ -204,7 +204,7 @@ ares_status_t ares__buf_set_length(ares__buf_t *buf, size_t len)
return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */ return ARES_EFORMERR; /* LCOV_EXCL_LINE: DefensiveCoding */
} }
buf->data_len = len; buf->data_len = len + buf->offset;
return ARES_SUCCESS; return ARES_SUCCESS;
} }

Some files were not shown because too many files have changed in this diff Show more