Merge branch 'devel/dnssec_maintenance' into features/valchain_without_lookups

This commit is contained in:
Willem Toorop 2017-11-02 12:49:19 +01:00
commit 58ff68a7a3
63 changed files with 5083 additions and 728 deletions

3
.gitmodules vendored
View File

@ -2,6 +2,9 @@
path = src/jsmn path = src/jsmn
url = https://github.com/getdnsapi/jsmn.git url = https://github.com/getdnsapi/jsmn.git
branch = getdns branch = getdns
[submodule "src/yxml"]
path = src/yxml
url = git://g.blicky.net/yxml.git
[submodule "stubby"] [submodule "stubby"]
path = stubby path = stubby
url = https://github.com/getdnsapi/stubby.git url = https://github.com/getdnsapi/stubby.git

View File

@ -8,9 +8,11 @@ addons:
packages: packages:
- libunbound-dev - libunbound-dev
- libidn11-dev - libidn11-dev
- libyaml-dev
- check - check
- libevent-dev - libevent-dev
- libev-dev - libev-dev
- libuv-dev
- valgrind - valgrind
- clang - clang
- wget - wget

View File

@ -1,3 +1,33 @@
* 2017-1?-??: Version 1.2.1
* Bugfix #348: Fix a linking issue in stubby when libbsd is present
Thanks Remi Gacogne
* Fix Makefile dependencies for parallel install.
Thanks ilovezfs
* 2017-09-29: Version 1.2.0
* Bugfix of rc1: authentication of first query with TLS
Thanks Travis Burtrum
* A function to set the location for library specific data,
like trust-anchors: getdns_context_set_appdata().
* Zero configuration DNSSEC - build upon the scheme
described in RFC7958. The URL from which to fetch
the trust anchor, the verification CA and email
can be set with the new getdns_context_set_trust_anchor_url(),
getdns_context_set_trust_anchor_verify_CA() and
getdns_context_set_trust_anchor_verify_email() functions.
The default values are to fetch from IANA and to validate
with the ICANN CA.
* Update of Stubby with yaml configuration file and
logging from a certain severity support.
* Fix tpkg exit status on test failure. Thanks Jim Hague.
* Refined logging levels for upstream statistics
* Reuse (best behaving) backed-off TLS upstreams when non are usable.
* Let TLS upstreams back-off a incremental amount of time.
Back-off time starts with 1 second and is doubled each failure, but
will not exceed the time given by getdns_context_set_tls_backoff_time()
* Make TLS upstream management more resilient to temporary outages
(like laptop sleeps)
* 2017-09-04: Version 1.1.3 * 2017-09-04: Version 1.1.3
* Small bugfixes that came out of static analysis * Small bugfixes that came out of static analysis
* No annotations with the output of getdns_query anymore, * No annotations with the output of getdns_query anymore,

View File

@ -71,21 +71,26 @@ install: getdns.pc getdns_ext_event.pc install-lib @INSTALL_GETDNS_QUERY@
$(INSTALL) -m 644 $(srcdir)/spec/index.html $(DESTDIR)$(docdir)/spec $(INSTALL) -m 644 $(srcdir)/spec/index.html $(DESTDIR)$(docdir)/spec
cd doc && $(MAKE) install cd doc && $(MAKE) install
@echo "***" @echo "***"
@echo "*** !!! IMPORTANT !!!! libgetdns needs a DNSSEC trust anchor!" @echo "*** !!! IMPORTANT !!!!"
@echo "***"
@echo "*** From release 1.2.0, getdns comes with built-in DNSSEC"
@echo "*** trust anchor management. External trust anchor management,"
@echo "*** for example with unbound-anchor, is no longer necessary"
@echo "*** and no longer recommended."
@echo "***"
@echo "*** Previously installed trust anchors, in the default location -"
@echo "***" @echo "***"
@echo "*** For the library to be able to perform DNSSEC, the root"
@echo "*** trust anchor needs to be present in presentation format"
@echo "*** in the file: "
@echo "*** @TRUST_ANCHOR_FILE@" @echo "*** @TRUST_ANCHOR_FILE@"
@echo "***" @echo "***"
@echo "*** We recomend using unbound-anchor to retrieve and install" @echo "*** - will be preferred and used for DNSSEC validation, however"
@echo "*** the root trust anchor like this: " @echo "*** getdns will fallback to trust-anchors obtained via built-in"
@echo "*** mkdir -p `dirname @TRUST_ANCHOR_FILE@`" @echo "*** trust anchor management when the anchors from the default"
@echo "*** unbound-anchor -a \"@TRUST_ANCHOR_FILE@\"" @echo "*** location fail to validate the root DNSKEY rrset."
@echo "***" @echo "***"
@echo "*** We strongly recommend package maintainers to provide the" @echo "*** To prevent expired DNSSEC trust anchors to be used for"
@echo "*** root trust anchor by installing it with unbound-anchor" @echo "*** validation, we strongly recommend removing the trust anchors"
@echo "*** at package installation time from the post-install script." @echo "*** on the default location when there is no active external"
@echo "*** trust anchor management keeping it up-to-date."
@echo "***" @echo "***"
uninstall: @UNINSTALL_GETDNS_QUERY@ uninstall: @UNINSTALL_GETDNS_QUERY@
@ -198,11 +203,13 @@ $(distdir):
mkdir -p $(distdir)/src/gldns mkdir -p $(distdir)/src/gldns
mkdir -p $(distdir)/src/tools mkdir -p $(distdir)/src/tools
mkdir -p $(distdir)/src/jsmn mkdir -p $(distdir)/src/jsmn
mkdir -p $(distdir)/src/yxml
mkdir -p $(distdir)/doc mkdir -p $(distdir)/doc
mkdir -p $(distdir)/spec mkdir -p $(distdir)/spec
mkdir -p $(distdir)/spec/example mkdir -p $(distdir)/spec/example
mkdir -p $(distdir)/stubby mkdir -p $(distdir)/stubby
mkdir -p $(distdir)/stubby/src mkdir -p $(distdir)/stubby/src
mkdir -p $(distdir)/stubby/src/yaml
cp $(srcdir)/configure.ac $(distdir) cp $(srcdir)/configure.ac $(distdir)
cp $(srcdir)/configure $(distdir) cp $(srcdir)/configure $(distdir)
cp $(srcdir)/AUTHORS $(distdir) cp $(srcdir)/AUTHORS $(distdir)
@ -245,14 +252,18 @@ $(distdir):
cp $(srcdir)/spec/example/*.[ch] $(distdir)/spec/example cp $(srcdir)/spec/example/*.[ch] $(distdir)/spec/example
cp $(srcdir)/src/tools/Makefile.in $(distdir)/src/tools cp $(srcdir)/src/tools/Makefile.in $(distdir)/src/tools
cp $(srcdir)/src/tools/*.[ch] $(distdir)/src/tools cp $(srcdir)/src/tools/*.[ch] $(distdir)/src/tools
cp $(srcdir)/stubby/stubby.conf.example $(distdir)/stubby cp $(srcdir)/stubby/stubby.yml.example $(distdir)/stubby
cp $(srcdir)/stubby/stubby-setdns-macos.sh $(distdir)/stubby cp $(srcdir)/stubby/stubby-setdns-macos.sh $(distdir)/stubby
cp $(srcdir)/stubby/src/stubby.c $(distdir)/stubby/src cp $(srcdir)/stubby/src/*.[ch] $(distdir)/stubby/src
cp $(srcdir)/stubby/src/yaml/*.[ch] $(distdir)/stubby/src/yaml
cp $(srcdir)/stubby/COPYING $(distdir)/stubby cp $(srcdir)/stubby/COPYING $(distdir)/stubby
cp $(srcdir)/stubby/README.md $(distdir)/stubby cp $(srcdir)/stubby/README.md $(distdir)/stubby
cp $(srcdir)/src/jsmn/*.[ch] $(distdir)/src/jsmn cp $(srcdir)/src/jsmn/*.[ch] $(distdir)/src/jsmn
cp $(srcdir)/src/jsmn/LICENSE $(distdir)/src/jsmn cp $(srcdir)/src/jsmn/LICENSE $(distdir)/src/jsmn
cp $(srcdir)/src/jsmn/README.md $(distdir)/src/jsmn cp $(srcdir)/src/jsmn/README.md $(distdir)/src/jsmn
cp $(srcdir)/src/yxml/*.[ch] $(distdir)/src/yxml
cp $(srcdir)/src/yxml/COPYING $(distdir)/src/yxml
cp $(srcdir)/src/yxml/yxml.pod $(distdir)/src/yxml
rm -f $(distdir)/Makefile $(distdir)/src/Makefile $(distdir)/src/getdns/getdns.h $(distdir)/spec/example/Makefile $(distdir)/src/test/Makefile $(distdir)/doc/Makefile $(distdir)/src/config.h rm -f $(distdir)/Makefile $(distdir)/src/Makefile $(distdir)/src/getdns/getdns.h $(distdir)/spec/example/Makefile $(distdir)/src/test/Makefile $(distdir)/doc/Makefile $(distdir)/src/config.h
distcheck: $(distdir).tar.gz distcheck: $(distdir).tar.gz

View File

@ -87,7 +87,7 @@ If you are building from git, you need to do the following before building:
# autoreconf -fi # autoreconf -fi
As well as building the getdns library 2 other tools are installed by default by the above process: As well as building the getdns library two other tools may be installed:
* getdns_query: a command line test script wrapper for getdns * getdns_query: a command line test script wrapper for getdns
* stubby: an experimental DNS Privacy enabled client * stubby: an experimental DNS Privacy enabled client
@ -112,7 +112,7 @@ The implementation works with a variety of event loops, each built as a separate
## Stubby ## Stubby
* Stubby is an experimental implementation of a DNS Privacy enabled stub resolver than encrypts DNS queries using TLS. It is currently suitable for advanced/technical users - all feedback is welcome! * Stubby is an experimental implementation of a DNS Privacy enabled stub resolver than encrypts DNS queries using TLS. It is currently suitable for advanced/technical users - all feedback is welcome!
* Details on how to use Stubby can be found in the [Stubby Reference Guide](https://getdnsapi.net/blog/dns-privacy-daemon-stubby). * Details on how to use Stubby can be found in the [Stubby Reference Guide](https://dnsprivacy.org/wiki/x/JYAT).
* Also see [dnsprivacy.org](https://dnsprivacy.org) for more information on DNS Privacy. * Also see [dnsprivacy.org](https://dnsprivacy.org) for more information on DNS Privacy.
## Regression Tests ## Regression Tests
@ -121,8 +121,6 @@ A suite of regression tests are included with the library, if you make changes o
want to sanity check things on your system take a look at src/test. You will need want to sanity check things on your system take a look at src/test. You will need
to install [libcheck](https://libcheck.github.io/check/). The check library is also available from many of the package repositories for the more popular operating systems. to install [libcheck](https://libcheck.github.io/check/). The check library is also available from many of the package repositories for the more popular operating systems.
The regression tests do not work with --enable-stub-only.
## DNSSEC dependencies ## DNSSEC dependencies
For the library to be DNSSEC capable, it needs to know the root trust anchor. For the library to be DNSSEC capable, it needs to know the root trust anchor.
@ -131,13 +129,16 @@ The library will try to load the root trust anchor from
or more `DS` or `DNSKEY` resource records in presentation (i.e. zone file) or more `DS` or `DNSKEY` resource records in presentation (i.e. zone file)
format. Note that this is different than the format of BIND.keys. format. Note that this is different than the format of BIND.keys.
The best way to setup or update the root trust anchor is by using ##$ Zero configuration DNSSEC
[`unbound-anchor`](https://www.unbound.net/documentation/unbound-anchor.html).
To setup the library with the root trust anchor at the default location,
execute the following steps as root:
# mkdir -p /etc/unbound When the root trust anchor is not installed in the default location and a DNSSEC query is done, getdns will try to use the trust anchors published here: http://data.iana.org/root-anchors/root-anchors.xml .
# unbound-anchor -a /etc/unbound/getdns-root.key It will validate these anchors with the ICANN Certificate Authority certificate following the procedure described in [RFC7958].
The `root-anchors.xml` and `root-anchors.p7s` S/MIME signature will be cached in the `$HOME/.getdns` directory.
When using trust-anchors from the `root-anchors.xml` file, getdns will track the keys in the root DNSKEY rrset and store a copy in $HOME/.getdns/root.key.
Only when the KSK DNSKEY's change, a new version of `root-anchors.xml` is tried to be retrieved from [data.iana.org](https://data.iana.org/root-anchors/).
A installed trust-anchor from the default location (`/etc/unbound/getdns-root.key`) that fails to validate the root DNSKEY RRset, will also trigger the "Zero configuration DNSSEC" procedure described above.
Support Support
======= =======
@ -206,7 +207,7 @@ The primary platforms targeted are Linux and FreeBSD, other platform are support
* RHEL/CentOS 6.4 * RHEL/CentOS 6.4
* OSX 10.8 * OSX 10.8
* Ubuntu 14.04 * Ubuntu 16.04
* Microsoft Windows 8.1 * Microsoft Windows 8.1
We intend to add Android and other platforms to future releases as we have time to port it. We intend to add Android and other platforms to future releases as we have time to port it.
@ -272,7 +273,7 @@ To install the [event loop integration libraries](https://getdnsapi.net/doxygen/
Note that in order to compile the examples, the `--with-libevent` switch is required. Note that in order to compile the examples, the `--with-libevent` switch is required.
As of the 0.2.0 release, when installing via Homebrew, the trust anchor is expected to be located at `$(brew --prefix)/etc/getdns-root.key`. Additionally, the OpenSSL library installed by Homebrew is linked against. Note that the Homebrew OpenSSL installation clones the Keychain certificates to the default OpenSSL location so TLS certificate authentication should work out of the box. Additionally, the OpenSSL library installed by Homebrew is linked against. Note that the Homebrew OpenSSL installation clones the Keychain certificates to the default OpenSSL location so TLS certificate authentication should work out of the box.
### Microsoft Windows 8.1 ### Microsoft Windows 8.1

View File

@ -36,12 +36,12 @@ sinclude(./m4/acx_getaddrinfo.m4)
sinclude(./m4/ax_check_compile_flag.m4) sinclude(./m4/ax_check_compile_flag.m4)
sinclude(./m4/pkg.m4) sinclude(./m4/pkg.m4)
AC_INIT([getdns], [1.1.3], [users@getdnsapi.net], [], [https://getdnsapi.net]) AC_INIT([getdns], [1.2.1], [users@getdnsapi.net], [], [https://getdnsapi.net])
# Dont forget to put a dash in front of the release candidate!!! # Dont forget to put a dash in front of the release candidate!!!
# That is how it is done with semantic versioning! # That is how it is done with semantic versioning!
# #
AC_SUBST(RELEASE_CANDIDATE, []) AC_SUBST(RELEASE_CANDIDATE, [rc1])
# Set current date from system if not set # Set current date from system if not set
AC_ARG_WITH([current-date], AC_ARG_WITH([current-date],
@ -51,7 +51,7 @@ AC_ARG_WITH([current-date],
[CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"]) [CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"])
AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"]) AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"])
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x01010300]) AC_SUBST(GETDNS_NUMERIC_VERSION, [0x010200C1])
AC_SUBST(API_VERSION, ["December 2015"]) AC_SUBST(API_VERSION, ["December 2015"])
AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00]) AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00])
GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API" GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API"
@ -84,10 +84,12 @@ GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRE
# getdns-1.0.0 had libversion 5:1:4 # getdns-1.0.0 had libversion 5:1:4
# getdns-1.1.0 had libversion 6:0:0 # getdns-1.1.0 had libversion 6:0:0
# getdns-1.1.1 had libversion 6:1:0 # getdns-1.1.1 had libversion 6:1:0
# getdns-1.1.2 has libversion 7:0:1 # getdns-1.1.2 had libversion 7:0:1
# getdns-1.1.3 will have libversion 7:1:1 # getdns-1.1.3 had libversion 7:1:1
# getdns-1.2.0 had libversion 8:0:2
# getdns-1.2.1 will have libversion 8:1:2
# #
GETDNS_LIBVERSION=7:1:1 GETDNS_LIBVERSION=8:1:2
AC_SUBST(GETDNS_COMPILATION_COMMENT) AC_SUBST(GETDNS_COMPILATION_COMMENT)
AC_SUBST(GETDNS_LIBVERSION) AC_SUBST(GETDNS_LIBVERSION)
@ -100,7 +102,18 @@ AC_PROG_CC
AC_PROG_CPP AC_PROG_CPP
# Checks for programs. # Checks for programs.
HOSTOS="unix"
AC_CANONICAL_HOST AC_CANONICAL_HOST
case "${host_os}" in
cygwin*|mingw*)
HOSTOS=windows
;;
darwin*)
HOSTOS=macos
;;
esac
AC_SUBST(HOSTOS)
CFLAGS="$CFLAGS" CFLAGS="$CFLAGS"
WPEDANTICFLAG="" WPEDANTICFLAG=""
@ -162,7 +175,8 @@ AC_ARG_ENABLE(debug-stub, AC_HELP_STRING([--enable-debug-stub], [Enable stub deb
AC_ARG_ENABLE(debug-daemon, AC_HELP_STRING([--enable-debug-daemon], [Enable daemon debugging messages])) AC_ARG_ENABLE(debug-daemon, AC_HELP_STRING([--enable-debug-daemon], [Enable daemon debugging messages]))
AC_ARG_ENABLE(debug-sec, AC_HELP_STRING([--enable-debug-sec], [Enable dnssec debugging messages])) AC_ARG_ENABLE(debug-sec, AC_HELP_STRING([--enable-debug-sec], [Enable dnssec debugging messages]))
AC_ARG_ENABLE(debug-server, AC_HELP_STRING([--enable-debug-server], [Enable server debugging messages])) AC_ARG_ENABLE(debug-server, AC_HELP_STRING([--enable-debug-server], [Enable server debugging messages]))
AC_ARG_ENABLE(all-debugging, AC_HELP_STRING([--enable-all-debugging], [Enable all debugging messages])) AC_ARG_ENABLE(debug-anchor, AC_HELP_STRING([--enable-debug-anchor], [Enable anchor debugging messages]))
AC_ARG_ENABLE(all-debugging, AC_HELP_STRING([--enable-all-debugging], [Enable scheduling, stub and dnssec debugging]))
case "$enable_all_debugging" in case "$enable_all_debugging" in
yes) yes)
enable_debug_req=yes enable_debug_req=yes
@ -171,6 +185,7 @@ case "$enable_all_debugging" in
enable_debug_daemon=yes enable_debug_daemon=yes
enable_debug_sec=yes enable_debug_sec=yes
enable_debug_server=yes enable_debug_server=yes
enable_debug_anchor=yes
;; ;;
no|*) no|*)
;; ;;
@ -217,6 +232,13 @@ case "$enable_debug_server" in
no|*) no|*)
;; ;;
esac esac
case "$enable_debug_anchor" in
yes)
AC_DEFINE_UNQUOTED([ANCHOR_DEBUG], [1], [Define this enable printing of anchor debugging messages.])
;;
no|*)
;;
esac
dnl Hidden debugging options dnl Hidden debugging options
@ -232,7 +254,7 @@ esac
DEFAULT_EVENTLOOP=select_eventloop DEFAULT_EVENTLOOP=select_eventloop
AC_CHECK_HEADERS([sys/poll.h poll.h sys/resource.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([signal.h sys/poll.h poll.h sys/resource.h sys/types.h],,, [AC_INCLUDES_DEFAULT])
AC_ARG_ENABLE(poll-eventloop, AC_HELP_STRING([--disable-poll-eventloop], [Disable default eventloop based on poll (default=enabled if available)])) AC_ARG_ENABLE(poll-eventloop, AC_HELP_STRING([--disable-poll-eventloop], [Disable default eventloop based on poll (default=enabled if available)]))
case "$enable_poll_eventloop" in case "$enable_poll_eventloop" in
no) no)
@ -280,11 +302,66 @@ case "$enable_native_stub_dnssec" in
;; ;;
esac esac
# check wether strptime also works
AC_DEFUN([AC_CHECK_STRPTIME_WORKS],
[AC_REQUIRE([AC_PROG_CC])
AC_MSG_CHECKING(whether strptime works)
if test c${cross_compiling} = cno; then
AC_RUN_IFELSE([AC_LANG_SOURCE([[
#define _XOPEN_SOURCE 600
#include <time.h>
int main(void) { struct tm tm; char *res;
res = strptime("2010-07-15T00:00:00+00:00", "%t%Y%t-%t%m%t-%t%d%tT%t%H%t:%t%M%t:%t%S%t", &tm);
if (!res) return 2;
res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm);
if (!res) return 1; return 0; }
]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"])
else
eval "ac_cv_c_strptime_works=maybe"
fi
AC_MSG_RESULT($ac_cv_c_strptime_works)
if test $ac_cv_c_strptime_works = no; then
AC_LIBOBJ(strptime)
else
AC_DEFINE_UNQUOTED([STRPTIME_WORKS], 1, [use default strptime.])
fi
])dnl
AC_CHECK_FUNCS([strptime],[AC_CHECK_STRPTIME_WORKS],[AC_LIBOBJ([strptime])])
# search to set include and library paths right # search to set include and library paths right
# find libidn (no libidn on windows though) # find libidn (no libidn on windows though)
AC_CHECK_HEADERS([windows.h winsock.h stdio.h winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([windows.h winsock.h stdio.h winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT])
ACX_CHECK_GETADDRINFO_WITH_INCLUDES ACX_CHECK_GETADDRINFO_WITH_INCLUDES
AC_ARG_WITH(fd-setsize, AS_HELP_STRING([--with-fd-setsize=size],
[Set maximum file descriptor number that can be used by select]),
[], [withval="no"])
case "$withval" in
no)
;;
*)
AC_DEFINE_UNQUOTED([FD_SETSIZE], [$withval], [Alternate value for the FD_SETSIZE])
my_enable_unbound_event_api=1
;;
esac
#---- check for pthreads library
AC_ARG_WITH(libpthread, AS_HELP_STRING([--without-libpthread],
[Disable libpthread (default is autodetect)]),
[], [withval="yes"])
case "$withval" in
yes)
AC_SEARCH_LIBS([pthread_mutex_init],[pthread], [
AC_DEFINE([HAVE_PTHREAD], [1], [Have pthreads library])
LIBS="-lpthread $LIBS"
], [AC_MSG_WARN([pthreads not available])])
;;
*)
;;
esac
USE_NSS="no" USE_NSS="no"
# openssl # openssl
if test $USE_NSS = "no"; then if test $USE_NSS = "no"; then
@ -512,7 +589,7 @@ case "$enable_ed25519" in
no) no)
;; ;;
*) *)
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then if test "$USE_NSS" = "no" -a "$USE_NETTLE" = "no"; then
AC_CHECK_DECLS([NID_ED25519], [ AC_CHECK_DECLS([NID_ED25519], [
AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.]) AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.])
use_ed25519="yes" use_ed25519="yes"
@ -577,6 +654,22 @@ case "$enable_stub_only" in
;; ;;
esac esac
my_with_yaml=0
AC_ARG_ENABLE(yaml-config,)
case "$enable_yaml_config" in
yes)
AC_DEFINE_UNQUOTED([USE_YAML_CONFIG], [1], [Define this to enable YAML config support.])
AC_DEFINE_UNQUOTED([HAVE_GETDNS_YAML2DICT], [1], [Define this to enable getdns_yaml2dict function.])
GETDNS_XTRA_OBJS="convert_yaml_to_json.lo"
my_with_yaml=1
;;
no|*)
GETDNS_XTRA_OBJS=""
;;
esac
AC_SUBST(GETDNS_XTRA_OBJS)
if test "$USE_WINSOCK" = 1; then if test "$USE_WINSOCK" = 1; then
AC_MSG_NOTICE([ Building on Windows ... YES! ]) AC_MSG_NOTICE([ Building on Windows ... YES! ])
AC_DEFINE_UNQUOTED([GETDNS_ON_WINDOWS], [1], [Define this to enable Windows build.]) AC_DEFINE_UNQUOTED([GETDNS_ON_WINDOWS], [1], [Define this to enable Windows build.])
@ -584,6 +677,30 @@ if test "$USE_WINSOCK" = 1; then
LIBS="$LIBS -lgdi32 -liphlpapi" LIBS="$LIBS -lgdi32 -liphlpapi"
fi fi
dnl sigset_t or _sigset_t? MinGW is latter by default.
AC_CHECK_TYPES([sigset_t],
[],
[AC_CHECK_TYPES([_sigset_t],
[],
[AC_MSG_ERROR([Can't find type `sigset_t' or type `_sigset_t'])],
[AC_INCLUDES_DEFAULT
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
])
],
[AC_INCLUDES_DEFAULT
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
])
AC_CHECK_FUNCS(sigemptyset sigfillset sigaddset)
my_with_libidn=1 my_with_libidn=1
AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname], AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname],
@ -691,11 +808,6 @@ then
]) ])
fi fi
if test $found_all_libs = 0
then
AC_MSG_ERROR([Missing dependencies: $MISSING_DEPS])
fi
AC_PATH_PROG([DOXYGEN], [doxygen]) AC_PATH_PROG([DOXYGEN], [doxygen])
if test -z "$DOXYGEN"; if test -z "$DOXYGEN";
then AC_MSG_WARN([doxygen not found, continuing without]) then AC_MSG_WARN([doxygen not found, continuing without])
@ -1010,6 +1122,7 @@ AC_SUBST(GETDNS_QUERY)
AC_SUBST(INSTALL_GETDNS_QUERY) AC_SUBST(INSTALL_GETDNS_QUERY)
AC_SUBST(UNINSTALL_GETDNS_QUERY) AC_SUBST(UNINSTALL_GETDNS_QUERY)
stubby_with_yaml=0
AC_ARG_WITH(stubby, AS_HELP_STRING([--with-stubby], AC_ARG_WITH(stubby, AS_HELP_STRING([--with-stubby],
[Compile and install stubby, the (stub) resolver daemon]), [Compile and install stubby, the (stub) resolver daemon]),
[], [withval="no"]) [], [withval="no"])
@ -1017,39 +1130,89 @@ if test x_$withval = x_yes; then
STUBBY="stubby" STUBBY="stubby"
INSTALL_STUBBY="install-stubby" INSTALL_STUBBY="install-stubby"
UNINSTALL_STUBBY="uninstall-stubby" UNINSTALL_STUBBY="uninstall-stubby"
if test $my_with_yaml = 0
then
STUBBY_XTRA_OBJS="convert_yaml_to_json.lo gbuffer.lo"
stubby_with_yaml=1
my_with_yaml=1
fi
else else
STUBBY="" STUBBY=""
INSTALL_STUBBY="" INSTALL_STUBBY=""
UNINSTALL_STUBBY="" UNINSTALL_STUBBY=""
STUBBY_XTRA_OBJS=""
fi fi
AC_SUBST(STUBBY) AC_SUBST(STUBBY)
AC_SUBST(INSTALL_STUBBY) AC_SUBST(INSTALL_STUBBY)
AC_SUBST(UNINSTALL_STUBBY) AC_SUBST(UNINSTALL_STUBBY)
AC_SUBST(STUBBY_XTRA_OBJS)
AC_ARG_WITH(fd-setsize, AS_HELP_STRING([--with-fd-setsize=size], STUBBY_LIBS=""
[Set maximum file descriptor number that can be used by select]), STUBBY_LDFLAGS=""
[], [withval="no"])
case "$withval" in if test $my_with_yaml = 1
no) then
;; if test $stubby_with_yaml = 1
*) then
AC_DEFINE_UNQUOTED([FD_SETSIZE], [$withval], [Alternate value for the FD_SETSIZE]) getdns_LIBS="$LIBS"
my_enable_unbound_event_api=1 getdns_LDFLAGS="$LDFLAGS"
;; LIBS="$initial_LIBS"
esac LDFLAGS="$initial_LDFLAGS"
fi
AC_ARG_WITH(libyaml, AS_HELP_STRING([--with-libyaml=pathname],
[path to libyaml (default: search /usr/local ..)]),
[], [withval="yes"])
if test x_$withval = x_yes; then
for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do
if test -f "$dir/include/yaml.h"; then
CFLAGS="$CFLAGS -I$dir/include"
LDFLAGS="$LDFLAGS -L$dir/lib"
AC_MSG_NOTICE([Found libyaml in $dir])
break
fi
done
else
if test x_$withval != x_no; then
CFLAGS="$CFLAGS -I$withval/include"
LDFLAGS="$LDFLAGS -L$withval/lib"
else
if test $stubby_with_yaml = 1
then
AC_MSG_ERROR([libyaml required for building Stubby])
fi
my_with_yaml=0
fi
fi
if test $my_with_yaml = 1
then
AC_MSG_NOTICE([Checking for dependency libyaml])
AC_CHECK_LIB([yaml], [yaml_parser_parse], [], [
MISSING_DEPS="${MISSING_DEPS}${MISSING_SEP}libyaml"
MISSING_SEP=", "
found_all_libs=0
])
fi
if test $stubby_with_yaml = 1
then
STUBBY_LDFLAGS="$LDFLAGS"
STUBBY_LIBS="$LIBS"
LIBS="$getdns_LIBS"
LDFLAGS="$getdns_LDFLAGS"
fi
fi
AC_SUBST(STUBBY_LDFLAGS)
AC_SUBST(STUBBY_LIBS)
if test $found_all_libs = 0
then
AC_MSG_ERROR([Missing dependencies: $MISSING_DEPS])
fi
AC_CONFIG_FILES([Makefile src/Makefile src/version.c src/getdns/getdns.h src/getdns/getdns_extra.h spec/example/Makefile src/test/Makefile src/tools/Makefile doc/Makefile getdns.pc getdns_ext_event.pc]) AC_CONFIG_FILES([Makefile src/Makefile src/version.c src/getdns/getdns.h src/getdns/getdns_extra.h spec/example/Makefile src/test/Makefile src/tools/Makefile doc/Makefile getdns.pc getdns_ext_event.pc])
if [ test -n "$DOXYGEN" ] if [ test -n "$DOXYGEN" ]
then AC_CONFIG_FILES([src/Doxyfile]) then AC_CONFIG_FILES([src/Doxyfile])
fi fi
#---- check for pthreads library
AC_SEARCH_LIBS([pthread_mutex_init],[pthread], [
AC_DEFINE([HAVE_PTHREAD], [1], [Have pthreads library])
LIBS="-lpthread $LIBS"
], [AC_MSG_WARN([pthreads not available])])
AC_MSG_CHECKING([whether the C compiler (${CC-cc}) supports the __func__ variable]) AC_MSG_CHECKING([whether the C compiler (${CC-cc}) supports the __func__ variable])
AC_LANG_PUSH(C) AC_LANG_PUSH(C)
AC_COMPILE_IFELSE( AC_COMPILE_IFELSE(
@ -1064,7 +1227,7 @@ dnl ----- Start of "Things needed for gldns" section
dnl ----- dnl -----
dnl --------------------------------------------------------------------------- dnl ---------------------------------------------------------------------------
AC_CHECK_HEADERS([stdarg.h stdint.h netinet/in.h arpa/inet.h netdb.h sys/socket.h time.h sys/time.h sys/select.h endian.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([stdarg.h stdint.h netinet/in.h arpa/inet.h netdb.h sys/socket.h time.h sys/time.h sys/select.h endian.h limits.h sys/limits.h],,, [AC_INCLUDES_DEFAULT])
dnl Check the printf-format attribute (if any) dnl Check the printf-format attribute (if any)
dnl result in HAVE_ATTR_FORMAT. dnl result in HAVE_ATTR_FORMAT.
@ -1107,11 +1270,12 @@ fi
# system implementation. # system implementation.
PKG_CHECK_MODULES([LIBBSD],[libbsd-overlay],[ PKG_CHECK_MODULES([LIBBSD],[libbsd-overlay],[
LIBS="$LIBS $LIBBSD_LIBS" LIBS="$LIBS $LIBBSD_LIBS"
STUBBY_LIBS="$STUBBY_LIBS $LIBBSD_LIBS"
CFLAGS="$CFLAGS $LIBBSD_CFLAGS" CFLAGS="$CFLAGS $LIBBSD_CFLAGS"
],[ ],[
AC_MSG_WARN([libbsd not found or usable; using embedded code instead]) AC_MSG_WARN([libbsd not found or usable; using embedded code instead])
]) ])
AC_CHECK_DECLS([strlcpy,arc4random,arc4random_uniform]) AC_CHECK_DECLS([inet_pton,inet_ntop,strlcpy,arc4random,arc4random_uniform])
AC_REPLACE_FUNCS(inet_pton) AC_REPLACE_FUNCS(inet_pton)
AC_REPLACE_FUNCS(inet_ntop) AC_REPLACE_FUNCS(inet_ntop)
AC_REPLACE_FUNCS(strlcpy) AC_REPLACE_FUNCS(strlcpy)
@ -1187,14 +1351,45 @@ AH_BOTTOM([
# ifndef FD_SETSIZE # ifndef FD_SETSIZE
# define FD_SETSIZE 1024 # define FD_SETSIZE 1024
# endif # endif
# define PRIsz "%Iu"
/* the version of the windows API enabled */
# ifndef WINVER
# define WINVER 0x0600 // 0x0502
# endif
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0600 // 0x0502
# endif
# ifdef HAVE_WS2TCPIP_H
# include <ws2tcpip.h>
# endif
# ifdef _MSC_VER
# if _MSC_VER >= 1800
# define PRIsz "zu"
# else
# define PRIsz "Iu"
# endif
# else
# define PRIsz "Iu"
# endif
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
# ifdef HAVE_WINSOCK2_H
# define FD_SET_T (u_int)
# else
# define FD_SET_T
# endif
/* Windows wants us to use _strdup instead of strdup */ /* Windows wants us to use _strdup instead of strdup */
# ifndef strdup # ifndef strdup
# define strdup _strdup # define strdup _strdup
# endif # endif
#else #else
# define PRIsz "%zu" # define PRIsz "zu"
#endif #endif
#include <stdint.h> #include <stdint.h>
@ -1203,34 +1398,6 @@ AH_BOTTOM([
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
/* the version of the windows API enabled */
#ifndef WINVER
#define WINVER 0x0600 // 0x0502
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600 // 0x0502
#endif
#ifdef HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#ifdef HAVE_WS2TCPIP_H
#include <ws2tcpip.h>
#endif
#ifndef USE_WINSOCK
#define ARG_LL "%ll"
#else
#define ARG_LL "%I64"
#endif
/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
#ifdef HAVE_WINSOCK2_H
#define FD_SET_T (u_int)
#else
#define FD_SET_T
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -1277,18 +1444,21 @@ void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest); unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest);
#endif /* COMPAT_SHA512 */ #endif /* COMPAT_SHA512 */
#ifndef HAVE_INET_PTON #ifndef HAVE_DECL_INET_PTON
int inet_pton(int af, const char* src, void* dst); int inet_pton(int af, const char* src, void* dst);
#endif /* HAVE_INET_PTON */ #endif /* HAVE_INET_PTON */
#ifndef HAVE_INET_NTOP #ifndef HAVE_DECL_INET_NTOP
const char *inet_ntop(int af, const void *src, char *dst, size_t size); const char *inet_ntop(int af, const void *src, char *dst, size_t size);
#endif #endif
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
# ifndef _CUSTOM_VSNPRINTF
# define _CUSTOM_VSNPRINTF
static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *format, va_list ap) static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *format, va_list ap)
{ int r = vsnprintf(str, size, format, ap); return r == -1 ? _vscprintf(format, ap) : r; } { int r = vsnprintf(str, size, format, ap); return r == -1 ? _vscprintf(format, ap) : r; }
# define vsnprintf _gldns_custom_vsnprintf # define vsnprintf _gldns_custom_vsnprintf
# endif
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
@ -1315,6 +1485,10 @@ static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *fo
#include <sys/select.h> #include <sys/select.h>
#endif #endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_NETINET_IN_H #ifdef HAVE_NETINET_IN_H
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
@ -1331,6 +1505,20 @@ static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *fo
#include <inttypes.h> #include <inttypes.h>
#endif #endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_SYS_LIMITS_H
#include <sys/limits.h>
#endif
#ifdef PATH_MAX
#define _GETDNS_PATH_MAX PATH_MAX
#else
#define _GETDNS_PATH_MAX 2048
#endif
#ifndef PRIu64 #ifndef PRIu64
#define PRIu64 "llu" #define PRIu64 "llu"
#endif #endif
@ -1363,6 +1551,29 @@ static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *fo
# endif # endif
#endif #endif
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(HAVE_STRPTIME) || !defined(STRPTIME_WORKS)
#define strptime unbound_strptime
struct tm;
char *strptime(const char *s, const char *format, struct tm *tm);
#endif
#if !defined(HAVE_SIGSET_T) && defined(HAVE__SIGSET_T)
typedef _sigset_t sigset_t;
#endif
#if !defined(HAVE_SIGEMPTYSET)
# define sigemptyset(pset) (*(pset) = 0)
#endif
#if !defined(HAVE_SIGFILLSET)
# define sigfillset(pset) (*(pset) = (sigset_t)-1)
#endif
#if !defined(HAVE_SIGADDSET)
# define sigaddset(pset, num) (*(pset) |= (1L<<(num)))
#endif
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
# include <unbound.h> # include <unbound.h>
# ifdef HAVE_UNBOUND_EVENT_H # ifdef HAVE_UNBOUND_EVENT_H
@ -1380,6 +1591,10 @@ int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
# endif # endif
# endif # endif
#endif #endif
#ifdef __cplusplus
}
#endif
]) ])
dnl --------------------------------------------------------------------------- dnl ---------------------------------------------------------------------------

