Merge pull request #195 from wtoorop/release/v1.1.0a1

Release/v1.1.0a1
This commit is contained in:
saradickinson 2016-07-13 16:46:54 +01:00 committed by GitHub
commit d25d60cc3e
25 changed files with 1733 additions and 1971 deletions

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,4 +1,49 @@
* 2016-??-??: Version 1.0.0
* 2016-??-??: Version 1.0.0b2
* Collect coverage information from the unit tests
Thanks Shane Kerr
* pkg-config for the getdns_ext_event library
Thanks Tom Pusateri
* Bugfix: Multiple requests on the same upstream with a transport
that keeps connections open in synchronous stub mode.
* Canonicalized DNSSEC chain with dnssec_return_validation_chain
(when validated)
* A dnssec_return_full_validation_chain extension which includes
then validated resource records.
* Bugfix: Callbacks fired while scheduling (answer from cache)
with the unbound plugable event API
* header extension to set opcode and flags in stub mode
* Unit tests that cover more code
* Static checking with the clang analyzer
* getdns_pretty_print_dict prints dname's as primitives
* Accept just bindata's instead of address dicts.
Allow misshing "address_type" in address dicts.
* TLS session resumption
* -C <config file> option to getdns_query to configure context
from a json like formated file. The output of -i (print API
information) can be used as config file directly.
Settings may also be given in this format as arguments of
the getdns_query command directly.
* DNS server mode for getdns_query. Enable by providing addresses
to listen on, either by giving "-z <listen address>" options or by
providing "listen_addresses" in the config file or settings.
* Bugfixes from deckard testing: CNAME loop protection.
* "srv_addresses" in response dict with getdns_service()
* use libbsd when available
Thanks Guillem Jover
* Bugfix: DNSSEC wildcard validation issue
* Bugfix: TLS timeouts not re-using a connection
* A getdns_context_get_eventloop(), to get the current
(pluggable) eventloop from context
* getdns_query now uses the default event loop (instead of custom)
* Return call_reporting info in case of timeout
Thanks Robert Groenenberg
* Bugfix: Build fails with autoconf 2.63, works with 2.68.
Thanks Robert Groenenberg
* Doxygen output for getdns.h and getdns_extra.h only
* Do not call SSL_library_init() from getdns_context_create() when
the second bit from the set_from_os parameter is set.
* 2016-03-31: Version 1.0.0b1
* openssl 1.1.0 support
* GETDNS_APPEND_NAME_TO_SINGLE_LABEL_FIRST default suffix handling
* getdns_context_set_follow_redirects()

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, [b1])
AC_INIT([getdns], [1.1.0], [users@getdnsapi.net], [], [https://getdnsapi.net])
AC_SUBST(RELEASE_CANDIDATE, [a1])
# 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, [0x00100100])
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x0100A100])
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"

Binary file not shown.

Binary file not shown.

View File

@ -65,7 +65,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
GLDNS_OBJ=keyraw.lo gbuffer.lo wire2str.lo parse.lo parseutil.lo rrdef.lo \
str2wire.lo
@ -76,6 +76,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
@ -104,6 +106,9 @@ $(COMPAT_OBJ):
$(UTIL_OBJ):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -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) -c $(srcdir)/extension/$(@:.lo=.c) -o $@
@ -144,8 +149,8 @@ libgetdns_ext_ev.la: libgetdns.la libev.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -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) $(CFLAGS) -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) $(CFLAGS) -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
@ -203,11 +208,12 @@ configure.status: configure
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' \
@ -231,69 +237,78 @@ context.lo context.o: $(srcdir)/context.c config.h $(srcdir)/debug.h $(srcdir)/g
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \
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
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
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
$(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
@ -324,6 +339,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 \
$(srcdir)/extension/default_eventloop.h config.h getdns/getdns.h \
getdns/getdns_extra.h $(srcdir)/debug.h config.h

View File

@ -123,3 +123,212 @@ 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_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

@ -1216,6 +1216,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
@ -1272,6 +1274,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;
@ -1291,13 +1314,14 @@ 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. */
SSL_library_init();
if (set_from_os & 2 == 0)
SSL_library_init();
#ifdef HAVE_LIBUNBOUND
result->unbound_ctx = NULL;
if ((r = rebuild_ub_ctx(result)))
@ -1369,6 +1393,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);
/* 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.
@ -1401,8 +1428,7 @@ 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);
getdns_list_destroy(context->dns_root_servers);
#if defined(HAVE_LIBUNBOUND) && !defined(HAVE_UB_CTX_SET_STUB)
if (context->root_servers_fn[0])
@ -1419,6 +1445,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
@ -3416,7 +3446,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;
}
@ -3891,4 +3921,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;
@ -250,8 +251,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 +261,8 @@ struct getdns_context {
*/
_getdns_rbtree_t outbound_requests;
struct listen_set *server;
/* Event loop extension. */
getdns_eventloop *extension;
@ -275,6 +276,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;
int add_warning_for_bad_dns : 1;
int dnssec_return_all_statuses : 1;
int dnssec_return_full_validation_chain : 1;
int dnssec_return_only_secure : 1;
int dnssec_return_status : 1;
int dnssec_return_validation_chain : 1;
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE
int dnssec_roadblock_avoidance : 1;
#endif
int edns_cookies : 1;
int return_api_information : 1; /* Not used */
int return_both_v4_and_v6 : 1;
int return_call_reporting : 1;
uint16_t specify_class;
/*
* state data used to detect changes to the system config files
*/

View File

