Merge pull request #9 from getdnsapi/develop

Align with develop branch
This commit is contained in:
huitema 2017-03-22 10:10:00 -07:00 committed by GitHub
commit 95da0b46e0
41 changed files with 3634 additions and 442 deletions

View File

@ -311,6 +311,15 @@ AC_INCLUDES_DEFAULT
fi fi
AC_ARG_ENABLE(sha1, AC_HELP_STRING([--disable-sha1], [Disable SHA1 RRSIG support, does not disable nsec3 support]))
case "$enable_sha1" in
no)
;;
yes|*)
AC_DEFINE([USE_SHA1], [1], [Define this to enable SHA1 support.])
;;
esac
AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support])) AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support]))
case "$enable_sha2" in case "$enable_sha2" in
no) no)
@ -1002,7 +1011,10 @@ fi
#---- check for pthreads library #---- check for pthreads library
AC_SEARCH_LIBS([pthread_mutex_init],[pthread],[AC_DEFINE([HAVE_PTHREAD], [1], [Have pthreads library])], [AC_MSG_WARN([pthreads not available])]) AC_SEARCH_LIBS([pthread_mutex_init],[pthread], [
AC_DEFINE([HAVE_PTHREAD], [1], [Have pthreads library])
LIBS="-lpthread $LIBS"
], [AC_MSG_WARN([pthreads not available])])
AC_MSG_CHECKING([whether the C compiler (${CC-cc}) supports the __func__ variable]) AC_MSG_CHECKING([whether the C compiler (${CC-cc}) supports the __func__ variable])
AC_LANG_PUSH(C) AC_LANG_PUSH(C)

View File