View File

@ -55,11 +55,13 @@ stubbysrcdir = $(srcdir)/../stubby
LIBTOOL = ../libtool LIBTOOL = ../libtool
CC=@CC@ CC=@CC@
CFLAGS=-I$(srcdir) -I. -I$(srcdir)/util/auxiliary @CFLAGS@ @CPPFLAGS@ $(XTRA_CFLAGS) CFLAGS=-I$(srcdir) -I. -I$(srcdir)/util/auxiliary -I$(stubbysrcdir)/src @CFLAGS@ @CPPFLAGS@ $(XTRA_CFLAGS)
WPEDANTICFLAG=@WPEDANTICFLAG@ WPEDANTICFLAG=@WPEDANTICFLAG@
WNOERRORFLAG=@WNOERRORFLAG@ WNOERRORFLAG=@WNOERRORFLAG@
LDFLAGS=@LDFLAGS@ @LIBS@ LDFLAGS=@LDFLAGS@ @LIBS@
STUBBY_LDFLAGS=@STUBBY_LDFLAGS@ @STUBBY_LIBS@
EXTENSION_LIBEVENT_LIB=@EXTENSION_LIBEVENT_LIB@ EXTENSION_LIBEVENT_LIB=@EXTENSION_LIBEVENT_LIB@
EXTENSION_LIBEVENT_EXT_LIBS=@EXTENSION_LIBEVENT_EXT_LIBS@ EXTENSION_LIBEVENT_EXT_LIBS=@EXTENSION_LIBEVENT_EXT_LIBS@
EXTENSION_LIBEVENT_LDFLAGS=@EXTENSION_LIBEVENT_LDFLAGS@ EXTENSION_LIBEVENT_LDFLAGS=@EXTENSION_LIBEVENT_LDFLAGS@
@ -75,7 +77,7 @@ C99COMPATFLAGS=@C99COMPATFLAGS@
DEFAULT_EVENTLOOP_OBJ=@DEFAULT_EVENTLOOP@.lo DEFAULT_EVENTLOOP_OBJ=@DEFAULT_EVENTLOOP@.lo
GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \ GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \
list.lo request-internal.lo pubkey-pinning.lo rr-dict.lo \ list.lo request-internal.lo platform.lo pubkey-pinning.lo rr-dict.lo \
rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo \ rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo \
mdns.lo mdns.lo
@ -91,10 +93,15 @@ COMPAT_OBJ=$(LIBOBJS:.o=.lo)
UTIL_OBJ=rbtree.lo val_secalgo.lo lruhash.lo lookup3.lo locks.lo UTIL_OBJ=rbtree.lo val_secalgo.lo lruhash.lo lookup3.lo locks.lo
JSMN_OBJ=jsmn.lo JSMN_OBJ=jsmn.lo
YXML_OBJ=yxml.lo
YAML_OBJ=convert_yaml_to_json.lo
GETDNS_XTRA_OBJS=@GETDNS_XTRA_OBJS@
STUBBY_XTRA_OBJS=@STUBBY_XTRA_OBJS@
EXTENSION_OBJ=$(DEFAULT_EVENTLOOP_OBJ) libevent.lo libev.lo EXTENSION_OBJ=$(DEFAULT_EVENTLOOP_OBJ) libevent.lo libev.lo
NON_C99_OBJS=context.lo libuv.lo NON_C99_OBJS=libuv.lo context.lo anchor.lo
.SUFFIXES: .c .o .a .lo .h .SUFFIXES: .c .o .a .lo .h
@ -123,9 +130,18 @@ $(UTIL_OBJ):
$(JSMN_OBJ): $(JSMN_OBJ):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -DJSMN_GETDNS -c $(srcdir)/jsmn/$(@:.lo=.c) -o $@ $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -DJSMN_GETDNS -c $(srcdir)/jsmn/$(@:.lo=.c) -o $@
$(YAML_OBJ):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(stubbysrcdir)/src/yaml/$(@:.lo=.c) -o $@
$(YXML_OBJ):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -I$(srcdir)/yxml -DYXML_GETDNS -Wno-unused-parameter -c $(srcdir)/yxml/$(@:.lo=.c) -o $@
$(EXTENSION_OBJ): $(EXTENSION_OBJ):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -c $(srcdir)/extension/$(@:.lo=.c) -o $@ $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -c $(srcdir)/extension/$(@:.lo=.c) -o $@
anchor.lo:
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) $(C99COMPATFLAGS) -c $(srcdir)/anchor.c -o anchor.lo
context.lo: context.lo:
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) $(C99COMPATFLAGS) -c $(srcdir)/context.c -o context.lo $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) $(C99COMPATFLAGS) -c $(srcdir)/context.c -o context.lo
@ -144,7 +160,7 @@ install-headers: getdns/getdns.h getdns/getdns_extra.h
uninstall-headers: uninstall-headers:
rm -rf $(DESTDIR)$(includedir)/getdns rm -rf $(DESTDIR)$(includedir)/getdns
install-libs: libgetdns.la install-libs: libgetdns.la $(EXTENSION_LIBEVENT_LIB) $(EXTENSION_LIBUV_LIB) $(EXTENSION_LIBEV_LIB)
$(INSTALL) -m 755 -d $(DESTDIR)$(libdir) $(INSTALL) -m 755 -d $(DESTDIR)$(libdir)
$(LIBTOOL) --mode=install cp libgetdns.la $(DESTDIR)$(libdir) $(LIBTOOL) --mode=install cp libgetdns.la $(DESTDIR)$(libdir)
if test $(have_libevent) = 1 ; then $(LIBTOOL) --mode=install cp $(EXTENSION_LIBEVENT_LIB) $(DESTDIR)$(libdir) ; fi if test $(have_libevent) = 1 ; then $(LIBTOOL) --mode=install cp $(EXTENSION_LIBEVENT_LIB) $(DESTDIR)$(libdir) ; fi
@ -172,9 +188,8 @@ libgetdns_ext_uv.la: libgetdns.la libuv.lo
libgetdns_ext_ev.la: libgetdns.la libev.lo libgetdns_ext_ev.la: libgetdns.la libev.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS)
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo anchor.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(YXML_OBJ) $(GETDNS_XTRA_OBJS) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
test: default test: default
cd test && $(MAKE) $@ cd test && $(MAKE) $@
@ -185,17 +200,29 @@ getdns_query: default
stubby.lo: $(stubbysrcdir)/src/stubby.c stubby.lo: $(stubbysrcdir)/src/stubby.c
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -DSTUBBYCONFDIR=\"$(sysconfdir)/stubby\" -DRUNSTATEDIR=\"$(runstatedir)\" -c $< -o $@ $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -DSTUBBYCONFDIR=\"$(sysconfdir)/stubby\" -DRUNSTATEDIR=\"$(runstatedir)\" -c $< -o $@
stubby: stubby.lo libgetdns.la stubby: stubby.lo libgetdns.la $(STUBBY_XTRA_OBJS)
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ stubby.lo $(LDFLAGS) libgetdns.la $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ stubby.lo $(STUBBY_XTRA_OBJS) $(STUBBY_LDFLAGS) libgetdns.la
install-stubby: stubby $(stubbysrcdir)/stubby.conf.example $(stubbysrcdir)/stubby-setdns-macos.sh install-stubby-files-unix: $(stubbysrcdir)/stubby.yml.example
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir) $(INSTALL) -m 755 -d $(DESTDIR)$(stubbyconfdir)
$(LIBTOOL) --mode=install cp stubby $(DESTDIR)$(bindir) test -f $(DESTDIR)$(stubbyconfdir)/stubby.yml || \
$(INSTALL_DATA) $(stubbysrcdir)/stubby.yml.example $(DESTDIR)$(stubbyconfdir)/stubby.yml
install-stubby-files-macos: $(stubbysrcdir)/stubby-setdns-macos.sh install-stubby-files-unix
$(INSTALL) -m 755 -d $(DESTDIR)$(sbindir) $(INSTALL) -m 755 -d $(DESTDIR)$(sbindir)
$(INSTALL) -m 755 $(stubbysrcdir)/stubby-setdns-macos.sh $(DESTDIR)$(sbindir) $(INSTALL) -m 755 $(stubbysrcdir)/stubby-setdns-macos.sh $(DESTDIR)$(sbindir)
stubby.yml.windows: $(stubbysrcdir)/stubby.yml.example
awk "{sub(/$$/,\"\r\")}1" $(stubbysrcdir)/stubby.yml.example > stubby.yml.windows
install-stubby-files-windows: stubby.yml.windows
$(INSTALL) -m 755 -d $(DESTDIR)$(stubbyconfdir) $(INSTALL) -m 755 -d $(DESTDIR)$(stubbyconfdir)
test -f $(DESTDIR)$(stubbyconfdir)/stubby.conf || \ test -f $(DESTDIR)$(stubbyconfdir)/stubby.yml || \
$(INSTALL_DATA) $(stubbysrcdir)/stubby.conf.example $(DESTDIR)$(stubbyconfdir)/stubby.conf $(INSTALL_DATA) stubby.yml.windows $(DESTDIR)$(stubbyconfdir)/stubby.yml
install-stubby: stubby install-stubby-files-@HOSTOS@
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
$(LIBTOOL) --mode=install cp stubby $(DESTDIR)$(bindir)
uninstall-stubby: uninstall-stubby:
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/stubby $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/stubby
@ -226,14 +253,17 @@ Makefile: $(srcdir)/Makefile.in ../config.status
depend: depend:
(cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new ) (cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new )
(blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" -Iutil/auxiliary *.c gldns/*.c compat/*.c util/*.c jsmn/*.c extension/*.c| \
(blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" -Iyxml -Iutil/auxiliary -I../stubby/src *.c gldns/*.c compat/*.c util/*.c jsmn/*.c yxml/*.c extension/*.c ../stubby/src/*.c | \
sed -e "s? $$blddir/? ?g" \ sed -e "s? $$blddir/? ?g" \
-e 's? gldns/? $$(srcdir)/gldns/?g' \ -e 's? gldns/? $$(srcdir)/gldns/?g' \
-e 's? compat/? $$(srcdir)/compat/?g' \ -e 's? compat/? $$(srcdir)/compat/?g' \
-e 's? util/auxiliary/util/? $$(srcdir)/util/auxiliary/util/?g' \ -e 's? util/auxiliary/util/? $$(srcdir)/util/auxiliary/util/?g' \
-e 's? util/? $$(srcdir)/util/?g' \ -e 's? util/? $$(srcdir)/util/?g' \
-e 's? jsmn/? $$(srcdir)/jsmn/?g' \ -e 's? jsmn/? $$(srcdir)/jsmn/?g' \
-e 's? yxml/? $$(srcdir)/yxml/?g' \
-e 's? extension/? $$(srcdir)/extension/?g' \ -e 's? extension/? $$(srcdir)/extension/?g' \
-e 's? \.\./stubby/? $$(stubbysrcdir)/?g' \
-e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \ -e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
-e 's? \$$(srcdir)/config\.h? config.h?g' \ -e 's? \$$(srcdir)/config\.h? config.h?g' \
-e 's? \$$(srcdir)/getdns/getdns_extra\.h? getdns/getdns_extra.h?g' \ -e 's? \$$(srcdir)/getdns/getdns_extra\.h? getdns/getdns_extra.h?g' \
@ -251,22 +281,36 @@ depend:
FORCE: FORCE:
# Dependencies for gldns, utils, the extensions and compat functions # Dependencies for gldns, utils, the extensions and compat functions
anchor.lo anchor.o: $(srcdir)/anchor.c \
config.h \
$(srcdir)/debug.h $(srcdir)/anchor.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/types-internal.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/yxml/yxml.h \
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \
$(srcdir)/gldns/keyraw.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/platform.h
const-info.lo const-info.o: $(srcdir)/const-info.c \ const-info.lo const-info.o: $(srcdir)/const-info.c \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/const-info.h $(srcdir)/const-info.h
context.lo context.o: $(srcdir)/context.c \ context.lo context.o: $(srcdir)/context.c \
config.h \ config.h \
$(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \ $(srcdir)/anchor.h \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/debug.h \
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \ $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/dnssec.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h \ $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
$(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
convert.lo convert.o: $(srcdir)/convert.c \ convert.lo convert.o: $(srcdir)/convert.c \
config.h \ config.h \
getdns/getdns.h \ getdns/getdns.h \
@ -276,9 +320,9 @@ convert.lo convert.o: $(srcdir)/convert.c \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \ $(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \ $(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/wire2str.h \ $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/wire2str.h \
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h \ $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h \
$(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(stubbysrcdir)/src/yaml/convert_yaml_to_json.h $(srcdir)/convert.h
dict.lo dict.o: $(srcdir)/dict.c \ dict.lo dict.o: $(srcdir)/dict.c \
config.h \ config.h \
$(srcdir)/types-internal.h \ $(srcdir)/types-internal.h \
@ -289,7 +333,7 @@ dict.lo dict.o: $(srcdir)/dict.c \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h \
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/parseutil.h
dnssec.lo dnssec.o: $(srcdir)/dnssec.c \ dnssec.lo dnssec.o: $(srcdir)/dnssec.c \
config.h \ config.h \
@ -301,10 +345,10 @@ dnssec.lo dnssec.o: $(srcdir)/dnssec.c \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h \ $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h \
$(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/util/val_secalgo.h \ $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/util/val_secalgo.h \
$(srcdir)/util/orig-headers/val_secalgo.h $(srcdir)/util/orig-headers/val_secalgo.h
general.lo general.o: $(srcdir)/general.c \ general.lo general.o: $(srcdir)/general.c \
config.h \ config.h \
@ -316,9 +360,9 @@ general.lo general.o: $(srcdir)/general.c \
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \
$(srcdir)/mdns.h $(srcdir)/dict.h $(srcdir)/mdns.h $(srcdir)/platform.h
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \ list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
@ -328,7 +372,7 @@ list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/list.h $(srcdir)/dict.h
mdns.lo mdns.o: $(srcdir)/mdns.c \ mdns.lo mdns.o: $(srcdir)/mdns.c \
config.h \ config.h \
$(srcdir)/debug.h $(srcdir)/context.h \ $(srcdir)/debug.h $(srcdir)/context.h \
@ -338,10 +382,12 @@ mdns.lo mdns.o: $(srcdir)/mdns.c \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h \ $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/mdns.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/general.h $(srcdir)/gldns/rrdef.h $(srcdir)/util-internal.h \
$(srcdir)/util/auxiliary/util/fptr_wlist.h $(srcdir)/util/lookup3.h \ $(srcdir)/platform.h $(srcdir)/mdns.h $(srcdir)/util/auxiliary/util/fptr_wlist.h $(srcdir)/util/lookup3.h \
$(srcdir)/util/orig-headers/lookup3.h $(srcdir)/util/orig-headers/lookup3.h
platform.lo platform.o: $(srcdir)/platform.c $(srcdir)/platform.h \
config.h
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \ pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \
config.h \ config.h \
$(srcdir)/debug.h \ $(srcdir)/debug.h \
@ -352,8 +398,8 @@ pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h
request-internal.lo request-internal.o: $(srcdir)/request-internal.c \ request-internal.lo request-internal.o: $(srcdir)/request-internal.c \
config.h \ config.h \
$(srcdir)/types-internal.h \ $(srcdir)/types-internal.h \
@ -364,8 +410,8 @@ request-internal.lo request-internal.o: $(srcdir)/request-internal.c \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/convert.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/convert.h $(srcdir)/general.h
rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \ rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \
config.h \ config.h \
getdns/getdns.h \ getdns/getdns.h \
@ -375,7 +421,8 @@ rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h \
$(srcdir)/dict.h
rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
config.h \ config.h \
getdns/getdns.h \ getdns/getdns.h \
@ -388,7 +435,8 @@ server.lo server.o: $(srcdir)/server.c \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/platform.h
stub.lo stub.o: $(srcdir)/stub.c \ stub.lo stub.o: $(srcdir)/stub.c \
config.h \ config.h \
$(srcdir)/debug.h $(srcdir)/stub.h \ $(srcdir)/debug.h $(srcdir)/stub.h \
@ -400,8 +448,8 @@ stub.lo stub.o: $(srcdir)/stub.c \
$(srcdir)/rr-dict.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \ $(srcdir)/rr-dict.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \ $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \ $(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h \ $(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/anchor.h \
$(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
sync.lo sync.o: $(srcdir)/sync.c \ sync.lo sync.o: $(srcdir)/sync.c \
getdns/getdns.h \ getdns/getdns.h \
config.h \ config.h \
@ -411,9 +459,9 @@ sync.lo sync.o: $(srcdir)/sync.c \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \ $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \ $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \ ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \
config.h \ config.h \
getdns/getdns.h \ getdns/getdns.h \
@ -428,8 +476,8 @@ util-internal.lo util-internal.o: $(srcdir)/util-internal.c \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \ $(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \ $(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/str2wire.h \
$(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h
gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c \ gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c \
config.h \ config.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/gbuffer.h
@ -479,6 +527,8 @@ sha512.lo sha512.o: $(srcdir)/compat/sha512.c \
config.h config.h
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c \ strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c \
config.h config.h
strptime.lo strptime.o: $(srcdir)/compat/strptime.c \
config.h
locks.lo locks.o: $(srcdir)/util/locks.c \ locks.lo locks.o: $(srcdir)/util/locks.c \
config.h \ config.h \
$(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h
@ -505,6 +555,7 @@ val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c \
$(srcdir)/gldns/rrdef.h $(srcdir)/util/auxiliary/sldns/keyraw.h $(srcdir)/gldns/keyraw.h \ $(srcdir)/gldns/rrdef.h $(srcdir)/util/auxiliary/sldns/keyraw.h $(srcdir)/gldns/keyraw.h \
$(srcdir)/util/auxiliary/sldns/sbuffer.h $(srcdir)/gldns/gbuffer.h $(srcdir)/util/auxiliary/sldns/sbuffer.h $(srcdir)/gldns/gbuffer.h
jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h
yxml.lo yxml.o: $(srcdir)/yxml/yxml.c $(srcdir)/yxml/yxml.h
libev.lo libev.o: $(srcdir)/extension/libev.c \ libev.lo libev.o: $(srcdir)/extension/libev.c \
config.h \ config.h \
$(srcdir)/types-internal.h \ $(srcdir)/types-internal.h \
@ -525,13 +576,24 @@ libuv.lo libuv.o: $(srcdir)/extension/libuv.c \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h
poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \ poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \
config.h \ config.h \
$(srcdir)/extension/poll_eventloop.h \ $(srcdir)/util-internal.h $(srcdir)/context.h \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/debug.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/platform.h
select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \ select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \
config.h \ config.h \
$(srcdir)/extension/select_eventloop.h \ $(srcdir)/debug.h $(srcdir)/types-internal.h \
getdns/getdns.h \ getdns/getdns.h \
getdns/getdns_extra.h \ getdns/getdns_extra.h \
$(srcdir)/debug.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/platform.h \
$(srcdir)/extension/select_eventloop.h
stubby.lo stubby.o: $(stubbysrcdir)/src/stubby.c \
config.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(stubbysrcdir)/src/yaml/convert_yaml_to_json.h

1925
src/anchor.c Normal file

File diff suppressed because it is too large Load Diff

59
src/anchor.h Normal file
View File

@ -0,0 +1,59 @@
/**
*
* /brief functions for DNSSEC trust anchor management
*
*/
/*
* Copyright (c) 2017, NLnet Labs
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ANCHOR_H_
#define ANCHOR_H_
#include "getdns/getdns.h"
#include "getdns/getdns_extra.h"
#include <time.h>
#include "rr-iter.h"
void _getdns_context_equip_with_anchor(getdns_context *context, uint64_t *now_ms);
void _getdns_start_fetching_ta(getdns_context *context, getdns_eventloop *loop);
#define MAX_KSKS 16
#define RRSIG_RDATA_LEN 16
typedef struct _getdns_ksks {
size_t n;
uint16_t ids[MAX_KSKS];
size_t n_rrsigs;
uint8_t rrsigs[MAX_KSKS][RRSIG_RDATA_LEN];
} _getdns_ksks;
void _getdns_context_update_root_ksk(
getdns_context *context, _getdns_rrset *dnskey_set);
#endif
/* anchor.h */

345
src/compat/strptime.c Normal file
View File

@ -0,0 +1,345 @@
/** strptime workaround (for oa macos leopard)
* This strptime follows the man strptime (2001-11-12)
* conforming to SUSv2, POSIX.1-2001
*
* This very simple version of strptime has no:
* - E alternatives
* - O alternatives
* - Glibc additions
* - Does not process week numbers
* - Does not properly processes year day
*
* LICENSE
* Copyright (c) 2008, NLnet Labs, Matthijs Mekking
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of NLnetLabs nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
**/
#include "config.h"
#ifndef HAVE_CONFIG_H
#include <time.h>
#endif
#ifndef STRPTIME_WORKS
#define TM_YEAR_BASE 1900
#include <ctype.h>
#include <string.h>
static const char *abb_weekdays[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
};
static const char *full_weekdays[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", NULL
};
static const char *abb_months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL
};
static const char *full_months[] = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December", NULL
};
static const char *ampm[] = {
"am", "pm", NULL
};
static int
match_string(const char **buf, const char **strs)
{
int i = 0;
for (i = 0; strs[i] != NULL; i++) {
int len = strlen(strs[i]);
if (strncasecmp (*buf, strs[i], len) == 0) {
*buf += len;
return i;
}
}
return -1;
}
static int
str2int(const char **buf, int max)
{
int ret=0, count=0;
while (*buf[0] != '\0' && isdigit((unsigned char)*buf[0]) && count<max) {
ret = ret*10 + (*buf[0] - '0');
(*buf)++;
count++;
}
if (!count)
return -1;
return ret;
}
/** Converts the character string s to values which are stored in tm
* using the format specified by format
**/
char *
unbound_strptime(const char *s, const char *format, struct tm *tm)
{
int c, ret;
int split_year = 0;
while ((c = *format) != '\0') {
/* whitespace, literal or format */
if (isspace((unsigned char)c)) { /* whitespace */
/** whitespace matches zero or more whitespace characters in the
* input string.
**/
while (isspace((unsigned char)*s))
s++;
}
else if (c == '%') { /* format */
format++;
c = *format;
switch (c) {
case '%': /* %% is converted to % */
if (*s != c) {
return NULL;
}
s++;
break;
case 'a': /* weekday name, abbreviated or full */
case 'A':
ret = match_string(&s, full_weekdays);
if (ret < 0)
ret = match_string(&s, abb_weekdays);
if (ret < 0) {
return NULL;
}
tm->tm_wday = ret;
break;
case 'b': /* month name, abbreviated or full */
case 'B':
case 'h':
ret = match_string(&s, full_months);
if (ret < 0)
ret = match_string(&s, abb_months);
if (ret < 0) {
return NULL;
}
tm->tm_mon = ret;
break;
case 'c': /* date and time representation */
if (!(s = unbound_strptime(s, "%x %X", tm))) {
return NULL;
}
break;
case 'C': /* century number */
ret = str2int(&s, 2);
if (ret < 0 || ret > 99) { /* must be in [00,99] */
return NULL;
}
if (split_year) {
tm->tm_year = ret*100 + (tm->tm_year%100);
}
else {
tm->tm_year = ret*100 - TM_YEAR_BASE;
split_year = 1;
}
break;
case 'd': /* day of month */
case 'e':
ret = str2int(&s, 2);
if (ret < 1 || ret > 31) { /* must be in [01,31] */
return NULL;
}
tm->tm_mday = ret;
break;
case 'D': /* equivalent to %m/%d/%y */
if (!(s = unbound_strptime(s, "%m/%d/%y", tm))) {
return NULL;
}
break;
case 'H': /* hour */
ret = str2int(&s, 2);
if (ret < 0 || ret > 23) { /* must be in [00,23] */
return NULL;
}
tm->tm_hour = ret;
break;
case 'I': /* 12hr clock hour */
ret = str2int(&s, 2);
if (ret < 1 || ret > 12) { /* must be in [01,12] */
return NULL;
}
if (ret == 12) /* actually [0,11] */
ret = 0;
tm->tm_hour = ret;
break;
case 'j': /* day of year */
ret = str2int(&s, 2);
if (ret < 1 || ret > 366) { /* must be in [001,366] */
return NULL;
}
tm->tm_yday = ret;
break;
case 'm': /* month */
ret = str2int(&s, 2);
if (ret < 1 || ret > 12) { /* must be in [01,12] */
return NULL;
}
/* months go from 0-11 */
tm->tm_mon = (ret-1);
break;
case 'M': /* minute */
ret = str2int(&s, 2);
if (ret < 0 || ret > 59) { /* must be in [00,59] */
return NULL;
}
tm->tm_min = ret;
break;
case 'n': /* arbitrary whitespace */
case 't':
while (isspace((unsigned char)*s))
s++;
break;
case 'p': /* am pm */
ret = match_string(&s, ampm);
if (ret < 0) {
return NULL;
}
if (tm->tm_hour < 0 || tm->tm_hour > 11) { /* %I */
return NULL;
}
if (ret == 1) /* pm */
tm->tm_hour += 12;
break;
case 'r': /* equivalent of %I:%M:%S %p */
if (!(s = unbound_strptime(s, "%I:%M:%S %p", tm))) {
return NULL;
}
break;
case 'R': /* equivalent of %H:%M */
if (!(s = unbound_strptime(s, "%H:%M", tm))) {
return NULL;
}
break;
case 'S': /* seconds */
ret = str2int(&s, 2);
/* 60 may occur for leap seconds */
/* earlier 61 was also allowed */
if (ret < 0 || ret > 60) { /* must be in [00,60] */
return NULL;
}
tm->tm_sec = ret;
break;
case 'T': /* equivalent of %H:%M:%S */
if (!(s = unbound_strptime(s, "%H:%M:%S", tm))) {
return NULL;
}
break;
case 'U': /* week number, with the first Sun of Jan being w1 */
ret = str2int(&s, 2);
if (ret < 0 || ret > 53) { /* must be in [00,53] */
return NULL;
}
/** it is hard (and not necessary for nsd) to determine time
* data from week number.
**/
break;
case 'w': /* day of week */
ret = str2int(&s, 1);
if (ret < 0 || ret > 6) { /* must be in [0,6] */
return NULL;
}
tm->tm_wday = ret;
break;
case 'W': /* week number, with the first Mon of Jan being w1 */
ret = str2int(&s, 2);
if (ret < 0 || ret > 53) { /* must be in [00,53] */
return NULL;
}
/** it is hard (and not necessary for nsd) to determine time
* data from week number.
**/
break;
case 'x': /* date format */
if (!(s = unbound_strptime(s, "%m/%d/%y", tm))) {
return NULL;
}
break;
case 'X': /* time format */
if (!(s = unbound_strptime(s, "%H:%M:%S", tm))) {
return NULL;
}
break;
case 'y': /* last two digits of a year */
ret = str2int(&s, 2);
if (ret < 0 || ret > 99) { /* must be in [00,99] */
return NULL;
}
if (split_year) {
tm->tm_year = ((tm->tm_year/100) * 100) + ret;
}
else {
split_year = 1;
/** currently:
* if in [0,68] we are in 21th century,
* if in [69,99] we are in 20th century.
**/
if (ret < 69) /* 2000 */
ret += 100;
tm->tm_year = ret;
}
break;
case 'Y': /* year */
ret = str2int(&s, 4);
if (ret < 0 || ret > 9999) {
return NULL;
}
tm->tm_year = ret - TM_YEAR_BASE;
break;
case '\0':
default: /* unsupported, cannot match format */
return NULL;
break;
}
}
else { /* literal */
/* if input cannot match format, return NULL */
if (*s != c)
return NULL;
s++;
}
format++;
}
/* return pointer to remainder of s */
return (char*) s;
}
#endif /* STRPTIME_WORKS */

View File

