diff --git a/.gitignore b/.gitignore index 7bbbdebd..d9315494 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,13 @@ m4/ltsugar.m4 m4/ltversion.m4 m4/lt~obsolete.m4 src/config.h.in -build/ getdns.pc getdns_ext_event.pc +/src/test/tpkg/result.* +/src/test/tpkg/.done-* +/src/test/tpkg/.tpkg.var.master +/src/test/tpkg/scan-build-reports/ +/src/test/tpkg/install/ +/src/test/tpkg/build/ +/src/test/tpkg/build-stub-only/ +/src/test/tpkg/build-event-loops/ diff --git a/configure.ac b/configure.ac index f3b35c98..555b7792 100644 --- a/configure.ac +++ b/configure.ac @@ -214,6 +214,30 @@ case "$enable_debug_keep_connections_open" in ;; esac + +DEFAULT_EVENTLOOP=select_eventloop +AC_CHECK_HEADERS([sys/poll.h poll.h sys/resource.h],,, [AC_INCLUDES_DEFAULT]) +AC_ARG_ENABLE(poll-eventloop, AC_HELP_STRING([--disable-poll-eventloop], [Disable default eventloop based on poll (default=enabled if available)])) +case "$enable_poll_eventloop" in + no) + ;; + yes|*) +AC_MSG_CHECKING(for poll) +AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#ifdef HAVE_SYS_POLL_H +#include +#else +#include +#endif +], [int rc; rc = poll((struct pollfd *)(0), 0, 0);])], [ +AC_MSG_RESULT(yes) +AC_DEFINE_UNQUOTED([USE_POLL_DEFAULT_EVENTLOOP], [1], [Define this to enable a default eventloop based on poll().]) +DEFAULT_EVENTLOOP=poll_eventloop +],[AC_MSG_RESULT(no)]) + ;; +esac +AC_SUBST(DEFAULT_EVENTLOOP) + AC_ARG_ENABLE(tcp-fastopen, AC_HELP_STRING([--disable-tcp-fastopen], Disable TCP Fast Open (default=enabled if available)), enable_tcp_fastopen="$enableval", enable_tcp_fastopen=yes) if test "x$enable_tcp_fastopen" = xno; then @@ -1076,8 +1100,6 @@ if test "$ac_cv_func_arc4random" = "no"; then ]) fi -AC_DEFINE(USE_MINI_EVENT, 1, [Needed for sync stub resolver functions]) - AC_TYPE_SIGNAL case `uname` in @@ -1101,17 +1123,16 @@ AH_BOTTOM([ #endif #ifdef GETDNS_ON_WINDOWS -/* On windows it is allowed to increase the FD_SETSIZE - * (and nescessary to make our custom eventloop work) - * See: https://support.microsoft.com/en-us/kb/111855 - */ -#ifndef FD_SETSIZE -#define FD_SETSIZE 1024 -#endif - -#define PRIsz "%Iu" + /* On windows it is allowed to increase the FD_SETSIZE + * (and nescessary to make our custom eventloop work) + * See: https://support.microsoft.com/en-us/kb/111855 + */ +# ifndef FD_SETSIZE +# define FD_SETSIZE 1024 +# endif +# define PRIsz "%Iu" #else -#define PRIsz "%zu" +# define PRIsz "%zu" #endif #include @@ -1148,8 +1169,6 @@ AH_BOTTOM([ #define FD_SET_T #endif - - #ifdef __cplusplus extern "C" { #endif @@ -1204,6 +1223,12 @@ int inet_pton(int af, const char* src, void* dst); const char *inet_ntop(int af, const void *src, char *dst, size_t size); #endif +#ifdef USE_WINSOCK +static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *format, va_list ap) +{ int r = vsnprintf(str, size, format, ap); return r == -1 ? _vscprintf(format, ap) : r; } +# define vsnprintf _gldns_custom_vsnprintf +#endif + #ifdef __cplusplus } #endif diff --git a/spec/example/Makefile.in b/spec/example/Makefile.in index 7bf5e016..8ff7f2d1 100644 --- a/spec/example/Makefile.in +++ b/spec/example/Makefile.in @@ -149,16 +149,24 @@ depend: # Dependencies for the examples example-all-functions.lo example-all-functions.o: $(srcdir)/example-all-functions.c $(srcdir)/getdns_libevent.h \ - ../../src/config.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/config.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 example-simple-answers.lo example-simple-answers.o: $(srcdir)/example-simple-answers.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/config.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 \ ../../src/getdns/getdns.h -example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h ../../src/config.h \ - ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ +example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h \ + ../../src/config.h \ + ../../src/getdns/getdns.h \ + $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/getdns/getdns_extra.h diff --git a/src/Makefile.in b/src/Makefile.in index bcd858e2..6f06858a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -65,6 +65,8 @@ EXTENSION_LIBUV_LDFLAGS=@EXTENSION_LIBUV_LDFLAGS@ C99COMPATFLAGS=@C99COMPATFLAGS@ +DEFAULT_EVENTLOOP_OBJ=@DEFAULT_EVENTLOOP@.lo + GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \ list.lo request-internal.lo pubkey-pinning.lo rr-dict.lo \ rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo \ @@ -81,7 +83,7 @@ UTIL_OBJ=rbtree.lo val_secalgo.lo JSMN_OBJ=jsmn.lo -EXTENSION_OBJ=default_eventloop.lo libevent.lo libev.lo +EXTENSION_OBJ=$(DEFAULT_EVENTLOOP_OBJ) libevent.lo libev.lo NON_C99_OBJS=context.lo libuv.lo @@ -152,8 +154,8 @@ libgetdns_ext_ev.la: libgetdns.la libev.lo $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols -libgetdns.la: $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) - $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols +libgetdns.la: $(GETDNS_OBJ) version.lo context.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) + $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols test: all cd test && $(MAKE) $@ @@ -213,132 +215,232 @@ depend: FORCE: # 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 \ - getdns/getdns.h $(srcdir)/const-info.h -context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \ - getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.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)/stub.h $(srcdir)/list.h $(srcdir)/dict.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)/extension/default_eventloop.h config.h getdns/getdns_extra.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-internal.h \ - $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.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 -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)/extension/default_eventloop.h config.h getdns/getdns_extra.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 -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)/ub_loop.h $(srcdir)/debug.h \ - $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ +const-info.lo const-info.o: $(srcdir)/const-info.c \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/const-info.h +context.lo context.o: $(srcdir)/context.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/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-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ + $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h +convert.lo convert.o: $(srcdir)/convert.c \ + config.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/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)/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 \ + $(srcdir)/util/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)/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 +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)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.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 +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)/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-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-internal.h config.h $(srcdir)/context.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.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)/extension/default_eventloop.h config.h getdns/getdns_extra.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)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.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-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.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)/extension/default_eventloop.h config.h \ - getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.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 \ +list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/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)/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)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.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_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/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-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-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)/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 \ + $(srcdir)/types-internal.h $(srcdir)/util/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)/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 getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ - $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ - $(srcdir)/debug.h $(srcdir)/server.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 getdns/getdns.h $(srcdir)/util/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 config.h getdns/getdns_extra.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)/extension/default_eventloop.h config.h getdns/getdns_extra.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)/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)/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 \ - getdns/getdns_extra.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 \ +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)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.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)/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-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)/extension/default_eventloop.h \ + $(srcdir)/extension/poll_eventloop.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 \ + $(srcdir)/types-internal.h $(srcdir)/util/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)/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)/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 -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 +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 -rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/debug.h config.h \ - $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h -val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \ - $(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h +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 +rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c \ + config.h \ + $(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h +val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c \ + config.h \ + $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h \ + $(srcdir)/gldns/gbuffer.h jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h -default_eventloop.lo default_eventloop.o: $(srcdir)/extension/default_eventloop.c config.h \ - $(srcdir)/extension/default_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ - $(srcdir)/util/rbtree.h -libev.lo libev.o: $(srcdir)/extension/libev.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ - getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/getdns/getdns_ext_libev.h getdns/getdns_extra.h -libevent.lo libevent.o: $(srcdir)/extension/libevent.c config.h $(srcdir)/types-internal.h \ - getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/getdns/getdns_ext_libevent.h getdns/getdns_extra.h -libuv.lo libuv.o: $(srcdir)/extension/libuv.c config.h $(srcdir)/debug.h config.h $(srcdir)/types-internal.h \ - getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ - $(srcdir)/getdns/getdns_ext_libuv.h getdns/getdns_extra.h +libev.lo libev.o: $(srcdir)/extension/libev.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libev.h +libevent.lo libevent.o: $(srcdir)/extension/libevent.c \ + config.h \ + $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h +libuv.lo libuv.o: $(srcdir)/extension/libuv.c \ + config.h \ + $(srcdir)/debug.h $(srcdir)/types-internal.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h +poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \ + config.h \ + $(srcdir)/extension/poll_eventloop.h \ + getdns/getdns.h \ + getdns/getdns_extra.h \ + $(srcdir)/types-internal.h $(srcdir)/util/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 diff --git a/src/const-info.c b/src/const-info.c index a71f928a..4556634a 100644 --- a/src/const-info.c +++ b/src/const-info.c @@ -24,6 +24,7 @@ static struct const_info consts_info[] = { { 310, "GETDNS_RETURN_MEMORY_ERROR", GETDNS_RETURN_MEMORY_ERROR_TEXT }, { 311, "GETDNS_RETURN_INVALID_PARAMETER", GETDNS_RETURN_INVALID_PARAMETER_TEXT }, { 312, "GETDNS_RETURN_NOT_IMPLEMENTED", GETDNS_RETURN_NOT_IMPLEMENTED_TEXT }, + { 398, "GETDNS_RETURN_NO_UPSTREAM_AVAILABLE", GETDNS_RETURN_NO_UPSTREAM_AVAILABLE_TEXT }, { 399, "GETDNS_RETURN_NEED_MORE_SPACE", GETDNS_RETURN_NEED_MORE_SPACE_TEXT }, { 400, "GETDNS_DNSSEC_SECURE", GETDNS_DNSSEC_SECURE_TEXT }, { 401, "GETDNS_DNSSEC_BOGUS", GETDNS_DNSSEC_BOGUS_TEXT }, @@ -223,6 +224,7 @@ static struct const_name_info consts_name_info[] = { { "GETDNS_RETURN_NO_SUCH_DICT_NAME", 305 }, { "GETDNS_RETURN_NO_SUCH_EXTENSION", 307 }, { "GETDNS_RETURN_NO_SUCH_LIST_ITEM", 304 }, + { "GETDNS_RETURN_NO_UPSTREAM_AVAILABLE", 398 }, { "GETDNS_RETURN_UNKNOWN_TRANSACTION", 303 }, { "GETDNS_RETURN_WRONG_TYPE_REQUESTED", 306 }, { "GETDNS_RRCLASS_ANY", 255 }, diff --git a/src/context.c b/src/context.c index 16e0da92..42810e26 100644 --- a/src/context.c +++ b/src/context.c @@ -145,8 +145,7 @@ static getdns_return_t create_default_namespaces(struct getdns_context *context) static getdns_return_t create_default_dns_transports(struct getdns_context *context); static int transaction_id_cmp(const void *, const void *); static void dispatch_updated(struct getdns_context *, uint16_t); -static void cancel_dns_req(getdns_dns_req *); -static void cancel_outstanding_requests(struct getdns_context*, int); +static void cancel_outstanding_requests(getdns_context*); /* unbound helpers */ #ifdef HAVE_LIBUNBOUND @@ -692,8 +691,7 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams) while (upstream->finished_dnsreqs) { dnsreq = upstream->finished_dnsreqs; upstream->finished_dnsreqs = dnsreq->finished_next; - (void) _getdns_context_cancel_request(dnsreq->context, - dnsreq->trans_id, 1); + _getdns_context_cancel_request(dnsreq); } if (upstream->tls_obj != NULL) { if (upstream->tls_session != NULL) @@ -1377,7 +1375,7 @@ getdns_context_create_with_extended_memory_functions( result->suffixes = no_suffixes; result->suffixes_len = sizeof(no_suffixes); - gldns_buffer_init_frm_data(&gbuf, result->trust_anchors_spc + gldns_buffer_init_vfixed_frm_data(&gbuf, result->trust_anchors_spc , sizeof(result->trust_anchors_spc)); if (!_getdns_parse_ta_file(NULL, &gbuf)) { @@ -1411,8 +1409,8 @@ getdns_context_create_with_extended_memory_functions( result->tls_ctx = NULL; result->extension = &result->default_eventloop.loop; - _getdns_default_eventloop_init(&result->default_eventloop); - _getdns_default_eventloop_init(&result->sync_eventloop); + _getdns_default_eventloop_init(&result->mf, &result->default_eventloop); + _getdns_default_eventloop_init(&result->mf, &result->sync_eventloop); /* request extension defaults */ @@ -1550,7 +1548,7 @@ getdns_context_destroy(struct getdns_context *context) context->destroying = 1; /* cancel all outstanding requests */ - cancel_outstanding_requests(context, 1); + cancel_outstanding_requests(context); /* Destroy listening addresses */ (void) getdns_context_set_listen_addresses(context, NULL, NULL, NULL); @@ -1741,7 +1739,7 @@ static getdns_return_t rebuild_ub_ctx(struct getdns_context* context) { if (context->unbound_ctx != NULL) { /* cancel all requests and delete */ - cancel_outstanding_requests(context, 1); + cancel_outstanding_requests(context); ub_ctx_delete(context->unbound_ctx); context->unbound_ctx = NULL; } @@ -2369,7 +2367,7 @@ getdns_context_set_suffix(getdns_context *context, getdns_list *value) context->suffixes_len = sizeof(no_suffixes); return GETDNS_RETURN_GOOD; } - gldns_buffer_init_frm_data(&gbuf, buf_spc, sizeof(buf_spc)); + gldns_buffer_init_vfixed_frm_data(&gbuf, buf_spc, sizeof(buf_spc)); for (;;) { for ( i = 0 ; !(r = getdns_list_get_bindata(value, i, &bindata)) @@ -2918,28 +2916,68 @@ getdns_context_set_memory_functions(struct getdns_context *context, context, MF_PLAIN, mf.ext.malloc, mf.ext.realloc, mf.ext.free); } /* getdns_context_set_memory_functions*/ -/* cancel the request */ -static void -cancel_dns_req(getdns_dns_req *req) +void +_getdns_context_track_outbound_request(getdns_dns_req *dnsreq) +{ + /* Called only by getdns_general_ns() after successful allocation */ + assert(dnsreq); + + dnsreq->node.key = &(dnsreq->trans_id); + if (_getdns_rbtree_insert( + &dnsreq->context->outbound_requests, &dnsreq->node)) + getdns_context_request_count_changed(dnsreq->context); +} + +void +_getdns_context_clear_outbound_request(getdns_dns_req *dnsreq) +{ + if (!dnsreq) return; + + if (dnsreq->loop && dnsreq->loop->vmt && dnsreq->timeout.timeout_cb) { + dnsreq->loop->vmt->clear(dnsreq->loop, &dnsreq->timeout); + dnsreq->timeout.timeout_cb = NULL; + } + /* delete the node from the tree */ + if (_getdns_rbtree_delete( + &dnsreq->context->outbound_requests, &dnsreq->trans_id)) + getdns_context_request_count_changed(dnsreq->context); + + if (dnsreq->chain) + _getdns_cancel_validation_chain(dnsreq); +} + +void +_getdns_context_cancel_request(getdns_dns_req *dnsreq) { getdns_network_req *netreq, **netreq_p; - for (netreq_p = req->netreqs; (netreq = *netreq_p); netreq_p++) + DEBUG_SCHED("%s(%p)\n", __FUNC__, (void *)dnsreq); + if (!dnsreq) return; + + _getdns_context_clear_outbound_request(dnsreq); + + /* cancel network requests */ + for (netreq_p = dnsreq->netreqs; (netreq = *netreq_p); netreq_p++) #ifdef HAVE_LIBUNBOUND if (netreq->unbound_id != -1) { - ub_cancel(req->context->unbound_ctx, + ub_cancel(dnsreq->context->unbound_ctx, netreq->unbound_id); netreq->unbound_id = -1; } else #endif _getdns_cancel_stub_request(netreq); - req->canceled = 1; + /* clean up */ + _getdns_dns_req_free(dnsreq); } +/* + * getdns_cancel_callback + * + */ getdns_return_t -_getdns_context_cancel_request(getdns_context *context, - getdns_transaction_t transaction_id, int fire_callback) +getdns_cancel_callback(getdns_context *context, + getdns_transaction_t transaction_id) { getdns_dns_req *dnsreq; @@ -2951,37 +2989,65 @@ _getdns_context_cancel_request(getdns_context *context, &context->outbound_requests, &transaction_id))) return GETDNS_RETURN_UNKNOWN_TRANSACTION; - /* do the cancel */ - cancel_dns_req(dnsreq); - - if (fire_callback) { - context->processing = 1; - dnsreq->user_callback(context, GETDNS_CALLBACK_CANCEL, - NULL, dnsreq->user_pointer, transaction_id); - context->processing = 0; - } - - /* clean up */ - _getdns_dns_req_free(dnsreq); - return GETDNS_RETURN_GOOD; -} - -/* - * getdns_cancel_callback - * - */ -getdns_return_t -getdns_cancel_callback(getdns_context *context, - getdns_transaction_t transaction_id) -{ - if (!context) - return GETDNS_RETURN_INVALID_PARAMETER; - - getdns_return_t r = _getdns_context_cancel_request(context, transaction_id, 1); getdns_context_request_count_changed(context); - return r; + + if (dnsreq->user_callback) { + dnsreq->context->processing = 1; + dnsreq->user_callback(dnsreq->context, GETDNS_CALLBACK_CANCEL, + NULL, dnsreq->user_pointer, dnsreq->trans_id); + dnsreq->context->processing = 0; + } + _getdns_context_cancel_request(dnsreq); + return GETDNS_RETURN_GOOD; } /* getdns_cancel_callback */ +void +_getdns_context_request_timed_out(getdns_dns_req *dnsreq) +{ + DEBUG_SCHED("%s(%p)\n", __FUNC__, (void *)dnsreq); + + if (dnsreq->user_callback) { + dnsreq->context->processing = 1; + dnsreq->user_callback(dnsreq->context, GETDNS_CALLBACK_TIMEOUT, + _getdns_create_getdns_response(dnsreq), + dnsreq->user_pointer, dnsreq->trans_id); + dnsreq->context->processing = 0; + } + _getdns_context_cancel_request(dnsreq); +} + +static void +accumulate_outstanding_transactions(_getdns_rbnode_t *node, void* arg) +{ + *(*(getdns_transaction_t**)arg)++ = ((getdns_dns_req*)node)->trans_id; +} + +static void +cancel_outstanding_requests(getdns_context* context) +{ + getdns_transaction_t *trans_ids, *tids_a, *tids_i; + + if (context->outbound_requests.count == 0) + return; + + tids_i = tids_a = trans_ids = GETDNS_XMALLOC(context->my_mf, + getdns_transaction_t, context->outbound_requests.count); + + _getdns_traverse_postorder(&context->outbound_requests, + accumulate_outstanding_transactions, &tids_a); + + while (tids_i < tids_a) { + + /* We have to cancel by transaction_id because we do not know + * what happens when the user_callback is called. It might + * delete getdns_dns_req's that were scheduled to be canceled. + * The extra lookup with transaction_id makes sure we do not + * access freed memory. + */ + (void) getdns_cancel_callback(context, *tids_i++); + } + GETDNS_FREE(context->my_mf, trans_ids); +} #ifndef STUB_NATIVE_DNSSEC @@ -3267,54 +3333,6 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context, return r; } /* _getdns_context_prepare_for_resolution */ -getdns_return_t -_getdns_context_track_outbound_request(getdns_dns_req *dnsreq) -{ - if (!dnsreq) - return GETDNS_RETURN_INVALID_PARAMETER; - - dnsreq->node.key = &(dnsreq->trans_id); - if (!_getdns_rbtree_insert( - &dnsreq->context->outbound_requests, &dnsreq->node)) - return GETDNS_RETURN_GENERIC_ERROR; - - getdns_context_request_count_changed(dnsreq->context); - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -_getdns_context_clear_outbound_request(getdns_dns_req *dnsreq) -{ - if (!dnsreq) - return GETDNS_RETURN_INVALID_PARAMETER; - - if (!_getdns_rbtree_delete( - &dnsreq->context->outbound_requests, &dnsreq->trans_id)) - return GETDNS_RETURN_GENERIC_ERROR; - - getdns_context_request_count_changed(dnsreq->context); - return GETDNS_RETURN_GOOD; -} - -getdns_return_t -_getdns_context_request_timed_out(getdns_dns_req *req) -{ - /* Don't use req after callback */ - getdns_context* context = req->context; - getdns_transaction_t trans_id = req->trans_id; - getdns_callback_t cb = req->user_callback; - void *user_arg = req->user_pointer; - getdns_dict *response = _getdns_create_getdns_response(req); - - /* cancel the req - also clears it from outbound and cleans up*/ - _getdns_context_cancel_request(context, trans_id, 0); - context->processing = 1; - cb(context, GETDNS_CALLBACK_TIMEOUT, response, user_arg, trans_id); - context->processing = 0; - getdns_context_request_count_changed(context); - return GETDNS_RETURN_GOOD; -} - char * _getdns_strdup(const struct mem_funcs *mfs, const char *s) { @@ -3396,33 +3414,6 @@ getdns_context_run(getdns_context *context) context->extension->vmt->run(context->extension); } -typedef struct timeout_accumulator { - getdns_transaction_t* ids; - int idx; -} timeout_accumulator; - -static void -accumulate_outstanding_transactions(_getdns_rbnode_t* node, void* arg) { - timeout_accumulator* acc = (timeout_accumulator*) arg; - acc->ids[acc->idx] = *((getdns_transaction_t*) node->key); - acc->idx++; -} - -static void -cancel_outstanding_requests(struct getdns_context* context, int fire_callback) { - if (context->outbound_requests.count > 0) { - timeout_accumulator acc; - int i; - acc.idx = 0; - acc.ids = GETDNS_XMALLOC(context->my_mf, getdns_transaction_t, context->outbound_requests.count); - _getdns_traverse_postorder(&context->outbound_requests, accumulate_outstanding_transactions, &acc); - for (i = 0; i < acc.idx; ++i) { - _getdns_context_cancel_request(context, acc.ids[i], fire_callback); - } - GETDNS_FREE(context->my_mf, acc.ids); - } -} - getdns_return_t getdns_context_detach_eventloop(struct getdns_context* context) { @@ -3436,10 +3427,10 @@ getdns_context_detach_eventloop(struct getdns_context* context) * and they may destroy the context ) */ /* cancel all outstanding requests */ - cancel_outstanding_requests(context, 1); + cancel_outstanding_requests(context); context->extension->vmt->cleanup(context->extension); context->extension = &context->default_eventloop.loop; - _getdns_default_eventloop_init(&context->default_eventloop); + _getdns_default_eventloop_init(&context->mf, &context->default_eventloop); #ifdef HAVE_UNBOUND_EVENT_API if (_getdns_ub_loop_enabled(&context->ub_loop)) context->ub_loop.extension = context->extension; @@ -3454,7 +3445,7 @@ getdns_context_set_eventloop(getdns_context* context, getdns_eventloop* loop) return GETDNS_RETURN_INVALID_PARAMETER; if (context->extension) { - cancel_outstanding_requests(context, 1); + cancel_outstanding_requests(context); context->extension->vmt->cleanup(context->extension); } context->extension = loop; diff --git a/src/context.h b/src/context.h index 69eb4d21..5745fcee 100644 --- a/src/context.h +++ b/src/context.h @@ -366,19 +366,34 @@ struct getdns_context { getdns_return_t _getdns_context_prepare_for_resolution(struct getdns_context *context, int usenamespaces); -/* track an outbound request */ -getdns_return_t _getdns_context_track_outbound_request(struct getdns_dns_req - *req); -/* clear the outbound request from being tracked - does not cancel it */ -getdns_return_t _getdns_context_clear_outbound_request(struct getdns_dns_req - *req); +/* Register a getdns_dns_req with context. + * - Without pluggable unbound event API, + * ub_fd() is scheduled when this was the first request. + */ +void _getdns_context_track_outbound_request(getdns_dns_req *dnsreq); -getdns_return_t _getdns_context_request_timed_out(struct getdns_dns_req - *req); +/* Deregister getdns_dns_req from the context. + * - Without pluggable unbound event API, + * ub_fd() is scheduled when this was the first request. + * - Potential timeout events will be cleared. + * - All associated getdns_dns_reqs (to get the validation chain) + * will be canceled. + */ +void _getdns_context_clear_outbound_request(getdns_dns_req *dnsreq); -/* cancel callback internal - flag to indicate if req should be freed and callback fired */ -getdns_return_t _getdns_context_cancel_request(struct getdns_context *context, - getdns_transaction_t transaction_id, int fire_callback); +/* Cancels and frees a getdns_dns_req (without calling user callbacks) + * - Deregisters getdns_dns_req with _getdns_context_clear_outbound_request() + * - Cancels associated getdns_network_reqs + * (by calling ub_cancel() or _getdns_cancel_stub_request()) + * - Frees the getdns_dns_req + */ +void _getdns_context_cancel_request(getdns_dns_req *dnsreq); + + +/* Calls user callback (with GETDNS_CALLBACK_TIMEOUT + response dict), then + * cancels and frees the getdns_dns_req with _getdns_context_cancel_request() + */ +void _getdns_context_request_timed_out(getdns_dns_req *dnsreq); char *_getdns_strdup(const struct mem_funcs *mfs, const char *str); diff --git a/src/convert.c b/src/convert.c index 5e2c2684..6417c6d1 100644 --- a/src/convert.c +++ b/src/convert.c @@ -297,7 +297,7 @@ getdns_rr_dict2wire_scan( return GETDNS_RETURN_INVALID_PARAMETER; - gldns_buffer_init_frm_data(&gbuf, *wire, *wire_sz); + gldns_buffer_init_vfixed_frm_data(&gbuf, *wire, *wire_sz); if ((r = _getdns_rr_dict2wire(rr_dict, &gbuf))) return r; @@ -447,7 +447,7 @@ getdns_rr_dict2str_scan( if (!rr_dict || !str || !*str || !str_len) return GETDNS_RETURN_INVALID_PARAMETER; - gldns_buffer_init_frm_data(&gbuf, buf, sizeof(buf_spc)); + gldns_buffer_init_vfixed_frm_data(&gbuf, buf, sizeof(buf_spc)); r = _getdns_rr_dict2wire(rr_dict, &gbuf); if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) { if (!(buf = GETDNS_XMALLOC( @@ -960,7 +960,7 @@ getdns_msg_dict2wire_scan( if (!msg_dict || !wire || !wire_sz || (!*wire && *wire_sz)) return GETDNS_RETURN_INVALID_PARAMETER; - gldns_buffer_init_frm_data(&gbuf, *wire, *wire_sz); + gldns_buffer_init_vfixed_frm_data(&gbuf, *wire, *wire_sz); if ((r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf))) return r; @@ -1036,7 +1036,7 @@ getdns_msg_dict2str_scan( if (!msg_dict || !str || !*str || !str_len) return GETDNS_RETURN_INVALID_PARAMETER; - gldns_buffer_init_frm_data(&gbuf, buf, sizeof(buf_spc)); + gldns_buffer_init_vfixed_frm_data(&gbuf, buf, sizeof(buf_spc)); r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf); if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) { if (!(buf = GETDNS_XMALLOC( @@ -1204,6 +1204,63 @@ static int _jsmn_get_ipdict(struct mem_funcs *mf, const char *js, jsmntok_t *t, return *value != NULL; } +static int _jsmn_get_base64_data(struct mem_funcs *mf, const char *js, jsmntok_t *t, + getdns_bindata **value) +{ + int e, i; + int size = t->end - t->start; + char value_str_buf[1025]; + char *value_str; + size_t target_buf_size; + + assert(size >= 4); + + if (size % 4 != 0) + return 0; + + e = t->end; + if (js[e - 1] == '=') e -= 1; + if (js[e - 1] == '=') e -= 1; + + for (i = t->start; i < e; i++) + if (!((js[i] >= '0' && js[i] <= '9') + ||(js[i] >= 'a' && js[i] <= 'z') + ||(js[i] >= 'A' && js[i] <= 'Z') + || js[i] == '+' || js[i] == '/')) + return 0; + + target_buf_size = gldns_b64_pton_calculate_size(size); + if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata))) + return 0; + + else if (!((*value)->data = GETDNS_XMALLOC( + *mf, uint8_t, target_buf_size))) { + GETDNS_FREE(*mf, *value); + return 0; + } + if ((size_t)size >= sizeof(value_str_buf)) + value_str = GETDNS_XMALLOC(*mf, char, size + 1); + else value_str = value_str_buf; + + if (value_str) { + (void) memcpy(value_str, js + t->start, size); + value_str[size] = '\0'; + + e = gldns_b64_pton(value_str, (*value)->data, target_buf_size); + + if (value_str != value_str_buf) + GETDNS_FREE(*mf, value_str); + + if (e > 0) { + (*value)->size = e; + return 1; + } + } + GETDNS_FREE(*mf, (*value)->data); + GETDNS_FREE(*mf, *value); + return 0; +} + static int _jsmn_get_data(struct mem_funcs *mf, const char *js, jsmntok_t *t, getdns_bindata **value) { @@ -1211,15 +1268,17 @@ static int _jsmn_get_data(struct mem_funcs *mf, const char *js, jsmntok_t *t, size_t j; uint8_t h, l; - if ((t->end - t->start) < 4 || (t->end - t->start) % 2 == 1 || - js[t->start] != '0' || js[t->start + 1] != 'x') + if ((t->end - t->start) < 4 || (t->end - t->start) % 2 == 1) return 0; + if (js[t->start] != '0' || js[t->start + 1] != 'x') + return _jsmn_get_base64_data(mf, js, t, value); + for (i = t->start + 2; i < t->end; i++) if (!((js[i] >= '0' && js[i] <= '9') ||(js[i] >= 'a' && js[i] <= 'f') ||(js[i] >= 'A' && js[i] <= 'F'))) - return 0; + return _jsmn_get_base64_data(mf, js, t, value); if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata))) return 0; diff --git a/src/dict.c b/src/dict.c index eba1a728..b8c9db99 100644 --- a/src/dict.c +++ b/src/dict.c @@ -51,6 +51,7 @@ #include "const-info.h" #include "gldns/gbuffer.h" #include "gldns/wire2str.h" +#include "gldns/parseutil.h" static char *_json_ptr_first(const struct mem_funcs *mf, @@ -731,6 +732,33 @@ _getdns_bindata_is_dname(getdns_bindata *bindata) bindata->data[bindata->size - 1] == 0; } +static int +getdns_pp_base64(gldns_buffer *buf, getdns_bindata *bindata) +{ + size_t p = gldns_buffer_position(buf); + size_t base64str_sz; + char *target; + size_t avail; + + if (gldns_buffer_printf(buf, " size); + target = (char *)gldns_buffer_current(buf); + avail = gldns_buffer_remaining(buf); + if (avail >= base64str_sz) + gldns_buffer_skip(buf, gldns_b64_ntop( + bindata->data, bindata->size, + target, base64str_sz)); + else + gldns_buffer_skip(buf, base64str_sz); + + if (gldns_buffer_printf(buf, ">") < 0) + return -1; + + return gldns_buffer_position(buf) - p; +} + /*---------------------------------------- getdns_pp_bindata */ /** * private function to pretty print bindata to a gldns_buffer @@ -1094,6 +1122,16 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, )) < 0) return -1; + } else if (!json && + (strcmp(item->node.key, "pin-sha256") == 0 || + strcmp(item->node.key, "value") == 0) && + item->i.data.bindata->size > 0 && + item->i.data.bindata->size % 4 == 0) { + + if (getdns_pp_base64(buf, + item->i.data.bindata) < 0) + return -1; + } else if (getdns_pp_bindata( buf, item->i.data.bindata, (strcmp(item->node.key, "rdata_raw") == 0), @@ -1186,7 +1224,7 @@ getdns_pretty_snprint_dict(char *str, size_t size, const getdns_dict *dict) if (!dict) return -1; - gldns_buffer_init_frm_data(&buf, str, size); + gldns_buffer_init_vfixed_frm_data(&buf, str, size); return getdns_pp_dict(&buf, 0, dict, 0) < 0 ? -1 : (int)gldns_buffer_position(&buf); } @@ -1220,7 +1258,7 @@ getdns_pretty_snprint_list(char *str, size_t size, const getdns_list *list) if (!list) return -1; - gldns_buffer_init_frm_data(&buf, str, size); + gldns_buffer_init_vfixed_frm_data(&buf, str, size); return getdns_pp_list(&buf, 0, list, 0, 0) < 0 ? -1 : (int)gldns_buffer_position(&buf); } @@ -1255,7 +1293,7 @@ getdns_snprint_json_dict( if (!dict) return -1; - gldns_buffer_init_frm_data(&buf, str, size); + gldns_buffer_init_vfixed_frm_data(&buf, str, size); return getdns_pp_dict(&buf, 0, dict, pretty ? 1 : 2) < 0 ? -1 : (int)gldns_buffer_position(&buf); } @@ -1290,7 +1328,7 @@ getdns_snprint_json_list( if (!list) return -1; - gldns_buffer_init_frm_data(&buf, str, size); + gldns_buffer_init_vfixed_frm_data(&buf, str, size); return getdns_pp_list(&buf, 0, list, 0, pretty ? 1 : 2) < 0 ? -1 : (int)gldns_buffer_position(&buf); } diff --git a/src/dnssec.c b/src/dnssec.c index 0269fe3d..0396f045 100644 --- a/src/dnssec.c +++ b/src/dnssec.c @@ -1044,7 +1044,6 @@ static void val_chain_node_cb(getdns_dns_req *dnsreq) _getdns_rrsig_iter *rrsig, rrsig_spc; size_t n_signers; - _getdns_context_clear_outbound_request(dnsreq); switch (netreq->request_type) { case GETDNS_RRTYPE_DS : node->ds.pkt = netreq->response; node->ds.pkt_len = netreq->response_len; @@ -1094,7 +1093,6 @@ static void val_chain_node_soa_cb(getdns_dns_req *dnsreq) _getdns_rrset_iter i_spc, *i; _getdns_rrset *rrset; - _getdns_context_clear_outbound_request(dnsreq); /* A SOA query is always scheduled with a node as the user argument. */ assert(node != NULL); @@ -1121,8 +1119,10 @@ static void val_chain_node_soa_cb(getdns_dns_req *dnsreq) } else { /* SOA for a different name */ node = (chain_node *)dnsreq->user_pointer; - node->lock++; - val_chain_sched_soa_node(node->parent); + if (node->parent) { + node->lock++; + val_chain_sched_soa_node(node->parent); + } } } else if (node->parent) { @@ -3049,7 +3049,10 @@ static void check_chain_complete(chain_head *chain) val_chain_list = dnsreq->dnssec_return_validation_chain ? getdns_list_create_with_context(context) : NULL; - /* Walk chain to add values to val_chain_list and to cleanup */ + /* Walk chain to add values to val_chain_list. We do not cleanup yet. + * The chain will eventually be freed when the dns request is descheduled + * with getdns_context_clear_outbound_request(). + */ for ( head = chain; head ; head = next ) { next = head->next; if (dnsreq->dnssec_return_full_validation_chain && @@ -3076,7 +3079,6 @@ static void check_chain_complete(chain_head *chain) context, val_chain_list, node->dnskey_req, node->dnskey_signer); - _getdns_dns_req_free(node->dnskey_req->owner); } if (node->ds_req) { if (val_chain_list) @@ -3094,13 +3096,8 @@ static void check_chain_complete(chain_head *chain) context, val_chain_list, &node->ds); } - _getdns_dns_req_free(node->ds_req->owner); - } - if (node->soa_req) { - _getdns_dns_req_free(node->soa_req->owner); } } - GETDNS_FREE(head->my_mf, head); } response_dict = _getdns_create_getdns_response(dnsreq); @@ -3115,6 +3112,36 @@ static void check_chain_complete(chain_head *chain) _getdns_call_user_callback(dnsreq, response_dict); } +void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq) +{ + chain_head *head = dnsreq->chain, *next; + chain_node *node; + size_t node_count; + + dnsreq->chain = NULL; + while (head) { + next = head->next; + + for ( node_count = head->node_count, node = head->parent + ; node_count + ; node_count--, node = node->parent ) { + + if (node->dnskey_req) + _getdns_context_cancel_request( + node->dnskey_req->owner); + + if (node->ds_req) + _getdns_context_cancel_request( + node->ds_req->owner); + + if (node->soa_req) + _getdns_context_cancel_request( + node->soa_req->owner); + } + GETDNS_FREE(head->my_mf, head); + head = next; + } +} void _getdns_get_validation_chain(getdns_dns_req *dnsreq) { @@ -3152,6 +3179,7 @@ void _getdns_get_validation_chain(getdns_dns_req *dnsreq) for (chain_p = chain; chain_p; chain_p = chain_p->next) { if (chain_p->lock) chain_p->lock--; } + dnsreq->chain = chain; check_chain_complete(chain); } else { dnsreq->validating = 0; diff --git a/src/dnssec.h b/src/dnssec.h index 4237f933..b7becfe9 100644 --- a/src/dnssec.h +++ b/src/dnssec.h @@ -46,6 +46,7 @@ /* Do some additional requests to fetch the complete validation chain */ void _getdns_get_validation_chain(getdns_dns_req *dns_req); +void _getdns_cancel_validation_chain(getdns_dns_req *dns_req); uint16_t _getdns_parse_ta_file(time_t *ta_mtime, gldns_buffer *gbuf); diff --git a/src/extension/default_eventloop.h b/src/extension/default_eventloop.h index 7f6b78f0..7b611349 100644 --- a/src/extension/default_eventloop.h +++ b/src/extension/default_eventloop.h @@ -1,6 +1,6 @@ /* * \file default_eventloop.h - * @brief Build in default eventloop extension that uses select. + * @brief Build in default eventloop extension that uses either poll or select. * */ /* @@ -32,28 +32,13 @@ #ifndef DEFAULT_EVENTLOOP_H_ #define DEFAULT_EVENTLOOP_H_ #include "config.h" -#include "getdns/getdns.h" -#include "getdns/getdns_extra.h" - -/* No more than select's capability queries can be outstanding, - * The number of outstanding timeouts should be less or equal then - * the number of outstanding queries, so MAX_TIMEOUTS equal to - * FD_SETSIZE should be safe. - */ -#define MAX_TIMEOUTS FD_SETSIZE - -/* Eventloop based on select */ -typedef struct _getdns_default_eventloop { - getdns_eventloop loop; - getdns_eventloop_event *fd_events[FD_SETSIZE]; - uint64_t fd_timeout_times[FD_SETSIZE]; - getdns_eventloop_event *timeout_events[MAX_TIMEOUTS]; - uint64_t timeout_times[MAX_TIMEOUTS]; -} _getdns_default_eventloop; - - -void -_getdns_default_eventloop_init(_getdns_default_eventloop *loop); - +#ifdef USE_POLL_DEFAULT_EVENTLOOP +#include "extension/poll_eventloop.h" +#define _getdns_default_eventloop _getdns_poll_eventloop +#define _getdns_default_eventloop_init _getdns_poll_eventloop_init +#else +#include "extension/select_eventloop.h" +#define _getdns_default_eventloop _getdns_select_eventloop +#define _getdns_default_eventloop_init _getdns_select_eventloop_init +#endif #endif - diff --git a/src/extension/poll_eventloop.c b/src/extension/poll_eventloop.c new file mode 100644 index 00000000..b59ad64d --- /dev/null +++ b/src/extension/poll_eventloop.c @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2013, NLNet Labs, Verisign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#ifdef HAVE_SYS_POLL_H +#include +#else +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include "extension/poll_eventloop.h" +#include "debug.h" + +enum { init_fd_events_capacity = 64 + , init_to_events_capacity = 64 }; + +static void *get_to_event(_getdns_poll_eventloop *loop, + getdns_eventloop_event *event, uint64_t timeout_time) +{ + if (loop->to_events_free == loop->to_events_capacity) { + if (loop->to_events_free) { + _getdns_poll_event *to_events = GETDNS_XREALLOC( + loop->mf, loop->to_events, _getdns_poll_event, + loop->to_events_free * 2); + if (!to_events) + return NULL; + (void) memset(&to_events[loop->to_events_free], + 0, sizeof(_getdns_poll_event) + * loop->to_events_free); + + loop->to_events_capacity = loop->to_events_free * 2; + loop->to_events = to_events; + } else { + if (!(loop->to_events = GETDNS_XMALLOC(loop->mf, + _getdns_poll_event, init_to_events_capacity))) + return NULL; + + (void) memset(loop->to_events, 0, + sizeof(_getdns_poll_event) + * init_to_events_capacity); + + loop->to_events_capacity = init_to_events_capacity; + } + } + loop->to_events[loop->to_events_free].event = event; + loop->to_events[loop->to_events_free].timeout_time = timeout_time; + loop->to_events_n_used++; + return (void *) (intptr_t) (++loop->to_events_free); +} + +static void *get_fd_event(_getdns_poll_eventloop *loop, int fd, + getdns_eventloop_event *event, uint64_t timeout_time) +{ + size_t i; + + if (loop->fd_events_free == loop->fd_events_capacity) { + if (loop->fd_events_free) { + _getdns_poll_event *fd_events = GETDNS_XREALLOC( + loop->mf, loop->fd_events, _getdns_poll_event, + loop->fd_events_free * 2); + struct pollfd *pfds = GETDNS_XREALLOC( + loop->mf, loop->pfds, struct pollfd, + loop->fd_events_free * 2); + + if (!fd_events || !pfds) { + if (fd_events) + GETDNS_FREE(loop->mf, fd_events); + if (pfds) + GETDNS_FREE(loop->mf, pfds); + return NULL; + } + (void) memset(&fd_events[loop->fd_events_free], + 0, sizeof(_getdns_poll_event) + * loop->fd_events_free); + for ( i = loop->fd_events_free + ; i < loop->fd_events_free * 2 + ; i++) { + pfds[i].fd = -1; + pfds[i].events = 0; + pfds[i].revents = 0; + } + loop->fd_events_capacity = loop->fd_events_free * 2; + loop->fd_events = fd_events; + loop->pfds = pfds; + } else { + if (!(loop->fd_events = GETDNS_XMALLOC(loop->mf, + _getdns_poll_event, init_fd_events_capacity)) || + !(loop->pfds = GETDNS_XMALLOC(loop->mf, + struct pollfd, init_fd_events_capacity))) { + GETDNS_NULL_FREE(loop->mf, loop->fd_events); + return NULL; + } + (void) memset(loop->fd_events, 0, + sizeof(_getdns_poll_event) + * init_fd_events_capacity); + for (i = 0; i < init_fd_events_capacity; i++) { + loop->pfds[i].fd = -1; + loop->pfds[i].events = 0; + loop->pfds[i].revents = 0; + } + loop->fd_events_capacity = init_fd_events_capacity; + } + } + loop->pfds[loop->fd_events_free].fd = fd; + loop->pfds[loop->fd_events_free].events = 0; + if (event->read_cb) + loop->pfds[loop->fd_events_free].events |= POLLIN; + if (event->write_cb) + loop->pfds[loop->fd_events_free].events |= POLLOUT; + loop->fd_events[loop->fd_events_free].event = event; + loop->fd_events[loop->fd_events_free].timeout_time = timeout_time; + loop->fd_events_n_used++; + return (void *) (intptr_t) (++loop->fd_events_free); +} + +static uint64_t get_now_plus(uint64_t amount) +{ + struct timeval tv; + uint64_t now; + + if (gettimeofday(&tv, NULL)) { + perror("gettimeofday() failed"); + exit(EXIT_FAILURE); + } + now = tv.tv_sec * 1000000 + tv.tv_usec; + + return (now + amount * 1000) >= now + ? now + amount * 1000 : TIMEOUT_FOREVER; +} + +static getdns_return_t +poll_eventloop_schedule(getdns_eventloop *loop, + int fd, uint64_t timeout, getdns_eventloop_event *event) +{ + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + + DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p)\n" + , __FUNC__, (void *)loop, fd, timeout, (void *)event); + + if (!loop || !event) + return GETDNS_RETURN_INVALID_PARAMETER; + + if (fd >= 0 && !(event->read_cb || event->write_cb)) { + DEBUG_SCHED("WARNING: fd event without " + "read or write cb!\n"); + fd = -1; + } + if (fd >= 0) { + if (!(event->ev = get_fd_event( + poll_loop, fd, event, get_now_plus(timeout)))) { + DEBUG_SCHED("ERROR: scheduled read/write slots!\n"); + return GETDNS_RETURN_GENERIC_ERROR; + } + DEBUG_SCHED( "scheduled read/write at for %d at %p\n" + , fd, (void *)event->ev); + return GETDNS_RETURN_GOOD; + } + if (!event->timeout_cb) { + DEBUG_SCHED("ERROR: fd < 0 without timeout_cb!\n"); + return GETDNS_RETURN_GENERIC_ERROR; + } + if (event->read_cb) { + DEBUG_SCHED("ERROR: timeout event with read_cb! Clearing.\n"); + event->read_cb = NULL; + } + if (event->write_cb) { + DEBUG_SCHED("ERROR: timeout event with write_cb! Clearing.\n"); + event->write_cb = NULL; + } + if (!(event->ev = get_to_event(poll_loop, event, get_now_plus(timeout)))) { + DEBUG_SCHED("ERROR: Out of timeout slots!\n"); + return GETDNS_RETURN_GENERIC_ERROR; + } + DEBUG_SCHED("scheduled timeout at slot %p\n", (void *)event->ev); + return GETDNS_RETURN_GOOD; +} + +static getdns_return_t +poll_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) +{ + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + + if (!loop || !event) + return GETDNS_RETURN_INVALID_PARAMETER; + + DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNC__, (void *)loop, (void *)event); + + if (!event->ev) + return GETDNS_RETURN_GOOD; + + else if (event->timeout_cb && !event->read_cb && !event->write_cb) { + size_t i = ((size_t) (intptr_t) event->ev) - 1; + + /* This may happen with full recursive synchronous requests + * with the unbound pluggable event API, because the default + * poll_eventloop is temporarily replaced by a poll_eventloop + * used only in synchronous calls. When the synchronous request + * had an answer, the poll_eventloop for the synchronous is + * cleaned, however it could still have outstanding events. + */ + if (i >= poll_loop->to_events_capacity || + poll_loop->to_events[i].event != event) { + event->ev = NULL; + DEBUG_SCHED( "ERROR: Event mismatch %p\n", (void *)event->ev); + return GETDNS_RETURN_GENERIC_ERROR; + } + poll_loop->to_events[i].event = NULL; + if (--poll_loop->to_events_n_used == 0) { + poll_loop->to_events_free = 0; + } + DEBUG_SCHED( "cleared timeout at slot %p\n", (void *)event->ev); + } else { + size_t i = ((size_t) (intptr_t) event->ev) - 1; + + /* This may happen with full recursive synchronous requests + * with the unbound pluggable event API, because the default + * poll_eventloop is temporarily replaced by a poll_eventloop + * used only in synchronous calls. When the synchronous request + * had an answer, the poll_eventloop for the synchronous is + * cleaned, however it could still have outstanding events. + */ + if (i >= poll_loop->fd_events_capacity || + poll_loop->fd_events[i].event != event) { + event->ev = NULL; + DEBUG_SCHED( "ERROR: Event mismatch %p\n", (void *)event->ev); + return GETDNS_RETURN_GENERIC_ERROR; + } + poll_loop->fd_events[i].event = NULL; + if (--poll_loop->fd_events_n_used == 0) { + poll_loop->fd_events_free = 0; + } + DEBUG_SCHED( "cleared read/write for %d at slot %p\n" + , poll_loop->pfds[i].fd, (void *)event->ev); + poll_loop->pfds[i].fd = -1; /* Not necessary, but to be sure */ + } + event->ev = NULL; + return GETDNS_RETURN_GOOD; +} + +static void +poll_eventloop_cleanup(getdns_eventloop *loop) +{ + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + struct mem_funcs *mf = &poll_loop->mf; + + GETDNS_NULL_FREE(*mf, poll_loop->pfds); + if (poll_loop->fd_events) { + GETDNS_FREE(*mf, poll_loop->fd_events); + poll_loop->fd_events = NULL; + poll_loop->fd_events_capacity = 0; + poll_loop->fd_events_free = 0; + poll_loop->fd_events_n_used = 0; + } + if (poll_loop->to_events) { + GETDNS_FREE(*mf, poll_loop->to_events); + poll_loop->to_events = NULL; + poll_loop->to_events_capacity = 0; + poll_loop->to_events_free = 0; + poll_loop->to_events_n_used = 0; + } +} + +static void +poll_read_cb(int fd, getdns_eventloop_event *event) +{ +#if !defined(SCHED_DEBUG) || !SCHED_DEBUG + (void)fd; +#endif + DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); + event->read_cb(event->userarg); +} + +static void +poll_write_cb(int fd, getdns_eventloop_event *event) +{ +#if !defined(SCHED_DEBUG) || !SCHED_DEBUG + (void)fd; +#endif + DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event); + event->write_cb(event->userarg); +} + +static void +poll_timeout_cb(getdns_eventloop_event *event) +{ + DEBUG_SCHED( "%s(event: %p)\n", __FUNC__, (void *)event); + event->timeout_cb(event->userarg); +} + +static void +poll_eventloop_run_once(getdns_eventloop *loop, int blocking) +{ + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + uint64_t now, timeout = TIMEOUT_FOREVER; + size_t i = 0, j; + int poll_timeout = 0; + + if (!loop) + return; + + now = get_now_plus(0); + + for (i = 0, j = 0; i < poll_loop->to_events_free; i++, j++) { + while (poll_loop->to_events[i].event == NULL) { + if (++i == poll_loop->to_events_free) { + poll_loop->to_events_free = j; + break; + } + } + if (j < i) { + if (j >= poll_loop->to_events_free) + break; + poll_loop->to_events[j] = poll_loop->to_events[i]; + poll_loop->to_events[i].event = NULL; + poll_loop->to_events[j].event->ev = + (void *) (intptr_t) (j + 1); + } + if (poll_loop->to_events[j].timeout_time < now) + poll_timeout_cb(poll_loop->to_events[j].event); + } + for (i = 0, j = 0; i < poll_loop->to_events_free; i++, j++) { + while (poll_loop->to_events[i].event == NULL) { + if (++i == poll_loop->to_events_free) { + poll_loop->to_events_free = j; + break; + } + } + if (j < i) { + if (j >= poll_loop->to_events_free) + break; + poll_loop->to_events[j] = poll_loop->to_events[i]; + poll_loop->to_events[i].event = NULL; + poll_loop->to_events[j].event->ev = + (void *) (intptr_t) (j + 1); + } + if (poll_loop->to_events[j].timeout_time < timeout) + timeout = poll_loop->to_events[j].timeout_time; + } + if ((timeout == TIMEOUT_FOREVER) && (poll_loop->fd_events_free == 0)) + return; + + for (i = 0, j = 0; i < poll_loop->fd_events_free; i++, j++) { + while (poll_loop->fd_events[i].event == NULL) { + if (++i == poll_loop->fd_events_free) { + poll_loop->fd_events_free = j; + break; + } + } + if (j < i) { + if (j >= poll_loop->fd_events_free) + break; + poll_loop->fd_events[j] = poll_loop->fd_events[i]; + poll_loop->fd_events[i].event = NULL; + poll_loop->fd_events[j].event->ev = + (void *) (intptr_t) (j + 1); + poll_loop->pfds[j] = poll_loop->pfds[i]; + poll_loop->pfds[i].fd = -1; + } + if (poll_loop->fd_events[j].timeout_time < timeout) + timeout = poll_loop->fd_events[j].timeout_time; + } + + if (timeout == TIMEOUT_FOREVER) { + poll_timeout = -1; + + } else if (! blocking || now > timeout) { + poll_timeout = 0; + } else { + /* turn microseconds into milliseconds */ + poll_timeout = (timeout - now) / 1000; + } + DEBUG_SCHED( "poll(fd_free: %d, fd_used: %d, to_free: %d, to_used: %d, timeout: %d)\n" + , (int)poll_loop->fd_events_free, (int)poll_loop->fd_events_n_used + , (int)poll_loop->to_events_free, (int)poll_loop->to_events_n_used + , poll_timeout + ); +#ifdef USE_WINSOCK + if (WSAPoll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) { +#else + if (poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) { +#endif + perror("poll() failed"); + exit(EXIT_FAILURE); + } + now = get_now_plus(0); + + for (i = 0, j = 0; i < poll_loop->fd_events_free; i++, j++) { + while (poll_loop->fd_events[i].event == NULL) { + if (++i == poll_loop->fd_events_free) { + poll_loop->fd_events_free = j; + break; + } + } + if (j < i) { + if (j >= poll_loop->fd_events_free) + break; + poll_loop->fd_events[j] = poll_loop->fd_events[i]; + poll_loop->fd_events[i].event = NULL; + poll_loop->fd_events[j].event->ev = + (void *) (intptr_t) (j + 1); + poll_loop->pfds[j] = poll_loop->pfds[i]; + poll_loop->pfds[i].fd = -1; + } + if (poll_loop->fd_events[j].event->write_cb && + poll_loop->pfds[j].revents & POLLOUT) + poll_write_cb( poll_loop->pfds[j].fd + , poll_loop->fd_events[j].event); + + if (poll_loop->fd_events[j].event && + poll_loop->fd_events[j].event->read_cb && + poll_loop->pfds[j].revents & POLLIN) + poll_read_cb( poll_loop->pfds[j].fd + , poll_loop->fd_events[j].event); + } + for (i = 0, j = 0; i < poll_loop->fd_events_free; i++, j++) { + while (poll_loop->fd_events[i].event == NULL) { + if (++i == poll_loop->fd_events_free) { + poll_loop->fd_events_free = j; + break; + } + } + if (j < i) { + if (j >= poll_loop->fd_events_free) + break; + poll_loop->fd_events[j] = poll_loop->fd_events[i]; + poll_loop->fd_events[i].event = NULL; + poll_loop->fd_events[j].event->ev = + (void *) (intptr_t) (j + 1); + poll_loop->pfds[j] = poll_loop->pfds[i]; + poll_loop->pfds[i].fd = -1; + } + if (poll_loop->fd_events[j].timeout_time < now) + poll_timeout_cb(poll_loop->fd_events[j].event); + } + + for (i = 0, j = 0; i < poll_loop->to_events_free; i++, j++) { + while (poll_loop->to_events[i].event == NULL) { + if (++i == poll_loop->to_events_free) { + poll_loop->to_events_free = j; + break; + } + } + if (j < i) { + if (j >= poll_loop->to_events_free) + break; + poll_loop->to_events[j] = poll_loop->to_events[i]; + poll_loop->to_events[i].event = NULL; + poll_loop->to_events[j].event->ev = + (void *) (intptr_t) (j + 1); + } + if (poll_loop->to_events[j].timeout_time < now) + poll_timeout_cb(poll_loop->to_events[j].event); + } +} + +static void +poll_eventloop_run(getdns_eventloop *loop) +{ + _getdns_poll_eventloop *poll_loop = (_getdns_poll_eventloop *)loop; + + if (!loop) + return; + + /* keep going until all the events are cleared */ + while (poll_loop->fd_events_n_used || poll_loop->to_events_n_used) { + poll_eventloop_run_once(loop, 1); + } +} + +void +_getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop) +{ + static getdns_eventloop_vmt poll_eventloop_vmt = { + poll_eventloop_cleanup, + poll_eventloop_schedule, + poll_eventloop_clear, + poll_eventloop_run, + poll_eventloop_run_once + }; + + loop->loop.vmt = &poll_eventloop_vmt; + loop->mf = *mf; + + loop->to_events_capacity = init_to_events_capacity; + if ((loop->to_events = GETDNS_XMALLOC( + *mf, _getdns_poll_event, init_to_events_capacity))) + (void) memset(loop->to_events, 0, + sizeof(_getdns_poll_event) * init_to_events_capacity); + else + loop->to_events_capacity = 0; + loop->to_events_free = 0; + loop->to_events_n_used = 0; + + loop->fd_events_capacity = init_fd_events_capacity; + if ((loop->fd_events = GETDNS_XMALLOC( + *mf, _getdns_poll_event, init_fd_events_capacity)) && + (loop->pfds = GETDNS_XMALLOC( + *mf, struct pollfd, init_fd_events_capacity))) { + size_t i; + + (void) memset(loop->fd_events, 0, + sizeof(_getdns_poll_event) * init_fd_events_capacity); + for (i = 0; i < init_fd_events_capacity; i++) { + loop->pfds[i].fd = -1; + loop->pfds[i].events = 0; + loop->pfds[i].revents = 0; + } + } else { + loop->fd_events_capacity = 0; + if (loop->fd_events) { + GETDNS_FREE(*mf, loop->fd_events); + loop->fd_events = NULL; + } + } + loop->fd_events_free = 0; + loop->fd_events_n_used = 0; +} + diff --git a/src/extension/poll_eventloop.h b/src/extension/poll_eventloop.h new file mode 100644 index 00000000..e4e4bb7e --- /dev/null +++ b/src/extension/poll_eventloop.h @@ -0,0 +1,66 @@ +/* + * \file poll_eventloop.h + * @brief Build in default eventloop extension that uses select. + * + */ +/* + * Copyright (c) 2013, NLNet Labs, Verisign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef POLL_EVENTLOOP_H_ +#define POLL_EVENTLOOP_H_ +#include "config.h" +#include "getdns/getdns.h" +#include "getdns/getdns_extra.h" +#include "types-internal.h" + +/* Eventloop based on poll */ + +typedef struct _getdns_poll_event { + getdns_eventloop_event *event; + uint64_t timeout_time; +} _getdns_poll_event; + +typedef struct _getdns_poll_eventloop { + getdns_eventloop loop; + struct mem_funcs mf; + + struct pollfd *pfds; + size_t fd_events_capacity; + _getdns_poll_event *fd_events; + size_t fd_events_free; + size_t fd_events_n_used; + + size_t to_events_capacity; + _getdns_poll_event *to_events; + size_t to_events_free; + size_t to_events_n_used; +} _getdns_poll_eventloop; + +void +_getdns_poll_eventloop_init(struct mem_funcs *mf, _getdns_poll_eventloop *loop); + +#endif + diff --git a/src/extension/default_eventloop.c b/src/extension/select_eventloop.c similarity index 65% rename from src/extension/default_eventloop.c rename to src/extension/select_eventloop.c index e9e74550..1b889fc1 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/select_eventloop.c @@ -27,7 +27,7 @@ #include "config.h" -#include "extension/default_eventloop.h" +#include "extension/select_eventloop.h" #include "debug.h" #include "types-internal.h" @@ -47,10 +47,10 @@ static uint64_t get_now_plus(uint64_t amount) } static getdns_return_t -default_eventloop_schedule(getdns_eventloop *loop, +select_eventloop_schedule(getdns_eventloop *loop, int fd, uint64_t timeout, getdns_eventloop_event *event) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + _getdns_select_eventloop *select_loop = (_getdns_select_eventloop *)loop; size_t i; DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, FD_SETSIZE: %d)\n" @@ -71,20 +71,20 @@ default_eventloop_schedule(getdns_eventloop *loop, } if (fd >= 0) { #if defined(SCHED_DEBUG) && SCHED_DEBUG - if (default_loop->fd_events[fd]) { - if (default_loop->fd_events[fd] == event) { + if (select_loop->fd_events[fd]) { + if (select_loop->fd_events[fd] == event) { DEBUG_SCHED("WARNING: Event %p not cleared " "before being rescheduled!\n" - , (void *)default_loop->fd_events[fd]); + , (void *)select_loop->fd_events[fd]); } else { DEBUG_SCHED("ERROR: A different event is " "already present at fd slot: %p!\n" - , (void *)default_loop->fd_events[fd]); + , (void *)select_loop->fd_events[fd]); } } #endif - default_loop->fd_events[fd] = event; - default_loop->fd_timeout_times[fd] = get_now_plus(timeout); + select_loop->fd_events[fd] = event; + select_loop->fd_timeout_times[fd] = get_now_plus(timeout); event->ev = (void *)(intptr_t)(fd + 1); DEBUG_SCHED( "scheduled read/write at %d\n", fd); return GETDNS_RETURN_GOOD; @@ -102,9 +102,9 @@ default_eventloop_schedule(getdns_eventloop *loop, event->write_cb = NULL; } for (i = 0; i < MAX_TIMEOUTS; i++) { - if (default_loop->timeout_events[i] == NULL) { - default_loop->timeout_events[i] = event; - default_loop->timeout_times[i] = get_now_plus(timeout); + if (select_loop->timeout_events[i] == NULL) { + select_loop->timeout_events[i] = event; + select_loop->timeout_times[i] = get_now_plus(timeout); event->ev = (void *)(intptr_t)(i + 1); DEBUG_SCHED( "scheduled timeout at %d\n", (int)i); return GETDNS_RETURN_GOOD; @@ -115,9 +115,9 @@ default_eventloop_schedule(getdns_eventloop *loop, } static getdns_return_t -default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) +select_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + _getdns_select_eventloop *select_loop = (_getdns_select_eventloop *)loop; ssize_t i; if (!loop || !event) @@ -131,33 +131,33 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event) } if (event->timeout_cb && !event->read_cb && !event->write_cb) { #if defined(SCHED_DEBUG) && SCHED_DEBUG - if (default_loop->timeout_events[i] != event) + if (select_loop->timeout_events[i] != event) DEBUG_SCHED( "ERROR: Different/wrong event present at " "timeout slot: %p!\n" - , (void *)default_loop->timeout_events[i]); + , (void *)select_loop->timeout_events[i]); #endif - default_loop->timeout_events[i] = NULL; + select_loop->timeout_events[i] = NULL; } else { #if defined(SCHED_DEBUG) && SCHED_DEBUG - if (default_loop->fd_events[i] != event) + if (select_loop->fd_events[i] != event) DEBUG_SCHED( "ERROR: Different/wrong event present at " "fd slot: %p!\n" - , (void *)default_loop->fd_events[i]); + , (void *)select_loop->fd_events[i]); #endif - default_loop->fd_events[i] = NULL; + select_loop->fd_events[i] = NULL; } event->ev = NULL; return GETDNS_RETURN_GOOD; } static void -default_eventloop_cleanup(getdns_eventloop *loop) +select_eventloop_cleanup(getdns_eventloop *loop) { (void)loop; } static void -default_read_cb(int fd, getdns_eventloop_event *event) +select_read_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG (void)fd; @@ -167,7 +167,7 @@ default_read_cb(int fd, getdns_eventloop_event *event) } static void -default_write_cb(int fd, getdns_eventloop_event *event) +select_write_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG (void)fd; @@ -177,7 +177,7 @@ default_write_cb(int fd, getdns_eventloop_event *event) } static void -default_timeout_cb(int fd, getdns_eventloop_event *event) +select_timeout_cb(int fd, getdns_eventloop_event *event) { #if !defined(SCHED_DEBUG) || !SCHED_DEBUG (void)fd; @@ -187,9 +187,9 @@ default_timeout_cb(int fd, getdns_eventloop_event *event) } static void -default_eventloop_run_once(getdns_eventloop *loop, int blocking) +select_eventloop_run_once(getdns_eventloop *loop, int blocking) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + _getdns_select_eventloop *select_loop = (_getdns_select_eventloop *)loop; fd_set readfds, writefds; int fd, max_fd = -1; @@ -205,24 +205,24 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) now = get_now_plus(0); for (i = 0; i < MAX_TIMEOUTS; i++) { - if (!default_loop->timeout_events[i]) + if (!select_loop->timeout_events[i]) continue; - if (now > default_loop->timeout_times[i]) - default_timeout_cb(-1, default_loop->timeout_events[i]); - else if (default_loop->timeout_times[i] < timeout) - timeout = default_loop->timeout_times[i]; + if (now > select_loop->timeout_times[i]) + select_timeout_cb(-1, select_loop->timeout_events[i]); + else if (select_loop->timeout_times[i] < timeout) + timeout = select_loop->timeout_times[i]; } for (fd = 0; fd < (int)FD_SETSIZE; fd++) { - if (!default_loop->fd_events[fd]) + if (!select_loop->fd_events[fd]) continue; - if (default_loop->fd_events[fd]->read_cb) + if (select_loop->fd_events[fd]->read_cb) FD_SET(fd, &readfds); - if (default_loop->fd_events[fd]->write_cb) + if (select_loop->fd_events[fd]->write_cb) FD_SET(fd, &writefds); if (fd > max_fd) max_fd = fd; - if (default_loop->fd_timeout_times[fd] < timeout) - timeout = default_loop->fd_timeout_times[fd]; + if (select_loop->fd_timeout_times[fd] < timeout) + timeout = select_loop->fd_timeout_times[fd]; } if (max_fd == -1 && timeout == TIMEOUT_FOREVER) return; @@ -241,33 +241,33 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) } now = get_now_plus(0); for (fd = 0; fd < (int)FD_SETSIZE; fd++) { - if (default_loop->fd_events[fd] && - default_loop->fd_events[fd]->read_cb && + if (select_loop->fd_events[fd] && + select_loop->fd_events[fd]->read_cb && FD_ISSET(fd, &readfds)) - default_read_cb(fd, default_loop->fd_events[fd]); + select_read_cb(fd, select_loop->fd_events[fd]); - if (default_loop->fd_events[fd] && - default_loop->fd_events[fd]->write_cb && + if (select_loop->fd_events[fd] && + select_loop->fd_events[fd]->write_cb && FD_ISSET(fd, &writefds)) - default_write_cb(fd, default_loop->fd_events[fd]); + select_write_cb(fd, select_loop->fd_events[fd]); - if (default_loop->fd_events[fd] && - default_loop->fd_events[fd]->timeout_cb && - now > default_loop->fd_timeout_times[fd]) - default_timeout_cb(fd, default_loop->fd_events[fd]); + if (select_loop->fd_events[fd] && + select_loop->fd_events[fd]->timeout_cb && + now > select_loop->fd_timeout_times[fd]) + select_timeout_cb(fd, select_loop->fd_events[fd]); i = fd; - if (default_loop->timeout_events[i] && - default_loop->timeout_events[i]->timeout_cb && - now > default_loop->timeout_times[i]) - default_timeout_cb(-1, default_loop->timeout_events[i]); + if (select_loop->timeout_events[i] && + select_loop->timeout_events[i]->timeout_cb && + now > select_loop->timeout_times[i]) + select_timeout_cb(-1, select_loop->timeout_events[i]); } } static void -default_eventloop_run(getdns_eventloop *loop) +select_eventloop_run(getdns_eventloop *loop) { - _getdns_default_eventloop *default_loop = (_getdns_default_eventloop *)loop; + _getdns_select_eventloop *select_loop = (_getdns_select_eventloop *)loop; size_t i; if (!loop) @@ -275,8 +275,8 @@ default_eventloop_run(getdns_eventloop *loop) i = 0; while (i < MAX_TIMEOUTS) { - if (default_loop->fd_events[i] || default_loop->timeout_events[i]) { - default_eventloop_run_once(loop, 1); + if (select_loop->fd_events[i] || select_loop->timeout_events[i]) { + select_eventloop_run_once(loop, 1); i = 0; } else { i++; @@ -285,16 +285,16 @@ default_eventloop_run(getdns_eventloop *loop) } void -_getdns_default_eventloop_init(_getdns_default_eventloop *loop) +_getdns_select_eventloop_init(struct mem_funcs *mf, _getdns_select_eventloop *loop) { - static getdns_eventloop_vmt default_eventloop_vmt = { - default_eventloop_cleanup, - default_eventloop_schedule, - default_eventloop_clear, - default_eventloop_run, - default_eventloop_run_once + static getdns_eventloop_vmt select_eventloop_vmt = { + select_eventloop_cleanup, + select_eventloop_schedule, + select_eventloop_clear, + select_eventloop_run, + select_eventloop_run_once }; - - (void) memset(loop, 0, sizeof(_getdns_default_eventloop)); - loop->loop.vmt = &default_eventloop_vmt; + (void) mf; + (void) memset(loop, 0, sizeof(_getdns_select_eventloop)); + loop->loop.vmt = &select_eventloop_vmt; } diff --git a/src/extension/select_eventloop.h b/src/extension/select_eventloop.h new file mode 100644 index 00000000..e830a2ac --- /dev/null +++ b/src/extension/select_eventloop.h @@ -0,0 +1,58 @@ +/* + * \file select_eventloop.h + * @brief Build in default eventloop extension that uses select. + * + */ +/* + * Copyright (c) 2013, NLNet Labs, Verisign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the names of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SELECT_EVENTLOOP_H_ +#define SELECT_EVENTLOOP_H_ +#include "config.h" +#include "getdns/getdns.h" +#include "getdns/getdns_extra.h" + +/* No more than select's capability queries can be outstanding, + * The number of outstanding timeouts should be less or equal then + * the number of outstanding queries, so MAX_TIMEOUTS equal to + * FD_SETSIZE should be safe. + */ +#define MAX_TIMEOUTS FD_SETSIZE + +/* Eventloop based on select */ +typedef struct _getdns_select_eventloop { + getdns_eventloop loop; + getdns_eventloop_event *fd_events[FD_SETSIZE]; + uint64_t fd_timeout_times[FD_SETSIZE]; + getdns_eventloop_event *timeout_events[MAX_TIMEOUTS]; + uint64_t timeout_times[MAX_TIMEOUTS]; +} _getdns_select_eventloop; + + +void +_getdns_select_eventloop_init(struct mem_funcs *mf, _getdns_select_eventloop *loop); + +#endif diff --git a/src/general.c b/src/general.c index 97a97dcf..69dc7462 100644 --- a/src/general.c +++ b/src/general.c @@ -54,31 +54,19 @@ #include "dict.h" #include "mdns.h" -/* cancel, cleanup and send timeout to callback */ -static void -ub_resolve_timeout(void *arg) +void _getdns_call_user_callback(getdns_dns_req *dnsreq, getdns_dict *response) { - getdns_dns_req *dns_req = (getdns_dns_req *) arg; - (void) _getdns_context_request_timed_out(dns_req); -} + _getdns_context_clear_outbound_request(dnsreq); -void _getdns_call_user_callback(getdns_dns_req *dns_req, - struct getdns_dict *response) -{ - struct getdns_context *context = dns_req->context; - getdns_transaction_t trans_id = dns_req->trans_id; - getdns_callback_t cb = dns_req->user_callback; - void *user_arg = dns_req->user_pointer; - - /* clean up */ - _getdns_context_clear_outbound_request(dns_req); - _getdns_dns_req_free(dns_req); - - context->processing = 1; - cb(context, - (response ? GETDNS_CALLBACK_COMPLETE : GETDNS_CALLBACK_ERROR), - response, user_arg, trans_id); - context->processing = 0; + if (dnsreq->user_callback) { + dnsreq->context->processing = 1; + dnsreq->user_callback(dnsreq->context, + (response ? GETDNS_CALLBACK_COMPLETE + : GETDNS_CALLBACK_ERROR), + response, dnsreq->user_pointer, dnsreq->trans_id); + dnsreq->context->processing = 0; + } + _getdns_dns_req_free(dnsreq); } static int @@ -186,9 +174,10 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req) return; } } - if (dns_req->internal_cb) + if (dns_req->internal_cb) { + _getdns_context_clear_outbound_request(dns_req); dns_req->internal_cb(dns_req); - else if (! results_found) + } else if (! results_found) _getdns_call_user_callback(dns_req, NULL); else if (dns_req->dnssec_return_validation_chain #ifdef DNSSEC_ROADBLOCK_AVOIDANCE @@ -290,7 +279,9 @@ _getdns_submit_netreq(getdns_network_req *netreq) dns_req->timeout.userarg = dns_req; dns_req->timeout.read_cb = NULL; dns_req->timeout.write_cb = NULL; - dns_req->timeout.timeout_cb = ub_resolve_timeout; + dns_req->timeout.timeout_cb = + (getdns_eventloop_callback) + _getdns_context_request_timed_out; dns_req->timeout.ev = NULL; if ((r = dns_req->loop->vmt->schedule(dns_req->loop, -1, dns_req->context->timeout, &dns_req->timeout))) diff --git a/src/getdns/getdns_extra.h.in b/src/getdns/getdns_extra.h.in index 5abf39e7..a76564eb 100644 --- a/src/getdns/getdns_extra.h.in +++ b/src/getdns/getdns_extra.h.in @@ -56,6 +56,8 @@ extern "C" { * \defgroup Ureturnvaluesandtext Additional return values and texts * @{ */ +#define GETDNS_RETURN_NO_UPSTREAM_AVAILABLE ((getdns_return_t) 398 ) +#define GETDNS_RETURN_NO_UPSTREAM_AVAILABLE_TEXT "None of the configured upstreams could be used to send queries on the specified transports" #define GETDNS_RETURN_NEED_MORE_SPACE ((getdns_return_t) 399 ) #define GETDNS_RETURN_NEED_MORE_SPACE_TEXT "The buffer was too small" /** @} diff --git a/src/gldns/gbuffer.c b/src/gldns/gbuffer.c index ac70415d..04c257fb 100644 --- a/src/gldns/gbuffer.c +++ b/src/gldns/gbuffer.c @@ -33,6 +33,7 @@ gldns_buffer_new(size_t capacity) buffer->_position = 0; buffer->_limit = buffer->_capacity = capacity; buffer->_fixed = 0; + buffer->_vfixed = 0; buffer->_status_err = 0; gldns_buffer_invariant(buffer); @@ -48,6 +49,7 @@ gldns_buffer_new_frm_data(gldns_buffer *buffer, void *data, size_t size) buffer->_position = 0; buffer->_limit = buffer->_capacity = size; buffer->_fixed = 0; + buffer->_vfixed = 0; buffer->_data = malloc(size); if(!buffer->_data) { buffer->_status_err = 1; @@ -66,6 +68,17 @@ gldns_buffer_init_frm_data(gldns_buffer *buffer, void *data, size_t size) buffer->_data = data; buffer->_capacity = buffer->_limit = size; buffer->_fixed = 1; + buffer->_vfixed = 0; +} + +void +gldns_buffer_init_vfixed_frm_data(gldns_buffer *buffer, void *data, size_t size) +{ + memset(buffer, 0, sizeof(*buffer)); + buffer->_data = data; + buffer->_capacity = buffer->_limit = size; + buffer->_fixed = 1; + buffer->_vfixed = 1; } int @@ -120,20 +133,19 @@ gldns_buffer_printf(gldns_buffer *buffer, const char *format, ...) remaining = gldns_buffer_remaining(buffer); va_start(args, format); - written = _gldns_vsnprintf((char*)gldns_buffer_current(buffer), - remaining, format, args); + written = vsnprintf((char *) gldns_buffer_current(buffer), remaining, + format, args); va_end(args); if (written == -1) { buffer->_status_err = 1; return -1; - } else if (!buffer->_fixed && (size_t) written >= remaining) { + } else if (!buffer->_vfixed && (size_t) written >= remaining) { if (!gldns_buffer_reserve(buffer, (size_t) written + 1)) { buffer->_status_err = 1; return -1; } va_start(args, format); - written = _gldns_vsnprintf( - (char *) gldns_buffer_current(buffer), + written = vsnprintf((char *) gldns_buffer_current(buffer), gldns_buffer_remaining(buffer), format, args); va_end(args); if (written == -1) { diff --git a/src/gldns/gbuffer.h b/src/gldns/gbuffer.h index 2db9e250..1b1eb498 100644 --- a/src/gldns/gbuffer.h +++ b/src/gldns/gbuffer.h @@ -27,21 +27,6 @@ extern "C" { # endif #endif -#ifndef USE_WINSOCK -#define _gldns_vsnprintf vsnprintf -#else -/* Unlike Linux and BSD, vsnprintf on Windows returns -1 on overflow. - * Here it is redefined to always return the amount printed - * if enough space had been available. - */ -INLINE int -_gldns_vsnprintf(char *str, size_t size, const char *format, va_list ap) -{ - int r = vsnprintf(str, size, format, ap); - return r == -1 ? _vscprintf(format, ap) : r; -} -#endif - /* * Copy data allowing for unaligned accesses in network byte order * (big endian). @@ -145,6 +130,17 @@ struct gldns_buffer /** If the buffer is fixed it cannot be resized */ unsigned _fixed : 1; + /** If the buffer is vfixed, no more than capacity bytes willl be + * written to _data, however the _position counter will be updated + * with the amount that would have been written in consecutive + * writes. This allows for a modus operandi in which a sequence is + * written on a fixed capacity buffer (perhaps with _data on stack). + * When everything could be written, then the _data is immediately + * usable, if not, then a buffer could be allocated sized precisely + * to fit the data for a second attempt. + */ + unsigned _vfixed : 1; + /** The current state of the buffer. If writing to the buffer fails * for any reason, this value is changed. This way, you can perform * multiple writes in sequence and check for success afterwards. */ @@ -162,9 +158,9 @@ INLINE void gldns_buffer_invariant(gldns_buffer *buffer) { assert(buffer != NULL); - assert(buffer->_position <= buffer->_limit || buffer->_fixed); + assert(buffer->_position <= buffer->_limit || buffer->_vfixed); assert(buffer->_limit <= buffer->_capacity); - assert(buffer->_data != NULL || (buffer->_capacity == 0 && buffer->_fixed)); + assert(buffer->_data != NULL || (buffer->_vfixed && buffer->_capacity == 0)); } #endif @@ -196,6 +192,19 @@ void gldns_buffer_new_frm_data(gldns_buffer *buffer, void *data, size_t size); */ void gldns_buffer_init_frm_data(gldns_buffer *buffer, void *data, size_t size); +/** + * Setup a buffer with the data pointed to. No data copied, no memory allocs. + * The buffer is "virtually" fixed. Writes beyond size (the capacity) will + * only update position, but no data will be written beyond capacity. This + * allows to determine how big the buffer should have been to contain all the + * written data, by looking at the position with gldns_buffer_position(), + * similarly to the return value of POSIX's snprintf. + * \param[in] buffer pointer to the buffer to put the data in + * \param[in] data the data to encapsulate in the buffer + * \param[in] size the size of the data + */ +void gldns_buffer_init_vfixed_frm_data(gldns_buffer *buffer, void *data, size_t size); + /** * clears the buffer and make it ready for writing. The buffer's limit * is set to the capacity and the position is set to 0. @@ -259,7 +268,7 @@ gldns_buffer_position(gldns_buffer *buffer) INLINE void gldns_buffer_set_position(gldns_buffer *buffer, size_t mark) { - assert(mark <= buffer->_limit || buffer->_fixed); + assert(mark <= buffer->_limit || buffer->_vfixed); buffer->_position = mark; } @@ -273,7 +282,7 @@ gldns_buffer_set_position(gldns_buffer *buffer, size_t mark) INLINE void gldns_buffer_skip(gldns_buffer *buffer, ssize_t count) { - assert(buffer->_position + count <= buffer->_limit || buffer->_fixed); + assert(buffer->_position + count <= buffer->_limit || buffer->_vfixed); buffer->_position += count; } @@ -345,7 +354,7 @@ int gldns_buffer_reserve(gldns_buffer *buffer, size_t amount); INLINE uint8_t * gldns_buffer_at(const gldns_buffer *buffer, size_t at) { - assert(at <= buffer->_limit || buffer->_fixed); + assert(at <= buffer->_limit || buffer->_vfixed); return buffer->_data + at; } @@ -395,6 +404,7 @@ INLINE size_t gldns_buffer_remaining_at(gldns_buffer *buffer, size_t at) { gldns_buffer_invariant(buffer); + assert(at <= buffer->_limit || buffer->_vfixed); return at < buffer->_limit ? buffer->_limit - at : 0; } @@ -447,7 +457,7 @@ gldns_buffer_available(gldns_buffer *buffer, size_t count) INLINE void gldns_buffer_write_at(gldns_buffer *buffer, size_t at, const void *data, size_t count) { - if (!buffer->_fixed) + if (!buffer->_vfixed) assert(gldns_buffer_available_at(buffer, at, count)); else if (gldns_buffer_remaining_at(buffer, at) == 0) return; @@ -504,7 +514,7 @@ gldns_buffer_write_string(gldns_buffer *buffer, const char *str) INLINE void gldns_buffer_write_u8_at(gldns_buffer *buffer, size_t at, uint8_t data) { - if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return; + if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return; assert(gldns_buffer_available_at(buffer, at, sizeof(data))); buffer->_data[at] = data; } @@ -530,7 +540,7 @@ gldns_buffer_write_u8(gldns_buffer *buffer, uint8_t data) INLINE void gldns_buffer_write_u16_at(gldns_buffer *buffer, size_t at, uint16_t data) { - if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return; + if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return; assert(gldns_buffer_available_at(buffer, at, sizeof(data))); gldns_write_uint16(buffer->_data + at, data); } @@ -556,7 +566,7 @@ gldns_buffer_write_u16(gldns_buffer *buffer, uint16_t data) INLINE void gldns_buffer_write_u32_at(gldns_buffer *buffer, size_t at, uint32_t data) { - if (buffer->_fixed && at + sizeof(data) > buffer->_limit) return; + if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return; assert(gldns_buffer_available_at(buffer, at, sizeof(data))); gldns_write_uint32(buffer->_data + at, data); } @@ -570,7 +580,7 @@ gldns_buffer_write_u32_at(gldns_buffer *buffer, size_t at, uint32_t data) INLINE void gldns_buffer_write_u48_at(gldns_buffer *buffer, size_t at, uint64_t data) { - if (buffer->_fixed && at + 6 > buffer->_limit) return; + if (buffer->_vfixed && at + 6 > buffer->_limit) return; assert(gldns_buffer_available_at(buffer, at, 6)); gldns_write_uint48(buffer->_data + at, data); } diff --git a/src/gldns/rrdef.h b/src/gldns/rrdef.h index f00fa33c..58132c23 100644 --- a/src/gldns/rrdef.h +++ b/src/gldns/rrdef.h @@ -372,6 +372,8 @@ enum gldns_enum_algorithm GLDNS_ECC_GOST = 12, /* RFC 5933 */ GLDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */ GLDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */ + GLDNS_ED25519 = 15, /* RFC 8080 */ + GLDNS_ED448 = 16, /* RFC 8080 */ GLDNS_INDIRECT = 252, GLDNS_PRIVATEDNS = 253, GLDNS_PRIVATEOID = 254 diff --git a/src/gldns/wire2str.c b/src/gldns/wire2str.c index 50d00967..35a6df9d 100644 --- a/src/gldns/wire2str.c +++ b/src/gldns/wire2str.c @@ -47,6 +47,8 @@ static gldns_lookup_table gldns_algorithms_data[] = { { GLDNS_ECC_GOST, "ECC-GOST"}, { GLDNS_ECDSAP256SHA256, "ECDSAP256SHA256"}, { GLDNS_ECDSAP384SHA384, "ECDSAP384SHA384"}, + { GLDNS_ED25519, "ED25519"}, + { GLDNS_ED448, "ED448"}, { GLDNS_INDIRECT, "INDIRECT" }, { GLDNS_PRIVATEDNS, "PRIVATEDNS" }, { GLDNS_PRIVATEOID, "PRIVATEOID" }, @@ -279,7 +281,7 @@ int gldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen) int gldns_str_vprint(char** str, size_t* slen, const char* format, va_list args) { - int w = _gldns_vsnprintf(*str, *slen, format, args); + int w = vsnprintf(*str, *slen, format, args); if(w < 0) { /* error in printout */ return 0; diff --git a/src/jsmn b/src/jsmn new file mode 160000 index 00000000..868c22e3 --- /dev/null +++ b/src/jsmn @@ -0,0 +1 @@ +Subproject commit 868c22e35ec223fc26ddefdb9ca83901dc6e2534 diff --git a/src/mdns.c b/src/mdns.c index 9efef1ff..9fa872ac 100644 --- a/src/mdns.c +++ b/src/mdns.c @@ -1757,7 +1757,7 @@ static void mdns_cleanup(getdns_network_req *netreq) { DEBUG_MDNS("%s %-35s: MSG: %p\n", - MDNS_DEBUG_CLEANUP, __FUNCTION__, netreq); + MDNS_DEBUG_CLEANUP, __FUNC__, netreq); getdns_dns_req *dnsreq = netreq->owner; GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); @@ -1781,7 +1781,7 @@ mdns_timeout_cb(void *userarg) { getdns_network_req *netreq = (getdns_network_req *)userarg; DEBUG_MDNS("%s %-35s: MSG: %p\n", - MDNS_DEBUG_CLEANUP, __FUNCTION__, netreq); + MDNS_DEBUG_CLEANUP, __FUNC__, netreq); /* TODO: do we need a retry logic here? */ @@ -1815,7 +1815,7 @@ mdns_udp_read_cb(void *userarg) getdns_dns_req *dnsreq = netreq->owner; ssize_t read; DEBUG_MDNS("%s %-35s: MSG: %p \n", MDNS_DEBUG_READ, - __FUNCTION__, netreq); + __FUNC__, netreq); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); @@ -1869,7 +1869,7 @@ mdns_udp_write_cb(void *userarg) int r; DEBUG_MDNS("%s %-35s: MSG: %p \n", MDNS_DEBUG_WRITE, - __FUNCTION__, netreq); + __FUNC__, netreq); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); @@ -1917,7 +1917,7 @@ mdns_udp_write_cb(void *userarg) getdns_return_t _getdns_submit_mdns_request(getdns_network_req *netreq) { - DEBUG_MDNS("%s %-35s: MSG: %p TYPE: %d\n", MDNS_DEBUG_ENTRY, __FUNCTION__, + DEBUG_MDNS("%s %-35s: MSG: %p TYPE: %d\n", MDNS_DEBUG_ENTRY, __FUNC__, netreq, netreq->request_type); int fd = -1; getdns_dns_req *dnsreq = netreq->owner; @@ -2244,4 +2244,4 @@ int mdns_test_prepare(struct getdns_context* context) return mdns_delayed_network_init(context); } -#endif \ No newline at end of file +#endif diff --git a/src/request-internal.c b/src/request-internal.c index 37ba93b4..eae467e9 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -383,7 +383,7 @@ _getdns_network_req_add_tsig(getdns_network_req *req) #endif tsig_info = _getdns_get_tsig_info(upstream->tsig_alg); - gldns_buffer_init_frm_data(&gbuf, req->response, MAXIMUM_TSIG_SPACE); + gldns_buffer_init_vfixed_frm_data(&gbuf, req->response, MAXIMUM_TSIG_SPACE); gldns_buffer_write(&gbuf, upstream->tsig_dname, upstream->tsig_dname_len); /* Name */ gldns_buffer_write_u16(&gbuf, GETDNS_RRCLASS_ANY); /* Class */ @@ -644,7 +644,7 @@ _getdns_dns_req_free(getdns_dns_req * req) network_req_cleanup(*net_req); /* clear timeout event */ - if (req->timeout.timeout_cb) { + if (req->loop && req->loop->vmt && req->timeout.timeout_cb) { req->loop->vmt->clear(req->loop, &req->timeout); req->timeout.timeout_cb = NULL; } @@ -896,9 +896,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, } result->context = context; result->loop = loop; - result->canceled = 0; - result->trans_id = (((uint64_t)arc4random()) << 32) | - ((uint64_t)arc4random()); + result->trans_id = (uint64_t) (intptr_t) result; result->dnssec_return_status = dnssec_return_status; result->dnssec_return_only_secure = dnssec_return_only_secure; result->dnssec_return_all_statuses = dnssec_return_all_statuses; @@ -934,6 +932,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, result->finished_next = NULL; result->freed = NULL; result->validating = 0; + result->chain = NULL; network_req_init(result->netreqs[0], result, request_type, dnssec_extension_set, with_opt, diff --git a/src/stub.c b/src/stub.c index 9421f5d8..e905f600 100644 --- a/src/stub.c +++ b/src/stub.c @@ -520,7 +520,7 @@ stub_cleanup(getdns_network_req *netreq) static void upstream_failed(getdns_upstream *upstream, int during_setup) { - DEBUG_STUB("%s %-35s: FD: %d During setup = %d\n", + DEBUG_STUB("%s %-35s: FD: %d Failure during connection setup = %d\n", STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd, during_setup); /* Fallback code should take care of queue queries and then close conn when idle.*/ @@ -602,7 +602,7 @@ stub_timeout_cb(void *userarg) if (netreq->owner->user_callback) { netreq->debug_end_time = _getdns_get_time_as_uintt64(); /* Note this calls cancel_request which calls stub_cleanup again....!*/ - (void) _getdns_context_request_timed_out(netreq->owner); + _getdns_context_request_timed_out(netreq->owner); } else _getdns_check_dns_req_complete(netreq->owner); } @@ -868,13 +868,21 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd, err, X509_verify_cert_error_string(err)); #endif +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG + if (!preverify_ok && !upstream->tls_fallback_ok) + DEBUG_DAEMON("%s %s : Conn failed : Transport=TLS - *Failure* - (%d) \"%s\"\n", + STUB_DEBUG_DAEMON, upstream->addr_str, err, + X509_verify_cert_error_string(err)); +#endif /* First deal with the hostname authentication done by OpenSSL. */ #ifdef X509_V_ERR_HOSTNAME_MISMATCH +# if defined(STUB_DEBUG) && STUB_DEBUG /*Report if error is hostname mismatch*/ if (err == X509_V_ERR_HOSTNAME_MISMATCH && upstream->tls_fallback_ok) - DEBUG_STUB("%s %-35s: FD: %d WARNING: Proceeding even though hostname validation failed!\n", - STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd); + DEBUG_STUB("%s %-35s: FD: %d WARNING: Proceeding even though hostname validation failed!\n", + STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd); +# endif #else /* if we weren't built against OpenSSL with hostname matching we * could not have matched the hostname, so this would be an automatic @@ -897,9 +905,15 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) if (upstream->tls_fallback_ok) DEBUG_STUB("%s %-35s: FD: %d, WARNING: Proceeding even though pinset validation failed!\n", STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd); +#if defined(DAEMON_DEBUG) && DAEMON_DEBUG + else + DEBUG_DAEMON("%s %s : Conn failed : Transport=TLS - *Failure* - Pinset validation failure\n", + STUB_DEBUG_DAEMON, upstream->addr_str); +#endif } else { /* If we _only_ had a pinset and it is good then force succesful - authentication when the cert self-signed */ + authentication when the cert self-signed + TODO: We need to check for other error cases here, not blindly accept the cert!! */ if ((upstream->tls_pubkey_pinset && upstream->tls_auth_name[0] == '\0') && (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN || err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)) { @@ -915,6 +929,7 @@ tls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) else if (upstream->tls_auth_state == GETDNS_AUTH_NONE && (upstream->tls_pubkey_pinset || upstream->tls_auth_name[0])) upstream->tls_auth_state = GETDNS_AUTH_OK; + /* If fallback is allowed, proceed regardless of what the auth error is (might not be hostname or pinset related) */ return (upstream->tls_fallback_ok) ? 1 : preverify_ok; @@ -1299,8 +1314,6 @@ stub_udp_read_cb(void *userarg) DEBUG_STUB("%s %-35s: MSG: %p \n", STUB_DEBUG_READ, __FUNC__, (void*)netreq); - GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); - read = recvfrom(netreq->fd, (void *)netreq->response, netreq->max_udp_payload_size + 1, /* If read == max_udp_payload_size * then all is good. If read == @@ -1322,6 +1335,8 @@ stub_udp_read_cb(void *userarg) upstream, netreq->response, read)) return; /* Client cookie didn't match? */ + GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); + #ifdef USE_WINSOCK closesocket(netreq->fd); #else @@ -2023,8 +2038,7 @@ _getdns_submit_stub_request(getdns_network_req *netreq) * All other set up is done async*/ fd = upstream_find_for_netreq(netreq); if (fd == -1) - /* Handle better, will give unhelpful error is some cases */ - return GETDNS_RETURN_GENERIC_ERROR; + return GETDNS_RETURN_NO_UPSTREAM_AVAILABLE; getdns_transport_list_t transport = netreq->transports[netreq->transport_current]; diff --git a/src/test/Makefile.in b/src/test/Makefile.in index c481fdab..758435c1 100644 --- a/src/test/Makefile.in +++ b/src/test/Makefile.in @@ -216,10 +216,13 @@ depend: .PHONY: clean test # Dependencies for the unit tests -check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c ../getdns/getdns.h $(srcdir)/check_getdns_common.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 \ +check_getdns.lo check_getdns.o: $(srcdir)/check_getdns.c \ + ../getdns/getdns.h \ + $(srcdir)/check_getdns_common.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_dns_transport.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_service.h $(srcdir)/check_getdns_service_sync.h \ $(srcdir)/check_getdns_transport.h -check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c ../getdns/getdns.h \ - ../config.h $(srcdir)/check_getdns_common.h ../getdns/getdns_extra.h \ +check_getdns_common.lo check_getdns_common.o: $(srcdir)/check_getdns_common.c \ + ../getdns/getdns.h \ + ../config.h \ + $(srcdir)/check_getdns_common.h \ + ../getdns/getdns_extra.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 \ $(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 \ - ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libev.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h + ../config.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 \ - ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libevent.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_libevent.h $(srcdir)/check_getdns_common.h + ../config.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 \ - ../config.h ../getdns/getdns.h $(srcdir)/../getdns/getdns_ext_libuv.h \ - ../getdns/getdns_extra.h $(srcdir)/check_getdns_common.h + ../config.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 \ - $(srcdir)/check_getdns_eventloop.h ../config.h ../getdns/getdns.h \ + $(srcdir)/check_getdns_eventloop.h \ + ../config.h \ + ../getdns/getdns.h \ ../getdns/getdns_extra.h 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 -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 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_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h ../getdns/getdns.h -tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.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 \ +tests_dict.lo tests_dict.o: $(srcdir)/tests_dict.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h +tests_list.lo tests_list.o: $(srcdir)/tests_list.c $(srcdir)/testmessages.h \ + ../getdns/getdns.h +tests_namespaces.lo tests_namespaces.o: $(srcdir)/tests_namespaces.c $(srcdir)/testmessages.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 diff --git a/src/test/tpkg/clean.sh b/src/test/tpkg/clean.sh new file mode 100755 index 00000000..b3ebef5e --- /dev/null +++ b/src/test/tpkg/clean.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +export SRCDIR=`dirname $0` +( cd $SRCDIR + ./tpkg clean + rm -fr build build-stub-only build-event-loops install scan-build-reports .tpkg.var.master +) diff --git a/src/tools/Makefile.in b/src/tools/Makefile.in index d98cf437..d066e824 100644 --- a/src/tools/Makefile.in +++ b/src/tools/Makefile.in @@ -113,5 +113,8 @@ depend: .PHONY: clean test # Dependencies for getdns_query -getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \ - ../getdns/getdns.h ../getdns/getdns_extra.h +getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c \ + ../config.h \ + $(srcdir)/../debug.h \ + ../getdns/getdns.h \ + ../getdns/getdns_extra.h diff --git a/src/tools/getdns_query.c b/src/tools/getdns_query.c index 61825f1b..bb452929 100644 --- a/src/tools/getdns_query.c +++ b/src/tools/getdns_query.c @@ -215,7 +215,7 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t\tThe file must be in json dict format.\n"); if (i_am_stubby) { fprintf(out, "\t\tBy default, configuration is first read from"); - fprintf(out, "\t\t\"/etc/stubby.conf\" and then from \"$HOME/.stubby.conf\""); + fprintf(out, "\n\t\t\"/etc/stubby.conf\" and then from \"$HOME/.stubby.conf\"\n"); } fprintf(out, "\t-D\tSet edns0 do bit\n"); fprintf(out, "\t-d\tclear edns0 do bit\n"); diff --git a/src/tools/stubby.conf b/src/tools/stubby.conf index 5deb03db..1055e277 100644 --- a/src/tools/stubby.conf +++ b/src/tools/stubby.conf @@ -5,54 +5,54 @@ , tls_auth_name: "dnsovertls.sinodun.com" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0xA132D34D34C181765337C70B83E3697B9524DDDB05A7118B43C0284033D5A0CC + , value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4= } ] }, { address_data: 145.100.185.16 , tls_auth_name: "dnsovertls1.sinodun.com" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0x659B41EB08DCC70EE9D624E6219C76EE31954DA1548B0C8519EAE5228CB24150 + , value: cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA= } ] }, { address_data: 185.49.141.38 , tls_auth_name: "getdnsapi.net" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0x7e8c59467221f606695a797ecc488a6b4109dab7421aba0c5a6d3681ac5273d4 + , value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q= } ] }, { address_data: 2001:610:1:40ba:145:100:185:15 , tls_auth_name: "dnsovertls.sinodun.com" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0xA132D34D34C181765337C70B83E3697B9524DDDB05A7118B43C0284033D5A0CC + , value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4= } ] }, { address_data: 2001:610:1:40ba:145:100:185:16 , tls_auth_name: "dnsovertls1.sinodun.com" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0x659B41EB08DCC70EE9D624E6219C76EE31954DA1548B0C8519EAE5228CB24150 + , value: cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA= } ] }, { address_data: 2a04:b900:0:100::38 , tls_auth_name: "getdnsapi.net" , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0x7e8c59467221f606695a797ecc488a6b4109dab7421aba0c5a6d3681ac5273d4 + , value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q= } ] }, { address_data: 184.105.193.78 , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0xA4E5EBA54B7D9203E06D6C411457014DB447DA17A8DB01F05E9D5F7780045572 + , value: pOXrpUt9kgPgbWxBFFcBTbRH2heo2wHwXp1fd4AEVXI= } ] }, { address_data: 2620:ff:c000:0:1::64:25 , tls_pubkey_pinset: [ { digest: "sha256" - , value: 0xA4E5EBA54B7D9203E06D6C411457014DB447DA17A8DB01F05E9D5F7780045572 + , value: pOXrpUt9kgPgbWxBFFcBTbRH2heo2wHwXp1fd4AEVXI= } ] } ] diff --git a/src/types-internal.h b/src/types-internal.h index 8f3e7ce2..922730a7 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -272,6 +272,7 @@ typedef struct getdns_network_req static inline int _getdns_netreq_finished(getdns_network_req *req) { return !req || (req->state & NET_REQ_FINISHED); } +struct chain_head; /** * dns request - manages a number of network requests and * the initial data passed to getdns_general @@ -294,9 +295,6 @@ typedef struct getdns_dns_req { size_t suffix_len; unsigned suffix_appended : 1; - /* canceled flag */ - unsigned canceled : 1; - /* request extensions */ unsigned dnssec_return_status : 1; unsigned dnssec_return_only_secure : 1; @@ -327,6 +325,9 @@ typedef struct getdns_dns_req { unsigned validating : 1; int *freed; + /* Validation chain to be canceled when this request is canceled */ + struct chain_head *chain; + uint16_t tls_query_padding_blocksize; /* internally scheduled request */ diff --git a/src/util-internal.c b/src/util-internal.c index c25cf5ce..fe05cd83 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -1510,7 +1510,7 @@ uint8_t *_getdns_list2wire( gldns_buffer gbuf; size_t sz; - gldns_buffer_init_frm_data(&gbuf, buf, *buf_len); + gldns_buffer_init_vfixed_frm_data(&gbuf, buf, *buf_len); _getdns_list2wire_buf(&gbuf, l); if ((sz = gldns_buffer_position(&gbuf)) <= *buf_len) { @@ -1531,7 +1531,7 @@ uint8_t *_getdns_reply2wire( gldns_buffer gbuf; size_t sz; - gldns_buffer_init_frm_data(&gbuf, buf, *buf_len); + gldns_buffer_init_vfixed_frm_data(&gbuf, buf, *buf_len); _getdns_reply2wire_buf(&gbuf, r); if ((sz = gldns_buffer_position(&gbuf)) <= *buf_len) {