Merge pull request #267 from wtoorop/features/mdns-client

Features/mdns client
This commit is contained in:
wtoorop 2017-03-20 22:15:57 +01:00 committed by GitHub
commit 1ad8047443
41 changed files with 5943 additions and 773 deletions

View File

@ -311,6 +311,15 @@ AC_INCLUDES_DEFAULT
fi
AC_ARG_ENABLE(sha1, AC_HELP_STRING([--disable-sha1], [Disable SHA1 RRSIG support, does not disable nsec3 support]))
case "$enable_sha1" in
no)
;;
yes|*)
AC_DEFINE([USE_SHA1], [1], [Define this to enable SHA1 support.])
;;
esac
AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support]))
case "$enable_sha2" in
no)
@ -481,9 +490,10 @@ case "$enable_dsa" in
;;
esac
AC_ARG_ENABLE(all-drafts, AC_HELP_STRING([--enable-all-drafts], [No drafts in this release]))
AC_ARG_ENABLE(all-drafts, AC_HELP_STRING([--enable-all-drafts], [Enables the draft mdns client support]))
case "$enable_all_drafts" in
yes)
AC_DEFINE_UNQUOTED([HAVE_MDNS_SUPPORT], [1], [Define this to enable the draft mdns client support.])
;;
no|*)
;;
@ -514,6 +524,15 @@ AC_DEFINE_UNQUOTED([EDNS_COOKIE_ROLLOVER_TIME], [(24 * 60 * 60)], [How often the
AC_DEFINE_UNQUOTED([MAXIMUM_UPSTREAM_OPTION_SPACE], [3000], [limit for dynamically-generated DNS options])
AC_DEFINE_UNQUOTED([EDNS_PADDING_OPCODE], [12], [The edns padding option code.])
AC_ARG_ENABLE(draft-mdns-support, AC_HELP_STRING([--enable-draft-mdns-support], [Enable draft mdns client support]))
case "$enable_draft_mdns_support" in
yes)
AC_DEFINE_UNQUOTED([HAVE_MDNS_SUPPORT], [1], [Define this to enable the draft mdns client support.])
;;
no|*)
;;
esac
my_with_libunbound=1
AC_ARG_ENABLE(stub-only, AC_HELP_STRING([--enable-stub-only], [Restricts resolution modes to STUB (which will be the default mode). Removes the libunbound dependency.]))
case "$enable_stub_only" in
@ -657,7 +676,7 @@ AC_TYPE_UINT16_T
AC_TYPE_UINT32_T
AC_TYPE_UINT64_T
AC_TYPE_UINT8_T
AC_CHECK_TYPE([u_char])
AC_CHECK_TYPES([u_char])
AC_CHECK_FUNCS([fcntl])
# check ioctlsocket
@ -742,7 +761,7 @@ AS_IF([test x_$withval = x_no],
[AC_MSG_ERROR([event2/event.h and event.h missing, try without libevent])]
[have_libevent=0],
[AC_INCLUDES_DEFAULT]
[#if HAVE_U_CHAR == 0
[#ifndef HAVE_U_CHAR
typedef unsigned char u_char;
#endif])],
[AC_INCLUDES_DEFAULT])],
@ -992,7 +1011,10 @@ fi
#---- check for pthreads library
AC_SEARCH_LIBS([pthread_mutex_init],[pthread],[AC_DEFINE([HAVE_PTHREADS], [1], [Have pthreads library])], [AC_MSG_WARN([pthreads not available])])
AC_SEARCH_LIBS([pthread_mutex_init],[pthread], [
AC_DEFINE([HAVE_PTHREAD], [1], [Have pthreads library])
LIBS="-lpthread $LIBS"
], [AC_MSG_WARN([pthreads not available])])
AC_MSG_CHECKING([whether the C compiler (${CC-cc}) supports the __func__ variable])
AC_LANG_PUSH(C)
@ -1008,7 +1030,7 @@ dnl ----- Start of "Things needed for gldns" section
dnl -----
dnl ---------------------------------------------------------------------------
AC_CHECK_HEADERS([stdarg.h stdint.h netinet/in.h arpa/inet.h netdb.h sys/socket.h time.h sys/time.h sys/select.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([stdarg.h stdint.h netinet/in.h arpa/inet.h netdb.h sys/socket.h time.h sys/time.h sys/select.h endian.h],,, [AC_INCLUDES_DEFAULT])
dnl Check the printf-format attribute (if any)
dnl result in HAVE_ATTR_FORMAT.

View File

@ -48,7 +48,7 @@ srcdir = @srcdir@
LIBTOOL = ../libtool
CC=@CC@
CFLAGS=-I$(srcdir) -I. @CFLAGS@ @CPPFLAGS@ $(XTRA_CFLAGS)
CFLAGS=-I$(srcdir) -I. -I$(srcdir)/util/auxiliary @CFLAGS@ @CPPFLAGS@ $(XTRA_CFLAGS)
WPEDANTICFLAG=@WPEDANTICFLAG@
WNOERRORFLAG=@WNOERRORFLAG@
LDFLAGS=@LDFLAGS@ @LIBS@
@ -79,7 +79,7 @@ LIBOBJDIR=
LIBOBJS=@LIBOBJS@
COMPAT_OBJ=$(LIBOBJS:.o=.lo)
UTIL_OBJ=rbtree.lo val_secalgo.lo
UTIL_OBJ=rbtree.lo val_secalgo.lo lruhash.lo lookup3.lo locks.lo
JSMN_OBJ=jsmn.lo
@ -191,13 +191,14 @@ Makefile: $(srcdir)/Makefile.in ../config.status
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 jsmn/*.c extension/*.c| \
(blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" -Iutil/auxiliary *.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? gldns/? $$(srcdir)/gldns/?g' \
-e 's? compat/? $$(srcdir)/compat/?g' \
-e 's? util/auxiliary/util/? $$(srcdir)/util/auxiliary/util/?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' \
-e 's? \$$(srcdir)/getdns/getdns_extra\.h? getdns/getdns_extra.h?g' \
@ -224,95 +225,122 @@ context.lo context.o: $(srcdir)/context.c \
$(srcdir)/debug.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h $(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/list.h \
$(srcdir)/dict.h $(srcdir)/pubkey-pinning.h
convert.lo convert.o: $(srcdir)/convert.c \
config.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/wire2str.h $(srcdir)/gldns/str2wire.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/jsmn/jsmn.h \
$(srcdir)/convert.h
$(srcdir)/util/orig-headers/rbtree.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/wire2str.h \
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/parseutil.h $(srcdir)/const-info.h $(srcdir)/dict.h \
$(srcdir)/list.h $(srcdir)/jsmn/jsmn.h $(srcdir)/convert.h
dict.lo dict.o: $(srcdir)/dict.c \
config.h \
$(srcdir)/types-internal.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h \
$(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h \
$(srcdir)/gldns/parseutil.h
dnssec.lo dnssec.o: $(srcdir)/dnssec.c \
config.h \
$(srcdir)/debug.h \
getdns/getdns.h \
$(srcdir)/context.h \
getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h \
$(srcdir)/gldns/keyraw.h $(srcdir)/gldns/parseutil.h $(srcdir)/general.h $(srcdir)/dict.h $(srcdir)/list.h \
$(srcdir)/util/val_secalgo.h
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/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)/util/orig-headers/val_secalgo.h
general.lo general.o: $(srcdir)/general.c \
config.h \
$(srcdir)/general.h \
getdns/getdns.h \
$(srcdir)/types-internal.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/gldns/wire2str.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/ub_loop.h $(srcdir)/debug.h \
$(srcdir)/gldns/wire2str.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/dict.h \
$(srcdir)/mdns.h
list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util-internal.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h \
config.h \
$(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/list.h $(srcdir)/dict.h
mdns.lo mdns.o: $(srcdir)/mdns.c \
config.h \
$(srcdir)/debug.h $(srcdir)/context.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/general.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/mdns.h
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/general.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/mdns.h \
$(srcdir)/util/auxiliary/util/fptr_wlist.h $(srcdir)/util/lookup3.h \
$(srcdir)/util/orig-headers/lookup3.h
pubkey-pinning.lo pubkey-pinning.o: $(srcdir)/pubkey-pinning.c \
config.h \
$(srcdir)/debug.h \
getdns/getdns.h \
$(srcdir)/context.h \
getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \
$(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h
request-internal.lo request-internal.o: $(srcdir)/request-internal.c \
config.h \
$(srcdir)/types-internal.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h $(srcdir)/convert.h
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/util-internal.h $(srcdir)/context.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/dict.h \
$(srcdir)/convert.h $(srcdir)/general.h
rr-dict.lo rr-dict.o: $(srcdir)/rr-dict.c $(srcdir)/rr-dict.h \
config.h \
getdns/getdns.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/util-internal.h $(srcdir)/context.h \
getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
$(srcdir)/rr-iter.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dict.h
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h $(srcdir)/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 \
@ -321,42 +349,52 @@ server.lo server.o: $(srcdir)/server.c \
config.h \
getdns/getdns_extra.h \
getdns/getdns.h \
$(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h
$(srcdir)/context.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h
stub.lo stub.o: $(srcdir)/stub.c \
config.h \
$(srcdir)/debug.h $(srcdir)/stub.h \
getdns/getdns.h \
$(srcdir)/types-internal.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/context.h $(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h $(srcdir)/util-internal.h $(srcdir)/general.h \
$(srcdir)/pubkey-pinning.h
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/wire2str.h $(srcdir)/rr-iter.h \
$(srcdir)/rr-dict.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/server.h \
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h \
$(srcdir)/util-internal.h $(srcdir)/general.h $(srcdir)/pubkey-pinning.h
sync.lo sync.o: $(srcdir)/sync.c \
getdns/getdns.h \
config.h \
$(srcdir)/context.h \
getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
$(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h \
$(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h $(srcdir)/gldns/wire2str.h
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h \
$(srcdir)/extension/default_eventloop.h $(srcdir)/extension/poll_eventloop.h \
$(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/general.h $(srcdir)/util-internal.h $(srcdir)/rr-iter.h \
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h $(srcdir)/stub.h \
$(srcdir)/gldns/wire2str.h
ub_loop.lo ub_loop.o: $(srcdir)/ub_loop.c $(srcdir)/ub_loop.h \
config.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/debug.h
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/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 \
$(srcdir)/dict.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/types-internal.h \
getdns/getdns_extra.h \
$(srcdir)/list.h $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/default_eventloop.h \
$(srcdir)/extension/poll_eventloop.h $(srcdir)/types-internal.h $(srcdir)/ub_loop.h $(srcdir)/debug.h $(srcdir)/server.h \
$(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h
$(srcdir)/util/lruhash.h $(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/rr-iter.h \
$(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/str2wire.h $(srcdir)/gldns/rrdef.h \
$(srcdir)/dnssec.h $(srcdir)/gldns/rrdef.h
gbuffer.lo gbuffer.o: $(srcdir)/gldns/gbuffer.c \
config.h \
$(srcdir)/gldns/gbuffer.h
@ -406,41 +444,59 @@ sha512.lo sha512.o: $(srcdir)/compat/sha512.c \
config.h
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c \
config.h
locks.lo locks.o: $(srcdir)/util/locks.c \
config.h \
$(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h
lookup3.lo lookup3.o: $(srcdir)/util/lookup3.c \
config.h \
$(srcdir)/util/auxiliary/util/storage/lookup3.h $(srcdir)/util/lookup3.h \
$(srcdir)/util/orig-headers/lookup3.h
lruhash.lo lruhash.o: $(srcdir)/util/lruhash.c \
config.h \
$(srcdir)/util/auxiliary/util/storage/lruhash.h $(srcdir)/util/lruhash.h \
$(srcdir)/util/orig-headers/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/orig-headers/locks.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util/auxiliary/util/fptr_wlist.h
rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c \
config.h \
$(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/rbtree.h
$(srcdir)/util/auxiliary/log.h $(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h \
$(srcdir)/util/auxiliary/fptr_wlist.h $(srcdir)/util/auxiliary/util/fptr_wlist.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h
val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c \
config.h \
$(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h $(srcdir)/debug.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h \
$(srcdir)/gldns/gbuffer.h
$(srcdir)/util/auxiliary/util/data/packed_rrset.h \
$(srcdir)/util/auxiliary/validator/val_secalgo.h $(srcdir)/util/val_secalgo.h \
$(srcdir)/util/orig-headers/val_secalgo.h $(srcdir)/util/auxiliary/validator/val_nsec3.h \
$(srcdir)/util/auxiliary/util/log.h $(srcdir)/debug.h $(srcdir)/util/auxiliary/sldns/rrdef.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/util/auxiliary/sldns/keyraw.h $(srcdir)/gldns/keyraw.h \
$(srcdir)/util/auxiliary/sldns/sbuffer.h $(srcdir)/gldns/gbuffer.h
jsmn.lo jsmn.o: $(srcdir)/jsmn/jsmn.c $(srcdir)/jsmn/jsmn.h
libev.lo libev.o: $(srcdir)/extension/libev.c \
config.h \
$(srcdir)/types-internal.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libev.h
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libev.h
libevent.lo libevent.o: $(srcdir)/extension/libevent.c \
config.h \
$(srcdir)/types-internal.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libevent.h
libuv.lo libuv.o: $(srcdir)/extension/libuv.c \
config.h \
$(srcdir)/debug.h $(srcdir)/types-internal.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/util/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h
$(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/getdns/getdns_ext_libuv.h
poll_eventloop.lo poll_eventloop.o: $(srcdir)/extension/poll_eventloop.c \
config.h \
$(srcdir)/extension/poll_eventloop.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/debug.h
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h $(srcdir)/debug.h
select_eventloop.lo select_eventloop.o: $(srcdir)/extension/select_eventloop.c \
config.h \
$(srcdir)/extension/select_eventloop.h \
getdns/getdns.h \
getdns/getdns_extra.h \
$(srcdir)/debug.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h
$(srcdir)/debug.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/util/orig-headers/rbtree.h

View File

@ -34,7 +34,7 @@
#include "config.h"
#define LOCKRET(func) func
#ifdef HAVE_PTHREADS
#ifdef HAVE_PTHREAD
#include "pthread.h"
static pthread_mutex_t arc_lock = PTHREAD_MUTEX_INITIALIZER;

View File

@ -62,7 +62,7 @@ typedef unsigned short in_port_t;
#include <assert.h>
#include <ctype.h>
#ifdef HAVE_PTHREADS
#ifdef HAVE_PTHREAD
#include <pthread.h>
#endif
#include <stdbool.h>
@ -93,11 +93,21 @@ typedef unsigned short in_port_t;
upstream. Using 1 hour for all transports - based on RFC7858 value for for TLS.*/
#define BACKOFF_RETRY 3600
#ifdef HAVE_PTHREADS
#ifdef HAVE_PTHREAD
static pthread_mutex_t ssl_init_lock = PTHREAD_MUTEX_INITIALIZER;
#endif
static bool ssl_init=false;
#ifdef HAVE_MDNS_SUPPORT
/*
* Forward declaration of MDNS context init and destroy function.
* We do this here instead of including mdns.h, in order to
* minimize dependencies.
*/
void _getdns_mdns_context_init(struct getdns_context *context);
void _getdns_mdns_context_destroy(struct getdns_context *context);
#endif
void *plain_mem_funcs_user_arg = MF_PLAIN;
typedef struct host_name_addrs {
@ -817,9 +827,22 @@ tls_only_is_in_transports_list(getdns_context *context) {
static int
net_req_query_id_cmp(const void *id1, const void *id2)
{
return (intptr_t)id1 - (intptr_t)id2;
/*
* old code was:
* return (intptr_t)id1 - (intptr_t)id2;
*but this is incorrect on 64 bit architectures.
*/
int ret = 0;
if (id1 != id2)
{
ret = ((intptr_t)id1 < (intptr_t)id2) ? -1 : 1;
}
return ret;
}
static getdns_tsig_info const tsig_info[] = {
{ GETDNS_NO_TSIG, NULL, 0, NULL, 0, 0, 0 }
, { GETDNS_HMAC_MD5 , "hmac-md5.sig-alg.reg.int", 24
@ -1463,7 +1486,7 @@ getdns_context_create_with_extended_memory_functions(
/* 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. */
#ifdef HAVE_PTHREADS
#ifdef HAVE_PTHREAD
pthread_mutex_lock(&ssl_init_lock);
#else
/* XXX implement Windows-style lock here */
@ -1473,7 +1496,7 @@ getdns_context_create_with_extended_memory_functions(
SSL_library_init();
ssl_init = true;
}
#ifdef HAVE_PTHREADS
#ifdef HAVE_PTHREAD
pthread_mutex_unlock(&ssl_init_lock);
#else
/* XXX implement Windows-style unlock here */
@ -1485,8 +1508,14 @@ getdns_context_create_with_extended_memory_functions(
goto error;
#endif
#ifdef HAVE_MDNS_SUPPORT
_getdns_mdns_context_init(result);
#endif
create_local_hosts(result);
*context = result;
return GETDNS_RETURN_GOOD;
error:
@ -1566,6 +1595,13 @@ getdns_context_destroy(struct getdns_context *context)
ub_ctx_delete(context->unbound_ctx);
#endif
#ifdef HAVE_MDNS_SUPPORT
/*
* Release all ressource allocated for MDNS.
*/
_getdns_mdns_context_destroy(context);
#endif
if (context->namespaces)
GETDNS_FREE(context->my_mf, context->namespaces);

View File

@ -45,6 +45,9 @@
#include "util/rbtree.h"
#include "ub_loop.h"
#include "server.h"
#ifdef HAVE_MDNS_SUPPORT
#include "util/lruhash.h"
#endif
struct getdns_dns_req;
struct ub_ctx;
@ -344,6 +347,23 @@ struct getdns_context {
/* We need to run WSAStartup() to be able to use getaddrinfo() */
WSADATA wsaData;
#endif
/* MDNS */
#ifdef HAVE_MDNS_SUPPORT
/*
* If supporting MDNS, context may be instantiated either in basic mode
* or in full mode. If working in extended mode, two multicast sockets are
* left open, for IPv4 and IPv6. Data can be received on either socket.
* The context also keeps a list of open queries, characterized by a
* name and an RR type, and a list of received answers, characterized
* by name, RR type and data value.
*/
int mdns_extended_support; /* 0 = no support, 1 = supported, 2 = initialization needed */
int mdns_connection_nb; /* typically 0 or 2 for IPv4 and IPv6 */
struct mdns_network_connection * mdns_connection;
struct lruhash * mdns_cache;
#endif /* HAVE_MDNS_SUPPORT */
}; /* getdns_context */
/** internal functions **/

View File

@ -128,6 +128,7 @@
#define MDNS_DEBUG_ENTRY "-> MDNS ENTRY: "
#define MDNS_DEBUG_READ "-- MDNS READ: "
#define MDNS_DEBUG_MREAD "-- MDNS MREAD: "
#define MDNS_DEBUG_WRITE "-- MDNS WRITE: "
#define MDNS_DEBUG_CLEANUP "-- MDNS CLEANUP:"
@ -138,5 +139,14 @@
#define DEBUG_MDNS(...) DEBUG_OFF(__VA_ARGS__)
#endif
#if (defined(SCHED_DEBUG) && SCHED_DEBUG) || \
(defined(STUB_DEBUG) && STUB_DEBUG) || \
(defined(DAEMON_DEBUG) && DAEMON_DEBUG) || \
(defined(SEC_DEBUG) && SEC_DEBUG) || \
(defined(SERVER_DEBUG) && SERVER_DEBUG) || \
(defined(MDNS_DEBUG) && MDNS_DEBUG)
#define DEBUGGING 1
#endif
#endif
/* debug.h */

View File

@ -110,7 +110,8 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
/* Do we have to check more suffixes on nxdomain/nodata?
*/
if (dns_req->suffix_appended && /* Something was appended */
if (dns_req->is_dns_request &&
dns_req->suffix_appended && /* Something was appended */
dns_req->suffix_len > 1 && /* Next suffix available */
no_answer(dns_req)) {
/* Remove suffix from name */
@ -146,6 +147,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
return;
}
} else if (
dns_req->is_dns_request &&
( dns_req->append_name ==
GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE ||
dns_req->append_name ==
@ -189,7 +191,9 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
dns_req->internal_cb(dns_req);
} else if (! results_found)
_getdns_call_user_callback(dns_req, NULL);
else if (dns_req->dnssec_return_validation_chain
else if (
dns_req->is_dns_request &&
(dns_req->dnssec_return_validation_chain
#ifdef DNSSEC_ROADBLOCK_AVOIDANCE
|| ( dns_req->dnssec_roadblock_avoidance
&& !dns_req->avoid_dnssec_roadblocks)
@ -202,7 +206,7 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req)
dns_req->dnssec_return_all_statuses
))
#endif
)
))
_getdns_get_validation_chain(dns_req);
else
_getdns_call_user_callback(
@ -301,7 +305,7 @@ _getdns_netreq_change_state(
uint64_t now_ms;
getdns_network_req *prev;
if (!netreq)
if (!netreq || !netreq->owner->is_dns_request)
return;
context = netreq->owner->context;
@ -571,7 +575,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
if (!(r = _getdns_context_local_namespace_resolve(
req, &localnames_response))) {
req->is_dns_request = 0;
_getdns_call_user_callback
( req, localnames_response);
break;
@ -581,6 +585,7 @@ getdns_general_ns(getdns_context *context, getdns_eventloop *loop,
/* Check whether the name belongs in the MDNS space */
if (!(r = _getdns_mdns_namespace_check(req)))
{
req->is_dns_request = 0;
// Submit the query to the MDNS transport.
for (netreq_p = req->netreqs
; !r && (netreq = *netreq_p)

1852
src/mdns.c

File diff suppressed because it is too large Load Diff

View File

@ -24,12 +24,98 @@
#ifdef HAVE_MDNS_SUPPORT
#include "getdns/getdns.h"
#include "types-internal.h"
#include "util/lruhash.h"
#include "config.h"
#ifndef USE_WINSOCK
#define SOCKADDR_STORAGE struct sockaddr_storage
#endif
getdns_return_t
_getdns_submit_mdns_request(getdns_network_req *netreq);
getdns_return_t
_getdns_mdns_namespace_check(getdns_dns_req *dnsreq);
/*
* data structure for continuous queries
*/
typedef struct getdns_mdns_known_record
{
/* For storage in context->mdns_known_records_by_value */
_getdns_rbnode_t node;
uint64_t insertion_microsec;
uint16_t record_type;
uint16_t record_class;
uint32_t ttl;
int name_len;
int record_data_len;
uint8_t* name;
uint8_t * record_data;
} getdns_mdns_known_record;
/*
* Each entry in the hash table is keyed by type, class and name.
* The key structure also contains the LRU hash entry structure.
* The data part contains:
* - 64 bit time stamp
* - 32 bit word describing the record size
* - 32 bit word describing teh allocated memory size
* - valid DNS response, including 1 query and N answers, 0 AUTH, 0 AD.
* For economy, the names of all answers are encoded using header compression, pointing
* to the name in the query, i.e. offset 12 from beginning of message.
* For stability, the names included in the data part of records are not compressed.
*/
typedef struct getdns_mdns_cached_key_header
{
/* embedded entry, for LRU hash */
struct lruhash_entry entry;
/* identification */
uint16_t record_type;
uint16_t record_class;
int name_len;
/* the octets following this structure contain the name */
} getdns_mdns_cached_key_header;
typedef struct getdns_mdns_cached_record_header
{
uint64_t insertion_microsec;
uint32_t content_len;
uint32_t allocated_length;
/* list of user queries */
getdns_network_req *netreq_first;
} getdns_mdns_cached_record_header;
typedef struct getdns_mdns_continuous_query
{
/* For storage in context->mdns_continuous_queries_by_name_rrtype */
_getdns_rbnode_t node;
uint8_t name[256]; /* binary representation of name being queried */
int name_len;
uint16_t request_class;
uint16_t request_type;
/* list of user queries */
getdns_network_req *netreq_first;
/* todo: do we need an expiration date, or a timer? */
/* todo: do we need an update mark for showing last results? */
} getdns_mdns_continuous_query;
typedef struct mdns_network_connection
{
struct getdns_context* context;
int fd;
int addr_mcast_len;
SOCKADDR_STORAGE addr_mcast;
getdns_eventloop_event event;
uint8_t response[1500];
} mdns_network_connection;
void _getdns_mdns_context_init(struct getdns_context *context);
void _getdns_mdns_context_destroy(struct getdns_context *context);
#endif /* HAVE_MDNS_SUPPORT */
#endif /* MDNS_H */

View File

@ -938,6 +938,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
result->finished_next = NULL;
result->freed = NULL;
result->validating = 0;
result->is_dns_request = 1;
result->chain = NULL;
network_req_init(result->netreqs[0], result,

View File

@ -135,7 +135,11 @@ static void tcp_connection_destroy(tcp_connection *conn)
loop->vmt->clear(loop, &conn->event);
if (conn->fd >= 0)
#ifdef USE_WINSOCK
(void) closesocket(conn->fd);
#else
(void) close(conn->fd);
#endif
GETDNS_FREE(*mf, conn->read_buf);
for (cur = conn->to_write; cur; cur = next) {
@ -185,8 +189,8 @@ static void tcp_write_cb(void *userarg)
}
to_write = conn->to_write;
if (conn->fd == -1 ||
(written = write(conn->fd, &to_write->write_buf[to_write->written],
to_write->write_buf_len - to_write->written)) == -1) {
(written = send(conn->fd, &to_write->write_buf[to_write->written],
to_write->write_buf_len - to_write->written, 0)) == -1) {
/* IO error, close connection */
conn->event.read_cb = conn->event.write_cb =
@ -280,7 +284,11 @@ getdns_reply(
(struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) {
/* IO error, cleanup this listener */
loop->vmt->clear(loop, &conn->l->event);
#ifdef USE_WINSOCK
closesocket(conn->l->fd);
#else
close(conn->l->fd);
#endif
conn->l->fd = -1;
}
/* Unlink this connection */
@ -359,7 +367,7 @@ static void tcp_read_cb(void *userarg)
(void) loop->vmt->schedule(loop, conn->fd,
DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
if ((bytes_read = read(conn->fd, conn->read_pos, conn->to_read)) < 0) {
if ((bytes_read = recv(conn->fd, conn->read_pos, conn->to_read, 0)) < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
return; /* Come back to do the read later */
@ -473,7 +481,11 @@ static void tcp_accept_cb(void *userarg)
&conn->super.remote_in, &conn->super.addrlen)) == -1) {
/* IO error, cleanup this listener */
loop->vmt->clear(loop, &l->event);
#ifdef USE_WINSOCK
closesocket(l->fd);
#else
close(l->fd);
#endif
l->fd = -1;
GETDNS_FREE(*mf, conn);
return;
@ -543,7 +555,11 @@ static void udp_read_cb(void *userarg)
(struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) {
/* IO error, cleanup this listener. */
loop->vmt->clear(loop, &l->event);
#ifdef USE_WINSOCK
closesocket(l->fd);
#else
close(l->fd);
#endif
l->fd = -1;
#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG
@ -692,7 +708,11 @@ static void remove_listeners(listen_set *set)
continue;
loop->vmt->clear(loop, &l->event);
#ifdef USE_WINSOCK
closesocket(l->fd);
#else
close(l->fd);
#endif
l->fd = -1;
if (l->transport != GETDNS_TRANSPORT_TCP)

View File

@ -15,7 +15,8 @@ rm -f report.txt
echo "*** running out of filedescriptors (sockets) and for the"
echo "*** limit_outstanding_queries feature."
echo "*** "
grep '[^!=]=[ ][ ]*NET_REQ_' *.[ch] */*.[ch]
grep -n '[^!=]=[ ][ ]*NET_REQ_' *.[ch] */*.[ch] | \
grep -v '^request-internal.c:[12][0-9][0-9]: *net_req->state = NET_REQ_NOT_SENT;$'
echo ""
fi
) >> report.txt
@ -28,7 +29,7 @@ rm -f report.txt
echo "*** __FUNC__ is aliases in config.h to name to be used"
echo "*** for the system with a #define"
echo "*** "
grep '__FUNCION__' *.[ch] */*.[ch]
grep -n '__FUNCTION__' *.[ch] */*.[ch]
echo ""
fi
) >> report.txt

View File

@ -183,7 +183,6 @@ typedef struct getdns_tcp_state {
} getdns_tcp_state;
/**
* Request data
**/
@ -191,6 +190,12 @@ typedef struct getdns_network_req
{
/* For storage in upstream->netreq_by_query_id */
_getdns_rbnode_t node;
#ifdef HAVE_MDNS_SUPPORT
/*
* for storage of continuous query context in hash table of cached results.
*/
struct getdns_network_req * mdns_netreq_next;
#endif /* HAVE_MDNS_SUPPORT */
/* the async_id from unbound */
int unbound_id;
/* state var */
@ -308,6 +313,7 @@ typedef struct getdns_dns_req {
/* Internally used by return_validation_chain */
unsigned dnssec_ok_checking_disabled : 1;
unsigned is_sync_request : 1;
unsigned is_dns_request : 1;
/* The validating and freed variables are used to make sure a single
* code path is followed while processing a DNS request, even when

View File

@ -0,0 +1 @@
#include "util/fptr_wlist.h"

1
src/util/auxiliary/log.h Normal file
View File

@ -0,0 +1 @@
#include "util/log.h"

View File

@ -0,0 +1 @@
#include "gldns/keyraw.h"

View File

@ -0,0 +1 @@
#include "gldns/rrdef.h"

View File

@ -0,0 +1 @@
#include "gldns/gbuffer.h"

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,58 @@
/**
*
* /brief dummy prototypes for logging a la unbound
*
*/
/*
* 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 UTIL_LOG_H
#define UTIL_LOG_H
#include "config.h"
#include "debug.h"
#ifdef DEBUGGING
#define verbose(x, ...) DEBUG_NL(__VA_ARGS__)
#define log_err(...) DEBUG_NL(__VA_ARGS__)
#define log_info(...) DEBUG_NL(__VA_ARGS__)
#define fatal_exit(...) do { DEBUG_NL(__VA_ARGS__); exit(EXIT_FAILURE); } while(0)
#define log_assert(x) do { if(!(x)) fatal_exit("%s:%d: %s: assertion %s failed", \
__FILE__, __LINE__, __FUNC__, #x); \
} while(0)
#else
#define verbose(...) ((void)0)
#define log_err(...) ((void)0)
#define log_info(...) ((void)0)
#define fatal_exit(...) ((void)0)
#define log_assert(x) ((void)0)
#endif
#endif /* UTIL_LOG_H */

View File

@ -0,0 +1 @@
#include "util/lookup3.h"

View File

@ -0,0 +1 @@
#include "util/lruhash.h"

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@
#include "util/val_secalgo.h"

View File

@ -1,60 +1,14 @@
#!/bin/sh
# Meant to be run from this directory
REPO=http://unbound.net/svn/trunk
mkdir ub || true
cd ub
for f in rbtree.c rbtree.h
do
wget http://unbound.net/svn/trunk/util/$f || \
ftp http://unbound.net/svn/trunk/util/$f || continue
sed -e 's/event_/_getdns_event_/g' \
-e 's/signal_add/_getdns_signal_add/g' \
-e 's/signal_del/_getdns_signal_del/g' \
-e 's/signal_set/_getdns_signal_set/g' \
-e 's/evtimer_/_getdns_evtimer_/g' \
-e 's/struct event/struct _getdns_event/g' \
-e 's/mini_ev_cmp/_getdns_mini_ev_cmp/g' \
-e 's/static void handle_timeouts/void handle_timeouts/g' \
-e 's/handle_timeouts/_getdns_handle_timeouts/g' \
-e 's/static int handle_select/int handle_select/g' \
-e 's/handle_select/_getdns_handle_select/g' \
-e 's/#include "rbtree\.h"/#include "util\/rbtree.h"/g' \
-e 's/rbnode_/_getdns_rbnode_/g' \
-e 's/rbtree_/_getdns_rbtree_/g' \
-e 's/traverse_post/_getdns_traverse_post/g' \
-e 's/#include "fptr_wlist\.h"/#include "util\/fptr_wlist.h"/g' \
-e 's/#include "log\.h"/#include "util\/log.h"/g' \
-e '/^#define _getdns_.* mini_getdns_/d' \
-e '/^\/\* redefine to use our own namespace so that on platforms where$/d' \
-e '/^ \* linkers crosslink library-private symbols with other symbols, it works \*\//d' \
$f > ../$f
done
for f in val_secalgo.h val_secalgo.c
do
wget http://unbound.net/svn/trunk/validator/$f || \
ftp http://unbound.net/svn/trunk/validator/$f || continue
sed -e 's/sldns/gldns/g' \
-e '/^\/\* packed_rrset on top to define enum types (forced by c99 standard) \*\/$/d' \
-e '/^#include "util\/data\/packed_rrset.h"$/d' \
-e 's/^#include "validator/#include "util/g' \
-e 's/^#include "gldns\/sbuffer/#include "gldns\/gbuffer/g' \
-e 's/^#include "util\/val_nsec3.h"/#define NSEC3_HASH_SHA1 0x01/g' \
-e 's/ds_digest_size_supported/_getdns_ds_digest_size_supported/g' \
-e 's/secalgo_ds_digest/_getdns_secalgo_ds_digest/g' \
-e 's/dnskey_algo_id_is_supported/_getdns_dnskey_algo_id_is_supported/g' \
-e 's/verify_canonrrset/_getdns_verify_canonrrset/g' \
-e 's/nsec3_hash_algo_size_supported/_getdns_nsec3_hash_algo_size_supported/g' \
-e 's/secalgo_nsec3_hash/_getdns_secalgo_nsec3_hash/g' \
-e 's/secalgo_hash_sha256/_getdns_secalgo_hash_sha256/g' \
-e 's/ecdsa_evp_workaround_init/_getdns_ecdsa_evp_workaround_init/g' \
-e 's/LDNS_/GLDNS_/g' \
-e 's/enum sec_status/int/g' \
-e 's/sec_status_bogus/0/g' \
-e 's/sec_status_unchecked/0/g' \
-e 's/sec_status_secure/1/g' \
$f > ../$f
done
cd ..
rm -r ub
wget -O rbtree.c ${REPO}/util/rbtree.c
wget -O orig-headers/rbtree.h ${REPO}/util/rbtree.h
wget -O val_secalgo.c ${REPO}/validator/val_secalgo.c
wget -O orig-headers/val_secalgo.h ${REPO}/validator/val_secalgo.h
wget -O lruhash.c ${REPO}/util/storage/lruhash.c
wget -O orig-headers/lruhash.h ${REPO}/util/storage/lruhash.h
wget -O lookup3.c ${REPO}/util/storage/lookup3.c
wget -O orig-headers/lookup3.h ${REPO}/util/storage/lookup3.h
wget -O locks.c ${REPO}/util/locks.c
wget -O orig-headers/locks.h ${REPO}/util/locks.h

264
src/util/locks.c Normal file
View File

@ -0,0 +1,264 @@
/**
* util/locks.c - unbound locking primitives
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 name of the NLNET LABS 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 THE COPYRIGHT
* HOLDER OR CONTRIBUTORS 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.
*/
/**
* \file
* Implementation of locking and threading support.
* A place for locking debug code since most locking functions are macros.
*/
#include "config.h"
#include "util/locks.h"
#include <signal.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
/** block all signals, masks them away. */
void
ub_thread_blocksigs(void)
{
#if defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS) || defined(HAVE_SIGPROCMASK)
# if defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS)
int err;
# endif
sigset_t sigset;
sigfillset(&sigset);
#ifdef HAVE_PTHREAD
if((err=pthread_sigmask(SIG_SETMASK, &sigset, NULL)))
fatal_exit("pthread_sigmask: %s", strerror(err));
#else
# ifdef HAVE_SOLARIS_THREADS
if((err=thr_sigsetmask(SIG_SETMASK, &sigset, NULL)))
fatal_exit("thr_sigsetmask: %s", strerror(err));
# else
/* have nothing, do single process signal mask */
if(sigprocmask(SIG_SETMASK, &sigset, NULL))
fatal_exit("sigprocmask: %s", strerror(errno));
# endif /* HAVE_SOLARIS_THREADS */
#endif /* HAVE_PTHREAD */
#endif /* have signal stuff */
}
/** unblock one signal, so we can catch it */
void ub_thread_sig_unblock(int sig)
{
#if defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS) || defined(HAVE_SIGPROCMASK)
# if defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS)
int err;
# endif
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, sig);
#ifdef HAVE_PTHREAD
if((err=pthread_sigmask(SIG_UNBLOCK, &sigset, NULL)))
fatal_exit("pthread_sigmask: %s", strerror(err));
#else
# ifdef HAVE_SOLARIS_THREADS
if((err=thr_sigsetmask(SIG_UNBLOCK, &sigset, NULL)))
fatal_exit("thr_sigsetmask: %s", strerror(err));
# else
/* have nothing, do single thread case */
if(sigprocmask(SIG_UNBLOCK, &sigset, NULL))
fatal_exit("sigprocmask: %s", strerror(errno));
# endif /* HAVE_SOLARIS_THREADS */
#endif /* HAVE_PTHREAD */
#else
(void)sig;
#endif /* have signal stuff */
}
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS) && !defined(HAVE_WINDOWS_THREADS)
/**
* No threading available: fork a new process.
* This means no shared data structure, and no locking.
* Only the main thread ever returns. Exits on errors.
* @param thr: the location where to store the thread-id.
* @param func: function body of the thread. Return value of func is lost.
* @param arg: user argument to func.
*/
void
ub_thr_fork_create(ub_thread_type* thr, void* (*func)(void*), void* arg)
{
pid_t pid = fork();
switch(pid) {
default: /* main */
*thr = (ub_thread_type)pid;
return;
case 0: /* child */
*thr = (ub_thread_type)getpid();
(void)(*func)(arg);
exit(0);
case -1: /* error */
fatal_exit("could not fork: %s", strerror(errno));
}
}
/**
* There is no threading. Wait for a process to terminate.
* Note that ub_thread_type is defined as pid_t.
* @param thread: the process id to wait for.
*/
void ub_thr_fork_wait(ub_thread_type thread)
{
int status = 0;
if(waitpid((pid_t)thread, &status, 0) == -1)
log_err("waitpid(%d): %s", (int)thread, strerror(errno));
if(status != 0)
log_warn("process %d abnormal exit with status %d",
(int)thread, status);
}
#endif /* !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS) && !defined(HAVE_WINDOWS_THREADS) */
#ifdef HAVE_SOLARIS_THREADS
void* ub_thread_key_get(ub_thread_key_type key)
{
void* ret=NULL;
LOCKRET(thr_getspecific(key, &ret));
return ret;
}
#endif
#ifdef HAVE_WINDOWS_THREADS
/** log a windows GetLastError message */
static void log_win_err(const char* str, DWORD err)
{
LPTSTR buf;
if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, err, 0, (LPTSTR)&buf, 0, NULL) == 0) {
/* could not format error message */
log_err("%s, GetLastError=%d", str, (int)err);
return;
}
log_err("%s, (err=%d): %s", str, (int)err, buf);
LocalFree(buf);
}
void lock_basic_init(lock_basic_type* lock)
{
/* implement own lock, because windows HANDLE as Mutex usage
* uses too many handles and would bog down the whole system. */
(void)InterlockedExchange(lock, 0);
}
void lock_basic_destroy(lock_basic_type* lock)
{
(void)InterlockedExchange(lock, 0);
}
void lock_basic_lock(lock_basic_type* lock)
{
LONG wait = 1; /* wait 1 msec at first */
while(InterlockedExchange(lock, 1)) {
/* if the old value was 1 then if was already locked */
Sleep(wait); /* wait with sleep */
wait *= 2; /* exponential backoff for waiting */
}
/* the old value was 0, but we inserted 1, we locked it! */
}
void lock_basic_unlock(lock_basic_type* lock)
{
/* unlock it by inserting the value of 0. xchg for cache coherency. */
(void)InterlockedExchange(lock, 0);
}
void ub_thread_key_create(ub_thread_key_type* key, void* f)
{
*key = TlsAlloc();
if(*key == TLS_OUT_OF_INDEXES) {
*key = 0;
log_win_err("TlsAlloc Failed(OUT_OF_INDEXES)", GetLastError());
}
else ub_thread_key_set(*key, f);
}
void ub_thread_key_set(ub_thread_key_type key, void* v)
{
if(!TlsSetValue(key, v)) {
log_win_err("TlsSetValue failed", GetLastError());
}
}
void* ub_thread_key_get(ub_thread_key_type key)
{
void* ret = (void*)TlsGetValue(key);
if(ret == NULL && GetLastError() != ERROR_SUCCESS) {
log_win_err("TlsGetValue failed", GetLastError());
}
return ret;
}
void ub_thread_create(ub_thread_type* thr, void* (*func)(void*), void* arg)
{
#ifndef HAVE__BEGINTHREADEX
*thr = CreateThread(NULL, /* default security (no inherit handle) */
0, /* default stack size */
(LPTHREAD_START_ROUTINE)func, arg,
0, /* default flags, run immediately */
NULL); /* do not store thread identifier anywhere */
#else
/* the beginthreadex routine setups for the C lib; aligns stack */
*thr=(ub_thread_type)_beginthreadex(NULL, 0, (void*)func, arg, 0, NULL);
#endif
if(*thr == NULL) {
log_win_err("CreateThread failed", GetLastError());
fatal_exit("thread create failed");
}
}
ub_thread_type ub_thread_self(void)
{
return GetCurrentThread();
}
void ub_thread_join(ub_thread_type thr)
{
DWORD ret = WaitForSingleObject(thr, INFINITE);
if(ret == WAIT_FAILED) {
log_win_err("WaitForSingleObject(Thread):WAIT_FAILED",
GetLastError());
} else if(ret == WAIT_TIMEOUT) {
log_win_err("WaitForSingleObject(Thread):WAIT_TIMEOUT",
GetLastError());
}
/* and close the handle to the thread */
if(!CloseHandle(thr)) {
log_win_err("CloseHandle(Thread) failed", GetLastError());
}
}
#endif /* HAVE_WINDOWS_THREADS */

64
src/util/locks.h Normal file
View File

@ -0,0 +1,64 @@
/**
*
* \file locks.h
* /brief Alternative symbol names for unbound's locks.h
*
*/
/*
* Copyright (c) 2017, NLnet Labs, the getdns team
* 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 LOCKS_H_SYMBOLS
#define LOCKS_H_SYMBOLS
#include "config.h"
#define ub_thread_blocksigs _getdns_ub_thread_blocksigs
#define ub_thread_sig_unblock _getdns_ub_thread_sig_unblock
#define ub_thread_type _getdns_ub_thread_type
#define ub_thr_fork_create _getdns_ub_thr_fork_create
#define ub_thr_fork_wait _getdns_ub_thr_fork_wait
#if defined(HAVE_SOLARIS_THREADS) || defined(HAVE_WINDOWS_THREADS)
#define ub_thread_key_type _getdns_ub_thread_key_type
#define ub_thread_key_create _getdns_ub_thread_key_create
#define ub_thread_key_set _getdns_ub_thread_key_set
#define ub_thread_key_get _getdns_ub_thread_key_get
#endif
#ifdef HAVE_WINDOWS_THREADS
#define lock_basic_type _getdns_lock_basic_type
#define lock_basic_init _getdns_lock_basic_init
#define lock_basic_destroy _getdns_lock_basic_destroy
#define lock_basic_lock _getdns_lock_basic_lock_
#define lock_basic_unlock _getdns_lock_basic_unlock
#define ub_thread_create _getdns_ub_thread_create
#define ub_thread_self _getdns_ub_thread_self
#endif
#include "util/orig-headers/locks.h"
#endif

1032
src/util/lookup3.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,11 @@
/**
*
* /brief dummy prototypes for logging a la unbound
* \file lookup3.h
* /brief Alternative symbol names for unbound's lookup3.h
*
*/
/*
* Copyright (c) 2013, NLnet Labs, Verisign, Inc.
* Copyright (c) 2017, NLnet Labs, the getdns team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -30,22 +30,12 @@
* (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 LOOKUP3_H_SYMBOLS
#define LOOKUP3_H_SYMBOLS
#ifndef UTIL_LOG_H
#define UTIL_LOG_H
#define hashword _getdns_hashword
#define hashlittle _getdns_hashlittle
#define hash_set_raninit _getdns_hash_set_raninit
#include "config.h"
#include "debug.h"
#if defined(SEC_DEBUG) && SEC_DEBUG
#define verbose(x, ...) DEBUG_NL(__VA_ARGS__)
#define log_err(...) DEBUG_NL(__VA_ARGS__)
#else
#define verbose(...)
#define log_err(...)
#include "util/orig-headers/lookup3.h"
#endif
#define log_assert(x)
#endif /* UTIL_LOG_H */

631
src/util/lruhash.c Normal file
View File

@ -0,0 +1,631 @@
/*
* util/storage/lruhash.c - hashtable, hash function, LRU keeping.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 name of the NLNET LABS 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 THE COPYRIGHT
* HOLDER OR CONTRIBUTORS 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.
*/
/**
* \file
*
* This file contains a hashtable with LRU keeping of entries.
*
*/
#include "config.h"
#include "util/storage/lruhash.h"
#include "util/fptr_wlist.h"
void
bin_init(struct lruhash_bin* array, size_t size)
{
size_t i;
#ifdef THREADS_DISABLED
(void)array;
#endif
for(i=0; i<size; i++) {
lock_quick_init(&array[i].lock);
lock_protect(&array[i].lock, &array[i],
sizeof(struct lruhash_bin));
}
}
struct lruhash*
lruhash_create(size_t start_size, size_t maxmem,
lruhash_sizefunc_type sizefunc, lruhash_compfunc_type compfunc,
lruhash_delkeyfunc_type delkeyfunc,
lruhash_deldatafunc_type deldatafunc, void* arg)
{
struct lruhash* table = (struct lruhash*)calloc(1,
sizeof(struct lruhash));
if(!table)
return NULL;
lock_quick_init(&table->lock);
table->sizefunc = sizefunc;
table->compfunc = compfunc;
table->delkeyfunc = delkeyfunc;
table->deldatafunc = deldatafunc;
table->cb_arg = arg;
table->size = start_size;
table->size_mask = (int)(start_size-1);
table->lru_start = NULL;
table->lru_end = NULL;
table->num = 0;
table->space_used = 0;
table->space_max = maxmem;
table->array = calloc(table->size, sizeof(struct lruhash_bin));
if(!table->array) {
lock_quick_destroy(&table->lock);
free(table);
return NULL;
}
bin_init(table->array, table->size);
lock_protect(&table->lock, table, sizeof(*table));
lock_protect(&table->lock, table->array,
table->size*sizeof(struct lruhash_bin));
return table;
}
void
bin_delete(struct lruhash* table, struct lruhash_bin* bin)
{
struct lruhash_entry* p, *np;
void *d;
if(!bin)
return;
lock_quick_destroy(&bin->lock);
p = bin->overflow_list;
bin->overflow_list = NULL;
while(p) {
np = p->overflow_next;
d = p->data;
(*table->delkeyfunc)(p->key, table->cb_arg);
(*table->deldatafunc)(d, table->cb_arg);
p = np;
}
}
void
bin_split(struct lruhash* table, struct lruhash_bin* newa,
int newmask)
{
size_t i;
struct lruhash_entry *p, *np;
struct lruhash_bin* newbin;
/* move entries to new table. Notice that since hash x is mapped to
* bin x & mask, and new mask uses one more bit, so all entries in
* one bin will go into the old bin or bin | newbit */
#ifndef THREADS_DISABLED
int newbit = newmask - table->size_mask;
#endif
/* so, really, this task could also be threaded, per bin. */
/* LRU list is not changed */
for(i=0; i<table->size; i++)
{
lock_quick_lock(&table->array[i].lock);
p = table->array[i].overflow_list;
/* lock both destination bins */
lock_quick_lock(&newa[i].lock);
lock_quick_lock(&newa[newbit|i].lock);
while(p) {
np = p->overflow_next;
/* link into correct new bin */
newbin = &newa[p->hash & newmask];
p->overflow_next = newbin->overflow_list;
newbin->overflow_list = p;
p=np;
}
lock_quick_unlock(&newa[i].lock);
lock_quick_unlock(&newa[newbit|i].lock);
lock_quick_unlock(&table->array[i].lock);
}
}
void
lruhash_delete(struct lruhash* table)
{
size_t i;
if(!table)
return;
/* delete lock on hashtable to force check its OK */
lock_quick_destroy(&table->lock);
for(i=0; i<table->size; i++)
bin_delete(table, &table->array[i]);
free(table->array);
free(table);
}
void
bin_overflow_remove(struct lruhash_bin* bin, struct lruhash_entry* entry)
{
struct lruhash_entry* p = bin->overflow_list;
struct lruhash_entry** prevp = &bin->overflow_list;
while(p) {
if(p == entry) {
*prevp = p->overflow_next;
return;
}
prevp = &p->overflow_next;
p = p->overflow_next;
}
}
void
reclaim_space(struct lruhash* table, struct lruhash_entry** list)
{
struct lruhash_entry* d;
struct lruhash_bin* bin;
log_assert(table);
/* does not delete MRU entry, so table will not be empty. */
while(table->num > 1 && table->space_used > table->space_max) {
/* notice that since we hold the hashtable lock, nobody
can change the lru chain. So it cannot be deleted underneath
us. We still need the hashbin and entry write lock to make
sure we flush all users away from the entry.
which is unlikely, since it is LRU, if someone got a rdlock
it would be moved to front, but to be sure. */
d = table->lru_end;
/* specialised, delete from end of double linked list,
and we know num>1, so there is a previous lru entry. */
log_assert(d && d->lru_prev);
table->lru_end = d->lru_prev;
d->lru_prev->lru_next = NULL;
/* schedule entry for deletion */
bin = &table->array[d->hash & table->size_mask];
table->num --;
lock_quick_lock(&bin->lock);
bin_overflow_remove(bin, d);
d->overflow_next = *list;
*list = d;
lock_rw_wrlock(&d->lock);
table->space_used -= table->sizefunc(d->key, d->data);
if(table->markdelfunc)
(*table->markdelfunc)(d->key);
lock_rw_unlock(&d->lock);
lock_quick_unlock(&bin->lock);
}
}
struct lruhash_entry*
bin_find_entry(struct lruhash* table,
struct lruhash_bin* bin, hashvalue_type hash, void* key)
{
struct lruhash_entry* p = bin->overflow_list;
while(p) {
if(p->hash == hash && table->compfunc(p->key, key) == 0)
return p;
p = p->overflow_next;
}
return NULL;
}
void
table_grow(struct lruhash* table)
{
struct lruhash_bin* newa;
int newmask;
size_t i;
if(table->size_mask == (int)(((size_t)-1)>>1)) {
log_err("hash array malloc: size_t too small");
return;
}
/* try to allocate new array, if not fail */
newa = calloc(table->size*2, sizeof(struct lruhash_bin));
if(!newa) {
log_err("hash grow: malloc failed");
/* continue with smaller array. Though its slower. */
return;
}
bin_init(newa, table->size*2);
newmask = (table->size_mask << 1) | 1;
bin_split(table, newa, newmask);
/* delete the old bins */
lock_unprotect(&table->lock, table->array);
for(i=0; i<table->size; i++) {
lock_quick_destroy(&table->array[i].lock);
}
free(table->array);
table->size *= 2;
table->size_mask = newmask;
table->array = newa;
lock_protect(&table->lock, table->array,
table->size*sizeof(struct lruhash_bin));
return;
}
void
lru_front(struct lruhash* table, struct lruhash_entry* entry)
{
entry->lru_prev = NULL;
entry->lru_next = table->lru_start;
if(!table->lru_start)
table->lru_end = entry;
else table->lru_start->lru_prev = entry;
table->lru_start = entry;
}
void
lru_remove(struct lruhash* table, struct lruhash_entry* entry)
{
if(entry->lru_prev)
entry->lru_prev->lru_next = entry->lru_next;
else table->lru_start = entry->lru_next;
if(entry->lru_next)
entry->lru_next->lru_prev = entry->lru_prev;
else table->lru_end = entry->lru_prev;
}
void
lru_touch(struct lruhash* table, struct lruhash_entry* entry)
{
log_assert(table && entry);
if(entry == table->lru_start)
return; /* nothing to do */
/* remove from current lru position */
lru_remove(table, entry);
/* add at front */
lru_front(table, entry);
}
void
lruhash_insert(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg)
{
struct lruhash_bin* bin;
struct lruhash_entry* found, *reclaimlist=NULL;
size_t need_size;
fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc));
fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc));
fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc));
need_size = table->sizefunc(entry->key, data);
if(cb_arg == NULL) cb_arg = table->cb_arg;
/* find bin */
lock_quick_lock(&table->lock);
bin = &table->array[hash & table->size_mask];
lock_quick_lock(&bin->lock);
/* see if entry exists already */
if(!(found=bin_find_entry(table, bin, hash, entry->key))) {
/* if not: add to bin */
entry->overflow_next = bin->overflow_list;
bin->overflow_list = entry;
lru_front(table, entry);
table->num++;
table->space_used += need_size;
} else {
/* if so: update data - needs a writelock */
table->space_used += need_size -
(*table->sizefunc)(found->key, found->data);
(*table->delkeyfunc)(entry->key, cb_arg);
lru_touch(table, found);
lock_rw_wrlock(&found->lock);
(*table->deldatafunc)(found->data, cb_arg);
found->data = data;
lock_rw_unlock(&found->lock);
}
lock_quick_unlock(&bin->lock);
if(table->space_used > table->space_max)
reclaim_space(table, &reclaimlist);
if(table->num >= table->size)
table_grow(table);
lock_quick_unlock(&table->lock);
/* finish reclaim if any (outside of critical region) */
while(reclaimlist) {
struct lruhash_entry* n = reclaimlist->overflow_next;
void* d = reclaimlist->data;
(*table->delkeyfunc)(reclaimlist->key, cb_arg);
(*table->deldatafunc)(d, cb_arg);
reclaimlist = n;
}
}
struct lruhash_entry*
lruhash_lookup(struct lruhash* table, hashvalue_type hash, void* key, int wr)
{
struct lruhash_entry* entry;
struct lruhash_bin* bin;
fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc));
lock_quick_lock(&table->lock);
bin = &table->array[hash & table->size_mask];
lock_quick_lock(&bin->lock);
if((entry=bin_find_entry(table, bin, hash, key)))
lru_touch(table, entry);
lock_quick_unlock(&table->lock);
if(entry) {
if(wr) { lock_rw_wrlock(&entry->lock); }
else { lock_rw_rdlock(&entry->lock); }
}
lock_quick_unlock(&bin->lock);
return entry;
}
void
lruhash_remove(struct lruhash* table, hashvalue_type hash, void* key)
{
struct lruhash_entry* entry;
struct lruhash_bin* bin;
void *d;
fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc));
fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc));
fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc));
lock_quick_lock(&table->lock);
bin = &table->array[hash & table->size_mask];
lock_quick_lock(&bin->lock);
if((entry=bin_find_entry(table, bin, hash, key))) {
bin_overflow_remove(bin, entry);
lru_remove(table, entry);
} else {
lock_quick_unlock(&table->lock);
lock_quick_unlock(&bin->lock);
return;
}
table->num--;
table->space_used -= (*table->sizefunc)(entry->key, entry->data);
lock_quick_unlock(&table->lock);
lock_rw_wrlock(&entry->lock);
if(table->markdelfunc)
(*table->markdelfunc)(entry->key);
lock_rw_unlock(&entry->lock);
lock_quick_unlock(&bin->lock);
/* finish removal */
d = entry->data;
(*table->delkeyfunc)(entry->key, table->cb_arg);
(*table->deldatafunc)(d, table->cb_arg);
}
/** clear bin, respecting locks, does not do space, LRU */
static void
bin_clear(struct lruhash* table, struct lruhash_bin* bin)
{
struct lruhash_entry* p, *np;
void *d;
lock_quick_lock(&bin->lock);
p = bin->overflow_list;
while(p) {
lock_rw_wrlock(&p->lock);
np = p->overflow_next;
d = p->data;
if(table->markdelfunc)
(*table->markdelfunc)(p->key);
lock_rw_unlock(&p->lock);
(*table->delkeyfunc)(p->key, table->cb_arg);
(*table->deldatafunc)(d, table->cb_arg);
p = np;
}
bin->overflow_list = NULL;
lock_quick_unlock(&bin->lock);
}
void
lruhash_clear(struct lruhash* table)
{
size_t i;
if(!table)
return;
fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc));
lock_quick_lock(&table->lock);
for(i=0; i<table->size; i++) {
bin_clear(table, &table->array[i]);
}
table->lru_start = NULL;
table->lru_end = NULL;
table->num = 0;
table->space_used = 0;
lock_quick_unlock(&table->lock);
}
void
lruhash_status(struct lruhash* table, const char* id, int extended)
{
lock_quick_lock(&table->lock);
log_info("%s: %u entries, memory %u / %u",
id, (unsigned)table->num, (unsigned)table->space_used,
(unsigned)table->space_max);
log_info(" itemsize %u, array %u, mask %d",
(unsigned)(table->num? table->space_used/table->num : 0),
(unsigned)table->size, table->size_mask);
if(extended) {
size_t i;
int min=(int)table->size*2, max=-2;
for(i=0; i<table->size; i++) {
int here = 0;
struct lruhash_entry *en;
lock_quick_lock(&table->array[i].lock);
en = table->array[i].overflow_list;
while(en) {
here ++;
en = en->overflow_next;
}
lock_quick_unlock(&table->array[i].lock);
if(extended >= 2)
log_info("bin[%d] %d", (int)i, here);
if(here > max) max = here;
if(here < min) min = here;
}
log_info(" bin min %d, avg %.2lf, max %d", min,
(double)table->num/(double)table->size, max);
}
lock_quick_unlock(&table->lock);
}
size_t
lruhash_get_mem(struct lruhash* table)
{
size_t s;
lock_quick_lock(&table->lock);
s = sizeof(struct lruhash) + table->space_used;
#ifdef USE_THREAD_DEBUG
if(table->size != 0) {
size_t i;
for(i=0; i<table->size; i++)
s += sizeof(struct lruhash_bin) +
lock_get_mem(&table->array[i].lock);
}
#else /* no THREAD_DEBUG */
if(table->size != 0)
s += (table->size)*(sizeof(struct lruhash_bin) +
lock_get_mem(&table->array[0].lock));
#endif
lock_quick_unlock(&table->lock);
s += lock_get_mem(&table->lock);
return s;
}
void
lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md)
{
lock_quick_lock(&table->lock);
table->markdelfunc = md;
lock_quick_unlock(&table->lock);
}
void
lruhash_traverse(struct lruhash* h, int wr,
void (*func)(struct lruhash_entry*, void*), void* arg)
{
size_t i;
struct lruhash_entry* e;
lock_quick_lock(&h->lock);
for(i=0; i<h->size; i++) {
lock_quick_lock(&h->array[i].lock);
for(e = h->array[i].overflow_list; e; e = e->overflow_next) {
if(wr) {
lock_rw_wrlock(&e->lock);
} else {
lock_rw_rdlock(&e->lock);
}
(*func)(e, arg);
lock_rw_unlock(&e->lock);
}
lock_quick_unlock(&h->array[i].lock);
}
lock_quick_unlock(&h->lock);
}
/*
* Demote: the opposite of touch, move an entry to the bottom
* of the LRU pile.
*/
void
lru_demote(struct lruhash* table, struct lruhash_entry* entry)
{
log_assert(table && entry);
if (entry == table->lru_end)
return; /* nothing to do */
/* remove from current lru position */
lru_remove(table, entry);
/* add at end */
entry->lru_next = NULL;
entry->lru_prev = table->lru_end;
if (table->lru_end == NULL)
{
table->lru_start = entry;
}
else
{
table->lru_end->lru_next = entry;
}
table->lru_end = entry;
}
struct lruhash_entry*
lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg)
{
struct lruhash_bin* bin;
struct lruhash_entry* found, *reclaimlist = NULL;
size_t need_size;
fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc));
fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
fptr_ok(fptr_whitelist_hash_compfunc(table->compfunc));
fptr_ok(fptr_whitelist_hash_markdelfunc(table->markdelfunc));
need_size = table->sizefunc(entry->key, data);
if (cb_arg == NULL) cb_arg = table->cb_arg;
/* find bin */
lock_quick_lock(&table->lock);
bin = &table->array[hash & table->size_mask];
lock_quick_lock(&bin->lock);
/* see if entry exists already */
if ((found = bin_find_entry(table, bin, hash, entry->key)) != NULL) {
/* if so: keep the existing data - acquire a writelock */
lock_rw_wrlock(&found->lock);
}
else
{
/* if not: add to bin */
entry->overflow_next = bin->overflow_list;
bin->overflow_list = entry;
lru_front(table, entry);
table->num++;
table->space_used += need_size;
/* return the entry that was presented, and lock it */
found = entry;
lock_rw_wrlock(&found->lock);
}
lock_quick_unlock(&bin->lock);
if (table->space_used > table->space_max)
reclaim_space(table, &reclaimlist);
if (table->num >= table->size)
table_grow(table);
lock_quick_unlock(&table->lock);
/* finish reclaim if any (outside of critical region) */
while (reclaimlist) {
struct lruhash_entry* n = reclaimlist->overflow_next;
void* d = reclaimlist->data;
(*table->delkeyfunc)(reclaimlist->key, cb_arg);
(*table->deldatafunc)(d, cb_arg);
reclaimlist = n;
}
/* return the entry that was selected */
return found;
}

