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
url = https://github.com/getdnsapi/jsmn.git
branch = getdns
[submodule "src/yxml"]
path = src/yxml
url = git://g.blicky.net/yxml.git
[submodule "stubby"]
path = stubby
url = https://github.com/getdnsapi/stubby.git

View File

@ -8,9 +8,11 @@ addons:
packages:
- libunbound-dev
- libidn11-dev
- libyaml-dev
- check
- libevent-dev
- libev-dev
- libuv-dev
- valgrind
- clang
- 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
* Small bugfixes that came out of static analysis
* 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
cd doc && $(MAKE) install
@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 "*** 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 "***"
@echo "*** We recomend using unbound-anchor to retrieve and install"
@echo "*** the root trust anchor like this: "
@echo "*** mkdir -p `dirname @TRUST_ANCHOR_FILE@`"
@echo "*** unbound-anchor -a \"@TRUST_ANCHOR_FILE@\""
@echo "*** - will be preferred and used for DNSSEC validation, however"
@echo "*** getdns will fallback to trust-anchors obtained via built-in"
@echo "*** trust anchor management when the anchors from the default"
@echo "*** location fail to validate the root DNSKEY rrset."
@echo "***"
@echo "*** We strongly recommend package maintainers to provide the"
@echo "*** root trust anchor by installing it with unbound-anchor"
@echo "*** at package installation time from the post-install script."
@echo "*** To prevent expired DNSSEC trust anchors to be used for"
@echo "*** validation, we strongly recommend removing the trust anchors"
@echo "*** on the default location when there is no active external"
@echo "*** trust anchor management keeping it up-to-date."
@echo "***"
uninstall: @UNINSTALL_GETDNS_QUERY@
@ -198,11 +203,13 @@ $(distdir):
mkdir -p $(distdir)/src/gldns
mkdir -p $(distdir)/src/tools
mkdir -p $(distdir)/src/jsmn
mkdir -p $(distdir)/src/yxml
mkdir -p $(distdir)/doc
mkdir -p $(distdir)/spec
mkdir -p $(distdir)/spec/example
mkdir -p $(distdir)/stubby
mkdir -p $(distdir)/stubby/src
mkdir -p $(distdir)/stubby/src/yaml
cp $(srcdir)/configure.ac $(distdir)
cp $(srcdir)/configure $(distdir)
cp $(srcdir)/AUTHORS $(distdir)
@ -245,14 +252,18 @@ $(distdir):
cp $(srcdir)/spec/example/*.[ch] $(distdir)/spec/example
cp $(srcdir)/src/tools/Makefile.in $(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/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/README.md $(distdir)/stubby
cp $(srcdir)/src/jsmn/*.[ch] $(distdir)/src/jsmn
cp $(srcdir)/src/jsmn/LICENSE $(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
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
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
* 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 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.
## 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
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
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)
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
[`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:
##$ Zero configuration DNSSEC
# mkdir -p /etc/unbound
# unbound-anchor -a /etc/unbound/getdns-root.key
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 .
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
=======
@ -206,7 +207,7 @@ The primary platforms targeted are Linux and FreeBSD, other platform are support
* RHEL/CentOS 6.4
* OSX 10.8
* Ubuntu 14.04
* Ubuntu 16.04
* Microsoft Windows 8.1
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.
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

View File

@ -36,12 +36,12 @@ sinclude(./m4/acx_getaddrinfo.m4)
sinclude(./m4/ax_check_compile_flag.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!!!
# 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
AC_ARG_WITH([current-date],
@ -51,7 +51,7 @@ AC_ARG_WITH([current-date],
[CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"])
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_NUMERIC_VERSION, [0x07df0c00])
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.1.0 had libversion 6:0:0
# getdns-1.1.1 had libversion 6:1:0
# getdns-1.1.2 has libversion 7:0:1
# getdns-1.1.3 will have libversion 7:1:1
# getdns-1.1.2 had libversion 7:0: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_LIBVERSION)
@ -100,7 +102,18 @@ AC_PROG_CC
AC_PROG_CPP
# Checks for programs.
HOSTOS="unix"
AC_CANONICAL_HOST
case "${host_os}" in
cygwin*|mingw*)
HOSTOS=windows
;;
darwin*)
HOSTOS=macos
;;
esac
AC_SUBST(HOSTOS)
CFLAGS="$CFLAGS"
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-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(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
yes)
enable_debug_req=yes
@ -171,6 +185,7 @@ case "$enable_all_debugging" in
enable_debug_daemon=yes
enable_debug_sec=yes
enable_debug_server=yes
enable_debug_anchor=yes
;;
no|*)
;;
@ -217,6 +232,13 @@ case "$enable_debug_server" in
no|*)
;;
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
@ -232,7 +254,7 @@ esac
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)]))
case "$enable_poll_eventloop" in
no)
@ -280,11 +302,66 @@ case "$enable_native_stub_dnssec" in
;;
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
# find libidn (no libidn on windows though)
AC_CHECK_HEADERS([windows.h winsock.h stdio.h winsock2.h ws2tcpip.h],,, [AC_INCLUDES_DEFAULT])
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"
# openssl
if test $USE_NSS = "no"; then
@ -512,7 +589,7 @@ case "$enable_ed25519" in
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_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.])
use_ed25519="yes"
@ -577,6 +654,22 @@ case "$enable_stub_only" in
;;
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
AC_MSG_NOTICE([ Building on Windows ... YES! ])
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"
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
AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname],
@ -691,11 +808,6 @@ then
])
fi
if test $found_all_libs = 0
then
AC_MSG_ERROR([Missing dependencies: $MISSING_DEPS])
fi
AC_PATH_PROG([DOXYGEN], [doxygen])
if test -z "$DOXYGEN";
then AC_MSG_WARN([doxygen not found, continuing without])
@ -1010,6 +1122,7 @@ AC_SUBST(GETDNS_QUERY)
AC_SUBST(INSTALL_GETDNS_QUERY)
AC_SUBST(UNINSTALL_GETDNS_QUERY)
stubby_with_yaml=0
AC_ARG_WITH(stubby, AS_HELP_STRING([--with-stubby],
[Compile and install stubby, the (stub) resolver daemon]),
[], [withval="no"])
@ -1017,39 +1130,89 @@ if test x_$withval = x_yes; then
STUBBY="stubby"
INSTALL_STUBBY="install-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
STUBBY=""
INSTALL_STUBBY=""
UNINSTALL_STUBBY=""
STUBBY_XTRA_OBJS=""
fi
AC_SUBST(STUBBY)
AC_SUBST(INSTALL_STUBBY)
AC_SUBST(UNINSTALL_STUBBY)
AC_SUBST(STUBBY_XTRA_OBJS)
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
STUBBY_LIBS=""
STUBBY_LDFLAGS=""
if test $my_with_yaml = 1
then
if test $stubby_with_yaml = 1
then
getdns_LIBS="$LIBS"
getdns_LDFLAGS="$LDFLAGS"
LIBS="$initial_LIBS"
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])
if [ test -n "$DOXYGEN" ]
then AC_CONFIG_FILES([src/Doxyfile])
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_LANG_PUSH(C)
AC_COMPILE_IFELSE(
@ -1064,7 +1227,7 @@ dnl ----- Start of "Things needed for gldns" section
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 result in HAVE_ATTR_FORMAT.
@ -1107,11 +1270,12 @@ fi
# system implementation.
PKG_CHECK_MODULES([LIBBSD],[libbsd-overlay],[
LIBS="$LIBS $LIBBSD_LIBS"
STUBBY_LIBS="$STUBBY_LIBS $LIBBSD_LIBS"
CFLAGS="$CFLAGS $LIBBSD_CFLAGS"
],[
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_ntop)
AC_REPLACE_FUNCS(strlcpy)
@ -1187,14 +1351,45 @@ AH_BOTTOM([
# ifndef FD_SETSIZE
# define FD_SETSIZE 1024
# 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 */
# ifndef strdup
# define strdup _strdup
# endif
#else
# define PRIsz "%zu"
# define PRIsz "zu"
#endif
#include <stdint.h>
@ -1203,34 +1398,6 @@ AH_BOTTOM([
#include <assert.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
extern "C" {
#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);
#endif /* COMPAT_SHA512 */
#ifndef HAVE_INET_PTON
#ifndef HAVE_DECL_INET_PTON
int inet_pton(int af, const char* src, void* dst);
#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);
#endif
#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)
{ 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
#ifdef __cplusplus
@ -1315,6 +1485,10 @@ static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *fo
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
@ -1331,6 +1505,20 @@ static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *fo
#include <inttypes.h>
#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
#define PRIu64 "llu"
#endif
@ -1363,6 +1551,29 @@ static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *fo
# 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
# include <unbound.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
#ifdef __cplusplus
}
#endif
])
dnl ---------------------------------------------------------------------------

View File

@ -55,11 +55,13 @@ stubbysrcdir = $(srcdir)/../stubby
LIBTOOL = ../libtool
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@
WNOERRORFLAG=@WNOERRORFLAG@
LDFLAGS=@LDFLAGS@ @LIBS@
STUBBY_LDFLAGS=@STUBBY_LDFLAGS@ @STUBBY_LIBS@
EXTENSION_LIBEVENT_LIB=@EXTENSION_LIBEVENT_LIB@
EXTENSION_LIBEVENT_EXT_LIBS=@EXTENSION_LIBEVENT_EXT_LIBS@
EXTENSION_LIBEVENT_LDFLAGS=@EXTENSION_LIBEVENT_LDFLAGS@
@ -75,7 +77,7 @@ C99COMPATFLAGS=@C99COMPATFLAGS@
DEFAULT_EVENTLOOP_OBJ=@DEFAULT_EVENTLOOP@.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 \
mdns.lo
@ -91,10 +93,15 @@ COMPAT_OBJ=$(LIBOBJS:.o=.lo)
UTIL_OBJ=rbtree.lo val_secalgo.lo lruhash.lo lookup3.lo locks.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
NON_C99_OBJS=context.lo libuv.lo
NON_C99_OBJS=libuv.lo context.lo anchor.lo
.SUFFIXES: .c .o .a .lo .h
@ -123,9 +130,18 @@ $(UTIL_OBJ):
$(JSMN_OBJ):
$(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):
$(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:
$(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:
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)
$(LIBTOOL) --mode=install cp libgetdns.la $(DESTDIR)$(libdir)
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
$(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 $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ)
$(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
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)
$(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
test: default
cd test && $(MAKE) $@
@ -185,17 +200,29 @@ getdns_query: default
stubby.lo: $(stubbysrcdir)/src/stubby.c
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -DSTUBBYCONFDIR=\"$(sysconfdir)/stubby\" -DRUNSTATEDIR=\"$(runstatedir)\" -c $< -o $@
stubby: stubby.lo libgetdns.la
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ stubby.lo $(LDFLAGS) libgetdns.la
stubby: stubby.lo libgetdns.la $(STUBBY_XTRA_OBJS)
$(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) -m 755 -d $(DESTDIR)$(bindir)
$(LIBTOOL) --mode=install cp stubby $(DESTDIR)$(bindir)
install-stubby-files-unix: $(stubbysrcdir)/stubby.yml.example
$(INSTALL) -m 755 -d $(DESTDIR)$(stubbyconfdir)
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 $(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)
test -f $(DESTDIR)$(stubbyconfdir)/stubby.conf || \
$(INSTALL_DATA) $(stubbysrcdir)/stubby.conf.example $(DESTDIR)$(stubbyconfdir)/stubby.conf
test -f $(DESTDIR)$(stubbyconfdir)/stubby.yml || \
$(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:
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/stubby
@ -226,14 +253,17 @@ Makefile: $(srcdir)/Makefile.in ../config.status
depend:
(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" \
-e 's? gldns/? $$(srcdir)/gldns/?g' \
-e 's? compat/? $$(srcdir)/compat/?g' \
-e 's? util/auxiliary/util/? $$(srcdir)/util/auxiliary/util/?g' \
-e 's? util/? $$(srcdir)/util/?g' \
-e 's? jsmn/? $$(srcdir)/jsmn/?g' \
-e 's? yxml/? $$(srcdir)/yxml/?g' \
-e 's? extension/? $$(srcdir)/extension/?g' \
-e 's? \.\./stubby/? $$(stubbysrcdir)/?g' \
-e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
-e 's? \$$(srcdir)/config\.h? config.h?g' \
-e 's? \$$(srcdir)/getdns/getdns_extra\.h? getdns/getdns_extra.h?g' \
@ -251,22 +281,36 @@ depend:
FORCE:
# 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 \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/const-info.h
context.lo context.o: $(srcdir)/context.c \
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_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)/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)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h \
$(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/dnssec.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
convert.lo convert.o: $(srcdir)/convert.c \
config.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)/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)/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)/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 \
config.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)/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)/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
dnssec.lo dnssec.o: $(srcdir)/dnssec.c \
config.h \
@ -301,10 +345,10 @@ dnssec.lo dnssec.o: $(srcdir)/dnssec.c \
$(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)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h \
$(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/util/val_secalgo.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)/dnssec.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.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
general.lo general.o: $(srcdir)/general.c \
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)/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/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h \
$(srcdir)/mdns.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)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \
$(srcdir)/dict.h $(srcdir)/mdns.h $(srcdir)/platform.h
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \
getdns/getdns.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)/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)/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 \
config.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)/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)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/mdns.h \
$(srcdir)/util/auxiliary/util/fptr_wlist.h $(srcdir)/util/lookup3.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)/general.h $(srcdir)/gldns/rrdef.h $(srcdir)/util-internal.h \
$(srcdir)/platform.h $(srcdir)/mdns.h $(srcdir)/util/auxiliary/util/fptr_wlist.h $(srcdir)/util/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 \
config.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)/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)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.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
request-internal.lo request-internal.o: $(srcdir)/request-internal.c \
config.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)/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)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h \
$(srcdir)/convert.h $(srcdir)/general.h
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/dict.h $(srcdir)/convert.h $(srcdir)/general.h
rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \
config.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)/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)/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 \
config.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)/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)/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 \
config.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)/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)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/anchor.h \
$(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
sync.lo sync.o: $(srcdir)/sync.c \
getdns/getdns.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)/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)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.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/wire2str.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)/general.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \
config.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)/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)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/dnssec.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)/gldns/rrdef.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h
gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c \
config.h \
$(srcdir)/gldns/gbuffer.h
@ -479,6 +527,8 @@ sha512.lo sha512.o: $(srcdir)/compat/sha512.c \
config.h
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c \
config.h
strptime.lo strptime.o: $(srcdir)/compat/strptime.c \
config.h
locks.lo locks.o: $(srcdir)/util/locks.c \
config.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)/util/auxiliary/sldns/sbuffer.h $(srcdir)/gldns/gbuffer.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 \
config.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
poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \
config.h \
$(srcdir)/extension/poll_eventloop.h \
$(srcdir)/util-internal.h $(srcdir)/context.h \
getdns/getdns.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 \
config.h \
$(srcdir)/extension/select_eventloop.h \
$(srcdir)/debug.h $(srcdir)/types-internal.h \
getdns/getdns.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 },
{ 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 },
{ 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 },
{ 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_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_ERROR", 703 },
{ "GETDNS_CALLBACK_TIMEOUT", 702 },
{ "GETDNS_CONTEXT_CODE_APPDATA_DIR", 628 },
{ "GETDNS_CONTEXT_CODE_APPEND_NAME", 607 },
{ "GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW", 614 },
{ "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_CONNECTION_RETRIES", 624 },
{ "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_DNSSEC_BOGUS", 401 },
{ "GETDNS_DNSSEC_INDETERMINATE", 402 },

View File

@ -35,11 +35,13 @@
*/
#include "config.h"
#include "anchor.h"
#ifndef USE_WINSOCK
#include <arpa/inet.h>
#include <sys/time.h>
#include <netdb.h>
#include <pwd.h>
#else
#include <winsock2.h>
#include <iphlpapi.h>
@ -52,6 +54,7 @@ typedef unsigned short in_port_t;
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#include <shlobj.h>
#endif
#include <sys/stat.h>
@ -68,7 +71,6 @@ typedef unsigned short in_port_t;
#endif
#include <stdbool.h>
#include "config.h"
#ifdef HAVE_LIBUNBOUND
#include <unbound.h>
#endif
@ -78,6 +80,7 @@ typedef unsigned short in_port_t;
#include "context.h"
#include "types-internal.h"
#include "util-internal.h"
#include "platform.h"
#include "dnssec.h"
#include "stub.h"
#include "list.h"
@ -702,11 +705,7 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
}
if (upstream->fd != -1)
{
#ifdef USE_WINSOCK
closesocket(upstream->fd);
#else
close(upstream->fd);
#endif
_getdns_closesocket(upstream->fd);
}
while (pin) {
sha256_pin_t *nextpin = pin->next;
@ -734,65 +733,65 @@ void _getdns_upstream_log(getdns_upstream *upstream, uint64_t system,
va_end(args);
}
void
_getdns_upstream_shutdown(getdns_upstream *upstream)
{
/*Set condition to tear down asap to stop any further scheduling*/
upstream->conn_state = GETDNS_CONN_TEARDOWN;
/* 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 : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\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_DEBUG,
"%-40s : Upstream stats: Transport=%s - Resp=%d,Timeouts=%d,Best_auth=%s\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_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
upstream_backoff(getdns_upstream *upstream) {
upstream->conn_state = GETDNS_CONN_BACKOFF;
/* Increase the backoff interval incrementally up to the tls_backoff_time*/
if (upstream->conn_backoff_interval < upstream->upstreams->tls_backoff_time) {
if (upstream->conn_backoff_interval < (UINT16_MAX-1)/2)
upstream->conn_backoff_interval *= 2;
else
upstream->conn_backoff_interval = upstream->upstreams->tls_backoff_time;
}
if (upstream->conn_backoff_interval < upstream->upstreams->tls_backoff_time)
upstream->conn_retry_time = time(NULL) + upstream->conn_backoff_interval;
else
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_NOTICE,
"%-40s : !Backing off this upstream - Will retry again in %ds at %s",
upstream->addr_str,
upstream->conn_backoff_interval,
asctime(gmtime(&upstream->conn_retry_time)));
}
static void
_getdns_upstream_reset(getdns_upstream *upstream)
{
/* Back off connections that never got up service at all (probably no
TCP service or incompatible TLS version/cipher).
Leave choice between working upstreams to the stub.
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.*/
uint16_t conn_retries = upstream->upstreams->tls_connection_retries;
/* [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
|| ((int)upstream->conn_shutdowns >= conn_retries*GETDNS_TRANSPORT_FAIL_MULT
&& upstream->total_responses == 0)
|| (upstream->conn_completed >= conn_retries &&
upstream->total_responses == 0 &&
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,
"%-40s : !Backing off this upstream - Will retry as new upstream at %s",
upstream->addr_str,
asctime(gmtime(&upstream->conn_retry_time)));
upstream_backoff(upstream);
}
/* 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
upstream->queries_sent = 0;
upstream->responses_received = 0;
@ -802,17 +801,17 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
/* Now TLS stuff*/
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) {
SSL_shutdown(upstream->tls_obj);
SSL_free(upstream->tls_obj);
upstream->tls_obj = NULL;
}
if (upstream->fd != -1) {
#ifdef USE_WINSOCK
closesocket(upstream->fd);
#else
close(upstream->fd);
#endif
_getdns_closesocket(upstream->fd);
upstream->fd = -1;
}
/* Set connection ready for use again*/
@ -820,6 +819,39 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
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
tls_is_in_transports_list(getdns_context *context)
{
@ -944,6 +976,7 @@ upstream_init(getdns_upstream *upstream,
upstream->conn_shutdowns = 0;
upstream->conn_setup_failed = 0;
upstream->conn_retry_time = 0;
upstream->conn_backoff_interval = 1;
upstream->conn_backoffs = 0;
upstream->total_responses = 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);
}
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
*
@ -1428,6 +1492,20 @@ getdns_context_create_with_extended_memory_functions(
result->suffixes = 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
, sizeof(result->trust_anchors_spc));
@ -1445,12 +1523,16 @@ getdns_context_create_with_extended_memory_functions(
, result->trust_anchors
, result->trust_anchors_len);
if (!_getdns_parse_ta_file(NULL, &gbuf)) {
GETDNS_FREE(result->mf, result->trust_anchors);
result->trust_anchors = NULL;
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_source = GETDNS_TASRC_ZONE;
}
result->upstreams = NULL;
@ -1484,6 +1566,9 @@ getdns_context_create_with_extended_memory_functions(
result->return_call_reporting = 0;
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
*/
result->fchg_resolvconf = NULL;
@ -1520,7 +1605,15 @@ getdns_context_create_with_extended_memory_functions(
#endif
/* Only initialise SSL once and ideally in a thread-safe manner */
if (ssl_init == false) {
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
OpenSSL_add_all_algorithms();
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;
}
#ifdef HAVE_PTHREAD
@ -1528,7 +1621,6 @@ getdns_context_create_with_extended_memory_functions(
#else
/* XXX implement Windows-style unlock here */
#endif
#ifdef HAVE_LIBUNBOUND
result->unbound_ctx = NULL;
if ((r = rebuild_ub_ctx(result)))
@ -1603,6 +1695,10 @@ getdns_context_destroy(struct getdns_context *context)
return;
context->destroying = 1;
if (context->sys_ctxt)
getdns_context_destroy(context->sys_ctxt);
/* cancel all outstanding requests */
cancel_outstanding_requests(context);
@ -1665,10 +1761,20 @@ getdns_context_destroy(struct getdns_context *context)
_getdns_traverse_postorder(&context->local_hosts,
destroy_local_host, context);
getdns_dict_destroy(context->header);
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
WSACleanup();
#endif
@ -2442,15 +2548,15 @@ getdns_context_set_dns_root_servers(
if (addr_bd->size == 16 &&
inet_ntop(AF_INET6, addr_bd->data, dst, sizeof(dst)))
fprintf(fh,". NS "PRIsz".root-servers.getdnsapi.net.\n"
PRIsz".root-servers.getdnsapi.net. AAAA %s\n",
fprintf(fh,". NS %"PRIsz".root-servers.getdnsapi.net.\n"
"%"PRIsz".root-servers.getdnsapi.net. AAAA %s\n",
i, i, dst);
else if (addr_bd->size == 4 &&
inet_ntop(AF_INET, addr_bd->data, dst, sizeof(dst)))
fprintf(fh,". NS "PRIsz".root-servers.getdnsapi.net.\n"
PRIsz".root-servers.getdnsapi.net. A %s\n",
fprintf(fh,". NS %"PRIsz".root-servers.getdnsapi.net.\n"
"%"PRIsz".root-servers.getdnsapi.net. A %s\n",
i, i, dst);
}
fclose(fh);
@ -2615,9 +2721,11 @@ getdns_context_set_dnssec_trust_anchors(
context->trust_anchors = _getdns_list2wire(value,
context->trust_anchors_spc, &context->trust_anchors_len,
&context->mf);
context->trust_anchors_source = GETDNS_TASRC_APP;
} else {
context->trust_anchors = NULL;
context->trust_anchors_len = 0;
context->trust_anchors_source = GETDNS_TASRC_NONE;
}
dispatch_updated(context, GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS);
return GETDNS_RETURN_GOOD;
@ -2666,11 +2774,14 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
struct addrinfo hints;
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 (count == 0 || r != GETDNS_RETURN_GOOD) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
if ( !upstream_list
|| (r = getdns_list_get_length(upstream_list, &count))
|| 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));
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_context_prepare_for_resolution(struct getdns_context *context,
int usenamespaces)
_getdns_context_prepare_for_resolution(getdns_context *context)
{
size_t i;
getdns_return_t r;
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
if (context->destroying) {
return GETDNS_RETURN_BAD_CONTEXT;
}
if (context->destroying)
return GETDNS_RETURN_BAD_CONTEXT;
/* Transport can in theory be set per query in stub mode */
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);
if (r == GETDNS_RETURN_GOOD)
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;
r = _getdns_ns_dns_setup(context);
if (r == GETDNS_RETURN_GOOD)
context->resolution_type_set = context->resolution_type;
return r;
} /* _getdns_context_prepare_for_resolution */
char *
_getdns_strdup(const struct mem_funcs *mfs, const char *s)
{
size_t sz = strlen(s) + 1;
char *r = GETDNS_XMALLOC(*mfs, char, sz);
if (r)
return memcpy(r, s, sz);
else
size_t sz;
char *r;
if (!s || !(r = GETDNS_XMALLOC(*mfs, char, (sz = strlen(s) + 1))))
return NULL;
else
return memcpy(r, s, sz);
}
struct getdns_bindata *
@ -3659,12 +3748,15 @@ getdns_context_get_eventloop(getdns_context *context, getdns_eventloop **loop)
return GETDNS_RETURN_GOOD;
}
static size_t _getdns_get_appdata(getdns_context *context, char *path);
static getdns_dict*
_get_context_settings(getdns_context* context)
{
getdns_dict *result = getdns_dict_create_with_context(context);
getdns_list *list;
size_t i;
const char *str_value;
char appdata_dir[_GETDNS_PATH_MAX] = "";
if (!result)
return NULL;
@ -3685,6 +3777,8 @@ _get_context_settings(getdns_context* context)
|| ( context->edns_maximum_udp_payload_size != -1
&& getdns_dict_set_int(result, "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",
context->edns_extended_rcode)
|| 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",
context->tls_backoff_time)
|| 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;
/* list fields */
@ -3719,6 +3818,14 @@ _get_context_settings(getdns_context* context)
getdns_list_destroy(list);
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) {
/* create a namespace list */
if (!(list = getdns_list_create_with_context(context)))
@ -3754,6 +3861,15 @@ _get_context_settings(getdns_context* context)
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;
error:
getdns_dict_destroy(result);
@ -3771,9 +3887,24 @@ getdns_context_get_api_information(getdns_context* context)
&& ! getdns_dict_util_set_string(
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(
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(
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; \
}
#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
_getdns_context_config_setting(getdns_context *context,
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];
size_t count, i;
uint32_t n;
getdns_bindata *bd;
int destroy_list = 0;
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_connection_retries)
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 ****/
/**** ****/
/************************************/
} else if (!_streq(setting, "implementation_string") &&
!_streq(setting, "version_string")) {
} else if (!_streq(setting, "implementation_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;
}
return r;
@ -4505,4 +4653,360 @@ getdns_context_config(getdns_context *context, const getdns_dict *config_dict)
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 */

View File

@ -48,6 +48,8 @@
#ifdef HAVE_MDNS_SUPPORT
#include "util/lruhash.h"
#endif
#include "rr-iter.h"
#include "anchor.h"
struct getdns_dns_req;
struct ub_ctx;
@ -92,6 +94,16 @@ typedef enum getdns_conn_state {
GETDNS_CONN_BACKOFF
} 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 {
GETDNS_NO_TSIG = 0, /* Do not use tsig */
GETDNS_HMAC_MD5 = 1, /* 128 bits */
@ -103,6 +115,7 @@ typedef enum getdns_tsig_algo {
GETDNS_HMAC_SHA512 = 7
} getdns_tsig_algo;
typedef struct getdns_tsig_info {
getdns_tsig_algo alg;
const char *name;
@ -170,6 +183,7 @@ typedef struct getdns_upstream {
size_t conn_shutdowns;
size_t conn_setup_failed;
time_t conn_retry_time;
uint16_t conn_backoff_interval;
size_t conn_backoffs;
size_t total_responses;
size_t total_timeouts;
@ -255,6 +269,44 @@ typedef struct getdns_upstreams {
getdns_upstream 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 {
/* Context values */
getdns_resolution_t resolution_type;
@ -276,8 +328,24 @@ struct getdns_context {
const uint8_t *suffixes;
/* Length of all suffixes in the suffix buffer */
size_t suffixes_len;
uint8_t *trust_anchors;
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;
uint16_t limit_outstanding_queries;
uint32_t dnssec_allowed_skew;
@ -372,6 +440,18 @@ struct getdns_context {
unsigned return_call_reporting : 1;
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
*/
@ -415,11 +495,9 @@ void _getdns_context_log(getdns_context *context, uint64_t system,
* Sets up the unbound contexts with stub or recursive behavior
* if needed.
* @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
*/
getdns_return_t _getdns_context_prepare_for_resolution(struct getdns_context *context,
int usenamespaces);
getdns_return_t _getdns_context_prepare_for_resolution(getdns_context *context);
/* Register a getdns_dns_req with context.
* - Without pluggable unbound event API,
@ -470,4 +548,13 @@ void _getdns_upstreams_dereference(getdns_upstreams *upstreams);
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_ */

View File

@ -32,10 +32,10 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include "config.h"
#ifndef USE_WINSOCK
#include <arpa/inet.h>
#endif
@ -54,6 +54,7 @@
#include "dict.h"
#include "list.h"
#include "jsmn/jsmn.h"
#include "yaml/convert_yaml_to_json.h"
#include "convert.h"
#include "debug.h"
@ -1802,3 +1803,101 @@ getdns_str2int(const char *str, uint32_t *value)
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
#define DEBUG_ON(...) do { \
struct timeval tv; \
struct tm tm; \
char buf[10]; \
time_t tsec; \
struct timeval tv_dEbUgSyM; \
struct tm tm_dEbUgSyM; \
char buf_dEbUgSyM[10]; \
time_t tsec_dEbUgSyM; \
\
gettimeofday(&tv, NULL); \
tsec = (time_t) tv.tv_sec; \
gmtime_s(&tm, (const time_t *) &tsec); \
strftime(buf, 10, "%H:%M:%S", &tm); \
fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \
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__); \
} 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__); \
} while (0)
#else
#define DEBUG_ON(...) do { \
struct timeval tv; \
struct tm tm; \
char buf[10]; \
struct timeval tv_dEbUgSyM; \
struct tm tm_dEbUgSyM; \
char buf_dEbUgSyM[10]; \
\
gettimeofday(&tv, NULL); \
gmtime_r(&tv.tv_sec, &tm); \
strftime(buf, 10, "%H:%M:%S", &tm); \
fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \
gettimeofday(&tv_dEbUgSyM, NULL); \
gmtime_r(&tv_dEbUgSyM.tv_sec, &tm_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__); \
} while (0)
#endif
#define DEBUG_NL(...) do { \
struct timeval tv; \
struct tm tm; \
char buf[10]; \
#define DEBUG_NL(...) do { \
struct timeval tv_dEbUgSyM; \
struct tm tm_dEbUgSyM; \
char buf_dEbUgSyM[10]; \
\
gettimeofday(&tv, NULL); \
gmtime_r(&tv.tv_sec, &tm); \
strftime(buf, 10, "%H:%M:%S", &tm); \
fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \
gettimeofday(&tv_dEbUgSyM, NULL); \
gmtime_r(&tv_dEbUgSyM.tv_sec, &tm_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, "\n"); \
} while (0)
#endif
#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__)
#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) || \
(defined(SCHED_DEBUG) && SCHED_DEBUG) || \
(defined(STUB_DEBUG) && STUB_DEBUG) || \
(defined(DAEMON_DEBUG) && DAEMON_DEBUG) || \
(defined(SEC_DEBUG) && SEC_DEBUG) || \
(defined(SERVER_DEBUG) && SERVER_DEBUG) || \
(defined(MDNS_DEBUG) && MDNS_DEBUG)
(defined(MDNS_DEBUG) && MDNS_DEBUG) || \
(defined(ANCHOR_DEBUG) && ANCHOR_DEBUG)
#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

View File

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

View File

@ -209,6 +209,7 @@
#include "dict.h"
#include "list.h"
#include "util/val_secalgo.h"
#include "anchor.h"
#define SIGNATURE_VERIFIED 0x10000
#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;
head_sz = (sizeof(chain_head) + dname_len + 7) / 8 * 8;
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);
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))
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)))
continue;
for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset), n_rrsigs = 0
; rrsig
for ( n_rrsigs = 0; rrsig
; rrsig = _getdns_rrsig_iter_next(rrsig), n_rrsigs++) {
/* 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);
}
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_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);
node->lock++;
if (! node->dnskey_req /* not scheduled */ &&
_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DNSKEY,
CD_extension(node->chains->netreq->owner),
node, &node->dnskey_req, NULL, val_chain_node_cb))
if (! node->dnskey_req) {
chain_head *head;
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 */ &&
_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS,
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 */
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);
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,
(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));
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)
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);
continue;
}
@ -1925,7 +1954,7 @@ static int ds_authenticates_keys(struct mem_funcs *mf,
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);
if (valid_dsses && !supported_dsses)
return NO_SUPPORTED_ALGORITHMS;
@ -2522,6 +2551,11 @@ static int chain_node_get_trusted_keys(
node->dnskey_signer = keytag;
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 */
if ((keytag = key_proves_nonexistance(
mf, now, skew, ta, &node->ds, NULL))) {
@ -2544,8 +2578,13 @@ static int chain_node_get_trusted_keys(
} else
return GETDNS_DNSSEC_BOGUS;
if (GETDNS_DNSSEC_SECURE != (s = chain_node_get_trusted_keys(
mf, now, skew, node->parent, ta, keys)))
s = chain_node_get_trusted_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;
/* 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
/* 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_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)
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))
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,
getdns_list *val_chain_list, int full)
@ -3078,30 +3180,40 @@ static void check_chain_complete(chain_head *chain)
_getdns_rrset_iter tas_iter;
if ((o = count_outstanding_requests(chain)) > 0) {
DEBUG_SEC(PRIsz" outstanding requests\n", o);
DEBUG_SEC("%"PRIsz" outstanding requests\n", o);
return;
}
DEBUG_SEC("Chain done!\n");
dnsreq = chain->netreq->owner;
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
/* Perform validation only on GETDNS_RESOLUTION_STUB (unbound_id == -1)
* 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)
if (context->trust_anchors)
chain_set_netreq_dnssec_status(chain,_getdns_rrset_iter_init(&tas_iter,
context->trust_anchors, context->trust_anchors_len,
SECTION_ANSWER));
#else
if (dnsreq->dnssec_return_validation_chain
&& context->trust_anchors)
if (context->trust_anchors)
(void) chain_validate_dnssec(priv_getdns_context_mf(context),
time(NULL), context->dnssec_allowed_skew,
@ -3110,10 +3222,52 @@ static void check_chain_complete(chain_head *chain)
, context->trust_anchors_len
, SECTION_ANSWER));
#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
if ( dnsreq->dnssec_roadblock_avoidance
&& !dnsreq->avoid_dnssec_roadblocks
&& dnsreq->netreqs[0]->dnssec_status == GETDNS_DNSSEC_BOGUS) {
&& _getdns_bogus(dnsreq)) {
getdns_network_req **netreq_p, *netreq;
uint64_t now_ms = 0;
@ -3167,6 +3321,7 @@ static void check_chain_complete(chain_head *chain)
return;
}
#endif
dnsreq->waiting_for_ta = 0;
val_chain_list = dnsreq->dnssec_return_validation_chain
? 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);
}
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)
{
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)
{
chain_head *head = dnsreq->chain, *next;
chain_head *head = dnsreq->chain, *next, *dnskey_head;
chain_node *node;
size_t node_count;
@ -3236,7 +3430,10 @@ void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq)
; node_count
; 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(
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)
; /* pass */
else for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p) ; netreq_p++) {
if (! netreq->response
|| 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;
continue;
}
} else if (netreq->unbound_id != -1)
netreq->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
add_pkt2val_chain( &dnsreq->my_mf, &chain
, netreq->response, netreq->response_len
, netreq
@ -3415,13 +3616,17 @@ getdns_validate_dnssec3(const getdns_list *records_to_validate,
fflush(stdout);
#endif
if (!records_to_validate || !support_records || !trust_anchors)
if (!records_to_validate || !trust_anchors)
return GETDNS_RETURN_INVALID_PARAMETER;
mf = (struct mem_funcs *)&records_to_validate->mf;
/* 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)))
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++) {
DEBUG_SEC("REPLY "PRIsz", r: %d\n", i, r);
DEBUG_SEC("REPLY %"PRIsz", r: %d\n", i, r);
if (to_val != to_val_buf)
GETDNS_FREE(*mf, to_val);
to_val_len = sizeof(to_val_buf);
@ -3468,7 +3673,7 @@ getdns_validate_dnssec3(const getdns_list *records_to_validate,
break;
}
}
DEBUG_SEC("REPLY "PRIsz", r: %d\n", i, r);
DEBUG_SEC("REPLY %"PRIsz", r: %d\n", i, r);
exit_free_to_val:
if (to_val != to_val_buf)

View File

@ -48,6 +48,7 @@
void _getdns_get_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_ta_notify_dnsreqs(getdns_context *context);
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;
}
int _getdns_bogus(getdns_dns_req *dns_req);
#endif
/* dnssec.h */

View File

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

View File

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

View File

@ -27,9 +27,10 @@
#include "config.h"
#include "extension/select_eventloop.h"
#include "debug.h"
#include "types-internal.h"
#include "platform.h"
#include "extension/select_eventloop.h"
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;
if (gettimeofday(&tv, NULL)) {
perror("gettimeofday() failed");
_getdns_perror("gettimeofday() failed");
exit(EXIT_FAILURE);
}
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);
}
#ifdef USE_WINSOCK
if (max_fd == -1)
{
if (timeout != TIMEOUT_FOREVER)
{
uint32_t timeout_ms = (tv.tv_usec / 1000) + (tv.tv_sec * 1000);
Sleep(timeout_ms);
}
} else
if (max_fd == -1) {
if (timeout != TIMEOUT_FOREVER) {
uint32_t timeout_ms = (tv.tv_usec / 1000) + (tv.tv_sec * 1000);
Sleep(timeout_ms);
}
} else {
#endif
if (select(max_fd + 1, &readfds, &writefds, NULL,
(timeout == TIMEOUT_FOREVER ? NULL : &tv)) < 0) {
perror("select() failed");
_getdns_perror("select() failed");
exit(EXIT_FAILURE);
}
#ifdef USE_WINSOCK
}
#endif
now = get_now_plus(0);
for (fd = 0; fd < (int)FD_SETSIZE; fd++) {
if (select_loop->fd_events[fd] &&

View File

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

View File

@ -54,6 +54,7 @@
#include "dict.h"
#include "mdns.h"
#include "debug.h"
#include "anchor.h"
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
#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->dnssec_return_status ||
dns_req->dnssec_return_only_secure ||
dns_req->dnssec_return_all_statuses
))
#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
*/
@ -235,6 +241,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
#if defined(REQ_DEBUG) && REQ_DEBUG
debug_req("getting validation chain for ", *dns_req->netreqs);
#endif
DEBUG_ANCHOR("Valchain lookup\n");
_getdns_get_validation_chain(dns_req);
} else
_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))
ub_resolve_r = ub_resolve_event(context->unbound_ctx,
name, netreq->request_type, dns_req->request_class,
netreq, ub_resolve_event_callback, &(netreq->unbound_id)) ?
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
netreq, ub_resolve_event_callback, &(netreq->unbound_id));
else
#endif
ub_resolve_r = ub_resolve_async(context->unbound_ctx,
name, netreq->request_type, dns_req->request_class,
netreq, ub_resolve_callback, &(netreq->unbound_id)) ?
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
netreq, ub_resolve_callback, &(netreq->unbound_id));
if (dnsreq_freed)
return DNS_REQ_FINISHED;
dns_req->freed = NULL;
@ -570,11 +575,6 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
if (extensions && (r = validate_extensions(extensions)))
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 */
if (!(req = _getdns_dns_req_new(
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);
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 */
for ( netreq_p = req->netreqs
else for ( netreq_p = req->netreqs
; !r && (netreq = *netreq_p)
; netreq_p++) {
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 (!(r = _getdns_context_local_namespace_resolve(
@ -639,6 +661,16 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
}
#endif /* HAVE_MDNS_SUPPORT */
} 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
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_CONNECTION_RETRIES 624
#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_ERR_TEXT "Error 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_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);
/**
*
* 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_context_set_logfunc(getdns_context *context, void *userarg,
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.
* @see getdns_context_set_resolution_type
@ -902,6 +1045,96 @@ getdns_return_t
getdns_context_get_update_callback(getdns_context *context, void **userarg,
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_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) {
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.
* \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
/**

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];
d5 = (*d)[5];
tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
#ifndef USE_WINSOCK
w = gldns_str_print(s, sl, "%llu", (long long)tsigtime);
#else
w = gldns_str_print(s, sl, "%I64u", (long long)tsigtime);
#endif
w = gldns_str_print(s, sl, "%"PRIu64, (uint64_t)tsigtime);
(*d)+=6;
(*dl)-=6;
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)
w += gldns_str_print(s, sl, " %s", llq_errors[error_code]);
else w += gldns_str_print(s, sl, " error %d", (int)error_code);
#ifndef USE_WINSOCK
w += gldns_str_print(s, sl, " id %llx lease-life %lu",
(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
w += gldns_str_print(s, sl, " id %"PRIx64" lease-life %lu",
(uint64_t)llq_id, (unsigned long)lease_life);
return w;
}

View File

@ -33,10 +33,14 @@ getdns_context_get_tls_authentication
getdns_context_get_tls_backoff_time
getdns_context_get_tls_connection_retries
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_upstream_recursive_servers
getdns_context_process_async
getdns_context_run
getdns_context_set_appdata_dir
getdns_context_set_append_name
getdns_context_set_context_update_callback
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_connection_retries
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_upstream_recursive_servers
getdns_context_set_use_threads

View File

@ -26,28 +26,11 @@
#include "gldns/pkthdr.h"
#include "gldns/rrdef.h"
#include "util-internal.h"
#include "platform.h"
#include "mdns.h"
#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 */
#ifndef IPV6_ADD_MEMBERSHIP
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
@ -1148,7 +1131,8 @@ mdns_udp_multicast_read_cb(void *userarg)
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! */
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)
{
#ifdef USE_WINSOCK
closesocket(fd4);
#else
close(fd4);
#endif
_getdns_closesocket(fd4);
fd4 = -1;
}
@ -1428,11 +1408,7 @@ static int mdns_open_ipv6_multicast(SOCKADDR_STORAGE* mcast_dest, int* mcast_des
if (ret != 0 && fd6 != -1)
{
#ifdef USE_WINSOCK
closesocket(fd6);
#else
close(fd6);
#endif
_getdns_closesocket(fd6);
fd6 = -1;
}
@ -1514,11 +1490,7 @@ static getdns_return_t mdns_delayed_network_init(struct getdns_context *context)
GETDNS_CLEAR_EVENT(context->extension
, &context->mdns_connection[i].event);
#ifdef USE_WINSOCK
closesocket(context->mdns_connection[i].fd);
#else
close(context->mdns_connection[i].fd);
#endif
_getdns_closesocket(context->mdns_connection[i].fd);
}
}
@ -1657,11 +1629,7 @@ void _getdns_mdns_context_destroy(struct getdns_context *context)
/* suppress the receive event */
GETDNS_CLEAR_EVENT(context->extension, &context->mdns_connection[i].event);
/* close the socket */
#ifdef USE_WINSOCK
closesocket(context->mdns_connection[i].fd);
#else
close(context->mdns_connection[i].fd);
#endif
_getdns_closesocket(context->mdns_connection[i].fd);
}
GETDNS_FREE(context->mf, context->mdns_connection);
@ -1686,11 +1654,7 @@ _getdns_cancel_mdns_request(getdns_network_req *netreq)
{
mdns_cleanup(netreq);
if (netreq->fd >= 0) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
}
}
@ -1706,11 +1670,7 @@ mdns_timeout_cb(void *userarg)
/* Check the required cleanup */
mdns_cleanup(netreq);
if (netreq->fd >= 0)
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
_getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
if (netreq->owner->user_callback) {
netreq->debug_end_time = _getdns_get_time_as_uintt64();
@ -1745,7 +1705,8 @@ mdns_udp_read_cb(void *userarg)
* i.e. overflow
*/
0, NULL, NULL);
if (read == -1 && _getdns_EWOULDBLOCK)
if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
_getdns_socketerror() == _getdns_ECONNRESET))
return;
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 TTL = 255
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
/*
* 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
@ -1814,11 +1771,7 @@ mdns_udp_write_cb(void *userarg)
netreq->fd, (const void *)netreq->query, pkt_len, 0,
(struct sockaddr *)&mdns_mcast_v4,
sizeof(mdns_mcast_v4))) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
return;
}
GETDNS_SCHEDULE_EVENT(

View File

@ -24,13 +24,11 @@
#ifdef HAVE_MDNS_SUPPORT
#include "getdns/getdns.h"
#include "types-internal.h"
#include "util-internal.h"
#include "platform.h"
#include "util/lruhash.h"
#include "config.h"
#ifndef USE_WINSOCK
#define SOCKADDR_STORAGE struct sockaddr_storage
#endif
getdns_return_t
_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
#echo getdns_yaml2dict >> libgetdns.symbols
echo plain_mem_funcs_user_arg >> libgetdns.symbols
echo priv_getdns_context_mf >> libgetdns.symbols
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 */
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL);
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));
continue;
}
next = raw;
i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next);
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);
continue;
}
@ -453,7 +453,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
/* compare it */
for (p = pinset; p; p = p->next)
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));
return GETDNS_RETURN_GOOD;
} else

