Merge branch 'release/1.1.0-alpha3' into develop

This commit is contained in:
Willem Toorop 2017-01-13 22:10:17 +01:00
commit 7c1c4c52d6
37 changed files with 2856 additions and 2055 deletions

3
.gitignore vendored
View File

@ -36,9 +36,10 @@ src/test/check_getdns
src/test/check_getdns_event src/test/check_getdns_event
src/test/check_getdns_uv src/test/check_getdns_uv
src/test/check_getdns_ev src/test/check_getdns_ev
src/test/getdns_query
src/test/scratchpad src/test/scratchpad
src/test/scratchpad.c src/test/scratchpad.c
src/tools/getdns_query
src/tools/stubby
doc/*.3 doc/*.3
src/getdns/getdns.h src/getdns/getdns.h
*.log *.log

2
.gitmodules vendored
View File

@ -1,4 +1,4 @@
[submodule "src/test/jsmn"] [submodule "src/test/jsmn"]
path = src/test/jsmn path = src/jsmn
url = https://github.com/getdnsapi/jsmn.git url = https://github.com/getdnsapi/jsmn.git
branch = getdns branch = getdns

View File

@ -14,6 +14,26 @@
getdns_get_suffix(). Thanks Jim Hague getdns_get_suffix(). Thanks Jim Hague
* Better README.md. Thanks Andrew Sullivan * Better README.md. Thanks Andrew Sullivan
* 2016-10-19: Version 1.1.0-a2
* Improved TLS connection management
* OpenSSL 1.1 support
* Stubby, Server version of getdns_query that by default listens
on 127.0.0.1 and ::1 and reads config from /etc/stubby.conf
and $HOME/.stubby.conf
* 2016-07-14: Version 1.1.0a1
* Conversion functions from text strings to getdns native types:
getdns_str2dict(), getdns_str2list(), getdns_str2bindata() and
getdns_str2int()
* A getdns_context_config() function that configures a context
with settings given in a getdns_dict
* A a getdns_context_set_listen_addresses() function and companion
getdns_reply() function to construct simple name servers.
* Relocate getdns_query to src/tools and build by default
* Enhancements to the logic used to select connection based upstream
transports (TCP, TLS) to improve robustness and re-use of
connections/upstreams.
* 2016-07-14: Version 1.0.0b2 * 2016-07-14: Version 1.0.0b2
* Collect coverage information from the unit tests * Collect coverage information from the unit tests
Thanks Shane Kerr Thanks Shane Kerr

View File

@ -44,7 +44,7 @@ libdir = @libdir@
srcdir = @srcdir@ srcdir = @srcdir@
INSTALL = @INSTALL@ INSTALL = @INSTALL@
all : default @GETDNS_QUERY@ all : default @GETDNS_QUERY@ @STUBBY@
everything: default everything: default
cd src/test && $(MAKE) cd src/test && $(MAKE)
@ -52,7 +52,7 @@ everything: default
default: default:
cd src && $(MAKE) $@ cd src && $(MAKE) $@
install: all getdns.pc getdns_ext_event.pc @INSTALL_GETDNS_QUERY@ install: all getdns.pc getdns_ext_event.pc @INSTALL_GETDNS_QUERY@ @INSTALL_STUBBY@
$(INSTALL) -m 755 -d $(DESTDIR)$(docdir) $(INSTALL) -m 755 -d $(DESTDIR)$(docdir)
$(INSTALL) -m 644 $(srcdir)/AUTHORS $(DESTDIR)$(docdir) $(INSTALL) -m 644 $(srcdir)/AUTHORS $(DESTDIR)$(docdir)
$(INSTALL) -m 644 $(srcdir)/ChangeLog $(DESTDIR)$(docdir) $(INSTALL) -m 644 $(srcdir)/ChangeLog $(DESTDIR)$(docdir)
@ -87,7 +87,7 @@ install: all getdns.pc getdns_ext_event.pc @INSTALL_GETDNS_QUERY@
@echo "*** at package installation time from the post-install script." @echo "*** at package installation time from the post-install script."
@echo "***" @echo "***"
uninstall: @UNINSTALL_GETDNS_QUERY@ uninstall: @UNINSTALL_GETDNS_QUERY@ @UNINSTALL_STUBBY@
rm -rf $(DESTDIR)$(docdir) rm -rf $(DESTDIR)$(docdir)
cd doc && $(MAKE) $@ cd doc && $(MAKE) $@
cd src && $(MAKE) $@ cd src && $(MAKE) $@
@ -104,6 +104,9 @@ test:
getdns_query: getdns_query:
cd src && $(MAKE) $@ cd src && $(MAKE) $@
stubby:
cd src && $(MAKE) $@
scratchpad: scratchpad:
cd src && $(MAKE) $@ cd src && $(MAKE) $@
@ -111,10 +114,16 @@ pad: scratchpad
src/test/scratchpad || ./libtool exec gdb src/test/scratchpad src/test/scratchpad || ./libtool exec gdb src/test/scratchpad
install-getdns_query: install-getdns_query:
cd src/test && $(MAKE) install cd src/tools && $(MAKE) $@
uninstall-getdns_query: uninstall-getdns_query:
cd src/test && $(MAKE) uninstall cd src/tools && $(MAKE) $@
install-stubby:
cd src/tools && $(MAKE) $@
uninstall-stubby:
cd src/tools && $(MAKE) $@
clean: clean:
cd src && $(MAKE) $@ cd src && $(MAKE) $@
@ -187,6 +196,8 @@ $(distdir):
mkdir -p $(distdir)/src/compat mkdir -p $(distdir)/src/compat
mkdir -p $(distdir)/src/util mkdir -p $(distdir)/src/util
mkdir -p $(distdir)/src/gldns mkdir -p $(distdir)/src/gldns
mkdir -p $(distdir)/src/tools
mkdir -p $(distdir)/src/jsmn
mkdir -p $(distdir)/doc mkdir -p $(distdir)/doc
mkdir -p $(distdir)/spec mkdir -p $(distdir)/spec
mkdir -p $(distdir)/spec/example mkdir -p $(distdir)/spec/example
@ -229,9 +240,11 @@ $(distdir):
cp $(srcdir)/spec/*.tgz $(distdir)/spec || true cp $(srcdir)/spec/*.tgz $(distdir)/spec || true
cp $(srcdir)/spec/example/Makefile.in $(distdir)/spec/example cp $(srcdir)/spec/example/Makefile.in $(distdir)/spec/example
cp $(srcdir)/spec/example/*.[ch] $(distdir)/spec/example cp $(srcdir)/spec/example/*.[ch] $(distdir)/spec/example
cp $(srcdir)/src/test/jsmn/*.[ch] $(distdir)/src/test/jsmn cp $(srcdir)/src/tools/Makefile.in $(distdir)/src/tools
cp $(srcdir)/src/test/jsmn/LICENSE $(distdir)/src/test/jsmn cp $(srcdir)/src/tools/*.[ch] $(distdir)/src/tools
cp $(srcdir)/src/test/jsmn/README.md $(distdir)/src/test/jsmn cp $(srcdir)/src/jsmn/*.[ch] $(distdir)/src/jsmn
cp $(srcdir)/src/jsmn/LICENSE $(distdir)/src/jsmn
cp $(srcdir)/src/jsmn/README.md $(distdir)/src/jsmn
rm -f $(distdir)/Makefile $(distdir)/src/Makefile $(distdir)/src/getdns/getdns.h $(distdir)/spec/example/Makefile $(distdir)/src/test/Makefile $(distdir)/doc/Makefile $(distdir)/src/config.h rm -f $(distdir)/Makefile $(distdir)/src/Makefile $(distdir)/src/getdns/getdns.h $(distdir)/spec/example/Makefile $(distdir)/src/test/Makefile $(distdir)/doc/Makefile $(distdir)/src/config.h
distcheck: $(distdir).tar.gz distcheck: $(distdir).tar.gz

View File

@ -19,6 +19,8 @@ Traditional access to DNS data from applications has several limitations:
* Sophisticated uses of the DNS (things like IDNA and DNSSEC validation) require considerable application work, possibly by application developers with little experience with the vagaries of DNS. * Sophisticated uses of the DNS (things like IDNA and DNSSEC validation) require considerable application work, possibly by application developers with little experience with the vagaries of DNS.
getdns also provides a experimental DNS Privacy enabled client called 'stubby' - see below for more details.
## Motivation for providing the API ## Motivation for providing the API
The developers are of the opinion that DNSSEC offers a unique global infrastructure for establishing and enhancing cryptographic trust relations. With the development of this API we intend to offer application developers a modern and flexible interface that enables end-to-end trust in the DNS architecture, and which will inspire application developers to implement innovative security solutions in their applications. The developers are of the opinion that DNSSEC offers a unique global infrastructure for establishing and enhancing cryptographic trust relations. With the development of this API we intend to offer application developers a modern and flexible interface that enables end-to-end trust in the DNS architecture, and which will inspire application developers to implement innovative security solutions in their applications.
@ -73,9 +75,13 @@ If you want to make use of the configuration files that utilise a JSON-like form
before building. before building.
If you want to use the getdns_query command line wrapper script for testing or to enable getdns as a daemon then you must build it using As well as building the getdns library 2 other tools are installed by default by the above process:
* getdns_query: a command line test script wrapper for getdns
* stubby: a experimental DNS Privacy enabled client
Note: If you only want to build stubby, then use the `--enable-stub-only` and `--without-libidn` options when running 'configure'.
# make getdns_query
## Minimizing dependencies ## Minimizing dependencies
@ -91,6 +97,18 @@ The implementation works with a variety of event loops, each built as a separate
* [libuv](https://github.com/joyent/libuv) * [libuv](https://github.com/joyent/libuv)
* [libev](http://software.schmorp.de/pkg/libev.html) * [libev](http://software.schmorp.de/pkg/libev.html)
## Stubby
* Stubby is an experimental implementation of a DNS Privacy enabled stub resolver. It is currently suitable for advanced/technical users - all feedback is welcome! Also see [dnsprivacy.org](https://dnsprivacy.org) for more information on DNS Privacy and stubby.
* By default stubby will attempt to use 'Opportunistic' Privacy for DNS queries.
* A sample configuration file is available in the source code (src/tools/stubby.conf) which uses 'Strict' Privacy and some of the available test DNS Privacy servers to resolve queries. Note these servers are test servers that offer no service guarantees. The location of a configuration file can be specified with the '-C' flag
* RECOMMENDED: Minimal logging output from Stubby is available (e.g. which servers are used and connection level statistics) by also using the '--enable-debug-daemon' flag when running 'configure'.
To use stubby
* Start stubby from the command line
* Test it by doing, for example, 'dig @127.0.0.1 www.example.com'
* Alter the default DNS resolvers on your system to point at localhost (127.0.0.1, ::1)
## Regression Tests ## Regression Tests
A suite of regression tests are included with the library, if you make changes or just A suite of regression tests are included with the library, if you make changes or just

View File

@ -36,8 +36,8 @@ sinclude(./m4/acx_getaddrinfo.m4)
sinclude(./m4/ax_check_compile_flag.m4) sinclude(./m4/ax_check_compile_flag.m4)
sinclude(./m4/pkg.m4) sinclude(./m4/pkg.m4)
AC_INIT([getdns], [1.0.0], [users@getdnsapi.net], [], [https://getdnsapi.net]) AC_INIT([getdns], [1.1.0], [users@getdnsapi.net], [], [https://getdnsapi.net])
AC_SUBST(RELEASE_CANDIDATE, []) AC_SUBST(RELEASE_CANDIDATE, [-alpha3])
# Set current date from system if not set # Set current date from system if not set
AC_ARG_WITH([current-date], AC_ARG_WITH([current-date],
@ -47,7 +47,7 @@ AC_ARG_WITH([current-date],
[CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"]) [CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"])
AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"]) AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"])
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x01000000]) AC_SUBST(GETDNS_NUMERIC_VERSION, [0x0100A300])
AC_SUBST(API_VERSION, ["December 2015"]) AC_SUBST(API_VERSION, ["December 2015"])
AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00]) AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00])
GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API" GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API"
@ -78,8 +78,9 @@ GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRE
# getdns-0.5.1 had libversion 4:1:3 (but should have been getdns-0.6.0) # getdns-0.5.1 had libversion 4:1:3 (but should have been getdns-0.6.0)
# getdns-0.9.0 had libversion 5:0:4 # getdns-0.9.0 had libversion 5:0:4
# getdns-1.0.0 will have libversion 5:1:4 # getdns-1.0.0 will have libversion 5:1:4
# getdns-1.1.0 will have libversion 6:0:0
# #
GETDNS_LIBVERSION=5:1:4 GETDNS_LIBVERSION=6:0:0
AC_SUBST(GETDNS_COMPILATION_COMMENT) AC_SUBST(GETDNS_COMPILATION_COMMENT)
AC_SUBST(GETDNS_LIBVERSION) AC_SUBST(GETDNS_LIBVERSION)
@ -150,6 +151,7 @@ ACX_ARG_RPATH
AC_ARG_ENABLE(debug-sched, AC_HELP_STRING([--enable-debug-sched], [Enable scheduling debugging messages])) AC_ARG_ENABLE(debug-sched, AC_HELP_STRING([--enable-debug-sched], [Enable scheduling debugging messages]))
AC_ARG_ENABLE(debug-stub, AC_HELP_STRING([--enable-debug-stub], [Enable stub debugging messages])) AC_ARG_ENABLE(debug-stub, AC_HELP_STRING([--enable-debug-stub], [Enable stub debugging messages]))
AC_ARG_ENABLE(debug-daemon, AC_HELP_STRING([--enable-debug-daemon], [Enable daemon debugging messages]))
AC_ARG_ENABLE(debug-sec, AC_HELP_STRING([--enable-debug-sec], [Enable dnssec debugging messages])) AC_ARG_ENABLE(debug-sec, AC_HELP_STRING([--enable-debug-sec], [Enable dnssec debugging messages]))
AC_ARG_ENABLE(debug-server, AC_HELP_STRING([--enable-debug-server], [Enable server debugging messages])) AC_ARG_ENABLE(debug-server, AC_HELP_STRING([--enable-debug-server], [Enable server debugging messages]))
AC_ARG_ENABLE(all-debugging, AC_HELP_STRING([--enable-all-debugging], [Enable scheduling, stub and dnssec debugging])) AC_ARG_ENABLE(all-debugging, AC_HELP_STRING([--enable-all-debugging], [Enable scheduling, stub and dnssec debugging]))
@ -157,6 +159,7 @@ case "$enable_all_debugging" in
yes) yes)
enable_debug_sched=yes enable_debug_sched=yes
enable_debug_stub=yes enable_debug_stub=yes
enable_debug_daemon=yes
enable_debug_sec=yes enable_debug_sec=yes
enable_debug_server=yes enable_debug_server=yes
;; ;;
@ -177,6 +180,13 @@ case "$enable_debug_stub" in
no|*) no|*)
;; ;;
esac esac
case "$enable_debug_daemon" in
yes)
AC_DEFINE_UNQUOTED([DAEMON_DEBUG], [1], [Define this to enable printing of daemon debugging messages.])
;;
no|*)
;;
esac
case "$enable_debug_sec" in case "$enable_debug_sec" in
yes) yes)
AC_DEFINE_UNQUOTED([SEC_DEBUG], [1], [Define this to enable printing of dnssec debugging messages.]) AC_DEFINE_UNQUOTED([SEC_DEBUG], [1], [Define this to enable printing of dnssec debugging messages.])
@ -907,9 +917,9 @@ AC_DEFINE_UNQUOTED([TRUST_ANCHOR_FILE], ["$TRUST_ANCHOR_FILE"], [Default trust a
AC_SUBST(TRUST_ANCHOR_FILE) AC_SUBST(TRUST_ANCHOR_FILE)
AC_MSG_NOTICE([Default trust anchor: $TRUST_ANCHOR_FILE]) AC_MSG_NOTICE([Default trust anchor: $TRUST_ANCHOR_FILE])
AC_ARG_WITH(getdns_query, AS_HELP_STRING([--with-getdns_query], AC_ARG_WITH(getdns_query, AS_HELP_STRING([--without-getdns_query],
[Also compile and install the getdns_query tool]), [Do not compile and install the getdns_query tool]),
[], [withval="no"]) [], [withval="yes"])
if test x_$withval = x_no; then if test x_$withval = x_no; then
GETDNS_QUERY="" GETDNS_QUERY=""
INSTALL_GETDNS_QUERY="" INSTALL_GETDNS_QUERY=""
@ -919,6 +929,26 @@ else
INSTALL_GETDNS_QUERY="install-getdns_query" INSTALL_GETDNS_QUERY="install-getdns_query"
UNINSTALL_GETDNS_QUERY="uninstall-getdns_query" UNINSTALL_GETDNS_QUERY="uninstall-getdns_query"
fi fi
AC_SUBST(GETDNS_QUERY)
AC_SUBST(INSTALL_GETDNS_QUERY)
AC_SUBST(UNINSTALL_GETDNS_QUERY)
AC_ARG_WITH(stubby, AS_HELP_STRING([--without-stubby],
[Do not compile and install stubby, the (stub) resolver daemon]),
[], [withval="yes"])
if test x_$withval = x_no; then
STUBBY=""
INSTALL_STUBBY=""
UNINSTALL_STUBBY=""
else
STUBBY="stubby"
INSTALL_STUBBY="install-stubby"
UNINSTALL_STUBBY="uninstall-stubby"
fi
AC_SUBST(STUBBY)
AC_SUBST(INSTALL_STUBBY)
AC_SUBST(UNINSTALL_STUBBY)
AC_ARG_WITH(fd-setsize, AS_HELP_STRING([--with-fd-setsize=size], AC_ARG_WITH(fd-setsize, AS_HELP_STRING([--with-fd-setsize=size],
[Set maximum file descriptor number that can be used by select]), [Set maximum file descriptor number that can be used by select]),
[], [withval="no"]) [], [withval="no"])
@ -931,11 +961,7 @@ case "$withval" in
;; ;;
esac esac
AC_SUBST(GETDNS_QUERY) AC_CONFIG_FILES([Makefile src/Makefile src/version.c src/getdns/getdns.h src/getdns/getdns_extra.h spec/example/Makefile src/test/Makefile src/tools/Makefile doc/Makefile getdns.pc getdns_ext_event.pc])
AC_SUBST(INSTALL_GETDNS_QUERY)
AC_SUBST(UNINSTALL_GETDNS_QUERY)
AC_CONFIG_FILES([Makefile src/Makefile src/version.c src/getdns/getdns.h src/getdns/getdns_extra.h spec/example/Makefile src/test/Makefile doc/Makefile getdns.pc getdns_ext_event.pc])
if [ test -n "$DOXYGEN" ] if [ test -n "$DOXYGEN" ]
then AC_CONFIG_FILES([src/Doxyfile]) then AC_CONFIG_FILES([src/Doxyfile])
fi fi

View File

@ -67,7 +67,7 @@ C99COMPATFLAGS=@C99COMPATFLAGS@
GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \ GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \
list.lo request-internal.lo pubkey-pinning.lo rr-dict.lo \ list.lo request-internal.lo pubkey-pinning.lo rr-dict.lo \
rr-iter.lo stub.lo sync.lo ub_loop.lo util-internal.lo rr-iter.lo server.lo stub.lo sync.lo ub_loop.lo util-internal.lo
GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \ GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \
str2wire.lo str2wire.lo
@ -78,6 +78,8 @@ COMPAT_OBJ=$(LIBOBJS:.o=.lo)
UTIL_OBJ=rbtree.lo val_secalgo.lo UTIL_OBJ=rbtree.lo val_secalgo.lo
JSMN_OBJ=jsmn.lo
EXTENSION_OBJ=default_eventloop.lo libevent.lo libev.lo EXTENSION_OBJ=default_eventloop.lo libevent.lo libev.lo
NON_C99_OBJS=context.lo libuv.lo NON_C99_OBJS=context.lo libuv.lo
@ -106,6 +108,9 @@ $(COMPAT_OBJ):
$(UTIL_OBJ): $(UTIL_OBJ):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WNOERRORFLAG) -c $(srcdir)/util/$(@:.lo=.c) -o $@ $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WNOERRORFLAG) -c $(srcdir)/util/$(@:.lo=.c) -o $@
$(JSMN_OBJ):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -DJSMN_GETDNS -c $(srcdir)/jsmn/$(@:.lo=.c) -o $@
$(EXTENSION_OBJ): $(EXTENSION_OBJ):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -c $(srcdir)/extension/$(@:.lo=.c) -o $@ $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -c $(srcdir)/extension/$(@:.lo=.c) -o $@
@ -146,15 +151,17 @@ libgetdns_ext_ev.la: libgetdns.la libev.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) libgetdns.la: $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ)
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
test: all test: all
cd test && $(MAKE) $@ cd test && $(MAKE) $@
getdns_query: all getdns_query: all
cd test && $(MAKE) $@ cd tools && $(MAKE) $@
stubby: all
cd tools && $(MAKE) $@
scratchpad: all scratchpad: all
cd test && $(MAKE) $@ cd test && $(MAKE) $@
@ -162,11 +169,13 @@ scratchpad: all
pad: scratchpad pad: scratchpad
clean: clean:
cd tools && $(MAKE) $@
cd test && $(MAKE) $@ cd test && $(MAKE) $@
rm -f *.o *.lo extension/*.lo extension/*.o $(PROGRAMS) libgetdns.la libgetdns_ext_*.la rm -f *.o *.lo extension/*.lo extension/*.o $(PROGRAMS) libgetdns.la libgetdns_ext_*.la
rm -rf .libs extension/.libs rm -rf .libs extension/.libs
distclean : clean distclean : clean
cd tools && $(MAKE) $@
cd test && $(MAKE) $@ cd test && $(MAKE) $@
rmdir test 2>/dev/null || true rmdir test 2>/dev/null || true
rm -f Makefile config.status config.log Doxyfile config.h version.c getdns/Makefile getdns/getdns.h getdns/getdns_extra.h rm -f Makefile config.status config.log Doxyfile config.h version.c getdns/Makefile getdns/getdns.h getdns/getdns_extra.h
@ -174,42 +183,17 @@ distclean : clean
rmdir extension 2>/dev/null || true rmdir extension 2>/dev/null || true
rm -Rf autom4te.cache rm -Rf autom4te.cache
$(distdir): FORCE
mkdir -p $(distdir)/src
cp configure.ac $(distdir)
cp configure $(distdir)
cp Makefile.in $(distdir)
cp src/Makefile.in $(distdir)/src
distcheck: $(distdir).tar.gz
gzip -cd $(distdir).tar.gz | tar xvf -
cd $(distdir) && ./configure
cd $(distdir) && $(MAKE) all
cd $(distdir) && $(MAKE) check
cd $(distdir) && $(MAKE) DESTDIR=$${PWD}/_inst install
cd $(distdir) && $(MAKE) DESTDIR=$${PWD}/_inst uninstall
@remaining="`find $${PWD}/$(distdir)/_inst -type f | wc -l`"; \
if test "$${remaining}" -ne 0; then
echo "@@@ $${remaining} file(s) remaining in stage directory!"; \
exit 1; \
fi
cd $(distdir) && $(MAKE) clean
rm -rf $(distdir)
@echo "*** Package $(distdir).tar.gz is ready for distribution"
Makefile: $(srcdir)/Makefile.in ../config.status Makefile: $(srcdir)/Makefile.in ../config.status
cd .. && ./config.status src/Makefile cd .. && ./config.status src/Makefile
configure.status: configure
cd .. && ./config.status --recheck
depend: depend:
(cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new ) (cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new )
(blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" *.c gldns/*.c compat/*.c util/*.c extension/*.c| \ (blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" *.c gldns/*.c compat/*.c util/*.c jsmn/*.c extension/*.c| \
sed -e "s? $$blddir/? ?g" \ sed -e "s? $$blddir/? ?g" \
-e 's?gldns/?$$(srcdir)/gldns/?g' \ -e 's?gldns/?$$(srcdir)/gldns/?g' \
-e 's?compat/?$$(srcdir)/compat/?g' \ -e 's?compat/?$$(srcdir)/compat/?g' \
-e 's?util/?$$(srcdir)/util/?g' \ -e 's?util/?$$(srcdir)/util/?g' \
-e 's?jsmn/?$$(srcdir)/jsmn/?g' \
-e 's?extension/?$$(srcdir)/extension/?g' \ -e 's?extension/?$$(srcdir)/extension/?g' \
-e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \ -e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
-e 's? \$$(srcdir)/config\.h? config.h?g' \ -e 's? \$$(srcdir)/config\.h? config.h?g' \
@ -221,6 +205,7 @@ depend:
-e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' >> Makefile.in.new ) -e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' >> Makefile.in.new )
(cd $(srcdir) ; diff Makefile.in.new Makefile.in && rm Makefile.in.new \ (cd $(srcdir) ; diff Makefile.in.new Makefile.in && rm Makefile.in.new \
|| mv Makefile.in.new Makefile.in ) || mv Makefile.in.new Makefile.in )
cd tools && $(MAKE) $@
cd test && $(MAKE) $@ cd test && $(MAKE) $@
.PHONY: clean test .PHONY: clean test
@ -233,69 +218,78 @@ context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/g
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \
getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h \
$(srcdir)/pubkey-pinning.h
convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \ convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \
getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/convert.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h \
$(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h
dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \ dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \
$(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h \ $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h \
$(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h
dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \ dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h \
$(srcdir)/util/val_secalgo.h $(srcdir)/list.h $(srcdir)/util/val_secalgo.h
general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \ general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \
getdns/getdns_extra.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ getdns/getdns_extra.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \
getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \ getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/list.h $(srcdir)/dict.h
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \ pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \
$(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \ $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \
$(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \
getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h
request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \ request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \
getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
$(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \
getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h
rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \ rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \ $(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \ $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \
getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h
rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h config.h getdns/getdns.h \ rr-iter.lo rr-iter.o: $(srcdir)/rr-iter.c $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h config.h getdns/getdns.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h
server.lo server.o: $(srcdir)/server.c config.h getdns/getdns_extra.h getdns/getdns.h \
$(srcdir)/context.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/debug.h $(srcdir)/server.h
stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \ stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \ $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h \ $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h getdns/getdns_extra.h \ sync.lo sync.o: $(srcdir)/sync.c getdns/getdns.h config.h $(srcdir)/context.h getdns/getdns_extra.h \
getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \ $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/debug.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \ $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \
$(srcdir)/gldns/wire2str.h
ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \ ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/debug.h $(srcdir)/debug.h
util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \ util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \
$(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \ $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \
$(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \ $(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \
getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \ getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h \ $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/rrdef.h
version.lo version.o: version.c version.lo version.o: version.c
@ -327,6 +321,7 @@ rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcd
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h
val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \ val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \
$(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h $(srcdir)/debug.h config.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h
jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h
default_eventloop.lo default_eventloop.o: $(srcdir)/extension/default_eventloop.c config.h \ default_eventloop.lo default_eventloop.o: $(srcdir)/extension/default_eventloop.c config.h \
$(srcdir)/extension/default_eventloop.h getdns/getdns.h getdns/getdns_extra.h \ $(srcdir)/extension/default_eventloop.h getdns/getdns.h getdns/getdns_extra.h \
$(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \ $(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \

View File

@ -123,3 +123,212 @@ getdns_get_errorstr_by_id(uint16_t err)
else else
return NULL; return NULL;
} }
static struct const_name_info consts_name_info[] = {
{ "GETDNS_APPEND_NAME_ALWAYS", 550 },
{ "GETDNS_APPEND_NAME_NEVER", 553 },
{ "GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE", 552 },
{ "GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE", 551 },
{ "GETDNS_APPEND_NAME_TO_SINGLE_LABEL_FIRST", 554 },
{ "GETDNS_AUTHENTICATION_NONE", 1300 },
{ "GETDNS_AUTHENTICATION_REQUIRED", 1301 },
{ "GETDNS_BAD_DNS_ALL_NUMERIC_LABEL", 1101 },
{ "GETDNS_BAD_DNS_CNAME_IN_TARGET", 1100 },
{ "GETDNS_BAD_DNS_CNAME_RETURNED_FOR_OTHER_TYPE", 1102 },
{ "GETDNS_CALLBACK_CANCEL", 701 },
{ "GETDNS_CALLBACK_COMPLETE", 700 },
{ "GETDNS_CALLBACK_ERROR", 703 },
{ "GETDNS_CALLBACK_TIMEOUT", 702 },
{ "GETDNS_CONTEXT_CODE_APPEND_NAME", 607 },
{ "GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW", 614 },
{ "GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS", 609 },
{ "GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS", 604 },
{ "GETDNS_CONTEXT_CODE_DNS_TRANSPORT", 605 },
{ "GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE", 619 },
{ "GETDNS_CONTEXT_CODE_EDNS_DO_BIT", 613 },
{ "GETDNS_CONTEXT_CODE_EDNS_EXTENDED_RCODE", 611 },
{ "GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE", 610 },
{ "GETDNS_CONTEXT_CODE_EDNS_VERSION", 612 },
{ "GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS", 602 },
{ "GETDNS_CONTEXT_CODE_IDLE_TIMEOUT", 617 },
{ "GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES", 606 },
{ "GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS", 615 },
{ "GETDNS_CONTEXT_CODE_NAMESPACES", 600 },
{ "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", 621 },
{ "GETDNS_CONTEXT_CODE_RESOLUTION_TYPE", 601 },
{ "GETDNS_CONTEXT_CODE_SUFFIX", 608 },
{ "GETDNS_CONTEXT_CODE_TIMEOUT", 616 },
{ "GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION", 618 },
{ "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 },
{ "GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS", 603 },
{ "GETDNS_DNSSEC_BOGUS", 401 },
{ "GETDNS_DNSSEC_INDETERMINATE", 402 },
{ "GETDNS_DNSSEC_INSECURE", 403 },
{ "GETDNS_DNSSEC_NOT_PERFORMED", 404 },
{ "GETDNS_DNSSEC_SECURE", 400 },
{ "GETDNS_EXTENSION_FALSE", 1001 },
{ "GETDNS_EXTENSION_TRUE", 1000 },
{ "GETDNS_NAMESPACE_DNS", 500 },
{ "GETDNS_NAMESPACE_LOCALNAMES", 501 },
{ "GETDNS_NAMESPACE_MDNS", 503 },
{ "GETDNS_NAMESPACE_NETBIOS", 502 },
{ "GETDNS_NAMESPACE_NIS", 504 },
{ "GETDNS_NAMETYPE_DNS", 800 },
{ "GETDNS_NAMETYPE_WINS", 801 },
{ "GETDNS_OPCODE_IQUERY", 1 },
{ "GETDNS_OPCODE_NOTIFY", 4 },
{ "GETDNS_OPCODE_QUERY", 0 },
{ "GETDNS_OPCODE_STATUS", 2 },
{ "GETDNS_OPCODE_UPDATE", 5 },
{ "GETDNS_RCODE_BADALG", 21 },
{ "GETDNS_RCODE_BADKEY", 17 },
{ "GETDNS_RCODE_BADMODE", 19 },
{ "GETDNS_RCODE_BADNAME", 20 },
{ "GETDNS_RCODE_BADSIG", 16 },
{ "GETDNS_RCODE_BADTIME", 18 },
{ "GETDNS_RCODE_BADTRUNC", 22 },
{ "GETDNS_RCODE_BADVERS", 16 },
{ "GETDNS_RCODE_FORMERR", 1 },
{ "GETDNS_RCODE_NOERROR", 0 },
{ "GETDNS_RCODE_NOTAUTH", 9 },
{ "GETDNS_RCODE_NOTIMP", 4 },
{ "GETDNS_RCODE_NOTZONE", 10 },
{ "GETDNS_RCODE_NXDOMAIN", 3 },
{ "GETDNS_RCODE_NXRRSET", 8 },
{ "GETDNS_RCODE_REFUSED", 5 },
{ "GETDNS_RCODE_SERVFAIL", 2 },
{ "GETDNS_RCODE_YXDOMAIN", 6 },
{ "GETDNS_RCODE_YXRRSET", 7 },
{ "GETDNS_REDIRECTS_DO_NOT_FOLLOW", 531 },
{ "GETDNS_REDIRECTS_FOLLOW", 530 },
{ "GETDNS_RESOLUTION_RECURSING", 521 },
{ "GETDNS_RESOLUTION_STUB", 520 },
{ "GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS", 904 },
{ "GETDNS_RESPSTATUS_ALL_TIMEOUT", 902 },
{ "GETDNS_RESPSTATUS_GOOD", 900 },
{ "GETDNS_RESPSTATUS_NO_NAME", 901 },
{ "GETDNS_RESPSTATUS_NO_SECURE_ANSWERS", 903 },
{ "GETDNS_RETURN_BAD_CONTEXT", 301 },
{ "GETDNS_RETURN_BAD_DOMAIN_NAME", 300 },
{ "GETDNS_RETURN_CONTEXT_UPDATE_FAIL", 302 },
{ "GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED", 309 },
{ "GETDNS_RETURN_EXTENSION_MISFORMAT", 308 },
{ "GETDNS_RETURN_GENERIC_ERROR", 1 },
{ "GETDNS_RETURN_GOOD", 0 },
{ "GETDNS_RETURN_INVALID_PARAMETER", 311 },
{ "GETDNS_RETURN_MEMORY_ERROR", 310 },
{ "GETDNS_RETURN_NEED_MORE_SPACE", 399 },
{ "GETDNS_RETURN_NOT_IMPLEMENTED", 312 },
{ "GETDNS_RETURN_NO_SUCH_DICT_NAME", 305 },
{ "GETDNS_RETURN_NO_SUCH_EXTENSION", 307 },
{ "GETDNS_RETURN_NO_SUCH_LIST_ITEM", 304 },
{ "GETDNS_RETURN_UNKNOWN_TRANSACTION", 303 },
{ "GETDNS_RETURN_WRONG_TYPE_REQUESTED", 306 },
{ "GETDNS_RRCLASS_ANY", 255 },
{ "GETDNS_RRCLASS_CH", 3 },
{ "GETDNS_RRCLASS_HS", 4 },
{ "GETDNS_RRCLASS_IN", 1 },
{ "GETDNS_RRCLASS_NONE", 254 },
{ "GETDNS_RRTYPE_A", 1 },
{ "GETDNS_RRTYPE_AAAA", 28 },
{ "GETDNS_RRTYPE_AFSDB", 18 },
{ "GETDNS_RRTYPE_ANY", 255 },
{ "GETDNS_RRTYPE_APL", 42 },
{ "GETDNS_RRTYPE_ATMA", 34 },
{ "GETDNS_RRTYPE_AXFR", 252 },
{ "GETDNS_RRTYPE_CAA", 257 },
{ "GETDNS_RRTYPE_CDNSKEY", 60 },
{ "GETDNS_RRTYPE_CDS", 59 },
{ "GETDNS_RRTYPE_CERT", 37 },
{ "GETDNS_RRTYPE_CNAME", 5 },
{ "GETDNS_RRTYPE_CSYNC", 62 },
{ "GETDNS_RRTYPE_DHCID", 49 },
{ "GETDNS_RRTYPE_DLV", 32769 },
{ "GETDNS_RRTYPE_DNAME", 39 },
{ "GETDNS_RRTYPE_DNSKEY", 48 },
{ "GETDNS_RRTYPE_DS", 43 },
{ "GETDNS_RRTYPE_EID", 31 },
{ "GETDNS_RRTYPE_GID", 102 },
{ "GETDNS_RRTYPE_GPOS", 27 },
{ "GETDNS_RRTYPE_HINFO", 13 },
{ "GETDNS_RRTYPE_HIP", 55 },
{ "GETDNS_RRTYPE_IPSECKEY", 45 },
{ "GETDNS_RRTYPE_ISDN", 20 },
{ "GETDNS_RRTYPE_IXFR", 251 },
{ "GETDNS_RRTYPE_KEY", 25 },
{ "GETDNS_RRTYPE_KX", 36 },
{ "GETDNS_RRTYPE_LOC", 29 },
{ "GETDNS_RRTYPE_LP", 107 },
{ "GETDNS_RRTYPE_MAILA", 254 },
{ "GETDNS_RRTYPE_MAILB", 253 },
{ "GETDNS_RRTYPE_MB", 7 },
{ "GETDNS_RRTYPE_MD", 3 },
{ "GETDNS_RRTYPE_MF", 4 },
{ "GETDNS_RRTYPE_MG", 8 },
{ "GETDNS_RRTYPE_MINFO", 14 },
{ "GETDNS_RRTYPE_MR", 9 },
{ "GETDNS_RRTYPE_MX", 15 },
{ "GETDNS_RRTYPE_NAPTR", 35 },
{ "GETDNS_RRTYPE_NID", 104 },
{ "GETDNS_RRTYPE_NIMLOC", 32 },
{ "GETDNS_RRTYPE_NINFO", 56 },
{ "GETDNS_RRTYPE_NS", 2 },
{ "GETDNS_RRTYPE_NSAP", 22 },
{ "GETDNS_RRTYPE_NSEC", 47 },
{ "GETDNS_RRTYPE_NULL", 10 },
{ "GETDNS_RRTYPE_NXT", 30 },
{ "GETDNS_RRTYPE_OPENPGPKEY", 61 },
{ "GETDNS_RRTYPE_OPT", 41 },
{ "GETDNS_RRTYPE_PTR", 12 },
{ "GETDNS_RRTYPE_PX", 26 },
{ "GETDNS_RRTYPE_RKEY", 57 },
{ "GETDNS_RRTYPE_RP", 17 },
{ "GETDNS_RRTYPE_RRSIG", 46 },
{ "GETDNS_RRTYPE_RT", 21 },
{ "GETDNS_RRTYPE_SIG", 24 },
{ "GETDNS_RRTYPE_SINK", 40 },
{ "GETDNS_RRTYPE_SOA", 6 },
{ "GETDNS_RRTYPE_SPF", 99 },
{ "GETDNS_RRTYPE_SRV", 33 },
{ "GETDNS_RRTYPE_SSHFP", 44 },
{ "GETDNS_RRTYPE_TA", 32768 },
{ "GETDNS_RRTYPE_TALINK", 58 },
{ "GETDNS_RRTYPE_TKEY", 249 },
{ "GETDNS_RRTYPE_TLSA", 52 },
{ "GETDNS_RRTYPE_TSIG", 250 },
{ "GETDNS_RRTYPE_TXT", 16 },
{ "GETDNS_RRTYPE_UID", 101 },
{ "GETDNS_RRTYPE_UINFO", 100 },
{ "GETDNS_RRTYPE_UNSPEC", 103 },
{ "GETDNS_RRTYPE_URI", 256 },
{ "GETDNS_RRTYPE_WKS", 11 },
{ "GETDNS_TRANSPORT_TCP", 1201 },
{ "GETDNS_TRANSPORT_TCP_ONLY", 542 },
{ "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", 543 },
{ "GETDNS_TRANSPORT_TLS", 1202 },
{ "GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN", 545 },
{ "GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN", 544 },
{ "GETDNS_TRANSPORT_UDP", 1200 },
{ "GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP", 540 },
{ "GETDNS_TRANSPORT_UDP_ONLY", 541 },
};
static int const_name_info_cmp(const void *a, const void *b)
{
return strcmp( ((struct const_name_info *) a)->name
, ((struct const_name_info *) b)->name );
}
int
_getdns_get_const_name_info(const char *name, uint32_t *code)
{
struct const_name_info key = { name, 0 };
struct const_name_info *i = bsearch(&key, consts_name_info,
sizeof(consts_name_info) / sizeof(struct const_name_info),
sizeof(struct const_name_info), const_name_info_cmp);
if (!i)
return 0;
if (code)
*code = i->code;
return 1;
}

View File

@ -47,6 +47,13 @@ struct const_info {
struct const_info *_getdns_get_const_info(int value); struct const_info *_getdns_get_const_info(int value);
struct const_name_info {
const char *name;
uint32_t code;
};
int _getdns_get_const_name_info(const char *name, uint32_t *code);
#endif #endif
/* const-info.h */ /* const-info.h */

