Upgrade to Unbound 1.5.9.

This commit is contained in:
Dag-Erling Smørgrav 2016-09-04 12:17:57 +00:00
commit e2d1500434
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=305381
96 changed files with 4479 additions and 719 deletions

View file

@ -108,11 +108,12 @@ util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \
util/rtt.c util/storage/dnstree.c util/storage/lookup3.c \
util/storage/lruhash.c util/storage/slabhash.c util/timehist.c util/tube.c \
util/winsock_event.c validator/autotrust.c validator/val_anchor.c \
validator/validator.c validator/val_kcache.c validator/val_kentry.c \
validator/val_neg.c validator/val_nsec3.c validator/val_nsec.c \
validator/val_secalgo.c validator/val_sigcrypt.c \
validator/val_utils.c dns64/dns64.c $(CHECKLOCK_SRC) $(DNSTAP_SRC)
util/ub_event.c util/ub_event_pluggable.c util/winsock_event.c \
validator/autotrust.c validator/val_anchor.c validator/validator.c \
validator/val_kcache.c validator/val_kentry.c validator/val_neg.c \
validator/val_nsec3.c validator/val_nsec.c validator/val_secalgo.c \
validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c cachedb/cachedb.c $(CHECKLOCK_SRC) \
$(DNSTAP_SRC)
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
@ -122,10 +123,11 @@ fptr_wlist.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \
slabhash.lo timehist.lo tube.lo winsock_event.lo autotrust.lo val_anchor.lo \
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo \
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo \
$(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ)
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
outside_network.lo
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
# set to $COMMON_OBJ or to "" if --enableallsymbols
COMMON_OBJ_ALL_SYMBOLS=@COMMON_OBJ_ALL_SYMBOLS@
COMPAT_SRC=compat/ctime_r.c compat/fake-rfc2553.c compat/gmtime_r.c \
@ -134,7 +136,8 @@ compat/memcmp.c compat/memmove.c compat/snprintf.c compat/strlcat.c \
compat/strlcpy.c compat/strptime.c compat/getentropy_linux.c \
compat/getentropy_osx.c compat/getentropy_solaris.c compat/getentropy_win.c \
compat/explicit_bzero.c compat/arc4random.c compat/arc4random_uniform.c \
compat/arc4_lock.c compat/sha512.c compat/reallocarray.c compat/isblank.c
compat/arc4_lock.c compat/sha512.c compat/reallocarray.c compat/isblank.c \
compat/strsep.c
COMPAT_OBJ=$(LIBOBJS:.o=.lo)
COMPAT_OBJ_WITHOUT_CTIME=$(LIBOBJ_WITHOUT_CTIME:.o=.lo)
COMPAT_OBJ_WITHOUT_CTIMEARC4=$(LIBOBJ_WITHOUT_CTIMEARC4:.o=.lo)
@ -177,7 +180,8 @@ daemon/worker.c daemon/acl_list.c daemon/daemon.c daemon/stats.c \
testcode/replay.c testcode/fake_event.c
TESTBOUND_OBJ=testbound.lo replay.lo fake_event.lo
TESTBOUND_OBJ_LINK=$(TESTBOUND_OBJ) testpkts.lo worker.lo acl_list.lo \
daemon.lo stats.lo $(COMMON_OBJ_WITHOUT_NETCALL) $(SLDNS_OBJ) $(COMPAT_OBJ)
daemon.lo stats.lo $(COMMON_OBJ_WITHOUT_NETCALL) ub_event.lo $(SLDNS_OBJ) \
$(COMPAT_OBJ)
LOCKVERIFY_SRC=testcode/lock_verify.c
LOCKVERIFY_OBJ=lock_verify.lo
LOCKVERIFY_OBJ_LINK=$(LOCKVERIFY_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \
@ -209,8 +213,8 @@ DELAYER_OBJ_LINK=$(DELAYER_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \
$(SLDNS_OBJ)
LIBUNBOUND_SRC=libunbound/context.c libunbound/libunbound.c \
libunbound/libworker.c
LIBUNBOUND_OBJ=context.lo libunbound.lo libworker.lo
LIBUNBOUND_OBJ_LINK=$(LIBUNBOUND_OBJ) $(COMMON_OBJ) $(SLDNS_OBJ) $(COMPAT_OBJ)
LIBUNBOUND_OBJ=context.lo libunbound.lo libworker.lo ub_event_pluggable.lo
LIBUNBOUND_OBJ_LINK=$(LIBUNBOUND_OBJ) $(COMMON_OBJ_WITHOUT_UB_EVENT) $(SLDNS_OBJ) $(COMPAT_OBJ)
# win apps or "" if not on windows
WINAPPS=@WINAPPS@
@ -552,7 +556,7 @@ uninstall: $(PYTHONMOD_UNINSTALL) $(PYUNBOUND_UNINSTALL) $(UNBOUND_EVENT_UNINSTA
@echo "You still need to remove "`dirname $(DESTDIR)$(configfile)`" , $(DESTDIR)$(configfile) by hand"
iana_update:
curl -o port-numbers.tmp http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml --compressed
curl -o port-numbers.tmp https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml --compressed
if file port-numbers.tmp | grep 'gzip' >/dev/null; then zcat port-numbers.tmp; else cat port-numbers.tmp; fi | awk '/<record>/ {p=0;} /<protocol>udp/ {p=1;} /<protocol>[^u]/ {p=0;} /Decomissioned|Decommissioned|Removed|De-registered|unassigned|Unassigned|Reserved/ {u=1;} /<number>/ { if(u==1) {u=0;} else { if(p==1) { match($$0,/[0-9]+/); print substr($$0, RSTART, RLENGTH) ","}}}' | sort -nu > util/iana_ports.inc
rm -f port-numbers.tmp
@ -596,7 +600,6 @@ depend:
rm -f $(DEPEND_TMP) $(DEPEND_TMP2)
# Dependencies
as112.lo as112.o: $(srcdir)/util/as112.c $(srcdir)/util/as112.h
dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
$(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/locks.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/msgreply.h \
@ -614,6 +617,7 @@ rrset.lo rrset.o: $(srcdir)/services/cache/rrset.c config.h $(srcdir)/services/c
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/slabhash.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/config_file.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/regional.h $(srcdir)/util/alloc.h
as112.lo as112.o: $(srcdir)/util/as112.c $(srcdir)/util/as112.h
dname.lo dname.o: $(srcdir)/util/data/dname.c config.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/storage/lookup3.h $(srcdir)/sldns/sbuffer.h
@ -624,9 +628,9 @@ msgencode.lo msgencode.o: $(srcdir)/util/data/msgencode.c config.h $(srcdir)/uti
$(srcdir)/sldns/sbuffer.h
msgparse.lo msgparse.o: $(srcdir)/util/data/msgparse.c config.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/util/data/dname.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h \
$(srcdir)/sldns/wire2str.h
$(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h
msgreply.lo msgreply.o: $(srcdir)/util/data/msgreply.c config.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/netevent.h $(srcdir)/util/net_help.h \
@ -718,7 +722,7 @@ modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/service
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/dns64/dns64.h \
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/validator/validator.h \
$(srcdir)/validator/val_utils.h
$(srcdir)/validator/val_utils.h $(PYTHONMOD_HEADER) $(srcdir)/cachedb/cachedb.h
outbound_list.lo outbound_list.o: $(srcdir)/services/outbound_list.c config.h \
$(srcdir)/services/outbound_list.h $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/netevent.h
@ -762,7 +766,8 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
$(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h \
$(srcdir)/validator/val_neg.h $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h \
$(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h \
$(PYTHONMOD_HEADER) $(srcdir)/cachedb/cachedb.h
locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
@ -773,12 +778,12 @@ mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/
module.lo module.o: $(srcdir)/util/module.c config.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h
netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/netevent.h $(srcdir)/util/log.h \
$(srcdir)/util/net_help.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/netevent.h $(srcdir)/util/ub_event.h \
$(srcdir)/util/log.h $(srcdir)/util/net_help.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/locks.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/dnstap/dnstap.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
$(srcdir)/dnstap/dnstap.h
net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
@ -808,7 +813,15 @@ tube.lo tube.o: $(srcdir)/util/tube.c config.h $(srcdir)/util/tube.h $(srcdir)/u
$(srcdir)/util/netevent.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/mesh.h \
$(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
$(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/util/ub_event.h
ub_event.lo ub_event.o: $(srcdir)/util/ub_event.c config.h $(srcdir)/util/ub_event.h $(srcdir)/util/log.h \
$(srcdir)/util/netevent.h $(srcdir)/util/tube.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
ub_event_pluggable.lo ub_event_pluggable.o: $(srcdir)/util/ub_event_pluggable.c config.h $(srcdir)/util/ub_event.h \
$(srcdir)/libunbound/unbound-event.h $(srcdir)/util/netevent.h $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
$(srcdir)/services/modstack.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
winsock_event.lo winsock_event.o: $(srcdir)/util/winsock_event.c config.h
autotrust.lo autotrust.o: $(srcdir)/validator/autotrust.c config.h $(srcdir)/validator/autotrust.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
@ -822,8 +835,8 @@ autotrust.lo autotrust.o: $(srcdir)/validator/autotrust.c config.h $(srcdir)/val
val_anchor.lo val_anchor.o: $(srcdir)/validator/val_anchor.c config.h $(srcdir)/validator/val_anchor.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_sigcrypt.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/validator/autotrust.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h $(srcdir)/util/as112.h
$(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/util/as112.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
validator.lo validator.o: $(srcdir)/validator/validator.c config.h $(srcdir)/validator/validator.h \
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
@ -880,7 +893,7 @@ val_utils.lo val_utils.o: $(srcdir)/validator/val_utils.c config.h $(srcdir)/val
$(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h \
$(srcdir)/validator/val_nsec.h $(srcdir)/validator/val_neg.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/net_help.h $(srcdir)/util/regional.h
$(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h
dns64.lo dns64.o: $(srcdir)/dns64/dns64.c config.h $(srcdir)/dns64/dns64.h $(srcdir)/util/module.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
@ -888,6 +901,14 @@ dns64.lo dns64.o: $(srcdir)/dns64/dns64.c config.h $(srcdir)/dns64/dns64.h $(src
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/config_file.h $(srcdir)/util/fptr_wlist.h \
$(srcdir)/util/netevent.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
$(srcdir)/services/modstack.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h
cachedb.lo cachedb.o: $(srcdir)/cachedb/cachedb.c config.h $(srcdir)/cachedb/cachedb.h $(srcdir)/util/module.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h \
$(srcdir)/util/data/msgencode.h $(srcdir)/services/cache/dns.h $(srcdir)/validator/val_neg.h \
$(srcdir)/util/rbtree.h $(srcdir)/validator/val_secalgo.h $(srcdir)/iterator/iter_utils.h \
$(srcdir)/iterator/iter_resptype.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h \
$(srcdir)/sldns/sbuffer.h
checklocks.lo checklocks.o: $(srcdir)/testcode/checklocks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/testcode/checklocks.h
unitanchor.lo unitanchor.o: $(srcdir)/testcode/unitanchor.c config.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
@ -994,7 +1015,7 @@ unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.h $
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/fptr_wlist.h \
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/net_help.h \
$(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
$(srcdir)/util/ub_event.h
worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
$(srcdir)/util/random.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
@ -1020,7 +1041,7 @@ testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/test
$(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/util/rtt.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
$(srcdir)/services/mesh.h $(srcdir)/util/net_help.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
$(srcdir)/services/mesh.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h
testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcode/testpkts.h \
$(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
@ -1101,7 +1122,7 @@ unbound-checkconf.lo unbound-checkconf.o: $(srcdir)/smallapp/unbound-checkconf.c
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
$(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/services/localzone.h \
$(srcdir)/sldns/sbuffer.h
$(srcdir)/sldns/sbuffer.h $(PYTHONMOD_HEADER)
worker_cb.lo worker_cb.o: $(srcdir)/smallapp/worker_cb.c config.h $(srcdir)/libunbound/context.h \
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
$(srcdir)/libunbound/unbound.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
@ -1121,9 +1142,10 @@ libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbou
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/libunbound/libworker.h \
$(srcdir)/util/config_file.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h \
$(srcdir)/util/random.h $(srcdir)/util/net_help.h $(srcdir)/util/tube.h $(srcdir)/services/localzone.h \
$(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/sldns/sbuffer.h
$(srcdir)/util/random.h $(srcdir)/util/net_help.h $(srcdir)/util/tube.h $(srcdir)/util/ub_event.h \
$(srcdir)/services/localzone.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
$(srcdir)/sldns/sbuffer.h
libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/libunbound/libworker.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
@ -1163,14 +1185,15 @@ pythonmod_utils.lo pythonmod_utils.o: $(srcdir)/pythonmod/pythonmod_utils.c conf
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/util/netevent.h $(srcdir)/util/net_help.h $(srcdir)/services/cache/dns.h \
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/regional.h \
$(srcdir)/iterator/iter_delegpt.h $(srcdir)/sldns/sbuffer.h
$(srcdir)/iterator/iter_delegpt.h $(srcdir)/sldns/sbuffer.h \
win_svc.lo win_svc.o: $(srcdir)/winrc/win_svc.c config.h $(srcdir)/winrc/win_svc.h $(srcdir)/winrc/w_inst.h \
$(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/netevent.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/util/module.h \
$(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/util/winsock_event.h
$(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/util/ub_event.h
w_inst.lo w_inst.o: $(srcdir)/winrc/w_inst.c config.h $(srcdir)/winrc/w_inst.h $(srcdir)/winrc/win_svc.h
unbound-service-install.lo unbound-service-install.o: $(srcdir)/winrc/unbound-service-install.c config.h \
$(srcdir)/winrc/w_inst.h
@ -1202,6 +1225,7 @@ snprintf.lo snprintf.o: $(srcdir)/compat/snprintf.c config.h
strlcat.lo strlcat.o: $(srcdir)/compat/strlcat.c config.h
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h
strptime.lo strptime.o: $(srcdir)/compat/strptime.c config.h
strsep.lo strsep.o: $(srcdir)/compat/strsep.c config.h
getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h
getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c config.h
getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h

View file

@ -2,7 +2,9 @@
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
# BSD licensed.
#
# Version 32
# Version 34
# 2016-03-21 Check -ldl -pthread for libcrypto for ldns and openssl 1.1.0.
# 2016-03-21 Use HMAC_Update instead of HMAC_CTX_Init (for openssl-1.1.0).
# 2016-01-04 -D_DEFAULT_SOURCE defined with -D_BSD_SOURCE for Linux glibc 2.20
# 2015-12-11 FLTO check for new OSX, clang.
# 2015-11-18 spelling check fix.
@ -671,16 +673,16 @@ AC_DEFUN([ACX_SSL_CHECKS], [
ACX_RUNTIME_PATH_ADD([$ssldir/lib])
fi
AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto])
AC_MSG_CHECKING([for HMAC_Update in -lcrypto])
LIBS="$LIBS -lcrypto"
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
AC_TRY_LINK(, [
int HMAC_CTX_init(void);
(void)HMAC_CTX_init();
int HMAC_Update(void);
(void)HMAC_Update();
], [
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
[If you have HMAC_CTX_init])
AC_DEFINE([HAVE_HMAC_UPDATE], 1,
[If you have HMAC_Update])
], [
AC_MSG_RESULT(no)
# check if -lwsock32 or -lgdi32 are needed.
@ -690,11 +692,11 @@ AC_DEFUN([ACX_SSL_CHECKS], [
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32"
AC_MSG_CHECKING([if -lcrypto needs -lgdi32])
AC_TRY_LINK([], [
int HMAC_CTX_init(void);
(void)HMAC_CTX_init();
int HMAC_Update(void);
(void)HMAC_Update();
],[
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
[If you have HMAC_CTX_init])
AC_DEFINE([HAVE_HMAC_UPDATE], 1,
[If you have HMAC_Update])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
@ -704,15 +706,30 @@ AC_DEFUN([ACX_SSL_CHECKS], [
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
AC_MSG_CHECKING([if -lcrypto needs -ldl])
AC_TRY_LINK([], [
int HMAC_CTX_init(void);
(void)HMAC_CTX_init();
int HMAC_Update(void);
(void)HMAC_Update();
],[
AC_DEFINE([HAVE_HMAC_CTX_INIT], 1,
[If you have HMAC_CTX_init])
AC_DEFINE([HAVE_HMAC_UPDATE], 1,
[If you have HMAC_Update])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
LIBS="$BAKLIBS"
LIBSSL_LIBS="$BAKSSLLIBS"
LIBS="$LIBS -ldl -pthread"
LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
AC_TRY_LINK([], [
int HMAC_Update(void);
(void)HMAC_Update();
],[
AC_DEFINE([HAVE_HMAC_UPDATE], 1,
[If you have HMAC_Update])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
])
])
])
])

View file

@ -0,0 +1,702 @@
/*
* cachedb/cachedb.c - cache from a database external to the program module
*
* Copyright (c) 2016, 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 module that uses an external database to cache
* dns responses.
*/
#include "config.h"
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
#include "util/regional.h"
#include "util/net_help.h"
#include "util/config_file.h"
#include "util/data/msgreply.h"
#include "util/data/msgencode.h"
#include "services/cache/dns.h"
#include "validator/val_neg.h"
#include "validator/val_secalgo.h"
#include "iterator/iter_utils.h"
#include "sldns/parseutil.h"
#include "sldns/wire2str.h"
#include "sldns/sbuffer.h"
#define CACHEDB_HASHSIZE 256 /* bit hash */
/** the unit test testframe for cachedb, its module state contains
* a cache for a couple queries (in memory). */
struct testframe_moddata {
/** key for single stored data element, NULL if none */
char* stored_key;
/** data for single stored data element, NULL if none */
uint8_t* stored_data;
/** length of stored data */
size_t stored_datalen;
};
static int
testframe_init(struct module_env* env, struct cachedb_env* cachedb_env)
{
(void)env;
verbose(VERB_ALGO, "testframe_init");
cachedb_env->backend_data = (void*)calloc(1,
sizeof(struct testframe_moddata));
if(!cachedb_env->backend_data) {
log_err("out of memory");
return 0;
}
return 1;
}
static void
testframe_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
{
struct testframe_moddata* d = (struct testframe_moddata*)
cachedb_env->backend_data;
(void)env;
verbose(VERB_ALGO, "testframe_deinit");
if(!d)
return;
free(d->stored_key);
free(d->stored_data);
free(d);
}
static int
testframe_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
char* key, struct sldns_buffer* result_buffer)
{
struct testframe_moddata* d = (struct testframe_moddata*)
cachedb_env->backend_data;
(void)env;
verbose(VERB_ALGO, "testframe_lookup of %s", key);
if(d->stored_key && strcmp(d->stored_key, key) == 0) {
if(d->stored_datalen > sldns_buffer_capacity(result_buffer))
return 0; /* too large */
verbose(VERB_ALGO, "testframe_lookup found %d bytes",
(int)d->stored_datalen);
sldns_buffer_clear(result_buffer);
sldns_buffer_write(result_buffer, d->stored_data,
d->stored_datalen);
sldns_buffer_flip(result_buffer);
return 1;
}
return 0;
}
static void
testframe_store(struct module_env* env, struct cachedb_env* cachedb_env,
char* key, uint8_t* data, size_t data_len)
{
struct testframe_moddata* d = (struct testframe_moddata*)
cachedb_env->backend_data;
(void)env;
verbose(VERB_ALGO, "testframe_store %s (%d bytes)", key, (int)data_len);
/* free old data element (if any) */
free(d->stored_key);
d->stored_key = NULL;
free(d->stored_data);
d->stored_data = NULL;
d->stored_datalen = 0;
d->stored_data = memdup(data, data_len);
if(!d->stored_data) {
log_err("out of memory");
return;
}
d->stored_datalen = data_len;
d->stored_key = strdup(key);
if(!d->stored_key) {
free(d->stored_data);
d->stored_data = NULL;
d->stored_datalen = 0;
return;
}
/* (key,data) successfully stored */
}
/** The testframe backend is for unit tests */
static struct cachedb_backend testframe_backend = { "testframe",
testframe_init, testframe_deinit, testframe_lookup, testframe_store
};
/** find a particular backend from possible backends */
static struct cachedb_backend*
cachedb_find_backend(const char* str)
{
if(strcmp(str, testframe_backend.name) == 0)
return &testframe_backend;
/* TODO add more backends here */
return NULL;
}
/** apply configuration to cachedb module 'global' state */
static int
cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
{
const char* backend_str = "testframe"; /* TODO get from cfg */
if(backend_str && backend_str[0]) {
cachedb_env->backend = cachedb_find_backend(backend_str);
if(!cachedb_env->backend) {
log_err("cachedb: cannot find backend name '%s",
backend_str);
return NULL;
}
}
/* TODO see if more configuration needs to be applied or not */
return 1;
}
int
cachedb_init(struct module_env* env, int id)
{
struct cachedb_env* cachedb_env = (struct cachedb_env*)calloc(1,
sizeof(struct cachedb_env));
if(!cachedb_env) {
log_err("malloc failure");
return 0;
}
env->modinfo[id] = (void*)cachedb_env;
if(!cachedb_apply_cfg(cachedb_env, env->cfg)) {
log_err("cachedb: could not apply configuration settings.");
return 0;
}
/* see if a backend is selected */
if(!cachedb_env->backend || !cachedb_env->backend->name)
return 1;
if(!(*cachedb_env->backend->init)(env, cachedb_env)) {
log_err("cachedb: could not init %s backend",
cachedb_env->backend->name);
return 0;
}
cachedb_env->enabled = 1;
return 1;
}
void
cachedb_deinit(struct module_env* env, int id)
{
struct cachedb_env* cachedb_env;
if(!env || !env->modinfo[id])
return;
cachedb_env = (struct cachedb_env*)env->modinfo[id];
/* free contents */
/* TODO */
if(cachedb_env->enabled) {
(*cachedb_env->backend->deinit)(env, cachedb_env);
}
free(cachedb_env);
env->modinfo[id] = NULL;
}
/** new query for cachedb */
static int
cachedb_new(struct module_qstate* qstate, int id)
{
struct cachedb_qstate* iq = (struct cachedb_qstate*)regional_alloc(
qstate->region, sizeof(struct cachedb_qstate));
qstate->minfo[id] = iq;
if(!iq)
return 0;
memset(iq, 0, sizeof(*iq));
/* initialise it */
/* TODO */
return 1;
}
/**
* Return an error
* @param qstate: our query state
* @param id: module id
* @param rcode: error code (DNS errcode).
* @return: 0 for use by caller, to make notation easy, like:
* return error_response(..).
*/
static int
error_response(struct module_qstate* qstate, int id, int rcode)
{
verbose(VERB_QUERY, "return error response %s",
sldns_lookup_by_id(sldns_rcodes, rcode)?
sldns_lookup_by_id(sldns_rcodes, rcode)->name:"??");
qstate->return_rcode = rcode;
qstate->return_msg = NULL;
qstate->ext_state[id] = module_finished;
return 0;
}
/**
* Hash the query name, type, class and dbacess-secret into lookup buffer.
* @param qstate: query state with query info
* and env->cfg with secret.
* @param buf: returned buffer with hash to lookup
* @param len: length of the buffer.
*/
static void
calc_hash(struct module_qstate* qstate, char* buf, size_t len)
{
uint8_t clear[1024];
size_t clen = 0;
uint8_t hash[CACHEDB_HASHSIZE/8];
const char* hex = "0123456789ABCDEF";
const char* secret = "default"; /* TODO: from qstate->env->cfg */
size_t i;
/* copy the hash info into the clear buffer */
if(clen + qstate->qinfo.qname_len < sizeof(clear)) {
memmove(clear+clen, qstate->qinfo.qname,
qstate->qinfo.qname_len);
clen += qstate->qinfo.qname_len;
}
if(clen + 4 < sizeof(clear)) {
uint16_t t = htons(qstate->qinfo.qtype);
uint16_t c = htons(qstate->qinfo.qclass);
memmove(clear+clen, &t, 2);
memmove(clear+clen+2, &c, 2);
clen += 4;
}
if(secret && secret[0] && clen + strlen(secret) < sizeof(clear)) {
memmove(clear+clen, secret, strlen(secret));
clen += strlen(secret);
}
/* hash the buffer */
secalgo_hash_sha256(clear, clen, hash);
memset(clear, 0, clen);
/* hex encode output for portability (some online dbs need
* no nulls, no control characters, and so on) */
log_assert(len >= sizeof(hash)*2 + 1);
(void)len;
for(i=0; i<sizeof(hash); i++) {
buf[i*2] = hex[(hash[i]&0xf0)>>4];
buf[i*2+1] = hex[hash[i]&0x0f];
}
buf[sizeof(hash)*2] = 0;
}
/** convert data from return_msg into the data buffer */
static int
prep_data(struct module_qstate* qstate, struct sldns_buffer* buf)
{
uint64_t timestamp, expiry;
size_t oldlim;
struct edns_data edns;
memset(&edns, 0, sizeof(edns));
edns.edns_present = 1;
edns.bits = EDNS_DO;
edns.ext_rcode = 0;
edns.edns_version = EDNS_ADVERTISED_VERSION;
edns.udp_size = EDNS_ADVERTISED_SIZE;
if(!qstate->return_msg || !qstate->return_msg->rep)
return 0;
if(verbosity >= VERB_ALGO)
log_dns_msg("cachedb encoding", &qstate->return_msg->qinfo,
qstate->return_msg->rep);
if(!reply_info_answer_encode(&qstate->return_msg->qinfo,
qstate->return_msg->rep, 0, qstate->query_flags,
buf, 0, 1, qstate->env->scratch, 65535, &edns, 1, 0))
return 0;
/* TTLs in the return_msg are relative to time(0) so we have to
* store that, we also store the smallest ttl in the packet+time(0)
* as the packet expiry time */
/* qstate->return_msg->rep->ttl contains that relative shortest ttl */
timestamp = (uint64_t)*qstate->env->now;
expiry = timestamp + (uint64_t)qstate->return_msg->rep->ttl;
timestamp = htobe64(timestamp);
expiry = htobe64(expiry);
oldlim = sldns_buffer_limit(buf);
if(oldlim + sizeof(timestamp)+sizeof(expiry) >=
sldns_buffer_capacity(buf))
return 0; /* doesn't fit. */
sldns_buffer_set_limit(buf, oldlim + sizeof(timestamp)+sizeof(expiry));
sldns_buffer_write_at(buf, oldlim, &timestamp, sizeof(timestamp));
sldns_buffer_write_at(buf, oldlim+sizeof(timestamp), &expiry,
sizeof(expiry));
return 1;
}
/** check expiry, return true if matches OK */
static int
good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
{
uint64_t expiry;
/* the expiry time is the last bytes of the buffer */
if(sldns_buffer_limit(buf) < sizeof(expiry))
return 0;
sldns_buffer_read_at(buf, sldns_buffer_limit(buf)-sizeof(expiry),
&expiry, sizeof(expiry));
expiry = be64toh(expiry);
if((time_t)expiry < *qstate->env->now)
return 0;
return 1;
}
/** convert dns message in buffer to return_msg */
static int
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
{
struct msg_parse* prs;
struct edns_data edns;
uint64_t timestamp, expiry;
time_t adjust;
size_t lim = sldns_buffer_limit(buf);
if(lim < LDNS_HEADER_SIZE+sizeof(timestamp)+sizeof(expiry))
return 0; /* too short */
/* remove timestamp and expiry from end */
sldns_buffer_read_at(buf, lim-sizeof(expiry), &expiry, sizeof(expiry));
sldns_buffer_read_at(buf, lim-sizeof(expiry)-sizeof(timestamp),
&timestamp, sizeof(timestamp));
expiry = be64toh(expiry);
timestamp = be64toh(timestamp);
/* parse DNS packet */
regional_free_all(qstate->env->scratch);
prs = (struct msg_parse*)regional_alloc(qstate->env->scratch,
sizeof(struct msg_parse));
if(!prs)
return 0; /* out of memory */
memset(prs, 0, sizeof(*prs));
memset(&edns, 0, sizeof(edns));
sldns_buffer_set_limit(buf, lim - sizeof(expiry)-sizeof(timestamp));
if(parse_packet(buf, prs, qstate->env->scratch) != LDNS_RCODE_NOERROR) {
sldns_buffer_set_limit(buf, lim);
return 0;
}
if(parse_extract_edns(prs, &edns, qstate->env->scratch) !=
LDNS_RCODE_NOERROR) {
sldns_buffer_set_limit(buf, lim);
return 0;
}
qstate->return_msg = dns_alloc_msg(buf, prs, qstate->region);
sldns_buffer_set_limit(buf, lim);
if(!qstate->return_msg)
return 0;
qstate->return_rcode = LDNS_RCODE_NOERROR;
/* see how much of the TTL expired, and remove it */
adjust = *qstate->env->now - (time_t)timestamp;
verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
/*adjust_msg(qstate->return_msg, adjust);*/
/* TODO:
msg->rep->ttl = r->ttl - adjust;
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
for(i=0; i<d->count + d->rrsig_count; i++) {
if(d->rr_ttl[i] < adjust)
d->rr_ttl[i] = 0;
else d->rr_ttl[i] -= adjust;
}
if(d->ttl < adjust)
d->ttl = 0;
else d->ttl -= adjust;
*/
/* TODO */
return 0;
}
/**
* Lookup the qstate.qinfo in extcache, store in qstate.return_msg.
* return true if lookup was successful.
*/
static int
cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie)
{
char key[(CACHEDB_HASHSIZE/8)*2+1];
calc_hash(qstate, key, sizeof(key));
/* call backend to fetch data for key into scratch buffer */
if( !(*ie->backend->lookup)(qstate->env, ie, key,
qstate->env->scratch_buffer)) {
return 0;
}
/* check expiry date and check if query-data matches */
if( !good_expiry_and_qinfo(qstate, qstate->env->scratch_buffer) ) {
return 0;
}
/* parse dns message into return_msg */
if( !parse_data(qstate, qstate->env->scratch_buffer) ) {
return 0;
}
return 1;
}
/**
* Store the qstate.return_msg in extcache for key qstate.info
*/
static void
cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
{
char key[(CACHEDB_HASHSIZE/8)*2+1];
calc_hash(qstate, key, sizeof(key));
/* prepare data in scratch buffer */
if(!prep_data(qstate, qstate->env->scratch_buffer))
return;
/* call backend */
(*ie->backend->store)(qstate->env, ie, key,
sldns_buffer_begin(qstate->env->scratch_buffer),
sldns_buffer_limit(qstate->env->scratch_buffer));
}
/**
* See if unbound's internal cache can answer the query
*/
static int
cachedb_intcache_lookup(struct module_qstate* qstate)
{
struct dns_msg* msg;
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
qstate->qinfo.qname_len, qstate->qinfo.qtype,
qstate->qinfo.qclass, qstate->query_flags,
qstate->region, qstate->env->scratch);
if(!msg && qstate->env->neg_cache) {
/* lookup in negative cache; may result in
* NOERROR/NODATA or NXDOMAIN answers that need validation */
msg = val_neg_getmsg(qstate->env->neg_cache, &qstate->qinfo,
qstate->region, qstate->env->rrset_cache,
qstate->env->scratch_buffer,
*qstate->env->now, 1/*add SOA*/, NULL);
}
if(!msg)
return 0;
/* this is the returned msg */
qstate->return_rcode = LDNS_RCODE_NOERROR;
qstate->return_msg = msg;
return 1;
}
/**
* Store query into the internal cache of unbound.
*/
static void
cachedb_intcache_store(struct module_qstate* qstate)
{
if(!qstate->return_msg)
return;
(void)dns_cache_store(qstate->env, &qstate->qinfo,
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
qstate->region, qstate->query_flags);
}
/**
* Handle a cachedb module event with a query
* @param qstate: query state (from the mesh), passed between modules.
* contains qstate->env module environment with global caches and so on.
* @param iq: query state specific for this module. per-query.
* @param ie: environment specific for this module. global.
* @param id: module id.
*/
static void
cachedb_handle_query(struct module_qstate* qstate,
struct cachedb_qstate* ATTR_UNUSED(iq),
struct cachedb_env* ie, int id)
{
/* check if we are enabled, and skip if so */
if(!ie->enabled) {
/* pass request to next module */
qstate->ext_state[id] = module_wait_module;
return;
}
if(qstate->blacklist) {
/* cache is blacklisted */
/* pass request to next module */
qstate->ext_state[id] = module_wait_module;
return;
}
/* lookup inside unbound's internal cache */
if(cachedb_intcache_lookup(qstate)) {
if(verbosity >= VERB_ALGO)
log_dns_msg("cachedb internal cache lookup",
&qstate->return_msg->qinfo,
qstate->return_msg->rep);
/* we are done with the query */
qstate->ext_state[id] = module_finished;
return;
}
/* ask backend cache to see if we have data */
if(cachedb_extcache_lookup(qstate, ie)) {
if(verbosity >= VERB_ALGO)
log_dns_msg(ie->backend->name,
&qstate->return_msg->qinfo,
qstate->return_msg->rep);
/* store this result in internal cache */
cachedb_intcache_store(qstate);
/* we are done with the query */
qstate->ext_state[id] = module_finished;
return;
}
/* no cache fetches */
/* pass request to next module */
qstate->ext_state[id] = module_wait_module;
}
/**
* Handle a cachedb module event with a response from the iterator.
* @param qstate: query state (from the mesh), passed between modules.
* contains qstate->env module environment with global caches and so on.
* @param iq: query state specific for this module. per-query.
* @param ie: environment specific for this module. global.
* @param id: module id.
*/
static void
cachedb_handle_response(struct module_qstate* qstate,
struct cachedb_qstate* ATTR_UNUSED(iq), struct cachedb_env* ie, int id)
{
/* check if we are enabled, and skip if not */
if(!ie->enabled) {
/* we are done with the query */
qstate->ext_state[id] = module_finished;
return;
}
/* store the item into the backend cache */
cachedb_extcache_store(qstate, ie);
/* we are done with the query */
qstate->ext_state[id] = module_finished;
}
void
cachedb_operate(struct module_qstate* qstate, enum module_ev event, int id,
struct outbound_entry* outbound)
{
struct cachedb_env* ie = (struct cachedb_env*)qstate->env->modinfo[id];
struct cachedb_qstate* iq = (struct cachedb_qstate*)qstate->minfo[id];
verbose(VERB_QUERY, "cachedb[module %d] operate: extstate:%s event:%s",
id, strextstate(qstate->ext_state[id]), strmodulevent(event));
if(iq) log_query_info(VERB_QUERY, "cachedb operate: query",
&qstate->qinfo);
/* perform cachedb state machine */
if((event == module_event_new || event == module_event_pass) &&
iq == NULL) {
if(!cachedb_new(qstate, id)) {
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return;
}
iq = (struct cachedb_qstate*)qstate->minfo[id];
}
if(iq && (event == module_event_pass || event == module_event_new)) {
cachedb_handle_query(qstate, iq, ie, id);
return;
}
if(iq && (event == module_event_moddone)) {
cachedb_handle_response(qstate, iq, ie, id);
return;
}
if(iq && outbound) {
/* cachedb does not need to process responses at this time
* ignore it.
cachedb_process_response(qstate, iq, ie, id, outbound, event);
*/
return;
}
if(event == module_event_error) {
verbose(VERB_ALGO, "got called with event error, giving up");
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return;
}
log_err("bad event for cachedb");
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
void
cachedb_inform_super(struct module_qstate* ATTR_UNUSED(qstate),
int ATTR_UNUSED(id), struct module_qstate* ATTR_UNUSED(super))
{
/* cachedb does not use subordinate requests at this time */
verbose(VERB_ALGO, "cachedb inform_super was called");
}
void
cachedb_clear(struct module_qstate* qstate, int id)
{
struct cachedb_qstate* iq;
if(!qstate)
return;
iq = (struct cachedb_qstate*)qstate->minfo[id];
if(iq) {
/* free contents of iq */
/* TODO */
}
qstate->minfo[id] = NULL;
}
size_t
cachedb_get_mem(struct module_env* env, int id)
{
struct cachedb_env* ie = (struct cachedb_env*)env->modinfo[id];
if(!ie)
return 0;
return sizeof(*ie); /* TODO - more mem */
}
/**
* The cachedb function block
*/
static struct module_func_block cachedb_block = {
"cachedb",
&cachedb_init, &cachedb_deinit, &cachedb_operate,
&cachedb_inform_super, &cachedb_clear, &cachedb_get_mem
};
struct module_func_block*
cachedb_get_funcblock(void)
{
return &cachedb_block;
}
#endif /* USE_CACHEDB */

View file

@ -0,0 +1,110 @@
/*
* cachedb/cachedb.h - cache from a database external to the program module
*
* Copyright (c) 2016, 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 module that uses an external database to cache
* dns responses.
*/
#include "util/module.h"
struct cachedb_backend;
/**
* The global variable environment contents for the cachedb
* Shared between threads, this represents long term information.
* Like database connections.
*/
struct cachedb_env {
/** true is cachedb is enabled, the backend is turned on */
int enabled;
/** the backend routines */
struct cachedb_backend* backend;
/** backend specific data here */
void* backend_data;
};
/**
* Per query state for the cachedb module.
*/
struct cachedb_qstate {
int todo;
};
/**
* Backend call routines
*/
struct cachedb_backend {
/** backend name */
const char* name;
/** Init(env, cachedb_env): false on setup failure */
int (*init)(struct module_env*, struct cachedb_env*);
/** Deinit - close db for program exit */
void (*deinit)(struct module_env*, struct cachedb_env*);
/** Lookup (env, cachedb_env, key, result_buffer): true if found */
int (*lookup)(struct module_env*, struct cachedb_env*, char*,
struct sldns_buffer*);
/** Store (env, cachedb_env, key, data, data_len) */
void (*store)(struct module_env*, struct cachedb_env*, char*,
uint8_t*, size_t);
};
/** Init the cachedb module */
int cachedb_init(struct module_env* env, int id);
/** Deinit the cachedb module */
void cachedb_deinit(struct module_env* env, int id);
/** Operate on an event on a query (in qstate). */
void cachedb_operate(struct module_qstate* qstate, enum module_ev event,
int id, struct outbound_entry* outbound);
/** Subordinate query done, inform this super request of its conclusion */
void cachedb_inform_super(struct module_qstate* qstate, int id,
struct module_qstate* super);
/** clear the cachedb query-specific contents out of qstate */
void cachedb_clear(struct module_qstate* qstate, int id);
/** return memory estimate for cachedb module */
size_t cachedb_get_mem(struct module_env* env, int id);
/**
* Get the function block with pointers to the cachedb functions
* @return the function block for "cachedb".
*/
struct module_func_block* cachedb_get_funcblock(void);

View file

@ -6,7 +6,11 @@
#include "config.h"
#include <string.h>
#ifdef HAVE_ATTR_WEAK
__attribute__((weak)) void
#else
void
#endif
__explicit_bzero_hook(void *ATTR_UNUSED(buf), size_t ATTR_UNUSED(len))
{
}

View file

@ -94,7 +94,7 @@ int getentropy(void *buf, size_t len);
extern int main(int, char *argv[]);
#endif
static int gotdata(char *buf, size_t len);
#ifdef SYS_getrandom
#if defined(SYS_getrandom) && defined(__NR_getrandom)
static int getentropy_getrandom(void *buf, size_t len);
#endif
static int getentropy_urandom(void *buf, size_t len);
@ -113,7 +113,7 @@ getentropy(void *buf, size_t len)
return -1;
}
#ifdef SYS_getrandom
#if defined(SYS_getrandom) && defined(__NR_getrandom)
/*
* Try descriptor-less getrandom()
*/
@ -209,7 +209,7 @@ gotdata(char *buf, size_t len)
return 0;
}
#ifdef SYS_getrandom
#if defined(SYS_getrandom) && defined(__NR_getrandom)
static int
getentropy_getrandom(void *buf, size_t len)
{

View file

@ -0,0 +1,65 @@
/**
* strsep implementation for compatibility.
*
* LICENSE
* Copyright (c) 2016, NLnet Labs
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of NLnetLabs 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 OWNER 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.
**/
#include "config.h"
/** see if character is in the delimiter array */
static int
in_delim(char c, const char* delim)
{
const char* p;
if(!delim)
return 0;
for(p=delim; *p; p++) {
if(*p == c)
return 1;
}
return 0;
}
char *strsep(char **stringp, const char *delim)
{
char* s;
char* orig;
if(stringp == NULL || *stringp == NULL)
return NULL;
orig = *stringp;
s = *stringp;
while(*s && !in_delim(*s, delim))
s++;
if(*s) {
*s = 0;
*stringp = s+1;
} else {
*stringp = NULL;
}
return orig;
}

View file

@ -43,6 +43,9 @@
/* Whether the C compiler accepts the "unused" attribute */
#define HAVE_ATTR_UNUSED 1
/* Whether the C compiler accepts the "weak" attribute */
#define HAVE_ATTR_WEAK 1
/* Define to 1 if you have the `chown' function. */
#define HAVE_CHOWN 1
@ -126,6 +129,9 @@
/* Define to 1 if you have the <event.h> header file. */
/* #undef HAVE_EVENT_H */
/* Define to 1 if you have the `EVP_MD_CTX_new' function. */
/* #undef HAVE_EVP_MD_CTX_NEW */
/* Define to 1 if you have the `EVP_sha1' function. */
#define HAVE_EVP_SHA1 1
@ -189,8 +195,8 @@
/* Define to 1 if you have the <grp.h> header file. */
#define HAVE_GRP_H 1
/* If you have HMAC_CTX_init */
#define HAVE_HMAC_CTX_INIT 1
/* If you have HMAC_Update */
#define HAVE_HMAC_UPDATE 1
/* Define to 1 if you have the `inet_aton' function. */
#define HAVE_INET_ATON 1
@ -378,6 +384,9 @@
/* Define to 1 if you have the `strptime' function. */
#define HAVE_STRPTIME 1
/* Define to 1 if you have the `strsep' function. */
#define HAVE_STRSEP 1
/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
/* #undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST */
@ -515,7 +524,7 @@
#define PACKAGE_NAME "unbound"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "unbound 1.5.8"
#define PACKAGE_STRING "unbound 1.5.9"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "unbound"
@ -524,7 +533,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.5.8"
#define PACKAGE_VERSION "1.5.9"
/* default pidfile location */
#define PIDFILE "/var/unbound/unbound.pid"
@ -543,7 +552,7 @@
#define ROOT_CERT_FILE "/var/unbound/icannbundle.pem"
/* version number for resource files */
#define RSRC_PACKAGE_VERSION 1,5,8,0
#define RSRC_PACKAGE_VERSION 1,5,9,0
/* Directory to chdir to */
#define RUN_DIR "/var/unbound"
@ -581,9 +590,15 @@
/* define this to enable debug checks. */
/* #undef UNBOUND_DEBUG */
/* Define to 1 to use cachedb support */
/* #undef USE_CACHEDB */
/* Define to 1 to enable dnstap support */
/* #undef USE_DNSTAP */
/* Define this to enable DSA support. */
#define USE_DSA 1
/* Define this to enable ECDSA support. */
#define USE_ECDSA 1
@ -980,6 +995,11 @@ int memcmp(const void *x, const void *y, size_t n);
char *ctime_r(const time_t *timep, char *buf);
#endif
#ifndef HAVE_STRSEP
#define strsep unbound_strsep
char *strsep(char **stringp, const char *delim);
#endif
#ifndef HAVE_ISBLANK
#define isblank unbound_isblank
int isblank(int c);

View file

@ -42,6 +42,9 @@
/* Whether the C compiler accepts the "unused" attribute */
#undef HAVE_ATTR_UNUSED
/* Whether the C compiler accepts the "weak" attribute */
#undef HAVE_ATTR_WEAK
/* Define to 1 if you have the `chown' function. */
#undef HAVE_CHOWN
@ -125,6 +128,9 @@
/* Define to 1 if you have the <event.h> header file. */
#undef HAVE_EVENT_H
/* Define to 1 if you have the `EVP_MD_CTX_new' function. */
#undef HAVE_EVP_MD_CTX_NEW
/* Define to 1 if you have the `EVP_sha1' function. */
#undef HAVE_EVP_SHA1
@ -188,8 +194,8 @@
/* Define to 1 if you have the <grp.h> header file. */
#undef HAVE_GRP_H
/* If you have HMAC_CTX_init */
#undef HAVE_HMAC_CTX_INIT
/* If you have HMAC_Update */
#undef HAVE_HMAC_UPDATE
/* Define to 1 if you have the `inet_aton' function. */
#undef HAVE_INET_ATON
@ -377,6 +383,9 @@
/* Define to 1 if you have the `strptime' function. */
#undef HAVE_STRPTIME
/* Define to 1 if you have the `strsep' function. */
#undef HAVE_STRSEP
/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
#undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
@ -580,9 +589,15 @@
/* define this to enable debug checks. */
#undef UNBOUND_DEBUG
/* Define to 1 to use cachedb support */
#undef USE_CACHEDB
/* Define to 1 to enable dnstap support */
#undef USE_DNSTAP
/* Define this to enable DSA support. */
#undef USE_DSA
/* Define this to enable ECDSA support. */
#undef USE_ECDSA
@ -979,6 +994,11 @@ int memcmp(const void *x, const void *y, size_t n);
char *ctime_r(const time_t *timep, char *buf);
#endif
#ifndef HAVE_STRSEP
#define strsep unbound_strsep
char *strsep(char **stringp, const char *delim);
#endif
#ifndef HAVE_ISBLANK
#define isblank unbound_isblank
int isblank(int c);

View file

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for unbound 1.5.8.
# Generated by GNU Autoconf 2.69 for unbound 1.5.9.
#
# Report bugs to <unbound-bugs@nlnetlabs.nl>.
#
@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unbound'
PACKAGE_TARNAME='unbound'
PACKAGE_VERSION='1.5.8'
PACKAGE_STRING='unbound 1.5.8'
PACKAGE_VERSION='1.5.9'
PACKAGE_STRING='unbound 1.5.9'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
PACKAGE_URL=''
@ -832,6 +832,7 @@ with_ssl
enable_sha2
enable_gost
enable_ecdsa
enable_dsa
enable_event_api
with_libevent
with_libexpat
@ -842,6 +843,7 @@ enable_dnstap
with_dnstap_socket_path
with_protobuf_c
with_libfstrm
enable_cachedb
with_libunbound_only
'
ac_precious_vars='build_alias
@ -1397,7 +1399,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures unbound 1.5.8 to adapt to many kinds of systems.
\`configure' configures unbound 1.5.9 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1462,7 +1464,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of unbound 1.5.8:";;
short | recursive ) echo "Configuration of unbound 1.5.9:";;
esac
cat <<\_ACEOF
@ -1495,8 +1497,9 @@ Optional Features:
--disable-sha2 Disable SHA256 and SHA512 RRSIG support
--disable-gost Disable GOST support
--disable-ecdsa Disable ECDSA support
--enable-event-api Enable (experimental) libevent-based libunbound API
installed to unbound-event.h
--disable-dsa Disable DSA support
--enable-event-api Enable (experimental) pluggable event base
libunbound API installed to unbound-event.h
--enable-static-exe enable to compile executables statically against
(event) libs, for debug purposes
--enable-lock-checks enable to check lock and unlock calls, for debug
@ -1505,6 +1508,8 @@ Optional Features:
to it, smaller install size but libunbound export
table is polluted by internal symbols
--enable-dnstap Enable dnstap support (requires fstrm, protobuf-c)
--enable-cachedb enable cachedb module that can use external cache
storage
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@ -1647,7 +1652,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
unbound configure 1.5.8
unbound configure 1.5.9
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -2356,7 +2361,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by unbound $as_me 1.5.8, which was
It was created by unbound $as_me 1.5.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -2708,11 +2713,11 @@ UNBOUND_VERSION_MAJOR=1
UNBOUND_VERSION_MINOR=5
UNBOUND_VERSION_MICRO=8
UNBOUND_VERSION_MICRO=9
LIBUNBOUND_CURRENT=6
LIBUNBOUND_REVISION=0
LIBUNBOUND_REVISION=1
LIBUNBOUND_AGE=4
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@ -2760,6 +2765,7 @@ LIBUNBOUND_AGE=4
# 1.5.6 had 5:9:3
# 1.5.7 had 5:10:3
# 1.5.8 had 6:0:4 # adds ub_ctx_set_stub
# 1.5.9 had 6:1:4
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@ -6117,6 +6123,48 @@ $as_echo "#define HAVE_ATTR_UNUSED 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler (${CC-cc}) accepts the \"weak\" attribute" >&5
$as_echo_n "checking whether the C compiler (${CC-cc}) accepts the \"weak\" attribute... " >&6; }
if ${ac_cv_c_weak_attribute+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_c_weak_attribute=no
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
__attribute__((weak)) void f(int x) { printf("%d", x); }
int
main ()
{
f(1);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_c_weak_attribute="yes"
else
ac_cv_c_weak_attribute="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_weak_attribute" >&5
$as_echo "$ac_cv_c_weak_attribute" >&6; }
if test $ac_cv_c_weak_attribute = yes; then
$as_echo "#define HAVE_ATTR_WEAK 1" >>confdefs.h
fi
if test "$srcdir" != "."; then
CPPFLAGS="$CPPFLAGS -I$srcdir"
fi
@ -17064,8 +17112,8 @@ $as_echo "found in $ssldir" >&6; }
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for HMAC_CTX_init in -lcrypto" >&5
$as_echo_n "checking for HMAC_CTX_init in -lcrypto... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for HMAC_Update in -lcrypto" >&5
$as_echo_n "checking for HMAC_Update in -lcrypto... " >&6; }
LIBS="$LIBS -lcrypto"
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@ -17075,8 +17123,8 @@ int
main ()
{
int HMAC_CTX_init(void);
(void)HMAC_CTX_init();
int HMAC_Update(void);
(void)HMAC_Update();
;
return 0;
@ -17087,7 +17135,7 @@ if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_HMAC_CTX_INIT 1" >>confdefs.h
$as_echo "#define HAVE_HMAC_UPDATE 1" >>confdefs.h
else
@ -17108,8 +17156,8 @@ int
main ()
{
int HMAC_CTX_init(void);
(void)HMAC_CTX_init();
int HMAC_Update(void);
(void)HMAC_Update();
;
return 0;
@ -17118,7 +17166,7 @@ _ACEOF
if ac_fn_c_try_link "$LINENO"; then :
$as_echo "#define HAVE_HMAC_CTX_INIT 1" >>confdefs.h
$as_echo "#define HAVE_HMAC_UPDATE 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@ -17140,8 +17188,8 @@ int
main ()
{
int HMAC_CTX_init(void);
(void)HMAC_CTX_init();
int HMAC_Update(void);
(void)HMAC_Update();
;
return 0;
@ -17150,7 +17198,7 @@ _ACEOF
if ac_fn_c_try_link "$LINENO"; then :
$as_echo "#define HAVE_HMAC_CTX_INIT 1" >>confdefs.h
$as_echo "#define HAVE_HMAC_UPDATE 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@ -17159,7 +17207,43 @@ else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
as_fn_error $? "OpenSSL found in $ssldir, but version 0.9.7 or higher is required" "$LINENO" 5
LIBS="$BAKLIBS"
LIBSSL_LIBS="$BAKSSLLIBS"
LIBS="$LIBS -ldl -pthread"
LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -ldl -pthread" >&5
$as_echo_n "checking if -lcrypto needs -ldl -pthread... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
int HMAC_Update(void);
(void)HMAC_Update();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
$as_echo "#define HAVE_HMAC_UPDATE 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
as_fn_error $? "OpenSSL found in $ssldir, but version 0.9.7 or higher is required" "$LINENO" 5
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext \
@ -17404,7 +17488,7 @@ fi
done
for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode
for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@ -17771,15 +17855,46 @@ _ACEOF
;;
esac
# Check whether --enable-dsa was given.
if test "${enable_dsa+set}" = set; then :
enableval=$enable_dsa;
fi
use_dsa="no"
case "$enable_ecdsa" in
no)
;;
*)
# detect if DSA is supported, and turn it off if not.
ac_fn_c_check_func "$LINENO" "EVP_dss1" "ac_cv_func_EVP_dss1"
if test "x$ac_cv_func_EVP_dss1" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define USE_DSA 1
_ACEOF
else
if test "x$enable_dsa" = "xyes"; then as_fn_error $? "OpenSSL does not support DSA and you used --enable-dsa." "$LINENO" 5
fi
fi
;;
esac
# Check whether --enable-event-api was given.
if test "${enable_event_api+set}" = set; then :
enableval=$enable_event_api;
fi
use_unbound_event="no"
case "$enable_event_api" in
yes)
use_unbound_event="yes"
UNBOUND_EVENT_INSTALL=unbound-event-install
UNBOUND_EVENT_UNINSTALL=unbound-event-uninstall
;;
*)
;;
@ -18126,12 +18241,6 @@ done
if test -n "$BAK_LDFLAGS_SET"; then
LDFLAGS="$BAK_LDFLAGS"
fi
if test "$use_unbound_event" = "yes"; then
UNBOUND_EVENT_INSTALL=unbound-event-install
UNBOUND_EVENT_UNINSTALL=unbound-event-uninstall
fi
else
$as_echo "#define USE_MINI_EVENT 1" >>confdefs.h
@ -19237,6 +19346,20 @@ esac
fi
ac_fn_c_check_func "$LINENO" "strsep" "ac_cv_func_strsep"
if test "x$ac_cv_func_strsep" = xyes; then :
$as_echo "#define HAVE_STRSEP 1" >>confdefs.h
else
case " $LIBOBJS " in
*" strsep.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS strsep.$ac_objext"
;;
esac
fi
# Check whether --enable-allsymbols was given.
if test "${enable_allsymbols+set}" = set; then :
@ -19520,6 +19643,23 @@ _ACEOF
fi
# check for cachedb if requested
# Check whether --enable-cachedb was given.
if test "${enable_cachedb+set}" = set; then :
enableval=$enable_cachedb;
fi
case "$enable_cachedb" in
yes)
$as_echo "#define USE_CACHEDB 1" >>confdefs.h
;;
no|*)
# nothing
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if ${MAKE:-make} supports $< with implicit rule in scope" >&5
$as_echo_n "checking if ${MAKE:-make} supports $< with implicit rule in scope... " >&6; }
# on openBSD, the implicit rule make $< work.
@ -19661,7 +19801,7 @@ _ACEOF
version=1.5.8
version=1.5.9
date=`date +'%b %e, %Y'`
@ -20176,7 +20316,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by unbound $as_me 1.5.8, which was
This file was extended by unbound $as_me 1.5.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -20242,7 +20382,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
unbound config.status 1.5.8
unbound config.status 1.5.9
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View file

@ -10,14 +10,14 @@ sinclude(dnstap/dnstap.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[5])
m4_define([VERSION_MICRO],[8])
m4_define([VERSION_MICRO],[9])
AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), unbound-bugs@nlnetlabs.nl, unbound)
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
LIBUNBOUND_CURRENT=6
LIBUNBOUND_REVISION=0
LIBUNBOUND_REVISION=1
LIBUNBOUND_AGE=4
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@ -65,6 +65,7 @@ LIBUNBOUND_AGE=4
# 1.5.6 had 5:9:3
# 1.5.7 had 5:10:3
# 1.5.8 had 6:0:4 # adds ub_ctx_set_stub
# 1.5.9 had 6:1:4
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@ -257,6 +258,29 @@ AC_C_INLINE
ACX_CHECK_FORMAT_ATTRIBUTE
ACX_CHECK_UNUSED_ATTRIBUTE
AC_DEFUN([CHECK_WEAK_ATTRIBUTE],
[AC_REQUIRE([AC_PROG_CC])
AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "weak" attribute)
AC_CACHE_VAL(ac_cv_c_weak_attribute,
[ac_cv_c_weak_attribute=no
AC_TRY_COMPILE(
[ #include <stdio.h>
__attribute__((weak)) void f(int x) { printf("%d", x); }
], [
f(1);
],
[ac_cv_c_weak_attribute="yes"],
[ac_cv_c_weak_attribute="no"])
])
AC_MSG_RESULT($ac_cv_c_weak_attribute)
if test $ac_cv_c_weak_attribute = yes; then
AC_DEFINE(HAVE_ATTR_WEAK, 1, [Whether the C compiler accepts the "weak" attribute])
fi
])dnl End of CHECK_WEAK_ATTRIBUTE
CHECK_WEAK_ATTRIBUTE
if test "$srcdir" != "."; then
CPPFLAGS="$CPPFLAGS -I$srcdir"
fi
@ -634,7 +658,7 @@ else
fi
AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode])
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new])
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
AC_INCLUDES_DEFAULT
#ifdef HAVE_OPENSSL_ERR_H
@ -816,11 +840,26 @@ case "$enable_ecdsa" in
;;
esac
AC_ARG_ENABLE(event-api, AC_HELP_STRING([--enable-event-api], [Enable (experimental) libevent-based libunbound API installed to unbound-event.h]))
use_unbound_event="no"
AC_ARG_ENABLE(dsa, AC_HELP_STRING([--disable-dsa], [Disable DSA support]))
use_dsa="no"
case "$enable_ecdsa" in
no)
;;
*)
# detect if DSA is supported, and turn it off if not.
AC_CHECK_FUNC(EVP_dss1, [
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
fi ])
;;
esac
AC_ARG_ENABLE(event-api, AC_HELP_STRING([--enable-event-api], [Enable (experimental) pluggable event base libunbound API installed to unbound-event.h]))
case "$enable_event_api" in
yes)
use_unbound_event="yes"
AC_SUBST(UNBOUND_EVENT_INSTALL, [unbound-event-install])
AC_SUBST(UNBOUND_EVENT_UNINSTALL, [unbound-event-uninstall])
;;
*)
;;
@ -906,10 +945,6 @@ large outgoing port ranges. ])
if test -n "$BAK_LDFLAGS_SET"; then
LDFLAGS="$BAK_LDFLAGS"
fi
if test "$use_unbound_event" = "yes"; then
AC_SUBST(UNBOUND_EVENT_INSTALL, [unbound-event-install])
AC_SUBST(UNBOUND_EVENT_UNINSTALL, [unbound-event-uninstall])
fi
else
AC_DEFINE(USE_MINI_EVENT, 1, [Define if you want to use internal select based events])
fi
@ -1140,6 +1175,7 @@ fi
LIBOBJ_WITHOUT_CTIME="$LIBOBJS"
AC_SUBST(LIBOBJ_WITHOUT_CTIME)
AC_REPLACE_FUNCS(ctime_r)
AC_REPLACE_FUNCS(strsep)
AC_ARG_ENABLE(allsymbols, AC_HELP_STRING([--enable-allsymbols], [export all symbols from libunbound and link binaries to it, smaller install size but libunbound export table is polluted by internal symbols]))
case "$enable_allsymbols" in
@ -1192,6 +1228,17 @@ dt_DNSTAP([$UNBOUND_RUN_DIR/dnstap.sock],
]
)
# check for cachedb if requested
AC_ARG_ENABLE(cachedb, AC_HELP_STRING([--enable-cachedb], [enable cachedb module that can use external cache storage]))
case "$enable_cachedb" in
yes)
AC_DEFINE([USE_CACHEDB], [1], [Define to 1 to use cachedb support])
;;
no|*)
# nothing
;;
esac
AC_MSG_CHECKING([if ${MAKE:-make} supports $< with implicit rule in scope])
# on openBSD, the implicit rule make $< work.
# on Solaris, it does not work ($? is changed sources, $^ lists dependencies).
@ -1358,6 +1405,11 @@ AHX_MEMCMP_BROKEN(unbound)
char *ctime_r(const time_t *timep, char *buf);
#endif
#ifndef HAVE_STRSEP
#define strsep unbound_strsep
char *strsep(char **stringp, const char *delim);
#endif
#ifndef HAVE_ISBLANK
#define isblank unbound_isblank
int isblank(int c);

View file

@ -206,9 +206,6 @@ daemon_init(void)
#ifdef HAVE_SSL
ERR_load_crypto_strings();
ERR_load_SSL_strings();
# ifdef HAVE_OPENSSL_CONFIG
OPENSSL_config("unbound");
# endif
# ifdef USE_GOST
(void)sldns_key_EVP_load_gost_id();
# endif
@ -647,18 +644,23 @@ daemon_delete(struct daemon* daemon)
# endif
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE
# ifndef S_SPLINT_S
# if OPENSSL_VERSION_NUMBER < 0x10100000
sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free);
# endif
# endif
# endif
# ifdef HAVE_OPENSSL_CONFIG
EVP_cleanup();
# if OPENSSL_VERSION_NUMBER < 0x10100000
ENGINE_cleanup();
# endif
CONF_modules_free();
# endif
CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */
ERR_remove_state(0);
ERR_free_strings();
# if OPENSSL_VERSION_NUMBER < 0x10100000
RAND_cleanup();
# endif
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
ub_openssl_lock_delete();
# endif

View file

@ -45,9 +45,6 @@
#include "util/locks.h"
#include "util/alloc.h"
#include "services/modstack.h"
#ifdef UB_ON_WINDOWS
# include "util/winsock_event.h"
#endif
struct config_file;
struct worker;
struct listen_port;

View file

@ -140,46 +140,46 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d)
/*
* The following function was generated using the openssl utility, using
* the command : "openssl dhparam -dsaparam -C 1024"
* the command : "openssl dhparam -C 2048"
* (some openssl versions reject DH that is 'too small', eg. 512).
*/
#ifndef S_SPLINT_S
DH *get_dh1024()
DH *get_dh2048()
{
static unsigned char dh1024_p[]={
0xB3,0x67,0x2E,0x3B,0x68,0xC5,0xDA,0x58,0x46,0xD6,0x2B,0xD3,
0x41,0x78,0x97,0xE4,0xE1,0x61,0x71,0x68,0xE6,0x0F,0x1D,0x78,
0x05,0xAA,0xF0,0xFF,0x30,0xDF,0xAC,0x49,0x7F,0xE0,0x90,0xFE,
0xB9,0x56,0x4E,0x3F,0xE2,0x98,0x8A,0xED,0xF5,0x28,0x39,0xEF,
0x2E,0xA6,0xB7,0x67,0xB2,0x43,0xE4,0x53,0xF8,0xEB,0x2C,0x1F,
0x06,0x77,0x3A,0x6F,0x62,0x98,0xC1,0x3B,0xF7,0xBA,0x4D,0x93,
0xF7,0xEB,0x5A,0xAD,0xC5,0x5F,0xF0,0xB7,0x24,0x35,0x81,0xF7,
0x7F,0x1F,0x24,0xC0,0xDF,0xD3,0xD8,0x40,0x72,0x7E,0xF3,0x19,
0x2B,0x26,0x27,0xF4,0xB6,0xB3,0xD4,0x7D,0x08,0x23,0xBE,0x68,
0x2B,0xCA,0xB4,0x46,0xA8,0x9E,0xDD,0x6C,0x3D,0x75,0xA6,0x48,
0xF7,0x44,0x43,0xBF,0x91,0xC2,0xB4,0x49,
static unsigned char dh2048_p[]={
0xE7,0x36,0x28,0x3B,0xE4,0xC3,0x32,0x1C,0x01,0xC3,0x67,0xD6,
0xF5,0xF3,0xDA,0xDC,0x71,0xC0,0x42,0x8B,0xE6,0xEB,0x8D,0x80,
0x35,0x7F,0x09,0x45,0x30,0xE5,0xB2,0x92,0x81,0x3F,0x08,0xCD,
0x36,0x5E,0x19,0x83,0x62,0xCC,0xAE,0x9B,0x81,0x66,0x24,0xEE,
0x16,0x6F,0xA9,0x9E,0xF4,0x82,0x1B,0xDD,0x46,0xC7,0x33,0x5D,
0xF4,0xCA,0xE6,0x8F,0xFC,0xD4,0xD8,0x58,0x94,0x24,0x5D,0xFF,
0x0A,0xE8,0xEF,0x3D,0xCE,0xBB,0x50,0x94,0xE0,0x5F,0xE8,0x41,
0xC3,0x35,0x30,0x37,0xD5,0xCB,0x8F,0x3D,0x95,0x15,0x1A,0x77,
0x42,0xB2,0x06,0x86,0xF6,0x09,0x66,0x0E,0x9A,0x25,0x94,0x3E,
0xD2,0x04,0x25,0x25,0x1D,0x23,0xEB,0xDC,0x4D,0x0C,0x83,0x28,
0x2E,0x15,0x81,0x2D,0xC1,0xAF,0x8D,0x36,0x64,0xE3,0x9A,0x83,
0x78,0xC2,0x8D,0xC0,0x9D,0xD9,0x3A,0x1C,0xC5,0x2B,0x50,0x68,
0x07,0xA9,0x4B,0x8C,0x07,0x57,0xD6,0x15,0x03,0x4E,0x9E,0x01,
0xF2,0x6F,0x35,0xAC,0x26,0x9C,0x92,0x68,0x61,0x13,0xFB,0x01,
0xBA,0x22,0x36,0x01,0x55,0xB6,0x62,0xD9,0xB2,0x98,0xCE,0x5D,
0x4B,0xA5,0x41,0xD6,0xE5,0x70,0x78,0x12,0x1F,0x64,0xB6,0x6F,
0xB0,0x91,0x51,0x91,0x92,0xC0,0x94,0x3A,0xD1,0x28,0x4D,0x30,
0x84,0x3E,0xE4,0xE4,0x7F,0x47,0x89,0xB1,0xB6,0x8C,0x8E,0x0E,
0x26,0xDB,0xCD,0x17,0x07,0x2A,0x21,0x7A,0xCC,0x68,0xE8,0x57,
0x94,0x9E,0x59,0x61,0xEC,0x20,0x34,0x26,0x0D,0x66,0x44,0xEB,
0x6F,0x02,0x58,0xE2,0xED,0xF6,0xF3,0x1B,0xBF,0x9E,0x45,0x52,
0x5A,0x49,0xA1,0x5B,
};
static unsigned char dh1024_g[]={
0x5F,0x37,0xB5,0x80,0x4D,0xB4,0xC4,0xB2,0x37,0x12,0xD5,0x2F,
0x56,0x81,0xB0,0xDF,0x3D,0x27,0xA2,0x54,0xE7,0x14,0x65,0x2D,
0x72,0xA8,0x97,0xE0,0xA9,0x4A,0x09,0x5E,0x89,0xBE,0x34,0x9A,
0x90,0x98,0xC1,0xE8,0xBB,0x01,0x2B,0xC2,0x74,0x74,0x90,0x59,
0x0B,0x72,0x62,0x5C,0xFD,0x49,0x63,0x4B,0x38,0x91,0xF1,0x7F,
0x13,0x25,0xEB,0x52,0x50,0x47,0xA2,0x8C,0x32,0x28,0x42,0xAC,
0xBD,0x7A,0xCC,0x58,0xBE,0x36,0xDA,0x6A,0x24,0x06,0xC7,0xF1,
0xDA,0x8D,0x8A,0x3B,0x03,0xFA,0x6F,0x25,0xE5,0x20,0xA7,0xD6,
0x6F,0x74,0x61,0x53,0x14,0x81,0x29,0x04,0xB5,0x61,0x12,0x53,
0xA3,0xD6,0x09,0x98,0x0C,0x8F,0x1C,0xBB,0xD7,0x1C,0x2C,0xEE,
0x56,0x4B,0x74,0x8F,0x4A,0xF8,0xA9,0xD5,
static unsigned char dh2048_g[]={
0x02,
};
DH *dh;
if ((dh=DH_new()) == NULL) return(NULL);
dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL);
dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL);
dh->p=BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL);
dh->g=BN_bin2bn(dh2048_g,sizeof(dh2048_g),NULL);
if ((dh->p == NULL) || (dh->g == NULL))
{ DH_free(dh); return(NULL); }
dh->length = 160;
return(dh);
}
#endif /* SPLINT */
@ -231,7 +231,7 @@ daemon_remote_create(struct config_file* cfg)
/* Since we have no certificates and hence no source of
* DH params, let's generate and set them
*/
if(!SSL_CTX_set_tmp_dh(rc->ctx,get_dh1024())) {
if(!SSL_CTX_set_tmp_dh(rc->ctx,get_dh2048())) {
log_crypto_err("Wanted to set DH param, but failed");
return NULL;
}
@ -389,7 +389,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
/* open fd */
fd = create_tcp_accept_sock(res, 1, &noproto, 0,
cfg->ip_transparent, 0);
cfg->ip_transparent, 0, cfg->ip_freebind);
freeaddrinfo(res);
}

View file

@ -57,6 +57,7 @@
#include "util/data/msgreply.h"
#include "util/module.h"
#include "util/net_help.h"
#include "util/ub_event.h"
#include <signal.h>
#include <fcntl.h>
#include <openssl/crypto.h>
@ -77,22 +78,6 @@
#include <login_cap.h>
#endif
#ifdef USE_MINI_EVENT
# ifdef USE_WINSOCK
# include "util/winsock_event.h"
# else
# include "util/mini_event.h"
# endif
#else
# ifdef HAVE_EVENT_H
# include <event.h>
# else
# include "event2/event.h"
# include "event2/event_struct.h"
# include "event2/event_compat.h"
# endif
#endif
#ifdef UB_ON_WINDOWS
# include "winrc/win_svc.h"
#endif
@ -107,54 +92,6 @@
void* unbound_start_brk = 0;
#endif
#if !defined(HAVE_EVENT_BASE_GET_METHOD) && (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP))
static const char* ev_backend2str(int b)
{
switch(b) {
case EVBACKEND_SELECT: return "select";
case EVBACKEND_POLL: return "poll";
case EVBACKEND_EPOLL: return "epoll";
case EVBACKEND_KQUEUE: return "kqueue";
case EVBACKEND_DEVPOLL: return "devpoll";
case EVBACKEND_PORT: return "evport";
}
return "unknown";
}
#endif
/** get the event system in use */
static void get_event_sys(const char** n, const char** s, const char** m)
{
#ifdef USE_WINSOCK
*n = "event";
*s = "winsock";
*m = "WSAWaitForMultipleEvents";
#elif defined(USE_MINI_EVENT)
*n = "mini-event";
*s = "internal";
*m = "select";
#else
struct event_base* b;
*s = event_get_version();
# ifdef HAVE_EVENT_BASE_GET_METHOD
*n = "libevent";
b = event_base_new();
*m = event_base_get_method(b);
# elif defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
*n = "libev";
b = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
*m = ev_backend2str(ev_backend((struct ev_loop*)b));
# else
*n = "unknown";
*m = "not obtainable";
b = NULL;
# endif
# ifdef HAVE_EVENT_BASE_FREE
event_base_free(b);
# endif
#endif
}
/** print usage. */
static void usage()
{
@ -173,7 +110,7 @@ static void usage()
printf(" service - used to start from services control panel\n");
#endif
printf("Version %s\n", PACKAGE_VERSION);
get_event_sys(&evnm, &evsys, &evmethod);
ub_get_event_sys(NULL, &evnm, &evsys, &evmethod);
printf("linked libs: %s %s (it uses %s), %s\n",
evnm, evsys, evmethod,
#ifdef HAVE_SSL
@ -230,7 +167,7 @@ checkrlimits(struct config_file* cfg)
struct rlimit rlim;
if(total > 1024 &&
strncmp(event_get_version(), "mini-event", 10) == 0) {
strncmp(ub_event_get_version(), "mini-event", 10) == 0) {
log_warn("too many file descriptors requested. The builtin"
"mini-event cannot handle more than 1024. Config "
"for less fds or compile with libevent");
@ -244,7 +181,7 @@ checkrlimits(struct config_file* cfg)
total = 1024;
}
if(perthread > 64 &&
strncmp(event_get_version(), "winsock-event", 13) == 0) {
strncmp(ub_event_get_version(), "winsock-event", 13) == 0) {
log_err("too many file descriptors requested. The winsock"
" event handler cannot handle more than 64 per "
" thread. Config for less fds");

View file

@ -483,7 +483,6 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
qinfo->qname_len, qinfo->qtype, qinfo->qclass,
worker->scratchpad, &msg, timenow);
if(!dp) { /* no delegation, need to reprime */
regional_free_all(worker->scratchpad);
return 0;
}
if(must_validate) {
@ -491,7 +490,6 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
case sec_status_unchecked:
/* some rrsets have not been verified yet, go and
* let validator do that */
regional_free_all(worker->scratchpad);
return 0;
case sec_status_bogus:
/* some rrsets are bogus, reply servfail */
@ -499,9 +497,10 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
if(!edns_opt_inplace_reply(edns, worker->scratchpad))
return 0;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
&msg->qinfo, id, flags, edns);
regional_free_all(worker->scratchpad);
if(worker->stats.extended) {
worker->stats.ans_bogus++;
worker->stats.ans_rcode[LDNS_RCODE_SERVFAIL]++;
@ -527,6 +526,8 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
if(!edns_opt_inplace_reply(edns, worker->scratchpad))
return 0;
msg->rep->flags |= BIT_QR|BIT_RA;
if(!reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags,
repinfo->c->buffer, 0, 1, worker->scratchpad,
@ -534,7 +535,6 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
&msg->qinfo, id, flags, edns);
}
regional_free_all(worker->scratchpad);
if(worker->stats.extended) {
if(secure) worker->stats.ans_secure++;
server_stats_insrcode(&worker->stats, repinfo->c->buffer);
@ -574,7 +574,6 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
bail_out:
rrset_array_unlock_touch(worker->env.rrset_cache,
worker->scratchpad, rep->ref, rep->rrset_count);
regional_free_all(worker->scratchpad);
return 0;
}
}
@ -585,11 +584,12 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
if(!edns_opt_inplace_reply(edns, worker->scratchpad))
return 0;
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, id, flags, edns);
rrset_array_unlock_touch(worker->env.rrset_cache,
worker->scratchpad, rep->ref, rep->rrset_count);
regional_free_all(worker->scratchpad);
if(worker->stats.extended) {
worker->stats.ans_bogus ++;
worker->stats.ans_rcode[LDNS_RCODE_SERVFAIL] ++;
@ -616,6 +616,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
if(!edns_opt_inplace_reply(edns, worker->scratchpad))
return 0;
if(!reply_info_answer_encode(qinfo, rep, id, flags,
repinfo->c->buffer, timenow, 1, worker->scratchpad,
udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
@ -626,7 +628,6 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
* is bad while holding locks. */
rrset_array_unlock_touch(worker->env.rrset_cache, worker->scratchpad,
rep->ref, rep->rrset_count);
regional_free_all(worker->scratchpad);
if(worker->stats.extended) {
if(secure) worker->stats.ans_secure++;
server_stats_insrcode(&worker->stats, repinfo->c->buffer);
@ -658,9 +659,11 @@ reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
* @param pkt: buffer
* @param str: string to put into text record (<255).
* @param edns: edns reply information.
* @param worker: worker with scratch region.
*/
static void
chaos_replystr(sldns_buffer* pkt, const char* str, struct edns_data* edns)
chaos_replystr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
struct worker* worker)
{
size_t len = strlen(str);
unsigned int rd = LDNS_RD_WIRE(sldns_buffer_begin(pkt));
@ -689,6 +692,8 @@ chaos_replystr(sldns_buffer* pkt, const char* str, struct edns_data* edns)
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->bits &= EDNS_DO;
if(!edns_opt_inplace_reply(edns, worker->scratchpad))
edns->opt_list = NULL;
attach_edns_record(pkt, edns);
}
@ -718,13 +723,13 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
char buf[MAXHOSTNAMELEN+1];
if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
buf[MAXHOSTNAMELEN] = 0;
chaos_replystr(pkt, buf, edns);
chaos_replystr(pkt, buf, edns, w);
} else {
log_err("gethostname: %s", strerror(errno));
chaos_replystr(pkt, "no hostname", edns);
chaos_replystr(pkt, "no hostname", edns, w);
}
}
else chaos_replystr(pkt, cfg->identity, edns);
else chaos_replystr(pkt, cfg->identity, edns, w);
return 1;
}
if(query_dname_compare(qinfo->qname,
@ -735,8 +740,8 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
if(cfg->hide_version)
return 0;
if(cfg->version==NULL || cfg->version[0]==0)
chaos_replystr(pkt, PACKAGE_STRING, edns);
else chaos_replystr(pkt, cfg->version, edns);
chaos_replystr(pkt, PACKAGE_STRING, edns, w);
else chaos_replystr(pkt, cfg->version, edns, w);
return 1;
}
return 0;
@ -865,7 +870,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
goto send_reply;
}
if((ret=parse_edns_from_pkt(c->buffer, &edns)) != 0) {
if((ret=parse_edns_from_pkt(c->buffer, &edns, worker->scratchpad)) != 0) {
struct edns_data reply_edns;
verbose(VERB_ALGO, "worker parse edns: formerror.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
@ -876,6 +881,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
error_encode(c->buffer, ret, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), &reply_edns);
regional_free_all(worker->scratchpad);
server_stats_insrcode(&worker->stats, c->buffer);
goto send_reply;
}
@ -884,12 +890,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
edns.edns_version = EDNS_ADVERTISED_VERSION;
edns.udp_size = EDNS_ADVERTISED_SIZE;
edns.bits &= EDNS_DO;
edns.opt_list = NULL;
verbose(VERB_ALGO, "query with bad edns version.");
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), NULL);
attach_edns_record(c->buffer, &edns);
regional_free_all(worker->scratchpad);
goto send_reply;
}
if(edns.edns_present && edns.udp_size < NORMAL_UDP_SIZE &&
@ -918,6 +926,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
sldns_buffer_write_at(c->buffer, 4,
(uint8_t*)"\0\0\0\0\0\0\0\0", 8);
sldns_buffer_flip(c->buffer);
regional_free_all(worker->scratchpad);
goto send_reply;
}
if(worker->stats.extended)
@ -928,6 +937,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo,
&edns, c->buffer)) {
server_stats_insrcode(&worker->stats, c->buffer);
regional_free_all(worker->scratchpad);
goto send_reply;
}
if(local_zones_answer(worker->daemon->local_zones, &qinfo, &edns,
@ -945,6 +955,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
* might need to bail out based on ACLs now. */
if((ret=deny_refuse_non_local(c, acl, worker, repinfo)) != -1)
{
regional_free_all(worker->scratchpad);
if(ret == 1)
goto send_reply;
return ret;
@ -961,6 +972,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_REFUSED);
sldns_buffer_flip(c->buffer);
regional_free_all(worker->scratchpad);
server_stats_insrcode(&worker->stats, c->buffer);
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->addr, repinfo->addrlen);
@ -984,9 +996,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
sldns_buffer_read_u16_at(c->buffer, 2),
repinfo, leeway);
rc = 0;
regional_free_all(worker->scratchpad);
goto send_reply_rc;
}
lock_rw_unlock(&e->lock);
regional_free_all(worker->scratchpad);
goto send_reply;
}
verbose(VERB_ALGO, "answer from the cache failed");
@ -997,6 +1011,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
&edns)) {
regional_free_all(worker->scratchpad);
goto send_reply;
}
verbose(VERB_ALGO, "answer norec from cache -- "
@ -1017,6 +1032,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
mesh_new_client(worker->env.mesh, &qinfo,
sldns_buffer_read_u16_at(c->buffer, 2),
&edns, repinfo, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer));
regional_free_all(worker->scratchpad);
worker_mem_report(worker, NULL);
return 0;
@ -1355,8 +1371,9 @@ worker_delete(struct worker* worker)
struct outbound_entry*
worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec,
int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, struct module_qstate* q)
int nocaps, struct edns_option* opt_list,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, struct module_qstate* q)
{
struct worker* worker = q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@ -1366,8 +1383,8 @@ worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
e->qstate = q;
e->qsent = outnet_serviced_query(worker->back, qname,
qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps,
q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
addrlen, zone, zonelen, worker_handle_service_reply, e,
q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, opt_list,
addr, addrlen, zone, zonelen, worker_handle_service_reply, e,
worker->back->udp_buff);
if(!e->qsent) {
return NULL;
@ -1412,7 +1429,8 @@ struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname),
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list),
struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
{

View file

@ -521,13 +521,14 @@ handle_event_moddone(struct module_qstate* qstate, int id)
* - An internal query.
* - A query for a record type other than AAAA.
* - CD FLAG was set on querier
* - An AAAA query for which an error was returned.
* - An AAAA query for which an error was returned.(qstate.return_rcode)
* -> treated as servfail thus synthesize (sec 5.1.3 6147), thus
* synthesize in (sec 5.1.2 of RFC6147).
* - A successful AAAA query with an answer.
*/
if ( (enum dns64_qstate)qstate->minfo[id] == DNS64_INTERNAL_QUERY
|| qstate->qinfo.qtype != LDNS_RR_TYPE_AAAA
|| (qstate->query_flags & BIT_CD)
|| qstate->return_rcode != LDNS_RCODE_NOERROR
|| (qstate->return_msg &&
qstate->return_msg->rep &&
reply_find_answer_rrset(&qstate->qinfo,

View file

@ -475,7 +475,7 @@ dt_msg_send_outside_response(struct dt_env *env,
return;
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE);
} else {
if (!env->log_resolver_query_messages)
if (!env->log_resolver_response_messages)
return;
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE);
}

View file

@ -1,3 +1,156 @@
2 June 2016: Wouter
- Fix libubound for edns optlist feature.
- Fix distinction between free and CRYPTO_free in dsa and ecdsa alloc.
- Fix #752: retry resource temporarily unavailable on control pipe.
- un-document localzone tags.
31 May 2016: Wouter
- Fix windows service to be created run with limited rights, as a
network service account, from Mario Turschmann.
- compat strsep implementation.
- generic edns option parse and store code.
- and also generic edns options for upstream messages (and replies).
after parse use edns_opt_find(edns.opt_list, LDNS_EDNS_NSID),
to insert use edns_opt_append(edns, region, code, len, bindata) on
the opt_list passed to send_query, or in edns_opt_inplace_reply.
30 May 2016: Wouter
- Fix time in case answer comes from cache in ub_resolve_event().
- Attempted fix for #765: _unboundmodule missing for python3.
27 May 2016: Wouter
- Fix #770: Small subgroup attack on DH used in unix pipe on localhost
if unbound control uses a unix local named pipe.
- Document write permission to directory of trust anchor needed.
- Fix #768: Unbound Service Sometimes Can Not Shutdown
Completely, WER Report Shown Up. Close handle before closing WSA.
26 May 2016: Wouter
- Updated patch from Charles Walker.
24 May 2016: Wouter
- disable-dnssec-lame-check config option from Charles Walker.
- remove memory leak from lame-check patch.
- iana portlist update.
23 May 2016: Wouter
- Fix #767: Reference to an expired Internet-Draft in
harden-below-nxdomain documentation.
20 May 2016: Ralph
- No QNAME minimisation fall-back for NXDOMAIN answers from DNSSEC
signed zones.
- iana portlist update.
19 May 2016: Wouter
- Fix #766: dns64 should synthesize results on timeout/errors.
18 May 2016: Wouter
- Fix #761: DNSSEC LAME false positive resolving nic.club.
17 May 2016: Wouter
- trunk updated with output of flex 2.6.0.
6 May 2016: Wouter
- Fix memory leak in out-of-memory conditions of local zone add.
29 April 2016: Wouter
- Fix sldns with static checking fixes copied from getdns.
28 April 2016: Wouter
- Fix #759: 0x20 capsforid no longer checks type PTR, for
compatibility with cisco dns guard. This lowers false positives.
18 April 2016: Wouter
- Fix some malformed reponses to edns queries get fallback to nonedns.
15 April 2016: Wouter
- cachedb module event handling design.
14 April 2016: Wouter
- cachedb module framework (empty).
- iana portlist update.
12 April 2016: Wouter
- Fix #753: document dump_requestlist is for first thread.
24 March 2016: Wouter
- Document permit-small-holddown for 5011 debug.
- Fix #749: unbound-checkconf gets SIGSEGV when use against a
malformatted conf file.
23 March 2016: Wouter
- OpenSSL 1.1.0 portability, --disable-dsa configure option.
21 March 2016: Wouter
- Fix compile of getentropy_linux for SLES11 servicepack 4.
- Fix dnstap-log-resolver-response-messages, from Nikolay Edigaryev.
- Fix test for openssl to use HMAC_Update for 1.1.0.
- acx_nlnetlabs.m4 to v33, with HMAC_Update.
- acx_nlnetlabs.m4 to v34, with -ldl -pthread test for libcrypto.
- ERR_remove_state deprecated since openssl 1.0.0.
- OPENSSL_config is deprecated, removing.
18 March 2016: Ralph
- Validate QNAME minimised NXDOMAIN responses.
- If QNAME minimisation is enabled, do cache lookup for QTYPE NS in
harden-below-nxdomain.
17 March 2016: Ralph
- Limit number of QNAME minimisation iterations.
17 March 2016: Wouter
- Fix #746: Fix unbound sets CD bit on all forwards.
If no trust anchors, it'll not set CD bit when forwarding to another
server. If a trust anchor, no CD bit on the first attempt to a
forwarder, but CD bit thereafter on repeated attempts to get DNSSEC.
- iana portlist update.
16 March 2016: Wouter
- Fix ip-transparent for ipv6 on FreeBSD, thanks to Nick Hibma.
- Fix ip-transparent for tcp on freebsd.
15 March 2016: Wouter
- ip_freebind: yesno option in unbound.conf sets IP_FREEBIND for
binding to an IP address while the interface or address is down.
14 March 2016: Wouter
- Fix warnings in ifdef corner case, older or unknown libevent.
- Fix compile for ub_event code with older libev.
11 March 2016: Wouter
- Remove warning about unused parameter in event_pluggable.c.
- Fix libev usage of dispatch return value.
- No side effects in tolower() call, in case it is a macro.
- For test put free in pluggable api in parenthesis.
10 March 2016: Wouter
- Fixup backend2str for libev.
09 March 2016: Willem
- User defined pluggable event API for libunbound
- Fixup of compile fix for pluggable event API from P.Y. Adi
Prasaja.
09 March 2016: Wouter
- Updated configure and ltmain.sh.
- Updated L root IPv6 address.
07 March 2016: Wouter
- Fix #747: assert in outnet_serviced_query_stop.
- iana ports fetched via https.
- iana portlist update.
03 March 2016: Wouter
- configure tests for the weak attribute support by the compiler.
02 March 2016: Wouter
- 1.5.8 release tag
- trunk contains 1.5.9 in development.
- iana portlist update.
- Fix #745: unbound.py - idn2dname throws UnicodeError when idnname
contains trailing dot.
24 February 2016: Wouter
- Fix OpenBSD asynclook lock free that gets used later (fix test code).
- Fix that NSEC3 negative cache is used when there is no salt.

View file

@ -1,4 +1,4 @@
README for Unbound 1.5.8
README for Unbound 1.5.9
Copyright 2007 NLnet Labs
http://unbound.net

View file

@ -1,7 +1,7 @@
#
# Example configuration file.
#
# See unbound.conf(5) man page, version 1.5.8.
# See unbound.conf(5) man page, version 1.5.9.
#
# this is a comment.
@ -93,6 +93,11 @@ server:
# (uses IP_BINDANY on FreeBSD).
# ip-transparent: no
# use IP_FREEBIND so the interface: addresses can be non-local
# and you can bind to nonexisting IPs and interfaces that are down.
# Linux only. On Linux you also have ip-transparent that is similar.
# ip-freebind: no
# EDNS reassembly buffer to advertise to UDP peers (the actual buffer
# is set with msg-buffer-size). 1480 can solve fragmentation (timeouts).
# edns-buffer-size: 4096
@ -364,6 +369,9 @@ server:
# into response messages when those sections are not required.
# minimal-responses: no
# true to disable DNSSEC lameness check in iterator.
# disable-dnssec-lame-check: no
# module configuration of the server. A string with identifiers
# separated by spaces. Syntax: "[dns64] [validator] iterator"
# module-config: "validator iterator"
@ -459,7 +467,8 @@ server:
# If the value 0 is given, missing anchors are not removed.
# keep-missing: 31622400 # 366 days
# debug option that allows very small holddown times for key rollover
# debug option that allows very small holddown times for key rollover,
# otherwise the RFC mandates probe intervals must be at least 1 hour.
# permit-small-holddown: no
# the amount of memory to use for the key cache.

View file

@ -1,7 +1,7 @@
#
# Example configuration file.
#
# See unbound.conf(5) man page, version 1.5.8.
# See unbound.conf(5) man page, version 1.5.9.
#
# this is a comment.
@ -93,6 +93,11 @@ server:
# (uses IP_BINDANY on FreeBSD).
# ip-transparent: no
# use IP_FREEBIND so the interface: addresses can be non-local
# and you can bind to nonexisting IPs and interfaces that are down.
# Linux only. On Linux you also have ip-transparent that is similar.
# ip-freebind: no
# EDNS reassembly buffer to advertise to UDP peers (the actual buffer
# is set with msg-buffer-size). 1480 can solve fragmentation (timeouts).
# edns-buffer-size: 4096
@ -364,6 +369,9 @@ server:
# into response messages when those sections are not required.
# minimal-responses: no
# true to disable DNSSEC lameness check in iterator.
# disable-dnssec-lame-check: no
# module configuration of the server. A string with identifiers
# separated by spaces. Syntax: "[dns64] [validator] iterator"
# module-config: "validator iterator"
@ -459,7 +467,8 @@ server:
# If the value 0 is given, missing anchors are not removed.
# keep-missing: 31622400 # 366 days
# debug option that allows very small holddown times for key rollover
# debug option that allows very small holddown times for key rollover,
# otherwise the RFC mandates probe intervals must be at least 1 hour.
# permit-small-holddown: no
# the amount of memory to use for the key cache.

View file

@ -1,4 +1,4 @@
.TH "libunbound" "3" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "libunbound" "3" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" libunbound.3 -- unbound library functions manual
.\"
@ -43,7 +43,7 @@
.B ub_ctx_zone_remove,
.B ub_ctx_data_add,
.B ub_ctx_data_remove
\- Unbound DNS validating resolver 1.5.8 functions.
\- Unbound DNS validating resolver 1.5.9 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP

View file

@ -1,4 +1,4 @@
.TH "libunbound" "3" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "libunbound" "3" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" libunbound.3 -- unbound library functions manual
.\"
@ -43,7 +43,7 @@
.B ub_ctx_zone_remove,
.B ub_ctx_data_add,
.B ub_ctx_data_remove
\- Unbound DNS validating resolver 1.5.8 functions.
\- Unbound DNS validating resolver 1.5.9 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP

View file

@ -1,4 +1,4 @@
.TH "unbound-anchor" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "unbound-anchor" "8" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"

View file

@ -1,4 +1,4 @@
.TH "unbound-anchor" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "unbound-anchor" "8" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"

View file

@ -1,4 +1,4 @@
.TH "unbound-checkconf" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "unbound-checkconf" "8" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"

View file

@ -1,4 +1,4 @@
.TH "unbound-checkconf" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "unbound-checkconf" "8" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"

View file

@ -1,4 +1,4 @@
.TH "unbound-control" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "unbound-control" "8" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"

View file

@ -1,4 +1,4 @@
.TH "unbound-control" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "unbound-control" "8" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"

View file

@ -1,4 +1,4 @@
.TH "unbound\-host" "1" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "unbound\-host" "1" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"

View file

@ -1,4 +1,4 @@
.TH "unbound\-host" "1" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "unbound\-host" "1" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"

View file

@ -1,4 +1,4 @@
.TH "unbound" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "unbound" "8" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" unbound.8 -- unbound manual
.\"
@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
\- Unbound DNS validating resolver 1.5.8.
\- Unbound DNS validating resolver 1.5.9.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]

View file

@ -1,4 +1,4 @@
.TH "unbound" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "unbound" "8" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" unbound.8 -- unbound manual
.\"
@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
\- Unbound DNS validating resolver 1.5.8.
\- Unbound DNS validating resolver 1.5.9.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]

View file

@ -1,4 +1,4 @@
.TH "unbound.conf" "5" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "unbound.conf" "5" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@ -277,6 +277,13 @@ and with this option you can select which (future) interfaces unbound
provides service on. This option needs unbound to be started with root
permissions on some systems. The option uses IP_BINDANY on FreeBSD systems.
.TP
.B ip\-freebind: \fI<yes or no>
If yes, then use IP_FREEBIND socket option on sockets where unbound
is listening to incoming traffic. Default no. Allows you to bind to
IP addresses that are nonlocal or do not exist, like when the network
interface or IP adress is down. Exists only on Linux, where the similar
ip\-transparent option is also available.
.TP
.B rrset\-cache\-size: \fI<number>
Number of bytes size of the RRset cache. Default is 4 megabytes.
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
@ -570,6 +577,7 @@ might return nxdomain for empty nonterminals (that usually happen for reverse
IP address lookups), and thus may be incompatible with this. To try to avoid
this only DNSSEC-secure nxdomains are used, because the old software does not
have DNSSEC. Default is off.
Currently, draft\-ietf\-dnsop\-nxdomain\-cut promotes this technique.
.TP
.B harden\-referral\-path: \fI<yes or no>
Harden the referral path by performing additional queries for
@ -673,6 +681,13 @@ This may cause a slight speedup. The default is no, because the DNS
protocol RFCs mandate these sections, and the additional content could
be of use and save roundtrips for clients.
.TP
.B disable-dnssec-lame-check: \fI<yes or no>
If true, disables the DNSSEC lameness check in the iterator. This check
sees if RRSIGs are present in the answer, when dnssec is expected,
and retries another authority if RRSIGs are unexpectedly missing.
The validator will insist in RRSIGs for DNSSEC signed domains regardless
of this setting, if a trust anchor is loaded.
.TP
.B module\-config: \fI<"module names">
Module configuration, a list of module names separated by spaces, surround
the string with quotes (""). The modules can be validator, iterator.
@ -691,7 +706,9 @@ File with trust anchor for one zone, which is tracked with RFC5011 probes.
The probes are several times per month, thus the machine must be online
frequently. The initial file can be one with contents as described in
\fBtrust\-anchor\-file\fR. The file is written to when the anchor is updated,
so the unbound user must have write permission.
so the unbound user must have write permission. Write permission to the file,
but also to the directory it is in (to create a temporary file, which is
necessary to deal with filesystem full events).
.TP
.B trust\-anchor: \fI<"Resource Record">
A DS or DNSKEY RR for a key to use for validation. Multiple entries can be

View file

@ -1,4 +1,4 @@
.TH "unbound.conf" "5" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
.TH "unbound.conf" "5" "Jun 9, 2016" "NLnet Labs" "unbound 1.5.9"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@ -277,6 +277,13 @@ and with this option you can select which (future) interfaces unbound
provides service on. This option needs unbound to be started with root
permissions on some systems. The option uses IP_BINDANY on FreeBSD systems.
.TP
.B ip\-freebind: \fI<yes or no>
If yes, then use IP_FREEBIND socket option on sockets where unbound
is listening to incoming traffic. Default no. Allows you to bind to
IP addresses that are nonlocal or do not exist, like when the network
interface or IP adress is down. Exists only on Linux, where the similar
ip\-transparent option is also available.
.TP
.B rrset\-cache\-size: \fI<number>
Number of bytes size of the RRset cache. Default is 4 megabytes.
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
@ -570,6 +577,7 @@ might return nxdomain for empty nonterminals (that usually happen for reverse
IP address lookups), and thus may be incompatible with this. To try to avoid
this only DNSSEC-secure nxdomains are used, because the old software does not
have DNSSEC. Default is off.
Currently, draft\-ietf\-dnsop\-nxdomain\-cut promotes this technique.
.TP
.B harden\-referral\-path: \fI<yes or no>
Harden the referral path by performing additional queries for
@ -673,6 +681,13 @@ This may cause a slight speedup. The default is no, because the DNS
protocol RFCs mandate these sections, and the additional content could
be of use and save roundtrips for clients.
.TP
.B disable-dnssec-lame-check: \fI<yes or no>
If true, disables the DNSSEC lameness check in the iterator. This check
sees if RRSIGs are present in the answer, when dnssec is expected,
and retries another authority if RRSIGs are unexpectedly missing.
The validator will insist in RRSIGs for DNSSEC signed domains regardless
of this setting, if a trust anchor is loaded.
.TP
.B module\-config: \fI<"module names">
Module configuration, a list of module names separated by spaces, surround
the string with quotes (""). The modules can be validator, iterator.
@ -691,7 +706,9 @@ File with trust anchor for one zone, which is tracked with RFC5011 probes.
The probes are several times per month, thus the machine must be online
frequently. The initial file can be one with contents as described in
\fBtrust\-anchor\-file\fR. The file is written to when the anchor is updated,
so the unbound user must have write permission.
so the unbound user must have write permission. Write permission to the file,
but also to the directory it is in (to create a temporary file, which is
necessary to deal with filesystem full events).
.TP
.B trust\-anchor: \fI<"Resource Record">
A DS or DNSKEY RR for a key to use for validation. Multiple entries can be

View file

@ -294,6 +294,7 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
uint8_t* dname;
size_t dname_len;
for(s = cfg->stubs; s; s = s->next) {
if(!s->name) continue;
dname = sldns_str2wire_dname(s->name, &dname_len);
if(!dname) {
log_err("cannot parse stub name '%s'", s->name);

View file

@ -590,6 +590,27 @@ iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
return 1;
}
int
iter_indicates_dnssec_fwd(struct module_env* env, struct query_info *qinfo)
{
struct trust_anchor* a;
if(!env || !env->anchors || !qinfo || !qinfo->qname)
return 0;
/* a trust anchor exists above the name? */
if((a=anchors_lookup(env->anchors, qinfo->qname, qinfo->qname_len,
qinfo->qclass))) {
if(a->numDS == 0 && a->numDNSKEY == 0) {
/* insecure trust point */
lock_basic_unlock(&a->lock);
return 0;
}
lock_basic_unlock(&a->lock);
return 1;
}
/* no trust anchor above it. */
return 0;
}
int
iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
struct dns_msg* msg, uint16_t dclass)

View file

@ -173,6 +173,18 @@ void iter_mark_pside_cycle_targets(struct module_qstate* qstate,
int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
struct delegpt* dp);
/**
* See if qname has DNSSEC needs in the forwarding case. This is true if
* there is a trust anchor above it. Whether there is an insecure delegation
* to the data is unknown, but CD-retry is needed.
* @param env: environment with anchors.
* @param qinfo: query name and class.
* @return true if trust anchor above qname, false if no anchor or insecure
* point above qname.
*/
int iter_indicates_dnssec_fwd(struct module_env* env,
struct query_info *qinfo);
/**
* See if delegation is expected to have DNSSEC information (RRSIGs) in
* its answers, or not. Inspects delegation point (name), trust anchors,

View file

@ -82,20 +82,6 @@ iter_init(struct module_env* env, int id)
log_err("iterator: could not apply configuration settings.");
return 0;
}
if(env->cfg->qname_minimisation) {
uint8_t dname[LDNS_MAX_DOMAINLEN+1];
size_t len = sizeof(dname);
if(sldns_str2wire_dname_buf("ip6.arpa.", dname, &len) != 0) {
log_err("ip6.arpa. parse error");
return 0;
}
iter_env->ip6arpa_dname = (uint8_t*)malloc(len);
if(!iter_env->ip6arpa_dname) {
log_err("malloc failure");
return 0;
}
memcpy(iter_env->ip6arpa_dname, dname, len);
}
return 1;
}
@ -117,7 +103,6 @@ iter_deinit(struct module_env* env, int id)
if(!env || !env->modinfo[id])
return;
iter_env = (struct iter_env*)env->modinfo[id];
free(iter_env->ip6arpa_dname);
free(iter_env->target_fetch_policy);
priv_delete(iter_env->priv);
donotq_delete(iter_env->donotq);
@ -162,6 +147,7 @@ iter_new(struct module_qstate* qstate, int id)
/* Start with the (current) qname. */
iq->qchase = qstate->qinfo;
outbound_list_init(&iq->outlist);
iq->minimise_count = 0;
if (qstate->env->cfg->qname_minimisation)
iq->minimisation_state = INIT_MINIMISE_STATE;
else
@ -1800,6 +1786,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
int tf_policy;
struct delegpt_addr* target;
struct outbound_entry* outq;
/* EDNS options to set on outgoing packet */
struct edns_option* opt_list = NULL;
/* NOTE: a request will encounter this state for each target it
* needs to send a query to. That is, at least one per referral,
@ -2009,9 +1997,10 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
}
if(iq->minimisation_state == INIT_MINIMISE_STATE) {
/* (Re)set qinfo_out to (new) delegation point, except
* when qinfo_out is already a subdomain of dp. This happens
* when resolving ip6.arpa dnames. */
/* (Re)set qinfo_out to (new) delegation point, except when
* qinfo_out is already a subdomain of dp. This happens when
* increasing by more than one label at once (QNAMEs with more
* than MAX_MINIMISE_COUNT labels). */
if(!(iq->qinfo_out.qname_len
&& dname_subdomain_c(iq->qchase.qname,
iq->qinfo_out.qname)
@ -2021,28 +2010,47 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
iq->qinfo_out.qname_len = iq->dp->namelen;
iq->qinfo_out.qtype = LDNS_RR_TYPE_NS;
iq->qinfo_out.qclass = iq->qchase.qclass;
iq->minimise_count = 0;
}
iq->minimisation_state = MINIMISE_STATE;
}
if(iq->minimisation_state == MINIMISE_STATE) {
int labdiff = dname_count_labels(iq->qchase.qname) -
int qchaselabs = dname_count_labels(iq->qchase.qname);
int labdiff = qchaselabs -
dname_count_labels(iq->qinfo_out.qname);
iq->qinfo_out.qname = iq->qchase.qname;
iq->qinfo_out.qname_len = iq->qchase.qname_len;
iq->minimise_count++;
/* Special treatment for ip6.arpa lookups.
* Reverse IPv6 dname has 34 labels, increment the IP part
* (usually first 32 labels) by 8 labels (7 more than the
* default 1 label increment). */
if(labdiff <= 32 &&
dname_subdomain_c(iq->qchase.qname, ie->ip6arpa_dname)) {
labdiff -= 7;
/* Small chance of zone cut after first label. Stop
* minimising */
if(labdiff <= 1)
labdiff = 0;
/* Limit number of iterations for QNAMEs with more
* than MAX_MINIMISE_COUNT labels. Send first MINIMISE_ONE_LAB
* labels of QNAME always individually.
*/
if(qchaselabs > MAX_MINIMISE_COUNT && labdiff > 1 &&
iq->minimise_count > MINIMISE_ONE_LAB) {
if(iq->minimise_count < MAX_MINIMISE_COUNT) {
int multilabs = qchaselabs - 1 -
MINIMISE_ONE_LAB;
int extralabs = multilabs /
MINIMISE_MULTIPLE_LABS;
if (MAX_MINIMISE_COUNT - iq->minimise_count >=
multilabs % MINIMISE_MULTIPLE_LABS)
/* Default behaviour is to add 1 label
* every iteration. Therefore, decrement
* the extralabs by 1 */
extralabs--;
if (extralabs < labdiff)
labdiff -= extralabs;
else
labdiff = 1;
}
/* Last minimised iteration, send all labels with
* QTYPE=NS */
else
labdiff = 1;
}
if(labdiff > 1) {
@ -2068,7 +2076,6 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
* cached as NOERROR/NODATA */
return 1;
}
}
if(iq->minimisation_state == SKIP_MINIMISE_STATE)
/* Do not increment qname, continue incrementing next
@ -2090,10 +2097,16 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
outq = (*qstate->env->send_query)(
iq->qinfo_out.qname, iq->qinfo_out.qname_len,
iq->qinfo_out.qtype, iq->qinfo_out.qclass,
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD,
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0),
/* unset CD if to forwarder(RD set) and not dnssec retry
* (blacklist nonempty) and no trust-anchors are configured
* above the qname or on the first attempt when dnssec is on */
EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&&
!qstate->blacklist&&(!iter_indicates_dnssec_fwd(qstate->env,
&iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
ie, iq), &target->addr, target->addrlen, iq->dp->name,
iq->dp->namelen, qstate);
ie, iq), opt_list, &target->addr, target->addrlen,
iq->dp->name, iq->dp->namelen, qstate);
if(!outq) {
log_addr(VERB_DETAIL, "error sending query to auth server",
&target->addr, target->addrlen);
@ -2161,8 +2174,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* differently. No queries should be sent elsewhere */
type = RESPONSE_TYPE_ANSWER;
}
if(iq->dnssec_expected && !iq->dnssec_lame_query &&
if(!qstate->env->cfg->disable_dnssec_lame_check && iq->dnssec_expected
&& !iq->dnssec_lame_query &&
!(iq->chase_flags&BIT_RD)
&& iq->sent_count < DNSSEC_LAME_DETECT_COUNT
&& type != RESPONSE_TYPE_LAME
&& type != RESPONSE_TYPE_REC_LAME
&& type != RESPONSE_TYPE_THROWAWAY
@ -2250,10 +2265,39 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
if(iq->minimisation_state != DONOT_MINIMISE_STATE) {
/* Best effort qname-minimisation.
* Stop minimising and send full query when RCODE
* is not NOERROR */
* is not NOERROR. */
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
LDNS_RCODE_NOERROR)
iq->minimisation_state = DONOT_MINIMISE_STATE;
if(FLAGS_GET_RCODE(iq->response->rep->flags) ==
LDNS_RCODE_NXDOMAIN) {
/* Stop resolving when NXDOMAIN is DNSSEC
* signed. Based on assumption that namservers
* serving signed zones do not return NXDOMAIN
* for empty-non-terminals. */
if(iq->dnssec_expected)
return final_state(iq);
/* Make subrequest to validate intermediate
* NXDOMAIN if harden-below-nxdomain is
* enabled. */
if(qstate->env->cfg->harden_below_nxdomain) {
struct module_qstate* subq = NULL;
log_query_info(VERB_QUERY,
"schedule NXDOMAIN validation:",
&iq->response->qinfo);
if(!generate_sub_request(
iq->response->qinfo.qname,
iq->response->qinfo.qname_len,
iq->response->qinfo.qtype,
iq->response->qinfo.qclass,
qstate, id, iq,
INIT_REQUEST_STATE,
FINISHED_STATE, &subq, 1))
verbose(VERB_ALGO,
"could not validate NXDOMAIN "
"response");
}
}
return next_state(iq, QUERYTARGETS_STATE);
}
return final_state(iq);
@ -3082,7 +3126,8 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
goto handle_it;
}
/* edns is not examined, but removed from message to help cache */
if(parse_extract_edns(prs, &edns) != LDNS_RCODE_NOERROR)
if(parse_extract_edns(prs, &edns, qstate->env->scratch) !=
LDNS_RCODE_NOERROR)
goto handle_it;
/* remove CD-bit, we asked for in case we handle validation ourself */
prs->flags &= ~BIT_CD;

View file

@ -61,6 +61,20 @@ struct rbtree_t;
#define MAX_REFERRAL_COUNT 130
/** max number of queries-sent-out. Make sure large NS set does not loop */
#define MAX_SENT_COUNT 32
/** max number of queries for which to perform dnsseclameness detection,
* (rrsigs misssing detection) after that, just pick up that response */
#define DNSSEC_LAME_DETECT_COUNT 4
/**
* max number of QNAME minimisation iterations. Limits number of queries for
* QNAMEs with a lot of labels.
*/
#define MAX_MINIMISE_COUNT 10
/**
* number of labels from QNAME that are always send individually when using
* QNAME minimisation, even when the number of labels of the QNAME is bigger
* tham MAX_MINIMISE_COUNT */
#define MINIMISE_ONE_LAB 4
#define MINIMISE_MULTIPLE_LABS (MAX_MINIMISE_COUNT - MINIMISE_ONE_LAB)
/** at what query-sent-count to stop target fetch policy */
#define TARGET_FETCH_STOP 3
/** how nice is a server without further information, in msec
@ -349,7 +363,7 @@ struct iter_qstate {
/** list of pending queries to authoritative servers. */
struct outbound_list outlist;
/** QNAME minimisation state */
/** QNAME minimisation state, RFC7816 */
enum minimisation_state minimisation_state;
/**
@ -357,6 +371,12 @@ struct iter_qstate {
* when qname minimisation is enabled.
*/
struct query_info qinfo_out;
/**
* Count number of QNAME minisation iterations. Used to limit number of
* outgoing queries when QNAME minimisation is enabled.
*/
int minimise_count;
};
/**

View file

@ -49,7 +49,7 @@
struct libworker;
struct tube;
struct sldns_buffer;
struct event_base;
struct ub_event_base;
/**
* The context structure
@ -114,7 +114,7 @@ struct ub_ctx {
struct ub_randstate* seed_rnd;
/** event base for event oriented interface */
struct event_base* event_base;
struct ub_event_base* event_base;
/** libworker for event based interface */
struct libworker* event_worker;

View file

@ -57,6 +57,7 @@
#include "util/random.h"
#include "util/net_help.h"
#include "util/tube.h"
#include "util/ub_event.h"
#include "services/modstack.h"
#include "services/localzone.h"
#include "services/cache/infra.h"
@ -169,6 +170,20 @@ ub_ctx_create(void)
return ctx;
}
struct ub_ctx*
ub_ctx_create_ub_event(struct ub_event_base* ueb)
{
struct ub_ctx* ctx = ub_ctx_create_nopipe();
if(!ctx)
return NULL;
/* no pipes, but we have the locks to make sure everything works */
ctx->created_bg = 0;
ctx->dothread = 1; /* the processing is in the same process,
makes ub_cancel and ub_ctx_delete do the right thing */
ctx->event_base = ueb;
return ctx;
}
struct ub_ctx*
ub_ctx_create_event(struct event_base* eb)
{
@ -179,7 +194,11 @@ ub_ctx_create_event(struct event_base* eb)
ctx->created_bg = 0;
ctx->dothread = 1; /* the processing is in the same process,
makes ub_cancel and ub_ctx_delete do the right thing */
ctx->event_base = eb;
ctx->event_base = ub_libevent_event_base(eb);
if (!ctx->event_base) {
ub_ctx_delete(ctx);
return NULL;
}
return ctx;
}
@ -698,6 +717,9 @@ ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
}
}
/* set time in case answer comes from cache */
ub_comm_base_now(ctx->event_worker->base);
/* create new ctx_query and attempt to add to the list */
q = context_new(ctx, name, rrtype, rrclass, (ub_callback_t)callback,
mydata);
@ -1323,10 +1345,12 @@ const char* ub_version(void)
int
ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) {
struct ub_event_base* new_base;
if (!ctx || !ctx->event_base || !base) {
return UB_INITFAIL;
}
if (ctx->event_base == base) {
if (ub_libevent_get_event_base(ctx->event_base) == base) {
/* already set */
return UB_NOERROR;
}
@ -1335,9 +1359,11 @@ ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) {
/* destroy the current worker - safe to pass in NULL */
libworker_delete_event(ctx->event_worker);
ctx->event_worker = NULL;
ctx->event_base = base;
new_base = ub_libevent_event_base(base);
if (new_base)
ctx->event_base = new_base;
ctx->created_bg = 0;
ctx->dothread = 1;
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
return new_base ? UB_NOERROR : UB_INITFAIL;
}

View file

@ -119,7 +119,7 @@ libworker_delete_event(struct libworker* w)
/** setup fresh libworker struct */
static struct libworker*
libworker_setup(struct ub_ctx* ctx, int is_bg, struct event_base* eb)
libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
{
unsigned int seed;
struct libworker* w = (struct libworker*)calloc(1, sizeof(*w));
@ -258,7 +258,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct event_base* eb)
}
struct libworker* libworker_create_event(struct ub_ctx* ctx,
struct event_base* eb)
struct ub_event_base* eb)
{
return libworker_setup(ctx, 0, eb);
}
@ -581,6 +581,7 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q,
edns->ext_rcode = 0;
edns->edns_version = 0;
edns->bits = EDNS_DO;
edns->opt_list = NULL;
if(sldns_buffer_capacity(w->back->udp_buff) < 65535)
edns->udp_size = (uint16_t)sldns_buffer_capacity(
w->back->udp_buff);
@ -822,9 +823,9 @@ void libworker_alloc_cleanup(void* arg)
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
int want_dnssec, int nocaps, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen,
struct module_qstate* q)
int want_dnssec, int nocaps, struct edns_option* opt_list,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, struct module_qstate* q)
{
struct libworker* w = (struct libworker*)q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@ -834,9 +835,9 @@ struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
e->qstate = q;
e->qsent = outnet_serviced_query(w->back, qname,
qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps,
q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
addrlen, zone, zonelen, libworker_handle_service_reply, e,
w->back->udp_buff);
q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, opt_list,
addr, addrlen, zone, zonelen, libworker_handle_service_reply,
e, w->back->udp_buff);
if(!e->qsent) {
return NULL;
}
@ -955,7 +956,8 @@ struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname),
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list),
struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
{

View file

@ -58,7 +58,7 @@ struct comm_reply;
struct regional;
struct tube;
struct sldns_buffer;
struct event_base;
struct ub_event_base;
/**
* The library-worker status structure
@ -115,7 +115,7 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q);
* @return new worker or NULL.
*/
struct libworker* libworker_create_event(struct ub_ctx* ctx,
struct event_base* eb);
struct ub_event_base* eb);
/**
* Attach context_query to mesh for callback in event-driven setup.

View file

@ -945,7 +945,7 @@ int _ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, int rrclass, v
:param idnname: (unicode string) IDN name
:returns: (string) domain name
"""
return '.'.join([encodings.idna.ToASCII(a) for a in idnname.split('.')])
return '.'.join([encodings.idna.ToASCII(a) if a else '' for a in idnname.split('.')])
def dname2idn(name):
"""Converts canonic domain name in IDN format to unicode string

View file

@ -6,6 +6,7 @@ ub_ctx_async
ub_ctx_config
ub_ctx_create
ub_ctx_create_event
ub_ctx_create_ub_event
ub_ctx_data_add
ub_ctx_data_remove
ub_ctx_debuglevel

View file

@ -36,20 +36,21 @@
/**
* \file
*
* This file contains the unbound interface for use with libevent.
* You have to use the same libevent that unbound was compiled with,
* otherwise it wouldn't work, the event and event_base structures would
* be different. If unbound is compiled without libevent support then
* this header file is not supposed to be installed on the system.
* This file contains the unbound interface for use with user defined
* pluggable event bases.
*
* Use ub_ctx_create_event_base() to create an unbound context that uses
* the event base that you have made. Then, use the ub_resolve_event call
* to add DNS resolve queries to the context. Those then run when you
* call event_dispatch() on your event_base, and when they are done you
* get a function callback.
* Use ub_ctx_create_event_ub_base() to create an unbound context that uses
* the user provided event base API. Then, use the ub_resolve_event call
* to add DNS resolve queries to the context. Those then run whith the
* provided event_base, and when they are done you get a function callback.
*
* This method does not fork another process or create a thread, the effort
* is done by the unbound state machines that are connected to the event_base.
* is done by the unbound state machines that are connected to the event base.
*
* It is also possible to provide a libevent based event base by using
* ub_ctx_create_event_base(). But you have to use the same libevent that
* unbound was compiled with, otherwise it wouldn't work, the event and
* event_base structures would be different.
*/
#ifndef _UB_UNBOUND_EVENT_H
#define _UB_UNBOUND_EVENT_H
@ -62,12 +63,136 @@ struct ub_ctx;
struct ub_result;
struct event_base;
/** event timeout */
#define UB_EV_TIMEOUT 0x01
/** event fd readable */
#define UB_EV_READ 0x02
/** event fd writable */
#define UB_EV_WRITE 0x04
/** event signal */
#define UB_EV_SIGNAL 0x08
/** event must persist */
#define UB_EV_PERSIST 0x10
/** magic number to identify this version of the pluggable event api */
#define UB_EVENT_MAGIC 0x44d74d78
struct ub_event;
struct ub_event_base;
struct timeval;
/**
* The Virtual Method Table for and ub_event_base "object"
*/
struct ub_event_base_vmt {
/** Destructor for the ub_event_base object,
* (not called by libunbound) */
void (*free)(struct ub_event_base*);
/** Run the event loop
* (not called by libunbound when using ub_resolve_event) */
int (*dispatch)(struct ub_event_base*);
/** Exit the given event loop */
int (*loopexit)(struct ub_event_base*, struct timeval*);
/** Instantiate a new ub_event associated with this event base */
struct ub_event* (*new_event)(struct ub_event_base*,
int fd, short bits, void (*cb)(int, short, void*), void* arg);
/** Instantiate a new signal associated with this event base,
* (not called by libunbound) */
struct ub_event* (*new_signal)(struct ub_event_base*, int fd,
void (*cb)(int, short, void*), void* arg);
/** Create a new ub_event associated with the given wsaevent,
* (not called by libunbound) */
struct ub_event* (*winsock_register_wsaevent)(struct ub_event_base*,
void* wsaevent, void (*cb)(int, short, void*), void* arg);
};
/**
* A user defined pluggable event base is registered by providing a
* ub_event_base "object" with the ub_ctx_create_ub_event() function.
* The magic number must be correct and the Virtual Method Table must be
* fully equipped providing the event base API to be used by libunbound.
*/
struct ub_event_base {
/** magic must be UB_EVENT_MAGIC (0x44d74d78) */
unsigned long magic;
/** Virtual Method Table for ub_event_base */
struct ub_event_base_vmt* vmt;
};
/**
* The Virtual Method Table for and ub_event "object"
*/
struct ub_event_vmt {
/** Add event bits for this event to fire on.
* The event will be deactivated before this function is called. */
void (*add_bits)(struct ub_event*, short);
/** Configure the event so it will not longer fire on given bits
* The event will be deactivated before this function is called. */
void (*del_bits)(struct ub_event*, short);
/** Change or set the file descriptor on the event
* The event will be deactivated before this function is called. */
void (*set_fd)(struct ub_event*, int);
/** Destructor for the ub_event object */
void (*free)(struct ub_event*);
/** Activate the event. The given timeval is an timeout value. */
int (*add)(struct ub_event*, struct timeval*);
/** Deactivate the event */
int (*del)(struct ub_event*);
/** Reconfigure and activate a timeout event */
int (*add_timer)(struct ub_event*, struct ub_event_base*,
void (*cb)(int, short, void*), void* arg, struct timeval*);
/** Deactivate the timeout event */
int (*del_timer)(struct ub_event*);
/** Activate a signal event (not called by libunbound). */
int (*add_signal)(struct ub_event*, struct timeval*);
/** Deactivate a signal event (not called by libunbound). */
int (*del_signal)(struct ub_event*);
/** Destructor for a ub_event associated with a wsaevent,
* (not called by libunbound)
*/
void (*winsock_unregister_wsaevent)(struct ub_event* ev);
/** Libunbound will signal the eventloop when a TCP windows socket
* will block on next read or write (given by the eventbits), to work
* around edge trigger event behaviour of select on windows with TCP.
*/
void (*winsock_tcp_wouldblock)(struct ub_event*, int eventbit);
};
/**
* An "object" comprising a user defined pluggable event.
* The magic number must be correct and the Virtual Method Table must be
* fully equipped providing the ub_event API to be used by libunbound.
*/
struct ub_event {
/** magic must be UB_EVENT_MAGIC (0x44d74d78) */
unsigned long magic;
/** Virtual Method Table for ub_event */
struct ub_event_vmt* vmt;
};
typedef void (*ub_event_callback_t)(void*, int, void*, int, int, char*);
/**
* Create a resolving and validation context.
* The information from /etc/resolv.conf and /etc/hosts is not utilised by
* default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them.
* @param base: the pluggable event base that the caller has created.
* The unbound context uses this event base.
* @return a new context. default initialisation.
* returns NULL on error.
* You must use ub_resolve_event with this context.
* Do not call ub_ctx_async, ub_poll, ub_wait, ub_process, this is all done
* with the event_base. Setup the options you like with the other functions.
*/
struct ub_ctx* ub_ctx_create_ub_event(struct ub_event_base* base);
/**
* Create a resolving and validation context.
* The information from /etc/resolv.conf and /etc/hosts is not utilised by
* default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them.
* You have to use the same libevent that unbound was compiled with,
* otherwise it wouldn't work, the event and event_base structures would
* be different.
* @param base: the event base that the caller has created. The unbound
* context uses this event base.
* @return a new context. default initialisation.
@ -79,7 +204,10 @@ typedef void (*ub_event_callback_t)(void*, int, void*, int, int, char*);
struct ub_ctx* ub_ctx_create_event(struct event_base* base);
/**
* Set a new event_base on a context created with ub_ctx_create_event.
* Set a new libevent event_base on a context created with ub_ctx_create_event.
* You have to use the same libevent that unbound was compiled with,
* otherwise it wouldn't work, the event and event_base structures would
* be different.
* Any outbound queries will be canceled.
* @param ctx the ub_ctx to update. Must have been created with ub_ctx_create_event
* @param base the new event_base to attach to the ctx

View file

@ -48,6 +48,7 @@ struct comm_reply;
struct comm_point;
struct module_qstate;
struct tube;
struct edns_option;
/**
* Worker service routine to send serviced queries to authoritative servers.
@ -59,6 +60,7 @@ struct tube;
* @param dnssec: if set, EDNS record will have DO bit set.
* @param want_dnssec: signatures needed.
* @param nocaps: ignore capsforid(if in config), do not perturb qname.
* @param opt_list: EDNS options on outgoing packet.
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: delegation point name.
@ -69,9 +71,9 @@ struct tube;
*/
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
int want_dnssec, int nocaps, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen,
struct module_qstate* q);
int want_dnssec, int nocaps, struct edns_option* opt_list,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, struct module_qstate* q);
/** process incoming replies from the network */
int libworker_handle_reply(struct comm_point* c, void* arg, int error,
@ -114,6 +116,7 @@ void worker_sighandler(int sig, void* arg);
* @param dnssec: if set, EDNS record will have DO bit set.
* @param want_dnssec: signatures needed.
* @param nocaps: ignore capsforid(if in config), do not perturb qname.
* @param opt_list: EDNS options on outgoing packet.
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: wireformat dname of the zone.
@ -124,9 +127,9 @@ void worker_sighandler(int sig, void* arg);
*/
struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
int want_dnssec, int nocaps, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen,
struct module_qstate* q);
int want_dnssec, int nocaps, struct edns_option* opt_list,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, struct module_qstate* q);
/**
* process control messages from the main thread. Frees the control

View file

@ -795,6 +795,12 @@ dns_cache_lookup(struct module_env* env,
dname_remove_label(&k.qname, &k.qname_len);
h = query_info_hash(&k, flags);
e = slabhash_lookup(env->msg_cache, h, &k, 0);
if(!e && k.qtype != LDNS_RR_TYPE_NS &&
env->cfg->qname_minimisation) {
k.qtype = LDNS_RR_TYPE_NS;
h = query_info_hash(&k, flags);
e = slabhash_lookup(env->msg_cache, h, &k, 0);
}
if(e) {
struct reply_info* data = (struct reply_info*)e->data;
struct dns_msg* msg;
@ -810,6 +816,7 @@ dns_cache_lookup(struct module_env* env,
}
lock_rw_unlock(&e->lock);
}
k.qtype = qtype;
}
/* fill common RR types for ANY response to avoid requery */

View file

@ -96,10 +96,11 @@ verbose_print_addr(struct addrinfo *addr)
int
create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto,
int rcv, int snd, int listen, int* reuseport, int transparent)
int rcv, int snd, int listen, int* reuseport, int transparent,
int freebind)
{
int s;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) || defined(IP_BINDANY)
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND)
int on=1;
#endif
#ifdef IPV6_MTU
@ -116,6 +117,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
#endif
#if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY)
(void)transparent;
#endif
#if !defined(IP_FREEBIND)
(void)freebind;
#endif
if((s = socket(family, socktype, 0)) == -1) {
*inuse = 0;
@ -180,6 +184,14 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
#else
(void)reuseport;
#endif /* defined(SO_REUSEPORT) */
#ifdef IP_FREEBIND
if (freebind &&
setsockopt(s, IPPROTO_IP, IP_FREEBIND, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
log_warn("setsockopt(.. IP_FREEBIND ..) failed: %s",
strerror(errno));
}
#endif /* IP_FREEBIND */
#ifdef IP_TRANSPARENT
if (transparent &&
setsockopt(s, IPPROTO_IP, IP_TRANSPARENT, (void*)&on,
@ -190,9 +202,10 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
#elif defined(IP_BINDANY)
if (transparent &&
setsockopt(s, (family==AF_INET6? IPPROTO_IPV6:IPPROTO_IP),
IP_BINDANY, (void*)&on, (socklen_t)sizeof(on)) < 0) {
log_warn("setsockopt(.. IP_BINDANY ..) failed: %s",
strerror(errno));
(family == AF_INET6? IPV6_BINDANY:IP_BINDANY),
(void*)&on, (socklen_t)sizeof(on)) < 0) {
log_warn("setsockopt(.. IP%s_BINDANY ..) failed: %s",
(family==AF_INET6?"V6":""), strerror(errno));
}
#endif /* IP_TRANSPARENT || IP_BINDANY */
}
@ -490,14 +503,17 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
int
create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
int* reuseport, int transparent, int mss)
int* reuseport, int transparent, int mss, int freebind)
{
int s;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT)
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND)
int on = 1;
#endif
#ifndef IP_TRANSPARENT
#if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY)
(void)transparent;
#endif
#if !defined(IP_FREEBIND)
(void)freebind;
#endif
verbose_print_addr(addr);
*noproto = 0;
@ -553,6 +569,13 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
return -1;
}
#endif /* SO_REUSEADDR */
#ifdef IP_FREEBIND
if (freebind && setsockopt(s, IPPROTO_IP, IP_FREEBIND, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
log_warn("setsockopt(.. IP_FREEBIND ..) failed: %s",
strerror(errno));
}
#endif /* IP_FREEBIND */
#ifdef SO_REUSEPORT
/* try to set SO_REUSEPORT so that incoming
* connections are distributed evenly among the receiving threads.
@ -599,7 +622,15 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
log_warn("setsockopt(.. IP_TRANSPARENT ..) failed: %s",
strerror(errno));
}
#endif /* IP_TRANSPARENT */
#elif defined(IP_BINDANY)
if (transparent &&
setsockopt(s, (addr->ai_family==AF_INET6? IPPROTO_IPV6:IPPROTO_IP),
(addr->ai_family == AF_INET6? IPV6_BINDANY:IP_BINDANY),
(void*)&on, (socklen_t)sizeof(on)) < 0) {
log_warn("setsockopt(.. IP%s_BINDANY ..) failed: %s",
(addr->ai_family==AF_INET6?"V6":""), strerror(errno));
}
#endif /* IP_TRANSPARENT || IP_BINDANY */
if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) {
#ifndef USE_WINSOCK
/* detect freebsd jail with no ipv6 permission */
@ -704,7 +735,7 @@ create_local_accept_sock(const char *path, int* noproto)
static int
make_sock(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
int* reuseport, int transparent, int tcp_mss)
int* reuseport, int transparent, int tcp_mss, int freebind)
{
struct addrinfo *res = NULL;
int r, s, inuse, noproto;
@ -732,7 +763,7 @@ make_sock(int stype, const char* ifname, const char* port,
s = create_udp_sock(res->ai_family, res->ai_socktype,
(struct sockaddr*)res->ai_addr, res->ai_addrlen,
v6only, &inuse, &noproto, (int)rcv, (int)snd, 1,
reuseport, transparent);
reuseport, transparent, freebind);
if(s == -1 && inuse) {
log_err("bind: address already in use");
} else if(s == -1 && noproto && hints->ai_family == AF_INET6){
@ -740,7 +771,7 @@ make_sock(int stype, const char* ifname, const char* port,
}
} else {
s = create_tcp_accept_sock(res, v6only, &noproto, reuseport,
transparent, tcp_mss);
transparent, tcp_mss, freebind);
if(s == -1 && noproto && hints->ai_family == AF_INET6){
*noip6 = 1;
}
@ -753,7 +784,7 @@ make_sock(int stype, const char* ifname, const char* port,
static int
make_sock_port(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
int* reuseport, int transparent, int tcp_mss)
int* reuseport, int transparent, int tcp_mss, int freebind)
{
char* s = strchr(ifname, '@');
if(s) {
@ -775,10 +806,10 @@ make_sock_port(int stype, const char* ifname, const char* port,
(void)strlcpy(p, s+1, sizeof(p));
p[strlen(s+1)]=0;
return make_sock(stype, newif, p, hints, v6only, noip6,
rcv, snd, reuseport, transparent, tcp_mss);
rcv, snd, reuseport, transparent, tcp_mss, freebind);
}
return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd,
reuseport, transparent, tcp_mss);
reuseport, transparent, tcp_mss, freebind);
}
/**
@ -874,13 +905,14 @@ set_recvpktinfo(int s, int family)
* set to false on exit if reuseport failed due to no kernel support.
* @param transparent: set IP_TRANSPARENT socket option.
* @param tcp_mss: maximum segment size of tcp socket. default if zero.
* @param freebind: set IP_FREEBIND socket option.
* @return: returns false on error.
*/
static int
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
struct addrinfo *hints, const char* port, struct listen_port** list,
size_t rcv, size_t snd, int ssl_port, int* reuseport, int transparent,
int tcp_mss)
int tcp_mss, int freebind)
{
int s, noip6=0;
if(!do_udp && !do_tcp)
@ -888,7 +920,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if(do_auto) {
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
tcp_mss)) == -1) {
tcp_mss, freebind)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
@ -916,7 +948,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
/* regular udp socket */
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
tcp_mss)) == -1) {
tcp_mss, freebind)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
@ -937,7 +969,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
atoi(strchr(ifname, '@')+1) == ssl_port) ||
(!strchr(ifname, '@') && atoi(port) == ssl_port));
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
&noip6, 0, 0, reuseport, transparent, tcp_mss)) == -1) {
&noip6, 0, 0, reuseport, transparent, tcp_mss,
freebind)) == -1) {
if(noip6) {
/*log_warn("IPv6 protocol not available");*/
return 1;
@ -1095,7 +1128,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, reuseport,
cfg->ip_transparent,
cfg->tcp_mss)) {
cfg->tcp_mss, cfg->ip_freebind)) {
listening_ports_free(list);
return NULL;
}
@ -1108,7 +1141,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, reuseport,
cfg->ip_transparent,
cfg->tcp_mss)) {
cfg->tcp_mss, cfg->ip_freebind)) {
listening_ports_free(list);
return NULL;
}
@ -1123,7 +1156,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, reuseport,
cfg->ip_transparent,
cfg->tcp_mss)) {
cfg->tcp_mss, cfg->ip_freebind)) {
listening_ports_free(list);
return NULL;
}
@ -1136,7 +1169,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, reuseport,
cfg->ip_transparent,
cfg->tcp_mss)) {
cfg->tcp_mss, cfg->ip_freebind)) {
listening_ports_free(list);
return NULL;
}

View file

@ -190,11 +190,12 @@ void listen_start_accept(struct listen_dnsport* listen);
* @param reuseport: if nonNULL and true, try to set SO_REUSEPORT on
* listening UDP port. Set to false on return if it failed to do so.
* @param transparent: set IP_TRANSPARENT socket option.
* @param freebind: set IP_FREEBIND socket option.
* @return: the socket. -1 on error.
*/
int create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv,
int snd, int listen, int* reuseport, int transparent);
int snd, int listen, int* reuseport, int transparent, int freebind);
/**
* Create and bind TCP listening socket
@ -205,10 +206,11 @@ int create_udp_sock(int family, int socktype, struct sockaddr* addr,
* listening UDP port. Set to false on return if it failed to do so.
* @param transparent: set IP_TRANSPARENT socket option.
* @param mss: maximum segment size of the socket. if zero, leaves the default.
* @param freebind: set IP_FREEBIND socket option.
* @return: the socket. -1 on error.
*/
int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
int* reuseport, int transparent, int mss);
int* reuseport, int transparent, int mss, int freebind);
/**
* Create and bind local listening socket

View file

@ -94,6 +94,7 @@ local_zone_delete(struct local_zone* z)
lock_rw_destroy(&z->lock);
regional_destroy(z->region);
free(z->name);
free(z->taglist);
free(z);
}
@ -171,6 +172,7 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len,
{
struct local_zone* z = local_zone_create(nm, len, labs, t, c);
if(!z) {
free(nm);
log_err("out of memory");
return NULL;
}
@ -506,6 +508,40 @@ lz_enter_rr_str(struct local_zones* zones, const char* rr)
return r;
}
/** enter tagstring into zone */
static int
lz_enter_zone_tag(struct local_zones* zones, char* zname, uint8_t* list,
size_t len, uint16_t rr_class)
{
uint8_t dname[LDNS_MAX_DOMAINLEN+1];
size_t dname_len = sizeof(dname);
int dname_labs, r = 0;
struct local_zone* z;
if(sldns_str2wire_dname_buf(zname, dname, &dname_len) != 0) {
log_err("cannot parse zone name in local-zone-tag: %s", zname);
return 0;
}
dname_labs = dname_count_labels(dname);
lock_rw_rdlock(&zones->lock);
z = local_zones_lookup(zones, dname, dname_len, dname_labs, rr_class);
if(!z) {
lock_rw_unlock(&zones->lock);
log_err("no local-zone for tag %s", zname);
return 0;
}
lock_rw_wrlock(&z->lock);
lock_rw_unlock(&zones->lock);
free(z->taglist);
z->taglist = memdup(list, len);
z->taglen = len;
if(z->taglist)
r = 1;
lock_rw_unlock(&z->lock);
return r;
}
/** parse local-zone: statements */
static int
lz_enter_zones(struct local_zones* zones, struct config_file* cfg)
@ -800,6 +836,22 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
return 1;
}
/** enter local-zone-tag info */
static int
lz_enter_zone_tags(struct local_zones* zones, struct config_file* cfg)
{
struct config_strbytelist* p;
int c = 0;
for(p = cfg->local_zone_tags; p; p = p->next) {
if(!lz_enter_zone_tag(zones, p->str, p->str2, p->str2len,
LDNS_RR_CLASS_IN))
return 0;
c++;
}
if(c) verbose(VERB_ALGO, "applied tags to %d local zones", c);
return 1;
}
/** enter auth data */
static int
lz_enter_data(struct local_zones* zones, struct config_file* cfg)
@ -842,6 +894,10 @@ local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
/* setup parent ptrs for lookup during data entry */
init_parents(zones);
/* insert local zone tags */
if(!lz_enter_zone_tags(zones, cfg)) {
return 0;
}
/* insert local data */
if(!lz_enter_data(zones, cfg)) {
return 0;
@ -986,7 +1042,8 @@ local_encode(struct query_info* qinfo, struct edns_data* edns,
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
if(!reply_info_answer_encode(qinfo, &rep,
if(!edns_opt_inplace_reply(edns, temp) ||
!reply_info_answer_encode(qinfo, &rep,
*(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2),
buf, 0, 0, temp, udpsize, edns,
@ -1220,7 +1277,10 @@ struct local_zone* local_zones_add_zone(struct local_zones* zones,
{
/* create */
struct local_zone* z = local_zone_create(name, len, labs, tp, dclass);
if(!z) return NULL;
if(!z) {
free(name);
return NULL;
}
lock_rw_wrlock(&z->lock);
/* find the closest parent */

View file

@ -115,6 +115,10 @@ struct local_zone {
/** how to process zone */
enum localzone_type type;
/** tag bitlist */
uint8_t* taglist;
/** length of the taglist (in bytes) */
size_t taglen;
/** in this region the zone's data is allocated.
* the struct local_zone itself is malloced. */

View file

@ -315,6 +315,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
s = mesh_state_create(mesh->env, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
if(!s) {
log_err("mesh_state_create: out of memory; SERVFAIL");
if(!edns_opt_inplace_reply(edns, mesh->env->scratch))
edns->opt_list = NULL;
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
@ -338,6 +340,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
/* add reply to s */
if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo->qname)) {
log_err("mesh_new_client: out of memory; SERVFAIL");
if(!edns_opt_inplace_reply(edns, mesh->env->scratch))
edns->opt_list = NULL;
error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
@ -809,7 +813,8 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
r->edns.udp_size = EDNS_ADVERTISED_SIZE;
r->edns.ext_rcode = 0;
r->edns.bits &= EDNS_DO;
if(!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
if(!edns_opt_inplace_reply(&r->edns, m->s.region) ||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->buf, 0, 1,
m->s.env->scratch, udp_size, &r->edns,
(int)(r->edns.bits & EDNS_DO), secure))
@ -859,7 +864,9 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
if(prev && prev->qflags == r->qflags &&
prev->edns.edns_present == r->edns.edns_present &&
prev->edns.bits == r->edns.bits &&
prev->edns.udp_size == r->edns.udp_size) {
prev->edns.udp_size == r->edns.udp_size &&
edns_opt_list_compare(prev->edns.opt_list, r->edns.opt_list)
== 0) {
/* if the previous reply is identical to this one, fix ID */
if(prev->query_reply.c->buffer != r->query_reply.c->buffer)
sldns_buffer_copy(r->query_reply.c->buffer,
@ -881,7 +888,8 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
r->edns.ext_rcode = 0;
r->edns.bits &= EDNS_DO;
m->s.qinfo.qname = r->qname;
if(!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
if(!edns_opt_inplace_reply(&r->edns, m->s.region) ||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->query_reply.c->buffer, 0, 1,
m->s.env->scratch, udp_size, &r->edns,
(int)(r->edns.bits & EDNS_DO), secure))
@ -973,6 +981,12 @@ int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
r->cb = cb;
r->cb_arg = cb_arg;
r->edns = *edns;
if(edns->opt_list) {
r->edns.opt_list = edns_opt_copy_region(edns->opt_list,
s->s.region);
if(!r->edns.opt_list)
return 0;
}
r->qid = qid;
r->qflags = qflags;
r->next = s->cb_list;
@ -990,6 +1004,12 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
return 0;
r->query_reply = *rep;
r->edns = *edns;
if(edns->opt_list) {
r->edns.opt_list = edns_opt_copy_region(edns->opt_list,
s->s.region);
if(!r->edns.opt_list)
return 0;
}
r->qid = qid;
r->qflags = qflags;
r->start_time = *s->s.env->now_tv;
@ -1000,7 +1020,6 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
return 0;
s->reply_list = r;
return 1;
}
/**

View file

@ -50,6 +50,9 @@
#ifdef WITH_PYTHONMODULE
#include "pythonmod/pythonmod.h"
#endif
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
#endif
/** count number of modules (words) in the string */
static int
@ -120,6 +123,9 @@ module_list_avail(void)
"dns64",
#ifdef WITH_PYTHONMODULE
"python",
#endif
#ifdef USE_CACHEDB
"cachedb",
#endif
"validator",
"iterator",
@ -138,6 +144,9 @@ module_funcs_avail(void)
&dns64_get_funcblock,
#ifdef WITH_PYTHONMODULE
&pythonmod_get_funcblock,
#endif
#ifdef USE_CACHEDB
&cachedb_get_funcblock,
#endif
&val_get_funcblock,
&iter_get_funcblock,

View file

@ -122,6 +122,8 @@ serviced_cmp(const void* key1, const void* key2)
}
if((r = query_dname_compare(q1->qbuf+10, q2->qbuf+10)) != 0)
return r;
if((r = edns_opt_list_compare(q1->opt_list, q2->opt_list)) != 0)
return r;
return sockaddr_cmp(&q1->addr, q1->addrlen, &q2->addr, q2->addrlen);
}
@ -757,6 +759,7 @@ serviced_node_del(rbnode_t* node, void* ATTR_UNUSED(arg))
struct service_callback* p = sq->cblist, *np;
free(sq->qbuf);
free(sq->zone);
edns_opt_list_free(sq->opt_list);
while(p) {
np = p->next;
free(p);
@ -909,13 +912,13 @@ udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int port,
sa->sin6_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET6, SOCK_DGRAM,
(struct sockaddr*)addr, addrlen, 1, inuse, &noproto,
0, 0, 0, NULL, 0);
0, 0, 0, NULL, 0, 0);
} else {
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
sa->sin_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET, SOCK_DGRAM,
(struct sockaddr*)addr, addrlen, 1, inuse, &noproto,
0, 0, 0, NULL, 0);
0, 0, 0, NULL, 0, 0);
}
return fd;
}
@ -1219,7 +1222,8 @@ serviced_gen_query(sldns_buffer* buff, uint8_t* qname, size_t qnamelen,
/** lookup serviced query in serviced query rbtree */
static struct serviced_query*
lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
struct sockaddr_storage* addr, socklen_t addrlen)
struct sockaddr_storage* addr, socklen_t addrlen,
struct edns_option* opt_list)
{
struct serviced_query key;
key.node.key = &key;
@ -1229,6 +1233,7 @@ lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
memcpy(&key.addr, addr, addrlen);
key.addrlen = addrlen;
key.outnet = outnet;
key.opt_list = opt_list;
return (struct serviced_query*)rbtree_search(outnet->serviced, &key);
}
@ -1237,7 +1242,7 @@ static struct serviced_query*
serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
int want_dnssec, int nocaps, int tcp_upstream, int ssl_upstream,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, int qtype)
size_t zonelen, int qtype, struct edns_option* opt_list)
{
struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq));
#ifdef UNBOUND_DEBUG
@ -1267,6 +1272,16 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
sq->ssl_upstream = ssl_upstream;
memcpy(&sq->addr, addr, addrlen);
sq->addrlen = addrlen;
sq->opt_list = NULL;
if(opt_list) {
sq->opt_list = edns_opt_copy_alloc(opt_list);
if(!sq->opt_list) {
free(sq->zone);
free(sq->qbuf);
free(sq);
return NULL;
}
}
sq->outnet = outnet;
sq->cblist = NULL;
sq->pending = NULL;
@ -1394,6 +1409,7 @@ serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns)
edns.edns_present = 1;
edns.ext_rcode = 0;
edns.edns_version = EDNS_ADVERTISED_VERSION;
edns.opt_list = sq->opt_list;
if(sq->status == serviced_query_UDP_EDNS_FRAG) {
if(addr_is_ip6(&sq->addr, sq->addrlen)) {
if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
@ -1527,7 +1543,10 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
sq->to_be_deleted = 1;
verbose(VERB_ALGO, "svcd callbacks start");
if(sq->outnet->use_caps_for_id && error == NETEVENT_NOERROR && c &&
!sq->nocaps) {
!sq->nocaps && sq->qtype != LDNS_RR_TYPE_PTR) {
/* for type PTR do not check perturbed name in answer,
* compatibility with cisco dns guard boxes that mess up
* reverse queries 0x20 contents */
/* noerror and nxdomain must have a qname in reply */
if(sldns_buffer_read_u16_at(c->buffer, 4) == 0 &&
(LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer))
@ -1708,6 +1727,44 @@ serviced_tcp_send(struct serviced_query* sq, sldns_buffer* buff)
return sq->pending != NULL;
}
/* see if packet is edns malformed; got zeroes at start.
* This is from servers that return malformed packets to EDNS0 queries,
* but they return good packets for nonEDNS0 queries.
* We try to detect their output; without resorting to a full parse or
* check for too many bytes after the end of the packet. */
static int
packet_edns_malformed(struct sldns_buffer* buf, int qtype)
{
size_t len;
if(sldns_buffer_limit(buf) < LDNS_HEADER_SIZE)
return 1; /* malformed */
/* they have NOERROR rcode, 1 answer. */
if(LDNS_RCODE_WIRE(sldns_buffer_begin(buf)) != LDNS_RCODE_NOERROR)
return 0;
/* one query (to skip) and answer records */
if(LDNS_QDCOUNT(sldns_buffer_begin(buf)) != 1 ||
LDNS_ANCOUNT(sldns_buffer_begin(buf)) == 0)
return 0;
/* skip qname */
len = dname_valid(sldns_buffer_at(buf, LDNS_HEADER_SIZE),
sldns_buffer_limit(buf)-LDNS_HEADER_SIZE);
if(len == 0)
return 0;
if(len == 1 && qtype == 0)
return 0; /* we asked for '.' and type 0 */
/* and then 4 bytes (type and class of query) */
if(sldns_buffer_limit(buf) < LDNS_HEADER_SIZE + len + 4 + 3)
return 0;
/* and start with 11 zeroes as the answer RR */
/* so check the qtype of the answer record, qname=0, type=0 */
if(sldns_buffer_at(buf, LDNS_HEADER_SIZE+len+4)[0] == 0 &&
sldns_buffer_at(buf, LDNS_HEADER_SIZE+len+4)[1] == 0 &&
sldns_buffer_at(buf, LDNS_HEADER_SIZE+len+4)[2] == 0)
return 1;
return 0;
}
int
serviced_udp_callback(struct comm_point* c, void* arg, int error,
struct comm_reply* rep)
@ -1778,7 +1835,9 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
||sq->status == serviced_query_UDP_EDNS_FRAG)
&& (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer))
== LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(
sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL)) {
sldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL
|| packet_edns_malformed(c->buffer, sq->qtype)
)) {
/* try to get an answer by falling back without EDNS */
verbose(VERB_ALGO, "serviced query: attempt without EDNS");
sq->status = serviced_query_UDP_EDNS_fallback;
@ -1873,15 +1932,15 @@ struct serviced_query*
outnet_serviced_query(struct outside_network* outnet,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen,
comm_point_callback_t* callback, void* callback_arg,
int tcp_upstream, int ssl_upstream, struct edns_option* opt_list,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
sldns_buffer* buff)
{
struct serviced_query* sq;
struct service_callback* cb;
serviced_gen_query(buff, qname, qnamelen, qtype, qclass, flags);
sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen);
sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen, opt_list);
/* duplicate entries are included in the callback list, because
* there is a counterpart registration by our caller that needs to
* be doubly-removed (with callbacks perhaps). */
@ -1891,7 +1950,7 @@ outnet_serviced_query(struct outside_network* outnet,
/* make new serviced query entry */
sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps,
tcp_upstream, ssl_upstream, addr, addrlen, zone,
zonelen, (int)qtype);
zonelen, (int)qtype, opt_list);
if(!sq) {
free(cb);
return NULL;
@ -1948,13 +2007,7 @@ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
callback_list_remove(sq, cb_arg);
/* if callbacks() routine scheduled deletion, let it do that */
if(!sq->cblist && !sq->to_be_deleted) {
#ifdef UNBOUND_DEBUG
rbnode_t* rem =
#else
(void)
#endif
rbtree_delete(sq->outnet->serviced, sq);
log_assert(rem); /* should be present */
(void)rbtree_delete(sq->outnet->serviced, sq);
serviced_delete(sq);
}
}

View file

@ -58,6 +58,7 @@ struct port_if;
struct sldns_buffer;
struct serviced_query;
struct dt_env;
struct edns_option;
/**
* Send queries to outside servers and wait for answers from servers.
@ -367,6 +368,8 @@ struct serviced_query {
int last_rtt;
/** do we know edns probe status already, for UDP_EDNS queries */
int edns_lame_known;
/** edns options to use for sending upstream packet */
struct edns_option* opt_list;
/** outside network this is part of */
struct outside_network* outnet;
/** list of interested parties that need callback on results. */
@ -477,6 +480,8 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
* @param nocaps: ignore use_caps_for_id and use unperturbed qname.
* @param tcp_upstream: use TCP for upstream queries.
* @param ssl_upstream: use SSL for upstream queries.
* @param opt_list: pass edns option list (deep copied into serviced query)
* these options are set on the outgoing packets.
* @param callback: callback function.
* @param callback_arg: user argument to callback function.
* @param addr: to which server to send the query.
@ -492,9 +497,9 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen,
comm_point_callback_t* callback, void* callback_arg,
int tcp_upstream, int ssl_upstream, struct edns_option* opt_list,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
struct sldns_buffer* buff);
/**

View file

@ -206,7 +206,6 @@ sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
offset += length;
Y = BN_bin2bn(key+offset, (int)length, NULL);
offset += length;
/* create the key and set its properties */
if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {

View file

@ -637,7 +637,7 @@ int sldns_b64_ntop(uint8_t const *src, size_t srclength,
target[o+1] = b64[ ((src[i]&0x03)<<4) | (src[i+1]>>4) ];
target[o+2] = b64[ ((src[i+1]&0x0f)<<2) ];
target[o+3] = pad64;
i += 2;
/* i += 2; */
o += 4;
break;
case 1:
@ -646,7 +646,7 @@ int sldns_b64_ntop(uint8_t const *src, size_t srclength,
target[o+1] = b64[ ((src[i]&0x03)<<4) ];
target[o+2] = pad64;
target[o+3] = pad64;
i += 1;
/* i += 1; */
o += 4;
break;
case 0:

View file

@ -420,7 +420,8 @@ enum sldns_enum_edns_option
LDNS_EDNS_DAU = 5, /* RFC6975 */
LDNS_EDNS_DHU = 6, /* RFC6975 */
LDNS_EDNS_N3U = 7, /* RFC6975 */
LDNS_EDNS_CLIENT_SUBNET = 8 /* draft-vandergaast-edns-client-subnet */
LDNS_EDNS_CLIENT_SUBNET = 8, /* draft-vandergaast-edns-client-subnet */
LDNS_EDNS_PADDING = 12 /* RFC7830 */
};
typedef enum sldns_enum_edns_option sldns_edns_option;

View file

@ -892,10 +892,10 @@ int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len,
parse_state?parse_state->default_ttl:0,
(parse_state&&parse_state->origin_len)?
parse_state->origin:NULL,
parse_state->origin_len,
parse_state?parse_state->origin_len:0,
(parse_state&&parse_state->prev_rr_len)?
parse_state->prev_rr:NULL,
parse_state->prev_rr_len);
parse_state?parse_state->prev_rr_len:0);
}
return LDNS_WIREPARSE_ERR_OK;
}

View file

@ -165,6 +165,7 @@ static sldns_lookup_table sldns_edns_options_data[] = {
{ 6, "DHU" },
{ 7, "N3U" },
{ 8, "edns-client-subnet" },
{ 12, "Padding" },
{ 0, NULL}
};
sldns_lookup_table* sldns_edns_options = sldns_edns_options_data;
@ -1864,6 +1865,9 @@ int sldns_wire2str_edns_option_print(char** s, size_t* sl,
case LDNS_EDNS_CLIENT_SUBNET:
w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen);
break;
case LDNS_EDNS_PADDING:
w += print_hex_buf(s, sl, optdata, optlen);
break;
default:
/* unknown option code */
w += print_hex_buf(s, sl, optdata, optlen);

View file

@ -411,6 +411,21 @@ morechecks(struct config_file* cfg, const char* fname)
&& strcmp(cfg->module_conf, "dns64 validator python iterator") != 0
&& strcmp(cfg->module_conf, "python dns64 iterator") != 0
&& strcmp(cfg->module_conf, "python dns64 validator iterator") != 0
#endif
#ifdef USE_CACHEDB
&& strcmp(cfg->module_conf, "validator cachedb iterator") != 0
&& strcmp(cfg->module_conf, "cachedb iterator") != 0
&& strcmp(cfg->module_conf, "dns64 validator cachedb iterator") != 0
&& strcmp(cfg->module_conf, "dns64 cachedb iterator") != 0
&& strcmp(cfg->module_conf, "python dns64 cachedb iterator") != 0
&& strcmp(cfg->module_conf, "python dns64 validator cachedb iterator") != 0
&& strcmp(cfg->module_conf, "dns64 python cachedb iterator") != 0
&& strcmp(cfg->module_conf, "dns64 python validator cachedb iterator") != 0
&& strcmp(cfg->module_conf, "python cachedb iterator") != 0
&& strcmp(cfg->module_conf, "python validator cachedb iterator") != 0
&& strcmp(cfg->module_conf, "cachedb python iterator") != 0
&& strcmp(cfg->module_conf, "validator cachedb python iterator") != 0
&& strcmp(cfg->module_conf, "validator python cachedb iterator") != 0
#endif
) {
fatal_exit("module conf '%s' is not known to work",

View file

@ -102,7 +102,7 @@ usage()
printf(" flush_negative flush all negative data\n");
printf(" flush_stats flush statistics, make zero\n");
printf(" flush_requestlist drop queries that are worked on\n");
printf(" dump_requestlist show what is worked on\n");
printf(" dump_requestlist show what is worked on by first thread\n");
printf(" flush_infra [all | ip] remove ping, edns for one IP or all\n");
printf(" dump_infra show ping and edns entries\n");
printf(" set_option opt: val set option to value, no reload\n");

View file

@ -103,7 +103,8 @@ struct outbound_entry* worker_send_query(uint8_t* ATTR_UNUSED(qname),
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list),
struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
{
@ -135,7 +136,8 @@ struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname),
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
int ATTR_UNUSED(nocaps), struct edns_option* ATTR_UNUSED(opt_list),
struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
{

View file

@ -163,6 +163,7 @@ config_create(void)
cfg->so_sndbuf = 0;
cfg->so_reuseport = 0;
cfg->ip_transparent = 0;
cfg->ip_freebind = 0;
cfg->num_ifs = 0;
cfg->ifs = NULL;
cfg->num_out_ifs = 0;
@ -237,6 +238,7 @@ config_create(void)
if(!(cfg->dnstap_socket_path = strdup(DNSTAP_SOCKET_PATH)))
goto error_exit;
#endif
cfg->disable_dnssec_lame_check = 0;
cfg->ratelimit = 0;
cfg->ratelimit_slabs = 4;
cfg->ratelimit_size = 4*1024*1024;
@ -393,6 +395,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_MEMSIZE("so-sndbuf:", so_sndbuf)
else S_YNO("so-reuseport:", so_reuseport)
else S_YNO("ip-transparent:", ip_transparent)
else S_YNO("ip-freebind:", ip_freebind)
else S_MEMSIZE("rrset-cache-size:", rrset_cache_size)
else S_POW2("rrset-cache-slabs:", rrset_cache_slabs)
else S_YNO("prefetch:", prefetch)
@ -473,6 +476,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("control-cert-file:", control_cert_file)
else S_STR("module-config:", module_conf)
else S_STR("python-script:", python_script)
else S_YNO("disable-dnssec-lame-check:", disable_dnssec_lame_check)
else if(strcmp(opt, "ratelimit:") == 0) {
IS_NUMBER_OR_ZERO; cfg->ratelimit = atoi(val);
infra_dp_ratelimit=cfg->ratelimit;
@ -481,9 +485,11 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_POW2("ratelimit-slabs:", ratelimit_slabs)
else S_NUMBER_OR_ZERO("ratelimit-factor:", ratelimit_factor)
else S_YNO("qname-minimisation:", qname_minimisation)
else if(strcmp(opt, "define-tag:") ==0) {
return config_add_tag(cfg, val);
/* val_sig_skew_min and max are copied into val_env during init,
* so this does not update val_env with set_option */
else if(strcmp(opt, "val-sig-skew-min:") == 0)
} else if(strcmp(opt, "val-sig-skew-min:") == 0)
{ IS_NUMBER_OR_ZERO; cfg->val_sig_skew_min = (int32_t)atoi(val); }
else if(strcmp(opt, "val-sig-skew-max:") == 0)
{ IS_NUMBER_OR_ZERO; cfg->val_sig_skew_max = (int32_t)atoi(val); }
@ -504,7 +510,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
* stub-zone, name, stub-addr, stub-host, stub-prime
* forward-first, stub-first,
* forward-zone, name, forward-addr, forward-host,
* ratelimit-for-domain, ratelimit-below-domain */
* ratelimit-for-domain, ratelimit-below-domain,
* local-zone-tag */
return 0;
}
return 1;
@ -628,9 +635,23 @@ config_collate_cat(struct config_strlist* list)
/** compare and print list option */
#define O_LS2(opt, name, lst) if(strcmp(opt, name)==0) { \
struct config_str2list* p = cfg->lst; \
for(p = cfg->lst; p; p = p->next) \
snprintf(buf, len, "%s %s\n", p->str, p->str2); \
for(p = cfg->lst; p; p = p->next) { \
snprintf(buf, len, "%s %s", p->str, p->str2); \
func(buf, arg); \
} \
}
/** compare and print taglist option */
#define O_LTG(opt, name, lst) if(strcmp(opt, name)==0) { \
char* tmpstr = NULL; \
struct config_strbytelist *p = cfg->lst; \
for(p = cfg->lst; p; p = p->next) {\
tmpstr = config_taglist2str(cfg, p->str2, p->str2len); \
if(tmpstr) {\
snprintf(buf, len, "%s %s", p->str, tmpstr); \
func(buf, arg); \
free(tmpstr); \
} \
} \
}
int
@ -664,6 +685,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_MEM(opt, "so-sndbuf", so_sndbuf)
else O_YNO(opt, "so-reuseport", so_reuseport)
else O_YNO(opt, "ip-transparent", ip_transparent)
else O_YNO(opt, "ip-freebind", ip_freebind)
else O_MEM(opt, "rrset-cache-size", rrset_cache_size)
else O_DEC(opt, "rrset-cache-slabs", rrset_cache_slabs)
else O_YNO(opt, "prefetch-key", prefetch_key)
@ -750,6 +772,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "insecure-lan-zones", insecure_lan_zones)
else O_DEC(opt, "max-udp-size", max_udp_size)
else O_STR(opt, "python-script", python_script)
else O_YNO(opt, "disable-dnssec-lame-check", disable_dnssec_lame_check)
else O_DEC(opt, "ratelimit", ratelimit)
else O_MEM(opt, "ratelimit-size", ratelimit_size)
else O_DEC(opt, "ratelimit-slabs", ratelimit_slabs)
@ -759,6 +782,8 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_DEC(opt, "val-sig-skew-min", val_sig_skew_min)
else O_DEC(opt, "val-sig-skew-max", val_sig_skew_max)
else O_YNO(opt, "qname-minimisation", qname_minimisation)
else O_IFC(opt, "define-tag", num_tags, tagname)
else O_LTG(opt, "local-zone-tag", local_zone_tags)
/* not here:
* outgoing-permit, outgoing-avoid - have list of ports
* local-zone - zones and nodefault variables
@ -931,6 +956,33 @@ config_delstubs(struct config_stub* p)
}
}
/** delete string array */
static void
config_del_strarray(char** array, int num)
{
int i;
if(!array)
return;
for(i=0; i<num; i++) {
free(array[i]);
}
free(array);
}
/** delete stringbytelist */
static void
config_del_strbytelist(struct config_strbytelist* p)
{
struct config_strbytelist* np;
while(p) {
np = p->next;
free(p->str);
free(p->str2);
free(p);
p = np;
}
}
void
config_delete(struct config_file* cfg)
{
@ -943,18 +995,8 @@ config_delete(struct config_file* cfg)
free(cfg->target_fetch_policy);
free(cfg->ssl_service_key);
free(cfg->ssl_service_pem);
if(cfg->ifs) {
int i;
for(i=0; i<cfg->num_ifs; i++)
free(cfg->ifs[i]);
free(cfg->ifs);
}
if(cfg->out_ifs) {
int i;
for(i=0; i<cfg->num_out_ifs; i++)
free(cfg->out_ifs[i]);
free(cfg->out_ifs);
}
config_del_strarray(cfg->ifs, cfg->num_ifs);
config_del_strarray(cfg->out_ifs, cfg->num_out_ifs);
config_delstubs(cfg->stubs);
config_delstubs(cfg->forwards);
config_delstrlist(cfg->donotqueryaddrs);
@ -978,6 +1020,8 @@ config_delete(struct config_file* cfg)
config_deldblstrlist(cfg->local_zones);
config_delstrlist(cfg->local_zones_nodefault);
config_delstrlist(cfg->local_data);
config_del_strarray(cfg->tagname, cfg->num_tags);
config_del_strbytelist(cfg->local_zone_tags);
config_delstrlist(cfg->control_ifs);
free(cfg->server_key_file);
free(cfg->server_cert_file);
@ -1166,6 +1210,24 @@ cfg_str2list_insert(struct config_str2list** head, char* item, char* i2)
return 1;
}
int
cfg_strbytelist_insert(struct config_strbytelist** head, char* item,
uint8_t* i2, size_t i2len)
{
struct config_strbytelist* s;
if(!item || !i2 || !head)
return 0;
s = (struct config_strbytelist*)calloc(1, sizeof(*s));
if(!s)
return 0;
s->str = item;
s->str2 = i2;
s->str2len = i2len;
s->next = *head;
*head = s;
return 1;
}
time_t
cfg_convert_timeval(const char* str)
{
@ -1270,6 +1332,122 @@ cfg_parse_memsize(const char* str, size_t* res)
return 1;
}
int
find_tag_id(struct config_file* cfg, const char* tag)
{
int i;
for(i=0; i<cfg->num_tags; i++) {
if(strcmp(cfg->tagname[i], tag) == 0)
return i;
}
return -1;
}
int
config_add_tag(struct config_file* cfg, const char* tag)
{
char** newarray;
char* newtag;
if(find_tag_id(cfg, tag) != -1)
return 1; /* nothing to do */
newarray = (char**)malloc(sizeof(char*)*(cfg->num_tags+1));
if(!newarray)
return 0;
newtag = strdup(tag);
if(!newtag) {
free(newarray);
return 0;
}
if(cfg->tagname) {
memcpy(newarray, cfg->tagname, sizeof(char*)*cfg->num_tags);
free(cfg->tagname);
}
newarray[cfg->num_tags++] = newtag;
cfg->tagname = newarray;
return 1;
}
/** set a bit in a bit array */
static void
cfg_set_bit(uint8_t* bitlist, size_t len, int id)
{
int pos = id/8;
log_assert((size_t)pos < len);
bitlist[pos] |= 1<<(id%8);
}
uint8_t* config_parse_taglist(struct config_file* cfg, char* str,
size_t* listlen)
{
uint8_t* taglist = NULL;
size_t len = 0;
char* p, *s;
/* allocate */
if(cfg->num_tags == 0) {
log_err("parse taglist, but no tags defined");
return 0;
}
len = (size_t)(cfg->num_tags+7)/8;
taglist = calloc(1, len);
if(!taglist) {
log_err("out of memory");
return 0;
}
/* parse */
s = str;
while((p=strsep(&s, " \t\n")) != NULL) {
if(*p) {
int id = find_tag_id(cfg, p);
/* set this bit in the bitlist */
if(id == -1) {
log_err("unknown tag: %s", p);
free(taglist);
return 0;
}
cfg_set_bit(taglist, len, id);
}
}
*listlen = len;
return taglist;
}
char* config_taglist2str(struct config_file* cfg, uint8_t* taglist,
size_t taglen)
{
char buf[10240];
size_t i, j, len = 0;
buf[0] = 0;
for(i=0; i<taglen; i++) {
if(taglist[i] == 0)
continue;
for(j=0; j<8; j++) {
if((taglist[i] & (1<<j)) != 0) {
size_t id = i*8 + j;
snprintf(buf+len, sizeof(buf)-len, "%s%s",
(len==0?"":" "), cfg->tagname[id]);
len += strlen(buf+len);
}
}
}
return strdup(buf);
}
int taglist_intersect(uint8_t* list1, size_t list1len, uint8_t* list2,
size_t list2len)
{
size_t i;
if(!list1 || !list2)
return 0;
for(i=0; i<list1len && i<list2len; i++) {
if((list1[i] & list2[i]) != 0)
return 1;
}
return 0;
}
void
config_apply(struct config_file* config)
{

View file

@ -44,6 +44,7 @@
struct config_stub;
struct config_strlist;
struct config_str2list;
struct config_strbytelist;
struct module_qstate;
struct sock_list;
struct ub_packed_rrset_key;
@ -142,6 +143,8 @@ struct config_file {
int so_reuseport;
/** IP_TRANSPARENT socket option requested on port 53 sockets */
int ip_transparent;
/** IP_FREEBIND socket option request on port 53 sockets */
int ip_freebind;
/** number of interfaces to open. If 0 default all interfaces. */
int num_ifs;
@ -293,6 +296,12 @@ struct config_file {
int unblock_lan_zones;
/** insecure lan zones (don't validate AS112 zones) */
int insecure_lan_zones;
/** list of zonename, tagbitlist */
struct config_strbytelist* local_zone_tags;
/** tag list, array with tagname[i] is malloced string */
char** tagname;
/** number of items in the taglist */
int num_tags;
/** remote control section. enable toggle. */
int remote_control_enable;
@ -358,6 +367,9 @@ struct config_file {
/** true to log dnstap FORWARDER_RESPONSE message events */
int dnstap_log_forwarder_response_messages;
/** true to disable DNSSEC lameness check in iterator */
int disable_dnssec_lame_check;
/** ratelimit 0 is off, otherwise qps (unless overridden) */
int ratelimit;
/** number of slabs for ratelimit cache */
@ -421,6 +433,19 @@ struct config_str2list {
char* str2;
};
/**
* List of string, bytestring for config options
*/
struct config_strbytelist {
/** next item in list */
struct config_strbytelist* next;
/** first string */
char* str;
/** second bytestring */
uint8_t* str2;
size_t str2len;
};
/** List head for strlist processing, used for append operation. */
struct config_strlist_head {
/** first in list of text items */
@ -559,6 +584,17 @@ int cfg_strlist_insert(struct config_strlist** head, char* item);
*/
int cfg_str2list_insert(struct config_str2list** head, char* item, char* i2);
/**
* Insert string into strbytelist.
* @param head: pointer to str2list head variable.
* @param item: new item. malloced by caller. If NULL the insertion fails.
* @param i2: 2nd string, malloced by caller. If NULL the insertion fails.
* @param i2len: length of the i2 bytestring.
* @return: true on success.
*/
int cfg_strbytelist_insert(struct config_strbytelist** head, char* item,
uint8_t* i2, size_t i2len);
/**
* Find stub in config list, also returns prevptr (for deletion).
* @param pp: call routine with pointer to a pointer to the start of the list,
@ -624,6 +660,54 @@ int cfg_count_numbers(const char* str);
*/
int cfg_parse_memsize(const char* str, size_t* res);
/**
* Add a tag name to the config. It is added at the end with a new ID value.
* @param cfg: the config structure.
* @param tag: string (which is copied) with the name.
* @return: false on alloc failure.
*/
int config_add_tag(struct config_file* cfg, const char* tag);
/**
* Find tag ID in the tag list.
* @param cfg: the config structure.
* @param tag: string with tag name to search for.
* @return: 0..(num_tags-1) with tag ID, or -1 if tagname is not found.
*/
int find_tag_id(struct config_file* cfg, const char* tag);
/**
* parse taglist from string into bytestring with bitlist.
* @param cfg: the config structure (with tagnames)
* @param str: the string to parse. Parse puts 0 bytes in string.
* @param listlen: returns length of in bytes.
* @return malloced bytes with a bitlist of the tags. or NULL on parse error
* or malloc failure.
*/
uint8_t* config_parse_taglist(struct config_file* cfg, char* str,
size_t* listlen);
/**
* convert tag bitlist to a malloced string with tag names. For debug output.
* @param cfg: the config structure (with tagnames)
* @param taglist: the tag bitlist.
* @param len: length of the tag bitlist.
* @return malloced string or NULL.
*/
char* config_taglist2str(struct config_file* cfg, uint8_t* taglist,
size_t len);
/**
* see if two taglists intersect (have tags in common).
* @param list1: first tag bitlist.
* @param list1len: length in bytes of first list.
* @param list2: second tag bitlist.
* @param list2len: length in bytes of second list.
* @return true if there are tags in common, 0 if not.
*/
int taglist_intersect(uint8_t* list1, size_t list1len, uint8_t* list2,
size_t list2len);
/**
* Parse local-zone directive into two strings and register it in the config.
* @param cfg: to put it in.

View file

@ -236,6 +236,7 @@ so-rcvbuf{COLON} { YDVAR(1, VAR_SO_RCVBUF) }
so-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) }
so-reuseport{COLON} { YDVAR(1, VAR_SO_REUSEPORT) }
ip-transparent{COLON} { YDVAR(1, VAR_IP_TRANSPARENT) }
ip-freebind{COLON} { YDVAR(1, VAR_IP_FREEBIND) }
chroot{COLON} { YDVAR(1, VAR_CHROOT) }
username{COLON} { YDVAR(1, VAR_USERNAME) }
directory{COLON} { YDVAR(1, VAR_DIRECTORY) }
@ -344,6 +345,8 @@ rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
max-udp-size{COLON} { YDVAR(1, VAR_MAX_UDP_SIZE) }
dns64-prefix{COLON} { YDVAR(1, VAR_DNS64_PREFIX) }
dns64-synthall{COLON} { YDVAR(1, VAR_DNS64_SYNTHALL) }
define-tag{COLON} { YDVAR(1, VAR_DEFINE_TAG) }
local-zone-tag{COLON} { YDVAR(2, VAR_LOCAL_ZONE_TAG) }
dnstap{COLON} { YDVAR(0, VAR_DNSTAP) }
dnstap-enable{COLON} { YDVAR(1, VAR_DNSTAP_ENABLE) }
dnstap-socket-path{COLON} { YDVAR(1, VAR_DNSTAP_SOCKET_PATH) }
@ -363,6 +366,7 @@ dnstap-log-forwarder-query-messages{COLON} {
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) }
dnstap-log-forwarder-response-messages{COLON} {
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) }
disable-dnssec-lame-check{COLON} { YDVAR(1, VAR_DISABLE_DNSSEC_LAME_CHECK) }
ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) }
ratelimit-slabs{COLON} { YDVAR(1, VAR_RATELIMIT_SLABS) }
ratelimit-size{COLON} { YDVAR(1, VAR_RATELIMIT_SIZE) }

View file

@ -121,10 +121,11 @@ extern struct config_parser_state* cfg_parser;
%token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
%token VAR_DISABLE_DNSSEC_LAME_CHECK
%token VAR_RATELIMIT VAR_RATELIMIT_SLABS VAR_RATELIMIT_SIZE
%token VAR_RATELIMIT_FOR_DOMAIN VAR_RATELIMIT_BELOW_DOMAIN VAR_RATELIMIT_FACTOR
%token VAR_CAPS_WHITELIST VAR_CACHE_MAX_NEGATIVE_TTL VAR_PERMIT_SMALL_HOLDDOWN
%token VAR_QNAME_MINIMISATION
%token VAR_QNAME_MINIMISATION VAR_IP_FREEBIND VAR_DEFINE_TAG VAR_LOCAL_ZONE_TAG
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -191,7 +192,9 @@ content_server: server_num_threads | server_verbosity | server_port |
server_ratelimit_size | server_ratelimit_for_domain |
server_ratelimit_below_domain | server_ratelimit_factor |
server_caps_whitelist | server_cache_max_negative_ttl |
server_permit_small_holddown | server_qname_minimisation
server_permit_small_holddown | server_qname_minimisation |
server_ip_freebind | server_define_tag | server_local_zone_tag |
server_disable_dnssec_lame_check
;
stubstart: VAR_STUB_ZONE
{
@ -662,6 +665,16 @@ server_ip_transparent: VAR_IP_TRANSPARENT STRING_ARG
free($2);
}
;
server_ip_freebind: VAR_IP_FREEBIND STRING_ARG
{
OUTYY(("P(server_ip_freebind:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->ip_freebind =
(strcmp($2, "yes")==0);
free($2);
}
;
server_edns_buffer_size: VAR_EDNS_BUFFER_SIZE STRING_ARG
{
OUTYY(("P(server_edns_buffer_size:%s)\n", $2));
@ -1286,6 +1299,39 @@ server_dns64_synthall: VAR_DNS64_SYNTHALL STRING_ARG
free($2);
}
;
server_define_tag: VAR_DEFINE_TAG STRING_ARG
{
char* p, *s = $2;
OUTYY(("P(server_define_tag:%s)\n", $2));
while((p=strsep(&s, " \t\n")) != NULL) {
if(*p) {
if(!config_add_tag(cfg_parser->cfg, p))
yyerror("could not define-tag, "
"out of memory");
}
}
free($2);
}
;
server_local_zone_tag: VAR_LOCAL_ZONE_TAG STRING_ARG STRING_ARG
{
size_t len = 0;
uint8_t* bitlist = config_parse_taglist(cfg_parser->cfg, $3,
&len);
free($3);
OUTYY(("P(server_local_zone_tag:%s)\n", $2));
if(!bitlist)
yyerror("could not parse tags, (define-tag them first)");
if(bitlist) {
if(!cfg_strbytelist_insert(
&cfg_parser->cfg->local_zone_tags,
$2, bitlist, len)) {
yyerror("out of memory");
free($2);
}
}
}
;
server_ratelimit: VAR_RATELIMIT STRING_ARG
{
OUTYY(("P(server_ratelimit:%s)\n", $2));
@ -1643,6 +1689,15 @@ py_script: VAR_PYTHON_SCRIPT STRING_ARG
free(cfg_parser->cfg->python_script);
cfg_parser->cfg->python_script = $2;
}
server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG
{
OUTYY(("P(disable_dnssec_lame_check:%s)\n", $2));
if (strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->disable_dnssec_lame_check =
(strcmp($2, "yes")==0);
free($2);
}
%%
/* parse helper routines could be here */

View file

@ -256,11 +256,13 @@ dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2)
log_assert(len1 == len2 && len1 != 0);
/* compare labels */
while(len1--) {
if(tolower((unsigned char)*d1++) != tolower((unsigned char)*d2++)) {
if(tolower((unsigned char)d1[-1]) < tolower((unsigned char)d2[-1]))
if(tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) {
if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2))
return -1;
return 1;
}
d1++;
d2++;
}
len1 = *d1++;
len2 = *d2++;
@ -281,8 +283,10 @@ dname_query_hash(uint8_t* dname, hashvalue_t h)
log_assert(lablen <= LDNS_MAX_LABELLEN);
labuf[0] = lablen;
i=0;
while(lablen--)
labuf[++i] = (uint8_t)tolower((unsigned char)*dname++);
while(lablen--) {
labuf[++i] = (uint8_t)tolower((unsigned char)*dname);
dname++;
}
h = hashlittle(labuf, labuf[0] + 1, h);
lablen = *dname++;
}
@ -309,8 +313,10 @@ dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_t h)
log_assert(lablen <= LDNS_MAX_LABELLEN);
labuf[0] = lablen;
i=0;
while(lablen--)
labuf[++i] = (uint8_t)tolower((unsigned char)*dname++);
while(lablen--) {
labuf[++i] = (uint8_t)tolower((unsigned char)*dname);
dname++;
}
h = hashlittle(labuf, labuf[0] + 1, h);
lablen = *dname++;
}

View file

@ -717,16 +717,23 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
uint16_t
calc_edns_field_size(struct edns_data* edns)
{
size_t rdatalen = 0;
struct edns_option* opt;
if(!edns || !edns->edns_present)
return 0;
/* domain root '.' + type + class + ttl + rdatalen(=0) */
return 1 + 2 + 2 + 4 + 2;
for(opt = edns->opt_list; opt; opt = opt->next) {
rdatalen += 4 + opt->opt_len;
}
/* domain root '.' + type + class + ttl + rdatalen */
return 1 + 2 + 2 + 4 + 2 + rdatalen;
}
void
attach_edns_record(sldns_buffer* pkt, struct edns_data* edns)
{
size_t len;
size_t rdatapos;
struct edns_option* opt;
if(!edns || !edns->edns_present)
return;
/* inc additional count */
@ -742,7 +749,18 @@ attach_edns_record(sldns_buffer* pkt, struct edns_data* edns)
sldns_buffer_write_u8(pkt, edns->ext_rcode); /* ttl */
sldns_buffer_write_u8(pkt, edns->edns_version);
sldns_buffer_write_u16(pkt, edns->bits);
rdatapos = sldns_buffer_position(pkt);
sldns_buffer_write_u16(pkt, 0); /* rdatalen */
/* write rdata */
for(opt=edns->opt_list; opt; opt=opt->next) {
sldns_buffer_write_u16(pkt, opt->opt_code);
sldns_buffer_write_u16(pkt, opt->opt_len);
if(opt->opt_len != 0)
sldns_buffer_write(pkt, opt->opt_data, opt->opt_len);
}
if(edns->opt_list)
sldns_buffer_write_u16_at(pkt, rdatapos,
sldns_buffer_position(pkt)-rdatapos-2);
sldns_buffer_flip(pkt);
}

View file

@ -38,6 +38,7 @@
*/
#include "config.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
#include "util/data/dname.h"
#include "util/data/packed_rrset.h"
#include "util/storage/lookup3.h"
@ -933,13 +934,41 @@ parse_packet(sldns_buffer* pkt, struct msg_parse* msg, struct regional* region)
return 0;
}
/** parse EDNS options from EDNS wireformat rdata */
static int
parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len,
struct edns_data* edns, struct regional* region)
{
/* while still more options, and have code+len to read */
/* ignores partial content (i.e. rdata len 3) */
while(rdata_len >= 4) {
uint16_t opt_code = sldns_read_uint16(rdata_ptr);
uint16_t opt_len = sldns_read_uint16(rdata_ptr+2);
rdata_ptr += 4;
rdata_len -= 4;
if(opt_len > rdata_len)
break; /* option code partial */
if(!edns_opt_append(edns, region, opt_code, opt_len,
rdata_ptr)) {
log_err("out of memory");
return 0;
}
rdata_ptr += opt_len;
rdata_len -= opt_len;
}
return 1;
}
int
parse_extract_edns(struct msg_parse* msg, struct edns_data* edns)
parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
struct regional* region)
{
struct rrset_parse* rrset = msg->rrset_first;
struct rrset_parse* prev = 0;
struct rrset_parse* found = 0;
struct rrset_parse* found_prev = 0;
size_t rdata_len;
uint8_t* rdata_ptr;
/* since the class encodes the UDP size, we cannot use hash table to
* find the EDNS OPT record. Scan the packet. */
while(rrset) {
@ -986,13 +1015,25 @@ parse_extract_edns(struct msg_parse* msg, struct edns_data* edns)
edns->edns_version = found->rr_last->ttl_data[1];
edns->bits = sldns_read_uint16(&found->rr_last->ttl_data[2]);
edns->udp_size = ntohs(found->rrset_class);
/* ignore rdata and rrsigs */
edns->opt_list = NULL;
/* take the options */
rdata_len = found->rr_first->size;
rdata_ptr = found->rr_first->ttl_data+6;
if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
return 0;
/* ignore rrsigs */
return 0;
}
int
parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns)
parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
struct regional* region)
{
size_t rdata_len;
uint8_t* rdata_ptr;
log_assert(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) == 1);
log_assert(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0);
log_assert(LDNS_NSCOUNT(sldns_buffer_begin(pkt)) == 0);
@ -1017,6 +1058,17 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns)
edns->ext_rcode = sldns_buffer_read_u8(pkt); /* ttl used for bits */
edns->edns_version = sldns_buffer_read_u8(pkt);
edns->bits = sldns_buffer_read_u16(pkt);
/* ignore rdata and rrsigs */
edns->opt_list = NULL;
/* take the options */
rdata_len = sldns_buffer_read_u16(pkt);
if(sldns_buffer_remaining(pkt) < rdata_len)
return LDNS_RCODE_FORMERR;
rdata_ptr = sldns_buffer_current(pkt);
if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
return LDNS_RCODE_SERVFAIL;
/* ignore rrsigs */
return 0;
}

View file

@ -69,6 +69,7 @@ struct sldns_buffer;
struct rrset_parse;
struct rr_parse;
struct regional;
struct edns_option;
/** number of buckets in parse rrset hash table. Must be power of 2. */
#define PARSE_TABLE_SIZE 32
@ -202,7 +203,8 @@ struct rr_parse {
/**
* EDNS data storage
* EDNS rdata is ignored.
* rdata is parsed in a list (has accessor functions). allocated in a
* region.
*/
struct edns_data {
/** if EDNS OPT record was present */
@ -215,6 +217,22 @@ struct edns_data {
uint16_t bits;
/** UDP reassembly size. */
uint16_t udp_size;
/** rdata element list, or NULL if none */
struct edns_option* opt_list;
};
/**
* EDNS option
*/
struct edns_option {
/** next item in list */
struct edns_option* next;
/** type of this edns option */
uint16_t opt_code;
/** length of this edns option (cannot exceed uint16 in encoding) */
size_t opt_len;
/** data of this edns option; allocated in region, or NULL if len=0 */
uint8_t* opt_data;
};
/**
@ -249,10 +267,12 @@ int parse_packet(struct sldns_buffer* pkt, struct msg_parse* msg,
* @param msg: parsed message structure. Modified on exit, if EDNS was present
* it is removed from the additional section.
* @param edns: the edns data is stored here. Does not have to be initialised.
* @param region: region to alloc results in (edns option contents)
* @return: 0 on success. or an RCODE on an error.
* RCODE formerr if OPT in wrong section, and so on.
*/
int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns);
int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
struct regional* region);
/**
* If EDNS data follows a query section, extract it and initialize edns struct.
@ -260,10 +280,12 @@ int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns);
* section. At end, right after EDNS data or no movement if failed.
* @param edns: the edns data allocated by the caller. Does not have to be
* initialised.
* @param region: region to alloc results in (edns option contents)
* @return: 0 on success, or an RCODE on error.
* RCODE formerr if OPT is badly formatted and so on.
*/
int parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns);
int parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns,
struct regional* region);
/**
* Calculate hash value for rrset in packet.

View file

@ -461,7 +461,7 @@ int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc,
if((ret = parse_packet(pkt, msg, region)) != 0) {
return ret;
}
if((ret = parse_extract_edns(msg, edns)) != 0)
if((ret = parse_extract_edns(msg, edns, region)) != 0)
return ret;
/* parse OK, allocate return structures */
@ -857,3 +857,155 @@ reply_all_rrsets_secure(struct reply_info* rep)
}
return 1;
}
int edns_opt_append(struct edns_data* edns, struct regional* region,
uint16_t code, size_t len, uint8_t* data)
{
struct edns_option** prevp;
struct edns_option* opt;
/* allocate new element */
opt = (struct edns_option*)regional_alloc(region, sizeof(*opt));
if(!opt)
return 0;
opt->next = NULL;
opt->opt_code = code;
opt->opt_len = len;
opt->opt_data = regional_alloc_init(region, data, len);
if(!opt->opt_data)
return 0;
/* append at end of list */
prevp = &edns->opt_list;
while(*prevp != NULL)
prevp = &((*prevp)->next);
*prevp = opt;
return 1;
}
int edns_opt_inplace_reply(struct edns_data* edns, struct regional* region)
{
(void)region;
/* remove all edns options from the reply, because only the
* options that we understand should be in the reply
* (sec 6.1.2 RFC 6891) */
edns->opt_list = NULL;
return 1;
}
struct edns_option* edns_opt_copy_region(struct edns_option* list,
struct regional* region)
{
struct edns_option* result = NULL, *cur = NULL, *s;
while(list) {
/* copy edns option structure */
s = regional_alloc_init(region, list, sizeof(*list));
if(!s) return NULL;
s->next = NULL;
/* copy option data */
if(s->opt_data) {
s->opt_data = regional_alloc_init(region, s->opt_data,
s->opt_len);
if(!s->opt_data)
return NULL;
}
/* link into list */
if(cur)
cur->next = s;
else result = s;
cur = s;
/* examine next element */
list = list->next;
}
return result;
}
int edns_opt_compare(struct edns_option* p, struct edns_option* q)
{
if(!p && !q) return 0;
if(!p) return -1;
if(!q) return 1;
log_assert(p && q);
if(p->opt_code != q->opt_code)
return (int)q->opt_code - (int)p->opt_code;
if(p->opt_len != q->opt_len)
return (int)q->opt_len - (int)p->opt_len;
if(p->opt_len != 0)
return memcmp(p->opt_data, q->opt_data, p->opt_len);
return 0;
}
int edns_opt_list_compare(struct edns_option* p, struct edns_option* q)
{
int r;
while(p && q) {
r = edns_opt_compare(p, q);
if(r != 0)
return r;
p = p->next;
q = q->next;
}
if(p || q) {
/* uneven length lists */
if(p) return 1;
if(q) return -1;
}
return 0;
}
void edns_opt_list_free(struct edns_option* list)
{
struct edns_option* n;
while(list) {
free(list->opt_data);
n = list->next;
free(list);
list = n;
}
}
struct edns_option* edns_opt_copy_alloc(struct edns_option* list)
{
struct edns_option* result = NULL, *cur = NULL, *s;
while(list) {
/* copy edns option structure */
s = memdup(list, sizeof(*list));
if(!s) {
edns_opt_list_free(result);
return NULL;
}
s->next = NULL;
/* copy option data */
if(s->opt_data) {
s->opt_data = memdup(s->opt_data, s->opt_len);
if(!s->opt_data) {
edns_opt_list_free(result);
return NULL;
}
}
/* link into list */
if(cur)
cur->next = s;
else result = s;
cur = s;
/* examine next element */
list = list->next;
}
return result;
}
struct edns_option* edns_opt_find(struct edns_option* list, uint16_t code)
{
struct edns_option* p;
for(p=list; p; p=p->next) {
if(p->opt_code == code)
return p;
}
return NULL;
}

View file

@ -437,4 +437,56 @@ void log_dns_msg(const char* str, struct query_info* qinfo,
void log_query_info(enum verbosity_value v, const char* str,
struct query_info* qinf);
/**
* Append edns option to edns data structure
*/
int edns_opt_append(struct edns_data* edns, struct regional* region,
uint16_t code, size_t len, uint8_t* data);
/**
* Find edns option in edns list
* @param list: list of edns options (eg. edns.opt_list)
* @param code: opt code to find.
* @return NULL or the edns_option element.
*/
struct edns_option* edns_opt_find(struct edns_option* list, uint16_t code);
/**
* Transform edns data structure from query structure into reply structure.
* In place transform, for errors and cache replies.
* @param edns: on input contains the edns from the query. On output contains
* the edns for the answer. Add new options to the opt_list to put them
* in the answer (allocated in the region, with edns_opt_append).
* @param region: to allocate stuff in.
* @return false on failure (servfail to client, or for some error encodings,
* no EDNS options in the answer).
*/
int edns_opt_inplace_reply(struct edns_data* edns, struct regional* region);
/**
* Copy edns option list allocated to the new region
*/
struct edns_option* edns_opt_copy_region(struct edns_option* list,
struct regional* region);
/**
* Copy edns option list allocated with malloc
*/
struct edns_option* edns_opt_copy_alloc(struct edns_option* list);
/**
* Free edns option list allocated with malloc
*/
void edns_opt_list_free(struct edns_option* list);
/**
* Compare an edns option. (not entire list). Also compares contents.
*/
int edns_opt_compare(struct edns_option* p, struct edns_option* q);
/**
* Compare edns option lists, also the order and contents of edns-options.
*/
int edns_opt_list_compare(struct edns_option* p, struct edns_option* q);
#endif /* UTIL_DATA_MSGREPLY_H */

View file

@ -78,6 +78,9 @@
#ifdef WITH_PYTHONMODULE
#include "pythonmod/pythonmod.h"
#endif
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
#endif
int
fptr_whitelist_comm_point(comm_point_callback_t *fptr)
@ -264,8 +267,8 @@ int
fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen,
struct edns_option* opt_list, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen,
struct module_qstate* q))
{
if(fptr == &worker_send_query) return 1;
@ -314,6 +317,9 @@ fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id))
else if(fptr == &dns64_init) return 1;
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_init) return 1;
#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_init) return 1;
#endif
return 0;
}
@ -326,6 +332,9 @@ fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id))
else if(fptr == &dns64_deinit) return 1;
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_deinit) return 1;
#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_deinit) return 1;
#endif
return 0;
}
@ -339,6 +348,9 @@ fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate,
else if(fptr == &dns64_operate) return 1;
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_operate) return 1;
#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_operate) return 1;
#endif
return 0;
}
@ -352,6 +364,9 @@ fptr_whitelist_mod_inform_super(void (*fptr)(
else if(fptr == &dns64_inform_super) return 1;
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_inform_super) return 1;
#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_inform_super) return 1;
#endif
return 0;
}
@ -365,6 +380,9 @@ fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate,
else if(fptr == &dns64_clear) return 1;
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_clear) return 1;
#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_clear) return 1;
#endif
return 0;
}
@ -377,6 +395,9 @@ fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id))
else if(fptr == &dns64_get_mem) return 1;
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_get_mem) return 1;
#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_get_mem) return 1;
#endif
return 0;
}

View file

@ -212,7 +212,7 @@ int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_t fptr);
int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen,
struct edns_option*, struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen,
struct module_qstate* q));

View file

@ -3844,6 +3844,8 @@
4412,
4413,
4416,
4418,
4420,
4425,
4426,
4430,
@ -3904,6 +3906,7 @@
4599,
4600,
4601,
4621,
4658,
4659,
4660,
@ -4222,6 +4225,7 @@
5436,
5437,
5443,
5450,
5453,
5454,
5455,
@ -4598,6 +4602,7 @@
7201,
7227,
7235,
7244,
7262,
7272,
7273,
@ -4651,6 +4656,7 @@
7570,
7574,
7588,
7606,
7624,
7627,
7628,
@ -5269,6 +5275,7 @@
23004,
23005,
23272,
23294,
23333,
23400,
23401,

View file

@ -214,6 +214,8 @@ struct module_env {
* EDNS, the answer is likely to be useless for this domain.
* @param nocaps: do not use caps_for_id, use the qname as given.
* (ignored if caps_for_id is disabled).
* @param opt_list: set these EDNS options on the outgoing packet.
* or NULL if none (the list is deep-copied).
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: delegation point name.
@ -226,9 +228,9 @@ struct module_env {
*/
struct outbound_entry* (*send_query)(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
int want_dnssec, int nocaps, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen,
struct module_qstate* q);
int want_dnssec, int nocaps, struct edns_option* opt_list,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, struct module_qstate* q);
/**
* Detach-subqueries.

View file

@ -783,7 +783,7 @@ void* outgoing_ssl_fd(void* sslctx, int fd)
#endif
}
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK)
/** global lock list for openssl locks */
static lock_basic_t *ub_openssl_locks = NULL;
@ -808,7 +808,7 @@ ub_crypto_lock_cb(int mode, int type, const char *ATTR_UNUSED(file),
int ub_openssl_lock_init(void)
{
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK)
int i;
ub_openssl_locks = (lock_basic_t*)reallocarray(
NULL, (size_t)CRYPTO_num_locks(), sizeof(lock_basic_t));
@ -825,7 +825,7 @@ int ub_openssl_lock_init(void)
void ub_openssl_lock_delete(void)
{
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK)
int i;
if(!ub_openssl_locks)
return;

View file

@ -40,6 +40,7 @@
*/
#include "config.h"
#include "util/netevent.h"
#include "util/ub_event.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/fptr_wlist.h"
@ -89,48 +90,29 @@
#define NUM_UDP_PER_SELECT 1
#endif
/* We define libevent structures here to hide the libevent stuff. */
#ifdef USE_MINI_EVENT
# ifdef USE_WINSOCK
# include "util/winsock_event.h"
# else
# include "util/mini_event.h"
# endif /* USE_WINSOCK */
#else /* USE_MINI_EVENT */
/* we use libevent */
# ifdef HAVE_EVENT_H
# include <event.h>
# else
# include "event2/event.h"
# include "event2/event_struct.h"
# include "event2/event_compat.h"
# endif
#endif /* USE_MINI_EVENT */
/**
* The internal event structure for keeping libevent info for the event.
* The internal event structure for keeping ub_event info for the event.
* Possibly other structures (list, tree) this is part of.
*/
struct internal_event {
/** the comm base */
struct comm_base* base;
/** libevent event type, alloced here */
struct event ev;
/** ub_event event type */
struct ub_event* ev;
};
/**
* Internal base structure, so that every thread has its own events.
*/
struct internal_base {
/** libevent event_base type. */
struct event_base* base;
/** ub_event event_base type. */
struct ub_event_base* base;
/** seconds time pointer points here */
time_t secs;
/** timeval with current time */
struct timeval now;
/** the event used for slow_accept timeouts */
struct event slow_accept;
struct ub_event* slow_accept;
/** true if slow_accept is enabled */
int slow_accept_enabled;
};
@ -139,10 +121,12 @@ struct internal_base {
* Internal timer structure, to store timer event in.
*/
struct internal_timer {
/** the super struct from which derived */
struct comm_timer super;
/** the comm base */
struct comm_base* base;
/** libevent event type, alloced here */
struct event ev;
/** ub_event event type */
struct ub_event* ev;
/** is timer enabled */
uint8_t enabled;
};
@ -151,8 +135,8 @@ struct internal_timer {
* Internal signal structure, to store signal event in.
*/
struct internal_signal {
/** libevent event type, alloced here */
struct event ev;
/** ub_event event type */
struct ub_event* ev;
/** next in signal list */
struct internal_signal* next;
};
@ -164,26 +148,13 @@ static struct comm_point* comm_point_create_tcp_handler(
/* -------- End of local definitions -------- */
#ifdef USE_MINI_EVENT
/** minievent updates the time when it blocks. */
#define comm_base_now(x) /* nothing to do */
#else /* !USE_MINI_EVENT */
/** fillup the time values in the event base */
static void
comm_base_now(struct comm_base* b)
{
if(gettimeofday(&b->eb->now, NULL) < 0) {
log_err("gettimeofday: %s", strerror(errno));
}
b->eb->secs = (time_t)b->eb->now.tv_sec;
}
#endif /* USE_MINI_EVENT */
struct comm_base*
comm_base_create(int sigs)
{
struct comm_base* b = (struct comm_base*)calloc(1,
sizeof(struct comm_base));
const char *evnm="event", *evsys="", *evmethod="";
if(!b)
return NULL;
b->eb = (struct internal_base*)calloc(1, sizeof(struct internal_base));
@ -191,55 +162,20 @@ comm_base_create(int sigs)
free(b);
return NULL;
}
#ifdef USE_MINI_EVENT
(void)sigs;
/* use mini event time-sharing feature */
b->eb->base = event_init(&b->eb->secs, &b->eb->now);
#else
# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
/* libev */
if(sigs)
b->eb->base=(struct event_base *)ev_default_loop(EVFLAG_AUTO);
else
b->eb->base=(struct event_base *)ev_loop_new(EVFLAG_AUTO);
# else
(void)sigs;
# ifdef HAVE_EVENT_BASE_NEW
b->eb->base = event_base_new();
# else
b->eb->base = event_init();
# endif
# endif
#endif
b->eb->base = ub_default_event_base(sigs, &b->eb->secs, &b->eb->now);
if(!b->eb->base) {
free(b->eb);
free(b);
return NULL;
}
comm_base_now(b);
/* avoid event_get_method call which causes crashes even when
* not printing, because its result is passed */
verbose(VERB_ALGO,
#if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
"libev"
#elif defined(USE_MINI_EVENT)
"event "
#else
"libevent "
#endif
"%s uses %s method.",
event_get_version(),
#ifdef HAVE_EVENT_BASE_GET_METHOD
event_base_get_method(b->eb->base)
#else
"not_obtainable"
#endif
);
ub_comm_base_now(b);
ub_get_event_sys(b->eb->base, &evnm, &evsys, &evmethod);
verbose(VERB_ALGO, "%s %s user %s method.", evnm, evsys, evmethod);
return b;
}
struct comm_base*
comm_base_create_event(struct event_base* base)
comm_base_create_event(struct ub_event_base* base)
{
struct comm_base* b = (struct comm_base*)calloc(1,
sizeof(struct comm_base));
@ -251,7 +187,7 @@ comm_base_create_event(struct event_base* base)
return NULL;
}
b->eb->base = base;
comm_base_now(b);
ub_comm_base_now(b);
return b;
}
@ -261,18 +197,12 @@ comm_base_delete(struct comm_base* b)
if(!b)
return;
if(b->eb->slow_accept_enabled) {
if(event_del(&b->eb->slow_accept) != 0) {
if(ub_event_del(b->eb->slow_accept) != 0) {
log_err("could not event_del slow_accept");
}
ub_event_free(b->eb->slow_accept);
}
#ifdef USE_MINI_EVENT
event_base_free(b->eb->base);
#elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE)
/* only libevent 1.2+ has it, but in 1.2 it is broken -
assertion fails on signal handling ev that is not deleted
in libevent 1.3c (event_base_once appears) this is fixed. */
event_base_free(b->eb->base);
#endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */
ub_event_base_free(b->eb->base);
b->eb->base = NULL;
free(b->eb);
free(b);
@ -284,9 +214,10 @@ comm_base_delete_no_base(struct comm_base* b)
if(!b)
return;
if(b->eb->slow_accept_enabled) {
if(event_del(&b->eb->slow_accept) != 0) {
if(ub_event_del(b->eb->slow_accept) != 0) {
log_err("could not event_del slow_accept");
}
ub_event_free(b->eb->slow_accept);
}
b->eb->base = NULL;
free(b->eb);
@ -304,8 +235,8 @@ void
comm_base_dispatch(struct comm_base* b)
{
int retval;
retval = event_base_dispatch(b->eb->base);
if(retval != 0) {
retval = ub_event_base_dispatch(b->eb->base);
if(retval < 0) {
fatal_exit("event_dispatch returned error %d, "
"errno is %s", retval, strerror(errno));
}
@ -313,7 +244,7 @@ comm_base_dispatch(struct comm_base* b)
void comm_base_exit(struct comm_base* b)
{
if(event_base_loopexit(b->eb->base, NULL) != 0) {
if(ub_event_base_loopexit(b->eb->base) != 0) {
log_err("Could not loopexit");
}
}
@ -326,7 +257,7 @@ void comm_base_set_slow_accept_handlers(struct comm_base* b,
b->cb_arg = arg;
}
struct event_base* comm_base_internal(struct comm_base* b)
struct ub_event_base* comm_base_internal(struct comm_base* b)
{
return b->eb->base;
}
@ -648,10 +579,10 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
rep.c = (struct comm_point*)arg;
log_assert(rep.c->type == comm_udp);
if(!(event&EV_READ))
if(!(event&UB_EV_READ))
return;
log_assert(rep.c && rep.c->buffer && rep.c->fd == fd);
comm_base_now(rep.c->ev->base);
ub_comm_base_now(rep.c->ev->base);
for(i=0; i<NUM_UDP_PER_SELECT; i++) {
sldns_buffer_clear(rep.c->buffer);
rep.addrlen = (socklen_t)sizeof(rep.addr);
@ -736,10 +667,10 @@ comm_point_udp_callback(int fd, short event, void* arg)
rep.c = (struct comm_point*)arg;
log_assert(rep.c->type == comm_udp);
if(!(event&EV_READ))
if(!(event&UB_EV_READ))
return;
log_assert(rep.c && rep.c->buffer && rep.c->fd == fd);
comm_base_now(rep.c->ev->base);
ub_comm_base_now(rep.c->ev->base);
for(i=0; i<NUM_UDP_PER_SELECT; i++) {
sldns_buffer_clear(rep.c->buffer);
rep.addrlen = (socklen_t)sizeof(rep.addr);
@ -839,15 +770,16 @@ int comm_point_perform_accept(struct comm_point* c,
/* set timeout, no mallocs */
tv.tv_sec = NETEVENT_SLOW_ACCEPT_TIME/1000;
tv.tv_usec = NETEVENT_SLOW_ACCEPT_TIME%1000;
event_set(&b->eb->slow_accept, -1, EV_TIMEOUT,
b->eb->slow_accept = ub_event_new(b->eb->base,
-1, UB_EV_TIMEOUT,
comm_base_handle_slow_accept, b);
if(event_base_set(b->eb->base,
&b->eb->slow_accept) != 0) {
if(b->eb->slow_accept == NULL) {
/* we do not want to log here, because
* that would spam the logfiles.
* error: "event_base_set failed." */
}
if(event_add(&b->eb->slow_accept, &tv) != 0) {
else if(ub_event_add(b->eb->slow_accept, &tv)
!= 0) {
/* we do not want to log here,
* error: "event_add failed." */
}
@ -861,7 +793,7 @@ int comm_point_perform_accept(struct comm_point* c,
WSAGetLastError() == WSAECONNRESET)
return -1;
if(WSAGetLastError() == WSAEWOULDBLOCK) {
winsock_tcp_wouldblock(&c->ev->ev, EV_READ);
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
return -1;
}
log_err_addr("accept failed", wsa_strerror(WSAGetLastError()),
@ -885,14 +817,14 @@ static long win_bio_cb(BIO *b, int oper, const char* ATTR_UNUSED(argp),
if( (oper == (BIO_CB_READ|BIO_CB_RETURN) && argl == 0) ||
(oper == (BIO_CB_GETS|BIO_CB_RETURN) && argl == 0)) {
if(WSAGetLastError() == WSAEWOULDBLOCK)
winsock_tcp_wouldblock((struct event*)
BIO_get_callback_arg(b), EV_READ);
ub_winsock_tcp_wouldblock((struct ub_event*)
BIO_get_callback_arg(b), UB_EV_READ);
}
if( (oper == (BIO_CB_WRITE|BIO_CB_RETURN) && argl == 0) ||
(oper == (BIO_CB_PUTS|BIO_CB_RETURN) && argl == 0)) {
if(WSAGetLastError() == WSAEWOULDBLOCK)
winsock_tcp_wouldblock((struct event*)
BIO_get_callback_arg(b), EV_WRITE);
ub_winsock_tcp_wouldblock((struct ub_event*)
BIO_get_callback_arg(b), UB_EV_WRITE);
}
/* return original return value */
return retvalue;
@ -905,9 +837,9 @@ comm_point_tcp_win_bio_cb(struct comm_point* c, void* thessl)
SSL* ssl = (SSL*)thessl;
/* set them both just in case, but usually they are the same BIO */
BIO_set_callback(SSL_get_rbio(ssl), &win_bio_cb);
BIO_set_callback_arg(SSL_get_rbio(ssl), (char*)&c->ev->ev);
BIO_set_callback_arg(SSL_get_rbio(ssl), (char*)c->ev->ev);
BIO_set_callback(SSL_get_wbio(ssl), &win_bio_cb);
BIO_set_callback_arg(SSL_get_wbio(ssl), (char*)&c->ev->ev);
BIO_set_callback_arg(SSL_get_wbio(ssl), (char*)c->ev->ev);
}
#endif
@ -917,11 +849,11 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
struct comm_point* c = (struct comm_point*)arg, *c_hdl;
int new_fd;
log_assert(c->type == comm_tcp_accept);
if(!(event & EV_READ)) {
if(!(event & UB_EV_READ)) {
log_info("ignoring tcp accept event %d", (int)event);
return;
}
comm_base_now(c->ev->base);
ub_comm_base_now(c->ev->base);
/* find free tcp handler. */
if(!c->tcp_free) {
log_warn("accepted too many tcp, connections full");
@ -1297,7 +1229,8 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
if(WSAGetLastError() == WSAEINPROGRESS)
return 1;
if(WSAGetLastError() == WSAEWOULDBLOCK) {
winsock_tcp_wouldblock(&c->ev->ev, EV_READ);
ub_winsock_tcp_wouldblock(c->ev->ev,
UB_EV_READ);
return 1;
}
log_err_addr("read (in tcp s)",
@ -1342,7 +1275,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
if(WSAGetLastError() == WSAEINPROGRESS)
return 1;
if(WSAGetLastError() == WSAEWOULDBLOCK) {
winsock_tcp_wouldblock(&c->ev->ev, EV_READ);
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
return 1;
}
log_err_addr("read (in tcp r)",
@ -1401,7 +1334,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
if(error == WSAEINPROGRESS)
return 1;
else if(error == WSAEWOULDBLOCK) {
winsock_tcp_wouldblock(&c->ev->ev, EV_WRITE);
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1;
} else if(error != 0 && verbosity < 2)
return 0;
@ -1451,7 +1384,8 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
if(WSAGetLastError() == WSAEINPROGRESS)
return 1;
if(WSAGetLastError() == WSAEWOULDBLOCK) {
winsock_tcp_wouldblock(&c->ev->ev, EV_WRITE);
ub_winsock_tcp_wouldblock(c->ev->ev,
UB_EV_WRITE);
return 1;
}
log_err_addr("tcp send s",
@ -1483,7 +1417,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
if(WSAGetLastError() == WSAEINPROGRESS)
return 1;
if(WSAGetLastError() == WSAEWOULDBLOCK) {
winsock_tcp_wouldblock(&c->ev->ev, EV_WRITE);
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1;
}
log_err_addr("tcp send r", wsa_strerror(WSAGetLastError()),
@ -1505,9 +1439,9 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
{
struct comm_point* c = (struct comm_point*)arg;
log_assert(c->type == comm_tcp);
comm_base_now(c->ev->base);
ub_comm_base_now(c->ev->base);
if(event&EV_READ) {
if(event&UB_EV_READ) {
if(!comm_point_tcp_handle_read(fd, c, 0)) {
reclaim_tcp_handler(c);
if(!c->tcp_do_close) {
@ -1519,7 +1453,7 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
}
return;
}
if(event&EV_WRITE) {
if(event&UB_EV_WRITE) {
if(!comm_point_tcp_handle_write(fd, c)) {
reclaim_tcp_handler(c);
if(!c->tcp_do_close) {
@ -1531,7 +1465,7 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
}
return;
}
if(event&EV_TIMEOUT) {
if(event&UB_EV_TIMEOUT) {
verbose(VERB_QUERY, "tcp took too long, dropped");
reclaim_tcp_handler(c);
if(!c->tcp_do_close) {
@ -1548,9 +1482,9 @@ void comm_point_local_handle_callback(int fd, short event, void* arg)
{
struct comm_point* c = (struct comm_point*)arg;
log_assert(c->type == comm_local);
comm_base_now(c->ev->base);
ub_comm_base_now(c->ev->base);
if(event&EV_READ) {
if(event&UB_EV_READ) {
if(!comm_point_tcp_handle_read(fd, c, 1)) {
fptr_ok(fptr_whitelist_comm_point(c->callback));
(void)(*c->callback)(c, c->cb_arg, NETEVENT_CLOSED,
@ -1567,9 +1501,9 @@ void comm_point_raw_handle_callback(int ATTR_UNUSED(fd),
struct comm_point* c = (struct comm_point*)arg;
int err = NETEVENT_NOERROR;
log_assert(c->type == comm_raw);
comm_base_now(c->ev->base);
ub_comm_base_now(c->ev->base);
if(event&EV_TIMEOUT)
if(event&UB_EV_TIMEOUT)
err = NETEVENT_TIMEOUT;
fptr_ok(fptr_whitelist_comm_point_raw(c->callback));
(void)(*c->callback)(c, c->cb_arg, err, NULL);
@ -1609,15 +1543,16 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer,
c->inuse = 0;
c->callback = callback;
c->cb_arg = callback_arg;
evbits = EV_READ | EV_PERSIST;
/* libevent stuff */
event_set(&c->ev->ev, c->fd, evbits, comm_point_udp_callback, c);
if(event_base_set(base->eb->base, &c->ev->ev) != 0) {
evbits = UB_EV_READ | UB_EV_PERSIST;
/* ub_event stuff */
c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
comm_point_udp_callback, c);
if(c->ev->ev == NULL) {
log_err("could not baseset udp event");
comm_point_delete(c);
return NULL;
}
if(fd!=-1 && event_add(&c->ev->ev, c->timeout) != 0 ) {
if(fd!=-1 && ub_event_add(c->ev->ev, c->timeout) != 0 ) {
log_err("could not add udp event");
comm_point_delete(c);
return NULL;
@ -1660,15 +1595,16 @@ comm_point_create_udp_ancil(struct comm_base *base, int fd,
c->tcp_check_nb_connect = 0;
c->callback = callback;
c->cb_arg = callback_arg;
evbits = EV_READ | EV_PERSIST;
/* libevent stuff */
event_set(&c->ev->ev, c->fd, evbits, comm_point_udp_ancil_callback, c);
if(event_base_set(base->eb->base, &c->ev->ev) != 0) {
evbits = UB_EV_READ | UB_EV_PERSIST;
/* ub_event stuff */
c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
comm_point_udp_ancil_callback, c);
if(c->ev->ev == NULL) {
log_err("could not baseset udp event");
comm_point_delete(c);
return NULL;
}
if(fd!=-1 && event_add(&c->ev->ev, c->timeout) != 0 ) {
if(fd!=-1 && ub_event_add(c->ev->ev, c->timeout) != 0 ) {
log_err("could not add udp event");
comm_point_delete(c);
return NULL;
@ -1725,10 +1661,11 @@ comm_point_create_tcp_handler(struct comm_base *base,
/* add to parent free list */
c->tcp_free = parent->tcp_free;
parent->tcp_free = c;
/* libevent stuff */
evbits = EV_PERSIST | EV_READ | EV_TIMEOUT;
event_set(&c->ev->ev, c->fd, evbits, comm_point_tcp_handle_callback, c);
if(event_base_set(base->eb->base, &c->ev->ev) != 0)
/* ub_event stuff */
evbits = UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT;
c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
comm_point_tcp_handle_callback, c);
if(c->ev->ev == NULL)
{
log_err("could not basetset tcphdl event");
parent->tcp_free = c->tcp_free;
@ -1780,17 +1717,20 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num, size_t bufsize,
c->tcp_check_nb_connect = 0;
c->callback = NULL;
c->cb_arg = NULL;
evbits = EV_READ | EV_PERSIST;
/* libevent stuff */
event_set(&c->ev->ev, c->fd, evbits, comm_point_tcp_accept_callback, c);
if(event_base_set(base->eb->base, &c->ev->ev) != 0 ||
event_add(&c->ev->ev, c->timeout) != 0 )
{
evbits = UB_EV_READ | UB_EV_PERSIST;
/* ub_event stuff */
c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
comm_point_tcp_accept_callback, c);
if(c->ev->ev == NULL) {
log_err("could not baseset tcpacc event");
comm_point_delete(c);
return NULL;
}
if (ub_event_add(c->ev->ev, c->timeout) != 0) {
log_err("could not add tcpacc event");
comm_point_delete(c);
return NULL;
}
/* now prealloc the tcp handlers */
for(i=0; i<num; i++) {
c->tcp_handlers[i] = comm_point_create_tcp_handler(base,
@ -1843,11 +1783,12 @@ comm_point_create_tcp_out(struct comm_base *base, size_t bufsize,
c->repinfo.c = c;
c->callback = callback;
c->cb_arg = callback_arg;
evbits = EV_PERSIST | EV_WRITE;
event_set(&c->ev->ev, c->fd, evbits, comm_point_tcp_handle_callback, c);
if(event_base_set(base->eb->base, &c->ev->ev) != 0)
evbits = UB_EV_PERSIST | UB_EV_WRITE;
c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
comm_point_tcp_handle_callback, c);
if(c->ev->ev == NULL)
{
log_err("could not basetset tcpout event");
log_err("could not baseset tcpout event");
sldns_buffer_free(c->buffer);
free(c->ev);
free(c);
@ -1895,14 +1836,19 @@ comm_point_create_local(struct comm_base *base, int fd, size_t bufsize,
c->tcp_check_nb_connect = 0;
c->callback = callback;
c->cb_arg = callback_arg;
/* libevent stuff */
evbits = EV_PERSIST | EV_READ;
event_set(&c->ev->ev, c->fd, evbits, comm_point_local_handle_callback,
c);
if(event_base_set(base->eb->base, &c->ev->ev) != 0 ||
event_add(&c->ev->ev, c->timeout) != 0 )
{
/* ub_event stuff */
evbits = UB_EV_PERSIST | UB_EV_READ;
c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
comm_point_local_handle_callback, c);
if(c->ev->ev == NULL) {
log_err("could not baseset localhdl event");
free(c->ev);
free(c);
return NULL;
}
if (ub_event_add(c->ev->ev, c->timeout) != 0) {
log_err("could not add localhdl event");
ub_event_free(c->ev->ev);
free(c->ev);
free(c);
return NULL;
@ -1943,16 +1889,21 @@ comm_point_create_raw(struct comm_base* base, int fd, int writing,
c->tcp_check_nb_connect = 0;
c->callback = callback;
c->cb_arg = callback_arg;
/* libevent stuff */
/* ub_event stuff */
if(writing)
evbits = EV_PERSIST | EV_WRITE;
else evbits = EV_PERSIST | EV_READ;
event_set(&c->ev->ev, c->fd, evbits, comm_point_raw_handle_callback,
c);
if(event_base_set(base->eb->base, &c->ev->ev) != 0 ||
event_add(&c->ev->ev, c->timeout) != 0 )
{
evbits = UB_EV_PERSIST | UB_EV_WRITE;
else evbits = UB_EV_PERSIST | UB_EV_READ;
c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
comm_point_raw_handle_callback, c);
if(c->ev->ev == NULL) {
log_err("could not baseset rawhdl event");
free(c->ev);
free(c);
return NULL;
}
if (ub_event_add(c->ev->ev, c->timeout) != 0) {
log_err("could not add rawhdl event");
ub_event_free(c->ev->ev);
free(c->ev);
free(c);
return NULL;
@ -1966,7 +1917,7 @@ comm_point_close(struct comm_point* c)
if(!c)
return;
if(c->fd != -1)
if(event_del(&c->ev->ev) != 0) {
if(ub_event_del(c->ev->ev) != 0) {
log_err("could not event_del on close");
}
/* close fd after removing from event lists, or epoll.. is messed up */
@ -2002,6 +1953,7 @@ comm_point_delete(struct comm_point* c)
free(c->timeout);
if(c->type == comm_tcp || c->type == comm_local)
sldns_buffer_free(c->buffer);
ub_event_free(c->ev->ev);
free(c->ev);
free(c);
}
@ -2051,7 +2003,7 @@ void
comm_point_stop_listening(struct comm_point* c)
{
verbose(VERB_ALGO, "comm point stop listening %d", c->fd);
if(event_del(&c->ev->ev) != 0) {
if(ub_event_del(c->ev->ev) != 0) {
log_err("event_del error to stoplisten");
}
}
@ -2074,17 +2026,17 @@ comm_point_start_listening(struct comm_point* c, int newfd, int sec)
return;
}
}
c->ev->ev.ev_events |= EV_TIMEOUT;
ub_event_add_bits(c->ev->ev, UB_EV_TIMEOUT);
#ifndef S_SPLINT_S /* splint fails on struct timeval. */
c->timeout->tv_sec = sec;
c->timeout->tv_usec = 0;
#endif /* S_SPLINT_S */
}
if(c->type == comm_tcp) {
c->ev->ev.ev_events &= ~(EV_READ|EV_WRITE);
ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE);
if(c->tcp_is_reading)
c->ev->ev.ev_events |= EV_READ;
else c->ev->ev.ev_events |= EV_WRITE;
ub_event_add_bits(c->ev->ev, UB_EV_READ);
else ub_event_add_bits(c->ev->ev, UB_EV_WRITE);
}
if(newfd != -1) {
if(c->fd != -1) {
@ -2095,9 +2047,9 @@ comm_point_start_listening(struct comm_point* c, int newfd, int sec)
#endif
}
c->fd = newfd;
c->ev->ev.ev_fd = c->fd;
ub_event_set_fd(c->ev->ev, c->fd);
}
if(event_add(&c->ev->ev, sec==0?NULL:c->timeout) != 0) {
if(ub_event_add(c->ev->ev, sec==0?NULL:c->timeout) != 0) {
log_err("event_add failed. in cpsl.");
}
}
@ -2105,13 +2057,13 @@ comm_point_start_listening(struct comm_point* c, int newfd, int sec)
void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr)
{
verbose(VERB_ALGO, "comm point listen_for_rw %d %d", c->fd, wr);
if(event_del(&c->ev->ev) != 0) {
if(ub_event_del(c->ev->ev) != 0) {
log_err("event_del error to cplf");
}
c->ev->ev.ev_events &= ~(EV_READ|EV_WRITE);
if(rd) c->ev->ev.ev_events |= EV_READ;
if(wr) c->ev->ev.ev_events |= EV_WRITE;
if(event_add(&c->ev->ev, c->timeout) != 0) {
ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE);
if(rd) ub_event_add_bits(c->ev->ev, UB_EV_READ);
if(wr) ub_event_add_bits(c->ev->ev, UB_EV_WRITE);
if(ub_event_add(c->ev->ev, c->timeout) != 0) {
log_err("event_add failed. in cplf.");
}
}
@ -2137,29 +2089,24 @@ size_t comm_point_get_mem(struct comm_point* c)
struct comm_timer*
comm_timer_create(struct comm_base* base, void (*cb)(void*), void* cb_arg)
{
struct comm_timer *tm = (struct comm_timer*)calloc(1,
sizeof(struct comm_timer));
if(!tm)
return NULL;
tm->ev_timer = (struct internal_timer*)calloc(1,
struct internal_timer *tm = (struct internal_timer*)calloc(1,
sizeof(struct internal_timer));
if(!tm->ev_timer) {
if(!tm) {
log_err("malloc failed");
free(tm);
return NULL;
}
tm->ev_timer->base = base;
tm->callback = cb;
tm->cb_arg = cb_arg;
event_set(&tm->ev_timer->ev, -1, EV_TIMEOUT,
comm_timer_callback, tm);
if(event_base_set(base->eb->base, &tm->ev_timer->ev) != 0) {
tm->super.ev_timer = tm;
tm->base = base;
tm->super.callback = cb;
tm->super.cb_arg = cb_arg;
tm->ev = ub_event_new(base->eb->base, -1, UB_EV_TIMEOUT,
comm_timer_callback, &tm->super);
if(tm->ev == NULL) {
log_err("timer_create: event_base_set failed.");
free(tm->ev_timer);
free(tm);
return NULL;
}
return tm;
return &tm->super;
}
void
@ -2167,7 +2114,7 @@ comm_timer_disable(struct comm_timer* timer)
{
if(!timer)
return;
evtimer_del(&timer->ev_timer->ev);
ub_timer_del(timer->ev_timer->ev);
timer->ev_timer->enabled = 0;
}
@ -2177,12 +2124,8 @@ comm_timer_set(struct comm_timer* timer, struct timeval* tv)
log_assert(tv);
if(timer->ev_timer->enabled)
comm_timer_disable(timer);
event_set(&timer->ev_timer->ev, -1, EV_TIMEOUT,
comm_timer_callback, timer);
if(event_base_set(timer->ev_timer->base->eb->base,
&timer->ev_timer->ev) != 0)
log_err("comm_timer_set: set_base failed.");
if(evtimer_add(&timer->ev_timer->ev, tv) != 0)
if(ub_timer_add(timer->ev_timer->ev, timer->ev_timer->base->eb->base,
comm_timer_callback, timer, tv) != 0)
log_err("comm_timer_set: evtimer_add failed.");
timer->ev_timer->enabled = 1;
}
@ -2193,17 +2136,20 @@ comm_timer_delete(struct comm_timer* timer)
if(!timer)
return;
comm_timer_disable(timer);
/* Free the sub struct timer->ev_timer derived from the super struct timer.
* i.e. assert(timer == timer->ev_timer)
*/
ub_event_free(timer->ev_timer->ev);
free(timer->ev_timer);
free(timer);
}
void
comm_timer_callback(int ATTR_UNUSED(fd), short event, void* arg)
{
struct comm_timer* tm = (struct comm_timer*)arg;
if(!(event&EV_TIMEOUT))
if(!(event&UB_EV_TIMEOUT))
return;
comm_base_now(tm->ev_timer->base);
ub_comm_base_now(tm->ev_timer->base);
tm->ev_timer->enabled = 0;
fptr_ok(fptr_whitelist_comm_timer(tm->callback));
(*tm->callback)(tm->cb_arg);
@ -2216,9 +2162,9 @@ comm_timer_is_set(struct comm_timer* timer)
}
size_t
comm_timer_get_mem(struct comm_timer* timer)
comm_timer_get_mem(struct comm_timer* ATTR_UNUSED(timer))
{
return sizeof(*timer) + sizeof(struct internal_timer);
return sizeof(struct internal_timer);
}
struct comm_signal*
@ -2242,9 +2188,9 @@ void
comm_signal_callback(int sig, short event, void* arg)
{
struct comm_signal* comsig = (struct comm_signal*)arg;
if(!(event & EV_SIGNAL))
if(!(event & UB_EV_SIGNAL))
return;
comm_base_now(comsig->base);
ub_comm_base_now(comsig->base);
fptr_ok(fptr_whitelist_comm_signal(comsig->callback));
(*comsig->callback)(sig, comsig->cb_arg);
}
@ -2260,14 +2206,16 @@ comm_signal_bind(struct comm_signal* comsig, int sig)
}
log_assert(comsig);
/* add signal event */
signal_set(&entry->ev, sig, comm_signal_callback, comsig);
if(event_base_set(comsig->base->eb->base, &entry->ev) != 0) {
log_err("Could not set signal base");
entry->ev = ub_signal_new(comsig->base->eb->base, sig,
comm_signal_callback, comsig);
if(entry->ev == NULL) {
log_err("Could not create signal event");
free(entry);
return 0;
}
if(signal_add(&entry->ev, NULL) != 0) {
if(ub_signal_add(entry->ev, NULL) != 0) {
log_err("Could not add signal handler");
ub_event_free(entry->ev);
free(entry);
return 0;
}
@ -2286,7 +2234,8 @@ comm_signal_delete(struct comm_signal* comsig)
p=comsig->ev_signal;
while(p) {
np = p->next;
signal_del(&p->ev);
ub_signal_del(p->ev);
ub_event_free(p->ev);
free(p);
p = np;
}

View file

@ -63,12 +63,12 @@
struct sldns_buffer;
struct comm_point;
struct comm_reply;
struct event_base;
struct ub_event_base;
/* internal event notification data storage structure. */
struct internal_event;
struct internal_base;
struct internal_timer;
struct internal_timer; /* A sub struct of the comm_timer super struct */
/** callback from communication point function type */
typedef int comm_point_callback_t(struct comm_point*, void*, int,
@ -265,7 +265,7 @@ struct comm_point {
* Structure only for making timeout events.
*/
struct comm_timer {
/** the internal event stuff */
/** the internal event stuff (derived) */
struct internal_timer* ev_timer;
/** callback function, takes user arg only */
@ -301,12 +301,12 @@ struct comm_signal {
struct comm_base* comm_base_create(int sigs);
/**
* Create comm base that uses the given event_base (underlying event
* mechanism pointer).
* @param base: underlying lib event base.
* Create comm base that uses the given ub_event_base (underlying pluggable
* event mechanism pointer).
* @param base: underlying pluggable event base.
* @return: the new comm base. NULL on error.
*/
struct comm_base* comm_base_create_event(struct event_base* base);
struct comm_base* comm_base_create_event(struct ub_event_base* base);
/**
* Delete comm base structure but not the underlying lib event base.
@ -357,9 +357,9 @@ void comm_base_set_slow_accept_handlers(struct comm_base* b,
/**
* Access internal data structure (for util/tube.c on windows)
* @param b: comm base
* @return event_base. Could be libevent, or internal event handler.
* @return ub_event_base.
*/
struct event_base* comm_base_internal(struct comm_base* b);
struct ub_event_base* comm_base_internal(struct comm_base* b);
/**
* Create an UDP comm point. Calls malloc.

View file

@ -44,6 +44,7 @@
#include "util/net_help.h"
#include "util/netevent.h"
#include "util/fptr_wlist.h"
#include "util/ub_event.h"
#ifndef USE_WINSOCK
/* on unix */
@ -303,6 +304,8 @@ int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len,
d = r;
while(d != (ssize_t)sizeof(len)) {
if((r=write(fd, ((char*)&len)+d, sizeof(len)-d)) == -1) {
if(errno == EAGAIN)
continue; /* temporarily unavail: try again*/
log_err("tube msg write failed: %s", strerror(errno));
(void)fd_set_nonblock(fd);
return 0;
@ -312,6 +315,8 @@ int tube_write_msg(struct tube* tube, uint8_t* buf, uint32_t len,
d = 0;
while(d != (ssize_t)len) {
if((r=write(fd, buf+d, len-d)) == -1) {
if(errno == EAGAIN)
continue; /* temporarily unavail: try again*/
log_err("tube msg write failed: %s", strerror(errno));
(void)fd_set_nonblock(fd);
return 0;
@ -537,7 +542,7 @@ void tube_close_write(struct tube* ATTR_UNUSED(tube))
void tube_remove_bg_listen(struct tube* tube)
{
verbose(VERB_ALGO, "tube remove_bg_listen");
winsock_unregister_wsaevent(&tube->ev_listen);
ub_winsock_unregister_wsaevent(tube->ev_listen);
}
void tube_remove_bg_write(struct tube* tube)
@ -668,8 +673,9 @@ int tube_setup_bg_listen(struct tube* tube, struct comm_base* base,
tube->listen_arg = arg;
if(!comm_base_internal(base))
return 1; /* ignore when no comm base - testing */
return winsock_register_wsaevent(comm_base_internal(base),
&tube->ev_listen, tube->event, &tube_handle_signal, tube);
tube->ev_listen = ub_winsock_register_wsaevent(
comm_base_internal(base), tube->event, &tube_handle_signal, tube);
return tube->ev_listen ? 1 : 0;
}
int tube_setup_bg_write(struct tube* ATTR_UNUSED(tube),

View file

@ -48,7 +48,6 @@ struct tube;
struct tube_res_list;
#ifdef USE_WINSOCK
#include "util/locks.h"
#include "util/winsock_event.h"
#endif
/**
@ -99,7 +98,7 @@ struct tube {
/** the windows sockets event (signaled if items in pipe) */
WSAEVENT event;
/** winsock event storage when registered with event base */
struct event ev_listen;
struct ub_event* ev_listen;
/** lock on the list of outstanding items */
lock_basic_t res_lock;

View file

@ -0,0 +1,448 @@
/*
* util/ub_event.c - directly call libevent (compatability) 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 and implementation for the indirection layer for pluggable
* events that transparently passes it either directly to libevent, or calls
* the libevent compatibility layer functions.
*/
#include "config.h"
#include <sys/time.h>
#include "util/ub_event.h"
#include "util/log.h"
#include "util/netevent.h"
#include "util/tube.h"
/* We define libevent structures here to hide the libevent stuff. */
#ifdef USE_MINI_EVENT
# ifdef USE_WINSOCK
# include "util/winsock_event.h"
# else
# include "util/mini_event.h"
# endif /* USE_WINSOCK */
#else /* USE_MINI_EVENT */
/* we use libevent */
# ifdef HAVE_EVENT_H
# include <event.h>
# else
# include "event2/event.h"
# include "event2/event_struct.h"
# include "event2/event_compat.h"
# endif
#endif /* USE_MINI_EVENT */
#if UB_EV_TIMEOUT != EV_TIMEOUT || UB_EV_READ != EV_READ || \
UB_EV_WRITE != EV_WRITE || UB_EV_SIGNAL != EV_SIGNAL || \
UB_EV_PERSIST != EV_PERSIST
/* Only necessary for libev */
# define NATIVE_BITS(b) ( \
(((b) & UB_EV_TIMEOUT) ? EV_TIMEOUT : 0) \
| (((b) & UB_EV_READ ) ? EV_READ : 0) \
| (((b) & UB_EV_WRITE ) ? EV_WRITE : 0) \
| (((b) & UB_EV_SIGNAL ) ? EV_SIGNAL : 0) \
| (((b) & UB_EV_PERSIST) ? EV_PERSIST : 0))
# define UB_EV_BITS(b) ( \
(((b) & EV_TIMEOUT) ? UB_EV_TIMEOUT : 0) \
| (((b) & EV_READ ) ? UB_EV_READ : 0) \
| (((b) & EV_WRITE ) ? UB_EV_WRITE : 0) \
| (((b) & EV_SIGNAL ) ? UB_EV_SIGNAL : 0) \
| (((b) & EV_PERSIST) ? UB_EV_PERSIST : 0))
# define UB_EV_BITS_CB(C) void my_ ## C (int fd, short bits, void *arg) \
{ (C)(fd, UB_EV_BITS(bits), arg); }
UB_EV_BITS_CB(comm_point_udp_callback);
UB_EV_BITS_CB(comm_point_udp_ancil_callback)
UB_EV_BITS_CB(comm_point_tcp_accept_callback)
UB_EV_BITS_CB(comm_point_tcp_handle_callback)
UB_EV_BITS_CB(comm_timer_callback)
UB_EV_BITS_CB(comm_signal_callback)
UB_EV_BITS_CB(comm_point_local_handle_callback)
UB_EV_BITS_CB(comm_point_raw_handle_callback)
UB_EV_BITS_CB(tube_handle_signal)
UB_EV_BITS_CB(comm_base_handle_slow_accept)
static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*)
{
if(cb == comm_point_udp_callback)
return my_comm_point_udp_callback;
else if(cb == comm_point_udp_ancil_callback)
return my_comm_point_udp_ancil_callback;
else if(cb == comm_point_tcp_accept_callback)
return my_comm_point_tcp_accept_callback;
else if(cb == comm_point_tcp_handle_callback)
return my_comm_point_tcp_handle_callback;
else if(cb == comm_timer_callback)
return my_comm_timer_callback;
else if(cb == comm_signal_callback)
return my_comm_signal_callback;
else if(cb == comm_point_local_handle_callback)
return my_comm_point_local_handle_callback;
else if(cb == comm_point_raw_handle_callback)
return my_comm_point_raw_handle_callback;
else if(cb == tube_handle_signal)
return my_tube_handle_signal;
else if(cb == comm_base_handle_slow_accept)
return my_comm_base_handle_slow_accept;
else
return NULL;
}
#else
# define NATIVE_BITS(b) (b)
# define NATIVE_BITS_CB(c) (c)
#endif
#ifndef EVFLAG_AUTO
#define EVFLAG_AUTO 0
#endif
#define AS_EVENT_BASE(x) \
(((union {struct ub_event_base* a; struct event_base* b;})x).b)
#define AS_UB_EVENT_BASE(x) \
(((union {struct event_base* a; struct ub_event_base* b;})x).b)
#define AS_EVENT(x) \
(((union {struct ub_event* a; struct event* b;})x).b)
#define AS_UB_EVENT(x) \
(((union {struct event* a; struct ub_event* b;})x).b)
const char* ub_event_get_version()
{
return event_get_version();
}
#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT)
static const char* ub_ev_backend2str(int b)
{
switch(b) {
case EVBACKEND_SELECT: return "select";
case EVBACKEND_POLL: return "poll";
case EVBACKEND_EPOLL: return "epoll";
case EVBACKEND_KQUEUE: return "kqueue";
case EVBACKEND_DEVPOLL: return "devpoll";
case EVBACKEND_PORT: return "evport";
}
return "unknown";
}
#endif
void
ub_get_event_sys(struct ub_event_base* base, const char** n, const char** s,
const char** m)
{
#ifdef USE_WINSOCK
(void)base;
*n = "event";
*s = "winsock";
*m = "WSAWaitForMultipleEvents";
#elif defined(USE_MINI_EVENT)
(void)base;
*n = "mini-event";
*s = "internal";
*m = "select";
#else
struct event_base* b = AS_EVENT_BASE(base);
*s = event_get_version();
# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
*n = "libev";
if (!b)
b = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
# ifdef EVBACKEND_SELECT
*m = ub_ev_backend2str(ev_backend((struct ev_loop*)b));
# else
*m = "not obtainable";
# endif
# elif defined(HAVE_EVENT_BASE_GET_METHOD)
*n = "libevent";
if (!b)
b = event_base_new();
*m = event_base_get_method(b);
# else
*n = "unknown";
*m = "not obtainable";
(void)b;
# endif
# ifdef HAVE_EVENT_BASE_FREE
if (b && b != AS_EVENT_BASE(base))
event_base_free(b);
# endif
#endif
}
struct ub_event_base*
ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv)
{
void* base;
(void)base;
#ifdef USE_MINI_EVENT
(void)sigs;
/* use mini event time-sharing feature */
base = event_init(time_secs, time_tv);
#else
(void)time_secs;
(void)time_tv;
# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
/* libev */
if(sigs)
base = ev_default_loop(EVFLAG_AUTO);
else
base = ev_loop_new(EVFLAG_AUTO);
# else
(void)sigs;
# ifdef HAVE_EVENT_BASE_NEW
base = event_base_new();
# else
base = event_init();
# endif
# endif
#endif
return (struct ub_event_base*)base;
}
struct ub_event_base *
ub_libevent_event_base(struct event_base* libevent_base)
{
#ifdef USE_MINI_EVENT
(void)libevent_base;
return NULL;
#else
return AS_UB_EVENT_BASE(libevent_base);
#endif
}
struct event_base *
ub_libevent_get_event_base(struct ub_event_base* base)
{
#ifdef USE_MINI_EVENT
(void)base;
return NULL;
#else
return AS_EVENT_BASE(base);
#endif
}
void
ub_event_base_free(struct ub_event_base* base)
{
#ifdef USE_MINI_EVENT
event_base_free(AS_EVENT_BASE(base));
#elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE)
/* only libevent 1.2+ has it, but in 1.2 it is broken -
assertion fails on signal handling ev that is not deleted
in libevent 1.3c (event_base_once appears) this is fixed. */
event_base_free(AS_EVENT_BASE(base));
#else
(void)base;
#endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */
}
int
ub_event_base_dispatch(struct ub_event_base* base)
{
return event_base_dispatch(AS_EVENT_BASE(base));
}
int
ub_event_base_loopexit(struct ub_event_base* base)
{
return event_base_loopexit(AS_EVENT_BASE(base), NULL);
}
struct ub_event*
ub_event_new(struct ub_event_base* base, int fd, short bits,
void (*cb)(int, short, void*), void* arg)
{
struct event *ev = (struct event*)calloc(1, sizeof(struct event));
if (!ev)
return NULL;
event_set(ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_EVENT_BASE(base), ev) != 0) {
free(ev);
return NULL;
}
return AS_UB_EVENT(ev);
}
struct ub_event*
ub_signal_new(struct ub_event_base* base, int fd,
void (*cb)(int, short, void*), void* arg)
{
struct event *ev = (struct event*)calloc(1, sizeof(struct event));
if (!ev)
return NULL;
signal_set(ev, fd, NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_EVENT_BASE(base), ev) != 0) {
free(ev);
return NULL;
}
return AS_UB_EVENT(ev);
}
struct ub_event*
ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
void (*cb)(int, short, void*), void* arg)
{
#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
struct event *ev = (struct event*)calloc(1, sizeof(struct event));
if (!ev)
return NULL;
if (winsock_register_wsaevent(AS_EVENT_BASE(base), ev, wsaevent, cb,
arg))
return AS_UB_EVENT(ev);
free(ev);
return NULL;
#else
(void)base;
(void)wsaevent;
(void)cb;
(void)arg;
return NULL;
#endif
}
void
ub_event_add_bits(struct ub_event* ev, short bits)
{
AS_EVENT(ev)->ev_events |= NATIVE_BITS(bits);
}
void
ub_event_del_bits(struct ub_event* ev, short bits)
{
AS_EVENT(ev)->ev_events &= ~NATIVE_BITS(bits);
}
void
ub_event_set_fd(struct ub_event* ev, int fd)
{
AS_EVENT(ev)->ev_fd = fd;
}
void
ub_event_free(struct ub_event* ev)
{
if (ev)
free(AS_EVENT(ev));
}
int
ub_event_add(struct ub_event* ev, struct timeval* tv)
{
return event_add(AS_EVENT(ev), tv);
}
int
ub_event_del(struct ub_event* ev)
{
return event_del(AS_EVENT(ev));
}
int
ub_timer_add(struct ub_event* ev, struct ub_event_base* base,
void (*cb)(int, short, void*), void* arg, struct timeval* tv)
{
event_set(AS_EVENT(ev), -1, EV_TIMEOUT, NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_EVENT_BASE(base), AS_EVENT(ev)) != 0)
return -1;
return evtimer_add(AS_EVENT(ev), tv);
}
int
ub_timer_del(struct ub_event* ev)
{
return evtimer_del(AS_EVENT(ev));
}
int
ub_signal_add(struct ub_event* ev, struct timeval* tv)
{
return signal_add(AS_EVENT(ev), tv);
}
int
ub_signal_del(struct ub_event* ev)
{
return signal_del(AS_EVENT(ev));
}
void
ub_winsock_unregister_wsaevent(struct ub_event* ev)
{
#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
winsock_unregister_wsaevent(AS_EVENT(ev));
free(AS_EVENT(ev));
#else
(void)ev;
#endif
}
void
ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
{
#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
winsock_tcp_wouldblock(AS_EVENT(ev), NATIVE_BITS(eventbits));
#else
(void)ev;
(void)eventbits;
#endif
}
void ub_comm_base_now(struct comm_base* cb)
{
#ifdef USE_MINI_EVENT
/** minievent updates the time when it blocks. */
(void)cb; /* nothing to do */
#else /* !USE_MINI_EVENT */
/** fillup the time values in the event base */
time_t *tt;
struct timeval *tv;
comm_base_timept(cb, &tt, &tv);
if(gettimeofday(tv, NULL) < 0) {
log_err("gettimeofday: %s", strerror(errno));
}
*tt = tv->tv_sec;
#endif /* USE_MINI_EVENT */
}

View file

@ -0,0 +1,127 @@
/*
* util/ub_event.h - indirection layer for pluggable events
*
* 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 prototypes for event loop functions.
*
*/
#ifndef UB_EVENT_H
#define UB_EVENT_H
struct ub_event_base;
struct ub_event;
struct comm_base;
struct event_base;
/** event timeout */
#define UB_EV_TIMEOUT 0x01
/** event fd readable */
#define UB_EV_READ 0x02
/** event fd writable */
#define UB_EV_WRITE 0x04
/** event signal */
#define UB_EV_SIGNAL 0x08
/** event must persist */
#define UB_EV_PERSIST 0x10
/** Returns event-base type. Could be "mini-event", "winsock-event" for the
* daemon compile, and will be "pluggable-event<PACKAGE_VERSION>" for
* libunbound.
*/
const char* ub_event_get_version(void);
/** Return the name, system and method for the pluggable event base */
void ub_get_event_sys(struct ub_event_base*, const char** n, const char** s,
const char** m);
/** Return a default event base. In the deamon thess will be the only event
* bases used.
*/
struct ub_event_base* ub_default_event_base(int, time_t*, struct timeval*);
/** Return an ub_event_base constructed for the given libevent event base */
struct ub_event_base* ub_libevent_event_base(struct event_base*);
/** Return the libevent base underlying the given ub_event_base. Will return
* NULL when the ub_event_base does not have an underlying libevent event base
*/
struct event_base* ub_libevent_get_event_base(struct ub_event_base*);
/** Free event base. Free events yourself */
void ub_event_base_free(struct ub_event_base*);
/** Run the event base */
int ub_event_base_dispatch(struct ub_event_base*);
/** exit that loop */
int ub_event_base_loopexit(struct ub_event_base*);
/** Create a new ub_event for the event base */
struct ub_event* ub_event_new(struct ub_event_base*,
int fd, short bits, void (*cb)(int, short, void*), void* arg);
/** Create a new ub_event signal for the event base */
struct ub_event* ub_signal_new(struct ub_event_base*, int fd,
void (*cb)(int, short, void*), void* arg);
/** Create a new ub_event associated with the wsaevent for the event base */
struct ub_event* ub_winsock_register_wsaevent(struct ub_event_base*,
void* wsaevent, void (*cb)(int, short, void*), void* arg);
/** Add event bits for this event to fire on */
void ub_event_add_bits(struct ub_event*, short bits);
/** Configure the event so it will not longer fire on given bits */
void ub_event_del_bits(struct ub_event*, short bits);
/** Change or set the file descriptor on the event */
void ub_event_set_fd(struct ub_event*, int fd);
/** free the event */
void ub_event_free(struct ub_event*);
/** Activate the event. The given timeval is an timeout value. */
int ub_event_add(struct ub_event*, struct timeval*);
/** Deactivate the event */
int ub_event_del(struct ub_event*);
/** Reconfigure and activate a timeout event */
int ub_timer_add(struct ub_event*, struct ub_event_base*,
void (*cb)(int, short, void*), void* arg, struct timeval*);
/** Deactivate the timeout event */
int ub_timer_del(struct ub_event*);
/** Activate a signal event */
int ub_signal_add(struct ub_event*, struct timeval*);
/** Deactivate a signal event */
int ub_signal_del(struct ub_event*);
/** Free a with a wsaevent associated event */
void ub_winsock_unregister_wsaevent(struct ub_event* ev);
/** Signal the eventloop when a TCP windows socket will block on next read
* or write (given by the eventbits)
*/
void ub_winsock_tcp_wouldblock(struct ub_event*, int bits);
/** Equip the comm_base with the current time */
void ub_comm_base_now(struct comm_base* cb);
#endif /* UB_EVENT_H */

View file

@ -0,0 +1,694 @@
/*
* util/ub_event_pluggable.c - call registered pluggable event 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 an implementation for the indirection layer for pluggable
* events that calls the registered pluggable event loop. It also defines a
* default pluggable event loop based on the default libevent (compatibility)
* functions.
*/
#include "config.h"
#include <sys/time.h>
#include "util/ub_event.h"
#include "libunbound/unbound-event.h"
#include "util/netevent.h"
#include "util/log.h"
#include "util/fptr_wlist.h"
/* We define libevent structures here to hide the libevent stuff. */
#ifdef USE_MINI_EVENT
# ifdef USE_WINSOCK
# include "util/winsock_event.h"
# else
# include "util/mini_event.h"
# endif /* USE_WINSOCK */
#else /* USE_MINI_EVENT */
/* we use libevent */
# ifdef HAVE_EVENT_H
# include <event.h>
# else
# include "event2/event.h"
# include "event2/event_struct.h"
# include "event2/event_compat.h"
# endif
#endif /* USE_MINI_EVENT */
#if UB_EV_TIMEOUT != EV_TIMEOUT || UB_EV_READ != EV_READ || \
UB_EV_WRITE != EV_WRITE || UB_EV_SIGNAL != EV_SIGNAL || \
UB_EV_PERSIST != EV_PERSIST
/* Only necessary for libev */
# define NATIVE_BITS(b) ( \
(((b) & UB_EV_TIMEOUT) ? EV_TIMEOUT : 0) \
| (((b) & UB_EV_READ ) ? EV_READ : 0) \
| (((b) & UB_EV_WRITE ) ? EV_WRITE : 0) \
| (((b) & UB_EV_SIGNAL ) ? EV_SIGNAL : 0) \
| (((b) & UB_EV_PERSIST) ? EV_PERSIST : 0))
# define UB_EV_BITS(b) ( \
(((b) & EV_TIMEOUT) ? UB_EV_TIMEOUT : 0) \
| (((b) & EV_READ ) ? UB_EV_READ : 0) \
| (((b) & EV_WRITE ) ? UB_EV_WRITE : 0) \
| (((b) & EV_SIGNAL ) ? UB_EV_SIGNAL : 0) \
| (((b) & EV_PERSIST) ? UB_EV_PERSIST : 0))
# define UB_EV_BITS_CB(C) void my_ ## C (int fd, short bits, void *arg) \
{ (C)(fd, UB_EV_BITS(bits), arg); }
UB_EV_BITS_CB(comm_point_udp_callback);
UB_EV_BITS_CB(comm_point_udp_ancil_callback)
UB_EV_BITS_CB(comm_point_tcp_accept_callback)
UB_EV_BITS_CB(comm_point_tcp_handle_callback)
UB_EV_BITS_CB(comm_timer_callback)
UB_EV_BITS_CB(comm_signal_callback)
UB_EV_BITS_CB(comm_point_local_handle_callback)
UB_EV_BITS_CB(comm_point_raw_handle_callback)
UB_EV_BITS_CB(tube_handle_signal)
UB_EV_BITS_CB(comm_base_handle_slow_accept)
static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*)
{
if(cb == comm_point_udp_callback)
return my_comm_point_udp_callback;
else if(cb == comm_point_udp_ancil_callback)
return my_comm_point_udp_ancil_callback;
else if(cb == comm_point_tcp_accept_callback)
return my_comm_point_tcp_accept_callback;
else if(cb == comm_point_tcp_handle_callback)
return my_comm_point_tcp_handle_callback;
else if(cb == comm_timer_callback)
return my_comm_timer_callback;
else if(cb == comm_signal_callback)
return my_comm_signal_callback;
else if(cb == comm_point_local_handle_callback)
return my_comm_point_local_handle_callback;
else if(cb == comm_point_raw_handle_callback)
return my_comm_point_raw_handle_callback;
else if(cb == tube_handle_signal)
return my_tube_handle_signal;
else if(cb == comm_base_handle_slow_accept)
return my_comm_base_handle_slow_accept;
else
return NULL;
}
#else
# define NATIVE_BITS(b) (b)
# define NATIVE_BITS_CB(c) (c)
#endif
#ifndef EVFLAG_AUTO
#define EVFLAG_AUTO 0
#endif
struct my_event_base {
struct ub_event_base super;
struct event_base* base;
};
struct my_event {
struct ub_event super;
struct event ev;
};
#define AS_MY_EVENT_BASE(x) \
(((union {struct ub_event_base* a; struct my_event_base* b;})x).b)
#define AS_MY_EVENT(x) \
(((union {struct ub_event* a; struct my_event* b;})x).b)
const char* ub_event_get_version()
{
return "pluggable-event"PACKAGE_VERSION;
}
static void
my_event_add_bits(struct ub_event* ev, short bits)
{
AS_MY_EVENT(ev)->ev.ev_events |= NATIVE_BITS(bits);
}
static void
my_event_del_bits(struct ub_event* ev, short bits)
{
AS_MY_EVENT(ev)->ev.ev_events &= ~NATIVE_BITS(bits);
}
static void
my_event_set_fd(struct ub_event* ev, int fd)
{
AS_MY_EVENT(ev)->ev.ev_fd = fd;
}
static void
my_event_free(struct ub_event* ev)
{
free(AS_MY_EVENT(ev));
}
static int
my_event_add(struct ub_event* ev, struct timeval* tv)
{
return event_add(&AS_MY_EVENT(ev)->ev, tv);
}
static int
my_event_del(struct ub_event* ev)
{
return event_del(&AS_MY_EVENT(ev)->ev);
}
static int
my_timer_add(struct ub_event* ev, struct ub_event_base* base,
void (*cb)(int, short, void*), void* arg, struct timeval* tv)
{
event_set(&AS_MY_EVENT(ev)->ev, -1, EV_TIMEOUT,NATIVE_BITS_CB(cb),arg);
if (event_base_set(AS_MY_EVENT_BASE(base)->base, &AS_MY_EVENT(ev)->ev)
!= 0)
return -1;
return evtimer_add(&AS_MY_EVENT(ev)->ev, tv);
}
static int
my_timer_del(struct ub_event* ev)
{
return evtimer_del(&AS_MY_EVENT(ev)->ev);
}
static int
my_signal_add(struct ub_event* ev, struct timeval* tv)
{
return signal_add(&AS_MY_EVENT(ev)->ev, tv);
}
static int
my_signal_del(struct ub_event* ev)
{
return signal_del(&AS_MY_EVENT(ev)->ev);
}
static void
my_winsock_unregister_wsaevent(struct ub_event* ev)
{
#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
winsock_unregister_wsaevent(&AS_MY_EVENT(ev)->ev);
free(AS_MY_EVENT(ev));
#else
(void)ev;
#endif
}
static void
my_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
{
#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
winsock_tcp_wouldblock(&AS_MY_EVENT(ev)->ev, NATIVE_BITS(eventbits));
#else
(void)ev;
(void)eventbits;
#endif
}
static struct ub_event_vmt default_event_vmt = {
my_event_add_bits, my_event_del_bits, my_event_set_fd,
my_event_free, my_event_add, my_event_del,
my_timer_add, my_timer_del, my_signal_add, my_signal_del,
my_winsock_unregister_wsaevent, my_winsock_tcp_wouldblock
};
static void
my_event_base_free(struct ub_event_base* base)
{
#ifdef USE_MINI_EVENT
event_base_free(AS_MY_EVENT_BASE(base)->base);
#elif defined(HAVE_EVENT_BASE_FREE) && defined(HAVE_EVENT_BASE_ONCE)
/* only libevent 1.2+ has it, but in 1.2 it is broken -
assertion fails on signal handling ev that is not deleted
in libevent 1.3c (event_base_once appears) this is fixed. */
event_base_free(AS_MY_EVENT_BASE(base)->base);
#endif /* HAVE_EVENT_BASE_FREE and HAVE_EVENT_BASE_ONCE */
free(AS_MY_EVENT_BASE(base));
}
static int
my_event_base_dispatch(struct ub_event_base* base)
{
return event_base_dispatch(AS_MY_EVENT_BASE(base)->base);
}
static int
my_event_base_loopexit(struct ub_event_base* base, struct timeval* tv)
{
return event_base_loopexit(AS_MY_EVENT_BASE(base)->base, tv);
}
static struct ub_event*
my_event_new(struct ub_event_base* base, int fd, short bits,
void (*cb)(int, short, void*), void* arg)
{
struct my_event *my_ev = (struct my_event*)calloc(1,
sizeof(struct my_event));
if (!my_ev)
return NULL;
event_set(&my_ev->ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
free(my_ev);
return NULL;
}
my_ev->super.magic = UB_EVENT_MAGIC;
my_ev->super.vmt = &default_event_vmt;
return &my_ev->super;
}
static struct ub_event*
my_signal_new(struct ub_event_base* base, int fd,
void (*cb)(int, short, void*), void* arg)
{
struct my_event *my_ev = (struct my_event*)calloc(1,
sizeof(struct my_event));
if (!my_ev)
return NULL;
signal_set(&my_ev->ev, fd, NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_MY_EVENT_BASE(base)->base, &my_ev->ev) != 0) {
free(my_ev);
return NULL;
}
my_ev->super.magic = UB_EVENT_MAGIC;
my_ev->super.vmt = &default_event_vmt;
return &my_ev->super;
}
static struct ub_event*
my_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
void (*cb)(int, short, void*), void* arg)
{
#if defined(USE_MINI_EVENT) && defined(USE_WINSOCK)
struct my_event *my_ev = (struct my_event*)calloc(1,
sizeof(struct my_event));
if (!my_ev)
return NULL;
if (!winsock_register_wsaevent(AS_MY_EVENT_BASE(base)->base,
&my_ev->ev, wsaevent, cb, arg)) {
free(my_ev);
return NULL;
}
my_ev->super.magic = UB_EVENT_MAGIC;
my_ev->super.vmt = &default_event_vmt;
return &my_ev->super;
#else
(void)base;
(void)wsaevent;
(void)cb;
(void)arg;
return NULL;
#endif
}
static struct ub_event_base_vmt default_event_base_vmt = {
my_event_base_free, my_event_base_dispatch,
my_event_base_loopexit, my_event_new, my_signal_new,
my_winsock_register_wsaevent
};
struct ub_event_base*
ub_default_event_base(int sigs, time_t* time_secs, struct timeval* time_tv)
{
struct my_event_base* my_base = (struct my_event_base*)calloc(1,
sizeof(struct my_event_base));
if (!my_base)
return NULL;
#ifdef USE_MINI_EVENT
(void)sigs;
/* use mini event time-sharing feature */
my_base->base = event_init(time_secs, time_tv);
#else
(void)time_secs;
(void)time_tv;
# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
/* libev */
if(sigs)
my_base->base = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
else
my_base->base = (struct event_base*)ev_loop_new(EVFLAG_AUTO);
# else
(void)sigs;
# ifdef HAVE_EVENT_BASE_NEW
my_base->base = event_base_new();
# else
my_base->base = event_init();
# endif
# endif
#endif
if (!my_base->base) {
free(my_base);
return NULL;
}
my_base->super.magic = UB_EVENT_MAGIC;
my_base->super.vmt = &default_event_base_vmt;
return &my_base->super;
}
struct ub_event_base*
ub_libevent_event_base(struct event_base* base)
{
#ifdef USE_MINI_EVENT
(void)base;
return NULL;
#else
struct my_event_base* my_base = (struct my_event_base*)calloc(1,
sizeof(struct my_event_base));
if (!my_base)
return NULL;
my_base->super.magic = UB_EVENT_MAGIC;
my_base->super.vmt = &default_event_base_vmt;
my_base->base = base;
return &my_base->super;
#endif
}
struct event_base*
ub_libevent_get_event_base(struct ub_event_base* base)
{
#ifndef USE_MINI_EVENT
if (base->vmt == &default_event_base_vmt)
return AS_MY_EVENT_BASE(base)->base;
#else
(void)base;
#endif
return NULL;
}
#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT)
static const char* ub_ev_backend2str_pluggable(int b)
{
switch(b) {
case EVBACKEND_SELECT: return "select";
case EVBACKEND_POLL: return "poll";
case EVBACKEND_EPOLL: return "epoll";
case EVBACKEND_KQUEUE: return "kqueue";
case EVBACKEND_DEVPOLL: return "devpoll";
case EVBACKEND_PORT: return "evport";
}
return "unknown";
}
#endif
void
ub_get_event_sys(struct ub_event_base* ub_base, const char** n, const char** s,
const char** m)
{
#ifdef USE_WINSOCK
(void)ub_base;
*n = "pluggable-event";
*s = "winsock";
*m = "WSAWaitForMultipleEvents";
#elif defined(USE_MINI_EVENT)
(void)ub_base;
*n = "pluggable-event";
*s = "internal";
*m = "select";
#else
struct event_base* b = ub_libevent_get_event_base(ub_base);
/* This function is only called from comm_base_create, so
* ub_base is guaranteed to exist and to be the default
* event base.
*/
assert(b);
*n = "pluggable-event";
*s = event_get_version();
# if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
*n = "pluggable-libev";
# ifdef EVBACKEND_SELECT
*m = ub_ev_backend2str_pluggable(ev_backend((struct ev_loop*)b));
# else
*m = "not obtainable";
# endif
# elif defined(HAVE_EVENT_BASE_GET_METHOD)
*n = "pluggable-libevent";
*m = event_base_get_method(b);
# else
*m = "not obtainable";
# endif
#endif
}
void
ub_event_base_free(struct ub_event_base* base)
{
if (base && base->magic == UB_EVENT_MAGIC) {
fptr_ok(base->vmt != &default_event_base_vmt ||
base->vmt->free == my_event_base_free);
(*base->vmt->free)(base);
}
}
int
ub_event_base_dispatch(struct ub_event_base* base)
{
if (base->magic == UB_EVENT_MAGIC) {
fptr_ok(base->vmt != &default_event_base_vmt ||
base->vmt->dispatch == my_event_base_dispatch);
return (*base->vmt->dispatch)(base);
}
return -1;
}
int
ub_event_base_loopexit(struct ub_event_base* base)
{
if (base->magic == UB_EVENT_MAGIC) {
fptr_ok(base->vmt != &default_event_base_vmt ||
base->vmt->loopexit == my_event_base_loopexit);
return (*base->vmt->loopexit)(base, NULL);
}
return -1;
}
struct ub_event*
ub_event_new(struct ub_event_base* base, int fd, short bits,
void (*cb)(int, short, void*), void* arg)
{
if (base->magic == UB_EVENT_MAGIC) {
fptr_ok(base->vmt != &default_event_base_vmt ||
base->vmt->new_event == my_event_new);
return (*base->vmt->new_event)(base, fd, bits, cb, arg);
}
return NULL;
}
struct ub_event*
ub_signal_new(struct ub_event_base* base, int fd,
void (*cb)(int, short, void*), void* arg)
{
if (base->magic == UB_EVENT_MAGIC) {
fptr_ok(base->vmt != &default_event_base_vmt ||
base->vmt->new_signal == my_signal_new);
return (*base->vmt->new_signal)(base, fd, cb, arg);
}
return NULL;
}
struct ub_event*
ub_winsock_register_wsaevent(struct ub_event_base* base, void* wsaevent,
void (*cb)(int, short, void*), void* arg)
{
if (base->magic == UB_EVENT_MAGIC) {
fptr_ok(base->vmt != &default_event_base_vmt ||
base->vmt->winsock_register_wsaevent ==
my_winsock_register_wsaevent);
return (*base->vmt->winsock_register_wsaevent)(base, wsaevent, cb, arg);
}
return NULL;
}
void
ub_event_add_bits(struct ub_event* ev, short bits)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->add_bits == my_event_add_bits);
(*ev->vmt->add_bits)(ev, bits);
}
}
void
ub_event_del_bits(struct ub_event* ev, short bits)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->del_bits == my_event_del_bits);
(*ev->vmt->del_bits)(ev, bits);
}
}
void
ub_event_set_fd(struct ub_event* ev, int fd)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->set_fd == my_event_set_fd);
(*ev->vmt->set_fd)(ev, fd);
}
}
void
ub_event_free(struct ub_event* ev)
{
if (ev && ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->free == my_event_free);
(*ev->vmt->free)(ev);
}
}
int
ub_event_add(struct ub_event* ev, struct timeval* tv)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->add == my_event_add);
return (*ev->vmt->add)(ev, tv);
}
return -1;
}
int
ub_event_del(struct ub_event* ev)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->del == my_event_del);
return (*ev->vmt->del)(ev);
}
return -1;
}
int
ub_timer_add(struct ub_event* ev, struct ub_event_base* base,
void (*cb)(int, short, void*), void* arg, struct timeval* tv)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->add_timer == my_timer_add);
return (*ev->vmt->add_timer)(ev, base, cb, arg, tv);
}
return -1;
}
int
ub_timer_del(struct ub_event* ev)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->del_timer == my_timer_del);
return (*ev->vmt->del_timer)(ev);
}
return -1;
}
int
ub_signal_add(struct ub_event* ev, struct timeval* tv)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->add_signal == my_signal_add);
return (*ev->vmt->add_signal)(ev, tv);
}
return -1;
}
int
ub_signal_del(struct ub_event* ev)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->del_signal == my_signal_del);
return (*ev->vmt->del_signal)(ev);
}
return -1;
}
void
ub_winsock_unregister_wsaevent(struct ub_event* ev)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->winsock_unregister_wsaevent ==
my_winsock_unregister_wsaevent);
(*ev->vmt->winsock_unregister_wsaevent)(ev);
}
}
void
ub_winsock_tcp_wouldblock(struct ub_event* ev, int eventbits)
{
if (ev->magic == UB_EVENT_MAGIC) {
fptr_ok(ev->vmt != &default_event_vmt ||
ev->vmt->winsock_tcp_wouldblock ==
my_winsock_tcp_wouldblock);
(*ev->vmt->winsock_tcp_wouldblock)(ev, eventbits);
}
}
void ub_comm_base_now(struct comm_base* cb)
{
time_t *tt;
struct timeval *tv;
#ifdef USE_MINI_EVENT
/** minievent updates the time when it blocks. */
if (comm_base_internal(cb)->magic == UB_EVENT_MAGIC &&
comm_base_internal(cb)->vmt == &default_event_base_vmt)
return; /* Actually using mini event, so do not set time */
#endif /* USE_MINI_EVENT */
/** fillup the time values in the event base */
comm_base_timept(cb, &tt, &tv);
if(gettimeofday(tv, NULL) < 0) {
log_err("gettimeofday: %s", strerror(errno));
}
*tt = tv->tv_sec;
}

View file

@ -2333,6 +2333,7 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp)
edns.ext_rcode = 0;
edns.edns_version = 0;
edns.bits = EDNS_DO;
edns.opt_list = NULL;
if(sldns_buffer_capacity(buf) < 65535)
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
else edns.udp_size = 65535;

View file

@ -1030,6 +1030,8 @@ anchors_assemble_rrsets(struct val_anchors* anchors)
")", b);
(void)rbtree_delete(anchors->tree, &ta->node);
lock_basic_unlock(&ta->lock);
if(anchors->dlv_anchor == ta)
anchors->dlv_anchor = NULL;
anchors_delfunc(&ta->node, NULL);
ta = next;
continue;

View file

@ -98,6 +98,12 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
}
}
void
secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
{
(void)SHA256(buf, len, res);
}
/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.
@ -186,8 +192,10 @@ dnskey_algo_id_is_supported(int id)
case LDNS_RSAMD5:
/* RFC 6725 deprecates RSAMD5 */
return 0;
#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
#endif
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
@ -227,6 +235,7 @@ log_crypto_error(const char* str, unsigned long e)
log_err("%s crypto %s", str, buf);
}
#ifdef USE_DSA
/**
* Setup DSA key digest in DER encoding ...
* @param sig: input is signature output alloced ptr (unless failure).
@ -268,6 +277,7 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
DSA_SIG_free(dsasig);
return 1;
}
#endif /* USE_DSA */
#ifdef USE_ECDSA
/**
@ -281,32 +291,61 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
static int
setup_ecdsa_sig(unsigned char** sig, unsigned int* len)
{
ECDSA_SIG* ecdsa_sig;
int newlen;
/* convert from two BIGNUMs in the rdata buffer, to ASN notation.
* ASN preable: 30440220 <R 32bytefor256> 0220 <S 32bytefor256>
* the '20' is the length of that field (=bnsize).
i * the '44' is the total remaining length.
* if negative, start with leading zero.
* if starts with 00s, remove them from the number.
*/
uint8_t pre[] = {0x30, 0x44, 0x02, 0x20};
int pre_len = 4;
uint8_t mid[] = {0x02, 0x20};
int mid_len = 2;
int raw_sig_len, r_high, s_high, r_rem=0, s_rem=0;
int bnsize = (int)((*len)/2);
unsigned char* d = *sig;
uint8_t* p;
/* if too short or not even length, fails */
if(*len < 16 || bnsize*2 != (int)*len)
return 0;
/* use the raw data to parse two evenly long BIGNUMs, "r | s". */
ecdsa_sig = ECDSA_SIG_new();
if(!ecdsa_sig) return 0;
ecdsa_sig->r = BN_bin2bn(*sig, bnsize, ecdsa_sig->r);
ecdsa_sig->s = BN_bin2bn(*sig+bnsize, bnsize, ecdsa_sig->s);
if(!ecdsa_sig->r || !ecdsa_sig->s) {
ECDSA_SIG_free(ecdsa_sig);
return 0;
}
/* spool it into ASN format */
*sig = NULL;
newlen = i2d_ECDSA_SIG(ecdsa_sig, sig);
if(newlen <= 0) {
ECDSA_SIG_free(ecdsa_sig);
free(*sig);
/* strip leading zeroes from r (but not last one) */
while(r_rem < bnsize-1 && d[r_rem] == 0)
r_rem++;
/* strip leading zeroes from s (but not last one) */
while(s_rem < bnsize-1 && d[bnsize+s_rem] == 0)
s_rem++;
r_high = ((d[0+r_rem]&0x80)?1:0);
s_high = ((d[bnsize+s_rem]&0x80)?1:0);
raw_sig_len = pre_len + r_high + bnsize - r_rem + mid_len +
s_high + bnsize - s_rem;
*sig = (unsigned char*)malloc((size_t)raw_sig_len);
if(!*sig)
return 0;
p = (uint8_t*)*sig;
p[0] = pre[0];
p[1] = (uint8_t)(raw_sig_len-2);
p[2] = pre[2];
p[3] = (uint8_t)(bnsize + r_high - r_rem);
p += 4;
if(r_high) {
*p = 0;
p += 1;
}
*len = (unsigned int)newlen;
ECDSA_SIG_free(ecdsa_sig);
memmove(p, d+r_rem, (size_t)bnsize-r_rem);
p += bnsize-r_rem;
memmove(p, mid, (size_t)mid_len-1);
p += mid_len-1;
*p = (uint8_t)(bnsize + s_high - s_rem);
p += 1;
if(s_high) {
*p = 0;
p += 1;
}
memmove(p, d+bnsize+s_rem, (size_t)bnsize-s_rem);
*len = (unsigned int)raw_sig_len;
return 1;
}
#endif /* USE_ECDSA */
@ -325,10 +364,13 @@ static int
setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
unsigned char* key, size_t keylen)
{
#ifdef USE_DSA
DSA* dsa;
#endif
RSA* rsa;
switch(algo) {
#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
*evp_key = EVP_PKEY_new();
@ -350,6 +392,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
*digest_type = EVP_dss1();
break;
#endif /* USE_DSA */
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#if defined(HAVE_EVP_SHA256) && defined(USE_SHA2)
@ -508,8 +551,8 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
char** reason)
{
const EVP_MD *digest_type;
EVP_MD_CTX ctx;
int res, dofree = 0;
EVP_MD_CTX* ctx;
int res, dofree = 0, docrypto_free = 0;
EVP_PKEY *evp_key = NULL;
if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) {
@ -518,6 +561,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
EVP_PKEY_free(evp_key);
return sec_status_bogus;
}
#ifdef USE_DSA
/* if it is a DSA signature in bind format, convert to DER format */
if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&
sigblock_len == 1+2*SHA_DIGEST_LENGTH) {
@ -527,10 +571,14 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
EVP_PKEY_free(evp_key);
return sec_status_bogus;
}
dofree = 1;
docrypto_free = 1;
}
#endif
#if defined(USE_ECDSA) && defined(USE_DSA)
else
#endif
#ifdef USE_ECDSA
else if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) {
if(algo == LDNS_ECDSAP256SHA256 || algo == LDNS_ECDSAP384SHA384) {
/* EVP uses ASN prefix on sig, which is not in the wire data */
if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) {
verbose(VERB_QUERY, "verify: failed to setup ECDSA sig");
@ -543,32 +591,48 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
#endif /* USE_ECDSA */
/* do the signature cryptography work */
EVP_MD_CTX_init(&ctx);
if(EVP_VerifyInit(&ctx, digest_type) == 0) {
verbose(VERB_QUERY, "verify: EVP_VerifyInit failed");
#ifdef HAVE_EVP_MD_CTX_NEW
ctx = EVP_MD_CTX_new();
#else
ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx));
if(ctx) EVP_MD_CTX_init(ctx);
#endif
if(!ctx) {
log_err("EVP_MD_CTX_new: malloc failure");
EVP_PKEY_free(evp_key);
if(dofree) free(sigblock);
else if(docrypto_free) CRYPTO_free(sigblock);
return sec_status_unchecked;
}
if(EVP_VerifyUpdate(&ctx, (unsigned char*)sldns_buffer_begin(buf),
if(EVP_VerifyInit(ctx, digest_type) == 0) {
verbose(VERB_QUERY, "verify: EVP_VerifyInit failed");
EVP_MD_CTX_destroy(ctx);
EVP_PKEY_free(evp_key);
if(dofree) free(sigblock);
else if(docrypto_free) CRYPTO_free(sigblock);
return sec_status_unchecked;
}
if(EVP_VerifyUpdate(ctx, (unsigned char*)sldns_buffer_begin(buf),
(unsigned int)sldns_buffer_limit(buf)) == 0) {
verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed");
EVP_MD_CTX_destroy(ctx);
EVP_PKEY_free(evp_key);
if(dofree) free(sigblock);
else if(docrypto_free) CRYPTO_free(sigblock);
return sec_status_unchecked;
}
res = EVP_VerifyFinal(&ctx, sigblock, sigblock_len, evp_key);
if(EVP_MD_CTX_cleanup(&ctx) == 0) {
verbose(VERB_QUERY, "verify: EVP_MD_CTX_cleanup failed");
EVP_PKEY_free(evp_key);
if(dofree) free(sigblock);
return sec_status_unchecked;
}
res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key);
#ifdef HAVE_EVP_MD_CTX_NEW
EVP_MD_CTX_destroy(ctx);
#else
EVP_MD_CTX_cleanup(ctx);
free(ctx);
#endif
EVP_PKEY_free(evp_key);
if(dofree)
free(sigblock);
if(dofree) free(sigblock);
else if(docrypto_free) CRYPTO_free(sigblock);
if(res == 1) {
return sec_status_secure;
@ -620,6 +684,12 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
}
}
void
secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
{
(void)HASH_HashBuf(HASH_AlgSHA256, res, buf, (unsigned long)len);
}
size_t
ds_digest_size_supported(int algo)
{
@ -678,8 +748,10 @@ dnskey_algo_id_is_supported(int id)
case LDNS_RSAMD5:
/* RFC 6725 deprecates RSAMD5 */
return 0;
#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
#endif
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#ifdef USE_SHA2
@ -920,6 +992,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
*/
switch(algo) {
#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
*pubkey = nss_buf2dsa(key, keylen);
@ -930,6 +1003,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
*htype = HASH_AlgSHA1;
/* no prefix for DSA verification */
break;
#endif
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#ifdef USE_SHA2
@ -1046,6 +1120,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_bogus;
}
#ifdef USE_DSA
/* need to convert DSA, ECDSA signatures? */
if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3)) {
if(sigblock_len == 1+2*SHA1_LENGTH) {
@ -1068,6 +1143,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
SECITEM_FreeItem(p, PR_TRUE);
}
}
#endif /* USE_DSA */
/* do the signature cryptography work */
/* hash the data */
@ -1206,6 +1282,12 @@ secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
}
}
void
secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res)
{
_digest_nettle(SHA256_DIGEST_SIZE, (uint8_t*)buf, len, res);
}
/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.
@ -1263,8 +1345,10 @@ dnskey_algo_id_is_supported(int id)
{
/* uses libnettle */
switch(id) {
#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
#endif
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:
#ifdef USE_SHA2
@ -1541,6 +1625,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
}
switch(algo) {
#ifdef USE_DSA
case LDNS_DSA:
case LDNS_DSA_NSEC3:
*reason = _verify_nettle_dsa(buf, sigblock, sigblock_len, key, keylen);
@ -1548,6 +1633,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_bogus;
else
return sec_status_secure;
#endif /* USE_DSA */
case LDNS_RSASHA1:
case LDNS_RSASHA1_NSEC3:

View file

@ -59,6 +59,14 @@ size_t nsec3_hash_algo_size_supported(int id);
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.

View file

@ -6,7 +6,7 @@ LDNSDIR= ${.CURDIR}/../../contrib/ldns
UNBOUNDDIR= ${.CURDIR}/../../contrib/unbound
# Hold my beer and watch this
.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/dns64 ${UNBOUNDDIR}/iterator ${UNBOUNDDIR}/sldns ${UNBOUNDDIR}/libunbound ${UNBOUNDDIR}/services ${UNBOUNDDIR}/services/cache ${UNBOUNDDIR}/util ${UNBOUNDDIR}/util/data ${UNBOUNDDIR}/util/storage ${UNBOUNDDIR}/validator
.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/cachedb ${UNBOUNDDIR}/dns64 ${UNBOUNDDIR}/iterator ${UNBOUNDDIR}/sldns ${UNBOUNDDIR}/libunbound ${UNBOUNDDIR}/services ${UNBOUNDDIR}/services/cache ${UNBOUNDDIR}/util ${UNBOUNDDIR}/util/data ${UNBOUNDDIR}/util/storage ${UNBOUNDDIR}/validator
LIB= unbound
PRIVATELIB=
@ -14,19 +14,19 @@ PACKAGE= unbound
CFLAGS+= -I${UNBOUNDDIR} -I${LDNSDIR} -I${.OBJDIR}
SRCS= alloc.c as112.c autotrust.c config_file.c configlexer.l configparser.y \
context.c dname.c dns.c dns64.c dnstree.c fptr_wlist.c infra.c \
iter_delegpt.c iter_donotq.c iter_fwd.c iter_hints.c iter_priv.c \
iter_resptype.c iter_scrub.c iter_utils.c iterator.c keyraw.c \
libunbound.c libworker.c listen_dnsport.c localzone.c locks.c log.c \
lookup3.c lruhash.c mesh.c mini_event.c modstack.c module.c \
msgencode.c msgparse.c msgreply.c net_help.c netevent.c \
outbound_list.c outside_network.c packed_rrset.c parse.c \
SRCS= alloc.c as112.c autotrust.c cachedb.c config_file.c configlexer.l \
configparser.y context.c dname.c dns.c dns64.c dnstree.c \
fptr_wlist.c infra.c iter_delegpt.c iter_donotq.c iter_fwd.c \
iter_hints.c iter_priv.c iter_resptype.c iter_scrub.c iter_utils.c \
iterator.c keyraw.c libunbound.c libworker.c listen_dnsport.c \
localzone.c locks.c log.c lookup3.c lruhash.c mesh.c mini_event.c \
modstack.c module.c msgencode.c msgparse.c msgreply.c net_help.c \
netevent.c outbound_list.c outside_network.c packed_rrset.c parse.c \
parseutil.c random.c rbtree.c regional.c rrdef.c rrset.c rtt.c \
sbuffer.c slabhash.c str2wire.c timehist.c tube.c val_anchor.c \
val_kcache.c val_kentry.c val_neg.c val_nsec.c val_nsec3.c \
val_secalgo.c val_sigcrypt.c val_utils.c validator.c \
winsock_event.c wire2str.c
sbuffer.c slabhash.c str2wire.c timehist.c tube.c \
ub_event_pluggable.c val_anchor.c val_kcache.c val_kentry.c \
val_neg.c val_nsec.c val_nsec3.c val_secalgo.c val_sigcrypt.c \
val_utils.c validator.c winsock_event.c wire2str.c
WARNS?= 3

View file

@ -4,10 +4,10 @@
LDNSDIR= ${.CURDIR}/../../../contrib/ldns
UNBOUNDDIR= ${.CURDIR}/../../../contrib/unbound
.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/smallapp ${UNBOUNDDIR}/doc
.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/smallapp ${UNBOUNDDIR}/util ${UNBOUNDDIR}/doc
PROG= unbound-checkconf
SRCS= unbound-checkconf.c worker_cb.c
SRCS= ub_event.c unbound-checkconf.c worker_cb.c
CFLAGS+= -I${UNBOUNDDIR} -I${LDNSDIR}
LIBADD= unbound pthread
MAN= unbound-checkconf.8

View file

@ -4,10 +4,10 @@
LDNSDIR= ${.CURDIR}/../../../contrib/ldns
UNBOUNDDIR= ${.CURDIR}/../../../contrib/unbound
.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/smallapp ${UNBOUNDDIR}/doc
.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/smallapp ${UNBOUNDDIR}/util ${UNBOUNDDIR}/doc
PROG= unbound-control
SRCS= unbound-control.c worker_cb.c
SRCS= ub_event.c unbound-control.c worker_cb.c
CFLAGS+= -I${UNBOUNDDIR} -I${LDNSDIR}
LIBADD= unbound crypto ssl pthread
MAN= unbound-control.8

View file

@ -4,10 +4,11 @@
LDNSDIR= ${.CURDIR}/../../../contrib/ldns
UNBOUNDDIR= ${.CURDIR}/../../../contrib/unbound
.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/daemon ${UNBOUNDDIR}/doc
.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/daemon ${UNBOUNDDIR}/util ${UNBOUNDDIR}/doc
PROG= unbound
SRCS= acl_list.c cachedump.c daemon.c remote.c stats.c unbound.c worker.c
SRCS= acl_list.c cachedump.c daemon.c remote.c stats.c ub_event.c \
unbound.c worker.c
CFLAGS+= -I${UNBOUNDDIR} -I${LDNSDIR}
LIBADD= unbound util ssl crypto pthread
MAN= unbound.8 unbound.conf.5