mirror of https://github.com/getdnsapi/getdns.git
Merge branch 'develop'
This commit is contained in:
commit
3098ed6fca
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
|||
* 2017-11-11: Version 1.2.1
|
||||
* Handle more I/O error cases. Also, when an I/O error does occur,
|
||||
never stop listening (with servers), and
|
||||
never exit (when running the built-in event loop).
|
||||
* Bugfix: Tolerate unsigned and unused RRsets in the authority section.
|
||||
Fixes DNSSEC with BIND upstream.
|
||||
* Bugfix: DNSSEC validation without support records
|
||||
* Bugfix: Validation of full recursive DNSKEY lookups
|
||||
* Bugfix: Retry to validate full recursion BOGUS replies with zero
|
||||
configuration DNSSEC only when DNSSEC was actually requested
|
||||
* Bugfix #348: Fix a linking issue in stubby when libbsd is present
|
||||
Thanks Remi Gacogne
|
||||
* More robust scheduling; Eliminating a segfault with long running
|
||||
applications.
|
||||
* Miscellaneous Windows portability fixes from Jim Hague.
|
||||
* Fix Makefile dependencies for parallel install.
|
||||
Thanks ilovezfs
|
||||
|
||||
* 2017-09-29: Version 1.2.0
|
||||
* Bugfix of rc1: authentication of first query with TLS
|
||||
Thanks Travis Burtrum
|
||||
|
|
151
configure.ac
151
configure.ac
|
@ -36,7 +36,18 @@ sinclude(./m4/acx_getaddrinfo.m4)
|
|||
sinclude(./m4/ax_check_compile_flag.m4)
|
||||
sinclude(./m4/pkg.m4)
|
||||
|
||||
AC_INIT([getdns], [1.2.0], [users@getdnsapi.net], [], [https://getdnsapi.net])
|
||||
AC_INIT([getdns], [1.2.1], [team@getdnsapi.net], [getdns], [https://getdnsapi.net])
|
||||
|
||||
# Autoconf 2.70 will have set up runstatedir. 2.69 is frequently (Debian)
|
||||
# patched to do the same, but frequently (MacOS) not. So add a with option
|
||||
# for pid file location, and default it to runstatedir if present.
|
||||
default_piddir=${runstatedir:-"${localstatedir}/run"}
|
||||
AC_ARG_WITH([piddir],
|
||||
[AS_HELP_STRING([--with-piddir=DIR],
|
||||
[directory for pid files @<:@default=RUNSTATEDIR or LOCALSTATEDIR/run@:>@])],
|
||||
[],
|
||||
[with_piddir=${default_piddir}])
|
||||
AC_SUBST([runstatedir], [$with_piddir])
|
||||
|
||||
# Dont forget to put a dash in front of the release candidate!!!
|
||||
# That is how it is done with semantic versioning!
|
||||
|
@ -51,7 +62,7 @@ AC_ARG_WITH([current-date],
|
|||
[CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"])
|
||||
|
||||
AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"])
|
||||
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x01020000])
|
||||
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x01020100])
|
||||
AC_SUBST(API_VERSION, ["December 2015"])
|
||||
AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00])
|
||||
GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API"
|
||||
|
@ -86,9 +97,10 @@ GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRE
|
|||
# getdns-1.1.1 had libversion 6:1:0
|
||||
# getdns-1.1.2 had libversion 7:0:1
|
||||
# getdns-1.1.3 had libversion 7:1:1
|
||||
# getdns-1.2.0 has libversion 8:0:2
|
||||
# getdns-1.2.0 had libversion 8:0:2
|
||||
# getdns-1.2.1 has libversion 8:1:2
|
||||
#
|
||||
GETDNS_LIBVERSION=8:0:2
|
||||
GETDNS_LIBVERSION=8:1:2
|
||||
|
||||
AC_SUBST(GETDNS_COMPILATION_COMMENT)
|
||||
AC_SUBST(GETDNS_LIBVERSION)
|
||||
|
@ -253,7 +265,7 @@ esac
|
|||
|
||||
|
||||
DEFAULT_EVENTLOOP=select_eventloop
|
||||
AC_CHECK_HEADERS([sys/poll.h poll.h sys/resource.h sys/types.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([signal.h sys/poll.h poll.h sys/resource.h sys/types.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_ARG_ENABLE(poll-eventloop, AC_HELP_STRING([--disable-poll-eventloop], [Disable default eventloop based on poll (default=enabled if available)]))
|
||||
case "$enable_poll_eventloop" in
|
||||
no)
|
||||
|
@ -588,7 +600,7 @@ case "$enable_ed25519" in
|
|||
no)
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
if test "$USE_NSS" = "no" -a "$USE_NETTLE" = "no"; then
|
||||
AC_CHECK_DECLS([NID_ED25519], [
|
||||
AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.])
|
||||
use_ed25519="yes"
|
||||
|
@ -676,28 +688,30 @@ if test "$USE_WINSOCK" = 1; then
|
|||
LIBS="$LIBS -lgdi32 -liphlpapi"
|
||||
fi
|
||||
|
||||
dnl Check if -D_POSIX is needed for sigset_t
|
||||
|
||||
AC_CHECK_TYPE([sigset_t], [
|
||||
AC_MSG_NOTICE(-D_POSIX is NOT needed for the sigset_t type)
|
||||
], [
|
||||
BACKCFLAGS="$CFLAGS"
|
||||
CFLAGS="-D_POSIX $CFLAGS"
|
||||
AC_CHECK_TYPE([sigset_t], [
|
||||
AC_MSG_NOTICE(-D_POSIX is needed for the sigset_t type)
|
||||
], [
|
||||
AC_MSG_NOTICE(Unclear whether -D_POSIX is needed for the sigset_t type)
|
||||
BACKCFLAGS="$CFLAGS"
|
||||
], [AC_INCLUDES_DEFAULT
|
||||
dnl sigset_t or _sigset_t? MinGW is latter by default.
|
||||
AC_CHECK_TYPES([sigset_t],
|
||||
[],
|
||||
[AC_CHECK_TYPES([_sigset_t],
|
||||
[],
|
||||
[AC_MSG_ERROR([Can't find type `sigset_t' or type `_sigset_t'])],
|
||||
[AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
])
|
||||
], [AC_INCLUDES_DEFAULT
|
||||
])
|
||||
],
|
||||
[AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
])
|
||||
AC_CHECK_FUNCS(sigemptyset sigfillset sigaddset)
|
||||
|
||||
my_with_libidn=1
|
||||
AC_ARG_WITH(libidn, AS_HELP_STRING([--with-libidn=pathname],
|
||||
|
@ -1144,8 +1158,8 @@ AC_SUBST(INSTALL_STUBBY)
|
|||
AC_SUBST(UNINSTALL_STUBBY)
|
||||
AC_SUBST(STUBBY_XTRA_OBJS)
|
||||
|
||||
STUBBY_LDFLAGS=""
|
||||
STUBBY_LIBS=""
|
||||
STUBBY_LDFLAGS=""
|
||||
|
||||
if test $my_with_yaml = 1
|
||||
then
|
||||
|
@ -1153,8 +1167,8 @@ then
|
|||
then
|
||||
getdns_LIBS="$LIBS"
|
||||
getdns_LDFLAGS="$LDFLAGS"
|
||||
LIBS=""
|
||||
LDFLAGS=""
|
||||
LIBS="$initial_LIBS"
|
||||
LDFLAGS="$initial_LDFLAGS"
|
||||
fi
|
||||
AC_ARG_WITH(libyaml, AS_HELP_STRING([--with-libyaml=pathname],
|
||||
[path to libyaml (default: search /usr/local ..)]),
|
||||
|
@ -1267,11 +1281,12 @@ fi
|
|||
# system implementation.
|
||||
PKG_CHECK_MODULES([LIBBSD],[libbsd-overlay],[
|
||||
LIBS="$LIBS $LIBBSD_LIBS"
|
||||
STUBBY_LIBS="$STUBBY_LIBS $LIBBSD_LIBS"
|
||||
CFLAGS="$CFLAGS $LIBBSD_CFLAGS"
|
||||
],[
|
||||
AC_MSG_WARN([libbsd not found or usable; using embedded code instead])
|
||||
])
|
||||
AC_CHECK_DECLS([strlcpy,arc4random,arc4random_uniform])
|
||||
AC_CHECK_DECLS([inet_pton,inet_ntop,strlcpy,arc4random,arc4random_uniform])
|
||||
AC_REPLACE_FUNCS(inet_pton)
|
||||
AC_REPLACE_FUNCS(inet_ntop)
|
||||
AC_REPLACE_FUNCS(strlcpy)
|
||||
|
@ -1347,7 +1362,38 @@ AH_BOTTOM([
|
|||
# ifndef FD_SETSIZE
|
||||
# define FD_SETSIZE 1024
|
||||
# endif
|
||||
# define PRIsz "Iu"
|
||||
|
||||
/* the version of the windows API enabled */
|
||||
# ifndef WINVER
|
||||
# define WINVER 0x0600 // 0x0502
|
||||
# endif
|
||||
# ifndef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0600 // 0x0502
|
||||
# endif
|
||||
# ifdef HAVE_WS2TCPIP_H
|
||||
# include <ws2tcpip.h>
|
||||
# endif
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# if _MSC_VER >= 1800
|
||||
# define PRIsz "zu"
|
||||
# else
|
||||
# define PRIsz "Iu"
|
||||
# endif
|
||||
# else
|
||||
# define PRIsz "Iu"
|
||||
# endif
|
||||
|
||||
# ifdef HAVE_WINSOCK2_H
|
||||
# include <winsock2.h>
|
||||
# endif
|
||||
|
||||
/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
|
||||
# ifdef HAVE_WINSOCK2_H
|
||||
# define FD_SET_T (u_int)
|
||||
# else
|
||||
# define FD_SET_T
|
||||
# endif
|
||||
|
||||
/* Windows wants us to use _strdup instead of strdup */
|
||||
# ifndef strdup
|
||||
|
@ -1363,34 +1409,6 @@ AH_BOTTOM([
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
/* the version of the windows API enabled */
|
||||
#ifndef WINVER
|
||||
#define WINVER 0x0600 // 0x0502
|
||||
#endif
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0600 // 0x0502
|
||||
#endif
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#ifndef USE_WINSOCK
|
||||
#define ARG_LL "%ll"
|
||||
#else
|
||||
#define ARG_LL "%I64"
|
||||
#endif
|
||||
|
||||
/* detect if we need to cast to unsigned int for FD_SET to avoid warnings */
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#define FD_SET_T (u_int)
|
||||
#else
|
||||
#define FD_SET_T
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -1437,11 +1455,11 @@ void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
|
|||
unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest);
|
||||
#endif /* COMPAT_SHA512 */
|
||||
|
||||
#ifndef HAVE_INET_PTON
|
||||
#ifndef HAVE_DECL_INET_PTON
|
||||
int inet_pton(int af, const char* src, void* dst);
|
||||
#endif /* HAVE_INET_PTON */
|
||||
|
||||
#ifndef HAVE_INET_NTOP
|
||||
#ifndef HAVE_DECL_INET_NTOP
|
||||
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif
|
||||
|
||||
|
@ -1544,12 +1562,29 @@ static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *fo
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_STRPTIME) || !defined(STRPTIME_WORKS)
|
||||
#define strptime unbound_strptime
|
||||
struct tm;
|
||||
char *strptime(const char *s, const char *format, struct tm *tm);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SIGSET_T) && defined(HAVE__SIGSET_T)
|
||||
typedef _sigset_t sigset_t;
|
||||
#endif
|
||||
#if !defined(HAVE_SIGEMPTYSET)
|
||||
# define sigemptyset(pset) (*(pset) = 0)
|
||||
#endif
|
||||
#if !defined(HAVE_SIGFILLSET)
|
||||
# define sigfillset(pset) (*(pset) = (sigset_t)-1)
|
||||
#endif
|
||||
#if !defined(HAVE_SIGADDSET)
|
||||
# define sigaddset(pset, num) (*(pset) |= (1L<<(num)))
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBUNBOUND
|
||||
# include <unbound.h>
|
||||
# ifdef HAVE_UNBOUND_EVENT_H
|
||||
|
@ -1567,6 +1602,10 @@ int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
|
|||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
])
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
|
|
@ -77,7 +77,7 @@ C99COMPATFLAGS=@C99COMPATFLAGS@
|
|||
DEFAULT_EVENTLOOP_OBJ=@DEFAULT_EVENTLOOP@.lo
|
||||
|
||||
GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \
|
||||
list.lo request-internal.lo pubkey-pinning.lo rr-dict.lo \
|
||||
list.lo request-internal.lo platform.lo pubkey-pinning.lo rr-dict.lo \
|
||||
rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo \
|
||||
mdns.lo
|
||||
|
||||
|
@ -160,7 +160,7 @@ install-headers: getdns/getdns.h getdns/getdns_extra.h
|
|||
uninstall-headers:
|
||||
rm -rf $(DESTDIR)$(includedir)/getdns
|
||||
|
||||
install-libs: libgetdns.la
|
||||
install-libs: libgetdns.la $(EXTENSION_LIBEVENT_LIB) $(EXTENSION_LIBUV_LIB) $(EXTENSION_LIBEV_LIB)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(libdir)
|
||||
$(LIBTOOL) --mode=install cp libgetdns.la $(DESTDIR)$(libdir)
|
||||
if test $(have_libevent) = 1 ; then $(LIBTOOL) --mode=install cp $(EXTENSION_LIBEVENT_LIB) $(DESTDIR)$(libdir) ; fi
|
||||
|
@ -223,6 +223,7 @@ install-stubby-files-windows: stubby.yml.windows
|
|||
install-stubby: stubby install-stubby-files-@HOSTOS@
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
|
||||
$(LIBTOOL) --mode=install cp stubby $(DESTDIR)$(bindir)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(runstatedir)
|
||||
|
||||
uninstall-stubby:
|
||||
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/stubby
|
||||
|
@ -293,7 +294,7 @@ anchor.lo anchor.o: $(srcdir)/anchor.c \
|
|||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/yxml/yxml.h \
|
||||
$(srcdir)/gldns/parseutil.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \
|
||||
$(srcdir)/gldns/keyraw.h $(srcdir)/general.h $(srcdir)/util-internal.h
|
||||
$(srcdir)/gldns/keyraw.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/platform.h
|
||||
const-info.lo const-info.o: $(srcdir)/const-info.c \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
|
@ -309,8 +310,8 @@ context.lo context.o: $(srcdir)/context.c \
|
|||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h \
|
||||
$(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/dnssec.h \
|
||||
$(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
|
||||
convert.lo convert.o: $(srcdir)/convert.c \
|
||||
config.h \
|
||||
getdns/getdns.h \
|
||||
|
@ -362,7 +363,7 @@ general.lo general.o: $(srcdir)/general.c \
|
|||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \
|
||||
$(srcdir)/dict.h $(srcdir)/mdns.h
|
||||
$(srcdir)/dict.h $(srcdir)/mdns.h $(srcdir)/platform.h
|
||||
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
|
@ -383,9 +384,11 @@ mdns.lo mdns.o: $(srcdir)/mdns.c \
|
|||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/general.h $(srcdir)/gldns/rrdef.h $(srcdir)/util-internal.h $(srcdir)/mdns.h \
|
||||
$(srcdir)/util/auxiliary/util/fptr_wlist.h $(srcdir)/util/lookup3.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/general.h $(srcdir)/gldns/rrdef.h $(srcdir)/util-internal.h \
|
||||
$(srcdir)/platform.h $(srcdir)/mdns.h $(srcdir)/util/auxiliary/util/fptr_wlist.h $(srcdir)/util/lookup3.h \
|
||||
$(srcdir)/util/orig-headers/lookup3.h
|
||||
platform.lo platform.o: $(srcdir)/platform.c $(srcdir)/platform.h \
|
||||
config.h
|
||||
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h \
|
||||
|
@ -434,7 +437,7 @@ server.lo server.o: $(srcdir)/server.c \
|
|||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/util-internal.h $(srcdir)/platform.h
|
||||
stub.lo stub.o: $(srcdir)/stub.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h $(srcdir)/stub.h \
|
||||
|
@ -447,7 +450,7 @@ stub.lo stub.o: $(srcdir)/stub.c \
|
|||
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \
|
||||
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/anchor.h \
|
||||
$(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
|
||||
$(srcdir)/util-internal.h $(srcdir)/platform.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
|
||||
sync.lo sync.o: $(srcdir)/sync.c \
|
||||
getdns/getdns.h \
|
||||
config.h \
|
||||
|
@ -574,16 +577,22 @@ libuv.lo libuv.o: $(srcdir)/extension/libuv.c \
|
|||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h
|
||||
poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \
|
||||
config.h \
|
||||
$(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/util-internal.h $(srcdir)/context.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/debug.h
|
||||
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
|
||||
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
|
||||
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
|
||||
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
|
||||
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
|
||||
$(srcdir)/gldns/pkthdr.h $(srcdir)/anchor.h $(srcdir)/platform.h
|
||||
select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \
|
||||
config.h \
|
||||
$(srcdir)/debug.h $(srcdir)/types-internal.h \
|
||||
getdns/getdns.h \
|
||||
getdns/getdns_extra.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/extension/select_eventloop.h
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/platform.h \
|
||||
$(srcdir)/extension/select_eventloop.h
|
||||
stubby.lo stubby.o: $(stubbysrcdir)/src/stubby.c \
|
||||
config.h \
|
||||
getdns/getdns.h \
|
||||
|
|
18
src/anchor.c
18
src/anchor.c
|
@ -50,6 +50,7 @@
|
|||
#include "gldns/keyraw.h"
|
||||
#include "general.h"
|
||||
#include "util-internal.h"
|
||||
#include "platform.h"
|
||||
|
||||
/* get key usage out of its extension, returns 0 if no key_usage extension */
|
||||
static unsigned long
|
||||
|
@ -1198,10 +1199,10 @@ static void tas_read_cb(void *userarg)
|
|||
return;
|
||||
}
|
||||
}
|
||||
} else if (_getdns_EWOULDBLOCK)
|
||||
} else if (_getdns_socketerror_wants_retry())
|
||||
return;
|
||||
|
||||
DEBUG_ANCHOR("Read error: %d %s\n", (int)n, strerror(errno));
|
||||
DEBUG_ANCHOR("Read error: %d %s\n", (int)n, _getdns_errnostr());
|
||||
GETDNS_CLEAR_EVENT(a->loop, &a->event);
|
||||
tas_next(context, a);
|
||||
}
|
||||
|
@ -1248,10 +1249,10 @@ static void tas_write_cb(void *userarg)
|
|||
tas_read_cb, NULL, tas_timeout_cb));
|
||||
return;
|
||||
|
||||
} else if (_getdns_EWOULDBLOCK || _getdns_EINPROGRESS)
|
||||
} else if (_getdns_socketerror_wants_retry())
|
||||
return;
|
||||
|
||||
DEBUG_ANCHOR("Write error: %s\n", strerror(errno));
|
||||
DEBUG_ANCHOR("Write error: %s\n", _getdns_errnostr());
|
||||
GETDNS_CLEAR_EVENT(a->loop, &a->event);
|
||||
tas_next(context, a);
|
||||
}
|
||||
|
@ -1315,7 +1316,8 @@ static void tas_connect(getdns_context *context, tas_connection *a)
|
|||
|
||||
if ((a->fd = socket(( a->req->request_type == GETDNS_RRTYPE_A
|
||||
? AF_INET : AF_INET6), SOCK_STREAM, IPPROTO_TCP)) == -1) {
|
||||
DEBUG_ANCHOR("Error creating socket: %s\n", strerror(errno));
|
||||
DEBUG_ANCHOR("Error creating socket: %s\n",
|
||||
_getdns_errnostr());
|
||||
tas_next(context, a);
|
||||
return;
|
||||
}
|
||||
|
@ -1348,8 +1350,8 @@ static void tas_connect(getdns_context *context, tas_connection *a)
|
|||
addr.sin6_scope_id = 0;
|
||||
r = connect(a->fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
}
|
||||
if (r == 0 || (r == -1 && (_getdns_EINPROGRESS ||
|
||||
_getdns_EWOULDBLOCK))) {
|
||||
if (r == 0 || (r == -1 && (_getdns_socketerror() == _getdns_EINPROGRESS ||
|
||||
_getdns_socketerror() == _getdns_EWOULDBLOCK))) {
|
||||
char tas_hostname[256];
|
||||
const char *path = "", *fmt;
|
||||
getdns_return_t R;
|
||||
|
@ -1425,7 +1427,7 @@ static void tas_connect(getdns_context *context, tas_connection *a)
|
|||
DEBUG_ANCHOR("Scheduled write with event\n");
|
||||
return;
|
||||
} else
|
||||
DEBUG_ANCHOR("Connect error: %s\n", strerror(errno));
|
||||
DEBUG_ANCHOR("Connect error: %s\n", _getdns_errnostr());
|
||||
|
||||
error:
|
||||
tas_next(context, a);
|
||||
|
|
|
@ -80,6 +80,7 @@ typedef unsigned short in_port_t;
|
|||
#include "context.h"
|
||||
#include "types-internal.h"
|
||||
#include "util-internal.h"
|
||||
#include "platform.h"
|
||||
#include "dnssec.h"
|
||||
#include "stub.h"
|
||||
#include "list.h"
|
||||
|
@ -704,11 +705,7 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
|
|||
}
|
||||
if (upstream->fd != -1)
|
||||
{
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(upstream->fd);
|
||||
#else
|
||||
close(upstream->fd);
|
||||
#endif
|
||||
_getdns_closesocket(upstream->fd);
|
||||
}
|
||||
while (pin) {
|
||||
sha256_pin_t *nextpin = pin->next;
|
||||
|
@ -736,7 +733,7 @@ void _getdns_upstream_log(getdns_upstream *upstream, uint64_t system,
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
upstream_backoff(getdns_upstream *upstream) {
|
||||
upstream->conn_state = GETDNS_CONN_BACKOFF;
|
||||
/* Increase the backoff interval incrementally up to the tls_backoff_time*/
|
||||
|
@ -757,12 +754,13 @@ upstream_backoff(getdns_upstream *upstream) {
|
|||
upstream->conn_shutdowns = 0;
|
||||
upstream->conn_backoffs++;
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_NOTICE,
|
||||
"%-40s : !Backing off this upstream - Will retry again at %s",
|
||||
"%-40s : !Backing off this upstream - Will retry again in %ds at %s",
|
||||
upstream->addr_str,
|
||||
upstream->conn_backoff_interval,
|
||||
asctime(gmtime(&upstream->conn_retry_time)));
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
_getdns_upstream_reset(getdns_upstream *upstream)
|
||||
{
|
||||
/* Back off connections that never got up service at all (probably no
|
||||
|
@ -803,17 +801,17 @@ _getdns_upstream_reset(getdns_upstream *upstream)
|
|||
|
||||
/* Now TLS stuff*/
|
||||
upstream->tls_auth_state = GETDNS_AUTH_NONE;
|
||||
if (upstream->event.ev && upstream->loop) {
|
||||
upstream->loop->vmt->clear(
|
||||
upstream->loop, &upstream->event);
|
||||
}
|
||||
if (upstream->tls_obj != NULL) {
|
||||
SSL_shutdown(upstream->tls_obj);
|
||||
SSL_free(upstream->tls_obj);
|
||||
upstream->tls_obj = NULL;
|
||||
}
|
||||
if (upstream->fd != -1) {
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(upstream->fd);
|
||||
#else
|
||||
close(upstream->fd);
|
||||
#endif
|
||||
_getdns_closesocket(upstream->fd);
|
||||
upstream->fd = -1;
|
||||
}
|
||||
/* Set connection ready for use again*/
|
||||
|
@ -2776,11 +2774,14 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
|||
struct addrinfo hints;
|
||||
|
||||
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
|
||||
RETURN_IF_NULL(upstream_list, GETDNS_RETURN_INVALID_PARAMETER);
|
||||
|
||||
r = getdns_list_get_length(upstream_list, &count);
|
||||
if (count == 0 || r != GETDNS_RETURN_GOOD) {
|
||||
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
|
||||
if ( !upstream_list
|
||||
|| (r = getdns_list_get_length(upstream_list, &count))
|
||||
|| count == 0) {
|
||||
_getdns_upstreams_dereference(context->upstreams);
|
||||
context->upstreams = NULL;
|
||||
dispatch_updated(context,
|
||||
GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS);
|
||||
}
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
|
||||
|
@ -3902,7 +3903,7 @@ getdns_context_get_api_information(getdns_context* context)
|
|||
result, "compilation_comment", GETDNS_COMPILATION_COMMENT)
|
||||
|
||||
&& ! getdns_dict_util_set_string(
|
||||
result, "trust_anchor_file", TRUST_ANCHOR_FILE)
|
||||
result, "default_trust_anchor_location", TRUST_ANCHOR_FILE)
|
||||
|
||||
&& ! getdns_dict_set_int(
|
||||
result, "resolution_type", context->resolution_type)
|
||||
|
@ -4622,6 +4623,7 @@ _getdns_context_config_setting(getdns_context *context,
|
|||
&& !_streq(setting, "api_version_string")
|
||||
&& !_streq(setting, "api_version_number")
|
||||
&& !_streq(setting, "trust_anchor_file")
|
||||
&& !_streq(setting, "default_trust_anchor_location")
|
||||
&& !_streq(setting, "compilation_comment")
|
||||
) {
|
||||
r = GETDNS_RETURN_NOT_IMPLEMENTED;
|
||||
|
|
|
@ -557,6 +557,4 @@ int _getdns_context_write_priv_file(getdns_context *context,
|
|||
|
||||
int _getdns_context_can_write_appdata(getdns_context *context);
|
||||
|
||||
void _getdns_upstream_reset(getdns_upstream *upstream);
|
||||
|
||||
#endif /* _GETDNS_CONTEXT_H_ */
|
||||
|
|
|
@ -32,10 +32,10 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
#include "config.h"
|
||||
#ifndef USE_WINSOCK
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
|
19
src/debug.h
19
src/debug.h
|
@ -59,6 +59,20 @@
|
|||
fprintf(stderr, "[%s.%.6d] ", buf_dEbUgSyM, (int)tv_dEbUgSyM.tv_usec); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define DEBUG_NL(...) do { \
|
||||
struct timeval tv_dEbUgSyM; \
|
||||
struct tm tm_dEbUgSyM; \
|
||||
char buf_dEbUgSyM[10]; \
|
||||
time_t tsec_dEbUgSyM; \
|
||||
\
|
||||
gettimeofday(&tv_dEbUgSyM, NULL); \
|
||||
tsec_dEbUgSyM = (time_t) tv_dEbUgSyM.tv_sec; \
|
||||
gmtime_s(&tm_dEbUgSyM, (const time_t *) &tsec_dEbUgSyM); \
|
||||
strftime(buf_dEbUgSyM, 10, "%H:%M:%S", &tm_dEbUgSyM); \
|
||||
fprintf(stderr, "[%s.%.6d] ", buf_dEbUgSyM, (int)tv_dEbUgSyM.tv_usec); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DEBUG_ON(...) do { \
|
||||
struct timeval tv_dEbUgSyM; \
|
||||
|
@ -71,9 +85,8 @@
|
|||
fprintf(stderr, "[%s.%.6d] ", buf_dEbUgSyM, (int)tv_dEbUgSyM.tv_usec); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define DEBUG_NL(...) do { \
|
||||
#define DEBUG_NL(...) do { \
|
||||
struct timeval tv_dEbUgSyM; \
|
||||
struct tm tm_dEbUgSyM; \
|
||||
char buf_dEbUgSyM[10]; \
|
||||
|
@ -85,7 +98,7 @@
|
|||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, "\n"); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#define DEBUG_OFF(...) do {} while (0)
|
||||
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "config.h"
|
||||
#include <ctype.h>
|
||||
#ifndef USE_WINSOCK
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
|
82
src/dnssec.c
82
src/dnssec.c
|
@ -802,11 +802,14 @@ static void add_pkt2val_chain(struct mem_funcs *mf,
|
|||
if (is_synthesized_cname(rrset))
|
||||
continue;
|
||||
|
||||
if (!(rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset))
|
||||
&& _getdns_rr_iter_section(&i->rr_i) != SECTION_ANSWER)
|
||||
continue; /* No sigs in authority section is okayish */
|
||||
|
||||
if (!(head = add_rrset2val_chain(mf, chain_p, rrset, netreq)))
|
||||
continue;
|
||||
|
||||
for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset), n_rrsigs = 0
|
||||
; rrsig
|
||||
for ( n_rrsigs = 0; rrsig
|
||||
; rrsig = _getdns_rrsig_iter_next(rrsig), n_rrsigs++) {
|
||||
|
||||
/* Signature, so lookup DS/DNSKEY at signer's name */
|
||||
|
@ -934,6 +937,17 @@ static void val_chain_sched_soa(chain_head *head, const uint8_t *dname)
|
|||
val_chain_sched_soa_node(node);
|
||||
}
|
||||
|
||||
static chain_head *_dnskey_query(const chain_node *node)
|
||||
{
|
||||
chain_head *head;
|
||||
|
||||
for (head = node->chains; head; head = head->next)
|
||||
if (head->rrset.rr_type == GETDNS_RRTYPE_DNSKEY &&
|
||||
head->parent == node)
|
||||
return head;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void val_chain_node_cb(getdns_dns_req *dnsreq);
|
||||
static void val_chain_sched_node(chain_node *node)
|
||||
{
|
||||
|
@ -951,13 +965,27 @@ static void val_chain_sched_node(chain_node *node)
|
|||
DEBUG_SEC("schedule DS & DNSKEY lookup for %s\n", name);
|
||||
|
||||
node->lock++;
|
||||
if (! node->dnskey_req /* not scheduled */ &&
|
||||
_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DNSKEY,
|
||||
CD_extension(node->chains->netreq->owner),
|
||||
node, &node->dnskey_req, NULL, val_chain_node_cb))
|
||||
if (! node->dnskey_req) {
|
||||
chain_head *head;
|
||||
|
||||
node->dnskey_req = NULL;
|
||||
/* Reuse the DNSKEY query if this node is scheduled in the
|
||||
* context of validating a DNSKEY query, because libunbound
|
||||
* does not callback from a callback for the same query.
|
||||
*/
|
||||
|
||||
if ((head = _dnskey_query(node))) {
|
||||
DEBUG_SEC("Found DNSKEY head: %p\n", (void *)head);
|
||||
node->dnskey_req = head->netreq;
|
||||
node->dnskey.pkt = head->netreq->response;
|
||||
node->dnskey.pkt_len = head->netreq->response_len;
|
||||
|
||||
} else if (_getdns_general_loop(
|
||||
context, loop, name, GETDNS_RRTYPE_DNSKEY,
|
||||
CD_extension(node->chains->netreq->owner),
|
||||
node, &node->dnskey_req, NULL, val_chain_node_cb))
|
||||
|
||||
node->dnskey_req = NULL;
|
||||
}
|
||||
if (! node->ds_req && node->parent /* not root */ &&
|
||||
_getdns_general_loop(context, loop, name, GETDNS_RRTYPE_DS,
|
||||
CD_extension(node->chains->netreq->owner),
|
||||
|
@ -2523,6 +2551,11 @@ static int chain_node_get_trusted_keys(
|
|||
node->dnskey_signer = keytag;
|
||||
return GETDNS_DNSSEC_SECURE;
|
||||
}
|
||||
/* ta is the DNSKEY for this name? */
|
||||
if (_dname_equal(ta->name, node->dnskey.name)) {
|
||||
*keys = ta;
|
||||
return GETDNS_DNSSEC_SECURE;
|
||||
}
|
||||
/* ta is parent's ZSK */
|
||||
if ((keytag = key_proves_nonexistance(
|
||||
mf, now, skew, ta, &node->ds, NULL))) {
|
||||
|
@ -2938,6 +2971,26 @@ static void append_rrset2val_chain_list(
|
|||
_getdns_list_append_this_dict(val_chain_list, rr_dict))
|
||||
getdns_dict_destroy(rr_dict);
|
||||
|
||||
/* Append the other RRSIGs, which were not used for validation too,
|
||||
* because other validators might not have the same algorithm support.
|
||||
*/
|
||||
for ( rrsig = _getdns_rrsig_iter_init(&rrsig_spc, rrset)
|
||||
; rrsig
|
||||
; rrsig = _getdns_rrsig_iter_next(rrsig)) {
|
||||
|
||||
if (rrsig->rr_i.nxt < rrsig->rr_i.rr_type + 28)
|
||||
continue;
|
||||
|
||||
if (gldns_read_uint16(rrsig->rr_i.rr_type + 26)
|
||||
== (signer & 0xFFFF))
|
||||
continue;
|
||||
|
||||
orig_ttl = gldns_read_uint32(rrsig->rr_i.rr_type + 14);
|
||||
if ((rr_dict = _getdns_rr_iter2rr_dict_canonical(
|
||||
&val_chain_list->mf, &rrsig->rr_i, &orig_ttl)) &&
|
||||
_getdns_list_append_this_dict(val_chain_list, rr_dict))
|
||||
getdns_dict_destroy(rr_dict);
|
||||
}
|
||||
if (val_rrset != val_rrset_spc)
|
||||
GETDNS_FREE(val_chain_list->mf, val_rrset);
|
||||
}
|
||||
|
@ -3341,7 +3394,7 @@ void _getdns_validation_chain_timeout(getdns_dns_req *dnsreq)
|
|||
|
||||
void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq)
|
||||
{
|
||||
chain_head *head = dnsreq->chain, *next;
|
||||
chain_head *head = dnsreq->chain, *next, *dnskey_head;
|
||||
chain_node *node;
|
||||
size_t node_count;
|
||||
|
||||
|
@ -3353,7 +3406,10 @@ void _getdns_cancel_validation_chain(getdns_dns_req *dnsreq)
|
|||
; node_count
|
||||
; node_count--, node = node->parent ) {
|
||||
|
||||
if (node->dnskey_req)
|
||||
if (node->dnskey_req &&
|
||||
!( (dnskey_head = _dnskey_query(node))
|
||||
&& dnskey_head->netreq == node->dnskey_req))
|
||||
|
||||
_getdns_context_cancel_request(
|
||||
node->dnskey_req->owner);
|
||||
|
||||
|
@ -3537,13 +3593,17 @@ getdns_validate_dnssec2(getdns_list *records_to_validate,
|
|||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
if (!records_to_validate || !support_records || !trust_anchors)
|
||||
if (!records_to_validate || !trust_anchors)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
mf = &records_to_validate->mf;
|
||||
|
||||
/* First convert everything to wire format
|
||||
*/
|
||||
if (!(support = _getdns_list2wire(support_records,
|
||||
|
||||
if (!support_records)
|
||||
(void) memset((support = support_buf), 0, GLDNS_HEADER_SIZE);
|
||||
|
||||
else if (!(support = _getdns_list2wire(support_records,
|
||||
support_buf, &support_len, mf)))
|
||||
return GETDNS_RETURN_MEMORY_ERROR;
|
||||
|
||||
|
|
|
@ -27,13 +27,8 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_SYS_POLL_H
|
||||
#include <sys/poll.h>
|
||||
#else
|
||||
#ifndef USE_WINSOCK
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#endif
|
||||
#include "util-internal.h"
|
||||
#include "platform.h"
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
@ -148,7 +143,7 @@ static uint64_t get_now_plus(uint64_t amount)
|
|||
uint64_t now;
|
||||
|
||||
if (gettimeofday(&tv, NULL)) {
|
||||
perror("gettimeofday() failed");
|
||||
_getdns_perror("gettimeofday() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
now = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
|
@ -411,12 +406,14 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking)
|
|||
{
|
||||
Sleep(poll_timeout);
|
||||
} else
|
||||
if (WSAPoll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) {
|
||||
#else
|
||||
if (poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) {
|
||||
#endif
|
||||
perror("poll() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
if (_getdns_poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) {
|
||||
if (_getdns_socketerror() == _getdns_EAGAIN ||
|
||||
_getdns_socketerror() == _getdns_EINTR )
|
||||
return;
|
||||
|
||||
DEBUG_SCHED("I/O error with poll(): %s\n", _getdns_errnostr());
|
||||
return;
|
||||
}
|
||||
now = get_now_plus(0);
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "debug.h"
|
||||
#include "types-internal.h"
|
||||
#include "platform.h"
|
||||
#include "extension/select_eventloop.h"
|
||||
|
||||
static uint64_t get_now_plus(uint64_t amount)
|
||||
|
@ -37,7 +38,7 @@ static uint64_t get_now_plus(uint64_t amount)
|
|||
uint64_t now;
|
||||
|
||||
if (gettimeofday(&tv, NULL)) {
|
||||
perror("gettimeofday() failed");
|
||||
_getdns_perror("gettimeofday() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
now = tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
|
@ -244,8 +245,11 @@ select_eventloop_run_once(getdns_eventloop *loop, int blocking)
|
|||
#endif
|
||||
if (select(max_fd + 1, &readfds, &writefds, NULL,
|
||||
(timeout == TIMEOUT_FOREVER ? NULL : &tv)) < 0) {
|
||||
perror("select() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
if (_getdns_socketerror_wants_retry())
|
||||
return;
|
||||
|
||||
DEBUG_SCHED("I/O error with select(): %s\n", _getdns_errnostr());
|
||||
return;
|
||||
}
|
||||
#ifdef USE_WINSOCK
|
||||
}
|
||||
|
|
|
@ -221,7 +221,10 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
|
|||
dns_req->dnssec_return_all_statuses
|
||||
))
|
||||
#endif
|
||||
|| ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING
|
||||
|| ( dns_req->context->resolution_type == GETDNS_RESOLUTION_RECURSING
|
||||
&& (dns_req->dnssec_return_status ||
|
||||
dns_req->dnssec_return_only_secure ||
|
||||
dns_req->dnssec_return_all_statuses)
|
||||
&& _getdns_bogus(dns_req))
|
||||
)) {
|
||||
/* Reschedule timeout for this DNS request
|
||||
|
@ -446,14 +449,12 @@ _getdns_submit_netreq(getdns_network_req *netreq, uint64_t *now_ms)
|
|||
if (_getdns_ub_loop_enabled(&context->ub_loop))
|
||||
ub_resolve_r = ub_resolve_event(context->unbound_ctx,
|
||||
name, netreq->request_type, dns_req->request_class,
|
||||
netreq, ub_resolve_event_callback, &(netreq->unbound_id)) ?
|
||||
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
|
||||
netreq, ub_resolve_event_callback, &(netreq->unbound_id));
|
||||
else
|
||||
#endif
|
||||
ub_resolve_r = ub_resolve_async(context->unbound_ctx,
|
||||
name, netreq->request_type, dns_req->request_class,
|
||||
netreq, ub_resolve_callback, &(netreq->unbound_id)) ?
|
||||
GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD;
|
||||
netreq, ub_resolve_callback, &(netreq->unbound_id));
|
||||
if (dnsreq_freed)
|
||||
return DNS_REQ_FINISHED;
|
||||
dns_req->freed = NULL;
|
||||
|
|
|
@ -1059,11 +1059,7 @@ int gldns_wire2str_tsigtime_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
|
|||
d4 = (*d)[4];
|
||||
d5 = (*d)[5];
|
||||
tsigtime = (d0<<40) | (d1<<32) | (d2<<24) | (d3<<16) | (d4<<8) | d5;
|
||||
#ifndef USE_WINSOCK
|
||||
w = gldns_str_print(s, sl, "%llu", (long long)tsigtime);
|
||||
#else
|
||||
w = gldns_str_print(s, sl, "%I64u", (long long)tsigtime);
|
||||
#endif
|
||||
w = gldns_str_print(s, sl, "%"PRIu64, (uint64_t)tsigtime);
|
||||
(*d)+=6;
|
||||
(*dl)-=6;
|
||||
return w;
|
||||
|
@ -1746,13 +1742,8 @@ int gldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data,
|
|||
if(error_code < llq_errors_num)
|
||||
w += gldns_str_print(s, sl, " %s", llq_errors[error_code]);
|
||||
else w += gldns_str_print(s, sl, " error %d", (int)error_code);
|
||||
#ifndef USE_WINSOCK
|
||||
w += gldns_str_print(s, sl, " id %llx lease-life %lu",
|
||||
(unsigned long long)llq_id, (unsigned long)lease_life);
|
||||
#else
|
||||
w += gldns_str_print(s, sl, " id %I64x lease-life %lu",
|
||||
(unsigned long long)llq_id, (unsigned long)lease_life);
|
||||
#endif
|
||||
w += gldns_str_print(s, sl, " id %"PRIx64" lease-life %lu",
|
||||
(uint64_t)llq_id, (unsigned long)lease_life);
|
||||
return w;
|
||||
}
|
||||
|
||||
|
|
73
src/mdns.c
73
src/mdns.c
|
@ -26,28 +26,11 @@
|
|||
#include "gldns/pkthdr.h"
|
||||
#include "gldns/rrdef.h"
|
||||
#include "util-internal.h"
|
||||
#include "platform.h"
|
||||
#include "mdns.h"
|
||||
|
||||
#ifdef HAVE_MDNS_SUPPORT
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
typedef u_short sa_family_t;
|
||||
#define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\
|
||||
WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
#define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS)
|
||||
#else
|
||||
#define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
#define _getdns_EINPROGRESS (errno == EINPROGRESS)
|
||||
#define SOCKADDR struct sockaddr
|
||||
#define SOCKADDR_IN struct sockaddr_in
|
||||
#define SOCKADDR_IN6 struct sockaddr_in6
|
||||
#define SOCKET int
|
||||
#define IP_MREQ struct ip_mreq
|
||||
#define IPV6_MREQ struct ipv6_mreq
|
||||
#define BOOL int
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
/* Define IPV6_ADD_MEMBERSHIP for FreeBSD and Mac OS X */
|
||||
#ifndef IPV6_ADD_MEMBERSHIP
|
||||
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
|
||||
|
@ -1148,7 +1131,8 @@ mdns_udp_multicast_read_cb(void *userarg)
|
|||
sizeof(cnx->response), 0, NULL, NULL);
|
||||
|
||||
|
||||
if (read == -1 && _getdns_EWOULDBLOCK)
|
||||
if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
|
||||
_getdns_socketerror() == _getdns_ECONNRESET))
|
||||
return; /* TODO: this will stop the receive loop! */
|
||||
|
||||
if (read >= GLDNS_HEADER_SIZE)
|
||||
|
@ -1353,11 +1337,7 @@ static int mdns_open_ipv4_multicast(SOCKADDR_STORAGE* mcast_dest, int* mcast_des
|
|||
|
||||
if (ret != 0 && fd4 != -1)
|
||||
{
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(fd4);
|
||||
#else
|
||||
close(fd4);
|
||||
#endif
|
||||
_getdns_closesocket(fd4);
|
||||
fd4 = -1;
|
||||
}
|
||||
|
||||
|
@ -1428,11 +1408,7 @@ static int mdns_open_ipv6_multicast(SOCKADDR_STORAGE* mcast_dest, int* mcast_des
|
|||
|
||||
if (ret != 0 && fd6 != -1)
|
||||
{
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(fd6);
|
||||
#else
|
||||
close(fd6);
|
||||
#endif
|
||||
_getdns_closesocket(fd6);
|
||||
fd6 = -1;
|
||||
}
|
||||
|
||||
|
@ -1514,11 +1490,7 @@ static getdns_return_t mdns_delayed_network_init(struct getdns_context *context)
|
|||
|
||||
GETDNS_CLEAR_EVENT(context->extension
|
||||
, &context->mdns_connection[i].event);
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(context->mdns_connection[i].fd);
|
||||
#else
|
||||
close(context->mdns_connection[i].fd);
|
||||
#endif
|
||||
_getdns_closesocket(context->mdns_connection[i].fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1657,11 +1629,7 @@ void _getdns_mdns_context_destroy(struct getdns_context *context)
|
|||
/* suppress the receive event */
|
||||
GETDNS_CLEAR_EVENT(context->extension, &context->mdns_connection[i].event);
|
||||
/* close the socket */
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(context->mdns_connection[i].fd);
|
||||
#else
|
||||
close(context->mdns_connection[i].fd);
|
||||
#endif
|
||||
_getdns_closesocket(context->mdns_connection[i].fd);
|
||||
}
|
||||
|
||||
GETDNS_FREE(context->mf, context->mdns_connection);
|
||||
|
@ -1686,11 +1654,7 @@ _getdns_cancel_mdns_request(getdns_network_req *netreq)
|
|||
{
|
||||
mdns_cleanup(netreq);
|
||||
if (netreq->fd >= 0) {
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(netreq->fd);
|
||||
#else
|
||||
close(netreq->fd);
|
||||
#endif
|
||||
_getdns_closesocket(netreq->fd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1706,11 +1670,7 @@ mdns_timeout_cb(void *userarg)
|
|||
/* Check the required cleanup */
|
||||
mdns_cleanup(netreq);
|
||||
if (netreq->fd >= 0)
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(netreq->fd);
|
||||
#else
|
||||
close(netreq->fd);
|
||||
#endif
|
||||
_getdns_closesocket(netreq->fd);
|
||||
_getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
|
||||
if (netreq->owner->user_callback) {
|
||||
netreq->debug_end_time = _getdns_get_time_as_uintt64();
|
||||
|
@ -1745,7 +1705,8 @@ mdns_udp_read_cb(void *userarg)
|
|||
* i.e. overflow
|
||||
*/
|
||||
0, NULL, NULL);
|
||||
if (read == -1 && _getdns_EWOULDBLOCK)
|
||||
if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
|
||||
_getdns_socketerror() == _getdns_ECONNRESET))
|
||||
return;
|
||||
|
||||
if (read < GLDNS_HEADER_SIZE)
|
||||
|
@ -1759,11 +1720,7 @@ mdns_udp_read_cb(void *userarg)
|
|||
// TODO: check that the source address originates from the local network.
|
||||
// TODO: check TTL = 255
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(netreq->fd);
|
||||
#else
|
||||
close(netreq->fd);
|
||||
#endif
|
||||
_getdns_closesocket(netreq->fd);
|
||||
/*
|
||||
* TODO: how to handle an MDNS response with TC bit set?
|
||||
* Ignore it for now, as we do not support any kind of TCP fallback
|
||||
|
@ -1814,11 +1771,7 @@ mdns_udp_write_cb(void *userarg)
|
|||
netreq->fd, (const void *)netreq->query, pkt_len, 0,
|
||||
(struct sockaddr *)&mdns_mcast_v4,
|
||||
sizeof(mdns_mcast_v4))) {
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(netreq->fd);
|
||||
#else
|
||||
close(netreq->fd);
|
||||
#endif
|
||||
_getdns_closesocket(netreq->fd);
|
||||
return;
|
||||
}
|
||||
GETDNS_SCHEDULE_EVENT(
|
||||
|
|
|
@ -24,13 +24,11 @@
|
|||
#ifdef HAVE_MDNS_SUPPORT
|
||||
#include "getdns/getdns.h"
|
||||
#include "types-internal.h"
|
||||
#include "util-internal.h"
|
||||
#include "platform.h"
|
||||
#include "util/lruhash.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifndef USE_WINSOCK
|
||||
#define SOCKADDR_STORAGE struct sockaddr_storage
|
||||
#endif
|
||||
|
||||
getdns_return_t
|
||||
_getdns_submit_mdns_request(getdns_network_req *netreq);
|
||||
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
/**
|
||||
*
|
||||
* \file platform.c
|
||||
* @brief general functions with platform-dependent implementations
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017, NLnet Labs, Sinodun
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
|
||||
void _getdns_perror(const char *str)
|
||||
{
|
||||
char msg[256];
|
||||
int errid = WSAGetLastError();
|
||||
|
||||
*msg = '\0';
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
errid,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
msg,
|
||||
sizeof(msg),
|
||||
NULL);
|
||||
if (*msg == '\0')
|
||||
sprintf(msg, "Unknown error: %d", errid);
|
||||
if (str && *str != '\0')
|
||||
fprintf(stderr, "%s: ", str);
|
||||
fputs(msg, stderr);
|
||||
}
|
||||
|
||||
const char *_getdns_strerror(DWORD errnum)
|
||||
{
|
||||
static char unknown[32];
|
||||
|
||||
switch(errnum) {
|
||||
case WSA_INVALID_HANDLE: return "Specified event object handle is invalid.";
|
||||
case WSA_NOT_ENOUGH_MEMORY: return "Insufficient memory available.";
|
||||
case WSA_INVALID_PARAMETER: return "One or more parameters are invalid.";
|
||||
case WSA_OPERATION_ABORTED: return "Overlapped operation aborted.";
|
||||
case WSA_IO_INCOMPLETE: return "Overlapped I/O event object not in signaled state.";
|
||||
case WSA_IO_PENDING: return "Overlapped operations will complete later.";
|
||||
case WSAEINTR: return "Interrupted function call.";
|
||||
case WSAEBADF: return "File handle is not valid.";
|
||||
case WSAEACCES: return "Permission denied.";
|
||||
case WSAEFAULT: return "Bad address.";
|
||||
case WSAEINVAL: return "Invalid argument.";
|
||||
case WSAEMFILE: return "Too many open files.";
|
||||
case WSAEWOULDBLOCK: return "Resource temporarily unavailable.";
|
||||
case WSAEINPROGRESS: return "Operation now in progress.";
|
||||
case WSAEALREADY: return "Operation already in progress.";
|
||||
case WSAENOTSOCK: return "Socket operation on nonsocket.";
|
||||
case WSAEDESTADDRREQ: return "Destination address required.";
|
||||
case WSAEMSGSIZE: return "Message too long.";
|
||||
case WSAEPROTOTYPE: return "Protocol wrong type for socket.";
|
||||
case WSAENOPROTOOPT: return "Bad protocol option.";
|
||||
case WSAEPROTONOSUPPORT: return "Protocol not supported.";
|
||||
case WSAESOCKTNOSUPPORT: return "Socket type not supported.";
|
||||
case WSAEOPNOTSUPP: return "Operation not supported.";
|
||||
case WSAEPFNOSUPPORT: return "Protocol family not supported.";
|
||||
case WSAEAFNOSUPPORT: return "Address family not supported by protocol family.";
|
||||
case WSAEADDRINUSE: return "Address already in use.";
|
||||
case WSAEADDRNOTAVAIL: return "Cannot assign requested address.";
|
||||
case WSAENETDOWN: return "Network is down.";
|
||||
case WSAENETUNREACH: return "Network is unreachable.";
|
||||
case WSAENETRESET: return "Network dropped connection on reset.";
|
||||
case WSAECONNABORTED: return "Software caused connection abort.";
|
||||
case WSAECONNRESET: return "Connection reset by peer.";
|
||||
case WSAENOBUFS: return "No buffer space available.";
|
||||
case WSAEISCONN: return "Socket is already connected.";
|
||||
case WSAENOTCONN: return "Socket is not connected.";
|
||||
case WSAESHUTDOWN: return "Cannot send after socket shutdown.";
|
||||
case WSAETOOMANYREFS: return "Too many references.";
|
||||
case WSAETIMEDOUT: return "Connection timed out.";
|
||||
case WSAECONNREFUSED: return "Connection refused.";
|
||||
case WSAELOOP: return "Cannot translate name.";
|
||||
case WSAENAMETOOLONG: return "Name too long.";
|
||||
case WSAEHOSTDOWN: return "Host is down.";
|
||||
case WSAEHOSTUNREACH: return "No route to host.";
|
||||
case WSAENOTEMPTY: return "Directory not empty.";
|
||||
case WSAEPROCLIM: return "Too many processes.";
|
||||
case WSAEUSERS: return "User quota exceeded.";
|
||||
case WSAEDQUOT: return "Disk quota exceeded.";
|
||||
case WSAESTALE: return "Stale file handle reference.";
|
||||
case WSAEREMOTE: return "Item is remote.";
|
||||
case WSASYSNOTREADY: return "Network subsystem is unavailable.";
|
||||
case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range.";
|
||||
case WSANOTINITIALISED: return "Successful WSAStartup not yet performed.";
|
||||
case WSAEDISCON: return "Graceful shutdown in progress.";
|
||||
case WSAENOMORE: return "No more results.";
|
||||
case WSAECANCELLED: return "Call has been canceled.";
|
||||
case WSAEINVALIDPROCTABLE: return "Procedure call table is invalid.";
|
||||
case WSAEINVALIDPROVIDER: return "Service provider is invalid.";
|
||||
case WSAEPROVIDERFAILEDINIT: return "Service provider failed to initialize.";
|
||||
case WSASYSCALLFAILURE: return "System call failure.";
|
||||
case WSASERVICE_NOT_FOUND: return "Service not found.";
|
||||
case WSATYPE_NOT_FOUND: return "Class type not found.";
|
||||
case WSA_E_NO_MORE: return "No more results.";
|
||||
case WSA_E_CANCELLED: return "Call was canceled.";
|
||||
case WSAEREFUSED: return "Database query was refused.";
|
||||
case WSAHOST_NOT_FOUND: return "Host not found.";
|
||||
case WSATRY_AGAIN: return "Nonauthoritative host not found.";
|
||||
case WSANO_RECOVERY: return "This is a nonrecoverable error.";
|
||||
case WSANO_DATA: return "Valid name, no data record of requested type.";
|
||||
case WSA_QOS_RECEIVERS: return "QOS receivers.";
|
||||
case WSA_QOS_SENDERS: return "QOS senders.";
|
||||
case WSA_QOS_NO_SENDERS: return "No QOS senders.";
|
||||
case WSA_QOS_NO_RECEIVERS: return "QOS no receivers.";
|
||||
case WSA_QOS_REQUEST_CONFIRMED: return "QOS request confirmed.";
|
||||
case WSA_QOS_ADMISSION_FAILURE: return "QOS admission error.";
|
||||
case WSA_QOS_POLICY_FAILURE: return "QOS policy failure.";
|
||||
case WSA_QOS_BAD_STYLE: return "QOS bad style.";
|
||||
case WSA_QOS_BAD_OBJECT: return "QOS bad object.";
|
||||
case WSA_QOS_TRAFFIC_CTRL_ERROR: return "QOS traffic control error.";
|
||||
case WSA_QOS_GENERIC_ERROR: return "QOS generic error.";
|
||||
case WSA_QOS_ESERVICETYPE: return "QOS service type error.";
|
||||
case WSA_QOS_EFLOWSPEC: return "QOS flowspec error.";
|
||||
case WSA_QOS_EPROVSPECBUF: return "Invalid QOS provider buffer.";
|
||||
case WSA_QOS_EFILTERSTYLE: return "Invalid QOS filter style.";
|
||||
case WSA_QOS_EFILTERTYPE: return "Invalid QOS filter type.";
|
||||
case WSA_QOS_EFILTERCOUNT: return "Incorrect QOS filter count.";
|
||||
case WSA_QOS_EOBJLENGTH: return "Invalid QOS object length.";
|
||||
case WSA_QOS_EFLOWCOUNT: return "Incorrect QOS flow count.";
|
||||
/*case WSA_QOS_EUNKOWNPSOBJ: return "Unrecognized QOS object.";*/
|
||||
case WSA_QOS_EPOLICYOBJ: return "Invalid QOS policy object.";
|
||||
case WSA_QOS_EFLOWDESC: return "Invalid QOS flow descriptor.";
|
||||
case WSA_QOS_EPSFLOWSPEC: return "Invalid QOS provider-specific flowspec.";
|
||||
case WSA_QOS_EPSFILTERSPEC: return "Invalid QOS provider-specific filterspec.";
|
||||
case WSA_QOS_ESDMODEOBJ: return "Invalid QOS shape discard mode object.";
|
||||
case WSA_QOS_ESHAPERATEOBJ: return "Invalid QOS shaping rate object.";
|
||||
case WSA_QOS_RESERVED_PETYPE: return "Reserved policy QOS element type.";
|
||||
default:
|
||||
snprintf(unknown, sizeof(unknown),
|
||||
"unknown WSA error code %d", (int)errnum);
|
||||
return unknown;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void _getdns_perror(const char *str)
|
||||
{
|
||||
perror(str);
|
||||
}
|
||||
|
||||
const char *_getdns_strerror(int errnum)
|
||||
{
|
||||
return strerror(errnum);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,151 @@
|
|||
/**
|
||||
*
|
||||
* \file platform.h
|
||||
* @brief general functions with platform-dependent implementations
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017, NLnet Labs, Sinodun
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
typedef u_short sa_family_t;
|
||||
#define _getdns_EINTR (WSAEINTR)
|
||||
#define _getdns_EAGAIN (WSATRY_AGAIN)
|
||||
#define _getdns_EWOULDBLOCK (WSAEWOULDBLOCK)
|
||||
#define _getdns_EINPROGRESS (WSAEINPROGRESS)
|
||||
#define _getdns_ENOBUFS (WSAENOBUFS)
|
||||
#define _getdns_EPROTO (0)
|
||||
#define _getdns_EMFILE (WSAEMFILE)
|
||||
#ifdef WSAENFILE
|
||||
# define _getdns_ENFILE (WSAENFILE)
|
||||
#else
|
||||
# define _getdns_ENFILE (0)
|
||||
#endif
|
||||
#define _getdns_ECONNRESET (WSAECONNRESET)
|
||||
#define _getdns_ECONNABORTED (0)
|
||||
#define _getdns_EISCONN (WSAEISCONN)
|
||||
|
||||
#define _getdns_closesocket(fd) closesocket(fd)
|
||||
#define _getdns_poll(fdarray, nsockets, timer) WSAPoll(fdarray, nsockets, timer)
|
||||
#define _getdns_socketerror() (WSAGetLastError())
|
||||
|
||||
const char *_getdns_strerror(DWORD errnum);
|
||||
#else /* USE_WINSOCK */
|
||||
|
||||
#ifdef HAVE_SYS_POLL_H
|
||||
# include <sys/poll.h>
|
||||
#else
|
||||
# include <poll.h>
|
||||
#endif
|
||||
|
||||
#define _getdns_EINTR (EINTR)
|
||||
#define _getdns_EAGAIN (EAGAIN)
|
||||
#ifdef EWOULDBLOCK
|
||||
#define _getdns_EWOULDBLOCK (EWOULDBLOCK)
|
||||
#else
|
||||
#define _getdns_EWOULDBLOCK (0)
|
||||
#endif
|
||||
#ifdef EINPROGRESS
|
||||
# define _getdns_EINPROGRESS (EINPROGRESS)
|
||||
#else
|
||||
# define _getdns_EINPROGRESS (0)
|
||||
#endif
|
||||
#ifdef ENOBUFS
|
||||
# define _getdns_ENOBUFS (ENOBUFS)
|
||||
#else
|
||||
# define _getdns_ENOBUFS (0)
|
||||
#endif
|
||||
#ifdef EPROTO
|
||||
# define _getdns_EPROTO (EPROTO)
|
||||
#else
|
||||
# define _getdns_EPROTO (0)
|
||||
#endif
|
||||
#ifdef EMFILE
|
||||
# define _getdns_EMFILE (EMFILE)
|
||||
#else
|
||||
# define _getdns_EMFILE (0)
|
||||
#endif
|
||||
#ifdef ENFILE
|
||||
# define _getdns_ENFILE (ENFILE)
|
||||
#else
|
||||
# define _getdns_ENFILE (0)
|
||||
#endif
|
||||
#ifdef ECONNRESET
|
||||
# define _getdns_ECONNRESET (ECONNRESET)
|
||||
#else
|
||||
# define _getdns_ECONNRESET (0)
|
||||
#endif
|
||||
#ifdef ECONNABORTED
|
||||
# define _getdns_ECONNABORTED (ECONNABORTED)
|
||||
#else
|
||||
# define _getdns_ECONNABORTED (0)
|
||||
#endif
|
||||
#ifdef EISCONN
|
||||
# define _getdns_EISCONN (EISCONN)
|
||||
#else
|
||||
# define _getdns_EISCONN (0)
|
||||
#endif
|
||||
|
||||
#define SOCKADDR struct sockaddr
|
||||
#define SOCKADDR_IN struct sockaddr_in
|
||||
#define SOCKADDR_IN6 struct sockaddr_in6
|
||||
#define SOCKADDR_STORAGE struct sockaddr_storage
|
||||
#define SOCKET int
|
||||
|
||||
#define IP_MREQ struct ip_mreq
|
||||
#define IPV6_MREQ struct ipv6_mreq
|
||||
#define BOOL int
|
||||
#define TRUE 1
|
||||
|
||||
#define _getdns_closesocket(fd) close(fd)
|
||||
#define _getdns_poll(fdarray, nsockets, timer) poll(fdarray, nsockets, timer)
|
||||
#define _getdns_socketerror() (errno)
|
||||
|
||||
const char *_getdns_strerror(int errnum);
|
||||
#endif
|
||||
|
||||
void _getdns_perror(const char *str);
|
||||
|
||||
#define _getdns_errnostr() (_getdns_strerror(_getdns_socketerror()))
|
||||
#define _getdns_error_wants_retry(X) ( (X) != 0 \
|
||||
&& ( (X) == _getdns_EINTR \
|
||||
|| (X) == _getdns_EAGAIN \
|
||||
|| (X) == _getdns_EWOULDBLOCK \
|
||||
|| (X) == _getdns_EINPROGRESS \
|
||||
|| (X) == _getdns_ENOBUFS ))
|
||||
#define _getdns_socketerror_wants_retry() (_getdns_error_wants_retry(_getdns_socketerror()))
|
||||
#define _getdns_resource_depletion() ( _getdns_socketerror() != 0 \
|
||||
&& ( _getdns_socketerror() == _getdns_ENFILE \
|
||||
|| _getdns_socketerror() == _getdns_EMFILE ))
|
||||
|
||||
#endif
|
|
@ -107,6 +107,12 @@ network_req_cleanup(getdns_network_req *net_req)
|
|||
{
|
||||
assert(net_req);
|
||||
|
||||
if (net_req->query_id_registered) {
|
||||
(void) _getdns_rbtree_delete(
|
||||
net_req->query_id_registered, net_req->node.key);
|
||||
net_req->query_id_registered = NULL;
|
||||
net_req->node.key = NULL;
|
||||
}
|
||||
if (net_req->response && (net_req->response < net_req->wire_data ||
|
||||
net_req->response > net_req->wire_data+ net_req->wire_data_sz))
|
||||
GETDNS_FREE(net_req->owner->my_mf, net_req->response);
|
||||
|
@ -123,6 +129,12 @@ netreq_reset(getdns_network_req *net_req)
|
|||
*/
|
||||
net_req->unbound_id = -1;
|
||||
_getdns_netreq_change_state(net_req, NET_REQ_NOT_SENT);
|
||||
if (net_req->query_id_registered) {
|
||||
(void) _getdns_rbtree_delete(net_req->query_id_registered,
|
||||
(void *)(intptr_t)GLDNS_ID_WIRE(net_req->query));
|
||||
net_req->query_id_registered = NULL;
|
||||
net_req->node.key = NULL;
|
||||
}
|
||||
net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
|
||||
net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE;
|
||||
net_req->response_len = 0;
|
||||
|
@ -196,6 +208,11 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
|
|||
/* Scheduling, touch only via _getdns_netreq_change_state!
|
||||
*/
|
||||
net_req->state = NET_REQ_NOT_SENT;
|
||||
/* A registered netreq (on a statefull transport)
|
||||
* Deregister on reset and cleanup.
|
||||
*/
|
||||
net_req->query_id_registered = NULL;
|
||||
net_req->node.key = NULL;
|
||||
|
||||
if (max_query_sz == 0) {
|
||||
net_req->query = NULL;
|
||||
|
|
78
src/server.c
78
src/server.c
|
@ -39,6 +39,8 @@
|
|||
#include "types-internal.h"
|
||||
#include "debug.h"
|
||||
#include "util/rbtree.h"
|
||||
#include "util-internal.h"
|
||||
#include "platform.h"
|
||||
#include "server.h"
|
||||
|
||||
#define DNS_REQUEST_SZ 4096
|
||||
|
@ -135,11 +137,7 @@ static void tcp_connection_destroy(tcp_connection *conn)
|
|||
loop->vmt->clear(loop, &conn->event);
|
||||
|
||||
if (conn->fd >= 0)
|
||||
#ifdef USE_WINSOCK
|
||||
(void) closesocket(conn->fd);
|
||||
#else
|
||||
(void) close(conn->fd);
|
||||
#endif
|
||||
(void) _getdns_closesocket(conn->fd);
|
||||
GETDNS_FREE(*mf, conn->read_buf);
|
||||
|
||||
for (cur = conn->to_write; cur; cur = next) {
|
||||
|
@ -193,6 +191,12 @@ static void tcp_write_cb(void *userarg)
|
|||
(const void *)&to_write->write_buf[to_write->written],
|
||||
to_write->write_buf_len - to_write->written, 0)) == -1) {
|
||||
|
||||
if (_getdns_socketerror_wants_retry())
|
||||
return;
|
||||
|
||||
DEBUG_SERVER("I/O error from send(): %s\n",
|
||||
_getdns_errnostr());
|
||||
|
||||
/* IO error, close connection */
|
||||
conn->event.read_cb = conn->event.write_cb =
|
||||
conn->event.timeout_cb = NULL;
|
||||
|
@ -283,14 +287,11 @@ getdns_reply(
|
|||
|
||||
if (conn->l->fd >= 0 && sendto(conn->l->fd, (void *)buf, len, 0,
|
||||
(struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) {
|
||||
/* IO error, cleanup this listener */
|
||||
loop->vmt->clear(loop, &conn->l->event);
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(conn->l->fd);
|
||||
#else
|
||||
close(conn->l->fd);
|
||||
#endif
|
||||
conn->l->fd = -1;
|
||||
/* TODO: handle _getdns_socketerror_wants_retry() */
|
||||
|
||||
/* IO error, never cleanup a listener because of I/O error */
|
||||
DEBUG_SERVER("I/O error from sendto(): %s\n",
|
||||
_getdns_errnostr());
|
||||
}
|
||||
/* Unlink this connection */
|
||||
(void) _getdns_rbtree_delete(
|
||||
|
@ -370,10 +371,13 @@ static void tcp_read_cb(void *userarg)
|
|||
|
||||
if ((bytes_read = recv(conn->fd,
|
||||
(void *)conn->read_pos, conn->to_read, 0)) < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
if (_getdns_socketerror_wants_retry())
|
||||
return; /* Come back to do the read later */
|
||||
|
||||
/* IO error, close connection */
|
||||
DEBUG_SERVER("I/O error from recv(): %s\n",
|
||||
_getdns_errnostr());
|
||||
|
||||
tcp_connection_destroy(conn);
|
||||
return;
|
||||
}
|
||||
|
@ -481,14 +485,19 @@ static void tcp_accept_cb(void *userarg)
|
|||
conn->super.addrlen = sizeof(conn->super.remote_in);
|
||||
if ((conn->fd = accept(l->fd, (struct sockaddr *)
|
||||
&conn->super.remote_in, &conn->super.addrlen)) == -1) {
|
||||
/* IO error, cleanup this listener */
|
||||
loop->vmt->clear(loop, &l->event);
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(l->fd);
|
||||
#else
|
||||
close(l->fd);
|
||||
#endif
|
||||
l->fd = -1;
|
||||
|
||||
if (_getdns_socketerror_wants_retry() ||
|
||||
_getdns_socketerror() == _getdns_ECONNRESET)
|
||||
; /* pass */
|
||||
|
||||
else if (_getdns_resource_depletion())
|
||||
; /* TODO: Stop listening for a little while? */
|
||||
|
||||
else
|
||||
DEBUG_SERVER("I/O error during accept: %s\n",
|
||||
_getdns_errnostr());
|
||||
|
||||
/* Never cleanup a listener because of I/O errors! */
|
||||
GETDNS_FREE(*mf, conn);
|
||||
return;
|
||||
}
|
||||
|
@ -555,14 +564,17 @@ static void udp_read_cb(void *userarg)
|
|||
conn->addrlen = sizeof(conn->remote_in);
|
||||
if ((len = recvfrom(l->fd, (void *)buf, sizeof(buf), 0,
|
||||
(struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) {
|
||||
/* IO error, cleanup this listener. */
|
||||
loop->vmt->clear(loop, &l->event);
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(l->fd);
|
||||
#else
|
||||
close(l->fd);
|
||||
#endif
|
||||
l->fd = -1;
|
||||
if ( _getdns_socketerror_wants_retry() &&
|
||||
_getdns_socketerror() != _getdns_ECONNRESET) {
|
||||
/*
|
||||
* WINSOCK gives ECONNRESET on ICMP Port Unreachable
|
||||
* being received. Ignore it.
|
||||
*/
|
||||
DEBUG_SERVER("I/O error from recvfrom: %s\n",
|
||||
_getdns_errnostr());
|
||||
|
||||
}
|
||||
/* Never cleanup a listener because of an I/O error! */
|
||||
|
||||
#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG
|
||||
} else {
|
||||
|
@ -710,11 +722,7 @@ static void remove_listeners(listen_set *set)
|
|||
continue;
|
||||
|
||||
loop->vmt->clear(loop, &l->event);
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(l->fd);
|
||||
#else
|
||||
close(l->fd);
|
||||
#endif
|
||||
_getdns_closesocket(l->fd);
|
||||
l->fd = -1;
|
||||
|
||||
if (l->transport != GETDNS_TRANSPORT_TCP)
|
||||
|
|
345
src/stub.c
345
src/stub.c
|
@ -38,17 +38,6 @@
|
|||
*/
|
||||
#define INTERCEPT_COM_DS 0
|
||||
|
||||
#ifdef USE_POLL_DEFAULT_EVENTLOOP
|
||||
# ifdef HAVE_SYS_POLL_H
|
||||
# include <sys/poll.h>
|
||||
# else
|
||||
#ifdef USE_WINSOCK
|
||||
#define poll(fdarray, nbsockets, timer) WSAPoll(fdarray, nbsockets, timer)
|
||||
#else
|
||||
# include <poll.h>
|
||||
#endif
|
||||
# endif
|
||||
#endif
|
||||
#include "debug.h"
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/conf.h>
|
||||
|
@ -63,20 +52,22 @@
|
|||
#include "rr-iter.h"
|
||||
#include "context.h"
|
||||
#include "util-internal.h"
|
||||
#include "platform.h"
|
||||
#include "general.h"
|
||||
#include "pubkey-pinning.h"
|
||||
|
||||
/* WSA TODO:
|
||||
* STUB_TCP_WOULDBLOCK added to deal with edge triggered event loops (versus
|
||||
* STUB_TCP_RETRY added to deal with edge triggered event loops (versus
|
||||
* level triggered). See also lines containing WSA TODO below...
|
||||
*/
|
||||
#define STUB_TRY_AGAIN_LATER -24 /* EMFILE, i.e. Out of OS resources */
|
||||
#define STUB_NO_AUTH -8 /* Existing TLS connection is not authenticated */
|
||||
#define STUB_CONN_GONE -7 /* Connection has failed, clear queue*/
|
||||
#define STUB_TCP_WOULDBLOCK -6
|
||||
#define STUB_TCP_RETRY -6
|
||||
#define STUB_OUT_OF_OPTIONS -5 /* upstream options exceeded MAXIMUM_UPSTREAM_OPTION_SPACE */
|
||||
#define STUB_SETUP_ERROR -4
|
||||
#define STUB_TCP_AGAIN -3
|
||||
#define STUB_TCP_MORE_TO_READ -3
|
||||
#define STUB_TCP_MORE_TO_WRITE -3
|
||||
#define STUB_TCP_ERROR -2
|
||||
|
||||
/* Don't currently have access to the context whilst doing handshake */
|
||||
|
@ -93,8 +84,7 @@ static void upstream_write_cb(void *userarg);
|
|||
static void upstream_idle_timeout_cb(void *userarg);
|
||||
static void upstream_schedule_netreq(getdns_upstream *upstream,
|
||||
getdns_network_req *netreq);
|
||||
static void upstream_reschedule_events(getdns_upstream *upstream,
|
||||
uint64_t idle_timeout);
|
||||
static void upstream_reschedule_events(getdns_upstream *upstream);
|
||||
static int upstream_working_ok(getdns_upstream *upstream);
|
||||
static int upstream_auth_status_ok(getdns_upstream *upstream,
|
||||
getdns_network_req *netreq);
|
||||
|
@ -418,21 +408,18 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport)
|
|||
NULL, 0, NULL, NULL) == 0) {
|
||||
return fd;
|
||||
}
|
||||
if (errno == EINPROGRESS) {
|
||||
if (_getdns_socketerror() == _getdns_EINPROGRESS ||
|
||||
_getdns_socketerror() == _getdns_EWOULDBLOCK)
|
||||
return fd;
|
||||
}
|
||||
#else
|
||||
(void)transport;
|
||||
#endif
|
||||
if (connect(fd, (struct sockaddr *)&upstream->addr,
|
||||
upstream->addr_len) == -1) {
|
||||
if (_getdns_EINPROGRESS || _getdns_EWOULDBLOCK)
|
||||
if (_getdns_socketerror() == _getdns_EINPROGRESS ||
|
||||
_getdns_socketerror() == _getdns_EWOULDBLOCK)
|
||||
return fd;
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(fd);
|
||||
#else
|
||||
close(fd);
|
||||
#endif
|
||||
_getdns_closesocket(fd);
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
|
@ -443,22 +430,11 @@ tcp_connected(getdns_upstream *upstream) {
|
|||
int error = 0;
|
||||
socklen_t len = (socklen_t)sizeof(error);
|
||||
getsockopt(upstream->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
|
||||
#ifdef USE_WINSOCK
|
||||
if (error == WSAEINPROGRESS)
|
||||
return STUB_TCP_AGAIN;
|
||||
else if (error == WSAEWOULDBLOCK)
|
||||
return STUB_TCP_WOULDBLOCK;
|
||||
else if (error != 0)
|
||||
return STUB_SETUP_ERROR;
|
||||
#else
|
||||
if (error == EINPROGRESS)
|
||||
return STUB_TCP_AGAIN;
|
||||
else if (error == EWOULDBLOCK || error == EAGAIN)
|
||||
return STUB_TCP_WOULDBLOCK;
|
||||
if (_getdns_error_wants_retry(error))
|
||||
return STUB_TCP_RETRY;
|
||||
else if (error != 0) {
|
||||
return STUB_SETUP_ERROR;
|
||||
}
|
||||
#endif
|
||||
if (upstream->transport == GETDNS_TRANSPORT_TCP &&
|
||||
upstream->queries_sent == 0) {
|
||||
upstream->conn_state = GETDNS_CONN_OPEN;
|
||||
|
@ -484,42 +460,56 @@ stub_next_upstream(getdns_network_req *netreq)
|
|||
dnsreq->upstreams->current_udp = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_from_write_queue(getdns_upstream *upstream, getdns_network_req * netreq)
|
||||
{
|
||||
getdns_network_req *r, *prev_r;
|
||||
|
||||
for ( r = upstream->write_queue, prev_r = NULL
|
||||
; r
|
||||
; prev_r = r, r = r->write_queue_tail) {
|
||||
|
||||
if (r != netreq)
|
||||
continue;
|
||||
|
||||
if (prev_r)
|
||||
prev_r->write_queue_tail = r->write_queue_tail;
|
||||
else
|
||||
upstream->write_queue = r->write_queue_tail;
|
||||
|
||||
if (r == upstream->write_queue_last) {
|
||||
/* If r was the last netreq,
|
||||
* its write_queue tail MUST be NULL
|
||||
*/
|
||||
assert(r->write_queue_tail == NULL);
|
||||
upstream->write_queue_last = prev_r ? prev_r : NULL;
|
||||
}
|
||||
|
||||
netreq->write_queue_tail = NULL;
|
||||
break; /* netreq found and removed */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stub_cleanup(getdns_network_req *netreq)
|
||||
{
|
||||
DEBUG_STUB("%s %-35s: MSG: %p\n",
|
||||
STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq);
|
||||
getdns_dns_req *dnsreq = netreq->owner;
|
||||
getdns_network_req *r, *prev_r;
|
||||
getdns_upstream *upstream;
|
||||
|
||||
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
||||
|
||||
/* Nothing globally scheduled? Then nothing queued */
|
||||
if (!netreq->upstream || !(upstream = netreq->upstream)->event.ev)
|
||||
return;
|
||||
|
||||
/* Delete from upstream->netreq_by_query_id (if present) */
|
||||
(void) _getdns_rbtree_delete(&upstream->netreq_by_query_id,
|
||||
(void *)(intptr_t)GLDNS_ID_WIRE(netreq->query));
|
||||
|
||||
/* Delete from upstream->write_queue (if present) */
|
||||
for (prev_r = NULL, r = upstream->write_queue; r;
|
||||
prev_r = r, r = r->write_queue_tail)
|
||||
|
||||
if (r == netreq) {
|
||||
if (prev_r)
|
||||
prev_r->write_queue_tail = r->write_queue_tail;
|
||||
else
|
||||
upstream->write_queue = r->write_queue_tail;
|
||||
|
||||
if (r == upstream->write_queue_last)
|
||||
upstream->write_queue_last =
|
||||
prev_r ? prev_r : NULL;
|
||||
netreq->write_queue_tail = NULL;
|
||||
break;
|
||||
}
|
||||
upstream_reschedule_events(upstream, upstream->keepalive_timeout);
|
||||
if (netreq->query_id_registered) {
|
||||
(void) _getdns_rbtree_delete(
|
||||
netreq->query_id_registered, netreq->node.key);
|
||||
netreq->query_id_registered = NULL;
|
||||
netreq->node.key = NULL;
|
||||
}
|
||||
if (netreq->upstream) {
|
||||
remove_from_write_queue(netreq->upstream, netreq);
|
||||
if (netreq->upstream->event.ev)
|
||||
upstream_reschedule_events(netreq->upstream);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -533,17 +523,8 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
|
|||
when idle.*/
|
||||
/* [TLS1]TODO: Work out how to re-open the connection and re-try
|
||||
the queries if there is only one upstream.*/
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
if (during_setup) {
|
||||
/* Reset timeout on setup failure to trigger fallback handling.*/
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
/* Need this check because if the setup failed because the interface is
|
||||
not up we get -1 and then a seg fault. Found when using IPv6 address
|
||||
but IPv6 interface not enabled.*/
|
||||
if (upstream->fd != -1) {
|
||||
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd, TIMEOUT_FOREVER,
|
||||
getdns_eventloop_event_init(&upstream->event, upstream,
|
||||
NULL, upstream_write_cb, NULL));
|
||||
}
|
||||
/* Special case if failure was due to authentication issues since this
|
||||
upstream could be used oppotunistically with no problem.*/
|
||||
if (!(upstream->transport == GETDNS_TRANSPORT_TLS &&
|
||||
|
@ -553,6 +534,11 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
|
|||
upstream->conn_shutdowns++;
|
||||
/* [TLS1]TODO: Re-try these queries if possible.*/
|
||||
}
|
||||
upstream->conn_state = GETDNS_CONN_TEARDOWN;
|
||||
|
||||
while (upstream->write_queue)
|
||||
upstream_write_cb(upstream);
|
||||
|
||||
while (upstream->netreq_by_query_id.count) {
|
||||
netreq = (getdns_network_req *)
|
||||
_getdns_rbtree_first(&upstream->netreq_by_query_id);
|
||||
|
@ -560,7 +546,7 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
|
|||
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
|
||||
_getdns_check_dns_req_complete(netreq->owner);
|
||||
}
|
||||
upstream->conn_state = GETDNS_CONN_TEARDOWN;
|
||||
_getdns_upstream_shutdown(upstream);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -570,11 +556,7 @@ _getdns_cancel_stub_request(getdns_network_req *netreq)
|
|||
STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq);
|
||||
stub_cleanup(netreq);
|
||||
if (netreq->fd >= 0) {
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(netreq->fd);
|
||||
#else
|
||||
close(netreq->fd);
|
||||
#endif
|
||||
_getdns_closesocket(netreq->fd);
|
||||
netreq->fd = -1;
|
||||
}
|
||||
}
|
||||
|
@ -589,11 +571,7 @@ stub_timeout_cb(void *userarg)
|
|||
_getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
|
||||
/* Handle upstream*/
|
||||
if (netreq->fd >= 0) {
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(netreq->fd);
|
||||
#else
|
||||
close(netreq->fd);
|
||||
#endif
|
||||
_getdns_closesocket(netreq->fd);
|
||||
netreq->fd = -1;
|
||||
netreq->upstream->udp_timeouts++;
|
||||
if (netreq->upstream->udp_timeouts % 100 == 0)
|
||||
|
@ -629,42 +607,12 @@ upstream_idle_timeout_cb(void *userarg)
|
|||
static void
|
||||
upstream_setup_timeout_cb(void *userarg)
|
||||
{
|
||||
int ret;
|
||||
getdns_upstream *upstream = (getdns_upstream *)userarg;
|
||||
#ifdef USE_POLL_DEFAULT_EVENTLOOP
|
||||
struct pollfd fds;
|
||||
#else
|
||||
fd_set fds;
|
||||
struct timeval tval;
|
||||
#endif
|
||||
|
||||
DEBUG_STUB("%s %-35s: FD: %d\n",
|
||||
STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd);
|
||||
/* Clean up and trigger a write to let the fallback code to its job */
|
||||
upstream_failed(upstream, 1);
|
||||
|
||||
/* Need to handle the case where the far end doesn't respond to a
|
||||
* TCP SYN and doesn't do a reset (as is the case with e.g. 8.8.8.8@853).
|
||||
* For that case the socket never becomes writable so doesn't trigger any
|
||||
* callbacks. If so then clear out the queue in one go.*/
|
||||
#ifdef USE_POLL_DEFAULT_EVENTLOOP
|
||||
fds.fd = upstream->fd;
|
||||
fds.events = POLLOUT;
|
||||
ret = poll(&fds, 1, 0);
|
||||
#else
|
||||
FD_ZERO(&fds);
|
||||
FD_SET((int)(upstream->fd), &fds);
|
||||
tval.tv_sec = 0;
|
||||
tval.tv_usec = 0;
|
||||
ret = select(upstream->fd+1, NULL, &fds, NULL, &tval);
|
||||
#endif
|
||||
if (ret == 0) {
|
||||
DEBUG_STUB("%s %-35s: FD: %d Cleaning up dangling queue\n",
|
||||
STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd);
|
||||
while (upstream->write_queue)
|
||||
upstream_write_cb(upstream);
|
||||
}
|
||||
_getdns_upstream_reset(upstream);
|
||||
upstream_failed(upstream, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -690,8 +638,8 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
|
|||
}
|
||||
read = recv(fd, (void *)tcp->read_pos, tcp->to_read, 0);
|
||||
if (read < 0) {
|
||||
if (_getdns_EWOULDBLOCK)
|
||||
return STUB_TCP_WOULDBLOCK;
|
||||
if (_getdns_socketerror_wants_retry())
|
||||
return STUB_TCP_RETRY;
|
||||
else
|
||||
return STUB_TCP_ERROR;
|
||||
} else if (read == 0) {
|
||||
|
@ -705,7 +653,7 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
|
|||
tcp->read_pos += read;
|
||||
|
||||
if (tcp->to_read > 0)
|
||||
return STUB_TCP_AGAIN;
|
||||
return STUB_TCP_MORE_TO_READ;
|
||||
|
||||
read = tcp->read_pos - tcp->read_buf;
|
||||
if (read == 2) {
|
||||
|
@ -730,14 +678,14 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
|
|||
}
|
||||
/* Ready to start reading the packet */
|
||||
tcp->read_pos = tcp->read_buf;
|
||||
return STUB_TCP_AGAIN;
|
||||
return STUB_TCP_MORE_TO_READ;
|
||||
}
|
||||
return GLDNS_ID_WIRE(tcp->read_buf);
|
||||
}
|
||||
|
||||
/* stub_tcp_write(fd, tcp, netreq)
|
||||
* will return STUB_TCP_AGAIN when we need to come back again,
|
||||
* STUB_TCP_ERROR on error and a query_id on successful sent.
|
||||
* will return STUB_TCP_RETRY or STUB_TCP_MORE_TO_WRITE when we need to come
|
||||
* back again, STUB_TCP_ERROR on error and a query_id on successful sent.
|
||||
*/
|
||||
static int
|
||||
stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
||||
|
@ -764,6 +712,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|||
|
||||
} while (!_getdns_rbtree_insert(
|
||||
&netreq->upstream->netreq_by_query_id, &netreq->node));
|
||||
netreq->query_id_registered = &netreq->upstream->netreq_by_query_id;
|
||||
|
||||
GLDNS_ID_SET(netreq->query, query_id);
|
||||
|
||||
|
@ -799,7 +748,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|||
netreq->upstream->addr_len);
|
||||
/* If pipelining we will find that the connection is already up so
|
||||
just fall back to a 'normal' write. */
|
||||
if (written == -1 && errno == EISCONN)
|
||||
if (written == -1 && _getdns_socketerror() == _getdns_EISCONN)
|
||||
written = write(fd, netreq->query - 2, pkt_len + 2);
|
||||
#else
|
||||
written = sendto(fd, (const char *)(netreq->query - 2),
|
||||
|
@ -807,27 +756,24 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|||
(struct sockaddr *)&(netreq->upstream->addr),
|
||||
netreq->upstream->addr_len);
|
||||
#endif
|
||||
if ((written < 0 && (_getdns_EWOULDBLOCK ||
|
||||
/* Add the error case where the connection is in progress which is when
|
||||
a cookie is not available (e.g. when doing the first request to an
|
||||
upstream). We must let the handshake complete since non-blocking. */
|
||||
_getdns_EINPROGRESS)) ||
|
||||
(size_t)written < pkt_len + 2) {
|
||||
if ((written == -1 && _getdns_socketerror_wants_retry()) ||
|
||||
(size_t)written < pkt_len + 2) {
|
||||
|
||||
/* We couldn't write the whole packet.
|
||||
* We have to return with STUB_TCP_AGAIN.
|
||||
* Setup tcp to track the state.
|
||||
*/
|
||||
tcp->write_buf = netreq->query - 2;
|
||||
tcp->write_buf_len = pkt_len + 2;
|
||||
tcp->written = written >= 0 ? written : 0;
|
||||
|
||||
return STUB_TCP_WOULDBLOCK;
|
||||
return written == -1
|
||||
? STUB_TCP_RETRY
|
||||
: STUB_TCP_MORE_TO_WRITE;
|
||||
|
||||
} else if (written == -1) {
|
||||
DEBUG_STUB("%s %-35s: MSG: %p error while writing to TCP socket:"
|
||||
" %s\n", STUB_DEBUG_WRITE, __FUNC__, (void*)netreq
|
||||
, strerror(errno));
|
||||
, _getdns_errnostr());
|
||||
|
||||
return STUB_TCP_ERROR;
|
||||
}
|
||||
|
@ -839,20 +785,15 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|||
|
||||
/* Coming back from an earlier unfinished write or handshake.
|
||||
* Try to send remaining data */
|
||||
#ifdef USE_WINSOCK
|
||||
written = send(fd, (void *)(tcp->write_buf + tcp->written),
|
||||
tcp->write_buf_len - tcp->written, 0);
|
||||
#else
|
||||
written = write(fd, tcp->write_buf + tcp->written,
|
||||
tcp->write_buf_len - tcp->written);
|
||||
#endif
|
||||
if (written == -1) {
|
||||
if (_getdns_EWOULDBLOCK)
|
||||
return STUB_TCP_WOULDBLOCK;
|
||||
if (_getdns_socketerror_wants_retry())
|
||||
return STUB_TCP_RETRY;
|
||||
else {
|
||||
DEBUG_STUB("%s %-35s: MSG: %p error while writing to TCP socket:"
|
||||
" %s\n", STUB_DEBUG_WRITE, __FUNC__, (void*)netreq
|
||||
, strerror(errno));
|
||||
, _getdns_errnostr());
|
||||
|
||||
return STUB_TCP_ERROR;
|
||||
}
|
||||
|
@ -860,7 +801,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|||
tcp->written += written;
|
||||
if (tcp->written < tcp->write_buf_len)
|
||||
/* Still more to send */
|
||||
return STUB_TCP_AGAIN;
|
||||
return STUB_TCP_MORE_TO_WRITE;
|
||||
|
||||
query_id = (int)GLDNS_ID_WIRE(tcp->write_buf + 2);
|
||||
/* Done. Start reading */
|
||||
|
@ -1005,8 +946,11 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
|
|||
X509_VERIFY_PARAM_set1_host(param, upstream->tls_auth_name, 0);
|
||||
#else
|
||||
if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_REQUIRED) {
|
||||
DEBUG_STUB("%s %-35s: ERROR: TLS Authentication functionality not available\n",
|
||||
DEBUG_STUB("%s %-35s: ERROR: Hostname Authentication not available from TLS library (check library version)\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__);
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_ERR,
|
||||
"%-40s : ERROR: Hostname Authentication not available from TLS library (check library version)\n",
|
||||
upstream->addr_str);
|
||||
upstream->tls_hs_state = GETDNS_HS_FAILED;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1081,7 +1025,7 @@ tls_do_handshake(getdns_upstream *upstream)
|
|||
GETDNS_SCHEDULE_EVENT(upstream->loop,
|
||||
upstream->fd, TIMEOUT_TLS, &upstream->event);
|
||||
upstream->tls_hs_state = GETDNS_HS_READ;
|
||||
return STUB_TCP_AGAIN;
|
||||
return STUB_TCP_RETRY;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
upstream->event.read_cb = NULL;
|
||||
|
@ -1089,7 +1033,7 @@ tls_do_handshake(getdns_upstream *upstream)
|
|||
GETDNS_SCHEDULE_EVENT(upstream->loop,
|
||||
upstream->fd, TIMEOUT_TLS, &upstream->event);
|
||||
upstream->tls_hs_state = GETDNS_HS_WRITE;
|
||||
return STUB_TCP_AGAIN;
|
||||
return STUB_TCP_RETRY;
|
||||
default:
|
||||
DEBUG_STUB("%s %-35s: FD: %d Handshake failed %d\n",
|
||||
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd,
|
||||
|
@ -1173,7 +1117,7 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
renegotiation. Need to keep handshake state to do that.*/
|
||||
int want = SSL_get_error(tls_obj, read);
|
||||
if (want == SSL_ERROR_WANT_READ) {
|
||||
return STUB_TCP_AGAIN; /* read more later */
|
||||
return STUB_TCP_RETRY; /* Come back later */
|
||||
} else
|
||||
return STUB_TCP_ERROR;
|
||||
}
|
||||
|
@ -1181,7 +1125,7 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
tcp->read_pos += read;
|
||||
|
||||
if ((int)tcp->to_read > 0)
|
||||
return STUB_TCP_AGAIN;
|
||||
return STUB_TCP_MORE_TO_READ;
|
||||
|
||||
read = tcp->read_pos - tcp->read_buf;
|
||||
if (read == 2) {
|
||||
|
@ -1213,14 +1157,14 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
renegotiation. Need to keep handshake state to do that.*/
|
||||
int want = SSL_get_error(tls_obj, read);
|
||||
if (want == SSL_ERROR_WANT_READ) {
|
||||
return STUB_TCP_AGAIN; /* read more later */
|
||||
return STUB_TCP_RETRY; /* read more later */
|
||||
} else
|
||||
return STUB_TCP_ERROR;
|
||||
}
|
||||
tcp->to_read -= read;
|
||||
tcp->read_pos += read;
|
||||
if ((int)tcp->to_read > 0)
|
||||
return STUB_TCP_AGAIN;
|
||||
return STUB_TCP_MORE_TO_READ;
|
||||
}
|
||||
return GLDNS_ID_WIRE(tcp->read_buf);
|
||||
}
|
||||
|
@ -1262,6 +1206,7 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
|
||||
} while (!_getdns_rbtree_insert(
|
||||
&netreq->upstream->netreq_by_query_id, &netreq->node));
|
||||
netreq->query_id_registered = &netreq->upstream->netreq_by_query_id;
|
||||
|
||||
GLDNS_ID_SET(netreq->query, query_id);
|
||||
|
||||
|
@ -1336,7 +1281,7 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
switch (SSL_get_error(tls_obj, written)) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
return STUB_TCP_AGAIN;
|
||||
return STUB_TCP_RETRY;
|
||||
default:
|
||||
return STUB_TCP_ERROR;
|
||||
}
|
||||
|
@ -1386,23 +1331,20 @@ stub_udp_read_cb(void *userarg)
|
|||
* i.e. overflow
|
||||
*/
|
||||
0, NULL, NULL);
|
||||
if (read == -1 && _getdns_EWOULDBLOCK)
|
||||
if (read == -1 && (_getdns_socketerror_wants_retry() ||
|
||||
_getdns_socketerror() == _getdns_ECONNRESET))
|
||||
return; /* Try again later */
|
||||
|
||||
if (read == -1) {
|
||||
DEBUG_STUB("%s %-35s: MSG: %p error while reading from socket:"
|
||||
" %s\n", STUB_DEBUG_READ, __FUNC__, (void*)netreq
|
||||
, strerror(errno));
|
||||
, _getdns_errnostr());
|
||||
|
||||
stub_cleanup(netreq);
|
||||
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
|
||||
/* Handle upstream*/
|
||||
if (netreq->fd >= 0) {
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(netreq->fd);
|
||||
#else
|
||||
close(netreq->fd);
|
||||
#endif
|
||||
_getdns_closesocket(netreq->fd);
|
||||
netreq->fd = -1;
|
||||
stub_next_upstream(netreq);
|
||||
}
|
||||
|
@ -1422,11 +1364,7 @@ stub_udp_read_cb(void *userarg)
|
|||
|
||||
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(netreq->fd);
|
||||
#else
|
||||
close(netreq->fd);
|
||||
#endif
|
||||
_getdns_closesocket(netreq->fd);
|
||||
netreq->fd = -1;
|
||||
while (GLDNS_TC_WIRE(netreq->response)) {
|
||||
DEBUG_STUB("%s %-35s: MSG: %p TC bit set in response \n", STUB_DEBUG_READ,
|
||||
|
@ -1509,7 +1447,7 @@ stub_udp_write_cb(void *userarg)
|
|||
if (written == -1)
|
||||
DEBUG_STUB( "%s %-35s: MSG: %p error: %s\n"
|
||||
, STUB_DEBUG_WRITE, __FUNC__, (void *)netreq
|
||||
, strerror(errno));
|
||||
, _getdns_errnostr());
|
||||
else
|
||||
DEBUG_STUB( "%s %-35s: MSG: %p returned: %d, expeced: %d\n"
|
||||
, STUB_DEBUG_WRITE, __FUNC__, (void *)netreq
|
||||
|
@ -1519,11 +1457,7 @@ stub_udp_write_cb(void *userarg)
|
|||
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
|
||||
/* Handle upstream*/
|
||||
if (netreq->fd >= 0) {
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(netreq->fd);
|
||||
#else
|
||||
close(netreq->fd);
|
||||
#endif
|
||||
_getdns_closesocket(netreq->fd);
|
||||
netreq->fd = -1;
|
||||
stub_next_upstream(netreq);
|
||||
}
|
||||
|
@ -1579,20 +1513,17 @@ upstream_read_cb(void *userarg)
|
|||
&upstream->upstreams->mf);
|
||||
|
||||
switch (q) {
|
||||
case STUB_TCP_AGAIN:
|
||||
case STUB_TCP_MORE_TO_READ:
|
||||
/* WSA TODO: if callback is still upstream_read_cb, do it again
|
||||
*/
|
||||
case STUB_TCP_WOULDBLOCK:
|
||||
case STUB_TCP_RETRY:
|
||||
return;
|
||||
case STUB_SETUP_ERROR: /* Can happen for TLS HS*/
|
||||
case STUB_TCP_ERROR:
|
||||
upstream_failed(upstream, (q == STUB_TCP_ERROR ? 0:1) );
|
||||
if (!upstream->write_queue)
|
||||
_getdns_upstream_shutdown(upstream);
|
||||
return;
|
||||
|
||||
default:
|
||||
|
||||
/* Lookup netreq */
|
||||
query_id = (uint16_t) q;
|
||||
query_id_intptr = (intptr_t) query_id;
|
||||
|
@ -1604,7 +1535,16 @@ upstream_read_cb(void *userarg)
|
|||
upstream->tcp.to_read = 2;
|
||||
return;
|
||||
}
|
||||
if (netreq->query_id_registered == &upstream->netreq_by_query_id) {
|
||||
netreq->query_id_registered = NULL;
|
||||
netreq->node.key = NULL;
|
||||
|
||||
} else if (netreq->query_id_registered) {
|
||||
(void) _getdns_rbtree_delete(
|
||||
netreq->query_id_registered, netreq->node.key);
|
||||
netreq->query_id_registered = NULL;
|
||||
netreq->node.key = NULL;
|
||||
}
|
||||
DEBUG_STUB("%s %-35s: MSG: %p (read)\n",
|
||||
STUB_DEBUG_READ, __FUNC__, (void*)netreq);
|
||||
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
|
||||
|
@ -1704,10 +1644,10 @@ upstream_write_cb(void *userarg)
|
|||
q = stub_tcp_write(upstream->fd, &upstream->tcp, netreq);
|
||||
|
||||
switch (q) {
|
||||
case STUB_TCP_AGAIN:
|
||||
case STUB_TCP_MORE_TO_WRITE:
|
||||
/* WSA TODO: if callback is still upstream_write_cb, do it again
|
||||
*/
|
||||
case STUB_TCP_WOULDBLOCK:
|
||||
case STUB_TCP_RETRY:
|
||||
return;
|
||||
case STUB_OUT_OF_OPTIONS:
|
||||
case STUB_TCP_ERROR:
|
||||
|
@ -1717,10 +1657,8 @@ upstream_write_cb(void *userarg)
|
|||
/* Could not complete the set up. Need to fallback.*/
|
||||
DEBUG_STUB("%s %-35s: Upstream: %p ERROR = %d\n", STUB_DEBUG_WRITE,
|
||||
__FUNC__, (void*)userarg, q);
|
||||
(void) _getdns_rbtree_delete(&upstream->netreq_by_query_id,
|
||||
(void *)(intptr_t)GLDNS_ID_WIRE(netreq->query));
|
||||
upstream_failed(upstream, (q == STUB_TCP_ERROR ? 0:1));
|
||||
/* Fall through */
|
||||
return;
|
||||
case STUB_CONN_GONE:
|
||||
case STUB_NO_AUTH:
|
||||
/* Cleaning up after connection or auth check failure. Need to fallback. */
|
||||
|
@ -1734,11 +1672,12 @@ upstream_write_cb(void *userarg)
|
|||
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
|
||||
_getdns_check_dns_req_complete(netreq->owner);
|
||||
}
|
||||
if (!upstream->write_queue)
|
||||
_getdns_upstream_shutdown(upstream);
|
||||
return;
|
||||
|
||||
default:
|
||||
/* Unqueue the netreq from the write_queue */
|
||||
remove_from_write_queue(upstream, netreq);
|
||||
|
||||
if (netreq->owner->return_call_reporting &&
|
||||
netreq->upstream->tls_obj &&
|
||||
netreq->debug_tls_peer_cert.data == NULL &&
|
||||
|
@ -1751,9 +1690,9 @@ upstream_write_cb(void *userarg)
|
|||
netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state;
|
||||
upstream->queries_sent++;
|
||||
|
||||
/* Unqueue the netreq from the write_queue */
|
||||
if (!(upstream->write_queue = netreq->write_queue_tail)) {
|
||||
upstream->write_queue_last = NULL;
|
||||
/* Empty write_queue?, then deschedule upstream write_cb */
|
||||
if (upstream->write_queue == NULL) {
|
||||
assert(upstream->write_queue_last == NULL);
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
upstream->event.write_cb = NULL;
|
||||
/* Reschedule (if already reading) to clear writable */
|
||||
|
@ -1896,7 +1835,6 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
|
|||
if (upstreams->upstreams[i].conn_state == GETDNS_CONN_BACKOFF &&
|
||||
upstreams->upstreams[i].conn_retry_time < now) {
|
||||
upstreams->upstreams[i].conn_state = GETDNS_CONN_CLOSED;
|
||||
upstreams->upstreams[i].conn_backoff_interval = 1;
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_NOTICE,
|
||||
"%-40s : Re-instating upstream\n",
|
||||
upstreams->upstreams[i].addr_str);
|
||||
|
@ -1957,8 +1895,8 @@ upstream_select_stateful(getdns_network_req *netreq, getdns_transport_list_t tra
|
|||
upstream->conn_state = GETDNS_CONN_CLOSED;
|
||||
upstream->conn_backoff_interval = 1;
|
||||
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_NOTICE,
|
||||
"%-40s : No valid upstreams... promoting backed-off upstream %s for re-try...\n",
|
||||
upstreams->upstreams[i].addr_str);
|
||||
"%-40s : No valid upstreams... promoting this backed-off upstream for re-try...\n",
|
||||
upstream->addr_str);
|
||||
return upstream;
|
||||
}
|
||||
|
||||
|
@ -2044,7 +1982,6 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
|
|||
fd = tcp_connect(upstream, transport);
|
||||
if (fd == -1) {
|
||||
upstream_failed(upstream, 1);
|
||||
_getdns_upstream_reset(upstream);
|
||||
return -1;
|
||||
}
|
||||
upstream->loop = dnsreq->loop;
|
||||
|
@ -2054,12 +1991,7 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
|
|||
upstream->tls_obj = tls_create_object(dnsreq, fd, upstream);
|
||||
if (upstream->tls_obj == NULL) {
|
||||
upstream_failed(upstream, 1);
|
||||
_getdns_upstream_reset(upstream);
|
||||
#ifdef USE_WINSOCK
|
||||
closesocket(fd);
|
||||
#else
|
||||
close(fd);
|
||||
#endif
|
||||
_getdns_closesocket(fd);
|
||||
return -1;
|
||||
}
|
||||
upstream->tls_hs_state = GETDNS_HS_WRITE;
|
||||
|
@ -2128,7 +2060,7 @@ upstream_find_for_netreq(getdns_network_req *netreq)
|
|||
continue;
|
||||
|
||||
if (fd == -1) {
|
||||
if (_getdns_EMFILE)
|
||||
if (_getdns_resource_depletion())
|
||||
return STUB_TRY_AGAIN_LATER;
|
||||
return -1;
|
||||
}
|
||||
|
@ -2170,11 +2102,17 @@ fallback_on_write(getdns_network_req *netreq)
|
|||
}
|
||||
|
||||
static void
|
||||
upstream_reschedule_events(getdns_upstream *upstream, uint64_t idle_timeout) {
|
||||
upstream_reschedule_events(getdns_upstream *upstream) {
|
||||
|
||||
DEBUG_STUB("%s %-35s: FD: %d \n", STUB_DEBUG_SCHEDULE,
|
||||
__FUNC__, upstream->fd);
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
if (upstream->event.ev)
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
|
||||
if (upstream->fd == -1 || !( upstream->conn_state == GETDNS_CONN_SETUP
|
||||
|| upstream->conn_state == GETDNS_CONN_OPEN ))
|
||||
return;
|
||||
|
||||
if (!upstream->write_queue && upstream->event.write_cb) {
|
||||
upstream->event.write_cb = NULL;
|
||||
}
|
||||
|
@ -2192,18 +2130,13 @@ upstream_reschedule_events(getdns_upstream *upstream, uint64_t idle_timeout) {
|
|||
upstream->fd, TIMEOUT_FOREVER, &upstream->event);
|
||||
else {
|
||||
DEBUG_STUB("%s %-35s: FD: %d Connection idle - timeout is %d\n",
|
||||
STUB_DEBUG_SCHEDULE, __FUNC__, upstream->fd, (int)idle_timeout);
|
||||
/* TODO: Schedule a read also anyway,
|
||||
* to digest timed out answers.
|
||||
* Dont forget to schedule with upstream->fd then!
|
||||
*
|
||||
* upstream->event.read_cb = upstream_read_cb;
|
||||
*/
|
||||
STUB_DEBUG_SCHEDULE, __FUNC__, upstream->fd,
|
||||
(int)upstream->keepalive_timeout);
|
||||
|
||||
upstream->event.read_cb = upstream_read_cb;
|
||||
upstream->event.timeout_cb = upstream_idle_timeout_cb;
|
||||
if (upstream->conn_state != GETDNS_CONN_OPEN)
|
||||
idle_timeout = 0;
|
||||
GETDNS_SCHEDULE_EVENT(upstream->loop, -1,
|
||||
idle_timeout, &upstream->event);
|
||||
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
|
||||
upstream->keepalive_timeout, &upstream->event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
34
src/sync.c
34
src/sync.c
|
@ -116,30 +116,24 @@ getdns_sync_data_cleanup(getdns_sync_data *data)
|
|||
upstream = &ctxt->upstreams->upstreams[i];
|
||||
if (upstream->loop != &data->context->sync_eventloop.loop)
|
||||
continue;
|
||||
if (upstream->event.read_cb || upstream->event.write_cb) {
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
|
||||
} else if (upstream->event.timeout_cb) {
|
||||
/* Timeout's at upstream are idle-timeouts only.
|
||||
* They should be fired on completion of the
|
||||
* synchronous request.
|
||||
*/
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
if (upstream->conn_state != GETDNS_CONN_OPEN ||
|
||||
upstream->keepalive_timeout == 0)
|
||||
(*upstream->event.timeout_cb)(upstream->event.userarg);
|
||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
||||
if (upstream->event.timeout_cb &&
|
||||
( upstream->conn_state != GETDNS_CONN_OPEN
|
||||
|| upstream->keepalive_timeout == 0)) {
|
||||
(*upstream->event.timeout_cb)(upstream->event.userarg);
|
||||
upstream->event.timeout_cb = NULL;
|
||||
}
|
||||
upstream->loop = data->context->extension;
|
||||
upstream->is_sync_loop = 0;
|
||||
if (upstream->event.read_cb || upstream->event.write_cb)
|
||||
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
|
||||
TIMEOUT_FOREVER, &upstream->event);
|
||||
|
||||
else if (upstream->event.timeout_cb &&
|
||||
upstream->conn_state == GETDNS_CONN_OPEN &&
|
||||
upstream->keepalive_timeout != 0) {
|
||||
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd,
|
||||
upstream->keepalive_timeout, &upstream->event);
|
||||
if ( upstream->event.read_cb || upstream->event.write_cb
|
||||
|| upstream->event.timeout_cb) {
|
||||
GETDNS_SCHEDULE_EVENT(upstream->loop,
|
||||
( upstream->event.read_cb
|
||||
|| upstream->event.write_cb ? upstream->fd : -1),
|
||||
( upstream->event.timeout_cb
|
||||
? upstream->keepalive_timeout : TIMEOUT_FOREVER ),
|
||||
&upstream->event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,6 +217,7 @@ void assert_address_in_answer(struct extracted_response *ex_response, int a, int
|
|||
case GETDNS_RRTYPE_A:
|
||||
if(a && type == GETDNS_RRTYPE_A)
|
||||
address_records++;
|
||||
/* fallthrough */
|
||||
case GETDNS_RRTYPE_AAAA:
|
||||
if(aaaa && type == GETDNS_RRTYPE_AAAA)
|
||||
address_records++;
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
CONTEXT_CREATE(TRUE);
|
||||
|
||||
ASSERT_RC(getdns_context_set_upstream_recursive_servers(context, NULL),
|
||||
GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_context_set_upstream_recursive_servers()");
|
||||
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_upstream_recursive_servers()");
|
||||
|
||||
|
||||
CONTEXT_DESTROY;
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
export SRCDIR=`dirname $0`
|
||||
( cd $SRCDIR
|
||||
./tpkg clean
|
||||
rm -fr build build-stub-only build-event-loops build-static-analysis install scan-build-reports .tpkg.var.master *.info
|
||||
rm -fr build build-stub-only build-event-loops build-static-analysis install scan-build-reports .tpkg.var.master *.info Makefile
|
||||
)
|
||||
|
|
|
@ -46,6 +46,10 @@ typedef unsigned short in_port_t;
|
|||
#include <wincrypt.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETDNS_YAML2DICT
|
||||
getdns_return_t getdns_yaml2dict(const char *, getdns_dict **dict);
|
||||
#endif
|
||||
|
@ -1279,7 +1283,9 @@ void read_line_cb(void *userarg)
|
|||
if (listen_count)
|
||||
(void) getdns_context_set_listen_addresses(
|
||||
context, NULL, NULL, NULL);
|
||||
(void) getdns_context_set_idle_timeout(context, 0);
|
||||
if (interactive && !query_file)
|
||||
(void) getdns_context_set_upstream_recursive_servers(
|
||||
context, NULL);
|
||||
return;
|
||||
}
|
||||
if (query_file && verbosity)
|
||||
|
@ -1678,16 +1684,22 @@ static void stubby_log(void *userarg, uint64_t system,
|
|||
#ifdef GETDNS_ON_WINDOWS
|
||||
time_t tsec;
|
||||
|
||||
if (!verbosity)
|
||||
return;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
tsec = (time_t) tv.tv_sec;
|
||||
gmtime_s(&tm, (const time_t *) &tsec);
|
||||
#else
|
||||
if (!verbosity)
|
||||
return;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
gmtime_r(&tv.tv_sec, &tm);
|
||||
#endif
|
||||
strftime(buf, 10, "%H:%M:%S", &tm);
|
||||
(void)userarg; (void)system; (void)level;
|
||||
(void) fprintf(stderr, "[%s.%.6d] STUBBY: ", buf, (int)tv.tv_usec);
|
||||
(void) fprintf(stderr, "[%s.%.6d] UPSTREAM ", buf, (int)tv.tv_usec);
|
||||
(void) vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
|
||||
|
@ -1741,10 +1753,10 @@ main(int argc, char **argv)
|
|||
(void) parse_config_file(home_stubby_conf_fn, 0);
|
||||
}
|
||||
clear_listen_list_on_arg = 1;
|
||||
|
||||
(void) getdns_context_set_logfunc(context, NULL,
|
||||
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, stubby_log);
|
||||
}
|
||||
(void) getdns_context_set_logfunc(context, NULL,
|
||||
GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG, stubby_log);
|
||||
|
||||
if ((r = parse_args(argc, argv)))
|
||||
goto done_destroy_context;
|
||||
clear_listen_list_on_arg = 0;
|
||||
|
@ -1786,27 +1798,10 @@ main(int argc, char **argv)
|
|||
}
|
||||
else if (listen_count) {
|
||||
assert(loop);
|
||||
#ifndef GETDNS_ON_WINDOWS
|
||||
if (i_am_stubby && !run_in_foreground) {
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) {
|
||||
perror("Could not fork of stubby daemon\n");
|
||||
r = GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
||||
} else if (pid) {
|
||||
FILE *fh = fopen("/var/rub/stubby.pid", "w");
|
||||
if (! fh)
|
||||
fh = fopen("/tmp/stubby.pid", "w");
|
||||
if (fh) {
|
||||
fprintf(fh, "%d", (int)pid);
|
||||
fclose(fh);
|
||||
batch_mode = 0;
|
||||
}
|
||||
} else
|
||||
loop->vmt->run(loop);
|
||||
} else
|
||||
#ifdef SIGPIPE
|
||||
(void) signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
loop->vmt->run(loop);
|
||||
loop->vmt->run(loop);
|
||||
} else
|
||||
r = do_the_call();
|
||||
|
||||
|
|
|
@ -188,7 +188,9 @@ typedef struct getdns_tcp_state {
|
|||
typedef struct getdns_network_req
|
||||
{
|
||||
/* For storage in upstream->netreq_by_query_id */
|
||||
_getdns_rbnode_t node;
|
||||
_getdns_rbnode_t node;
|
||||
/* The netreq_by_query_id tree in which this netreq was registered */
|
||||
_getdns_rbtree_t *query_id_registered;
|
||||
#ifdef HAVE_MDNS_SUPPORT
|
||||
/*
|
||||
* for storage of continuous query context in hash table of cached results.
|
||||
|
|
|
@ -218,18 +218,5 @@ INLINE uint64_t _getdns_ms_until_expiry2(uint64_t expires, uint64_t *now_ms)
|
|||
return *now_ms >= expires ? 0 : expires - *now_ms;
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
typedef u_short sa_family_t;
|
||||
#define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\
|
||||
WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
#define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS)
|
||||
#define _getdns_EMFILE (WSAGetLastError() == WSAEMFILE)
|
||||
#else
|
||||
#define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
#define _getdns_EINPROGRESS (errno == EINPROGRESS)
|
||||
#define _getdns_EMFILE (errno == EMFILE)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* util-internal.h */
|
||||
|
|
2
stubby
2
stubby
|
@ -1 +1 @@
|
|||
Subproject commit d541e60530717f590d4a4a9d458f987cbe90fc59
|
||||
Subproject commit a43be56e28f3a802f74b7c5b19b4b4c5fbaa908a
|
Loading…
Reference in New Issue