Merge branch 'develop' of https://github.com/huitema/getdns into develop

Conflicts:
	src/jsmn
This commit is contained in:
Christian Huitema 2017-01-20 19:57:11 -08:00
commit 83ec9b74e9
50 changed files with 3048 additions and 2227 deletions

3
.gitignore vendored
View File

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

2
.gitmodules vendored
View File

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

View File

@ -1,3 +1,39 @@
* 2017-01-13: Version 1.0.0
* edns0_cookies extension enabled by default (per RFC7873)
* dnssec_roadblock_avoidance enabled by default (per RFC8027)
* bugfix: DSA support with OpenSSL 1.1.0
* Initialize OpenSSL just once in a thread safe way
* Thread safety with arc4random function
* Improvements that came from Visual Studio static analysis
Thanks Christian Huitema
* Conventional RFC3986 IPv6 [address]:port parsing from getdns_query
* bugfix: OpenSSL 1.1.0 style crypto locking
Thanks volkommenheit
* configure tells *which* dependency is missing
* bugfix: Exclude terminating '\0' from bindata's returned by
getdns_get_suffix(). Thanks Jim Hague
* 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
* Collect coverage information from the unit tests
Thanks Shane Kerr

View File

@ -44,7 +44,7 @@ libdir = @libdir@
srcdir = @srcdir@
INSTALL = @INSTALL@
all : default @GETDNS_QUERY@
all : default @GETDNS_QUERY@ @STUBBY@
everything: default
cd src/test && $(MAKE)
@ -52,7 +52,7 @@ everything: default
default:
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 644 $(srcdir)/AUTHORS $(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 "***"
uninstall: @UNINSTALL_GETDNS_QUERY@
uninstall: @UNINSTALL_GETDNS_QUERY@ @UNINSTALL_STUBBY@
rm -rf $(DESTDIR)$(docdir)
cd doc && $(MAKE) $@
cd src && $(MAKE) $@
@ -104,6 +104,9 @@ test:
getdns_query:
cd src && $(MAKE) $@
stubby:
cd src && $(MAKE) $@
scratchpad:
cd src && $(MAKE) $@
@ -111,10 +114,16 @@ pad: scratchpad
src/test/scratchpad || ./libtool exec gdb src/test/scratchpad
install-getdns_query:
cd src/test && $(MAKE) install
cd src/tools && $(MAKE) $@
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:
cd src && $(MAKE) $@
@ -141,18 +150,22 @@ distclean:
rm -f m4/ltoptions.m4
rm -f m4/ltsugar.m4
rm -f m4/ltversion.m4
rm -f $(distdir).tar.gz $(distdir).tar.gz.sha1
rm -f $(distdir).tar.gz $(distdir).tar.gz.sha256
rm -f $(distdir).tar.gz.md5 $(distdir).tar.gz.asc
megaclean:
cd $(srcdir) && rm -fr * .dir-locals.el .gitignore .indent.pro .travis.yml && git reset --hard
cd $(srcdir) && rm -fr * .dir-locals.el .gitignore .indent.pro .travis.yml && git reset --hard && git submodule update --init
autoclean: megaclean
libtoolize -ci
autoreconf -fi
dist: $(distdir).tar.gz
pub: $(distdir).tar.gz.sha1 $(distdir).tar.gz.md5 $(distdir).tar.gz.asc
pub: $(distdir).tar.gz.sha256 $(distdir).tar.gz.md5 $(distdir).tar.gz.asc
$(distdir).tar.gz.sha1: $(distdir).tar.gz
openssl sha1 $(distdir).tar.gz >$@
$(distdir).tar.gz.sha256: $(distdir).tar.gz
openssl sha256 $(distdir).tar.gz >$@
$(distdir).tar.gz.md5: $(distdir).tar.gz
openssl md5 $(distdir).tar.gz >$@
@ -183,6 +196,8 @@ $(distdir):
mkdir -p $(distdir)/src/compat
mkdir -p $(distdir)/src/util
mkdir -p $(distdir)/src/gldns
mkdir -p $(distdir)/src/tools
mkdir -p $(distdir)/src/jsmn
mkdir -p $(distdir)/doc
mkdir -p $(distdir)/spec
mkdir -p $(distdir)/spec/example
@ -225,9 +240,11 @@ $(distdir):
cp $(srcdir)/spec/*.tgz $(distdir)/spec || true
cp $(srcdir)/spec/example/Makefile.in $(distdir)/spec/example
cp $(srcdir)/spec/example/*.[ch] $(distdir)/spec/example
cp $(srcdir)/src/test/jsmn/*.[ch] $(distdir)/src/test/jsmn
cp $(srcdir)/src/test/jsmn/LICENSE $(distdir)/src/test/jsmn
cp $(srcdir)/src/test/jsmn/README.md $(distdir)/src/test/jsmn
cp $(srcdir)/src/tools/Makefile.in $(distdir)/src/tools
cp $(srcdir)/src/tools/*.[ch] $(distdir)/src/tools
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
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.
getdns also provides a experimental DNS Privacy enabled client called 'stubby' - see below for more details.
## 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.
@ -73,9 +75,13 @@ If you want to make use of the configuration files that utilise a JSON-like form
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
@ -83,7 +89,7 @@ If you want to use the getdns_query command line wrapper script for testing or t
* Currently getdns only offers two helper functions to deal with IDN: `getdns_convert_ulabel_to_alabel` and `getdns_convert_alabel_to_ulabel`. If you do not need these functions, getdns can be configured to compile without them with the `--without-libidn` option to configure.
* When both `--enable-stub-only` and `--without-libidn` options are used, getdns has only one dependency left, which is OpenSSL.
## Extensions / Event loop dependencies
## Extensions and Event loop dependencies
The implementation works with a variety of event loops, each built as a separate shared library. See [the wiki](https://github.com/getdnsapi/getdns/wiki/Asynchronous-Support#wiki-included-event-loop-integrations) for more details.
@ -91,6 +97,18 @@ The implementation works with a variety of event loops, each built as a separate
* [libuv](https://github.com/joyent/libuv)
* [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
A suite of regression tests are included with the library, if you make changes or just
@ -124,7 +142,7 @@ We have a [getdns users list](https://getdnsapi.net/mailman/listinfo/users) for
The [getdns-api mailing list](https://getdnsapi.net/mailman/listinfo/spec) is a good place to engage in discussions regarding the design of the API.
# Tickets/Bug Reports
# Tickets and Bug Reports
Tickets and bug reports should be reported via the [GitHub issues list](https://github.com/getdnsapi/getdns/issues).
@ -179,7 +197,18 @@ Stub mode does not support:
# Known Issues
* None
* The synchronous lookup functions will not work when new file descriptors
needed for the lookup will be larger than `FD_SETSIZE`. This is because
the synchronous functions use a "default" event loop under the hood
which is based on `select()` and thus inherits the limits that `select()` has.
If you need only slightly more file descriptors, it is possible to enlarge
the `FD_SETSIZE` with the `--with-fd-setsize=`*`size`* flag to `configure`.
To resolve, use the asynchronous functions with an event loop extension for
libevent, libev or libuv. Note that the asynchronous functions will have
the same problem when used in combination with `getdns_context_run()`, which
also uses the default event loop.
# Supported Platforms
@ -203,7 +232,7 @@ If you're using [FreeBSD](https://www.freebsd.org/), you may install getdns via
If you are using FreeBSD 10 getdns can be intalled via 'pkg install getdns'.
### CentOS/RHEL 6.5
### CentOS and RHEL 6.5
We rely on the most excellent package manager fpm to build the linux packages, which
means that the packaging platform requires ruby 2.1.0. There are other ways to
@ -261,7 +290,7 @@ The build has been tested using the following:
32 bit only Mingw: [Mingw(3.21.0) and Msys 1.0](http://www.mingw.org/) on Windows 8.1
32 bit build on a 64 bit Mingw [Download latest from: http://mingw-w64.org/doku.php/download/mingw-builds and http://msys2.github.io/]. IMPORTANT: Install tested ONLY on the "x86_64" for 64-bit installer of msys2.
#### Dependencies:
#### Dependencies
The following dependencies are
* openssl-1.0.2j
* libidn

View File

@ -36,8 +36,8 @@ sinclude(./m4/acx_getaddrinfo.m4)
sinclude(./m4/ax_check_compile_flag.m4)
sinclude(./m4/pkg.m4)
AC_INIT([getdns], [1.0.0], [users@getdnsapi.net], [], [https://getdnsapi.net])
AC_SUBST(RELEASE_CANDIDATE, [b2])
AC_INIT([getdns], [1.1.0], [users@getdnsapi.net], [], [https://getdnsapi.net])
AC_SUBST(RELEASE_CANDIDATE, [-alpha3])
# Set current date from system if not set
AC_ARG_WITH([current-date],
@ -47,7 +47,7 @@ AC_ARG_WITH([current-date],
[CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"])
AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"])
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x00100200])
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x0100A300])
AC_SUBST(API_VERSION, ["December 2015"])
AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00])
GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API"
@ -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.9.0 had libversion 5:0: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_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-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-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]))
@ -157,6 +159,7 @@ case "$enable_all_debugging" in
yes)
enable_debug_sched=yes
enable_debug_stub=yes
enable_debug_daemon=yes
enable_debug_sec=yes
enable_debug_server=yes
;;
@ -177,6 +180,13 @@ case "$enable_debug_stub" in
no|*)
;;
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
yes)
AC_DEFINE_UNQUOTED([SEC_DEBUG], [1], [Define this to enable printing of dnssec debugging messages.])
@ -253,7 +263,7 @@ fi
AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/bn.h openssl/rsa.h openssl/dsa.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method])
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode ENGINE_load_cryptodev EVP_PKEY_keygen ECDSA_SIG_get0 EVP_MD_CTX_new EVP_PKEY_base_id HMAC_CTX_new HMAC_CTX_free TLS_client_method DSA_SIG_set0 EVP_dss1])
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
AC_INCLUDES_DEFAULT
#ifdef HAVE_OPENSSL_ERR_H
@ -440,39 +450,38 @@ case "$enable_dsa" in
;;
*) dnl default
# detect if DSA is supported, and turn it off if not.
AC_CHECK_FUNC(EVP_dss1, [
AC_CHECK_FUNC(DSA_SIG_new, [
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
fi ])
;;
esac
AC_ARG_ENABLE(draft-dnssec-roadblock-avoidance, AC_HELP_STRING([--enable-draft-dnssec-roadblock-avoidance], [Enable experimental dnssec roadblock avoidance]))
AC_ARG_ENABLE(draft-edns-cookies, AC_HELP_STRING([--enable-draft-edns-cookies], [Enable experimental edns cookies]))
AC_ARG_ENABLE(all-drafts, AC_HELP_STRING([--enable-all-drafts], [Enable cookies and roadblock avoidance]))
AC_ARG_ENABLE(all-drafts, AC_HELP_STRING([--enable-all-drafts], [No drafts in this release]))
case "$enable_all_drafts" in
yes)
enable_draft_dnssec_roadblock_avoidance=yes
enable_draft_edns_cookies=yes
;;
no|*)
;;
esac
case "$enable_draft_dnssec_roadblock_avoidance" in
yes)
AC_DEFINE_UNQUOTED([DNSSEC_ROADBLOCK_AVOIDANCE], [1], [Define this to enable the experimental draft dnssec roadblock avoidance.])
AC_ARG_ENABLE(dnssec-roadblock-avoidance, AC_HELP_STRING([--disable-dnssec-roadblock-avoidance], [Disable dnssec roadblock avoidance]))
case "$enable_dnssec_roadblock_avoidance" in
no)
;;
no|*)
yes|*)
AC_DEFINE_UNQUOTED([DNSSEC_ROADBLOCK_AVOIDANCE], [1], [Define this to enable the experimental dnssec roadblock avoidance.])
;;
esac
case "$enable_draft_edns_cookies" in
yes)
AC_ARG_ENABLE(edns-cookies, AC_HELP_STRING([--disable-edns-cookies], [Disable edns cookies]))
case "$enable_edns_cookies" in
no)
;;
yes|*)
if test "x_$HAVE_SSL" != "x_yes"; then
AC_MSG_ERROR([edns cookies need openssl libcrypto which is not available, please rerun without --enable-draft-edns-cookies])
AC_MSG_ERROR([edns cookies need openssl libcrypto which is not available, please rerun with --disable-edns-cookies])
fi
AC_DEFINE_UNQUOTED([EDNS_COOKIES], [1], [Define this to enable the experimental draft edns cookies.])
;;
no|*)
AC_DEFINE_UNQUOTED([EDNS_COOKIES], [1], [Define this to enable the experimental edns cookies.])
;;
esac
AC_DEFINE_UNQUOTED([EDNS_COOKIE_OPCODE], [10], [The edns cookie option code.])
@ -908,9 +917,9 @@ AC_DEFINE_UNQUOTED([TRUST_ANCHOR_FILE], ["$TRUST_ANCHOR_FILE"], [Default trust a
AC_SUBST(TRUST_ANCHOR_FILE)
AC_MSG_NOTICE([Default trust anchor: $TRUST_ANCHOR_FILE])
AC_ARG_WITH(getdns_query, AS_HELP_STRING([--with-getdns_query],
[Also compile and install the getdns_query tool]),
[], [withval="no"])
AC_ARG_WITH(getdns_query, AS_HELP_STRING([--without-getdns_query],
[Do not compile and install the getdns_query tool]),
[], [withval="yes"])
if test x_$withval = x_no; then
GETDNS_QUERY=""
INSTALL_GETDNS_QUERY=""
@ -920,6 +929,26 @@ else
INSTALL_GETDNS_QUERY="install-getdns_query"
UNINSTALL_GETDNS_QUERY="uninstall-getdns_query"
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],
[Set maximum file descriptor number that can be used by select]),
[], [withval="no"])
@ -932,11 +961,7 @@ case "$withval" in
;;
esac
AC_SUBST(GETDNS_QUERY)
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])
AC_CONFIG_FILES([Makefile src/Makefile src/version.c src/getdns/getdns.h src/getdns/getdns_extra.h spec/example/Makefile src/test/Makefile src/tools/Makefile doc/Makefile getdns.pc getdns_ext_event.pc])
if [ test -n "$DOXYGEN" ]
then AC_CONFIG_FILES([src/Doxyfile])
fi
@ -945,6 +970,14 @@ fi
#---- check for pthreads library
AC_SEARCH_LIBS([pthread_mutex_init],[pthread],[AC_DEFINE([HAVE_PTHREADS], [1], [Have pthreads library])], [AC_MSG_WARN([pthreads not available])])
AC_MSG_CHECKING([whether the C compiler (${CC-cc}) supports the __func__ variable])
AC_LANG_PUSH(C)
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[char*s=__func__;]],[[]])],
[AC_MSG_RESULT([yes])
AC_DEFINE(HAVE___FUNC__, [1], [Whether the C compiler support the __func__ variable])],
[AC_MSG_RESULT([no])])
AC_LANG_POP(C)
dnl -----
dnl ----- Start of "Things needed for gldns" section
@ -1061,6 +1094,12 @@ AC_DEFINE_UNQUOTED([MAX_CNAME_REFERRALS], [100], [The maximum number of cname re
AH_BOTTOM([
#ifdef HAVE___FUNC__
#define __FUNC__ __func__
#else
#define __FUNC__ __FUNCTION__
#endif
#ifdef GETDNS_ON_WINDOWS
/* On windows it is allowed to increase the FD_SETSIZE
* (and nescessary to make our custom eventloop work)

View File

@ -67,7 +67,7 @@ C99COMPATFLAGS=@C99COMPATFLAGS@
GETDNS_OBJ=const-info.lo convert.lo dict.lo dnssec.lo general.lo \
list.lo request-internal.lo pubkey-pinning.lo rr-dict.lo \
rr-iter.lo 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 \
mdns.lo
GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \
@ -79,6 +79,8 @@ COMPAT_OBJ=$(LIBOBJS:.o=.lo)
UTIL_OBJ=rbtree.lo val_secalgo.lo
JSMN_OBJ=jsmn.lo
EXTENSION_OBJ=default_eventloop.lo libevent.lo libev.lo
NON_C99_OBJS=context.lo libuv.lo
@ -107,6 +109,9 @@ $(COMPAT_OBJ):
$(UTIL_OBJ):
$(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):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -c $(srcdir)/extension/$(@:.lo=.c) -o $@
@ -147,15 +152,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
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_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
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ)
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo default_eventloop.lo $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
test: all
cd test && $(MAKE) $@
getdns_query: all
cd test && $(MAKE) $@
cd tools && $(MAKE) $@
stubby: all
cd tools && $(MAKE) $@
scratchpad: all
cd test && $(MAKE) $@
@ -163,11 +170,13 @@ scratchpad: all
pad: scratchpad
clean:
cd tools && $(MAKE) $@
cd test && $(MAKE) $@
rm -f *.o *.lo extension/*.lo extension/*.o $(PROGRAMS) libgetdns.la libgetdns_ext_*.la
rm -rf .libs extension/.libs
distclean : clean
cd tools && $(MAKE) $@
cd test && $(MAKE) $@
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
@ -175,42 +184,17 @@ distclean : clean
rmdir extension 2>/dev/null || true
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
cd .. && ./config.status src/Makefile
configure.status: configure
cd .. && ./config.status --recheck
depend:
(cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new )
(blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" *.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" \
-e 's?gldns/?$$(srcdir)/gldns/?g' \
-e 's?compat/?$$(srcdir)/compat/?g' \
-e 's?util/?$$(srcdir)/util/?g' \
-e 's?jsmn/?$$(srcdir)/jsmn/?g' \
-e 's?extension/?$$(srcdir)/extension/?g' \
-e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
-e 's? \$$(srcdir)/config\.h? config.h?g' \
@ -222,6 +206,7 @@ depend:
-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 )
cd tools && $(MAKE) $@
cd test && $(MAKE) $@
.PHONY: clean test
@ -234,76 +219,84 @@ 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 \
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)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
$(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h \
$(srcdir)/pubkey-pinning.h
convert.lo convert.o: $(srcdir)/convert.c config.h getdns/getdns.h getdns/getdns_extra.h \
getdns/getdns.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/debug.h $(srcdir)/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)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h \
$(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h
dict.lo dict.o: $(srcdir)/dict.c config.h $(srcdir)/types-internal.h getdns/getdns.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \
$(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h \
$(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h
$(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h
dnssec.lo dnssec.o: $(srcdir)/dnssec.c config.h $(srcdir)/debug.h getdns/getdns.h $(srcdir)/context.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \
$(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h \
$(srcdir)/util/val_secalgo.h
$(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h \
$(srcdir)/list.h $(srcdir)/util/val_secalgo.h
general.lo general.o: $(srcdir)/general.c config.h $(srcdir)/general.h getdns/getdns.h $(srcdir)/types-internal.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \
getdns/getdns_extra.h $(srcdir)/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)/mdns.h
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \
getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/debug.h $(srcdir)/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
mdns.lo mdns.o: $(srcdir)/mdns.c config.h $(srcdir)/debug.h $(srcdir)/context.h getdns/getdns.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/server.h $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/mdns.h
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c config.h $(srcdir)/debug.h getdns/getdns.h \
$(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h $(srcdir)/types-internal.h \
$(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \
getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h
getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h
request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \
getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
$(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \
getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/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/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h
rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h config.h getdns/getdns.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/util-internal.h $(srcdir)/context.h getdns/getdns_extra.h getdns/getdns.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h config.h \
getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/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 \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h
server.lo server.o: $(srcdir)/server.c config.h getdns/getdns_extra.h getdns/getdns.h \
$(srcdir)/context.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/debug.h $(srcdir)/server.h
stub.lo stub.o: $(srcdir)/stub.c config.h $(srcdir)/debug.h $(srcdir)/stub.h getdns/getdns.h $(srcdir)/types-internal.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
mdns.lo mdns.o: $(srcdir)/mdns.c config.h $(srcdir)/debug.h $(srcdir)/mdns.h getdns/getdns.h $(srcdir)/types-internal.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns_extra.h $(srcdir)/ub_loop.h \
$(srcdir)/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 \
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)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
$(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \
$(srcdir)/gldns/wire2str.h
ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h config.h getdns/getdns.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/debug.h
util-internal.lo util-internal.o: $(srcdir)/util-internal.c config.h getdns/getdns.h $(srcdir)/dict.h \
$(srcdir)/util/rbtree.h $(srcdir)/types-internal.h getdns/getdns_extra.h getdns/getdns.h \
$(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h config.h \
getdns/getdns_extra.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/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/rrdef.h
version.lo version.o: version.c
@ -335,6 +328,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
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
jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h
default_eventloop.lo default_eventloop.o: $(srcdir)/extension/default_eventloop.c config.h \
$(srcdir)/extension/default_eventloop.h getdns/getdns.h getdns/getdns_extra.h \
$(srcdir)/debug.h config.h $(srcdir)/types-internal.h getdns/getdns.h getdns/getdns_extra.h \

View File

@ -123,3 +123,213 @@ getdns_get_errorstr_by_id(uint16_t err)
else
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_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 );
}
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_name_info {
const char *name;
uint32_t code;
};
int _getdns_get_const_name_info(const char *name, uint32_t *code);
#endif
/* const-info.h */

View File

@ -62,6 +62,11 @@ typedef unsigned short in_port_t;
#include <assert.h>
#include <ctype.h>
#ifdef HAVE_PTHREADS
#include <pthread.h>
#endif
#include <stdbool.h>
#include "config.h"
#ifdef HAVE_LIBUNBOUND
#include <unbound.h>
@ -84,6 +89,14 @@ typedef unsigned short in_port_t;
#define GETDNS_STR_PORT_ZERO "0"
#define GETDNS_STR_PORT_DNS "53"
#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
static pthread_mutex_t ssl_init_lock = PTHREAD_MUTEX_INITIALIZER;
#endif
static bool ssl_init=false;
void *plain_mem_funcs_user_arg = MF_PLAIN;
@ -152,7 +165,7 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
HCERTSTORE hSystemStore;
PCCERT_CONTEXT pTargetCert = NULL;
DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNCTION__,
DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__,
"Adding Windows certificates to CA store");
/* load just once per context lifetime for this version of getdns
@ -181,7 +194,7 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
/* failure if the CA store is empty or the call fails */
if ((pTargetCert = CertEnumCertificatesInStore(
hSystemStore, pTargetCert)) == 0) {
DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNCTION__,
DEBUG_STUB("%s %-35s: %s\n", STUB_DEBUG_SETUP_TLS, __FUNC__,
"CA certificate store for Windows is empty.");
return 0;
}
@ -193,7 +206,7 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
pTargetCert->cbCertEncoded);
if (!cert1) {
/* return error if a cert fails */
DEBUG_STUB("%s %-35s: %s %d:%s\n", STUB_DEBUG_SETUP_TLS, __FUNCTION__,
DEBUG_STUB("%s %-35s: %s %d:%s\n", STUB_DEBUG_SETUP_TLS, __FUNC__,
"Unable to parse certificate in memory",
ERR_get_error(), ERR_error_string(ERR_get_error(), NULL));
return 0;
@ -201,7 +214,7 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
else {
/* return error if a cert add to store fails */
if (X509_STORE_add_cert(store, cert1) == 0) {
DEBUG_STUB("%s %-35s: %s %d:%s\n", STUB_DEBUG_SETUP_TLS, __FUNCTION__,
DEBUG_STUB("%s %-35s: %s %d:%s\n", STUB_DEBUG_SETUP_TLS, __FUNC__,
"Error adding certificate", ERR_get_error(),
ERR_error_string(ERR_get_error(), NULL));
return 0;
@ -224,6 +237,25 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
}
#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)
{
getdns_context *context = (getdns_context *)arg;
@ -264,7 +296,6 @@ create_default_dns_transports(struct getdns_context *context)
context->dns_transports[0] = GETDNS_TRANSPORT_UDP;
context->dns_transports[1] = GETDNS_TRANSPORT_TCP;
context->dns_transport_count = 2;
context->dns_transport_current = 0;
return GETDNS_RETURN_GOOD;
}
@ -616,7 +647,7 @@ upstreams_create(getdns_context *context, size_t size)
r->mf = context->mf;
r->referenced = 1;
r->count = 0;
r->current = 0;
r->current_udp = 0;
return r;
}
@ -678,48 +709,89 @@ _getdns_upstreams_dereference(getdns_upstreams *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
_getdns_upstream_shutdown(getdns_upstream *upstream)
{
/*There is a race condition with a new request being scheduled
while this happens so take ownership of the fd asap*/
int fd = upstream->fd;
upstream->fd = -1;
/* If the connection had a problem, but had worked this time,
* then allow re-use in the future*/
if (upstream->tcp.write_error == 1 &&
upstream->responses_received > 0)
upstream->tcp.write_error = 0;
upstream->writes_done = 0;
upstream->responses_received = 0;
upstream->keepalive_timeout = 0;
if (upstream->tls_hs_state != GETDNS_HS_FAILED) {
upstream->tls_hs_state = GETDNS_HS_NONE;
upstream->tls_auth_failed = 0;
/*Set condition to tear down asap to stop any further scheduling*/
upstream->conn_state = GETDNS_CONN_TEARDOWN;
/* Update total stats for the upstream.*/
upstream->total_responses+=upstream->responses_received;
upstream->total_timeouts+=upstream->responses_timeouts;
/* Need the last auth state when using session resumption*/
upstream->last_tls_auth_state = upstream->tls_auth_state;
/* Keep track of the best auth state this upstream has had*/
if (upstream->tls_auth_state > upstream->best_tls_auth_state)
upstream->best_tls_auth_state = upstream->tls_auth_state;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %s : Conn closed : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n",
STUB_DEBUG_DAEMON, upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->responses_received, (int)upstream->responses_timeouts,
_getdns_auth_str(upstream->tls_auth_state), (int)upstream->keepalive_timeout);
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*/
upstream->tls_auth_state = GETDNS_AUTH_NONE;
if (upstream->tls_obj != NULL) {
SSL_shutdown(upstream->tls_obj);
SSL_free(upstream->tls_obj);
upstream->tls_obj = NULL;
}
if (fd != -1)
{
if (upstream->fd != -1) {
#ifdef USE_WINSOCK
closesocket(fd);
closesocket(upstream->fd);
#else
close(fd);
close(upstream->fd);
#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
@ -832,13 +904,30 @@ upstream_init(getdns_upstream *upstream,
upstream->addr_len = 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? */
upstream->writes_done = 0;
/* How is this upstream doing on connections? */
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_timeouts = 0;
upstream->keepalive_shutdown = 0;
upstream->keepalive_timeout = 0;
/* How is this upstream doing on UDP? */
upstream->to_retry = 2;
upstream->back_off = 1;
upstream->udp_responses = 0;
upstream->udp_timeouts = 0;
/* For sharing a socket to this upstream with TCP */
upstream->fd = -1;
@ -846,10 +935,11 @@ upstream_init(getdns_upstream *upstream,
upstream->tls_session = NULL;
upstream->transport = GETDNS_TRANSPORT_TCP;
upstream->tls_hs_state = GETDNS_HS_NONE;
upstream->tls_auth_failed = 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->tcp.write_error = 0;
upstream->loop = NULL;
(void) getdns_eventloop_event_init(
&upstream->event, upstream, NULL, NULL, NULL);
@ -1250,6 +1340,8 @@ getdns_context_create_with_extended_memory_functions(
_getdns_rbtree_init(&result->outbound_requests, transaction_id_cmp);
_getdns_rbtree_init(&result->local_hosts, local_host_cmp);
result->server = NULL;
#ifdef HAVE_LIBUNBOUND
result->resolution_type = GETDNS_RESOLUTION_RECURSING;
#else
@ -1306,6 +1398,27 @@ getdns_context_create_with_extended_memory_functions(
_getdns_default_eventloop_init(&result->default_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_hosts = NULL;
@ -1325,14 +1438,26 @@ getdns_context_create_with_extended_memory_functions(
result->tls_auth = GETDNS_AUTHENTICATION_NONE;
result->tls_auth_min = GETDNS_AUTHENTICATION_NONE;
result->limit_outstanding_queries = 0;
result->return_dnssec_status = GETDNS_EXTENSION_FALSE;
/* unbound context is initialized here */
/* Unbound needs SSL to be init'ed this early when TLS is used. However we
* don't know that till later so we will have to do this every time. */
if ((set_from_os & 2) == 0)
#ifdef HAVE_PTHREADS
pthread_mutex_lock(&ssl_init_lock);
#else
/* XXX implement Windows-style lock here */
#endif
/* Only initialise SSL once and ideally in a thread-safe manner */
if (ssl_init == false) {
SSL_library_init();
ssl_init = true;
}
#ifdef HAVE_PTHREADS
pthread_mutex_unlock(&ssl_init_lock);
#else
/* XXX implement Windows-style unlock here */
#endif
#ifdef HAVE_LIBUNBOUND
result->unbound_ctx = NULL;
@ -1405,6 +1530,9 @@ getdns_context_destroy(struct getdns_context *context)
/* cancel all outstanding requests */
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
* might be an idle_timeout schedules, which will not get unscheduled
* with cancel_outstanding_requests.
@ -1437,7 +1565,6 @@ getdns_context_destroy(struct getdns_context *context)
if (context->tls_ctx)
SSL_CTX_free(context->tls_ctx);
if (context->dns_root_servers)
getdns_list_destroy(context->dns_root_servers);
#if defined(HAVE_LIBUNBOUND) && !defined(HAVE_UB_CTX_SET_STUB)
@ -1455,6 +1582,10 @@ getdns_context_destroy(struct getdns_context *context)
_getdns_traverse_postorder(&context->local_hosts,
destroy_local_host, context);
getdns_dict_destroy(context->header);
getdns_dict_destroy(context->add_opt_parameters);
#ifdef USE_WINSOCK
WSACleanup();
#endif
@ -1532,7 +1663,7 @@ getdns_context_request_count_changed(getdns_context *context)
if (context->outbound_requests.count && ! context->ub_event.ev){
DEBUG_SCHED("gc_request_count_changed "
"-> ub schedule(el_ev = %p, el_ev->ev = %p)\n",
&context->ub_event, context->ub_event.ev);
(void *)&context->ub_event, (void *)context->ub_event.ev);
#ifndef USE_WINSOCK
#ifdef HAVE_UNBOUND_EVENT_API
if (!_getdns_ub_loop_enabled(&context->ub_loop))
@ -1546,7 +1677,7 @@ getdns_context_request_count_changed(getdns_context *context)
context->ub_event.ev) {
DEBUG_SCHED("gc_request_count_changed "
"-> ub clear(el_ev = %p, el_ev->ev = %p)\n",
&context->ub_event, context->ub_event.ev);
(void *)&context->ub_event, (void *)context->ub_event.ev);
#ifndef USE_WINSOCK
#ifdef HAVE_UNBOUND_EVENT_API
@ -2822,22 +2953,8 @@ getdns_cancel_callback(getdns_context *context,
return r;
} /* 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
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);
}
#ifndef STUB_NATIVE_DNSSEC
static uint32_t *
upstream_scope_id(getdns_upstream *upstream)
@ -3333,14 +3450,6 @@ getdns_context_get_eventloop(getdns_context *context, getdns_eventloop **loop)
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*
_get_context_settings(getdns_context* context)
{
@ -3469,7 +3578,7 @@ getdns_context_set_return_dnssec_status(getdns_context* context, int enabled) {
enabled != GETDNS_EXTENSION_FALSE) {
return GETDNS_RETURN_INVALID_PARAMETER;
}
context->return_dnssec_status = enabled;
context->dnssec_return_status = enabled == GETDNS_EXTENSION_TRUE;
return GETDNS_RETURN_GOOD;
}
@ -3943,4 +4052,209 @@ getdns_context_get_tls_query_padding_blocksize(getdns_context *context, uint16_t
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 */

View File

@ -44,6 +44,7 @@
#include "extension/default_eventloop.h"
#include "util/rbtree.h"
#include "ub_loop.h"
#include "server.h"
struct getdns_dns_req;
struct ub_ctx;
@ -80,6 +81,14 @@ typedef enum getdns_tls_hs_state {
GETDNS_HS_FAILED
} 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 {
GETDNS_NO_TSIG = 0, /* Do not use tsig */
GETDNS_HMAC_MD5 = 1, /* 128 bits */
@ -115,32 +124,56 @@ typedef struct getdns_upstream {
socklen_t addr_len;
struct sockaddr_storage addr;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
char addr_str[INET6_ADDRSTRLEN];
#endif
/* How is this upstream doing? */
size_t writes_done;
size_t responses_received;
uint64_t keepalive_timeout;
/* How is this upstream doing over UDP? */
int to_retry;
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;
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 *loop;
getdns_tcp_state tcp;
char tls_auth_name[256];
size_t tls_auth_failed;
sha256_pin_t *tls_pubkey_pinset;
/* These are running totals or historical info */
size_t conn_completed;
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_last;
_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
* that is kept open, and a synchronous call is then done with the
* upstream before all scheduled requests have been answered, answers
@ -157,6 +190,7 @@ typedef struct getdns_upstream {
*/
getdns_dns_req *finished_dnsreqs;
getdns_eventloop_event finished_event;
unsigned is_sync_loop : 1;
/* EDNS cookies */
uint32_t secret;
@ -168,8 +202,6 @@ typedef struct getdns_upstream {
unsigned has_prev_client_cookie : 1;
unsigned has_server_cookie : 1;
unsigned server_cookie_len : 5;
unsigned tls_fallback_ok : 1;
unsigned is_sync_loop : 1;
/* TSIG */
uint8_t tsig_dname[256];
@ -184,7 +216,7 @@ typedef struct getdns_upstreams {
struct mem_funcs mf;
size_t referenced;
size_t count;
size_t current;
size_t current_udp;
getdns_upstream upstreams[];
} getdns_upstreams;
@ -219,7 +251,6 @@ struct getdns_context {
getdns_transport_list_t *dns_transports;
size_t dns_transport_count;
size_t dns_transport_current;
uint8_t edns_extended_rcode;
uint8_t edns_version;
@ -250,8 +281,6 @@ struct getdns_context {
/* A tree to hold local host information*/
_getdns_rbtree_t local_hosts;
int return_dnssec_status;
/* which resolution type the contexts are configured for
* 0 means nothing set
*/
@ -262,6 +291,8 @@ struct getdns_context {
*/
_getdns_rbtree_t outbound_requests;
struct listen_set *server;
/* Event loop extension. */
getdns_eventloop *extension;
@ -275,6 +306,24 @@ struct getdns_context {
_getdns_default_eventloop default_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
*/

View File

@ -48,8 +48,12 @@
#include "util-internal.h"
#include "gldns/wire2str.h"
#include "gldns/str2wire.h"
#include "gldns/parseutil.h"
#include "const-info.h"
#include "types-internal.h" /* For getdns_item */
#include "dict.h"
#include "list.h"
#include "jsmn/jsmn.h"
#include "convert.h"
#include "debug.h"
@ -156,6 +160,7 @@ getdns_convert_ulabel_to_alabel(const char *ulabel)
free(prepped2);
return buf;
#else
(void)ulabel;
return NULL;
#endif
}
@ -185,6 +190,7 @@ getdns_convert_alabel_to_ulabel(const char *alabel)
}
return buf;
#else
(void)alabel;
return NULL;
#endif
}
@ -832,7 +838,6 @@ _getdns_reply_dict2wire(
}
}
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)) {
for ( n = 0, i = 0
@ -1067,5 +1072,673 @@ getdns_msg_dict2str_scan(
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"
#define STUB_DEBUG_ENTRY "-> ENTRY: "
#define STUB_DEBUG_ENTRY "=> ENTRY: "
#define STUB_DEBUG_SETUP "--- SETUP: "
#define STUB_DEBUG_SETUP_TLS "--- SETUP(TLS): "
#define STUB_DEBUG_TSIG "--- TSIG: "
@ -45,6 +45,7 @@
#define STUB_DEBUG_READ "------- READ: "
#define STUB_DEBUG_WRITE "------- WRITE: "
#define STUB_DEBUG_CLEANUP "--- CLEANUP: "
#define STUB_DEBUG_DAEMON "GETDNS_DAEMON: "
#ifdef GETDNS_ON_WINDOWS
#define DEBUG_ON(...) do { \
@ -67,7 +68,7 @@
char buf[10]; \
\
gettimeofday(&tv, NULL); \
gmtime_r(&tm, &tv.tv_sec); \
gmtime_r(&tv.tv_sec, &tm); \
strftime(buf, 10, "%H:%M:%S", &tm); \
fprintf(stderr, "[%s.%.6d] ", buf, (int)tv.tv_usec); \
fprintf(stderr, __VA_ARGS__); \
@ -104,6 +105,13 @@
#define DEBUG_STUB(...) DEBUG_OFF(__VA_ARGS__)
#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
#include <time.h>
#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
* 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)
{
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
* processing each head in turn. The worst outcome is the dnssec status for

View File

@ -54,7 +54,7 @@ default_eventloop_schedule(getdns_eventloop *loop,
size_t i;
DEBUG_SCHED( "%s(loop: %p, fd: %d, timeout: %"PRIu64", event: %p, FD_SETSIZE: %d)\n"
, __FUNCTION__, loop, fd, timeout, event, FD_SETSIZE);
, __FUNC__, (void *)loop, fd, timeout, (void *)event, FD_SETSIZE);
if (!loop || !event)
return GETDNS_RETURN_INVALID_PARAMETER;
@ -75,11 +75,11 @@ default_eventloop_schedule(getdns_eventloop *loop,
if (default_loop->fd_events[fd] == event) {
DEBUG_SCHED("WARNING: Event %p not cleared "
"before being rescheduled!\n"
, default_loop->fd_events[fd]);
, (void *)default_loop->fd_events[fd]);
} else {
DEBUG_SCHED("ERROR: A different event is "
"already present at fd slot: %p!\n"
, default_loop->fd_events[fd]);
, (void *)default_loop->fd_events[fd]);
}
}
#endif
@ -123,7 +123,7 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event)
if (!loop || !event)
return GETDNS_RETURN_INVALID_PARAMETER;
DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNCTION__, loop, event);
DEBUG_SCHED( "%s(loop: %p, event: %p)\n", __FUNC__, (void *)loop, (void *)event);
i = (intptr_t)event->ev - 1;
if (i < 0 || i >= FD_SETSIZE) {
@ -134,7 +134,7 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event)
if (default_loop->timeout_events[i] != event)
DEBUG_SCHED( "ERROR: Different/wrong event present at "
"timeout slot: %p!\n"
, default_loop->timeout_events[i]);
, (void *)default_loop->timeout_events[i]);
#endif
default_loop->timeout_events[i] = NULL;
} else {
@ -142,7 +142,7 @@ default_eventloop_clear(getdns_eventloop *loop, getdns_eventloop_event *event)
if (default_loop->fd_events[i] != event)
DEBUG_SCHED( "ERROR: Different/wrong event present at "
"fd slot: %p!\n"
, default_loop->fd_events[i]);
, (void *)default_loop->fd_events[i]);
#endif
default_loop->fd_events[i] = NULL;
}
@ -162,7 +162,7 @@ default_read_cb(int fd, getdns_eventloop_event *event)
#if !defined(SCHED_DEBUG) || !SCHED_DEBUG
(void)fd;
#endif
DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNCTION__, fd, event);
DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event);
event->read_cb(event->userarg);
}
@ -172,7 +172,7 @@ default_write_cb(int fd, getdns_eventloop_event *event)
#if !defined(SCHED_DEBUG) || !SCHED_DEBUG
(void)fd;
#endif
DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNCTION__, fd, event);
DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event);
event->write_cb(event->userarg);
}
@ -182,7 +182,7 @@ default_timeout_cb(int fd, getdns_eventloop_event *event)
#if !defined(SCHED_DEBUG) || !SCHED_DEBUG
(void)fd;
#endif
DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNCTION__, fd, event);
DEBUG_SCHED( "%s(fd: %d, event: %p)\n", __FUNC__, fd, (void *)event);
event->timeout_cb(event->userarg);
}
@ -212,7 +212,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking)
else if (default_loop->timeout_times[i] < timeout)
timeout = default_loop->timeout_times[i];
}
for (fd = 0; fd < FD_SETSIZE; fd++) {
for (fd = 0; fd < (int)FD_SETSIZE; fd++) {
if (!default_loop->fd_events[fd])
continue;
if (default_loop->fd_events[fd]->read_cb)
@ -240,7 +240,7 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking)
exit(EXIT_FAILURE);
}
now = get_now_plus(0);
for (fd = 0; fd < FD_SETSIZE; fd++) {
for (fd = 0; fd < (int)FD_SETSIZE; fd++) {
if (default_loop->fd_events[fd] &&
default_loop->fd_events[fd]->read_cb &&
FD_ISSET(fd, &readfds))

View File

@ -485,6 +485,7 @@ typedef enum getdns_callback_type_t {
#define GETDNS_RCODE_BADNAME 20
#define GETDNS_RCODE_BADALG 21
#define GETDNS_RCODE_BADTRUNC 22
#define GETDNS_RCODE_COOKIE 23
/** @}
*/

View File

@ -900,6 +900,196 @@ getdns_msg_dict2str_buf(
getdns_return_t
getdns_msg_dict2str_scan(
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_sync
getdns_cancel_callback
getdns_context_config
getdns_context_create
getdns_context_create_with_extended_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_idle_timeout
getdns_context_set_limit_outstanding_queries
getdns_context_set_listen_addresses
getdns_context_set_memory_functions
getdns_context_set_namespaces
getdns_context_set_resolution_type
@ -123,6 +125,7 @@ getdns_print_json_dict
getdns_print_json_list
getdns_pubkey_pin_create_from_string
getdns_pubkey_pinset_sanity_check
getdns_reply
getdns_root_trust_anchor
getdns_rr_dict2str
getdns_rr_dict2str_buf
@ -134,6 +137,10 @@ getdns_service
getdns_service_sync
getdns_snprint_json_dict
getdns_snprint_json_list
getdns_str2bindata
getdns_str2dict
getdns_str2int
getdns_str2list
getdns_str2rr_dict
getdns_strerror
getdns_validate_dnssec

View File

@ -46,18 +46,20 @@ getdns_get_errorstr_by_id(uint16_t err)
else
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
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
cat >> test/new-getdns_str2dict.c << END_OF_TAIL
static struct const_name_info consts_name_info[] = {
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)
{
return strcmp( ((struct const_name_info *) a)->name
, ((struct const_name_info *) b)->name );
}
static int
int
_getdns_get_const_name_info(const char *name, uint32_t *code)
{
struct const_name_info key = { name, 0 };
@ -71,5 +73,4 @@ _getdns_get_const_name_info(const char *name, uint32_t *code)
return 1;
}
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)
{
getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR;
X509 *x;
X509 *x, *prev;
int i, len;
unsigned char raw[4096];
unsigned char *next = raw;
unsigned char *next;
unsigned char buf[sizeof(pinset->pin)];
const sha256_pin_t *p;
@ -407,33 +407,45 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
/* TODO: how do we handle raw public keys? */
for (i = 0; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store)); i++) {
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;
}
for (i = 0; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store)); i++, prev = x) {
x = sk_X509_value(X509_STORE_CTX_get0_untrusted(store), i);
#if defined(STUB_DEBUG) && STUB_DEBUG
DEBUG_STUB("%s %-35s: Name of cert: %d ",
STUB_DEBUG_SETUP_TLS, __FUNCTION__, i);
STUB_DEBUG_SETUP_TLS, __FUNC__, i);
X509_NAME_print_ex_fp(stderr, X509_get_subject_name(x), 1, XN_FLAG_ONELINE);
fprintf(stderr, "\n");
#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 */
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL);
if (len > (int)sizeof(raw)) {
DEBUG_STUB("%s %-35s: Pubkey %d is larger than "PRIsz" octets\n",
STUB_DEBUG_SETUP_TLS, __FUNCTION__, i, sizeof(raw));
STUB_DEBUG_SETUP_TLS, __FUNC__, i, sizeof(raw));
continue;
}
next = raw;
i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next);
if (next - raw != len) {
DEBUG_STUB("%s %-35s: Pubkey %d claimed it needed %d octets, really needed "PRIsz"\n",
STUB_DEBUG_SETUP_TLS, __FUNCTION__, i, len, next - raw);
STUB_DEBUG_SETUP_TLS, __FUNC__, i, len, next - raw);
continue;
}
SHA256(raw, len, buf);
@ -442,11 +454,11 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
for (p = pinset; p; p = p->next)
if (0 == memcmp(buf, p->pin, sizeof(p->pin))) {
DEBUG_STUB("%s %-35s: Pubkey %d matched pin %p ("PRIsz")\n",
STUB_DEBUG_SETUP_TLS, __FUNCTION__, i, p, sizeof(p->pin));
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p, sizeof(p->pin));
return GETDNS_RETURN_GOOD;
} else
DEBUG_STUB("%s %-35s: Pubkey %d did not match pin %p\n",
STUB_DEBUG_SETUP_TLS, __FUNCTION__, i, p);
STUB_DEBUG_SETUP_TLS, __FUNC__, i, (void*)p);
}
return ret;