@ -82,6 +82,10 @@ static struct const_info consts_info[] = {
{ 622, "GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS", GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS_TEXT }, { 622, "GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS", GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS_TEXT },
{ 623, "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME_TEXT }, { 623, "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME_TEXT },
{ 624, "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES_TEXT }, { 624, "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES_TEXT },
{ 625, "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL", GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL_TEXT },
{ 626, "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_CA", GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_CA_TEXT },
{ 627, "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_EMAIL", GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_EMAIL_TEXT },
{ 628, "GETDNS_CONTEXT_CODE_APPDATA_DIR", GETDNS_CONTEXT_CODE_APPDATA_DIR_TEXT },
{ 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT }, { 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT },
{ 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT }, { 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT },
{ 702, "GETDNS_CALLBACK_TIMEOUT", GETDNS_CALLBACK_TIMEOUT_TEXT }, { 702, "GETDNS_CALLBACK_TIMEOUT", GETDNS_CALLBACK_TIMEOUT_TEXT },
@ -150,6 +154,7 @@ static struct const_name_info consts_name_info[] = {
{ "GETDNS_CALLBACK_COMPLETE", 700 }, { "GETDNS_CALLBACK_COMPLETE", 700 },
{ "GETDNS_CALLBACK_ERROR", 703 }, { "GETDNS_CALLBACK_ERROR", 703 },
{ "GETDNS_CALLBACK_TIMEOUT", 702 }, { "GETDNS_CALLBACK_TIMEOUT", 702 },
{ "GETDNS_CONTEXT_CODE_APPDATA_DIR", 628 },
{ "GETDNS_CONTEXT_CODE_APPEND_NAME", 607 }, { "GETDNS_CONTEXT_CODE_APPEND_NAME", 607 },
{ "GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW", 614 }, { "GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW", 614 },
{ "GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS", 609 }, { "GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS", 609 },
@ -174,6 +179,9 @@ static struct const_name_info consts_name_info[] = {
{ "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", 623 }, { "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", 623 },
{ "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", 624 }, { "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", 624 },
{ "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 }, { "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 },
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL", 625 },
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_CA", 626 },
{ "GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_EMAIL", 627 },
{ "GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS", 603 }, { "GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS", 603 },
{ "GETDNS_DNSSEC_BOGUS", 401 }, { "GETDNS_DNSSEC_BOGUS", 401 },
{ "GETDNS_DNSSEC_INDETERMINATE", 402 }, { "GETDNS_DNSSEC_INDETERMINATE", 402 },

View File

@ -35,11 +35,13 @@
*/ */
#include "config.h" #include "config.h"
#include "anchor.h"
#ifndef USE_WINSOCK #ifndef USE_WINSOCK
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/time.h> #include <sys/time.h>
#include <netdb.h> #include <netdb.h>
#include <pwd.h>
#else #else
#include <winsock2.h> #include <winsock2.h>
#include <iphlpapi.h> #include <iphlpapi.h>
@ -52,6 +54,7 @@ typedef unsigned short in_port_t;
#include <stdio.h> #include <stdio.h>
#include <windows.h> #include <windows.h>
#include <wincrypt.h> #include <wincrypt.h>
#include <shlobj.h>
#endif #endif
#include <sys/stat.h> #include <sys/stat.h>
@ -68,7 +71,6 @@ typedef unsigned short in_port_t;
#endif #endif
#include <stdbool.h> #include <stdbool.h>
#include "config.h"
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
#include <unbound.h> #include <unbound.h>
#endif #endif
@ -78,6 +80,7 @@ typedef unsigned short in_port_t;
#include "context.h" #include "context.h"
#include "types-internal.h" #include "types-internal.h"
#include "util-internal.h" #include "util-internal.h"
#include "platform.h"
#include "dnssec.h" #include "dnssec.h"
#include "stub.h" #include "stub.h"
#include "list.h" #include "list.h"
@ -702,11 +705,7 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
} }
if (upstream->fd != -1) if (upstream->fd != -1)
{ {
#ifdef USE_WINSOCK _getdns_closesocket(upstream->fd);
closesocket(upstream->fd);
#else
close(upstream->fd);
#endif
} }
while (pin) { while (pin) {
sha256_pin_t *nextpin = pin->next; sha256_pin_t *nextpin = pin->next;
@ -734,65 +733,65 @@ void _getdns_upstream_log(getdns_upstream *upstream, uint64_t system,
va_end(args); va_end(args);
} }
void static void
_getdns_upstream_shutdown(getdns_upstream *upstream) upstream_backoff(getdns_upstream *upstream) {
{ upstream->conn_state = GETDNS_CONN_BACKOFF;
/*Set condition to tear down asap to stop any further scheduling*/ /* Increase the backoff interval incrementally up to the tls_backoff_time*/
upstream->conn_state = GETDNS_CONN_TEARDOWN; if (upstream->conn_backoff_interval < upstream->upstreams->tls_backoff_time) {
/* Update total stats for the upstream.*/ if (upstream->conn_backoff_interval < (UINT16_MAX-1)/2)
upstream->total_responses+=upstream->responses_received; upstream->conn_backoff_interval *= 2;
upstream->total_timeouts+=upstream->responses_timeouts; else
/* Need the last auth state when using session resumption*/ upstream->conn_backoff_interval = upstream->upstreams->tls_backoff_time;
upstream->last_tls_auth_state = upstream->tls_auth_state; }
/* Keep track of the best auth state this upstream has had*/ if (upstream->conn_backoff_interval < upstream->upstreams->tls_backoff_time)
if (upstream->tls_auth_state > upstream->best_tls_auth_state) upstream->conn_retry_time = time(NULL) + upstream->conn_backoff_interval;
upstream->best_tls_auth_state = upstream->tls_auth_state; else
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, upstream->conn_retry_time = time(NULL) + upstream->upstreams->tls_backoff_time;
"%-40s : Conn closed : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n", upstream->total_responses = 0;
upstream->addr_str, upstream->total_timeouts = 0;
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"), upstream->conn_completed = 0;
(int)upstream->responses_received, (int)upstream->responses_timeouts, upstream->conn_setup_failed = 0;
_getdns_auth_str(upstream->tls_auth_state), (int)upstream->keepalive_timeout); upstream->conn_shutdowns = 0;
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, upstream->conn_backoffs++;
"%-40s : Upstream stats: Transport=%s - Resp=%d,Timeouts=%d,Best_auth=%s\n", _getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_NOTICE,
upstream->addr_str, "%-40s : !Backing off this upstream - Will retry again in %ds at %s",
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"), upstream->addr_str,
(int)upstream->total_responses, (int)upstream->total_timeouts, upstream->conn_backoff_interval,
_getdns_auth_str(upstream->best_tls_auth_state)); asctime(gmtime(&upstream->conn_retry_time)));
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, }
"%-40s : Upstream stats: Transport=%s - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n",
upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->conn_completed, (int)upstream->conn_setup_failed,
(int)upstream->conn_shutdowns, (int)upstream->conn_backoffs);
static void
_getdns_upstream_reset(getdns_upstream *upstream)
{
/* Back off connections that never got up service at all (probably no /* Back off connections that never got up service at all (probably no
TCP service or incompatible TLS version/cipher). TCP service or incompatible TLS version/cipher).
Leave choice between working upstreams to the stub. Leave choice between working upstreams to the stub.
This back-off should be time based for TLS according to RFC7858. For now, This back-off should be time based for TLS according to RFC7858. For now,
use the same basis if we simply can't get TCP service either.*/ use the same basis if we simply can't get TCP service either.*/
uint16_t conn_retries = upstream->upstreams->tls_connection_retries;
/* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/ /* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/
/*This is the configured number of retries to attempt*/
uint16_t conn_retries = upstream->upstreams->tls_connection_retries;
if (upstream->conn_setup_failed >= conn_retries if (upstream->conn_setup_failed >= conn_retries
|| ((int)upstream->conn_shutdowns >= conn_retries*GETDNS_TRANSPORT_FAIL_MULT || ((int)upstream->conn_shutdowns >= conn_retries*GETDNS_TRANSPORT_FAIL_MULT
&& upstream->total_responses == 0) && upstream->total_responses == 0)
|| (upstream->conn_completed >= conn_retries && || (upstream->conn_completed >= conn_retries &&
upstream->total_responses == 0 && upstream->total_responses == 0 &&
upstream->total_timeouts > GETDNS_TRANSPORT_FAIL_MULT)) { upstream->total_timeouts > GETDNS_TRANSPORT_FAIL_MULT)) {
upstream->conn_state = GETDNS_CONN_BACKOFF;
upstream->conn_retry_time = time(NULL) + upstream->upstreams->tls_backoff_time;
upstream->total_responses = 0;
upstream->total_timeouts = 0;
upstream->conn_completed = 0;
upstream->conn_setup_failed = 0;
upstream->conn_shutdowns = 0;
upstream->conn_backoffs++;
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, upstream_backoff(upstream);
"%-40s : !Backing off this upstream - Will retry as new upstream at %s",
upstream->addr_str,
asctime(gmtime(&upstream->conn_retry_time)));
} }
/* If we didn't backoff it would be nice to reset the conn_backoff_interval
if the upstream is working well again otherwise it would get stuck at the
tls_backoff_time forever... How about */
if (upstream->conn_state != GETDNS_CONN_BACKOFF &&
upstream->responses_received > 1)
upstream->conn_backoff_interval = 1;
// Reset per connection counters // Reset per connection counters
upstream->queries_sent = 0; upstream->queries_sent = 0;
upstream->responses_received = 0; upstream->responses_received = 0;
@ -802,17 +801,17 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
/* Now TLS stuff*/ /* Now TLS stuff*/
upstream->tls_auth_state = GETDNS_AUTH_NONE; upstream->tls_auth_state = GETDNS_AUTH_NONE;
if (upstream->event.ev && upstream->loop) {
upstream->loop->vmt->clear(
upstream->loop, &upstream->event);
}
if (upstream->tls_obj != NULL) { if (upstream->tls_obj != NULL) {
SSL_shutdown(upstream->tls_obj); SSL_shutdown(upstream->tls_obj);
SSL_free(upstream->tls_obj); SSL_free(upstream->tls_obj);
upstream->tls_obj = NULL; upstream->tls_obj = NULL;
} }
if (upstream->fd != -1) { if (upstream->fd != -1) {
#ifdef USE_WINSOCK _getdns_closesocket(upstream->fd);
closesocket(upstream->fd);
#else
close(upstream->fd);
#endif
upstream->fd = -1; upstream->fd = -1;
} }
/* Set connection ready for use again*/ /* Set connection ready for use again*/
@ -820,6 +819,39 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
upstream->conn_state = GETDNS_CONN_CLOSED; upstream->conn_state = GETDNS_CONN_CLOSED;
} }
void
_getdns_upstream_shutdown(getdns_upstream *upstream)
{
/* Update total stats for the upstream.*/
upstream->total_responses+=upstream->responses_received;
upstream->total_timeouts+=upstream->responses_timeouts;
/* Need the last auth state when using session resumption*/
upstream->last_tls_auth_state = upstream->tls_auth_state;
/* Keep track of the best auth state this upstream has had*/
if (upstream->tls_auth_state > upstream->best_tls_auth_state)
upstream->best_tls_auth_state = upstream->tls_auth_state;
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
"%-40s : Conn closed: %s - Resps=%6d, Timeouts =%6d, Curr_auth =%7s, Keepalive(ms)=%6d\n",
upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->responses_received, (int)upstream->responses_timeouts,
_getdns_auth_str(upstream->tls_auth_state), (int)upstream->keepalive_timeout);
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_INFO,
"%-40s : Upstream : %s - Resps=%6d, Timeouts =%6d, Best_auth =%7s\n",
upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->total_responses, (int)upstream->total_timeouts,
_getdns_auth_str(upstream->best_tls_auth_state));
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_INFO,
"%-40s : Upstream : %s - Conns=%6d, Conn_fails=%6d, Conn_shuts=%7d, Backoffs =%6d\n",
upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->conn_completed, (int)upstream->conn_setup_failed,
(int)upstream->conn_shutdowns, (int)upstream->conn_backoffs);
_getdns_upstream_reset(upstream);
}
static int static int
tls_is_in_transports_list(getdns_context *context) tls_is_in_transports_list(getdns_context *context)
{ {
@ -944,6 +976,7 @@ upstream_init(getdns_upstream *upstream,
upstream->conn_shutdowns = 0; upstream->conn_shutdowns = 0;
upstream->conn_setup_failed = 0; upstream->conn_setup_failed = 0;
upstream->conn_retry_time = 0; upstream->conn_retry_time = 0;
upstream->conn_backoff_interval = 1;
upstream->conn_backoffs = 0; upstream->conn_backoffs = 0;
upstream->total_responses = 0; upstream->total_responses = 0;
upstream->total_timeouts = 0; upstream->total_timeouts = 0;
@ -1329,6 +1362,37 @@ static void _getdns_check_expired_pending_netreqs_cb(void *arg)
_getdns_check_expired_pending_netreqs((getdns_context *)arg, &now_ms); _getdns_check_expired_pending_netreqs((getdns_context *)arg, &now_ms);
} }
static const char *_getdns_default_trust_anchors_url =
"http://data.iana.org/root-anchors/root-anchors.xml";
/* The ICANN CA fetched at 24 Sep 2010. Valid to 2028 */
static const char *_getdns_default_trust_anchors_verify_CA =
"-----BEGIN CERTIFICATE-----\n"
"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n"
"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n"
"BAMTDUlDQU5OIFJvb3QgQ0ExCzAJBgNVBAYTAlVTMB4XDTA5MTIyMzA0MTkxMloX\n"
"DTI5MTIxODA0MTkxMlowXTEOMAwGA1UEChMFSUNBTk4xJjAkBgNVBAsTHUlDQU5O\n"
"IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1JQ0FOTiBSb290IENB\n"
"MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKDb\n"
"cLhPNNqc1NB+u+oVvOnJESofYS9qub0/PXagmgr37pNublVThIzyLPGCJ8gPms9S\n"
"G1TaKNIsMI7d+5IgMy3WyPEOECGIcfqEIktdR1YWfJufXcMReZwU4v/AdKzdOdfg\n"
"ONiwc6r70duEr1IiqPbVm5T05l1e6D+HkAvHGnf1LtOPGs4CHQdpIUcy2kauAEy2\n"
"paKcOcHASvbTHK7TbbvHGPB+7faAztABLoneErruEcumetcNfPMIjXKdv1V1E3C7\n"
"MSJKy+jAqqQJqjZoQGB0necZgUMiUv7JK1IPQRM2CXJllcyJrm9WFxY0c1KjBO29\n"
"iIKK69fcglKcBuFShUECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B\n"
"Af8EBAMCAf4wHQYDVR0OBBYEFLpS6UmDJIZSL8eZzfyNa2kITcBQMA0GCSqGSIb3\n"
"DQEBCwUAA4IBAQAP8emCogqHny2UYFqywEuhLys7R9UKmYY4suzGO4nkbgfPFMfH\n"
"6M+Zj6owwxlwueZt1j/IaCayoKU3QsrYYoDRolpILh+FPwx7wseUEV8ZKpWsoDoD\n"
"2JFbLg2cfB8u/OlE4RYmcxxFSmXBg0yQ8/IoQt/bxOcEEhhiQ168H2yE5rxJMt9h\n"
"15nu5JBSewrCkYqYYmaxyOC3WrVGfHZxVI7MpIFcGdvSb2a1uyuua8l0BKgk3ujF\n"
"0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg\n"
"j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n"
"-----END CERTIFICATE-----\n";
static const char *_getdns_default_trust_anchors_verify_email =
"dnssec@iana.org";
/* /*
* getdns_context_create * getdns_context_create
* *
@ -1428,6 +1492,20 @@ getdns_context_create_with_extended_memory_functions(
result->suffixes = no_suffixes; result->suffixes = no_suffixes;
result->suffixes_len = sizeof(no_suffixes); result->suffixes_len = sizeof(no_suffixes);
result->trust_anchors_source = GETDNS_TASRC_NONE;
result->can_write_appdata = PROP_UNKNOWN;
result->trust_anchors_url = NULL;
result->trust_anchors_verify_email = NULL;
result->trust_anchors_verify_CA = NULL;
result->appdata_dir = NULL;
(void) memset(&result->root_ksk, 0, sizeof(result->root_ksk));
(void) memset(&result->a, 0, sizeof(result->a));
(void) memset(&result->aaaa, 0, sizeof(result->aaaa));
result->a.fd = -1;
result->aaaa.fd = -1;
gldns_buffer_init_vfixed_frm_data(&gbuf, result->trust_anchors_spc gldns_buffer_init_vfixed_frm_data(&gbuf, result->trust_anchors_spc
, sizeof(result->trust_anchors_spc)); , sizeof(result->trust_anchors_spc));
@ -1445,12 +1523,16 @@ getdns_context_create_with_extended_memory_functions(
, result->trust_anchors , result->trust_anchors
, result->trust_anchors_len); , result->trust_anchors_len);
if (!_getdns_parse_ta_file(NULL, &gbuf)) { if (!_getdns_parse_ta_file(NULL, &gbuf)) {
GETDNS_FREE(result->mf, result->trust_anchors);
result->trust_anchors = NULL; result->trust_anchors = NULL;
result->trust_anchors_len = 0; result->trust_anchors_len = 0;
} } else
result->trust_anchors_source = GETDNS_TASRC_ZONE;
} }
} else } else {
result->trust_anchors = result->trust_anchors_spc; result->trust_anchors = result->trust_anchors_spc;
result->trust_anchors_source = GETDNS_TASRC_ZONE;
}
result->upstreams = NULL; result->upstreams = NULL;
@ -1484,6 +1566,9 @@ getdns_context_create_with_extended_memory_functions(
result->return_call_reporting = 0; result->return_call_reporting = 0;
result->specify_class = GETDNS_RRCLASS_IN; result->specify_class = GETDNS_RRCLASS_IN;
result->sys_ctxt = NULL;
result->ta_notify = NULL;
/* state data used to detect changes to the system config files /* state data used to detect changes to the system config files
*/ */
result->fchg_resolvconf = NULL; result->fchg_resolvconf = NULL;
@ -1520,7 +1605,15 @@ getdns_context_create_with_extended_memory_functions(
#endif #endif
/* Only initialise SSL once and ideally in a thread-safe manner */ /* Only initialise SSL once and ideally in a thread-safe manner */
if (ssl_init == false) { if (ssl_init == false) {
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
OpenSSL_add_all_algorithms();
SSL_library_init(); SSL_library_init();
#else
OPENSSL_init_crypto( OPENSSL_INIT_ADD_ALL_CIPHERS
| OPENSSL_INIT_ADD_ALL_DIGESTS
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
(void)OPENSSL_init_ssl(0, NULL);
#endif
ssl_init = true; ssl_init = true;
} }
#ifdef HAVE_PTHREAD #ifdef HAVE_PTHREAD
@ -1528,7 +1621,6 @@ getdns_context_create_with_extended_memory_functions(
#else #else
/* XXX implement Windows-style unlock here */ /* XXX implement Windows-style unlock here */
#endif #endif
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
result->unbound_ctx = NULL; result->unbound_ctx = NULL;
if ((r = rebuild_ub_ctx(result))) if ((r = rebuild_ub_ctx(result)))
@ -1603,6 +1695,10 @@ getdns_context_destroy(struct getdns_context *context)
return; return;
context->destroying = 1; context->destroying = 1;
if (context->sys_ctxt)
getdns_context_destroy(context->sys_ctxt);
/* cancel all outstanding requests */ /* cancel all outstanding requests */
cancel_outstanding_requests(context); cancel_outstanding_requests(context);
@ -1665,10 +1761,20 @@ getdns_context_destroy(struct getdns_context *context)
_getdns_traverse_postorder(&context->local_hosts, _getdns_traverse_postorder(&context->local_hosts,
destroy_local_host, context); destroy_local_host, context);
getdns_dict_destroy(context->header); getdns_dict_destroy(context->header);
getdns_dict_destroy(context->add_opt_parameters); getdns_dict_destroy(context->add_opt_parameters);
if (context->trust_anchors_url)
GETDNS_FREE(context->mf, context->trust_anchors_url);
if (context->trust_anchors_verify_CA)
GETDNS_FREE( context->mf
, context->trust_anchors_verify_CA);
if (context->trust_anchors_verify_email)
GETDNS_FREE( context->mf
, context->trust_anchors_verify_email);
if (context->appdata_dir)
GETDNS_FREE(context->mf, context->appdata_dir);
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
WSACleanup(); WSACleanup();
#endif #endif
@ -2442,15 +2548,15 @@ getdns_context_set_dns_root_servers(
if (addr_bd->size == 16 && if (addr_bd->size == 16 &&
inet_ntop(AF_INET6, addr_bd->data, dst, sizeof(dst))) inet_ntop(AF_INET6, addr_bd->data, dst, sizeof(dst)))
fprintf(fh,". NS "PRIsz".root-servers.getdnsapi.net.\n" fprintf(fh,". NS %"PRIsz".root-servers.getdnsapi.net.\n"
PRIsz".root-servers.getdnsapi.net. AAAA %s\n", "%"PRIsz".root-servers.getdnsapi.net. AAAA %s\n",
i, i, dst); i, i, dst);
else if (addr_bd->size == 4 && else if (addr_bd->size == 4 &&
inet_ntop(AF_INET, addr_bd->data, dst, sizeof(dst))) inet_ntop(AF_INET, addr_bd->data, dst, sizeof(dst)))
fprintf(fh,". NS "PRIsz".root-servers.getdnsapi.net.\n" fprintf(fh,". NS %"PRIsz".root-servers.getdnsapi.net.\n"
PRIsz".root-servers.getdnsapi.net. A %s\n", "%"PRIsz".root-servers.getdnsapi.net. A %s\n",
i, i, dst); i, i, dst);
} }
fclose(fh); fclose(fh);
@ -2615,9 +2721,11 @@ getdns_context_set_dnssec_trust_anchors(
context->trust_anchors = _getdns_list2wire(value, context->trust_anchors = _getdns_list2wire(value,
context->trust_anchors_spc, &context->trust_anchors_len, context->trust_anchors_spc, &context->trust_anchors_len,
&context->mf); &context->mf);
context->trust_anchors_source = GETDNS_TASRC_APP;
} else { } else {
context->trust_anchors = NULL; context->trust_anchors = NULL;
context->trust_anchors_len = 0; context->trust_anchors_len = 0;
context->trust_anchors_source = GETDNS_TASRC_NONE;
} }
dispatch_updated(context, GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS); dispatch_updated(context, GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS);
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
@ -2666,11 +2774,14 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
struct addrinfo hints; struct addrinfo hints;
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(upstream_list, GETDNS_RETURN_INVALID_PARAMETER);
r = getdns_list_get_length(upstream_list, &count); if ( !upstream_list
if (count == 0 || r != GETDNS_RETURN_GOOD) { || (r = getdns_list_get_length(upstream_list, &count))
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; || count == 0) {
_getdns_upstreams_dereference(context->upstreams);
context->upstreams = NULL;
dispatch_updated(context,
GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS);
} }
memset(&hints, 0, sizeof(struct addrinfo)); memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
@ -3411,16 +3522,13 @@ _getdns_ns_dns_setup(struct getdns_context *context)
} }
getdns_return_t getdns_return_t
_getdns_context_prepare_for_resolution(struct getdns_context *context, _getdns_context_prepare_for_resolution(getdns_context *context)
int usenamespaces)
{ {
size_t i;
getdns_return_t r; getdns_return_t r;
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
if (context->destroying) { if (context->destroying)
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
}
/* Transport can in theory be set per query in stub mode */ /* Transport can in theory be set per query in stub mode */
if (context->resolution_type == GETDNS_RESOLUTION_STUB && if (context->resolution_type == GETDNS_RESOLUTION_STUB &&
@ -3497,40 +3605,21 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context,
*/ */
if (! usenamespaces) { r = _getdns_ns_dns_setup(context);
r = _getdns_ns_dns_setup(context); if (r == GETDNS_RETURN_GOOD)
if (r == GETDNS_RETURN_GOOD) context->resolution_type_set = context->resolution_type;
context->resolution_type_set = context->resolution_type;
return r;
}
r = GETDNS_RETURN_GOOD;
for (i = 0; i < context->namespace_count; i++) {
switch (context->namespaces[i]) {
case GETDNS_NAMESPACE_DNS:
r = _getdns_ns_dns_setup(context);
break;
default:
r = GETDNS_RETURN_BAD_CONTEXT;
break;
}
if (r != GETDNS_RETURN_GOOD)
return r; /* try again later (resolution_type_set) */
}
context->resolution_type_set = context->resolution_type;
return r; return r;
} /* _getdns_context_prepare_for_resolution */ } /* _getdns_context_prepare_for_resolution */
char * char *
_getdns_strdup(const struct mem_funcs *mfs, const char *s) _getdns_strdup(const struct mem_funcs *mfs, const char *s)
{ {
size_t sz = strlen(s) + 1; size_t sz;
char *r = GETDNS_XMALLOC(*mfs, char, sz); char *r;
if (r) if (!s || !(r = GETDNS_XMALLOC(*mfs, char, (sz = strlen(s) + 1))))
return memcpy(r, s, sz);
else
return NULL; return NULL;
else
return memcpy(r, s, sz);
} }
struct getdns_bindata * struct getdns_bindata *
@ -3659,12 +3748,15 @@ getdns_context_get_eventloop(getdns_context *context, getdns_eventloop **loop)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
static size_t _getdns_get_appdata(getdns_context *context, char *path);
static getdns_dict* static getdns_dict*
_get_context_settings(getdns_context* context) _get_context_settings(getdns_context* context)
{ {
getdns_dict *result = getdns_dict_create_with_context(context); getdns_dict *result = getdns_dict_create_with_context(context);
getdns_list *list; getdns_list *list;
size_t i; size_t i;
const char *str_value;
char appdata_dir[_GETDNS_PATH_MAX] = "";
if (!result) if (!result)
return NULL; return NULL;
@ -3685,6 +3777,8 @@ _get_context_settings(getdns_context* context)
|| ( context->edns_maximum_udp_payload_size != -1 || ( context->edns_maximum_udp_payload_size != -1
&& getdns_dict_set_int(result, "edns_maximum_udp_payload_size", && getdns_dict_set_int(result, "edns_maximum_udp_payload_size",
context->edns_maximum_udp_payload_size)) context->edns_maximum_udp_payload_size))
|| getdns_dict_set_int(result, "edns_client_subnet_private",
context->edns_client_subnet_private)
|| getdns_dict_set_int(result, "edns_extended_rcode", || getdns_dict_set_int(result, "edns_extended_rcode",
context->edns_extended_rcode) context->edns_extended_rcode)
|| getdns_dict_set_int(result, "edns_version", || getdns_dict_set_int(result, "edns_version",
@ -3700,7 +3794,12 @@ _get_context_settings(getdns_context* context)
|| getdns_dict_set_int(result, "tls_backoff_time", || getdns_dict_set_int(result, "tls_backoff_time",
context->tls_backoff_time) context->tls_backoff_time)
|| getdns_dict_set_int(result, "tls_connection_retries", || getdns_dict_set_int(result, "tls_connection_retries",
context->tls_connection_retries)) context->tls_connection_retries)
|| getdns_dict_set_int(result, "tls_query_padding_blocksize",
context->tls_query_padding_blocksize)
|| getdns_dict_set_int(result, "resolution_type",
context->resolution_type)
)
goto error; goto error;
/* list fields */ /* list fields */
@ -3719,6 +3818,14 @@ _get_context_settings(getdns_context* context)
getdns_list_destroy(list); getdns_list_destroy(list);
goto error; goto error;
} }
if (getdns_context_get_dnssec_trust_anchors(context, &list))
; /* pass */
else if (list && _getdns_dict_set_this_list(
result, "dnssec_trust_anchors", list)) {
getdns_list_destroy(list);
goto error;
}
if (context->dns_transport_count > 0) { if (context->dns_transport_count > 0) {
/* create a namespace list */ /* create a namespace list */
if (!(list = getdns_list_create_with_context(context))) if (!(list = getdns_list_create_with_context(context)))
@ -3754,6 +3861,15 @@ _get_context_settings(getdns_context* context)
return NULL; return NULL;
} }
} }
(void) _getdns_get_appdata(context, appdata_dir);
(void) getdns_dict_util_set_string(result, "appdata_dir", appdata_dir);
if (!getdns_context_get_trust_anchors_url(context, &str_value) && str_value)
(void) getdns_dict_util_set_string(result, "trust_anchors_url", str_value);
if (!getdns_context_get_trust_anchors_verify_CA(context, &str_value) && str_value)
(void) getdns_dict_util_set_string(result, "trust_anchors_verify_CA", str_value);
if (!getdns_context_get_trust_anchors_verify_email(context, &str_value) && str_value)
(void) getdns_dict_util_set_string(result, "trust_anchors_verify_email", str_value);
return result; return result;
error: error:
getdns_dict_destroy(result); getdns_dict_destroy(result);
@ -3771,9 +3887,24 @@ getdns_context_get_api_information(getdns_context* context)
&& ! getdns_dict_util_set_string( && ! getdns_dict_util_set_string(
result, "version_string", GETDNS_VERSION) result, "version_string", GETDNS_VERSION)
&& ! getdns_dict_set_int(
result, "version_number", getdns_get_version_number())
&& ! getdns_dict_util_set_string(
result, "api_version_string", getdns_get_api_version())
&& ! getdns_dict_set_int(
result, "api_version_number", getdns_get_api_version_number())
&& ! getdns_dict_util_set_string( && ! getdns_dict_util_set_string(
result, "implementation_string", PACKAGE_URL) result, "implementation_string", PACKAGE_URL)
&& ! getdns_dict_util_set_string(
result, "compilation_comment", GETDNS_COMPILATION_COMMENT)
&& ! getdns_dict_util_set_string(
result, "trust_anchor_file", TRUST_ANCHOR_FILE)
&& ! getdns_dict_set_int( && ! getdns_dict_set_int(
result, "resolution_type", context->resolution_type) result, "resolution_type", context->resolution_type)
@ -4375,6 +4506,12 @@ static getdns_return_t _get_list_or_read_file(const getdns_dict *config_dict,
else r = GETDNS_RETURN_INVALID_PARAMETER; \ else r = GETDNS_RETURN_INVALID_PARAMETER; \
} }
#define CONTEXT_SETTING_STRING(X) \
} else if (_streq(setting, #X )) { \
if (!(r = getdns_dict_get_bindata(config_dict, #X , &bd))) \
r = getdns_context_set_ ## X( \
context, (char *)bd->data);
static getdns_return_t static getdns_return_t
_getdns_context_config_setting(getdns_context *context, _getdns_context_config_setting(getdns_context *context,
const getdns_dict *config_dict, const getdns_bindata *setting) const getdns_dict *config_dict, const getdns_bindata *setting)
@ -4386,6 +4523,7 @@ _getdns_context_config_setting(getdns_context *context,
getdns_transport_list_t dns_transport_list[100]; getdns_transport_list_t dns_transport_list[100];
size_t count, i; size_t count, i;
uint32_t n; uint32_t n;
getdns_bindata *bd;
int destroy_list = 0; int destroy_list = 0;
if (_streq(setting, "all_context")) { if (_streq(setting, "all_context")) {
@ -4423,6 +4561,10 @@ _getdns_context_config_setting(getdns_context *context,
CONTEXT_SETTING_INT(tls_backoff_time) CONTEXT_SETTING_INT(tls_backoff_time)
CONTEXT_SETTING_INT(tls_connection_retries) CONTEXT_SETTING_INT(tls_connection_retries)
CONTEXT_SETTING_INT(tls_query_padding_blocksize) CONTEXT_SETTING_INT(tls_query_padding_blocksize)
CONTEXT_SETTING_STRING(trust_anchors_url)
CONTEXT_SETTING_STRING(trust_anchors_verify_CA)
CONTEXT_SETTING_STRING(trust_anchors_verify_email)
CONTEXT_SETTING_STRING(appdata_dir)
/**************************************/ /**************************************/
/**** ****/ /**** ****/
@ -4475,8 +4617,14 @@ _getdns_context_config_setting(getdns_context *context,
/**** Ignored context settings ****/ /**** Ignored context settings ****/
/**** ****/ /**** ****/
/************************************/ /************************************/
} else if (!_streq(setting, "implementation_string") && } else if (!_streq(setting, "implementation_string")
!_streq(setting, "version_string")) { && !_streq(setting, "version_string")
&& !_streq(setting, "version_number")
&& !_streq(setting, "api_version_string")
&& !_streq(setting, "api_version_number")
&& !_streq(setting, "trust_anchor_file")
&& !_streq(setting, "compilation_comment")
) {
r = GETDNS_RETURN_NOT_IMPLEMENTED; r = GETDNS_RETURN_NOT_IMPLEMENTED;
} }
return r; return r;
@ -4505,4 +4653,360 @@ getdns_context_config(getdns_context *context, const getdns_dict *config_dict)
return r; return r;
} }
static size_t _getdns_get_appdata(getdns_context *context, char *path)
{
size_t len = 0;
#ifdef USE_WINSOCK
# define SLASHTOK '\\'
# define APPDATA_SUBDIR "getdns"
if (context->appdata_dir) {
(void) strcpy(path, context->appdata_dir);
len = strlen(path);
} else if (! SUCCEEDED(SHGetFolderPath(NULL,
CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path)))
DEBUG_ANCHOR("ERROR %s(): Could not get %%AppData%% directory\n"
, __FUNC__);
else if ((len = strlen(path)) + sizeof(APPDATA_SUBDIR) + 2 >= _GETDNS_PATH_MAX)
DEBUG_ANCHOR("ERROR %s(): Home path too long for appdata\n"
, __FUNC__);
#else
# define SLASHTOK '/'
# define APPDATA_SUBDIR ".getdns"
struct passwd *p = getpwuid(getuid());
char *home = NULL;
if (context->appdata_dir) {
(void) strcpy(path, context->appdata_dir);
len = strlen(path);
} else if (!(home = p ? p->pw_dir : getenv("HOME")))
DEBUG_ANCHOR("ERROR %s(): Could not get home directory\n"
, __FUNC__);
else if ((len = strlen(home)) + sizeof(APPDATA_SUBDIR) + 2 >= _GETDNS_PATH_MAX)
DEBUG_ANCHOR("ERROR %s(): Home path too long for appdata\n"
, __FUNC__);
else if (!strcpy(path, home))
; /* strcpy returns path always */
#endif
else {
if (len == 0 || ( path[len - 1] != '/'
&& path[len - 1] != '\\')) {
path[len++] = SLASHTOK;
path[len ] = '\0';
}
(void) strcpy(path + len, APPDATA_SUBDIR);
len += sizeof(APPDATA_SUBDIR) - 1;
}
if (len) {
if (path[len - 1] == '/' || path[len - 1] == '\\') {
path[--len] = '\0';
}
if (0 >
#ifdef USE_WINSOCK
mkdir(path)
#else
mkdir(path, 0755)
#endif
&& errno != EEXIST)
DEBUG_ANCHOR("ERROR %s(): Could not mkdir %s: %s\n"
, __FUNC__, path, strerror(errno));
else {
path[len++] = SLASHTOK;
path[len ] = '\0';
return len;
}
}
return 0;
}
FILE *_getdns_context_get_priv_fp(getdns_context *context, const char *fn)
{
char path[_GETDNS_PATH_MAX];
FILE *f = NULL;
size_t len;
(void) context;
if (!(len = _getdns_get_appdata(context, path)))
DEBUG_ANCHOR("ERROR %s(): Could nog get application data path\n"
, __FUNC__);
else if (len + strlen(fn) >= sizeof(path))
DEBUG_ANCHOR("ERROR %s(): Application data too long\n", __FUNC__);
else if (!strcpy(path + len, fn))
; /* strcpy returns path + len always */
else if (!(f = fopen(path, "r")))
DEBUG_ANCHOR("ERROR %s(): Opening \"%s\": %s\n"
, __FUNC__, path, strerror(errno));
return f;
}
uint8_t *_getdns_context_get_priv_file(getdns_context *context,
const char *fn, uint8_t *buf, size_t buf_len, size_t *file_sz)
{
FILE *f = NULL;
if (!(f = _getdns_context_get_priv_fp(context, fn)))
; /* pass */
else if ((*file_sz = fread(buf, 1, buf_len, f)) < (buf_len - 1) && feof(f)) {
buf[*file_sz] = 0;
(void) fclose(f);
return buf;
}
else if (fseek(f, 0, SEEK_END) < 0)
DEBUG_ANCHOR("ERROR %s(): Determining size of \"%s\": %s\n"
, __FUNC__, fn, strerror(errno));
else if (!(buf = GETDNS_XMALLOC(
context->mf, uint8_t, (buf_len = ftell(f) + 1))))
DEBUG_ANCHOR("ERROR %s(): Allocating %d memory for \"%s\"\n"
, __FUNC__, (int)buf_len, fn);
else {
rewind(f);
if ((*file_sz = fread(buf, 1, buf_len, f)) >= buf_len || !feof(f)) {
GETDNS_FREE(context->mf, buf);
DEBUG_ANCHOR("ERROR %s(): Reading \"%s\": %s\n"
, __FUNC__, fn, strerror(errno));
}
else {
buf[*file_sz] = 0;
(void) fclose(f);
return buf;
}
}
if (f)
(void) fclose(f);
return NULL;
}
int _getdns_context_write_priv_file(getdns_context *context,
const char *fn, getdns_bindata *content)
{
char path[_GETDNS_PATH_MAX], tmpfn[_GETDNS_PATH_MAX];
int fd = -1;
FILE *f = NULL;
size_t len;
if (!(len = _getdns_get_appdata(context, path)))
DEBUG_ANCHOR("ERROR %s(): Could nog get application data path\n"
, __FUNC__);
else if (len + 6 >= sizeof(tmpfn)
|| len + strlen(fn) >= sizeof(path))
DEBUG_ANCHOR("ERROR %s(): Application data too long\n", __FUNC__);
else if (snprintf(tmpfn, sizeof(tmpfn), "%sXXXXXX", path) < 0)
DEBUG_ANCHOR("ERROR %s(): Creating temporary filename template\n"
, __FUNC__);
else if (!strcpy(path + len, fn))
; /* strcpy returns path + len always */
else if ((fd = mkstemp(tmpfn)) < 0)
DEBUG_ANCHOR("ERROR %s(): Creating temporary file: %s\n"
, __FUNC__, strerror(errno));
else if (!(f = fdopen(fd, "w")))
DEBUG_ANCHOR("ERROR %s(): Opening temporary file: %s\n"
, __FUNC__, strerror(errno));
else if (fwrite(content->data, 1, content->size, f) < content->size)
DEBUG_ANCHOR("ERROR %s(): Writing temporary file: %s\n"
, __FUNC__, strerror(errno));
else if (fclose(f) < 0)
DEBUG_ANCHOR("ERROR %s(): Closing temporary file: %s\n"
, __FUNC__, strerror(errno));
else if (rename(tmpfn, path) < 0)
DEBUG_ANCHOR("ERROR %s(): Renaming temporary file: %s\n"
, __FUNC__, strerror(errno));
else {
context->can_write_appdata = PROP_ABLE;
return 1;
}
if (f)
(void) fclose(f);
else if (fd >= 0)
(void) close(fd);
context->can_write_appdata = PROP_UNABLE;
return 0;
}
int _getdns_context_can_write_appdata(getdns_context *context)
{
char test_fn[30], path[_GETDNS_PATH_MAX];
size_t len;
getdns_bindata test_content = { 4, (void *)"TEST" };
if (context->can_write_appdata == PROP_ABLE)
return 1;
else if (context->can_write_appdata == PROP_UNABLE)
return 0;
(void) snprintf( test_fn, sizeof(test_fn)
, "write-test-%d.tmp", arc4random());
if (!_getdns_context_write_priv_file(context, test_fn, &test_content))
return 0;
if (!(len = _getdns_get_appdata(context, path)))
DEBUG_ANCHOR("ERROR %s(): Could nog get application data path\n"
, __FUNC__);
else if (len + strlen(test_fn) >= sizeof(path))
DEBUG_ANCHOR("ERROR %s(): Application data too long\n", __FUNC__);
else if (!strcpy(path + len, test_fn))
; /* strcpy returns path + len always */
else if (unlink(path) < 0)
DEBUG_ANCHOR("ERROR %s(): Unlinking write test file \"%s\": %s\n"
, __FUNC__, path, strerror(errno));
return 1;
}
getdns_return_t
getdns_context_set_trust_anchors_url(
getdns_context *context, const char *url)
{
const char *path;
size_t path_len;
if (!context)
return GETDNS_RETURN_INVALID_PARAMETER;
if (url) {
if (! ((url[0] == 'h' || url[0] == 'H')
&& (url[1] == 't' || url[1] == 'T')
&& (url[2] == 't' || url[2] == 'T')
&& (url[3] == 'p' || url[3] == 'P')
&& url[4] == ':' && url[5] == '/' && url[6] == '/'
&& (path = strchr(url + 7, '/'))))
return GETDNS_RETURN_NOT_IMPLEMENTED;
path_len = strlen(path);
if (! ( path_len >= 5
&& path[path_len - 4] == '.'
&& ( path[path_len - 3] == 'x'
|| path[path_len - 3] == 'X')
&& ( path[path_len - 2] == 'm'
|| path[path_len - 2] == 'M')
&& ( path[path_len - 1] == 'l'
|| path[path_len - 1] == 'L')))
return GETDNS_RETURN_NOT_IMPLEMENTED;
}
if (context->trust_anchors_url)
GETDNS_FREE(context->mf, context->trust_anchors_url);
context->trust_anchors_url = _getdns_strdup(&context->mf, url);
dispatch_updated(context, GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL);
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_trust_anchors_url(
getdns_context *context, const char **url)
{
if (!context || !url)
return GETDNS_RETURN_INVALID_PARAMETER;
*url = context && context->trust_anchors_url
? context->trust_anchors_url
: _getdns_default_trust_anchors_url;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_set_trust_anchors_verify_CA(
getdns_context *context, const char *verify_CA)
{
if (!context)
return GETDNS_RETURN_INVALID_PARAMETER;
if (context->trust_anchors_verify_CA)
GETDNS_FREE(context->mf, context->trust_anchors_verify_CA);
context->trust_anchors_verify_CA =
_getdns_strdup(&context->mf, verify_CA);
dispatch_updated( context
, GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_CA);
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_trust_anchors_verify_CA(
getdns_context *context, const char **verify_CA)
{
if (!verify_CA)
return GETDNS_RETURN_INVALID_PARAMETER;
*verify_CA = context && context->trust_anchors_verify_CA
? context->trust_anchors_verify_CA
: _getdns_default_trust_anchors_verify_CA;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_set_trust_anchors_verify_email(
getdns_context *context, const char *verify_email)
{
if (!context)
return GETDNS_RETURN_INVALID_PARAMETER;
if (context->trust_anchors_verify_email)
GETDNS_FREE(context->mf, context->trust_anchors_verify_email);
context->trust_anchors_verify_email =
_getdns_strdup(&context->mf, verify_email);
dispatch_updated( context
, GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_EMAIL);
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_trust_anchors_verify_email(
getdns_context *context, const char **verify_email)
{
if (!verify_email)
return GETDNS_RETURN_INVALID_PARAMETER;
*verify_email = context && context->trust_anchors_verify_email
? context->trust_anchors_verify_email
: _getdns_default_trust_anchors_verify_email;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_set_appdata_dir(
getdns_context *context, const char *appdata_dir)
{
if (!context)
return GETDNS_RETURN_INVALID_PARAMETER;
if (context->appdata_dir)
GETDNS_FREE(context->mf, context->appdata_dir);
context->appdata_dir = _getdns_strdup(&context->mf, appdata_dir);
dispatch_updated(context, GETDNS_CONTEXT_CODE_APPDATA_DIR);
return GETDNS_RETURN_GOOD;
}
/* context.c */ /* context.c */

View File

@ -48,6 +48,8 @@
#ifdef HAVE_MDNS_SUPPORT #ifdef HAVE_MDNS_SUPPORT
#include "util/lruhash.h" #include "util/lruhash.h"
#endif #endif
#include "rr-iter.h"
#include "anchor.h"
struct getdns_dns_req; struct getdns_dns_req;
struct ub_ctx; struct ub_ctx;
@ -92,6 +94,16 @@ typedef enum getdns_conn_state {
GETDNS_CONN_BACKOFF GETDNS_CONN_BACKOFF
} getdns_conn_state_t; } getdns_conn_state_t;
typedef enum getdns_tasrc {
GETDNS_TASRC_NONE,
GETDNS_TASRC_ZONE,
GETDNS_TASRC_APP,
GETDNS_TASRC_FETCHING,
GETDNS_TASRC_XML,
GETDNS_TASRC_XML_UPDATE,
GETDNS_TASRC_FAILED
} getdns_tasrc;
typedef enum getdns_tsig_algo { typedef enum getdns_tsig_algo {
GETDNS_NO_TSIG = 0, /* Do not use tsig */ GETDNS_NO_TSIG = 0, /* Do not use tsig */
GETDNS_HMAC_MD5 = 1, /* 128 bits */ GETDNS_HMAC_MD5 = 1, /* 128 bits */
@ -103,6 +115,7 @@ typedef enum getdns_tsig_algo {
GETDNS_HMAC_SHA512 = 7 GETDNS_HMAC_SHA512 = 7
} getdns_tsig_algo; } getdns_tsig_algo;
typedef struct getdns_tsig_info { typedef struct getdns_tsig_info {
getdns_tsig_algo alg; getdns_tsig_algo alg;
const char *name; const char *name;
@ -170,6 +183,7 @@ typedef struct getdns_upstream {
size_t conn_shutdowns; size_t conn_shutdowns;
size_t conn_setup_failed; size_t conn_setup_failed;
time_t conn_retry_time; time_t conn_retry_time;
uint16_t conn_backoff_interval;
size_t conn_backoffs; size_t conn_backoffs;
size_t total_responses; size_t total_responses;
size_t total_timeouts; size_t total_timeouts;
@ -255,6 +269,44 @@ typedef struct getdns_upstreams {
getdns_upstream upstreams[]; getdns_upstream upstreams[];
} getdns_upstreams; } getdns_upstreams;
typedef enum tas_state {
TAS_LOOKUP_ADDRESSES = 0,
TAS_WRITE_GET_XML,
TAS_READ_XML_HDR,
TAS_READ_XML_DOC,
TAS_WRITE_GET_PS7,
TAS_READ_PS7_HDR,
TAS_READ_PS7_DOC,
TAS_DONE,
TAS_RETRY,
TAS_RETRY_GET_PS7,
TAS_RETRY_PS7_HDR,
TAS_RETRY_PS7_DOC,
TAS_RETRY_DONE
} tas_state;
typedef enum _getdns_property {
PROP_INHERIT = 0,
PROP_UNKNOWN = 1,
PROP_UNABLE = 2,
PROP_ABLE = 3
} _getdns_property;
typedef struct tas_connection {
getdns_eventloop *loop;
getdns_network_req *req;
_getdns_rrset_spc rrset_spc;
_getdns_rrset *rrset;
_getdns_rrtype_iter rr_spc;
_getdns_rrtype_iter *rr;
int fd;
getdns_eventloop_event event;
tas_state state;
getdns_tcp_state tcp;
char *http;
getdns_bindata xml;
} tas_connection;
struct getdns_context { struct getdns_context {
/* Context values */ /* Context values */
getdns_resolution_t resolution_type; getdns_resolution_t resolution_type;
@ -276,8 +328,24 @@ struct getdns_context {
const uint8_t *suffixes; const uint8_t *suffixes;
/* Length of all suffixes in the suffix buffer */ /* Length of all suffixes in the suffix buffer */
size_t suffixes_len; size_t suffixes_len;
uint8_t *trust_anchors; uint8_t *trust_anchors;
size_t trust_anchors_len; size_t trust_anchors_len;
getdns_tasrc trust_anchors_source;
tas_connection a;
tas_connection aaaa;
uint8_t tas_hdr_spc[512];
char *trust_anchors_url;
char *trust_anchors_verify_CA;
char *trust_anchors_verify_email;
_getdns_ksks root_ksk;
char *appdata_dir;
_getdns_property can_write_appdata;
getdns_upstreams *upstreams; getdns_upstreams *upstreams;
uint16_t limit_outstanding_queries; uint16_t limit_outstanding_queries;
uint32_t dnssec_allowed_skew; uint32_t dnssec_allowed_skew;
@ -372,6 +440,18 @@ struct getdns_context {
unsigned return_call_reporting : 1; unsigned return_call_reporting : 1;
uint16_t specify_class; uint16_t specify_class;
/*
* Context for doing system queries.
* For example to resolve data.iana.org or to resolver the addresses
* of upstreams without specified addresses.
*/
getdns_context *sys_ctxt;
/* List of dnsreqs that want to be notified when we have fetched a
* trust anchor from data.iana.org.
*/
getdns_dns_req *ta_notify;
/* /*
* state data used to detect changes to the system config files * state data used to detect changes to the system config files
*/ */
@ -415,11 +495,9 @@ void _getdns_context_log(getdns_context *context, uint64_t system,
* Sets up the unbound contexts with stub or recursive behavior * Sets up the unbound contexts with stub or recursive behavior
* if needed. * if needed.
* @param context previously initialized getdns_context * @param context previously initialized getdns_context
* @param usenamespaces if 0 then only use the DNS, else use context namespace list
* @return GETDNS_RETURN_GOOD on success * @return GETDNS_RETURN_GOOD on success
*/ */
getdns_return_t _getdns_context_prepare_for_resolution(struct getdns_context *context, getdns_return_t _getdns_context_prepare_for_resolution(getdns_context *context);
int usenamespaces);
/* Register a getdns_dns_req with context. /* Register a getdns_dns_req with context.
* - Without pluggable unbound event API, * - Without pluggable unbound event API,
@ -470,4 +548,13 @@ void _getdns_upstreams_dereference(getdns_upstreams *upstreams);
void _getdns_upstream_shutdown(getdns_upstream *upstream); void _getdns_upstream_shutdown(getdns_upstream *upstream);
FILE *_getdns_context_get_priv_fp(getdns_context *context, const char *fn);
uint8_t *_getdns_context_get_priv_file(getdns_context *context,
const char *fn, uint8_t *buf, size_t buf_len, size_t *file_sz);
int _getdns_context_write_priv_file(getdns_context *context,
const char *fn, getdns_bindata *content);
int _getdns_context_can_write_appdata(getdns_context *context);
#endif /* _GETDNS_CONTEXT_H_ */ #endif /* _GETDNS_CONTEXT_H_ */

View File

@ -32,10 +32,10 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "config.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <locale.h> #include <locale.h>
#include "config.h"
#ifndef USE_WINSOCK #ifndef USE_WINSOCK
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
@ -54,6 +54,7 @@
#include "dict.h" #include "dict.h"
#include "list.h" #include "list.h"
#include "jsmn/jsmn.h" #include "jsmn/jsmn.h"
#include "yaml/convert_yaml_to_json.h"
#include "convert.h" #include "convert.h"
#include "debug.h" #include "debug.h"
@ -1802,3 +1803,101 @@ getdns_str2int(const char *str, uint32_t *value)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
#ifdef USE_YAML_CONFIG
getdns_return_t
getdns_yaml2dict(const char *str, getdns_dict **dict)
{
char *jsonstr;
if (!str || !dict)
return GETDNS_RETURN_INVALID_PARAMETER;
jsonstr = yaml_string_to_json_string(str);
if (jsonstr) {
getdns_return_t res = getdns_str2dict(jsonstr, dict);
free(jsonstr);
return res;
} else {
return GETDNS_RETURN_GENERIC_ERROR;
}
}
#endif /* USE_YAML_CONFIG */
/* WT: I am not certain about the value of yaml2list...
* I don't see how yaml2bindata and yaml2int would be different from
* the str2bindata and str2int ones.
*/
#if 0
getdns_return_t
getdns_yaml2list(const char *str, getdns_list **list)
{
#ifdef USE_YAML_CONFIG
char *jsonstr;
if (!str || !list)
return GETDNS_RETURN_INVALID_PARAMETER;
jsonstr = yaml_string_to_json_string(str);
if (jsonstr) {
getdns_return_t res = getdns_str2list(jsonstr, list);
free(jsonstr);
return res;
} else {
return GETDNS_RETURN_GENERIC_ERROR;
}
#else /* USE_YAML_CONFIG */
(void) str;
(void) list;
return GETDNS_RETURN_NOT_IMPLEMENTED;
#endif /* USE_YAML_CONFIG */
}
getdns_return_t
getdns_yaml2bindata(const char *str, getdns_bindata **bindata)
{
#ifdef USE_YAML_CONFIG
char *jsonstr;
if (!str || !bindata)
return GETDNS_RETURN_INVALID_PARAMETER;
jsonstr = yaml_string_to_json_string(str);
if (jsonstr) {
getdns_return_t res = getdns_str2bindata(jsonstr, bindata);
free(jsonstr);
return res;
} else {
return GETDNS_RETURN_GENERIC_ERROR;
}
#else /* USE_YAML_CONFIG */
(void) str;
(void) bindata;
return GETDNS_RETURN_NOT_IMPLEMENTED;
#endif /* USE_YAML_CONFIG */
}
getdns_return_t
getdns_yaml2int(const char *str, uint32_t *value)
{
#ifdef USE_YAML_CONFIG
char *jsonstr;
if (!str || !value)
return GETDNS_RETURN_INVALID_PARAMETER;
jsonstr = yaml_string_to_json_string(str);
if (jsonstr) {
getdns_return_t res = getdns_str2int(jsonstr, value);
free(jsonstr);
return res;
} else {
return GETDNS_RETURN_GENERIC_ERROR;
}
#else /* USE_YAML_CONFIG */
(void) str;
(void) value;
return GETDNS_RETURN_NOT_IMPLEMENTED;
#endif /* USE_YAML_CONFIG */
}
#endif

View File

@ -47,45 +47,58 @@
#ifdef GETDNS_ON_WINDOWS #ifdef GETDNS_ON_WINDOWS
#define DEBUG_ON(...) do { \ #define DEBUG_ON(...) do { \
struct timeval tv; \ struct timeval tv_dEbUgSyM; \
struct tm tm; \ struct tm tm_dEbUgSyM; \
char buf[10]; \ char buf_dEbUgSyM[10]; \
time_t tsec; \ time_t tsec_dEbUgSyM; \
\ \
gettimeofday(&tv, NULL); \ gettimeofday(&tv_dEbUgSyM, NULL); \
tsec = (time_t) tv.tv_sec; \ tsec_dEbUgSyM = (time_t) tv_dEbUgSyM.tv_sec; \
gmtime_s(&tm, (const time_t *) &tsec); \ gmtime_s(&tm_dEbUgSyM, (const time_t *) &tsec_dEbUgSyM); \
strftime(buf, 10, "%H:%M:%S", &tm); \ strftime(buf_dEbUgSyM, 10, "%H:%M:%S", &tm_dEbUgSyM); \
fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \ fprintf(stderr, "[%s.%.6d] ", buf_dEbUgSyM, (int)tv_dEbUgSyM.tv_usec); \
fprintf(stderr, __VA_ARGS__); \
} while (0)
#define DEBUG_NL(...) do { \
struct timeval tv_dEbUgSyM; \
struct tm tm_dEbUgSyM; \
char buf_dEbUgSyM[10]; \
time_t tsec_dEbUgSyM; \
\
gettimeofday(&tv_dEbUgSyM, NULL); \
tsec_dEbUgSyM = (time_t) tv_dEbUgSyM.tv_sec; \
gmtime_s(&tm_dEbUgSyM, (const time_t *) &tsec_dEbUgSyM); \
strftime(buf_dEbUgSyM, 10, "%H:%M:%S", &tm_dEbUgSyM); \
fprintf(stderr, "[%s.%.6d] ", buf_dEbUgSyM, (int)tv_dEbUgSyM.tv_usec); \
fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, __VA_ARGS__); \
} while (0) } while (0)
#else #else
#define DEBUG_ON(...) do { \ #define DEBUG_ON(...) do { \
struct timeval tv; \ struct timeval tv_dEbUgSyM; \
struct tm tm; \ struct tm tm_dEbUgSyM; \
char buf[10]; \ char buf_dEbUgSyM[10]; \
\ \
gettimeofday(&tv, NULL); \ gettimeofday(&tv_dEbUgSyM, NULL); \
gmtime_r(&tv.tv_sec, &tm); \ gmtime_r(&tv_dEbUgSyM.tv_sec, &tm_dEbUgSyM); \
strftime(buf, 10, "%H:%M:%S", &tm); \ strftime(buf_dEbUgSyM, 10, "%H:%M:%S", &tm_dEbUgSyM); \
fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \ fprintf(stderr, "[%s.%.6d] ", buf_dEbUgSyM, (int)tv_dEbUgSyM.tv_usec); \
fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, __VA_ARGS__); \
} while (0) } while (0)
#endif
#define DEBUG_NL(...) do { \ #define DEBUG_NL(...) do { \
struct timeval tv; \ struct timeval tv_dEbUgSyM; \
struct tm tm; \ struct tm tm_dEbUgSyM; \
char buf[10]; \ char buf_dEbUgSyM[10]; \
\ \
gettimeofday(&tv, NULL); \ gettimeofday(&tv_dEbUgSyM, NULL); \
gmtime_r(&tv.tv_sec, &tm); \ gmtime_r(&tv_dEbUgSyM.tv_sec, &tm_dEbUgSyM); \
strftime(buf, 10, "%H:%M:%S", &tm); \ strftime(buf_dEbUgSyM, 10, "%H:%M:%S", &tm_dEbUgSyM); \
fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \ fprintf(stderr, "[%s.%.6d] ", buf_dEbUgSyM, (int)tv_dEbUgSyM.tv_usec); \
fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \ fprintf(stderr, "\n"); \
} while (0) } while (0)
#endif
#define DEBUG_OFF(...) do {} while (0) #define DEBUG_OFF(...) do {} while (0)
@ -162,14 +175,25 @@ static inline void debug_req(const char *msg, getdns_network_req *netreq)
#define DEBUG_MDNS(...) DEBUG_OFF(__VA_ARGS__) #define DEBUG_MDNS(...) DEBUG_OFF(__VA_ARGS__)
#endif #endif
#if defined(ANCHOR_DEBUG) && ANCHOR_DEBUG
#include <time.h>
#define DEBUG_ANCHOR(...) DEBUG_ON(__VA_ARGS__)
#else
#define DEBUG_ANCHOR(...) DEBUG_OFF(__VA_ARGS__)
#endif
#if (defined(REQ_DEBUG) && REQ_DEBUG) || \ #if (defined(REQ_DEBUG) && REQ_DEBUG) || \
(defined(SCHED_DEBUG) && SCHED_DEBUG) || \ (defined(SCHED_DEBUG) && SCHED_DEBUG) || \
(defined(STUB_DEBUG) && STUB_DEBUG) || \ (defined(STUB_DEBUG) && STUB_DEBUG) || \
(defined(DAEMON_DEBUG) && DAEMON_DEBUG) || \ (defined(DAEMON_DEBUG) && DAEMON_DEBUG) || \
(defined(SEC_DEBUG) && SEC_DEBUG) || \ (defined(SEC_DEBUG) && SEC_DEBUG) || \
(defined(SERVER_DEBUG) && SERVER_DEBUG) || \ (defined(SERVER_DEBUG) && SERVER_DEBUG) || \
(defined(MDNS_DEBUG) && MDNS_DEBUG) (defined(MDNS_DEBUG) && MDNS_DEBUG) || \
(defined(ANCHOR_DEBUG) && ANCHOR_DEBUG)
#define DEBUGGING 1 #define DEBUGGING 1
static inline int
_getdns_ERR_print_errors_cb_f(const char *str, size_t len, void *u)
{ DEBUG_ON("%.*s (u: %p)\n", (int)len, str, u); return 1; }
#endif #endif
#endif #endif

View File

@ -34,8 +34,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <ctype.h>
#include "config.h" #include "config.h"
#include <ctype.h>
#ifndef USE_WINSOCK #ifndef USE_WINSOCK
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>

View File

@ -209,6 +209,7 @@
#include "dict.h" #include "dict.h"
#include "list.h" #include "list.h"
#include "util/val_secalgo.h" #include "util/val_secalgo.h"
#include "anchor.h"
#define SIGNATURE_VERIFIED 0x10000 #define SIGNATURE_VERIFIED 0x10000
#define NSEC3_ITERATION_COUNT_HIGH 0x20000 #define NSEC3_ITERATION_COUNT_HIGH 0x20000
@ -601,7 +602,7 @@ static chain_head *add_rrset2val_chain(struct mem_funcs *mf,
dname_len = *labels - last_label[-1] + 1; dname_len = *labels - last_label[-1] + 1;
head_sz = (sizeof(chain_head) + dname_len + 7) / 8 * 8; head_sz = (sizeof(chain_head) + dname_len + 7) / 8 * 8;
node_count = last_label - labels - max_labels; node_count = last_label - labels - max_labels;
DEBUG_SEC( PRIsz" labels in common. "PRIsz" labels to allocate\n" DEBUG_SEC( "%"PRIsz" labels in common. %"PRIsz" labels to allocate\n"
, max_labels, node_count); , max_labels, node_count);
if (! (region = GETDNS_XMALLOC(*mf, uint8_t, head_sz + if (! (region = GETDNS_XMALLOC(*mf, uint8_t, head_sz +
@ -801,11 +802,14 @@ static void add_pkt2val_chain(struct mem_funcs *mf,
if (is_synthesized_cname(rrset)) if (is_synthesized_cname(rrset))
continue; continue;
if (!(rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset))
&& _getdns_rr_iter_section(&i->rr_i) != SECTION_ANSWER)
continue; /* No sigs in authority section is okayish */
if (!(head = add_rrset2val_chain(mf, chain_p, rrset, netreq))) if (!(head = add_rrset2val_chain(mf, chain_p, rrset, netreq)))
continue; continue;
for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset), n_rrsigs = 0 for ( n_rrsigs = 0; rrsig
; rrsig
; rrsig = _getdns_rrsig_iter_next(rrsig), n_rrsigs++) { ; rrsig = _getdns_rrsig_iter_next(rrsig), n_rrsigs++) {
/* Signature, so lookup DS/DNSKEY at signer's name */ /* Signature, so lookup DS/DNSKEY at signer's name */
@ -933,6 +937,17 @@ static void val_chain_sched_soa(chain_head *head, const uint8_t *dname)
val_chain_sched_soa_node(node); val_chain_sched_soa_node(node);
} }
static chain_head *_dnskey_query(const chain_node *node)
{
chain_head *head;
for (head = node->chains; head; head = head->next)
if (head->rrset.rr_type == GETDNS_RRTYPE_DNSKEY &&
head->parent == node)
return head;
return NULL;
}
static void val_chain_node_cb(getdns_dns_req *dnsreq); static void val_chain_node_cb(getdns_dns_req *dnsreq);
static void val_chain_sched_node(chain_node *node) static void val_chain_sched_node(chain_node *node)
{ {
@ -950,13 +965,27 @@ static void val_chain_sched_node(chain_node *node)
DEBUG_SEC("schedule DS & DNSKEY lookup for %s\n", name); DEBUG_SEC("schedule DS & DNSKEY lookup for %s\n", name);
node->lock++; node->lock++;
if (! node->dnskey_req /* not scheduled */ && if (! node->dnskey_req) {
_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DNSKEY, chain_head *head;
CD_extension(node->chains->netreq->owner),
node, &node->dnskey_req, NULL, val_chain_node_cb))
node->dnskey_req = NULL; /* Reuse the DNSKEY query if this node is scheduled in the
* context of validating a DNSKEY query, because libunbound
* does not callback from a callback for the same query.
*/
if ((head = _dnskey_query(node))) {
DEBUG_SEC("Found DNSKEY head: %p\n", (void *)head);
node->dnskey_req = head->netreq;
node->dnskey.pkt = head->netreq->response;
node->dnskey.pkt_len = head->netreq->response_len;
} else if (_getdns_general_loop(
context, loop, name, GETDNS_RRTYPE_DNSKEY,
CD_extension(node->chains->netreq->owner),
node, &node->dnskey_req, NULL, val_chain_node_cb))
node->dnskey_req = NULL;
}
if (! node->ds_req && node->parent /* not root */ && if (! node->ds_req && node->parent /* not root */ &&
_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS, _getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS,
CD_extension(node->chains->netreq->owner), CD_extension(node->chains->netreq->owner),
@ -1423,7 +1452,7 @@ static int _getdns_verify_rrsig(struct mem_funcs *mf,
/* More space needed for val_rrset */ /* More space needed for val_rrset */
val_rrset = GETDNS_XMALLOC(*mf, _getdns_rr_iter, n_rrs); val_rrset = GETDNS_XMALLOC(*mf, _getdns_rr_iter, n_rrs);
} }
DEBUG_SEC( "sizes: "PRIsz" rrs, "PRIsz" bytes for validation buffer\n" DEBUG_SEC( "sizes: %"PRIsz" rrs, %"PRIsz" bytes for validation buffer\n"
, n_rrs, valbuf_sz); , n_rrs, valbuf_sz);
qsort(val_rrset, n_rrs, sizeof(_getdns_rr_iter), _rr_iter_rdata_cmp); qsort(val_rrset, n_rrs, sizeof(_getdns_rr_iter), _rr_iter_rdata_cmp);
@ -1480,7 +1509,7 @@ static int _getdns_verify_rrsig(struct mem_funcs *mf,
gldns_buffer_write_u16_at(&valbuf, pos, gldns_buffer_write_u16_at(&valbuf, pos,
(uint16_t)(gldns_buffer_position(&valbuf) - pos - 2)); (uint16_t)(gldns_buffer_position(&valbuf) - pos - 2));
} }
DEBUG_SEC( "written to valbuf: "PRIsz" bytes\n" DEBUG_SEC( "written to valbuf: %"PRIsz" bytes\n"
, gldns_buffer_position(&valbuf)); , gldns_buffer_position(&valbuf));
assert(gldns_buffer_position(&valbuf) <= valbuf_sz); assert(gldns_buffer_position(&valbuf) <= valbuf_sz);
@ -1902,7 +1931,7 @@ static int ds_authenticates_keys(struct mem_funcs *mf,
if (digest_buf != digest_buf_spc) if (digest_buf != digest_buf_spc)
GETDNS_FREE(*mf, digest_buf); GETDNS_FREE(*mf, digest_buf);
DEBUG_SEC("HASH length mismatch "PRIsz" != "PRIsz"\n", DEBUG_SEC("HASH length mismatch %"PRIsz" != %"PRIsz"\n",
digest_len, ds->rr_i.nxt - ds->rr_i.rr_type-14); digest_len, ds->rr_i.nxt - ds->rr_i.rr_type-14);
continue; continue;
} }
@ -1925,7 +1954,7 @@ static int ds_authenticates_keys(struct mem_funcs *mf,
max_supported_result = SIGNATURE_VERIFIED | keytag; max_supported_result = SIGNATURE_VERIFIED | keytag;
} }
} }
DEBUG_SEC("valid_dsses: "PRIsz", supported_dsses: "PRIsz"\n", DEBUG_SEC("valid_dsses: %"PRIsz", supported_dsses: %"PRIsz"\n",
valid_dsses, supported_dsses); valid_dsses, supported_dsses);
if (valid_dsses && !supported_dsses) if (valid_dsses && !supported_dsses)
return NO_SUPPORTED_ALGORITHMS; return NO_SUPPORTED_ALGORITHMS;
@ -2522,6 +2551,11 @@ static int chain_node_get_trusted_keys(
node->dnskey_signer = keytag; node->dnskey_signer = keytag;
return GETDNS_DNSSEC_SECURE; return GETDNS_DNSSEC_SECURE;
} }
/* ta is the DNSKEY for this name? */
if (_dname_equal(ta->name, node->dnskey.name)) {
*keys = ta;
return GETDNS_DNSSEC_SECURE;
}
/* ta is parent's ZSK */ /* ta is parent's ZSK */
if ((keytag = key_proves_nonexistance( if ((keytag = key_proves_nonexistance(
mf, now, skew, ta, &node->ds, NULL))) { mf, now, skew, ta, &node->ds, NULL))) {
@ -2544,8 +2578,13 @@ static int chain_node_get_trusted_keys(
} else } else
return GETDNS_DNSSEC_BOGUS; return GETDNS_DNSSEC_BOGUS;
if (GETDNS_DNSSEC_SECURE != (s = chain_node_get_trusted_keys( s = chain_node_get_trusted_keys(mf, now, skew, node->parent, ta, keys);
mf, now, skew, node->parent, ta, keys))) /* Set dnssec status on root DNSKEY request (for TA management) */
if (!node->parent && node->dnskey_req &&
node->dnskey.name && *node->dnskey.name == 0)
node->dnskey_req->dnssec_status = s;
if (s != GETDNS_DNSSEC_SECURE)
return s; return s;
/* keys is an authenticated dnskey rrset always now (i.e. ZSK) */ /* keys is an authenticated dnskey rrset always now (i.e. ZSK) */
@ -2750,6 +2789,33 @@ static void chain_set_netreq_dnssec_status(chain_head *chain, _getdns_rrset_iter
} }
} }
} }
static void chain_clear_netreq_dnssec_status(chain_head *chain)
{
chain_head *head;
size_t node_count;
chain_node *node;
/* The netreq status is the worst for any head */
for (head = chain; head; head = head->next) {
if (!head->netreq)
continue;
head->netreq->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
for ( node_count = head->node_count, node = head->parent
; node && node_count ; node_count--, node = node->parent ) {
node->ds_signer = -1;
node->dnskey_signer = -1;
if ( ! node->parent && node->dnskey_req
&& node->dnskey.name && !*node->dnskey.name) {
node->dnskey_req->dnssec_status =
GETDNS_DNSSEC_INDETERMINATE;
}
}
}
}
#endif #endif
/* The DNSSEC status of all heads for a chain structure is evaluated by /* The DNSSEC status of all heads for a chain structure is evaluated by
@ -2905,6 +2971,26 @@ static void append_rrset2val_chain_list(
_getdns_list_append_this_dict(val_chain_list, rr_dict)) _getdns_list_append_this_dict(val_chain_list, rr_dict))
getdns_dict_destroy(rr_dict); getdns_dict_destroy(rr_dict);
/* Append the other RRSIGs, which were not used for validation too,
* because other validators might not have the same algorithm support.
*/
for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset)
; rrsig
; rrsig = _getdns_rrsig_iter_next(rrsig)) {
if (rrsig->rr_i.nxt < rrsig->rr_i.rr_type + 28)
continue;
if (gldns_read_uint16(rrsig->rr_i.rr_type + 26)
== (signer & 0xFFFF))
continue;
orig_ttl = gldns_read_uint32(rrsig->rr_i.rr_type + 14);
if ((rr_dict = _getdns_rr_iter2rr_dict_canonical(
&val_chain_list->mf, &rrsig->rr_i, &orig_ttl)) &&
_getdns_list_append_this_dict(val_chain_list, rr_dict))
getdns_dict_destroy(rr_dict);
}
if (val_rrset != val_rrset_spc) if (val_rrset != val_rrset_spc)
GETDNS_FREE(val_chain_list->mf, val_rrset); GETDNS_FREE(val_chain_list->mf, val_rrset);
} }
@ -2999,6 +3085,22 @@ static void append_empty_ds2val_chain_list(
if (_getdns_list_append_this_dict(val_chain_list, rr_dict)) if (_getdns_list_append_this_dict(val_chain_list, rr_dict))
getdns_dict_destroy(rr_dict); getdns_dict_destroy(rr_dict);
} }
static inline chain_node *_to_the_root(chain_node *node)
{
while (node->parent) node = node->parent;
return node;
}
int _getdns_bogus(getdns_dns_req *dnsreq)
{
getdns_network_req **netreq_p, *netreq;
for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) {
if (netreq->dnssec_status == GETDNS_DNSSEC_BOGUS)
return 1;
}
return 0;
}
static void _cleanup_chain(chain_head *chain, static void _cleanup_chain(chain_head *chain,
getdns_list *val_chain_list, int full) getdns_list *val_chain_list, int full)
@ -3078,30 +3180,40 @@ static void check_chain_complete(chain_head *chain)
_getdns_rrset_iter tas_iter; _getdns_rrset_iter tas_iter;
if ((o = count_outstanding_requests(chain)) > 0) { if ((o = count_outstanding_requests(chain)) > 0) {
DEBUG_SEC(PRIsz" outstanding requests\n", o); DEBUG_SEC("%"PRIsz" outstanding requests\n", o);
return; return;
} }
DEBUG_SEC("Chain done!\n"); DEBUG_SEC("Chain done!\n");
dnsreq = chain->netreq->owner; dnsreq = chain->netreq->owner;
context = dnsreq->context; context = dnsreq->context;
if (dnsreq->waiting_for_ta) {
getdns_dns_req **d;
for (d = &context->ta_notify; *d; d = &(*d)->ta_notify) {
if (*d == dnsreq) {
*d = dnsreq->ta_notify;
dnsreq->ta_notify = NULL;
break;
}
}
} else {
if (context->trust_anchors_source == GETDNS_TASRC_FETCHING) {
dnsreq->waiting_for_ta = 1;
dnsreq->ta_notify = context->ta_notify;
context->ta_notify = dnsreq;
return;
}
}
#ifdef STUB_NATIVE_DNSSEC #ifdef STUB_NATIVE_DNSSEC
/* Perform validation only on GETDNS_RESOLUTION_STUB (unbound_id == -1) if (context->trust_anchors)
* Or when asked for the validation chain (to identify the RRSIGs that
* signed the RRSETs, so that only those will be included in the
* validation chain)
* In any case we must have a trust anchor.
*/
if (( chain->netreq->unbound_id == -1
|| dnsreq->dnssec_return_validation_chain)
&& context->trust_anchors)
chain_set_netreq_dnssec_status(chain,_getdns_rrset_iter_init(&tas_iter, chain_set_netreq_dnssec_status(chain,_getdns_rrset_iter_init(&tas_iter,
context->trust_anchors, context->trust_anchors_len, context->trust_anchors, context->trust_anchors_len,
SECTION_ANSWER)); SECTION_ANSWER));
#else #else
if (dnsreq->dnssec_return_validation_chain if (context->trust_anchors)
&& context->trust_anchors)
(void) chain_validate_dnssec(priv_getdns_context_mf(context), (void) chain_validate_dnssec(priv_getdns_context_mf(context),
time(NULL), context->dnssec_allowed_skew, time(NULL), context->dnssec_allowed_skew,
@ -3110,10 +3222,52 @@ static void check_chain_complete(chain_head *chain)
, context->trust_anchors_len , context->trust_anchors_len
, SECTION_ANSWER)); , SECTION_ANSWER));
#endif #endif
if (context->trust_anchors_source == GETDNS_TASRC_XML) {
if ((head = chain) && (node = _to_the_root(head->parent)) &&
node->dnskey.name && *node->dnskey.name == 0)
_getdns_context_update_root_ksk(context,&node->dnskey);
} else if (_getdns_bogus(dnsreq)) {
DEBUG_ANCHOR("Request was bogus!\n");
if ((head = chain) && (node = _to_the_root(head->parent))
&& node->dnskey.name && *node->dnskey.name == 0
&& node->dnskey_req->dnssec_status == GETDNS_DNSSEC_BOGUS){
DEBUG_ANCHOR("root DNSKEY set was bogus!\n");
if (!dnsreq->waiting_for_ta) {
uint64_t now = 0;
dnsreq->waiting_for_ta = 1;
_getdns_context_equip_with_anchor(
context, &now);
if (context->trust_anchors_source
== GETDNS_TASRC_XML) {
chain_clear_netreq_dnssec_status(chain);
check_chain_complete(chain);
return;
}
_getdns_start_fetching_ta(
context, dnsreq->loop);
if (dnsreq->waiting_for_ta &&
context->trust_anchors_source
== GETDNS_TASRC_FETCHING) {
chain_clear_netreq_dnssec_status(chain);
dnsreq->ta_notify = context->ta_notify;
context->ta_notify = dnsreq;
return;
}
}
}
}
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
if ( dnsreq->dnssec_roadblock_avoidance if ( dnsreq->dnssec_roadblock_avoidance
&& !dnsreq->avoid_dnssec_roadblocks && !dnsreq->avoid_dnssec_roadblocks
&& dnsreq->netreqs[0]->dnssec_status == GETDNS_DNSSEC_BOGUS) { && _getdns_bogus(dnsreq)) {
getdns_network_req **netreq_p, *netreq; getdns_network_req **netreq_p, *netreq;
uint64_t now_ms = 0; uint64_t now_ms = 0;
@ -3167,6 +3321,7 @@ static void check_chain_complete(chain_head *chain)
return; return;
} }
#endif #endif
dnsreq->waiting_for_ta = 0;
val_chain_list = dnsreq->dnssec_return_validation_chain val_chain_list = dnsreq->dnssec_return_validation_chain
? getdns_list_create_with_context(context) : NULL; ? getdns_list_create_with_context(context) : NULL;
@ -3185,6 +3340,45 @@ static void check_chain_complete(chain_head *chain)
_getdns_call_user_callback(dnsreq, response_dict); _getdns_call_user_callback(dnsreq, response_dict);
} }
void _getdns_ta_notify_dnsreqs(getdns_context *context)
{
getdns_dns_req **dnsreq_p, *dnsreq = NULL;
uint64_t now_ms = 0;
assert(context);
if (context->trust_anchors_source == GETDNS_TASRC_NONE ||
context->trust_anchors_source == GETDNS_TASRC_FETCHING)
return;
dnsreq_p = &context->ta_notify;
while ((dnsreq = *dnsreq_p)) {
assert(dnsreq->waiting_for_ta);
if (dnsreq->chain)
check_chain_complete(dnsreq->chain);
else {
getdns_network_req *netreq, **netreq_p;
int r = GETDNS_RETURN_GOOD;
(void) _getdns_context_prepare_for_resolution(context);
*dnsreq_p = dnsreq->ta_notify;
for ( netreq_p = dnsreq->netreqs
; !r && (netreq = *netreq_p)
; netreq_p++ ) {
if (!(r = _getdns_submit_netreq(netreq, &now_ms)))
continue;
if (r == DNS_REQ_FINISHED)
break;
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
}
}
assert(*dnsreq_p != dnsreq);
}
}
void _getdns_validation_chain_timeout(getdns_dns_req *dnsreq) void _getdns_validation_chain_timeout(getdns_dns_req *dnsreq)
{ {
chain_head *head = dnsreq->chain, *next; chain_head *head = dnsreq->chain, *next;
@ -3224,7 +3418,7 @@ void _getdns_validation_chain_timeout(getdns_dns_req *dnsreq)
void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq) void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq)
{ {
chain_head *head = dnsreq->chain, *next; chain_head *head = dnsreq->chain, *next, *dnskey_head;
chain_node *node; chain_node *node;
size_t node_count; size_t node_count;
@ -3236,7 +3430,10 @@ void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq)
; node_count ; node_count
; node_count--, node = node->parent ) { ; node_count--, node = node->parent ) {
if (node->dnskey_req) if (node->dnskey_req &&
!( (dnskey_head = _dnskey_query(node))
&& dnskey_head->netreq == node->dnskey_req))
_getdns_context_cancel_request( _getdns_context_cancel_request(
node->dnskey_req->owner); node->dnskey_req->owner);
@ -3267,6 +3464,7 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
if (dnsreq->avoid_dnssec_roadblocks && chain->lock == 0) if (dnsreq->avoid_dnssec_roadblocks && chain->lock == 0)
; /* pass */ ; /* pass */
else for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) { else for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) {
if (! netreq->response if (! netreq->response
|| netreq->response_len < GLDNS_HEADER_SIZE || netreq->response_len < GLDNS_HEADER_SIZE
@ -3277,7 +3475,10 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq)
netreq->dnssec_status = GETDNS_DNSSEC_INSECURE; netreq->dnssec_status = GETDNS_DNSSEC_INSECURE;
continue; continue;
}
} else if (netreq->unbound_id != -1)
netreq->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
add_pkt2val_chain( &dnsreq->my_mf, &chain add_pkt2val_chain( &dnsreq->my_mf, &chain
, netreq->response, netreq->response_len , netreq->response, netreq->response_len
, netreq , netreq
@ -3415,13 +3616,17 @@ getdns_validate_dnssec3(const getdns_list *records_to_validate,
fflush(stdout); fflush(stdout);
#endif #endif
if (!records_to_validate || !support_records || !trust_anchors) if (!records_to_validate || !trust_anchors)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
mf = (struct mem_funcs *)&records_to_validate->mf; mf = (struct mem_funcs *)&records_to_validate->mf;
/* First convert everything to wire format /* First convert everything to wire format
*/ */
if (!(support = _getdns_list2wire(support_records,
if (!support_records)
(void) memset((support = support_buf), 0, GLDNS_HEADER_SIZE);
else if (!(support = _getdns_list2wire(support_records,
support_buf, &support_len, mf))) support_buf, &support_len, mf)))
return GETDNS_RETURN_MEMORY_ERROR; return GETDNS_RETURN_MEMORY_ERROR;
@ -3440,7 +3645,7 @@ getdns_validate_dnssec3(const getdns_list *records_to_validate,
for (i = 0; !getdns_list_get_dict(records_to_validate,i,&reply); i++) { for (i = 0; !getdns_list_get_dict(records_to_validate,i,&reply); i++) {
DEBUG_SEC("REPLY "PRIsz", r: %d\n", i, r); DEBUG_SEC("REPLY %"PRIsz", r: %d\n", i, r);
if (to_val != to_val_buf) if (to_val != to_val_buf)
GETDNS_FREE(*mf, to_val); GETDNS_FREE(*mf, to_val);
to_val_len = sizeof(to_val_buf); to_val_len = sizeof(to_val_buf);
@ -3468,7 +3673,7 @@ getdns_validate_dnssec3(const getdns_list *records_to_validate,
break; break;
} }
} }
DEBUG_SEC("REPLY "PRIsz", r: %d\n", i, r); DEBUG_SEC("REPLY %"PRIsz", r: %d\n", i, r);
exit_free_to_val: exit_free_to_val:
if (to_val != to_val_buf) if (to_val != to_val_buf)

View File

@ -48,6 +48,7 @@
void _getdns_get_validation_chain(getdns_dns_req *dns_req); void _getdns_get_validation_chain(getdns_dns_req *dns_req);
void _getdns_cancel_validation_chain(getdns_dns_req *dns_req); void _getdns_cancel_validation_chain(getdns_dns_req *dns_req);
void _getdns_validation_chain_timeout(getdns_dns_req *dns_req); void _getdns_validation_chain_timeout(getdns_dns_req *dns_req);
void _getdns_ta_notify_dnsreqs(getdns_context *context);
uint16_t _getdns_parse_ta_file(time_t *ta_mtime, gldns_buffer *gbuf); uint16_t _getdns_parse_ta_file(time_t *ta_mtime, gldns_buffer *gbuf);
@ -66,6 +67,8 @@ static inline int _dnssec_rdata_to_canonicalize(uint16_t rr_type)
|| rr_type == GLDNS_RR_TYPE_DNAME || rr_type == GLDNS_RR_TYPE_RRSIG; || rr_type == GLDNS_RR_TYPE_DNAME || rr_type == GLDNS_RR_TYPE_RRSIG;
} }
int _getdns_bogus(getdns_dns_req *dns_req);
#endif #endif
/* dnssec.h */ /* dnssec.h */

View File

@ -172,6 +172,9 @@ getdns_libuv_timeout_cb(uv_timer_t *timer, int status)
#endif #endif
{ {
getdns_eventloop_event *el_ev = (getdns_eventloop_event *)timer->data; getdns_eventloop_event *el_ev = (getdns_eventloop_event *)timer->data;
#ifndef HAVE_NEW_UV_TIMER_CB
(void)status;
#endif
assert(el_ev->timeout_cb); assert(el_ev->timeout_cb);
DEBUG_UV("enter libuv_timeout_cb(el_ev = %p, el_ev->ev = %p)\n" DEBUG_UV("enter libuv_timeout_cb(el_ev = %p, el_ev->ev = %p)\n"
, el_ev, el_ev->ev); , el_ev, el_ev->ev);

View File

@ -27,13 +27,8 @@
#include "config.h" #include "config.h"
#ifdef HAVE_SYS_POLL_H #include "util-internal.h"
#include <sys/poll.h> #include "platform.h"
#else
#ifndef USE_WINSOCK
#include <poll.h>
#endif
#endif
#ifdef HAVE_SYS_RESOURCE_H #ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h> #include <sys/resource.h>
#endif #endif
@ -148,7 +143,7 @@ static uint64_t get_now_plus(uint64_t amount)
uint64_t now; uint64_t now;
if (gettimeofday(&tv, NULL)) { if (gettimeofday(&tv, NULL)) {
perror("gettimeofday() failed"); _getdns_perror("gettimeofday() failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
now = tv.tv_sec * 1000000 + tv.tv_usec; now = tv.tv_sec * 1000000 + tv.tv_usec;
@ -296,7 +291,8 @@ poll_read_cb(int fd, getdns_eventloop_event *event)
(void)fd; (void)fd;
#endif #endif
DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event);
event->read_cb(event->userarg); if (event && event->read_cb)
event->read_cb(event->userarg);
} }
static void static void
@ -306,14 +302,16 @@ poll_write_cb(int fd, getdns_eventloop_event *event)
(void)fd; (void)fd;
#endif #endif
DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event);
event->write_cb(event->userarg); if (event && event->write_cb)
event->write_cb(event->userarg);
} }
static void static void
poll_timeout_cb(getdns_eventloop_event *event) poll_timeout_cb(getdns_eventloop_event *event)
{ {
DEBUG_SCHED( "%s(event: %p)\n", __FUNC__, (void *)event); DEBUG_SCHED( "%s(event: %p)\n", __FUNC__, (void *)event);
event->timeout_cb(event->userarg); if (event && event->timeout_cb)
event->timeout_cb(event->userarg);
} }
static void static void
@ -408,11 +406,9 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking)
{ {
Sleep(poll_timeout); Sleep(poll_timeout);
} else } else
if (WSAPoll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) {
#else
if (poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) {
#endif #endif
perror("poll() failed"); if (_getdns_poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) {
_getdns_perror("poll() failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
now = get_now_plus(0); now = get_now_plus(0);

View File

@ -27,9 +27,10 @@
#include "config.h" #include "config.h"
#include "extension/select_eventloop.h"
#include "debug.h" #include "debug.h"
#include "types-internal.h" #include "types-internal.h"
#include "platform.h"
#include "extension/select_eventloop.h"
static uint64_t get_now_plus(uint64_t amount) static uint64_t get_now_plus(uint64_t amount)
{ {
@ -37,7 +38,7 @@ static uint64_t get_now_plus(uint64_t amount)
uint64_t now; uint64_t now;
if (gettimeofday(&tv, NULL)) { if (gettimeofday(&tv, NULL)) {
perror("gettimeofday() failed"); _getdns_perror("gettimeofday() failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
now = tv.tv_sec * 1000000 + tv.tv_usec; now = tv.tv_sec * 1000000 + tv.tv_usec;
@ -235,20 +236,21 @@ select_eventloop_run_once(getdns_eventloop *loop, int blocking)
tv.tv_usec = (long)((timeout - now) % 1000000); tv.tv_usec = (long)((timeout - now) % 1000000);
} }
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
if (max_fd == -1) if (max_fd == -1) {
{ if (timeout != TIMEOUT_FOREVER) {
if (timeout != TIMEOUT_FOREVER) uint32_t timeout_ms = (tv.tv_usec / 1000) + (tv.tv_sec * 1000);
{ Sleep(timeout_ms);
uint32_t timeout_ms = (tv.tv_usec / 1000) + (tv.tv_sec * 1000); }
Sleep(timeout_ms); } else {
}
} else
#endif #endif
if (select(max_fd + 1, &readfds, &writefds, NULL, if (select(max_fd + 1, &readfds, &writefds, NULL,
(timeout == TIMEOUT_FOREVER ? NULL : &tv)) < 0) { (timeout == TIMEOUT_FOREVER ? NULL : &tv)) < 0) {
perror("select() failed"); _getdns_perror("select() failed");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
#ifdef USE_WINSOCK
}
#endif
now = get_now_plus(0); now = get_now_plus(0);
for (fd = 0; fd < (int)FD_SETSIZE; fd++) { for (fd = 0; fd < (int)FD_SETSIZE; fd++) {
if (select_loop->fd_events[fd] && if (select_loop->fd_events[fd] &&

View File

@ -34,6 +34,7 @@
#include "config.h" #include "config.h"
#include "getdns/getdns.h" #include "getdns/getdns.h"
#include "getdns/getdns_extra.h" #include "getdns/getdns_extra.h"
#include "types-internal.h"
/* No more than select's capability queries can be outstanding, /* No more than select's capability queries can be outstanding,
* The number of outstanding timeouts should be less or equal then * The number of outstanding timeouts should be less or equal then

View File

@ -54,6 +54,7 @@
#include "dict.h" #include "dict.h"
#include "mdns.h" #include "mdns.h"
#include "debug.h" #include "debug.h"
#include "anchor.h"
void _getdns_call_user_callback(getdns_dns_req *dnsreq, getdns_dict *response) void _getdns_call_user_callback(getdns_dns_req *dnsreq, getdns_dict *response)
{ {
@ -213,13 +214,18 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
#endif #endif
#ifdef STUB_NATIVE_DNSSEC #ifdef STUB_NATIVE_DNSSEC
|| (dns_req->context->resolution_type == GETDNS_RESOLUTION_STUB || ( dns_req->context->resolution_type == GETDNS_RESOLUTION_STUB
&& !dns_req->avoid_dnssec_roadblocks && !dns_req->avoid_dnssec_roadblocks
&& (dns_req->dnssec_return_status || && (dns_req->dnssec_return_status ||
dns_req->dnssec_return_only_secure || dns_req->dnssec_return_only_secure ||
dns_req->dnssec_return_all_statuses dns_req->dnssec_return_all_statuses
)) ))
#endif #endif
|| ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING
&& (dns_req->dnssec_return_status ||
dns_req->dnssec_return_only_secure ||
dns_req->dnssec_return_all_statuses)
&& _getdns_bogus(dns_req))
)) { )) {
/* Reschedule timeout for this DNS request /* Reschedule timeout for this DNS request
*/ */
@ -235,6 +241,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
#if defined(REQ_DEBUG) && REQ_DEBUG #if defined(REQ_DEBUG) && REQ_DEBUG
debug_req("getting validation chain for ", *dns_req->netreqs); debug_req("getting validation chain for ", *dns_req->netreqs);
#endif #endif
DEBUG_ANCHOR("Valchain lookup\n");
_getdns_get_validation_chain(dns_req); _getdns_get_validation_chain(dns_req);
} else } else
_getdns_call_user_callback( _getdns_call_user_callback(
@ -442,14 +449,12 @@ _getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms)
if (_getdns_ub_loop_enabled(&context->ub_loop)) if (_getdns_ub_loop_enabled(&context->ub_loop))
ub_resolve_r = ub_resolve_event(context->unbound_ctx, ub_resolve_r = ub_resolve_event(context->unbound_ctx,
name, netreq->request_type, dns_req->request_class, name, netreq->request_type, dns_req->request_class,
netreq, ub_resolve_event_callback, &(netreq->unbound_id)) ? netreq, ub_resolve_event_callback, &(netreq->unbound_id));
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
else else
#endif #endif
ub_resolve_r = ub_resolve_async(context->unbound_ctx, ub_resolve_r = ub_resolve_async(context->unbound_ctx,
name, netreq->request_type, dns_req->request_class, name, netreq->request_type, dns_req->request_class,
netreq, ub_resolve_callback, &(netreq->unbound_id)) ? netreq, ub_resolve_callback, &(netreq->unbound_id));
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
if (dnsreq_freed) if (dnsreq_freed)
return DNS_REQ_FINISHED; return DNS_REQ_FINISHED;
dns_req->freed = NULL; dns_req->freed = NULL;
@ -570,11 +575,6 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
if (extensions && (r = validate_extensions(extensions))) if (extensions && (r = validate_extensions(extensions)))
return r; return r;
/* Set up the context assuming we won't use the specified namespaces.
This is (currently) identical to setting up a pure DNS namespace */
if ((r = _getdns_context_prepare_for_resolution(context, 0)))
return r;
/* create the request */ /* create the request */
if (!(req = _getdns_dns_req_new( if (!(req = _getdns_dns_req_new(
context, loop, name, request_type, extensions, &now_ms))) context, loop, name, request_type, extensions, &now_ms)))
@ -590,9 +590,31 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
_getdns_context_track_outbound_request(req); _getdns_context_track_outbound_request(req);
if (!usenamespaces) if (req->dnssec_extension_set) {
if (context->trust_anchors_source == GETDNS_TASRC_XML_UPDATE)
_getdns_start_fetching_ta(context, loop);
else if (context->trust_anchors_source == GETDNS_TASRC_NONE) {
_getdns_context_equip_with_anchor(context, &now_ms);
if (context->trust_anchors_source == GETDNS_TASRC_NONE) {
_getdns_start_fetching_ta(context, loop);
}
}
}
if (!usenamespaces) {
if (context->trust_anchors_source == GETDNS_TASRC_FETCHING
&& context->resolution_type == GETDNS_RESOLUTION_RECURSING
&& context->resolution_type != context->resolution_type_set) {
req->waiting_for_ta = 1;
req->ta_notify = context->ta_notify;
context->ta_notify = req;
return GETDNS_RETURN_GOOD;
}
if ((r = _getdns_context_prepare_for_resolution(context)))
; /* pass */
/* issue all network requests */ /* issue all network requests */
for ( netreq_p = req->netreqs else for ( netreq_p = req->netreqs
; !r && (netreq = *netreq_p) ; !r && (netreq = *netreq_p)
; netreq_p++) { ; netreq_p++) {
if ((r = _getdns_submit_netreq(netreq, &now_ms))) { if ((r = _getdns_submit_netreq(netreq, &now_ms))) {
@ -605,7 +627,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
} }
} }
else for (i = 0; i < context->namespace_count; i++) { } else for (i = 0; i < context->namespace_count; i++) {
if (context->namespaces[i] == GETDNS_NAMESPACE_LOCALNAMES) { if (context->namespaces[i] == GETDNS_NAMESPACE_LOCALNAMES) {
if (!(r = _getdns_context_local_namespace_resolve( if (!(r = _getdns_context_local_namespace_resolve(
@ -639,6 +661,16 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
} }
#endif /* HAVE_MDNS_SUPPORT */ #endif /* HAVE_MDNS_SUPPORT */
} else if (context->namespaces[i] == GETDNS_NAMESPACE_DNS) { } else if (context->namespaces[i] == GETDNS_NAMESPACE_DNS) {
if (context->trust_anchors_source == GETDNS_TASRC_FETCHING
&& context->resolution_type == GETDNS_RESOLUTION_RECURSING
&& context->resolution_type != context->resolution_type_set) {
req->waiting_for_ta = 1;
req->ta_notify = context->ta_notify;
context->ta_notify = req;
return GETDNS_RETURN_GOOD;
}
if ((r = _getdns_context_prepare_for_resolution(context)))
break;
/* TODO: We will get a good return code here even if /* TODO: We will get a good return code here even if
the name is not found (NXDOMAIN). We should consider the name is not found (NXDOMAIN). We should consider

View File

@ -79,6 +79,16 @@ extern "C" {
#define GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME_TEXT "Change related to getdns_context_set_tls_backoff_time" #define GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME_TEXT "Change related to getdns_context_set_tls_backoff_time"
#define GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES 624 #define GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES 624
#define GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES_TEXT "Change related to getdns_context_set_tls_connection_retries" #define GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES_TEXT "Change related to getdns_context_set_tls_connection_retries"
#define GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL 625
#define GETDNS_CONTEXT_CODE_TRUST_ANCHORS_URL_TEXT "Change related to getdns_context_set_trust_anchors_url"
#define GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_CA 626
#define GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_CA_TEXT "Change related to getdns_context_set_trust_anchors_verify_ca"
#define GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_EMAIL 627
#define GETDNS_CONTEXT_CODE_TRUST_ANCHORS_VERIFY_EMAIL_TEXT "Change related to getdns_context_set_trust_anchors_verify_email"
#define GETDNS_CONTEXT_CODE_APPDATA_DIR 628
#define GETDNS_CONTEXT_CODE_APPDATA_DIR_TEXT "Change related to getdns_context_set_appdata_dir"
/** @} /** @}
*/ */
@ -520,7 +530,7 @@ typedef enum getdns_loglevel_type {
#define GETDNS_LOG_CRIT_TEXT "Critical conditions" #define GETDNS_LOG_CRIT_TEXT "Critical conditions"
#define GETDNS_LOG_ERR_TEXT "Error conditions" #define GETDNS_LOG_ERR_TEXT "Error conditions"
#define GETDNS_LOG_WARNING_TEXT "Warning conditions" #define GETDNS_LOG_WARNING_TEXT "Warning conditions"
#define GETDNS_LOG_NOTICE_TEXT "normal, but significant, condition" #define GETDNS_LOG_NOTICE_TEXT "Normal, but significant, condition"
#define GETDNS_LOG_INFO_TEXT "Informational message" #define GETDNS_LOG_INFO_TEXT "Informational message"
#define GETDNS_LOG_DEBUG_TEXT "Debug-level message" #define GETDNS_LOG_DEBUG_TEXT "Debug-level message"
@ -531,12 +541,145 @@ typedef void (*getdns_logfunc_type) (void *userarg, uint64_t log_systems,
getdns_loglevel_type, const char *, va_list ap); getdns_loglevel_type, const char *, va_list ap);
/** /**
* * Register a function that will be called when there is something to log
* equally or more severe than the given level for the given system.
* @param[in] context The context from which to get the setting
* @param[in] userarg A user defined argument to be passed to the
* log function.
* @param[in] system A bitwise ORed collection of systems for which the log
* function should be called. Currently only logging
* information about upstream statistics is available;
* i.e.: GETDNS_LOG_UPSTREAM_STATS
* @param[in] level A severity level. The log function will be called
* only for messages with an equal or more severe level.
* More severe has a lower value.
* @param[in] func The log function to call with the user argument,
* the system for which the log message, the severity
* level, a printf style format string and the arguments
* for the format string, as parameter.
* @see getdns_loglevel_type
* @see getdns_logfunc_type
* @return GETDNS_RETURN_GOOD when successful
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/ */
getdns_return_t getdns_return_t
getdns_context_set_logfunc(getdns_context *context, void *userarg, getdns_context_set_logfunc(getdns_context *context, void *userarg,
uint64_t system, getdns_loglevel_type level, getdns_logfunc_type func); uint64_t system, getdns_loglevel_type level, getdns_logfunc_type func);
/**
* Define the location for storing library specific data. The location should
* be writable for the current user using the application with which the
* library is linked. Currently this is only used for storing data concerning
* zero configuration dnssec.
* @param[in] context The context from which to get the setting
* @param[in] appdata_dir A user writable location in which the library can
* store data. The last element of the path is tried
* to be created if it does not exist. When NULL is
* given, the default location is used which is
* ${HOME}/.getdns/ on Unix line systems (Linux, BSD's,
* MacOS), and %AppData%\getnds\ on Windows.
* @return GETDNS_RETURN_GOOD when successful
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/
getdns_return_t
getdns_context_set_appdata_dir(
getdns_context *context, const char *appdata_dir);
/**
* Sets the url for the location of the XML file from which to fetch the
* trust anchors with Zero configuration DNSSEC. The url should be for
* http, and the file should have the .xml extension.
*
* Alongside the XML file, also the S/MIME signature that will be used to
* validate the XML file, will be fetched from the url with the .xml extension
* replaced by .p7s.
*
* When successfully validated with the verify Certificate Authority and the
* verify email address, the context will be equipped with the DNSSEC trust
* anchors defined within the XML file as described in RFC7958.
* The XML file will also be stored together with the .p7s file in the
* appdata directory with the names "root-anchors.xml" and "root-anchors.p7s"
* respectively.
*
* When the trust-anchors from the XML file are used, the root DNSKEY is
* tracked and stored in the appdata directory too as "root.key"
*
* Trust anchors from the XML file will be tried when:
* - There were no other trust anchors provided, either by the default
* trust anchor file "@TRUST_ANCHOR_FILE@", or set with the
* getdns_context_set_dnssec_trust_anchors() function.
* - or the available trust anchors (from the default location or set by
* the application) caused the root DNSKEY rrset to be BOGUS.
*
* Trust anchors from the XML file will be read from the root-anchors.xml
* file in appdata directory and will only be used when validation with the
* S/MIME signatures in root-anchors.p7s succeeds with the verification
* Certificate Authority and the verification email address.
*
* A (new) version of "root-anchors.xml" and "root-anchors.p7s" will be
* fetched when:
* - The appdata directory is writeable by the current used, but the
* "root-anchors.xml" or "root-anchors.p7s" files were not available.
* - or there is a new root DNSKEY RRset (or signature) and it contains
* key_ids which were not in "root-anchors.xml."
*
* @see getdns_context_get_trust_anchors_url
* @see getdns_context_set_trust_anchors_verify_CA
* @see getdns_context_set_trust_anchors_verify_email
* @param[in] context The context to configure
* @param[in] url The url including the XML file from which the
* trust anchors (and the S/MIME signature) will be
* fetched. Default is:
* http://data.iana.org/root-anchors/root-anchors.xml
* When NULL is given, the default will be used.
* @return GETDNS_RETURN_GOOD when successful
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/
getdns_return_t
getdns_context_set_trust_anchors_url(getdns_context *context, const char *url);
/**
* Sets the public certificate for the Certificate Authority with which to
* validate the XML file with the S/MIME signatures fetch from the url
* given with the getdns_context_set_trust_anchors_url() function.
* @see getdns_context_get_trust_anchors_verify_CA
* @see getdns_context_set_trust_anchors_url
* @see getdns_context_set_trust_anchors_verify_email
* @param[in] context The context to configure
* @param[in] verify_CA The certificate of the Certificate Authority with
* which to validate the XML trust anchors.
* The default is the ICANN Root CA, which is valid
* till Dec 18 2029.
* When NULL is given, the default will be used.
* When an empty string is given, Zero configuration
* DNSSEC will be disabled.
* @return GETDNS_RETURN_GOOD when successful
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/
getdns_return_t
getdns_context_set_trust_anchors_verify_CA(
getdns_context *context, const char *verify_CA);
/**
* Sets the email address for the Subject of the signer's certificate from the
* p7s signature file with which to validate the XML file fetched from the url
* given with the getdns_context_set_trust_anchors_url() function.
* @see getdns_context_get_trust_anchors_verify_email
* @see getdns_context_set_trust_anchors_url
* @see getdns_context_set_trust_anchors_verify_CA
* @param[in] context The context to configure
* @param[in] verify_email Only signatures from this name are allowed.
* The default dnssec@iana.org.
* When NULL is given, the default will be used.
* When an empty string is given, Zero configuration
* DNSSEC will be disabled.
* @return GETDNS_RETURN_GOOD when successful
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/
getdns_return_t
getdns_context_set_trust_anchors_verify_email(
getdns_context *context, const char *verify_email);
/** /**
* Get the current resolution type setting from this context. * Get the current resolution type setting from this context.
* @see getdns_context_set_resolution_type * @see getdns_context_set_resolution_type
@ -902,6 +1045,96 @@ getdns_return_t
getdns_context_get_update_callback(getdns_context *context, void **userarg, getdns_context_get_update_callback(getdns_context *context, void **userarg,
void (**value) (getdns_context *, getdns_context_code_t, void *)); void (**value) (getdns_context *, getdns_context_code_t, void *));
/**
* Gets the url for the location of the XML file from which to fetch the
* trust anchors with Zero configuration DNSSEC.
*
* Alongside the XML file, also the S/MIME signature that will be used to
* validate the XML file, will be fetched from the url with the .xml extension
* replaced by .p7s.
*
* When successfully validated with the verify Certificate Authority and the
* verify email address, the context will be equipped with the DNSSEC trust
* anchors defined within the XML file as described in RFC7958.
* The XML file will also be stored together with the .p7s file in the
* appdata directory with the names "root-anchors.xml" and "root-anchors.p7s"
* respectively.
*
* When the trust-anchors from the XML file are used, the root DNSKEY is
* tracked and stored in the appdata directory too as "root.key"
*
* Trust anchors from the XML file will be tried when:
* - There were no other trust anchors provided, either by the default
* trust anchor file "@TRUST_ANCHOR_FILE@", or set with the
* getdns_context_set_dnssec_trust_anchors() function.
* - or the available trust anchors (from the default location or set by
* the application) caused the root DNSKEY rrset to be BOGUS.
*
* Trust anchors from the XML file will be read from the root-anchors.xml
* file in appdata directory and will only be used when validation with the
* S/MIME signatures in root-anchors.p7s succeeds with the verification
* Certificate Authority and the verification email address.
*
* A (new) version of "root-anchors.xml" and "root-anchors.p7s" will be
* fetched when:
* - The appdata directory is writeable by the current used, but the
* "root-anchors.xml" or "root-anchors.p7s" files were not available.
* - or there is a new root DNSKEY RRset (or signature) and it contains
* key_ids which were not in "root-anchors.xml."
*
* @see getdns_context_set_trust_anchors_url
* @see getdns_context_get_trust_anchors_verify_CA
* @see getdns_context_get_trust_anchors_verify_email
* @param[in] context The context to configure
* @param[out] url The url including the XML file, from which the
* trust anchors (and the S/MIME signature) will be
* fetched. Default is:
* http://data.iana.org/root-anchors/root-anchors.xml
* @return GETDNS_RETURN_GOOD when successful
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/
getdns_return_t
getdns_context_get_trust_anchors_url(
getdns_context *context, const char **url);
/**
* Gets the public certificate for the Certificate Authority with which to
* validate the XML file with the S/MIME signatures fetch from the url
* given with the getdns_context_set_trust_anchors_url() function.
* @see getdns_context_set_trust_anchors_verify_CA
* @see getdns_context_get_trust_anchors_url
* @see getdns_context_get_trust_anchors_verify_email
* @param[in] context The context to configure
* @param[out] verify_CA The certificate of the Certificate Authority with
* which to validate the XML trust anchors.
* The default is the ICANN Root CA, which is valid
* till Dec 18 2029.
* @return GETDNS_RETURN_GOOD when successful
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/
getdns_return_t
getdns_context_get_trust_anchors_verify_CA(
getdns_context *context, const char **verify_CA);
/**
* Gets the email address for the Subject of the signer's certificate from the
* p7s signature file with which to validate the XML file fetched from the url
* given with the getdns_context_set_trust_anchors_url() function.
* @see getdns_context_set_trust_anchors_verify_email
* @see getdns_context_get_trust_anchors_url
* @see getdns_context_get_trust_anchors_verify_CA
* @param[in] context The context to configure
* @param[out] verify_email Only signatures from this name are allowed.
* The default dnssec@iana.org.
* @return GETDNS_RETURN_GOOD when successful
* @return GETDNS_RETURN_INVALID_PARAMETER when context was NULL.
*/
getdns_return_t
getdns_context_get_trust_anchors_verify_email(
getdns_context *context, const char **verify_email);
/** @} /** @}
*/ */
@ -1723,6 +1956,7 @@ getdns_str2bindata(const char *str, getdns_bindata **bindata);
getdns_return_t getdns_return_t
getdns_str2int(const char *str, uint32_t *value); getdns_str2int(const char *str, uint32_t *value);
/** @} /** @}
*/ */

View File

@ -95,7 +95,7 @@ gldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
} }
} }
uint16_t gldns_calc_keytag_raw(uint8_t* key, size_t keysize) uint16_t gldns_calc_keytag_raw(const uint8_t* key, size_t keysize)
{ {
if(keysize < 4) { if(keysize < 4) {
return 0; return 0;

View File

@ -44,7 +44,7 @@ size_t gldns_rr_dnskey_key_size_raw(const unsigned char *keydata,
* \param[in] keysize length of key data. * \param[in] keysize length of key data.
* \return the keytag * \return the keytag
*/ */
uint16_t gldns_calc_keytag_raw(uint8_t* key, size_t keysize); uint16_t gldns_calc_keytag_raw(const uint8_t* key, size_t keysize);
#if GLDNS_BUILD_CONFIG_HAVE_SSL #if GLDNS_BUILD_CONFIG_HAVE_SSL
/** /**

View File

@ -1059,11 +1059,7 @@ int gldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
d4 = (*d)[4]; d4 = (*d)[4];
d5 = (*d)[5]; d5 = (*d)[5];
tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5; tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
#ifndef USE_WINSOCK w = gldns_str_print(s, sl, "%"PRIu64, (uint64_t)tsigtime);
w = gldns_str_print(s, sl, "%llu", (long long)tsigtime);
#else
w = gldns_str_print(s, sl, "%I64u", (long long)tsigtime);
#endif
(*d)+=6; (*d)+=6;
(*dl)-=6; (*dl)-=6;
return w; return w;
@ -1746,13 +1742,8 @@ int gldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data,
if(error_code < llq_errors_num) if(error_code < llq_errors_num)
w += gldns_str_print(s, sl, " %s", llq_errors[error_code]); w += gldns_str_print(s, sl, " %s", llq_errors[error_code]);
else w += gldns_str_print(s, sl, " error %d", (int)error_code); else w += gldns_str_print(s, sl, " error %d", (int)error_code);
#ifndef USE_WINSOCK w += gldns_str_print(s, sl, " id %"PRIx64" lease-life %lu",
w += gldns_str_print(s, sl, " id %llx lease-life %lu", (uint64_t)llq_id, (unsigned long)lease_life);
(unsigned long long)llq_id, (unsigned long)lease_life);
#else
w += gldns_str_print(s, sl, " id %I64x lease-life %lu",
(unsigned long long)llq_id, (unsigned long)lease_life);
#endif
return w; return w;
} }

View File

@ -33,10 +33,14 @@ getdns_context_get_tls_authentication
getdns_context_get_tls_backoff_time getdns_context_get_tls_backoff_time
getdns_context_get_tls_connection_retries getdns_context_get_tls_connection_retries
getdns_context_get_tls_query_padding_blocksize getdns_context_get_tls_query_padding_blocksize
getdns_context_get_trust_anchors_url
getdns_context_get_trust_anchors_verify_CA
getdns_context_get_trust_anchors_verify_email
getdns_context_get_update_callback getdns_context_get_update_callback
getdns_context_get_upstream_recursive_servers getdns_context_get_upstream_recursive_servers
getdns_context_process_async getdns_context_process_async
getdns_context_run getdns_context_run
getdns_context_set_appdata_dir
getdns_context_set_append_name getdns_context_set_append_name
getdns_context_set_context_update_callback getdns_context_set_context_update_callback
getdns_context_set_dns_root_servers getdns_context_set_dns_root_servers
@ -67,6 +71,9 @@ getdns_context_set_tls_authentication
getdns_context_set_tls_backoff_time getdns_context_set_tls_backoff_time
getdns_context_set_tls_connection_retries getdns_context_set_tls_connection_retries
getdns_context_set_tls_query_padding_blocksize getdns_context_set_tls_query_padding_blocksize
getdns_context_set_trust_anchors_url
getdns_context_set_trust_anchors_verify_CA
getdns_context_set_trust_anchors_verify_email
getdns_context_set_update_callback getdns_context_set_update_callback
getdns_context_set_upstream_recursive_servers getdns_context_set_upstream_recursive_servers
getdns_context_set_use_threads getdns_context_set_use_threads

View File

@ -26,28 +26,11 @@
#include "gldns/pkthdr.h" #include "gldns/pkthdr.h"
#include "gldns/rrdef.h" #include "gldns/rrdef.h"
#include "util-internal.h" #include "util-internal.h"
#include "platform.h"
#include "mdns.h" #include "mdns.h"
#ifdef HAVE_MDNS_SUPPORT #ifdef HAVE_MDNS_SUPPORT
#ifdef USE_WINSOCK
typedef u_short sa_family_t;
#define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\
WSAGetLastError() == WSAEWOULDBLOCK)
#define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS)
#else
#define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK)
#define _getdns_EINPROGRESS (errno == EINPROGRESS)
#define SOCKADDR struct sockaddr
#define SOCKADDR_IN struct sockaddr_in
#define SOCKADDR_IN6 struct sockaddr_in6
#define SOCKET int
#define IP_MREQ struct ip_mreq
#define IPV6_MREQ struct ipv6_mreq
#define BOOL int
#define TRUE 1
#endif
/* Define IPV6_ADD_MEMBERSHIP for FreeBSD and Mac OS X */ /* Define IPV6_ADD_MEMBERSHIP for FreeBSD and Mac OS X */
#ifndef IPV6_ADD_MEMBERSHIP #ifndef IPV6_ADD_MEMBERSHIP
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
@ -1148,7 +1131,8 @@ mdns_udp_multicast_read_cb(void *userarg)
sizeof(cnx->response), 0, NULL, NULL); sizeof(cnx->response), 0, NULL, NULL);
if (read == -1 && _getdns_EWOULDBLOCK) if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
_getdns_socketerror() == _getdns_ECONNRESET))
return; /* TODO: this will stop the receive loop! */ return; /* TODO: this will stop the receive loop! */
if (read >= GLDNS_HEADER_SIZE) if (read >= GLDNS_HEADER_SIZE)
@ -1353,11 +1337,7 @@ static int mdns_open_ipv4_multicast(SOCKADDR_STORAGE* mcast_dest, int* mcast_des
if (ret != 0 && fd4 != -1) if (ret != 0 && fd4 != -1)
{ {
#ifdef USE_WINSOCK _getdns_closesocket(fd4);
closesocket(fd4);
#else
close(fd4);
#endif
fd4 = -1; fd4 = -1;
} }
@ -1428,11 +1408,7 @@ static int mdns_open_ipv6_multicast(SOCKADDR_STORAGE* mcast_dest, int* mcast_des
if (ret != 0 && fd6 != -1) if (ret != 0 && fd6 != -1)
{ {
#ifdef USE_WINSOCK _getdns_closesocket(fd6);
closesocket(fd6);
#else
close(fd6);
#endif
fd6 = -1; fd6 = -1;
} }
@ -1514,11 +1490,7 @@ static getdns_return_t mdns_delayed_network_init(struct getdns_context *context)
GETDNS_CLEAR_EVENT(context->extension GETDNS_CLEAR_EVENT(context->extension
, &context->mdns_connection[i].event); , &context->mdns_connection[i].event);
#ifdef USE_WINSOCK _getdns_closesocket(context->mdns_connection[i].fd);
closesocket(context->mdns_connection[i].fd);
#else
close(context->mdns_connection[i].fd);
#endif
} }
} }
@ -1657,11 +1629,7 @@ void _getdns_mdns_context_destroy(struct getdns_context *context)
/* suppress the receive event */ /* suppress the receive event */
GETDNS_CLEAR_EVENT(context->extension, &context->mdns_connection[i].event); GETDNS_CLEAR_EVENT(context->extension, &context->mdns_connection[i].event);
/* close the socket */ /* close the socket */
#ifdef USE_WINSOCK _getdns_closesocket(context->mdns_connection[i].fd);
closesocket(context->mdns_connection[i].fd);
#else
close(context->mdns_connection[i].fd);
#endif
} }
GETDNS_FREE(context->mf, context->mdns_connection); GETDNS_FREE(context->mf, context->mdns_connection);
@ -1686,11 +1654,7 @@ _getdns_cancel_mdns_request(getdns_network_req *netreq)
{ {
mdns_cleanup(netreq); mdns_cleanup(netreq);
if (netreq->fd >= 0) { if (netreq->fd >= 0) {
#ifdef USE_WINSOCK _getdns_closesocket(netreq->fd);
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
} }
} }
@ -1706,11 +1670,7 @@ mdns_timeout_cb(void *userarg)
/* Check the required cleanup */ /* Check the required cleanup */
mdns_cleanup(netreq); mdns_cleanup(netreq);
if (netreq->fd >= 0) if (netreq->fd >= 0)
#ifdef USE_WINSOCK _getdns_closesocket(netreq->fd);
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT); _getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
if (netreq->owner->user_callback) { if (netreq->owner->user_callback) {
netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->debug_end_time = _getdns_get_time_as_uintt64();
@ -1745,7 +1705,8 @@ mdns_udp_read_cb(void *userarg)
* i.e. overflow * i.e. overflow
*/ */
0, NULL, NULL); 0, NULL, NULL);
if (read == -1 && _getdns_EWOULDBLOCK) if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
_getdns_socketerror() == _getdns_ECONNRESET))
return; return;
if (read < GLDNS_HEADER_SIZE) if (read < GLDNS_HEADER_SIZE)
@ -1759,11 +1720,7 @@ mdns_udp_read_cb(void *userarg)
// TODO: check that the source address originates from the local network. // TODO: check that the source address originates from the local network.
// TODO: check TTL = 255 // TODO: check TTL = 255
#ifdef USE_WINSOCK _getdns_closesocket(netreq->fd);
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
/* /*
* TODO: how to handle an MDNS response with TC bit set? * TODO: how to handle an MDNS response with TC bit set?
* Ignore it for now, as we do not support any kind of TCP fallback * Ignore it for now, as we do not support any kind of TCP fallback
@ -1814,11 +1771,7 @@ mdns_udp_write_cb(void *userarg)
netreq->fd, (const void *)netreq->query, pkt_len, 0, netreq->fd, (const void *)netreq->query, pkt_len, 0,
(struct sockaddr *)&mdns_mcast_v4, (struct sockaddr *)&mdns_mcast_v4,
sizeof(mdns_mcast_v4))) { sizeof(mdns_mcast_v4))) {
#ifdef USE_WINSOCK _getdns_closesocket(netreq->fd);
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
return; return;
} }
GETDNS_SCHEDULE_EVENT( GETDNS_SCHEDULE_EVENT(

View File

@ -24,13 +24,11 @@
#ifdef HAVE_MDNS_SUPPORT #ifdef HAVE_MDNS_SUPPORT
#include "getdns/getdns.h" #include "getdns/getdns.h"
#include "types-internal.h" #include "types-internal.h"
#include "util-internal.h"
#include "platform.h"
#include "util/lruhash.h" #include "util/lruhash.h"
#include "config.h" #include "config.h"
#ifndef USE_WINSOCK
#define SOCKADDR_STORAGE struct sockaddr_storage
#endif
getdns_return_t getdns_return_t
_getdns_submit_mdns_request(getdns_network_req *netreq); _getdns_submit_mdns_request(getdns_network_req *netreq);

View File

@ -8,6 +8,7 @@ write_symbols() {
} }
write_symbols libgetdns.symbols getdns/getdns.h.in getdns/getdns_extra.h.in write_symbols libgetdns.symbols getdns/getdns.h.in getdns/getdns_extra.h.in
#echo getdns_yaml2dict >> libgetdns.symbols
echo plain_mem_funcs_user_arg >> libgetdns.symbols echo plain_mem_funcs_user_arg >> libgetdns.symbols
echo priv_getdns_context_mf >> libgetdns.symbols echo priv_getdns_context_mf >> libgetdns.symbols
write_symbols extension/libevent.symbols getdns/getdns_ext_libevent.h write_symbols extension/libevent.symbols getdns/getdns_ext_libevent.h

69
src/platform.c Normal file
View File

@ -0,0 +1,69 @@
/**
*
* \file platform.c
* @brief general functions with platform-dependent implementations
*
*/
/*
* Copyright (c) 2017, NLnet Labs, Sinodun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "platform.h"
#include <stdio.h>
#ifdef USE_WINSOCK
void _getdns_perror(const char *str)
{
char msg[256];
int errid = WSAGetLastError();
*msg = '\0';
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errid,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
msg,
sizeof(msg),
NULL);
if (*msg == '\0')
sprintf(msg, "Unknown error: %d", errid);
if (str && *str != '\0')
fprintf(stderr, "%s: ", str);
fputs(msg, stderr);
}
#else
void _getdns_perror(const char *str)
{
perror(str);
}
#endif

84
src/platform.h Normal file
View File

@ -0,0 +1,84 @@
/**
*
* \file platform.h
* @brief general functions with platform-dependent implementations
*
*/
/*
* Copyright (c) 2017, NLnet Labs, Sinodun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PLATFORM_H
#define PLATFORM_H
#include "config.h"
#ifdef USE_WINSOCK
typedef u_short sa_family_t;
#define _getdns_EAGAIN (WSATRY_AGAIN)
#define _getdns_EWOULDBLOCK (WSAEWOULDBLOCK)
#define _getdns_EINPROGRESS (WSAEINPROGRESS)
#define _getdns_EMFILE (WSAEMFILE)
#define _getdns_ECONNRESET (WSAECONNRESET)
#define _getdns_closesocket(fd) closesocket(fd)
#define _getdns_poll(fdarray, nsockets, timer) WSAPoll(fdarray, nsockets, timer)
#define _getdns_socketerror() (WSAGetLastError())
#else /* USE_WINSOCK */
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
#else
# include <poll.h>
#endif
#define _getdns_EAGAIN (EAGAIN)
#define _getdns_EWOULDBLOCK (EWOULDBLOCK)
#define _getdns_EINPROGRESS (EINPROGRESS)
#define _getdns_EMFILE (EMFILE)
#define _getdns_ECONNRESET (ECONNRESET)
#define SOCKADDR struct sockaddr
#define SOCKADDR_IN struct sockaddr_in
#define SOCKADDR_IN6 struct sockaddr_in6
#define SOCKADDR_STORAGE struct sockaddr_storage
#define SOCKET int
#define IP_MREQ struct ip_mreq
#define IPV6_MREQ struct ipv6_mreq
#define BOOL int
#define TRUE 1
#define _getdns_closesocket(fd) close(fd)
#define _getdns_poll(fdarray, nsockets, timer) poll(fdarray, nsockets, timer)
#define _getdns_socketerror() (errno)
#endif
void _getdns_perror(const char *str);
#endif

View File

@ -437,14 +437,14 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
/* digest the cert with sha256 */ /* digest the cert with sha256 */
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL); len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL);
if (len > (int)sizeof(raw)) { if (len > (int)sizeof(raw)) {
DEBUG_STUB("%s %-35s: Pubkey %d is larger than "PRIsz" octets\n", DEBUG_STUB("%s %-35s: Pubkey %d is larger than %"PRIsz" octets\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, sizeof(raw)); STUB_DEBUG_SETUP_TLS, __FUNC__, i, sizeof(raw));
continue; continue;
} }
next = raw; next = raw;
i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next); i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next);
if (next - raw != len) { if (next - raw != len) {
DEBUG_STUB("%s %-35s: Pubkey %d claimed it needed %d octets, really needed "PRIsz"\n", DEBUG_STUB("%s %-35s: Pubkey %d claimed it needed %d octets, really needed %"PRIsz"\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, len, next - raw); STUB_DEBUG_SETUP_TLS, __FUNC__, i, len, next - raw);
continue; continue;
} }
@ -453,7 +453,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
/* compare it */ /* compare it */
for (p = pinset; p; p = p->next) for (p = pinset; p; p = p->next)
if (0 == memcmp(buf, p->pin, sizeof(p->pin))) { if (0 == memcmp(buf, p->pin, sizeof(p->pin))) {
DEBUG_STUB("%s %-35s: Pubkey %d matched pin %p ("PRIsz")\n", DEBUG_STUB("%s %-35s: Pubkey %d matched pin %p (%"PRIsz")\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p, sizeof(p->pin)); STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p, sizeof(p->pin));
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} else } else

View File

@ -107,6 +107,12 @@ network_req_cleanup(getdns_network_req *net_req)
{ {
assert(net_req); assert(net_req);
if (net_req->query_id_registered) {
(void) _getdns_rbtree_delete(
net_req->query_id_registered, net_req->node.key);
net_req->query_id_registered = NULL;
net_req->node.key = NULL;
}
if (net_req->response && (net_req->response < net_req->wire_data || if (net_req->response && (net_req->response < net_req->wire_data ||
net_req->response > net_req->wire_data+ net_req->wire_data_sz)) net_req->response > net_req->wire_data+ net_req->wire_data_sz))
GETDNS_FREE(net_req->owner->my_mf, net_req->response); GETDNS_FREE(net_req->owner->my_mf, net_req->response);
@ -123,6 +129,12 @@ netreq_reset(getdns_network_req *net_req)
*/ */
net_req->unbound_id = -1; net_req->unbound_id = -1;
_getdns_netreq_change_state(net_req, NET_REQ_NOT_SENT); _getdns_netreq_change_state(net_req, NET_REQ_NOT_SENT);
if (net_req->query_id_registered) {
(void) _getdns_rbtree_delete(net_req->query_id_registered,
(void *)(intptr_t)GLDNS_ID_WIRE(net_req->query));
net_req->query_id_registered = NULL;
net_req->node.key = NULL;
}
net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE; net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE; net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE;
net_req->response_len = 0; net_req->response_len = 0;
@ -170,7 +182,12 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
net_req->transport_count = owner->context->dns_transport_count; net_req->transport_count = owner->context->dns_transport_count;
memcpy(net_req->transports, owner->context->dns_transports, memcpy(net_req->transports, owner->context->dns_transports,
net_req->transport_count * sizeof(getdns_transport_list_t)); net_req->transport_count * sizeof(getdns_transport_list_t));
net_req->tls_auth_min = owner->context->tls_auth_min; net_req->tls_auth_min =
owner->context->tls_auth == GETDNS_AUTHENTICATION_REQUIRED
&& owner->context->dns_transport_count == 1
&& owner->context->dns_transports[0] == GETDNS_TRANSPORT_TLS
? GETDNS_AUTHENTICATION_REQUIRED
: GETDNS_AUTHENTICATION_NONE;
net_req->follow_redirects = owner->context->follow_redirects; net_req->follow_redirects = owner->context->follow_redirects;
@ -191,6 +208,11 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
/* Scheduling, touch only via _getdns_netreq_change_state! /* Scheduling, touch only via _getdns_netreq_change_state!
*/ */
net_req->state = NET_REQ_NOT_SENT; net_req->state = NET_REQ_NOT_SENT;
/* A registered netreq (on a statefull transport)
* Deregister on reset and cleanup.
*/
net_req->query_id_registered = NULL;
net_req->node.key = NULL;
if (max_query_sz == 0) { if (max_query_sz == 0) {
net_req->query = NULL; net_req->query = NULL;
@ -914,6 +936,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
dnssec_return_full_validation_chain; dnssec_return_full_validation_chain;
result->dnssec_return_validation_chain = dnssec_return_validation_chain result->dnssec_return_validation_chain = dnssec_return_validation_chain
|| dnssec_return_full_validation_chain; || dnssec_return_full_validation_chain;
result->dnssec_extension_set = dnssec_extension_set;
result->edns_cookies = edns_cookies; result->edns_cookies = edns_cookies;
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
result->dnssec_roadblock_avoidance = dnssec_roadblock_avoidance; result->dnssec_roadblock_avoidance = dnssec_roadblock_avoidance;
@ -940,8 +963,10 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
result->upstreams->referenced++; result->upstreams->referenced++;
result->finished_next = NULL; result->finished_next = NULL;
result->ta_notify = NULL;
result->freed = NULL; result->freed = NULL;
result->validating = 0; result->validating = 0;
result->waiting_for_ta = 0;
result->is_dns_request = 1; result->is_dns_request = 1;
result->request_timed_out = 0; result->request_timed_out = 0;
result->chain = NULL; result->chain = NULL;

View File

@ -39,6 +39,8 @@
#include "types-internal.h" #include "types-internal.h"
#include "debug.h" #include "debug.h"
#include "util/rbtree.h" #include "util/rbtree.h"
#include "util-internal.h"
#include "platform.h"
#include "server.h" #include "server.h"
#define DNS_REQUEST_SZ 4096 #define DNS_REQUEST_SZ 4096
@ -135,11 +137,7 @@ static void tcp_connection_destroy(tcp_connection *conn)
loop->vmt->clear(loop, &conn->event); loop->vmt->clear(loop, &conn->event);
if (conn->fd >= 0) if (conn->fd >= 0)
#ifdef USE_WINSOCK (void) _getdns_closesocket(conn->fd);
(void) closesocket(conn->fd);
#else
(void) close(conn->fd);
#endif
GETDNS_FREE(*mf, conn->read_buf); GETDNS_FREE(*mf, conn->read_buf);
for (cur = conn->to_write; cur; cur = next) { for (cur = conn->to_write; cur; cur = next) {
@ -189,7 +187,8 @@ static void tcp_write_cb(void *userarg)
} }
to_write = conn->to_write; to_write = conn->to_write;
if (conn->fd == -1 || if (conn->fd == -1 ||
(written = send(conn->fd, &to_write->write_buf[to_write->written], (written = send(conn->fd,
(const void *)&to_write->write_buf[to_write->written],
to_write->write_buf_len - to_write->written, 0)) == -1) { to_write->write_buf_len - to_write->written, 0)) == -1) {
/* IO error, close connection */ /* IO error, close connection */
@ -284,11 +283,7 @@ getdns_reply(
(struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) { (struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) {
/* IO error, cleanup this listener */ /* IO error, cleanup this listener */
loop->vmt->clear(loop, &conn->l->event); loop->vmt->clear(loop, &conn->l->event);
#ifdef USE_WINSOCK _getdns_closesocket(conn->l->fd);
closesocket(conn->l->fd);
#else
close(conn->l->fd);
#endif
conn->l->fd = -1; conn->l->fd = -1;
} }
/* Unlink this connection */ /* Unlink this connection */
@ -367,7 +362,8 @@ static void tcp_read_cb(void *userarg)
(void) loop->vmt->schedule(loop, conn->fd, (void) loop->vmt->schedule(loop, conn->fd,
DOWNSTREAM_IDLE_TIMEOUT, &conn->event); DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
if ((bytes_read = recv(conn->fd, conn->read_pos, conn->to_read, 0)) < 0) { if ((bytes_read = recv(conn->fd,
(void *)conn->read_pos, conn->to_read, 0)) < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) if (errno == EAGAIN || errno == EWOULDBLOCK)
return; /* Come back to do the read later */ return; /* Come back to do the read later */
@ -481,11 +477,7 @@ static void tcp_accept_cb(void *userarg)
&conn->super.remote_in, &conn->super.addrlen)) == -1) { &conn->super.remote_in, &conn->super.addrlen)) == -1) {
/* IO error, cleanup this listener */ /* IO error, cleanup this listener */
loop->vmt->clear(loop, &l->event); loop->vmt->clear(loop, &l->event);
#ifdef USE_WINSOCK _getdns_closesocket(l->fd);
closesocket(l->fd);
#else
close(l->fd);
#endif
l->fd = -1; l->fd = -1;
GETDNS_FREE(*mf, conn); GETDNS_FREE(*mf, conn);
return; return;
@ -553,13 +545,17 @@ static void udp_read_cb(void *userarg)
conn->addrlen = sizeof(conn->remote_in); conn->addrlen = sizeof(conn->remote_in);
if ((len = recvfrom(l->fd, (void *)buf, sizeof(buf), 0, if ((len = recvfrom(l->fd, (void *)buf, sizeof(buf), 0,
(struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) { (struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) {
if (_getdns_socketerror() == _getdns_ECONNRESET) {
/*
* WINSOCK gives ECONNRESET on ICMP Port Unreachable
* being received. Ignore it.
* */
GETDNS_FREE(*mf, conn);
return;
}
/* IO error, cleanup this listener. */ /* IO error, cleanup this listener. */
loop->vmt->clear(loop, &l->event); loop->vmt->clear(loop, &l->event);
#ifdef USE_WINSOCK _getdns_closesocket(l->fd);
closesocket(l->fd);
#else
close(l->fd);
#endif
l->fd = -1; l->fd = -1;
#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG #if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG
@ -708,11 +704,7 @@ static void remove_listeners(listen_set *set)
continue; continue;
loop->vmt->clear(loop, &l->event); loop->vmt->clear(loop, &l->event);
#ifdef USE_WINSOCK _getdns_closesocket(l->fd);
closesocket(l->fd);
#else
close(l->fd);
#endif
l->fd = -1; l->fd = -1;
if (l->transport != GETDNS_TRANSPORT_TCP) if (l->transport != GETDNS_TRANSPORT_TCP)

View File

@ -38,17 +38,6 @@
*/ */
#define INTERCEPT_COM_DS 0 #define INTERCEPT_COM_DS 0
#ifdef USE_POLL_DEFAULT_EVENTLOOP
# ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
# else
#ifdef USE_WINSOCK
#define poll(fdarray, nbsockets, timer) WSAPoll(fdarray, nbsockets, timer)
#else
# include <poll.h>
#endif
# endif
#endif
#include "debug.h" #include "debug.h"
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/conf.h> #include <openssl/conf.h>
@ -63,21 +52,10 @@
#include "rr-iter.h" #include "rr-iter.h"
#include "context.h" #include "context.h"
#include "util-internal.h" #include "util-internal.h"
#include "platform.h"
#include "general.h" #include "general.h"
#include "pubkey-pinning.h" #include "pubkey-pinning.h"
#ifdef USE_WINSOCK
typedef u_short sa_family_t;
#define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\
WSAGetLastError() == WSAEWOULDBLOCK)
#define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS)
#define _getdns_EMFILE (WSAGetLastError() == WSAEMFILE)
#else
#define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK)
#define _getdns_EINPROGRESS (errno == EINPROGRESS)
#define _getdns_EMFILE (errno == EMFILE)
#endif
/* WSA TODO: /* WSA TODO:
* STUB_TCP_WOULDBLOCK added to deal with edge triggered event loops (versus * STUB_TCP_WOULDBLOCK added to deal with edge triggered event loops (versus
* level triggered). See also lines containing WSA TODO below... * level triggered). See also lines containing WSA TODO below...
@ -105,8 +83,7 @@ static void upstream_write_cb(void *userarg);
static void upstream_idle_timeout_cb(void *userarg); static void upstream_idle_timeout_cb(void *userarg);
static void upstream_schedule_netreq(getdns_upstream *upstream, static void upstream_schedule_netreq(getdns_upstream *upstream,
getdns_network_req *netreq); getdns_network_req *netreq);
static void upstream_reschedule_events(getdns_upstream *upstream, static void upstream_reschedule_events(getdns_upstream *upstream);
uint64_t idle_timeout);
static int upstream_working_ok(getdns_upstream *upstream); static int upstream_working_ok(getdns_upstream *upstream);
static int upstream_auth_status_ok(getdns_upstream *upstream, static int upstream_auth_status_ok(getdns_upstream *upstream,
getdns_network_req *netreq); getdns_network_req *netreq);
@ -438,13 +415,10 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport)
#endif #endif
if (connect(fd, (struct sockaddr *)&upstream->addr, if (connect(fd, (struct sockaddr *)&upstream->addr,
upstream->addr_len) == -1) { upstream->addr_len) == -1) {
if (_getdns_EINPROGRESS || _getdns_EWOULDBLOCK) if (_getdns_socketerror() == _getdns_EINPROGRESS ||
_getdns_socketerror() == _getdns_EWOULDBLOCK)
return fd; return fd;
#ifdef USE_WINSOCK _getdns_closesocket(fd);
closesocket(fd);
#else
close(fd);
#endif
return -1; return -1;
} }
return fd; return fd;
@ -455,22 +429,13 @@ tcp_connected(getdns_upstream *upstream) {
int error = 0; int error = 0;
socklen_t len = (socklen_t)sizeof(error); socklen_t len = (socklen_t)sizeof(error);
getsockopt(upstream->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len); getsockopt(upstream->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
#ifdef USE_WINSOCK if (error == _getdns_EINPROGRESS)
if (error == WSAEINPROGRESS)
return STUB_TCP_AGAIN; return STUB_TCP_AGAIN;
else if (error == WSAEWOULDBLOCK) else if (error == _getdns_EWOULDBLOCK || error == _getdns_EAGAIN)
return STUB_TCP_WOULDBLOCK;
else if (error != 0)
return STUB_SETUP_ERROR;
#else
if (error == EINPROGRESS)
return STUB_TCP_AGAIN;
else if (error == EWOULDBLOCK || error == EAGAIN)
return STUB_TCP_WOULDBLOCK; return STUB_TCP_WOULDBLOCK;
else if (error != 0) { else if (error != 0) {
return STUB_SETUP_ERROR; return STUB_SETUP_ERROR;
} }
#endif
if (upstream->transport == GETDNS_TRANSPORT_TCP && if (upstream->transport == GETDNS_TRANSPORT_TCP &&
upstream->queries_sent == 0) { upstream->queries_sent == 0) {
upstream->conn_state = GETDNS_CONN_OPEN; upstream->conn_state = GETDNS_CONN_OPEN;
@ -496,42 +461,56 @@ stub_next_upstream(getdns_network_req *netreq)
dnsreq->upstreams->current_udp = 0; dnsreq->upstreams->current_udp = 0;
} }
static void
remove_from_write_queue(getdns_upstream *upstream, getdns_network_req * netreq)
{
getdns_network_req *r, *prev_r;
for ( r = upstream->write_queue, prev_r = NULL
; r
; prev_r = r, r = r->write_queue_tail) {
if (r != netreq)
continue;
if (prev_r)
prev_r->write_queue_tail = r->write_queue_tail;
else
upstream->write_queue = r->write_queue_tail;
if (r == upstream->write_queue_last) {
/* If r was the last netreq,
* its write_queue tail MUST be NULL
*/
assert(r->write_queue_tail == NULL);
upstream->write_queue_last = prev_r ? prev_r : NULL;
}
netreq->write_queue_tail = NULL;
break; /* netreq found and removed */
}
}
static void static void
stub_cleanup(getdns_network_req *netreq) stub_cleanup(getdns_network_req *netreq)
{ {
DEBUG_STUB("%s %-35s: MSG: %p\n", DEBUG_STUB("%s %-35s: MSG: %p\n",
STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq); STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq);
getdns_dns_req *dnsreq = netreq->owner; getdns_dns_req *dnsreq = netreq->owner;
getdns_network_req *r, *prev_r;
getdns_upstream *upstream;
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
/* Nothing globally scheduled? Then nothing queued */ if (netreq->query_id_registered) {
if (!netreq->upstream || !(upstream = netreq->upstream)->event.ev) (void) _getdns_rbtree_delete(
return; netreq->query_id_registered, netreq->node.key);
netreq->query_id_registered = NULL;
/* Delete from upstream->netreq_by_query_id (if present) */ netreq->node.key = NULL;
(void) _getdns_rbtree_delete(&upstream->netreq_by_query_id, }
(void *)(intptr_t)GLDNS_ID_WIRE(netreq->query)); if (netreq->upstream) {
remove_from_write_queue(netreq->upstream, netreq);
/* Delete from upstream->write_queue (if present) */ if (netreq->upstream->event.ev)
for (prev_r = NULL, r = upstream->write_queue; r; upstream_reschedule_events(netreq->upstream);
prev_r = r, r = r->write_queue_tail) }
if (r == netreq) {
if (prev_r)
prev_r->write_queue_tail = r->write_queue_tail;
else
upstream->write_queue = r->write_queue_tail;
if (r == upstream->write_queue_last)
upstream->write_queue_last =
prev_r ? prev_r : NULL;
netreq->write_queue_tail = NULL;
break;
}
upstream_reschedule_events(upstream, upstream->keepalive_timeout);
} }
static void static void
@ -545,17 +524,8 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
when idle.*/ when idle.*/
/* [TLS1]TODO: Work out how to re-open the connection and re-try /* [TLS1]TODO: Work out how to re-open the connection and re-try
the queries if there is only one upstream.*/ the queries if there is only one upstream.*/
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
if (during_setup) { if (during_setup) {
/* Reset timeout on setup failure to trigger fallback handling.*/
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
/* Need this check because if the setup failed because the interface is
not up we get -1 and then a seg fault. Found when using IPv6 address
but IPv6 interface not enabled.*/
if (upstream->fd != -1) {
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd, TIMEOUT_FOREVER,
getdns_eventloop_event_init(&upstream->event, upstream,
NULL, upstream_write_cb, NULL));
}
/* Special case if failure was due to authentication issues since this /* Special case if failure was due to authentication issues since this
upstream could be used oppotunistically with no problem.*/ upstream could be used oppotunistically with no problem.*/
if (!(upstream->transport == GETDNS_TRANSPORT_TLS && if (!(upstream->transport == GETDNS_TRANSPORT_TLS &&
@ -565,6 +535,11 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
upstream->conn_shutdowns++; upstream->conn_shutdowns++;
/* [TLS1]TODO: Re-try these queries if possible.*/ /* [TLS1]TODO: Re-try these queries if possible.*/
} }
upstream->conn_state = GETDNS_CONN_TEARDOWN;
while (upstream->write_queue)
upstream_write_cb(upstream);
while (upstream->netreq_by_query_id.count) { while (upstream->netreq_by_query_id.count) {
netreq = (getdns_network_req *) netreq = (getdns_network_req *)
_getdns_rbtree_first(&upstream->netreq_by_query_id); _getdns_rbtree_first(&upstream->netreq_by_query_id);
@ -572,7 +547,7 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED); _getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
_getdns_check_dns_req_complete(netreq->owner); _getdns_check_dns_req_complete(netreq->owner);
} }
upstream->conn_state = GETDNS_CONN_TEARDOWN; _getdns_upstream_shutdown(upstream);
} }
void void
@ -582,11 +557,7 @@ _getdns_cancel_stub_request(getdns_network_req *netreq)
STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq); STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq);
stub_cleanup(netreq); stub_cleanup(netreq);
if (netreq->fd >= 0) { if (netreq->fd >= 0) {
#ifdef USE_WINSOCK _getdns_closesocket(netreq->fd);
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
netreq->fd = -1; netreq->fd = -1;
} }
} }
@ -601,15 +572,11 @@ stub_timeout_cb(void *userarg)
_getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT); _getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
/* Handle upstream*/ /* Handle upstream*/
if (netreq->fd >= 0) { if (netreq->fd >= 0) {
#ifdef USE_WINSOCK _getdns_closesocket(netreq->fd);
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
netreq->fd = -1; netreq->fd = -1;
netreq->upstream->udp_timeouts++; netreq->upstream->udp_timeouts++;
if (netreq->upstream->udp_timeouts % 100 == 0) if (netreq->upstream->udp_timeouts % 100 == 0)
_getdns_upstream_log(netreq->upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, _getdns_upstream_log(netreq->upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_INFO,
"%-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n", "%-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
netreq->upstream->addr_str, netreq->upstream->addr_str,
(int)netreq->upstream->udp_responses, (int)netreq->upstream->udp_timeouts); (int)netreq->upstream->udp_responses, (int)netreq->upstream->udp_timeouts);
@ -641,41 +608,12 @@ upstream_idle_timeout_cb(void *userarg)
static void static void
upstream_setup_timeout_cb(void *userarg) upstream_setup_timeout_cb(void *userarg)
{ {
int ret;
getdns_upstream *upstream = (getdns_upstream *)userarg; getdns_upstream *upstream = (getdns_upstream *)userarg;
#ifdef USE_POLL_DEFAULT_EVENTLOOP
struct pollfd fds;
#else
fd_set fds;
struct timeval tval;
#endif
DEBUG_STUB("%s %-35s: FD: %d\n", DEBUG_STUB("%s %-35s: FD: %d\n",
STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd); STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd);
/* Clean up and trigger a write to let the fallback code to its job */
upstream_failed(upstream, 1);
/* Need to handle the case where the far end doesn't respond to a upstream_failed(upstream, 1);
* TCP SYN and doesn't do a reset (as is the case with e.g. 8.8.8.8@853).
* For that case the socket never becomes writable so doesn't trigger any
* callbacks. If so then clear out the queue in one go.*/
#ifdef USE_POLL_DEFAULT_EVENTLOOP
fds.fd = upstream->fd;
fds.events = POLLOUT;
ret = poll(&fds, 1, 0);
#else
FD_ZERO(&fds);
FD_SET((int)(upstream->fd), &fds);
tval.tv_sec = 0;
tval.tv_usec = 0;
ret = select(upstream->fd+1, NULL, &fds, NULL, &tval);
#endif
if (ret == 0) {
DEBUG_STUB("%s %-35s: FD: %d Cleaning up dangling queue\n",
STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd);
while (upstream->write_queue)
upstream_write_cb(upstream);
}
} }
@ -701,7 +639,7 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
} }
read = recv(fd, (void *)tcp->read_pos, tcp->to_read, 0); read = recv(fd, (void *)tcp->read_pos, tcp->to_read, 0);
if (read < 0) { if (read < 0) {
if (_getdns_EWOULDBLOCK) if (_getdns_socketerror() == _getdns_EWOULDBLOCK)
return STUB_TCP_WOULDBLOCK; return STUB_TCP_WOULDBLOCK;
else else
return STUB_TCP_ERROR; return STUB_TCP_ERROR;
@ -775,6 +713,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
} while (!_getdns_rbtree_insert( } while (!_getdns_rbtree_insert(
&netreq->upstream->netreq_by_query_id, &netreq->node)); &netreq->upstream->netreq_by_query_id, &netreq->node));
netreq->query_id_registered = &netreq->upstream->netreq_by_query_id;
GLDNS_ID_SET(netreq->query, query_id); GLDNS_ID_SET(netreq->query, query_id);
@ -818,11 +757,11 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
(struct sockaddr *)&(netreq->upstream->addr), (struct sockaddr *)&(netreq->upstream->addr),
netreq->upstream->addr_len); netreq->upstream->addr_len);
#endif #endif
if ((written < 0 && (_getdns_EWOULDBLOCK || if ((written < 0 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
/* Add the error case where the connection is in progress which is when /* Add the error case where the connection is in progress which is when
a cookie is not available (e.g. when doing the first request to an a cookie is not available (e.g. when doing the first request to an
upstream). We must let the handshake complete since non-blocking. */ upstream). We must let the handshake complete since non-blocking. */
_getdns_EINPROGRESS)) || _getdns_socketerror() == _getdns_EINPROGRESS)) ||
(size_t)written < pkt_len + 2) { (size_t)written < pkt_len + 2) {
/* We couldn't write the whole packet. /* We couldn't write the whole packet.
@ -850,15 +789,10 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
/* Coming back from an earlier unfinished write or handshake. /* Coming back from an earlier unfinished write or handshake.
* Try to send remaining data */ * Try to send remaining data */
#ifdef USE_WINSOCK written = send(fd, (void *)(tcp->write_buf + tcp->written),
written = send(fd, tcp->write_buf + tcp->written,
tcp->write_buf_len - tcp->written, 0); tcp->write_buf_len - tcp->written, 0);
#else
written = write(fd, tcp->write_buf + tcp->written,
tcp->write_buf_len - tcp->written);
#endif
if (written == -1) { if (written == -1) {
if (_getdns_EWOULDBLOCK) if (_getdns_socketerror() == _getdns_EWOULDBLOCK)
return STUB_TCP_WOULDBLOCK; return STUB_TCP_WOULDBLOCK;
else { else {
DEBUG_STUB("%s %-35s: MSG: %p error while writing to TCP socket:" DEBUG_STUB("%s %-35s: MSG: %p error while writing to TCP socket:"
@ -909,7 +843,7 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
X509_verify_cert_error_string(err)); X509_verify_cert_error_string(err));
#endif #endif
if (!preverify_ok && !upstream->tls_fallback_ok) if (!preverify_ok && !upstream->tls_fallback_ok)
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, _getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
"%-40s : Verify failed : Transport=TLS - *Failure* - (%d) \"%s\"\n", "%-40s : Verify failed : Transport=TLS - *Failure* - (%d) \"%s\"\n",
upstream->addr_str, err, upstream->addr_str, err,
X509_verify_cert_error_string(err)); X509_verify_cert_error_string(err));
@ -945,7 +879,7 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
DEBUG_STUB("%s %-35s: FD: %d, WARNING: Proceeding even though pinset validation failed!\n", DEBUG_STUB("%s %-35s: FD: %d, WARNING: Proceeding even though pinset validation failed!\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd); STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd);
else else
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, _getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
"%-40s : Conn failed : Transport=TLS - *Failure* - Pinset validation failure\n", "%-40s : Conn failed : Transport=TLS - *Failure* - Pinset validation failure\n",
upstream->addr_str); upstream->addr_str);
} else { } else {
@ -1016,8 +950,11 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
X509_VERIFY_PARAM_set1_host(param, upstream->tls_auth_name, 0); X509_VERIFY_PARAM_set1_host(param, upstream->tls_auth_name, 0);
#else #else
if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) { if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) {
DEBUG_STUB("%s %-35s: ERROR: TLS Authentication functionality not available\n", DEBUG_STUB("%s %-35s: ERROR: Hostname Authentication not available from TLS library (check library version)\n",
STUB_DEBUG_SETUP_TLS, __FUNC__); STUB_DEBUG_SETUP_TLS, __FUNC__);
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
"%-40s : ERROR: Hostname Authentication not available from TLS library (check library version)\n",
upstream->addr_str);
upstream->tls_hs_state = GETDNS_HS_FAILED; upstream->tls_hs_state = GETDNS_HS_FAILED;
return NULL; return NULL;
} }
@ -1273,6 +1210,7 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
} while (!_getdns_rbtree_insert( } while (!_getdns_rbtree_insert(
&netreq->upstream->netreq_by_query_id, &netreq->node)); &netreq->upstream->netreq_by_query_id, &netreq->node));
netreq->query_id_registered = &netreq->upstream->netreq_by_query_id;
GLDNS_ID_SET(netreq->query, query_id); GLDNS_ID_SET(netreq->query, query_id);
@ -1397,7 +1335,8 @@ stub_udp_read_cb(void *userarg)
* i.e. overflow * i.e. overflow
*/ */
0, NULL, NULL); 0, NULL, NULL);
if (read == -1 && _getdns_EWOULDBLOCK) if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
_getdns_socketerror() == _getdns_ECONNRESET))
return; /* Try again later */ return; /* Try again later */
if (read == -1) { if (read == -1) {
@ -1409,11 +1348,7 @@ stub_udp_read_cb(void *userarg)
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED); _getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
/* Handle upstream*/ /* Handle upstream*/
if (netreq->fd >= 0) { if (netreq->fd >= 0) {
#ifdef USE_WINSOCK _getdns_closesocket(netreq->fd);
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
netreq->fd = -1; netreq->fd = -1;
stub_next_upstream(netreq); stub_next_upstream(netreq);
} }
@ -1433,11 +1368,7 @@ stub_udp_read_cb(void *userarg)
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
#ifdef USE_WINSOCK _getdns_closesocket(netreq->fd);
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
netreq->fd = -1; netreq->fd = -1;
while (GLDNS_TC_WIRE(netreq->response)) { while (GLDNS_TC_WIRE(netreq->response)) {
DEBUG_STUB("%s %-35s: MSG: %p TC bit set in response \n", STUB_DEBUG_READ, DEBUG_STUB("%s %-35s: MSG: %p TC bit set in response \n", STUB_DEBUG_READ,
@ -1474,7 +1405,7 @@ stub_udp_read_cb(void *userarg)
upstream->udp_responses++; upstream->udp_responses++;
if (upstream->udp_responses == 1 || if (upstream->udp_responses == 1 ||
upstream->udp_responses % 100 == 0) upstream->udp_responses % 100 == 0)
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, _getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_INFO,
"%-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n", "%-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
upstream->addr_str, upstream->addr_str,
(int)upstream->udp_responses, (int)upstream->udp_timeouts); (int)upstream->udp_responses, (int)upstream->udp_timeouts);
@ -1530,11 +1461,7 @@ stub_udp_write_cb(void *userarg)
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED); _getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
/* Handle upstream*/ /* Handle upstream*/
if (netreq->fd >= 0) { if (netreq->fd >= 0) {
#ifdef USE_WINSOCK _getdns_closesocket(netreq->fd);
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
netreq->fd = -1; netreq->fd = -1;
stub_next_upstream(netreq); stub_next_upstream(netreq);
} }
@ -1601,7 +1528,6 @@ upstream_read_cb(void *userarg)
return; return;
default: default:
/* Lookup netreq */ /* Lookup netreq */
query_id = (uint16_t) q; query_id = (uint16_t) q;
query_id_intptr = (intptr_t) query_id; query_id_intptr = (intptr_t) query_id;
@ -1613,7 +1539,16 @@ upstream_read_cb(void *userarg)
upstream->tcp.to_read = 2; upstream->tcp.to_read = 2;
return; return;
} }
if (netreq->query_id_registered == &upstream->netreq_by_query_id) {
netreq->query_id_registered = NULL;
netreq->node.key = NULL;
} else if (netreq->query_id_registered) {
(void) _getdns_rbtree_delete(
netreq->query_id_registered, netreq->node.key);
netreq->query_id_registered = NULL;
netreq->node.key = NULL;
}
DEBUG_STUB("%s %-35s: MSG: %p (read)\n", DEBUG_STUB("%s %-35s: MSG: %p (read)\n",
STUB_DEBUG_READ, __FUNC__, (void*)netreq); STUB_DEBUG_READ, __FUNC__, (void*)netreq);
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED); _getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
@ -1700,7 +1635,9 @@ upstream_write_cb(void *userarg)
__FUNC__, (void*)netreq); __FUNC__, (void*)netreq);
/* Health checks on current connection */ /* Health checks on current connection */
if (upstream->conn_state == GETDNS_CONN_TEARDOWN) if (upstream->conn_state == GETDNS_CONN_TEARDOWN ||
upstream->conn_state == GETDNS_CONN_CLOSED ||
upstream->fd == -1)
q = STUB_CONN_GONE; q = STUB_CONN_GONE;
else if (!upstream_working_ok(upstream)) else if (!upstream_working_ok(upstream))
q = STUB_TCP_ERROR; q = STUB_TCP_ERROR;
@ -1724,10 +1661,8 @@ upstream_write_cb(void *userarg)
/* Could not complete the set up. Need to fallback.*/ /* Could not complete the set up. Need to fallback.*/
DEBUG_STUB("%s %-35s: Upstream: %p ERROR = %d\n", STUB_DEBUG_WRITE, DEBUG_STUB("%s %-35s: Upstream: %p ERROR = %d\n", STUB_DEBUG_WRITE,
__FUNC__, (void*)userarg, q); __FUNC__, (void*)userarg, q);
(void) _getdns_rbtree_delete(&upstream->netreq_by_query_id,
(void *)(intptr_t)GLDNS_ID_WIRE(netreq->query));
upstream_failed(upstream, (q == STUB_TCP_ERROR ? 0:1)); upstream_failed(upstream, (q == STUB_TCP_ERROR ? 0:1));
/* Fall through */ return;
case STUB_CONN_GONE: case STUB_CONN_GONE:
case STUB_NO_AUTH: case STUB_NO_AUTH:
/* Cleaning up after connection or auth check failure. Need to fallback. */ /* Cleaning up after connection or auth check failure. Need to fallback. */
@ -1744,6 +1679,9 @@ upstream_write_cb(void *userarg)
return; return;
default: default:
/* Unqueue the netreq from the write_queue */
remove_from_write_queue(upstream, netreq);
if (netreq->owner->return_call_reporting && if (netreq->owner->return_call_reporting &&
netreq->upstream->tls_obj && netreq->upstream->tls_obj &&
netreq->debug_tls_peer_cert.data == NULL && netreq->debug_tls_peer_cert.data == NULL &&
@ -1756,9 +1694,9 @@ upstream_write_cb(void *userarg)
netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state; netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state;
upstream->queries_sent++; upstream->queries_sent++;
/* Unqueue the netreq from the write_queue */ /* Empty write_queue?, then deschedule upstream write_cb */
if (!(upstream->write_queue = netreq->write_queue_tail)) { if (upstream->write_queue == NULL) {
upstream->write_queue_last = NULL; assert(upstream->write_queue_last == NULL);
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
upstream->event.write_cb = NULL; upstream->event.write_cb = NULL;
/* Reschedule (if already reading) to clear writable */ /* Reschedule (if already reading) to clear writable */
@ -1806,13 +1744,20 @@ upstream_active(getdns_upstream *upstream)
} }
static int static int
upstream_usable(getdns_upstream *upstream) upstream_usable(getdns_upstream *upstream, int backoff_ok)
{ {
/* If backoff_ok is not true then only use upstreams that are in a healthy
state. */
if ((upstream->conn_state == GETDNS_CONN_CLOSED || if ((upstream->conn_state == GETDNS_CONN_CLOSED ||
upstream->conn_state == GETDNS_CONN_SETUP || upstream->conn_state == GETDNS_CONN_SETUP ||
upstream->conn_state == GETDNS_CONN_OPEN) && upstream->conn_state == GETDNS_CONN_OPEN) &&
upstream->keepalive_shutdown == 0) upstream->keepalive_shutdown == 0)
return 1; return 1;
/* Otherwise, allow upstreams that are backed off to be used because that
is better that having no upstream at all. */
if (backoff_ok == 1 &&
upstream->conn_state == GETDNS_CONN_BACKOFF)
return 1;
return 0; return 0;
} }
@ -1828,15 +1773,22 @@ upstream_stats(getdns_upstream *upstream)
{ {
/* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/ /* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/
return (upstream->total_responses - upstream->total_timeouts return (upstream->total_responses - upstream->total_timeouts
- upstream->conn_shutdowns*GETDNS_TRANSPORT_FAIL_MULT); - upstream->conn_shutdowns*GETDNS_TRANSPORT_FAIL_MULT
- upstream->conn_setup_failed);
} }
static int static int
upstream_valid(getdns_upstream *upstream, upstream_valid(getdns_upstream *upstream,
getdns_transport_list_t transport, getdns_transport_list_t transport,
getdns_network_req *netreq) getdns_network_req *netreq,
int backoff_ok)
{ {
if (!(upstream->transport == transport && upstream_usable(upstream))) /* Checking upstreams with backoff_ok true will aslo return upstreams
that are in a backoff state. Otherwise only use upstreams that have
a 'good' connection state. backoff_ok is usefull when no upstreams at all
are valid, for example when the network connection is down and need to
keep trying to connect before failing completely. */
if (!(upstream->transport == transport && upstream_usable(upstream, backoff_ok)))
return 0; return 0;
if (transport == GETDNS_TRANSPORT_TCP) if (transport == GETDNS_TRANSPORT_TCP)
return 1; return 1;
@ -1887,7 +1839,7 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
if (upstreams->upstreams[i].conn_state == GETDNS_CONN_BACKOFF && if (upstreams->upstreams[i].conn_state == GETDNS_CONN_BACKOFF &&
upstreams->upstreams[i].conn_retry_time < now) { upstreams->upstreams[i].conn_retry_time < now) {
upstreams->upstreams[i].conn_state = GETDNS_CONN_CLOSED; upstreams->upstreams[i].conn_state = GETDNS_CONN_CLOSED;
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, _getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_NOTICE,
"%-40s : Re-instating upstream\n", "%-40s : Re-instating upstream\n",
upstreams->upstreams[i].addr_str); upstreams->upstreams[i].addr_str);
} }
@ -1902,14 +1854,13 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
} }
/* OK - Find the next one to use. First check we have at least one valid /* OK - Find the next one to use. First check we have at least one valid
upstream because we completely back off failed upstream (not backed-off) because we completely back off failed
upstreams we may have no valid upstream at all (in contrast to UDP). This upstreams we may have no valid upstream at all (in contrast to UDP).*/
will be better communicated to the user when we have better error codes*/
i = upstreams->current_stateful; i = upstreams->current_stateful;
do { do {
DEBUG_STUB("%s %-35s: Testing upstreams %d %d\n", STUB_DEBUG_SETUP, DEBUG_STUB("%s %-35s: Testing upstreams %d %d\n", STUB_DEBUG_SETUP,
__FUNC__, (int)i, (int)upstreams->upstreams[i].conn_state); __FUNC__, (int)i, (int)upstreams->upstreams[i].conn_state);
if (upstream_valid(&upstreams->upstreams[i], transport, netreq)) { if (upstream_valid(&upstreams->upstreams[i], transport, netreq, 0)) {
upstream = &upstreams->upstreams[i]; upstream = &upstreams->upstreams[i];
break; break;
} }
@ -1917,14 +1868,48 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
if (i >= upstreams->count) if (i >= upstreams->count)
i = 0; i = 0;
} while (i != upstreams->current_stateful); } while (i != upstreams->current_stateful);
if (!upstream) if (!upstream) {
return NULL; /* Oh, oh. We have no valid upstreams. Try to find one that might work so
allow backed off upstreams to be considered valid.
Don't worry about the policy, just use the one with the least bad
stats that still fits the bill (right transport, right authentication)
to try to avoid total failure due to network outages. */
do {
if (upstream_valid(&upstreams->upstreams[i], transport, netreq, 1)) {
upstream = &upstreams->upstreams[i];
break;
}
i++;
if (i >= upstreams->count)
i = 0;
} while (i != upstreams->current_stateful);
if (!upstream) {
/* We _really_ have nothing that authenticates well enough right now...
leave to regular backoff logic. */
return NULL;
}
do {
i++;
if (i >= upstreams->count)
i = 0;
if (upstream_valid(&upstreams->upstreams[i], transport, netreq, 1) &&
upstream_stats(&upstreams->upstreams[i]) > upstream_stats(upstream))
upstream = &upstreams->upstreams[i];
} while (i != upstreams->current_stateful);
upstream->conn_state = GETDNS_CONN_CLOSED;
upstream->conn_backoff_interval = 1;
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_NOTICE,
"%-40s : No valid upstreams... promoting this backed-off upstream for re-try...\n",
upstream->addr_str);
return upstream;
}
/* Now select the specific upstream */ /* Now select the specific upstream */
if (netreq->owner->context->round_robin_upstreams == 0) { if (netreq->owner->context->round_robin_upstreams == 0) {
/* Base the decision on the stats, noting we will have started from 0*/ /* Base the decision on the stats and being not backed-off,
noting we will have started from 0*/
for (i++; i < upstreams->count; i++) { for (i++; i < upstreams->count; i++) {
if (upstream_valid(&upstreams->upstreams[i], transport, netreq) && if (upstream_valid(&upstreams->upstreams[i], transport, netreq, 0) &&
upstream_stats(&upstreams->upstreams[i]) > upstream_stats(upstream)) upstream_stats(&upstreams->upstreams[i]) > upstream_stats(upstream))
upstream = &upstreams->upstreams[i]; upstream = &upstreams->upstreams[i];
} }
@ -2010,18 +1995,14 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
upstream->tls_obj = tls_create_object(dnsreq, fd, upstream); upstream->tls_obj = tls_create_object(dnsreq, fd, upstream);
if (upstream->tls_obj == NULL) { if (upstream->tls_obj == NULL) {
upstream_failed(upstream, 1); upstream_failed(upstream, 1);
#ifdef USE_WINSOCK _getdns_closesocket(fd);
closesocket(fd);
#else
close(fd);
#endif
return -1; return -1;
} }
upstream->tls_hs_state = GETDNS_HS_WRITE; upstream->tls_hs_state = GETDNS_HS_WRITE;
} }
upstream->conn_state = GETDNS_CONN_SETUP; upstream->conn_state = GETDNS_CONN_SETUP;
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, _getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
"%-40s : Conn init : Transport=%s - Profile=%s\n", "%-40s : Conn opened: %s - %s Profile\n",
upstream->addr_str, transport == GETDNS_TRANSPORT_TLS ? "TLS":"TCP", upstream->addr_str, transport == GETDNS_TRANSPORT_TLS ? "TLS":"TCP",
dnsreq->context->tls_auth_min == GETDNS_AUTHENTICATION_NONE ? "Opportunistic":"Strict"); dnsreq->context->tls_auth_min == GETDNS_AUTHENTICATION_NONE ? "Opportunistic":"Strict");
break; break;
@ -2048,12 +2029,17 @@ upstream_find_for_transport(getdns_network_req *netreq,
} }
else { else {
/* For stateful transport we should keep trying until all our transports /* For stateful transport we should keep trying until all our transports
are exhausted/backed-off (no upstream)*/ are exhausted/backed-off (no upstream) and until we have tried each
upstream at least once for this netreq in a total backoff scenario */
size_t i = 0;
do { do {
upstream = upstream_select_stateful(netreq, transport); upstream = upstream_select_stateful(netreq, transport);
if (!upstream) if (!upstream)
return NULL; return NULL;
*fd = upstream_connect(upstream, transport, netreq->owner); *fd = upstream_connect(upstream, transport, netreq->owner);
if (i >= upstream->upstreams->count)
return NULL;
i++;
} while (*fd == -1); } while (*fd == -1);
DEBUG_STUB("%s %-35s: FD: %d Connecting to upstream: %p No: %d\n", DEBUG_STUB("%s %-35s: FD: %d Connecting to upstream: %p No: %d\n",
STUB_DEBUG_SETUP, __FUNC__, *fd, (void*)upstream, STUB_DEBUG_SETUP, __FUNC__, *fd, (void*)upstream,
@ -2078,7 +2064,7 @@ upstream_find_for_netreq(getdns_network_req *netreq)
continue; continue;
if (fd == -1) { if (fd == -1) {
if (_getdns_EMFILE) if (_getdns_socketerror() == _getdns_EMFILE)
return STUB_TRY_AGAIN_LATER; return STUB_TRY_AGAIN_LATER;
return -1; return -1;
} }
@ -2091,7 +2077,7 @@ upstream_find_for_netreq(getdns_network_req *netreq)
} }
/* Handle better, will give generic error*/ /* Handle better, will give generic error*/
DEBUG_STUB("%s %-35s: MSG: %p No valid upstream! \n", STUB_DEBUG_SCHEDULE, __FUNC__, (void*)netreq); DEBUG_STUB("%s %-35s: MSG: %p No valid upstream! \n", STUB_DEBUG_SCHEDULE, __FUNC__, (void*)netreq);
_getdns_context_log(netreq->owner->context, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, _getdns_context_log(netreq->owner->context, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
"*FAILURE* no valid transports or upstreams available!\n"); "*FAILURE* no valid transports or upstreams available!\n");
return -1; return -1;
} }
@ -2120,11 +2106,17 @@ fallback_on_write(getdns_network_req *netreq)
} }
static void static void
upstream_reschedule_events(getdns_upstream *upstream, uint64_t idle_timeout) { upstream_reschedule_events(getdns_upstream *upstream) {
DEBUG_STUB("%s %-35s: FD: %d \n", STUB_DEBUG_SCHEDULE, DEBUG_STUB("%s %-35s: FD: %d \n", STUB_DEBUG_SCHEDULE,
__FUNC__, upstream->fd); __FUNC__, upstream->fd);
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); if (upstream->event.ev)
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
if (upstream->fd == -1 || !( upstream->conn_state == GETDNS_CONN_SETUP
|| upstream->conn_state == GETDNS_CONN_OPEN ))
return;
if (!upstream->write_queue && upstream->event.write_cb) { if (!upstream->write_queue && upstream->event.write_cb) {
upstream->event.write_cb = NULL; upstream->event.write_cb = NULL;
} }
@ -2142,18 +2134,13 @@ upstream_reschedule_events(getdns_upstream *upstream, uint64_t idle_timeout) {
upstream->fd, TIMEOUT_FOREVER, &upstream->event); upstream->fd, TIMEOUT_FOREVER, &upstream->event);
else { else {
DEBUG_STUB("%s %-35s: FD: %d Connection idle - timeout is %d\n", DEBUG_STUB("%s %-35s: FD: %d Connection idle - timeout is %d\n",
STUB_DEBUG_SCHEDULE, __FUNC__, upstream->fd, (int)idle_timeout); STUB_DEBUG_SCHEDULE, __FUNC__, upstream->fd,
/* TODO: Schedule a read also anyway, (int)upstream->keepalive_timeout);
* to digest timed out answers.
* Dont forget to schedule with upstream->fd then! upstream->event.read_cb = upstream_read_cb;
*
* upstream->event.read_cb = upstream_read_cb;
*/
upstream->event.timeout_cb = upstream_idle_timeout_cb; upstream->event.timeout_cb = upstream_idle_timeout_cb;
if (upstream->conn_state != GETDNS_CONN_OPEN) GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
idle_timeout = 0; upstream->keepalive_timeout, &upstream->event);
GETDNS_SCHEDULE_EVENT(upstream->loop, -1,
idle_timeout, &upstream->event);
} }
} }