View File

@ -89,6 +89,9 @@ typedef unsigned short in_port_t;
#define GETDNS_STR_PORT_ZERO "0" #define GETDNS_STR_PORT_ZERO "0"
#define GETDNS_STR_PORT_DNS "53" #define GETDNS_STR_PORT_DNS "53"
#define GETDNS_STR_PORT_DNS_OVER_TLS "853" #define GETDNS_STR_PORT_DNS_OVER_TLS "853"
/* How long to wait in seconds before re-trying a connection based backed-off
upstream. Using 1 hour for all transports - based on RFC7858 value for for TLS.*/
#define BACKOFF_RETRY 3600
#ifdef HAVE_PTHREADS #ifdef HAVE_PTHREADS
static pthread_mutex_t ssl_init_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t ssl_init_lock = PTHREAD_MUTEX_INITIALIZER;
@ -234,6 +237,25 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
} }
#endif #endif
#if !defined(STUB_NATIVE_DNSSEC) || (defined(DAEMON_DEBUG) && DAEMON_DEBUG)
static uint8_t*
upstream_addr(getdns_upstream *upstream)
{
return upstream->addr.ss_family == AF_INET
? (void *)&((struct sockaddr_in*)&upstream->addr)->sin_addr
: (void *)&((struct sockaddr_in6*)&upstream->addr)->sin6_addr;
}
#endif
static in_port_t
upstream_port(getdns_upstream *upstream)
{
return ntohs(upstream->addr.ss_family == AF_INET
? ((struct sockaddr_in *)&upstream->addr)->sin_port
: ((struct sockaddr_in6*)&upstream->addr)->sin6_port);
}
static void destroy_local_host(_getdns_rbnode_t * node, void *arg) static void destroy_local_host(_getdns_rbnode_t * node, void *arg)
{ {
getdns_context *context = (getdns_context *)arg; getdns_context *context = (getdns_context *)arg;
@ -274,7 +296,6 @@ create_default_dns_transports(struct getdns_context *context)
context->dns_transports[0] = GETDNS_TRANSPORT_UDP; context->dns_transports[0] = GETDNS_TRANSPORT_UDP;
context->dns_transports[1] = GETDNS_TRANSPORT_TCP; context->dns_transports[1] = GETDNS_TRANSPORT_TCP;
context->dns_transport_count = 2; context->dns_transport_count = 2;
context->dns_transport_current = 0;
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
@ -626,7 +647,7 @@ upstreams_create(getdns_context *context, size_t size)
r->mf = context->mf; r->mf = context->mf;
r->referenced = 1; r->referenced = 1;
r->count = 0; r->count = 0;
r->current = 0; r->current_udp = 0;
return r; return r;
} }
@ -688,48 +709,89 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
GETDNS_FREE(upstreams->mf, upstreams); GETDNS_FREE(upstreams->mf, upstreams);
} }
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
static char*
getdns_auth_str_array[] = {
GETDNS_STR_AUTH_NONE,
GETDNS_STR_AUTH_FAILED,
GETDNS_STR_AUTH_OK
};
#endif
void void
_getdns_upstream_shutdown(getdns_upstream *upstream) _getdns_upstream_shutdown(getdns_upstream *upstream)
{ {
/*There is a race condition with a new request being scheduled /*Set condition to tear down asap to stop any further scheduling*/
while this happens so take ownership of the fd asap*/ upstream->conn_state = GETDNS_CONN_TEARDOWN;
int fd = upstream->fd; /* Update total stats for the upstream.*/
upstream->fd = -1; upstream->total_responses+=upstream->responses_received;
/* If the connection had a problem, but had worked this time, upstream->total_timeouts+=upstream->responses_timeouts;
* then allow re-use in the future*/ /* Need the last auth state when using session resumption*/
if (upstream->tcp.write_error == 1 && upstream->last_tls_auth_state = upstream->tls_auth_state;
upstream->responses_received > 0) /* Keep track of the best auth state this upstream has had*/
upstream->tcp.write_error = 0; if (upstream->tls_auth_state > upstream->best_tls_auth_state)
upstream->writes_done = 0; upstream->best_tls_auth_state = upstream->tls_auth_state;
upstream->responses_received = 0; #if defined(DAEMON_DEBUG) && DAEMON_DEBUG
upstream->keepalive_timeout = 0; DEBUG_DAEMON("%s %s : Conn closed : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n",
if (upstream->tls_hs_state != GETDNS_HS_FAILED) { STUB_DEBUG_DAEMON, upstream->addr_str,
upstream->tls_hs_state = GETDNS_HS_NONE; (upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
upstream->tls_auth_failed = 0; (int)upstream->responses_received, (int)upstream->responses_timeouts,
_getdns_auth_str(upstream->tls_auth_state), (int)upstream->keepalive_timeout);
DEBUG_DAEMON("%s %s : Upstream stats: Transport=%s - Resp=%d,Timeouts=%d,Best_auth=%s\n",
STUB_DEBUG_DAEMON, upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->total_responses, (int)upstream->total_timeouts,
_getdns_auth_str(upstream->best_tls_auth_state));
DEBUG_DAEMON("%s %s : Upstream stats: Transport=%s - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n",
STUB_DEBUG_DAEMON, upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->conn_completed, (int)upstream->conn_setup_failed,
(int)upstream->conn_shutdowns, (int)upstream->conn_backoffs);
#endif
/* Back off connections that never got up service at all (probably no
TCP service or incompatible TLS version/cipher).
Leave choice between working upstreams to the stub.
This back-off should be time based for TLS according to RFC7858. For now,
use the same basis if we simply can't get TCP service either.*/
/* [TLS1]TODO: This arbitrary logic at the moment - review and improve!*/
if (upstream->conn_setup_failed >= GETDNS_CONN_ATTEMPTS ||
(upstream->conn_shutdowns >= GETDNS_CONN_ATTEMPTS*GETDNS_TRANSPORT_FAIL_MULT
&& upstream->total_responses == 0) ||
(upstream->conn_completed >= GETDNS_CONN_ATTEMPTS &&
upstream->total_responses == 0 &&
upstream->total_timeouts > GETDNS_TRANSPORT_FAIL_MULT)) {
upstream->conn_state = GETDNS_CONN_BACKOFF;
upstream->conn_retry_time = time(NULL) + BACKOFF_RETRY;
upstream->total_responses = 0;
upstream->total_timeouts = 0;
upstream->conn_completed = 0;
upstream->conn_setup_failed = 0;
upstream->conn_shutdowns = 0;
upstream->conn_backoffs++;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %s : !Backing off this upstream - Will retry as new upstream at %s",
STUB_DEBUG_DAEMON, upstream->addr_str,
asctime(gmtime(&upstream->conn_retry_time)));
#endif
} }
// Reset per connection counters
upstream->queries_sent = 0;
upstream->responses_received = 0;
upstream->responses_timeouts = 0;
upstream->keepalive_timeout = 0;
upstream->keepalive_shutdown = 0;
/* Now TLS stuff*/ /* Now TLS stuff*/
upstream->tls_auth_state = GETDNS_AUTH_NONE;
if (upstream->tls_obj != NULL) { if (upstream->tls_obj != NULL) {
SSL_shutdown(upstream->tls_obj); SSL_shutdown(upstream->tls_obj);
SSL_free(upstream->tls_obj); SSL_free(upstream->tls_obj);
upstream->tls_obj = NULL; upstream->tls_obj = NULL;
} }
if (fd != -1) if (upstream->fd != -1) {
{
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
closesocket(fd); closesocket(upstream->fd);
#else #else
close(fd); close(upstream->fd);
#endif #endif
upstream->fd = -1;
} }
/* Set connection ready for use again*/
if (upstream->conn_state != GETDNS_CONN_BACKOFF)
upstream->conn_state = GETDNS_CONN_CLOSED;
} }
static int static int
@ -835,13 +897,30 @@ upstream_init(getdns_upstream *upstream,
upstream->addr_len = ai->ai_addrlen; upstream->addr_len = ai->ai_addrlen;
(void) memcpy(&upstream->addr, ai->ai_addr, ai->ai_addrlen); (void) memcpy(&upstream->addr, ai->ai_addr, ai->ai_addrlen);
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
inet_ntop(upstream->addr.ss_family, upstream_addr(upstream),
upstream->addr_str, INET6_ADDRSTRLEN);
#endif
/* How is this upstream doing? */ /* How is this upstream doing on connections? */
upstream->writes_done = 0; upstream->conn_completed = 0;
upstream->conn_shutdowns = 0;
upstream->conn_setup_failed = 0;
upstream->conn_retry_time = 0;
upstream->conn_backoffs = 0;
upstream->total_responses = 0;
upstream->total_timeouts = 0;
upstream->conn_state = GETDNS_CONN_CLOSED;
upstream->queries_sent = 0;
upstream->responses_received = 0; upstream->responses_received = 0;
upstream->responses_timeouts = 0;
upstream->keepalive_shutdown = 0;
upstream->keepalive_timeout = 0; upstream->keepalive_timeout = 0;
/* How is this upstream doing on UDP? */
upstream->to_retry = 2; upstream->to_retry = 2;
upstream->back_off = 1; upstream->back_off = 1;
upstream->udp_responses = 0;
upstream->udp_timeouts = 0;
/* For sharing a socket to this upstream with TCP */ /* For sharing a socket to this upstream with TCP */
upstream->fd = -1; upstream->fd = -1;
@ -849,10 +928,11 @@ upstream_init(getdns_upstream *upstream,
upstream->tls_session = NULL; upstream->tls_session = NULL;
upstream->transport = GETDNS_TRANSPORT_TCP; upstream->transport = GETDNS_TRANSPORT_TCP;
upstream->tls_hs_state = GETDNS_HS_NONE; upstream->tls_hs_state = GETDNS_HS_NONE;
upstream->tls_auth_failed = 0;
upstream->tls_auth_name[0] = '\0'; upstream->tls_auth_name[0] = '\0';
upstream->tls_auth_state = GETDNS_AUTH_NONE;
upstream->last_tls_auth_state = GETDNS_AUTH_NONE;
upstream->best_tls_auth_state = GETDNS_AUTH_NONE;
upstream->tls_pubkey_pinset = NULL; upstream->tls_pubkey_pinset = NULL;
upstream->tcp.write_error = 0;
upstream->loop = NULL; upstream->loop = NULL;
(void) getdns_eventloop_event_init( (void) getdns_eventloop_event_init(
&upstream->event, upstream, NULL, NULL, NULL); &upstream->event, upstream, NULL, NULL, NULL);
@ -1253,6 +1333,8 @@ getdns_context_create_with_extended_memory_functions(
_getdns_rbtree_init(&result->outbound_requests, transaction_id_cmp); _getdns_rbtree_init(&result->outbound_requests, transaction_id_cmp);
_getdns_rbtree_init(&result->local_hosts, local_host_cmp); _getdns_rbtree_init(&result->local_hosts, local_host_cmp);
result->server = NULL;
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
result->resolution_type = GETDNS_RESOLUTION_RECURSING; result->resolution_type = GETDNS_RESOLUTION_RECURSING;
#else #else
@ -1309,6 +1391,27 @@ getdns_context_create_with_extended_memory_functions(
_getdns_default_eventloop_init(&result->default_eventloop); _getdns_default_eventloop_init(&result->default_eventloop);
_getdns_default_eventloop_init(&result->sync_eventloop); _getdns_default_eventloop_init(&result->sync_eventloop);
/* request extension defaults
*/
result->header = NULL;
result->add_opt_parameters = NULL;
result->add_warning_for_bad_dns = 0;
result->dnssec_return_all_statuses = 0;
result->dnssec_return_full_validation_chain = 0;
result->dnssec_return_only_secure = 0;
result->dnssec_return_status = 0;
result->dnssec_return_validation_chain = 0;
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE
result->dnssec_roadblock_avoidance = 0;
#endif
result->edns_cookies = 0;
result->return_api_information = 0;
result->return_both_v4_and_v6 = 0;
result->return_call_reporting = 0;
result->specify_class = GETDNS_RRCLASS_IN;
/* state data used to detect changes to the system config files
*/
result->fchg_resolvconf = NULL; result->fchg_resolvconf = NULL;
result->fchg_hosts = NULL; result->fchg_hosts = NULL;
@ -1328,7 +1431,6 @@ getdns_context_create_with_extended_memory_functions(
result->tls_auth = GETDNS_AUTHENTICATION_NONE; result->tls_auth = GETDNS_AUTHENTICATION_NONE;
result->tls_auth_min = GETDNS_AUTHENTICATION_NONE; result->tls_auth_min = GETDNS_AUTHENTICATION_NONE;
result->limit_outstanding_queries = 0; result->limit_outstanding_queries = 0;
result->return_dnssec_status = GETDNS_EXTENSION_FALSE;
/* unbound context is initialized here */ /* unbound context is initialized here */
/* Unbound needs SSL to be init'ed this early when TLS is used. However we /* Unbound needs SSL to be init'ed this early when TLS is used. However we
@ -1421,6 +1523,9 @@ getdns_context_destroy(struct getdns_context *context)
/* cancel all outstanding requests */ /* cancel all outstanding requests */
cancel_outstanding_requests(context, 1); cancel_outstanding_requests(context, 1);
/* Destroy listening addresses */
(void) getdns_context_set_listen_addresses(context, NULL, NULL, NULL);
/* This needs to be done before cleaning the extension, because there /* This needs to be done before cleaning the extension, because there
* might be an idle_timeout schedules, which will not get unscheduled * might be an idle_timeout schedules, which will not get unscheduled
* with cancel_outstanding_requests. * with cancel_outstanding_requests.
@ -1453,7 +1558,6 @@ getdns_context_destroy(struct getdns_context *context)
if (context->tls_ctx) if (context->tls_ctx)
SSL_CTX_free(context->tls_ctx); SSL_CTX_free(context->tls_ctx);
if (context->dns_root_servers)
getdns_list_destroy(context->dns_root_servers); getdns_list_destroy(context->dns_root_servers);
#if defined(HAVE_LIBUNBOUND) && !defined(HAVE_UB_CTX_SET_STUB) #if defined(HAVE_LIBUNBOUND) && !defined(HAVE_UB_CTX_SET_STUB)
@ -1471,6 +1575,10 @@ getdns_context_destroy(struct getdns_context *context)
_getdns_traverse_postorder(&context->local_hosts, _getdns_traverse_postorder(&context->local_hosts,
destroy_local_host, context); destroy_local_host, context);
getdns_dict_destroy(context->header);
getdns_dict_destroy(context->add_opt_parameters);
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
WSACleanup(); WSACleanup();
#endif #endif
@ -2833,22 +2941,8 @@ getdns_cancel_callback(getdns_context *context,
return r; return r;
} /* getdns_cancel_callback */ } /* getdns_cancel_callback */
#ifndef STUB_NATIVE_DNSSEC
static uint8_t*
upstream_addr(getdns_upstream *upstream)
{
return upstream->addr.ss_family == AF_INET
? (void *)&((struct sockaddr_in*)&upstream->addr)->sin_addr
: (void *)&((struct sockaddr_in6*)&upstream->addr)->sin6_addr;
}
static in_port_t #ifndef STUB_NATIVE_DNSSEC
upstream_port(getdns_upstream *upstream)
{
return ntohs(upstream->addr.ss_family == AF_INET
? ((struct sockaddr_in *)&upstream->addr)->sin_port
: ((struct sockaddr_in6*)&upstream->addr)->sin6_port);
}
static uint32_t * static uint32_t *
upstream_scope_id(getdns_upstream *upstream) upstream_scope_id(getdns_upstream *upstream)
@ -3344,14 +3438,6 @@ getdns_context_get_eventloop(getdns_context *context, getdns_eventloop **loop)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
static in_port_t
upstream_port(getdns_upstream *upstream)
{
return ntohs(upstream->addr.ss_family == AF_INET
? ((struct sockaddr_in *)&upstream->addr)->sin_port
: ((struct sockaddr_in6*)&upstream->addr)->sin6_port);
}
static getdns_dict* static getdns_dict*
_get_context_settings(getdns_context* context) _get_context_settings(getdns_context* context)
{ {
@ -3480,7 +3566,7 @@ getdns_context_set_return_dnssec_status(getdns_context* context, int enabled) {
enabled != GETDNS_EXTENSION_FALSE) { enabled != GETDNS_EXTENSION_FALSE) {
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
} }
context->return_dnssec_status = enabled; context->dnssec_return_status = enabled == GETDNS_EXTENSION_TRUE;
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
@ -3954,4 +4040,209 @@ getdns_context_get_tls_query_padding_blocksize(getdns_context *context, uint16_t
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
static int _streq(const getdns_bindata *name, const char *str)
{
if (strlen(str) != name->size)
return 0;
else return strncmp((const char *)name->data, str, name->size) == 0;
}
static getdns_return_t _get_list_or_read_file(const getdns_dict *config_dict,
const char *setting, getdns_list **r_list, int *destroy_list)
{
getdns_bindata *fn_bd;
char fn[FILENAME_MAX];
FILE *fh;
getdns_return_t r;
assert(r_list);
assert(destroy_list);
*destroy_list = 0;
if (!(r = getdns_dict_get_list(config_dict, setting, r_list)))
return GETDNS_RETURN_GOOD;
else if ((r = getdns_dict_get_bindata(config_dict, setting, &fn_bd)))
return r;
else if (fn_bd->size >= FILENAME_MAX)
return GETDNS_RETURN_INVALID_PARAMETER;
(void)memcpy(fn, fn_bd->data, fn_bd->size);
fn[fn_bd->size] = 0;
if (!(fh = fopen(fn, "r")))
return GETDNS_RETURN_GENERIC_ERROR;
if (!(r = getdns_fp2rr_list(fh, r_list, NULL, 3600)))
*destroy_list = 1;
fclose(fh);
return r;
}
#define CONTEXT_SETTING_INT(X) \
} else if (_streq(setting, #X)) { \
if (!(r = getdns_dict_get_int(config_dict, #X , &n))) \
r = getdns_context_set_ ## X (context, n);
#define CONTEXT_SETTING_LIST(X) \
} else if (_streq(setting, #X)) { \
if (!(r = getdns_dict_get_list(config_dict, #X , &list))) \
r = getdns_context_set_ ## X (context, list);
#define CONTEXT_SETTING_LIST_OR_ZONEFILE(X) \
} else if (_streq(setting, #X)) { \
if (!(r = _get_list_or_read_file( \
config_dict, #X , &list, &destroy_list))) \
r = getdns_context_set_ ## X(context, list); \
if (destroy_list) getdns_list_destroy(list);
#define CONTEXT_SETTING_ARRAY(X, T) \
} else if (_streq(setting, #X )) { \
if (!(r = getdns_dict_get_list(config_dict, #X , &list)) && \
!(r = getdns_list_get_length(list, &count))) { \
for (i=0; i<count && i<(sizeof(X)/sizeof(*X)); i++) { \
if ((r = getdns_list_get_int(list, i, &n))) \
break; \
X[i] = (getdns_ ## T ## _t)n; \
} \
r = getdns_context_set_ ##X (context, count, X); \
}
#define EXTENSION_SETTING_BOOL(X) \
} else if (_streq(setting, #X )) { \
if (!(r = getdns_dict_get_int(config_dict, #X , &n))) { \
if (n == GETDNS_EXTENSION_TRUE) context->X = 1; \
else if (n == GETDNS_EXTENSION_FALSE) context->X = 0; \
else r = GETDNS_RETURN_INVALID_PARAMETER; \
}
static getdns_return_t
_getdns_context_config_setting(getdns_context *context,
const getdns_dict *config_dict, const getdns_bindata *setting)
{
getdns_return_t r = GETDNS_RETURN_GOOD;
getdns_dict *dict;
getdns_list *list;
getdns_namespace_t namespaces[100];
getdns_transport_list_t dns_transport_list[100];
size_t count, i;
uint32_t n;
int destroy_list = 0;
if (_streq(setting, "all_context")) {
if (!(r = getdns_dict_get_dict(config_dict, "all_context", &dict)))
r = getdns_context_config(context, dict);
CONTEXT_SETTING_INT(resolution_type)
CONTEXT_SETTING_ARRAY(namespaces, namespace)
CONTEXT_SETTING_INT(dns_transport)
CONTEXT_SETTING_ARRAY(dns_transport_list, transport_list)
CONTEXT_SETTING_INT(idle_timeout)
CONTEXT_SETTING_INT(limit_outstanding_queries)
CONTEXT_SETTING_INT(timeout)
CONTEXT_SETTING_INT(follow_redirects)
CONTEXT_SETTING_LIST_OR_ZONEFILE(dns_root_servers)
CONTEXT_SETTING_INT(append_name)
CONTEXT_SETTING_LIST(suffix)
CONTEXT_SETTING_LIST_OR_ZONEFILE(dnssec_trust_anchors)
CONTEXT_SETTING_INT(dnssec_allowed_skew)
CONTEXT_SETTING_LIST(upstream_recursive_servers)
CONTEXT_SETTING_INT(edns_maximum_udp_payload_size)
CONTEXT_SETTING_INT(edns_extended_rcode)
CONTEXT_SETTING_INT(edns_version)
CONTEXT_SETTING_INT(edns_do_bit)
/***************************************/
/**** ****/
/**** Unofficial context settings ****/
/**** ****/
/***************************************/
CONTEXT_SETTING_INT(edns_client_subnet_private)
CONTEXT_SETTING_INT(tls_authentication)
CONTEXT_SETTING_INT(tls_query_padding_blocksize)
/**************************************/
/**** ****/
/**** Default extensions setting ****/
/**** ****/
/**************************************/
EXTENSION_SETTING_BOOL(add_warning_for_bad_dns)
EXTENSION_SETTING_BOOL(dnssec_return_all_statuses)
EXTENSION_SETTING_BOOL(dnssec_return_full_validation_chain)
EXTENSION_SETTING_BOOL(dnssec_return_only_secure)
EXTENSION_SETTING_BOOL(dnssec_return_status)
EXTENSION_SETTING_BOOL(dnssec_return_validation_chain)
#if defined(DNSSEC_ROADBLOCK_AVOIDANCE) && defined(HAVE_LIBUNBOUND)
EXTENSION_SETTING_BOOL(dnssec_roadblock_avoidance)
#endif
#ifdef EDNS_COOKIES
EXTENSION_SETTING_BOOL(edns_cookies)
#endif
EXTENSION_SETTING_BOOL(return_api_information)
EXTENSION_SETTING_BOOL(return_both_v4_and_v6)
EXTENSION_SETTING_BOOL(return_call_reporting)
} else if (_streq(setting, "add_opt_parameters")) {
if (!(r = getdns_dict_get_dict(config_dict, "add_opt_parameters" , &dict))) {
if (context->add_opt_parameters)
getdns_dict_destroy(context->add_opt_parameters);
context->add_opt_parameters = NULL;
r = _getdns_dict_copy(dict, &context->add_opt_parameters);
}
} else if (_streq(setting, "header")) {
if (!(r = getdns_dict_get_dict(config_dict, "header" , &dict))) {
if (context->header)
getdns_dict_destroy(context->header);
if (!(context->header =
getdns_dict_create_with_context(context)))
r = GETDNS_RETURN_MEMORY_ERROR;
else r = getdns_dict_set_dict(
context->header, "header", dict);
}
} else if (_streq(setting, "specify_class")) {
if (!(r = getdns_dict_get_int(
config_dict, "specify_class" , &n)))
context->specify_class = (uint16_t)n;
/************************************/
/**** ****/
/**** Ignored context settings ****/
/**** ****/
/************************************/
} else if (!_streq(setting, "implementation_string") &&
!_streq(setting, "version_string")) {
r = GETDNS_RETURN_NOT_IMPLEMENTED;
}
return r;
}
getdns_return_t
getdns_context_config(getdns_context *context, const getdns_dict *config_dict)
{
getdns_list *settings;
getdns_return_t r;
getdns_bindata *setting;
size_t i;
if ((r = getdns_dict_get_names(config_dict, &settings)))
return r;
for (i = 0; !(r = getdns_list_get_bindata(settings,i,&setting)); i++) {
if ((r = _getdns_context_config_setting(
context, config_dict, setting)))
break;
}
if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM)
r = GETDNS_RETURN_GOOD;
getdns_list_destroy(settings);
return r;
}
/* context.c */ /* context.c */

View File

@ -44,6 +44,7 @@
#include "extension/default_eventloop.h" #include "extension/default_eventloop.h"
#include "util/rbtree.h" #include "util/rbtree.h"
#include "ub_loop.h" #include "ub_loop.h"
#include "server.h"
struct getdns_dns_req; struct getdns_dns_req;
struct ub_ctx; struct ub_ctx;
@ -80,6 +81,14 @@ typedef enum getdns_tls_hs_state {
GETDNS_HS_FAILED GETDNS_HS_FAILED
} getdns_tls_hs_state_t; } getdns_tls_hs_state_t;
typedef enum getdns_conn_state {
GETDNS_CONN_CLOSED,
GETDNS_CONN_SETUP,
GETDNS_CONN_OPEN,
GETDNS_CONN_TEARDOWN,
GETDNS_CONN_BACKOFF
} getdns_conn_state_t;
typedef enum getdns_tsig_algo { typedef enum getdns_tsig_algo {
GETDNS_NO_TSIG = 0, /* Do not use tsig */ GETDNS_NO_TSIG = 0, /* Do not use tsig */
GETDNS_HMAC_MD5 = 1, /* 128 bits */ GETDNS_HMAC_MD5 = 1, /* 128 bits */
@ -115,32 +124,56 @@ typedef struct getdns_upstream {
socklen_t addr_len; socklen_t addr_len;
struct sockaddr_storage addr; struct sockaddr_storage addr;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
char addr_str[INET6_ADDRSTRLEN];
#endif
/* How is this upstream doing? */ /* How is this upstream doing over UDP? */
size_t writes_done;
size_t responses_received;
uint64_t keepalive_timeout;
int to_retry; int to_retry;
int back_off; int back_off;
size_t udp_responses;
size_t udp_timeouts;
/* For sharing a TCP socket to this upstream */ /* For stateful upstreams, need to share the connection and track the
activity on the connection */
int fd; int fd;
getdns_transport_list_t transport; getdns_transport_list_t transport;
SSL* tls_obj;
SSL_SESSION* tls_session;
getdns_tls_hs_state_t tls_hs_state;
getdns_eventloop_event event; getdns_eventloop_event event;
getdns_eventloop *loop; getdns_eventloop *loop;
getdns_tcp_state tcp; getdns_tcp_state tcp;
char tls_auth_name[256]; /* These are running totals or historical info */
size_t tls_auth_failed; size_t conn_completed;
sha256_pin_t *tls_pubkey_pinset; size_t conn_shutdowns;
size_t conn_setup_failed;
time_t conn_retry_time;
size_t conn_backoffs;
size_t total_responses;
size_t total_timeouts;
getdns_auth_state_t best_tls_auth_state;
getdns_auth_state_t last_tls_auth_state;
/* These are per connection. */
getdns_conn_state_t conn_state;
size_t queries_sent;
size_t responses_received;
size_t responses_timeouts;
size_t keepalive_shutdown;
uint64_t keepalive_timeout;
/* Pipelining of TCP network requests */ /* Management of outstanding requests on stateful transports */
getdns_network_req *write_queue; getdns_network_req *write_queue;
getdns_network_req *write_queue_last; getdns_network_req *write_queue_last;
_getdns_rbtree_t netreq_by_query_id; _getdns_rbtree_t netreq_by_query_id;
/* TLS specific connection handling*/
SSL* tls_obj;
SSL_SESSION* tls_session;
getdns_tls_hs_state_t tls_hs_state;
getdns_auth_state_t tls_auth_state;
unsigned tls_fallback_ok : 1;
/* Auth credentials*/
char tls_auth_name[256];
sha256_pin_t *tls_pubkey_pinset;
/* When requests have been scheduled asynchronously on an upstream /* When requests have been scheduled asynchronously on an upstream
* that is kept open, and a synchronous call is then done with the * that is kept open, and a synchronous call is then done with the
* upstream before all scheduled requests have been answered, answers * upstream before all scheduled requests have been answered, answers
@ -157,6 +190,7 @@ typedef struct getdns_upstream {
*/ */
getdns_dns_req *finished_dnsreqs; getdns_dns_req *finished_dnsreqs;
getdns_eventloop_event finished_event; getdns_eventloop_event finished_event;
unsigned is_sync_loop : 1;
/* EDNS cookies */ /* EDNS cookies */
uint32_t secret; uint32_t secret;
@ -168,8 +202,6 @@ typedef struct getdns_upstream {
unsigned has_prev_client_cookie : 1; unsigned has_prev_client_cookie : 1;
unsigned has_server_cookie : 1; unsigned has_server_cookie : 1;
unsigned server_cookie_len : 5; unsigned server_cookie_len : 5;
unsigned tls_fallback_ok : 1;
unsigned is_sync_loop : 1;
/* TSIG */ /* TSIG */
uint8_t tsig_dname[256]; uint8_t tsig_dname[256];
@ -184,7 +216,7 @@ typedef struct getdns_upstreams {
struct mem_funcs mf; struct mem_funcs mf;
size_t referenced; size_t referenced;
size_t count; size_t count;
size_t current; size_t current_udp;
getdns_upstream upstreams[]; getdns_upstream upstreams[];
} getdns_upstreams; } getdns_upstreams;
@ -219,7 +251,6 @@ struct getdns_context {
getdns_transport_list_t *dns_transports; getdns_transport_list_t *dns_transports;
size_t dns_transport_count; size_t dns_transport_count;
size_t dns_transport_current;
uint8_t edns_extended_rcode; uint8_t edns_extended_rcode;
uint8_t edns_version; uint8_t edns_version;
@ -250,8 +281,6 @@ struct getdns_context {
/* A tree to hold local host information*/ /* A tree to hold local host information*/
_getdns_rbtree_t local_hosts; _getdns_rbtree_t local_hosts;
int return_dnssec_status;
/* which resolution type the contexts are configured for /* which resolution type the contexts are configured for
* 0 means nothing set * 0 means nothing set
*/ */
@ -262,6 +291,8 @@ struct getdns_context {
*/ */
_getdns_rbtree_t outbound_requests; _getdns_rbtree_t outbound_requests;
struct listen_set *server;
/* Event loop extension. */ /* Event loop extension. */
getdns_eventloop *extension; getdns_eventloop *extension;
@ -275,6 +306,24 @@ struct getdns_context {
_getdns_default_eventloop default_eventloop; _getdns_default_eventloop default_eventloop;
_getdns_default_eventloop sync_eventloop; _getdns_default_eventloop sync_eventloop;
/* request extension defaults */
getdns_dict *header;
getdns_dict *add_opt_parameters;
unsigned add_warning_for_bad_dns : 1;
unsigned dnssec_return_all_statuses : 1;
unsigned dnssec_return_full_validation_chain : 1;
unsigned dnssec_return_only_secure : 1;
unsigned dnssec_return_status : 1;
unsigned dnssec_return_validation_chain : 1;
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE
unsigned dnssec_roadblock_avoidance : 1;
#endif
unsigned edns_cookies : 1;
unsigned return_api_information : 1; /* Not used */
unsigned return_both_v4_and_v6 : 1;
unsigned return_call_reporting : 1;
uint16_t specify_class;
/* /*
* state data used to detect changes to the system config files * state data used to detect changes to the system config files
*/ */

View File

@ -48,8 +48,12 @@
#include "util-internal.h" #include "util-internal.h"
#include "gldns/wire2str.h" #include "gldns/wire2str.h"
#include "gldns/str2wire.h" #include "gldns/str2wire.h"
#include "gldns/parseutil.h"
#include "const-info.h"
#include "types-internal.h" /* For getdns_item */
#include "dict.h" #include "dict.h"
#include "list.h" #include "list.h"
#include "jsmn/jsmn.h"
#include "convert.h" #include "convert.h"
#include "debug.h" #include "debug.h"
@ -834,7 +838,6 @@ _getdns_reply_dict2wire(
} }
} }
remove_dnssec = !getdns_dict_get_int(reply, "/header/do", &n) && n == 0; remove_dnssec = !getdns_dict_get_int(reply, "/header/do", &n) && n == 0;
DEBUG_SERVER("remove_dnssec: %d\n", remove_dnssec);
if (!getdns_dict_get_list(reply, "answer", &section)) { if (!getdns_dict_get_list(reply, "answer", &section)) {
for ( n = 0, i = 0 for ( n = 0, i = 0
@ -1069,5 +1072,673 @@ getdns_msg_dict2str_scan(
return r; return r;
} }
static getdns_dict *
_getdns_ipaddr_dict_mf(struct mem_funcs *mf, const char *ipstr)
{
getdns_dict *r = _getdns_dict_create_with_mf(mf);
char *s = strchr(ipstr, '%'), *scope_id_str = "";
char *p = strchr(ipstr, '@'), *portstr = "";
char *t = strchr(ipstr, '#'), *tls_portstr = "";
char *n = strchr(ipstr, '~'), *tls_namestr = "";
/* ^[alg:]name:key */
char *T = strchr(ipstr, '^'), *tsig_name_str = ""
, *tsig_secret_str = ""
, *tsig_algorithm_str = "";
char *br, *c;
int tsig_secret_size;
uint8_t tsig_secret_buf[256]; /* 4 times SHA512 */
getdns_bindata tsig_secret;
uint8_t buf[sizeof(struct in6_addr)];
getdns_bindata addr;
addr.data = buf;
if (!r) return NULL;
if (*ipstr == '[') {
char *br = strchr(ipstr, ']');
if (br) {
ipstr += 1;
*br = 0;
if ((c = strchr(br + 1, ':'))) {
p = c;
}
}
} else if ((br = strchr(ipstr, '.')) && (c = strchr(br + 1, ':'))
&& (T == NULL || c < T))
p = c;
else if ((*ipstr == '*') && (c = strchr(ipstr+1, ':')))
p = c;
if (s) {
*s = 0;
scope_id_str = s + 1;
}
if (p) {
*p = 0;
portstr = p + 1;
}
if (t) {
*t = 0;
tls_portstr = t + 1;
}
if (n) {
*n = 0;
tls_namestr = n + 1;
}
if (T) {
*T = 0;
tsig_name_str = T + 1;
if ((T = strchr(tsig_name_str, ':'))) {
*T = 0;
tsig_secret_str = T + 1;
if ((T = strchr(tsig_secret_str, ':'))) {
*T = 0;
tsig_algorithm_str = tsig_name_str;
tsig_name_str = tsig_secret_str;
tsig_secret_str = T + 1;
}
} else {
tsig_name_str = "";
}
}
if (*ipstr == '*') {
getdns_dict_util_set_string(r, "address_type", "IPv6");
addr.size = 16;
(void) memset(buf, 0, 16);
} else if (strchr(ipstr, ':')) {
getdns_dict_util_set_string(r, "address_type", "IPv6");
addr.size = 16;
if (inet_pton(AF_INET6, ipstr, buf) <= 0) {
getdns_dict_destroy(r);
return NULL;
}
} else {
getdns_dict_util_set_string(r, "address_type", "IPv4");
addr.size = 4;
if (inet_pton(AF_INET, ipstr, buf) <= 0) {
getdns_dict_destroy(r);
return NULL;
}
}
getdns_dict_set_bindata(r, "address_data", &addr);
if (*portstr)
getdns_dict_set_int(r, "port", (int32_t)atoi(portstr));
if (*tls_portstr)
getdns_dict_set_int(r, "tls_port", (int32_t)atoi(tls_portstr));
if (*tls_namestr) {
getdns_dict_util_set_string(r, "tls_auth_name", tls_namestr);
}
if (*scope_id_str)
getdns_dict_util_set_string(r, "scope_id", scope_id_str);
if (*tsig_name_str)
getdns_dict_util_set_string(r, "tsig_name", tsig_name_str);
if (*tsig_algorithm_str)
getdns_dict_util_set_string(r, "tsig_algorithm", tsig_algorithm_str);
if (*tsig_secret_str) {
tsig_secret_size = gldns_b64_pton(
tsig_secret_str, tsig_secret_buf, sizeof(tsig_secret_buf));
if (tsig_secret_size > 0) {
tsig_secret.size = tsig_secret_size;
tsig_secret.data = tsig_secret_buf;
getdns_dict_set_bindata(r, "tsig_secret", &tsig_secret);
}
}
return r;
}
static int _jsmn_get_ipdict(struct mem_funcs *mf, const char *js, jsmntok_t *t,
getdns_dict **value)
{
char value_str[3072];
int size = t->end - t->start;
if (size <= 0 || size >= (int)sizeof(value_str))
return 0;
(void) memcpy(value_str, js + t->start, size);
value_str[size] = '\0';
*value = _getdns_ipaddr_dict_mf(mf, value_str);
return *value != NULL;
}
static int _jsmn_get_data(struct mem_funcs *mf, const char *js, jsmntok_t *t,
getdns_bindata **value)
{
int i;
size_t j;
uint8_t h, l;
if ((t->end - t->start) < 4 || (t->end - t->start) % 2 == 1 ||
js[t->start] != '0' || js[t->start + 1] != 'x')
return 0;
for (i = t->start + 2; i < t->end; i++)
if (!((js[i] >= '0' && js[i] <= '9')
||(js[i] >= 'a' && js[i] <= 'f')
||(js[i] >= 'A' && js[i] <= 'F')))
return 0;
if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
return 0;
else if (!((*value)->data = GETDNS_XMALLOC(
*mf, uint8_t, (t->end - t->start) / 2 - 1))) {
GETDNS_FREE(*mf, *value);
return 0;
}
for (i = t->start + 2, j = 0; i < t->end; i++, j++) {
h = js[i] >= '0' && js[i] <= '9' ? js[i] - '0'
: js[i] >= 'A' && js[i] <= 'F' ? js[i] + 10 - 'A'
: js[i] + 10 - 'a';
h <<= 4;
i++;
l = js[i] >= '0' && js[i] <= '9' ? js[i] - '0'
: js[i] >= 'A' && js[i] <= 'F' ? js[i] + 10 - 'A'
: js[i] + 10 - 'a';
(*value)->data[j] = h | l;
}
(*value)->size = j;
return 1;
}
static int _jsmn_get_dname(struct mem_funcs *mf, const char *js, jsmntok_t *t,
getdns_bindata **value)
{
char value_str[1025];
int size = t->end - t->start;
(void)mf; /* TODO: Fix to use mf */
if (size <= 0 || size >= (int)sizeof(value_str) || js[t->end - 1] != '.')
return 0;
(void) memcpy(value_str, js + t->start, size);
value_str[size] = '\0';
return !getdns_convert_fqdn_to_dns_name(value_str, value);
}
static int _jsmn_get_ipv4(struct mem_funcs *mf, const char *js, jsmntok_t *t,
getdns_bindata **value)
{
char value_str[16];
int size = t->end - t->start;
uint8_t buf[4];
if (size <= 0 || size >= (int)sizeof(value_str))
return 0;
(void) memcpy(value_str, js + t->start, size);
value_str[size] = '\0';
if (inet_pton(AF_INET, value_str, buf) <= 0)
; /* pass */
else if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
; /* pass */
else if (!((*value)->data = GETDNS_XMALLOC(*mf, uint8_t, 4)))
GETDNS_FREE(*mf, *value);
else {
(*value)->size = 4;
(void) memcpy((*value)->data, buf, 4);
return 1;
}
return 0;
}
static int _jsmn_get_ipv6(struct mem_funcs *mf, const char *js, jsmntok_t *t,
getdns_bindata **value)
{
char value_str[40];
int size = t->end - t->start;
uint8_t buf[16];
if (size <= 0 || size >= (int)sizeof(value_str))
return 0;
(void) memcpy(value_str, js + t->start, size);
value_str[size] = '\0';
if (inet_pton(AF_INET6, value_str, buf) <= 0)
; /* pass */
else if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
; /* pass */
else if (!((*value)->data = GETDNS_XMALLOC(*mf, uint8_t, 16)))
GETDNS_FREE(*mf, *value);
else {
(*value)->size = 16;
(void) memcpy((*value)->data, buf, 16);
return 1;
}
return 0;
}
static int _jsmn_get_int(const char *js, jsmntok_t *t, uint32_t *value)
{
char value_str[11];
int size = t->end - t->start;
char *endptr;
if (size <= 0 || size >= (int)sizeof(value_str))
return 0;
(void) memcpy(value_str, js + t->start, size);
value_str[size] = '\0';
*value = (uint32_t)strtoul(value_str, &endptr, 10);
return *value_str != '\0' && *endptr == '\0';
}
static int _jsmn_get_const(const char *js, jsmntok_t *t, uint32_t *value)
{
char value_str[80];
int size = t->end - t->start;
if (size <= 0 || size >= (int)sizeof(value_str))
return 0;
(void) memcpy(value_str, js + t->start, size);
value_str[size] = '\0';
return _getdns_get_const_name_info(value_str, value);
}
static void
_getdns_destroy_item_data(struct mem_funcs *mf, getdns_item *item)
{
switch (item->dtype) {
case t_dict:
getdns_dict_destroy(item->data.dict);
break;
case t_list:
getdns_list_destroy(item->data.list);
break;
case t_bindata:
GETDNS_FREE(*mf, item->data.bindata->data);
GETDNS_FREE(*mf, item->data.bindata);
default:
break;
}
}
static int _jsmn_get_item(struct mem_funcs *mf, const char *js, jsmntok_t *t,
size_t count, getdns_item *item, getdns_return_t *r);
static int _jsmn_get_dict(struct mem_funcs *mf, const char *js, jsmntok_t *t,
size_t count, getdns_dict *dict, getdns_return_t *r)
{
int i;
size_t j = 1;
char key_spc[1024], *key = NULL;
getdns_item child_item;
if (t->size <= 0)
*r = GETDNS_RETURN_GOOD;
else for (i = 0; i < t->size; i++) {
if (t[j].type != JSMN_STRING &&
t[j].type != JSMN_PRIMITIVE) {
/* Key must be string or primitive */
*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
break;
}
if (t[j].end <= t[j].start) {
/* Key must be at least 1 character */
*r = GETDNS_RETURN_GENERIC_ERROR; /* range error */
break;
}
if (t[j].end - t[j].start < (int)sizeof(key_spc))
key = key_spc;
else if (!(key = GETDNS_XMALLOC(
*mf, char, t[j].end - t[j].start + 1))) {
*r = GETDNS_RETURN_MEMORY_ERROR;
break;
}
(void) memcpy(key, js + t[j].start, t[j].end - t[j].start);
key[t[j].end - t[j].start] = '\0';
j += 1;
j += _jsmn_get_item(mf, js, t + j, count - j, &child_item, r);
if (*r) break;
switch (child_item.dtype) {
case t_int:
*r = getdns_dict_set_int(dict, key,
child_item.data.n);
break;
case t_bindata:
*r = getdns_dict_set_bindata(dict, key,
child_item.data.bindata);
break;
case t_list:
*r = getdns_dict_set_list(dict, key,
child_item.data.list);
break;
case t_dict:
*r = getdns_dict_set_dict(dict, key,
child_item.data.dict);
break;
default:
*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
break;
}
_getdns_destroy_item_data(mf, &child_item);
if (*r) break;
if (key && key != key_spc) {
GETDNS_FREE(*mf, key);
key = NULL;
}
}
if (key && key != key_spc)
GETDNS_FREE(*mf, key);
if (*r) {
getdns_dict_destroy(dict);
return 0;
}
return j;
}
static int _jsmn_get_list(struct mem_funcs *mf, const char *js, jsmntok_t *t,
size_t count, getdns_list *list, getdns_return_t *r)
{
int i;
size_t j = 1, index = 0;
getdns_item child_item;
if (t->size <= 0)
*r = GETDNS_RETURN_GOOD;
else for (i = 0; i < t->size; i++) {
j += _jsmn_get_item(mf, js, t + j, count - j, &child_item, r);
if (*r) break;
switch (child_item.dtype) {
case t_int:
*r = getdns_list_set_int(list, index++,
child_item.data.n);
break;
case t_bindata:
*r = getdns_list_set_bindata(list, index++,
child_item.data.bindata);
break;
case t_list:
*r = getdns_list_set_list(list, index++,
child_item.data.list);
break;
case t_dict:
*r = getdns_list_set_dict(list, index++,
child_item.data.dict);
break;
default:
*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
break;
}
_getdns_destroy_item_data(mf, &child_item);
if (*r) break;
}
if (*r) {
getdns_list_destroy(list);
return 0;
}
return j;
}
static int _jsmn_get_item(struct mem_funcs *mf, const char *js, jsmntok_t *t,
size_t count, getdns_item *item, getdns_return_t *r)
{
assert(item);
switch (t->type) {
case JSMN_STRING:
if (t->end < t->start)
*r = GETDNS_RETURN_GENERIC_ERROR;
else if (!(item->data.bindata =
GETDNS_MALLOC(*mf, getdns_bindata)))
*r = GETDNS_RETURN_MEMORY_ERROR;
else if (!(item->data.bindata->data = GETDNS_XMALLOC(
*mf, uint8_t, t->end - t->start + 1))) {
GETDNS_FREE(*mf, item->data.bindata);
*r = GETDNS_RETURN_MEMORY_ERROR;
} else {
item->dtype = t_bindata;
if (t->end - t->start) {
(void) memcpy(item->data.bindata->data,
js + t->start, t->end - t->start);
}
item->data.bindata->data[t->end - t->start] = '\0';
item->data.bindata->size = t->end - t->start;
*r = GETDNS_RETURN_GOOD;
return 1;
}
break;
case JSMN_PRIMITIVE:
/* There is no such thing as an empty primitive */
if (t->end <= t->start) {
*r = GETDNS_RETURN_GENERIC_ERROR;
break;
} else if (_jsmn_get_int(js, t, &item->data.n)
|| _jsmn_get_const(js, t, &item->data.n)) {
item->dtype = t_int;
}
else if (_jsmn_get_data(mf, js, t, &item->data.bindata)
|| _jsmn_get_dname(mf, js, t, &item->data.bindata)
|| _jsmn_get_ipv4(mf, js, t, &item->data.bindata)
|| _jsmn_get_ipv6(mf, js, t, &item->data.bindata))
item->dtype = t_bindata;
else if (_jsmn_get_ipdict(mf, js, t, &item->data.dict))
item->dtype = t_dict;
else {
*r = GETDNS_RETURN_GENERIC_ERROR;
break;
}
*r = GETDNS_RETURN_GOOD;
return 1;
case JSMN_OBJECT:
if (!(item->data.dict = _getdns_dict_create_with_mf(mf))) {
*r = GETDNS_RETURN_MEMORY_ERROR;
break;
}
item->dtype = t_dict;
return _jsmn_get_dict(mf, js, t, count, item->data.dict, r);
case JSMN_ARRAY:
if (!(item->data.list = _getdns_list_create_with_mf(mf))) {
*r = GETDNS_RETURN_MEMORY_ERROR;
break;
}
item->dtype = t_list;
return _jsmn_get_list(mf, js, t, count, item->data.list, r);
default:
*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
break;
}
return 0;
}
static getdns_return_t
_getdns_str2item_mf(struct mem_funcs *mf, const char *str, getdns_item *item)
{
jsmn_parser p;
jsmntok_t *tok = NULL, *new_tok;
size_t tokcount = 100;
int r;
getdns_return_t gr;
jsmn_init(&p);
tok = GETDNS_XMALLOC(*mf, jsmntok_t, tokcount);
do {
r = jsmn_parse(&p, str, strlen(str), tok, tokcount);
if (r == JSMN_ERROR_NOMEM) {
tokcount *= 2;
if (!(new_tok = GETDNS_XREALLOC(
*mf, tok, jsmntok_t, tokcount))) {
GETDNS_FREE(*mf, tok);
return GETDNS_RETURN_MEMORY_ERROR;
}
tok = new_tok;
}
} while (r == JSMN_ERROR_NOMEM);
if (r < 0)
gr = GETDNS_RETURN_GENERIC_ERROR;
else
(void) _jsmn_get_item(mf, str, tok, p.toknext, item, &gr);
GETDNS_FREE(*mf, tok);
return gr;
}
getdns_return_t
getdns_str2dict(const char *str, getdns_dict **dict)
{
getdns_item item;
getdns_return_t r;
if (!str || !dict)
return GETDNS_RETURN_INVALID_PARAMETER;
while (*str && isspace(*str))
str++;
if (*str != '{') {
getdns_dict *dict_r = _getdns_ipaddr_dict_mf(
&_getdns_plain_mem_funcs, str);
if (dict_r) {
*dict = dict_r;
return GETDNS_RETURN_GOOD;
}
}
if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
return r;
else if (item.dtype != t_dict) {
uint8_t buf[16];
getdns_dict *dict_r;
if (item.dtype != t_bindata)
r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
else if (item.data.bindata->size == 4 &&
inet_pton(AF_INET, str, buf) == 1) {
if (!(dict_r = getdns_dict_create()))
r = GETDNS_RETURN_MEMORY_ERROR;
else if ((r = getdns_dict_util_set_string(
dict_r, "address_type", "IPv4")))
getdns_dict_destroy(dict_r);
else if ((r = getdns_dict_set_bindata(
dict_r, "address_data", item.data.bindata)))
getdns_dict_destroy(dict_r);
else
*dict = dict_r;
} else if (item.data.bindata->size == 16 &&
inet_pton(AF_INET6, str, buf) == 1) {
if (!(dict_r = getdns_dict_create()))
r = GETDNS_RETURN_MEMORY_ERROR;
else if ((r = getdns_dict_util_set_string(
dict_r, "address_type", "IPv6")))
getdns_dict_destroy(dict_r);
else if ((r = getdns_dict_set_bindata(
dict_r, "address_data", item.data.bindata)))
getdns_dict_destroy(dict_r);
else
*dict = dict_r;
} else
r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
return r;
}
*dict = item.data.dict;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_str2list(const char *str, getdns_list **list)
{
getdns_item item;
getdns_return_t r;
if (!str || !list)
return GETDNS_RETURN_INVALID_PARAMETER;
if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
return r;
else if (item.dtype != t_list) {
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
}
*list = item.data.list;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_str2bindata(const char *str, getdns_bindata **bindata)
{
getdns_item item;
getdns_return_t r;
if (!str || !bindata)
return GETDNS_RETURN_INVALID_PARAMETER;
if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
return r;
else if (item.dtype != t_bindata) {
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
}
*bindata = item.data.bindata;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_str2int(const char *str, uint32_t *value)
{
getdns_item item;
getdns_return_t r;
if (!str || !value)
return GETDNS_RETURN_INVALID_PARAMETER;
if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
return r;
else if (item.dtype != t_int) {
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
}
*value = item.data.n;
return GETDNS_RETURN_GOOD;
}
/* convert.c */

View File

@ -37,7 +37,7 @@
#include "config.h" #include "config.h"
#define STUB_DEBUG_ENTRY "-> ENTRY: " #define STUB_DEBUG_ENTRY "=> ENTRY: "
#define STUB_DEBUG_SETUP "--- SETUP: " #define STUB_DEBUG_SETUP "--- SETUP: "
#define STUB_DEBUG_SETUP_TLS "--- SETUP(TLS): " #define STUB_DEBUG_SETUP_TLS "--- SETUP(TLS): "
#define STUB_DEBUG_TSIG "--- TSIG: " #define STUB_DEBUG_TSIG "--- TSIG: "
@ -45,6 +45,7 @@
#define STUB_DEBUG_READ "------- READ: " #define STUB_DEBUG_READ "------- READ: "
#define STUB_DEBUG_WRITE "------- WRITE: " #define STUB_DEBUG_WRITE "------- WRITE: "
#define STUB_DEBUG_CLEANUP "--- CLEANUP: " #define STUB_DEBUG_CLEANUP "--- CLEANUP: "
#define STUB_DEBUG_DAEMON "GETDNS_DAEMON: "
#define DEBUG_ON(...) do { \ #define DEBUG_ON(...) do { \
struct timeval tv; \ struct timeval tv; \
@ -88,6 +89,13 @@
#define DEBUG_STUB(...) DEBUG_OFF(__VA_ARGS__) #define DEBUG_STUB(...) DEBUG_OFF(__VA_ARGS__)
#endif #endif
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
#include <time.h>
#define DEBUG_DAEMON(...) DEBUG_ON(__VA_ARGS__)
#else
#define DEBUG_DAEMON(...) DEBUG_OFF(__VA_ARGS__)
#endif
#if defined(SEC_DEBUG) && SEC_DEBUG #if defined(SEC_DEBUG) && SEC_DEBUG
#include <time.h> #include <time.h>
#define DEBUG_SEC(...) DEBUG_ON(__VA_ARGS__) #define DEBUG_SEC(...) DEBUG_ON(__VA_ARGS__)

View File

@ -2696,6 +2696,7 @@ static int chain_head_validate(struct mem_funcs *mf, time_t now, uint32_t skew,
* evaluated by processing each head in turn. The worst outcome per network request * evaluated by processing each head in turn. The worst outcome per network request
* is the dnssec status for that network request. * is the dnssec status for that network request.
*/ */
#ifdef STUB_NATIVE_DNSSEC
static void chain_set_netreq_dnssec_status(chain_head *chain, _getdns_rrset_iter *tas) static void chain_set_netreq_dnssec_status(chain_head *chain, _getdns_rrset_iter *tas)
{ {
chain_head *head; chain_head *head;
@ -2732,6 +2733,7 @@ static void chain_set_netreq_dnssec_status(chain_head *chain, _getdns_rrset_iter
} }
} }
} }
#endif
/* The DNSSEC status of all heads for a chain structure is evaluated by /* The DNSSEC status of all heads for a chain structure is evaluated by
* processing each head in turn. The worst outcome is the dnssec status for * processing each head in turn. The worst outcome is the dnssec status for

View File

@ -900,6 +900,196 @@ getdns_msg_dict2str_buf(
getdns_return_t getdns_return_t
getdns_msg_dict2str_scan( getdns_msg_dict2str_scan(
const getdns_dict *msg_dict, char **str, int *str_len); const getdns_dict *msg_dict, char **str, int *str_len);
/**
* Convert string text to a getdns_dict.
*
* @param str A textual representation of a getdns_dict.
* The format is similar, but not precisely JSON.
* - dict keys may be given without quotes.
* For example: `{ timeout: 2000 }` is the same as { "timeout": 2000 }
* - When str contains an IP or IPv6 address, it is converted
* to an getdns dict representation of that address. This may contain
* a port, tls_port, tsig spec or tls authentication name in the same
* way as may be given with the `getdns_query` tool. For example:
* `185.49.140.67:80#443` will result in the following getdns_dict:
*
* { address_type: "IPv4"
* , address_data: "185.49.140.67"
* , port: 80
* , tls_port: 443
* }
*
* @param dict The returned getdns_dict.
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
*/
getdns_return_t
getdns_str2dict(const char *str, getdns_dict **dict);
/**
* Convert string text to a getdns_list.
*
* @param str A textual representation of a getdns_list.
* The format is similar, but not precisely JSON.
* @param list The returned getdns_list.
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
*/
getdns_return_t
getdns_str2list(const char *str, getdns_list **list);
/**
* Convert string text to a getdns_bindata.
*
* @param str A textual representation of a getdns_bindata
* The format is similar, but not precisely JSON.
* - Strings between double-quotes will be converted to bindata
* containers, but *without the trailing null byte*.
* For example: `{ suffix: [ "nlnetlabs.nl.", "nlnet.nl." ] }`
* - bindata representation of IP or IPv6 addresses may be
* given in their presentation format. For example:
* `{ dns_root_servers: [ 2001:7fd::1, 193.0.14.129 ] }`
* - Arbitrary binary data may be given with a `0x` prefix.
* For example:
*
* { add_opt_parameters:
* { options: [ { option_code: 10
* , option_data: 0xA9E4EC50C03F5D65
* } ]
* }
* }
*
* - Wireformat domain name bindatas can be given with a trailing dot.
* For example:
*
* { upstream_recursive_servers:
* [ { address_data : 2a04:b900:0:100::37
* , tsig_name : hmac-md5.tsigs.getdnsapi.net.
* , tsig_algorithm: hmac-md5.sig-alg.reg.int.
* , tsig_secret : 0xD7A1BAF4E4DE5D6EB149
* } ]
* }
*
* @param bindata The returned getdns_bindata.
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
*/
getdns_return_t
getdns_str2bindata(const char *str, getdns_bindata **bindata);
/**
* Convert string text to a getdns 32 bits unsigned integer.
*
* @param str A textual representation of the integer.
* The format is similar, but not precisely JSON.
* - integer values may be given by the constant name.
* For example: `{ resolution_type: GETDNS_RESOLUTION_STUB }`
* or `{ specify_class: GETDNS_RRCLASS_CH }`
* @param value The returned integer.
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
*/
getdns_return_t
getdns_str2int(const char *str, uint32_t *value);
/**
* Configure a context with settings given in a getdns_dict.
*
* @param context The context to be configured.
* @param config_dict The getdns_dict containing the settings.
* The settings have the same name as returned by the
* getdns_context_get_api_information() function, or as
* used in the names of the getdns_context_get_*() and
* getdns_context_set_*() functions.
* - The dict returned by
* getdns_context_get_api_information() can be used
* as the config_dict directly, but context settings
* do *not* have to be below a `"all_context"` key.
* - It is possible to set default values for extensions
* that could otherwise only be given on a per query
* basis. For example:
* `{ dnssec_return_status: GETDNS_EXTENSION_TRUE }` is
* equivalent to using the
* getdns_context_set_return_dnssec_status() function
* with that value, but default values for the other
* extensions can be set by this method now too.
* For example
* `{ return_call_reporting: GETDNS_EXTENSION_TRUE}`
* - Trust anchor files and root hints content can also be
* given by file, for example:
*
* { dns_root_servers : "named.root"
* , dnssec_trust_anchors: "/etc/unbound/getdns-root.key"
* }
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
* **Beware** that context might be partially configured on error. For retry
* strategies it is advised to recreate a new config.
*/
getdns_return_t
getdns_context_config(getdns_context *context, const getdns_dict *config_dict);
/**
* The user defined request handler that will be called on incoming requests.
*/
typedef void (*getdns_request_handler_t)(
getdns_context *context,
getdns_callback_type_t callback_type,
getdns_dict *request,
void *userarg,
getdns_transaction_t request_id
);
/**
* Create a name server by registering a list of addresses to listen on and
* a user defined function that will handle the requests.
*
* @param context The context managing the eventloop that needs to be run to
* start serving.
* @param listen_addresses A list of address dicts or bindatas that will be
* listened on for DNS requests. Both UDP and TCP
* transports will be used.
* @param userarg A user defined argument that will be passed to the handler
* untouched.
* @param handler The user defined request handler that will be called with the
* request received in reply dict format. To reply to this request
* the function has to construct a response (or modify the request)
* and call getdns_reply() with the response and the with the request
* associated request_id. The user is responsible of destroying
* both the replies and the response. **Beware** that if requests are
* not answered by the function, by not calling getdns_reply() this
* will cause a memory leak. The user most use getdns_reply()
* with NULL as the response to not answer/cancel a request.
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
* On failure, the current set of listening addresses is left in place.
* Also, if there is overlap in listening_addresses between the active set
* and the newly given set, the ones in the active set will remain in their
* current condition and will not be closed and reopened, also all assoicated
* DNS transactions will remain.
*/
getdns_return_t
getdns_context_set_listen_addresses(
getdns_context *context, const getdns_list *listen_addresses,
void *userarg, getdns_request_handler_t handler);
/**
* Answer the request associated with a request_id that is received by a
* request handler
*
* @param context The context managing the eventloop that needs to be run to
* listen for and answer requests.
* @param reply The answer in getdns reply dict or response dict format.
* When NULL is given as reply, the request is not answered
* but all associated state is deleted.
* @param request_id The identifier that links this response with the
* received request.
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
* On fatal failure (no retry strategy possible) the user still needs to
* cancel the request by recalling getdns_reply() but with NULL as response,
* to clean up state.
*/
getdns_return_t
getdns_reply(getdns_context *context,
getdns_dict *reply, getdns_transaction_t request_id);
/** @} /** @}
*/ */
@ -918,7 +1108,6 @@ getdns_return_t getdns_strerror(getdns_return_t err, char *buf, size_t buflen);
*/ */
/** @} /** @}
*/ */
/** @} /** @}
*/ */

View File

@ -1,6 +1,7 @@
getdns_address getdns_address
getdns_address_sync getdns_address_sync
getdns_cancel_callback getdns_cancel_callback
getdns_context_config
getdns_context_create getdns_context_create
getdns_context_create_with_extended_memory_functions getdns_context_create_with_extended_memory_functions
getdns_context_create_with_memory_functions getdns_context_create_with_memory_functions
@ -50,6 +51,7 @@ getdns_context_set_extended_memory_functions
getdns_context_set_follow_redirects getdns_context_set_follow_redirects
getdns_context_set_idle_timeout getdns_context_set_idle_timeout
getdns_context_set_limit_outstanding_queries getdns_context_set_limit_outstanding_queries
getdns_context_set_listen_addresses
getdns_context_set_memory_functions getdns_context_set_memory_functions
getdns_context_set_namespaces getdns_context_set_namespaces
getdns_context_set_resolution_type getdns_context_set_resolution_type
@ -123,6 +125,7 @@ getdns_print_json_dict
getdns_print_json_list getdns_print_json_list
getdns_pubkey_pin_create_from_string getdns_pubkey_pin_create_from_string
getdns_pubkey_pinset_sanity_check getdns_pubkey_pinset_sanity_check
getdns_reply
getdns_root_trust_anchor getdns_root_trust_anchor
getdns_rr_dict2str getdns_rr_dict2str
getdns_rr_dict2str_buf getdns_rr_dict2str_buf
@ -134,6 +137,10 @@ getdns_service
getdns_service_sync getdns_service_sync
getdns_snprint_json_dict getdns_snprint_json_dict
getdns_snprint_json_list getdns_snprint_json_list
getdns_str2bindata
getdns_str2dict
getdns_str2int
getdns_str2list
getdns_str2rr_dict getdns_str2rr_dict
getdns_strerror getdns_strerror
getdns_validate_dnssec getdns_validate_dnssec

View File

@ -46,18 +46,20 @@ getdns_get_errorstr_by_id(uint16_t err)
else else
return NULL; return NULL;
} }
END_OF_TAIL
gawk 'BEGIN{p=1}{if(p)print}/^static struct const_name_info consts_name_info\[\] = {$/{p=0}' test/getdns_str2dict.c > test/new-getdns_str2dict.c static struct const_name_info consts_name_info[] = {
gawk '/^[ ]+GETDNS_[A-Z_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%d", $3); consts[$1] = key; }/^#define GETDNS_[A-Z_]+[ ]+[0-9]+/ && !/_TEXT/{ key = sprintf("%d", $3); consts[$2] = key; }/^#define GETDNS_[A-Z_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%d", $4); consts[$2] = key; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ \""val"\", "name" },"}}' getdns/getdns.h.in getdns/getdns_extra.h.in | sed 's/,,/,/g' >> test/new-getdns_str2dict.c END_OF_TAIL
cat >> test/new-getdns_str2dict.c << END_OF_TAIL gawk '/^[ ]+GETDNS_[A-Z_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%d", $3); consts[$1] = key; }/^#define GETDNS_[A-Z_]+[ ]+[0-9]+/ && !/_TEXT/{ key = sprintf("%d", $3); consts[$2] = key; }/^#define GETDNS_[A-Z_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%d", $4); consts[$2] = key; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ \""val"\", "name" },"}}' getdns/getdns.h.in getdns/getdns_extra.h.in | sed 's/,,/,/g' >> const-info.c
cat >> const-info.c << END_OF_TAIL
}; };
static int const_name_info_cmp(const void *a, const void *b) static int const_name_info_cmp(const void *a, const void *b)
{ {
return strcmp( ((struct const_name_info *) a)->name return strcmp( ((struct const_name_info *) a)->name
, ((struct const_name_info *) b)->name ); , ((struct const_name_info *) b)->name );
} }
static int
int
_getdns_get_const_name_info(const char *name, uint32_t *code) _getdns_get_const_name_info(const char *name, uint32_t *code)
{ {
struct const_name_info key = { name, 0 }; struct const_name_info key = { name, 0 };
@ -71,5 +73,4 @@ _getdns_get_const_name_info(const char *name, uint32_t *code)
return 1; return 1;
} }
END_OF_TAIL END_OF_TAIL
mv test/new-getdns_str2dict.c test/getdns_str2dict.c

View File

@ -382,10 +382,10 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
X509_STORE_CTX *store) X509_STORE_CTX *store)
{ {
getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR; getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR;
X509 *x; X509 *x, *prev;
int i, len; int i, len;
unsigned char raw[4096]; unsigned char raw[4096];
unsigned char *next = raw; unsigned char *next;
unsigned char buf[sizeof(pinset->pin)]; unsigned char buf[sizeof(pinset->pin)];
const sha256_pin_t *p; const sha256_pin_t *p;
@ -407,14 +407,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
/* TODO: how do we handle raw public keys? */ /* TODO: how do we handle raw public keys? */
for (i = 0; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store)); i++) { for (i = 0; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store)); i++, prev = x) {
if (i > 0) {
/* TODO: how do we ensure that the certificates in
* each stage appropriately sign the previous one?
* for now, to be safe, we only examine the end-entity
* cert: */
return GETDNS_RETURN_GENERIC_ERROR;
}
x = sk_X509_value(X509_STORE_CTX_get0_untrusted(store), i); x = sk_X509_value(X509_STORE_CTX_get0_untrusted(store), i);
#if defined(STUB_DEBUG) && STUB_DEBUG #if defined(STUB_DEBUG) && STUB_DEBUG
@ -423,6 +416,24 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
X509_NAME_print_ex_fp(stderr, X509_get_subject_name(x), 1, XN_FLAG_ONELINE); X509_NAME_print_ex_fp(stderr, X509_get_subject_name(x), 1, XN_FLAG_ONELINE);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
#endif #endif
if (i > 0) {
/* we ensure that "prev" is signed by "x" */
EVP_PKEY *pkey = X509_get_pubkey(x);
int verified;
if (!pkey) {
DEBUG_STUB("%s %-35s: Could not get pubkey from cert %d (%p)\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)x);
return GETDNS_RETURN_GENERIC_ERROR;
}
verified = X509_verify(prev, pkey);
EVP_PKEY_free(pkey);
if (!verified) {
DEBUG_STUB("%s %-35s: cert %d (%p) was not signed by cert %d\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i-1, (void*)prev, i);
return GETDNS_RETURN_GENERIC_ERROR;
}
}
/* digest the cert with sha256 */ /* digest the cert with sha256 */
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL); len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL);
if (len > (int)sizeof(raw)) { if (len > (int)sizeof(raw)) {
@ -430,6 +441,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
STUB_DEBUG_SETUP_TLS, __FUNC__, i, sizeof(raw)); STUB_DEBUG_SETUP_TLS, __FUNC__, i, sizeof(raw));
continue; continue;
} }
next = raw;
i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next); i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next);
if (next - raw != len) { if (next - raw != len) {
DEBUG_STUB("%s %-35s: Pubkey %d claimed it needed %d octets, really needed "PRIsz"\n", DEBUG_STUB("%s %-35s: Pubkey %d claimed it needed %d octets, really needed "PRIsz"\n",
@ -442,11 +454,11 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
for (p = pinset; p; p = p->next) for (p = pinset; p; p = p->next)
if (0 == memcmp(buf, p->pin, sizeof(p->pin))) { if (0 == memcmp(buf, p->pin, sizeof(p->pin))) {
DEBUG_STUB("%s %-35s: Pubkey %d matched pin %p ("PRIsz")\n", DEBUG_STUB("%s %-35s: Pubkey %d matched pin %p ("PRIsz")\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void *)p, sizeof(p->pin)); STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p, sizeof(p->pin));
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} else } else
DEBUG_STUB("%s %-35s: Pubkey %d did not match pin %p\n", DEBUG_STUB("%s %-35s: Pubkey %d did not match pin %p\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void *)p); STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p);
} }
return ret; return ret;

View File

@ -85,20 +85,20 @@ getdns_dict *dnssec_ok_checking_disabled_avoid_roadblocks
static int static int
is_extension_set(getdns_dict *extensions, const char *extension) is_extension_set(getdns_dict *extensions, const char *name, int default_value)
{ {
getdns_return_t r; getdns_return_t r;
uint32_t value; uint32_t value;
if (! extensions) if ( ! extensions
return 0; || extensions == dnssec_ok_checking_disabled
else if (extensions == dnssec_ok_checking_disabled
|| extensions == dnssec_ok_checking_disabled_roadblock_avoidance || extensions == dnssec_ok_checking_disabled_roadblock_avoidance
|| extensions == dnssec_ok_checking_disabled_avoid_roadblocks) || extensions == dnssec_ok_checking_disabled_avoid_roadblocks)
return 0; return 0;
r = getdns_dict_get_int(extensions, extension, &value); r = getdns_dict_get_int(extensions, name, &value);
return r == GETDNS_RETURN_GOOD && value == GETDNS_EXTENSION_TRUE; return r == GETDNS_RETURN_GOOD ? ( value == GETDNS_EXTENSION_TRUE )
: default_value;
} }
static void static void
@ -177,11 +177,10 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
net_req->fd = -1; net_req->fd = -1;
net_req->transport_current = 0; net_req->transport_current = 0;
memset(&net_req->event, 0, sizeof(net_req->event)); memset(&net_req->event, 0, sizeof(net_req->event));
memset(&net_req->tcp, 0, sizeof(net_req->tcp));
net_req->keepalive_sent = 0; net_req->keepalive_sent = 0;
net_req->write_queue_tail = NULL; net_req->write_queue_tail = NULL;
/* Some fields to record info for return_call_reporting */ /* Some fields to record info for return_call_reporting */
net_req->debug_tls_auth_status = 0; net_req->debug_tls_auth_status = GETDNS_AUTH_NONE;
net_req->debug_udp = 0; net_req->debug_udp = 0;
if (max_query_sz == 0) { if (max_query_sz == 0) {
@ -206,6 +205,9 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
buf = netreq_reset(net_req); buf = netreq_reset(net_req);
gldns_buffer_init_frm_data( gldns_buffer_init_frm_data(
&gbuf, net_req->query, net_req->wire_data_sz - 2); &gbuf, net_req->query, net_req->wire_data_sz - 2);
if (owner->context->header)
_getdns_reply_dict2wire(owner->context->header, &gbuf, 1);
gldns_buffer_rewind(&gbuf);
_getdns_reply_dict2wire(extensions, &gbuf, 1); _getdns_reply_dict2wire(extensions, &gbuf, 1);
if (dnssec_extension_set) /* We will do validation ourselves */ if (dnssec_extension_set) /* We will do validation ourselves */
GLDNS_CD_SET(net_req->query); GLDNS_CD_SET(net_req->query);
@ -658,28 +660,32 @@ getdns_dns_req *
_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop, _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions) const char *name, uint16_t request_type, getdns_dict *extensions)
{ {
int dnssec_return_status int dnssec_return_status = is_extension_set(
= context->return_dnssec_status == GETDNS_EXTENSION_TRUE extensions, "dnssec_return_status",
|| is_extension_set(extensions, "dnssec_return_status"); context->dnssec_return_status);
int dnssec_return_only_secure int dnssec_return_only_secure = is_extension_set(
= is_extension_set(extensions, "dnssec_return_only_secure"); extensions, "dnssec_return_only_secure",
int dnssec_return_all_statuses context->dnssec_return_only_secure);
= is_extension_set(extensions, "dnssec_return_all_statuses"); int dnssec_return_all_statuses = is_extension_set(
int dnssec_return_full_validation_chain extensions, "dnssec_return_all_statuses",
= is_extension_set(extensions, "dnssec_return_full_validation_chain"); context->dnssec_return_all_statuses);
int dnssec_return_validation_chain int dnssec_return_full_validation_chain = is_extension_set(
= is_extension_set(extensions, "dnssec_return_validation_chain"); extensions, "dnssec_return_full_validation_chain",
int edns_cookies context->dnssec_return_full_validation_chain);
= is_extension_set(extensions, "edns_cookies"); int dnssec_return_validation_chain = is_extension_set(
extensions, "dnssec_return_validation_chain",
context->dnssec_return_validation_chain);
int edns_cookies = is_extension_set(
extensions, "edns_cookies",
context->edns_cookies);
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE #ifdef DNSSEC_ROADBLOCK_AVOIDANCE
int avoid_dnssec_roadblocks int avoid_dnssec_roadblocks
= (extensions == dnssec_ok_checking_disabled_avoid_roadblocks); = (extensions == dnssec_ok_checking_disabled_avoid_roadblocks);
int dnssec_roadblock_avoidance int dnssec_roadblock_avoidance = avoid_dnssec_roadblocks
= is_extension_set(extensions, "dnssec_roadblock_avoidance")
|| (extensions == dnssec_ok_checking_disabled_roadblock_avoidance) || (extensions == dnssec_ok_checking_disabled_roadblock_avoidance)
|| avoid_dnssec_roadblocks; || is_extension_set(extensions, "dnssec_roadblock_avoidance",
context->dnssec_roadblock_avoidance);
#endif #endif
int dnssec_extension_set = dnssec_return_status int dnssec_extension_set = dnssec_return_status
|| dnssec_return_only_secure || dnssec_return_all_statuses || dnssec_return_only_secure || dnssec_return_all_statuses
|| dnssec_return_validation_chain || dnssec_return_validation_chain
@ -713,9 +719,9 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
int with_opt; int with_opt;
getdns_dns_req *result = NULL; getdns_dns_req *result = NULL;
uint32_t klass = GLDNS_RR_CLASS_IN; uint32_t klass = context->specify_class;
int a_aaaa_query = int a_aaaa_query = is_extension_set(extensions,
is_extension_set(extensions, "return_both_v4_and_v6") && "return_both_v4_and_v6", context->return_both_v4_and_v6) &&
( request_type == GETDNS_RRTYPE_A || ( request_type == GETDNS_RRTYPE_A ||
request_type == GETDNS_RRTYPE_AAAA ); request_type == GETDNS_RRTYPE_AAAA );
/* Reserve for the buffer at least one more byte /* Reserve for the buffer at least one more byte
@ -732,7 +738,10 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
have_add_opt_parameters = getdns_dict_get_dict(extensions, have_add_opt_parameters = getdns_dict_get_dict(extensions,
"add_opt_parameters", &add_opt_parameters) == GETDNS_RETURN_GOOD; "add_opt_parameters", &add_opt_parameters) == GETDNS_RETURN_GOOD;
if (!have_add_opt_parameters && context->add_opt_parameters) {
add_opt_parameters = context->add_opt_parameters;
have_add_opt_parameters = 1;
}
if (dnssec_extension_set) { if (dnssec_extension_set) {
edns_maximum_udp_payload_size = -1; edns_maximum_udp_payload_size = -1;
edns_extended_rcode = 0; edns_extended_rcode = 0;
@ -895,10 +904,10 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
#endif #endif
result->edns_client_subnet_private = context->edns_client_subnet_private; result->edns_client_subnet_private = context->edns_client_subnet_private;
result->tls_query_padding_blocksize = context->tls_query_padding_blocksize; result->tls_query_padding_blocksize = context->tls_query_padding_blocksize;
result->return_call_reporting = result->return_call_reporting = is_extension_set(extensions,
is_extension_set(extensions, "return_call_reporting"); "return_call_reporting" , context->return_call_reporting);
result->add_warning_for_bad_dns = result->add_warning_for_bad_dns = is_extension_set(extensions,
is_extension_set(extensions, "add_warning_for_bad_dns"); "add_warning_for_bad_dns", context->add_warning_for_bad_dns);
/* will be set by caller */ /* will be set by caller */
result->user_pointer = NULL; result->user_pointer = NULL;

View File

@ -26,11 +26,20 @@
*/ */
#include "config.h" #include "config.h"
#include "getdns_context_set_listen_addresses.h"
#ifndef USE_WINSOCK
#include <netdb.h>
#else
#include <winsock2.h>
#include <iphlpapi.h>
#endif
#include "getdns/getdns_extra.h" #include "getdns/getdns_extra.h"
#include "context.h"
#include "types-internal.h" #include "types-internal.h"
#include "debug.h" #include "debug.h"
#include <netdb.h> #include "util/rbtree.h"
#include "server.h"
#define DNS_REQUEST_SZ 4096 #define DNS_REQUEST_SZ 4096
#define DOWNSTREAM_IDLE_TIMEOUT 5000 #define DOWNSTREAM_IDLE_TIMEOUT 5000
@ -63,9 +72,10 @@ struct listener {
*/ */
struct listen_set { struct listen_set {
getdns_context *context; getdns_context *context;
listen_set *next; void *userarg;
getdns_request_handler_t handler; getdns_request_handler_t handler;
_getdns_rbtree_t connections_set;
size_t count; size_t count;
listener items[]; listener items[];
}; };
@ -79,6 +89,9 @@ struct tcp_to_write {
}; };
struct connection { struct connection {
/* struct connection is a sub struct of _getdns_rbnode_t */
_getdns_rbnode_t super;
listener *l; listener *l;
struct sockaddr_storage remote_in; struct sockaddr_storage remote_in;
socklen_t addrlen; socklen_t addrlen;
@ -88,14 +101,8 @@ struct connection {
}; };
typedef struct tcp_connection { typedef struct tcp_connection {
/* A TCP connection is a connection */ /* struct tcp_connection is a sub struct of connection */
listener *l; connection super;
struct sockaddr_storage remote_in;
socklen_t addrlen;
connection *next;
connection **prev_next;
/************************************/
int fd; int fd;
getdns_eventloop_event event; getdns_eventloop_event event;
@ -118,10 +125,10 @@ static void tcp_connection_destroy(tcp_connection *conn)
tcp_to_write *cur, *next; tcp_to_write *cur, *next;
if (!(mf = priv_getdns_context_mf(conn->l->set->context))) if (!(mf = &conn->super.l->set->context->mf))
return; return;
if (getdns_context_get_eventloop(conn->l->set->context, &loop)) if (getdns_context_get_eventloop(conn->super.l->set->context, &loop))
return; return;
if (conn->event.read_cb||conn->event.write_cb||conn->event.timeout_cb) if (conn->event.read_cb||conn->event.write_cb||conn->event.timeout_cb)
@ -139,10 +146,14 @@ static void tcp_connection_destroy(tcp_connection *conn)
return; return;
/* Unlink this connection */ /* Unlink this connection */
if ((*conn->prev_next = conn->next)) (void) _getdns_rbtree_delete(
conn->next->prev_next = conn->prev_next; &conn->super.l->set->connections_set, conn);
DEBUG_SERVER("[connection del] count: %d\n",
(int)conn->super.l->set->connections_set.count);
if ((*conn->super.prev_next = conn->super.next))
conn->super.next->prev_next = conn->super.prev_next;
free_listen_set_when_done(conn->l->set); free_listen_set_when_done(conn->super.l->set);
GETDNS_FREE(*mf, conn); GETDNS_FREE(*mf, conn);
} }
@ -157,10 +168,10 @@ static void tcp_write_cb(void *userarg)
assert(userarg); assert(userarg);
if (!(mf = priv_getdns_context_mf(conn->l->set->context))) if (!(mf = &conn->super.l->set->context->mf))
return; return;
if (getdns_context_get_eventloop(conn->l->set->context, &loop)) if (getdns_context_get_eventloop(conn->super.l->set->context, &loop))
return; return;
/* Reset tcp_connection idle timeout */ /* Reset tcp_connection idle timeout */
@ -195,28 +206,30 @@ static void tcp_write_cb(void *userarg)
DOWNSTREAM_IDLE_TIMEOUT, &conn->event); DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
} }
void static void
_getdns_cancel_reply(getdns_context *context, getdns_transaction_t request_id) _getdns_cancel_reply(getdns_context *context, connection *conn)
{ {
/* TODO: Check request_id at context->outbound_requests */
connection *conn = (connection *)(intptr_t)request_id;
struct mem_funcs *mf; struct mem_funcs *mf;
if (!context || !conn) if (!context || !conn)
return; return;
if (conn->l->transport == GETDNS_TRANSPORT_TCP) { if (conn->l->transport == GETDNS_TRANSPORT_TCP) {
tcp_connection *conn = (tcp_connection *)(intptr_t)request_id; tcp_connection *tcp_conn = (tcp_connection *)conn;
if (conn->to_answer > 0 && --conn->to_answer == 0 && if (tcp_conn->to_answer > 0 && --tcp_conn->to_answer == 0 &&
conn->fd == -1) tcp_conn->fd == -1)
tcp_connection_destroy(conn); tcp_connection_destroy(tcp_conn);
} else if (conn->l->transport == GETDNS_TRANSPORT_UDP && } else if (conn->l->transport == GETDNS_TRANSPORT_UDP &&
(mf = priv_getdns_context_mf(conn->l->set->context))) { (mf = &conn->l->set->context->mf)) {
listen_set *set = conn->l->set; listen_set *set = conn->l->set;
/* Unlink this connection */ /* Unlink this connection */
(void) _getdns_rbtree_delete(
&set->connections_set, conn);
DEBUG_SERVER("[connection del] count: %d\n",
(int)set->connections_set.count);
if ((*conn->prev_next = conn->next)) if ((*conn->prev_next = conn->next))
conn->next->prev_next = conn->prev_next; conn->next->prev_next = conn->prev_next;
GETDNS_FREE(*mf, conn); GETDNS_FREE(*mf, conn);
@ -226,7 +239,7 @@ _getdns_cancel_reply(getdns_context *context, getdns_transaction_t request_id)
getdns_return_t getdns_return_t
getdns_reply( getdns_reply(
getdns_context *context, getdns_transaction_t request_id, getdns_dict *reply) getdns_context *context, getdns_dict *reply, getdns_transaction_t request_id)
{ {
/* TODO: Check request_id at context->outbound_requests */ /* TODO: Check request_id at context->outbound_requests */
connection *conn = (connection *)(intptr_t)request_id; connection *conn = (connection *)(intptr_t)request_id;
@ -236,10 +249,21 @@ getdns_reply(
size_t len; size_t len;
getdns_return_t r; getdns_return_t r;
if (!context || !reply || !conn) if (!context || !conn)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
if (!(mf = priv_getdns_context_mf(conn->l->set->context))) if (!context->server)
return GETDNS_RETURN_GENERIC_ERROR;;
if (_getdns_rbtree_search(&context->server->connections_set, conn)
!= &conn->super)
return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
if (!reply) {
_getdns_cancel_reply(context, conn);
return GETDNS_RETURN_GOOD;
}
if (!(mf = &conn->l->set->context->mf))
return GETDNS_RETURN_GENERIC_ERROR;; return GETDNS_RETURN_GENERIC_ERROR;;
if ((r = getdns_context_get_eventloop(conn->l->set->context, &loop))) if ((r = getdns_context_get_eventloop(conn->l->set->context, &loop)))
@ -252,7 +276,7 @@ getdns_reply(
else if (conn->l->transport == GETDNS_TRANSPORT_UDP) { else if (conn->l->transport == GETDNS_TRANSPORT_UDP) {
listener *l = conn->l; listener *l = conn->l;
if (conn->l->fd >= 0 && sendto(conn->l->fd, buf, len, 0, if (conn->l->fd >= 0 && sendto(conn->l->fd, (void *)buf, len, 0,
(struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) { (struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) {
/* IO error, cleanup this listener */ /* IO error, cleanup this listener */
loop->vmt->clear(loop, &conn->l->event); loop->vmt->clear(loop, &conn->l->event);
@ -260,6 +284,10 @@ getdns_reply(
conn->l->fd = -1; conn->l->fd = -1;
} }
/* Unlink this connection */ /* Unlink this connection */
(void) _getdns_rbtree_delete(
&l->set->connections_set, conn);
DEBUG_SERVER("[connection del] count: %d\n",
(int)l->set->connections_set.count);
if ((*conn->prev_next = conn->next)) if ((*conn->prev_next = conn->next))
conn->next->prev_next = conn->prev_next; conn->next->prev_next = conn->prev_next;
@ -320,10 +348,10 @@ static void tcp_read_cb(void *userarg)
assert(userarg); assert(userarg);
if (!(mf = priv_getdns_context_mf(conn->l->set->context))) if (!(mf = &conn->super.l->set->context->mf))
return; return;
if ((r = getdns_context_get_eventloop(conn->l->set->context, &loop))) if ((r = getdns_context_get_eventloop(conn->super.l->set->context, &loop)))
return; return;
/* Reset tcp_connection idle timeout */ /* Reset tcp_connection idle timeout */
@ -380,9 +408,14 @@ static void tcp_read_cb(void *userarg)
else { else {
conn->to_answer++; conn->to_answer++;
/* TODO: wish list item:
* (void) getdns_dict_set_int64(
* request_dict, "request_id", intptr_t)conn);
*/
/* Call request handler */ /* Call request handler */
conn->l->set->handler( conn->super.l->set->handler(
conn->l->set->context, request_dict, (intptr_t)conn); conn->super.l->set->context, GETDNS_CALLBACK_COMPLETE,
request_dict, conn->super.l->set->userarg, (intptr_t)conn);
conn->read_pos = conn->read_buf; conn->read_pos = conn->read_buf;
conn->to_read = 2; conn->to_read = 2;
@ -402,7 +435,8 @@ static void tcp_timeout_cb(void *userarg)
if (conn->to_answer) { if (conn->to_answer) {
getdns_eventloop *loop; getdns_eventloop *loop;
if (getdns_context_get_eventloop(conn->l->set->context, &loop)) if (getdns_context_get_eventloop(
conn->super.l->set->context, &loop))
return; return;
loop->vmt->clear(loop, &conn->event); loop->vmt->clear(loop, &conn->event);
@ -423,7 +457,7 @@ static void tcp_accept_cb(void *userarg)
assert(userarg); assert(userarg);
if (!(mf = priv_getdns_context_mf(l->set->context))) if (!(mf = &l->set->context->mf))
return; return;
if ((r = getdns_context_get_eventloop(l->set->context, &loop))) if ((r = getdns_context_get_eventloop(l->set->context, &loop)))
@ -433,11 +467,10 @@ static void tcp_accept_cb(void *userarg)
return; return;
(void) memset(conn, 0, sizeof(tcp_connection)); (void) memset(conn, 0, sizeof(tcp_connection));
conn->super.l = l;
conn->l = l; conn->super.addrlen = sizeof(conn->super.remote_in);
conn->addrlen = sizeof(conn->remote_in); if ((conn->fd = accept(l->fd, (struct sockaddr *)
if ((conn->fd = accept(l->fd, &conn->super.remote_in, &conn->super.addrlen)) == -1) {
(struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) {
/* IO error, cleanup this listener */ /* IO error, cleanup this listener */
loop->vmt->clear(loop, &l->event); loop->vmt->clear(loop, &l->event);
close(l->fd); close(l->fd);
@ -458,11 +491,21 @@ static void tcp_accept_cb(void *userarg)
conn->event.timeout_cb = tcp_timeout_cb; conn->event.timeout_cb = tcp_timeout_cb;
/* Insert connection */ /* Insert connection */
if ((conn->next = l->connections)) conn->super.super.key = conn;
conn->next->prev_next = &conn->next; if (!_getdns_rbtree_insert(
conn->prev_next = &l->connections; &l->set->connections_set, &conn->super.super)) {
/* Memory error */
GETDNS_FREE(*mf, conn);
return;
}
DEBUG_SERVER("[connection add] count: %d\n",
(int)l->set->connections_set.count);
if ((conn->super.next = l->connections))
conn->super.next->prev_next = &conn->super.next;
conn->super.prev_next = &l->connections;
l->connections = (connection *)conn; l->connections = (connection *)conn;
(void) loop->vmt->schedule(loop, conn->fd, (void) loop->vmt->schedule(loop, conn->fd,
DOWNSTREAM_IDLE_TIMEOUT, &conn->event); DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
} }
@ -485,7 +528,7 @@ static void udp_read_cb(void *userarg)
if (l->fd == -1) if (l->fd == -1)
return; return;
if (!(mf = priv_getdns_context_mf(l->set->context))) if (!(mf = &l->set->context->mf))
return; return;
if ((r = getdns_context_get_eventloop(l->set->context, &loop))) if ((r = getdns_context_get_eventloop(l->set->context, &loop)))
@ -496,7 +539,7 @@ static void udp_read_cb(void *userarg)
conn->l = l; conn->l = l;
conn->addrlen = sizeof(conn->remote_in); conn->addrlen = sizeof(conn->remote_in);
if ((len = recvfrom(l->fd, buf, sizeof(buf), 0, if ((len = recvfrom(l->fd, (void *)buf, sizeof(buf), 0,
(struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) { (struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) {
/* IO error, cleanup this listener. */ /* IO error, cleanup this listener. */
loop->vmt->clear(loop, &l->event); loop->vmt->clear(loop, &l->event);
@ -574,37 +617,33 @@ static void udp_read_cb(void *userarg)
else { else {
/* Insert connection */ /* Insert connection */
conn->super.key = conn;
if (!_getdns_rbtree_insert(
&l->set->connections_set, &conn->super)) {
/* Memory error */
GETDNS_FREE(*mf, conn);
return;
}
DEBUG_SERVER("[connection add] count: %d\n",
(int)l->set->connections_set.count);
if ((conn->next = l->connections)) if ((conn->next = l->connections))
conn->next->prev_next = &conn->next; conn->next->prev_next = &conn->next;
conn->prev_next = &l->connections; conn->prev_next = &l->connections;
l->connections = conn; l->connections = conn;
/* TODO: wish list item:
* (void) getdns_dict_set_int64(
* request_dict, "request_id", (intptr_t)conn);
*/
/* Call request handler */ /* Call request handler */
l->set->handler(l->set->context, request_dict, (intptr_t)conn); l->set->handler(l->set->context, GETDNS_CALLBACK_COMPLETE,
request_dict, l->set->userarg, (intptr_t)conn);
return; return;
} }
GETDNS_FREE(*mf, conn); GETDNS_FREE(*mf, conn);
} }
static void rm_listen_set(listen_set **root, listen_set *set)
{
assert(root);
while (*root && *root != set)
root = &(*root)->next;
*root = set->next;
set->next = NULL;
}
static listen_set *lookup_listen_set(listen_set *root, getdns_context *key)
{
while (root && root->context != key)
root = root->next;
return root;
}
static void free_listen_set_when_done(listen_set *set) static void free_listen_set_when_done(listen_set *set)
{ {
struct mem_funcs *mf; struct mem_funcs *mf;
@ -613,7 +652,7 @@ static void free_listen_set_when_done(listen_set *set)
assert(set); assert(set);
assert(set->context); assert(set->context);
if (!(mf = priv_getdns_context_mf(set->context))) if (!(mf = &set->context->mf))
return; return;
DEBUG_SERVER("To free listen set: %p\n", (void *)set); DEBUG_SERVER("To free listen set: %p\n", (void *)set);
@ -639,7 +678,7 @@ static void remove_listeners(listen_set *set)
assert(set); assert(set);
assert(set->context); assert(set->context);
if (!(mf = priv_getdns_context_mf(set->context))) if (!(mf = &set->context->mf))
return; return;
if (getdns_context_get_eventloop(set->context, &loop)) if (getdns_context_get_eventloop(set->context, &loop))
@ -663,7 +702,8 @@ static void remove_listeners(listen_set *set)
while (*conn_p) { while (*conn_p) {
tcp_connection_destroy(*conn_p); tcp_connection_destroy(*conn_p);
if (*conn_p && (*conn_p)->to_answer > 0) if (*conn_p && (*conn_p)->to_answer > 0)
conn_p = (tcp_connection **)&(*conn_p)->next; conn_p = (tcp_connection **)
&(*conn_p)->super.next;
} }
} }
free_listen_set_when_done(set); free_listen_set_when_done(set);
@ -671,7 +711,11 @@ static void remove_listeners(listen_set *set)
static getdns_return_t add_listeners(listen_set *set) static getdns_return_t add_listeners(listen_set *set)
{ {
#ifdef USE_WINSOCK
static const char enable = 1;
#else
static const int enable = 1; static const int enable = 1;
#endif
struct mem_funcs *mf; struct mem_funcs *mf;
getdns_eventloop *loop; getdns_eventloop *loop;
@ -681,7 +725,7 @@ static getdns_return_t add_listeners(listen_set *set)
assert(set); assert(set);
assert(set->context); assert(set->context);
if (!(mf = priv_getdns_context_mf(set->context))) if (!(mf = &set->context->mf))
return GETDNS_RETURN_GENERIC_ERROR; return GETDNS_RETURN_GENERIC_ERROR;
if ((r = getdns_context_get_eventloop(set->context, &loop))) if ((r = getdns_context_get_eventloop(set->context, &loop)))
@ -738,17 +782,21 @@ static getdns_return_t add_listeners(listen_set *set)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
getdns_return_t getdns_context_set_listen_addresses(getdns_context *context, static int
getdns_request_handler_t request_handler, ptr_cmp(const void *a, const void *b)
const getdns_list *listen_addresses) {
return a == b ? 0 : (a < b ? -1 : 1);
}
getdns_return_t getdns_context_set_listen_addresses(
getdns_context *context, const getdns_list *listen_addresses,
void *userarg, getdns_request_handler_t request_handler)
{ {
static const getdns_transport_list_t listen_transports[] static const getdns_transport_list_t listen_transports[]
= { GETDNS_TRANSPORT_UDP, GETDNS_TRANSPORT_TCP }; = { GETDNS_TRANSPORT_UDP, GETDNS_TRANSPORT_TCP };
static const uint32_t transport_ports[] = { 53, 53 }; static const uint32_t transport_ports[] = { 53, 53 };
static const size_t n_transports = sizeof( listen_transports) static const size_t n_transports = sizeof( listen_transports)
/ sizeof(*listen_transports); / sizeof(*listen_transports);
static listen_set *root = NULL;
listen_set *current_set; listen_set *current_set;
listen_set *new_set; listen_set *new_set;
size_t new_set_count; size_t new_set_count;
@ -763,7 +811,8 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context,
DEBUG_SERVER("getdns_context_set_listen_addresses(%p, <func>, %p)\n", DEBUG_SERVER("getdns_context_set_listen_addresses(%p, <func>, %p)\n",
(void *)context, (void *)listen_addresses); (void *)context, (void *)listen_addresses);
if (!(mf = priv_getdns_context_mf(context)))
if (!(mf = &context->mf))
return GETDNS_RETURN_GENERIC_ERROR; return GETDNS_RETURN_GENERIC_ERROR;
if ((r = getdns_context_get_eventloop(context, &loop))) if ((r = getdns_context_get_eventloop(context, &loop)))
@ -775,7 +824,7 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context,
else if ((r = getdns_list_get_length(listen_addresses, &new_set_count))) else if ((r = getdns_list_get_length(listen_addresses, &new_set_count)))
return r; return r;
if ((current_set = lookup_listen_set(root, context))) { if ((current_set = context->server)) {
for (i = 0; i < current_set->count; i++) for (i = 0; i < current_set->count; i++)
current_set->items[i].action = to_remove; current_set->items[i].action = to_remove;
} }
@ -783,7 +832,7 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context,
if (!current_set) if (!current_set)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
rm_listen_set(&root, current_set); context->server = NULL;
/* action is already to_remove */ /* action is already to_remove */
remove_listeners(current_set); remove_listeners(current_set);
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
@ -796,12 +845,14 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context,
sizeof(listener) * new_set_count * n_transports))) sizeof(listener) * new_set_count * n_transports)))
return GETDNS_RETURN_MEMORY_ERROR; return GETDNS_RETURN_MEMORY_ERROR;
_getdns_rbtree_init(&new_set->connections_set, ptr_cmp);
DEBUG_SERVER("New listen set: %p, current_set: %p\n", DEBUG_SERVER("New listen set: %p, current_set: %p\n",
(void *)new_set, (void *)current_set); (void *)new_set, (void *)current_set);
new_set->context = context; new_set->context = context;
new_set->next = root;
new_set->handler = request_handler; new_set->handler = request_handler;
new_set->userarg = userarg;
new_set->count = new_set_count * n_transports; new_set->count = new_set_count * n_transports;
(void) memset(new_set->items, 0, (void) memset(new_set->items, 0,
sizeof(listener) * new_set_count * n_transports); sizeof(listener) * new_set_count * n_transports);
@ -941,10 +992,10 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context,
} }
} }
if (current_set) { if (current_set) {
rm_listen_set(&root, current_set); context->server = NULL;
remove_listeners(current_set); /* Is already remove */ remove_listeners(current_set); /* Is already remove */
} }
root = new_set; context->server = new_set;
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }

View File

@ -1,3 +1,11 @@
/**
* \file server.h
* @brief Functions for serving requests
*
* getdns_context_set_listen_addresses() and getdns_reply() are implemented
* here.
*/
/* /*
* Copyright (c) 2013, NLNet Labs, Verisign, Inc. * Copyright (c) 2013, NLNet Labs, Verisign, Inc.
* All rights reserved. * All rights reserved.
@ -24,18 +32,9 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef _GETDNS_SERVER_H_
#define _GETDNS_SERVER_H_
#include "getdns/getdns.h" struct listen_set;
#ifndef GETDNS_CONTEXT_CONFIG_H_
#define GETDNS_CONTEXT_CONFIG_H_
/*
getdns_return_t getdns_context_config(
getdns_context *context, const getdns_dict *config_dict);
*/
getdns_return_t _getdns_context_config_(getdns_context *context,
getdns_dict *extensions, const getdns_dict *config_dict);
#endif
#endif /* _GETDNS_SERVER_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -67,20 +67,14 @@ CHECK_CFLAGS=@CHECK_CFLAGS@
CHECK_OBJS=check_getdns_common.lo check_getdns_context_set_timeout.lo \ CHECK_OBJS=check_getdns_common.lo check_getdns_context_set_timeout.lo \
check_getdns.lo check_getdns_transport.lo check_getdns.lo check_getdns_transport.lo
DECOMPOSED_OBJS_WITHOUT_JSMN=getdns_str2dict.lo getdns_context_config.lo \
getdns_context_set_listen_addresses.lo
DECOMPOSED_OBJS=$(DECOMPOSED_OBJS_WITHOUT_JSMN) jsmn.lo
ALL_OBJS=$(CHECK_OBJS) check_getdns_libevent.lo check_getdns_libev.lo \ ALL_OBJS=$(CHECK_OBJS) check_getdns_libevent.lo check_getdns_libev.lo \
check_getdns_selectloop.lo getdns_query.lo scratchpad.lo \ check_getdns_selectloop.lo scratchpad.lo \
testmessages.lo tests_dict.lo tests_list.lo tests_namespaces.lo \ testmessages.lo tests_dict.lo tests_list.lo tests_namespaces.lo \
tests_stub_async.lo tests_stub_sync.lo \ tests_stub_async.lo tests_stub_sync.lo
$(DECOMPOSED_OBJS_WITHOUT_JSMN)
NON_C99_OBJS=check_getdns_libuv.lo NON_C99_OBJS=check_getdns_libuv.lo
PROGRAMS=tests_dict tests_list tests_namespaces tests_stub_async tests_stub_sync getdns_query $(CHECK_GETDNS) $(CHECK_EV_PROG) $(CHECK_EVENT_PROG) $(CHECK_UV_PROG) PROGRAMS=tests_dict tests_list tests_namespaces tests_stub_async tests_stub_sync $(CHECK_GETDNS) $(CHECK_EV_PROG) $(CHECK_EVENT_PROG) $(CHECK_UV_PROG)
.SUFFIXES: .c .o .a .lo .h .SUFFIXES: .c .o .a .lo .h
@ -95,9 +89,6 @@ default: all
all: $(PROGRAMS) all: $(PROGRAMS)
jsmn.lo:
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -DJSMN_GETDNS -c $(srcdir)/jsmn/jsmn.c -o $@
$(ALL_OBJS): $(ALL_OBJS):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -c $(srcdir)/$(@:.lo=.c) -o $@ $(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -c $(srcdir)/$(@:.lo=.c) -o $@
@ -134,9 +125,6 @@ check_getdns_uv: check_getdns.lo check_getdns_common.lo check_getdns_context_set
check_getdns_ev: check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libev.lo ../libgetdns_ext_ev.la check_getdns_ev: check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libev.lo ../libgetdns_ext_ev.la
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libev.lo $(LDFLAGS) $(LDLIBS) $(CHECK_LIBS) ../libgetdns_ext_ev.la $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ check_getdns.lo check_getdns_common.lo check_getdns_context_set_timeout.lo check_getdns_transport.lo check_getdns_libev.lo $(LDFLAGS) $(LDLIBS) $(CHECK_LIBS) ../libgetdns_ext_ev.la $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS)
getdns_query: getdns_query.lo $(DECOMPOSED_OBJS)
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ getdns_query.lo $(DECOMPOSED_OBJS) $(LDFLAGS) $(LDLIBS)
scratchpad: scratchpad.lo scratchpad: scratchpad.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ scratchpad.lo $(LDFLAGS) $(LDLIBS) $(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ scratchpad.lo $(LDFLAGS) $(LDLIBS)
@ -145,12 +133,11 @@ scratchpad.lo: scratchpad.c
$(srcdir)/scratchpad.c: scratchpad.template.c $(srcdir)/scratchpad.c: scratchpad.template.c
[ ! -f $(srcdir)/scratchpad.c ] && cp -p $(srcdir)/scratchpad.template.c $(srcdir)/scratchpad.c || true [ ! -f $(srcdir)/scratchpad.c ] && cp -p $(srcdir)/scratchpad.template.c $(srcdir)/scratchpad.c || true
install: getdns_query install:
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir) echo nothing to install
$(LIBTOOL) --mode=install cp getdns_query $(DESTDIR)$(bindir)
uninstall: uninstall:
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/getdns_query echo nothing to uninstall
nolibcheck: nolibcheck:
@echo "***" @echo "***"
@ -222,7 +209,6 @@ depend:
-e 's? \$$(srcdir)/\.\./config\.h? ../config.h?g' \ -e 's? \$$(srcdir)/\.\./config\.h? ../config.h?g' \
-e 's? \$$(srcdir)/\.\./getdns/getdns\.h? ../getdns/getdns.h?g' \ -e 's? \$$(srcdir)/\.\./getdns/getdns\.h? ../getdns/getdns.h?g' \
-e 's? \$$(srcdir)/\.\./getdns/getdns_extra\.h? ../getdns/getdns_extra.h?g' \ -e 's? \$$(srcdir)/\.\./getdns/getdns_extra\.h? ../getdns/getdns_extra.h?g' \
-e 's? jsmn/jsmn\.h? $$(srcdir)/jsmn/jsmn.h?g' \
-e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' >> Makefile.in.new ) -e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' >> Makefile.in.new )
(cd $(srcdir) ; diff Makefile.in.new Makefile.in && rm Makefile.in.new \ (cd $(srcdir) ; diff Makefile.in.new Makefile.in && rm Makefile.in.new \
|| mv Makefile.in.new Makefile.in ) || mv Makefile.in.new Makefile.in )
@ -274,20 +260,6 @@ check_getdns_selectloop.lo check_getdns_selectloop.o: $(srcdir)/check_getdns_sel
check_getdns_transport.lo check_getdns_transport.o: $(srcdir)/check_getdns_transport.c \ check_getdns_transport.lo check_getdns_transport.o: $(srcdir)/check_getdns_transport.c \
$(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \ $(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h ../getdns/getdns.h \
../getdns/getdns_extra.h ../getdns/getdns_extra.h
getdns_context_config.lo getdns_context_config.o: $(srcdir)/getdns_context_config.c $(srcdir)/getdns_context_config.h \
../getdns/getdns.h ../getdns/getdns_extra.h
getdns_context_set_listen_addresses.lo getdns_context_set_listen_addresses.o: \
$(srcdir)/getdns_context_set_listen_addresses.c ../config.h \
$(srcdir)/getdns_context_set_listen_addresses.h ../getdns/getdns.h \
../getdns/getdns_extra.h $(srcdir)/../types-internal.h ../getdns/getdns.h \
../getdns/getdns_extra.h $(srcdir)/../util/rbtree.h $(srcdir)/../debug.h ../config.h
getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \
$(srcdir)/getdns_str2dict.h ../getdns/getdns.h $(srcdir)/getdns_context_config.h \
$(srcdir)/getdns_context_set_listen_addresses.h ../getdns/getdns_extra.h
getdns_str2dict.lo getdns_str2dict.o: $(srcdir)/getdns_str2dict.c ../config.h $(srcdir)/../const-info.h \
$(srcdir)/jsmn/jsmn.h $(srcdir)/getdns_str2dict.h ../getdns/getdns.h $(srcdir)/../types-internal.h \
../getdns/getdns.h ../getdns/getdns_extra.h $(srcdir)/../util/rbtree.h $(srcdir)/../list.h \
$(srcdir)/../types-internal.h $(srcdir)/../dict.h
scratchpad.template.lo scratchpad.template.o: scratchpad.template.c ../getdns/getdns.h \ scratchpad.template.lo scratchpad.template.o: scratchpad.template.c ../getdns/getdns.h \
../getdns/getdns_extra.h ../getdns/getdns_extra.h
testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h

View File

@ -300,6 +300,7 @@
} }
CONTEXT_DESTROY; CONTEXT_DESTROY;
getdns_dict_destroy(extensions); getdns_dict_destroy(extensions);
getdns_list_destroy(root_servers); getdns_list_destroy(root_servers);

View File

@ -1,220 +0,0 @@
/*
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "getdns_context_config.h"
#include "getdns/getdns_extra.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
static int _streq(const getdns_bindata *name, const char *str)
{
if (strlen(str) != name->size)
return 0;
else return strncmp((const char *)name->data, str, name->size) == 0;
}
static getdns_return_t _get_list_or_read_file(const getdns_dict *config_dict,
const char *setting, getdns_list **r_list, int *destroy_list)
{
getdns_bindata *fn_bd;
char fn[FILENAME_MAX];
FILE *fh;
getdns_return_t r;
assert(r_list);
assert(destroy_list);
*destroy_list = 0;
if (!(r = getdns_dict_get_list(config_dict, setting, r_list)))
return GETDNS_RETURN_GOOD;
else if ((r = getdns_dict_get_bindata(config_dict, setting, &fn_bd)))
return r;
else if (fn_bd->size >= FILENAME_MAX)
return GETDNS_RETURN_INVALID_PARAMETER;
(void)memcpy(fn, fn_bd->data, fn_bd->size);
fn[fn_bd->size] = 0;
if (!(fh = fopen(fn, "r")))
return GETDNS_RETURN_GENERIC_ERROR;
if (!(r = getdns_fp2rr_list(fh, r_list, NULL, 3600)))
*destroy_list = 1;
fclose(fh);
return r;
}
#define CONTEXT_SETTING_INT(X) \
} else if (_streq(setting, #X)) { \
if (!(r = getdns_dict_get_int(config_dict, #X , &n))) \
r = getdns_context_set_ ## X (context, n);
#define CONTEXT_SETTING_LIST(X) \
} else if (_streq(setting, #X)) { \
if (!(r = getdns_dict_get_list(config_dict, #X , &list))) \
r = getdns_context_set_ ## X (context, list);
#define CONTEXT_SETTING_LIST_OR_ZONEFILE(X) \
} else if (_streq(setting, #X)) { \
if (!(r = _get_list_or_read_file( \
config_dict, #X , &list, &destroy_list))) \
r = getdns_context_set_ ## X(context, list); \
if (destroy_list) getdns_list_destroy(list);
#define CONTEXT_SETTING_ARRAY(X, T) \
} else if (_streq(setting, #X )) { \
if (!(r = getdns_dict_get_list(config_dict, #X , &list)) && \
!(r = getdns_list_get_length(list, &count))) { \
for (i=0; i<count && i<(sizeof(X)/sizeof(*X)); i++) { \
if ((r = getdns_list_get_int(list, i, &n))) \
break; \
X[i] = (getdns_ ## T ## _t)n; \
} \
r = getdns_context_set_ ##X (context, count, X); \
}
#define EXTENSION_SETTING_INT(X) \
} else if (_streq(setting, #X )) { \
if (!(r = getdns_dict_get_int(config_dict, #X , &n))) \
r = getdns_dict_set_int(extensions, #X , n);
#define EXTENSION_SETTING_DICT(X) \
} else if (_streq(setting, #X )) { \
if (!(r = getdns_dict_get_dict(config_dict, #X , &dict))) \
r = getdns_dict_set_dict(extensions, #X , dict);
static getdns_return_t
_getdns_context_config_setting_(
getdns_context *context, getdns_dict *extensions,
const getdns_dict *config_dict, const getdns_bindata *setting)
{
getdns_return_t r = GETDNS_RETURN_GOOD;
getdns_dict *dict;
getdns_list *list;
getdns_namespace_t namespaces[100];
getdns_transport_list_t dns_transport_list[100];
size_t count, i;
uint32_t n;
int destroy_list = 0;
if (_streq(setting, "all_context")) {
if (!(r = getdns_dict_get_dict(config_dict, "all_context", &dict)))
r = _getdns_context_config_(context, extensions, dict);
CONTEXT_SETTING_INT(resolution_type)
CONTEXT_SETTING_ARRAY(namespaces, namespace)
CONTEXT_SETTING_INT(dns_transport)
CONTEXT_SETTING_ARRAY(dns_transport_list, transport_list)
CONTEXT_SETTING_INT(idle_timeout)
CONTEXT_SETTING_INT(limit_outstanding_queries)
CONTEXT_SETTING_INT(timeout)
CONTEXT_SETTING_INT(follow_redirects)
CONTEXT_SETTING_LIST_OR_ZONEFILE(dns_root_servers)
CONTEXT_SETTING_INT(append_name)
CONTEXT_SETTING_LIST(suffix)
CONTEXT_SETTING_LIST_OR_ZONEFILE(dnssec_trust_anchors)
CONTEXT_SETTING_INT(dnssec_allowed_skew)
CONTEXT_SETTING_LIST(upstream_recursive_servers)
CONTEXT_SETTING_INT(edns_maximum_udp_payload_size)
CONTEXT_SETTING_INT(edns_extended_rcode)
CONTEXT_SETTING_INT(edns_version)
CONTEXT_SETTING_INT(edns_do_bit)
/***************************************/
/**** ****/
/**** Unofficial context settings ****/
/**** ****/
/***************************************/
CONTEXT_SETTING_INT(edns_client_subnet_private)
CONTEXT_SETTING_INT(tls_authentication)
CONTEXT_SETTING_INT(tls_query_padding_blocksize)
/**************************************/
/**** ****/
/**** Default extensions setting ****/
/**** ****/
/**************************************/
EXTENSION_SETTING_DICT(add_opt_parameters)
EXTENSION_SETTING_INT(add_warning_for_bad_dns)
EXTENSION_SETTING_INT(dnssec_return_all_statuses)
EXTENSION_SETTING_INT(dnssec_return_full_validation_chain)
EXTENSION_SETTING_INT(dnssec_return_only_secure)
EXTENSION_SETTING_INT(dnssec_return_status)
EXTENSION_SETTING_INT(dnssec_return_validation_chain)
#if defined(DNSSEC_ROADBLOCK_AVOIDANCE) && defined(HAVE_LIBUNBOUND)
EXTENSION_SETTING_INT(dnssec_roadblock_avoidance)
#endif
#ifdef EDNS_COOKIES
EXTENSION_SETTING_INT(edns_cookies)
#endif
EXTENSION_SETTING_DICT(header)
EXTENSION_SETTING_INT(return_api_information)
EXTENSION_SETTING_INT(return_both_v4_and_v6)
EXTENSION_SETTING_INT(return_call_reporting)
EXTENSION_SETTING_INT(specify_class)
/************************************/
/**** ****/
/**** Ignored context settings ****/
/**** ****/
/************************************/
} else if (!_streq(setting, "implementation_string") &&
!_streq(setting, "version_string")) {
r = GETDNS_RETURN_NOT_IMPLEMENTED;
}
return r;
}
getdns_return_t
_getdns_context_config_(getdns_context *context,
getdns_dict *extensions, const getdns_dict *config_dict)
{
getdns_list *settings;
getdns_return_t r;
getdns_bindata *setting;
size_t i;
if ((r = getdns_dict_get_names(config_dict, &settings)))
return r;
for (i = 0; !(r = getdns_list_get_bindata(settings,i,&setting)); i++) {
if ((r = _getdns_context_config_setting_(
context, extensions, config_dict, setting)))
break;
}
if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM)
r = GETDNS_RETURN_GOOD;
getdns_list_destroy(settings);
return r;
}

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GETDNS_CONTEXT_SET_LISTEN_ADDRESSES_H_
#define GETDNS_CONTEXT_SET_LISTEN_ADDRESSES_H_
#include "getdns/getdns.h"
typedef void (*getdns_request_handler_t)(
getdns_context *context,
getdns_dict *request,
getdns_transaction_t request_id
);
getdns_return_t getdns_context_set_listen_addresses(
getdns_context *context, getdns_request_handler_t request_handler,
const getdns_list *listen_addresses);
getdns_return_t getdns_reply(getdns_context *context,
getdns_transaction_t request_id, getdns_dict *reply);
void _getdns_cancel_reply(getdns_context *context,
getdns_transaction_t request_id);
#endif

View File

@ -1,971 +0,0 @@
/*
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "const-info.h"
#include "jsmn/jsmn.h"
#include "getdns_str2dict.h"
#include "types-internal.h" /* For getdns_item */
#include "list.h" /* For _getdns_list_create_from_mf() */
#include "dict.h" /* For _getdns_dict_create_from_mf() */
#include <stdlib.h> /* For bsearch */
#include <ctype.h> /* For isspace */
static struct mem_funcs _getdns_plain_mem_funcs = {
MF_PLAIN, .mf.pln = { malloc, realloc, free }
};
/* TODO: Replace with gldns_b64_pton
* once getdns_ipaddr_dict becomes part of the library
*/
static int _gldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
{
const uint8_t pad64 = 64; /* is 64th in the b64 array */
const char* s = src;
uint8_t in[4];
size_t o = 0, incount = 0;
while(*s) {
/* skip any character that is not base64 */
/* conceptually we do:
const char* b64 = pad'=' is appended to array
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
const char* d = strchr(b64, *s++);
and use d-b64;
*/
char d = *s++;
if(d <= 'Z' && d >= 'A')
d -= 'A';
else if(d <= 'z' && d >= 'a')
d = d - 'a' + 26;
else if(d <= '9' && d >= '0')
d = d - '0' + 52;
else if(d == '+')
d = 62;
else if(d == '/')
d = 63;
else if(d == '=')
d = 64;
else continue;
in[incount++] = (uint8_t)d;
if(incount != 4)
continue;
/* process whole block of 4 characters into 3 output bytes */
if(in[3] == pad64 && in[2] == pad64) { /* A B = = */
if(o+1 > targsize)
return -1;
target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
o += 1;
break; /* we are done */
} else if(in[3] == pad64) { /* A B C = */
if(o+2 > targsize)
return -1;
target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
target[o+1]= ((in[1]&0x0f)<<4) | ((in[2]&0x3c)>>2);
o += 2;
break; /* we are done */
} else {
if(o+3 > targsize)
return -1;
/* write xxxxxxyy yyyyzzzz zzwwwwww */
target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
target[o+1]= ((in[1]&0x0f)<<4) | ((in[2]&0x3c)>>2);
target[o+2]= ((in[2]&0x03)<<6) | in[3];
o += 3;
}
incount = 0;
}
return (int)o;
}
static getdns_dict *
_getdns_ipaddr_dict_mf(struct mem_funcs *mf, const char *ipstr)
{
getdns_dict *r = _getdns_dict_create_with_mf(mf);
char *s = strchr(ipstr, '%'), *scope_id_str = "";
char *p = strchr(ipstr, '@'), *portstr = "";
char *t = strchr(ipstr, '#'), *tls_portstr = "";
char *n = strchr(ipstr, '~'), *tls_namestr = "";
/* ^[alg:]name:key */
char *T = strchr(ipstr, '^'), *tsig_name_str = ""
, *tsig_secret_str = ""
, *tsig_algorithm_str = "";
char *br, *c;
int tsig_secret_size;
uint8_t tsig_secret_buf[256]; /* 4 times SHA512 */
getdns_bindata tsig_secret;
uint8_t buf[sizeof(struct in6_addr)];
getdns_bindata addr;
addr.data = buf;
if (!r) return NULL;
if (*ipstr == '[') {
char *br = strchr(ipstr, ']');
if (br) {
ipstr += 1;
*br = 0;
if ((c = strchr(br + 1, ':'))) {
p = c;
}
}
} else if ((br = strchr(ipstr, '.')) && (c = strchr(br + 1, ':'))
&& (T == NULL || c < T))
p = c;
else if ((*ipstr == '*') && (c = strchr(ipstr+1, ':')))
p = c;
if (s) {
*s = 0;
scope_id_str = s + 1;
}
if (p) {
*p = 0;
portstr = p + 1;
}
if (t) {
*t = 0;
tls_portstr = t + 1;
}
if (n) {
*n = 0;
tls_namestr = n + 1;
}
if (T) {
*T = 0;
tsig_name_str = T + 1;
if ((T = strchr(tsig_name_str, ':'))) {
*T = 0;
tsig_secret_str = T + 1;
if ((T = strchr(tsig_secret_str, ':'))) {
*T = 0;
tsig_algorithm_str = tsig_name_str;
tsig_name_str = tsig_secret_str;
tsig_secret_str = T + 1;
}
} else {
tsig_name_str = "";
}
}
if (*ipstr == '*') {
getdns_dict_util_set_string(r, "address_type", "IPv6");
addr.size = 16;
(void) memset(buf, 0, 16);
} else if (strchr(ipstr, ':')) {
getdns_dict_util_set_string(r, "address_type", "IPv6");
addr.size = 16;
if (inet_pton(AF_INET6, ipstr, buf) <= 0) {
getdns_dict_destroy(r);
return NULL;
}
} else {
getdns_dict_util_set_string(r, "address_type", "IPv4");
addr.size = 4;
if (inet_pton(AF_INET, ipstr, buf) <= 0) {
getdns_dict_destroy(r);
return NULL;
}
}
getdns_dict_set_bindata(r, "address_data", &addr);
if (*portstr)
getdns_dict_set_int(r, "port", (int32_t)atoi(portstr));
if (*tls_portstr)
getdns_dict_set_int(r, "tls_port", (int32_t)atoi(tls_portstr));
if (*tls_namestr) {
getdns_dict_util_set_string(r, "tls_auth_name", tls_namestr);
}
if (*scope_id_str)
getdns_dict_util_set_string(r, "scope_id", scope_id_str);
if (*tsig_name_str)
getdns_dict_util_set_string(r, "tsig_name", tsig_name_str);
if (*tsig_algorithm_str)
getdns_dict_util_set_string(r, "tsig_algorithm", tsig_algorithm_str);
if (*tsig_secret_str) {
tsig_secret_size = _gldns_b64_pton(
tsig_secret_str, tsig_secret_buf, sizeof(tsig_secret_buf));
if (tsig_secret_size > 0) {
tsig_secret.size = tsig_secret_size;
tsig_secret.data = tsig_secret_buf;
getdns_dict_set_bindata(r, "tsig_secret", &tsig_secret);
}
}
return r;
}
static int _jsmn_get_ipdict(struct mem_funcs *mf, const char *js, jsmntok_t *t,
getdns_dict **value)
{
char value_str[3072];
int size = t->end - t->start;
if (size <= 0 || size >= (int)sizeof(value_str))
return 0;
(void) memcpy(value_str, js + t->start, size);
value_str[size] = '\0';
*value = _getdns_ipaddr_dict_mf(mf, value_str);
return *value != NULL;
}
static int _jsmn_get_data(struct mem_funcs *mf, const char *js, jsmntok_t *t,
getdns_bindata **value)
{
int i;
size_t j;
uint8_t h, l;
if ((t->end - t->start) < 4 || (t->end - t->start) % 2 == 1 ||
js[t->start] != '0' || js[t->start + 1] != 'x')
return 0;
for (i = t->start + 2; i < t->end; i++)
if (!((js[i] >= '0' && js[i] <= '9')
||(js[i] >= 'a' && js[i] <= 'f')
||(js[i] >= 'A' && js[i] <= 'F')))
return 0;
if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
return 0;
else if (!((*value)->data = GETDNS_XMALLOC(
*mf, uint8_t, (t->end - t->start) / 2 - 1))) {
GETDNS_FREE(*mf, *value);
return 0;
}
for (i = t->start + 2, j = 0; i < t->end; i++, j++) {
h = js[i] >= '0' && js[i] <= '9' ? js[i] - '0'
: js[i] >= 'A' && js[i] <= 'F' ? js[i] + 10 - 'A'
: js[i] + 10 - 'a';
h <<= 4;
i++;
l = js[i] >= '0' && js[i] <= '9' ? js[i] - '0'
: js[i] >= 'A' && js[i] <= 'F' ? js[i] + 10 - 'A'
: js[i] + 10 - 'a';
(*value)->data[j] = h | l;
}
(*value)->size = j;
return 1;
}
static int _jsmn_get_dname(const char *js, jsmntok_t *t,
getdns_bindata **value)
{
char value_str[1025];
int size = t->end - t->start;
if (size <= 0 || size >= (int)sizeof(value_str) || js[t->end - 1] != '.')
return 0;
(void) memcpy(value_str, js + t->start, size);
value_str[size] = '\0';
return !getdns_convert_fqdn_to_dns_name(value_str, value);
}
static int _jsmn_get_ipv4(struct mem_funcs *mf, const char *js, jsmntok_t *t,
getdns_bindata **value)
{
char value_str[16];
int size = t->end - t->start;
uint8_t buf[4];
if (size <= 0 || size >= (int)sizeof(value_str))
return 0;
(void) memcpy(value_str, js + t->start, size);
value_str[size] = '\0';
if (inet_pton(AF_INET, value_str, buf) <= 0)
; /* pass */
else if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
; /* pass */
else if (!((*value)->data = GETDNS_XMALLOC(*mf, uint8_t, 4)))
GETDNS_FREE(*mf, *value);
else {
(*value)->size = 4;
(void) memcpy((*value)->data, buf, 4);
return 1;
}
return 0;
}
static int _jsmn_get_ipv6(struct mem_funcs *mf, const char *js, jsmntok_t *t,
getdns_bindata **value)
{
char value_str[40];
int size = t->end - t->start;
uint8_t buf[16];
if (size <= 0 || size >= (int)sizeof(value_str))
return 0;
(void) memcpy(value_str, js + t->start, size);
value_str[size] = '\0';
if (inet_pton(AF_INET6, value_str, buf) <= 0)
; /* pass */
else if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
; /* pass */
else if (!((*value)->data = GETDNS_XMALLOC(*mf, uint8_t, 16)))
GETDNS_FREE(*mf, *value);
else {
(*value)->size = 16;
(void) memcpy((*value)->data, buf, 16);
return 1;
}
return 0;
}
static int _jsmn_get_int(const char *js, jsmntok_t *t, uint32_t *value)
{
char value_str[11];
int size = t->end - t->start;
char *endptr;
if (size <= 0 || size >= (int)sizeof(value_str))
return 0;
(void) memcpy(value_str, js + t->start, size);
value_str[size] = '\0';
*value = (uint32_t)strtoul(value_str, &endptr, 10);
return *value_str != '\0' && *endptr == '\0';
}
static int _getdns_get_const_name_info(const char *name, uint32_t *code);
static int _jsmn_get_const(const char *js, jsmntok_t *t, uint32_t *value)
{
char value_str[80];
int size = t->end - t->start;
if (size <= 0 || size >= (int)sizeof(value_str))
return 0;
(void) memcpy(value_str, js + t->start, size);
value_str[size] = '\0';
return _getdns_get_const_name_info(value_str, value);
}
static void
_getdns_destroy_item_data(struct mem_funcs *mf, getdns_item *item)
{
switch (item->dtype) {
case t_dict:
getdns_dict_destroy(item->data.dict);
break;
case t_list:
getdns_list_destroy(item->data.list);
break;
case t_bindata:
GETDNS_FREE(*mf, item->data.bindata->data);
GETDNS_FREE(*mf, item->data.bindata);
default:
break;
}
}
static int _jsmn_get_item(struct mem_funcs *mf, const char *js, jsmntok_t *t,
size_t count, getdns_item *item, getdns_return_t *r);
static int _jsmn_get_dict(struct mem_funcs *mf, const char *js, jsmntok_t *t,
size_t count, getdns_dict *dict, getdns_return_t *r)
{
int i;
size_t j = 1;
char key_spc[1024], *key = NULL;
getdns_item child_item;
if (t->size <= 0)
*r = GETDNS_RETURN_GOOD;
else for (i = 0; i < t->size; i++) {
if (t[j].type != JSMN_STRING &&
t[j].type != JSMN_PRIMITIVE) {
/* Key must be string or primitive */
*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
break;
}
if (t[j].end <= t[j].start) {
/* Key must be at least 1 character */
*r = GETDNS_RETURN_GENERIC_ERROR; /* range error */
break;
}
if (t[j].end - t[j].start < (int)sizeof(key_spc))
key = key_spc;
else if (!(key = GETDNS_XMALLOC(
*mf, char, t[j].end - t[j].start + 1))) {
*r = GETDNS_RETURN_MEMORY_ERROR;
break;
}
(void) memcpy(key, js + t[j].start, t[j].end - t[j].start);
key[t[j].end - t[j].start] = '\0';
j += 1;
j += _jsmn_get_item(mf, js, t + j, count - j, &child_item, r);
if (*r) break;
switch (child_item.dtype) {
case t_int:
*r = getdns_dict_set_int(dict, key,
child_item.data.n);
break;
case t_bindata:
*r = getdns_dict_set_bindata(dict, key,
child_item.data.bindata);
break;
case t_list:
*r = getdns_dict_set_list(dict, key,
child_item.data.list);
break;
case t_dict:
*r = getdns_dict_set_dict(dict, key,
child_item.data.dict);
break;
default:
*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
break;
}
_getdns_destroy_item_data(mf, &child_item);
if (*r) break;
if (key && key != key_spc) {
GETDNS_FREE(*mf, key);
key = NULL;
}
}
if (key && key != key_spc)
GETDNS_FREE(*mf, key);
if (*r) {
getdns_dict_destroy(dict);
return 0;
}
return j;
}
static int _jsmn_get_list(struct mem_funcs *mf, const char *js, jsmntok_t *t,
size_t count, getdns_list *list, getdns_return_t *r)
{
int i;
size_t j = 1, index = 0;
getdns_item child_item;
if (t->size <= 0)
*r = GETDNS_RETURN_GOOD;
else for (i = 0; i < t->size; i++) {
j += _jsmn_get_item(mf, js, t + j, count - j, &child_item, r);
if (*r) break;
switch (child_item.dtype) {
case t_int:
*r = getdns_list_set_int(list, index++,
child_item.data.n);
break;
case t_bindata:
*r = getdns_list_set_bindata(list, index++,
child_item.data.bindata);
break;
case t_list:
*r = getdns_list_set_list(list, index++,
child_item.data.list);
break;
case t_dict:
*r = getdns_list_set_dict(list, index++,
child_item.data.dict);
break;
default:
*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
break;
}
_getdns_destroy_item_data(mf, &child_item);
if (*r) break;
}
if (*r) {
getdns_list_destroy(list);
return 0;
}
return j;
}
static int _jsmn_get_item(struct mem_funcs *mf, const char *js, jsmntok_t *t,
size_t count, getdns_item *item, getdns_return_t *r)
{
assert(item);
switch (t->type) {
case JSMN_STRING:
if (t->end < t->start)
*r = GETDNS_RETURN_GENERIC_ERROR;
else if (!(item->data.bindata =
GETDNS_MALLOC(*mf, getdns_bindata)))
*r = GETDNS_RETURN_MEMORY_ERROR;
else if (!(item->data.bindata->data = GETDNS_XMALLOC(
*mf, uint8_t, t->end - t->start + 1))) {
GETDNS_FREE(*mf, item->data.bindata);
*r = GETDNS_RETURN_MEMORY_ERROR;
} else {
item->dtype = t_bindata;
if (t->end - t->start) {
(void) memcpy(item->data.bindata->data,
js + t->start, t->end - t->start);
}
item->data.bindata->data[t->end - t->start] = '\0';
item->data.bindata->size = t->end - t->start;
*r = GETDNS_RETURN_GOOD;
return 1;
}
break;
case JSMN_PRIMITIVE:
/* There is no such thing as an empty primitive */
if (t->end <= t->start) {
*r = GETDNS_RETURN_GENERIC_ERROR;
break;
} else if (_jsmn_get_int(js, t, &item->data.n)
|| _jsmn_get_const(js, t, &item->data.n)) {
item->dtype = t_int;
}
else if (_jsmn_get_data(mf, js, t, &item->data.bindata)
|| _jsmn_get_dname(js, t, &item->data.bindata)
|| _jsmn_get_ipv4(mf, js, t, &item->data.bindata)
|| _jsmn_get_ipv6(mf, js, t, &item->data.bindata))
item->dtype = t_bindata;
else if (_jsmn_get_ipdict(mf, js, t, &item->data.dict))
item->dtype = t_dict;
else {
*r = GETDNS_RETURN_GENERIC_ERROR;
break;
}
*r = GETDNS_RETURN_GOOD;
return 1;
case JSMN_OBJECT:
if (!(item->data.dict = _getdns_dict_create_with_mf(mf))) {
*r = GETDNS_RETURN_MEMORY_ERROR;
break;
}
item->dtype = t_dict;
return _jsmn_get_dict(mf, js, t, count, item->data.dict, r);
case JSMN_ARRAY:
if (!(item->data.list = _getdns_list_create_with_mf(mf))) {
*r = GETDNS_RETURN_MEMORY_ERROR;
break;
}
item->dtype = t_list;
return _jsmn_get_list(mf, js, t, count, item->data.list, r);
default:
*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
break;
}
return 0;
}
static getdns_return_t
_getdns_str2item_mf(struct mem_funcs *mf, const char *str, getdns_item *item)
{
jsmn_parser p;
jsmntok_t *tok = NULL, *new_tok;
size_t tokcount = 100;
int r;
getdns_return_t gr;
jsmn_init(&p);
tok = GETDNS_XMALLOC(*mf, jsmntok_t, tokcount);
do {
r = jsmn_parse(&p, str, strlen(str), tok, tokcount);
if (r == JSMN_ERROR_NOMEM) {
tokcount *= 2;
if (!(new_tok = GETDNS_XREALLOC(
*mf, tok, jsmntok_t, tokcount))) {
GETDNS_FREE(*mf, tok);
return GETDNS_RETURN_MEMORY_ERROR;
}
tok = new_tok;
}
} while (r == JSMN_ERROR_NOMEM);
if (r < 0)
gr = GETDNS_RETURN_GENERIC_ERROR;
else
(void) _jsmn_get_item(mf, str, tok, p.toknext, item, &gr);
GETDNS_FREE(*mf, tok);
return gr;
}
getdns_return_t
getdns_str2dict(const char *str, getdns_dict **dict)
{
getdns_item item;
getdns_return_t r;
while (*str && isspace(*str))
str++;
if (*str != '{') {
getdns_dict *dict_r = _getdns_ipaddr_dict_mf(
&_getdns_plain_mem_funcs, str);
if (dict_r) {
*dict = dict_r;
return GETDNS_RETURN_GOOD;
}
}
if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
return r;
else if (item.dtype != t_dict) {
uint8_t buf[16];
getdns_dict *dict_r;
if (item.dtype != t_bindata)
r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
else if (item.data.bindata->size == 4 &&
inet_pton(AF_INET, str, buf) == 1) {
if (!(dict_r = getdns_dict_create()))
r = GETDNS_RETURN_MEMORY_ERROR;
else if ((r = getdns_dict_util_set_string(
dict_r, "address_type", "IPv4")))
getdns_dict_destroy(dict_r);
else if ((r = getdns_dict_set_bindata(
dict_r, "address_data", item.data.bindata)))
getdns_dict_destroy(dict_r);
else
*dict = dict_r;
} else if (item.data.bindata->size == 16 &&
inet_pton(AF_INET6, str, buf) == 1) {
if (!(dict_r = getdns_dict_create()))
r = GETDNS_RETURN_MEMORY_ERROR;
else if ((r = getdns_dict_util_set_string(
dict_r, "address_type", "IPv6")))
getdns_dict_destroy(dict_r);
else if ((r = getdns_dict_set_bindata(
dict_r, "address_data", item.data.bindata)))
getdns_dict_destroy(dict_r);
else
*dict = dict_r;
} else
r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
return r;
}
*dict = item.data.dict;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_str2list(const char *str, getdns_list **list)
{
getdns_item item;
getdns_return_t r;
if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
return r;
else if (item.dtype != t_list) {
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
}
*list = item.data.list;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_str2bindata(const char *str, getdns_bindata **bindata)
{
getdns_item item;
getdns_return_t r;
if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
return r;
else if (item.dtype != t_bindata) {
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
}
*bindata = item.data.bindata;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_str2int(const char *str, uint32_t *value)
{
getdns_item item;
getdns_return_t r;
if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
return r;
else if (item.dtype != t_int) {
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
}
*value = item.data.n;
return GETDNS_RETURN_GOOD;
}
struct const_name_info { const char *name; uint32_t code; };
static struct const_name_info consts_name_info[] = {
{ "GETDNS_APPEND_NAME_ALWAYS", 550 },
{ "GETDNS_APPEND_NAME_NEVER", 553 },
{ "GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE", 552 },
{ "GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE", 551 },
{ "GETDNS_APPEND_NAME_TO_SINGLE_LABEL_FIRST", 554 },
{ "GETDNS_AUTHENTICATION_NONE", 1300 },
{ "GETDNS_AUTHENTICATION_REQUIRED", 1301 },
{ "GETDNS_BAD_DNS_ALL_NUMERIC_LABEL", 1101 },
{ "GETDNS_BAD_DNS_CNAME_IN_TARGET", 1100 },
{ "GETDNS_BAD_DNS_CNAME_RETURNED_FOR_OTHER_TYPE", 1102 },
{ "GETDNS_CALLBACK_CANCEL", 701 },
{ "GETDNS_CALLBACK_COMPLETE", 700 },
{ "GETDNS_CALLBACK_ERROR", 703 },
{ "GETDNS_CALLBACK_TIMEOUT", 702 },
{ "GETDNS_CONTEXT_CODE_APPEND_NAME", 607 },
{ "GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW", 614 },
{ "GETDNS_CONTEXT_CODE_DNSSEC_TRUST_ANCHORS", 609 },
{ "GETDNS_CONTEXT_CODE_DNS_ROOT_SERVERS", 604 },
{ "GETDNS_CONTEXT_CODE_DNS_TRANSPORT", 605 },
{ "GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE", 619 },
{ "GETDNS_CONTEXT_CODE_EDNS_DO_BIT", 613 },
{ "GETDNS_CONTEXT_CODE_EDNS_EXTENDED_RCODE", 611 },
{ "GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE", 610 },
{ "GETDNS_CONTEXT_CODE_EDNS_VERSION", 612 },
{ "GETDNS_CONTEXT_CODE_FOLLOW_REDIRECTS", 602 },
{ "GETDNS_CONTEXT_CODE_IDLE_TIMEOUT", 617 },
{ "GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES", 606 },
{ "GETDNS_CONTEXT_CODE_MEMORY_FUNCTIONS", 615 },
{ "GETDNS_CONTEXT_CODE_NAMESPACES", 600 },
{ "GETDNS_CONTEXT_CODE_PUBKEY_PINSET", 621 },
{ "GETDNS_CONTEXT_CODE_RESOLUTION_TYPE", 601 },
{ "GETDNS_CONTEXT_CODE_SUFFIX", 608 },
{ "GETDNS_CONTEXT_CODE_TIMEOUT", 616 },
{ "GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION", 618 },
{ "GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE", 620 },
{ "GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS", 603 },
{ "GETDNS_DNSSEC_BOGUS", 401 },
{ "GETDNS_DNSSEC_INDETERMINATE", 402 },
{ "GETDNS_DNSSEC_INSECURE", 403 },
{ "GETDNS_DNSSEC_NOT_PERFORMED", 404 },
{ "GETDNS_DNSSEC_SECURE", 400 },
{ "GETDNS_EXTENSION_FALSE", 1001 },
{ "GETDNS_EXTENSION_TRUE", 1000 },
{ "GETDNS_NAMESPACE_DNS", 500 },
{ "GETDNS_NAMESPACE_LOCALNAMES", 501 },
{ "GETDNS_NAMESPACE_MDNS", 503 },
{ "GETDNS_NAMESPACE_NETBIOS", 502 },
{ "GETDNS_NAMESPACE_NIS", 504 },
{ "GETDNS_NAMETYPE_DNS", 800 },
{ "GETDNS_NAMETYPE_WINS", 801 },
{ "GETDNS_OPCODE_IQUERY", 1 },
{ "GETDNS_OPCODE_NOTIFY", 4 },
{ "GETDNS_OPCODE_QUERY", 0 },
{ "GETDNS_OPCODE_STATUS", 2 },
{ "GETDNS_OPCODE_UPDATE", 5 },
{ "GETDNS_RCODE_BADALG", 21 },
{ "GETDNS_RCODE_BADKEY", 17 },
{ "GETDNS_RCODE_BADMODE", 19 },
{ "GETDNS_RCODE_BADNAME", 20 },
{ "GETDNS_RCODE_BADSIG", 16 },
{ "GETDNS_RCODE_BADTIME", 18 },
{ "GETDNS_RCODE_BADTRUNC", 22 },
{ "GETDNS_RCODE_BADVERS", 16 },
{ "GETDNS_RCODE_COOKIE", 23 },
{ "GETDNS_RCODE_FORMERR", 1 },
{ "GETDNS_RCODE_NOERROR", 0 },
{ "GETDNS_RCODE_NOTAUTH", 9 },
{ "GETDNS_RCODE_NOTIMP", 4 },
{ "GETDNS_RCODE_NOTZONE", 10 },
{ "GETDNS_RCODE_NXDOMAIN", 3 },
{ "GETDNS_RCODE_NXRRSET", 8 },
{ "GETDNS_RCODE_REFUSED", 5 },
{ "GETDNS_RCODE_SERVFAIL", 2 },
{ "GETDNS_RCODE_YXDOMAIN", 6 },
{ "GETDNS_RCODE_YXRRSET", 7 },
{ "GETDNS_REDIRECTS_DO_NOT_FOLLOW", 531 },
{ "GETDNS_REDIRECTS_FOLLOW", 530 },
{ "GETDNS_RESOLUTION_RECURSING", 521 },
{ "GETDNS_RESOLUTION_STUB", 520 },
{ "GETDNS_RESPSTATUS_ALL_BOGUS_ANSWERS", 904 },
{ "GETDNS_RESPSTATUS_ALL_TIMEOUT", 902 },
{ "GETDNS_RESPSTATUS_GOOD", 900 },
{ "GETDNS_RESPSTATUS_NO_NAME", 901 },
{ "GETDNS_RESPSTATUS_NO_SECURE_ANSWERS", 903 },
{ "GETDNS_RETURN_BAD_CONTEXT", 301 },
{ "GETDNS_RETURN_BAD_DOMAIN_NAME", 300 },
{ "GETDNS_RETURN_CONTEXT_UPDATE_FAIL", 302 },
{ "GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED", 309 },
{ "GETDNS_RETURN_EXTENSION_MISFORMAT", 308 },
{ "GETDNS_RETURN_GENERIC_ERROR", 1 },
{ "GETDNS_RETURN_GOOD", 0 },
{ "GETDNS_RETURN_INVALID_PARAMETER", 311 },
{ "GETDNS_RETURN_MEMORY_ERROR", 310 },
{ "GETDNS_RETURN_NEED_MORE_SPACE", 399 },
{ "GETDNS_RETURN_NOT_IMPLEMENTED", 312 },
{ "GETDNS_RETURN_NO_SUCH_DICT_NAME", 305 },
{ "GETDNS_RETURN_NO_SUCH_EXTENSION", 307 },
{ "GETDNS_RETURN_NO_SUCH_LIST_ITEM", 304 },
{ "GETDNS_RETURN_UNKNOWN_TRANSACTION", 303 },
{ "GETDNS_RETURN_WRONG_TYPE_REQUESTED", 306 },
{ "GETDNS_RRCLASS_ANY", 255 },
{ "GETDNS_RRCLASS_CH", 3 },
{ "GETDNS_RRCLASS_HS", 4 },
{ "GETDNS_RRCLASS_IN", 1 },
{ "GETDNS_RRCLASS_NONE", 254 },
{ "GETDNS_RRTYPE_A", 1 },
{ "GETDNS_RRTYPE_AAAA", 28 },
{ "GETDNS_RRTYPE_AFSDB", 18 },
{ "GETDNS_RRTYPE_ANY", 255 },
{ "GETDNS_RRTYPE_APL", 42 },
{ "GETDNS_RRTYPE_ATMA", 34 },
{ "GETDNS_RRTYPE_AXFR", 252 },
{ "GETDNS_RRTYPE_CAA", 257 },
{ "GETDNS_RRTYPE_CDNSKEY", 60 },
{ "GETDNS_RRTYPE_CDS", 59 },
{ "GETDNS_RRTYPE_CERT", 37 },
{ "GETDNS_RRTYPE_CNAME", 5 },
{ "GETDNS_RRTYPE_CSYNC", 62 },
{ "GETDNS_RRTYPE_DHCID", 49 },
{ "GETDNS_RRTYPE_DLV", 32769 },
{ "GETDNS_RRTYPE_DNAME", 39 },
{ "GETDNS_RRTYPE_DNSKEY", 48 },
{ "GETDNS_RRTYPE_DS", 43 },
{ "GETDNS_RRTYPE_EID", 31 },
{ "GETDNS_RRTYPE_GID", 102 },
{ "GETDNS_RRTYPE_GPOS", 27 },
{ "GETDNS_RRTYPE_HINFO", 13 },
{ "GETDNS_RRTYPE_HIP", 55 },
{ "GETDNS_RRTYPE_IPSECKEY", 45 },
{ "GETDNS_RRTYPE_ISDN", 20 },
{ "GETDNS_RRTYPE_IXFR", 251 },
{ "GETDNS_RRTYPE_KEY", 25 },
{ "GETDNS_RRTYPE_KX", 36 },
{ "GETDNS_RRTYPE_LOC", 29 },
{ "GETDNS_RRTYPE_LP", 107 },
{ "GETDNS_RRTYPE_MAILA", 254 },
{ "GETDNS_RRTYPE_MAILB", 253 },
{ "GETDNS_RRTYPE_MB", 7 },
{ "GETDNS_RRTYPE_MD", 3 },
{ "GETDNS_RRTYPE_MF", 4 },
{ "GETDNS_RRTYPE_MG", 8 },
{ "GETDNS_RRTYPE_MINFO", 14 },
{ "GETDNS_RRTYPE_MR", 9 },
{ "GETDNS_RRTYPE_MX", 15 },
{ "GETDNS_RRTYPE_NAPTR", 35 },
{ "GETDNS_RRTYPE_NID", 104 },
{ "GETDNS_RRTYPE_NIMLOC", 32 },
{ "GETDNS_RRTYPE_NINFO", 56 },
{ "GETDNS_RRTYPE_NS", 2 },
{ "GETDNS_RRTYPE_NSAP", 22 },
{ "GETDNS_RRTYPE_NSEC", 47 },
{ "GETDNS_RRTYPE_NULL", 10 },
{ "GETDNS_RRTYPE_NXT", 30 },
{ "GETDNS_RRTYPE_OPENPGPKEY", 61 },
{ "GETDNS_RRTYPE_OPT", 41 },
{ "GETDNS_RRTYPE_PTR", 12 },
{ "GETDNS_RRTYPE_PX", 26 },
{ "GETDNS_RRTYPE_RKEY", 57 },
{ "GETDNS_RRTYPE_RP", 17 },
{ "GETDNS_RRTYPE_RRSIG", 46 },
{ "GETDNS_RRTYPE_RT", 21 },
{ "GETDNS_RRTYPE_SIG", 24 },
{ "GETDNS_RRTYPE_SINK", 40 },
{ "GETDNS_RRTYPE_SOA", 6 },
{ "GETDNS_RRTYPE_SPF", 99 },
{ "GETDNS_RRTYPE_SRV", 33 },
{ "GETDNS_RRTYPE_SSHFP", 44 },
{ "GETDNS_RRTYPE_TA", 32768 },
{ "GETDNS_RRTYPE_TALINK", 58 },
{ "GETDNS_RRTYPE_TKEY", 249 },
{ "GETDNS_RRTYPE_TLSA", 52 },
{ "GETDNS_RRTYPE_TSIG", 250 },
{ "GETDNS_RRTYPE_TXT", 16 },
{ "GETDNS_RRTYPE_UID", 101 },
{ "GETDNS_RRTYPE_UINFO", 100 },
{ "GETDNS_RRTYPE_UNSPEC", 103 },
{ "GETDNS_RRTYPE_URI", 256 },
{ "GETDNS_RRTYPE_WKS", 11 },
{ "GETDNS_TRANSPORT_TCP", 1201 },
{ "GETDNS_TRANSPORT_TCP_ONLY", 542 },
{ "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", 543 },
{ "GETDNS_TRANSPORT_TLS", 1202 },
{ "GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN", 545 },
{ "GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN", 544 },
{ "GETDNS_TRANSPORT_UDP", 1200 },
{ "GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP", 540 },
{ "GETDNS_TRANSPORT_UDP_ONLY", 541 },
};
static int const_name_info_cmp(const void *a, const void *b)
{
return strcmp( ((struct const_name_info *) a)->name
, ((struct const_name_info *) b)->name );
}
static int
_getdns_get_const_name_info(const char *name, uint32_t *code)
{
struct const_name_info key = { name, 0 };
struct const_name_info *i = bsearch(&key, consts_name_info,
sizeof(consts_name_info) / sizeof(struct const_name_info),
sizeof(struct const_name_info), const_name_info_cmp);
if (!i)
return 0;
if (code)
*code = i->code;
return 1;
}

View File

@ -1,37 +0,0 @@
/*
* Copyright (c) 2013, NLNet Labs, Verisign, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the copyright holders nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GETDNS_STR2DICT_H_
#define GETDNS_STR2DICT_H_
#include "getdns/getdns.h"
getdns_return_t getdns_str2dict(const char *str, getdns_dict **dict);
getdns_return_t getdns_str2list(const char *str, getdns_list **list);
getdns_return_t getdns_str2bindata(const char *str, getdns_bindata **bindata);
getdns_return_t getdns_str2int(const char *str, uint32_t *value);
#endif

View File

@ -5,24 +5,71 @@ SERVER_IP="8.8.8.8"
SERVER_IPv6="2001:4860:4860::8888" SERVER_IPv6="2001:4860:4860::8888"
TLS_SERVER_IP="185.49.141.38~getdnsapi.net" TLS_SERVER_IP="185.49.141.38~getdnsapi.net"
TLS_SERVER_IPv6="2a04:b900:0:100::38~getdnsapi.net" TLS_SERVER_IPv6="2a04:b900:0:100::38~getdnsapi.net"
TLS_SERVER_SS_IP="184.105.193.78~tls-dns-u.odvr.dns-oarc.net" #Self signed cert
TLS_SERVER_KEY="foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9S=" TLS_SERVER_KEY="foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9S="
TLS_SERVER_SS_KEY="pOXrpUt9kgPgbWxBFFcBTbRH2heo2wHwXp1fd4AEVXI="
TLS_SERVER_WRONG_KEY="foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc1S=" TLS_SERVER_WRONG_KEY="foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc1S="
GOOD_RESULT_SYNC="Status was: At least one response was returned" GOOD_RESULT_SYNC="Status was: At least one response was returned"
GOOD_RESULT_ASYNC="successfull" GOOD_RESULT_ASYNC="successfull"
BAD_RESULT_SYNC="1 'Generic error'" BAD_RESULT_SYNC="1 'Generic error'"
BAD_RESULT_ASYNC="callback_type of 703" BAD_RESULT_ASYNC="callback_type of 703"
NUM_ARGS=3
GOOD_COUNT=0 GOOD_COUNT=0
FAIL_COUNT=0 FAIL_COUNT=0
check_auth () {
local my_auth_ok=0;
auth_result=`echo $1 | sed 's/.*tls_auth_status\": <bindata of "//' | sed 's/\">.*//'`
if [[ $2 == "-" ]] ; then
my_auth_ok=1;
fi
if [[ $2 == "N" ]] && [[ $auth_result == "None" ]]; then
my_auth_ok=1;
fi
if [[ $2 == "F" ]] && [[ $auth_result == "Failed" ]]; then
my_auth_ok=1;
fi
if [[ $2 == "S" ]] && [[ $auth_result == "Success" ]]; then
my_auth_ok=1;
fi
echo $my_auth_ok;
}
check_trans () {
local my_trans_ok=0;
trans_result=`echo $1 | sed "s/.*\"transport\": GETDNS_TRANSPORT_//" | sed 's/ }.*//' | sed 's/,.*//'`
if [[ $2 == "U" ]] && [[ $trans_result == "UDP" ]]; then
my_trans_ok=1;
fi
if [[ $2 == "T" ]] && [[ $trans_result == "TCP" ]]; then
my_trans_ok=1;
fi
if [[ $2 == "L" ]] && [[ $trans_result == "TLS" ]]; then
my_trans_ok=1;
fi
echo $my_trans_ok;
}
check_good () { check_good () {
result=`echo $1 | grep "Response code was: GOOD." | tail -1 | sed 's/ All done.'// | sed 's/Response code was: GOOD. '//` auth_ok=0;
result_ok=0;
trans_ok=0;
result=`echo $1 | sed 's/ All done.'// | sed 's/.*Response code was: GOOD. '//`
async_success=`echo $result | grep -c "$GOOD_RESULT_ASYNC"` async_success=`echo $result | grep -c "$GOOD_RESULT_ASYNC"`
if [[ $result =~ $GOOD_RESULT_SYNC ]] || [[ $async_success =~ 1 ]]; then if [[ $result =~ $GOOD_RESULT_SYNC ]] || [[ $async_success =~ 1 ]]; then
result_ok=1;
fi
if [[ $result_ok == 1 ]] ; then
trans_ok=$(check_trans "$1" "$2")
auth_ok=$(check_auth "$1" "$3")
fi
if [[ $result_ok == 1 ]] && [[ $auth_ok == 1 ]] && [[ $trans_ok == 1 ]]; then
(( GOOD_COUNT++ )) (( GOOD_COUNT++ ))
echo -n "PASS: " echo -n "PASS: "
else else
(( FAIL_COUNT++ )) (( FAIL_COUNT++ ))
echo "FAIL (RESULT): " $1 echo "FAIL (RESULT): Result: $result Auth: $auth_ok Trans: $trans_ok"
echo -n "FAIL: " echo -n "FAIL: "
fi fi
} }
@ -80,30 +127,38 @@ while getopts ":p:s:t:k:idh" opt; do
done done
TLS_SERVER_IP_NO_NAME=`echo ${TLS_SERVER_IP%~*}` TLS_SERVER_IP_NO_NAME=`echo ${TLS_SERVER_IP%~*}`
TLS_SERVER_SS_IP_NO_NAME=`echo ${TLS_SERVER_SS_IP%~*}`
TLS_SERVER_IP_WRONG_NAME=`echo ${TLS_SERVER_IP::${#TLS_SERVER_IP}-1}` TLS_SERVER_IP_WRONG_NAME=`echo ${TLS_SERVER_IP::${#TLS_SERVER_IP}-1}`
NUM_GOOD_QUERIES=7
GOOD_QUERIES=( GOOD_QUERIES=(
"-s -A -q getdnsapi.net -l U @${SERVER_IP} " "-s -A getdnsapi.net -l U @${SERVER_IP}" "U" "-"
"-s -A -q getdnsapi.net -l T @${SERVER_IP} " "-s -A getdnsapi.net -l T @${SERVER_IP}" "T" "-"
"-s -A -q getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}" "-s -A getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}" "L" "N"
"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP}" "-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP}" "L" "S"
"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S"
"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S"
"-s -G -q DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D") "-s -A getdnsapi.net -l L -m @${TLS_SERVER_SS_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_SS_KEY}\"" "L" "S"
"-s -G DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D" "U" "-")
NUM_GOOD_FB_QUERIES=6
GOOD_FALLBACK_QUERIES=( GOOD_FALLBACK_QUERIES=(
"-s -A -q getdnsapi.net -l LT @${SERVER_IP}" "-s -A getdnsapi.net -l LU @${SERVER_IP}" "U" "-"
"-s -A -q getdnsapi.net -l LT @${SERVER_IP}" "-s -A getdnsapi.net -l LT @${SERVER_IP}" "T" "-"
"-s -A -q getdnsapi.net -l LT @${TLS_SERVER_IP_NO_NAME}" "-s -A getdnsapi.net -l LT @${TLS_SERVER_IP_NO_NAME}" "L" "N"
"-s -A -q getdnsapi.net -l LT -m @${TLS_SERVER_IP_NO_NAME}" "-s -A getdnsapi.net -l LT -m @${TLS_SERVER_IP_NO_NAME}" "L" "N"
"-s -A -q getdnsapi.net -l L @${SERVER_IP} @${TLS_SERVER_IP_NO_NAME}" "-s -A getdnsapi.net -l L @${SERVER_IP} @${TLS_SERVER_IP_NO_NAME}" "L" "-"
"-s -G -q DNSKEY getdnsapi.net -l UT @${SERVER_IP} -b 512 -D") "-s -G DNSKEY getdnsapi.net -l UT @${SERVER_IP} -b 512 -D" "T" "-")
NOT_AVAILABLE_QUERIES=( NOT_AVAILABLE_QUERIES=(
"-s -A -q getdnsapi.net -l L @${SERVER_IP}" "-s -A getdnsapi.net -l L @${SERVER_IP}"
"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_WRONG_NAME}" "-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_WRONG_NAME}"
"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME}" "-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME}"
"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_WRONG_KEY}\"") "-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_WRONG_KEY}\""
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP} -K pin-sha256=\"${TLS_SERVER_WRONG_KEY}\""
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_WRONG_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\""
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_WRONG_NAME} -K pin-sha256=\"${TLS_SERVER_WRONG_KEY}\""
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_SS_IP} -K pin-sha256=\"${TLS_SERVER_SS_KEY}\"")
echo "Starting transport test" echo "Starting transport test"
@ -118,16 +173,16 @@ for (( i = 0; i < 2; i+=1 )); do
fi fi
echo "*Success cases:" echo "*Success cases:"
for (( j = 0; j < ${#GOOD_QUERIES[@]}; j+=1 )); do for (( j = 0; j < $NUM_GOOD_QUERIES; j+=1 )); do
check_good "`$DIR/getdns_query $SYNC_MODE ${GOOD_QUERIES[${j}]} 2>/dev/null`" check_good "`$DIR/getdns_query +return_call_reporting $SYNC_MODE ${GOOD_QUERIES[$j*$NUM_ARGS]} 2>/dev/null`" ${GOOD_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_QUERIES[$((j*NUM_ARGS))+2]}
echo "getdns_query $SYNC_MODE ${GOOD_QUERIES[${j}]}" echo "getdns_query $SYNC_MODE ${GOOD_QUERIES[$j*$NUM_ARGS]}"
(( COUNT++ )) (( COUNT++ ))
done done
echo "*Success fallback cases:" echo "*Success fallback cases:"
for (( j = 0; j < ${#GOOD_FALLBACK_QUERIES[@]}; j+=1 )); do for (( j = 0; j < $NUM_GOOD_FB_QUERIES; j+=1 )); do
check_good "`$DIR/getdns_query $SYNC_MODE ${GOOD_FALLBACK_QUERIES[${j}]} 2>/dev/null`" check_good "`$DIR/getdns_query +return_call_reporting $SYNC_MODE ${GOOD_FALLBACK_QUERIES[$j*$NUM_ARGS]} 2>/dev/null`" ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+2]}
echo "getdns_query $SYNC_MODE ${GOOD_FALLBACK_QUERIES[${j}]}" echo "getdns_query $SYNC_MODE ${GOOD_FALLBACK_QUERIES[$j*$NUM_ARGS]} TESTS: ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+2]}"
(( COUNT++ )) (( COUNT++ ))
done done

View File

@ -6,5 +6,5 @@
cd "${BUILDDIR}/build" cd "${BUILDDIR}/build"
make getdns_query \ make getdns_query \
&& echo "export GETDNS_QUERY=\"${BUILDDIR}/build/src/test/getdns_query\"" \ && echo "export GETDNS_QUERY=\"${BUILDDIR}/build/src/tools/getdns_query\"" \
>> ../.tpkg.var.master >> ../.tpkg.var.master

View File

@ -6,5 +6,5 @@
cd "${BUILDDIR}/build-stub-only" cd "${BUILDDIR}/build-stub-only"
make getdns_query \ make getdns_query \
&& echo "export GETDNS_STUB_QUERY=\"${BUILDDIR}/build-stub-only/src/test/getdns_query\"" \ && echo "export GETDNS_STUB_QUERY=\"${BUILDDIR}/build-stub-only/src/tools/getdns_query\"" \
>> ../.tpkg.var.master >> ../.tpkg.var.master

117
src/tools/Makefile.in Normal file
View File

@ -0,0 +1,117 @@
#
# @configure_input@
#
# Copyright (c) 2013, Verisign, Inc., NLNet Labs
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the names of the copyright holders nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package = @PACKAGE_NAME@
version = @PACKAGE_VERSION@
tarname = @PACKAGE_TARNAME@
distdir = $(tarname)-$(version)
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
INSTALL = @INSTALL@
LIBTOOL = ../../libtool
srcdir = @srcdir@
CC=@CC@
WPEDANTICFLAG=@WPEDANTICFLAG@
CFLAGS=-I$(srcdir)/.. -I$(srcdir) -I.. $(cflags) @CFLAGS@ @CPPFLAGS@ $(WPEDANTICFLAG) $(XTRA_CFLAGS)
LDFLAGS=-L.. @LDFLAGS@
LDLIBS=../libgetdns.la @LIBS@
ALL_OBJS=getdns_query.lo
PROGRAMS=getdns_query
.SUFFIXES: .c .o .a .lo .h
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
.c.lo:
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $< -o $@
default: all
all: $(PROGRAMS)
$(ALL_OBJS):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/$(@:.lo=.c) -o $@
getdns_query: getdns_query.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_query.lo $(LDFLAGS) $(LDLIBS)
stubby: getdns_query.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_query.lo $(LDFLAGS) $(LDLIBS)
install-getdns_query: getdns_query
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
$(LIBTOOL) --mode=install cp getdns_query $(DESTDIR)$(bindir)
uninstall-getdns_query:
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/getdns_query
install-stubby: getdns_query
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
$(LIBTOOL) --mode=install cp getdns_query $(DESTDIR)$(bindir)/stubby
uninstall-stubby:
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/stubby
clean:
rm -f *.o *.lo $(PROGRAMS)
rm -rf .libs
distclean : clean
rm -f Makefile
Makefile: $(srcdir)/Makefile.in ../../config.status
cd ../.. && ./config.status src/test/Makefile
depend:
(cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new )
(blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I.. -I"$$blddir"/.. *.c | \
sed -e "s? $$blddir/? ?g" \
-e 's? \([a-z0-9_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
-e 's? \.\./\([a-z0-9_-]*\)\.h? $$(srcdir)/../\1.h?g' \
-e 's? \.\./\([a-z0-9_-]*\)/\([a-z0-9_-]*\)\.h? $$(srcdir)/../\1/\2.h?g' \
-e 's? \$$(srcdir)/config\.h? ../config.h?g' \
-e 's? \$$(srcdir)/\.\./config\.h? ../config.h?g' \
-e 's? \$$(srcdir)/\.\./getdns/getdns\.h? ../getdns/getdns.h?g' \
-e 's? \$$(srcdir)/\.\./getdns/getdns_extra\.h? ../getdns/getdns_extra.h?g' \
-e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' >> Makefile.in.new )
(cd $(srcdir) ; diff Makefile.in.new Makefile.in && rm Makefile.in.new \
|| mv Makefile.in.new Makefile.in )
.PHONY: clean test
# Dependencies for getdns_query
getdns_query.lo getdns_query.o: $(srcdir)/getdns_query.c ../config.h $(srcdir)/../debug.h ../config.h \
../getdns/getdns.h ../getdns/getdns_extra.h

View File

@ -27,9 +27,6 @@
#include "config.h" #include "config.h"
#include "debug.h" #include "debug.h"
#include "getdns_str2dict.h"
#include "getdns_context_config.h"
#include "getdns_context_set_listen_addresses.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -51,6 +48,19 @@ typedef unsigned short in_port_t;
#define EXAMPLE_PIN "pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\"" #define EXAMPLE_PIN "pin-sha256=\"E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=\""
static int i_am_stubby = 0;
static const char *default_stubby_config =
"{ resolution_type: GETDNS_RESOLUTION_STUB"
", dns_transport_list: [ GETDNS_TRANSPORT_TLS, GETDNS_TRANSPORT_UDP, GETDNS_TRANSPORT_TCP ]"
", idle_timeout: 10000"
", listen_addresses: [ 127.0.0.1@53, 0::1@53 ]"
", tls_query_padding_blocksize: 256"
", edns_client_subnet_private : 1"
"}";
static int clear_listen_list_on_arg = 0;
#ifndef GETDNS_ON_WINDOWS
static int run_in_foreground = 1;
#endif
static int quiet = 0; static int quiet = 0;
static int batch_mode = 0; static int batch_mode = 0;
static char *query_file = NULL; static char *query_file = NULL;
@ -154,6 +164,7 @@ print_usage(FILE *out, const char *progname)
{ {
fprintf(out, "usage: %s [<option> ...] \\\n" fprintf(out, "usage: %s [<option> ...] \\\n"
"\t[@<upstream> ...] [+<extension> ...] [\'{ <settings> }\'] [<name>] [<type>]\n", progname); "\t[@<upstream> ...] [+<extension> ...] [\'{ <settings> }\'] [<name>] [<type>]\n", progname);
if (!i_am_stubby) {
fprintf(out, "\ndefault mode: " fprintf(out, "\ndefault mode: "
#ifdef HAVE_LIBUNBOUND #ifdef HAVE_LIBUNBOUND
"recursive" "recursive"
@ -161,6 +172,11 @@ print_usage(FILE *out, const char *progname)
"stub" "stub"
#endif #endif
", synchronous resolution of NS record\n\t\tusing UDP with TCP fallback\n"); ", synchronous resolution of NS record\n\t\tusing UDP with TCP fallback\n");
}
else {
fprintf(out, "\ndefault mode: "
"stub, asynchronous resolution \n\t\tusing TLS with UDP then TCP fallback\n");
}
fprintf(out, "\nupstreams: @<ip>[%%<scope_id>][@<port>][#<tls port>][~<tls name>][^<tsig spec>]"); fprintf(out, "\nupstreams: @<ip>[%%<scope_id>][@<port>][#<tls port>][~<tls name>][^<tsig spec>]");
fprintf(out, "\n <ip>@<port> may be given as <IPv4>:<port>"); fprintf(out, "\n <ip>@<port> may be given as <IPv4>:<port>");
fprintf(out, "\n or \'[\'<IPv6>[%%<scope_id>]\']\':<port> too\n"); fprintf(out, "\n or \'[\'<IPv6>[%%<scope_id>]\']\':<port> too\n");
@ -185,25 +201,39 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t+0\t\t\tClear all extensions\n"); fprintf(out, "\t+0\t\t\tClear all extensions\n");
fprintf(out, "\nsettings in json dict format (like outputted by -i option).\n"); fprintf(out, "\nsettings in json dict format (like outputted by -i option).\n");
fprintf(out, "\noptions:\n"); fprintf(out, "\noptions:\n");
if (!i_am_stubby) {
fprintf(out, "\t-a\tPerform asynchronous resolution " fprintf(out, "\t-a\tPerform asynchronous resolution "
"(default = synchronous)\n"); "(default = synchronous)\n");
fprintf(out, "\t-A\taddress lookup (<type> is ignored)\n"); fprintf(out, "\t-A\taddress lookup (<type> is ignored)\n");
fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n"); fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n");
}
fprintf(out, "\t-b <bufsize>\tSet edns0 max_udp_payload size\n"); fprintf(out, "\t-b <bufsize>\tSet edns0 max_udp_payload size\n");
fprintf(out, "\t-c\tSend Client Subnet privacy request\n"); fprintf(out, "\t-c\tSend Client Subnet privacy request\n");
fprintf(out, "\t-C\t<filename>\n"); fprintf(out, "\t-C\t<filename>\n");
fprintf(out, "\t\tRead settings from config file <filename>\n"); fprintf(out, "\t\tRead settings from config file <filename>\n");
fprintf(out, "\t\tThe getdns context will be configured with these settings\n"); fprintf(out, "\t\tThe getdns context will be configured with these settings\n");
fprintf(out, "\t\tThe file must be in json dict format.\n"); fprintf(out, "\t\tThe file must be in json dict format.\n");
if (i_am_stubby) {
fprintf(out, "\t\tBy default, configuration is first read from");
fprintf(out, "\t\t\"/etc/stubby.conf\" and then from \"$HOME/.stubby.conf\"");
}
fprintf(out, "\t-D\tSet edns0 do bit\n"); fprintf(out, "\t-D\tSet edns0 do bit\n");
fprintf(out, "\t-d\tclear edns0 do bit\n"); fprintf(out, "\t-d\tclear edns0 do bit\n");
fprintf(out, "\t-e <idle_timeout>\tSet idle timeout in miliseconds\n"); fprintf(out, "\t-e <idle_timeout>\tSet idle timeout in miliseconds\n");
if (!i_am_stubby)
fprintf(out, "\t-F <filename>\tread the queries from the specified file\n"); fprintf(out, "\t-F <filename>\tread the queries from the specified file\n");
fprintf(out, "\t-f <filename>\tRead DNSSEC trust anchors from <filename>\n"); fprintf(out, "\t-f <filename>\tRead DNSSEC trust anchors from <filename>\n");
#ifndef GETDNS_ON_WINDOWS
if (i_am_stubby)
fprintf(out, "\t-g\tRun stubby in background (default is foreground)\n");
#endif
if (!i_am_stubby) {
fprintf(out, "\t-G\tgeneral lookup\n"); fprintf(out, "\t-G\tgeneral lookup\n");
fprintf(out, "\t-H\thostname lookup. (<name> must be an IP address; <type> is ignored)\n"); fprintf(out, "\t-H\thostname lookup. (<name> must be an IP address; <type> is ignored)\n");
}
fprintf(out, "\t-h\tPrint this help\n"); fprintf(out, "\t-h\tPrint this help\n");
fprintf(out, "\t-i\tPrint api information\n"); fprintf(out, "\t-i\tPrint api information\n");
if (!i_am_stubby)
fprintf(out, "\t-I\tInteractive mode (> 1 queries on same context)\n"); fprintf(out, "\t-I\tInteractive mode (> 1 queries on same context)\n");
fprintf(out, "\t-j\tOutput json response dict\n"); fprintf(out, "\t-j\tOutput json response dict\n");
fprintf(out, "\t-J\tPretty print json response dict\n"); fprintf(out, "\t-J\tPretty print json response dict\n");
@ -215,11 +245,15 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t-p\tPretty print response dict\n"); fprintf(out, "\t-p\tPretty print response dict\n");
fprintf(out, "\t-P <blocksize>\tPad TLS queries to a multiple of blocksize\n"); fprintf(out, "\t-P <blocksize>\tPad TLS queries to a multiple of blocksize\n");
fprintf(out, "\t-q\tQuiet mode - don't print response\n"); fprintf(out, "\t-q\tQuiet mode - don't print response\n");
fprintf(out, "\t-r\tSet recursing resolution type\n"); fprintf( out, "\t-r\tSet recursing resolution type%s\n"
, i_am_stubby ? "(default = stub)" : "");
fprintf(out, "\t-R <filename>\tRead root hints from <filename>\n"); fprintf(out, "\t-R <filename>\tRead root hints from <filename>\n");
fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n"); fprintf(out, "\t-s\tSet stub resolution type%s\n"
, i_am_stubby ? "" : "(default = recursing)" );
if (!i_am_stubby)
fprintf(out, "\t-S\tservice lookup (<type> is ignored)\n"); fprintf(out, "\t-S\tservice lookup (<type> is ignored)\n");
fprintf(out, "\t-t <timeout>\tSet timeout in miliseconds\n"); fprintf(out, "\t-t <timeout>\tSet timeout in miliseconds\n");
fprintf(out, "\t-v\tPrint getdns release version\n");
fprintf(out, "\t-x\tDo not follow redirects\n"); fprintf(out, "\t-x\tDo not follow redirects\n");
fprintf(out, "\t-X\tFollow redirects (default)\n"); fprintf(out, "\t-X\tFollow redirects (default)\n");
@ -242,6 +276,8 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t\tListen for DNS requests on the given IP address\n"); fprintf(out, "\t\tListen for DNS requests on the given IP address\n");
fprintf(out, "\t\t<listen address> is in the same format as upstreams.\n"); fprintf(out, "\t\t<listen address> is in the same format as upstreams.\n");
fprintf(out, "\t\tThis option can be given more than once.\n"); fprintf(out, "\t\tThis option can be given more than once.\n");
if (i_am_stubby)
fprintf(out, "\t\t(default is to listen on 127.0.0.1:53)\n");
} }
static getdns_return_t validate_chain(getdns_dict *response) static getdns_return_t validate_chain(getdns_dict *response)
@ -443,11 +479,12 @@ static void parse_config(const char *config_str)
* will get destroyed. * will get destroyed.
*/ */
if (!listen_dict && if (!listen_dict &&
!(listen_dict = getdns_dict_create())) !(listen_dict = getdns_dict_create())) {
fprintf(stderr, "Could not create " fprintf(stderr, "Could not create "
"listen_dict"); "listen_dict");
r = GETDNS_RETURN_MEMORY_ERROR;
else if ((r = getdns_dict_set_list( } else if ((r = getdns_dict_set_list(
listen_dict, "listen_list", list))) listen_dict, "listen_list", list)))
fprintf(stderr, "Could not set listen_list"); fprintf(stderr, "Could not set listen_list");
@ -464,8 +501,7 @@ static void parse_config(const char *config_str)
touched_listen_list = 1; touched_listen_list = 1;
} }
if ((r = _getdns_context_config_( if ((r = getdns_context_config(context, config_dict))) {
context, extensions, config_dict))) {
fprintf(stderr, "Could not configure context with " fprintf(stderr, "Could not configure context with "
"config dict: %s\n", getdns_get_errorstr_by_id(r)); "config dict: %s\n", getdns_get_errorstr_by_id(r));
} }
@ -473,6 +509,48 @@ static void parse_config(const char *config_str)
} }
} }
int parse_config_file(const char *fn, int report_open_failure)
{
FILE *fh;
char *config_file = NULL;
long config_file_sz;
if (!(fh = fopen(fn, "r"))) {
if (report_open_failure)
fprintf( stderr, "Could not open \"%s\": %s\n"
, fn, strerror(errno));
return GETDNS_RETURN_GENERIC_ERROR;
}
if (fseek(fh, 0,SEEK_END) == -1) {
perror("fseek");
fclose(fh);
return GETDNS_RETURN_GENERIC_ERROR;
}
config_file_sz = ftell(fh);
if (config_file_sz <= 0) {
/* Empty config is no config */
fclose(fh);
return GETDNS_RETURN_GOOD;
}
if (!(config_file = malloc(config_file_sz + 1))){
fclose(fh);
fprintf(stderr, "Could not allocate memory for \"%s\"\n", fn);
return GETDNS_RETURN_MEMORY_ERROR;
}
rewind(fh);
if (fread(config_file, 1, config_file_sz, fh) != (size_t)config_file_sz) {
fprintf( stderr, "An error occurred while reading \"%s\": %s\n"
, fn, strerror(errno));
fclose(fh);
return GETDNS_RETURN_MEMORY_ERROR;
}
config_file[config_file_sz] = 0;
fclose(fh);
parse_config(config_file);
free(config_file);
return GETDNS_RETURN_GOOD;
}
getdns_return_t parse_args(int argc, char **argv) getdns_return_t parse_args(int argc, char **argv)
{ {
getdns_return_t r = GETDNS_RETURN_GOOD; getdns_return_t r = GETDNS_RETURN_GOOD;
@ -488,8 +566,6 @@ getdns_return_t parse_args(int argc, char **argv)
getdns_bindata bindata; getdns_bindata bindata;
size_t upstream_count = 0; size_t upstream_count = 0;
FILE *fh; FILE *fh;
char *config_file = NULL;
long config_file_sz;
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
arg = argv[i]; arg = argv[i];
@ -600,42 +676,7 @@ getdns_return_t parse_args(int argc, char **argv)
"after -C\n"); "after -C\n");
return GETDNS_RETURN_GENERIC_ERROR; return GETDNS_RETURN_GENERIC_ERROR;
} }
if (!(fh = fopen(argv[i], "r"))) { (void) parse_config_file(argv[i], 1);
fprintf(stderr, "Could not open \"%s\""
": %s\n",argv[i], strerror(errno));
return GETDNS_RETURN_GENERIC_ERROR;
}
if (fseek(fh, 0,SEEK_END) == -1) {
perror("fseek");
fclose(fh);
return GETDNS_RETURN_GENERIC_ERROR;
}
config_file_sz = ftell(fh);
if (config_file_sz <= 0) {
/* Empty config is no config */
fclose(fh);
break;
}
if (!(config_file=malloc(config_file_sz + 1))){
fclose(fh);
fprintf(stderr, "Could not allocate me"
"mory for \"%s\"\n", argv[i]);
return GETDNS_RETURN_MEMORY_ERROR;
}
rewind(fh);
if (fread(config_file, 1, config_file_sz, fh)
!= (size_t)config_file_sz) {
fprintf(stderr, "An error occurred whil"
"e reading \"%s\": %s\n",argv[i],
strerror(errno));
fclose(fh);
return GETDNS_RETURN_MEMORY_ERROR;
}
config_file[config_file_sz] = 0;
fclose(fh);
parse_config(config_file);
free(config_file);
config_file = NULL;
break; break;
case 'D': case 'D':
(void) getdns_context_set_edns_do_bit(context, 1); (void) getdns_context_set_edns_do_bit(context, 1);
@ -818,6 +859,9 @@ getdns_return_t parse_args(int argc, char **argv)
getdns_context_set_timeout( getdns_context_set_timeout(
context, timeout); context, timeout);
goto next; goto next;
case 'v':
fprintf(stdout, "Version %s\n", GETDNS_VERSION);
return CONTINUE;
case 'x': case 'x':
getdns_context_set_follow_redirects( getdns_context_set_follow_redirects(
context, GETDNS_REDIRECTS_DO_NOT_FOLLOW); context, GETDNS_REDIRECTS_DO_NOT_FOLLOW);
@ -932,17 +976,23 @@ getdns_return_t parse_args(int argc, char **argv)
"expected after -z\n"); "expected after -z\n");
return GETDNS_RETURN_GENERIC_ERROR; return GETDNS_RETURN_GENERIC_ERROR;
} }
if (argv[i][0] == '-' && argv[i][1] == '\0') { if (clear_listen_list_on_arg ||
(argv[i][0] == '-' && argv[i][1] == '\0')) {
if (listen_list && !listen_dict) if (listen_list && !listen_dict)
getdns_list_destroy( getdns_list_destroy(
listen_list); listen_list);
listen_list = NULL; listen_list = NULL;
listen_count = 0; listen_count = 0;
if (!clear_listen_list_on_arg) {
touched_listen_list = 1; touched_listen_list = 1;
DEBUG_SERVER("Clear listen list\n"); DEBUG_SERVER("Clear listen list\n");
break; break;
} else if (listen_dict) {
getdns_dict_destroy(listen_dict);
listen_dict = NULL;
}
clear_listen_list_on_arg = 0;
} }
if ((r = getdns_str2dict(argv[i], &downstream))) if ((r = getdns_str2dict(argv[i], &downstream)))
fprintf(stderr, "Could not convert \"%s\" to " fprintf(stderr, "Could not convert \"%s\" to "
"an IP dict: %s\n", argv[i], "an IP dict: %s\n", argv[i],
@ -971,6 +1021,12 @@ getdns_return_t parse_args(int argc, char **argv)
} }
break; break;
default: default:
#ifndef GETDNS_ON_WINDOWS
if (i_am_stubby && *c == 'g') {
run_in_foreground = 0;
break;
}
#endif
fprintf(stderr, "Unknown option " fprintf(stderr, "Unknown option "
"\"%c\"\n", *c); "\"%c\"\n", *c);
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
@ -1007,7 +1063,24 @@ next: ;
if (print_api_info) { if (print_api_info) {
getdns_dict *api_information = getdns_dict *api_information =
getdns_context_get_api_information(context); getdns_context_get_api_information(context);
char *api_information_str = char *api_information_str;
if (listen_dict && !getdns_dict_get_list(
listen_dict, "listen_list", &listen_list)) {
(void) getdns_dict_set_list(api_information,
"listen_addresses", listen_list);
} else if (listen_list) {
(void) getdns_dict_set_list(api_information,
"listen_addresses", listen_list);
} else if ((listen_list = getdns_list_create())) {
(void) getdns_dict_set_list(api_information,
"listen_addresses", listen_list);
getdns_list_destroy(listen_list);
listen_list = NULL;
}
api_information_str =
getdns_pretty_print_dict(api_information); getdns_pretty_print_dict(api_information);
fprintf(stdout, "%s\n", api_information_str); fprintf(stdout, "%s\n", api_information_str);
free(api_information_str); free(api_information_str);
@ -1137,7 +1210,8 @@ getdns_return_t do_the_call(void)
getdns_eventloop *loop = NULL; getdns_eventloop *loop = NULL;
FILE *fp; FILE *fp;
static void incoming_request_handler(getdns_context *context, static void incoming_request_handler(getdns_context *context,
getdns_dict *request, getdns_transaction_t request_id); getdns_callback_type_t callback_type, getdns_dict *request,
void *userarg, getdns_transaction_t request_id);
void read_line_cb(void *userarg) void read_line_cb(void *userarg)
@ -1154,7 +1228,7 @@ void read_line_cb(void *userarg)
loop->vmt->clear(loop, read_line_ev); loop->vmt->clear(loop, read_line_ev);
if (listen_count) if (listen_count)
(void) getdns_context_set_listen_addresses( (void) getdns_context_set_listen_addresses(
context, NULL, NULL); context, NULL, NULL, NULL);
return; return;
} }
if (query_file) if (query_file)
@ -1184,7 +1258,7 @@ void read_line_cb(void *userarg)
r = parse_args(linec, linev); r = parse_args(linec, linev);
if (!r && touched_listen_list) { if (!r && touched_listen_list) {
r = getdns_context_set_listen_addresses( r = getdns_context_set_listen_addresses(
context, incoming_request_handler, listen_list); context, listen_list, NULL, incoming_request_handler);
} }
if ((r || (r = do_the_call())) && if ((r || (r = do_the_call())) &&
(r != CONTINUE && r != CONTINUE_ERROR)) (r != CONTINUE && r != CONTINUE_ERROR))
@ -1284,12 +1358,23 @@ static void request_cb(
getdns_return_t r = GETDNS_RETURN_GOOD; getdns_return_t r = GETDNS_RETURN_GOOD;
uint32_t n, rcode, dnssec_status; uint32_t n, rcode, dnssec_status;
#if !defined(SERVER_DEBUG) || !SERVER_DEBUG #if defined(SERVER_DEBUG) && SERVER_DEBUG
getdns_bindata *qname;
char *qname_str, *unknown_qname = "<unknown_qname>";
if (getdns_dict_get_bindata(msg->request, "/question/qname", &qname)
|| getdns_convert_dns_name_to_fqdn(qname, &qname_str))
qname_str = unknown_qname;
DEBUG_SERVER("reply for: %p %"PRIu64" %d (edns0: %d, do: %d, ad: %d,"
" cd: %d, qname: %s)\n", (void *)msg, transaction_id, (int)callback_type,
msg->has_edns0, msg->do_bit, msg->ad_bit, msg->cd_bit, qname_str);
if (qname_str != unknown_qname)
free(qname_str);
#else
(void)transaction_id; (void)transaction_id;
#endif #endif
DEBUG_SERVER("reply for: %p %"PRIu64" %d (edns0: %d, do: %d, ad: %d,"
" cd: %d)\n", (void *)msg, transaction_id, (int)callback_type,
msg->has_edns0, msg->do_bit, msg->ad_bit, msg->cd_bit);
assert(msg); assert(msg);
#if 0 #if 0
@ -1352,14 +1437,11 @@ static void request_cb(
else if (n == 0) else if (n == 0)
SERVFAIL("Recursion not available", 0, msg, &response); SERVFAIL("Recursion not available", 0, msg, &response);
if (!response) if ((r = getdns_reply(context, response, msg->request_id))) {
/* No response, no reply */
_getdns_cancel_reply(context, msg->request_id);
else if ((r = getdns_reply(context, msg->request_id, response))) {
fprintf(stderr, "Could not reply: %s\n", fprintf(stderr, "Could not reply: %s\n",
getdns_get_errorstr_by_id(r)); getdns_get_errorstr_by_id(r));
_getdns_cancel_reply(context, msg->request_id); /* Cancel reply */
(void) getdns_reply(context, NULL, msg->request_id);
} }
if (msg) { if (msg) {
getdns_dict_destroy(msg->request); getdns_dict_destroy(msg->request);
@ -1370,7 +1452,8 @@ static void request_cb(
} }
static void incoming_request_handler(getdns_context *context, static void incoming_request_handler(getdns_context *context,
getdns_dict *request, getdns_transaction_t request_id) getdns_callback_type_t callback_type, getdns_dict *request,
void *userarg, getdns_transaction_t request_id)
{ {
getdns_bindata *qname; getdns_bindata *qname;
char *qname_str = NULL; char *qname_str = NULL;
@ -1389,6 +1472,9 @@ static void incoming_request_handler(getdns_context *context,
getdns_dict *rr; getdns_dict *rr;
uint32_t rr_type; uint32_t rr_type;
(void)callback_type;
(void)userarg;
if (!query_extensions_spc && if (!query_extensions_spc &&
!(query_extensions_spc = getdns_dict_create())) !(query_extensions_spc = getdns_dict_create()))
fprintf(stderr, "Could not create query extensions space\n"); fprintf(stderr, "Could not create query extensions space\n");
@ -1516,14 +1602,11 @@ error:
free(request_str); free(request_str);
} while(0); } while(0);
#endif #endif
if (!response) if ((r = getdns_reply(context, response, request_id))) {
/* No response, no reply */
_getdns_cancel_reply(context, request_id);
else if ((r = getdns_reply(context, request_id, response))) {
fprintf(stderr, "Could not reply: %s\n", fprintf(stderr, "Could not reply: %s\n",
getdns_get_errorstr_by_id(r)); getdns_get_errorstr_by_id(r));
_getdns_cancel_reply(context, request_id); /* Cancel reply */
getdns_reply(context, NULL, request_id);
} }
if (msg) { if (msg) {
if (msg->request) if (msg->request)
@ -1545,7 +1628,18 @@ error:
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
char home_stubby_conf_fn[1024];
getdns_return_t r; getdns_return_t r;
#ifndef USE_WINSOCK
char *prg_name = strrchr(argv[0], '/');
#else
char *prg_name = strrchr(argv[0], '\\');
#endif
prg_name = prg_name ? prg_name + 1 : argv[0];
i_am_stubby = strcasecmp(prg_name, "stubby") == 0
|| strcasecmp(prg_name, "lt-stubby") == 0
|| strcasecmp(prg_name, "stubby.exe") == 0;
name = the_root; name = the_root;
if ((r = getdns_context_create(&context, 1))) { if ((r = getdns_context_create(&context, 1))) {
@ -1560,8 +1654,22 @@ main(int argc, char **argv)
r = GETDNS_RETURN_MEMORY_ERROR; r = GETDNS_RETURN_MEMORY_ERROR;
goto done_destroy_context; goto done_destroy_context;
} }
if (i_am_stubby) {
int n_chars = snprintf( home_stubby_conf_fn
, sizeof(home_stubby_conf_fn)
, "%s/.stubby.conf"
, getenv("HOME")
);
(void) parse_config(default_stubby_config);
(void) parse_config_file("/etc/stubby.conf", 0);
if (n_chars > 0 && n_chars < (int)sizeof(home_stubby_conf_fn)){
(void) parse_config_file(home_stubby_conf_fn, 0);
}
clear_listen_list_on_arg = 1;
}
if ((r = parse_args(argc, argv))) if ((r = parse_args(argc, argv)))
goto done_destroy_context; goto done_destroy_context;
clear_listen_list_on_arg = 0;
if (query_file) { if (query_file) {
fp = fopen(query_file, "rt"); fp = fopen(query_file, "rt");
@ -1578,8 +1686,10 @@ main(int argc, char **argv)
assert(loop); assert(loop);
} }
if (listen_count && (r = getdns_context_set_listen_addresses( if (listen_count && (r = getdns_context_set_listen_addresses(
context, incoming_request_handler, listen_list))) context, listen_list, NULL, incoming_request_handler))) {
perror("error: Could not bind on given addresses");
goto done_destroy_context; goto done_destroy_context;
}
/* Make the call */ /* Make the call */
if (interactive) { if (interactive) {
@ -1598,6 +1708,26 @@ main(int argc, char **argv)
} }
else if (listen_count) { else if (listen_count) {
assert(loop); 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
#endif
loop->vmt->run(loop); loop->vmt->run(loop);
} else } else
r = do_the_call(); r = do_the_call();
@ -1620,8 +1750,9 @@ done_destroy_context:
return 0; return 0;
else if (r == CONTINUE_ERROR) else if (r == CONTINUE_ERROR)
return 1; return 1;
if (!i_am_stubby)
fprintf(stdout, "\nAll done.\n"); fprintf(stdout, "\nAll done.\n");
return r; return r;
} }

64
src/tools/stubby.conf Normal file
View File

@ -0,0 +1,64 @@
{ resolution_type: GETDNS_RESOLUTION_STUB
, dns_transport_list: [ GETDNS_TRANSPORT_TLS ]
, upstream_recursive_servers:
[ { address_data: 145.100.185.15
, tls_auth_name: "dnsovertls.sinodun.com"
, tls_pubkey_pinset:
[ { digest: "sha256"
, value: 0xA132D34D34C181765337C70B83E3697B9524DDDB05A7118B43C0284033D5A0CC
} ]
},
{ address_data: 145.100.185.16
, tls_auth_name: "dnsovertls1.sinodun.com"
, tls_pubkey_pinset:
[ { digest: "sha256"
, value: 0x659B41EB08DCC70EE9D624E6219C76EE31954DA1548B0C8519EAE5228CB24150
} ]
},
{ address_data: 185.49.141.38
, tls_auth_name: "getdnsapi.net"
, tls_pubkey_pinset:
[ { digest: "sha256"
, value: 0x7e8c59467221f606695a797ecc488a6b4109dab7421aba0c5a6d3681ac5273d4
} ]
},
{ address_data: 2001:610:1:40ba:145:100:185:15
, tls_auth_name: "dnsovertls.sinodun.com"
, tls_pubkey_pinset:
[ { digest: "sha256"
, value: 0xA132D34D34C181765337C70B83E3697B9524DDDB05A7118B43C0284033D5A0CC
} ]
},
{ address_data: 2001:610:1:40ba:145:100:185:16
, tls_auth_name: "dnsovertls1.sinodun.com"
, tls_pubkey_pinset:
[ { digest: "sha256"
, value: 0x659B41EB08DCC70EE9D624E6219C76EE31954DA1548B0C8519EAE5228CB24150
} ]
},
{ address_data: 2a04:b900:0:100::38
, tls_auth_name: "getdnsapi.net"
, tls_pubkey_pinset:
[ { digest: "sha256"
, value: 0x7e8c59467221f606695a797ecc488a6b4109dab7421aba0c5a6d3681ac5273d4
} ]
},
{ address_data: 184.105.193.78
, tls_pubkey_pinset:
[ { digest: "sha256"
, value: 0xA4E5EBA54B7D9203E06D6C411457014DB447DA17A8DB01F05E9D5F7780045572
} ]
},
{ address_data: 2620:ff:c000:0:1::64:25
, tls_pubkey_pinset:
[ { digest: "sha256"
, value: 0xA4E5EBA54B7D9203E06D6C411457014DB447DA17A8DB01F05E9D5F7780045572
} ]
}
]
, tls_authentication: GETDNS_AUTHENTICATION_REQUIRED
, tls_query_padding_blocksize: 256
, edns_client_subnet_private : 1
, listen_addresses: [ 127.0.0.1, 0::1 ]
, idle_timeout: 10000
}

View File

@ -57,6 +57,15 @@ typedef struct getdns_item {
getdns_union data; getdns_union data;
} getdns_item; } getdns_item;
typedef enum getdns_auth_state {
GETDNS_AUTH_NONE, /* Not tried (Oppotunistic)*/
GETDNS_AUTH_FAILED, /* Tried but failed or not possible*/
GETDNS_AUTH_OK, /* Tried and worked (Strict) */
} getdns_auth_state_t;
#define GETDNS_STR_AUTH_NONE "None"
#define GETDNS_STR_AUTH_FAILED "Failed"
#define GETDNS_STR_AUTH_OK "Success"
struct getdns_context; struct getdns_context;
struct getdns_upstreams; struct getdns_upstreams;
@ -115,6 +124,8 @@ struct getdns_upstream;
#define GETDNS_TRANSPORTS_MAX 3 #define GETDNS_TRANSPORTS_MAX 3
#define GETDNS_UPSTREAM_TRANSPORTS 2 #define GETDNS_UPSTREAM_TRANSPORTS 2
#define GETDNS_CONN_ATTEMPTS 2
#define GETDNS_TRANSPORT_FAIL_MULT 5
/* declarations */ /* declarations */
@ -164,7 +175,6 @@ typedef struct getdns_tcp_state {
uint8_t *write_buf; uint8_t *write_buf;
size_t write_buf_len; size_t write_buf_len;
size_t written; size_t written;
int write_error;
uint8_t *read_buf; uint8_t *read_buf;
size_t read_buf_len; size_t read_buf_len;
@ -212,7 +222,6 @@ typedef struct getdns_network_req
size_t transport_current; size_t transport_current;
getdns_tls_authentication_t tls_auth_min; getdns_tls_authentication_t tls_auth_min;
getdns_eventloop_event event; getdns_eventloop_event event;
getdns_tcp_state tcp;
uint16_t query_id; uint16_t query_id;
int edns_maximum_udp_payload_size; int edns_maximum_udp_payload_size;
@ -226,7 +235,7 @@ typedef struct getdns_network_req
/* Some fields to record info for return_call_reporting */ /* Some fields to record info for return_call_reporting */
uint64_t debug_start_time; uint64_t debug_start_time;
uint64_t debug_end_time; uint64_t debug_end_time;
size_t debug_tls_auth_status; getdns_auth_state_t debug_tls_auth_status;
size_t debug_udp; size_t debug_udp;
/* When more space is needed for the wire_data response than is /* When more space is needed for the wire_data response than is
@ -414,5 +423,7 @@ void _getdns_network_validate_tsig(getdns_network_req *req);
void _getdns_netreq_reinit(getdns_network_req *netreq); void _getdns_netreq_reinit(getdns_network_req *netreq);
const char * _getdns_auth_str(getdns_auth_state_t auth);
#endif #endif
/* types-internal.h */ /* types-internal.h */

View File

@ -838,6 +838,16 @@ _getdns_create_call_reporting_dict(
was actually used for the last successful query.*/ was actually used for the last successful query.*/
if (transport == GETDNS_TRANSPORT_TCP && netreq->debug_udp == 1) { if (transport == GETDNS_TRANSPORT_TCP && netreq->debug_udp == 1) {
transport = GETDNS_TRANSPORT_UDP; transport = GETDNS_TRANSPORT_UDP;
if (getdns_dict_set_int( netreq_debug, "udp_responses_for_this_upstream",
netreq->upstream->udp_responses)) {
getdns_dict_destroy(netreq_debug);
return NULL;
}
if (getdns_dict_set_int( netreq_debug, "udp_timeouts_for_this_upstream",
netreq->upstream->udp_timeouts)) {
getdns_dict_destroy(netreq_debug);
return NULL;
}
} }
if (getdns_dict_set_int( netreq_debug, "transport", transport)) { if (getdns_dict_set_int( netreq_debug, "transport", transport)) {
getdns_dict_destroy(netreq_debug); getdns_dict_destroy(netreq_debug);
@ -858,6 +868,30 @@ _getdns_create_call_reporting_dict(
return NULL; return NULL;
} }
} }
/* The running totals are only updated when a connection is closed.
Since it is open as we have just used it, calcualte the value on the fly */
if (getdns_dict_set_int( netreq_debug, "responses_on_this_connection",
netreq->upstream->responses_received)) {
getdns_dict_destroy(netreq_debug);
return NULL;
}
if (getdns_dict_set_int( netreq_debug, "timeouts_on_this_connection",
netreq->upstream->responses_timeouts)) {
getdns_dict_destroy(netreq_debug);
return NULL;
}
if (getdns_dict_set_int( netreq_debug, "responses_for_this_upstream",
netreq->upstream->responses_received +
netreq->upstream->total_responses)) {
getdns_dict_destroy(netreq_debug);
return NULL;
}
if (getdns_dict_set_int( netreq_debug, "timeouts_for_this_upstream",
netreq->upstream->responses_timeouts +
netreq->upstream->total_timeouts)) {
getdns_dict_destroy(netreq_debug);
return NULL;
}
} }
if (netreq->upstream->transport != GETDNS_TRANSPORT_TLS) if (netreq->upstream->transport != GETDNS_TRANSPORT_TLS)
@ -865,8 +899,7 @@ _getdns_create_call_reporting_dict(
/* Only include the auth status if TLS was used */ /* Only include the auth status if TLS was used */
if (getdns_dict_util_set_string(netreq_debug, "tls_auth_status", if (getdns_dict_util_set_string(netreq_debug, "tls_auth_status",
netreq->debug_tls_auth_status == 0 ? _getdns_auth_str(netreq->debug_tls_auth_status))){
"OK: Hostname matched valid cert":"FAILED: Server not validated")){
getdns_dict_destroy(netreq_debug); getdns_dict_destroy(netreq_debug);
return NULL; return NULL;
@ -1529,4 +1562,14 @@ void _getdns_wire2list(uint8_t *pkt, size_t pkt_len, getdns_list *l)
} }
} }
const char * _getdns_auth_str(getdns_auth_state_t auth) {
static const char*
getdns_auth_str_array[] = {
GETDNS_STR_AUTH_NONE,
GETDNS_STR_AUTH_FAILED,
GETDNS_STR_AUTH_OK
};
return getdns_auth_str_array[auth];
}
/* util-internal.c */ /* util-internal.c */