71
src/util/lruhash.h Normal file
View File

@ -0,0 +1,71 @@
/**
*
* \file lruhash.h
* /brief Alternative symbol names for unbound's lruhash.h
*
*/
/*
* Copyright (c) 2017, NLnet Labs, the getdns team
* 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 LRUHASH_H_SYMBOLS
#define LRUHASH_H_SYMBOLS
#define lruhash _getdns_lruhash
#define lruhash_bin _getdns_lruhash_bin
#define lruhash_entry _getdns_lruhash_entry
#define hashvalue_type _getdns_hashvalue_type
#define lruhash_sizefunc_type _getdns_lruhash_sizefunc_type
#define lruhash_compfunc_type _getdns_lruhash_compfunc_type
#define lruhash_delkeyfunc_type _getdns_lruhash_delkeyfunc_type
#define lruhash_deldatafunc_type _getdns_lruhash_deldatafunc_type
#define lruhash_markdelfunc_type _getdns_lruhash_markdelfunc_type
#define lruhash_create _getdns_lruhash_create
#define lruhash_delete _getdns_lruhash_delete
#define lruhash_clear _getdns_lruhash_clear
#define lruhash_insert _getdns_lruhash_insert
#define lruhash_lookup _getdns_lruhash_lookup
#define lru_touch _getdns_lru_touch
#define lruhash_setmarkdel _getdns_lruhash_setmarkdel
#define lru_demote _getdns_lru_demote
#define lruhash_insert_or_retrieve _getdns_lruhash_insert_or_retrieve
#define lruhash_remove _getdns_lruhash_remove
#define bin_init _getdns_bin_init
#define bin_delete _getdns_bin_delete
#define bin_find_entry _getdns_bin_find_entry
#define bin_overflow_remove _getdns_bin_overflow_remove
#define bin_split _getdns_bin_split
#define reclaim_space _getdns_reclaim_space
#define table_grow _getdns_table_grow
#define lru_front _getdns_lru_front
#define lru_remove _getdns_lru_remove
#define lruhash_status _getdns_lruhash_status
#define lruhash_get_mem _getdns_lruhash_get_mem
#define lruhash_traverse _getdns_lruhash_traverse
#include "util/orig-headers/lruhash.h"
#endif

View File

@ -0,0 +1,313 @@
/**
* util/locks.h - unbound locking primitives
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 name of the NLNET LABS 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 THE COPYRIGHT
* HOLDER OR CONTRIBUTORS 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 UTIL_LOCKS_H
#define UTIL_LOCKS_H
/**
* \file
* Locking primitives.
* If pthreads is available, these are used.
* If no locking exists, they do nothing.
*
* The idea is to have different sorts of locks for different tasks.
* This allows the locking code to be ported more easily.
*
* Types of locks that are supported.
* o lock_rw: lock that has many readers and one writer (to a data entry).
* o lock_basic: simple mutex. Blocking, one person has access only.
* This lock is meant for non performance sensitive uses.
* o lock_quick: speed lock. For performance sensitive locking of critical
* sections. Could be implemented by a mutex or a spinlock.
*
* Also thread creation and deletion functions are defined here.
*/
/* if you define your own LOCKRET before including locks.h, you can get most
* locking functions without the dependency on log_err. */
#ifndef LOCKRET
#include "util/log.h"
/**
* The following macro is used to check the return value of the
* pthread calls. They return 0 on success and an errno on error.
* The errno is logged to the logfile with a descriptive comment.
*/
#define LOCKRET(func) do {\
int lockret_err; \
if( (lockret_err=(func)) != 0) \
log_err("%s at %d could not " #func ": %s", \
__FILE__, __LINE__, strerror(lockret_err)); \
} while(0)
#endif
/** DEBUG: use thread debug whenever possible */
#if defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_SPINLOCK_T) && defined(ENABLE_LOCK_CHECKS)
# define USE_THREAD_DEBUG
#endif
#ifdef USE_THREAD_DEBUG
/******************* THREAD DEBUG ************************/
/* (some) checking; to detect races and deadlocks. */
#include "testcode/checklocks.h"
#else /* USE_THREAD_DEBUG */
#define lock_protect(lock, area, size) /* nop */
#define lock_unprotect(lock, area) /* nop */
#define lock_get_mem(lock) (0) /* nothing */
#define checklock_start() /* nop */
#define checklock_stop() /* nop */
#ifdef HAVE_PTHREAD
#include <pthread.h>
/******************* PTHREAD ************************/
/** use pthread mutex for basic lock */
typedef pthread_mutex_t lock_basic_type;
/** small front for pthread init func, NULL is default attrs. */
#define lock_basic_init(lock) LOCKRET(pthread_mutex_init(lock, NULL))
#define lock_basic_destroy(lock) LOCKRET(pthread_mutex_destroy(lock))
#define lock_basic_lock(lock) LOCKRET(pthread_mutex_lock(lock))
#define lock_basic_unlock(lock) LOCKRET(pthread_mutex_unlock(lock))
#ifndef HAVE_PTHREAD_RWLOCK_T
/** in case rwlocks are not supported, use a mutex. */
typedef pthread_mutex_t lock_rw_type;
#define lock_rw_init(lock) LOCKRET(pthread_mutex_init(lock, NULL))
#define lock_rw_destroy(lock) LOCKRET(pthread_mutex_destroy(lock))
#define lock_rw_rdlock(lock) LOCKRET(pthread_mutex_lock(lock))
#define lock_rw_wrlock(lock) LOCKRET(pthread_mutex_lock(lock))
#define lock_rw_unlock(lock) LOCKRET(pthread_mutex_unlock(lock))
#else /* HAVE_PTHREAD_RWLOCK_T */
/** we use the pthread rwlock */
typedef pthread_rwlock_t lock_rw_type;
/** small front for pthread init func, NULL is default attrs. */
#define lock_rw_init(lock) LOCKRET(pthread_rwlock_init(lock, NULL))
#define lock_rw_destroy(lock) LOCKRET(pthread_rwlock_destroy(lock))
#define lock_rw_rdlock(lock) LOCKRET(pthread_rwlock_rdlock(lock))
#define lock_rw_wrlock(lock) LOCKRET(pthread_rwlock_wrlock(lock))
#define lock_rw_unlock(lock) LOCKRET(pthread_rwlock_unlock(lock))
#endif /* HAVE_PTHREAD_RWLOCK_T */
#ifndef HAVE_PTHREAD_SPINLOCK_T
/** in case spinlocks are not supported, use a mutex. */
typedef pthread_mutex_t lock_quick_type;
/** small front for pthread init func, NULL is default attrs. */
#define lock_quick_init(lock) LOCKRET(pthread_mutex_init(lock, NULL))
#define lock_quick_destroy(lock) LOCKRET(pthread_mutex_destroy(lock))
#define lock_quick_lock(lock) LOCKRET(pthread_mutex_lock(lock))
#define lock_quick_unlock(lock) LOCKRET(pthread_mutex_unlock(lock))
#else /* HAVE_PTHREAD_SPINLOCK_T */
/** use pthread spinlock for the quick lock */
typedef pthread_spinlock_t lock_quick_type;
/**
* allocate process private since this is available whether
* Thread Process-Shared Synchronization is supported or not.
* This means only threads inside this process may access the lock.
* (not threads from another process that shares memory).
* spinlocks are not supported on all pthread platforms.
*/
#define lock_quick_init(lock) LOCKRET(pthread_spin_init(lock, PTHREAD_PROCESS_PRIVATE))
#define lock_quick_destroy(lock) LOCKRET(pthread_spin_destroy(lock))
#define lock_quick_lock(lock) LOCKRET(pthread_spin_lock(lock))
#define lock_quick_unlock(lock) LOCKRET(pthread_spin_unlock(lock))
#endif /* HAVE SPINLOCK */
/** Thread creation */
typedef pthread_t ub_thread_type;
/** On alpine linux default thread stack size is 80 Kb. See
http://wiki.musl-libc.org/wiki/Functional_differences_from_glibc#Thread_stack_size
This is not enough and cause segfault. Other linux distros have 2 Mb at least.
Wrapper for set up thread stack size */
#define PTHREADSTACKSIZE 2*1024*1024
#define PTHREADCREATE(thr, stackrequired, func, arg) do {\
pthread_attr_t attr; \
size_t stacksize; \
LOCKRET(pthread_attr_init(&attr)); \
LOCKRET(pthread_attr_getstacksize(&attr, &stacksize)); \
if (stacksize < stackrequired) { \
LOCKRET(pthread_attr_setstacksize(&attr, stackrequired)); \
LOCKRET(pthread_create(thr, &attr, func, arg)); \
LOCKRET(pthread_attr_getstacksize(&attr, &stacksize)); \
verbose(VERB_ALGO, "Thread stack size set to %u", (unsigned)stacksize); \
} else {LOCKRET(pthread_create(thr, NULL, func, arg));} \
} while(0)
/** Use wrapper for set thread stack size on attributes. */
#define ub_thread_create(thr, func, arg) PTHREADCREATE(thr, PTHREADSTACKSIZE, func, arg)
/** get self id. */
#define ub_thread_self() pthread_self()
/** wait for another thread to terminate */
#define ub_thread_join(thread) LOCKRET(pthread_join(thread, NULL))
typedef pthread_key_t ub_thread_key_type;
#define ub_thread_key_create(key, f) LOCKRET(pthread_key_create(key, f))
#define ub_thread_key_set(key, v) LOCKRET(pthread_setspecific(key, v))
#define ub_thread_key_get(key) pthread_getspecific(key)
#else /* we do not HAVE_PTHREAD */
#ifdef HAVE_SOLARIS_THREADS
/******************* SOLARIS THREADS ************************/
#include <synch.h>
#include <thread.h>
typedef rwlock_t lock_rw_type;
#define lock_rw_init(lock) LOCKRET(rwlock_init(lock, USYNC_THREAD, NULL))
#define lock_rw_destroy(lock) LOCKRET(rwlock_destroy(lock))
#define lock_rw_rdlock(lock) LOCKRET(rw_rdlock(lock))
#define lock_rw_wrlock(lock) LOCKRET(rw_wrlock(lock))
#define lock_rw_unlock(lock) LOCKRET(rw_unlock(lock))
/** use basic mutex */
typedef mutex_t lock_basic_type;
#define lock_basic_init(lock) LOCKRET(mutex_init(lock, USYNC_THREAD, NULL))
#define lock_basic_destroy(lock) LOCKRET(mutex_destroy(lock))
#define lock_basic_lock(lock) LOCKRET(mutex_lock(lock))
#define lock_basic_unlock(lock) LOCKRET(mutex_unlock(lock))
/** No spinlocks in solaris threads API. Use a mutex. */
typedef mutex_t lock_quick_type;
#define lock_quick_init(lock) LOCKRET(mutex_init(lock, USYNC_THREAD, NULL))
#define lock_quick_destroy(lock) LOCKRET(mutex_destroy(lock))
#define lock_quick_lock(lock) LOCKRET(mutex_lock(lock))
#define lock_quick_unlock(lock) LOCKRET(mutex_unlock(lock))
/** Thread creation, create a default thread. */
typedef thread_t ub_thread_type;
#define ub_thread_create(thr, func, arg) LOCKRET(thr_create(NULL, NULL, func, arg, NULL, thr))
#define ub_thread_self() thr_self()
#define ub_thread_join(thread) LOCKRET(thr_join(thread, NULL, NULL))
typedef thread_key_t ub_thread_key_type;
#define ub_thread_key_create(key, f) LOCKRET(thr_keycreate(key, f))
#define ub_thread_key_set(key, v) LOCKRET(thr_setspecific(key, v))
void* ub_thread_key_get(ub_thread_key_type key);
#else /* we do not HAVE_SOLARIS_THREADS and no PTHREADS */
/******************* WINDOWS THREADS ************************/
#ifdef HAVE_WINDOWS_THREADS
#include <windows.h>
/* Use a mutex */
typedef LONG lock_rw_type;
#define lock_rw_init(lock) lock_basic_init(lock)
#define lock_rw_destroy(lock) lock_basic_destroy(lock)
#define lock_rw_rdlock(lock) lock_basic_lock(lock)
#define lock_rw_wrlock(lock) lock_basic_lock(lock)
#define lock_rw_unlock(lock) lock_basic_unlock(lock)
/** the basic lock is a mutex, implemented opaquely, for error handling. */
typedef LONG lock_basic_type;
void lock_basic_init(lock_basic_type* lock);
void lock_basic_destroy(lock_basic_type* lock);
void lock_basic_lock(lock_basic_type* lock);
void lock_basic_unlock(lock_basic_type* lock);
/** on windows no spinlock, use mutex too. */
typedef LONG lock_quick_type;
#define lock_quick_init(lock) lock_basic_init(lock)
#define lock_quick_destroy(lock) lock_basic_destroy(lock)
#define lock_quick_lock(lock) lock_basic_lock(lock)
#define lock_quick_unlock(lock) lock_basic_unlock(lock)
/** Thread creation, create a default thread. */
typedef HANDLE ub_thread_type;
void ub_thread_create(ub_thread_type* thr, void* (*func)(void*), void* arg);
ub_thread_type ub_thread_self(void);
void ub_thread_join(ub_thread_type thr);
typedef DWORD ub_thread_key_type;
void ub_thread_key_create(ub_thread_key_type* key, void* f);
void ub_thread_key_set(ub_thread_key_type key, void* v);
void* ub_thread_key_get(ub_thread_key_type key);
#else /* we do not HAVE_SOLARIS_THREADS, PTHREADS or WINDOWS_THREADS */
/******************* NO THREADS ************************/
#define THREADS_DISABLED 1
/** In case there is no thread support, define locks to do nothing */
typedef int lock_rw_type;
#define lock_rw_init(lock) /* nop */
#define lock_rw_destroy(lock) /* nop */
#define lock_rw_rdlock(lock) /* nop */
#define lock_rw_wrlock(lock) /* nop */
#define lock_rw_unlock(lock) /* nop */
/** define locks to do nothing */
typedef int lock_basic_type;
#define lock_basic_init(lock) /* nop */
#define lock_basic_destroy(lock) /* nop */
#define lock_basic_lock(lock) /* nop */
#define lock_basic_unlock(lock) /* nop */
/** define locks to do nothing */
typedef int lock_quick_type;
#define lock_quick_init(lock) /* nop */
#define lock_quick_destroy(lock) /* nop */
#define lock_quick_lock(lock) /* nop */
#define lock_quick_unlock(lock) /* nop */
/** Thread creation, threads do not exist */
typedef pid_t ub_thread_type;
/** ub_thread_create is simulated with fork (extremely heavy threads,
* with no shared memory). */
#define ub_thread_create(thr, func, arg) \
ub_thr_fork_create(thr, func, arg)
#define ub_thread_self() getpid()
#define ub_thread_join(thread) ub_thr_fork_wait(thread)
void ub_thr_fork_wait(ub_thread_type thread);
void ub_thr_fork_create(ub_thread_type* thr, void* (*func)(void*), void* arg);
typedef void* ub_thread_key_type;
#define ub_thread_key_create(key, f) (*(key)) = NULL
#define ub_thread_key_set(key, v) (key) = (v)
#define ub_thread_key_get(key) (key)
#endif /* HAVE_WINDOWS_THREADS */
#endif /* HAVE_SOLARIS_THREADS */
#endif /* HAVE_PTHREAD */
#endif /* USE_THREAD_DEBUG */
/**
* Block all signals for this thread.
* fatal exit on error.
*/
void ub_thread_blocksigs(void);
/**
* unblock one signal for this thread.
*/
void ub_thread_sig_unblock(int sig);
#endif /* UTIL_LOCKS_H */