View File

@ -76,7 +76,7 @@ getdns_sync_data_init(getdns_context *context, getdns_sync_data *data)
# ifdef HAVE_UNBOUND_EVENT_API # ifdef HAVE_UNBOUND_EVENT_API
if (_getdns_ub_loop_enabled(&context->ub_loop)) { if (_getdns_ub_loop_enabled(&context->ub_loop)) {
context->ub_loop.extension = ext; context->ub_loop.extension = ext;
} else } else
# endif # endif
# ifndef USE_WINSOCK # ifndef USE_WINSOCK
return ext->vmt->schedule(ext, ub_fd(context->unbound_ctx), return ext->vmt->schedule(ext, ub_fd(context->unbound_ctx),
@ -85,7 +85,9 @@ getdns_sync_data_init(getdns_context *context, getdns_sync_data *data)
/* No sync full recursion requests on windows without /* No sync full recursion requests on windows without
* UNBOUND_EVENT_API because ub_fd() doesn't work on windows. * UNBOUND_EVENT_API because ub_fd() doesn't work on windows.
*/ */
; /* pass */ # ifdef HAVE_UNBOUND_EVENT_API
{ ; } /* pass */
# endif
# endif # endif
#endif #endif
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
@ -114,30 +116,24 @@ getdns_sync_data_cleanup(getdns_sync_data *data)
upstream = &ctxt->upstreams->upstreams[i]; upstream = &ctxt->upstreams->upstreams[i];
if (upstream->loop != &data->context->sync_eventloop.loop) if (upstream->loop != &data->context->sync_eventloop.loop)
continue; continue;
if (upstream->event.read_cb || upstream->event.write_cb) { GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event); if (upstream->event.timeout_cb &&
( upstream->conn_state != GETDNS_CONN_OPEN
} else if (upstream->event.timeout_cb) { || upstream->keepalive_timeout == 0)) {
/* Timeout's at upstream are idle-timeouts only. (*upstream->event.timeout_cb)(upstream->event.userarg);
* They should be fired on completion of the upstream->event.timeout_cb = NULL;
* synchronous request.
*/
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
if (upstream->conn_state != GETDNS_CONN_OPEN ||
upstream->keepalive_timeout == 0)
(*upstream->event.timeout_cb)(upstream->event.userarg);
} }
upstream->loop = data->context->extension; upstream->loop = data->context->extension;
upstream->is_sync_loop = 0; upstream->is_sync_loop = 0;
if (upstream->event.read_cb || upstream->event.write_cb)
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
TIMEOUT_FOREVER, &upstream->event);
else if (upstream->event.timeout_cb && if ( upstream->event.read_cb || upstream->event.write_cb
upstream->conn_state == GETDNS_CONN_OPEN && || upstream->event.timeout_cb) {
upstream->keepalive_timeout != 0) { GETDNS_SCHEDULE_EVENT(upstream->loop,
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd, ( upstream->event.read_cb
upstream->keepalive_timeout, &upstream->event); || upstream->event.write_cb ? upstream->fd : -1),
( upstream->event.timeout_cb
? upstream->keepalive_timeout : TIMEOUT_FOREVER ),
&upstream->event);
} }
} }
} }