View File

@ -85,20 +85,20 @@ getdns_dict *dnssec_ok_checking_disabled_avoid_roadblocks
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;
uint32_t value;
if (! extensions)
return 0;
else if (extensions == dnssec_ok_checking_disabled
if ( ! extensions
|| extensions == dnssec_ok_checking_disabled
|| extensions == dnssec_ok_checking_disabled_roadblock_avoidance
|| extensions == dnssec_ok_checking_disabled_avoid_roadblocks)
return 0;
r = getdns_dict_get_int(extensions, extension, &value);
return r == GETDNS_RETURN_GOOD && value == GETDNS_EXTENSION_TRUE;
r = getdns_dict_get_int(extensions, name, &value);
return r == GETDNS_RETURN_GOOD ? ( value == GETDNS_EXTENSION_TRUE )
: default_value;
}
static void
@ -177,11 +177,10 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
net_req->fd = -1;
net_req->transport_current = 0;
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->write_queue_tail = NULL;
/* 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;
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);
gldns_buffer_init_frm_data(
&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);
if (dnssec_extension_set) /* We will do validation ourselves */
GLDNS_CD_SET(net_req->query);
@ -472,7 +474,7 @@ _getdns_network_validate_tsig(getdns_network_req *req)
HMAC_CTX ctx_space;
#endif
DEBUG_STUB("%s %-35s: Validate TSIG\n", STUB_DEBUG_TSIG, __FUNCTION__);
DEBUG_STUB("%s %-35s: Validate TSIG\n", STUB_DEBUG_TSIG, __FUNC__);
for ( rr = _getdns_rr_iter_init(&rr_spc, req->query,
(req->response - req->query))
; rr
@ -489,7 +491,7 @@ _getdns_network_validate_tsig(getdns_network_req *req)
if (request_mac_len != rdf->nxt - rdf->pos - 2)
return;
DEBUG_STUB("%s %-35s: Request MAC found length %d\n",
STUB_DEBUG_TSIG, __FUNCTION__, (int)(request_mac_len));
STUB_DEBUG_TSIG, __FUNC__, (int)(request_mac_len));
request_mac = rdf->pos + 2;
@ -546,7 +548,7 @@ _getdns_network_validate_tsig(getdns_network_req *req)
if (response_mac_len != rdf->nxt - rdf->pos - 2)
return;
DEBUG_STUB("%s %-35s: Response MAC found length: %d\n",
STUB_DEBUG_TSIG, __FUNCTION__, (int)(response_mac_len));
STUB_DEBUG_TSIG, __FUNC__, (int)(response_mac_len));
response_mac = rdf->pos + 2;
if (!(rdf = _getdns_rdf_iter_next(rdf)) ||
@ -571,7 +573,7 @@ _getdns_network_validate_tsig(getdns_network_req *req)
/* TSIG found */
DEBUG_STUB("%s %-35s: TSIG found, original ID: %d\n",
STUB_DEBUG_TSIG, __FUNCTION__, (int)original_id);
STUB_DEBUG_TSIG, __FUNC__, (int)original_id);
gldns_write_uint16(req->response + 10,
gldns_read_uint16(req->response + 10) - 1);
@ -612,7 +614,7 @@ _getdns_network_validate_tsig(getdns_network_req *req)
HMAC_Final(ctx, result_mac, &result_mac_len);
DEBUG_STUB("%s %-35s: Result MAC length: %d\n",
STUB_DEBUG_TSIG, __FUNCTION__, (int)(result_mac_len));
STUB_DEBUG_TSIG, __FUNC__, (int)(result_mac_len));
if (result_mac_len == response_mac_len &&
memcmp(result_mac, response_mac, result_mac_len) == 0)
req->tsig_status = GETDNS_DNSSEC_SECURE;
@ -658,28 +660,32 @@ getdns_dns_req *
_getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
const char *name, uint16_t request_type, getdns_dict *extensions)
{
int dnssec_return_status
= context->return_dnssec_status == GETDNS_EXTENSION_TRUE
|| is_extension_set(extensions, "dnssec_return_status");
int dnssec_return_only_secure
= is_extension_set(extensions, "dnssec_return_only_secure");
int dnssec_return_all_statuses
= is_extension_set(extensions, "dnssec_return_all_statuses");
int dnssec_return_full_validation_chain
= is_extension_set(extensions, "dnssec_return_full_validation_chain");
int dnssec_return_validation_chain
= is_extension_set(extensions, "dnssec_return_validation_chain");
int edns_cookies
= is_extension_set(extensions, "edns_cookies");
int dnssec_return_status = is_extension_set(
extensions, "dnssec_return_status",
context->dnssec_return_status);
int dnssec_return_only_secure = is_extension_set(
extensions, "dnssec_return_only_secure",
context->dnssec_return_only_secure);
int dnssec_return_all_statuses = is_extension_set(
extensions, "dnssec_return_all_statuses",
context->dnssec_return_all_statuses);
int dnssec_return_full_validation_chain = is_extension_set(
extensions, "dnssec_return_full_validation_chain",
context->dnssec_return_full_validation_chain);
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
int avoid_dnssec_roadblocks
= (extensions == dnssec_ok_checking_disabled_avoid_roadblocks);
int dnssec_roadblock_avoidance
= is_extension_set(extensions, "dnssec_roadblock_avoidance")
int dnssec_roadblock_avoidance = avoid_dnssec_roadblocks
|| (extensions == dnssec_ok_checking_disabled_roadblock_avoidance)
|| avoid_dnssec_roadblocks;
|| is_extension_set(extensions, "dnssec_roadblock_avoidance",
context->dnssec_roadblock_avoidance);
#endif
int dnssec_extension_set = dnssec_return_status
|| dnssec_return_only_secure || dnssec_return_all_statuses
|| dnssec_return_validation_chain
@ -713,9 +719,9 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
int with_opt;
getdns_dns_req *result = NULL;
uint32_t klass = GLDNS_RR_CLASS_IN;
int a_aaaa_query =
is_extension_set(extensions, "return_both_v4_and_v6") &&
uint32_t klass = context->specify_class;
int a_aaaa_query = is_extension_set(extensions,
"return_both_v4_and_v6", context->return_both_v4_and_v6) &&
( request_type == GETDNS_RRTYPE_A ||
request_type == GETDNS_RRTYPE_AAAA );
/* 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,
"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) {
edns_maximum_udp_payload_size = -1;
edns_extended_rcode = 0;
@ -746,17 +755,26 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
edns_do_bit = context->edns_do_bit;
if (have_add_opt_parameters) {
if (!getdns_dict_get_int(add_opt_parameters,
if (getdns_dict_get_int(add_opt_parameters,
"maximum_udp_payload_size",
&get_edns_maximum_udp_payload_size)) {
if (!getdns_dict_get_int(
add_opt_parameters, "udp_payload_size",
&get_edns_maximum_udp_payload_size))
edns_maximum_udp_payload_size =
get_edns_maximum_udp_payload_size;
} else
edns_maximum_udp_payload_size =
get_edns_maximum_udp_payload_size;
(void) getdns_dict_get_int(add_opt_parameters,
"extended_rcode", &edns_extended_rcode);
(void) getdns_dict_get_int(add_opt_parameters,
"version", &edns_version);
(void) getdns_dict_get_int(add_opt_parameters,
"do_bit", &edns_do_bit);
if (getdns_dict_get_int(add_opt_parameters,
"do_bit", &edns_do_bit))
(void) getdns_dict_get_int(
add_opt_parameters, "do", &edns_do_bit);
}
}
if (have_add_opt_parameters && getdns_dict_get_list(
@ -895,10 +913,10 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
#endif
result->edns_client_subnet_private = context->edns_client_subnet_private;
result->tls_query_padding_blocksize = context->tls_query_padding_blocksize;
result->return_call_reporting =
is_extension_set(extensions, "return_call_reporting");
result->add_warning_for_bad_dns =
is_extension_set(extensions, "add_warning_for_bad_dns");
result->return_call_reporting = is_extension_set(extensions,
"return_call_reporting" , context->return_call_reporting);
result->add_warning_for_bad_dns = is_extension_set(extensions,
"add_warning_for_bad_dns", context->add_warning_for_bad_dns);
/* will be set by caller */
result->user_pointer = NULL;

View File

@ -76,7 +76,7 @@ _getdns_rr_iter *_getdns_single_rr_iter_init(_getdns_rr_iter *i,
const uint8_t *wire, const size_t wire_len);
static inline _getdns_rr_iter *_getdns_rr_iter_rewind(_getdns_rr_iter *i)
{ return _getdns_rr_iter_init(i, i->pkt, i->pkt_end - i->pkt); }
{ return i ? _getdns_rr_iter_init(i, i->pkt, i->pkt_end - i->pkt) : NULL; }
_getdns_rr_iter *_getdns_rr_iter_next(_getdns_rr_iter *i);
@ -181,7 +181,7 @@ static inline _getdns_rrset *_getdns_rrset_iter_value(_getdns_rrset_iter *i)
{ return i && i->rr_i.pos ? &i->rrset : NULL; }
static inline _getdns_rrset_iter *_getdns_rrset_iter_rewind(_getdns_rrset_iter *i)
{ return _getdns_rrset_iter_init(i, i->rrset.pkt, i->rrset.pkt_len, i->rrset.sections); }
{ return i ? _getdns_rrset_iter_init(i, i->rrset.pkt, i->rrset.pkt_len, i->rrset.sections) : NULL; }
typedef struct _getdns_rdf_iter {
const uint8_t *pkt;

View File

@ -26,11 +26,20 @@
*/
#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 "context.h"
#include "types-internal.h"
#include "debug.h"
#include <netdb.h>
#include "util/rbtree.h"
#include "server.h"
#define DNS_REQUEST_SZ 4096
#define DOWNSTREAM_IDLE_TIMEOUT 5000
@ -63,9 +72,10 @@ struct listener {
*/
struct listen_set {
getdns_context *context;
listen_set *next;
void *userarg;
getdns_request_handler_t handler;
_getdns_rbtree_t connections_set;
size_t count;
listener items[];
};
@ -79,6 +89,9 @@ struct tcp_to_write {
};
struct connection {
/* struct connection is a sub struct of _getdns_rbnode_t */
_getdns_rbnode_t super;
listener *l;
struct sockaddr_storage remote_in;
socklen_t addrlen;
@ -88,14 +101,8 @@ struct connection {
};
typedef struct tcp_connection {
/* A TCP connection is a connection */
listener *l;
struct sockaddr_storage remote_in;
socklen_t addrlen;
connection *next;
connection **prev_next;
/************************************/
/* struct tcp_connection is a sub struct of connection */
connection super;
int fd;
getdns_eventloop_event event;
@ -118,10 +125,10 @@ static void tcp_connection_destroy(tcp_connection *conn)
tcp_to_write *cur, *next;
if (!(mf = priv_getdns_context_mf(conn->l->set->context)))
if (!(mf = &conn->super.l->set->context->mf))
return;
if (getdns_context_get_eventloop(conn->l->set->context, &loop))
if (getdns_context_get_eventloop(conn->super.l->set->context, &loop))
return;
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;
/* Unlink this connection */
if ((*conn->prev_next = conn->next))
conn->next->prev_next = conn->prev_next;
(void) _getdns_rbtree_delete(
&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);
}
@ -157,10 +168,10 @@ static void tcp_write_cb(void *userarg)
assert(userarg);
if (!(mf = priv_getdns_context_mf(conn->l->set->context)))
if (!(mf = &conn->super.l->set->context->mf))
return;
if (getdns_context_get_eventloop(conn->l->set->context, &loop))
if (getdns_context_get_eventloop(conn->super.l->set->context, &loop))
return;
/* Reset tcp_connection idle timeout */
@ -195,28 +206,30 @@ static void tcp_write_cb(void *userarg)
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
}
void
_getdns_cancel_reply(getdns_context *context, getdns_transaction_t request_id)
static void
_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;
if (!context || !conn)
return;
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 &&
conn->fd == -1)
tcp_connection_destroy(conn);
if (tcp_conn->to_answer > 0 && --tcp_conn->to_answer == 0 &&
tcp_conn->fd == -1)
tcp_connection_destroy(tcp_conn);
} 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;
/* 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))
conn->next->prev_next = conn->prev_next;
GETDNS_FREE(*mf, conn);
@ -226,7 +239,7 @@ _getdns_cancel_reply(getdns_context *context, getdns_transaction_t request_id)
getdns_return_t
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 */
connection *conn = (connection *)(intptr_t)request_id;
@ -236,10 +249,21 @@ getdns_reply(
size_t len;
getdns_return_t r;
if (!context || !reply || !conn)
if (!context || !conn)
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;;
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) {
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) {
/* IO error, cleanup this listener */
loop->vmt->clear(loop, &conn->l->event);
@ -260,6 +284,10 @@ getdns_reply(
conn->l->fd = -1;
}
/* 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))
conn->next->prev_next = conn->prev_next;
@ -320,10 +348,10 @@ static void tcp_read_cb(void *userarg)
assert(userarg);
if (!(mf = priv_getdns_context_mf(conn->l->set->context)))
if (!(mf = &conn->super.l->set->context->mf))
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;
/* Reset tcp_connection idle timeout */
@ -380,9 +408,14 @@ static void tcp_read_cb(void *userarg)
else {
conn->to_answer++;
/* TODO: wish list item:
* (void) getdns_dict_set_int64(
* request_dict, "request_id", intptr_t)conn);
*/
/* Call request handler */
conn->l->set->handler(
conn->l->set->context, request_dict, (intptr_t)conn);
conn->super.l->set->handler(
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->to_read = 2;
@ -402,7 +435,8 @@ static void tcp_timeout_cb(void *userarg)
if (conn->to_answer) {
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;
loop->vmt->clear(loop, &conn->event);
@ -423,7 +457,7 @@ static void tcp_accept_cb(void *userarg)
assert(userarg);
if (!(mf = priv_getdns_context_mf(l->set->context)))
if (!(mf = &l->set->context->mf))
return;
if ((r = getdns_context_get_eventloop(l->set->context, &loop)))
@ -433,11 +467,10 @@ static void tcp_accept_cb(void *userarg)
return;
(void) memset(conn, 0, sizeof(tcp_connection));
conn->l = l;
conn->addrlen = sizeof(conn->remote_in);
if ((conn->fd = accept(l->fd,
(struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) {
conn->super.l = l;
conn->super.addrlen = sizeof(conn->super.remote_in);
if ((conn->fd = accept(l->fd, (struct sockaddr *)
&conn->super.remote_in, &conn->super.addrlen)) == -1) {
/* IO error, cleanup this listener */
loop->vmt->clear(loop, &l->event);
close(l->fd);
@ -458,11 +491,21 @@ static void tcp_accept_cb(void *userarg)
conn->event.timeout_cb = tcp_timeout_cb;
/* Insert connection */
if ((conn->next = l->connections))
conn->next->prev_next = &conn->next;
conn->prev_next = &l->connections;
conn->super.super.key = conn;
if (!_getdns_rbtree_insert(
&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;
(void) loop->vmt->schedule(loop, conn->fd,
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
}
@ -485,7 +528,7 @@ static void udp_read_cb(void *userarg)
if (l->fd == -1)
return;
if (!(mf = priv_getdns_context_mf(l->set->context)))
if (!(mf = &l->set->context->mf))
return;
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->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) {
/* IO error, cleanup this listener. */
loop->vmt->clear(loop, &l->event);
@ -574,37 +617,33 @@ static void udp_read_cb(void *userarg)
else {
/* 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))
conn->next->prev_next = &conn->next;
conn->prev_next = &l->connections;
l->connections = conn;
/* TODO: wish list item:
* (void) getdns_dict_set_int64(
* request_dict, "request_id", (intptr_t)conn);
*/
/* 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;
}
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)
{
struct mem_funcs *mf;
@ -613,10 +652,10 @@ static void free_listen_set_when_done(listen_set *set)
assert(set);
assert(set->context);
if (!(mf = priv_getdns_context_mf(set->context)))
if (!(mf = &set->context->mf))
return;
DEBUG_SERVER("To free listen set: %p\n", set);
DEBUG_SERVER("To free listen set: %p\n", (void *)set);
for (i = 0; i < set->count; i++) {
listener *l = &set->items[i];
@ -627,7 +666,7 @@ static void free_listen_set_when_done(listen_set *set)
return;
}
GETDNS_FREE(*mf, set);
DEBUG_SERVER("Listen set: %p freed\n", set);
DEBUG_SERVER("Listen set: %p freed\n", (void *)set);
}
static void remove_listeners(listen_set *set)
@ -639,7 +678,7 @@ static void remove_listeners(listen_set *set)
assert(set);
assert(set->context);
if (!(mf = priv_getdns_context_mf(set->context)))
if (!(mf = &set->context->mf))
return;
if (getdns_context_get_eventloop(set->context, &loop))
@ -663,7 +702,8 @@ static void remove_listeners(listen_set *set)
while (*conn_p) {
tcp_connection_destroy(*conn_p);
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);
@ -671,7 +711,11 @@ static void remove_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;
#endif
struct mem_funcs *mf;
getdns_eventloop *loop;
@ -681,7 +725,7 @@ static getdns_return_t add_listeners(listen_set *set)
assert(set);
assert(set->context);
if (!(mf = priv_getdns_context_mf(set->context)))
if (!(mf = &set->context->mf))
return GETDNS_RETURN_GENERIC_ERROR;
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;
}
getdns_return_t getdns_context_set_listen_addresses(getdns_context *context,
getdns_request_handler_t request_handler,
const getdns_list *listen_addresses)
static int
ptr_cmp(const void *a, const void *b)
{
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[]
= { GETDNS_TRANSPORT_UDP, GETDNS_TRANSPORT_TCP };
static const uint32_t transport_ports[] = { 53, 53 };
static const size_t n_transports = sizeof( listen_transports)
/ sizeof(*listen_transports);
static listen_set *root = NULL;
listen_set *current_set;
listen_set *new_set;
size_t new_set_count;
@ -761,9 +809,10 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context,
size_t i;
struct addrinfo hints;
DEBUG_SERVER("getdns_context_set_listen_addresses(%p, %p, %p)\n", context, request_handler,
listen_addresses);
if (!(mf = priv_getdns_context_mf(context)))
DEBUG_SERVER("getdns_context_set_listen_addresses(%p, <func>, %p)\n",
(void *)context, (void *)listen_addresses);
if (!(mf = &context->mf))
return GETDNS_RETURN_GENERIC_ERROR;
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)))
return r;
if ((current_set = lookup_listen_set(root, context))) {
if ((current_set = context->server)) {
for (i = 0; i < current_set->count; i++)
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)
return GETDNS_RETURN_GOOD;
rm_listen_set(&root, current_set);
context->server = NULL;
/* action is already to_remove */
remove_listeners(current_set);
return GETDNS_RETURN_GOOD;
@ -796,11 +845,14 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context,
sizeof(listener) * new_set_count * n_transports)))
return GETDNS_RETURN_MEMORY_ERROR;
DEBUG_SERVER("New listen set: %p, current_set: %p\n", new_set, current_set);
_getdns_rbtree_init(&new_set->connections_set, ptr_cmp);
DEBUG_SERVER("New listen set: %p, current_set: %p\n",
(void *)new_set, (void *)current_set);
new_set->context = context;
new_set->next = root;
new_set->handler = request_handler;
new_set->userarg = userarg;
new_set->count = new_set_count * n_transports;
(void) memset(new_set->items, 0,
sizeof(listener) * new_set_count * n_transports);
@ -940,10 +992,10 @@ getdns_return_t getdns_context_set_listen_addresses(getdns_context *context,
}
}
if (current_set) {
rm_listen_set(&root, current_set);
context->server = NULL;
remove_listeners(current_set); /* Is already remove */
}
root = new_set;
context->server = new_set;
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.
* All rights reserved.
@ -24,18 +32,9 @@
* (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_SERVER_H_
#define _GETDNS_SERVER_H_
#include "getdns/getdns.h"
#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
struct listen_set;
#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_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 \
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 \
tests_stub_async.lo tests_stub_sync.lo \
$(DECOMPOSED_OBJS_WITHOUT_JSMN)
tests_stub_async.lo tests_stub_sync.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
@ -95,9 +89,6 @@ default: all
all: $(PROGRAMS)
jsmn.lo:
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -DJSMN_GETDNS -c $(srcdir)/jsmn/jsmn.c -o $@
$(ALL_OBJS):
$(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
$(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
$(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
[ ! -f $(srcdir)/scratchpad.c ] && cp -p $(srcdir)/scratchpad.template.c $(srcdir)/scratchpad.c || true
install: getdns_query
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
$(LIBTOOL) --mode=install cp getdns_query $(DESTDIR)$(bindir)
install:
echo nothing to install
uninstall:
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/getdns_query
echo nothing to uninstall
nolibcheck:
@echo "***"
@ -222,7 +209,6 @@ depend:
-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? jsmn/jsmn\.h? $$(srcdir)/jsmn/jsmn.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 )
@ -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 \
$(srcdir)/check_getdns_transport.h $(srcdir)/check_getdns_common.h ../getdns/getdns.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 \
../getdns/getdns_extra.h
testmessages.lo testmessages.o: $(srcdir)/testmessages.c $(srcdir)/testmessages.h

View File

@ -224,7 +224,7 @@
EVENT_BASE_CREATE;
ASSERT_RC(getdns_address(context, "hostnamedoesntexist", NULL,
ASSERT_RC(getdns_address(context, "hostnamedoesntexist.", NULL,
&fn_ref, &transaction_id, callbackfn),
GETDNS_RETURN_GOOD, "Return code from getdns_address()");

View File

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

View File

@ -124,7 +124,7 @@
*/
struct getdns_context *context = NULL;
struct getdns_dict *response = NULL;
const char *name = "labelsizeofsixtythreecharacterscom";
const char *name = "labelsizeofsixtythreecharacterscom.";
CONTEXT_CREATE(TRUE);

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,970 +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_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

@ -1 +0,0 @@
Subproject commit 49024a6e11739c866bce0e9f3617278b98906ad0

View File

@ -5,24 +5,71 @@ SERVER_IP="8.8.8.8"
SERVER_IPv6="2001:4860:4860::8888"
TLS_SERVER_IP="185.49.141.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_SS_KEY="pOXrpUt9kgPgbWxBFFcBTbRH2heo2wHwXp1fd4AEVXI="
TLS_SERVER_WRONG_KEY="foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc1S="
GOOD_RESULT_SYNC="Status was: At least one response was returned"
GOOD_RESULT_ASYNC="successfull"
BAD_RESULT_SYNC="1 'Generic error'"
BAD_RESULT_ASYNC="callback_type of 703"
NUM_ARGS=3
GOOD_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 () {
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"`
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++ ))
echo -n "PASS: "
else
(( FAIL_COUNT++ ))
echo "FAIL (RESULT): " $1
echo "FAIL (RESULT): Result: $result Auth: $auth_ok Trans: $trans_ok"
echo -n "FAIL: "
fi
}
@ -80,30 +127,38 @@ while getopts ":p:s:t:k:idh" opt; do
done
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}`
NUM_GOOD_QUERIES=7
GOOD_QUERIES=(
"-s -A -q getdnsapi.net -l U @${SERVER_IP} "
"-s -A -q getdnsapi.net -l T @${SERVER_IP} "
"-s -A -q getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}"
"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP}"
"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\""
"-s -A -q getdnsapi.net -l L -m @${TLS_SERVER_IP} -K pin-sha256=\"${TLS_SERVER_KEY}\""
"-s -G -q DNSKEY getdnsapi.net -l U @${SERVER_IP} -b 512 -D")
"-s -A getdnsapi.net -l U @${SERVER_IP}" "U" "-"
"-s -A getdnsapi.net -l T @${SERVER_IP}" "T" "-"
"-s -A getdnsapi.net -l L @${TLS_SERVER_IP_NO_NAME}" "L" "N"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP}" "L" "S"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP} -K pin-sha256=\"${TLS_SERVER_KEY}\"" "L" "S"
"-s -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=(
"-s -A -q getdnsapi.net -l LT @${SERVER_IP}"
"-s -A -q getdnsapi.net -l LT @${SERVER_IP}"
"-s -A -q getdnsapi.net -l LT @${TLS_SERVER_IP_NO_NAME}"
"-s -A -q getdnsapi.net -l LT -m @${TLS_SERVER_IP_NO_NAME}"
"-s -A -q getdnsapi.net -l L @${SERVER_IP} @${TLS_SERVER_IP_NO_NAME}"
"-s -G -q DNSKEY getdnsapi.net -l UT @${SERVER_IP} -b 512 -D")
"-s -A getdnsapi.net -l LU @${SERVER_IP}" "U" "-"
"-s -A getdnsapi.net -l LT @${SERVER_IP}" "T" "-"
"-s -A getdnsapi.net -l LT @${TLS_SERVER_IP_NO_NAME}" "L" "N"
"-s -A getdnsapi.net -l LT -m @${TLS_SERVER_IP_NO_NAME}" "L" "N"
"-s -A getdnsapi.net -l L @${SERVER_IP} @${TLS_SERVER_IP_NO_NAME}" "L" "-"
"-s -G DNSKEY getdnsapi.net -l UT @${SERVER_IP} -b 512 -D" "T" "-")
NOT_AVAILABLE_QUERIES=(
"-s -A -q getdnsapi.net -l L @${SERVER_IP}"
"-s -A -q 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 -q getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME} -K pin-sha256=\"${TLS_SERVER_WRONG_KEY}\"")
"-s -A getdnsapi.net -l L @${SERVER_IP}"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_WRONG_NAME}"
"-s -A getdnsapi.net -l L -m @${TLS_SERVER_IP_NO_NAME}"
"-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"
@ -118,16 +173,16 @@ for (( i = 0; i < 2; i+=1 )); do
fi
echo "*Success cases:"
for (( j = 0; j < ${#GOOD_QUERIES[@]}; j+=1 )); do
check_good "`$DIR/getdns_query $SYNC_MODE ${GOOD_QUERIES[${j}]} 2>/dev/null`"
echo "getdns_query $SYNC_MODE ${GOOD_QUERIES[${j}]}"
for (( j = 0; j < $NUM_GOOD_QUERIES; j+=1 )); do
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*$NUM_ARGS]}"
(( COUNT++ ))
done
echo "*Success fallback cases:"
for (( j = 0; j < ${#GOOD_FALLBACK_QUERIES[@]}; j+=1 )); do
check_good "`$DIR/getdns_query $SYNC_MODE ${GOOD_FALLBACK_QUERIES[${j}]} 2>/dev/null`"
echo "getdns_query $SYNC_MODE ${GOOD_FALLBACK_QUERIES[${j}]}"
for (( j = 0; j < $NUM_GOOD_FB_QUERIES; j+=1 )); do
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*$NUM_ARGS]} TESTS: ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+1]} ${GOOD_FALLBACK_QUERIES[$((j*NUM_ARGS))+2]}"
(( COUNT++ ))
done

View File

@ -6,5 +6,5 @@
cd "${BUILDDIR}/build"
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

View File

@ -6,5 +6,5 @@
cd "${BUILDDIR}/build-stub-only"
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

View File

@ -1,16 +0,0 @@
BaseName: 315-event-loops-compile
Version: 1.0
Description: Compile
CreationDate: do 8 dec 2016 23:38:18 CET
Maintainer: Willem Toorop
Category:
Component:
CmdDepends:
Depends: 300-event-loops-configure.tpkg
Help:
Pre: 315-event-loops-compile.pre
Post: 315-event-loops-compile.post
Test: 315-event-loops-compile.test
AuxFiles:
Passed:
Failure:

View File

@ -1,20 +0,0 @@
# #-- 315-event-loops-compile.post --#
# source the master var file when it's there
if [ -f ../.tpkg.var.master ]
then
source ../.tpkg.var.master
else
(
cd ..
[ -f "${TPKG_SRCDIR}/setup-env.sh" ] \
&& sh "${TPKG_SRCDIR}/setup-env.sh"
) && source ../.tpkg.var.master
fi
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
for f in `cat restore-srcdir-configure-settings`
do
mv "${SRCROOT}/${f}.build-event-loops" "${SRCROOT}/${f}"
done

View File

@ -1,24 +0,0 @@
# #-- 315-event-loops-compile.pre--#
# source the master var file when it's there
if [ -f ../.tpkg.var.master ]
then
source ../.tpkg.var.master
else
(
cd ..
[ -f "${TPKG_SRCDIR}/setup-env.sh" ] \
&& sh "${TPKG_SRCDIR}/setup-env.sh"
) && source ../.tpkg.var.master
fi
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
echo "" > restore-srcdir-configure-settings
for f in `grep 'CONFIG_[FH][IE][LA][ED][SE]' "${SRCROOT}/configure.ac" | sed -e 's/^.*(\[//g' -e 's/\])//g'`
do
if [ -f "${SRCROOT}/$f" ]
then
mv "${SRCROOT}/${f}" "${SRCROOT}/${f}.build-event-loops" && \
echo "$f" >> restore-srcdir-configure-settings
fi
done

View File

@ -1,8 +0,0 @@
# #-- 315-event-loops-compile.test --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
cd "${BUILDDIR}/build-event-loops"
make XTRA_CFLAGS='-Werror'

View File

@ -5,5 +5,4 @@
[ -f .tpkg.var.test ] && source .tpkg.var.test
cd "${BUILDDIR}/build-event-loops"
make clean
make
make XTRA_CFLAGS=-Werror

View File

@ -15,7 +15,7 @@ LCOV_MERGE=""
for TEST_PKG in ${SRCDIR}/*.tpkg
do
# when we run our test, we need to compile with profiling
CFLAGS="-fprofile-arcs -ftest-coverage -O0" "${TPKG}" $* exe "${TEST_PKG}"
LDFLAGS="-lgcov --coverage" CFLAGS="-fprofile-arcs -ftest-coverage -O0" "${TPKG}" $* exe "${TEST_PKG}"
# after the test is complete, we need to collect the coverage data
INFO_FILE=`echo $TEST_PKG | sed 's/.tpkg$//'`.info
geninfo $SRCDIR/.. -o $INFO_FILE

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 "debug.h"
#include "getdns_str2dict.h"
#include "getdns_context_config.h"
#include "getdns_context_set_listen_addresses.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -51,6 +48,19 @@ typedef unsigned short in_port_t;
#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 batch_mode = 0;
static char *query_file = NULL;
@ -154,6 +164,7 @@ print_usage(FILE *out, const char *progname)
{
fprintf(out, "usage: %s [<option> ...] \\\n"
"\t[@<upstream> ...] [+<extension> ...] [\'{ <settings> }\'] [<name>] [<type>]\n", progname);
if (!i_am_stubby) {
fprintf(out, "\ndefault mode: "
#ifdef HAVE_LIBUNBOUND
"recursive"
@ -161,6 +172,11 @@ print_usage(FILE *out, const char *progname)
"stub"
#endif
", 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, "\n <ip>@<port> may be given as <IPv4>:<port>");
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, "\nsettings in json dict format (like outputted by -i option).\n");
fprintf(out, "\noptions:\n");
if (!i_am_stubby) {
fprintf(out, "\t-a\tPerform asynchronous resolution "
"(default = synchronous)\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 <bufsize>\tSet edns0 max_udp_payload size\n");
fprintf(out, "\t-c\tSend Client Subnet privacy request\n");
fprintf(out, "\t-C\t<filename>\n");
fprintf(out, "\t\tRead settings from config file <filename>\n");
fprintf(out, "\t\tThe getdns context will be configured with these settings\n");
fprintf(out, "\t\tThe file must be in json dict format.\n");
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\tclear edns0 do bit\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 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-H\thostname lookup. (<name> must be an IP address; <type> is ignored)\n");
}
fprintf(out, "\t-h\tPrint this help\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-j\tOutput 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 <blocksize>\tPad TLS queries to a multiple of blocksize\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-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-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\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\t<listen address> is in the same format as upstreams.\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)
@ -443,11 +479,12 @@ static void parse_config(const char *config_str)
* will get destroyed.
*/
if (!listen_dict &&
!(listen_dict = getdns_dict_create()))
!(listen_dict = getdns_dict_create())) {
fprintf(stderr, "Could not create "
"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)))
fprintf(stderr, "Could not set listen_list");
@ -464,8 +501,7 @@ static void parse_config(const char *config_str)
touched_listen_list = 1;
}
if ((r = _getdns_context_config_(
context, extensions, config_dict))) {
if ((r = getdns_context_config(context, config_dict))) {
fprintf(stderr, "Could not configure context with "
"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 r = GETDNS_RETURN_GOOD;
@ -488,8 +566,6 @@ getdns_return_t parse_args(int argc, char **argv)
getdns_bindata bindata;
size_t upstream_count = 0;
FILE *fh;
char *config_file = NULL;
long config_file_sz;
for (i = 1; i < argc; i++) {
arg = argv[i];
@ -600,42 +676,7 @@ getdns_return_t parse_args(int argc, char **argv)
"after -C\n");
return GETDNS_RETURN_GENERIC_ERROR;
}
if (!(fh = fopen(argv[i], "r"))) {
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;
(void) parse_config_file(argv[i], 1);
break;
case 'D':
(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(
context, timeout);
goto next;
case 'v':
fprintf(stdout, "Version %s\n", GETDNS_VERSION);
return CONTINUE;
case 'x':
getdns_context_set_follow_redirects(
context, GETDNS_REDIRECTS_DO_NOT_FOLLOW);
@ -932,17 +976,23 @@ getdns_return_t parse_args(int argc, char **argv)
"expected after -z\n");
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)
getdns_list_destroy(
listen_list);
listen_list = NULL;
listen_count = 0;
if (!clear_listen_list_on_arg) {
touched_listen_list = 1;
DEBUG_SERVER("Clear listen list\n");
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)))
fprintf(stderr, "Could not convert \"%s\" to "
"an IP dict: %s\n", argv[i],
@ -971,6 +1021,12 @@ getdns_return_t parse_args(int argc, char **argv)
}
break;
default:
#ifndef GETDNS_ON_WINDOWS
if (i_am_stubby && *c == 'g') {
run_in_foreground = 0;
break;
}
#endif
fprintf(stderr, "Unknown option "
"\"%c\"\n", *c);
for (i = 0; i < argc; i++)
@ -1007,7 +1063,24 @@ next: ;
if (print_api_info) {
getdns_dict *api_information =
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);
fprintf(stdout, "%s\n", api_information_str);
free(api_information_str);
@ -1137,7 +1210,8 @@ getdns_return_t do_the_call(void)
getdns_eventloop *loop = NULL;
FILE *fp;
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)
@ -1154,7 +1228,7 @@ void read_line_cb(void *userarg)
loop->vmt->clear(loop, read_line_ev);
if (listen_count)
(void) getdns_context_set_listen_addresses(
context, NULL, NULL);
context, NULL, NULL, NULL);
return;
}
if (query_file)
@ -1184,7 +1258,7 @@ void read_line_cb(void *userarg)
r = parse_args(linec, linev);
if (!r && touched_listen_list) {
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())) &&
(r != CONTINUE && r != CONTINUE_ERROR))
@ -1284,12 +1358,23 @@ static void request_cb(
getdns_return_t r = GETDNS_RETURN_GOOD;
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;
#endif
DEBUG_SERVER("reply for: %p %"PRIu64" %d (edns0: %d, do: %d, ad: %d,"
" cd: %d)\n", msg, transaction_id, (int)callback_type,
msg->has_edns0, msg->do_bit, msg->ad_bit, msg->cd_bit);
assert(msg);
#if 0
@ -1352,14 +1437,11 @@ static void request_cb(
else if (n == 0)
SERVFAIL("Recursion not available", 0, msg, &response);
if (!response)
/* No response, no reply */
_getdns_cancel_reply(context, msg->request_id);
else if ((r = getdns_reply(context, msg->request_id, response))) {
if ((r = getdns_reply(context, response, msg->request_id))) {
fprintf(stderr, "Could not reply: %s\n",
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) {
getdns_dict_destroy(msg->request);
@ -1370,7 +1452,8 @@ static void request_cb(
}
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;
char *qname_str = NULL;
@ -1389,6 +1472,9 @@ static void incoming_request_handler(getdns_context *context,
getdns_dict *rr;
uint32_t rr_type;
(void)callback_type;
(void)userarg;
if (!query_extensions_spc &&
!(query_extensions_spc = getdns_dict_create()))
fprintf(stderr, "Could not create query extensions space\n");
@ -1498,7 +1584,7 @@ static void incoming_request_handler(getdns_context *context,
getdns_get_errorstr_by_id(r));
else {
DEBUG_SERVER("scheduled: %p %"PRIu64" for %s %d\n",
msg, transaction_id, qname_str, (int)qtype);
(void *)msg, transaction_id, qname_str, (int)qtype);
free(qname_str);
return;
}
@ -1516,14 +1602,11 @@ error:
free(request_str);
} while(0);
#endif
if (!response)
/* No response, no reply */
_getdns_cancel_reply(context, request_id);
else if ((r = getdns_reply(context, request_id, response))) {
if ((r = getdns_reply(context, response, request_id))) {
fprintf(stderr, "Could not reply: %s\n",
getdns_get_errorstr_by_id(r));
_getdns_cancel_reply(context, request_id);
/* Cancel reply */
getdns_reply(context, NULL, request_id);
}
if (msg) {
if (msg->request)
@ -1545,7 +1628,18 @@ error:
int
main(int argc, char **argv)
{
char home_stubby_conf_fn[1024];
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;
if ((r = getdns_context_create(&context, 1))) {
@ -1560,8 +1654,22 @@ main(int argc, char **argv)
r = GETDNS_RETURN_MEMORY_ERROR;
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)))
goto done_destroy_context;
clear_listen_list_on_arg = 0;
if (query_file) {
fp = fopen(query_file, "rt");
@ -1578,8 +1686,10 @@ main(int argc, char **argv)
assert(loop);
}
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;
}
/* Make the call */
if (interactive) {
@ -1598,6 +1708,26 @@ main(int argc, char **argv)
}
else if (listen_count) {
assert(loop);
#ifndef GETDNS_ON_WINDOWS
if (i_am_stubby && !run_in_foreground) {
pid_t pid = fork();
if (pid == -1) {
perror("Could not fork of stubby daemon\n");
r = GETDNS_RETURN_GENERIC_ERROR;
} else if (pid) {
FILE *fh = fopen("/var/rub/stubby.pid", "w");
if (! fh)
fh = fopen("/tmp/stubby.pid", "w");
if (fh) {
fprintf(fh, "%d", (int)pid);
fclose(fh);
batch_mode = 0;
}
} else
loop->vmt->run(loop);
} else
#endif
loop->vmt->run(loop);
} else
r = do_the_call();
@ -1620,8 +1750,9 @@ done_destroy_context:
return 0;
else if (r == CONTINUE_ERROR)
return 1;
if (!i_am_stubby)
fprintf(stdout, "\nAll done.\n");
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_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_upstreams;
@ -115,6 +124,8 @@ struct getdns_upstream;
#define GETDNS_TRANSPORTS_MAX 3
#define GETDNS_UPSTREAM_TRANSPORTS 2
#define GETDNS_CONN_ATTEMPTS 2
#define GETDNS_TRANSPORT_FAIL_MULT 5
/* declarations */
@ -164,7 +175,6 @@ typedef struct getdns_tcp_state {
uint8_t *write_buf;
size_t write_buf_len;
size_t written;
int write_error;
uint8_t *read_buf;
size_t read_buf_len;
@ -212,7 +222,6 @@ typedef struct getdns_network_req
size_t transport_current;
getdns_tls_authentication_t tls_auth_min;
getdns_eventloop_event event;
getdns_tcp_state tcp;
uint16_t query_id;
int edns_maximum_udp_payload_size;
@ -226,7 +235,7 @@ typedef struct getdns_network_req
/* Some fields to record info for return_call_reporting */
uint64_t debug_start_time;
uint64_t debug_end_time;
size_t debug_tls_auth_status;
getdns_auth_state_t debug_tls_auth_status;
size_t debug_udp;
/* 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);
const char * _getdns_auth_str(getdns_auth_state_t auth);
#endif
/* types-internal.h */

View File

@ -149,7 +149,7 @@ static int my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv
static void clear_my_event(my_event *ev)
{
DEBUG_SCHED("UB_LOOP: to clear %p(%d, %d, %"PRIu64"), total: %d\n"
, ev, ev->fd, ev->bits, ev->timeout, ev->loop->n_events);
, (void *)ev, ev->fd, ev->bits, ev->timeout, ev->loop->n_events);
(ev)->loop->extension->vmt->clear((ev)->loop->extension, &(ev)->gev);
(ev)->added = 0;
if ((ev)->active) {
@ -157,7 +157,7 @@ static void clear_my_event(my_event *ev)
(ev)->active = NULL;
}
DEBUG_SCHED("UB_LOOP: %p(%d, %d, %"PRIu64") cleared, total: %d\n"
, ev, ev->fd, ev->bits, ev->timeout, --ev->loop->n_events);
, (void *)ev, ev->fd, ev->bits, ev->timeout, --ev->loop->n_events);
}
static getdns_return_t schedule_my_event(my_event *ev)
@ -165,16 +165,16 @@ static getdns_return_t schedule_my_event(my_event *ev)
getdns_return_t r;
DEBUG_SCHED("UB_LOOP: to schedule %p(%d, %d, %"PRIu64"), total: %d\n"
, ev, ev->fd, ev->bits, ev->timeout, ev->loop->n_events);
, (void *)ev, ev->fd, ev->bits, ev->timeout, ev->loop->n_events);
if (ev->gev.read_cb || ev->gev.write_cb || ev->gev.timeout_cb) {
if ((r = ev->loop->extension->vmt->schedule(
ev->loop->extension, ev->fd, ev->timeout, &ev->gev))) {
DEBUG_SCHED("UB_LOOP ERROR: scheduling event: %p\n", ev);
DEBUG_SCHED("UB_LOOP ERROR: scheduling event: %p\n", (void *)ev);
return r;
}
ev->added = 1;
DEBUG_SCHED("UB_LOOP: event %p(%d, %d, %"PRIu64") scheduled, "
"total: %d\n", ev, ev->fd, ev->bits, ev->timeout
"total: %d\n", (void *)ev, ev->fd, ev->bits, ev->timeout
, ++ev->loop->n_events);
}
return GETDNS_RETURN_GOOD;

View File

@ -838,6 +838,16 @@ _getdns_create_call_reporting_dict(
was actually used for the last successful query.*/
if (transport == GETDNS_TRANSPORT_TCP && netreq->debug_udp == 1) {
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)) {
getdns_dict_destroy(netreq_debug);
@ -858,6 +868,30 @@ _getdns_create_call_reporting_dict(
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)
@ -865,8 +899,7 @@ _getdns_create_call_reporting_dict(
/* Only include the auth status if TLS was used */
if (getdns_dict_util_set_string(netreq_debug, "tls_auth_status",
netreq->debug_tls_auth_status == 0 ?
"OK: Hostname matched valid cert":"FAILED: Server not validated")){
_getdns_auth_str(netreq->debug_tls_auth_status))){
getdns_dict_destroy(netreq_debug);
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 */

View File

@ -230,6 +230,7 @@ log_crypto_error(const char* str, unsigned long e)
ERR_error_string_n(e, buf, sizeof(buf));
/* buf now contains */
/* error:[error code]:[library name]:[function name]:[reason string] */
(void)str;
log_err("%s crypto %s", str, buf);
}
@ -262,8 +263,12 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
dsasig = DSA_SIG_new();
if(!dsasig) return 0;
#ifdef HAVE_DSA_SIG_SET0
if(!DSA_SIG_set0(dsasig, R, S)) return 0;
#else
dsasig->r = R;
dsasig->s = S;
#endif
*sig = NULL;
newlen = i2d_DSA_SIG(dsasig, sig);
if(newlen < 0) {
@ -404,7 +409,11 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
"EVP_PKEY_assign_DSA failed");
return 0;
}
#ifdef HAVE_EVP_DSS1
*digest_type = EVP_dss1();
#else
*digest_type = EVP_sha1();
#endif
break;
#endif /* USE_DSA */