@ -149,16 +149,24 @@ depend:
# Dependencies for the examples # Dependencies for the examples
example-all-functions.lo example-all-functions.o: $(srcdir)/example-all-functions.c $(srcdir)/getdns_libevent.h \ example-all-functions.lo example-all-functions.o: $(srcdir)/example-all-functions.c $(srcdir)/getdns_libevent.h \
../../src/config.h ../../src/getdns/getdns.h \ ../../src/config.h \
$(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h ../../src/getdns/getdns.h \
example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h ../../src/config.h \ $(srcdir)/../../src/getdns/getdns_ext_libevent.h \
../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/getdns/getdns_extra.h
example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h \
../../src/config.h \
../../src/getdns/getdns.h \
$(srcdir)/../../src/getdns/getdns_ext_libevent.h \
../../src/getdns/getdns_extra.h ../../src/getdns/getdns_extra.h
example-simple-answers.lo example-simple-answers.o: $(srcdir)/example-simple-answers.c $(srcdir)/getdns_libevent.h \ example-simple-answers.lo example-simple-answers.o: $(srcdir)/example-simple-answers.c $(srcdir)/getdns_libevent.h \
../../src/config.h ../../src/getdns/getdns.h \ ../../src/config.h \
$(srcdir)/../../src/getdns/getdns_ext_libevent.h ../../src/getdns/getdns_extra.h ../../src/getdns/getdns.h \
$(srcdir)/../../src/getdns/getdns_ext_libevent.h \
../../src/getdns/getdns_extra.h
example-synchronous.lo example-synchronous.o: $(srcdir)/example-synchronous.c $(srcdir)/getdns_core_only.h \ example-synchronous.lo example-synchronous.o: $(srcdir)/example-synchronous.c $(srcdir)/getdns_core_only.h \
../../src/getdns/getdns.h ../../src/getdns/getdns.h
example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h ../../src/config.h \ example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h \
../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/config.h \
../../src/getdns/getdns.h \
$(srcdir)/../../src/getdns/getdns_ext_libevent.h \
../../src/getdns/getdns_extra.h ../../src/getdns/getdns_extra.h

View File

@ -216,169 +216,287 @@ depend:
FORCE: FORCE:
# Dependencies for gldns, utils, the extensions and compat functions # Dependencies for gldns, utils, the extensions and compat functions
const-info.lo const-info.o: $(srcdir)/const-info.c getdns/getdns.h getdns/getdns_extra.h \ const-info.lo const-info.o: $(srcdir)/const-info.c \
getdns/getdns.h $(srcdir)/const-info.h getdns/getdns.h \
context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ getdns/getdns_extra.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \ $(srcdir)/const-info.h
getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ context.lo context.o: $(srcdir)/context.c \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ config.h \
$(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \
$(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ getdns/getdns.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h \ getdns/getdns_extra.h \
$(srcdir)/pubkey-pinning.h
convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \
getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \
$(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \
$(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.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
dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \
getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.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/parseutil.h
dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \
$(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \
$(srcdir)/ub_loop.h $(srcdir)/server.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/orig-headers/val_secalgo.h
general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \
getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/server.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
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \
getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h \
config.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \
$(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \
$(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h
mdns.lo mdns.o: $(srcdir)/mdns.c config.h $(srcdir)/debug.h $(srcdir)/context.h getdns/getdns.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \
$(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \
$(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/mdns.h
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.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)/extension/default_eventloop.h \
config.h $(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h
request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \
getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \
getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.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
rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \ $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \ $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \ $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h config.h getdns/getdns.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)/gldns/rrdef.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h \
server.lo server.o: $(srcdir)/server.c config.h getdns/getdns_extra.h getdns/getdns.h \ $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
$(srcdir)/context.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ convert.lo convert.o: $(srcdir)/convert.c \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ config.h \
$(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ getdns/getdns.h \
$(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h getdns/getdns_extra.h \
stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \ $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h \ $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \
$(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \
$(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h getdns/getdns_extra.h \
getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \
$(srcdir)/extension/poll_eventloop.h getdns/getdns_extra.h $(srcdir)/types-internal.h \
$(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.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
ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/debug.h
util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/types-internal.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h config.h $(srcdir)/extension/poll_eventloop.h \
getdns/getdns_extra.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.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
version.lo version.o: version.c
gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c config.h $(srcdir)/gldns/gbuffer.h
keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c config.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h
parse.lo parse.o: $(srcdir)/gldns/parse.c config.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h \
$(srcdir)/gldns/gbuffer.h
parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c config.h $(srcdir)/gldns/parseutil.h
rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h
str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c config.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h
wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c config.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/keyraw.h
arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c config.h
arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c config.h $(srcdir)/compat/chacha_private.h
arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c config.h
explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c config.h
getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h
getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c config.h
getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h
getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c
gettimeofday.lo gettimeofday.o: $(srcdir)/compat/gettimeofday.c config.h
inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c config.h
inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c config.h
sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.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 config.h
lookup3.lo lookup3.o: $(srcdir)/util/lookup3.c config.h $(srcdir)/util/auxiliary/util/storage/lookup3.h \
$(srcdir)/util/lookup3.h $(srcdir)/util/orig-headers/lookup3.h
lruhash.lo lruhash.o: $(srcdir)/util/lruhash.c config.h $(srcdir)/util/auxiliary/util/storage/lruhash.h \
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \ $(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h config.h \ $(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \
$(srcdir)/util/auxiliary/util/fptr_wlist.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/wire2str.h \
rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/auxiliary/log.h \ $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h config.h $(srcdir)/util/auxiliary/fptr_wlist.h \ $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h
$(srcdir)/util/auxiliary/util/fptr_wlist.h $(srcdir)/util/rbtree.h \ dict.lo dict.o: $(srcdir)/dict.c \
$(srcdir)/util/orig-headers/rbtree.h config.h \
val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h \ $(srcdir)/types-internal.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.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)/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 \
$(srcdir)/debug.h \
getdns/getdns.h \
$(srcdir)/context.h \
getdns/getdns_extra.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)/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 \
$(srcdir)/general.h \
getdns/getdns.h \
$(srcdir)/types-internal.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/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
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h \
config.h \
$(srcdir)/context.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)/list.h $(srcdir)/dict.h
mdns.lo mdns.o: $(srcdir)/mdns.c \
config.h \
$(srcdir)/debug.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)/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/orig-headers/lookup3.h
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \
config.h \
$(srcdir)/debug.h \
getdns/getdns.h \
$(srcdir)/context.h \
getdns/getdns_extra.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
request-internal.lo request-internal.o: $(srcdir)/request-internal.c \
config.h \
$(srcdir)/types-internal.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.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)/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 \
$(srcdir)/gldns/gbuffer.h $(srcdir)/util-internal.h $(srcdir)/context.h \
getdns/getdns_extra.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)/gldns/pkthdr.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 \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h
server.lo server.o: $(srcdir)/server.c \
config.h \
getdns/getdns_extra.h \
getdns/getdns.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)/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
stub.lo stub.o: $(srcdir)/stub.c \
config.h \
$(srcdir)/debug.h $(srcdir)/stub.h \
getdns/getdns.h \
$(srcdir)/types-internal.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h \
$(srcdir)/rr-dict.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \
$(srcdir)/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
sync.lo sync.o: $(srcdir)/sync.c \
getdns/getdns.h \
config.h \
$(srcdir)/context.h \
getdns/getdns_extra.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)/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
ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \
config.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
util-internal.lo util-internal.o: $(srcdir)/util-internal.c \
config.h \
getdns/getdns.h \
$(srcdir)/dict.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/types-internal.h \
getdns/getdns_extra.h \
$(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.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)/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
keyraw.lo keyraw.o: $(srcdir)/gldns/keyraw.c \
config.h \
$(srcdir)/gldns/keyraw.h $(srcdir)/gldns/rrdef.h
parse.lo parse.o: $(srcdir)/gldns/parse.c \
config.h \
$(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h
parseutil.lo parseutil.o: $(srcdir)/gldns/parseutil.c \
config.h \
$(srcdir)/gldns/parseutil.h
rrdef.lo rrdef.o: $(srcdir)/gldns/rrdef.c \
config.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h
str2wire.lo str2wire.o: $(srcdir)/gldns/str2wire.c \
config.h \
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/parse.h $(srcdir)/gldns/parseutil.h
wire2str.lo wire2str.o: $(srcdir)/gldns/wire2str.c \
config.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/keyraw.h
arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c \
config.h
arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c \
config.h \
$(srcdir)/compat/chacha_private.h
arc4random_uniform.lo arc4random_uniform.o: $(srcdir)/compat/arc4random_uniform.c \
config.h
explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c \
config.h
getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c \
config.h
getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c \
config.h
getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c \
config.h
getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c
gettimeofday.lo gettimeofday.o: $(srcdir)/compat/gettimeofday.c \
config.h
inet_ntop.lo inet_ntop.o: $(srcdir)/compat/inet_ntop.c \
config.h
inet_pton.lo inet_pton.o: $(srcdir)/compat/inet_pton.c \
config.h
sha512.lo sha512.o: $(srcdir)/compat/sha512.c \
config.h
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.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
lookup3.lo lookup3.o: $(srcdir)/util/lookup3.c \
config.h \
$(srcdir)/util/auxiliary/util/storage/lookup3.h $(srcdir)/util/lookup3.h \
$(srcdir)/util/orig-headers/lookup3.h
lruhash.lo lruhash.o: $(srcdir)/util/lruhash.c \
config.h \
$(srcdir)/util/auxiliary/util/storage/lruhash.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/fptr_wlist.h
rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c \
config.h \
$(srcdir)/util/auxiliary/log.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h \
$(srcdir)/util/auxiliary/fptr_wlist.h $(srcdir)/util/auxiliary/util/fptr_wlist.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h
val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c \
config.h \
$(srcdir)/util/auxiliary/util/data/packed_rrset.h \ $(srcdir)/util/auxiliary/util/data/packed_rrset.h \
$(srcdir)/util/auxiliary/validator/val_secalgo.h $(srcdir)/util/val_secalgo.h \ $(srcdir)/util/auxiliary/validator/val_secalgo.h $(srcdir)/util/val_secalgo.h \
$(srcdir)/util/orig-headers/val_secalgo.h $(srcdir)/util/auxiliary/validator/val_nsec3.h \ $(srcdir)/util/orig-headers/val_secalgo.h $(srcdir)/util/auxiliary/validator/val_nsec3.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h config.h $(srcdir)/util/auxiliary/sldns/rrdef.h \ $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util/auxiliary/sldns/rrdef.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/util/auxiliary/sldns/keyraw.h $(srcdir)/gldns/keyraw.h \ $(srcdir)/gldns/rrdef.h $(srcdir)/util/auxiliary/sldns/keyraw.h $(srcdir)/gldns/keyraw.h \
$(srcdir)/util/auxiliary/sldns/sbuffer.h $(srcdir)/gldns/gbuffer.h $(srcdir)/util/auxiliary/sldns/sbuffer.h $(srcdir)/gldns/gbuffer.h
jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h
libev.lo libev.o: $(srcdir)/extension/libev.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ libev.lo libev.o: $(srcdir)/extension/libev.c \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ config.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libev.h \ $(srcdir)/types-internal.h \
getdns/getdns_extra.h getdns/getdns.h \
libevent.lo libevent.o: $(srcdir)/extension/libevent.c config.h $(srcdir)/types-internal.h \ getdns/getdns_extra.h \
getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libev.h
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h \ libevent.lo libevent.o: $(srcdir)/extension/libevent.c \
getdns/getdns_extra.h config.h \
libuv.lo libuv.o: $(srcdir)/extension/libuv.c config.h $(srcdir)/debug.h config.h $(srcdir)/types-internal.h \ $(srcdir)/types-internal.h \
getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ getdns/getdns.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h \ getdns/getdns_extra.h \
getdns/getdns_extra.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h
poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c config.h \ libuv.lo libuv.o: $(srcdir)/extension/libuv.c \
$(srcdir)/extension/poll_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ config.h \
$(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/util/rbtree.h \ $(srcdir)/debug.h $(srcdir)/types-internal.h \
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/debug.h config.h getdns/getdns.h \
select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c config.h \ getdns/getdns_extra.h \
$(srcdir)/extension/select_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h
$(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h config.h \
$(srcdir)/extension/poll_eventloop.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
select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \
config.h \
$(srcdir)/extension/select_eventloop.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

View File

@ -73,6 +73,9 @@ static struct const_info consts_info[] = {
{ 619, "GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE", GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE_TEXT }, { 619, "GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE", GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE_TEXT },
{ 620, "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT }, { 620, "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT },
{ 621, "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT }, { 621, "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT },
{ 622, "GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS", GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS_TEXT },
{ 623, "GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME", GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME_TEXT },
{ 624, "GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES", GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES_TEXT },
{ 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT }, { 700, "GETDNS_CALLBACK_COMPLETE", GETDNS_CALLBACK_COMPLETE_TEXT },
{ 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT }, { 701, "GETDNS_CALLBACK_CANCEL", GETDNS_CALLBACK_CANCEL_TEXT },
{ 702, "GETDNS_CALLBACK_TIMEOUT", GETDNS_CALLBACK_TIMEOUT_TEXT }, { 702, "GETDNS_CALLBACK_TIMEOUT", GETDNS_CALLBACK_TIMEOUT_TEXT },
@ -157,9 +160,12 @@ static struct const_name_info consts_name_info[] = {
{ "GETDNS_CONTEXT_CODE_NAMESPACES", 600 }, { "GETDNS_CONTEXT_CODE_NAMESPACES", 600 },
{ "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", 621 }, { "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", 621 },
{ "GETDNS_CONTEXT_CODE_RESOLUTION_TYPE", 601 }, { "GETDNS_CONTEXT_CODE_RESOLUTION_TYPE", 601 },
{ "GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS", 622 },
{ "GETDNS_CONTEXT_CODE_SUFFIX", 608 }, { "GETDNS_CONTEXT_CODE_SUFFIX", 608 },
{ "GETDNS_CONTEXT_CODE_TIMEOUT", 616 }, { "GETDNS_CONTEXT_CODE_TIMEOUT", 616 },
{ "GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION", 618 }, { "GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION", 618 },
{ "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_TLS_QUERY_PADDING_BLOCKSIZE", 620 },
{ "GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS", 603 }, { "GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS", 603 },
{ "GETDNS_DNSSEC_BOGUS", 401 }, { "GETDNS_DNSSEC_BOGUS", 401 },

View File

@ -89,9 +89,6 @@ typedef unsigned short in_port_t;
#define GETDNS_STR_PORT_ZERO "0" #define GETDNS_STR_PORT_ZERO "0"
#define GETDNS_STR_PORT_DNS "53" #define GETDNS_STR_PORT_DNS "53"
#define GETDNS_STR_PORT_DNS_OVER_TLS "853" #define GETDNS_STR_PORT_DNS_OVER_TLS "853"
/* How long to wait in seconds before re-trying a connection based backed-off
upstream. Using 1 hour for all transports - based on RFC7858 value for for TLS.*/
#define BACKOFF_RETRY 3600
#ifdef HAVE_PTHREAD #ifdef HAVE_PTHREAD
static pthread_mutex_t ssl_init_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t ssl_init_lock = PTHREAD_MUTEX_INITIALIZER;
@ -657,6 +654,9 @@ upstreams_create(getdns_context *context, size_t size)
r->referenced = 1; r->referenced = 1;
r->count = 0; r->count = 0;
r->current_udp = 0; r->current_udp = 0;
r->current_stateful = 0;
r->tls_backoff_time = context->tls_backoff_time;
r->tls_connection_retries = context->tls_connection_retries;
return r; return r;
} }
@ -731,17 +731,17 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
if (upstream->tls_auth_state > upstream->best_tls_auth_state) if (upstream->tls_auth_state > upstream->best_tls_auth_state)
upstream->best_tls_auth_state = upstream->tls_auth_state; upstream->best_tls_auth_state = upstream->tls_auth_state;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG #if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %s : Conn closed : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n", DEBUG_DAEMON("%s %-40s : Conn closed : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n",
STUB_DEBUG_DAEMON, upstream->addr_str, STUB_DEBUG_DAEMON, upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"), (upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->responses_received, (int)upstream->responses_timeouts, (int)upstream->responses_received, (int)upstream->responses_timeouts,
_getdns_auth_str(upstream->tls_auth_state), (int)upstream->keepalive_timeout); _getdns_auth_str(upstream->tls_auth_state), (int)upstream->keepalive_timeout);
DEBUG_DAEMON("%s %s : Upstream stats: Transport=%s - Resp=%d,Timeouts=%d,Best_auth=%s\n", DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=%s - Resp=%d,Timeouts=%d,Best_auth=%s\n",
STUB_DEBUG_DAEMON, upstream->addr_str, STUB_DEBUG_DAEMON, upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"), (upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->total_responses, (int)upstream->total_timeouts, (int)upstream->total_responses, (int)upstream->total_timeouts,
_getdns_auth_str(upstream->best_tls_auth_state)); _getdns_auth_str(upstream->best_tls_auth_state));
DEBUG_DAEMON("%s %s : Upstream stats: Transport=%s - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n", DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=%s - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n",
STUB_DEBUG_DAEMON, upstream->addr_str, STUB_DEBUG_DAEMON, upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"), (upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->conn_completed, (int)upstream->conn_setup_failed, (int)upstream->conn_completed, (int)upstream->conn_setup_failed,
@ -753,16 +753,16 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
Leave choice between working upstreams to the stub. Leave choice between working upstreams to the stub.
This back-off should be time based for TLS according to RFC7858. For now, This back-off should be time based for TLS according to RFC7858. For now,
use the same basis if we simply can't get TCP service either.*/ use the same basis if we simply can't get TCP service either.*/
uint16_t conn_retries = upstream->upstreams->tls_connection_retries;
/* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/ /* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/
if (upstream->conn_setup_failed >= GETDNS_CONN_ATTEMPTS || if (upstream->conn_setup_failed >= conn_retries
(upstream->conn_shutdowns >= GETDNS_CONN_ATTEMPTS*GETDNS_TRANSPORT_FAIL_MULT || (upstream->conn_shutdowns >= conn_retries*GETDNS_TRANSPORT_FAIL_MULT
&& upstream->total_responses == 0) || && upstream->total_responses == 0)
(upstream->conn_completed >= GETDNS_CONN_ATTEMPTS && || (upstream->conn_completed >= conn_retries &&
upstream->total_responses == 0 && upstream->total_responses == 0 &&
upstream->total_timeouts > GETDNS_TRANSPORT_FAIL_MULT)) { upstream->total_timeouts > GETDNS_TRANSPORT_FAIL_MULT)) {
upstream->conn_state = GETDNS_CONN_BACKOFF; upstream->conn_state = GETDNS_CONN_BACKOFF;
upstream->conn_retry_time = time(NULL) + BACKOFF_RETRY; upstream->conn_retry_time = time(NULL) + upstream->upstreams->tls_backoff_time;
upstream->total_responses = 0; upstream->total_responses = 0;
upstream->total_timeouts = 0; upstream->total_timeouts = 0;
upstream->conn_completed = 0; upstream->conn_completed = 0;
@ -770,7 +770,7 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
upstream->conn_shutdowns = 0; upstream->conn_shutdowns = 0;
upstream->conn_backoffs++; upstream->conn_backoffs++;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG #if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %s : !Backing off this upstream - Will retry as new upstream at %s", DEBUG_DAEMON("%s %-40s : !Backing off this upstream - Will retry as new upstream at %s",
STUB_DEBUG_DAEMON, upstream->addr_str, STUB_DEBUG_DAEMON, upstream->addr_str,
asctime(gmtime(&upstream->conn_retry_time))); asctime(gmtime(&upstream->conn_retry_time)));
#endif #endif
@ -1290,6 +1290,26 @@ NULL_update_callback(
getdns_context *context, getdns_context_code_t code, void *userarg) getdns_context *context, getdns_context_code_t code, void *userarg)
{ (void)context; (void)code; (void)userarg; } { (void)context; (void)code; (void)userarg; }
static int
netreq_expiry_cmp(const void *id1, const void *id2)
{
getdns_network_req *req1 = (getdns_network_req *)id1;
getdns_network_req *req2 = (getdns_network_req *)id2;
return req1->owner->expires < req2->owner->expires ? -1 :
req1->owner->expires > req2->owner->expires ? 1 :
req1 < req2 ? -1 :
req1 > req2 ? 1 : 0;
}
void _getdns_check_expired_pending_netreqs(
getdns_context *context, uint64_t *now_ms);
static void _getdns_check_expired_pending_netreqs_cb(void *arg)
{
uint64_t now_ms = 0;
_getdns_check_expired_pending_netreqs((getdns_context *)arg, &now_ms);
}
/* /*
* getdns_context_create * getdns_context_create
* *
@ -1353,6 +1373,15 @@ getdns_context_create_with_extended_memory_functions(
_getdns_rbtree_init(&result->outbound_requests, transaction_id_cmp); _getdns_rbtree_init(&result->outbound_requests, transaction_id_cmp);
_getdns_rbtree_init(&result->local_hosts, local_host_cmp); _getdns_rbtree_init(&result->local_hosts, local_host_cmp);
_getdns_rbtree_init(&result->pending_netreqs, netreq_expiry_cmp);
result->first_pending_netreq = NULL;
result->netreqs_in_flight = 0;
result->pending_timeout_event.userarg = result;
result->pending_timeout_event.read_cb = NULL;
result->pending_timeout_event.write_cb = NULL;
result->pending_timeout_event.timeout_cb =
_getdns_check_expired_pending_netreqs_cb;
result->pending_timeout_event.ev = NULL;
result->server = NULL; result->server = NULL;
@ -1451,6 +1480,9 @@ getdns_context_create_with_extended_memory_functions(
goto error; goto error;
result->tls_auth = GETDNS_AUTHENTICATION_NONE; result->tls_auth = GETDNS_AUTHENTICATION_NONE;
result->tls_auth_min = GETDNS_AUTHENTICATION_NONE; result->tls_auth_min = GETDNS_AUTHENTICATION_NONE;
result->round_robin_upstreams = 0;
result->tls_backoff_time = 3600;
result->tls_connection_retries = 2;
result->limit_outstanding_queries = 0; result->limit_outstanding_queries = 0;
/* unbound context is initialized here */ /* unbound context is initialized here */
@ -2067,6 +2099,62 @@ getdns_context_set_tls_authentication(getdns_context *context,
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* getdns_context_set_tls_authentication_list */ } /* getdns_context_set_tls_authentication_list */
/*
* getdns_context_set_round_robin_upstreams
*
*/
getdns_return_t
getdns_context_set_round_robin_upstreams(getdns_context *context, uint8_t value)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
/* only allow 0 or 1 */
if (value != 0 && value != 1) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
}
context->round_robin_upstreams = value;
dispatch_updated(context, GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS);
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_round_robin_upstreams */
/*
* getdns_context_set_tls_backoff_time
*
*/
getdns_return_t
getdns_context_set_tls_backoff_time(getdns_context *context, uint16_t value)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
/* Value is in seconds. Should we have a lower limit? 1 second?*/
context->tls_backoff_time = value;
dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME);
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_tls_backoff_time */
/*
* getdns_context_set_tls_connection_retries
*
*/
getdns_return_t
getdns_context_set_tls_connection_retries(getdns_context *context, uint16_t value)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
/* Should we put a sensible upper limit on this? 10?*/
// if (value > 10) {
// return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
// }
context->tls_connection_retries = value;
dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES);
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_tls_connection retries */
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
static void static void
set_ub_limit_outstanding_queries(getdns_context* context, uint16_t value) { set_ub_limit_outstanding_queries(getdns_context* context, uint16_t value) {
@ -3503,7 +3591,13 @@ _get_context_settings(getdns_context* context)
|| getdns_dict_set_int(result, "append_name", || getdns_dict_set_int(result, "append_name",
context->append_name) context->append_name)
|| getdns_dict_set_int(result, "tls_authentication", || getdns_dict_set_int(result, "tls_authentication",
context->tls_auth)) context->tls_auth)
|| getdns_dict_set_int(result, "round_robin_upstreams",
context->round_robin_upstreams)
|| getdns_dict_set_int(result, "tls_backoff_time",
context->tls_backoff_time)
|| getdns_dict_set_int(result, "tls_connection_retries",
context->tls_connection_retries))
goto error; goto error;
/* list fields */ /* list fields */
@ -3799,6 +3893,33 @@ getdns_context_get_tls_authentication(getdns_context *context,
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
getdns_return_t
getdns_context_get_round_robin_upstreams(getdns_context *context,
uint8_t* value) {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
*value = context->round_robin_upstreams;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_tls_backoff_time(getdns_context *context,
uint16_t* value) {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
*value = context->tls_backoff_time;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_tls_connection_retries(getdns_context *context,
uint16_t* value) {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
*value = context->tls_connection_retries;
return GETDNS_RETURN_GOOD;
}
getdns_return_t getdns_return_t
getdns_context_get_limit_outstanding_queries(getdns_context *context, getdns_context_get_limit_outstanding_queries(getdns_context *context,
uint16_t* value) { uint16_t* value) {
@ -4194,6 +4315,9 @@ _getdns_context_config_setting(getdns_context *context,
CONTEXT_SETTING_INT(edns_client_subnet_private) CONTEXT_SETTING_INT(edns_client_subnet_private)
CONTEXT_SETTING_INT(tls_authentication) CONTEXT_SETTING_INT(tls_authentication)
CONTEXT_SETTING_INT(round_robin_upstreams)
CONTEXT_SETTING_INT(tls_backoff_time)
CONTEXT_SETTING_INT(tls_connection_retries)
CONTEXT_SETTING_INT(tls_query_padding_blocksize) CONTEXT_SETTING_INT(tls_query_padding_blocksize)
/**************************************/ /**************************************/

View File

@ -220,6 +220,9 @@ typedef struct getdns_upstreams {
size_t referenced; size_t referenced;
size_t count; size_t count;
size_t current_udp; size_t current_udp;
size_t current_stateful;
uint16_t tls_backoff_time;
uint16_t tls_connection_retries;
getdns_upstream upstreams[]; getdns_upstream upstreams[];
} getdns_upstreams; } getdns_upstreams;
@ -251,6 +254,9 @@ struct getdns_context {
uint32_t dnssec_allowed_skew; uint32_t dnssec_allowed_skew;
getdns_tls_authentication_t tls_auth; /* What user requested for TLS*/ getdns_tls_authentication_t tls_auth; /* What user requested for TLS*/
getdns_tls_authentication_t tls_auth_min; /* Derived minimum auth allowed*/ getdns_tls_authentication_t tls_auth_min; /* Derived minimum auth allowed*/
uint8_t round_robin_upstreams;
uint16_t tls_backoff_time;
uint16_t tls_connection_retries;
getdns_transport_list_t *dns_transports; getdns_transport_list_t *dns_transports;
size_t dns_transport_count; size_t dns_transport_count;
@ -294,6 +300,14 @@ struct getdns_context {
*/ */
_getdns_rbtree_t outbound_requests; _getdns_rbtree_t outbound_requests;
/* network requests
*/
size_t netreqs_in_flight;
_getdns_rbtree_t pending_netreqs;
getdns_network_req *first_pending_netreq;
getdns_eventloop_event pending_timeout_event;
struct listen_set *server; struct listen_set *server;
/* Event loop extension. */ /* Event loop extension. */
@ -392,7 +406,6 @@ void _getdns_context_clear_outbound_request(getdns_dns_req *dnsreq);
*/ */
void _getdns_context_cancel_request(getdns_dns_req *dnsreq); void _getdns_context_cancel_request(getdns_dns_req *dnsreq);
/* Calls user callback (with GETDNS_CALLBACK_TIMEOUT + response dict), then /* Calls user callback (with GETDNS_CALLBACK_TIMEOUT + response dict), then
* cancels and frees the getdns_dns_req with _getdns_context_cancel_request() * cancels and frees the getdns_dns_req with _getdns_context_cancel_request()
*/ */

View File

@ -3032,6 +3032,7 @@ static void check_chain_complete(chain_head *chain)
int r = GETDNS_RETURN_GOOD; int r = GETDNS_RETURN_GOOD;
getdns_network_req **netreq_p, *netreq; getdns_network_req **netreq_p, *netreq;
uint64_t now_ms = 0;
dnsreq->avoid_dnssec_roadblocks = 1; dnsreq->avoid_dnssec_roadblocks = 1;
@ -3039,9 +3040,9 @@ static void check_chain_complete(chain_head *chain)
; !r && (netreq = *netreq_p) ; !r && (netreq = *netreq_p)
; netreq_p++) { ; netreq_p++) {
netreq->state = NET_REQ_NOT_SENT; _getdns_netreq_change_state(netreq, NET_REQ_NOT_SENT);
netreq->owner = dnsreq; netreq->owner = dnsreq;
r = _getdns_submit_netreq(netreq); r = _getdns_submit_netreq(netreq, &now_ms);
} }
return; return;
} }

View File

@ -90,17 +90,28 @@ void
_getdns_check_dns_req_complete(getdns_dns_req *dns_req) _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
{ {
getdns_network_req **netreq_p, *netreq; getdns_network_req **netreq_p, *netreq;
int results_found = 0, r; int results_found = 0, timed_out = 1, r;
uint64_t now_ms = 0;
for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++) for (netreq_p = dns_req->netreqs; (netreq = *netreq_p); netreq_p++)
if (!_getdns_netreq_finished(netreq)) if (!_getdns_netreq_finished(netreq))
return; return;
else if (netreq->response_len > 0) else {
results_found = 1; if (netreq->state != NET_REQ_TIMED_OUT)
timed_out = 0;
if (netreq->response_len > 0)
results_found = 1;
}
if (timed_out) {
_getdns_context_request_timed_out(dns_req);
return;
}
/* Do we have to check more suffixes on nxdomain/nodata? /* Do we have to check more suffixes on nxdomain/nodata?
*/ */
if (dns_req->suffix_appended && /* Something was appended */ if (dns_req->is_dns_request &&
dns_req->suffix_appended && /* Something was appended */
dns_req->suffix_len > 1 && /* Next suffix available */ dns_req->suffix_len > 1 && /* Next suffix available */
no_answer(dns_req)) { no_answer(dns_req)) {
/* Remove suffix from name */ /* Remove suffix from name */
@ -126,16 +137,17 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
; (netreq = *netreq_p) ; (netreq = *netreq_p)
; netreq_p++ ) { ; netreq_p++ ) {
_getdns_netreq_reinit(netreq); _getdns_netreq_reinit(netreq);
if ((r = _getdns_submit_netreq(netreq))) { if ((r = _getdns_submit_netreq(netreq, &now_ms))) {
if (r == DNS_REQ_FINISHED) if (r == DNS_REQ_FINISHED)
return; return;
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
} }
} }
_getdns_check_dns_req_complete(dns_req); _getdns_check_dns_req_complete(dns_req);
return; return;
} }
} else if ( } else if (
dns_req->is_dns_request &&
( dns_req->append_name == ( dns_req->append_name ==
GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE || GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE ||
dns_req->append_name == dns_req->append_name ==
@ -164,10 +176,10 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
; (netreq = *netreq_p) ; (netreq = *netreq_p)
; netreq_p++ ) { ; netreq_p++ ) {
_getdns_netreq_reinit(netreq); _getdns_netreq_reinit(netreq);
if ((r = _getdns_submit_netreq(netreq))) { if ((r = _getdns_submit_netreq(netreq, &now_ms))) {
if (r == DNS_REQ_FINISHED) if (r == DNS_REQ_FINISHED)
return; return;
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
} }
} }
_getdns_check_dns_req_complete(dns_req); _getdns_check_dns_req_complete(dns_req);
@ -179,7 +191,9 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
dns_req->internal_cb(dns_req); dns_req->internal_cb(dns_req);
} else if (! results_found) } else if (! results_found)
_getdns_call_user_callback(dns_req, NULL); _getdns_call_user_callback(dns_req, NULL);
else if (dns_req->dnssec_return_validation_chain else if (
dns_req->is_dns_request &&
(dns_req->dnssec_return_validation_chain
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
|| ( dns_req->dnssec_roadblock_avoidance || ( dns_req->dnssec_roadblock_avoidance
&& !dns_req->avoid_dnssec_roadblocks) && !dns_req->avoid_dnssec_roadblocks)
@ -192,7 +206,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
dns_req->dnssec_return_all_statuses dns_req->dnssec_return_all_statuses
)) ))
#endif #endif
) ))
_getdns_get_validation_chain(dns_req); _getdns_get_validation_chain(dns_req);
else else
_getdns_call_user_callback( _getdns_call_user_callback(
@ -208,7 +222,7 @@ ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len,
getdns_network_req *netreq = (getdns_network_req *) arg; getdns_network_req *netreq = (getdns_network_req *) arg;
getdns_dns_req *dns_req = netreq->owner; getdns_dns_req *dns_req = netreq->owner;
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
/* parse */ /* parse */
if (getdns_apply_network_result( if (getdns_apply_network_result(
netreq, rcode, pkt, pkt_len, sec, why_bogus)) { netreq, rcode, pkt, pkt_len, sec, why_bogus)) {
@ -226,7 +240,7 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res)
getdns_network_req *netreq = (getdns_network_req *) arg; getdns_network_req *netreq = (getdns_network_req *) arg;
getdns_dns_req *dns_req = netreq->owner; getdns_dns_req *dns_req = netreq->owner;
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
if (err != 0) { if (err != 0) {
_getdns_call_user_callback(dns_req, NULL); _getdns_call_user_callback(dns_req, NULL);
return; return;
@ -247,28 +261,124 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res)
#endif #endif
void _getdns_check_expired_pending_netreqs(
getdns_context *context, uint64_t *now_ms)
{
getdns_network_req *first;
assert(context);
while (context->pending_netreqs.count) {
first = (getdns_network_req *)
_getdns_rbtree_first(&context->pending_netreqs);
if (_getdns_ms_until_expiry2(first->owner->expires, now_ms) > 0)
break;
(void) _getdns_rbtree_delete(&context->pending_netreqs, first);
_getdns_netreq_change_state(first, NET_REQ_TIMED_OUT);
_getdns_check_dns_req_complete(first->owner);
}
first = context->pending_netreqs.count ? (getdns_network_req *)
_getdns_rbtree_first(&context->pending_netreqs) : NULL;
if (first == context->first_pending_netreq ||
(first && context->first_pending_netreq &&
first->owner->expires == context->first_pending_netreq->owner->expires))
return; /* Nothing changed */
if (context->first_pending_netreq)
GETDNS_CLEAR_EVENT( context->extension
, &context->pending_timeout_event);
if ((context->first_pending_netreq = first))
GETDNS_SCHEDULE_EVENT( context->extension, -1,
_getdns_ms_until_expiry2(first->owner->expires, now_ms),
&context->pending_timeout_event);
}
void
_getdns_netreq_change_state(
getdns_network_req *netreq, network_req_state new_state)
{
getdns_context *context;
uint64_t now_ms;
getdns_network_req *prev;
if (!netreq || !netreq->owner->is_dns_request)
return;
context = netreq->owner->context;
if (netreq->state != NET_REQ_IN_FLIGHT) {
if (new_state == NET_REQ_IN_FLIGHT)
context->netreqs_in_flight += 1;
netreq->state = new_state;
return;
}
if (new_state == NET_REQ_IN_FLIGHT) /* No change */
return;
netreq->state = new_state;
context->netreqs_in_flight -= 1;
now_ms = 0;
prev = NULL;
while (context->pending_netreqs.count > 0 &&
( context->limit_outstanding_queries > context->netreqs_in_flight
|| context->limit_outstanding_queries == 0 )) {
getdns_network_req *first = (getdns_network_req *)
_getdns_rbtree_first(&context->pending_netreqs);
/* To prevent loops due to _getdns_submit_netreq re-inserting
* because of errno == EMFILE
*/
if (first == prev)
break;
else
prev = first;
(void) _getdns_rbtree_delete(&context->pending_netreqs, first);
(void) _getdns_submit_netreq(first, &now_ms);
}
}
int int
_getdns_submit_netreq(getdns_network_req *netreq) _getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms)
{ {
getdns_return_t r; getdns_return_t r;
getdns_dns_req *dns_req = netreq->owner; getdns_dns_req *dns_req = netreq->owner;
getdns_context *context = dns_req->context;
char name[1024]; char name[1024];
int dnsreq_freed = 0; int dnsreq_freed = 0;
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
int ub_resolve_r; int ub_resolve_r;
#endif #endif
if (context->limit_outstanding_queries > 0 &&
context->netreqs_in_flight >= context->limit_outstanding_queries) {
netreq->node.key = netreq;
if (_getdns_rbtree_insert(
&context->pending_netreqs, &netreq->node)) {
_getdns_check_expired_pending_netreqs(context, now_ms);
return GETDNS_RETURN_GOOD;
}
}
_getdns_netreq_change_state(netreq, NET_REQ_IN_FLIGHT);
#ifdef STUB_NATIVE_DNSSEC #ifdef STUB_NATIVE_DNSSEC
# ifdef DNSSEC_ROADBLOCK_AVOIDANCE # ifdef DNSSEC_ROADBLOCK_AVOIDANCE
if ((dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING if ((context->resolution_type == GETDNS_RESOLUTION_RECURSING
&& !dns_req->dnssec_roadblock_avoidance) && !dns_req->dnssec_roadblock_avoidance)
|| dns_req->avoid_dnssec_roadblocks) { || dns_req->avoid_dnssec_roadblocks) {
# else # else
if ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING) { if ( context->resolution_type == GETDNS_RESOLUTION_RECURSING) {
# endif # endif
#else #else
if ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING if ( context->resolution_type == GETDNS_RESOLUTION_RECURSING
|| dns_req->dnssec_return_status || dns_req->dnssec_return_status
|| dns_req->dnssec_return_only_secure || dns_req->dnssec_return_only_secure
|| dns_req->dnssec_return_all_statuses || dns_req->dnssec_return_all_statuses
@ -284,7 +394,8 @@ _getdns_submit_netreq(getdns_network_req *netreq)
_getdns_context_request_timed_out; _getdns_context_request_timed_out;
dns_req->timeout.ev = NULL; dns_req->timeout.ev = NULL;
if ((r = dns_req->loop->vmt->schedule(dns_req->loop, -1, if ((r = dns_req->loop->vmt->schedule(dns_req->loop, -1,
dns_req->context->timeout, &dns_req->timeout))) _getdns_ms_until_expiry2(dns_req->expires, now_ms),
&dns_req->timeout)))
return r; return r;
} }
(void) gldns_wire2str_dname_buf(dns_req->name, (void) gldns_wire2str_dname_buf(dns_req->name,
@ -293,15 +404,15 @@ _getdns_submit_netreq(getdns_network_req *netreq)
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
dns_req->freed = &dnsreq_freed; dns_req->freed = &dnsreq_freed;
#ifdef HAVE_UNBOUND_EVENT_API #ifdef HAVE_UNBOUND_EVENT_API
if (_getdns_ub_loop_enabled(&dns_req->context->ub_loop)) if (_getdns_ub_loop_enabled(&context->ub_loop))
ub_resolve_r = ub_resolve_event(dns_req->context->unbound_ctx, ub_resolve_r = ub_resolve_event(context->unbound_ctx,
name, netreq->request_type, netreq->owner->request_class, name, netreq->request_type, dns_req->request_class,
netreq, ub_resolve_event_callback, &(netreq->unbound_id)) ? netreq, ub_resolve_event_callback, &(netreq->unbound_id)) ?
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD; GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
else else
#endif #endif
ub_resolve_r = ub_resolve_async(dns_req->context->unbound_ctx, ub_resolve_r = ub_resolve_async(context->unbound_ctx,
name, netreq->request_type, netreq->owner->request_class, name, netreq->request_type, dns_req->request_class,
netreq, ub_resolve_callback, &(netreq->unbound_id)) ? netreq, ub_resolve_callback, &(netreq->unbound_id)) ?
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD; GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
if (dnsreq_freed) if (dnsreq_freed)
@ -314,7 +425,7 @@ _getdns_submit_netreq(getdns_network_req *netreq)
} }
/* Submit with stub resolver */ /* Submit with stub resolver */
dns_req->freed = &dnsreq_freed; dns_req->freed = &dnsreq_freed;
r = _getdns_submit_stub_request(netreq); r = _getdns_submit_stub_request(netreq, now_ms);
if (dnsreq_freed) if (dnsreq_freed)
return DNS_REQ_FINISHED; return DNS_REQ_FINISHED;
dns_req->freed = NULL; dns_req->freed = NULL;
@ -413,6 +524,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
getdns_dns_req *req; getdns_dns_req *req;
getdns_dict *localnames_response; getdns_dict *localnames_response;
size_t i; size_t i;
uint64_t now_ms = 0;
if (!context || !name || (!callbackfn && !internal_cb)) if (!context || !name || (!callbackfn && !internal_cb))
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
@ -430,7 +542,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
/* create the request */ /* create the request */
if (!(req = _getdns_dns_req_new( if (!(req = _getdns_dns_req_new(
context, loop, name, request_type, extensions))) context, loop, name, request_type, extensions, &now_ms)))
return GETDNS_RETURN_MEMORY_ERROR; return GETDNS_RETURN_MEMORY_ERROR;
req->user_pointer = userarg; req->user_pointer = userarg;
@ -448,13 +560,13 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
for ( netreq_p = req->netreqs for ( netreq_p = req->netreqs
; !r && (netreq = *netreq_p) ; !r && (netreq = *netreq_p)
; netreq_p++) { ; netreq_p++) {
if ((r = _getdns_submit_netreq(netreq))) { if ((r = _getdns_submit_netreq(netreq, &now_ms))) {
if (r == DNS_REQ_FINISHED) { if (r == DNS_REQ_FINISHED) {
if (return_netreq_p) if (return_netreq_p)
*return_netreq_p = NULL; *return_netreq_p = NULL;
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
} }
} }
@ -463,7 +575,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
if (!(r = _getdns_context_local_namespace_resolve( if (!(r = _getdns_context_local_namespace_resolve(
req, &localnames_response))) { req, &localnames_response))) {
req->is_dns_request = 0;
_getdns_call_user_callback _getdns_call_user_callback
( req, localnames_response); ( req, localnames_response);
break; break;
@ -473,6 +585,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
/* Check whether the name belongs in the MDNS space */ /* Check whether the name belongs in the MDNS space */
if (!(r = _getdns_mdns_namespace_check(req))) if (!(r = _getdns_mdns_namespace_check(req)))
{ {
req->is_dns_request = 0;
// Submit the query to the MDNS transport. // Submit the query to the MDNS transport.
for (netreq_p = req->netreqs for (netreq_p = req->netreqs
; !r && (netreq = *netreq_p) ; !r && (netreq = *netreq_p)
@ -483,7 +596,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
*return_netreq_p = NULL; *return_netreq_p = NULL;
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
} }
} }
/* Stop processing more namespaces, since there was a match */ /* Stop processing more namespaces, since there was a match */
@ -500,13 +613,13 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
for ( netreq_p = req->netreqs for ( netreq_p = req->netreqs
; !r && (netreq = *netreq_p) ; !r && (netreq = *netreq_p)
; netreq_p++) { ; netreq_p++) {
if ((r = _getdns_submit_netreq(netreq))) { if ((r = _getdns_submit_netreq(netreq, &now_ms))) {
if (r == DNS_REQ_FINISHED) { if (r == DNS_REQ_FINISHED) {
if (return_netreq_p) if (return_netreq_p)
*return_netreq_p = NULL; *return_netreq_p = NULL;
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
} }
} }
break; break;

View File

@ -45,8 +45,20 @@
#define DNS_REQ_FINISHED -1 #define DNS_REQ_FINISHED -1
void _getdns_call_user_callback(getdns_dns_req *, getdns_dict *); void _getdns_call_user_callback(getdns_dns_req *, getdns_dict *);
/* Change state of the netreq req.
* - Increments context->netreqs_in_flight
* when state changes from NOT_SENT to IN_FLIGHT
* - Decrements context->netreqs_in_flight
* when state changes from IN_FLIGHT to FINISHED, TIMED_OUT or ERRORED
* - Resubmits NOT_SENT netreqs from context->pending_netreqs,
* when # pending_netreqs < limit_outstanding_queries
*/
void _getdns_netreq_change_state(
getdns_network_req *netreq, network_req_state new_state);
void _getdns_check_dns_req_complete(getdns_dns_req *dns_req); void _getdns_check_dns_req_complete(getdns_dns_req *dns_req);
int _getdns_submit_netreq(getdns_network_req *netreq); int _getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms);
getdns_return_t getdns_return_t

View File

@ -76,6 +76,12 @@ extern "C" {
#define GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT "Change related to getdns_context_set_tls_query_padding_blocksize" #define GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT "Change related to getdns_context_set_tls_query_padding_blocksize"
#define GETDNS_CONTEXT_CODE_PUBKEY_PINSET 621 #define GETDNS_CONTEXT_CODE_PUBKEY_PINSET 621
#define GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT "Change related to getdns_context_set_pubkey_pinset" #define GETDNS_CONTEXT_CODE_PUBKEY_PINSET_TEXT "Change related to getdns_context_set_pubkey_pinset"
#define GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS 622
#define GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS_TEXT "Change related to getdns_context_set_pubkey_pinset"
#define GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME 623
#define GETDNS_CONTEXT_CODE_TLS_BACKOFF_TIME_TEXT "Change related to getdns_context_set_pubkey_pinset"
#define GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES 624
#define GETDNS_CONTEXT_CODE_TLS_CONNECTION_RETRIES_TEXT "Change related to getdns_context_set_pubkey_pinset"
/** @} /** @}
*/ */
@ -265,6 +271,15 @@ getdns_return_t
getdns_context_set_tls_authentication( getdns_context_set_tls_authentication(
getdns_context *context, getdns_tls_authentication_t value); getdns_context *context, getdns_tls_authentication_t value);
getdns_return_t
getdns_context_set_round_robin_upstreams(getdns_context *context, uint8_t value);
getdns_return_t
getdns_context_set_tls_backoff_time(getdns_context *context, uint16_t value);
getdns_return_t
getdns_context_set_tls_connection_retries(getdns_context *context, uint16_t value);
getdns_return_t getdns_return_t
getdns_context_set_edns_client_subnet_private(getdns_context *context, uint8_t value); getdns_context_set_edns_client_subnet_private(getdns_context *context, uint8_t value);
@ -356,6 +371,18 @@ getdns_return_t
getdns_context_get_tls_authentication(getdns_context *context, getdns_context_get_tls_authentication(getdns_context *context,
getdns_tls_authentication_t* value); getdns_tls_authentication_t* value);
getdns_return_t
getdns_context_get_round_robin_upstreams(getdns_context *context,
uint8_t* value);
getdns_return_t
getdns_context_get_tls_backoff_time(getdns_context *context,
uint16_t* value);
getdns_return_t
getdns_context_get_tls_connection_retries(getdns_context *context,
uint16_t* value);
/** /**
* Get the currently registered callback function and user defined argument * Get the currently registered callback function and user defined argument
* for context changes. * for context changes.

View File

@ -26,9 +26,12 @@ getdns_context_get_limit_outstanding_queries
getdns_context_get_namespaces getdns_context_get_namespaces
getdns_context_get_num_pending_requests getdns_context_get_num_pending_requests
getdns_context_get_resolution_type getdns_context_get_resolution_type
getdns_context_get_round_robin_upstreams
getdns_context_get_suffix getdns_context_get_suffix
getdns_context_get_timeout getdns_context_get_timeout
getdns_context_get_tls_authentication 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_tls_query_padding_blocksize
getdns_context_get_update_callback getdns_context_get_update_callback
getdns_context_get_upstream_recursive_servers getdns_context_get_upstream_recursive_servers
@ -56,9 +59,12 @@ getdns_context_set_memory_functions
getdns_context_set_namespaces getdns_context_set_namespaces
getdns_context_set_resolution_type getdns_context_set_resolution_type
getdns_context_set_return_dnssec_status getdns_context_set_return_dnssec_status
getdns_context_set_round_robin_upstreams
getdns_context_set_suffix getdns_context_set_suffix
getdns_context_set_timeout getdns_context_set_timeout
getdns_context_set_tls_authentication 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_tls_query_padding_blocksize
getdns_context_set_update_callback getdns_context_set_update_callback
getdns_context_set_upstream_recursive_servers getdns_context_set_upstream_recursive_servers

View File

@ -513,7 +513,7 @@ static void msdn_cache_deldata(void* vdata, void* vcontext)
/* TODO: treating as a timeout for now, may consider treating as error */ /* TODO: treating as a timeout for now, may consider treating as error */
netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->debug_end_time = _getdns_get_time_as_uintt64();
netreq->state = NET_REQ_TIMED_OUT; _getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
if (netreq->owner->user_callback) { if (netreq->owner->user_callback) {
(void)_getdns_context_request_timed_out(netreq->owner); (void)_getdns_context_request_timed_out(netreq->owner);
} }
@ -788,7 +788,9 @@ mdns_update_cache_ttl_and_prune(struct getdns_context *context,
memmove(old_record + last_copied_index, old_record + current_hole_index, memmove(old_record + last_copied_index, old_record + current_hole_index,
answer_index - current_hole_index); answer_index - current_hole_index);
last_copied_index += answer_index - current_hole_index; last_copied_index += answer_index - current_hole_index;
answer_index = last_copied_index;
/* dead assignment */
/* answer_index = last_copied_index; */
} }
/* if some records were deleted, update the record headers */ /* if some records were deleted, update the record headers */
@ -1008,7 +1010,7 @@ mdns_complete_query_from_cache_entry(
netreq->response_len = packet_length; netreq->response_len = packet_length;
netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->debug_end_time = _getdns_get_time_as_uintt64();
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
_getdns_check_dns_req_complete(netreq->owner); _getdns_check_dns_req_complete(netreq->owner);
} }
else else
@ -1016,7 +1018,7 @@ mdns_complete_query_from_cache_entry(
/* Fail the query? */ /* Fail the query? */
netreq->response_len = 0; netreq->response_len = 0;
netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->debug_end_time = _getdns_get_time_as_uintt64();
netreq->state = NET_REQ_ERRORED; _getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
_getdns_check_dns_req_complete(netreq->owner); _getdns_check_dns_req_complete(netreq->owner);
} }
} }
@ -1026,7 +1028,7 @@ mdns_complete_query_from_cache_entry(
/* Failure */ /* Failure */
netreq->response_len = 0; netreq->response_len = 0;
netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->debug_end_time = _getdns_get_time_as_uintt64();
netreq->state = NET_REQ_ERRORED; _getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
_getdns_check_dns_req_complete(netreq->owner); _getdns_check_dns_req_complete(netreq->owner);
} }
@ -1085,7 +1087,7 @@ mdns_mcast_timeout_cb(void *userarg)
int found = 0; int found = 0;
DEBUG_MDNS("%s %-35s: MSG: %p\n", DEBUG_MDNS("%s %-35s: MSG: %p\n",
MDNS_DEBUG_CLEANUP, __FUNCTION__, netreq); MDNS_DEBUG_CLEANUP, __FUNC__, netreq);
msdn_cache_create_key_in_buffer(temp_key, dnsreq->name, dnsreq->name_len, msdn_cache_create_key_in_buffer(temp_key, dnsreq->name, dnsreq->name_len,
netreq->request_type, dnsreq->request_class); netreq->request_type, dnsreq->request_class);
@ -1113,7 +1115,7 @@ mdns_mcast_timeout_cb(void *userarg)
/* Fail the request on timeout */ /* Fail the request on timeout */
netreq->response_len = 0; netreq->response_len = 0;
netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->debug_end_time = _getdns_get_time_as_uintt64();
netreq->state = NET_REQ_ERRORED; _getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
_getdns_check_dns_req_complete(netreq->owner); _getdns_check_dns_req_complete(netreq->owner);
} }
} }
@ -1128,7 +1130,7 @@ mdns_udp_multicast_read_cb(void *userarg)
uint64_t current_time; uint64_t current_time;
ssize_t read; ssize_t read;
DEBUG_MDNS("%s %-35s: CTX: %p, NET=%d \n", MDNS_DEBUG_MREAD, DEBUG_MDNS("%s %-35s: CTX: %p, NET=%d \n", MDNS_DEBUG_MREAD,
__FUNCTION__, cnx->context, cnx->addr_mcast.ss_family); __FUNC__, cnx->context, cnx->addr_mcast.ss_family);
current_time = _getdns_get_time_as_uintt64(); current_time = _getdns_get_time_as_uintt64();
@ -1699,7 +1701,7 @@ mdns_timeout_cb(void *userarg)
#else #else
close(netreq->fd); close(netreq->fd);
#endif #endif
netreq->state = NET_REQ_TIMED_OUT; _getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
if (netreq->owner->user_callback) { if (netreq->owner->user_callback) {
netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->debug_end_time = _getdns_get_time_as_uintt64();
(void)_getdns_context_request_timed_out(netreq->owner); (void)_getdns_context_request_timed_out(netreq->owner);
@ -1760,7 +1762,7 @@ mdns_udp_read_cb(void *userarg)
netreq->response_len = read; netreq->response_len = read;
netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->debug_end_time = _getdns_get_time_as_uintt64();
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
_getdns_check_dns_req_complete(dnsreq); _getdns_check_dns_req_complete(dnsreq);
} }

View File

@ -43,6 +43,7 @@
#include "dict.h" #include "dict.h"
#include "debug.h" #include "debug.h"
#include "convert.h" #include "convert.h"
#include "general.h"
/* MAXIMUM_TSIG_SPACE = TSIG name (dname) : 256 /* MAXIMUM_TSIG_SPACE = TSIG name (dname) : 256
* TSIG type (uint16_t) : 2 * TSIG type (uint16_t) : 2
@ -118,7 +119,7 @@ netreq_reset(getdns_network_req *net_req)
/* variables that need to be reset on reinit /* variables that need to be reset on reinit
*/ */
net_req->unbound_id = -1; net_req->unbound_id = -1;
net_req->state = NET_REQ_NOT_SENT; _getdns_netreq_change_state(net_req, NET_REQ_NOT_SENT);
net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE; net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE; net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE;
net_req->query_id = 0; net_req->query_id = 0;
@ -183,6 +184,10 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
net_req->debug_tls_auth_status = GETDNS_AUTH_NONE; net_req->debug_tls_auth_status = GETDNS_AUTH_NONE;
net_req->debug_udp = 0; net_req->debug_udp = 0;
/* Scheduling, touch only via _getdns_netreq_change_state!
*/
net_req->state = NET_REQ_NOT_SENT;
if (max_query_sz == 0) { if (max_query_sz == 0) {
net_req->query = NULL; net_req->query = NULL;
net_req->opt = NULL; net_req->opt = NULL;
@ -658,7 +663,8 @@ static const uint8_t no_suffixes[] = { 1, 0 };
/* create a new dns req to be submitted */ /* create a new dns req to be submitted */
getdns_dns_req * getdns_dns_req *
_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions) const char *name, uint16_t request_type, getdns_dict *extensions,
uint64_t *now_ms)
{ {
int dnssec_return_status = is_extension_set( int dnssec_return_status = is_extension_set(
extensions, "dnssec_return_status", extensions, "dnssec_return_status",
@ -932,6 +938,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
result->finished_next = NULL; result->finished_next = NULL;
result->freed = NULL; result->freed = NULL;
result->validating = 0; result->validating = 0;
result->is_dns_request = 1;
result->chain = NULL; result->chain = NULL;
network_req_init(result->netreqs[0], result, network_req_init(result->netreqs[0], result,
@ -953,5 +960,10 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
netreq_sz - sizeof(getdns_network_req), max_query_sz, netreq_sz - sizeof(getdns_network_req), max_query_sz,
extensions); extensions);
if (*now_ms == 0 && (*now_ms = _getdns_get_now_ms()) == 0)
result->expires = 0;
else
result->expires = *now_ms + context->timeout;
return result; return result;
} }

View File

@ -54,15 +54,18 @@ typedef u_short sa_family_t;
#define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\ #define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\
WSAGetLastError() == WSAEWOULDBLOCK) WSAGetLastError() == WSAEWOULDBLOCK)
#define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS) #define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS)
#define _getdns_EMFILE (WSAGetLastError() == WSAEMFILE)
#else #else
#define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK) #define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK)
#define _getdns_EINPROGRESS (errno == EINPROGRESS) #define _getdns_EINPROGRESS (errno == EINPROGRESS)
#define _getdns_EMFILE (errno == EMFILE)
#endif #endif
/* WSA TODO: /* WSA TODO:
* STUB_TCP_WOULDBLOCK added to deal with edge triggered event loops (versus * STUB_TCP_WOULDBLOCK added to deal with edge triggered event loops (versus
* level triggered). See also lines containing WSA TODO below... * level triggered). See also lines containing WSA TODO below...
*/ */
#define STUB_TRY_AGAIN_LATER -24 /* EMFILE, i.e. Out of OS resources */
#define STUB_NO_AUTH -8 /* Existing TLS connection is not authenticated */ #define STUB_NO_AUTH -8 /* Existing TLS connection is not authenticated */
#define STUB_CONN_GONE -7 /* Connection has failed, clear queue*/ #define STUB_CONN_GONE -7 /* Connection has failed, clear queue*/
#define STUB_TCP_WOULDBLOCK -6 #define STUB_TCP_WOULDBLOCK -6
@ -550,7 +553,7 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
netreq = (getdns_network_req *) netreq = (getdns_network_req *)
_getdns_rbtree_first(&upstream->netreq_by_query_id); _getdns_rbtree_first(&upstream->netreq_by_query_id);
stub_cleanup(netreq); stub_cleanup(netreq);
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
_getdns_check_dns_req_complete(netreq->owner); _getdns_check_dns_req_complete(netreq->owner);
} }
} }
@ -580,7 +583,7 @@ stub_timeout_cb(void *userarg)
DEBUG_STUB("%s %-35s: MSG: %p\n", DEBUG_STUB("%s %-35s: MSG: %p\n",
STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq); STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq);
stub_cleanup(netreq); stub_cleanup(netreq);
netreq->state = NET_REQ_TIMED_OUT; _getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
/* Handle upstream*/ /* Handle upstream*/
if (netreq->fd >= 0) { if (netreq->fd >= 0) {
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
@ -591,7 +594,7 @@ stub_timeout_cb(void *userarg)
netreq->upstream->udp_timeouts++; netreq->upstream->udp_timeouts++;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG #if defined(DAEMON_DEBUG) && DAEMON_DEBUG
if (netreq->upstream->udp_timeouts % 100 == 0) if (netreq->upstream->udp_timeouts % 100 == 0)
DEBUG_DAEMON("%s %s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n", DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
STUB_DEBUG_DAEMON, netreq->upstream->addr_str, STUB_DEBUG_DAEMON, netreq->upstream->addr_str,
(int)netreq->upstream->udp_responses, (int)netreq->upstream->udp_timeouts); (int)netreq->upstream->udp_responses, (int)netreq->upstream->udp_timeouts);
#endif #endif
@ -870,7 +873,7 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
#endif #endif
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG #if defined(DAEMON_DEBUG) && DAEMON_DEBUG
if (!preverify_ok && !upstream->tls_fallback_ok) if (!preverify_ok && !upstream->tls_fallback_ok)
DEBUG_DAEMON("%s %s : Conn failed : Transport=TLS - *Failure* - (%d) \"%s\"\n", DEBUG_DAEMON("%s %-40s : Verify failed : Transport=TLS - *Failure* - (%d) \"%s\"\n",
STUB_DEBUG_DAEMON, upstream->addr_str, err, STUB_DEBUG_DAEMON, upstream->addr_str, err,
X509_verify_cert_error_string(err)); X509_verify_cert_error_string(err));
#endif #endif
@ -907,7 +910,7 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd); STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd);
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG #if defined(DAEMON_DEBUG) && DAEMON_DEBUG
else else
DEBUG_DAEMON("%s %s : Conn failed : Transport=TLS - *Failure* - Pinset validation failure\n", DEBUG_DAEMON("%s %-40s : Conn failed : Transport=TLS - *Failure* - Pinset validation failure\n",
STUB_DEBUG_DAEMON, upstream->addr_str); STUB_DEBUG_DAEMON, upstream->addr_str);
#endif #endif
} else { } else {
@ -920,6 +923,10 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
preverify_ok = 1; preverify_ok = 1;
DEBUG_STUB("%s %-35s: FD: %d, Allowing self-signed (%d) cert since pins match\n", DEBUG_STUB("%s %-35s: FD: %d, Allowing self-signed (%d) cert since pins match\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd, err); STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd, err);
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %-40s : Verify passed : Transport=TLS - Allowing self-signed cert since pins match\n",
STUB_DEBUG_DAEMON, upstream->addr_str);
#endif
} }
} }
@ -1358,22 +1365,28 @@ stub_udp_read_cb(void *userarg)
dnsreq)) == -1) dnsreq)) == -1)
break; break;
upstream_schedule_netreq(netreq->upstream, netreq); upstream_schedule_netreq(netreq->upstream, netreq);
GETDNS_SCHEDULE_EVENT( GETDNS_SCHEDULE_EVENT(dnsreq->loop, -1,
dnsreq->loop, -1, dnsreq->context->timeout, _getdns_ms_until_expiry(dnsreq->expires),
getdns_eventloop_event_init(&netreq->event, getdns_eventloop_event_init(&netreq->event,
netreq, NULL, NULL, stub_timeout_cb)); netreq, NULL, NULL, stub_timeout_cb));
return; return;
} }
netreq->response_len = read; netreq->response_len = read;
dnsreq->upstreams->current_udp = 0; if (!dnsreq->context->round_robin_upstreams)
dnsreq->upstreams->current_udp = 0;
else {
dnsreq->upstreams->current_udp+=GETDNS_UPSTREAM_TRANSPORTS;
if (dnsreq->upstreams->current_udp >= dnsreq->upstreams->count)
dnsreq->upstreams->current_udp = 0;
}
netreq->debug_end_time = _getdns_get_time_as_uintt64(); netreq->debug_end_time = _getdns_get_time_as_uintt64();
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
upstream->udp_responses++; upstream->udp_responses++;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG #if defined(DAEMON_DEBUG) && DAEMON_DEBUG
if (upstream->udp_responses == 1 || if (upstream->udp_responses == 1 ||
upstream->udp_responses % 100 == 0) upstream->udp_responses % 100 == 0)
DEBUG_DAEMON("%s %s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n", DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=UDP - Resp=%d,Timeouts=%d\n",
STUB_DEBUG_DAEMON, upstream->addr_str, STUB_DEBUG_DAEMON, upstream->addr_str,
(int)upstream->udp_responses, (int)upstream->udp_timeouts); (int)upstream->udp_responses, (int)upstream->udp_timeouts);
#endif #endif
@ -1421,8 +1434,8 @@ stub_udp_write_cb(void *userarg)
#endif #endif
return; return;
} }
GETDNS_SCHEDULE_EVENT( GETDNS_SCHEDULE_EVENT(dnsreq->loop, netreq->fd,
dnsreq->loop, netreq->fd, dnsreq->context->timeout, _getdns_ms_until_expiry(dnsreq->expires),
getdns_eventloop_event_init(&netreq->event, netreq, getdns_eventloop_event_init(&netreq->event, netreq,
stub_udp_read_cb, NULL, stub_timeout_cb)); stub_udp_read_cb, NULL, stub_timeout_cb));
} }
@ -1495,7 +1508,7 @@ upstream_read_cb(void *userarg)
DEBUG_STUB("%s %-35s: MSG: %p (read)\n", DEBUG_STUB("%s %-35s: MSG: %p (read)\n",
STUB_DEBUG_READ, __FUNC__, (void*)netreq); STUB_DEBUG_READ, __FUNC__, (void*)netreq);
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
netreq->response = upstream->tcp.read_buf; netreq->response = upstream->tcp.read_buf;
netreq->response_len = netreq->response_len =
upstream->tcp.read_pos - upstream->tcp.read_buf; upstream->tcp.read_pos - upstream->tcp.read_buf;
@ -1608,13 +1621,13 @@ upstream_write_cb(void *userarg)
/* Cleaning up after connection or auth check failure. Need to fallback. */ /* Cleaning up after connection or auth check failure. Need to fallback. */
stub_cleanup(netreq); stub_cleanup(netreq);
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG #if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %s : Conn closed : Transport=%s - *Failure*\n", DEBUG_DAEMON("%s %-40s : Conn closed : Transport=%s - *Failure*\n",
STUB_DEBUG_DAEMON, upstream->addr_str, STUB_DEBUG_DAEMON, upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP")); (upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"));
#endif #endif
if (fallback_on_write(netreq) == STUB_TCP_ERROR) { if (fallback_on_write(netreq) == STUB_TCP_ERROR) {
/* TODO: Need new state to report transport unavailable*/ /* TODO: Need new state to report transport unavailable*/
netreq->state = NET_REQ_FINISHED; _getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
_getdns_check_dns_req_complete(netreq->owner); _getdns_check_dns_req_complete(netreq->owner);
} }
return; return;
@ -1659,7 +1672,8 @@ upstream_working_ok(getdns_upstream *upstream)
{ {
/* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/ /* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/
return (upstream->responses_timeouts > return (upstream->responses_timeouts >
upstream->responses_received*GETDNS_CONN_ATTEMPTS ? 0 : 1); upstream->responses_received*
upstream->upstreams->tls_connection_retries ? 0 : 1);
} }
static int static int
@ -1672,6 +1686,17 @@ upstream_active(getdns_upstream *upstream)
return 0; return 0;
} }
static int
upstream_usable(getdns_upstream *upstream)
{
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;
return 0;
}
static int static int
upstream_auth_status_ok(getdns_upstream *upstream, getdns_network_req *netreq) { upstream_auth_status_ok(getdns_upstream *upstream, getdns_network_req *netreq) {
if (netreq->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED) if (netreq->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED)
@ -1692,10 +1717,16 @@ upstream_valid(getdns_upstream *upstream,
getdns_transport_list_t transport, getdns_transport_list_t transport,
getdns_network_req *netreq) getdns_network_req *netreq)
{ {
if (upstream->transport != transport || upstream->conn_state != GETDNS_CONN_CLOSED) if (!(upstream->transport == transport && upstream_usable(upstream)))
return 0; return 0;
if (transport == GETDNS_TRANSPORT_TCP) if (transport == GETDNS_TRANSPORT_TCP)
return 1; return 1;
if (upstream->conn_state == GETDNS_CONN_OPEN) {
if (!upstream_auth_status_ok(upstream, netreq))
return 0;
else
return 1;
}
/* We need to check past authentication history to see if this is usable for TLS.*/ /* We need to check past authentication history to see if this is usable for TLS.*/
if (netreq->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED) if (netreq->tls_auth_min != GETDNS_AUTHENTICATION_REQUIRED)
return 1; return 1;
@ -1738,37 +1769,55 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
upstreams->upstreams[i].conn_retry_time < now) { upstreams->upstreams[i].conn_retry_time < now) {
upstreams->upstreams[i].conn_state = GETDNS_CONN_CLOSED; upstreams->upstreams[i].conn_state = GETDNS_CONN_CLOSED;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG #if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %s : Re-instating upstream\n", DEBUG_DAEMON("%s %-40s : Re-instating upstream\n",
STUB_DEBUG_DAEMON, upstreams->upstreams[i].addr_str); STUB_DEBUG_DAEMON, upstreams->upstreams[i].addr_str);
#endif #endif
} }
} }
/* First find if an open upstream has the correct properties and use that*/ if (netreq->owner->context->round_robin_upstreams == 0) {
for (i = 0; i < upstreams->count; i++) { /* First find if an open upstream has the correct properties and use that*/
if (upstream_valid_and_open(&upstreams->upstreams[i], transport, netreq)) for (i = 0; i < upstreams->count; i++) {
return &upstreams->upstreams[i]; if (upstream_valid_and_open(&upstreams->upstreams[i], transport, netreq))
return &upstreams->upstreams[i];
}
} }
/* OK - we will have to open one. Choose the first one that has the best stats /* OK - Find the next one to use. First check we have at least one valid
and the right properties, but because we completely back off failed upstream because we completely back off failed
upstreams we may have no valid upstream at all (in contrast to UDP). This upstreams we may have no valid upstream at all (in contrast to UDP). This
will be better communicated to the user when we have better error codes*/ will be better communicated to the user when we have better error codes*/
for (i = 0; i < upstreams->count; i++) { i = upstreams->current_stateful;
do {
DEBUG_STUB("%s %-35s: Testing upstreams %d %d\n", STUB_DEBUG_SETUP, DEBUG_STUB("%s %-35s: Testing upstreams %d %d\n", STUB_DEBUG_SETUP,
__FUNC__, (int)i, (int)upstreams->upstreams[i].conn_state); __FUNC__, (int)i, (int)upstreams->upstreams[i].conn_state);
if (upstream_valid(&upstreams->upstreams[i], transport, netreq)) { if (upstream_valid(&upstreams->upstreams[i], transport, netreq)) {
upstream = &upstreams->upstreams[i]; upstream = &upstreams->upstreams[i];
break; break;
} }
} i++;
if (i >= upstreams->count)
i = 0;
} while (i != upstreams->current_stateful);
if (!upstream) if (!upstream)
return NULL; return NULL;
for (i++; i < upstreams->count; i++) {
if (upstream_valid(&upstreams->upstreams[i], transport, netreq) && /* Now select the specific upstream */
upstream_stats(&upstreams->upstreams[i]) > upstream_stats(upstream)) if (netreq->owner->context->round_robin_upstreams == 0) {
upstream = &upstreams->upstreams[i]; /* Base the decision on the stats, noting we will have started from 0*/
for (i++; i < upstreams->count; i++) {
if (upstream_valid(&upstreams->upstreams[i], transport, netreq) &&
upstream_stats(&upstreams->upstreams[i]) > upstream_stats(upstream))
upstream = &upstreams->upstreams[i];
}
} else {
/* Simplistic, but always just pick the first one, incrementing the current.
Note we are not distinguishing TCP/TLS here....*/
upstreams->current_stateful+=GETDNS_UPSTREAM_TRANSPORTS;
if (upstreams->current_stateful >= upstreams->count)
upstreams->current_stateful = 0;
} }
return upstream; return upstream;
} }
@ -1853,7 +1902,7 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
} }
upstream->conn_state = GETDNS_CONN_SETUP; upstream->conn_state = GETDNS_CONN_SETUP;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG #if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %s : Conn init : Transport=%s - Profile=%s\n", STUB_DEBUG_DAEMON, DEBUG_DAEMON("%s %-40s : Conn init : Transport=%s - Profile=%s\n", STUB_DEBUG_DAEMON,
upstream->addr_str, transport == GETDNS_TRANSPORT_TLS ? "TLS":"TCP", upstream->addr_str, transport == GETDNS_TRANSPORT_TLS ? "TLS":"TCP",
dnsreq->context->tls_auth_min == GETDNS_AUTHENTICATION_NONE ? "Opportunistic":"Strict"); dnsreq->context->tls_auth_min == GETDNS_AUTHENTICATION_NONE ? "Opportunistic":"Strict");
#endif #endif
@ -1905,8 +1954,14 @@ upstream_find_for_netreq(getdns_network_req *netreq)
upstream = upstream_find_for_transport(netreq, upstream = upstream_find_for_transport(netreq,
netreq->transports[i], netreq->transports[i],
&fd); &fd);
if (fd == -1 || !upstream) if (!upstream)
continue; continue;
if (fd == -1) {
if (_getdns_EMFILE)
return STUB_TRY_AGAIN_LATER;
return -1;
}
netreq->transport_current = i; netreq->transport_current = i;
netreq->upstream = upstream; netreq->upstream = upstream;
netreq->keepalive_sent = 0; netreq->keepalive_sent = 0;
@ -1928,12 +1983,13 @@ upstream_find_for_netreq(getdns_network_req *netreq)
static int static int
fallback_on_write(getdns_network_req *netreq) fallback_on_write(getdns_network_req *netreq)
{ {
uint64_t now_ms = 0;
/* Deal with UDP one day*/ /* Deal with UDP one day*/
DEBUG_STUB("%s %-35s: MSG: %p FALLING BACK \n", STUB_DEBUG_SCHEDULE, __FUNC__, (void*)netreq); DEBUG_STUB("%s %-35s: MSG: %p FALLING BACK \n", STUB_DEBUG_SCHEDULE, __FUNC__, (void*)netreq);
/* Try to find a fallback transport*/ /* Try to find a fallback transport*/
getdns_return_t result = _getdns_submit_stub_request(netreq); getdns_return_t result = _getdns_submit_stub_request(netreq, &now_ms);
if (result != GETDNS_RETURN_GOOD) if (result != GETDNS_RETURN_GOOD)
return STUB_TCP_ERROR; return STUB_TCP_ERROR;
@ -1997,8 +2053,8 @@ upstream_schedule_netreq(getdns_upstream *upstream, getdns_network_req *netreq)
if (upstream->queries_sent == 0) { if (upstream->queries_sent == 0) {
/* Set a timeout on the upstream so we can catch failed setup*/ /* Set a timeout on the upstream so we can catch failed setup*/
upstream->event.timeout_cb = upstream_setup_timeout_cb; upstream->event.timeout_cb = upstream_setup_timeout_cb;
GETDNS_SCHEDULE_EVENT(upstream->loop, GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
upstream->fd, netreq->owner->context->timeout / 2, _getdns_ms_until_expiry(netreq->owner->expires)/2,
&upstream->event); &upstream->event);
} else { } else {
GETDNS_SCHEDULE_EVENT(upstream->loop, GETDNS_SCHEDULE_EVENT(upstream->loop,
@ -2027,12 +2083,17 @@ upstream_schedule_netreq(getdns_upstream *upstream, getdns_network_req *netreq)
} }
getdns_return_t getdns_return_t
_getdns_submit_stub_request(getdns_network_req *netreq) _getdns_submit_stub_request(getdns_network_req *netreq, uint64_t *now_ms)
{ {
int fd = -1;
getdns_dns_req *dnsreq;
getdns_context *context;
DEBUG_STUB("%s %-35s: MSG: %p TYPE: %d\n", STUB_DEBUG_ENTRY, __FUNC__, DEBUG_STUB("%s %-35s: MSG: %p TYPE: %d\n", STUB_DEBUG_ENTRY, __FUNC__,
(void*)netreq, netreq->request_type); (void*)netreq, netreq->request_type);
int fd = -1;
getdns_dns_req *dnsreq = netreq->owner; dnsreq = netreq->owner;
context = dnsreq->context;
/* This does a best effort to get a initial fd. /* This does a best effort to get a initial fd.
* All other set up is done async*/ * All other set up is done async*/
@ -2040,14 +2101,20 @@ _getdns_submit_stub_request(getdns_network_req *netreq)
if (fd == -1) if (fd == -1)
return GETDNS_RETURN_NO_UPSTREAM_AVAILABLE; return GETDNS_RETURN_NO_UPSTREAM_AVAILABLE;
getdns_transport_list_t transport = else if (fd == STUB_TRY_AGAIN_LATER) {
netreq->transports[netreq->transport_current]; _getdns_netreq_change_state(netreq, NET_REQ_NOT_SENT);
switch(transport) { netreq->node.key = netreq;
if (_getdns_rbtree_insert(
&context->pending_netreqs, &netreq->node))
return GETDNS_RETURN_GOOD;
return GETDNS_RETURN_NO_UPSTREAM_AVAILABLE;
}
switch(netreq->transports[netreq->transport_current]) {
case GETDNS_TRANSPORT_UDP: case GETDNS_TRANSPORT_UDP:
netreq->fd = fd; netreq->fd = fd;
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
GETDNS_SCHEDULE_EVENT( GETDNS_SCHEDULE_EVENT(dnsreq->loop, netreq->fd,
dnsreq->loop, netreq->fd, dnsreq->context->timeout, _getdns_ms_until_expiry2(dnsreq->expires, now_ms),
getdns_eventloop_event_init(&netreq->event, netreq, getdns_eventloop_event_init(&netreq->event, netreq,
NULL, stub_udp_write_cb, stub_timeout_cb)); NULL, stub_udp_write_cb, stub_timeout_cb));
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
@ -2121,7 +2188,7 @@ _getdns_submit_stub_request(getdns_network_req *netreq)
*/ */
GETDNS_SCHEDULE_EVENT( GETDNS_SCHEDULE_EVENT(
dnsreq->loop, -1, dnsreq->loop, -1,
dnsreq->context->timeout, _getdns_ms_until_expiry2(dnsreq->expires, now_ms),
getdns_eventloop_event_init( getdns_eventloop_event_init(
&netreq->event, netreq, NULL, NULL, &netreq->event, netreq, NULL, NULL,
stub_timeout_cb)); stub_timeout_cb));

View File

@ -37,7 +37,8 @@
#include "getdns/getdns.h" #include "getdns/getdns.h"
#include "types-internal.h" #include "types-internal.h"
getdns_return_t _getdns_submit_stub_request(getdns_network_req *netreq); getdns_return_t _getdns_submit_stub_request(
getdns_network_req *netreq, uint64_t *now_ms);
void _getdns_cancel_stub_request(getdns_network_req *netreq); void _getdns_cancel_stub_request(getdns_network_req *netreq);

View File

@ -216,10 +216,13 @@ depend:
.PHONY: clean test .PHONY: clean test
# Dependencies for the unit tests # Dependencies for the unit tests
check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(srcdir)/check_getdns_common.h \ check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c \
../getdns/getdns_extra.h $(srcdir)/check_getdns_address.h \ ../getdns/getdns.h \
$(srcdir)/check_getdns_address_sync.h $(srcdir)/check_getdns_cancel_callback.h \ $(srcdir)/check_getdns_common.h \
$(srcdir)/check_getdns_context_create.h $(srcdir)/check_getdns_context_destroy.h \ ../getdns/getdns_extra.h \
$(srcdir)/check_getdns_address.h $(srcdir)/check_getdns_address_sync.h \
$(srcdir)/check_getdns_cancel_callback.h $(srcdir)/check_getdns_context_create.h \
$(srcdir)/check_getdns_context_destroy.h \
$(srcdir)/check_getdns_context_set_context_update_callback.h \ $(srcdir)/check_getdns_context_set_context_update_callback.h \
$(srcdir)/check_getdns_context_set_dns_transport.h \ $(srcdir)/check_getdns_context_set_dns_transport.h \
$(srcdir)/check_getdns_context_set_timeout.h \ $(srcdir)/check_getdns_context_set_timeout.h \
@ -239,34 +242,58 @@ check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(sr
$(srcdir)/check_getdns_list_get_list.h $(srcdir)/check_getdns_pretty_print_dict.h \ $(srcdir)/check_getdns_list_get_list.h $(srcdir)/check_getdns_pretty_print_dict.h \
$(srcdir)/check_getdns_service.h $(srcdir)/check_getdns_service_sync.h \ $(srcdir)/check_getdns_service.h $(srcdir)/check_getdns_service_sync.h \
$(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_transport.h
check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c ../getdns/getdns.h \ check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c \
../config.h $(srcdir)/check_getdns_common.h ../getdns/getdns_extra.h \ ../getdns/getdns.h \
../config.h \
$(srcdir)/check_getdns_common.h \
../getdns/getdns_extra.h \
$(srcdir)/check_getdns_eventloop.h $(srcdir)/check_getdns_eventloop.h
check_getdns_context_set_timeout.lo check_getdns_context_set_timeout.o: $(srcdir)/check_getdns_context_set_timeout.c \ check_getdns_context_set_timeout.lo check_getdns_context_set_timeout.o: $(srcdir)/check_getdns_context_set_timeout.c \
$(srcdir)/check_getdns_context_set_timeout.h $(srcdir)/check_getdns_common.h \ $(srcdir)/check_getdns_context_set_timeout.h $(srcdir)/check_getdns_common.h \
../getdns/getdns.h ../getdns/getdns_extra.h ../getdns/getdns.h \
../getdns/getdns_extra.h
check_getdns_libev.lo check_getdns_libev.o: $(srcdir)/check_getdns_libev.c $(srcdir)/check_getdns_eventloop.h \ check_getdns_libev.lo check_getdns_libev.o: $(srcdir)/check_getdns_libev.c $(srcdir)/check_getdns_eventloop.h \
../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libev.h \ ../config.h \
../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \
$(srcdir)/../getdns/getdns_ext_libev.h \
../getdns/getdns_extra.h \
$(srcdir)/check_getdns_common.h
check_getdns_libevent.lo check_getdns_libevent.o: $(srcdir)/check_getdns_libevent.c $(srcdir)/check_getdns_eventloop.h \ check_getdns_libevent.lo check_getdns_libevent.o: $(srcdir)/check_getdns_libevent.c $(srcdir)/check_getdns_eventloop.h \
../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libevent.h \ ../config.h \
../getdns/getdns_extra.h $(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \
$(srcdir)/../getdns/getdns_ext_libevent.h \
../getdns/getdns_extra.h \
$(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h
check_getdns_libuv.lo check_getdns_libuv.o: $(srcdir)/check_getdns_libuv.c $(srcdir)/check_getdns_eventloop.h \ check_getdns_libuv.lo check_getdns_libuv.o: $(srcdir)/check_getdns_libuv.c $(srcdir)/check_getdns_eventloop.h \
../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libuv.h \ ../config.h \
../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \
$(srcdir)/../getdns/getdns_ext_libuv.h \
../getdns/getdns_extra.h \
$(srcdir)/check_getdns_common.h
check_getdns_selectloop.lo check_getdns_selectloop.o: $(srcdir)/check_getdns_selectloop.c \ check_getdns_selectloop.lo check_getdns_selectloop.o: $(srcdir)/check_getdns_selectloop.c \
$(srcdir)/check_getdns_eventloop.h ../config.h ../getdns/getdns.h \ $(srcdir)/check_getdns_eventloop.h \
../config.h \
../getdns/getdns.h \
../getdns/getdns_extra.h ../getdns/getdns_extra.h
check_getdns_transport.lo check_getdns_transport.o: $(srcdir)/check_getdns_transport.c \ check_getdns_transport.lo check_getdns_transport.o: $(srcdir)/check_getdns_transport.c \
$(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \ $(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h \
../getdns/getdns.h \
../getdns/getdns_extra.h ../getdns/getdns_extra.h
scratchpad.template.lo scratchpad.template.o: scratchpad.template.c ../getdns/getdns.h \ scratchpad.template.lo scratchpad.template.o: scratchpad.template.c \
../getdns/getdns.h \
../getdns/getdns_extra.h ../getdns/getdns_extra.h
testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h
tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h ../getdns/getdns.h tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h \
tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h ../getdns/getdns.h ../getdns/getdns.h
tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h ../getdns/getdns.h tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h \
tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c ../config.h $(srcdir)/testmessages.h \ ../getdns/getdns.h
../getdns/getdns.h ../getdns/getdns_extra.h tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.h \
tests_stub_sync.lo tests_stub_sync.o: $(srcdir)/tests_stub_sync.c $(srcdir)/testmessages.h ../getdns/getdns.h \ ../getdns/getdns.h
tests_stub_async.lo tests_stub_async.o: $(srcdir)/tests_stub_async.c \
../config.h \
$(srcdir)/testmessages.h \
../getdns/getdns.h \
../getdns/getdns_extra.h
tests_stub_sync.lo tests_stub_sync.o: $(srcdir)/tests_stub_sync.c $(srcdir)/testmessages.h \
../getdns/getdns.h \
../getdns/getdns_extra.h ../getdns/getdns_extra.h

View File

@ -435,6 +435,29 @@
} }
END_TEST END_TEST
START_TEST (getdns_context_set_context_update_callback_23)
{
/*
* value is NULL
* expect: GETDNS_RETURN_INVALID_PARAMETER
*/
struct getdns_context *context = NULL;
CONTEXT_CREATE(TRUE);
ASSERT_RC(getdns_context_set_context_update_callback(context, update_callbackfn),
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_context_update_callback()");
expected_changed_item = GETDNS_CONTEXT_CODE_ROUND_ROBIN_UPSTREAMS;
ASSERT_RC(getdns_context_set_round_robin_upstreams(context, 1),
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_timeout()");
CONTEXT_DESTROY;
}
END_TEST
Suite * Suite *
getdns_context_set_context_update_callback_suite (void) getdns_context_set_context_update_callback_suite (void)
{ {
@ -462,6 +485,7 @@
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_20); tcase_add_test(tc_pos, getdns_context_set_context_update_callback_20);
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_21); tcase_add_test(tc_pos, getdns_context_set_context_update_callback_21);
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_22); tcase_add_test(tc_pos, getdns_context_set_context_update_callback_22);
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_23);
suite_add_tcase(s, tc_pos); suite_add_tcase(s, tc_pos);
return s; return s;

View File

@ -0,0 +1,16 @@
BaseName: 070-coding-practice
Version: 1.0
Description: Check for non-recommended coding practices
CreationDate: ma 20 mrt 2017 15:55:19 CET
Maintainer: Willem Toorop
Category:
Component:
CmdDepends:
Depends:
Help:
Pre: 070-coding-practice.pre
Post:
Test: 070-coding-practice.test
AuxFiles:
Passed:
Failure:

View File

@ -0,0 +1,14 @@
# #-- 070-coding-practice.pre--#
# source the master var file when it's there
if [ -f ../.tpkg.var.master ]
then
source ../.tpkg.var.master
else
(
cd ..
[ -f "${TPKG_SRCDIR}/setup-env.sh" ] \
&& sh "${TPKG_SRCDIR}/setup-env.sh"
) && source ../.tpkg.var.master
fi
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test

View File

@ -0,0 +1,41 @@
# #-- 070-coding-practice.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
rm -f report.txt
(
cd ${SRCROOT}/src
if [ `grep '[^!=]=[ ][ ]*NET_REQ_' *.[ch] */*.[ch] | wc -l` -gt 1 ]
then
echo "*** "
echo "*** Setting getdns_network_req->state should be done via"
echo "*** _getdns_netreq_change_state() only, for anticipating"
echo "*** running out of filedescriptors (sockets) and for the"
echo "*** limit_outstanding_queries feature."
echo "*** "
grep -n '[^!=]=[ ][ ]*NET_REQ_' *.[ch] */*.[ch] | \
grep -v '^request-internal.c:[12][0-9][0-9]: *net_req->state = NET_REQ_NOT_SENT;$'
echo ""
fi
) >> report.txt
(
cd ${SRCROOT}/src
if [ `grep '__FUNCTION__' *.[ch] */*.[ch] | wc -l` -gt 0 ]
then
echo "*** "
echo "*** Use __FUNC__ instead of __FUNCTION__ for portability"
echo "*** __FUNC__ is aliases in config.h to name to be used"
echo "*** for the system with a #define"
echo "*** "
grep -n '__FUNCTION__' *.[ch] */*.[ch]
echo ""
fi
) >> report.txt
if [ -s report.txt ]
then
cat report.txt
false
fi

View File

@ -0,0 +1,15 @@
builddir = @BUILDDIR@
testname = @TPKG_NAME@
LIBTOOL = $(builddir)/libtool
CFLAGS=-Wall -Wextra -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,138 @@
/*
* delaydns.c - A DNS proxy that adds delay to replies
*
* Copyright (c) 2016, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 the NLNET LABS 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
* HOLDER 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 <getdns/getdns_extra.h>
#include <stdio.h>
#include <string.h>
static int n_requests = 0;
typedef struct transaction_t {
getdns_transaction_t request_id;
getdns_dict *request;
getdns_context *context;
getdns_eventloop *loop;
getdns_eventloop_event ev;
} transaction_t;
void delay_cb(void *userarg)
{
transaction_t *trans = userarg;
trans->loop->vmt->clear(trans->loop, &trans->ev);
(void) getdns_reply(trans->context, trans->request, trans->request_id);
getdns_dict_destroy(trans->request);
free(trans);
n_requests -= 1;
}
void handler(getdns_context *context, getdns_callback_type_t callback_type,
getdns_dict *request, void *userarg, getdns_transaction_t request_id)
{
transaction_t *trans = NULL;
getdns_bindata *qname;
char nreq_str[255];
getdns_bindata nreq_bd = { 0, (void *)nreq_str };
(void) userarg; (void)callback_type;
nreq_bd.size = snprintf(nreq_str, sizeof(nreq_str), "n_requests: %d", ++n_requests);
if (getdns_dict_get_bindata(request, "/question/qname", &qname) ||
getdns_dict_set_bindata(request, "/answer/0/name", qname) ||
getdns_dict_set_int(request, "/answer/0/type", GETDNS_RRTYPE_TXT) ||
getdns_dict_set_bindata(request, "/answer/0/rdata/txt_strings/-", &nreq_bd))
fprintf(stderr, "Request init error\n");
else if (qname->size >= 6 && qname->data[0] == 4 &&
qname->data[1] == 'q' && qname->data[2] == 'u' &&
qname->data[3] == 'i' && qname->data[4] == 't') {
(void) getdns_reply(context, request, request_id);
(void) getdns_context_set_listen_addresses(context, NULL, NULL, NULL);
getdns_dict_destroy(request);
return;
} else if (!(trans = malloc(sizeof(transaction_t))))
perror("memerror");
else {
(void) memset(trans, 0, sizeof(transaction_t));
trans->request_id = request_id;
trans->request = request;
trans->context = context;
trans->ev.userarg = trans;
trans->ev.timeout_cb = delay_cb;
if (getdns_context_get_eventloop(context, &trans->loop)
|| trans->loop->vmt->schedule(trans->loop, -1, 300, &trans->ev))
fprintf(stderr, "Could not schedule delay\n");
else return;
}
getdns_dict_destroy(trans->request);
if (trans) free(trans);
exit(EXIT_FAILURE);
}
int main()
{
getdns_context *context = NULL;
getdns_list *listeners = NULL;
getdns_dict *address = NULL;
uint32_t port = 18000;
getdns_return_t r;
if ((r = getdns_str2list("[ 127.0.0.1:18000 ]", &listeners)) ||
(r = getdns_list_get_dict(listeners, 0, &address)) ||
(r = getdns_context_create(&context, 0)))
fprintf(stderr, "Error initializing: ");
else while (++port < 18200 &&
!(r = getdns_dict_set_int(address, "port", port)) &&
(r = getdns_context_set_listen_addresses(
context, listeners, NULL, handler)))
; /* pass */
if (r) fprintf(stderr, "%s\n", getdns_get_errorstr_by_id(r));
else {
fprintf(stdout, "%d\n", (int)port);
fflush(stdout);
getdns_context_run(context);
}
getdns_list_destroy(listeners);
getdns_context_destroy(context);
return r;
}

View File

@ -0,0 +1,16 @@
BaseName: 280-limit_outstanding_queries
Version: 1.0
Description: Test if outstanding queries setting is obeyed
CreationDate: Tue Mar 14 10:43:45 CET 2017
Maintainer: Willem Toorop
Category:
Component:
CmdDepends:
Depends: 210-stub-only-link.tpkg
Help:
Pre: 280-limit_outstanding_queries.pre
Post:
Test: 280-limit_outstanding_queries.test
AuxFiles:
Passed:
Failure:

View File

@ -0,0 +1,14 @@
# #-- 280-limit_outstanding_queries.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,40 @@
# #-- 280-limit_outstanding_queries.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
QLIMIT=64
NQUERIES=`wc "./${TPKG_NAME}.queries"|sed 's/ .*$//g'`
# Test will take NQUERIES / QLIMIT * answer delay
# For current parameters this is 1000 / 64 * 0.3 = 4.6875
# which is smaller than 5 seconds default query timeout value,
# so the test should succeed.
make && "./${TPKG_NAME}" | (
read PORT
${GETDNS_STUB_QUERY} @127.0.0.1:$PORT TXT \
-a -F "./${TPKG_NAME}.queries" \
"{limit_outstanding_queries:$QLIMIT}" 2>&1 > out
${GETDNS_STUB_QUERY} -q @127.0.0.1:$PORT TXT quit.
) && grep '"n_requests: [0-9][0-9]*"' out | sed -e 's/^.*n_requests: //g' -e 's/".*$//g' \
| awk -vQLIMIT=$QLIMIT -vNQUERIES=$NQUERIES '
BEGIN{
max_outstanding = 0;
}
{
if ($1 > max_outstanding)
max_outstanding = $1;
}
END{
printf("%d of %d queries answered (%.1f%%)\n", NR, NQUERIES, (NR / NQUERIES * 100));
if (max_outstanding > QLIMIT) {
print "ERROR: More than "QLIMIT" outstanding queries: "max_outstanding;
exit(-1);
} else
print "SUCCESS: No more than "QLIMIT" outstanding queries: "max_outstanding;
}'

View File

@ -0,0 +1,15 @@
builddir = @BUILDDIR@
testname = @TPKG_NAME@
LIBTOOL = $(builddir)/libtool
CFLAGS=-Wall -Wextra -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,143 @@
/*
* delaydns.c - A DNS proxy that adds delay to replies
*
* Copyright (c) 2016, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 the NLNET LABS 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
* HOLDER 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 <getdns/getdns_extra.h>
#include <stdio.h>
#include <string.h>
static int n_requests = 0;
typedef struct transaction_t {
getdns_transaction_t request_id;
getdns_dict *request;
getdns_context *context;
getdns_eventloop *loop;
getdns_eventloop_event ev;
} transaction_t;
void delay_cb(void *userarg)
{
transaction_t *trans = userarg;
trans->loop->vmt->clear(trans->loop, &trans->ev);
(void) getdns_reply(trans->context, trans->request, trans->request_id);
getdns_dict_destroy(trans->request);
free(trans);
n_requests -= 1;
}
void handler(getdns_context *context, getdns_callback_type_t callback_type,
getdns_dict *request, void *userarg, getdns_transaction_t request_id)
{
transaction_t *trans = NULL;
getdns_bindata *qname;
char nreq_str[255];
getdns_bindata nreq_bd = { 0, (void *)nreq_str };
(void) userarg; (void)callback_type;
nreq_bd.size = snprintf(nreq_str, sizeof(nreq_str), "n_requests: %d", ++n_requests);
if (getdns_dict_get_bindata(request, "/question/qname", &qname) ||
getdns_dict_set_bindata(request, "/answer/0/name", qname) ||
getdns_dict_set_int(request, "/answer/0/type", GETDNS_RRTYPE_TXT) ||
getdns_dict_set_bindata(request, "/answer/0/rdata/txt_strings/-", &nreq_bd))
fprintf(stderr, "Request init error\n");
else if (qname->size >= 6 && qname->data[0] == 4 &&
qname->data[1] == 'q' && qname->data[2] == 'u' &&
qname->data[3] == 'i' && qname->data[4] == 't') {
(void) getdns_reply(context, request, request_id);
(void) getdns_context_set_listen_addresses(context, NULL, NULL, NULL);
getdns_dict_destroy(request);
return;
} else if (!(trans = malloc(sizeof(transaction_t))))
perror("memerror");
else {
char *fqdn;
getdns_convert_dns_name_to_fqdn(qname, &fqdn);
(void) memset(trans, 0, sizeof(transaction_t));
trans->request_id = request_id;
trans->request = request;
trans->context = context;
trans->ev.userarg = trans;
trans->ev.timeout_cb = delay_cb;
fprintf(stderr, "sched delay for query %s, n_request %d\n", fqdn, (int)n_requests);
free(fqdn);
if (getdns_context_get_eventloop(context, &trans->loop)
|| trans->loop->vmt->schedule(trans->loop, -1, 300, &trans->ev))
fprintf(stderr, "Could not schedule delay\n");
else return;
}
getdns_dict_destroy(trans->request);
if (trans) free(trans);
exit(EXIT_FAILURE);
}
int main()
{
getdns_context *context = NULL;
getdns_list *listeners = NULL;
getdns_dict *address = NULL;
uint32_t port = 18000;
getdns_return_t r;
if ((r = getdns_str2list("[ 127.0.0.1:18000 ]", &listeners)) ||
(r = getdns_list_get_dict(listeners, 0, &address)) ||
(r = getdns_context_create(&context, 0)))
fprintf(stderr, "Error initializing: ");
else while (++port < 18200 &&
!(r = getdns_dict_set_int(address, "port", port)) &&
(r = getdns_context_set_listen_addresses(
context, listeners, NULL, handler)))
; /* pass */
if (r) fprintf(stderr, "%s\n", getdns_get_errorstr_by_id(r));
else {
fprintf(stdout, "%d\n", (int)port);
fflush(stdout);
getdns_context_run(context);
}
getdns_list_destroy(listeners);
getdns_context_destroy(context);
return r;
}

View File

@ -0,0 +1,16 @@
BaseName: 285-out_of_filedescriptors
Version: 1.0
Description: Test if outstanding queries setting is obeyed
CreationDate: ma 20 mrt 2017 15:17:45 CET
Maintainer: Willem Toorop
Category:
Component:
CmdDepends:
Depends: 210-stub-only-link.tpkg
Help:
Pre: 285-out_of_filedescriptors.pre
Post:
Test: 285-out_of_filedescriptors.test
AuxFiles:
Passed:
Failure:

View File

@ -0,0 +1,14 @@
# #-- 285-out_of_filedescriptors.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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
# #-- 285-out_of_filedescriptors.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
QLIMIT=79
NQUERIES=`wc "./${TPKG_NAME}.queries"|sed 's/ .*$//g'`
# This time the query limit is set by setting the maximum open
# filedescriptors. We seem to be needing a higher QLIMIT, than
# with limit_outstanding_queries unit test.
#
# 4 filedescriptors are already needed for overhead (logging etc),
# but experiments showed that to prevent timeouts, we should
# have a higher value than 72 at least.
#
# Test will take NQUERIES / QLIMIT * answer delay
# For current parameters this is 1000 / 75 * 0.3 = 4.0
# which is smaller than 5 seconds default query timeout value,
# so the test should succeed.
make && "./${TPKG_NAME}" | (
read PORT
ulimit -n $QLIMIT
${GETDNS_STUB_QUERY} @127.0.0.1:$PORT TXT \
-a -F "./${TPKG_NAME}.queries" 2>&1 > out
${GETDNS_STUB_QUERY} -q @127.0.0.1:$PORT TXT quit.
) && grep '"n_requests: [0-9][0-9]*"' out | sed -e 's/^.*n_requests: //g' -e 's/".*$//g' \
| awk -vQLIMIT=$QLIMIT -vNQUERIES=$NQUERIES '
BEGIN{
max_outstanding = 0;
}
{
if ($1 > max_outstanding)
max_outstanding = $1;
}
END{
printf("%d of %d queries answered (%.1f%%)\n", NR, NQUERIES, (NR / NQUERIES * 100));
if (max_outstanding > QLIMIT) {
print "ERROR: More than "QLIMIT" outstanding queries: "max_outstanding;
exit(-1);
} else
print "SUCCESS: No more than "QLIMIT" outstanding queries: "max_outstanding;
}'

View File

@ -113,5 +113,8 @@ depend:
.PHONY: clean test .PHONY: clean test
# Dependencies for getdns_query # Dependencies for getdns_query
getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \ getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c \
../getdns/getdns.h ../getdns/getdns_extra.h ../config.h \
$(srcdir)/../debug.h \
../getdns/getdns.h \
../getdns/getdns_extra.h

View File

@ -1,5 +1,11 @@
{ resolution_type: GETDNS_RESOLUTION_STUB { resolution_type: GETDNS_RESOLUTION_STUB
, dns_transport_list: [ GETDNS_TRANSPORT_TLS ] , dns_transport_list: [ GETDNS_TRANSPORT_TLS ]
, tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
, tls_query_padding_blocksize: 256
, edns_client_subnet_private : 1
, listen_addresses: [ 127.0.0.1, 0::1 ]
, idle_timeout: 10000
, round_robin_upstreams: 1
, upstream_recursive_servers: , upstream_recursive_servers:
[ { address_data: 145.100.185.15 [ { address_data: 145.100.185.15
, tls_auth_name: "dnsovertls.sinodun.com" , tls_auth_name: "dnsovertls.sinodun.com"
@ -56,9 +62,4 @@
} ] } ]
} }
] ]
, tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
, tls_query_padding_blocksize: 256
, edns_client_subnet_private : 1
, listen_addresses: [ 127.0.0.1, 0::1 ]
, idle_timeout: 10000
} }

View File

@ -124,7 +124,6 @@ struct getdns_upstream;
#define GETDNS_TRANSPORTS_MAX 3 #define GETDNS_TRANSPORTS_MAX 3
#define GETDNS_UPSTREAM_TRANSPORTS 2 #define GETDNS_UPSTREAM_TRANSPORTS 2
#define GETDNS_CONN_ATTEMPTS 2
#define GETDNS_TRANSPORT_FAIL_MULT 5 #define GETDNS_TRANSPORT_FAIL_MULT 5
@ -313,6 +312,7 @@ typedef struct getdns_dns_req {
/* Internally used by return_validation_chain */ /* Internally used by return_validation_chain */
unsigned dnssec_ok_checking_disabled : 1; unsigned dnssec_ok_checking_disabled : 1;
unsigned is_sync_request : 1; unsigned is_sync_request : 1;
unsigned is_dns_request : 1;
/* The validating and freed variables are used to make sure a single /* The validating and freed variables are used to make sure a single
* code path is followed while processing a DNS request, even when * code path is followed while processing a DNS request, even when
@ -343,6 +343,11 @@ typedef struct getdns_dns_req {
/* the transaction id */ /* the transaction id */
getdns_transaction_t trans_id; getdns_transaction_t trans_id;
/* Absolute time (in miliseconds since epoch),
* after which this dns request is expired; i.e. timed out
*/
uint64_t expires;
/* for scheduling timeouts when using libunbound */ /* for scheduling timeouts when using libunbound */
getdns_eventloop_event timeout; getdns_eventloop_event timeout;
@ -413,7 +418,7 @@ extern getdns_dict *dnssec_ok_checking_disabled_avoid_roadblocks;
/* dns request utils */ /* dns request utils */
getdns_dns_req *_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, getdns_dns_req *_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions); const char *name, uint16_t request_type, getdns_dict *extensions, uint64_t *now_ms);
void _getdns_dns_req_free(getdns_dns_req * req); void _getdns_dns_req_free(getdns_dns_req * req);

View File

@ -198,5 +198,25 @@ INLINE void _dname_canonicalize2(uint8_t *dname)
_dname_canonicalize(dname, dname); _dname_canonicalize(dname, dname);
} }
INLINE uint64_t _getdns_get_now_ms()
{
struct timeval tv;
(void) gettimeofday(&tv, NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
INLINE uint64_t _getdns_ms_until_expiry(uint64_t expires)
{
uint64_t now_ms = _getdns_get_now_ms();
return now_ms >= expires ? 0 : expires - now_ms;
}
INLINE uint64_t _getdns_ms_until_expiry2(uint64_t expires, uint64_t *now_ms)
{
if (*now_ms == 0) *now_ms = _getdns_get_now_ms();
return *now_ms >= expires ? 0 : expires - *now_ms;
}
#endif #endif
/* util-internal.h */ /* util-internal.h */

View File

@ -45,7 +45,6 @@ on 1 byte), but shoehorning those bytes into integers efficiently is messy.
/*#define SELF_TEST 1*/ /*#define SELF_TEST 1*/
#include "config.h" #include "config.h"
#include "util/lookup3.h"
#include "util/storage/lookup3.h" #include "util/storage/lookup3.h"
#include <stdio.h> /* defines printf for tests */ #include <stdio.h> /* defines printf for tests */
#include <time.h> /* defines time_t for timings in the test */ #include <time.h> /* defines time_t for timings in the test */

View File

@ -41,7 +41,6 @@
*/ */
#include "config.h" #include "config.h"
#include "util/lruhash.h"
#include "util/storage/lruhash.h" #include "util/storage/lruhash.h"
#include "util/fptr_wlist.h" #include "util/fptr_wlist.h"
@ -297,92 +296,6 @@ lru_touch(struct lruhash* table, struct lruhash_entry* entry)
lru_front(table, entry); lru_front(table, entry);
} }
/*
* Demote: the opposite of touch, move an entry to the bottom
* of the LRU pile.
*/
void
lru_demote(struct lruhash* table, struct lruhash_entry* entry)
{
log_assert(table && entry);
if (entry == table->lru_end)
return; /* nothing to do */
/* remove from current lru position */
lru_remove(table, entry);
/* add at end */
entry->lru_next = NULL;
entry->lru_prev = table->lru_end;
if (table->lru_end == NULL)
{
table->lru_start = entry;
}
else
{
table->lru_end->lru_next = entry;
}
table->lru_end = entry;
}
struct lruhash_entry*
lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg)
{
struct lruhash_bin* bin;
struct lruhash_entry* found, *reclaimlist = NULL;
size_t need_size;
fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc));
fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc));
fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc));
need_size = table->sizefunc(entry->key, data);
if (cb_arg == NULL) cb_arg = table->cb_arg;
/* find bin */
lock_quick_lock(&table->lock);
bin = &table->array[hash & table->size_mask];
lock_quick_lock(&bin->lock);
/* see if entry exists already */
if ((found = bin_find_entry(table, bin, hash, entry->key)) != NULL) {
/* if so: keep the existing data - acquire a writelock */
lock_rw_wrlock(&found->lock);
}
else
{
/* if not: add to bin */
entry->overflow_next = bin->overflow_list;
bin->overflow_list = entry;
lru_front(table, entry);
table->num++;
table->space_used += need_size;
/* return the entry that was presented, and lock it */
found = entry;
lock_rw_wrlock(&found->lock);
}
lock_quick_unlock(&bin->lock);
if (table->space_used > table->space_max)
reclaim_space(table, &reclaimlist);
if (table->num >= table->size)
table_grow(table);
lock_quick_unlock(&table->lock);
/* finish reclaim if any (outside of critical region) */
while (reclaimlist) {
struct lruhash_entry* n = reclaimlist->overflow_next;
void* d = reclaimlist->data;
(*table->delkeyfunc)(reclaimlist->key, cb_arg);
(*table->deldatafunc)(d, cb_arg);
reclaimlist = n;
}
/* return the entry that was selected */
return found;
}
void void
lruhash_insert(struct lruhash* table, hashvalue_type hash, lruhash_insert(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg) struct lruhash_entry* entry, void* data, void* cb_arg)
@ -630,3 +543,89 @@ lruhash_traverse(struct lruhash* h, int wr,
} }
lock_quick_unlock(&h->lock); lock_quick_unlock(&h->lock);
} }
/*
* Demote: the opposite of touch, move an entry to the bottom
* of the LRU pile.
*/
void
lru_demote(struct lruhash* table, struct lruhash_entry* entry)
{
log_assert(table && entry);
if (entry == table->lru_end)
return; /* nothing to do */
/* remove from current lru position */
lru_remove(table, entry);
/* add at end */
entry->lru_next = NULL;
entry->lru_prev = table->lru_end;
if (table->lru_end == NULL)
{
table->lru_start = entry;
}
else
{
table->lru_end->lru_next = entry;
}
table->lru_end = entry;
}
struct lruhash_entry*
lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg)
{
struct lruhash_bin* bin;
struct lruhash_entry* found, *reclaimlist = NULL;
size_t need_size;
fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc));
fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc));
fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc));
need_size = table->sizefunc(entry->key, data);
if (cb_arg == NULL) cb_arg = table->cb_arg;
/* find bin */
lock_quick_lock(&table->lock);
bin = &table->array[hash & table->size_mask];
lock_quick_lock(&bin->lock);
/* see if entry exists already */
if ((found = bin_find_entry(table, bin, hash, entry->key)) != NULL) {
/* if so: keep the existing data - acquire a writelock */
lock_rw_wrlock(&found->lock);
}
else
{
/* if not: add to bin */
entry->overflow_next = bin->overflow_list;
bin->overflow_list = entry;
lru_front(table, entry);
table->num++;
table->space_used += need_size;
/* return the entry that was presented, and lock it */
found = entry;
lock_rw_wrlock(&found->lock);
}
lock_quick_unlock(&bin->lock);
if (table->space_used > table->space_max)
reclaim_space(table, &reclaimlist);
if (table->num >= table->size)
table_grow(table);
lock_quick_unlock(&table->lock);
/* finish reclaim if any (outside of critical region) */
while (reclaimlist) {
struct lruhash_entry* n = reclaimlist->overflow_next;
void* d = reclaimlist->data;
(*table->delkeyfunc)(reclaimlist->key, cb_arg);
(*table->deldatafunc)(d, cb_arg);
reclaimlist = n;
}
/* return the entry that was selected */
return found;
}

View File

@ -46,12 +46,13 @@
#define lruhash_delete _getdns_lruhash_delete #define lruhash_delete _getdns_lruhash_delete
#define lruhash_clear _getdns_lruhash_clear #define lruhash_clear _getdns_lruhash_clear
#define lruhash_insert _getdns_lruhash_insert #define lruhash_insert _getdns_lruhash_insert
#define lruhash_insert_or_retrieve _getdns_lruhash_insert_or_retrieve
#define lruhash_lookup _getdns_lruhash_lookup #define lruhash_lookup _getdns_lruhash_lookup
#define lru_touch _getdns_lru_touch #define lru_touch _getdns_lru_touch
#define lru_demote _getdns_lru_demote
#define lruhash_setmarkdel _getdns_lruhash_setmarkdel #define lruhash_setmarkdel _getdns_lruhash_setmarkdel
#define lru_demote _getdns_lru_demote
#define lruhash_insert_or_retrieve _getdns_lruhash_insert_or_retrieve
#define lruhash_remove _getdns_lruhash_remove #define lruhash_remove _getdns_lruhash_remove
#define bin_init _getdns_bin_init #define bin_init _getdns_bin_init
#define bin_delete _getdns_bin_delete #define bin_delete _getdns_bin_delete
@ -67,37 +68,4 @@
#define lruhash_traverse _getdns_lruhash_traverse #define lruhash_traverse _getdns_lruhash_traverse
#include "util/orig-headers/lruhash.h" #include "util/orig-headers/lruhash.h"
/*
* Additional function definitions, not found in original header.
*/
/**
* Demote entry, so it becomes the least recently used in the LRU list.
* Caller must hold hash table lock. The entry must be inserted already.
* @param table: hash table.
* @param entry: entry to make last in LRU.
*/
void lru_demote(struct lruhash* table, struct lruhash_entry* entry);
/**
* Insert a new element into the hashtable, or retrieve the corresponding
* element of it exits.
*
* If key is already present data pointer in that entry is kept.
* If it is not present, a new entry is created. In that case,
* the space calculation function is called with the key, data.
* If necessary the least recently used entries are deleted to make space.
* If necessary the hash array is grown up.
*
* @param table: hash table.
* @param hash: hash value. User calculates the hash.
* @param entry: identifies the entry.
* @param data: the data.
* @param cb_override: if not null overrides the cb_arg for the deletefunc.
* @return: pointer to the existing entry if the key was already present,
* or to the entry argument if it was not.
*/
struct lruhash_entry* lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg);
#endif #endif

View File

@ -301,6 +301,38 @@ void lru_touch(struct lruhash* table, struct lruhash_entry* entry);
*/ */
void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md); void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md);
/************************* getdns functions ************************/
/*** these are used by getdns only and not by unbound. ***/
/**
* Demote entry, so it becomes the least recently used in the LRU list.
* Caller must hold hash table lock. The entry must be inserted already.
* @param table: hash table.
* @param entry: entry to make last in LRU.
*/
void lru_demote(struct lruhash* table, struct lruhash_entry* entry);
/**
* Insert a new element into the hashtable, or retrieve the corresponding
* element of it exits.
*
* If key is already present data pointer in that entry is kept.
* If it is not present, a new entry is created. In that case,
* the space calculation function is called with the key, data.
* If necessary the least recently used entries are deleted to make space.
* If necessary the hash array is grown up.
*
* @param table: hash table.
* @param hash: hash value. User calculates the hash.
* @param entry: identifies the entry.
* @param data: the data.
* @param cb_override: if not null overrides the cb_arg for the deletefunc.
* @return: pointer to the existing entry if the key was already present,
* or to the entry argument if it was not.
*/
struct lruhash_entry* lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg);
/************************* Internal functions ************************/ /************************* Internal functions ************************/
/*** these are only exposed for unit tests. ***/ /*** these are only exposed for unit tests. ***/

View File

@ -74,6 +74,8 @@
/** fake DSA support for unit tests */ /** fake DSA support for unit tests */
int fake_dsa = 0; int fake_dsa = 0;
/** fake SHA1 support for unit tests */
int fake_sha1 = 0;
/* return size of digest if supported, or 0 otherwise */ /* return size of digest if supported, or 0 otherwise */
size_t size_t
@ -116,9 +118,12 @@ size_t
ds_digest_size_supported(int algo) ds_digest_size_supported(int algo)
{ {
switch(algo) { switch(algo) {
#ifdef HAVE_EVP_SHA1
case LDNS_SHA1: case LDNS_SHA1:
#if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
return SHA_DIGEST_LENGTH; return SHA_DIGEST_LENGTH;
#else
if(fake_sha1) return 20;
return 0;
#endif #endif
#ifdef HAVE_EVP_SHA256 #ifdef HAVE_EVP_SHA256
case LDNS_SHA256: case LDNS_SHA256:
@ -158,7 +163,7 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
unsigned char* res) unsigned char* res)
{ {
switch(algo) { switch(algo) {
#ifdef HAVE_EVP_SHA1 #if defined(HAVE_EVP_SHA1) && defined(USE_SHA1)
case LDNS_SHA1: case LDNS_SHA1:
(void)SHA1(buf, len, res); (void)SHA1(buf, len, res);
return 1; return 1;
@ -197,14 +202,22 @@ dnskey_algo_id_is_supported(int id)
return 0; return 0;
case LDNS_DSA: case LDNS_DSA:
case LDNS_DSA_NSEC3: case LDNS_DSA_NSEC3:
#ifdef USE_DSA #if defined(USE_DSA) && defined(USE_SHA1)
return 1; return 1;
#else #else
if(fake_dsa) return 1; if(fake_dsa || fake_sha1) return 1;
return 0; return 0;
#endif #endif
case LDNS_RSASHA1: case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3: case LDNS_RSASHA1_NSEC3:
#ifdef USE_SHA1
return 1;
#else
if(fake_sha1) return 1;
return 0;
#endif
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
case LDNS_RSASHA256: case LDNS_RSASHA256:
#endif #endif
@ -215,7 +228,10 @@ dnskey_algo_id_is_supported(int id)
case LDNS_ECDSAP256SHA256: case LDNS_ECDSAP256SHA256:
case LDNS_ECDSAP384SHA384: case LDNS_ECDSAP384SHA384:
#endif #endif
#if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA)
return 1; return 1;
#endif
#ifdef USE_GOST #ifdef USE_GOST
case LDNS_ECC_GOST: case LDNS_ECC_GOST:
/* we support GOST if it can be loaded */ /* we support GOST if it can be loaded */
@ -392,13 +408,13 @@ static int
setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type, setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
unsigned char* key, size_t keylen) unsigned char* key, size_t keylen)
{ {
#ifdef USE_DSA #if defined(USE_DSA) && defined(USE_SHA1)
DSA* dsa; DSA* dsa;
#endif #endif
RSA* rsa; RSA* rsa;
switch(algo) { switch(algo) {
#ifdef USE_DSA #if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA: case LDNS_DSA:
case LDNS_DSA_NSEC3: case LDNS_DSA_NSEC3:
*evp_key = EVP_PKEY_new(); *evp_key = EVP_PKEY_new();
@ -424,9 +440,13 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
#endif #endif
break; break;
#endif /* USE_DSA */ #endif /* USE_DSA && USE_SHA1 */
#if defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2))
#ifdef USE_SHA1
case LDNS_RSASHA1: case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3: case LDNS_RSASHA1_NSEC3:
#endif
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2) #if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
case LDNS_RSASHA256: case LDNS_RSASHA256:
#endif #endif
@ -461,9 +481,14 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
*digest_type = EVP_sha512(); *digest_type = EVP_sha512();
else else
#endif #endif
#ifdef USE_SHA1
*digest_type = EVP_sha1(); *digest_type = EVP_sha1();
#else
{ verbose(VERB_QUERY, "no digest available"); return 0; }
#endif
break; break;
#endif /* defined(USE_SHA1) || (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) */
case LDNS_RSAMD5: case LDNS_RSAMD5:
*evp_key = EVP_PKEY_new(); *evp_key = EVP_PKEY_new();
if(!*evp_key) { if(!*evp_key) {
@ -562,7 +587,11 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
EVP_PKEY *evp_key = NULL; EVP_PKEY *evp_key = NULL;
#ifndef USE_DSA #ifndef USE_DSA
if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) && fake_dsa) if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1))
return sec_status_secure;
#endif
#ifndef USE_SHA1
if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3))
return sec_status_secure; return sec_status_secure;
#endif #endif
@ -706,8 +735,10 @@ ds_digest_size_supported(int algo)
{ {
/* uses libNSS */ /* uses libNSS */
switch(algo) { switch(algo) {
#ifdef USE_SHA1
case LDNS_SHA1: case LDNS_SHA1:
return SHA1_LENGTH; return SHA1_LENGTH;
#endif
#ifdef USE_SHA2 #ifdef USE_SHA2
case LDNS_SHA256: case LDNS_SHA256:
return SHA256_LENGTH; return SHA256_LENGTH;
@ -729,9 +760,11 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
{ {
/* uses libNSS */ /* uses libNSS */
switch(algo) { switch(algo) {
#ifdef USE_SHA1
case LDNS_SHA1: case LDNS_SHA1:
return HASH_HashBuf(HASH_AlgSHA1, res, buf, len) return HASH_HashBuf(HASH_AlgSHA1, res, buf, len)
== SECSuccess; == SECSuccess;
#endif
#if defined(USE_SHA2) #if defined(USE_SHA2)
case LDNS_SHA256: case LDNS_SHA256:
return HASH_HashBuf(HASH_AlgSHA256, res, buf, len) return HASH_HashBuf(HASH_AlgSHA256, res, buf, len)
@ -759,12 +792,15 @@ dnskey_algo_id_is_supported(int id)
case LDNS_RSAMD5: case LDNS_RSAMD5:
/* RFC 6725 deprecates RSAMD5 */ /* RFC 6725 deprecates RSAMD5 */
return 0; return 0;
#ifdef USE_DSA #if defined(USE_SHA1) || defined(USE_SHA2)
#if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA: case LDNS_DSA:
case LDNS_DSA_NSEC3: case LDNS_DSA_NSEC3:
#endif #endif
#ifdef USE_SHA1
case LDNS_RSASHA1: case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3: case LDNS_RSASHA1_NSEC3:
#endif
#ifdef USE_SHA2 #ifdef USE_SHA2
case LDNS_RSASHA256: case LDNS_RSASHA256:
#endif #endif
@ -772,6 +808,8 @@ dnskey_algo_id_is_supported(int id)
case LDNS_RSASHA512: case LDNS_RSASHA512:
#endif #endif
return 1; return 1;
#endif /* SHA1 or SHA2 */
#ifdef USE_ECDSA #ifdef USE_ECDSA
case LDNS_ECDSAP256SHA256: case LDNS_ECDSAP256SHA256:
case LDNS_ECDSAP384SHA384: case LDNS_ECDSAP384SHA384:
@ -1003,7 +1041,9 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
*/ */
switch(algo) { switch(algo) {
#ifdef USE_DSA
#if defined(USE_SHA1) || defined(USE_SHA2)
#if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA: case LDNS_DSA:
case LDNS_DSA_NSEC3: case LDNS_DSA_NSEC3:
*pubkey = nss_buf2dsa(key, keylen); *pubkey = nss_buf2dsa(key, keylen);
@ -1015,8 +1055,10 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
/* no prefix for DSA verification */ /* no prefix for DSA verification */
break; break;
#endif #endif
#ifdef USE_SHA1
case LDNS_RSASHA1: case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3: case LDNS_RSASHA1_NSEC3:
#endif
#ifdef USE_SHA2 #ifdef USE_SHA2
case LDNS_RSASHA256: case LDNS_RSASHA256:
#endif #endif
@ -1043,13 +1085,22 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
*prefixlen = sizeof(p_sha512); *prefixlen = sizeof(p_sha512);
} else } else
#endif #endif
#ifdef USE_SHA1
{ {
*htype = HASH_AlgSHA1; *htype = HASH_AlgSHA1;
*prefix = p_sha1; *prefix = p_sha1;
*prefixlen = sizeof(p_sha1); *prefixlen = sizeof(p_sha1);
} }
#else
{
verbose(VERB_QUERY, "verify: no digest algo");
return 0;
}
#endif
break; break;
#endif /* SHA1 or SHA2 */
case LDNS_RSAMD5: case LDNS_RSAMD5:
*pubkey = nss_buf2rsa(key, keylen); *pubkey = nss_buf2rsa(key, keylen);
if(!*pubkey) { if(!*pubkey) {
@ -1131,7 +1182,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_bogus; return sec_status_bogus;
} }
#ifdef USE_DSA #if defined(USE_DSA) && defined(USE_SHA1)
/* need to convert DSA, ECDSA signatures? */ /* need to convert DSA, ECDSA signatures? */
if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) { if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) {
if(sigblock_len == 1+2*SHA1_LENGTH) { if(sigblock_len == 1+2*SHA1_LENGTH) {
@ -1312,7 +1363,12 @@ ds_digest_size_supported(int algo)
{ {
switch(algo) { switch(algo) {
case LDNS_SHA1: case LDNS_SHA1:
#ifdef USE_SHA1
return SHA1_DIGEST_SIZE; return SHA1_DIGEST_SIZE;
#else
if(fake_sha1) return 20;
return 0;
#endif
#ifdef USE_SHA2 #ifdef USE_SHA2
case LDNS_SHA256: case LDNS_SHA256:
return SHA256_DIGEST_SIZE; return SHA256_DIGEST_SIZE;
@ -1334,8 +1390,10 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
unsigned char* res) unsigned char* res)
{ {
switch(algo) { switch(algo) {
#ifdef USE_SHA1
case LDNS_SHA1: case LDNS_SHA1:
return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res); return _digest_nettle(SHA1_DIGEST_SIZE, buf, len, res);
#endif
#if defined(USE_SHA2) #if defined(USE_SHA2)
case LDNS_SHA256: case LDNS_SHA256:
return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res); return _digest_nettle(SHA256_DIGEST_SIZE, buf, len, res);
@ -1359,12 +1417,14 @@ dnskey_algo_id_is_supported(int id)
{ {
/* uses libnettle */ /* uses libnettle */
switch(id) { switch(id) {
#ifdef USE_DSA #if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA: case LDNS_DSA:
case LDNS_DSA_NSEC3: case LDNS_DSA_NSEC3:
#endif #endif
#ifdef USE_SHA1
case LDNS_RSASHA1: case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3: case LDNS_RSASHA1_NSEC3:
#endif
#ifdef USE_SHA2 #ifdef USE_SHA2
case LDNS_RSASHA256: case LDNS_RSASHA256:
case LDNS_RSASHA512: case LDNS_RSASHA512:
@ -1381,7 +1441,7 @@ dnskey_algo_id_is_supported(int id)
} }
} }
#ifdef USE_DSA #if defined(USE_DSA) && defined(USE_SHA1)
static char * static char *
_verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock, _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
unsigned int sigblock_len, unsigned char* key, unsigned int keylen) unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
@ -1641,7 +1701,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
} }
switch(algo) { switch(algo) {
#ifdef USE_DSA #if defined(USE_DSA) && defined(USE_SHA1)
case LDNS_DSA: case LDNS_DSA:
case LDNS_DSA_NSEC3: case LDNS_DSA_NSEC3:
*reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen); *reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen);
@ -1651,9 +1711,11 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_secure; return sec_status_secure;
#endif /* USE_DSA */ #endif /* USE_DSA */
#ifdef USE_SHA1
case LDNS_RSASHA1: case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3: case LDNS_RSASHA1_NSEC3:
digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE); digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE);
#endif
#ifdef USE_SHA2 #ifdef USE_SHA2
case LDNS_RSASHA256: case LDNS_RSASHA256:
digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE); digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);