@ -48,9 +48,14 @@
#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"
/* stuff to make it compile pedantically */
#define UNUSED_PARAM(x) ((void)(x))
@ -611,6 +616,15 @@ _getdns_wire2msg_dict_scan(struct mem_funcs *mf,
if (!wire || !*wire || !wire_len || !msg_dict)
return GETDNS_RETURN_INVALID_PARAMETER;
#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG
do {
char *str = gldns_wire2str_pkt((uint8_t *)*wire, *wire_len);
DEBUG_SERVER("_getdns_wire2msg_dict_scan for a packet size: %d: %s\n",
(int)*wire_len, str);
free(str);
} while(0);
#endif
if (!(result = _getdns_dict_create_with_mf(mf)) ||
!(header = _getdns_dict_create_with_mf(mf)) ||
!(sections[SECTION_ANSWER]
@ -768,11 +782,12 @@ _getdns_reply_dict2wire(
const getdns_dict *reply, gldns_buffer *buf, int reuse_header)
{
uint8_t header_spc[GLDNS_HEADER_SIZE], *header;
uint32_t n, qtype, qclass = GETDNS_RRCLASS_IN;
uint32_t n, qtype, qclass = GETDNS_RRCLASS_IN, rr_type;
size_t pkt_start, i;
getdns_list *section;
getdns_dict *rr_dict;
getdns_bindata *qname;
int remove_dnssec;
pkt_start = gldns_buffer_position(buf);
if (reuse_header) {
@ -814,11 +829,18 @@ _getdns_reply_dict2wire(
buf, pkt_start+GLDNS_ARCOUNT_OFF, 0);
}
}
remove_dnssec = !getdns_dict_get_int(reply, "/header/do", &n) && n == 0;
DEBUG_SERVER("remove_dnssec: %d\n", remove_dnssec);
if (!getdns_dict_get_list(reply, "answer", &section)) {
for ( n = 0, i = 0
; !getdns_list_get_dict(section, i, &rr_dict); i++) {
if (!_getdns_rr_dict2wire(rr_dict, buf))
if (remove_dnssec &&
!getdns_dict_get_int(rr_dict, "type", &rr_type) &&
rr_type == GETDNS_RRTYPE_RRSIG)
continue;
if (!_getdns_rr_dict2wire(rr_dict, buf))
n++;
}
gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_ANCOUNT_OFF, n);
@ -827,7 +849,15 @@ _getdns_reply_dict2wire(
for ( n = 0, i = 0
; !getdns_list_get_dict(section, i, &rr_dict); i++) {
if (!_getdns_rr_dict2wire(rr_dict, buf))
if (remove_dnssec &&
!getdns_dict_get_int(rr_dict, "type", &rr_type) &&
( rr_type == GETDNS_RRTYPE_RRSIG
|| rr_type == GETDNS_RRTYPE_NSEC
|| rr_type == GETDNS_RRTYPE_NSEC3
|| rr_type == GETDNS_RRTYPE_DS
))
continue;
if (!_getdns_rr_dict2wire(rr_dict, buf))
n++;
}
gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_NSCOUNT_OFF, n);
@ -836,6 +866,10 @@ _getdns_reply_dict2wire(
for ( n = 0, i = 0
; !getdns_list_get_dict(section, i, &rr_dict); i++) {
if (remove_dnssec &&
!getdns_dict_get_int(rr_dict, "type", &rr_type) &&
rr_type == GETDNS_RRTYPE_RRSIG)
continue;
if (!_getdns_rr_dict2wire(rr_dict, buf))
n++;
}
@ -1031,5 +1065,641 @@ getdns_msg_dict2str_scan(
return r;
}
static getdns_dict *
_getdns_ipaddr_dict_mf(struct mem_funcs *mf, 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 >= 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)
{
size_t i, 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;
if (size <= 0 || size >= 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 >= 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 >= 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(struct mem_funcs *mf, 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 >= 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(struct mem_funcs *mf, const char *js, jsmntok_t *t,
uint32_t *value)
{
char value_str[80];
int size = t->end - t->start;
if (size <= 0 || size >= 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)
{
size_t i, j = 1;
char key_spc[1024], *key = NULL;
getdns_item child_item;
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 < 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)
{
size_t i, j = 1, index = 0;
getdns_item child_item;
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(mf, js, t, &item->data.n)
|| _jsmn_get_const(mf, 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 ((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;
}
/* convert.c */

View File

@ -918,10 +918,30 @@ getdns_return_t getdns_strerror(getdns_return_t err, char *buf, size_t buflen);
*/
/** @}
*/
/** @}
*/
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);
getdns_return_t
getdns_context_config(getdns_context *context, const getdns_dict *config_dict);
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 handler, const getdns_list *listen_addresses);
getdns_return_t getdns_reply(getdns_context *context,
getdns_transaction_t request_id, getdns_dict *reply);
#ifdef __cplusplus
}
#endif

1
src/jsmn Submodule

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

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

@ -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
@ -206,6 +206,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);
@ -658,28 +661,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 +720,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 +739,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;
@ -895,10 +905,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

@ -26,11 +26,13 @@
*/
#include "config.h"
#include "getdns_context_set_listen_addresses.h"
#include <netdb.h>
#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 +65,9 @@ struct listener {
*/
struct listen_set {
getdns_context *context;
listen_set *next;
getdns_request_handler_t handler;
_getdns_rbtree_t connections_set;
size_t count;
listener items[];
};
@ -79,6 +81,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 +93,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 +117,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 +138,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 +160,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 +198,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 *conn = (tcp_connection *)conn;
if (conn->to_answer > 0 && --conn->to_answer == 0 &&
conn->fd == -1)
tcp_connection_destroy(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);
@ -236,10 +241,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)))
@ -260,6 +276,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 +340,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 */
@ -381,8 +401,8 @@ static void tcp_read_cb(void *userarg)
conn->to_answer++;
/* 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, request_dict, (intptr_t)conn);
conn->read_pos = conn->read_buf;
conn->to_read = 2;
@ -402,7 +422,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 +444,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 +454,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,10 +478,20 @@ 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 +515,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)))
@ -503,11 +533,86 @@ static void udp_read_cb(void *userarg)
close(l->fd);
l->fd = -1;
#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG
} else {
char addrbuf[100];
char hexbuf[4096], *hexptr;
size_t l, i, j;
if (conn->remote_in.ss_family == AF_INET) {
if (inet_ntop(AF_INET,
&((struct sockaddr_in*)&conn->remote_in)->sin_addr,
addrbuf, sizeof(addrbuf))) {
l = strlen(addrbuf);
(void) snprintf(addrbuf + l,
sizeof(addrbuf) - l, ":%d",
(int)((struct sockaddr_in*)
&conn->remote_in)->sin_port);
} else
(void) strncpy(
addrbuf, "error ipv4", sizeof(addrbuf));
} else if (conn->remote_in.ss_family == AF_INET6) {
addrbuf[0] = '[';
if (inet_ntop(AF_INET6,
&((struct sockaddr_in6*)
&conn->remote_in)->sin6_addr,
addrbuf, sizeof(addrbuf))) {
l = strlen(addrbuf);
(void) snprintf(addrbuf + l,
sizeof(addrbuf) - l, ":%d",
(int)((struct sockaddr_in6*)
&conn->remote_in)->sin6_port);
} else
(void) strncpy(
addrbuf, "error ipv6", sizeof(addrbuf));
} else {
(void) strncpy(
addrbuf, "unknown address", sizeof(addrbuf));
}
*(hexptr = hexbuf) = 0;
for (i = 0; i < len; i++) {
if (i % 12 == 0) {
hexptr += snprintf(hexptr,
sizeof(hexbuf) - (hexptr - hexbuf) - 1,
"\n%.4x", (int)i);
} else if (i % 4 == 0) {
hexptr += snprintf(hexptr,
sizeof(hexbuf) - (hexptr - hexbuf) - 1,
" ");
}
if (hexptr - hexbuf > sizeof(hexbuf))
break;
hexptr += snprintf(hexptr,
sizeof(hexbuf) - (hexptr - hexbuf) - 1,
" %.2x", (int)buf[i]);
if (hexptr - hexbuf > sizeof(hexbuf))
break;
}
DEBUG_SERVER("Received %d bytes from %s: %s\n",
(int)len, addrbuf, hexbuf);
}
if (len == -1) {
; /* pass */
#endif
} else if ((r = getdns_wire2msg_dict(buf, len, &request_dict)))
; /* FROMERR on input, ignore */
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;
@ -520,25 +625,6 @@ static void udp_read_cb(void *userarg)
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;
@ -547,7 +633,7 @@ 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);
@ -573,7 +659,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))
@ -597,7 +683,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);
@ -615,7 +702,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)))
@ -672,16 +759,21 @@ static getdns_return_t add_listeners(listen_set *set)
return GETDNS_RETURN_GOOD;
}
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,
getdns_request_handler_t request_handler, getdns_list *listen_addresses)
getdns_request_handler_t request_handler,
const getdns_list *listen_addresses)
{
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;
@ -694,9 +786,11 @@ 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,
DEBUG_SERVER("getdns_context_set_listen_addresses(%p, %p, %p)\n",
context, request_handler,
listen_addresses);
if (!(mf = priv_getdns_context_mf(context)))
if (!(mf = &context->mf))
return GETDNS_RETURN_GENERIC_ERROR;
if ((r = getdns_context_get_eventloop(context, &loop)))
@ -708,7 +802,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;
}
@ -716,7 +810,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;
@ -729,10 +823,12 @@ 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",
new_set, current_set);
new_set->context = context;
new_set->next = root;
new_set->handler = request_handler;
new_set->count = new_set_count * n_transports;
(void) memset(new_set->items, 0,
@ -871,10 +967,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_ */

View File

@ -66,16 +66,10 @@ 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 \
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
@ -94,9 +88,6 @@ default: all
all: $(PROGRAMS)
jsmn.lo:
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -DJSMN_GETDNS -c $(srcdir)/jsmn/jsmn.c -o $@
$(ALL_OBJS):
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/$(@:.lo=.c) -o $@
@ -133,8 +124,8 @@ 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) $(CFLAGS) -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_CFLAGS) $(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) $(CFLAGS) -o $@ getdns_query.lo $(DECOMPOSED_OBJS) $(LDFLAGS) $(LDLIBS)
getdns_query: getdns_query.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ getdns_query.lo $(LDFLAGS) $(LDLIBS)
scratchpad: scratchpad.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) -o $@ scratchpad.lo $(LDFLAGS) $(LDLIBS)
@ -221,7 +212,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 )
@ -273,20 +263,8 @@ 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
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
../getdns/getdns.h ../getdns/getdns_extra.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