View File

@ -0,0 +1,71 @@
/*
* util/storage/lookup3.h - header file for hashing functions.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 name of the NLNET LABS 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 THE COPYRIGHT
* HOLDER OR CONTRIBUTORS 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.
*/
/**
* \file
*
* This file contains header definitions for the hash functions we use.
* The hash functions are public domain (see lookup3.c).
*/
#ifndef UTIL_STORAGE_LOOKUP3_H
#define UTIL_STORAGE_LOOKUP3_H
/**
* Hash key made of 4byte chunks.
* @param k: the key, an array of uint32_t values
* @param length: the length of the key, in uint32_ts
* @param initval: the previous hash, or an arbitrary value
* @return: hash value.
*/
uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval);
/**
* Hash key data.
* @param k: the key, array of uint8_t
* @param length: the length of the key, in uint8_ts
* @param initval: the previous hash, or an arbitrary value
* @return: hash value.
*/
uint32_t hashlittle(const void *k, size_t length, uint32_t initval);
/**
* Set the randomisation initial value, set this before threads start,
* and before hashing stuff (because it changes subsequent results).
* @param v: value
*/
void hash_set_raninit(uint32_t v);
#endif /* UTIL_STORAGE_LOOKUP3_H */

View File

@ -0,0 +1,446 @@
/*
* util/storage/lruhash.h - hashtable, hash function, LRU keeping.
*
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 name of the NLNET LABS 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 THE COPYRIGHT
* HOLDER OR CONTRIBUTORS 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.
*/
/**
* \file
*
* This file contains a hashtable with LRU keeping of entries.
*
* The hash table keeps a maximum memory size. Old entries are removed
* to make space for new entries.
*
* The locking strategy is as follows:
* o since (almost) every read also implies a LRU update, the
* hashtable lock is a spinlock, not rwlock.
* o the idea is to move every thread through the hash lock quickly,
* so that the next thread can access the lookup table.
* o User performs hash function.
*
* For read:
* o lock hashtable.
* o lookup hash bin.
* o lock hash bin.
* o find entry (if failed, unlock hash, unl bin, exit).
* o swizzle pointers for LRU update.
* o unlock hashtable.
* o lock entry (rwlock).
* o unlock hash bin.
* o work on entry.
* o unlock entry.
*
* To update an entry, gain writelock and change the entry.
* (the entry must keep the same hashvalue, so a data update.)
* (you cannot upgrade a readlock to a writelock, because the item may
* be deleted, it would cause race conditions. So instead, unlock and
* relookup it in the hashtable.)
*
* To delete an entry:
* o unlock the entry if you hold the lock already.
* o lock hashtable.
* o lookup hash bin.
* o lock hash bin.
* o find entry (if failed, unlock hash, unl bin, exit).
* o remove entry from hashtable bin overflow chain.
* o unlock hashtable.
* o lock entry (writelock).
* o unlock hash bin.
* o unlock entry (nobody else should be waiting for this lock,
* since you removed it from hashtable, and you got writelock while
* holding the hashbinlock so you are the only one.)
* Note you are only allowed to obtain a lock while holding hashbinlock.
* o delete entry.
*
* The above sequence is:
* o race free, works with read, write and delete.
* o but has a queue, imagine someone needing a writelock on an item.
* but there are still readlocks. The writelocker waits, but holds
* the hashbinlock. The next thread that comes in and needs the same
* hashbin will wait for the lock while holding the hashtable lock.
* thus halting the entire system on hashtable.
* This is because of the delete protection.
* Readlocks will be easier on the rwlock on entries.
* While the writer is holding writelock, similar problems happen with
* a reader or writer needing the same item.
* the scenario requires more than three threads.
* o so the queue length is 3 threads in a bad situation. The fourth is
* unable to use the hashtable.
*
* If you need to acquire locks on multiple items from the hashtable.
* o you MUST release all locks on items from the hashtable before
* doing the next lookup/insert/delete/whatever.
* o To acquire multiple items you should use a special routine that
* obtains the locks on those multiple items in one go.
*/
#ifndef UTIL_STORAGE_LRUHASH_H
#define UTIL_STORAGE_LRUHASH_H
#include "util/locks.h"
struct lruhash_bin;
struct lruhash_entry;
/** default start size for hash arrays */
#define HASH_DEFAULT_STARTARRAY 1024 /* entries in array */
/** default max memory for hash arrays */
#define HASH_DEFAULT_MAXMEM 4*1024*1024 /* bytes */
/** the type of a hash value */
typedef uint32_t hashvalue_type;
/**
* Type of function that calculates the size of an entry.
* Result must include the size of struct lruhash_entry.
* Keys that are identical must also calculate to the same size.
* size = func(key, data).
*/
typedef size_t (*lruhash_sizefunc_type)(void*, void*);
/** type of function that compares two keys. return 0 if equal. */
typedef int (*lruhash_compfunc_type)(void*, void*);
/** old keys are deleted.
* The RRset type has to revoke its ID number, markdel() is used first.
* This function is called: func(key, userarg) */
typedef void (*lruhash_delkeyfunc_type)(void*, void*);
/** old data is deleted. This function is called: func(data, userarg). */
typedef void (*lruhash_deldatafunc_type)(void*, void*);
/** mark a key as pending to be deleted (and not to be used by anyone).
* called: func(key) */
typedef void (*lruhash_markdelfunc_type)(void*);
/**
* Hash table that keeps LRU list of entries.
*/
struct lruhash {
/** lock for exclusive access, to the lookup array */
lock_quick_type lock;
/** the size function for entries in this table */
lruhash_sizefunc_type sizefunc;
/** the compare function for entries in this table. */
lruhash_compfunc_type compfunc;
/** how to delete keys. */
lruhash_delkeyfunc_type delkeyfunc;
/** how to delete data. */
lruhash_deldatafunc_type deldatafunc;
/** how to mark a key pending deletion */
lruhash_markdelfunc_type markdelfunc;
/** user argument for user functions */
void* cb_arg;
/** the size of the lookup array */
size_t size;
/** size bitmask - since size is a power of 2 */
int size_mask;
/** lookup array of bins */
struct lruhash_bin* array;
/** the lru list, start and end, noncyclical double linked list. */
struct lruhash_entry* lru_start;
/** lru list end item (least recently used) */
struct lruhash_entry* lru_end;
/** the number of entries in the hash table. */
size_t num;
/** the amount of space used, roughly the number of bytes in use. */
size_t space_used;
/** the amount of space the hash table is maximally allowed to use. */
size_t space_max;
};
/**
* A single bin with a linked list of entries in it.
*/
struct lruhash_bin {
/**
* Lock for exclusive access to the linked list
* This lock makes deletion of items safe in this overflow list.
*/
lock_quick_type lock;
/** linked list of overflow entries */
struct lruhash_entry* overflow_list;
};
/**
* An entry into the hash table.
* To change overflow_next you need to hold the bin lock.
* To change the lru items you need to hold the hashtable lock.
* This structure is designed as part of key struct. And key pointer helps
* to get the surrounding structure. Data should be allocated on its own.
*/
struct lruhash_entry {
/**
* rwlock for access to the contents of the entry
* Note that it does _not_ cover the lru_ and overflow_ ptrs.
* Even with a writelock, you cannot change hash and key.
* You need to delete it to change hash or key.
*/
lock_rw_type lock;
/** next entry in overflow chain. Covered by hashlock and binlock. */
struct lruhash_entry* overflow_next;
/** next entry in lru chain. covered by hashlock. */
struct lruhash_entry* lru_next;
/** prev entry in lru chain. covered by hashlock. */
struct lruhash_entry* lru_prev;
/** hash value of the key. It may not change, until entry deleted. */
hashvalue_type hash;
/** key */
void* key;
/** data */
void* data;
};
/**
* Create new hash table.
* @param start_size: size of hashtable array at start, must be power of 2.
* @param maxmem: maximum amount of memory this table is allowed to use.
* @param sizefunc: calculates memory usage of entries.
* @param compfunc: compares entries, 0 on equality.
* @param delkeyfunc: deletes key.
* Calling both delkey and deldata will also free the struct lruhash_entry.
* Make it part of the key structure and delete it in delkeyfunc.
* @param deldatafunc: deletes data.
* @param arg: user argument that is passed to user function calls.
* @return: new hash table or NULL on malloc failure.
*/
struct lruhash* lruhash_create(size_t start_size, size_t maxmem,
lruhash_sizefunc_type sizefunc, lruhash_compfunc_type compfunc,
lruhash_delkeyfunc_type delkeyfunc,
lruhash_deldatafunc_type deldatafunc, void* arg);
/**
* Delete hash table. Entries are all deleted.
* @param table: to delete.
*/
void lruhash_delete(struct lruhash* table);
/**
* Clear hash table. Entries are all deleted, while locking them before
* doing so. At end the table is empty.
* @param table: to make empty.
*/
void lruhash_clear(struct lruhash* table);
/**
* Insert a new element into the hashtable.
* If key is already present data pointer in that entry is updated.
* The space calculation function is called with the key, data.
* If necessary the least recently used entries are deleted to make space.
* If necessary the hash array is grown up.
*
* @param table: hash table.
* @param hash: hash value. User calculates the hash.
* @param entry: identifies the entry.
* If key already present, this entry->key is deleted immediately.
* But entry->data is set to NULL before deletion, and put into
* the existing entry. The data is then freed.
* @param data: the data.
* @param cb_override: if not null overrides the cb_arg for the deletefunc.
*/
void lruhash_insert(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_override);
/**
* Lookup an entry in the hashtable.
* At the end of the function you hold a (read/write)lock on the entry.
* The LRU is updated for the entry (if found).
* @param table: hash table.
* @param hash: hash of key.
* @param key: what to look for, compared against entries in overflow chain.
* the hash value must be set, and must work with compare function.
* @param wr: set to true if you desire a writelock on the entry.
* with a writelock you can update the data part.
* @return: pointer to the entry or NULL. The entry is locked.
* The user must unlock the entry when done.
*/
struct lruhash_entry* lruhash_lookup(struct lruhash* table,
hashvalue_type hash, void* key, int wr);
/**
* Touch entry, so it becomes the most recently used in the LRU list.
* Caller must hold hash table lock. The entry must be inserted already.
* @param table: hash table.
* @param entry: entry to make first in LRU.
*/
void lru_touch(struct lruhash* table, struct lruhash_entry* entry);
/**
* Set the markdelfunction (or NULL)
*/
void lruhash_setmarkdel(struct lruhash* table, lruhash_markdelfunc_type md);
/************************* getdns functions ************************/
/*** these are used by getdns only and not by unbound. ***/
/**
* Demote entry, so it becomes the least recently used in the LRU list.
* Caller must hold hash table lock. The entry must be inserted already.
* @param table: hash table.
* @param entry: entry to make last in LRU.
*/
void lru_demote(struct lruhash* table, struct lruhash_entry* entry);
/**
* Insert a new element into the hashtable, or retrieve the corresponding
* element of it exits.
*
* If key is already present data pointer in that entry is kept.
* If it is not present, a new entry is created. In that case,
* the space calculation function is called with the key, data.
* If necessary the least recently used entries are deleted to make space.
* If necessary the hash array is grown up.
*
* @param table: hash table.
* @param hash: hash value. User calculates the hash.
* @param entry: identifies the entry.
* @param data: the data.
* @param cb_override: if not null overrides the cb_arg for the deletefunc.
* @return: pointer to the existing entry if the key was already present,
* or to the entry argument if it was not.
*/
struct lruhash_entry* lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_entry* entry, void* data, void* cb_arg);
/************************* Internal functions ************************/
/*** these are only exposed for unit tests. ***/
/**
* Remove entry from hashtable. Does nothing if not found in hashtable.
* Delfunc is called for the entry.
* @param table: hash table.
* @param hash: hash of key.
* @param key: what to look for.
*/
void lruhash_remove(struct lruhash* table, hashvalue_type hash, void* key);
/** init the hash bins for the table */
void bin_init(struct lruhash_bin* array, size_t size);
/** delete the hash bin and entries inside it */
void bin_delete(struct lruhash* table, struct lruhash_bin* bin);
/**
* Find entry in hash bin. You must have locked the bin.
* @param table: hash table with function pointers.
* @param bin: hash bin to look into.
* @param hash: hash value to look for.
* @param key: key to look for.
* @return: the entry or NULL if not found.
*/
struct lruhash_entry* bin_find_entry(struct lruhash* table,
struct lruhash_bin* bin, hashvalue_type hash, void* key);
/**
* Remove entry from bin overflow chain.
* You must have locked the bin.
* @param bin: hash bin to look into.
* @param entry: entry ptr that needs removal.
*/
void bin_overflow_remove(struct lruhash_bin* bin,
struct lruhash_entry* entry);
/**
* Split hash bin into two new ones. Based on increased size_mask.
* Caller must hold hash table lock.
* At the end the routine acquires all hashbin locks (in the old array).
* This makes it wait for other threads to finish with the bins.
* So the bins are ready to be deleted after this function.
* @param table: hash table with function pointers.
* @param newa: new increased array.
* @param newmask: new lookup mask.
*/
void bin_split(struct lruhash* table, struct lruhash_bin* newa,
int newmask);
/**
* Try to make space available by deleting old entries.
* Assumes that the lock on the hashtable is being held by caller.
* Caller must not hold bin locks.
* @param table: hash table.
* @param list: list of entries that are to be deleted later.
* Entries have been removed from the hash table and writelock is held.
*/
void reclaim_space(struct lruhash* table, struct lruhash_entry** list);
/**
* Grow the table lookup array. Becomes twice as large.
* Caller must hold the hash table lock. Must not hold any bin locks.
* Tries to grow, on malloc failure, nothing happened.
* @param table: hash table.
*/
void table_grow(struct lruhash* table);
/**
* Put entry at front of lru. entry must be unlinked from lru.
* Caller must hold hash table lock.
* @param table: hash table with lru head and tail.
* @param entry: entry to make most recently used.
*/
void lru_front(struct lruhash* table, struct lruhash_entry* entry);
/**
* Remove entry from lru list.
* Caller must hold hash table lock.
* @param table: hash table with lru head and tail.
* @param entry: entry to remove from lru.
*/
void lru_remove(struct lruhash* table, struct lruhash_entry* entry);
/**
* Output debug info to the log as to state of the hash table.
* @param table: hash table.
* @param id: string printed with table to identify the hash table.
* @param extended: set to true to print statistics on overflow bin lengths.
*/
void lruhash_status(struct lruhash* table, const char* id, int extended);
/**
* Get memory in use now by the lruhash table.
* @param table: hash table. Will be locked before use. And unlocked after.
* @return size in bytes.
*/
size_t lruhash_get_mem(struct lruhash* table);
/**
* Traverse a lruhash. Call back for every element in the table.
* @param h: hash table. Locked before use.
* @param wr: if true writelock is obtained on element, otherwise readlock.
* @param func: function for every element. Do not lock or unlock elements.
* @param arg: user argument to func.
*/
void lruhash_traverse(struct lruhash* h, int wr,
void (*func)(struct lruhash_entry*, void*), void* arg);
#endif /* UTIL_STORAGE_LRUHASH_H */