View File

@ -65,7 +65,7 @@
CONTEXT_CREATE(TRUE); CONTEXT_CREATE(TRUE);
ASSERT_RC(getdns_context_set_upstream_recursive_servers(context, NULL), ASSERT_RC(getdns_context_set_upstream_recursive_servers(context, NULL),
GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_context_set_upstream_recursive_servers()"); GETDNS_RETURN_GOOD, "Return code from getdns_context_set_upstream_recursive_servers()");
CONTEXT_DESTROY; CONTEXT_DESTROY;

View File

@ -25,4 +25,4 @@ done
rm -fr "${BUILDDIR}/build" rm -fr "${BUILDDIR}/build"
mkdir "${BUILDDIR}/build" mkdir "${BUILDDIR}/build"
cd "${BUILDDIR}/build" cd "${BUILDDIR}/build"
"${SRCROOT}/configure" $* --prefix "${BUILDDIR}/install" "${SRCROOT}/configure" $* --prefix "${BUILDDIR}/install" --enable-debug-anchor

View File

@ -0,0 +1,15 @@
builddir = @BUILDDIR@
testname = @TPKG_NAME@
LIBTOOL = $(builddir)/libtool
CFLAGS=-I$(builddir)/src
LDLIBS=$(builddir)/src/libgetdns.la
.SUFFIXES: .c .o .a .lo .h
.c.lo:
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $< -o $@
$(testname): $(testname).lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(LDLIBS) $(LDFLAGS) -o $(testname) $(testname).lo

View File

@ -0,0 +1,111 @@
#include <stdio.h>
#include <stdlib.h>
#include <getdns/getdns.h>
#include <getdns/getdns_extra.h>
int main(int ac, char *av[])
{
FILE *f;
char *buf = NULL;
size_t len;
ssize_t bytes_read;
f = fopen(av[1], "r");
if (!f) {
fprintf(stderr, "Could not open %s", av[1]);
exit(EXIT_FAILURE);
}
bytes_read = getdelim(&buf, &len, '\0', f);
fclose(f);
if (bytes_read == -1) {
fprintf(stderr, "Could not read %s", av[1]);
exit(EXIT_FAILURE);
}
buf = realloc(buf, bytes_read + 1);
if (!buf) {
fprintf(stderr, "Could not grow buffer");
exit(EXIT_FAILURE);
}
buf[bytes_read] = '\0';
getdns_dict *dict = NULL;
getdns_list *list = NULL;
getdns_bindata *bindata = NULL;
getdns_return_t r;
if (!(dict = getdns_dict_create())) {
fprintf(stderr, "Could not create dict");
goto fail;
}
r = getdns_yaml2dict(buf, &dict);
if (r) {
fprintf(stderr, "Error setting dict data: %s", getdns_get_errorstr_by_id(r));
goto fail;
}
/*
* Now add a list, bindata and int to the dict by hand to check
* the other yaml2* functions work.
*/
if (!(list = getdns_list_create())) {
fprintf(stderr, "Could not create list");
goto fail;
}
r = getdns_str2list("[\"One\", \"two\", \"three\"]", &list);
if (r) {
fprintf(stderr, "Error setting list data: %s", getdns_get_errorstr_by_id(r));
goto fail;
}
r = getdns_dict_set_list(dict, "List entry", list);
if (r) {
fprintf(stderr, "Error adding list to dict: %s", getdns_get_errorstr_by_id(r));
goto fail;
}
r = getdns_str2bindata("2001:7fd::1", &bindata);
if (r) {
fprintf(stderr, "Error setting bindata: %s", getdns_get_errorstr_by_id(r));
goto fail;
}
r = getdns_dict_set_bindata(dict, "Bindata entry", bindata);
if (r) {
fprintf(stderr, "Error adding list to dict: %s", getdns_get_errorstr_by_id(r));
goto fail;
}
uint32_t intval;
r = getdns_str2int("32767", &intval);
if (r) {
fprintf(stderr, "Error setting int: %s", getdns_get_errorstr_by_id(r));
goto fail;
}
if (intval != 32767) {
fprintf(stderr, "Error reading int: wrong value");
goto fail;
}
char *dict_str = getdns_pretty_print_dict(dict);
if (!dict_str) {
fprintf(stderr, "Could not convert dict to string");
goto fail;
}
printf("%s\n", dict_str);
free(dict_str);
getdns_dict_destroy(dict);
exit(EXIT_SUCCESS);
fail:
if (dict)
getdns_dict_destroy(dict);
if (list)
getdns_list_destroy(list);
exit(EXIT_FAILURE);
}

View File

@ -0,0 +1,16 @@
BaseName: 255-yaml-config
Version: 1.0
Description: Test YAML configuration
CreationDate: Wed 13 Sep 2017 12:42:32 BST
Maintainer: Jim Hague
Category:
Component:
CmdDepends:
Depends: 200-stub-only-compile.tpkg
Help:
Pre: 255-yaml-config.pre
Post:
Test: 255-yaml-config.test
AuxFiles:
Passed:
Failure:

View File

@ -0,0 +1,87 @@
{
"Bindata entry": <bindata of 0x200107fd000000000000000000000001>,
"List entry":
[
<bindata of "One">,
<bindata of "two">,
<bindata of "three">
],
"dnssec_return_status": 1000,
"upstream_recursive_servers":
[
{
"address_data": <bindata for 145.100.185.15>,
"tls_auth_name": <bindata of "dnsovertls.sinodun.com">,
"tls_pubkey_pinset":
[
{
"digest": <bindata of "sha256">,
"value": <bindata of 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4=>
}
]
},
{
"address_data": <bindata for 145.100.185.16>,
"tls_auth_name": <bindata of "dnsovertls1.sinodun.com">,
"tls_pubkey_pinset":
[
{
"digest": <bindata of "sha256">,
"value": <bindata of cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA=>
}
]
},
{
"address_data": <bindata for 185.49.141.37>,
"tls_auth_name": <bindata of "getdnsapi.net">,
"tls_pubkey_pinset":
[
{
"digest": <bindata of "sha256">,
"value": <bindata of foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q=>
}
]
},
{
"address_data": <bindata for 184.105.193.78>,
"tls_auth_name": <bindata of "unicast.censurfridns.dk">
},
{
"address_data": <bindata for 2001:610:1:40ba:145:100:185:15>,
"tls_auth_name": <bindata of "dnsovertls.sinodun.com">,
"tls_pubkey_pinset":
[
{
"digest": <bindata of "sha256">,
"value": <bindata of 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4=>
}
]
},
{
"address_data": <bindata for 2001:610:1:40ba:145:100:185:16>,
"tls_auth_name": <bindata of "dnsovertls1.sinodun.com">,
"tls_pubkey_pinset":
[
{
"digest": <bindata of "sha256">,
"value": <bindata of cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA=>
}
]
},
{
"address_data": <bindata for 2a04:b900:0:100::38>,
"tls_auth_name": <bindata of "getdnsapi.net">,
"tls_pubkey_pinset":
[
{
"digest": <bindata of "sha256">,
"value": <bindata of foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q=>
}
]
},
{
"address_data": <bindata for 2620:ff:c000:0:1:0:64:25>,
"tls_auth_name": <bindata of "unicast.censurfridns.dk">
}
]
}

View File

@ -0,0 +1,47 @@
upstream_recursive_servers:
# IPv4 addresses
# The Surfnet/Sinodun servers
- address_data: 145.100.185.15
tls_auth_name: "dnsovertls.sinodun.com"
tls_pubkey_pinset:
- digest: "sha256"
value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4=
- address_data: 145.100.185.16
tls_auth_name: "dnsovertls1.sinodun.com"
tls_pubkey_pinset:
- digest: "sha256"
value: cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA=
# The getdnsapi.net server
- address_data: 185.49.141.37
tls_auth_name: "getdnsapi.net"
tls_pubkey_pinset:
- digest: "sha256"
value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q=
# The uncensored DNS servers (no SPKI available)
- address_data: 184.105.193.78
tls_auth_name: "unicast.censurfridns.dk"
# IPv6 addresses
# The Surfnet/Sinodun servers
- address_data: 2001:610:1:40ba:145:100:185:15
tls_auth_name: "dnsovertls.sinodun.com"
tls_pubkey_pinset:
- digest: "sha256"
value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4=
- address_data: 2001:610:1:40ba:145:100:185:16
tls_auth_name: "dnsovertls1.sinodun.com"
tls_pubkey_pinset:
- digest: "sha256"
value: cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA=
# The getdnsapi.net server
- address_data: 2a04:b900:0:100::38
tls_auth_name: "getdnsapi.net"
tls_pubkey_pinset:
- digest: "sha256"
value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q=
# The uncensored DNS server (no SPKI available)
- address_data: 2620:ff:c000:0:1::64:25
tls_auth_name: "unicast.censurfridns.dk"
# Require DNSSEC validation. For releases earlier than 1.2 a trust anchor must
# be configured configured manually. This can be done with unbound-anchor.
dnssec_return_status: GETDNS_EXTENSION_TRUE

View File

@ -0,0 +1,14 @@
# #-- 255-yaml-config.test --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
(
grep '^CC=' "${BUILDDIR}/build-stub-only/src/Makefile"
grep '^LDFLAGS=' "${BUILDDIR}/build-stub-only/src/Makefile"
BUILDDIR4SED=`echo "${BUILDDIR}/build-stub-only" | sed 's/\//\\\\\//g'`
sed -e "s/@BUILDDIR@/${BUILDDIR4SED}/g" \
-e "s/@TPKG_NAME@/${TPKG_NAME}/g" "${TPKG_NAME}.Makefile"
) > Makefile

View File

@ -0,0 +1,7 @@
# #-- 255-yaml-config.test --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
make && "./${TPKG_NAME}" 255-yaml-config.input | tee out && diff out "${TPKG_NAME}.good"

View File

@ -6,7 +6,7 @@ Maintainer: Hoda Rohani
Category: Category:
Component: Component:
CmdDepends: CmdDepends:
Depends: 110-link.tpkg Depends: 210-stub-only-link.tpkg
Help: Help:
Pre: Pre:
Post: Post:

View File

@ -4,6 +4,12 @@
# use .tpkg.var.test for in test variable passing # use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test [ -f .tpkg.var.test ] && source .tpkg.var.test
if grep -q '^#define HAVE_SSL_HN_AUTH 1' "${BUILDDIR}/build-stub-only/src/config.h"
then
HAVE_SSL_HN_AUTH=1
else
HAVE_SSL_HN_AUTH=0
fi
SERVER_IP="8.8.8.8" SERVER_IP="8.8.8.8"
SERVER_IPv6="2001:4860:4860::8888" SERVER_IPv6="2001:4860:4860::8888"
@ -126,17 +132,30 @@ for (( ii = 0; ii < 1; ii++)); do
SERVER_IP_TSIG_WRONG_NAME=`echo ${SERVER_IP_TSIG}${TSIG_ALG}":"${TSIG_NAME::${#TSIG_NAME}-1}":"${TSIG_SECRET}` SERVER_IP_TSIG_WRONG_NAME=`echo ${SERVER_IP_TSIG}${TSIG_ALG}":"${TSIG_NAME::${#TSIG_NAME}-1}":"${TSIG_SECRET}`
SERVER_IP_TSIG_WRONG_SECRET=`echo ${SERVER_IP_TSIG}${TSIG_ALG}":"${TSIG_NAME}":"${TSIG_SECRET::${#TSIG_SECRET}-1}` SERVER_IP_TSIG_WRONG_SECRET=`echo ${SERVER_IP_TSIG}${TSIG_ALG}":"${TSIG_NAME}":"${TSIG_SECRET::${#TSIG_SECRET}-1}`
NUM_GOOD_QUERIES=9 if [[ $HAVE_SSL_HN_AUTH = 1 ]]
GOOD_QUERIES=( then
"-s -A getdnsapi.net -l U @${SERVER_IP} +edns_cookies" "U" "-" NUM_GOOD_QUERIES=9
"-s -A getdnsapi.net -l T @${SERVER_IP}" "T" "-" GOOD_QUERIES=(
"-s -A getdnsapi.net -l U @${SERVER_IP_TSIG}${TSIG_ALG}:${TSIG_NAME}:${TSIG_SECRET}" "U" "-" "-s -A getdnsapi.net -l U @${SERVER_IP} +edns_cookies" "U" "-"
"-s -A getdnsapi.net -l U @${SERVER_IP_TSIG}${TSIG_NAME}:${TSIG_SECRET}" "U" "-" "-s -A getdnsapi.net -l T @${SERVER_IP}" "T" "-"
"-s -A getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}" "L" "N" "-s -A getdnsapi.net -l U @${SERVER_IP_TSIG}${TSIG_ALG}:${TSIG_NAME}:${TSIG_SECRET}" "U" "-"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP}" "L" "S" "-s -A getdnsapi.net -l U @${SERVER_IP_TSIG}${TSIG_NAME}:${TSIG_SECRET}" "U" "-"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S" "-s -A getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}" "L" "N"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S" "-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP}" "L" "S"
"-s -G DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D" "U" "-") "-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S"
"-s -G DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D" "U" "-")
else
NUM_GOOD_QUERIES=7
GOOD_QUERIES=(
"-s -A getdnsapi.net -l U @${SERVER_IP} +edns_cookies" "U" "-"
"-s -A getdnsapi.net -l T @${SERVER_IP}" "T" "-"
"-s -A getdnsapi.net -l U @${SERVER_IP_TSIG}${TSIG_ALG}:${TSIG_NAME}:${TSIG_SECRET}" "U" "-"
"-s -A getdnsapi.net -l U @${SERVER_IP_TSIG}${TSIG_NAME}:${TSIG_SECRET}" "U" "-"
"-s -A getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}" "L" "N"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S"
"-s -G DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D" "U" "-")
fi
#"-s -A getdnsapi.net -l L -m @${TLS_SERVER_SS_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_SS_KEY}\"" "L" "S" #"-s -A getdnsapi.net -l L -m @${TLS_SERVER_SS_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_SS_KEY}\"" "L" "S"
NUM_GOOD_FB_QUERIES=6 NUM_GOOD_FB_QUERIES=6
@ -173,21 +192,21 @@ for (( ii = 0; ii < 1; ii++)); do
fi fi
echo "*Success cases:" echo "*Success cases:"
for (( j = 0; j < $NUM_GOOD_QUERIES; j+=1 )); do for (( j = 0; j < $NUM_GOOD_QUERIES; j+=1 )); do
check_good "`"${GETDNS_QUERY}" -V +return_call_reporting $SYNC_MODE ${GOOD_QUERIES[$j*$NUM_ARGS]} `" ${GOOD_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_QUERIES[$((j*NUM_ARGS))+2]} check_good "`"${GETDNS_STUB_QUERY}" -V +return_call_reporting $SYNC_MODE ${GOOD_QUERIES[$j*$NUM_ARGS]} `" ${GOOD_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_QUERIES[$((j*NUM_ARGS))+2]}
echo "getdns_query $SYNC_MODE ${GOOD_QUERIES[$j*$NUM_ARGS]}" echo "getdns_query $SYNC_MODE ${GOOD_QUERIES[$j*$NUM_ARGS]}"
(( COUNT++ )) (( COUNT++ ))
done done
echo "*Success fallback cases:" echo "*Success fallback cases:"
for (( j = 0; j < $NUM_GOOD_FB_QUERIES; j+=1 )); do for (( j = 0; j < $NUM_GOOD_FB_QUERIES; j+=1 )); do
check_good "`"${GETDNS_QUERY}" -V +return_call_reporting $SYNC_MODE ${GOOD_FALLBACK_QUERIES[$j*$NUM_ARGS]} 2>/dev/null`" ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+2]} check_good "`"${GETDNS_STUB_QUERY}" -V +return_call_reporting $SYNC_MODE ${GOOD_FALLBACK_QUERIES[$j*$NUM_ARGS]} 2>/dev/null`" ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+2]}
echo "getdns_query $SYNC_MODE ${GOOD_FALLBACK_QUERIES[$j*$NUM_ARGS]} TESTS: ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+2]}" echo "getdns_query $SYNC_MODE ${GOOD_FALLBACK_QUERIES[$j*$NUM_ARGS]} TESTS: ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+2]}"
(( COUNT++ )) (( COUNT++ ))
done done
echo "*Transport not available cases:" echo "*Transport not available cases:"
for (( j = 0; j < ${#NOT_AVAILABLE_QUERIES[@]}; j+=1 )); do for (( j = 0; j < ${#NOT_AVAILABLE_QUERIES[@]}; j+=1 )); do
check_bad "`"${GETDNS_QUERY}" -V $SYNC_MODE ${NOT_AVAILABLE_QUERIES[${j}]} 2>&1`" check_bad "`"${GETDNS_STUB_QUERY}" -V $SYNC_MODE ${NOT_AVAILABLE_QUERIES[${j}]} 2>&1`"
echo "getdns_query $SYNC_MODE ${NOT_AVAILABLE_QUERIES[${j}]}" echo "getdns_query $SYNC_MODE ${NOT_AVAILABLE_QUERIES[${j}]}"
(( COUNT++ )) (( COUNT++ ))
done done
@ -198,3 +217,8 @@ done
echo echo
echo "Finished transport test: did $COUNT queries, $GOOD_COUNT passes, $FAIL_COUNT failures" echo "Finished transport test: did $COUNT queries, $GOOD_COUNT passes, $FAIL_COUNT failures"
echo echo
if [[ $FAIL_COUNT -gt 0 ]]
then
exit 1
fi

View File

@ -15,6 +15,11 @@ find . -type f -name "Makefile.in" -print0 | xargs -0 rm -f && (
) )
( (
cd "${BUILDDIR}/build-event-loops" cd "${BUILDDIR}/build-event-loops"
if test "`hostname`" != "bonobo"
then
echo Sorry, running dependency test on bonobo only
exit 0
fi
if ! ./config.status --config | grep -q 'enable-all-drafts.*--with-libevent.*--with-libev.*--with-libuv' if ! ./config.status --config | grep -q 'enable-all-drafts.*--with-libevent.*--with-libev.*--with-libuv'
then then
echo Skipping because not covering enough code echo Skipping because not covering enough code

View File

@ -5,10 +5,43 @@
[ -f .tpkg.var.test ] && source .tpkg.var.test [ -f .tpkg.var.test ] && source .tpkg.var.test
cd "${BUILDDIR}/build-event-loops" cd "${BUILDDIR}/build-event-loops"
if make -j 4 test make -j 4 test
if test -e "${BUILDDIR}/build-event-loops/src/test/fails"
then then
if test -e "${BUILDDIR}/build-event-loops/src/test/fails" if test -e "${BUILDDIR}/build-event-loops/src/test/check_getdns.failed"
then then
exit 1 echo ""
echo "********************"
echo "*** check_getdns ***"
echo "********************"
cat "${BUILDDIR}/build-event-loops/src/test/check_getdns.log"
fi fi
if test -e "${BUILDDIR}/build-event-loops/src/test/check_getdns_event.failed"
then
echo ""
echo "**************************"
echo "*** check_getdns_event ***"
echo "**************************"
cat "${BUILDDIR}/build-event-loops/src/test/check_getdns_event.log"
fi
if test -e "${BUILDDIR}/build-event-loops/src/test/check_getdns_ev.failed"
then
echo ""
echo "***********************"
echo "*** check_getdns_ev ***"
echo "***********************"
cat "${BUILDDIR}/build-event-loops/src/test/check_getdns_ev.log"
fi
if test -e "${BUILDDIR}/build-event-loops/src/test/check_getdns_uv.failed"
then
echo ""
echo "***********************"
echo "*** check_getdns_uv ***"
echo "***********************"
cat "${BUILDDIR}/build-event-loops/src/test/check_getdns_uv.log"
fi
exit 1
else
exit 0
fi fi

View File

@ -3,5 +3,5 @@
export SRCDIR=`dirname $0` export SRCDIR=`dirname $0`
( cd $SRCDIR ( cd $SRCDIR
./tpkg clean ./tpkg clean
rm -fr build build-stub-only build-event-loops build-static-analysis install scan-build-reports .tpkg.var.master *.info rm -fr build build-stub-only build-event-loops build-static-analysis install scan-build-reports .tpkg.var.master *.info Makefile
) )

View File

@ -25,4 +25,4 @@ do
done done
lcov $LCOV_MERGE -o run-all.info lcov $LCOV_MERGE -o run-all.info
genhtml run-all.info --output-directory coverage-html genhtml run-all.info --output-directory coverage-html
"${TPKG}" r "${TPKG}" -n -1 r

View File

@ -17,4 +17,4 @@ do
# trap keyboard interrupt (control-c) # trap keyboard interrupt (control-c)
trap control_c 2 trap control_c 2
done done
"${TPKG}" r "${TPKG}" -n -1 r

View File

@ -31,7 +31,7 @@ do
fi fi
done done
echo "${ALL}" >> Makefile echo "${ALL}" >> Makefile
printf '\t"%s" r\n\n' "${TPKG}" >> Makefile printf '\t"%s" -n -1 r\n\n' "${TPKG}" >> Makefile
printf 'clean:\n\t"%s" clean\n\trm -fr build build-stub-only build-event-loops build-static-analysis install scan-build-reports .tpkg.var.master *.info\n\n' "${TPKG}" >> Makefile printf 'clean:\n\t"%s" clean\n\trm -fr build build-stub-only build-event-loops build-static-analysis install scan-build-reports .tpkg.var.master *.info\n\n' "${TPKG}" >> Makefile
for P in ${OTHERS} for P in ${OTHERS}
do do

View File

@ -36,3 +36,4 @@ export TPKG="${TPKG}"
export LIBTOOL="${LIBTOOL}" export LIBTOOL="${LIBTOOL}"
END_OF_TPKG_VAR_MASTER END_OF_TPKG_VAR_MASTER
${TPKG} f 255-yaml-config.tpkg

View File

@ -193,10 +193,13 @@ function usage() {
out " -p PRI\tlog using PRI as priority" out " -p PRI\tlog using PRI as priority"
out " -k\t\tdon't remove test directory when creating/executing a tpkg package" out " -k\t\tdon't remove test directory when creating/executing a tpkg package"
out " -n NUM\tif less than NUM of the tests are passed exit with 1" out " -n NUM\tif less than NUM of the tests are passed exit with 1"
out " \t\tOtherwise exit with 0. When NUM is -1, no tests may fail"
out " \t\tOnly valid when running tpkg report"
out " \t\tOtherwise exit with 0. Only valid when running tpkg report" out " \t\tOtherwise exit with 0. Only valid when running tpkg report"
out " -b DIR\tuse DIR is a base directory in stead of ." out " -b DIR\tuse DIR is a base directory in stead of ."
out " -a ARGS\tpass the string ARGS through to the test scripts" out " -a ARGS\tpass the string ARGS through to the test scripts"
out " -d\t\tUse directories instead of tar.gz for tpkg archive format" out " -d\t\tUse directories instead of tar.gz for tpkg archive format"
out " -f\t\tForce test to be re-run if already executed"
out out
out " (C) NLnetLabs, Miek Gieben. Licensed under the GPL version 2." out " (C) NLnetLabs, Miek Gieben. Licensed under the GPL version 2."
} }
@ -329,11 +332,12 @@ function report() {
if [[ $passed -lt $TPKG_PASS ]]; then if [[ $passed -lt $TPKG_PASS ]]; then
exit 1 exit 1
fi fi
elif [[ $failed -gt 0 ]]; then elif [[ $TPKG_PASS -lt 0 ]]; then
exit 1 if [[ $failed -gt 0 ]]; then
else exit 1
exit 0 fi
fi fi
exit 0
} }
# clone test1 to test2 # clone test1 to test2
@ -858,9 +862,10 @@ echo "--------------- Test Output ------------------" | write_result result.$dsc
pre pre
out "[log] Executing test" out "[log] Executing test"
( ${SHELL} $dsc_test ${TPKG_ARGS} 2>&1 ) > result.$dsc_basename.tmp
( ${SHELL} $dsc_test ${TPKG_ARGS} 2>&1 ) | write_result result.$dsc_basename
test_result=$? test_result=$?
write_result result.$dsc_basename < result.$dsc_basename.tmp
rm -f result.$dsc_basename.tmp
epoch # would like to run after post, but that is not possible :-( epoch # would like to run after post, but that is not possible :-(
if [ $test_result -ne 0 ]; then if [ $test_result -ne 0 ]; then
err "[warning] Test executed with errors: $test_result." err "[warning] Test executed with errors: $test_result."

View File

@ -46,6 +46,10 @@ typedef unsigned short in_port_t;
#include <wincrypt.h> #include <wincrypt.h>
#endif #endif
#ifdef HAVE_GETDNS_YAML2DICT
getdns_return_t getdns_yaml2dict(const char *, getdns_dict **dict);
#endif
#define EXAMPLE_PIN "pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\"" #define EXAMPLE_PIN "pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\""
static int verbosity = 0; static int verbosity = 0;
@ -215,7 +219,8 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t-C\t<filename>\n"); fprintf(out, "\t-C\t<filename>\n");
fprintf(out, "\t\tRead settings from config file <filename>\n"); fprintf(out, "\t\tRead settings from config file <filename>\n");
fprintf(out, "\t\tThe getdns context will be configured with these settings\n"); fprintf(out, "\t\tThe getdns context will be configured with these settings\n");
fprintf(out, "\t\tThe file must be in json dict format.\n"); fprintf(out, "\t\tThe file must be in YAML format (with extension of '.yml')\n");
fprintf(out, "\t\tor JSON dict format (with extension '.conf')\n");
if (i_am_stubby) { if (i_am_stubby) {
fprintf(out, "\t\tBy default, configuration is first read from"); fprintf(out, "\t\tBy default, configuration is first read from");
fprintf(out, "\n\t\t\"/etc/stubby.conf\" and then from \"$HOME/.stubby.conf\"\n"); fprintf(out, "\n\t\t\"/etc/stubby.conf\" and then from \"$HOME/.stubby.conf\"\n");
@ -346,7 +351,7 @@ static getdns_return_t validate_chain(getdns_dict *response)
if ((r = getdns_list_set_dict(to_validate, 0, reply))) if ((r = getdns_list_set_dict(to_validate, 0, reply)))
goto error; goto error;
if (verbosity) printf("reply "PRIsz", dnssec_status: ", i); if (verbosity) printf("reply %d, dnssec_status: ", (int)i);
switch ((s = getdns_validate_dnssec( switch ((s = getdns_validate_dnssec(
to_validate, validation_chain, trust_anchor))) { to_validate, validation_chain, trust_anchor))) {
@ -478,16 +483,25 @@ done:
return r; return r;
} }
static void parse_config(const char *config_str) static void parse_config(const char *config_str, int yaml_config)
{ {
getdns_dict *config_dict; getdns_dict *config_dict;
getdns_list *list; getdns_list *list;
getdns_return_t r; getdns_return_t r;
if ((r = getdns_str2dict(config_str, &config_dict))) if (yaml_config) {
#ifdef USE_YAML_CONFIG
r = getdns_yaml2dict(config_str, &config_dict);
#else
fprintf(stderr, "Support for YAML configuration files not available.\n");
return;
#endif
} else {
r = getdns_str2dict(config_str, &config_dict);
}
if (r)
fprintf(stderr, "Could not parse config file: %s\n", fprintf(stderr, "Could not parse config file: %s\n",
getdns_get_errorstr_by_id(r)); getdns_get_errorstr_by_id(r));
else { else {
if (!(r = getdns_dict_get_list( if (!(r = getdns_dict_get_list(
config_dict, "listen_addresses", &list))) { config_dict, "listen_addresses", &list))) {
@ -535,6 +549,7 @@ int parse_config_file(const char *fn, int report_open_failure)
FILE *fh; FILE *fh;
char *config_file = NULL; char *config_file = NULL;
long config_file_sz; long config_file_sz;
size_t read_sz;
if (!(fh = fopen(fn, "r"))) { if (!(fh = fopen(fn, "r"))) {
if (report_open_failure) if (report_open_failure)
@ -559,15 +574,16 @@ int parse_config_file(const char *fn, int report_open_failure)
return GETDNS_RETURN_MEMORY_ERROR; return GETDNS_RETURN_MEMORY_ERROR;
} }
rewind(fh); rewind(fh);
if (fread(config_file, 1, config_file_sz, fh) != (size_t)config_file_sz) { read_sz = fread(config_file, 1, config_file_sz + 1, fh);
if (read_sz > (size_t)config_file_sz || ferror(fh) || !feof(fh)) {
fprintf( stderr, "An error occurred while reading \"%s\": %s\n" fprintf( stderr, "An error occurred while reading \"%s\": %s\n"
, fn, strerror(errno)); , fn, strerror(errno));
fclose(fh); fclose(fh);
return GETDNS_RETURN_MEMORY_ERROR; return GETDNS_RETURN_MEMORY_ERROR;
} }
config_file[config_file_sz] = 0; config_file[read_sz] = 0;
fclose(fh); fclose(fh);
parse_config(config_file); parse_config(config_file, strstr(fn, ".yml") != NULL);
free(config_file); free(config_file);
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
@ -656,7 +672,7 @@ getdns_return_t parse_args(int argc, char **argv)
} }
continue; continue;
} else if (arg[0] == '{') { } else if (arg[0] == '{') {
parse_config(arg); parse_config(arg, 0);
continue; continue;
} else if (arg[0] != '-') { } else if (arg[0] != '-') {
@ -1071,11 +1087,11 @@ next: ;
/* apply the accumulated pubkey pinset to all upstreams: */ /* apply the accumulated pubkey pinset to all upstreams: */
for (j = 0; j < upstream_count; j++) { for (j = 0; j < upstream_count; j++) {
if (r = getdns_list_get_dict(upstream_list, j, &upstream), r) { if (r = getdns_list_get_dict(upstream_list, j, &upstream), r) {
fprintf(stderr, "Failed to get upstream "PRIsz" when adding pinset\n", j); fprintf(stderr, "Failed to get upstream %d when adding pinset\n", (int)j);
return r; return r;
} }
if (r = getdns_dict_set_list(upstream, "tls_pubkey_pinset", pubkey_pinset), r) { if (r = getdns_dict_set_list(upstream, "tls_pubkey_pinset", pubkey_pinset), r) {
fprintf(stderr, "Failed to set pubkey pinset on upstream "PRIsz"\n", j); fprintf(stderr, "Failed to set pubkey pinset on upstream %d\n", (int)j);
return r; return r;
} }
} }
@ -1269,7 +1285,9 @@ void read_line_cb(void *userarg)
if (listen_count) if (listen_count)
(void) getdns_context_set_listen_addresses( (void) getdns_context_set_listen_addresses(
context, NULL, NULL, NULL); context, NULL, NULL, NULL);
(void) getdns_context_set_idle_timeout(context, 0); if (interactive && !query_file)
(void) getdns_context_set_upstream_recursive_servers(
context, NULL);
return; return;
} }
if (query_file && verbosity) if (query_file && verbosity)
@ -1668,16 +1686,22 @@ static void stubby_log(void *userarg, uint64_t system,
#ifdef GETDNS_ON_WINDOWS #ifdef GETDNS_ON_WINDOWS
time_t tsec; time_t tsec;
if (!verbosity)
return;
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
tsec = (time_t) tv.tv_sec; tsec = (time_t) tv.tv_sec;
gmtime_s(&tm, (const time_t *) &tsec); gmtime_s(&tm, (const time_t *) &tsec);
#else #else
if (!verbosity)
return;
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
gmtime_r(&tv.tv_sec, &tm); gmtime_r(&tv.tv_sec, &tm);
#endif #endif
strftime(buf, 10, "%H:%M:%S", &tm); strftime(buf, 10, "%H:%M:%S", &tm);
(void)userarg; (void)system; (void)level; (void)userarg; (void)system; (void)level;
(void) fprintf(stderr, "[%s.%.6d] STUBBY: ", buf, (int)tv.tv_usec); (void) fprintf(stderr, "[%s.%.6d] UPSTREAM ", buf, (int)tv.tv_usec);
(void) vfprintf(stderr, fmt, ap); (void) vfprintf(stderr, fmt, ap);
} }
@ -1725,16 +1749,16 @@ main(int argc, char **argv)
, "%s/.stubby.conf" , "%s/.stubby.conf"
, getenv("HOME") , getenv("HOME")
); );
(void) parse_config(default_stubby_config); (void) parse_config(default_stubby_config, 0);
(void) parse_config_file("/etc/stubby.conf", 0); (void) parse_config_file("/etc/stubby.conf", 0);
if (n_chars > 0 && n_chars < (int)sizeof(home_stubby_conf_fn)){ if (n_chars > 0 && n_chars < (int)sizeof(home_stubby_conf_fn)){
(void) parse_config_file(home_stubby_conf_fn, 0); (void) parse_config_file(home_stubby_conf_fn, 0);
} }
clear_listen_list_on_arg = 1; clear_listen_list_on_arg = 1;
(void) getdns_context_set_logfunc(context, NULL,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, stubby_log);
} }
(void) getdns_context_set_logfunc(context, NULL,
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, stubby_log);
if ((r = parse_args(argc, argv))) if ((r = parse_args(argc, argv)))
goto done_destroy_context; goto done_destroy_context;
clear_listen_list_on_arg = 0; clear_listen_list_on_arg = 0;

View File

@ -171,7 +171,7 @@ typedef enum network_req_state_enum
/* State for async tcp stub resolving */ /* State for async tcp stub resolving */
typedef struct getdns_tcp_state { typedef struct getdns_tcp_state {
uint8_t *write_buf; const uint8_t *write_buf;
size_t write_buf_len; size_t write_buf_len;
size_t written; size_t written;
@ -188,7 +188,9 @@ typedef struct getdns_tcp_state {
typedef struct getdns_network_req typedef struct getdns_network_req
{ {
/* For storage in upstream->netreq_by_query_id */ /* For storage in upstream->netreq_by_query_id */
_getdns_rbnode_t node; _getdns_rbnode_t node;
/* The netreq_by_query_id tree in which this netreq was registered */
_getdns_rbtree_t *query_id_registered;
#ifdef HAVE_MDNS_SUPPORT #ifdef HAVE_MDNS_SUPPORT
/* /*
* for storage of continuous query context in hash table of cached results. * for storage of continuous query context in hash table of cached results.
@ -300,6 +302,7 @@ typedef struct getdns_dns_req {
unsigned dnssec_return_all_statuses : 1; unsigned dnssec_return_all_statuses : 1;
unsigned dnssec_return_validation_chain : 1; unsigned dnssec_return_validation_chain : 1;
unsigned dnssec_return_full_validation_chain : 1; unsigned dnssec_return_full_validation_chain : 1;
unsigned dnssec_extension_set : 1;
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
unsigned dnssec_roadblock_avoidance : 1; unsigned dnssec_roadblock_avoidance : 1;
unsigned avoid_dnssec_roadblocks : 1; unsigned avoid_dnssec_roadblocks : 1;
@ -324,6 +327,7 @@ typedef struct getdns_dns_req {
* freed is touched by _getdns_submit_netreq only * freed is touched by _getdns_submit_netreq only
*/ */
unsigned validating : 1; unsigned validating : 1;
unsigned waiting_for_ta : 1;
int *freed; int *freed;
/* Validation chain to be canceled when this request is canceled */ /* Validation chain to be canceled when this request is canceled */
@ -365,6 +369,11 @@ typedef struct getdns_dns_req {
*/ */
struct getdns_dns_req *finished_next; struct getdns_dns_req *finished_next;
/* Linked list pointer for dns requests, which need to validate DNSSEC
* and are waiting for the root trust-anchors fetch.
*/
struct getdns_dns_req *ta_notify;
/* network requests for this dns request. /* network requests for this dns request.
* The array is terminated with NULL. * The array is terminated with NULL.
* *

View File

@ -203,7 +203,7 @@ INLINE uint64_t _getdns_get_now_ms()
struct timeval tv; struct timeval tv;
(void) gettimeofday(&tv, NULL); (void) gettimeofday(&tv, NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000; return (uint64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
} }
INLINE uint64_t _getdns_ms_until_expiry(uint64_t expires) INLINE uint64_t _getdns_ms_until_expiry(uint64_t expires)

View File

@ -45,6 +45,8 @@
#define sec_status_insecure _getdns_sec_status_insecure #define sec_status_insecure _getdns_sec_status_insecure
#define sec_status_unchecked _getdns_sec_status_unchecked #define sec_status_unchecked _getdns_sec_status_unchecked
#define sec_status_bogus _getdns_sec_status_bogus #define sec_status_bogus _getdns_sec_status_bogus
#define fake_sha1 _getdns_fake_sha1
#define fake_dsa _getdns_fake_dsa
enum sec_status { sec_status_bogus = 0 enum sec_status { sec_status_bogus = 0
, sec_status_unchecked = 0 , sec_status_unchecked = 0

1
src/yxml Submodule

@ -0,0 +1 @@
Subproject commit 10f968b0e78b9aeee357d0de81a46b445c3fb27b

2
stubby

@ -1 +1 @@
Subproject commit 6114230904d9413514d521358ca7956aac99e822 Subproject commit 0cbd46ea6d0da727c42b0890d498366cd2b1ec2c