View File

@ -107,6 +107,12 @@ network_req_cleanup(getdns_network_req *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 ||
net_req->response > net_req->wire_data+ net_req->wire_data_sz))
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;
_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->tsig_status = GETDNS_DNSSEC_INDETERMINATE;
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;
memcpy(net_req->transports, owner->context->dns_transports,
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;
@ -191,6 +208,11 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
/* Scheduling, touch only via _getdns_netreq_change_state!
*/
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) {
net_req->query = NULL;
@ -914,6 +936,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
dnssec_return_full_validation_chain;
result->dnssec_return_validation_chain = dnssec_return_validation_chain
|| dnssec_return_full_validation_chain;
result->dnssec_extension_set = dnssec_extension_set;
result->edns_cookies = edns_cookies;
#ifdef 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->finished_next = NULL;
result->ta_notify = NULL;
result->freed = NULL;
result->validating = 0;
result->waiting_for_ta = 0;
result->is_dns_request = 1;
result->request_timed_out = 0;
result->chain = NULL;

View File

@ -39,6 +39,8 @@
#include "types-internal.h"
#include "debug.h"
#include "util/rbtree.h"
#include "util-internal.h"
#include "platform.h"
#include "server.h"
#define DNS_REQUEST_SZ 4096
@ -135,11 +137,7 @@ static void tcp_connection_destroy(tcp_connection *conn)
loop->vmt->clear(loop, &conn->event);
if (conn->fd >= 0)
#ifdef USE_WINSOCK
(void) closesocket(conn->fd);
#else
(void) close(conn->fd);
#endif
(void) _getdns_closesocket(conn->fd);
GETDNS_FREE(*mf, conn->read_buf);
for (cur = conn->to_write; cur; cur = next) {
@ -189,7 +187,8 @@ static void tcp_write_cb(void *userarg)
}
to_write = conn->to_write;
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) {
/* IO error, close connection */
@ -284,11 +283,7 @@ getdns_reply(
(struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) {
/* IO error, cleanup this listener */
loop->vmt->clear(loop, &conn->l->event);
#ifdef USE_WINSOCK
closesocket(conn->l->fd);
#else
close(conn->l->fd);
#endif
_getdns_closesocket(conn->l->fd);
conn->l->fd = -1;
}
/* Unlink this connection */
@ -367,7 +362,8 @@ static void tcp_read_cb(void *userarg)
(void) loop->vmt->schedule(loop, conn->fd,
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)
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) {
/* IO error, cleanup this listener */
loop->vmt->clear(loop, &l->event);
#ifdef USE_WINSOCK
closesocket(l->fd);
#else
close(l->fd);
#endif
_getdns_closesocket(l->fd);
l->fd = -1;
GETDNS_FREE(*mf, conn);
return;
@ -553,13 +545,17 @@ static void udp_read_cb(void *userarg)
conn->addrlen = sizeof(conn->remote_in);
if ((len = recvfrom(l->fd, (void *)buf, sizeof(buf), 0,
(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. */
loop->vmt->clear(loop, &l->event);
#ifdef USE_WINSOCK
closesocket(l->fd);
#else
close(l->fd);
#endif
_getdns_closesocket(l->fd);
l->fd = -1;
#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG
@ -708,11 +704,7 @@ static void remove_listeners(listen_set *set)
continue;
loop->vmt->clear(loop, &l->event);
#ifdef USE_WINSOCK
closesocket(l->fd);
#else
close(l->fd);
#endif
_getdns_closesocket(l->fd);
l->fd = -1;
if (l->transport != GETDNS_TRANSPORT_TCP)

View File

@ -38,17 +38,6 @@
*/
#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 <openssl/err.h>
#include <openssl/conf.h>
@ -63,21 +52,10 @@
#include "rr-iter.h"
#include "context.h"
#include "util-internal.h"
#include "platform.h"
#include "general.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:
* STUB_TCP_WOULDBLOCK added to deal with edge triggered event loops (versus
* 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_schedule_netreq(getdns_upstream *upstream,
getdns_network_req *netreq);
static void upstream_reschedule_events(getdns_upstream *upstream,
uint64_t idle_timeout);
static void upstream_reschedule_events(getdns_upstream *upstream);
static int upstream_working_ok(getdns_upstream *upstream);
static int upstream_auth_status_ok(getdns_upstream *upstream,
getdns_network_req *netreq);
@ -438,13 +415,10 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport)
#endif
if (connect(fd, (struct sockaddr *)&upstream->addr,
upstream->addr_len) == -1) {
if (_getdns_EINPROGRESS || _getdns_EWOULDBLOCK)
if (_getdns_socketerror() == _getdns_EINPROGRESS ||
_getdns_socketerror() == _getdns_EWOULDBLOCK)
return fd;
#ifdef USE_WINSOCK
closesocket(fd);
#else
close(fd);
#endif
_getdns_closesocket(fd);
return -1;
}
return fd;
@ -455,22 +429,13 @@ tcp_connected(getdns_upstream *upstream) {
int error = 0;
socklen_t len = (socklen_t)sizeof(error);
getsockopt(upstream->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
#ifdef USE_WINSOCK
if (error == WSAEINPROGRESS)
if (error == _getdns_EINPROGRESS)
return STUB_TCP_AGAIN;
else if (error == WSAEWOULDBLOCK)
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)
else if (error == _getdns_EWOULDBLOCK || error == _getdns_EAGAIN)
return STUB_TCP_WOULDBLOCK;
else if (error != 0) {
return STUB_SETUP_ERROR;
}
#endif
if (upstream->transport == GETDNS_TRANSPORT_TCP &&
upstream->queries_sent == 0) {
upstream->conn_state = GETDNS_CONN_OPEN;
@ -496,42 +461,56 @@ stub_next_upstream(getdns_network_req *netreq)
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
stub_cleanup(getdns_network_req *netreq)
{
DEBUG_STUB("%s %-35s: MSG: %p\n",
STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq);
getdns_dns_req *dnsreq = netreq->owner;
getdns_network_req *r, *prev_r;
getdns_upstream *upstream;
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
/* Nothing globally scheduled? Then nothing queued */
if (!netreq->upstream || !(upstream = netreq->upstream)->event.ev)
return;
/* Delete from upstream->netreq_by_query_id (if present) */
(void) _getdns_rbtree_delete(&upstream->netreq_by_query_id,
(void *)(intptr_t)GLDNS_ID_WIRE(netreq->query));
/* Delete from upstream->write_queue (if present) */
for (prev_r = NULL, r = upstream->write_queue; r;
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);
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;
}
if (netreq->upstream) {
remove_from_write_queue(netreq->upstream, netreq);
if (netreq->upstream->event.ev)
upstream_reschedule_events(netreq->upstream);
}
}
static void
@ -545,17 +524,8 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
when idle.*/
/* [TLS1]TODO: Work out how to re-open the connection and re-try
the queries if there is only one upstream.*/
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
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
upstream could be used oppotunistically with no problem.*/
if (!(upstream->transport == GETDNS_TRANSPORT_TLS &&
@ -565,6 +535,11 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
upstream->conn_shutdowns++;
/* [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) {
netreq = (getdns_network_req *)
_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_check_dns_req_complete(netreq->owner);
}
upstream->conn_state = GETDNS_CONN_TEARDOWN;
_getdns_upstream_shutdown(upstream);
}
void
@ -582,11 +557,7 @@ _getdns_cancel_stub_request(getdns_network_req *netreq)
STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq);
stub_cleanup(netreq);
if (netreq->fd >= 0) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
netreq->fd = -1;
}
}
@ -601,15 +572,11 @@ stub_timeout_cb(void *userarg)
_getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
/* Handle upstream*/
if (netreq->fd >= 0) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
netreq->fd = -1;
netreq->upstream->udp_timeouts++;
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",
netreq->upstream->addr_str,
(int)netreq->upstream->udp_responses, (int)netreq->upstream->udp_timeouts);
@ -641,41 +608,12 @@ upstream_idle_timeout_cb(void *userarg)
static void
upstream_setup_timeout_cb(void *userarg)
{
int ret;
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",
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
* 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);
}
upstream_failed(upstream, 1);
}
@ -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);
if (read < 0) {
if (_getdns_EWOULDBLOCK)
if (_getdns_socketerror() == _getdns_EWOULDBLOCK)
return STUB_TCP_WOULDBLOCK;
else
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(
&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);
@ -818,11 +757,11 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
(struct sockaddr *)&(netreq->upstream->addr),
netreq->upstream->addr_len);
#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
a cookie is not available (e.g. when doing the first request to an
upstream). We must let the handshake complete since non-blocking. */
_getdns_EINPROGRESS)) ||
_getdns_socketerror() == _getdns_EINPROGRESS)) ||
(size_t)written < pkt_len + 2) {
/* 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.
* Try to send remaining data */
#ifdef USE_WINSOCK
written = send(fd, tcp->write_buf + tcp->written,
written = send(fd, (void *)(tcp->write_buf + tcp->written),
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 (_getdns_EWOULDBLOCK)
if (_getdns_socketerror() == _getdns_EWOULDBLOCK)
return STUB_TCP_WOULDBLOCK;
else {
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));
#endif
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",
upstream->addr_str, 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",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd);
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",
upstream->addr_str);
} 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);
#else
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__);
_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;
return NULL;
}
@ -1273,6 +1210,7 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
} while (!_getdns_rbtree_insert(
&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);
@ -1397,7 +1335,8 @@ stub_udp_read_cb(void *userarg)
* i.e. overflow
*/
0, NULL, NULL);
if (read == -1 && _getdns_EWOULDBLOCK)
if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
_getdns_socketerror() == _getdns_ECONNRESET))
return; /* Try again later */
if (read == -1) {
@ -1409,11 +1348,7 @@ stub_udp_read_cb(void *userarg)
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
/* Handle upstream*/
if (netreq->fd >= 0) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
netreq->fd = -1;
stub_next_upstream(netreq);
}
@ -1433,11 +1368,7 @@ stub_udp_read_cb(void *userarg)
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
netreq->fd = -1;
while (GLDNS_TC_WIRE(netreq->response)) {
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++;
if (upstream->udp_responses == 1 ||
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",
upstream->addr_str,
(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);
/* Handle upstream*/
if (netreq->fd >= 0) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
netreq->fd = -1;
stub_next_upstream(netreq);
}
@ -1601,7 +1528,6 @@ upstream_read_cb(void *userarg)
return;
default:
/* Lookup netreq */
query_id = (uint16_t) q;
query_id_intptr = (intptr_t) query_id;
@ -1613,7 +1539,16 @@ upstream_read_cb(void *userarg)
upstream->tcp.to_read = 2;
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",
STUB_DEBUG_READ, __FUNC__, (void*)netreq);
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
@ -1700,7 +1635,9 @@ upstream_write_cb(void *userarg)
__FUNC__, (void*)netreq);
/* 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;
else if (!upstream_working_ok(upstream))
q = STUB_TCP_ERROR;
@ -1724,10 +1661,8 @@ upstream_write_cb(void *userarg)
/* Could not complete the set up. Need to fallback.*/
DEBUG_STUB("%s %-35s: Upstream: %p ERROR = %d\n", STUB_DEBUG_WRITE,
__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));
/* Fall through */
return;
case STUB_CONN_GONE:
case STUB_NO_AUTH:
/* Cleaning up after connection or auth check failure. Need to fallback. */
@ -1744,6 +1679,9 @@ upstream_write_cb(void *userarg)
return;
default:
/* Unqueue the netreq from the write_queue */
remove_from_write_queue(upstream, netreq);
if (netreq->owner->return_call_reporting &&
netreq->upstream->tls_obj &&
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;
upstream->queries_sent++;
/* Unqueue the netreq from the write_queue */
if (!(upstream->write_queue = netreq->write_queue_tail)) {
upstream->write_queue_last = NULL;
/* Empty write_queue?, then deschedule upstream write_cb */
if (upstream->write_queue == NULL) {
assert(upstream->write_queue_last == NULL);
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
upstream->event.write_cb = NULL;
/* Reschedule (if already reading) to clear writable */
@ -1806,13 +1744,20 @@ upstream_active(getdns_upstream *upstream)
}
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 ||
upstream->conn_state == GETDNS_CONN_SETUP ||
upstream->conn_state == GETDNS_CONN_OPEN) &&
upstream->keepalive_shutdown == 0)
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;
}
@ -1828,15 +1773,22 @@ upstream_stats(getdns_upstream *upstream)
{
/* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/
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
upstream_valid(getdns_upstream *upstream,
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;
if (transport == GETDNS_TRANSPORT_TCP)
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 &&
upstreams->upstreams[i].conn_retry_time < now) {
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",
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
upstream because we completely back off failed
upstreams we may have no valid upstream at all (in contrast to UDP). This
will be better communicated to the user when we have better error codes*/
upstream (not backed-off) because we completely back off failed
upstreams we may have no valid upstream at all (in contrast to UDP).*/
i = upstreams->current_stateful;
do {
DEBUG_STUB("%s %-35s: Testing upstreams %d %d\n", STUB_DEBUG_SETUP,
__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];
break;
}
@ -1917,14 +1868,48 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
if (i >= upstreams->count)
i = 0;
} while (i != upstreams->current_stateful);
if (!upstream)
return NULL;
if (!upstream) {
/* 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 */
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++) {
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 = &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);
if (upstream->tls_obj == NULL) {
upstream_failed(upstream, 1);
#ifdef USE_WINSOCK
closesocket(fd);
#else
close(fd);
#endif
_getdns_closesocket(fd);
return -1;
}
upstream->tls_hs_state = GETDNS_HS_WRITE;
}
upstream->conn_state = GETDNS_CONN_SETUP;
_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",
dnsreq->context->tls_auth_min == GETDNS_AUTHENTICATION_NONE ? "Opportunistic":"Strict");
break;
@ -2048,12 +2029,17 @@ upstream_find_for_transport(getdns_network_req *netreq,
}
else {
/* 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 {
upstream = upstream_select_stateful(netreq, transport);
if (!upstream)
return NULL;
*fd = upstream_connect(upstream, transport, netreq->owner);
if (i >= upstream->upstreams->count)
return NULL;
i++;
} while (*fd == -1);
DEBUG_STUB("%s %-35s: FD: %d Connecting to upstream: %p No: %d\n",
STUB_DEBUG_SETUP, __FUNC__, *fd, (void*)upstream,
@ -2078,7 +2064,7 @@ upstream_find_for_netreq(getdns_network_req *netreq)
continue;
if (fd == -1) {
if (_getdns_EMFILE)
if (_getdns_socketerror() == _getdns_EMFILE)
return STUB_TRY_AGAIN_LATER;
return -1;
}
@ -2091,7 +2077,7 @@ upstream_find_for_netreq(getdns_network_req *netreq)
}
/* Handle better, will give generic error*/
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");
return -1;
}
@ -2120,11 +2106,17 @@ fallback_on_write(getdns_network_req *netreq)
}
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,
__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) {
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);
else {
DEBUG_STUB("%s %-35s: FD: %d Connection idle - timeout is %d\n",
STUB_DEBUG_SCHEDULE, __FUNC__, upstream->fd, (int)idle_timeout);
/* TODO: Schedule a read also anyway,
* to digest timed out answers.
* Dont forget to schedule with upstream->fd then!
*
* upstream->event.read_cb = upstream_read_cb;
*/
STUB_DEBUG_SCHEDULE, __FUNC__, upstream->fd,
(int)upstream->keepalive_timeout);
upstream->event.read_cb = upstream_read_cb;
upstream->event.timeout_cb = upstream_idle_timeout_cb;
if (upstream->conn_state != GETDNS_CONN_OPEN)
idle_timeout = 0;
GETDNS_SCHEDULE_EVENT(upstream->loop, -1,
idle_timeout, &upstream->event);
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
upstream->keepalive_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
if (_getdns_ub_loop_enabled(&context->ub_loop)) {
context->ub_loop.extension = ext;
} else
} else
# endif
# ifndef USE_WINSOCK
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
* UNBOUND_EVENT_API because ub_fd() doesn't work on windows.
*/
; /* pass */
# ifdef HAVE_UNBOUND_EVENT_API
{ ; } /* pass */
# endif
# endif
#endif
return GETDNS_RETURN_GOOD;
@ -114,30 +116,24 @@ getdns_sync_data_cleanup(getdns_sync_data *data)
upstream = &ctxt->upstreams->upstreams[i];
if (upstream->loop != &data->context->sync_eventloop.loop)
continue;
if (upstream->event.read_cb || upstream->event.write_cb) {
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
} else if (upstream->event.timeout_cb) {
/* Timeout's at upstream are idle-timeouts only.
* They should be fired on completion of the
* 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);
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
if (upstream->event.timeout_cb &&
( upstream->conn_state != GETDNS_CONN_OPEN
|| upstream->keepalive_timeout == 0)) {
(*upstream->event.timeout_cb)(upstream->event.userarg);
upstream->event.timeout_cb = NULL;
}
upstream->loop = data->context->extension;
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 &&
upstream->conn_state == GETDNS_CONN_OPEN &&
upstream->keepalive_timeout != 0) {
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
upstream->keepalive_timeout, &upstream->event);
if ( upstream->event.read_cb || upstream->event.write_cb
|| upstream->event.timeout_cb) {
GETDNS_SCHEDULE_EVENT(upstream->loop,
( upstream->event.read_cb
|| 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);
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;

View File

@ -25,4 +25,4 @@ done
rm -fr "${BUILDDIR}/build"
mkdir "${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:
Component:
CmdDepends:
Depends: 110-link.tpkg
Depends: 210-stub-only-link.tpkg
Help:
Pre:
Post:

View File

@ -4,6 +4,12 @@
# use .tpkg.var.test for in test variable passing
[ -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_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_SECRET=`echo ${SERVER_IP_TSIG}${TSIG_ALG}":"${TSIG_NAME}":"${TSIG_SECRET::${#TSIG_SECRET}-1}`
NUM_GOOD_QUERIES=9
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}" "L" "S"
"-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" "-")
if [[ $HAVE_SSL_HN_AUTH = 1 ]]
then
NUM_GOOD_QUERIES=9
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}" "L" "S"
"-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"
NUM_GOOD_FB_QUERIES=6
@ -173,21 +192,21 @@ for (( ii = 0; ii < 1; ii++)); do
fi
echo "*Success cases:"
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]}"
(( COUNT++ ))
done
echo "*Success fallback cases:"
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]}"
(( COUNT++ ))
done
echo "*Transport not available cases:"
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}]}"
(( COUNT++ ))
done
@ -198,3 +217,8 @@ done
echo
echo "Finished transport test: did $COUNT queries, $GOOD_COUNT passes, $FAIL_COUNT failures"
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"
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'
then
echo Skipping because not covering enough code

View File

@ -5,10 +5,43 @@
[ -f .tpkg.var.test ] && source .tpkg.var.test
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
if test -e "${BUILDDIR}/build-event-loops/src/test/fails"
if test -e "${BUILDDIR}/build-event-loops/src/test/check_getdns.failed"
then
exit 1
echo ""
echo "********************"
echo "*** check_getdns ***"
echo "********************"
cat "${BUILDDIR}/build-event-loops/src/test/check_getdns.log"
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

View File

@ -3,5 +3,5 @@
export SRCDIR=`dirname $0`
( cd $SRCDIR
./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
lcov $LCOV_MERGE -o run-all.info
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 control_c 2
done
"${TPKG}" r
"${TPKG}" -n -1 r

View File

@ -31,7 +31,7 @@ do
fi
done
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
for P in ${OTHERS}
do

View File

@ -36,3 +36,4 @@ export TPKG="${TPKG}"
export LIBTOOL="${LIBTOOL}"
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 " -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 " \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 " -b DIR\tuse DIR is a base directory in stead of ."
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 " -f\t\tForce test to be re-run if already executed"
out
out " (C) NLnetLabs, Miek Gieben. Licensed under the GPL version 2."
}
@ -329,11 +332,12 @@ function report() {
if [[ $passed -lt $TPKG_PASS ]]; then
exit 1
fi
elif [[ $failed -gt 0 ]]; then
exit 1
else
exit 0
elif [[ $TPKG_PASS -lt 0 ]]; then
if [[ $failed -gt 0 ]]; then
exit 1
fi
fi
exit 0
}
# clone test1 to test2
@ -858,9 +862,10 @@ echo "--------------- Test Output ------------------" | write_result result.$dsc
pre
out "[log] Executing test"
( ${SHELL} $dsc_test ${TPKG_ARGS} 2>&1 ) | write_result result.$dsc_basename
( ${SHELL} $dsc_test ${TPKG_ARGS} 2>&1 ) > result.$dsc_basename.tmp
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 :-(
if [ $test_result -ne 0 ]; then
err "[warning] Test executed with errors: $test_result."

View File

@ -46,6 +46,10 @@ typedef unsigned short in_port_t;
#include <wincrypt.h>
#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=\""
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\tRead settings from config file <filename>\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) {
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");
@ -346,7 +351,7 @@ static getdns_return_t validate_chain(getdns_dict *response)
if ((r = getdns_list_set_dict(to_validate, 0, reply)))
goto error;
if (verbosity) printf("reply "PRIsz", dnssec_status: ", i);
if (verbosity) printf("reply %d, dnssec_status: ", (int)i);
switch ((s = getdns_validate_dnssec(
to_validate, validation_chain, trust_anchor))) {
@ -478,16 +483,25 @@ done:
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_list *list;
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",
getdns_get_errorstr_by_id(r));
else {
if (!(r = getdns_dict_get_list(
config_dict, "listen_addresses", &list))) {
@ -535,6 +549,7 @@ int parse_config_file(const char *fn, int report_open_failure)
FILE *fh;
char *config_file = NULL;
long config_file_sz;
size_t read_sz;
if (!(fh = fopen(fn, "r"))) {
if (report_open_failure)
@ -559,15 +574,16 @@ int parse_config_file(const char *fn, int report_open_failure)
return GETDNS_RETURN_MEMORY_ERROR;
}
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"
, fn, strerror(errno));
fclose(fh);
return GETDNS_RETURN_MEMORY_ERROR;
}
config_file[config_file_sz] = 0;
config_file[read_sz] = 0;
fclose(fh);
parse_config(config_file);
parse_config(config_file, strstr(fn, ".yml") != NULL);
free(config_file);
return GETDNS_RETURN_GOOD;
}
@ -656,7 +672,7 @@ getdns_return_t parse_args(int argc, char **argv)
}
continue;
} else if (arg[0] == '{') {
parse_config(arg);
parse_config(arg, 0);
continue;
} else if (arg[0] != '-') {
@ -1071,11 +1087,11 @@ next: ;
/* apply the accumulated pubkey pinset to all upstreams: */
for (j = 0; j < upstream_count; j++) {
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;
}
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;
}
}
@ -1269,7 +1285,9 @@ void read_line_cb(void *userarg)
if (listen_count)
(void) getdns_context_set_listen_addresses(
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;
}
if (query_file && verbosity)
@ -1668,16 +1686,22 @@ static void stubby_log(void *userarg, uint64_t system,
#ifdef GETDNS_ON_WINDOWS
time_t tsec;
if (!verbosity)
return;
gettimeofday(&tv, NULL);
tsec = (time_t) tv.tv_sec;
gmtime_s(&tm, (const time_t *) &tsec);
#else
if (!verbosity)
return;
gettimeofday(&tv, NULL);
gmtime_r(&tv.tv_sec, &tm);
#endif
strftime(buf, 10, "%H:%M:%S", &tm);
(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);
}
@ -1725,16 +1749,16 @@ main(int argc, char **argv)
, "%s/.stubby.conf"
, getenv("HOME")
);
(void) parse_config(default_stubby_config);
(void) parse_config(default_stubby_config, 0);
(void) parse_config_file("/etc/stubby.conf", 0);
if (n_chars > 0 && n_chars < (int)sizeof(home_stubby_conf_fn)){
(void) parse_config_file(home_stubby_conf_fn, 0);
}
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)))
goto done_destroy_context;
clear_listen_list_on_arg = 0;