View File

@ -0,0 +1,192 @@
/*
* rbtree.h -- generic red-black tree
*
* Copyright (c) 2001-2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 name of the NLNET LABS 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 THE COPYRIGHT
* HOLDER OR CONTRIBUTORS 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.
*
*/
/**
* \file
* Red black tree. Implementation taken from NSD 3.0.5, adjusted for use
* in unbound (memory allocation, logging and so on).
*/
#ifndef UTIL_RBTREE_H_
#define UTIL_RBTREE_H_
/**
* This structure must be the first member of the data structure in
* the rbtree. This allows easy casting between an rbnode_type and the
* user data (poor man's inheritance).
*/
typedef struct rbnode_type rbnode_type;
/**
* The rbnode_type struct definition.
*/
struct rbnode_type {
/** parent in rbtree, RBTREE_NULL for root */
rbnode_type *parent;
/** left node (smaller items) */
rbnode_type *left;
/** right node (larger items) */
rbnode_type *right;
/** pointer to sorting key */
const void *key;
/** colour of this node */
uint8_t color;
};
/** The nullpointer, points to empty node */
#define RBTREE_NULL &rbtree_null_node
/** the global empty node */
extern rbnode_type rbtree_null_node;
/** An entire red black tree */
typedef struct rbtree_type rbtree_type;
/** definition for tree struct */
struct rbtree_type {
/** The root of the red-black tree */
rbnode_type *root;
/** The number of the nodes in the tree */
size_t count;
/**
* Key compare function. <0,0,>0 like strcmp.
* Return 0 on two NULL ptrs.
*/
int (*cmp) (const void *, const void *);
};
/**
* Create new tree (malloced) with given key compare function.
* @param cmpf: compare function (like strcmp) takes pointers to two keys.
* @return: new tree, empty.
*/
rbtree_type *rbtree_create(int (*cmpf)(const void *, const void *));
/**
* Init a new tree (malloced by caller) with given key compare function.
* @param rbtree: uninitialised memory for new tree, returned empty.
* @param cmpf: compare function (like strcmp) takes pointers to two keys.
*/
void rbtree_init(rbtree_type *rbtree, int (*cmpf)(const void *, const void *));
/**
* Insert data into the tree.
* @param rbtree: tree to insert to.
* @param data: element to insert.
* @return: data ptr or NULL if key already present.
*/
rbnode_type *rbtree_insert(rbtree_type *rbtree, rbnode_type *data);
/**
* Delete element from tree.
* @param rbtree: tree to delete from.
* @param key: key of item to delete.
* @return: node that is now unlinked from the tree. User to delete it.
* returns 0 if node not present
*/
rbnode_type *rbtree_delete(rbtree_type *rbtree, const void *key);
/**
* Find key in tree. Returns NULL if not found.
* @param rbtree: tree to find in.
* @param key: key that must match.
* @return: node that fits or NULL.
*/
rbnode_type *rbtree_search(rbtree_type *rbtree, const void *key);
/**
* Find, but match does not have to be exact.
* @param rbtree: tree to find in.
* @param key: key to find position of.
* @param result: set to the exact node if present, otherwise to element that
* precedes the position of key in the tree. NULL if no smaller element.
* @return: true if exact match in result. Else result points to <= element,
* or NULL if key is smaller than the smallest key.
*/
int rbtree_find_less_equal(rbtree_type *rbtree, const void *key,
rbnode_type **result);
/**
* Returns first (smallest) node in the tree
* @param rbtree: tree
* @return: smallest element or NULL if tree empty.
*/
rbnode_type *rbtree_first(rbtree_type *rbtree);
/**
* Returns last (largest) node in the tree
* @param rbtree: tree
* @return: largest element or NULL if tree empty.
*/
rbnode_type *rbtree_last(rbtree_type *rbtree);
/**
* Returns next larger node in the tree
* @param rbtree: tree
* @return: next larger element or NULL if no larger in tree.
*/
rbnode_type *rbtree_next(rbnode_type *rbtree);
/**
* Returns previous smaller node in the tree
* @param rbtree: tree
* @return: previous smaller element or NULL if no previous in tree.
*/
rbnode_type *rbtree_previous(rbnode_type *rbtree);
/**
* Call with node=variable of struct* with rbnode_type as first element.
* with type is the type of a pointer to that struct.
*/
#define RBTREE_FOR(node, type, rbtree) \
for(node=(type)rbtree_first(rbtree); \
(rbnode_type*)node != RBTREE_NULL; \
node = (type)rbtree_next((rbnode_type*)node))
/**
* Call function for all elements in the redblack tree, such that
* leaf elements are called before parent elements. So that all
* elements can be safely free()d.
* Note that your function must not remove the nodes from the tree.
* Since that may trigger rebalances of the rbtree.
* @param tree: the tree
* @param func: function called with element and user arg.
* The function must not alter the rbtree.
* @param arg: user argument.
*/
void traverse_postorder(rbtree_type* tree, void (*func)(rbnode_type*, void*),
void* arg);
#endif /* UTIL_RBTREE_H_ */