@ -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,47 +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, 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

@ -27,13 +27,11 @@
#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>
#include <inttypes.h>
#include <ctype.h>
#include <getdns/getdns.h>
#include <getdns/getdns_extra.h>
#ifndef USE_WINSOCK
@ -70,7 +68,55 @@ static int timeout, edns0_size, padding_blocksize;
static int async = 0, interactive = 0;
static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL;
int get_rrtype(const char *t);
static int get_rrtype(const char *t)
{
char buf[1024] = "GETDNS_RRTYPE_";
uint32_t rrtype;
long int l;
size_t i;
char *endptr;
if (strlen(t) > sizeof(buf) - 15)
return -1;
for (i = 14; *t && i < sizeof(buf) - 1; i++, t++)
buf[i] = toupper(*t);
buf[i] = '\0';
if (!getdns_str2int(buf, &rrtype))
return (int)rrtype;
if (strncasecmp(buf + 14, "TYPE", 4) == 0) {
l = strtol(buf + 18, &endptr, 10);
if (!*endptr && l >= 0 && l < 65536)
return l;
}
return -1;
}
static int get_rrclass(const char *t)
{
char buf[1024] = "GETDNS_RRCLASS_";
uint32_t rrclass;
long int l;
size_t i;
char *endptr;
if (strlen(t) > sizeof(buf) - 16)
return -1;
for (i = 15; *t && i < sizeof(buf) - 1; i++, t++)
buf[i] = toupper(*t);
buf[i] = '\0';
if (!getdns_str2int(buf, &rrclass))
return (int)rrclass;
if (strncasecmp(buf + 15, "CLASS", 5) == 0) {
l = strtol(buf + 20, &endptr, 10);
if (!*endptr && l >= 0 && l < 65536)
return l;
}
return -1;
}
static getdns_return_t
fill_transport_list(getdns_context *context, char *transport_list_str,
@ -415,8 +461,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));
}
@ -457,34 +502,13 @@ getdns_return_t parse_args(int argc, char **argv)
break;
}
} else if (strncmp(arg+1, "specify_class=", 14) == 0) {
if (strncasecmp(arg+15, "IN", 3) == 0)
if ((klass = get_rrclass(arg+15)) >= 0)
r = getdns_dict_set_int(extensions,
"specify_class", GETDNS_RRCLASS_IN);
else if (strncasecmp(arg+15, "CH", 3) == 0)
r = getdns_dict_set_int(extensions,
"specify_class", GETDNS_RRCLASS_CH);
else if (strncasecmp(arg+15, "HS", 3) == 0)
r = getdns_dict_set_int(extensions,
"specify_class", GETDNS_RRCLASS_HS);
else if (strncasecmp(arg+15, "NONE", 5) == 0)
r = getdns_dict_set_int(extensions,
"specify_class", GETDNS_RRCLASS_NONE);
else if (strncasecmp(arg+15, "ANY", 4) == 0)
r = getdns_dict_set_int(extensions,
"specify_class", GETDNS_RRCLASS_ANY);
else if (strncasecmp(arg+15, "CLASS", 5) == 0) {
klass = strtol(arg + 20, &endptr, 10);
if (*endptr || klass > 255)
fprintf(stderr,
"Unknown class: %s\n",
arg+15);
else
r = getdns_dict_set_int(extensions,
"specify_class", klass);
} else
else
fprintf(stderr,
"Unknown class: %s\n", arg+15);
} else if (arg[1] == '0') {
/* Unset all existing extensions*/
getdns_dict_destroy(extensions);
@ -499,8 +523,23 @@ getdns_return_t parse_args(int argc, char **argv)
continue;
} else if (arg[0] == '@') {
getdns_dict *upstream = _getdns_ipaddr_dict(arg + 1);
if (upstream) {
getdns_dict *upstream;
getdns_bindata *address;
if ((r = getdns_str2dict(arg + 1, &upstream)))
fprintf(stderr, "Could not convert \"%s\" to "
"an IP dict: %s\n", arg + 1,
getdns_get_errorstr_by_id(r));
else if ((r = getdns_dict_get_bindata(
upstream, "address_data", &address))) {
fprintf(stderr, "\"%s\" did not translate to "
"an IP dict: %s\n", arg + 1,
getdns_get_errorstr_by_id(r));
getdns_dict_destroy(upstream);
} else {
if (!upstream_list &&
!(upstream_list =
getdns_list_create_with_context(context))){
@ -521,6 +560,9 @@ getdns_return_t parse_args(int argc, char **argv)
continue;
}
for (c = arg+1; *c; c++) {
getdns_dict *downstream;
getdns_bindata *address;
switch (*c) {
case 'a':
async = 1;
@ -896,23 +938,33 @@ getdns_return_t parse_args(int argc, char **argv)
DEBUG_SERVER("Clear listen list\n");
break;
}
getdns_dict *downstream =
_getdns_ipaddr_dict(argv[i]);
if (!downstream) {
fprintf(stderr, "could not parse "
"listen address: %s", argv[i]);
if ((r = getdns_str2dict(argv[i], &downstream)))
fprintf(stderr, "Could not convert \"%s\" to "
"an IP dict: %s\n", argv[i],
getdns_get_errorstr_by_id(r));
else if ((r = getdns_dict_get_bindata(
downstream, "address_data", &address))) {
fprintf(stderr, "\"%s\" did not translate to "
"an IP dict: %s\n", argv[i],
getdns_get_errorstr_by_id(r));
getdns_dict_destroy(downstream);
} else {
if (!listen_list &&
!(listen_list =
getdns_list_create_with_context(context))){
fprintf(stderr, "Could not create "
"downstream list\n");
return GETDNS_RETURN_MEMORY_ERROR;
}
getdns_list_set_dict(listen_list,
listen_count++, downstream);
getdns_dict_destroy(downstream);
touched_listen_list = 1;
}
if (!listen_list &&
!(listen_list =
getdns_list_create_with_context(context))){
fprintf(stderr, "Could not create "
"downstram list\n");
return GETDNS_RETURN_MEMORY_ERROR;
}
getdns_list_set_dict(listen_list,
listen_count++, downstream);
getdns_dict_destroy(downstream);
touched_listen_list = 1;
break;
default:
fprintf(stderr, "Unknown option "
@ -976,14 +1028,26 @@ getdns_return_t do_the_call(void)
{
getdns_return_t r;
getdns_dict *address = NULL;
getdns_bindata *address_bindata;
getdns_dict *response = NULL;
char *response_str;
uint32_t status;
if (calltype == HOSTNAME &&
!(address = _getdns_ipaddr_dict(name))) {
fprintf(stderr, "Could not convert \"%s\" "
"to an IP address", name);
if (calltype != HOSTNAME)
; /* pass */
else if ((r = getdns_str2dict(name, &address))) {
fprintf(stderr, "Could not convert \"%s\" to an IP dict: %s\n"
, name, getdns_get_errorstr_by_id(r));
return GETDNS_RETURN_GOOD;
} else if ((r = getdns_dict_get_bindata(
address, "address_data", &address_bindata))) {
fprintf(stderr, "Could not convert \"%s\" to an IP dict: %s\n"
, name, getdns_get_errorstr_by_id(r));
getdns_dict_destroy(address);
return GETDNS_RETURN_GOOD;
}
if (async) {
@ -1132,8 +1196,10 @@ typedef struct dns_msg {
getdns_transaction_t request_id;
getdns_dict *request;
uint32_t rt;
uint32_t ad_bit;
uint32_t do_bit;
uint32_t cd_bit;
int has_edns0;
} dns_msg;
#if defined(SERVER_DEBUG) && SERVER_DEBUG
@ -1168,15 +1234,55 @@ void servfail(dns_msg *msg, getdns_dict **resp_p)
(void) getdns_dict_set_int(*resp_p, "/header/ad", 0);
}
void request_cb(getdns_context *context, getdns_callback_type_t callback_type,
static getdns_return_t _handle_edns0(
getdns_dict *response, int has_edns0)
{
getdns_return_t r;
getdns_list *additional;
size_t len, i;
getdns_dict *rr;
uint32_t rr_type;
char remove_str[100] = "/replies_tree/0/additional/";
if ((r = getdns_dict_set_int(
response, "/replies_tree/0/header/do", 0)))
return r;
if ((r = getdns_dict_get_list(response, "/replies_tree/0/additional",
&additional)))
return r;
if ((r = getdns_list_get_length(additional, &len)))
return r;
for (i = 0; i < len; i++) {
if ((r = getdns_list_get_dict(additional, i, &rr)))
return r;
if ((r = getdns_dict_get_int(rr, "type", &rr_type)))
return r;
if (rr_type != GETDNS_RRTYPE_OPT)
continue;
if (has_edns0) {
(void) getdns_dict_set_int(rr, "do", 0);
break;
}
(void) snprintf(remove_str + 27, 60, "%d", (int)i);
if ((r = getdns_dict_remove_name(response, remove_str)))
return r;
break;
}
return GETDNS_RETURN_GOOD;
}
static void request_cb(
getdns_context *context, getdns_callback_type_t callback_type,
getdns_dict *response, void *userarg, getdns_transaction_t transaction_id)
{
dns_msg *msg = (dns_msg *)userarg;
uint32_t qid;
getdns_return_t r = GETDNS_RETURN_GOOD;
uint32_t n;
uint32_t n, rcode, dnssec_status;
DEBUG_SERVER("reply for: %p %"PRIu64" %d\n", msg, transaction_id, (int)callback_type);
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
@ -1195,21 +1301,36 @@ void request_cb(getdns_context *context, getdns_callback_type_t callback_type,
SERVFAIL("Could not copy QID", r, msg, &response);
else if (getdns_dict_get_int(
response, "/replies_tree/0/header/rcode", &n))
response, "/replies_tree/0/header/rcode", &rcode))
SERVFAIL("No reply in replies tree", 0, msg, &response);
else if (msg->cd_bit != 1 && !getdns_dict_get_int(
response, "/replies_tree/0/dnssec_status", &n)
&& n == GETDNS_DNSSEC_BOGUS)
/* ansers when CD or not BOGUS */
else if (!msg->cd_bit && !getdns_dict_get_int(
response, "/replies_tree/0/dnssec_status", &dnssec_status)
&& dnssec_status == GETDNS_DNSSEC_BOGUS)
SERVFAIL("DNSSEC status was bogus", 0, msg, &response);
else if ((r = getdns_dict_get_int(
response, "/replies_tree/0/header/rcode", &n)))
SERVFAIL("Could not get rcode from reply", r, msg, &response);
else if (n == GETDNS_RCODE_SERVFAIL)
else if (rcode == GETDNS_RCODE_SERVFAIL)
servfail(msg, &response);
/* RRsigs when DO and (CD or not BOGUS)
* Implemented in conversion to wireformat function by checking for DO
* bit. In recursing resolution mode we have to copy the do bit from
* the request, because libunbound has it in the answer always.
*/
else if (msg->rt == GETDNS_RESOLUTION_RECURSING && !msg->do_bit &&
(r = _handle_edns0(response, msg->has_edns0)))
SERVFAIL("Could not handle EDNS0", r, msg, &response);
/* AD when (DO or AD) and SECURE */
else if ((r = getdns_dict_set_int(response,"/replies_tree/0/header/ad",
((msg->do_bit || msg->ad_bit)
&& ( (!msg->cd_bit && dnssec_status == GETDNS_DNSSEC_SECURE)
|| ( msg->cd_bit && !getdns_dict_get_int(response,
"/replies_tree/0/dnssec_status", &dnssec_status)
&& dnssec_status == GETDNS_DNSSEC_SECURE ))) ? 1 : 0)))
SERVFAIL("Could not set AD bit", r, msg, &response);
else if (msg->rt == GETDNS_RESOLUTION_STUB)
; /* following checks are for RESOLUTION_RECURSING only */
@ -1224,14 +1345,11 @@ void request_cb(getdns_context *context, getdns_callback_type_t callback_type,
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, msg->request_id, response))) {
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, msg->request_id, NULL);
}
if (msg) {
getdns_dict_destroy(msg->request);
@ -1256,6 +1374,10 @@ static void incoming_request_handler(getdns_context *context,
getdns_dict *qext = NULL;
dns_msg *msg = NULL;
getdns_dict *response = NULL;
size_t i, len;
getdns_list *additional;
getdns_dict *rr;
uint32_t rr_type;
if (!query_extensions_spc &&
!(query_extensions_spc = getdns_dict_create()))
@ -1277,10 +1399,26 @@ static void incoming_request_handler(getdns_context *context,
n = 0;
msg->request_id = request_id;
msg->request = request;
msg->do_bit = msg->cd_bit = 0;
msg->rt = GETDNS_RESOLUTION_STUB;
(void) getdns_dict_get_int(request, "/additional/0/do", &msg->do_bit);
msg->ad_bit = msg->do_bit = msg->cd_bit = 0;
msg->has_edns0 = 0;
msg->rt = GETDNS_RESOLUTION_RECURSING;
(void) getdns_dict_get_int(request, "/header/ad", &msg->ad_bit);
(void) getdns_dict_get_int(request, "/header/cd", &msg->cd_bit);
if (!getdns_dict_get_list(request, "additional", &additional)) {
if (getdns_list_get_length(additional, &len))
len = 0;
for (i = 0; i < len; i++) {
if (getdns_list_get_dict(additional, i, &rr))
break;
if (getdns_dict_get_int(rr, "type", &rr_type))
break;
if (rr_type != GETDNS_RRTYPE_OPT)
continue;
msg->has_edns0 = 1;
(void) getdns_dict_get_int(rr, "do", &msg->do_bit);
break;
}
}
if ((r = getdns_context_get_resolution_type(context, &msg->rt)))
fprintf(stderr, "Could get resolution type from context: %s\n",
getdns_get_errorstr_by_id(r));
@ -1291,15 +1429,10 @@ static void incoming_request_handler(getdns_context *context,
if (!getdns_dict_get_dict(request, "header", &header))
(void)getdns_dict_set_dict(qext, "header", header);
} else if (getdns_dict_get_int(extensions,"dnssec_return_status",&n) ||
n == GETDNS_EXTENSION_FALSE)
(void)getdns_dict_set_int(qext, "dnssec_return_status",
msg->do_bit ? GETDNS_EXTENSION_TRUE : GETDNS_EXTENSION_FALSE);
if (!getdns_dict_get_int(qext, "dnssec_return_status", &n) &&
n == GETDNS_EXTENSION_TRUE)
(void) getdns_dict_set_int(qext, "dnssec_return_all_statuses",
msg->cd_bit ? GETDNS_EXTENSION_TRUE : GETDNS_EXTENSION_FALSE);
}
if (msg->cd_bit)
getdns_dict_set_int(qext, "dnssec_return_all_statuses",
GETDNS_EXTENSION_TRUE);
if (!getdns_dict_get_int(request, "/additional/0/extended_rcode",&n))
(void)getdns_dict_set_int(
@ -1363,14 +1496,21 @@ error:
if (qname_str)
free(qname_str);
servfail(msg, &response);
if (!response)
/* No response, no reply */
_getdns_cancel_reply(context, request_id);
else if ((r = getdns_reply(context, request_id, response))) {
#if defined(SERVER_DEBUG) && SERVER_DEBUG
do {
char *request_str = getdns_pretty_print_dict(request);
char *response_str = getdns_pretty_print_dict(response);
DEBUG_SERVER("request error, request: %s\n, response: %s\n"
, request_str, response_str);
free(response_str);
free(request_str);
} while(0);
#endif
if ((r = getdns_reply(context, request_id, response))) {
fprintf(stderr, "Could not reply: %s\n",
getdns_get_errorstr_by_id(r));
_getdns_cancel_reply(context, request_id);
/* Cancel reply */
getdns_reply(context, request_id, NULL);
}
if (msg) {
if (msg->request)
@ -1471,462 +1611,4 @@ done_destroy_context:
return r;
}
int get_rrtype(const char *t) {
char *endptr;
int r;
switch (t[0]) {
case 'A':
case 'a': switch (t[1]) {
case '\0': return GETDNS_RRTYPE_A;
case '6': if (t[2] == '\0') return GETDNS_RRTYPE_A6;
return -1;
case 'A':
case 'a': /* before "AA", final "AA" (GETDNS_RRTYPE_AAAA) */
if ((t[2]|0x20) == 'a' && (t[3]|0x20) == 'a' && t[4] == '\0')
return GETDNS_RRTYPE_AAAA;
return -1;
case 'F':
case 'f': /* before "AF", final "SDB" (GETDNS_RRTYPE_AFSDB) */
if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'd' && (t[4]|0x20) == 'b' && t[5] == '\0')
return GETDNS_RRTYPE_AFSDB;
return -1;
case 'P':
case 'p': /* before "AP", final "L" (GETDNS_RRTYPE_APL) */
if ((t[2]|0x20) == 'l' && t[3] == '\0')
return GETDNS_RRTYPE_APL;
return -1;
case 'T':
case 't': /* before "AT", final "MA" (GETDNS_RRTYPE_ATMA) */
if ((t[2]|0x20) == 'm' && (t[3]|0x20) == 'a' && t[4] == '\0')
return GETDNS_RRTYPE_ATMA;
return -1;
case 'X':
case 'x': /* before "AX", final "FR" (GETDNS_RRTYPE_AXFR) */
if ((t[2]|0x20) == 'f' && (t[3]|0x20) == 'r' && t[4] == '\0')
return GETDNS_RRTYPE_AXFR;
return -1;
default : return -1;
};
case 'C':
case 'c': switch (t[1]) {
case 'A':
case 'a': /* before "CA", final "A" (GETDNS_RRTYPE_CAA) */
if ((t[2]|0x20) == 'a' && t[3] == '\0')
return GETDNS_RRTYPE_CAA;
return -1;
case 'D':
case 'd': switch (t[2]) {
case 'N':
case 'n': /* before "CDN", final "SKEY" (GETDNS_RRTYPE_CDNSKEY) */
if ((t[3]|0x20) == 's' && (t[4]|0x20) == 'k' && (t[5]|0x20) == 'e' && (t[6]|0x20) == 'y' && t[7] == '\0')
return GETDNS_RRTYPE_CDNSKEY;
return -1;
case 'S':
case 's': if (t[3] == '\0') return GETDNS_RRTYPE_CDS;
return -1;
default : return -1;
};
case 'E':
case 'e': /* before "CE", final "RT" (GETDNS_RRTYPE_CERT) */
if ((t[2]|0x20) == 'r' && (t[3]|0x20) == 't' && t[4] == '\0')
return GETDNS_RRTYPE_CERT;
return -1;
case 'N':
case 'n': /* before "CN", final "AME" (GETDNS_RRTYPE_CNAME) */
if ((t[2]|0x20) == 'a' && (t[3]|0x20) == 'm' && (t[4]|0x20) == 'e' && t[5] == '\0')
return GETDNS_RRTYPE_CNAME;
return -1;
case 'S':
case 's': /* before "CS", final "YNC" (GETDNS_RRTYPE_CSYNC) */
if ((t[2]|0x20) == 'y' && (t[3]|0x20) == 'n' && (t[4]|0x20) == 'c' && t[5] == '\0')
return GETDNS_RRTYPE_CSYNC;
return -1;
default : return -1;
};
case 'D':
case 'd': switch (t[1]) {
case 'H':
case 'h': /* before "DH", final "CID" (GETDNS_RRTYPE_DHCID) */
if ((t[2]|0x20) == 'c' && (t[3]|0x20) == 'i' && (t[4]|0x20) == 'd' && t[5] == '\0')
return GETDNS_RRTYPE_DHCID;
return -1;
case 'L':
case 'l': /* before "DL", final "V" (GETDNS_RRTYPE_DLV) */
if ((t[2]|0x20) == 'v' && t[3] == '\0')
return GETDNS_RRTYPE_DLV;
return -1;
case 'N':
case 'n': switch (t[2]) {
case 'A':
case 'a': /* before "DNA", final "ME" (GETDNS_RRTYPE_DNAME) */
if ((t[3]|0x20) == 'm' && (t[4]|0x20) == 'e' && t[5] == '\0')
return GETDNS_RRTYPE_DNAME;
return -1;
case 'S':
case 's': /* before "DNS", final "KEY" (GETDNS_RRTYPE_DNSKEY) */
if ((t[3]|0x20) == 'k' && (t[4]|0x20) == 'e' && (t[5]|0x20) == 'y' && t[6] == '\0')
return GETDNS_RRTYPE_DNSKEY;
return -1;
default : return -1;
};
case 'S':
case 's': if (t[2] == '\0') return GETDNS_RRTYPE_DS;
return -1;
default : return -1;
};
case 'E':
case 'e': switch (t[1]) {
case 'I':
case 'i': /* before "EI", final "D" (GETDNS_RRTYPE_EID) */
if ((t[2]|0x20) == 'd' && t[3] == '\0')
return GETDNS_RRTYPE_EID;
return -1;
case 'U':
case 'u': /* before "EU", next "I" */
if ((t[2]|0x20) != 'i')
return -1;
switch (t[3]) {
case '4': /* before "EUI4", final "8" (GETDNS_RRTYPE_EUI48) */
if (t[4] == '8' && t[5] == '\0')
return GETDNS_RRTYPE_EUI48;
return -1;
case '6': /* before "EUI6", final "4" (GETDNS_RRTYPE_EUI64) */
if (t[4] == '4' && t[5] == '\0')
return GETDNS_RRTYPE_EUI64;
return -1;
default : return -1;
};
default : return -1;
};
case 'G':
case 'g': switch (t[1]) {
case 'I':
case 'i': /* before "GI", final "D" (GETDNS_RRTYPE_GID) */
if ((t[2]|0x20) == 'd' && t[3] == '\0')
return GETDNS_RRTYPE_GID;
return -1;
case 'P':
case 'p': /* before "GP", final "OS" (GETDNS_RRTYPE_GPOS) */
if ((t[2]|0x20) == 'o' && (t[3]|0x20) == 's' && t[4] == '\0')
return GETDNS_RRTYPE_GPOS;
return -1;
default : return -1;
};
case 'H':
case 'h': /* before "H", next "I" */
if ((t[1]|0x20) != 'i')
return -1;
switch (t[2]) {
case 'N':
case 'n': /* before "HIN", final "FO" (GETDNS_RRTYPE_HINFO) */
if ((t[3]|0x20) == 'f' && (t[4]|0x20) == 'o' && t[5] == '\0')
return GETDNS_RRTYPE_HINFO;
return -1;
case 'P':
case 'p': if (t[3] == '\0') return GETDNS_RRTYPE_HIP;
return -1;
default : return -1;
};
case 'I':
case 'i': switch (t[1]) {
case 'P':
case 'p': /* before "IP", final "SECKEY" (GETDNS_RRTYPE_IPSECKEY) */
if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'e' && (t[4]|0x20) == 'c' && (t[5]|0x20) == 'k' && (t[6]|0x20) == 'e' && (t[7]|0x20) == 'y' && t[8] == '\0')
return GETDNS_RRTYPE_IPSECKEY;
return -1;
case 'S':
case 's': /* before "IS", final "DN" (GETDNS_RRTYPE_ISDN) */
if ((t[2]|0x20) == 'd' && (t[3]|0x20) == 'n' && t[4] == '\0')
return GETDNS_RRTYPE_ISDN;
return -1;
case 'X':
case 'x': /* before "IX", final "FR" (GETDNS_RRTYPE_IXFR) */
if ((t[2]|0x20) == 'f' && (t[3]|0x20) == 'r' && t[4] == '\0')
return GETDNS_RRTYPE_IXFR;
return -1;
default : return -1;
};
case 'K':
case 'k': switch (t[1]) {
case 'E':
case 'e': /* before "KE", final "Y" (GETDNS_RRTYPE_KEY) */
if ((t[2]|0x20) == 'y' && t[3] == '\0')
return GETDNS_RRTYPE_KEY;
return -1;
case 'X':
case 'x': if (t[2] == '\0') return GETDNS_RRTYPE_KX;
return -1;
default : return -1;
};
case 'L':
case 'l': switch (t[1]) {
case '3': /* before "L3", final "2" (GETDNS_RRTYPE_L32) */
if (t[2] == '2' && t[3] == '\0')
return GETDNS_RRTYPE_L32;
return -1;
case '6': /* before "L6", final "4" (GETDNS_RRTYPE_L64) */
if (t[2] == '4' && t[3] == '\0')
return GETDNS_RRTYPE_L64;
return -1;
case 'O':
case 'o': /* before "LO", final "C" (GETDNS_RRTYPE_LOC) */
if ((t[2]|0x20) == 'c' && t[3] == '\0')
return GETDNS_RRTYPE_LOC;
return -1;
case 'P':
case 'p': if (t[2] == '\0') return GETDNS_RRTYPE_LP;
return -1;
default : return -1;
};
case 'M':
case 'm': switch (t[1]) {
case 'A':
case 'a': /* before "MA", next "IL" */
if ((t[2]|0x20) != 'i' && (t[3]|0x20) != 'l')
return -1;
switch (t[4]) {
case 'A':
case 'a': if (t[5] == '\0') return GETDNS_RRTYPE_MAILA;
return -1;
case 'B':
case 'b': if (t[5] == '\0') return GETDNS_RRTYPE_MAILB;
return -1;
default : return -1;
};
case 'B':
case 'b': if (t[2] == '\0') return GETDNS_RRTYPE_MB;
return -1;
case 'D':
case 'd': if (t[2] == '\0') return GETDNS_RRTYPE_MD;
return -1;
case 'F':
case 'f': if (t[2] == '\0') return GETDNS_RRTYPE_MF;
return -1;
case 'G':
case 'g': if (t[2] == '\0') return GETDNS_RRTYPE_MG;
return -1;
case 'I':
case 'i': /* before "MI", final "NFO" (GETDNS_RRTYPE_MINFO) */
if ((t[2]|0x20) == 'n' && (t[3]|0x20) == 'f' && (t[4]|0x20) == 'o' && t[5] == '\0')
return GETDNS_RRTYPE_MINFO;
return -1;
case 'R':
case 'r': if (t[2] == '\0') return GETDNS_RRTYPE_MR;
return -1;
case 'X':
case 'x': if (t[2] == '\0') return GETDNS_RRTYPE_MX;
return -1;
default : return -1;
};
case 'N':
case 'n': switch (t[1]) {
case 'A':
case 'a': /* before "NA", final "PTR" (GETDNS_RRTYPE_NAPTR) */
if ((t[2]|0x20) == 'p' && (t[3]|0x20) == 't' && (t[4]|0x20) == 'r' && t[5] == '\0')
return GETDNS_RRTYPE_NAPTR;
return -1;
case 'I':
case 'i': switch (t[2]) {
case 'D':
case 'd': if (t[3] == '\0') return GETDNS_RRTYPE_NID;
return -1;
case 'M':
case 'm': /* before "NIM", final "LOC" (GETDNS_RRTYPE_NIMLOC) */
if ((t[3]|0x20) == 'l' && (t[4]|0x20) == 'o' && (t[5]|0x20) == 'c' && t[6] == '\0')
return GETDNS_RRTYPE_NIMLOC;
return -1;
case 'N':
case 'n': /* before "NIN", final "FO" (GETDNS_RRTYPE_NINFO) */
if ((t[3]|0x20) == 'f' && (t[4]|0x20) == 'o' && t[5] == '\0')
return GETDNS_RRTYPE_NINFO;
return -1;
default : return -1;
};
case 'S':
case 's': switch (t[2]) {
case '\0': return GETDNS_RRTYPE_NS;
case 'A':
case 'a': /* before "NSA", final "P" (GETDNS_RRTYPE_NSAP) */
if ((t[3]|0x20) == 'p' && t[4] == '\0')
return GETDNS_RRTYPE_NSAP;
return -1;
case 'E':
case 'e': /* before "NSE", final "C3PARAM" (GETDNS_RRTYPE_NSEC3PARAM) */
if ((t[3]|0x20) == 'c' && t[4] == '3' && (t[5]|0x20) == 'p' && (t[6]|0x20) == 'a' && (t[7]|0x20) == 'r' && (t[8]|0x20) == 'a' && (t[9]|0x20) == 'm' && t[10] == '\0')
return GETDNS_RRTYPE_NSEC3PARAM;
return -1;
default : return -1;
};
case 'U':
case 'u': /* before "NU", final "LL" (GETDNS_RRTYPE_NULL) */
if ((t[2]|0x20) == 'l' && (t[3]|0x20) == 'l' && t[4] == '\0')
return GETDNS_RRTYPE_NULL;
return -1;
case 'X':
case 'x': /* before "NX", final "T" (GETDNS_RRTYPE_NXT) */
if ((t[2]|0x20) == 't' && t[3] == '\0')
return GETDNS_RRTYPE_NXT;
return -1;
default : return -1;
};
case 'O':
case 'o': /* before "O", next "P" */
if ((t[1]|0x20) != 'p')
return -1;
switch (t[2]) {
case 'E':
case 'e': /* before "OPE", final "NPGPKEY" (GETDNS_RRTYPE_OPENPGPKEY) */
if ((t[3]|0x20) == 'n' && (t[4]|0x20) == 'p' && (t[5]|0x20) == 'g' && (t[6]|0x20) == 'p' && (t[7]|0x20) == 'k' && (t[8]|0x20) == 'e' && (t[9]|0x20) == 'y' && t[10] == '\0')
return GETDNS_RRTYPE_OPENPGPKEY;
return -1;
case 'T':
case 't': if (t[3] == '\0') return GETDNS_RRTYPE_OPT;
return -1;
default : return -1;
};
case 'P':
case 'p': switch (t[1]) {
case 'T':
case 't': /* before "PT", final "R" (GETDNS_RRTYPE_PTR) */
if ((t[2]|0x20) == 'r' && t[3] == '\0')
return GETDNS_RRTYPE_PTR;
return -1;
case 'X':
case 'x': if (t[2] == '\0') return GETDNS_RRTYPE_PX;
return -1;
default : return -1;
};
case 'R':
case 'r': switch (t[1]) {
case 'K':
case 'k': /* before "RK", final "EY" (GETDNS_RRTYPE_RKEY) */
if ((t[2]|0x20) == 'e' && (t[3]|0x20) == 'y' && t[4] == '\0')
return GETDNS_RRTYPE_RKEY;
return -1;
case 'P':
case 'p': if (t[2] == '\0') return GETDNS_RRTYPE_RP;
return -1;
case 'R':
case 'r': /* before "RR", final "SIG" (GETDNS_RRTYPE_RRSIG) */
if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'i' && (t[4]|0x20) == 'g' && t[5] == '\0')
return GETDNS_RRTYPE_RRSIG;
return -1;
case 'T':
case 't': if (t[2] == '\0') return GETDNS_RRTYPE_RT;
return -1;
default : return -1;
};
case 'S':
case 's': switch (t[1]) {
case 'I':
case 'i': switch (t[2]) {
case 'G':
case 'g': if (t[3] == '\0') return GETDNS_RRTYPE_SIG;
return -1;
case 'N':
case 'n': /* before "SIN", final "K" (GETDNS_RRTYPE_SINK) */
if ((t[3]|0x20) == 'k' && t[4] == '\0')
return GETDNS_RRTYPE_SINK;
return -1;
default : return -1;
};
case 'O':
case 'o': /* before "SO", final "A" (GETDNS_RRTYPE_SOA) */
if ((t[2]|0x20) == 'a' && t[3] == '\0')
return GETDNS_RRTYPE_SOA;
return -1;
case 'P':
case 'p': /* before "SP", final "F" (GETDNS_RRTYPE_SPF) */
if ((t[2]|0x20) == 'f' && t[3] == '\0')
return GETDNS_RRTYPE_SPF;
return -1;
case 'R':
case 'r': /* before "SR", final "V" (GETDNS_RRTYPE_SRV) */
if ((t[2]|0x20) == 'v' && t[3] == '\0')
return GETDNS_RRTYPE_SRV;
return -1;
case 'S':
case 's': /* before "SS", final "HFP" (GETDNS_RRTYPE_SSHFP) */
if ((t[2]|0x20) == 'h' && (t[3]|0x20) == 'f' && (t[4]|0x20) == 'p' && t[5] == '\0')
return GETDNS_RRTYPE_SSHFP;
return -1;
default : return -1;
};
case 'T':
case 't': switch (t[1]) {
case 'A':
case 'a': /* before "TA", final "LINK" (GETDNS_RRTYPE_TALINK) */
if ((t[2]|0x20) == 'l' && (t[3]|0x20) == 'i' && (t[4]|0x20) == 'n' && (t[5]|0x20) == 'k' && t[6] == '\0')
return GETDNS_RRTYPE_TALINK;
return -1;
case 'K':
case 'k': /* before "TK", final "EY" (GETDNS_RRTYPE_TKEY) */
if ((t[2]|0x20) == 'e' && (t[3]|0x20) == 'y' && t[4] == '\0')
return GETDNS_RRTYPE_TKEY;
return -1;
case 'L':
case 'l': /* before "TL", final "SA" (GETDNS_RRTYPE_TLSA) */
if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'a' && t[4] == '\0')
return GETDNS_RRTYPE_TLSA;
return -1;
case 'S':
case 's': /* before "TS", final "IG" (GETDNS_RRTYPE_TSIG) */
if ((t[2]|0x20) == 'i' && (t[3]|0x20) == 'g' && t[4] == '\0')
return GETDNS_RRTYPE_TSIG;
return -1;
case 'X':
case 'x': /* before "TX", final "T" (GETDNS_RRTYPE_TXT) */
if ((t[2]|0x20) == 't' && t[3] == '\0')
return GETDNS_RRTYPE_TXT;
return -1;
case 'Y':
case 'y': /* before "TY", then "PE" followed by a number */
if ((t[2]|0x20) == 'p' && (t[3]|0x20) == 'e' && t[4] != '\0') {
r = (int) strtol(t + 4, &endptr, 10);
if (*endptr == '\0') return r;
}
return -1;
default : return -1;
};
case 'U':
case 'u': switch (t[1]) {
case 'I':
case 'i': switch (t[2]) {
case 'D':
case 'd': if (t[3] == '\0') return GETDNS_RRTYPE_UID;
return -1;
case 'N':
case 'n': /* before "UIN", final "FO" (GETDNS_RRTYPE_UINFO) */
if ((t[3]|0x20) == 'f' && (t[4]|0x20) == 'o' && t[5] == '\0')
return GETDNS_RRTYPE_UINFO;
return -1;
default : return -1;
};
case 'N':
case 'n': /* before "UN", final "SPEC" (GETDNS_RRTYPE_UNSPEC) */
if ((t[2]|0x20) == 's' && (t[3]|0x20) == 'p' && (t[4]|0x20) == 'e' && (t[5]|0x20) == 'c' && t[6] == '\0')
return GETDNS_RRTYPE_UNSPEC;
return -1;
case 'R':
case 'r': /* before "UR", final "I" (GETDNS_RRTYPE_URI) */
if ((t[2]|0x20) == 'i' && t[3] == '\0')
return GETDNS_RRTYPE_URI;
return -1;
default : return -1;
};
case 'W':
case 'w': /* before "W", final "KS" (GETDNS_RRTYPE_WKS) */
if ((t[1]|0x20) == 'k' && (t[2]|0x20) == 's' && t[3] == '\0')
return GETDNS_RRTYPE_WKS;
return -1;
case 'X':
case 'x': /* before "X", final "25" (GETDNS_RRTYPE_X25) */
if (t[1] == '2' && t[2] == '5' && t[3] == '\0')
return GETDNS_RRTYPE_X25;
return -1;
default : return -1;
};
}

View File

@ -1,926 +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 */
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, 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 >= 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;
}
getdns_dict *
_getdns_ipaddr_dict(const char *ipstr)
{
char value_str[3072];
size_t size = strlen(ipstr);
if (size >= sizeof(value_str))
return NULL;
(void) memcpy(value_str, ipstr, size);
value_str[size] = '\0';
return _getdns_ipaddr_dict_mf(&_getdns_plain_mem_funcs, value_str);
}
static int _jsmn_get_data(struct mem_funcs *mf, const char *js, jsmntok_t *t,
getdns_bindata **value)
{
size_t i, 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;
if (size <= 0 || size >= 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 >= 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 >= 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(struct mem_funcs *mf, 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 >= 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(struct mem_funcs *mf, const char *js, jsmntok_t *t,
uint32_t *value)
{
char value_str[80];
int size = t->end - t->start;
if (size <= 0 || size >= 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)
{
size_t i, j = 1;
char key_spc[1024], *key = NULL;
getdns_item child_item;
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 < 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)
{
size_t i, j = 1, index = 0;
getdns_item child_item;
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(mf, js, t, &item->data.n)
|| _jsmn_get_const(mf, 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 ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
return r;
else if (item.dtype != t_dict) {
_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
}
*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,39 +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_dict *_getdns_ipaddr_dict(const char *ipstr);
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 daa17063c67f0dfe873af25ab6b664641c8cf90c