View File

@ -171,7 +171,7 @@ typedef enum network_req_state_enum
/* State for async tcp stub resolving */
typedef struct getdns_tcp_state {
uint8_t *write_buf;
const uint8_t *write_buf;
size_t write_buf_len;
size_t written;
@ -188,7 +188,9 @@ typedef struct getdns_tcp_state {
typedef struct getdns_network_req
{
/* 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
/*
* 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_validation_chain : 1;
unsigned dnssec_return_full_validation_chain : 1;
unsigned dnssec_extension_set : 1;
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE
unsigned dnssec_roadblock_avoidance : 1;
unsigned avoid_dnssec_roadblocks : 1;
@ -324,6 +327,7 @@ typedef struct getdns_dns_req {
* freed is touched by _getdns_submit_netreq only
*/
unsigned validating : 1;
unsigned waiting_for_ta : 1;
int *freed;
/* 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;
/* 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.
* The array is terminated with NULL.
*

View File

@ -203,7 +203,7 @@ INLINE uint64_t _getdns_get_now_ms()
struct timeval tv;
(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)

View File

@ -45,6 +45,8 @@
#define sec_status_insecure _getdns_sec_status_insecure
#define sec_status_unchecked _getdns_sec_status_unchecked
#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
, sec_status_unchecked = 0

1
src/yxml Submodule

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

2
stubby

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