View File

@ -0,0 +1,107 @@
/*
* validator/val_secalgo.h - validator security algorithm functions.
*
* Copyright (c) 2012, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 name of the NLNET LABS 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 THE COPYRIGHT
* HOLDER OR CONTRIBUTORS 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.
*/
/**
* \file
*
* This file contains helper functions for the validator module.
* The functions take buffers with raw data and convert to library calls.
*/
#ifndef VALIDATOR_VAL_SECALGO_H
#define VALIDATOR_VAL_SECALGO_H
struct sldns_buffer;
/** Return size of nsec3 hash algorithm, 0 if not supported */
size_t nsec3_hash_algo_size_supported(int id);
/**
* Hash a single hash call of an NSEC3 hash algorithm.
* Iterations and salt are done by the caller.
* @param algo: nsec3 hash algorithm.
* @param buf: the buffer to digest
* @param len: length of buffer to digest.
* @param res: result stored here (must have sufficient space).
* @return false on failure.
*/
int secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
unsigned char* res);
/**
* Calculate the sha256 hash for the data buffer into the result.
* @param buf: buffer to digest.
* @param len: length of the buffer to digest.
* @param res: result is stored here (space 256/8 bytes).
*/
void secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res);
/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.
* @return size in bytes of digest, or 0 if not supported.
*/
size_t ds_digest_size_supported(int algo);
/**
* @param algo: the DS digest algo
* @param buf: the buffer to digest
* @param len: length of buffer to digest.
* @param res: result stored here (must have sufficient space).
* @return false on failure.
*/
int secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
unsigned char* res);
/** return true if DNSKEY algorithm id is supported */
int dnskey_algo_id_is_supported(int id);
/**
* Check a canonical sig+rrset and signature against a dnskey
* @param buf: buffer with data to verify, the first rrsig part and the
* canonicalized rrset.
* @param algo: DNSKEY algorithm.
* @param sigblock: signature rdata field from RRSIG
* @param sigblock_len: length of sigblock data.
* @param key: public key data from DNSKEY RR.
* @param keylen: length of keydata.
* @param reason: bogus reason in more detail.
* @return secure if verification succeeded, bogus on crypto failure,
* unchecked on format errors and alloc failures.
*/
enum sec_status verify_canonrrset(struct sldns_buffer* buf, int algo,
unsigned char* sigblock, unsigned int sigblock_len,
unsigned char* key, unsigned int keylen, char** reason);
#endif /* VALIDATOR_VAL_SECALGO_H */

View File

@ -40,8 +40,8 @@
*/
#include "config.h"
#include "util/log.h"
#include "util/fptr_wlist.h"
#include "log.h"
#include "fptr_wlist.h"
#include "util/rbtree.h"
/** Node colour black */
@ -50,7 +50,7 @@
#define RED 1
/** the NULL node, global alloc */
_getdns_rbnode_t _getdns_rbtree_null_node = {
rbnode_type rbtree_null_node = {
RBTREE_NULL, /* Parent. */
RBTREE_NULL, /* Left. */
RBTREE_NULL, /* Right. */
@ -59,13 +59,14 @@ _getdns_rbnode_t _getdns_rbtree_null_node = {
};
/** rotate subtree left (to preserve redblack property) */
static void _getdns_rbtree_rotate_left(_getdns_rbtree_t *rbtree, _getdns_rbnode_t *node);
static void rbtree_rotate_left(rbtree_type *rbtree, rbnode_type *node);
/** rotate subtree right (to preserve redblack property) */
static void _getdns_rbtree_rotate_right(_getdns_rbtree_t *rbtree, _getdns_rbnode_t *node);
static void rbtree_rotate_right(rbtree_type *rbtree, rbnode_type *node);
/** Fixup node colours when insert happened */
static void _getdns_rbtree_insert_fixup(_getdns_rbtree_t *rbtree, _getdns_rbnode_t *node);
static void rbtree_insert_fixup(rbtree_type *rbtree, rbnode_type *node);
/** Fixup node colours when delete happened */
static void _getdns_rbtree_delete_fixup(_getdns_rbtree_t* rbtree, _getdns_rbnode_t* child, _getdns_rbnode_t* child_parent);
static void rbtree_delete_fixup(rbtree_type* rbtree, rbnode_type* child,
rbnode_type* child_parent);
/*
* Creates a new red black tree, initializes and returns a pointer to it.
@ -73,25 +74,25 @@ static void _getdns_rbtree_delete_fixup(_getdns_rbtree_t* rbtree, _getdns_rbnode
* Return NULL on failure.
*
*/
_getdns_rbtree_t *
_getdns_rbtree_create (int (*cmpf)(const void *, const void *))
rbtree_type *
rbtree_create (int (*cmpf)(const void *, const void *))
{
_getdns_rbtree_t *rbtree;
rbtree_type *rbtree;
/* Allocate memory for it */
rbtree = (_getdns_rbtree_t *) malloc(sizeof(_getdns_rbtree_t));
rbtree = (rbtree_type *) malloc(sizeof(rbtree_type));
if (!rbtree) {
return NULL;
}
/* Initialize it */
_getdns_rbtree_init(rbtree, cmpf);
rbtree_init(rbtree, cmpf);
return rbtree;
}
void
_getdns_rbtree_init(_getdns_rbtree_t *rbtree, int (*cmpf)(const void *, const void *))
rbtree_init(rbtree_type *rbtree, int (*cmpf)(const void *, const void *))
{
/* Initialize it */
rbtree->root = RBTREE_NULL;
@ -104,9 +105,9 @@ _getdns_rbtree_init(_getdns_rbtree_t *rbtree, int (*cmpf)(const void *, const vo
*
*/
static void
_getdns_rbtree_rotate_left(_getdns_rbtree_t *rbtree, _getdns_rbnode_t *node)
rbtree_rotate_left(rbtree_type *rbtree, rbnode_type *node)
{
_getdns_rbnode_t *right = node->right;
rbnode_type *right = node->right;
node->right = right->left;
if (right->left != RBTREE_NULL)
right->left->parent = node;
@ -131,9 +132,9 @@ _getdns_rbtree_rotate_left(_getdns_rbtree_t *rbtree, _getdns_rbnode_t *node)
*
*/
static void
_getdns_rbtree_rotate_right(_getdns_rbtree_t *rbtree, _getdns_rbnode_t *node)
rbtree_rotate_right(rbtree_type *rbtree, rbnode_type *node)
{
_getdns_rbnode_t *left = node->left;
rbnode_type *left = node->left;
node->left = left->right;
if (left->right != RBTREE_NULL)
left->right->parent = node;
@ -154,9 +155,9 @@ _getdns_rbtree_rotate_right(_getdns_rbtree_t *rbtree, _getdns_rbnode_t *node)
}
static void
_getdns_rbtree_insert_fixup(_getdns_rbtree_t *rbtree, _getdns_rbnode_t *node)
rbtree_insert_fixup(rbtree_type *rbtree, rbnode_type *node)
{
_getdns_rbnode_t *uncle;
rbnode_type *uncle;
/* While not at the root and need fixing... */
while (node != rbtree->root && node->parent->color == RED) {
@ -179,12 +180,12 @@ _getdns_rbtree_insert_fixup(_getdns_rbtree_t *rbtree, _getdns_rbnode_t *node)
/* Are we the right child? */
if (node == node->parent->right) {
node = node->parent;
_getdns_rbtree_rotate_left(rbtree, node);
rbtree_rotate_left(rbtree, node);
}
/* Now we're the left child, repaint and rotate... */
node->parent->color = BLACK;
node->parent->parent->color = RED;
_getdns_rbtree_rotate_right(rbtree, node->parent->parent);
rbtree_rotate_right(rbtree, node->parent->parent);
}
} else {
uncle = node->parent->parent->left;
@ -204,12 +205,12 @@ _getdns_rbtree_insert_fixup(_getdns_rbtree_t *rbtree, _getdns_rbnode_t *node)
/* Are we the right child? */
if (node == node->parent->left) {
node = node->parent;
_getdns_rbtree_rotate_right(rbtree, node);
rbtree_rotate_right(rbtree, node);
}
/* Now we're the right child, repaint and rotate... */
node->parent->color = BLACK;
node->parent->parent->color = RED;
_getdns_rbtree_rotate_left(rbtree, node->parent->parent);
rbtree_rotate_left(rbtree, node->parent->parent);
}
}
}
@ -223,17 +224,17 @@ _getdns_rbtree_insert_fixup(_getdns_rbtree_t *rbtree, _getdns_rbnode_t *node)
* Returns NULL on failure or the pointer to the newly added node
* otherwise.
*/
_getdns_rbnode_t *
_getdns_rbtree_insert (_getdns_rbtree_t *rbtree, _getdns_rbnode_t *data)
rbnode_type *
rbtree_insert (rbtree_type *rbtree, rbnode_type *data)
{
/* XXX Not necessary, but keeps compiler quiet... */
int r = 0;
/* We start at the root of the tree */
_getdns_rbnode_t *node = rbtree->root;
_getdns_rbnode_t *parent = RBTREE_NULL;
rbnode_type *node = rbtree->root;
rbnode_type *parent = RBTREE_NULL;
fptr_ok(fptr_whitelist__getdns_rbtree_cmp(rbtree->cmp));
fptr_ok(fptr_whitelist_rbtree_cmp(rbtree->cmp));
/* Lets find the new parent... */
while (node != RBTREE_NULL) {
/* Compare two keys, do we have a duplicate? */
@ -267,7 +268,7 @@ _getdns_rbtree_insert (_getdns_rbtree_t *rbtree, _getdns_rbnode_t *data)
}
/* Fix up the red-black properties... */
_getdns_rbtree_insert_fixup(rbtree, data);
rbtree_insert_fixup(rbtree, data);
return data;
}
@ -276,12 +277,12 @@ _getdns_rbtree_insert (_getdns_rbtree_t *rbtree, _getdns_rbnode_t *data)
* Searches the red black tree, returns the data if key is found or NULL otherwise.
*
*/
_getdns_rbnode_t *
_getdns_rbtree_search (_getdns_rbtree_t *rbtree, const void *key)
rbnode_type *
rbtree_search (rbtree_type *rbtree, const void *key)
{
_getdns_rbnode_t *node;
rbnode_type *node;
if (_getdns_rbtree_find_less_equal(rbtree, key, &node)) {
if (rbtree_find_less_equal(rbtree, key, &node)) {
return node;
} else {
return NULL;
@ -295,13 +296,14 @@ static void swap_int8(uint8_t* x, uint8_t* y)
}
/** helpers for delete: swap node pointers */
static void swap_np(_getdns_rbnode_t** x, _getdns_rbnode_t** y)
static void swap_np(rbnode_type** x, rbnode_type** y)
{
_getdns_rbnode_t* t = *x; *x = *y; *y = t;
rbnode_type* t = *x; *x = *y; *y = t;
}
/** Update parent pointers of child trees of 'parent' */
static void change_parent_ptr(_getdns_rbtree_t* rbtree, _getdns_rbnode_t* parent, _getdns_rbnode_t* old, _getdns_rbnode_t* new)
static void change_parent_ptr(rbtree_type* rbtree, rbnode_type* parent,
rbnode_type* old, rbnode_type* new)
{
if(parent == RBTREE_NULL)
{
@ -315,30 +317,31 @@ static void change_parent_ptr(_getdns_rbtree_t* rbtree, _getdns_rbnode_t* parent
if(parent->right == old) parent->right = new;
}
/** Update parent pointer of a node 'child' */
static void change_child_ptr(_getdns_rbnode_t* child, _getdns_rbnode_t* old, _getdns_rbnode_t* new)
static void change_child_ptr(rbnode_type* child, rbnode_type* old,
rbnode_type* new)
{
if(child == RBTREE_NULL) return;
log_assert(child->parent == old || child->parent == new);
if(child->parent == old) child->parent = new;
}
_getdns_rbnode_t*
_getdns_rbtree_delete(_getdns_rbtree_t *rbtree, const void *key)
rbnode_type*
rbtree_delete(rbtree_type *rbtree, const void *key)
{
_getdns_rbnode_t *to_delete;
_getdns_rbnode_t *child;
if((to_delete = _getdns_rbtree_search(rbtree, key)) == 0) return 0;
rbnode_type *to_delete;
rbnode_type *child;
if((to_delete = rbtree_search(rbtree, key)) == 0) return 0;
rbtree->count--;
/* make sure we have at most one non-leaf child */
if(to_delete->left != RBTREE_NULL && to_delete->right != RBTREE_NULL)
{
/* swap with smallest from right subtree (or largest from left) */
_getdns_rbnode_t *smright = to_delete->right;
rbnode_type *smright = to_delete->right;
while(smright->left != RBTREE_NULL)
smright = smright->left;
/* swap the smright and to_delete elements in the tree,
* but the _getdns_rbnode_t is first part of user data struct
* but the rbnode_type is first part of user data struct
* so cannot just swap the keys and data pointers. Instead
* readjust the pointers left,right,parent */
@ -390,7 +393,7 @@ _getdns_rbtree_delete(_getdns_rbtree_t *rbtree, const void *key)
/* change child to BLACK, removing a RED node is no problem */
if(child!=RBTREE_NULL) child->color = BLACK;
}
else _getdns_rbtree_delete_fixup(rbtree, child, to_delete->parent);
else rbtree_delete_fixup(rbtree, child, to_delete->parent);
/* unlink completely */
to_delete->parent = RBTREE_NULL;
@ -400,9 +403,10 @@ _getdns_rbtree_delete(_getdns_rbtree_t *rbtree, const void *key)
return to_delete;
}
static void _getdns_rbtree_delete_fixup(_getdns_rbtree_t* rbtree, _getdns_rbnode_t* child, _getdns_rbnode_t* child_parent)
static void rbtree_delete_fixup(rbtree_type* rbtree, rbnode_type* child,
rbnode_type* child_parent)
{
_getdns_rbnode_t* sibling;
rbnode_type* sibling;
int go_up = 1;
/* determine sibling to the node that is one-black short */
@ -422,8 +426,8 @@ static void _getdns_rbtree_delete_fixup(_getdns_rbtree_t* rbtree, _getdns_rbnode
child_parent->color = RED;
sibling->color = BLACK;
if(child_parent->right == child)
_getdns_rbtree_rotate_right(rbtree, child_parent);
else _getdns_rbtree_rotate_left(rbtree, child_parent);
rbtree_rotate_right(rbtree, child_parent);
else rbtree_rotate_left(rbtree, child_parent);
/* new sibling after rotation */
if(child_parent->right == child) sibling = child_parent->left;
else sibling = child_parent->right;
@ -468,7 +472,7 @@ static void _getdns_rbtree_delete_fixup(_getdns_rbtree_t* rbtree, _getdns_rbnode
{
sibling->color = RED;
sibling->right->color = BLACK;
_getdns_rbtree_rotate_left(rbtree, sibling);
rbtree_rotate_left(rbtree, sibling);
/* new sibling after rotation */
if(child_parent->right == child) sibling = child_parent->left;
else sibling = child_parent->right;
@ -480,7 +484,7 @@ static void _getdns_rbtree_delete_fixup(_getdns_rbtree_t* rbtree, _getdns_rbnode
{
sibling->color = RED;
sibling->left->color = BLACK;
_getdns_rbtree_rotate_right(rbtree, sibling);
rbtree_rotate_right(rbtree, sibling);
/* new sibling after rotation */
if(child_parent->right == child) sibling = child_parent->left;
else sibling = child_parent->right;
@ -493,21 +497,22 @@ static void _getdns_rbtree_delete_fixup(_getdns_rbtree_t* rbtree, _getdns_rbnode
{
log_assert(sibling->left->color == RED);
sibling->left->color = BLACK;
_getdns_rbtree_rotate_right(rbtree, child_parent);
rbtree_rotate_right(rbtree, child_parent);
}
else
{
log_assert(sibling->right->color == RED);
sibling->right->color = BLACK;
_getdns_rbtree_rotate_left(rbtree, child_parent);
rbtree_rotate_left(rbtree, child_parent);
}
}
int
_getdns_rbtree_find_less_equal(_getdns_rbtree_t *rbtree, const void *key, _getdns_rbnode_t **result)
rbtree_find_less_equal(rbtree_type *rbtree, const void *key,
rbnode_type **result)
{
int r;
_getdns_rbnode_t *node;
rbnode_type *node;
log_assert(result);
@ -515,7 +520,7 @@ _getdns_rbtree_find_less_equal(_getdns_rbtree_t *rbtree, const void *key, _getdn
node = rbtree->root;
*result = NULL;
fptr_ok(fptr_whitelist__getdns_rbtree_cmp(rbtree->cmp));
fptr_ok(fptr_whitelist_rbtree_cmp(rbtree->cmp));
/* While there are children... */
while (node != RBTREE_NULL) {
@ -540,19 +545,19 @@ _getdns_rbtree_find_less_equal(_getdns_rbtree_t *rbtree, const void *key, _getdn
* Finds the first element in the red black tree
*
*/
_getdns_rbnode_t *
_getdns_rbtree_first (_getdns_rbtree_t *rbtree)
rbnode_type *
rbtree_first (rbtree_type *rbtree)
{
_getdns_rbnode_t *node;
rbnode_type *node;
for (node = rbtree->root; node->left != RBTREE_NULL; node = node->left);
return node;
}
_getdns_rbnode_t *
_getdns_rbtree_last (_getdns_rbtree_t *rbtree)
rbnode_type *
rbtree_last (rbtree_type *rbtree)
{
_getdns_rbnode_t *node;
rbnode_type *node;
for (node = rbtree->root; node->right != RBTREE_NULL; node = node->right);
return node;
@ -562,10 +567,10 @@ _getdns_rbtree_last (_getdns_rbtree_t *rbtree)
* Returns the next node...
*
*/
_getdns_rbnode_t *
_getdns_rbtree_next (_getdns_rbnode_t *node)
rbnode_type *
rbtree_next (rbnode_type *node)
{
_getdns_rbnode_t *parent;
rbnode_type *parent;
if (node->right != RBTREE_NULL) {
/* One right, then keep on going left... */
@ -581,10 +586,10 @@ _getdns_rbtree_next (_getdns_rbnode_t *node)
return node;
}
_getdns_rbnode_t *
_getdns_rbtree_previous(_getdns_rbnode_t *node)
rbnode_type *
rbtree_previous(rbnode_type *node)
{
_getdns_rbnode_t *parent;
rbnode_type *parent;
if (node->left != RBTREE_NULL) {
/* One left, then keep on going right... */
@ -602,19 +607,20 @@ _getdns_rbtree_previous(_getdns_rbnode_t *node)
/** recursive descent traverse */
static void
_getdns_traverse_post(void (*func)(_getdns_rbnode_t*, void*), void* arg, _getdns_rbnode_t* node)
traverse_post(void (*func)(rbnode_type*, void*), void* arg, rbnode_type* node)
{
if(!node || node == RBTREE_NULL)
return;
/* recurse */
_getdns_traverse_post(func, arg, node->left);
_getdns_traverse_post(func, arg, node->right);
traverse_post(func, arg, node->left);
traverse_post(func, arg, node->right);
/* call user func */
(*func)(node, arg);
}
void
_getdns_traverse_postorder(_getdns_rbtree_t* tree, void (*func)(_getdns_rbnode_t*, void*), void* arg)
traverse_postorder(rbtree_type* tree, void (*func)(rbnode_type*, void*),
void* arg)
{
_getdns_traverse_post(func, arg, tree->root);
traverse_post(func, arg, tree->root);
}

View File

@ -1,192 +1,50 @@
/**
*
* \file rbtree.h
* /brief Alternative symbol names for unbound's rbtree.h
*
*/
/*
* rbtree.h -- generic red-black tree
* Copyright (c) 2017, NLnet Labs, the getdns team
* All rights reserved.
*
* Copyright (c) 2001-2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 name of the NLNET LABS 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 THE COPYRIGHT
* HOLDER OR CONTRIBUTORS 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.
* 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.
*/
/**
* \file
* Red black tree. Implementation taken from NSD 3.0.5, adjusted for use
* in unbound (memory allocation, logging and so on).
*/
#ifndef UTIL_RBTREE_H_
#define UTIL_RBTREE_H_
/**
* This structure must be the first member of the data structure in
* the rbtree. This allows easy casting between an _getdns_rbnode_t and the
* user data (poor man's inheritance).
*/
typedef struct _getdns_rbnode_t _getdns_rbnode_t;
/**
* The _getdns_rbnode_t struct definition.
*/
struct _getdns_rbnode_t {
/** parent in rbtree, RBTREE_NULL for root */
_getdns_rbnode_t *parent;
/** left node (smaller items) */
_getdns_rbnode_t *left;
/** right node (larger items) */
_getdns_rbnode_t *right;
/** pointer to sorting key */
const void *key;
/** colour of this node */
uint8_t color;
};
/** The nullpointer, points to empty node */
#define RBTREE_NULL &_getdns_rbtree_null_node
/** the global empty node */
extern _getdns_rbnode_t _getdns_rbtree_null_node;
/** An entire red black tree */
typedef struct _getdns_rbtree_t _getdns_rbtree_t;
/** definition for tree struct */
struct _getdns_rbtree_t {
/** The root of the red-black tree */
_getdns_rbnode_t *root;
/** The number of the nodes in the tree */
size_t count;
/**
* Key compare function. <0,0,>0 like strcmp.
* Return 0 on two NULL ptrs.
*/
int (*cmp) (const void *, const void *);
};
/**
* Create new tree (malloced) with given key compare function.
* @param cmpf: compare function (like strcmp) takes pointers to two keys.
* @return: new tree, empty.
*/
_getdns_rbtree_t *_getdns_rbtree_create(int (*cmpf)(const void *, const void *));
/**
* Init a new tree (malloced by caller) with given key compare function.
* @param rbtree: uninitialised memory for new tree, returned empty.
* @param cmpf: compare function (like strcmp) takes pointers to two keys.
*/
void _getdns_rbtree_init(_getdns_rbtree_t *rbtree, int (*cmpf)(const void *, const void *));
/**
* Insert data into the tree.
* @param rbtree: tree to insert to.
* @param data: element to insert.
* @return: data ptr or NULL if key already present.
*/
_getdns_rbnode_t *_getdns_rbtree_insert(_getdns_rbtree_t *rbtree, _getdns_rbnode_t *data);
/**
* Delete element from tree.
* @param rbtree: tree to delete from.
* @param key: key of item to delete.
* @return: node that is now unlinked from the tree. User to delete it.
* returns 0 if node not present
*/
_getdns_rbnode_t *_getdns_rbtree_delete(_getdns_rbtree_t *rbtree, const void *key);
/**
* Find key in tree. Returns NULL if not found.
* @param rbtree: tree to find in.
* @param key: key that must match.
* @return: node that fits or NULL.
*/
_getdns_rbnode_t *_getdns_rbtree_search(_getdns_rbtree_t *rbtree, const void *key);
/**
* Find, but match does not have to be exact.
* @param rbtree: tree to find in.
* @param key: key to find position of.
* @param result: set to the exact node if present, otherwise to element that
* precedes the position of key in the tree. NULL if no smaller element.
* @return: true if exact match in result. Else result points to <= element,
* or NULL if key is smaller than the smallest key.
*/
int _getdns_rbtree_find_less_equal(_getdns_rbtree_t *rbtree, const void *key,
_getdns_rbnode_t **result);
/**
* Returns first (smallest) node in the tree
* @param rbtree: tree
* @return: smallest element or NULL if tree empty.
*/
_getdns_rbnode_t *_getdns_rbtree_first(_getdns_rbtree_t *rbtree);
/**
* Returns last (largest) node in the tree
* @param rbtree: tree
* @return: largest element or NULL if tree empty.
*/
_getdns_rbnode_t *_getdns_rbtree_last(_getdns_rbtree_t *rbtree);
/**
* Returns next larger node in the tree
* @param rbtree: tree
* @return: next larger element or NULL if no larger in tree.
*/
_getdns_rbnode_t *_getdns_rbtree_next(_getdns_rbnode_t *rbtree);
/**
* Returns previous smaller node in the tree
* @param rbtree: tree
* @return: previous smaller element or NULL if no previous in tree.
*/
_getdns_rbnode_t *_getdns_rbtree_previous(_getdns_rbnode_t *rbtree);
/**
* Call with node=variable of struct* with _getdns_rbnode_t as first element.
* with type is the type of a pointer to that struct.
*/
#define RBTREE_FOR(node, type, rbtree) \
for(node=(type)_getdns_rbtree_first(rbtree); \
(_getdns_rbnode_t*)node != RBTREE_NULL; \
node = (type)_getdns_rbtree_next((_getdns_rbnode_t*)node))
/**
* Call function for all elements in the redblack tree, such that
* leaf elements are called before parent elements. So that all
* elements can be safely free()d.
* Note that your function must not remove the nodes from the tree.
* Since that may trigger rebalances of the rbtree.
* @param tree: the tree
* @param func: function called with element and user arg.
* The function must not alter the rbtree.
* @param arg: user argument.
*/
void _getdns_traverse_postorder(_getdns_rbtree_t* tree, void (*func)(_getdns_rbnode_t*, void*),
void* arg);
#endif /* UTIL_RBTREE_H_ */
#ifndef RBTREE_H_SYMBOLS
#define RBTREE_H_SYMBOLS
#define rbnode_type _getdns_rbnode_t
#define rbtree_null_node _getdns_rbtree_null_node
#define rbtree_type _getdns_rbtree_t
#define rbtree_create _getdns_rbtree_create
#define rbtree_init _getdns_rbtree_init
#define rbtree_insert _getdns_rbtree_insert
#define rbtree_delete _getdns_rbtree_delete
#define rbtree_search _getdns_rbtree_search
#define rbtree_find_less_equal _getdns_rbtree_find_less_equal
#define rbtree_first _getdns_rbtree_first
#define rbtree_last _getdns_rbtree_last
#define rbtree_next _getdns_rbtree_next
#define rbtree_previous _getdns_rbtree_previous
#define traverse_postorder _getdns_traverse_postorder
#include "util/orig-headers/rbtree.h"
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,107 +1,78 @@
/**
*
* \file rbtree.h
* /brief Alternative symbol names for unbound's rbtree.h
*
*/
/*
* validator/val_secalgo.h - validator security algorithm functions.
* Copyright (c) 2017, NLnet Labs, the getdns team
* All rights reserved.
*
* Copyright (c) 2012, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* 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 name of the NLNET LABS 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 THE COPYRIGHT
* HOLDER OR CONTRIBUTORS 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
* 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 VAL_SECALGO_H_SYMBOLS
#define VAL_SECALGO_H_SYMBOLS
#define sldns_buffer gldns_buffer
#define nsec3_hash_algo_size_supported _getdns_nsec3_hash_algo_size_supported
#define secalgo_nsec3_hash _getdns_secalgo_nsec3_hash
#define secalgo_hash_sha256 _getdns_secalgo_hash_sha256
#define ds_digest_size_supported _getdns_ds_digest_size_supported
#define secalgo_ds_digest _getdns_secalgo_ds_digest
#define dnskey_algo_id_is_supported _getdns_dnskey_algo_id_is_supported
#define verify_canonrrset _getdns_verify_canonrrset
#define sec_status _getdns_sec_status
#define sec_status_secure _getdns_sec_status_secure
#define sec_status_insecure _getdns_sec_status_insecure
#define sec_status_unchecked _getdns_sec_status_unchecked
#define sec_status_bogus _getdns_sec_status_bogus
/**
* \file
*
* This file contains helper functions for the validator module.
* The functions take buffers with raw data and convert to library calls.
*/
enum sec_status { sec_status_bogus = 0
, sec_status_unchecked = 0
, sec_status_insecure = 0
, sec_status_secure = 1 };
#define NSEC3_HASH_SHA1 0x01
#ifndef VALIDATOR_VAL_SECALGO_H
#define VALIDATOR_VAL_SECALGO_H
struct gldns_buffer;
/** Return size of nsec3 hash algorithm, 0 if not supported */
size_t _getdns_nsec3_hash_algo_size_supported(int id);
/**
* Hash a single hash call of an NSEC3 hash algorithm.
* Iterations and salt are done by the caller.
* @param algo: nsec3 hash algorithm.
* @param buf: the buffer to digest
* @param len: length of buffer to digest.
* @param res: result stored here (must have sufficient space).
* @return false on failure.
*/
int _getdns_secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
unsigned char* res);
/**
* Calculate the sha256 hash for the data buffer into the result.
* @param buf: buffer to digest.
* @param len: length of the buffer to digest.
* @param res: result is stored here (space 256/8 bytes).
*/
void _getdns_secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res);
/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.
* @return size in bytes of digest, or 0 if not supported.
*/
size_t _getdns_ds_digest_size_supported(int algo);
/**
* @param algo: the DS digest algo
* @param buf: the buffer to digest
* @param len: length of buffer to digest.
* @param res: result stored here (must have sufficient space).
* @return false on failure.
*/
int _getdns_secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
unsigned char* res);
/** return true if DNSKEY algorithm id is supported */
int _getdns_dnskey_algo_id_is_supported(int id);
/**
* Check a canonical sig+rrset and signature against a dnskey
* @param buf: buffer with data to verify, the first rrsig part and the
* canonicalized rrset.
* @param algo: DNSKEY algorithm.
* @param sigblock: signature rdata field from RRSIG
* @param sigblock_len: length of sigblock data.
* @param key: public key data from DNSKEY RR.
* @param keylen: length of keydata.
* @param reason: bogus reason in more detail.
* @return secure if verification succeeded, bogus on crypto failure,
* unchecked on format errors and alloc failures.
*/
int _getdns_verify_canonrrset(struct gldns_buffer* buf, int algo,
unsigned char* sigblock, unsigned int sigblock_len,
unsigned char* key, unsigned int keylen, char** reason);
#endif /* VALIDATOR_VAL_SECALGO_H */
#define LDNS_SHA1 GLDNS_SHA1
#define LDNS_SHA256 GLDNS_SHA256
#define LDNS_SHA384 GLDNS_SHA384
#define LDNS_HASH_GOST GLDNS_HASH_GOST
#define LDNS_RSAMD5 GLDNS_RSAMD5
#define LDNS_DSA GLDNS_DSA
#define LDNS_DSA_NSEC3 GLDNS_DSA_NSEC3
#define LDNS_RSASHA1 GLDNS_RSASHA1
#define LDNS_RSASHA1_NSEC3 GLDNS_RSASHA1_NSEC3
#define LDNS_RSASHA256 GLDNS_RSASHA256
#define LDNS_RSASHA512 GLDNS_RSASHA512
#define LDNS_ECDSAP256SHA256 GLDNS_ECDSAP256SHA256
#define LDNS_ECDSAP384SHA384 GLDNS_ECDSAP384SHA384
#define LDNS_ECC_GOST GLDNS_ECC_GOST
#define sldns_key_EVP_load_gost_id gldns_key_EVP_load_gost_id
#define sldns_digest_evp gldns_digest_evp
#define sldns_key_buf2dsa_raw gldns_key_buf2dsa_raw
#define sldns_key_buf2rsa_raw gldns_key_buf2rsa_raw
#define sldns_gost2pkey_raw gldns_gost2pkey_raw
#define sldns_ecdsa2pkey_raw gldns_ecdsa2pkey_raw
#define sldns_buffer_begin gldns_buffer_begin
#define sldns_buffer_limit gldns_buffer_limit
#include "util/orig-headers/val_secalgo.h"
#endif