summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2016-10-21 14:28:35 +0000
committerdes <des@FreeBSD.org>2016-10-21 14:28:35 +0000
commit962480b2ab226916f69182001ad8aacdc0cd839e (patch)
tree708cc00e6b46dd6756a68a75a46449e799e4bbfb
parent9590e954cbe2100263a41aba9beeccfa0b8022b3 (diff)
downloadFreeBSD-src-962480b2ab226916f69182001ad8aacdc0cd839e.zip
FreeBSD-src-962480b2ab226916f69182001ad8aacdc0cd839e.tar.gz
MFH (r305381, r306457): upgrade to unbound 1.5.10 via 1.5.9
-rw-r--r--contrib/unbound/Makefile.in130
-rw-r--r--contrib/unbound/acx_nlnetlabs.m447
-rw-r--r--contrib/unbound/acx_python.m42
-rw-r--r--contrib/unbound/cachedb/cachedb.c702
-rw-r--r--contrib/unbound/cachedb/cachedb.h110
-rw-r--r--contrib/unbound/compat/arc4random.c3
-rw-r--r--contrib/unbound/compat/explicit_bzero.c4
-rw-r--r--contrib/unbound/compat/getentropy_linux.c9
-rw-r--r--contrib/unbound/compat/strsep.c65
-rw-r--r--contrib/unbound/config.h81
-rw-r--r--contrib/unbound/config.h.in75
-rwxr-xr-xcontrib/unbound/configure399
-rw-r--r--contrib/unbound/configure.ac152
-rw-r--r--contrib/unbound/contrib/README31
-rw-r--r--contrib/unbound/contrib/aaaa-filter-iterator.patch413
-rwxr-xr-xcontrib/unbound/contrib/build-unbound-localzone-from-hosts.pl67
-rw-r--r--contrib/unbound/contrib/create_unbound_ad_servers.cmd33
-rwxr-xr-xcontrib/unbound/contrib/create_unbound_ad_servers.sh39
-rw-r--r--contrib/unbound/contrib/libunbound.pc.in13
-rwxr-xr-xcontrib/unbound/contrib/parseunbound.pl140
-rw-r--r--contrib/unbound/contrib/patch_rsamd5_enable.diff22
-rwxr-xr-xcontrib/unbound/contrib/rc_d_unbound25
-rw-r--r--contrib/unbound/contrib/selinux/unbound.fc4
-rw-r--r--contrib/unbound/contrib/selinux/unbound.te42
-rw-r--r--contrib/unbound/contrib/unbound-host.nagios.patch134
-rw-r--r--contrib/unbound/contrib/unbound.init139
-rw-r--r--contrib/unbound/contrib/unbound.init_fedora119
-rw-r--r--contrib/unbound/contrib/unbound.plist42
-rw-r--r--contrib/unbound/contrib/unbound.spec112
-rw-r--r--contrib/unbound/contrib/unbound.spec_fedora433
-rw-r--r--contrib/unbound/contrib/unbound_cache.cmd105
-rwxr-xr-xcontrib/unbound/contrib/unbound_cache.sh174
-rw-r--r--contrib/unbound/contrib/unbound_cacti.tar.gzbin0 -> 73219 bytes
-rwxr-xr-xcontrib/unbound/contrib/unbound_munin_574
-rw-r--r--contrib/unbound/contrib/unbound_smf22.tar.gzbin0 -> 4578 bytes
-rwxr-xr-xcontrib/unbound/contrib/update-anchor.sh158
-rwxr-xr-xcontrib/unbound/contrib/validation-reporter.sh117
-rw-r--r--contrib/unbound/contrib/warmup.cmd153
-rwxr-xr-xcontrib/unbound/contrib/warmup.sh150
-rw-r--r--contrib/unbound/daemon/acl_list.c250
-rw-r--r--contrib/unbound/daemon/acl_list.h29
-rw-r--r--contrib/unbound/daemon/daemon.c33
-rw-r--r--contrib/unbound/daemon/daemon.h3
-rw-r--r--contrib/unbound/daemon/remote.c108
-rw-r--r--contrib/unbound/daemon/remote.h4
-rw-r--r--contrib/unbound/daemon/unbound.c84
-rw-r--r--contrib/unbound/daemon/worker.c68
-rw-r--r--contrib/unbound/dns64/dns64.c7
-rw-r--r--contrib/unbound/dnstap/dnstap.c2
-rw-r--r--contrib/unbound/doc/Changelog364
-rw-r--r--contrib/unbound/doc/README2
-rw-r--r--contrib/unbound/doc/example.conf53
-rw-r--r--contrib/unbound/doc/example.conf.in53
-rw-r--r--contrib/unbound/doc/libunbound.34
-rw-r--r--contrib/unbound/doc/libunbound.3.in4
-rw-r--r--contrib/unbound/doc/unbound-anchor.88
-rw-r--r--contrib/unbound/doc/unbound-anchor.8.in8
-rw-r--r--contrib/unbound/doc/unbound-checkconf.82
-rw-r--r--contrib/unbound/doc/unbound-checkconf.8.in2
-rw-r--r--contrib/unbound/doc/unbound-control.82
-rw-r--r--contrib/unbound/doc/unbound-control.8.in2
-rw-r--r--contrib/unbound/doc/unbound-host.12
-rw-r--r--contrib/unbound/doc/unbound-host.1.in2
-rw-r--r--contrib/unbound/doc/unbound.84
-rw-r--r--contrib/unbound/doc/unbound.8.in4
-rw-r--r--contrib/unbound/doc/unbound.conf.593
-rw-r--r--contrib/unbound/doc/unbound.conf.5.in93
-rw-r--r--contrib/unbound/doc/unbound.doxygen4
-rw-r--r--contrib/unbound/iterator/iter_fwd.c1
-rw-r--r--contrib/unbound/iterator/iter_hints.c1
-rw-r--r--contrib/unbound/iterator/iter_utils.c54
-rw-r--r--contrib/unbound/iterator/iter_utils.h12
-rw-r--r--contrib/unbound/iterator/iterator.c157
-rw-r--r--contrib/unbound/iterator/iterator.h30
-rw-r--r--contrib/unbound/libunbound/context.h4
-rw-r--r--contrib/unbound/libunbound/libunbound.c34
-rw-r--r--contrib/unbound/libunbound/libworker.c29
-rw-r--r--contrib/unbound/libunbound/libworker.h4
-rw-r--r--contrib/unbound/libunbound/python/libunbound.i2
-rw-r--r--contrib/unbound/libunbound/ubsyms.def1
-rw-r--r--contrib/unbound/libunbound/unbound-event.h152
-rw-r--r--contrib/unbound/libunbound/worker.h15
-rw-r--r--contrib/unbound/services/cache/dns.c7
-rw-r--r--contrib/unbound/services/listen_dnsport.c103
-rw-r--r--contrib/unbound/services/listen_dnsport.h6
-rw-r--r--contrib/unbound/services/localzone.c437
-rw-r--r--contrib/unbound/services/localzone.h58
-rw-r--r--contrib/unbound/services/mesh.c33
-rw-r--r--contrib/unbound/services/modstack.c9
-rw-r--r--contrib/unbound/services/outside_network.c159
-rw-r--r--contrib/unbound/services/outside_network.h15
-rw-r--r--contrib/unbound/sldns/keyraw.c40
-rw-r--r--contrib/unbound/sldns/parseutil.c4
-rw-r--r--contrib/unbound/sldns/rrdef.h5
-rw-r--r--contrib/unbound/sldns/str2wire.c4
-rw-r--r--contrib/unbound/sldns/wire2str.c4
-rw-r--r--contrib/unbound/sldns/wire2str.h18
-rw-r--r--contrib/unbound/smallapp/unbound-anchor.c27
-rw-r--r--contrib/unbound/smallapp/unbound-checkconf.c34
-rw-r--r--contrib/unbound/smallapp/unbound-control.c18
-rw-r--r--contrib/unbound/smallapp/unbound-host.c4
-rw-r--r--contrib/unbound/smallapp/worker_cb.c12
-rw-r--r--contrib/unbound/util/alloc.c4
-rw-r--r--contrib/unbound/util/config_file.c276
-rw-r--r--contrib/unbound/util/config_file.h135
-rw-r--r--contrib/unbound/util/configlexer.lex12
-rw-r--r--contrib/unbound/util/configparser.y161
-rw-r--r--contrib/unbound/util/data/dname.c18
-rw-r--r--contrib/unbound/util/data/msgencode.c22
-rw-r--r--contrib/unbound/util/data/msgparse.c60
-rw-r--r--contrib/unbound/util/data/msgparse.h28
-rw-r--r--contrib/unbound/util/data/msgreply.c154
-rw-r--r--contrib/unbound/util/data/msgreply.h52
-rw-r--r--contrib/unbound/util/fptr_wlist.c25
-rw-r--r--contrib/unbound/util/fptr_wlist.h2
-rw-r--r--contrib/unbound/util/iana_ports.inc10
-rw-r--r--contrib/unbound/util/module.h8
-rw-r--r--contrib/unbound/util/net_help.c6
-rw-r--r--contrib/unbound/util/netevent.c489
-rw-r--r--contrib/unbound/util/netevent.h31
-rw-r--r--contrib/unbound/util/storage/dnstree.c13
-rw-r--r--contrib/unbound/util/storage/dnstree.h11
-rw-r--r--contrib/unbound/util/storage/lookup3.c10
-rw-r--r--contrib/unbound/util/tube.c12
-rw-r--r--contrib/unbound/util/tube.h3
-rw-r--r--contrib/unbound/util/ub_event.c444
-rw-r--r--contrib/unbound/util/ub_event.h127
-rw-r--r--contrib/unbound/util/ub_event_pluggable.c692
-rw-r--r--contrib/unbound/util/winsock_event.c5
-rw-r--r--contrib/unbound/validator/autotrust.c5
-rw-r--r--contrib/unbound/validator/val_anchor.c2
-rw-r--r--contrib/unbound/validator/val_secalgo.c208
-rw-r--r--contrib/unbound/validator/val_secalgo.h8
-rw-r--r--contrib/unbound/validator/val_sigcrypt.c16
-rw-r--r--contrib/unbound/validator/validator.c6
-rw-r--r--lib/libunbound/Makefile26
-rw-r--r--usr.sbin/unbound/checkconf/Makefile4
-rw-r--r--usr.sbin/unbound/control/Makefile4
-rw-r--r--usr.sbin/unbound/daemon/Makefile5
139 files changed, 9927 insertions, 972 deletions
diff --git a/contrib/unbound/Makefile.in b/contrib/unbound/Makefile.in
index ff46581..77e38ea 100644
--- a/contrib/unbound/Makefile.in
+++ b/contrib/unbound/Makefile.in
@@ -81,7 +81,7 @@ LINTFLAGS+=@NETBSD_LINTFLAGS@
# compat with OpenBSD
LINTFLAGS+="-Dsigset_t=long"
# FreeBSD
-LINTFLAGS+="-D__uint16_t=uint16_t" "-DEVP_PKEY_ASN1_METHOD=int" "-D_RuneLocale=int" "-D__va_list=va_list"
+LINTFLAGS+="-D__uint16_t=uint16_t" "-DEVP_PKEY_ASN1_METHOD=int" "-D_RuneLocale=int" "-D__va_list=va_list" "-D__uint32_t=uint32_t"
INSTALL=$(SHELL) $(srcdir)/install-sh
@@ -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@
@@ -224,7 +228,7 @@ SVCUNINST_OBJ_LINK=$(SVCUNINST_OBJ) w_inst.lo rsrc_svcuninst.o \
$(COMPAT_OBJ_WITHOUT_CTIMEARC4)
ANCHORUPD_SRC=winrc/anchor-update.c
ANCHORUPD_OBJ=anchor-update.lo
-ANCHORUPD_OBJ_LINK=$(ANCHORUPD_OBJ) rsrc_anchorupd.o $(COMPAT_OBJ_WITHOUT_CTIMEARC4)
+ANCHORUPD_OBJ_LINK=$(ANCHORUPD_OBJ) rsrc_anchorupd.o $(COMPAT_OBJ_WITHOUT_CTIMEARC4) wire2str.lo str2wire.lo parseutil.lo sbuffer.lo rrdef.lo keyraw.lo parse.lo
RSRC_OBJ=rsrc_svcinst.o rsrc_svcuninst.o rsrc_anchorupd.o rsrc_unbound.o \
rsrc_unbound_host.o rsrc_unbound_anchor.o rsrc_unbound_control.o \
rsrc_unbound_checkconf.o
@@ -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 \
@@ -700,11 +704,12 @@ listen_dnsport.lo listen_dnsport.o: $(srcdir)/services/listen_dnsport.c config.h
$(srcdir)/util/rbtree.h $(srcdir)/util/log.h $(srcdir)/util/config_file.h \
$(srcdir)/util/net_help.h $(srcdir)/sldns/sbuffer.h
localzone.lo localzone.o: $(srcdir)/services/localzone.c config.h $(srcdir)/services/localzone.h \
- $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/netevent.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/util/as112.h
+ $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/regional.h \
+ $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/net_help.h \
+ $(srcdir)/util/netevent.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/util/as112.h
mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/netevent.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/module.h \
@@ -718,7 +723,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
@@ -755,14 +760,15 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
$(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 $(srcdir)/services/outside_network.h \
- $(srcdir)/services/localzone.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/cache/infra.h \
$(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h \
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
$(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h \
$(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 +779,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 +814,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 +836,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 +894,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 +902,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 \
@@ -935,7 +957,8 @@ unitldns.lo unitldns.o: $(srcdir)/testcode/unitldns.c config.h $(srcdir)/util/lo
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/regional.h $(srcdir)/util/log.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h
+ $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/services/localzone.h $(srcdir)/util/locks.h \
+ $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h $(srcdir)/daemon/cachedump.h \
$(srcdir)/daemon/remote.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 $(srcdir)/util/log.h \
@@ -994,7 +1017,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 +1043,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
@@ -1042,7 +1065,8 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
$(srcdir)/libunbound/libworker.h
acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/regional.h $(srcdir)/util/log.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h
+ $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/services/localzone.h $(srcdir)/util/locks.h \
+ $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.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 \
@@ -1101,7 +1125,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 \
@@ -1113,17 +1137,18 @@ context.lo context.o: $(srcdir)/libunbound/context.c config.h $(srcdir)/libunbou
$(srcdir)/libunbound/unbound.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.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/config_file.h $(srcdir)/util/net_help.h $(srcdir)/services/localzone.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h $(srcdir)/sldns/sbuffer.h
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
+ $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/sldns/sbuffer.h
libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbound/unbound.h \
$(srcdir)/libunbound/unbound-event.h 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)/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)/util/storage/dnstree.h $(srcdir)/services/cache/infra.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 \
@@ -1131,11 +1156,12 @@ libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/li
$(srcdir)/libunbound/unbound-event.h $(srcdir)/services/outside_network.h $(srcdir)/util/netevent.h \
$(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/services/localzone.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/regional.h \
- $(srcdir)/util/random.h $(srcdir)/util/config_file.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h \
- $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/str2wire.h
+ $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/outbound_list.h $(srcdir)/util/fptr_wlist.h \
+ $(srcdir)/util/tube.h $(srcdir)/util/regional.h $(srcdir)/util/random.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
+ $(srcdir)/sldns/str2wire.h
unbound-host.lo unbound-host.o: $(srcdir)/smallapp/unbound-host.c config.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libunbound/unbound.h \
@@ -1163,14 +1189,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
@@ -1213,3 +1240,4 @@ arc4_lock.lo arc4_lock.o: $(srcdir)/compat/arc4_lock.c config.h $(srcdir)/util/l
sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h
reallocarray.lo reallocarray.o: $(srcdir)/compat/reallocarray.c config.h
isblank.lo isblank.o: $(srcdir)/compat/isblank.c config.h
+strsep.lo strsep.o: $(srcdir)/compat/strsep.c config.h
diff --git a/contrib/unbound/acx_nlnetlabs.m4 b/contrib/unbound/acx_nlnetlabs.m4
index d43b66e..a6c174f 100644
--- a/contrib/unbound/acx_nlnetlabs.m4
+++ b/contrib/unbound/acx_nlnetlabs.m4
@@ -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])
+ ])
])
])
])
diff --git a/contrib/unbound/acx_python.m4 b/contrib/unbound/acx_python.m4
index 254ff20..4e83d77 100644
--- a/contrib/unbound/acx_python.m4
+++ b/contrib/unbound/acx_python.m4
@@ -54,7 +54,7 @@ $ac_distutils_result])
AC_MSG_CHECKING([for Python library path])
if test -z "$PYTHON_LDFLAGS"; then
PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \
- print(get_config_var('BLDLIBRARY'));"`
+ print('-L'+get_config_var('LIBDIR')+' -L'+get_config_var('LIBDEST')+' '+get_config_var('BLDLIBRARY'));"`
fi
AC_MSG_RESULT([$PYTHON_LDFLAGS])
AC_SUBST([PYTHON_LDFLAGS])
diff --git a/contrib/unbound/cachedb/cachedb.c b/contrib/unbound/cachedb/cachedb.c
new file mode 100644
index 0000000..76d9afa
--- /dev/null
+++ b/contrib/unbound/cachedb/cachedb.c
@@ -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 */
diff --git a/contrib/unbound/cachedb/cachedb.h b/contrib/unbound/cachedb/cachedb.h
new file mode 100644
index 0000000..d477e90
--- /dev/null
+++ b/contrib/unbound/cachedb/cachedb.h
@@ -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);
+
diff --git a/contrib/unbound/compat/arc4random.c b/contrib/unbound/compat/arc4random.c
index 2c859f1..a09665c 100644
--- a/contrib/unbound/compat/arc4random.c
+++ b/contrib/unbound/compat/arc4random.c
@@ -48,6 +48,9 @@
#else /* !__GNUC__ */
#define inline
#endif /* !__GNUC__ */
+#ifndef MAP_ANON
+#define MAP_ANON MAP_ANONYMOUS
+#endif
#define KEYSZ 32
#define IVSZ 8
diff --git a/contrib/unbound/compat/explicit_bzero.c b/contrib/unbound/compat/explicit_bzero.c
index a3ba279..5f1c427 100644
--- a/contrib/unbound/compat/explicit_bzero.c
+++ b/contrib/unbound/compat/explicit_bzero.c
@@ -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))
{
}
diff --git a/contrib/unbound/compat/getentropy_linux.c b/contrib/unbound/compat/getentropy_linux.c
index 37d86a8..b86c0fb 100644
--- a/contrib/unbound/compat/getentropy_linux.c
+++ b/contrib/unbound/compat/getentropy_linux.c
@@ -60,6 +60,9 @@
#include <sys/auxv.h>
#endif
#include <sys/vfs.h>
+#ifndef MAP_ANON
+#define MAP_ANON MAP_ANONYMOUS
+#endif
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
@@ -94,7 +97,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 +116,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 +212,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)
{
diff --git a/contrib/unbound/compat/strsep.c b/contrib/unbound/compat/strsep.c
new file mode 100644
index 0000000..4e3f05c
--- /dev/null
+++ b/contrib/unbound/compat/strsep.c
@@ -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;
+}
diff --git a/contrib/unbound/config.h b/contrib/unbound/config.h
index 6e2a875..c8c0cf7 100644
--- a/contrib/unbound/config.h
+++ b/contrib/unbound/config.h
@@ -43,12 +43,18 @@
/* 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
/* Define to 1 if you have the `chroot' function. */
#define HAVE_CHROOT 1
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
+
/* Define to 1 if you have the `ctime_r' function. */
#define HAVE_CTIME_R 1
@@ -108,9 +114,18 @@
/* Define to 1 if you have the `endprotoent' function. */
#define HAVE_ENDPROTOENT 1
+/* Define to 1 if you have the `endpwent' function. */
+#define HAVE_ENDPWENT 1
+
/* Define to 1 if you have the `endservent' function. */
#define HAVE_ENDSERVENT 1
+/* Define to 1 if you have the `ERR_free_strings' function. */
+#define HAVE_ERR_FREE_STRINGS 1
+
+/* Define to 1 if you have the `ERR_load_crypto_strings' function. */
+#define HAVE_ERR_LOAD_CRYPTO_STRINGS 1
+
/* Define to 1 if you have the `event_base_free' function. */
/* #undef HAVE_EVENT_BASE_FREE */
@@ -126,6 +141,12 @@
/* Define to 1 if you have the <event.h> header file. */
/* #undef HAVE_EVENT_H */
+/* Define to 1 if you have the `EVP_cleanup' function. */
+#define HAVE_EVP_CLEANUP 1
+
+/* 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 +210,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
@@ -249,24 +270,48 @@
/* Use libnettle for crypto */
/* #undef HAVE_NETTLE */
+/* Define to 1 if you have the <nettle/dsa-compat.h> header file. */
+/* #undef HAVE_NETTLE_DSA_COMPAT_H */
+
/* Use libnss for crypto */
/* #undef HAVE_NSS */
+/* Define to 1 if you have the `OpenSSL_add_all_digests' function. */
+#define HAVE_OPENSSL_ADD_ALL_DIGESTS 1
+
+/* Define to 1 if you have the <openssl/bn.h> header file. */
+#define HAVE_OPENSSL_BN_H 1
+
/* Define to 1 if you have the `OPENSSL_config' function. */
#define HAVE_OPENSSL_CONFIG 1
/* Define to 1 if you have the <openssl/conf.h> header file. */
#define HAVE_OPENSSL_CONF_H 1
+/* Define to 1 if you have the <openssl/dh.h> header file. */
+#define HAVE_OPENSSL_DH_H 1
+
+/* Define to 1 if you have the <openssl/dsa.h> header file. */
+#define HAVE_OPENSSL_DSA_H 1
+
/* Define to 1 if you have the <openssl/engine.h> header file. */
#define HAVE_OPENSSL_ENGINE_H 1
/* Define to 1 if you have the <openssl/err.h> header file. */
#define HAVE_OPENSSL_ERR_H 1
+/* Define to 1 if you have the `OPENSSL_init_crypto' function. */
+/* #undef HAVE_OPENSSL_INIT_CRYPTO */
+
+/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
+/* #undef HAVE_OPENSSL_INIT_SSL */
+
/* Define to 1 if you have the <openssl/rand.h> header file. */
#define HAVE_OPENSSL_RAND_H 1
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+#define HAVE_OPENSSL_RSA_H 1
+
/* Define to 1 if you have the <openssl/ssl.h> header file. */
#define HAVE_OPENSSL_SSL_H 1
@@ -291,6 +336,9 @@
/* Define to 1 if you have the `random' function. */
#define HAVE_RANDOM 1
+/* Define to 1 if you have the `RAND_cleanup' function. */
+#define HAVE_RAND_CLEANUP 1
+
/* Define to 1 if you have the `reallocarray' function. */
#define HAVE_REALLOCARRAY 1
@@ -378,6 +426,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 +566,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.10"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "unbound"
@@ -524,7 +575,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.5.8"
+#define PACKAGE_VERSION "1.5.10"
/* default pidfile location */
#define PIDFILE "/var/unbound/unbound.pid"
@@ -543,7 +594,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,10,0
/* Directory to chdir to */
#define RUN_DIR "/var/unbound"
@@ -581,9 +632,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
@@ -596,6 +653,12 @@
/* Define if you want to use internal select based events */
#define USE_MINI_EVENT 1
+/* Define this to enable client TCP Fast Open. */
+/* #undef USE_MSG_FASTOPEN */
+
+/* Define this to enable client TCP Fast Open. */
+/* #undef USE_OSX_MSG_FASTOPEN */
+
/* Define this to enable SHA256 and SHA512 support. */
#define USE_SHA2 1
@@ -621,6 +684,9 @@
#endif
+/* Define this to enable server TCP Fast Open. */
+/* #undef USE_TCP_FASTOPEN */
+
/* Whether the windows socket API is used */
/* #undef USE_WINSOCK */
@@ -980,6 +1046,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);
diff --git a/contrib/unbound/config.h.in b/contrib/unbound/config.h.in
index 59277dd..04fc743 100644
--- a/contrib/unbound/config.h.in
+++ b/contrib/unbound/config.h.in
@@ -42,12 +42,18 @@
/* 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
/* Define to 1 if you have the `chroot' function. */
#undef HAVE_CHROOT
+/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */
+#undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
+
/* Define to 1 if you have the `ctime_r' function. */
#undef HAVE_CTIME_R
@@ -107,9 +113,18 @@
/* Define to 1 if you have the `endprotoent' function. */
#undef HAVE_ENDPROTOENT
+/* Define to 1 if you have the `endpwent' function. */
+#undef HAVE_ENDPWENT
+
/* Define to 1 if you have the `endservent' function. */
#undef HAVE_ENDSERVENT
+/* Define to 1 if you have the `ERR_free_strings' function. */
+#undef HAVE_ERR_FREE_STRINGS
+
+/* Define to 1 if you have the `ERR_load_crypto_strings' function. */
+#undef HAVE_ERR_LOAD_CRYPTO_STRINGS
+
/* Define to 1 if you have the `event_base_free' function. */
#undef HAVE_EVENT_BASE_FREE
@@ -125,6 +140,12 @@
/* Define to 1 if you have the <event.h> header file. */
#undef HAVE_EVENT_H
+/* Define to 1 if you have the `EVP_cleanup' function. */
+#undef HAVE_EVP_CLEANUP
+
+/* 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 +209,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
@@ -248,24 +269,48 @@
/* Use libnettle for crypto */
#undef HAVE_NETTLE
+/* Define to 1 if you have the <nettle/dsa-compat.h> header file. */
+#undef HAVE_NETTLE_DSA_COMPAT_H
+
/* Use libnss for crypto */
#undef HAVE_NSS
+/* Define to 1 if you have the `OpenSSL_add_all_digests' function. */
+#undef HAVE_OPENSSL_ADD_ALL_DIGESTS
+
+/* Define to 1 if you have the <openssl/bn.h> header file. */
+#undef HAVE_OPENSSL_BN_H
+
/* Define to 1 if you have the `OPENSSL_config' function. */
#undef HAVE_OPENSSL_CONFIG
/* Define to 1 if you have the <openssl/conf.h> header file. */
#undef HAVE_OPENSSL_CONF_H
+/* Define to 1 if you have the <openssl/dh.h> header file. */
+#undef HAVE_OPENSSL_DH_H
+
+/* Define to 1 if you have the <openssl/dsa.h> header file. */
+#undef HAVE_OPENSSL_DSA_H
+
/* Define to 1 if you have the <openssl/engine.h> header file. */
#undef HAVE_OPENSSL_ENGINE_H
/* Define to 1 if you have the <openssl/err.h> header file. */
#undef HAVE_OPENSSL_ERR_H
+/* Define to 1 if you have the `OPENSSL_init_crypto' function. */
+#undef HAVE_OPENSSL_INIT_CRYPTO
+
+/* Define to 1 if you have the `OPENSSL_init_ssl' function. */
+#undef HAVE_OPENSSL_INIT_SSL
+
/* Define to 1 if you have the <openssl/rand.h> header file. */
#undef HAVE_OPENSSL_RAND_H
+/* Define to 1 if you have the <openssl/rsa.h> header file. */
+#undef HAVE_OPENSSL_RSA_H
+
/* Define to 1 if you have the <openssl/ssl.h> header file. */
#undef HAVE_OPENSSL_SSL_H
@@ -290,6 +335,9 @@
/* Define to 1 if you have the `random' function. */
#undef HAVE_RANDOM
+/* Define to 1 if you have the `RAND_cleanup' function. */
+#undef HAVE_RAND_CLEANUP
+
/* Define to 1 if you have the `reallocarray' function. */
#undef HAVE_REALLOCARRAY
@@ -377,6 +425,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 +631,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
@@ -595,6 +652,12 @@
/* Define if you want to use internal select based events */
#undef USE_MINI_EVENT
+/* Define this to enable client TCP Fast Open. */
+#undef USE_MSG_FASTOPEN
+
+/* Define this to enable client TCP Fast Open. */
+#undef USE_OSX_MSG_FASTOPEN
+
/* Define this to enable SHA256 and SHA512 support. */
#undef USE_SHA2
@@ -620,6 +683,9 @@
#endif
+/* Define this to enable server TCP Fast Open. */
+#undef USE_TCP_FASTOPEN
+
/* Whether the windows socket API is used */
#undef USE_WINSOCK
@@ -979,6 +1045,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);
diff --git a/contrib/unbound/configure b/contrib/unbound/configure
index 6c6b9ef..54f93db 100755
--- a/contrib/unbound/configure
+++ b/contrib/unbound/configure
@@ -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.10.
#
# 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.10'
+PACKAGE_STRING='unbound 1.5.10'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
PACKAGE_URL=''
@@ -832,7 +832,10 @@ with_ssl
enable_sha2
enable_gost
enable_ecdsa
+enable_dsa
enable_event_api
+enable_tfo_client
+enable_tfo_server
with_libevent
with_libexpat
enable_static_exe
@@ -842,6 +845,7 @@ enable_dnstap
with_dnstap_socket_path
with_protobuf_c
with_libfstrm
+enable_cachedb
with_libunbound_only
'
ac_precious_vars='build_alias
@@ -1397,7 +1401,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.10 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1462,7 +1466,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.10:";;
esac
cat <<\_ACEOF
@@ -1495,8 +1499,11 @@ 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-tfo-client Enable TCP Fast Open for client mode
+ --enable-tfo-server Enable TCP Fast Open for server mode
--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 +1512,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 +1656,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.10
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2356,7 +2365,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.10, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2708,11 +2717,11 @@ UNBOUND_VERSION_MAJOR=1
UNBOUND_VERSION_MINOR=5
-UNBOUND_VERSION_MICRO=8
+UNBOUND_VERSION_MICRO=10
LIBUNBOUND_CURRENT=6
-LIBUNBOUND_REVISION=0
+LIBUNBOUND_REVISION=2
LIBUNBOUND_AGE=4
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -2760,6 +2769,8 @@ 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
+# 1.5.10 had 6:2:4
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -4048,7 +4059,7 @@ esac
# are we on MinGW?
if uname -s 2>&1 | grep MINGW32 >/dev/null; then on_mingw="yes"
else
- if echo $target | grep mingw32 >/dev/null; then on_mingw="yes"
+ if echo $host $target | grep mingw32 >/dev/null; then on_mingw="yes"
else on_mingw="no"; fi
fi
@@ -4058,7 +4069,7 @@ fi
if test $on_mingw = "no"; then
ub_conf_file=`eval echo "${sysconfdir}/unbound/unbound.conf"`
else
- ub_conf_file="C:\\Program Files\\Unbound\\service.conf"
+ ub_conf_file="C:\\Program Files (x86)\\Unbound\\service.conf"
fi
# Check whether --with-conf_file was given.
@@ -4189,7 +4200,7 @@ else
if test $on_mingw = no; then
UNBOUND_ROOTKEY_FILE="$UNBOUND_RUN_DIR/root.key"
else
- UNBOUND_ROOTKEY_FILE="C:\\Program Files\\Unbound\\root.key"
+ UNBOUND_ROOTKEY_FILE="C:\\Program Files (x86)\\Unbound\\root.key"
fi
fi
@@ -4211,7 +4222,7 @@ else
if test $on_mingw = no; then
UNBOUND_ROOTCERT_FILE="$UNBOUND_RUN_DIR/icannbundle.pem"
else
- UNBOUND_ROOTCERT_FILE="C:\\Program Files\\Unbound\\icannbundle.pem"
+ UNBOUND_ROOTCERT_FILE="C:\\Program Files (x86)\\Unbound\\icannbundle.pem"
fi
fi
@@ -6117,6 +6128,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
@@ -16666,7 +16719,7 @@ $as_echo "$PYTHON_CPPFLAGS" >&6; }
$as_echo_n "checking for Python library path... " >&6; }
if test -z "$PYTHON_LDFLAGS"; then
PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \
- print(get_config_var('BLDLIBRARY'));"`
+ print('-L'+get_config_var('LIBDIR')+' -L'+get_config_var('LIBDEST')+' '+get_config_var('BLDLIBRARY'));"`
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_LDFLAGS" >&5
$as_echo "$PYTHON_LDFLAGS" >&6; }
@@ -16985,6 +17038,19 @@ if test "${with_nettle+set}" = set; then :
$as_echo "#define HAVE_NETTLE 1" >>confdefs.h
+ for ac_header in nettle/dsa-compat.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "nettle/dsa-compat.h" "ac_cv_header_nettle_dsa_compat_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_nettle_dsa_compat_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_NETTLE_DSA_COMPAT_H 1
+_ACEOF
+
+fi
+
+done
+
if test "$withval" != "" -a "$withval" != "yes"; then
CPPFLAGS="$CPPFLAGS -I$withval/include/nettle"
LDFLAGS="$LDFLAGS -L$withval/lib"
@@ -17064,8 +17130,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 +17141,8 @@ int
main ()
{
- int HMAC_CTX_init(void);
- (void)HMAC_CTX_init();
+ int HMAC_Update(void);
+ (void)HMAC_Update();
;
return 0;
@@ -17087,7 +17153,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 +17174,8 @@ int
main ()
{
- int HMAC_CTX_init(void);
- (void)HMAC_CTX_init();
+ int HMAC_Update(void);
+ (void)HMAC_Update();
;
return 0;
@@ -17118,7 +17184,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 +17206,8 @@ int
main ()
{
- int HMAC_CTX_init(void);
- (void)HMAC_CTX_init();
+ int HMAC_Update(void);
+ (void)HMAC_Update();
;
return 0;
@@ -17150,7 +17216,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 +17225,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 \
@@ -17313,6 +17415,47 @@ fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
SSLLIB="-lssl"
+
+# check if -lcrypt32 is needed because CAPIENG needs that. (on windows)
+BAKLIBS="$LIBS"
+LIBS="-lssl $LIBS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libssl needs -lcrypt32" >&5
+$as_echo_n "checking if libssl needs -lcrypt32... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char HMAC_Update ();
+int
+main ()
+{
+return HMAC_Update ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ LIBS="$BAKLIBS"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ LIBS="$BAKLIBS"
+ LIBS="$LIBS -lcrypt32"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LibreSSL" >&5
$as_echo_n "checking for LibreSSL... " >&6; }
if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then
@@ -17378,44 +17521,49 @@ else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
-for ac_header in openssl/conf.h
+for ac_header in openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h
do :
- ac_fn_c_check_header_compile "$LINENO" "openssl/conf.h" "ac_cv_header_openssl_conf_h" "$ac_includes_default
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
"
-if test "x$ac_cv_header_openssl_conf_h" = xyes; then :
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
-#define HAVE_OPENSSL_CONF_H 1
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
-for ac_header in openssl/engine.h
+for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup
do :
- ac_fn_c_check_header_compile "$LINENO" "openssl/engine.h" "ac_cv_header_openssl_engine_h" "$ac_includes_default
-"
-if test "x$ac_cv_header_openssl_engine_h" = xyes; then :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
-#define HAVE_OPENSSL_ENGINE_H 1
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
-
done
-for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode
+
+# these check_funcs need -lssl
+BAKLIBS="$LIBS"
+LIBS="-lssl $LIBS"
+for ac_func in OPENSSL_init_ssl
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"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ ac_fn_c_check_func "$LINENO" "OPENSSL_init_ssl" "ac_cv_func_OPENSSL_init_ssl"
+if test "x$ac_cv_func_OPENSSL_init_ssl" = xyes; then :
cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_OPENSSL_INIT_SSL 1
_ACEOF
fi
done
+LIBS="$BAKLIBS"
+
ac_fn_c_check_decl "$LINENO" "SSL_COMP_get_compression_methods" "ac_cv_have_decl_SSL_COMP_get_compression_methods" "
$ac_includes_default
#ifdef HAVE_OPENSSL_ERR_H
@@ -17771,20 +17919,127 @@ _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
+
;;
*)
;;
esac
+# Check whether --enable-tfo-client was given.
+if test "${enable_tfo_client+set}" = set; then :
+ enableval=$enable_tfo_client;
+fi
+
+case "$enable_tfo_client" in
+ yes)
+ case `uname` in
+ Linux) ac_fn_c_check_decl "$LINENO" "MSG_FASTOPEN" "ac_cv_have_decl_MSG_FASTOPEN" "$ac_includes_default
+#include <netinet/tcp.h>
+
+"
+if test "x$ac_cv_have_decl_MSG_FASTOPEN" = xyes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO" >&5
+$as_echo "$as_me: WARNING: Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO" >&2;}
+else
+ as_fn_error $? "TCP Fast Open is not available for client mode: please rerun without --enable-tfo-client" "$LINENO" 5
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define USE_MSG_FASTOPEN 1
+_ACEOF
+
+ ;;
+ Darwin) ac_fn_c_check_decl "$LINENO" "CONNECT_RESUME_ON_READ_WRITE" "ac_cv_have_decl_CONNECT_RESUME_ON_READ_WRITE" "$ac_includes_default
+#include <sys/socket.h>
+
+"
+if test "x$ac_cv_have_decl_CONNECT_RESUME_ON_READ_WRITE" = xyes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO" >&5
+$as_echo "$as_me: WARNING: Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO" >&2;}
+else
+ as_fn_error $? "TCP Fast Open is not available for client mode: please rerun without --enable-tfo-client" "$LINENO" 5
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define USE_OSX_MSG_FASTOPEN 1
+_ACEOF
+
+ ;;
+ esac
+ ;;
+ no|*)
+ ;;
+esac
+
+# Check whether --enable-tfo-server was given.
+if test "${enable_tfo_server+set}" = set; then :
+ enableval=$enable_tfo_server;
+fi
+
+case "$enable_tfo_server" in
+ yes)
+ ac_fn_c_check_decl "$LINENO" "TCP_FASTOPEN" "ac_cv_have_decl_TCP_FASTOPEN" "$ac_includes_default
+#include <netinet/tcp.h>
+
+"
+if test "x$ac_cv_have_decl_TCP_FASTOPEN" = xyes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Check the platform specific TFO kernel parameters are correctly configured to support server mode TFO" >&5
+$as_echo "$as_me: WARNING: Check the platform specific TFO kernel parameters are correctly configured to support server mode TFO" >&2;}
+else
+ as_fn_error $? "TCP Fast Open is not available for server mode: please rerun without --enable-tfo-server" "$LINENO" 5
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define USE_TCP_FASTOPEN 1
+_ACEOF
+
+ ;;
+ no|*)
+ ;;
+esac
+
# check for libevent
# Check whether --with-libevent was given.
@@ -18126,12 +18381,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
@@ -18205,10 +18454,8 @@ if test x_$enable_static_exe = x_yes; then
staticexe="-static"
if test "$on_mingw" = yes; then
staticexe="-all-static"
- # for static crosscompile, include gdi32 and zlib here.
- if test "`uname`" = "Linux"; then
- LIBS="$LIBS -lgdi32 -lz"
- fi
+ # for static compile, include gdi32 and zlib here.
+ LIBS="$LIBS -lgdi32 -lz"
fi
fi
@@ -18653,7 +18900,7 @@ if test "$ac_res" != no; then :
fi
-for ac_func in tzset sigprocmask fcntl getpwnam getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync
+for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync
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"
@@ -19237,6 +19484,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 +19781,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,12 +19939,12 @@ _ACEOF
-version=1.5.8
+version=1.5.10
date=`date +'%b %e, %Y'`
-ac_config_files="$ac_config_files Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h"
+ac_config_files="$ac_config_files Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h contrib/libunbound.pc"
ac_config_headers="$ac_config_headers config.h"
@@ -20176,7 +20454,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.10, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -20242,7 +20520,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.10
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -20664,6 +20942,7 @@ do
"doc/unbound-host.1") CONFIG_FILES="$CONFIG_FILES doc/unbound-host.1" ;;
"smallapp/unbound-control-setup.sh") CONFIG_FILES="$CONFIG_FILES smallapp/unbound-control-setup.sh" ;;
"dnstap/dnstap_config.h") CONFIG_FILES="$CONFIG_FILES dnstap/dnstap_config.h" ;;
+ "contrib/libunbound.pc") CONFIG_FILES="$CONFIG_FILES contrib/libunbound.pc" ;;
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
diff --git a/contrib/unbound/configure.ac b/contrib/unbound/configure.ac
index 0e53a5b..fc2c676 100644
--- a/contrib/unbound/configure.ac
+++ b/contrib/unbound/configure.ac
@@ -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],[10])
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=2
LIBUNBOUND_AGE=4
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -65,6 +65,8 @@ 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
+# 1.5.10 had 6:2:4
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -106,7 +108,7 @@ esac
# are we on MinGW?
if uname -s 2>&1 | grep MINGW32 >/dev/null; then on_mingw="yes"
else
- if echo $target | grep mingw32 >/dev/null; then on_mingw="yes"
+ if echo $host $target | grep mingw32 >/dev/null; then on_mingw="yes"
else on_mingw="no"; fi
fi
@@ -116,7 +118,7 @@ fi
if test $on_mingw = "no"; then
ub_conf_file=`eval echo "${sysconfdir}/unbound/unbound.conf"`
else
- ub_conf_file="C:\\Program Files\\Unbound\\service.conf"
+ ub_conf_file="C:\\Program Files (x86)\\Unbound\\service.conf"
fi
AC_ARG_WITH([conf_file],
AC_HELP_STRING([--with-conf-file=path],
@@ -186,7 +188,7 @@ AC_ARG_WITH(rootkey-file,
if test $on_mingw = no; then
UNBOUND_ROOTKEY_FILE="$UNBOUND_RUN_DIR/root.key"
else
- UNBOUND_ROOTKEY_FILE="C:\\Program Files\\Unbound\\root.key"
+ UNBOUND_ROOTKEY_FILE="C:\\Program Files (x86)\\Unbound\\root.key"
fi
)
AC_SUBST(UNBOUND_ROOTKEY_FILE)
@@ -200,7 +202,7 @@ AC_ARG_WITH(rootcert-file,
if test $on_mingw = no; then
UNBOUND_ROOTCERT_FILE="$UNBOUND_RUN_DIR/icannbundle.pem"
else
- UNBOUND_ROOTCERT_FILE="C:\\Program Files\\Unbound\\icannbundle.pem"
+ UNBOUND_ROOTCERT_FILE="C:\\Program Files (x86)\\Unbound\\icannbundle.pem"
fi
)
AC_SUBST(UNBOUND_ROOTCERT_FILE)
@@ -257,6 +259,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
@@ -605,6 +630,7 @@ AC_ARG_WITH([nettle], AC_HELP_STRING([--with-nettle=path],
[
USE_NETTLE="yes"
AC_DEFINE(HAVE_NETTLE, 1, [Use libnettle for crypto])
+ AC_CHECK_HEADERS([nettle/dsa-compat.h],,, [AC_INCLUDES_DEFAULT])
if test "$withval" != "" -a "$withval" != "yes"; then
CPPFLAGS="$CPPFLAGS -I$withval/include/nettle"
LDFLAGS="$LDFLAGS -L$withval/lib"
@@ -622,6 +648,20 @@ if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
ACX_WITH_SSL
ACX_LIB_SSL
SSLLIB="-lssl"
+
+# check if -lcrypt32 is needed because CAPIENG needs that. (on windows)
+BAKLIBS="$LIBS"
+LIBS="-lssl $LIBS"
+AC_MSG_CHECKING([if libssl needs -lcrypt32])
+AC_TRY_LINK_FUNC([HMAC_Update], [
+ AC_MSG_RESULT([no])
+ LIBS="$BAKLIBS"
+], [
+ AC_MSG_RESULT([yes])
+ LIBS="$BAKLIBS"
+ LIBS="$LIBS -lcrypt32"
+])
+
AC_MSG_CHECKING([for LibreSSL])
if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then
AC_MSG_RESULT([yes])
@@ -632,9 +672,15 @@ if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/
else
AC_MSG_RESULT([no])
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_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h],,, [AC_INCLUDES_DEFAULT])
+AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup])
+
+# these check_funcs need -lssl
+BAKLIBS="$LIBS"
+LIBS="-lssl $LIBS"
+AC_CHECK_FUNCS([OPENSSL_init_ssl])
+LIBS="$BAKLIBS"
+
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,16 +862,67 @@ 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])
;;
*)
;;
esac
+AC_ARG_ENABLE(tfo-client, AC_HELP_STRING([--enable-tfo-client], [Enable TCP Fast Open for client mode]))
+case "$enable_tfo_client" in
+ yes)
+ case `uname` in
+ Linux) AC_CHECK_DECL([MSG_FASTOPEN], [AC_MSG_WARN([Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO])],
+ [AC_MSG_ERROR([TCP Fast Open is not available for client mode: please rerun without --enable-tfo-client])],
+ [AC_INCLUDES_DEFAULT
+#include <netinet/tcp.h>
+])
+ AC_DEFINE_UNQUOTED([USE_MSG_FASTOPEN], [1], [Define this to enable client TCP Fast Open.])
+ ;;
+ Darwin) AC_CHECK_DECL([CONNECT_RESUME_ON_READ_WRITE], [AC_MSG_WARN([Check the platform specific TFO kernel parameters are correctly configured to support client mode TFO])],
+ [AC_MSG_ERROR([TCP Fast Open is not available for client mode: please rerun without --enable-tfo-client])],
+ [AC_INCLUDES_DEFAULT
+#include <sys/socket.h>
+])
+ AC_DEFINE_UNQUOTED([USE_OSX_MSG_FASTOPEN], [1], [Define this to enable client TCP Fast Open.])
+ ;;
+ esac
+ ;;
+ no|*)
+ ;;
+esac
+
+AC_ARG_ENABLE(tfo-server, AC_HELP_STRING([--enable-tfo-server], [Enable TCP Fast Open for server mode]))
+case "$enable_tfo_server" in
+ yes)
+ AC_CHECK_DECL([TCP_FASTOPEN], [AC_MSG_WARN([Check the platform specific TFO kernel parameters are correctly configured to support server mode TFO])], [AC_MSG_ERROR([TCP Fast Open is not available for server mode: please rerun without --enable-tfo-server])], [AC_INCLUDES_DEFAULT
+#include <netinet/tcp.h>
+ ])
+ AC_DEFINE_UNQUOTED([USE_TCP_FASTOPEN], [1], [Define this to enable server TCP Fast Open.])
+ ;;
+ no|*)
+ ;;
+esac
+
# check for libevent
AC_ARG_WITH(libevent, AC_HELP_STRING([--with-libevent=pathname],
[use libevent (will check /usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr or you can specify an explicit path). Slower, but allows use of large outgoing port ranges.]),
@@ -906,10 +1003,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
@@ -950,10 +1043,8 @@ if test x_$enable_static_exe = x_yes; then
staticexe="-static"
if test "$on_mingw" = yes; then
staticexe="-all-static"
- # for static crosscompile, include gdi32 and zlib here.
- if test "`uname`" = "Linux"; then
- LIBS="$LIBS -lgdi32 -lz"
- fi
+ # for static compile, include gdi32 and zlib here.
+ LIBS="$LIBS -lgdi32 -lz"
fi
fi
@@ -1047,7 +1138,7 @@ AC_INCLUDES_DEFAULT
#endif
])
AC_SEARCH_LIBS([setusercontext], [util])
-AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync])
+AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync])
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
@@ -1140,6 +1231,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 +1284,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 +1461,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);
@@ -1471,6 +1579,6 @@ dnl if this is a distro tarball, that was already done by makedist.sh
AC_SUBST(version, [VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO])
AC_SUBST(date, [`date +'%b %e, %Y'`])
-AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h])
+AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h contrib/libunbound.pc])
AC_CONFIG_HEADER([config.h])
AC_OUTPUT
diff --git a/contrib/unbound/contrib/README b/contrib/unbound/contrib/README
new file mode 100644
index 0000000..8eae9b5
--- /dev/null
+++ b/contrib/unbound/contrib/README
@@ -0,0 +1,31 @@
+These files are contributed to unbound, and are not part of the official
+distribution but may be helpful.
+
+* rc_d_unbound: FreeBSD compatible /etc/rc.d script.
+* parseunbound.pl: perl script to run from cron that parses statistics from
+ the log file and stores them.
+* unbound.spec and unbound.init: RPM specfile and Linux rc.d initfile.
+* update-anchor.sh: shell script that uses unbound-host to update a set
+ of trust anchor files. Run from cron twice a month.
+* unbound_munin_ : plugin for munin statistics report
+* unbound_cacti.tar.gz : setup files for cacti statistics report
+* selinux: the .fc and .te files for SElinux protection of the unbound daemon
+* unbound.plist: launchd configuration file for MacOSX.
+* build-unbound-localzone-from-hosts.pl: perl script to turn /etc/hosts into
+ a local-zone and local-data include file for unbound.conf.
+* unbound-host.nagios.patch: makes unbound-host return status that fits right
+ in with the nagios monitoring framework. Contributed by Migiel de Vos.
+* patch_rsamd5_enable.diff: this patch enables RSAMD5 validation (otherwise
+ it is treated as insecure). The RSAMD5 algorithm is deprecated (RFC6725).
+* create_unbound_ad_servers.sh: shell script to enter anti-ad server lists.
+* create_unbound_ad_servers.cmd: windows script to enter anti-ad server lists.
+* unbound_cache.sh: shell script to save and load the cache.
+* unbound_cache.cmd: windows script to save and load the cache.
+* warmup.sh: shell script to warm up DNS cache by your own MRU domains.
+* warmup.cmd: windows script to warm up DNS cache by your own MRU domains.
+* aaaa-filter-iterator.patch: adds config option aaaa-filter: yes that
+ works like the BIND feature (removes AAAA records unless AAAA-only domain).
+ Useful for certain 'broken IPv6 default route' scenarios.
+ Patch from Stephane Lapie for ASAHI Net.
+* unbound_smf22.tar.gz: Solaris SMF installation/removal scripts.
+ Contributed by Yuri Voinov.
diff --git a/contrib/unbound/contrib/aaaa-filter-iterator.patch b/contrib/unbound/contrib/aaaa-filter-iterator.patch
new file mode 100644
index 0000000..0647f49
--- /dev/null
+++ b/contrib/unbound/contrib/aaaa-filter-iterator.patch
@@ -0,0 +1,413 @@
+Index: trunk/doc/unbound.conf.5.in
+===================================================================
+--- trunk/doc/unbound.conf.5.in (revision 3587)
++++ trunk/doc/unbound.conf.5.in (working copy)
+@@ -593,6 +593,13 @@
+ possible. Best effort approach, full QNAME and original QTYPE will be sent when
+ upstream replies with a RCODE other than NOERROR. Default is off.
+ .TP
++.B aaaa\-filter: \fI<yes or no>
++Activate behavior similar to BIND's AAAA-filter.
++This forces the dropping of all AAAA records, unless in the case of
++explicit AAAA queries, when no A records have been confirmed.
++This also causes an additional A query to be sent for each AAAA query.
++This breaks DNSSEC!
++.TP
+ .B private\-address: \fI<IP address or subnet>
+ Give IPv4 of IPv6 addresses or classless subnets. These are addresses
+ on your private network, and are not allowed to be returned for
+Index: trunk/iterator/iter_scrub.c
+===================================================================
+--- trunk/iterator/iter_scrub.c (revision 3587)
++++ trunk/iterator/iter_scrub.c (working copy)
+@@ -617,6 +617,32 @@
+ }
+
+ /**
++ * ASN: Lookup A records from rrset cache.
++ * @param qinfo: the question originally asked.
++ * @param env: module environment with config and cache.
++ * @param ie: iterator environment with private address data.
++ * @return 0 if no A record found, 1 if A record found.
++ */
++static int
++asn_lookup_a_record_from_cache(struct query_info* qinfo,
++ struct module_env* env, struct iter_env* ATTR_UNUSED(ie))
++{
++ struct ub_packed_rrset_key* akey;
++
++ /* get cached A records for queried name */
++ akey = rrset_cache_lookup(env->rrset_cache, qinfo->qname,
++ qinfo->qname_len, LDNS_RR_TYPE_A, qinfo->qclass,
++ 0, *env->now, 0);
++ if(akey) { /* we had some. */
++ log_rrset_key(VERB_ALGO, "ASN-AAAA-filter: found A record",
++ akey);
++ lock_rw_unlock(&akey->entry.lock);
++ return 1;
++ }
++ return 0;
++}
++
++/**
+ * Given a response event, remove suspect RRsets from the response.
+ * "Suspect" rrsets are potentially poison. Note that this routine expects
+ * the response to be in a "normalized" state -- that is, all "irrelevant"
+@@ -635,6 +661,7 @@
+ struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
+ struct iter_env* ie)
+ {
++ int found_a_record = 0; /* ASN: do we have a A record? */
+ int del_addi = 0; /* if additional-holding rrsets are deleted, we
+ do not trust the normalized additional-A-AAAA any more */
+ struct rrset_parse* rrset, *prev;
+@@ -670,6 +697,13 @@
+ rrset = rrset->rrset_all_next;
+ }
+
++ /* ASN: Locate any A record we can find */
++ if((ie->aaaa_filter) && (qinfo->qtype == LDNS_RR_TYPE_AAAA)) {
++ found_a_record = asn_lookup_a_record_from_cache(qinfo,
++ env, ie);
++ }
++ /* ASN: End of added code */
++
+ /* At this point, we brutally remove ALL rrsets that aren't
+ * children of the originating zone. The idea here is that,
+ * as far as we know, the server that we contacted is ONLY
+@@ -681,6 +715,24 @@
+ rrset = msg->rrset_first;
+ while(rrset) {
+
++ /* ASN: For AAAA records only... */
++ if((ie->aaaa_filter) && (rrset->type == LDNS_RR_TYPE_AAAA)) {
++ /* ASN: If this is not a AAAA query, then remove AAAA
++ * records, no questions asked. If this IS a AAAA query
++ * then remove AAAA records if we have an A record.
++ * Otherwise, leave things be. */
++ if((qinfo->qtype != LDNS_RR_TYPE_AAAA) ||
++ (found_a_record)) {
++ remove_rrset("ASN-AAAA-filter: removing AAAA "
++ "for record", pkt, msg, prev, &rrset);
++ continue;
++ }
++ log_nametypeclass(VERB_ALGO, "ASN-AAAA-filter: "
++ "keep AAAA for", zonename,
++ LDNS_RR_TYPE_AAAA, qinfo->qclass);
++ }
++ /* ASN: End of added code */
++
+ /* remove private addresses */
+ if( (rrset->type == LDNS_RR_TYPE_A ||
+ rrset->type == LDNS_RR_TYPE_AAAA)) {
+Index: trunk/iterator/iter_utils.c
+===================================================================
+--- trunk/iterator/iter_utils.c (revision 3587)
++++ trunk/iterator/iter_utils.c (working copy)
+@@ -175,6 +175,7 @@
+ }
+ iter_env->supports_ipv6 = cfg->do_ip6;
+ iter_env->supports_ipv4 = cfg->do_ip4;
++ iter_env->aaaa_filter = cfg->aaaa_filter;
+ return 1;
+ }
+
+Index: trunk/iterator/iterator.c
+===================================================================
+--- trunk/iterator/iterator.c (revision 3587)
++++ trunk/iterator/iterator.c (working copy)
+@@ -1776,6 +1776,53 @@
+
+ return 0;
+ }
++
++/**
++ * ASN: This event state was added as an intermediary step between
++ * QUERYTARGETS_STATE and the next step, in order to cast a subquery for the
++ * purpose of caching A records for the queried name.
++ *
++ * @param qstate: query state.
++ * @param iq: iterator query state.
++ * @param ie: iterator shared global environment.
++ * @param id: module id.
++ * @return true if the event requires more request processing immediately,
++ * false if not. This state only returns true when it is generating
++ * a SERVFAIL response because the query has hit a dead end.
++ */
++static int
++asn_processQueryAAAA(struct module_qstate* qstate, struct iter_qstate* iq,
++ struct iter_env* ATTR_UNUSED(ie), int id)
++{
++ struct module_qstate* subq = NULL;
++
++ log_assert(iq->fetch_a_for_aaaa == 0);
++
++ /* flag the query properly in order to not loop */
++ iq->fetch_a_for_aaaa = 1;
++
++ /* re-throw same query, but with a different type */
++ if(!generate_sub_request(iq->qchase.qname,
++ iq->qchase.qname_len, LDNS_RR_TYPE_A,
++ iq->qchase.qclass, qstate, id, iq,
++ INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
++ log_nametypeclass(VERB_ALGO, "ASN-AAAA-filter: failed "
++ "preloading of A record for",
++ iq->qchase.qname, LDNS_RR_TYPE_A,
++ iq->qchase.qclass);
++ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
++ }
++ log_nametypeclass(VERB_ALGO, "ASN-AAAA-filter: "
++ "preloading records in cache for",
++ iq->qchase.qname, LDNS_RR_TYPE_A,
++ iq->qchase.qclass);
++
++ /* set this query as waiting */
++ qstate->ext_state[id] = module_wait_subquery;
++ /* at this point break loop */
++ return 0;
++}
++/* ASN: End of added code */
+
+ /**
+ * This is the request event state where the request will be sent to one of
+@@ -1823,6 +1870,13 @@
+ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ }
+
++ /* ASN: If we have a AAAA query, then also query for A records */
++ if((ie->aaaa_filter) && (iq->qchase.qtype == LDNS_RR_TYPE_AAAA) &&
++ (iq->fetch_a_for_aaaa == 0)) {
++ return next_state(iq, ASN_FETCH_A_FOR_AAAA_STATE);
++ }
++ /* ASN: End of added code */
++
+ /* Make sure we have a delegation point, otherwise priming failed
+ * or another failure occurred */
+ if(!iq->dp) {
+@@ -2922,6 +2976,61 @@
+ return 0;
+ }
+
++/**
++ * ASN: Do final processing on responses to A queries originated from AAAA
++ * queries. Events reach this state after the iterative resolution algorithm
++ * terminates.
++ * This is required down the road to decide whether to scrub AAAA records
++ * from the results or not.
++ *
++ * @param qstate: query state.
++ * @param id: module id.
++ * @param forq: super query state.
++ */
++static void
++asn_processAAAAResponse(struct module_qstate* qstate, int id,
++ struct module_qstate* super)
++{
++ /*struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id];*/
++ struct iter_qstate* super_iq = (struct iter_qstate*)super->minfo[id];
++ struct delegpt_ns* dpns = NULL;
++ int error = (qstate->return_rcode != LDNS_RCODE_NOERROR);
++
++ log_assert(super_iq->fetch_a_for_aaaa > 0);
++
++ /* let super go to evaluation of targets after this */
++ super_iq->state = QUERYTARGETS_STATE;
++
++ log_query_info(VERB_ALGO, "ASN-AAAA-filter: processAAAAResponse",
++ &qstate->qinfo);
++ log_query_info(VERB_ALGO, "ASN-AAAA-filter: processAAAAResponse super",
++ &super->qinfo);
++
++ if(super_iq->dp)
++ dpns = delegpt_find_ns(super_iq->dp,
++ qstate->qinfo.qname, qstate->qinfo.qname_len);
++ if (!dpns) {
++ /* not interested */
++ verbose(VERB_ALGO, "ASN-AAAA-filter: subq: %s, but parent not "
++ "interested%s", (error ? "error, but" : "success"),
++ (super_iq->dp ? "anymore" : " (was reset)"));
++ log_query_info(VERB_ALGO, "ASN-AAAA-filter: superq", &super->qinfo);
++ if(super_iq->dp && error)
++ delegpt_log(VERB_ALGO, super_iq->dp);
++ return;
++ } else if (error) {
++ verbose(VERB_ALGO, "ASN-AAAA-filter: mark as failed, "
++ "and go to target query.");
++ /* see if the failure did get (parent-lame) info */
++ if(!cache_fill_missing(super->env,
++ super_iq->qchase.qclass, super->region,
++ super_iq->dp))
++ log_err("ASN-AAAA-filter: out of memory adding missing");
++ dpns->resolved = 1; /* mark as failed */
++ }
++}
++/* ASN: End of added code */
++
+ /*
+ * Return priming query results to interestes super querystates.
+ *
+@@ -2941,6 +3050,9 @@
+ else if(super->qinfo.qtype == LDNS_RR_TYPE_DS && ((struct iter_qstate*)
+ super->minfo[id])->state == DSNS_FIND_STATE)
+ processDSNSResponse(qstate, id, super);
++ else if (super->qinfo.qtype == LDNS_RR_TYPE_AAAA && ((struct iter_qstate*)
++ super->minfo[id])->state == ASN_FETCH_A_FOR_AAAA_STATE)
++ asn_processAAAAResponse(qstate, id, super);
+ else if(qstate->return_rcode != LDNS_RCODE_NOERROR)
+ error_supers(qstate, id, super);
+ else if(qstate->is_priming)
+@@ -2978,6 +3090,9 @@
+ case INIT_REQUEST_3_STATE:
+ cont = processInitRequest3(qstate, iq, id);
+ break;
++ case ASN_FETCH_A_FOR_AAAA_STATE:
++ cont = asn_processQueryAAAA(qstate, iq, ie, id);
++ break;
+ case QUERYTARGETS_STATE:
+ cont = processQueryTargets(qstate, iq, ie, id);
+ break;
+@@ -3270,6 +3385,8 @@
+ return "INIT REQUEST STATE (stage 2)";
+ case INIT_REQUEST_3_STATE:
+ return "INIT REQUEST STATE (stage 3)";
++ case ASN_FETCH_A_FOR_AAAA_STATE:
++ return "ASN_FETCH_A_FOR_AAAA_STATE";
+ case QUERYTARGETS_STATE :
+ return "QUERY TARGETS STATE";
+ case PRIME_RESP_STATE :
+@@ -3294,6 +3411,7 @@
+ case INIT_REQUEST_STATE :
+ case INIT_REQUEST_2_STATE :
+ case INIT_REQUEST_3_STATE :
++ case ASN_FETCH_A_FOR_AAAA_STATE :
+ case QUERYTARGETS_STATE :
+ case COLLECT_CLASS_STATE :
+ return 0;
+Index: trunk/iterator/iterator.h
+===================================================================
+--- trunk/iterator/iterator.h (revision 3587)
++++ trunk/iterator/iterator.h (working copy)
+@@ -113,6 +113,9 @@
+ */
+ int* target_fetch_policy;
+
++ /** ASN: AAAA-filter flag */
++ int aaaa_filter;
++
+ /** ip6.arpa dname in wireformat, used for qname-minimisation */
+ uint8_t* ip6arpa_dname;
+ };
+@@ -163,6 +166,14 @@
+ INIT_REQUEST_3_STATE,
+
+ /**
++ * This state is responsible for intercepting AAAA queries,
++ * and launch a A subquery on the same target, to populate the
++ * cache with A records, so the AAAA filter scrubbing logic can
++ * work.
++ */
++ ASN_FETCH_A_FOR_AAAA_STATE,
++
++ /**
+ * Each time a delegation point changes for a given query or a
+ * query times out and/or wakes up, this state is (re)visited.
+ * This state is reponsible for iterating through a list of
+@@ -346,6 +357,13 @@
+ */
+ int refetch_glue;
+
++ /**
++ * ASN: This is a flag that, if true, means that this query is
++ * for fetching A records to populate cache and determine if we must
++ * return AAAA records or not.
++ */
++ int fetch_a_for_aaaa;
++
+ /** list of pending queries to authoritative servers. */
+ struct outbound_list outlist;
+
+Index: trunk/pythonmod/interface.i
+===================================================================
+--- trunk/pythonmod/interface.i (revision 3587)
++++ trunk/pythonmod/interface.i (working copy)
+@@ -632,6 +632,7 @@
+ int harden_dnssec_stripped;
+ int harden_referral_path;
+ int use_caps_bits_for_id;
++ int aaaa_filter; /* ASN */
+ struct config_strlist* private_address;
+ struct config_strlist* private_domain;
+ size_t unwanted_threshold;
+Index: trunk/util/config_file.c
+===================================================================
+--- trunk/util/config_file.c (revision 3587)
++++ trunk/util/config_file.c (working copy)
+@@ -176,6 +176,7 @@
+ cfg->harden_referral_path = 0;
+ cfg->harden_algo_downgrade = 0;
+ cfg->use_caps_bits_for_id = 0;
++ cfg->aaaa_filter = 0; /* ASN: default is disabled */
+ cfg->caps_whitelist = NULL;
+ cfg->private_address = NULL;
+ cfg->private_domain = NULL;
+Index: trunk/util/config_file.h
+===================================================================
+--- trunk/util/config_file.h (revision 3587)
++++ trunk/util/config_file.h (working copy)
+@@ -179,6 +179,8 @@
+ int harden_algo_downgrade;
+ /** use 0x20 bits in query as random ID bits */
+ int use_caps_bits_for_id;
++ /** ASN: enable AAAA filter? */
++ int aaaa_filter;
+ /** 0x20 whitelist, domains that do not use capsforid */
+ struct config_strlist* caps_whitelist;
+ /** strip away these private addrs from answers, no DNS Rebinding */
+Index: trunk/util/configlexer.lex
+===================================================================
+--- trunk/util/configlexer.lex (revision 3587)
++++ trunk/util/configlexer.lex (working copy)
+@@ -267,6 +267,7 @@
+ use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
+ caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
+ unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
++aaaa-filter{COLON} { YDVAR(1, VAR_AAAA_FILTER) }
+ private-address{COLON} { YDVAR(1, VAR_PRIVATE_ADDRESS) }
+ private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) }
+ prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) }
+Index: trunk/util/configparser.y
+===================================================================
+--- trunk/util/configparser.y (revision 3587)
++++ trunk/util/configparser.y (working copy)
+@@ -92,6 +92,7 @@
+ %token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT
+ %token VAR_OUTGOING_PORT_AVOID VAR_DLV_ANCHOR_FILE VAR_DLV_ANCHOR
+ %token VAR_NEG_CACHE_SIZE VAR_HARDEN_REFERRAL_PATH VAR_PRIVATE_ADDRESS
++%token VAR_AAAA_FILTER
+ %token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE
+ %token VAR_CONTROL_INTERFACE VAR_CONTROL_PORT VAR_SERVER_KEY_FILE
+ %token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE
+@@ -169,6 +170,7 @@
+ server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size |
+ server_harden_referral_path | server_private_address |
+ server_private_domain | server_extended_statistics |
++ server_aaaa_filter |
+ server_local_data_ptr | server_jostle_timeout |
+ server_unwanted_reply_threshold | server_log_time_ascii |
+ server_domain_insecure | server_val_sig_skew_min |
+@@ -893,6 +895,15 @@
+ yyerror("out of memory");
+ }
+ ;
++server_aaaa_filter: VAR_AAAA_FILTER STRING_ARG
++ {
++ OUTYY(("P(server_aaaa_filter:%s)\n", $2));
++ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
++ yyerror("expected yes or no.");
++ else cfg_parser->cfg->aaaa_filter = (strcmp($2, "yes")==0);
++ free($2);
++ }
++ ;
+ server_private_address: VAR_PRIVATE_ADDRESS STRING_ARG
+ {
+ OUTYY(("P(server_private_address:%s)\n", $2));
diff --git a/contrib/unbound/contrib/build-unbound-localzone-from-hosts.pl b/contrib/unbound/contrib/build-unbound-localzone-from-hosts.pl
new file mode 100755
index 0000000..c11bbc3
--- /dev/null
+++ b/contrib/unbound/contrib/build-unbound-localzone-from-hosts.pl
@@ -0,0 +1,67 @@
+#!/usr/bin/perl -WT
+
+use strict;
+use warnings;
+
+my $hostsfile = '/etc/hosts';
+my $localzonefile = '/etc/unbound/localzone.conf.new';
+
+my $localzone = 'example.com';
+
+open( HOSTS,"<${hostsfile}" ) or die( "Could not open ${hostsfile}: $!" );
+open( ZONE,">${localzonefile}" ) or die( "Could not open ${localzonefile}: $!" );
+
+print ZONE "server:\n\n";
+print ZONE "local-zone: \"${localzone}\" transparent\n\n";
+
+my %ptrhash;
+
+while ( my $hostline = <HOSTS> ) {
+
+ # Skip comments
+ if ( $hostline !~ "^#" and $hostline !~ '^\s+$' ) {
+
+ my @entries = split( /\s+/, $hostline );
+
+ my $ip;
+
+ my $count = 0;
+ foreach my $entry ( @entries ) {
+ if ( $count == 0 ) {
+ $ip = $entry;
+ } else {
+
+ if ( $count == 1) {
+
+ # Only return localhost for 127.0.0.1 and ::1
+ if ( ($ip ne '127.0.0.1' and $ip ne '::1') or $entry =~ 'localhost' ) {
+ if ( ! defined $ptrhash{$ip} ) {
+ $ptrhash{$ip} = $entry;
+ print ZONE "local-data-ptr: \"$ip $entry\"\n";
+ }
+ }
+
+ }
+
+ # Use AAAA for IPv6 addresses
+ my $a = 'A';
+ if ( $ip =~ ':' ) {
+ $a = 'AAAA';
+ }
+
+ print ZONE "local-data: \"$entry ${a} $ip\"\n";
+
+ }
+ $count++;
+ }
+ print ZONE "\n";
+
+
+ }
+}
+
+
+
+
+__END__
+
diff --git a/contrib/unbound/contrib/create_unbound_ad_servers.cmd b/contrib/unbound/contrib/create_unbound_ad_servers.cmd
new file mode 100644
index 0000000..91d18db
--- /dev/null
+++ b/contrib/unbound/contrib/create_unbound_ad_servers.cmd
@@ -0,0 +1,33 @@
+@Echo off
+rem Convert the Yoyo.org anti-ad server listing
+rem into an unbound dns spoof redirection list.
+rem Written by Y.Voinov (c) 2014
+
+rem Note: Wget required!
+
+rem Variables
+set prefix="C:\Program Files (x86)"
+set dst_dir=%prefix%\Unbound
+set work_dir=%TEMP%
+set list_addr="http://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml&showintro=1&startdate%5Bday%5D=&startdate%5Bmonth%5D=&startdate%5Byear%5D="
+
+rem Check Wget installed
+for /f "delims=" %%a in ('where wget') do @set wget=%%a
+if /I "%wget%"=="" echo Wget not found. If installed, add path to PATH environment variable. & exit 1
+echo Wget found: %wget%
+
+"%wget%" -O %work_dir%\yoyo_ad_servers %list_addr%
+
+del /Q /F /S %dst_dir%\unbound_ad_servers
+
+for /F "eol=; tokens=*" %%a in (%work_dir%\yoyo_ad_servers) do (
+echo local-zone: %%a redirect>>%dst_dir%\unbound_ad_servers
+echo local-data: "%%a A 127.0.0.1">>%dst_dir%\unbound_ad_servers
+)
+
+echo Done.
+rem then add an include line to your unbound.conf pointing to the full path of
+rem the unbound_ad_servers file:
+rem
+rem include: $dst_dir/unbound_ad_servers
+rem
diff --git a/contrib/unbound/contrib/create_unbound_ad_servers.sh b/contrib/unbound/contrib/create_unbound_ad_servers.sh
new file mode 100755
index 0000000..d31f078b
--- /dev/null
+++ b/contrib/unbound/contrib/create_unbound_ad_servers.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# Convert the Yoyo.org anti-ad server listing
+# into an unbound dns spoof redirection list.
+# Modified by Y.Voinov (c) 2014
+
+# Note: Wget required!
+
+# Variables
+dst_dir="/etc/opt/csw/unbound"
+work_dir="/tmp"
+list_addr="http://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml&showintro=1&startdate%5Bday%5D=&startdate%5Bmonth%5D=&startdate%5Byear%5D="
+
+# OS commands
+CAT=`which cat`
+ECHO=`which echo`
+WGET=`which wget`
+
+# Check Wget installed
+if [ ! -f $WGET ]; then
+ echo "Wget not found. Exiting..."
+ exit 1
+fi
+
+$WGET -O $work_dir/yoyo_ad_servers "$list_addr" && \
+$CAT $work_dir/yoyo_ad_servers | \
+while read line ; \
+ do \
+ $ECHO "local-zone: \"$line\" redirect" ;\
+ $ECHO "local-data: \"$line A 127.0.0.1\"" ;\
+ done > \
+$dst_dir/unbound_ad_servers
+
+echo "Done."
+# then add an include line to your unbound.conf pointing to the full path of
+# the unbound_ad_servers file:
+#
+# include: $dst_dir/unbound_ad_servers
+# \ No newline at end of file
diff --git a/contrib/unbound/contrib/libunbound.pc.in b/contrib/unbound/contrib/libunbound.pc.in
new file mode 100644
index 0000000..c0d1286
--- /dev/null
+++ b/contrib/unbound/contrib/libunbound.pc.in
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: unbound
+Description: Library with validating, recursive, and caching DNS resolver
+URL: http://www.unbound.net
+Version: @PACKAGE_VERSION@
+Requires:
+Libs: -L${libdir} -lunbound @SSLLIB@ @LIBS@
+Libs.private: @LDFLAGS@
+Cflags: -I${includedir}
diff --git a/contrib/unbound/contrib/parseunbound.pl b/contrib/unbound/contrib/parseunbound.pl
new file mode 100755
index 0000000..6a6a76d
--- /dev/null
+++ b/contrib/unbound/contrib/parseunbound.pl
@@ -0,0 +1,140 @@
+#!/usr/local/bin/perl -w
+#
+# Script to parse the output from the unbound namedaemon.
+# Unbound supports a threading model, and outputs a multiline log-blob for
+# every thread.
+#
+# This script should parse all threads of the once, and store it
+# in a local cached file for speedy results when queried lots.
+#
+use strict;
+use POSIX qw(SEEK_END);
+use Storable;
+use FileHandle;
+use Carp qw(croak carp);
+use constant UNBOUND_CACHE => "/var/tmp/unbound-cache.stor";
+
+my $run_from_cron = @ARGV && $ARGV[0] eq "--cron" && shift;
+my $DEBUG = -t STDERR;
+
+# NB. VERY IMPORTANTES: set this when running this script.
+my $numthreads = 4;
+
+### if cache exists, read it in. and is newer than 3 minutes
+if ( -r UNBOUND_CACHE ) {
+ my $result = retrieve(UNBOUND_CACHE);
+ if (-M _ < 3/24/60 && !$run_from_cron ) {
+ print STDERR "Cached results:\n" if $DEBUG;
+ print join("\n", @$result), "\n";
+ exit;
+ }
+}
+my $logfile = shift or die "Usage: parseunbound.pl --cron unboundlogfile";
+my $in = new FileHandle $logfile or die "Cannot open $logfile: $!\n";
+
+# there is a special key 'thread' that indicates the thread. its not used, but returned anyway.
+my @records = ('thread', 'queries', 'cachehits', 'recursions', 'recursionavg',
+ 'outstandingmax', 'outstandingavg', 'outstandingexc',
+ 'median25', 'median50', 'median75',
+ 'us_0', 'us_1', 'us_2', 'us_4', 'us_8', 'us_16', 'us_32',
+ 'us_64', 'us_128', 'us_256', 'us_512', 'us_1024', 'us_2048',
+ 'us_4096', 'us_8192', 'us_16384', 'us_32768', 'us_65536',
+ 'us_131072', 'us_262144', 'us_524288', 's_1', 's_2', 's_4',
+ 's_8', 's_16', 's_32', 's_64', 's_128', 's_256', 's_512');
+# Stats hash containing one or more keys. for every thread, 1 key.
+my %allstats = (); # key="$threadid", stats={key => value}
+my %startstats = (); # when we got a queries entry for this thread
+my %donestats = (); # same, but only when we got a histogram entry for it
+# stats hash contains name/value pairs of the actual numbers for that thread.
+my $offset = 0;
+my $inthread=0;
+my $inpid;
+
+# We should continue looping untill we meet these conditions:
+# a) more total queries than the previous run (which defaults to 0) AND
+# b) parsed all $numthreads threads in the log.
+my $numqueries = $previousresult ? $previousresult->[1] : 0;
+
+# Main loop
+while ( scalar keys %startstats < $numthreads || scalar keys %donestats < $numthreads) {
+ $offset += 10000;
+ if ( $offset > -s $logfile or $offset > 10_000_000 ) {
+ die "Cannot find stats in $logfile\n";
+ }
+ $in->seek(-$offset, SEEK_END) or croak "cannot seek $logfile: $!\n";
+
+ for my $line ( <$in> ) {
+ chomp($line);
+
+ #[1208777234] unbound[6705:0]
+ if ($line =~ m/^\[\d+\] unbound\[\d+:(\d+)\]/) {
+ $inthread = $1;
+ if ($inthread + 1 > $numthreads) {
+ die "Hey. lazy. change \$numthreads in this script to ($inthread)\n";
+ }
+ }
+ # this line doesn't contain a pid:thread. skip.
+ else {
+ next;
+ }
+
+ if ( $line =~ m/info: server stats for thread \d+: (\d+) queries, (\d+) answers from cache, (\d+) recursions/ ) {
+ $startstats{$inthread} = 1;
+ $allstats{$inthread}->{thread} = $inthread;
+ $allstats{$inthread}->{queries} = $1;
+ $allstats{$inthread}->{cachehits} = $2;
+ $allstats{$inthread}->{recursions} = $3;
+ }
+ elsif ( $line =~ m/info: server stats for thread (\d+): requestlist max (\d+) avg ([0-9\.]+) exceeded (\d+)/ ) {
+ $allstats{$inthread}->{outstandingmax} = $2;
+ $allstats{$inthread}->{outstandingavg} = int($3); # This is a float; rrdtool only handles ints.
+ $allstats{$inthread}->{outstandingexc} = $4;
+ }
+ elsif ( $line =~ m/info: average recursion processing time ([0-9\.]+) sec/ ) {
+ $allstats{$inthread}->{recursionavg} = int($1 * 1000); # change sec to milisec.
+ }
+ elsif ( $line =~ m/info: histogram of recursion processing times/ ) {
+ next;
+ }
+ elsif ( $line =~ m/info: \[25%\]=([0-9\.]+) median\[50%\]=([0-9\.]+) \[75%\]=([0-9\.]+)/ ) {
+ $allstats{$inthread}->{median25} = int($1 * 1000000); # change seconds to usec
+ $allstats{$inthread}->{median50} = int($2 * 1000000);
+ $allstats{$inthread}->{median75} = int($3 * 1000000);
+ }
+ elsif ( $line =~ m/info: lower\(secs\) upper\(secs\) recursions/ ) {
+ # since after this line we're unsure if we get these numbers
+ # at all, we sould consider this marker as the end of the
+ # block. Chances that we're parsing a file halfway written
+ # at this stage are small. Bold statement.
+ $donestats{$inthread} = 1;
+ next;
+ }
+ elsif ( $line =~ m/info:\s+(\d+)\.(\d+)\s+(\d+)\.(\d+)\s+(\d+)/ ) {
+ my ($froms, $fromus, $toms, $tous, $counter) = ($1, $2, $3, $4, $5);
+ my $prefix = '';
+ if ($froms > 0) {
+ $allstats{$inthread}->{'s_' . int($froms)} = $counter;
+ } else {
+ $allstats{$inthread}->{'us_' . int($fromus)} = $counter;
+ }
+ }
+ }
+}
+
+my @result;
+# loop on the records we want to store
+for my $key ( @records ) {
+ my $sum = 0;
+ # these are the different threads parsed
+ foreach my $thread ( 0 .. $numthreads - 1 ) {
+ $sum += ($allstats{$thread}->{$key} || 0);
+ }
+ print STDERR "$key = " . $sum . "\n" if $DEBUG;
+ push @result, $sum;
+}
+print join("\n", @result), "\n";
+store \@result, UNBOUND_CACHE;
+
+if ($DEBUG) {
+ print STDERR "Threads: " . (scalar keys %allstats) . "\n";
+}
diff --git a/contrib/unbound/contrib/patch_rsamd5_enable.diff b/contrib/unbound/contrib/patch_rsamd5_enable.diff
new file mode 100644
index 0000000..dfd4a7b
--- /dev/null
+++ b/contrib/unbound/contrib/patch_rsamd5_enable.diff
@@ -0,0 +1,22 @@
+Index: validator/val_secalgo.c
+===================================================================
+--- validator/val_secalgo.c (revision 2759)
++++ validator/val_secalgo.c (working copy)
+@@ -153,7 +153,7 @@
+ switch(id) {
+ case LDNS_RSAMD5:
+ /* RFC 6725 deprecates RSAMD5 */
+- return 0;
++ return 1;
+ case LDNS_DSA:
+ case LDNS_DSA_NSEC3:
+ case LDNS_RSASHA1:
+@@ -617,7 +617,7 @@
+ switch(id) {
+ case LDNS_RSAMD5:
+ /* RFC 6725 deprecates RSAMD5 */
+- return 0;
++ return 1;
+ case LDNS_DSA:
+ case LDNS_DSA_NSEC3:
+ case LDNS_RSASHA1:
diff --git a/contrib/unbound/contrib/rc_d_unbound b/contrib/unbound/contrib/rc_d_unbound
new file mode 100755
index 0000000..5651614
--- /dev/null
+++ b/contrib/unbound/contrib/rc_d_unbound
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# unbound freebsd startup rc.d script, modified from the named script.
+# uses the default unbound installation path and pidfile location.
+# copy this to /etc/rc.d/unbound
+# and put unbound_enable="YES" into rc.conf
+#
+
+# PROVIDE: unbound
+# REQUIRE: SERVERS cleanvar
+# KEYWORD: shutdown
+
+. /etc/rc.subr
+
+name="unbound"
+rcvar=`set_rcvar`
+
+load_rc_config $name
+
+command="/usr/local/sbin/unbound"
+pidfile=${unbound_pidfile:-"/usr/local/etc/unbound/unbound.pid"}
+command_args=${unbound_flags:-"-c /usr/local/etc/unbound/unbound.conf"}
+extra_commands="reload"
+
+run_rc_command "$1"
diff --git a/contrib/unbound/contrib/selinux/unbound.fc b/contrib/unbound/contrib/selinux/unbound.fc
new file mode 100644
index 0000000..f7e63ea
--- /dev/null
+++ b/contrib/unbound/contrib/selinux/unbound.fc
@@ -0,0 +1,4 @@
+/etc/unbound(/.*)? system_u:object_r:unbound_conf_t:s0
+/etc/rc\.d/init\.d/unbound -- system_u:object_r:unbound_initrc_exec_t:s0
+/usr/sbin/unbound -- system_u:object_r:unbound_exec_t:s0
+/var/run/unbound(/.*)? system_u:object_r:unbound_var_run_t:s0
diff --git a/contrib/unbound/contrib/selinux/unbound.te b/contrib/unbound/contrib/selinux/unbound.te
new file mode 100644
index 0000000..d407ed3
--- /dev/null
+++ b/contrib/unbound/contrib/selinux/unbound.te
@@ -0,0 +1,42 @@
+policy_module(unbound, 0.1.0)
+
+type unbound_t;
+type unbound_conf_t;
+type unbound_exec_t;
+type unbound_initrc_exec_t;
+type unbound_var_run_t;
+
+init_daemon_domain(unbound_t, unbound_exec_t)
+init_script_file(unbound_initrc_exec_t)
+
+role system_r types unbound_t;
+
+# XXX
+# unbound-{checkconf,control} are not protected. Do we need protect them?
+
+# Unbound daemon
+
+auth_use_nsswitch(unbound_t)
+dev_read_urand(unbound_t)
+corenet_all_recvfrom_unlabeled(unbound_t)
+corenet_tcp_bind_all_nodes(unbound_t)
+corenet_tcp_bind_dns_port(unbound_t)
+corenet_tcp_bind_rndc_port(unbound_t)
+corenet_udp_bind_all_nodes(unbound_t)
+corenet_udp_bind_all_unreserved_ports(unbound_t)
+corenet_udp_bind_dns_port(unbound_t)
+files_read_etc_files(unbound_t)
+files_pid_file(unbound_var_run_t)
+files_type(unbound_conf_t)
+libs_use_ld_so(unbound_t)
+libs_use_shared_libs(unbound_t)
+logging_send_syslog_msg(unbound_t)
+manage_files_pattern(unbound_t, unbound_var_run_t, unbound_var_run_t)
+miscfiles_read_localization(unbound_t)
+read_files_pattern(unbound_t, unbound_conf_t, unbound_conf_t)
+
+allow unbound_t self:capability { setuid chown net_bind_service setgid dac_override };
+allow unbound_t self:tcp_socket create_stream_socket_perms;
+allow unbound_t self:udp_socket create_socket_perms;
+
+###################################################
diff --git a/contrib/unbound/contrib/unbound-host.nagios.patch b/contrib/unbound/contrib/unbound-host.nagios.patch
new file mode 100644
index 0000000..5b249b6
--- /dev/null
+++ b/contrib/unbound/contrib/unbound-host.nagios.patch
@@ -0,0 +1,134 @@
+Index: smallapp/unbound-host.c
+===================================================================
+--- smallapp/unbound-host.c (revision 2115)
++++ smallapp/unbound-host.c (working copy)
+@@ -62,9 +62,18 @@
+ #include "libunbound/unbound.h"
+ #include <ldns/ldns.h>
+
++/** status variable ala nagios */
++#define FINAL_STATUS_OK 0
++#define FINAL_STATUS_WARNING 1
++#define FINAL_STATUS_CRITICAL 2
++#define FINAL_STATUS_UNKNOWN 3
++
+ /** verbosity for unbound-host app */
+ static int verb = 0;
+
++/** variable to determine final output */
++static int final_status = FINAL_STATUS_UNKNOWN;
++
+ /** Give unbound-host usage, and exit (1). */
+ static void
+ usage()
+@@ -93,7 +102,7 @@
+ printf("Version %s\n", PACKAGE_VERSION);
+ printf("BSD licensed, see LICENSE in source package for details.\n");
+ printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+
+ /** determine if str is ip4 and put into reverse lookup format */
+@@ -138,7 +147,7 @@
+ *res = strdup(buf);
+ if(!*res) {
+ fprintf(stderr, "error: out of memory\n");
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ return 1;
+ }
+@@ -158,7 +167,7 @@
+ }
+ if(!res) {
+ fprintf(stderr, "error: out of memory\n");
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ return res;
+ }
+@@ -172,7 +181,7 @@
+ if(r == 0 && strcasecmp(t, "TYPE0") != 0 &&
+ strcmp(t, "") != 0) {
+ fprintf(stderr, "error unknown type %s\n", t);
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ return r;
+ }
+@@ -191,7 +200,7 @@
+ if(r == 0 && strcasecmp(c, "CLASS0") != 0 &&
+ strcmp(c, "") != 0) {
+ fprintf(stderr, "error unknown class %s\n", c);
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ return r;
+ }
+@@ -207,6 +216,19 @@
+ return "(insecure)";
+ }
+
++/** update the final status for the exit code */
++void
++update_final_status(struct ub_result* result)
++{
++ if (final_status == FINAL_STATUS_UNKNOWN || final_status == FINAL_STATUS_OK) {
++ if (result->secure) final_status = FINAL_STATUS_OK;
++ else if (result->bogus) final_status = FINAL_STATUS_CRITICAL;
++ else final_status = FINAL_STATUS_WARNING;
++ }
++ else if (final_status == FINAL_STATUS_WARNING && result->bogus)
++ final_status = FINAL_STATUS_CRITICAL;
++}
++
+ /** nice string for type */
+ static void
+ pretty_type(char* s, size_t len, int t)
+@@ -353,7 +375,7 @@
+ } else {
+ fprintf(stderr, "could not parse "
+ "reply packet to ANY query\n");
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ ldns_pkt_free(p);
+
+@@ -388,9 +410,10 @@
+ ret = ub_resolve(ctx, q, t, c, &result);
+ if(ret != 0) {
+ fprintf(stderr, "resolve error: %s\n", ub_strerror(ret));
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ pretty_output(q, t, c, result, docname);
++ update_final_status(result);
+ ret = result->nxdomain;
+ ub_resolve_free(result);
+ return ret;
+@@ -427,7 +450,7 @@
+ {
+ if(r != 0) {
+ fprintf(stderr, "error: %s\n", ub_strerror(r));
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+ }
+
+@@ -448,7 +471,7 @@
+ ctx = ub_ctx_create();
+ if(!ctx) {
+ fprintf(stderr, "error: out of memory\n");
+- exit(1);
++ exit(FINAL_STATUS_UNKNOWN);
+ }
+
+ /* parse the options */
+@@ -509,5 +532,5 @@
+ usage();
+
+ lookup(ctx, argv[0], qtype, qclass);
+- return 0;
++ return final_status;
+ }
diff --git a/contrib/unbound/contrib/unbound.init b/contrib/unbound/contrib/unbound.init
new file mode 100644
index 0000000..747f94e
--- /dev/null
+++ b/contrib/unbound/contrib/unbound.init
@@ -0,0 +1,139 @@
+#!/bin/sh
+#
+# unbound This shell script takes care of starting and stopping
+# unbound (DNS server).
+#
+# chkconfig: - 14 86
+# description: unbound is a Domain Name Server (DNS) \
+# that is used to resolve host names to IP addresses.
+
+### BEGIN INIT INFO
+# Provides: $named unbound
+# Required-Start: $network $local_fs
+# Required-Stop: $network $local_fs
+# Should-Start: $syslog
+# Should-Stop: $syslog
+# Short-Description: unbound recursive Domain Name Server.
+# Description: unbound is a Domain Name Server (DNS)
+# that is used to resolve host names to IP addresses.
+### END INIT INFO
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+exec="/usr/sbin/unbound"
+prog="unbound"
+config="/var/unbound/unbound.conf"
+pidfile="/var/unbound/unbound.pid"
+rootdir="/var/unbound"
+
+[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
+
+lockfile=/var/lock/subsys/$prog
+
+start() {
+ [ -x $exec ] || exit 5
+ [ -f $config ] || exit 6
+ echo -n $"Starting $prog: "
+
+ # setup root jail
+ if [ -s /etc/localtime ]; then
+ [ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
+ if [ ! -e ${rootdir}/etc/localtime ] || /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
+ cp -fp /etc/localtime ${rootdir}/etc/localtime
+ fi;
+ fi;
+ if [ -s /etc/resolv.conf ]; then
+ [ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
+ if [ ! -e ${rootdir}/etc/resolv.conf ] || /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
+ cp -fp /etc/resolv.conf ${rootdir}/etc/resolv.conf
+ fi;
+ fi;
+ if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
+ [ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
+ [ -e ${rootdir}/dev/log ] || touch ${rootdir}/dev/log
+ mount --bind -n /dev/log ${rootdir}/dev/log >/dev/null 2>&1;
+ fi;
+ if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
+ [ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
+ [ -e ${rootdir}/dev/random ] || touch ${rootdir}/dev/random
+ mount --bind -n /dev/random ${rootdir}/dev/random >/dev/null 2>&1;
+ fi;
+
+ # if not running, start it up here
+ daemon $exec
+ retval=$?
+ echo
+ [ $retval -eq 0 ] && touch $lockfile
+ return $retval
+}
+
+stop() {
+ echo -n $"Stopping $prog: "
+ # stop it here, often "killproc $prog"
+ killproc -p $pidfile $prog
+ retval=$?
+ echo
+ [ $retval -eq 0 ] && rm -f $lockfile
+ if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
+ umount ${rootdir}/dev/log >/dev/null 2>&1
+ fi;
+ if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
+ umount ${rootdir}/dev/random >/dev/null 2>&1
+ fi;
+ return $retval
+}
+
+restart() {
+ stop
+ start
+}
+
+reload() {
+ kill -HUP `cat $pidfile`
+}
+
+force_reload() {
+ restart
+}
+
+rh_status() {
+ # run checks to determine if the service is running or use generic status
+ status -p $pidfile $prog
+}
+
+rh_status_q() {
+ rh_status -p $pidfile >/dev/null 2>&1
+}
+
+case "$1" in
+ start)
+ rh_status_q && exit 0
+ $1
+ ;;
+ stop)
+ rh_status_q || exit 0
+ $1
+ ;;
+ restart)
+ $1
+ ;;
+ reload)
+ rh_status_q || exit 7
+ $1
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ status)
+ rh_status
+ ;;
+ condrestart|try-restart)
+ rh_status_q || exit 0
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
+ exit 2
+esac
+exit $?
diff --git a/contrib/unbound/contrib/unbound.init_fedora b/contrib/unbound/contrib/unbound.init_fedora
new file mode 100644
index 0000000..9f7e442
--- /dev/null
+++ b/contrib/unbound/contrib/unbound.init_fedora
@@ -0,0 +1,119 @@
+#!/bin/sh
+#
+# unbound This shell script takes care of starting and stopping
+# unbound (DNS server).
+#
+# chkconfig: - 14 86
+# description: unbound is a Domain Name Server (DNS) \
+# that is used to resolve host names to IP addresses.
+
+### BEGIN INIT INFO
+# Provides: unbound
+# Required-Start: $network $local_fs
+# Required-Stop: $network $local_fs
+# Should-Start: $syslog
+# Should-Stop: $syslog
+# Short-Description: unbound recursive Domain Name Server.
+# Description: unbound is a Domain Name Server (DNS)
+# that is used to resolve host names to IP addresses.
+### END INIT INFO
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+exec="/usr/sbin/unbound"
+config="/var/lib/unbound/unbound.conf"
+rootdir="/var/lib/unbound"
+pidfile="/var/run/unbound/unbound.pid"
+
+[ -e /etc/sysconfig/unbound ] && . /etc/sysconfig/unbound
+
+lockfile=/var/lock/subsys/unbound
+
+start() {
+ [ -x $exec ] || exit 5
+ [ -f $config ] || exit 6
+ echo -n $"Starting unbound: "
+
+ if [ ! -e ${rootdir}/etc/resolv.conf ] || /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
+ cp -fp /etc/resolv.conf ${rootdir}/etc/resolv.conf
+ fi;
+ if [ ! -e ${rootdir}/etc/localtime ] || /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
+ cp -fp /etc/localtime ${rootdir}/etc/localtime
+ fi;
+ mount --bind -n /dev/log ${rootdir}/dev/log >/dev/null 2>&1;
+ mount --bind -n /dev/random ${rootdir}/dev/random >/dev/null 2>&1;
+ mount --bind -n /var/run/unbound ${rootdir}/var/run/unbound >/dev/null 2>&1;
+
+ # if not running, start it up here
+ daemon $exec
+ retval=$?
+ [ $retval -eq 0 ] && touch $lockfile
+ echo
+}
+
+stop() {
+ echo -n $"Stopping unbound: "
+ # stop it here, often "killproc unbound"
+ killproc -p $pidfile unbound
+ retval=$?
+ [ $retval -eq 0 ] && rm -f $lockfile
+ for mountfile in /dev/log /dev/random /etc/localtime /etc/resolv.conf /var/run/unbound
+ do
+ if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}''${mountfile}'' /proc/mounts; then
+ umount ${rootdir}$mountfile >/dev/null 2>&1
+ fi;
+ done
+ echo
+}
+
+restart() {
+ stop
+ start
+}
+
+reload() {
+ kill -HUP `cat $pidfile`
+}
+
+force_reload() {
+ restart
+}
+
+rh_status() {
+ # run checks to determine if the service is running or use generic status
+ status -p $pidfile unbound
+}
+
+rh_status_q() {
+ rh_status -p $pidfile >/dev/null 2>&1
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart)
+ restart
+ ;;
+ reload)
+ reload
+ ;;
+ force-reload)
+ force_reload
+ ;;
+ status)
+ rh_status
+ ;;
+ condrestart|try-restart)
+ rh_status_q || exit 0
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
+ exit 2
+esac
+exit $?
diff --git a/contrib/unbound/contrib/unbound.plist b/contrib/unbound/contrib/unbound.plist
new file mode 100644
index 0000000..15e1162
--- /dev/null
+++ b/contrib/unbound/contrib/unbound.plist
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd >
+<plist version="1.0">
+<!--
+Unbound plist file for use by MacOSX launchd(8) using launchctl(1).
+Copy this file to /Library/LaunchDaemons. Launchd keeps unbound running.
+
+Setup your unbound.conf with the following additional settings.
+server:
+ do-daemonize: no
+ username: ""
+ chroot: ""
+ directory: ""
+These actions are performed by launchd (for the option values, see below).
+
+-->
+<dict>
+ <key>Label</key>
+ <string>unbound</string>
+
+ <key>ProgramArguments</key>
+ <array>
+ <string>unbound</string>
+ </array>
+
+ <key>UserName</key>
+ <string>unbound</string>
+
+ <key>RootDirectory</key>
+ <string>/usr/local/etc/unbound</string>
+
+ <key>WorkingDirectory</key>
+ <string>/usr/local/etc/unbound</string>
+
+ <key>KeepAlive</key>
+ <true/>
+
+ <key>RunAtLoad</key>
+ <true/>
+
+</dict>
+</plist>
diff --git a/contrib/unbound/contrib/unbound.spec b/contrib/unbound/contrib/unbound.spec
new file mode 100644
index 0000000..6ddc5f1
--- /dev/null
+++ b/contrib/unbound/contrib/unbound.spec
@@ -0,0 +1,112 @@
+Summary: Validating, recursive, and caching DNS resolver
+Name: unbound
+Version: 1.4.18
+Release: 1%{?dist}
+License: BSD
+Url: http://www.nlnetlabs.nl/unbound/
+Source: http://www.unbound.net/downloads/%{name}-%{version}.tar.gz
+#Source1: unbound.init
+Group: System Environment/Daemons
+Requires: ldns
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+BuildRequires: flex, openssl-devel, expat-devel, ldns-devel
+
+%description
+Unbound is a validating, recursive, and caching DNS resolver.
+
+The C implementation of Unbound is developed and maintained by NLnet
+Labs. It is based on ideas and algorithms taken from a java prototype
+developed by Verisign labs, Nominet, Kirei and ep.net.
+
+Unbound is designed as a set of modular components, so that also
+DNSSEC (secure DNS) validation and stub-resolvers (that do not run
+as a server, but are linked into an application) are easily possible.
+
+The source code is under a BSD License.
+
+%prep
+%setup -q
+
+# configure with /var/unbound/unbound.conf so that all default chroot,
+# pidfile and config file are in /var/unbound, ready for chroot jail set up.
+%configure --with-conf-file=%{_localstatedir}/%{name}/unbound.conf --disable-rpath
+
+%build
+#%{__make} %{?_smp_mflags}
+make
+
+%install
+rm -rf %{buildroot}
+%{__make} DESTDIR=%{buildroot} install
+install -d 0700 %{buildroot}%{_localstatedir}/%{name}
+install -d 0755 %{buildroot}%{_initrddir}
+install -m 0755 contrib/unbound.init %{buildroot}%{_initrddir}/unbound
+# add symbolic link from /etc/unbound.conf -> /var/unbound/unbound.conf
+ln -s %{_localstatedir}/unbound/unbound.conf %{buildroot}%{_sysconfdir}/unbound.conf
+# remove static library from install (fedora packaging guidelines)
+rm -f %{buildroot}%{_libdir}/libunbound.a %{buildroot}%{_libdir}/libunbound.la
+
+%clean
+rm -rf ${RPM_BUILD_ROOT}
+
+%files
+%defattr(-,root,root,-)
+%doc doc/README doc/CREDITS doc/LICENSE doc/FEATURES
+%attr(0755,root,root) %{_initrddir}/%{name}
+%attr(0700,%{name},%{name}) %dir %{_localstatedir}/%{name}
+%attr(0644,%{name},%{name}) %config(noreplace) %{_localstatedir}/%{name}/unbound.conf
+%attr(0644,%{name},%{name}) %config(noreplace) %{_sysconfdir}/unbound.conf
+%{_sbindir}/*
+%{_mandir}/*/*
+%{_includedir}/*
+%{_libdir}/libunbound*
+
+%pre
+getent group unbound >/dev/null || groupadd -r unbound
+getent passwd unbound >/dev/null || \
+useradd -r -g unbound -d /var/unbound -s /sbin/nologin \
+ -c "unbound name daemon" unbound
+exit 0
+
+%post
+# This adds the proper /etc/rc*.d links for the script
+/sbin/chkconfig --add %{name}
+
+%preun
+if [ $1 -eq 0 ]; then
+ /sbin/service %{name} stop >/dev/null 2>&1
+ /sbin/chkconfig --del %{name}
+ # remove root jail
+ rm -f /var/unbound/dev/log /var/unbound/dev/random /var/unbound/etc/localtime /var/unbound/etc/resolv.conf >/dev/null 2>&1
+ rmdir /var/unbound/dev >/dev/null 2>&1 || :
+ rmdir /var/unbound/etc >/dev/null 2>&1 || :
+ rmdir /var/unbound >/dev/null 2>&1 || :
+fi
+
+%postun
+if [ "$1" -ge "1" ]; then
+ /sbin/service %{name} condrestart >/dev/null 2>&1 || :
+fi
+
+%changelog
+* Thu Jul 13 2011 Wouter Wijngaards <wouter@nlnetlabs.nl> - 1.4.8
+- ldns required and ldns-devel required for build, no more ldns-builtin.
+
+* Thu Mar 17 2011 Wouter Wijngaards <wouter@nlnetlabs.nl> - 1.4.8
+- removed --disable-gost, assume recent openssl on the destination platform.
+
+* Wed Mar 16 2011 Harold Jones <hajones@verisign.com> - 1.4.8
+- Bump version number to latest
+- Add expat-devel to BuildRequires
+- Added --disable-gost for building on CentOS 5.x
+- Added --with-ldns-builtin for CentOS 5.x
+
+* Thu May 22 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 1.0.0
+- contrib changes from Patrick Vande Walle.
+
+* Thu Apr 25 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.12
+- Using parts from ports collection entry by Jaap Akkerhuis.
+- Using Fedoraproject wiki guidelines.
+
+* Wed Apr 23 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.11
+- Initial version.
diff --git a/contrib/unbound/contrib/unbound.spec_fedora b/contrib/unbound/contrib/unbound.spec_fedora
new file mode 100644
index 0000000..e7e9ac0
--- /dev/null
+++ b/contrib/unbound/contrib/unbound.spec_fedora
@@ -0,0 +1,433 @@
+# not ready yet
+%{?!with_python: %global with_python 1}
+
+%if %{with_python}
+%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
+%{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
+%endif
+
+Summary: Validating, recursive, and caching DNS(SEC) resolver
+Name: unbound
+Version: 1.4.13
+Release: 1%{?dist}
+License: BSD
+Url: http://www.nlnetlabs.nl/unbound/
+Source: http://www.unbound.net/downloads/%{name}-%{version}.tar.gz
+Source1: unbound.init
+Source2: unbound.conf
+Source3: unbound.munin
+Source4: unbound_munin_
+Source5: root.key
+Patch1: unbound-1.2-glob.patch
+
+Group: System Environment/Daemons
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+BuildRequires: flex, openssl-devel , ldns-devel >= 1.5.0,
+BuildRequires: libevent-devel expat-devel
+%if %{with_python}
+BuildRequires: python-devel swig
+%endif
+# Required for SVN versions
+# BuildRequires: bison
+
+Requires(post): chkconfig
+Requires(preun): chkconfig
+Requires(preun): initscripts
+Requires(postun): initscripts
+Requires: ldns >= 1.5.0
+Requires(pre): shadow-utils
+
+Obsoletes: dnssec-conf < 1.27-2
+Provides: dnssec-conf = 1.27-1
+
+%description
+Unbound is a validating, recursive, and caching DNS(SEC) resolver.
+
+The C implementation of Unbound is developed and maintained by NLnet
+Labs. It is based on ideas and algorithms taken from a java prototype
+developed by Verisign labs, Nominet, Kirei and ep.net.
+
+Unbound is designed as a set of modular components, so that also
+DNSSEC (secure DNS) validation and stub-resolvers (that do not run
+as a server, but are linked into an application) are easily possible.
+
+%package munin
+Summary: Plugin for the munin / munin-node monitoring package
+Group: System Environment/Daemons
+Requires: munin-node
+Requires: %{name} = %{version}-%{release}, bc
+
+%description munin
+Plugin for the munin / munin-node monitoring package
+
+%package devel
+Summary: Development package that includes the unbound header files
+Group: Development/Libraries
+Requires: %{name}-libs = %{version}-%{release}, openssl-devel, ldns-devel
+
+%description devel
+The devel package contains the unbound library and the include files
+
+%package libs
+Summary: Libraries used by the unbound server and client applications
+Group: Applications/System
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+Requires: openssl
+
+%description libs
+Contains libraries used by the unbound server and client applications
+
+%if %{with_python}
+%package python
+Summary: Python modules and extensions for unbound
+Group: Applications/System
+Requires: %{name}-libs = %{version}-%{release}
+
+%description python
+Python modules and extensions for unbound
+%endif
+
+%prep
+%setup -q
+%patch1 -p1
+
+%build
+%configure --with-ldns= --with-libevent --with-pthreads --with-ssl \
+ --disable-rpath --disable-static \
+ --with-conf-file=%{_sysconfdir}/%{name}/unbound.conf \
+ --with-pidfile=%{_localstatedir}/run/%{name}/%{name}.pid \
+%if %{with_python}
+ --with-pythonmodule --with-pyunbound \
+%endif
+ --enable-sha2 --disable-gost
+%{__make} %{?_smp_mflags}
+
+%install
+rm -rf %{buildroot}
+%{__make} DESTDIR=%{buildroot} install
+install -d 0755 %{buildroot}%{_initrddir}
+install -m 0755 %{SOURCE1} %{buildroot}%{_initrddir}/unbound
+install -m 0755 %{SOURCE2} %{buildroot}%{_sysconfdir}/unbound
+# Install munin plugin and its softlinks
+install -d 0755 %{buildroot}%{_sysconfdir}/munin/plugin-conf.d
+install -m 0644 %{SOURCE3} %{buildroot}%{_sysconfdir}/munin/plugin-conf.d/unbound
+install -d 0755 %{buildroot}%{_datadir}/munin/plugins/
+install -m 0755 %{SOURCE4} %{buildroot}%{_datadir}/munin/plugins/unbound
+for plugin in unbound_munin_hits unbound_munin_queue unbound_munin_memory unbound_munin_by_type unbound_munin_by_class unbound_munin_by_opcode unbound_munin_by_rcode unbound_munin_by_flags unbound_munin_histogram; do
+ ln -s unbound %{buildroot}%{_datadir}/munin/plugins/$plugin
+done
+
+# install root and DLV key
+install -m 0644 %{SOURCE5} %{SOURCE6} %{buildroot}%{_sysconfdir}/unbound/
+
+# remove static library from install (fedora packaging guidelines)
+rm %{buildroot}%{_libdir}/*.la
+%if %{with_python}
+rm %{buildroot}%{python_sitearch}/*.la
+%endif
+
+mkdir -p %{buildroot}%{_localstatedir}/run/unbound
+
+%clean
+rm -rf ${RPM_BUILD_ROOT}
+
+%files
+%defattr(-,root,root,-)
+%doc doc/README doc/CREDITS doc/LICENSE doc/FEATURES
+%attr(0755,root,root) %{_initrddir}/%{name}
+%attr(0755,root,root) %dir %{_sysconfdir}/%{name}
+%ghost %attr(0755,unbound,unbound) %dir %{_localstatedir}/run/%{name}
+%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/%{name}/unbound.conf
+%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/%{name}/root.key
+%{_sbindir}/*
+%{_mandir}/*/*
+
+%if %{with_python}
+%files python
+%defattr(-,root,root,-)
+%{python_sitearch}/*
+%doc libunbound/python/examples/*
+%doc pythonmod/examples/*
+%endif
+
+%files munin
+%defattr(-,root,root,-)
+%config(noreplace) %{_sysconfdir}/munin/plugin-conf.d/unbound
+%{_datadir}/munin/plugins/unbound*
+
+%files devel
+%defattr(-,root,root,-)
+%{_libdir}/libunbound.so
+%{_includedir}/unbound.h
+%doc README
+
+%files libs
+%defattr(-,root,root,-)
+%{_libdir}/libunbound.so.*
+%doc doc/README doc/LICENSE
+
+%pre
+getent group unbound >/dev/null || groupadd -r unbound
+getent passwd unbound >/dev/null || \
+useradd -r -g unbound -d %{_sysconfdir}/unbound -s /sbin/nologin \
+-c "Unbound DNS resolver" unbound
+exit 0
+
+%post
+/sbin/chkconfig --add %{name}
+
+%post libs -p /sbin/ldconfig
+
+%preun
+if [ "$1" -eq 0 ]; then
+ /sbin/service %{name} stop >/dev/null 2>&1
+ /sbin/chkconfig --del %{name}
+fi
+
+%postun
+if [ "$1" -ge "1" ]; then
+ /sbin/service %{name} condrestart >/dev/null 2>&1 || :
+fi
+
+%postun libs -p /sbin/ldconfig
+
+%changelog
+* Tue Sep 06 2011 Paul Wouters <paul@xelerance.com> - 1.4.13-1
+- Updated to 1.4.13
+- Fix install location of pythonmod from sitelib to sitearch
+- Removed patches merged in by upstream
+- Removed versioned openssl dep, it differs per branch
+
+* Mon Aug 08 2011 Paul Wouters <paul@xelerance.com> - 1.4.12-3
+- Added pythonmod docs and examples
+- Fix for python module load in the server (Tom Hendrikx)
+- No longer enable --enable-debug as it causes degraded performance
+ under load.
+
+* Mon Jul 18 2011 Paul Wouters <paul@xelerance.com> - 1.4.12-1
+- Updated to 1.4.12
+
+* Sun Jul 03 2011 Paul Wouters <paul@xelerance.com> - 1.4.11-1
+- Updated to 1.4.11
+- removed integrated CVE patch
+- updated stock unbound.conf for new options introduced
+
+* Mon Jun 06 2011 Paul Wouters <paul@xelerance.com> - 1.4.10-1
+- Added ghost for /var/run/unbound (bz#656710)
+
+* Mon Jun 06 2011 Paul Wouters <paul@xelerance.com> - 1.4.9-3
+- rebuilt
+
+* Wed May 25 2011 Paul Wouters <paul@xelerance.com> - 1.4.9-2
+- Applied patch for CVE-2011-1922 DoS vulnerability
+
+* Sun Mar 27 2011 Paul Wouters <paul@xelerance.com> - 1.4.9-1
+- Updated to 1.4.9
+
+* Sat Feb 12 2011 Paul Wouters <paul@xelerance.com> - 1.4.8-2
+- rebuilt
+
+* Tue Jan 25 2011 Paul Wouters <paul@xelerance.com> - 1.4.8-1
+- Updated to 1.4.8
+- Enable root key for DNSSEC
+- Fix unbound-munin to use proper file (could cause excessive logging)
+- Build unbound-python per default
+- Disable gost as Fedora/EPEL does not allow ECC and has mangled openssl
+
+* Tue Oct 26 2010 Paul Wouters <paul@xelerance.com> - 1.4.5-4
+- Revert last build - it was on the wrong branch
+
+* Tue Oct 26 2010 Paul Wouters <paul@xelerance.com> - 1.4.5-3
+- Disable do-ipv6 per default - causes severe degradation on non-ipv6 machines
+ (see comments in inbound.conf)
+
+* Tue Jun 15 2010 Paul Wouters <paul@xelerance.com> - 1.4.5-2
+- Bump release - forgot to upload the new tar ball.
+
+* Tue Jun 15 2010 Paul Wouters <paul@xelerance.com> - 1.4.5-1
+- Upgraded to 1.4.5
+
+* Mon May 31 2010 Paul Wouters <paul@xelerance.com> - 1.4.4-2
+- Added accidentally omitted svn patches to cvs
+
+* Mon May 31 2010 Paul Wouters <paul@xelerance.com> - 1.4.4-1
+- Upgraded to 1.4.4 with svn patches
+- Obsolete dnssec-conf to ensure it is de-installed
+
+* Thu Mar 11 2010 Paul Wouters <paul@xelerance.com> - 1.4.3-1
+- Update to 1.4.3 that fixes 64bit crasher
+
+* Tue Mar 09 2010 Paul Wouters <paul@xelerance.com> - 1.4.2-1
+- Updated to 1.4.2
+- Updated unbound.conf with new options
+- Enabled pre-fetching DNSKEY records (DNSSEC speedup)
+- Enabled re-fetching popular records before they expire
+- Enabled logging of DNSSEC validation errors
+
+* Mon Mar 01 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-5
+- Overriding -D_GNU_SOURCE is no longer needed. This fixes DSO issues
+ with pthreads
+
+* Wed Feb 24 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-3
+- Change make/configure lines to attempt to fix -lphtread linking issue
+
+* Thu Feb 18 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-2
+- Removed dependency for dnssec-conf
+- Added ISC DLV key (formerly in dnssec-conf)
+- Fixup old DLV locations in unbound.conf file via %%post
+- Fix parent child disagreement handling and no-ipv6 present [svn r1953]
+
+* Tue Jan 05 2010 Paul Wouters <paul@xelerance.com> - 1.4.1-1
+- Updated to 1.4.1
+- Changed %%define to %%global
+
+* Thu Oct 08 2009 Paul Wouters <paul@xelerance.com> - 1.3.4-2
+- Bump version
+
+* Thu Oct 08 2009 Paul Wouters <paul@xelerance.com> - 1.3.4-1
+- Upgraded to 1.3.4. Security fix with validating NSEC3 records
+
+* Fri Aug 21 2009 Tomas Mraz <tmraz@redhat.com> - 1.3.3-2
+- rebuilt with new openssl
+
+* Mon Aug 17 2009 Paul Wouters <paul@xelerance.com> - 1.3.3-1
+- Updated to 1.3.3
+
+* Sun Jul 26 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.3.0-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Sat Jun 20 2009 Paul Wouters <paul@xelerance.com> - 1.3.0-2
+- Added missing glob patch to cvs
+- Place python macros within the %%with_python check
+
+* Sat Jun 20 2009 Paul Wouters <paul@xelerance.com> - 1.3.0-1
+- Updated to 1.3.0
+- Added unbound-python sub package. disabled for now
+- Patch from svn to fix DLV lookups
+- Patches from svn to detect wrong truncated response from BIND 9.6.1 with
+ minimal-responses)
+- Added Default-Start and Default-Stop to unbound.init
+- Re-enabled --enable-sha2
+- Re-enabled glob.patch
+
+* Wed May 20 2009 Paul Wouters <paul@xelerance.com> - 1.2.1-7
+- unbound-iterator.patch was not committed
+
+* Wed May 20 2009 Paul Wouters <paul@xelerance.com> - 1.2.1-6
+- Fix for https://bugzilla.redhat.com/show_bug.cgi?id=499793
+
+* Tue Mar 17 2009 Paul Wouters <paul@xelerance.com> - 1.2.1-5
+- Use --nocheck to avoid giving an error on missing unbound-remote certs/keys
+
+* Tue Mar 10 2009 Adam Tkac <atkac redhat com> - 1.2.1-4
+- enable DNSSEC only if it is enabled in sysconfig/dnssec
+
+* Mon Mar 09 2009 Adam Tkac <atkac redhat com> - 1.2.1-3
+- add DNSSEC support to initscript and enabled it per default
+- add requires dnssec-conf
+
+* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.1-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Tue Feb 10 2009 Paul Wouters <paul@xelerance.com - 1.2.1-1
+- updated to 1.2.1
+
+* Sun Jan 18 2009 Tomas Mraz <tmraz@redhat.com> - 1.2.0-2
+- rebuild with new openssl
+
+* Wed Jan 14 2009 Paul Wouters <paul@xelerance.com - 1.2.0-1
+- Updated to 1.2.0
+- Added dependency on minimum SSL for CVE-2008-5077
+- Added dependency on bc for unbound-munin
+- Added minimum requirement of libevent 1.4.5. Crashes with older versions
+ (note: libevent is stale in EL-4 and not in EL-5, needs fixing there)
+- Removed dependency on selinux-policy (will get used when available)
+- Enable options as per draft-wijngaards-dnsext-resolver-side-mitigation-00.txt
+- Enable unwanted-reply-threshold to mitigate against a Kaminsky attack
+- Enable val-clean-additional to drop addition unsigned data from signed
+ response.
+- Removed patches (got merged into upstream)
+
+* Mon Jan 5 2009 Paul Wouters <paul@xelerance.com> - 1.1.1-7
+- Modified scandir patch to silently fail when wildcard matches nothing
+- Patch to allow unbound-checkconf to find empty wildcard matches
+
+* Mon Jan 5 2009 Paul Wouters <paul@xelerance.com> - 1.1.1-6
+- Added scandir patch for trusted-keys-file: option, which
+ is used to load multiple dnssec keys in bind file format
+
+* Mon Dec 8 2008 Paul Wouters <paul@xelerance.com> - 1.1.1-4
+- Added Requires: for selinux-policy >= 3.5.13-33 for proper SElinux rules.
+
+* Mon Dec 1 2008 Paul Wouters <paul@xelerance.com> - 1.1.1-3
+- We did not own the /etc/unbound directory (#474020)
+- Fixed cvs anomalies
+
+* Fri Nov 28 2008 Adam Tkac <atkac redhat com> - 1.1.1-2
+- removed all obsolete chroot related stuff
+- label control certs after generation correctly
+
+* Thu Nov 20 2008 Paul Wouters <paul@xelerance.com> - 1.1.1-1
+- Updated to unbound 1.1.1 which fixes a crasher and
+ addresses nlnetlabs bug #219
+
+* Wed Nov 19 2008 Paul Wouters <paul@xelerance.com> - 1.1.0-3
+- Remove the chroot, obsoleted by SElinux
+- Add additional munin plugin links supported by unbound plugin
+- Move configuration directory from /var/lib/unbound to /etc/unbound
+- Modified unbound.init and unbound.conf to account for chroot changes
+- Updated unbound.conf with new available options
+- Enabled dns-0x20 protection per default
+
+* Wed Nov 19 2008 Adam Tkac <atkac redhat com> - 1.1.0-2
+- unbound-1.1.0-log_open.patch
+ - make sure log is opened before chroot call
+ - tracked as http://www.nlnetlabs.nl/bugs/show_bug.cgi?id=219
+- removed /dev/log and /var/run/unbound and /etc/resolv.conf from
+ chroot, not needed
+- don't mount files in chroot, it causes problems during updates
+- fixed typo in default config file
+
+* Fri Nov 14 2008 Paul Wouters <paul@xelerance.com> - 1.1.0-1
+- Updated to version 1.1.0
+- Updated unbound.conf's statistics options and remote-control
+ to work properly for munin
+- Added unbound-munin package
+- Generate unbound remote-control key/certs on first startup
+- Required ldns is now 1.4.0
+
+* Wed Oct 22 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-5
+- Only call ldconfig in -libs package
+- Move configure into build section
+- devel subpackage should only depend on libs subpackage
+
+* Tue Oct 21 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-4
+- Fix CFLAGS getting lost in build
+- Don't enable interface-automatic:yes because that
+ causes unbound to listen on 0.0.0.0 instead of 127.0.0.1
+
+* Sun Oct 19 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-3
+- Split off unbound-libs, make build verbose
+
+* Thu Oct 9 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-2
+- FSB compliance, chroot fixes, initscript fixes
+
+* Thu Sep 11 2008 Paul Wouters <paul@xelerance.com> - 1.0.2-1
+- Upgraded to 1.0.2
+
+* Wed Jul 16 2008 Paul Wouters <paul@xelerance.com> - 1.0.1-1
+- upgraded to new release
+
+* Wed May 21 2008 Paul Wouters <paul@xelerance.com> - 1.0.0-2
+- Build against ldns-1.3.0
+
+* Wed May 21 2008 Paul Wouters <paul@xelerance.com> - 1.0.0-1
+- Split of -devel package, fixed dependencies, make rpmlint happy
+
+* Thu Apr 25 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.12
+- Using parts from ports collection entry by Jaap Akkerhuis.
+- Using Fedoraproject wiki guidelines.
+
+* Wed Apr 23 2008 Wouter Wijngaards <wouter@nlnetlabs.nl> - 0.11
+- Initial version.
diff --git a/contrib/unbound/contrib/unbound_cache.cmd b/contrib/unbound/contrib/unbound_cache.cmd
new file mode 100644
index 0000000..532162b
--- /dev/null
+++ b/contrib/unbound/contrib/unbound_cache.cmd
@@ -0,0 +1,105 @@
+@echo off
+rem --------------------------------------------------------------
+rem -- DNS cache save/load script
+rem --
+rem -- Version 1.2
+rem -- By Yuri Voinov (c) 2014
+rem --------------------------------------------------------------
+
+rem Variables
+set prefix="C:\Program Files (x86)"
+set program_path=%prefix%\Unbound
+set uc=%program_path%\unbound-control.exe
+set fname="unbound_cache.dmp"
+
+rem Check Unbound installed
+if exist %uc% goto start
+echo Unbound control not found. Exiting...
+exit 1
+
+:start
+
+rem arg1 - command (optional)
+rem arg2 - file name (optional)
+set arg1=%1
+set arg2=%2
+
+if /I "%arg1%" == "-h" goto help
+
+if "%arg1%" == "" (
+echo Loading cache from %program_path%\%fname%
+dir /a %program_path%\%fname%
+type %program_path%\%fname%|%uc% load_cache
+goto end
+)
+
+if defined %arg2% (goto Not_Defined) else (goto Defined)
+
+rem If file not specified; use default dump file
+:Not_defined
+if /I "%arg1%" == "-s" (
+echo Saving cache to %program_path%\%fname%
+%uc% dump_cache>%program_path%\%fname%
+dir /a %program_path%\%fname%
+echo ok
+goto end
+)
+
+if /I "%arg1%" == "-l" (
+echo Loading cache from %program_path%\%fname%
+dir /a %program_path%\%fname%
+type %program_path%\%fname%|%uc% load_cache
+goto end
+)
+
+if /I "%arg1%" == "-r" (
+echo Saving cache to %program_path%\%fname%
+dir /a %program_path%\%fname%
+%uc% dump_cache>%program_path%\%fname%
+echo ok
+echo Loading cache from %program_path%\%fname%
+type %program_path%\%fname%|%uc% load_cache
+goto end
+)
+
+rem If file name specified; use this filename
+:Defined
+if /I "%arg1%" == "-s" (
+echo Saving cache to %arg2%
+%uc% dump_cache>%arg2%
+dir /a %arg2%
+echo ok
+goto end
+)
+
+if /I "%arg1%" == "-l" (
+echo Loading cache from %arg2%
+dir /a %arg2%
+type %arg2%|%uc% load_cache
+goto end
+)
+
+if /I "%arg1%" == "-r" (
+echo Saving cache to %arg2%
+dir /a %arg2%
+%uc% dump_cache>%arg2%
+echo ok
+echo Loading cache from %arg2%
+type %arg2%|%uc% load_cache
+goto end
+)
+
+:help
+echo Usage: unbound_cache.cmd [-s] or [-l] or [-r] or [-h] [filename]
+echo.
+echo l - Load - default mode. Warming up Unbound DNS cache from saved file. cache-ttl must be high value.
+echo s - Save - save Unbound DNS cache contents to plain file with domain names.
+echo r - Reload - reloadind new cache entries and refresh existing cache
+echo h - this screen.
+echo filename - file to save/load dumped cache. If not specified, %program_path%\%fname% will be used instead.
+echo Note: Run without any arguments will be in default mode.
+echo Also, unbound-control must be configured.
+exit 1
+
+:end
+exit 0
diff --git a/contrib/unbound/contrib/unbound_cache.sh b/contrib/unbound/contrib/unbound_cache.sh
new file mode 100755
index 0000000..b3e876b
--- /dev/null
+++ b/contrib/unbound/contrib/unbound_cache.sh
@@ -0,0 +1,174 @@
+#!/sbin/sh
+
+# --------------------------------------------------------------
+# -- DNS cache save/load script
+# --
+# -- Version 1.2
+# -- By Yuri Voinov (c) 2006, 2014
+# --------------------------------------------------------------
+#
+# ident "@(#)unbound_cache.sh 1.2 14/10/30 YV"
+#
+
+#############
+# Variables #
+#############
+
+# Installation base dir
+CONF="/etc/opt/csw/unbound"
+BASE="/opt/csw"
+
+# Unbound binaries
+UC="$BASE/sbin/unbound-control"
+FNAME="unbound_cache.dmp"
+
+# OS utilities
+BASENAME=`which basename`
+CAT=`which cat`
+CUT=`which cut`
+ECHO=`which echo`
+EXPR=`which expr`
+GETOPT=`which getopt`
+ID=`which id`
+LS=`which ls`
+
+###############
+# Subroutines #
+###############
+
+usage_note ()
+{
+# Script usage note
+ $ECHO "Usage: `$BASENAME $0` [-s] or [-l] or [-r] or [-h] [filename]"
+ $ECHO .
+ $ECHO "l - Load - default mode. Warming up Unbound DNS cache from saved file. cache-ttl must be high value."
+ $ECHO "s - Save - save Unbound DNS cache contents to plain file with domain names."
+ $ECHO "r - Reload - reloadind new cache entries and refresh existing cache"
+ $ECHO "h - this screen."
+ $ECHO "filename - file to save/load dumped cache. If not specified, $CONF/$FNAME will be used instead."
+ $ECHO "Note: Run without any arguments will be in default mode."
+ $ECHO " Also, unbound-control must be configured."
+ exit 0
+}
+
+root_check ()
+{
+ if [ ! `$ID | $CUT -f1 -d" "` = "uid=0(root)" ]; then
+ $ECHO "ERROR: You must be super-user to run this script."
+ exit 1
+ fi
+}
+
+check_uc ()
+{
+ if [ ! -f "$UC" ]; then
+ $ECHO .
+ $ECHO "ERROR: $UC not found. Exiting..."
+ exit 1
+ fi
+}
+
+check_saved_file ()
+{
+ filename=$1
+ if [ ! -z "$filename" -a ! -f "$filename" ]; then
+ $ECHO .
+ $ECHO "ERROR: File $filename does not exists. Save it first."
+ exit 1
+ elif [ ! -f "$CONF/$FNAME" ]; then
+ $ECHO .
+ $ECHO "ERROR: File $CONF/$FNAME does not exists. Save it first."
+ exit 1
+ fi
+}
+
+save_cache ()
+{
+ # Save unbound cache
+ filename=$1
+ if [ -z "$filename" ]; then
+ $ECHO "Saving cache in $CONF/$FNAME..."
+ $UC dump_cache>$CONF/$FNAME
+ $LS -lh $CONF/$FNAME
+ else
+ $ECHO "Saving cache in $filename..."
+ $UC dump_cache>$filename
+ $LS -lh $filename
+ fi
+ $ECHO "ok"
+}
+
+load_cache ()
+{
+ # Load saved cache contents and warmup cache
+ filename=$1
+ if [ -z "$filename" ]; then
+ $ECHO "Loading cache from saved $CONF/$FNAME..."
+ $LS -lh $CONF/$FNAME
+ check_saved_file $filename
+ $CAT $CONF/$FNAME|$UC load_cache
+ else
+ $ECHO "Loading cache from saved $filename..."
+ $LS -lh $filename
+ check_saved_file $filename
+ $CAT $filename|$UC load_cache
+ fi
+}
+
+reload_cache ()
+{
+ # Reloading and refresh existing cache and saved dump
+ filename=$1
+ save_cache $filename
+ load_cache $filename
+}
+
+##############
+# Main block #
+##############
+
+# Root check
+root_check
+
+# Check unbound-control
+check_uc
+
+# Check command-line arguments
+if [ "x$*" = "x" ]; then
+ # If arguments list empty,load cache by default
+ load_cache
+else
+ arg_list=$*
+ # Parse command line
+ set -- `$GETOPT sSlLrRhH: $arg_list` || {
+ usage_note 1>&2
+ }
+
+ # Read arguments
+ for i in $arg_list
+ do
+ case $i in
+ -s | -S) save="1";;
+ -l | -L) save="0";;
+ -r | -R) save="2";;
+ -h | -H | \?) usage_note;;
+ *) shift
+ file=$1
+ break;;
+ esac
+ shift
+ done
+
+ # Remove trailing --
+ shift `$EXPR $OPTIND - 1`
+fi
+
+if [ "$save" = "1" ]; then
+ save_cache $file
+elif [ "$save" = "0" ]; then
+ load_cache $file
+elif [ "$save" = "2" ]; then
+ reload_cache $file
+fi
+
+exit 0 \ No newline at end of file
diff --git a/contrib/unbound/contrib/unbound_cacti.tar.gz b/contrib/unbound/contrib/unbound_cacti.tar.gz
new file mode 100644
index 0000000..36bbdec
--- /dev/null
+++ b/contrib/unbound/contrib/unbound_cacti.tar.gz
Binary files differ
diff --git a/contrib/unbound/contrib/unbound_munin_ b/contrib/unbound/contrib/unbound_munin_
new file mode 100755
index 0000000..69e9f31
--- /dev/null
+++ b/contrib/unbound/contrib/unbound_munin_
@@ -0,0 +1,574 @@
+#!/bin/sh
+#
+# plugin for munin to monitor usage of unbound servers.
+# To install copy this to /usr/local/share/munin/plugins/unbound_munin_
+# and use munin-node-configure (--suggest, --shell).
+#
+# (C) 2008 W.C.A. Wijngaards. BSD Licensed.
+#
+# To install; enable statistics and unbound-control in unbound.conf
+# server: extended-statistics: yes
+# statistics-cumulative: no
+# statistics-interval: 0
+# remote-control: control-enable: yes
+# Run the command unbound-control-setup to generate the key files.
+#
+# Environment variables for this script
+# statefile - where to put temporary statefile.
+# unbound_conf - where the unbound.conf file is located.
+# unbound_control - where to find unbound-control executable.
+# spoof_warn - what level to warn about spoofing
+# spoof_crit - what level to crit about spoofing
+#
+# You can set them in your munin/plugin-conf.d/plugins.conf file
+# with:
+# [unbound*]
+# user root
+# env.statefile /usr/local/var/munin/plugin-state/unbound-state
+# env.unbound_conf /usr/local/etc/unbound/unbound.conf
+# env.unbound_control /usr/local/sbin/unbound-control
+# env.spoof_warn 1000
+# env.spoof_crit 100000
+#
+# This plugin can create different graphs depending on what name
+# you link it as (with ln -s) into the plugins directory
+# You can link it multiple times.
+# If you are only a casual user, the _hits and _by_type are most interesting,
+# possibly followed by _by_rcode.
+#
+# unbound_munin_hits - base volume, cache hits, unwanted traffic
+# unbound_munin_queue - to monitor the internal requestlist
+# unbound_munin_memory - memory usage
+# unbound_munin_by_type - incoming queries by type
+# unbound_munin_by_class - incoming queries by class
+# unbound_munin_by_opcode - incoming queries by opcode
+# unbound_munin_by_rcode - answers by rcode, validation status
+# unbound_munin_by_flags - incoming queries by flags
+# unbound_munin_histogram - histogram of query resolving times
+#
+# Magic markers - optional - used by installation scripts and
+# munin-config: (originally contrib family but munin-node-configure ignores it)
+#
+#%# family=auto
+#%# capabilities=autoconf suggest
+
+# POD documentation
+: <<=cut
+=head1 NAME
+
+unbound_munin_ - Munin plugin to monitor the Unbound DNS resolver.
+
+=head1 APPLICABLE SYSTEMS
+
+System with unbound daemon.
+
+=head1 CONFIGURATION
+
+ [unbound*]
+ user root
+ env.statefile /usr/local/var/munin/plugin-state/unbound-state
+ env.unbound_conf /usr/local/etc/unbound/unbound.conf
+ env.unbound_control /usr/local/sbin/unbound-control
+ env.spoof_warn 1000
+ env.spoof_crit 100000
+
+Use the .env settings to override the defaults.
+
+=head1 USAGE
+
+Can be used to present different graphs. Use ln -s for that name in
+the plugins directory to enable the graph.
+unbound_munin_hits - base volume, cache hits, unwanted traffic
+unbound_munin_queue - to monitor the internal requestlist
+unbound_munin_memory - memory usage
+unbound_munin_by_type - incoming queries by type
+unbound_munin_by_class - incoming queries by class
+unbound_munin_by_opcode - incoming queries by opcode
+unbound_munin_by_rcode - answers by rcode, validation status
+unbound_munin_by_flags - incoming queries by flags
+unbound_munin_histogram - histogram of query resolving times
+
+=head1 AUTHOR
+
+Copyright 2008 W.C.A. Wijngaards
+
+=head1 LICENSE
+
+BSD
+
+=cut
+
+state=${statefile:-/usr/local/var/munin/plugin-state/unbound-state}
+conf=${unbound_conf:-/usr/local/etc/unbound/unbound.conf}
+ctrl=${unbound_control:-/usr/local/sbin/unbound-control}
+warn=${spoof_warn:-1000}
+crit=${spoof_crit:-100000}
+lock=$state.lock
+
+# number of seconds between polling attempts.
+# makes the statefile hang around for at least this many seconds,
+# so that multiple links of this script can share the results.
+lee=55
+
+# to keep things within 19 characters
+ABBREV="-e s/total/t/ -e s/thread/t/ -e s/num/n/ -e s/query/q/ -e s/answer/a/ -e s/unwanted/u/ -e s/requestlist/ql/ -e s/type/t/ -e s/class/c/ -e s/opcode/o/ -e s/rcode/r/ -e s/edns/e/ -e s/mem/m/ -e s/cache/c/ -e s/mod/m/"
+
+# get value from $1 into return variable $value
+get_value ( ) {
+ value="`grep '^'$1'=' $state | sed -e 's/^.*=//'`"
+ if test "$value"x = ""x; then
+ value="0"
+ fi
+}
+
+# download the state from the unbound server.
+get_state ( ) {
+ # obtain lock for fetching the state
+ # because there is a race condition in fetching and writing to file
+
+ # see if the lock is stale, if so, take it
+ if test -f $lock ; then
+ pid="`cat $lock 2>&1`"
+ kill -0 "$pid" >/dev/null 2>&1
+ if test $? -ne 0 -a "$pid" != $$ ; then
+ echo $$ >$lock
+ fi
+ fi
+
+ i=0
+ while test ! -f $lock || test "`cat $lock 2>&1`" != $$; do
+ while test -f $lock; do
+ # wait
+ i=`expr $i + 1`
+ if test $i -gt 1000; then
+ sleep 1;
+ fi
+ if test $i -gt 1500; then
+ echo "error locking $lock" "=" `cat $lock`
+ rm -f $lock
+ exit 1
+ fi
+ done
+ # try to get it
+ echo $$ >$lock
+ done
+ # do not refetch if the file exists and only LEE seconds old
+ if test -f $state; then
+ now=`date +%s`
+ get_value "time.now"
+ value="`echo $value | sed -e 's/\..*$//'`"
+ if test $now -lt `expr $value + $lee`; then
+ rm -f $lock
+ return
+ fi
+ fi
+ $ctrl -c $conf stats > $state
+ if test $? -ne 0; then
+ echo "error retrieving data from unbound server"
+ rm -f $lock
+ exit 1
+ fi
+ rm -f $lock
+}
+
+if test "$1" = "autoconf" ; then
+ if test ! -f $conf; then
+ echo no "($conf does not exist)"
+ exit 1
+ fi
+ if test ! -d `dirname $state`; then
+ echo no "(`dirname $state` directory does not exist)"
+ exit 1
+ fi
+ echo yes
+ exit 0
+fi
+
+if test "$1" = "suggest" ; then
+ echo "hits"
+ echo "queue"
+ echo "memory"
+ echo "by_type"
+ echo "by_class"
+ echo "by_opcode"
+ echo "by_rcode"
+ echo "by_flags"
+ echo "histogram"
+ exit 0
+fi
+
+# determine my type, by name
+id=`echo $0 | sed -e 's/^.*unbound_munin_//'`
+if test "$id"x = ""x; then
+ # some default to keep people sane.
+ id="hits"
+fi
+
+# if $1 exists in statefile, config is echoed with label $2
+exist_config ( ) {
+ mn=`echo $1 | sed $ABBREV | tr . _`
+ if grep '^'$1'=' $state >/dev/null 2>&1; then
+ echo "$mn.label $2"
+ echo "$mn.min 0"
+ echo "$mn.type ABSOLUTE"
+ fi
+}
+
+# print label and min 0 for a name $1 in unbound format
+p_config ( ) {
+ mn=`echo $1 | sed $ABBREV | tr . _`
+ echo $mn.label "$2"
+ echo $mn.min 0
+ echo $mn.type $3
+}
+
+if test "$1" = "config" ; then
+ if test ! -f $state; then
+ get_state
+ fi
+ case $id in
+ hits)
+ echo "graph_title Unbound DNS traffic and cache hits"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
+ sed -e 's/=.*//'`; do
+ exist_config $x "queries handled by `basename $x .num.queries`"
+ done
+ p_config "total.num.queries" "total queries from clients" "ABSOLUTE"
+ p_config "total.num.cachehits" "cache hits" "ABSOLUTE"
+ p_config "total.num.prefetch" "cache prefetch" "ABSOLUTE"
+ p_config "num.query.tcp" "TCP queries" "ABSOLUTE"
+ p_config "num.query.tcpout" "TCP out queries" "ABSOLUTE"
+ p_config "num.query.ipv6" "IPv6 queries" "ABSOLUTE"
+ p_config "unwanted.queries" "queries that failed acl" "ABSOLUTE"
+ p_config "unwanted.replies" "unwanted or unsolicited replies" "ABSOLUTE"
+ echo "u_replies.warning $warn"
+ echo "u_replies.critical $crit"
+ echo "graph_info DNS queries to the recursive resolver. The unwanted replies could be innocent duplicate packets, late replies, or spoof threats."
+ ;;
+ queue)
+ echo "graph_title Unbound requestlist size"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel number of queries"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ p_config "total.requestlist.avg" "Average size of queue on insert" "GAUGE"
+ p_config "total.requestlist.max" "Max size of queue (in 5 min)" "GAUGE"
+ p_config "total.requestlist.overwritten" "Number of queries replaced by new ones" "GAUGE"
+ p_config "total.requestlist.exceeded" "Number of queries dropped due to lack of space" "GAUGE"
+ echo "graph_info The queries that did not hit the cache and need recursion service take up space in the requestlist. If there are too many queries, first queries get overwritten, and at last resort dropped."
+ ;;
+ memory)
+ echo "graph_title Unbound memory usage"
+ echo "graph_args --base 1024 -l 0"
+ echo "graph_vlabel memory used in bytes"
+ echo "graph_category DNS"
+ p_config "mem.total.sbrk" "Total memory" "GAUGE"
+ p_config "mem.cache.rrset" "RRset cache memory" "GAUGE"
+ p_config "mem.cache.message" "Message cache memory" "GAUGE"
+ p_config "mem.mod.iterator" "Iterator module memory" "GAUGE"
+ p_config "mem.mod.validator" "Validator module and key cache memory" "GAUGE"
+ p_config "msg.cache.count" "msg cache count" "GAUGE"
+ p_config "rrset.cache.count" "rrset cache count" "GAUGE"
+ p_config "infra.cache.count" "infra cache count" "GAUGE"
+ p_config "key.cache.count" "key cache count" "GAUGE"
+ echo "graph_info The memory used by unbound."
+ ;;
+ by_type)
+ echo "graph_title Unbound DNS queries by type"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ for x in `grep "^num.query.type" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ tp=`echo $nm | sed -e s/num.query.type.//`
+ p_config "$nm" "$tp" "ABSOLUTE"
+ done
+ echo "graph_info queries by DNS RR type queried for"
+ ;;
+ by_class)
+ echo "graph_title Unbound DNS queries by class"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ for x in `grep "^num.query.class" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ tp=`echo $nm | sed -e s/num.query.class.//`
+ p_config "$nm" "$tp" "ABSOLUTE"
+ done
+ echo "graph_info queries by DNS RR class queried for."
+ ;;
+ by_opcode)
+ echo "graph_title Unbound DNS queries by opcode"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ for x in `grep "^num.query.opcode" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ tp=`echo $nm | sed -e s/num.query.opcode.//`
+ p_config "$nm" "$tp" "ABSOLUTE"
+ done
+ echo "graph_info queries by opcode in the query packet."
+ ;;
+ by_rcode)
+ echo "graph_title Unbound DNS answers by return code"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel answer packets / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ for x in `grep "^num.answer.rcode" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ tp=`echo $nm | sed -e s/num.answer.rcode.//`
+ p_config "$nm" "$tp" "ABSOLUTE"
+ done
+ p_config "num.answer.secure" "answer secure" "ABSOLUTE"
+ p_config "num.answer.bogus" "answer bogus" "ABSOLUTE"
+ p_config "num.rrset.bogus" "num rrsets marked bogus" "ABSOLUTE"
+ echo "graph_info answers sorted by return value. rrsets bogus is the number of rrsets marked bogus per \${graph_period} by the validator"
+ ;;
+ by_flags)
+ echo "graph_title Unbound DNS incoming queries by flags"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ p_config "num.query.flags.QR" "QR (query reply) flag" "ABSOLUTE"
+ p_config "num.query.flags.AA" "AA (auth answer) flag" "ABSOLUTE"
+ p_config "num.query.flags.TC" "TC (truncated) flag" "ABSOLUTE"
+ p_config "num.query.flags.RD" "RD (recursion desired) flag" "ABSOLUTE"
+ p_config "num.query.flags.RA" "RA (rec avail) flag" "ABSOLUTE"
+ p_config "num.query.flags.Z" "Z (zero) flag" "ABSOLUTE"
+ p_config "num.query.flags.AD" "AD (auth data) flag" "ABSOLUTE"
+ p_config "num.query.flags.CD" "CD (check disabled) flag" "ABSOLUTE"
+ p_config "num.query.edns.present" "EDNS OPT present" "ABSOLUTE"
+ p_config "num.query.edns.DO" "DO (DNSSEC OK) flag" "ABSOLUTE"
+ echo "graph_info This graphs plots the flags inside incoming queries. For example, if QR, AA, TC, RA, Z flags are set, the query can be rejected. RD, AD, CD and DO are legitimately set by some software."
+ ;;
+ histogram)
+ echo "graph_title Unbound DNS histogram of reply time"
+ echo "graph_args --base 1000 -l 0"
+ echo "graph_vlabel queries / \${graph_period}"
+ echo "graph_scale no"
+ echo "graph_category DNS"
+ echo hcache.label "cache hits"
+ echo hcache.min 0
+ echo hcache.type ABSOLUTE
+ echo hcache.draw AREA
+ echo hcache.colour 999999
+ echo h64ms.label "0 msec - 66 msec"
+ echo h64ms.min 0
+ echo h64ms.type ABSOLUTE
+ echo h64ms.draw STACK
+ echo h64ms.colour 0000FF
+ echo h128ms.label "66 msec - 131 msec"
+ echo h128ms.min 0
+ echo h128ms.type ABSOLUTE
+ echo h128ms.colour 1F00DF
+ echo h128ms.draw STACK
+ echo h256ms.label "131 msec - 262 msec"
+ echo h256ms.min 0
+ echo h256ms.type ABSOLUTE
+ echo h256ms.draw STACK
+ echo h256ms.colour 3F00BF
+ echo h512ms.label "262 msec - 524 msec"
+ echo h512ms.min 0
+ echo h512ms.type ABSOLUTE
+ echo h512ms.draw STACK
+ echo h512ms.colour 5F009F
+ echo h1s.label "524 msec - 1 sec"
+ echo h1s.min 0
+ echo h1s.type ABSOLUTE
+ echo h1s.draw STACK
+ echo h1s.colour 7F007F
+ echo h2s.label "1 sec - 2 sec"
+ echo h2s.min 0
+ echo h2s.type ABSOLUTE
+ echo h2s.draw STACK
+ echo h2s.colour 9F005F
+ echo h4s.label "2 sec - 4 sec"
+ echo h4s.min 0
+ echo h4s.type ABSOLUTE
+ echo h4s.draw STACK
+ echo h4s.colour BF003F
+ echo h8s.label "4 sec - 8 sec"
+ echo h8s.min 0
+ echo h8s.type ABSOLUTE
+ echo h8s.draw STACK
+ echo h8s.colour DF001F
+ echo h16s.label "8 sec - ..."
+ echo h16s.min 0
+ echo h16s.type ABSOLUTE
+ echo h16s.draw STACK
+ echo h16s.colour FF0000
+ echo "graph_info Histogram of the reply times for queries."
+ ;;
+ esac
+
+ exit 0
+fi
+
+# do the stats itself
+get_state
+
+# get the time elapsed
+get_value "time.elapsed"
+if test $value = 0 || test $value = "0.000000"; then
+ echo "error: time elapsed 0 or could not retrieve data"
+ exit 1
+fi
+elapsed="$value"
+
+# print value for $1
+print_value ( ) {
+ mn=`echo $1 | sed $ABBREV | tr . _`
+ get_value $1
+ echo "$mn.value" $value
+}
+
+# print value if line already found in $2
+print_value_line ( ) {
+ mn=`echo $1 | sed $ABBREV | tr . _`
+ value="`echo $2 | sed -e 's/^.*=//'`"
+ echo "$mn.value" $value
+}
+
+
+case $id in
+hits)
+ for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
+ sed -e 's/=.*//'` total.num.queries \
+ total.num.cachehits total.num.prefetch num.query.tcp \
+ num.query.tcpout num.query.ipv6 unwanted.queries \
+ unwanted.replies; do
+ if grep "^"$x"=" $state >/dev/null 2>&1; then
+ print_value $x
+ fi
+ done
+ ;;
+queue)
+ for x in total.requestlist.avg total.requestlist.max \
+ total.requestlist.overwritten total.requestlist.exceeded; do
+ print_value $x
+ done
+ ;;
+memory)
+ mn=`echo mem.total.sbrk | sed $ABBREV | tr . _`
+ get_value 'mem.total.sbrk'
+ if test $value -eq 0; then
+ chk=`echo $ctrl | sed -e 's/-control$/-checkconf/'`
+ pidf=`$chk -o pidfile $conf 2>&1`
+ pid=`cat $pidf 2>&1`
+ value=`ps -p "$pid" -o rss= 2>&1`
+ if test "`expr $value + 1 - 1 2>&1`" -eq "$value" 2>&1; then
+ value=`expr $value \* 1024`
+ else
+ value=0
+ fi
+ fi
+ echo "$mn.value" $value
+ for x in mem.cache.rrset mem.cache.message mem.mod.iterator \
+ mem.mod.validator msg.cache.count rrset.cache.count \
+ infra.cache.count key.cache.count; do
+ print_value $x
+ done
+ ;;
+by_type)
+ for x in `grep "^num.query.type" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ print_value_line $nm $x
+ done
+ ;;
+by_class)
+ for x in `grep "^num.query.class" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ print_value_line $nm $x
+ done
+ ;;
+by_opcode)
+ for x in `grep "^num.query.opcode" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ print_value_line $nm $x
+ done
+ ;;
+by_rcode)
+ for x in `grep "^num.answer.rcode" $state`; do
+ nm=`echo $x | sed -e 's/=.*$//'`
+ print_value_line $nm $x
+ done
+ print_value "num.answer.secure"
+ print_value "num.answer.bogus"
+ print_value "num.rrset.bogus"
+ ;;
+by_flags)
+ for x in num.query.flags.QR num.query.flags.AA num.query.flags.TC num.query.flags.RD num.query.flags.RA num.query.flags.Z num.query.flags.AD num.query.flags.CD num.query.edns.present num.query.edns.DO; do
+ print_value $x
+ done
+ ;;
+histogram)
+ get_value total.num.cachehits
+ echo hcache.value $value
+ r=0
+ for x in histogram.000000.000000.to.000000.000001 \
+ histogram.000000.000001.to.000000.000002 \
+ histogram.000000.000002.to.000000.000004 \
+ histogram.000000.000004.to.000000.000008 \
+ histogram.000000.000008.to.000000.000016 \
+ histogram.000000.000016.to.000000.000032 \
+ histogram.000000.000032.to.000000.000064 \
+ histogram.000000.000064.to.000000.000128 \
+ histogram.000000.000128.to.000000.000256 \
+ histogram.000000.000256.to.000000.000512 \
+ histogram.000000.000512.to.000000.001024 \
+ histogram.000000.001024.to.000000.002048 \
+ histogram.000000.002048.to.000000.004096 \
+ histogram.000000.004096.to.000000.008192 \
+ histogram.000000.008192.to.000000.016384 \
+ histogram.000000.016384.to.000000.032768 \
+ histogram.000000.032768.to.000000.065536; do
+ get_value $x
+ r=`expr $r + $value`
+ done
+ echo h64ms.value $r
+ get_value histogram.000000.065536.to.000000.131072
+ echo h128ms.value $value
+ get_value histogram.000000.131072.to.000000.262144
+ echo h256ms.value $value
+ get_value histogram.000000.262144.to.000000.524288
+ echo h512ms.value $value
+ get_value histogram.000000.524288.to.000001.000000
+ echo h1s.value $value
+ get_value histogram.000001.000000.to.000002.000000
+ echo h2s.value $value
+ get_value histogram.000002.000000.to.000004.000000
+ echo h4s.value $value
+ get_value histogram.000004.000000.to.000008.000000
+ echo h8s.value $value
+ r=0
+ for x in histogram.000008.000000.to.000016.000000 \
+ histogram.000016.000000.to.000032.000000 \
+ histogram.000032.000000.to.000064.000000 \
+ histogram.000064.000000.to.000128.000000 \
+ histogram.000128.000000.to.000256.000000 \
+ histogram.000256.000000.to.000512.000000 \
+ histogram.000512.000000.to.001024.000000 \
+ histogram.001024.000000.to.002048.000000 \
+ histogram.002048.000000.to.004096.000000 \
+ histogram.004096.000000.to.008192.000000 \
+ histogram.008192.000000.to.016384.000000 \
+ histogram.016384.000000.to.032768.000000 \
+ histogram.032768.000000.to.065536.000000 \
+ histogram.065536.000000.to.131072.000000 \
+ histogram.131072.000000.to.262144.000000 \
+ histogram.262144.000000.to.524288.000000; do
+ get_value $x
+ r=`expr $r + $value`
+ done
+ echo h16s.value $r
+ ;;
+esac
diff --git a/contrib/unbound/contrib/unbound_smf22.tar.gz b/contrib/unbound/contrib/unbound_smf22.tar.gz
new file mode 100644
index 0000000..e4c51c3
--- /dev/null
+++ b/contrib/unbound/contrib/unbound_smf22.tar.gz
Binary files differ
diff --git a/contrib/unbound/contrib/update-anchor.sh b/contrib/unbound/contrib/update-anchor.sh
new file mode 100755
index 0000000..95032a0
--- /dev/null
+++ b/contrib/unbound/contrib/update-anchor.sh
@@ -0,0 +1,158 @@
+#!/bin/sh
+# update-anchor.sh, update a trust anchor.
+# Copyright 2008, W.C.A. Wijngaards
+# This file is BSD licensed, see doc/LICENSE.
+
+# which validating lookup to use.
+ubhost=unbound-host
+
+usage ( )
+{
+ echo "usage: update-anchor [-r hs] [-b] <zone name> <trust anchor file>"
+ echo " performs an update of trust anchor file"
+ echo " the trust anchor file is overwritten with the latest keys"
+ echo " the trust anchor file should contain only keys for one zone"
+ echo " -b causes keyfile to be made in bind format."
+ echo " without -b the file is made in unbound format."
+ echo " "
+ echo "alternate:"
+ echo " update-anchor [-r hints] [-b] -d directory"
+ echo " update all <zone>.anchor files in the directory."
+ echo " "
+ echo " name the files br.anchor se.anchor ..., and include them in"
+ echo " the validating resolver config file."
+ echo " put keys for the root in a file with the name root.anchor."
+ echo ""
+ echo "-r root.hints use different root hints. Strict option order."
+ echo ""
+ echo "Exit code 0 means anchors updated, 1 no changes, others are errors."
+ exit 2
+}
+
+if test $# -eq 0; then
+ usage
+fi
+bindformat="no"
+filearg='-f'
+roothints=""
+if test X"$1" = "X-r"; then
+ shift
+ roothints="$1"
+ shift
+fi
+if test X"$1" = "X-b"; then
+ shift
+ bindformat="yes"
+ filearg='-F'
+fi
+if test $# -ne 2; then
+ echo "arguments wrong."
+ usage
+fi
+
+do_update ( ) {
+ # arguments: <zonename> <keyfile>
+ zonename="$1"
+ keyfile="$2"
+ tmpfile="/tmp/update-anchor.$$"
+ tmp2=$tmpfile.2
+ tmp3=$tmpfile.3
+ rh=""
+ if test -n "$roothints"; then
+ echo "server: root-hints: '$roothints'" > $tmp3
+ rh="-C $tmp3"
+ fi
+ $ubhost -v $rh $filearg "$keyfile" -t DNSKEY "$zonename" >$tmpfile
+ if test $? -ne 0; then
+ rm -f $tmpfile
+ echo "Error: Could not update zone $zonename anchor file $keyfile"
+ echo "Cause: $ubhost lookup failed"
+ echo " (Is the domain decommissioned? Is connectivity lost?)"
+ return 2
+ fi
+
+ # has the lookup been DNSSEC validated?
+ if grep '(secure)$' $tmpfile >/dev/null 2>&1; then
+ :
+ else
+ rm -f $tmpfile
+ echo "Error: Could not update zone $zonename anchor file $keyfile"
+ echo "Cause: result of lookup was not secure"
+ echo " (keys too far out of date? domain changed ownership? need root hints?)"
+ return 3
+ fi
+
+ if test $bindformat = "yes"; then
+ # are there any KSK keys on board?
+ echo 'trusted-keys {' > "$tmp2"
+ if grep ' has DNSKEY record 257' $tmpfile >/dev/null 2>&1; then
+ # store KSK keys in anchor file
+ grep '(secure)$' $tmpfile | \
+ grep ' has DNSKEY record 257' | \
+ sed -e 's/ (secure)$/";/' | \
+ sed -e 's/ has DNSKEY record \([0-9]*\) \([0-9]*\) \([0-9]*\) /. \1 \2 \3 "/' | \
+ sed -e 's/^\.\././' | sort >> "$tmp2"
+ else
+ # store all keys in the anchor file
+ grep '(secure)$' $tmpfile | \
+ sed -e 's/ (secure)$/";/' | \
+ sed -e 's/ has DNSKEY record \([0-9]*\) \([0-9]*\) \([0-9]*\) /. \1 \2 \3 "/' | \
+ sed -e 's/^\.\././' | sort >> "$tmp2"
+ fi
+ echo '};' >> "$tmp2"
+ else #not bindformat
+ # are there any KSK keys on board?
+ if grep ' has DNSKEY record 257' $tmpfile >/dev/null 2>&1; then
+ # store KSK keys in anchor file
+ grep '(secure)$' $tmpfile | \
+ grep ' has DNSKEY record 257' | \
+ sed -e 's/ (secure)$//' | \
+ sed -e 's/ has DNSKEY record /. IN DNSKEY /' | \
+ sed -e 's/^\.\././' | sort > "$tmp2"
+ else
+ # store all keys in the anchor file
+ grep '(secure)$' $tmpfile | \
+ sed -e 's/ (secure)$//' | \
+ sed -e 's/ has DNSKEY record /. IN DNSKEY /' | \
+ sed -e 's/^\.\././' | sort > "$tmp2"
+ fi
+ fi # endif-bindformat
+
+ # copy over if changed
+ diff $tmp2 $keyfile >/dev/null 2>&1
+ if test $? -eq 1; then # 0 means no change, 2 means trouble.
+ cat $tmp2 > $keyfile
+ no_updated=0
+ echo "$zonename key file $keyfile updated."
+ else
+ echo "$zonename key file $keyfile unchanged."
+ fi
+
+ rm -f $tmpfile $tmp2 $tmp3
+}
+
+no_updated=1
+if test X"$1" = "X-d"; then
+ tdir="$2"
+ echo "start updating in $2"
+ for x in $tdir/*.anchor; do
+ if test `basename "$x"` = "root.anchor"; then
+ zname="."
+ else
+ zname=`basename "$x" .anchor`
+ fi
+ do_update "$zname" "$x"
+ done
+ echo "done updating in $2"
+else
+ # regular invocation
+ if test X"$1" = "X."; then
+ zname="$1"
+ else
+ # strip trailing dot from zone name
+ zname="`echo $1 | sed -e 's/\.$//'`"
+ fi
+ kfile="$2"
+ do_update $zname $kfile
+fi
+exit $no_updated
diff --git a/contrib/unbound/contrib/validation-reporter.sh b/contrib/unbound/contrib/validation-reporter.sh
new file mode 100755
index 0000000..7c1a421
--- /dev/null
+++ b/contrib/unbound/contrib/validation-reporter.sh
@@ -0,0 +1,117 @@
+#!/bin/sh
+# validation reporter - reports validation failures to a collection server.
+# Copyright NLnet Labs, 2010
+# BSD license.
+
+
+###
+# Here is the configuration for the validation reporter
+# it greps the failure lines out of the log and sends them to a server.
+
+# The pidfile for the reporter daemon.
+pidfile="/var/run/validation-reporter.pid"
+
+# The logfile to watch for logged validation failures.
+logfile="/var/log/unbound.log"
+
+# how to notify the upstream
+# nc is netcat, it sends tcp to given host port. It makes a tcp connection
+# and writes one log-line to it (grepped from the logfile).
+# the notify command can be: "nc the.server.name.org 1234"
+# the listening daemon could be: nc -lk 127.0.0.1 1234 >> outputfile &
+notify_cmd="nc localhost 1234"
+
+
+###
+# Below this line is the code for the validation reporter,
+# first the daemon itself, then the controller for the daemon.
+reporter_daemon() {
+ trap "rm -f \"$pidfile\"" EXIT
+ tail -F $logfile | grep --line-buffered "unbound.*info: validation failure" | \
+ while read x; do
+ echo "$x" | $notify_cmd
+ done
+}
+
+
+###
+# controller for daemon.
+start_daemon() {
+ echo "starting reporter"
+ nohup $0 rundaemon </dev/null >/dev/null 2>&1 &
+ echo $! > "$pidfile"
+}
+
+kill_daemon() {
+ echo "stopping reporter"
+ if test -s "$pidfile"; then
+ kill `cat "$pidfile"`
+ # check it is really dead
+ if kill -0 `cat "$pidfile"` >/dev/null 2>&1; then
+ sleep 1
+ while kill -0 `cat "$pidfile"` >/dev/null 2>&1; do
+ kill `cat "$pidfile"` >/dev/null 2>&1
+ echo "waiting for reporter to stop"
+ sleep 1
+ done
+ fi
+ fi
+}
+
+get_status_daemon() {
+ if test -s "$pidfile"; then
+ if kill -0 `cat "$pidfile"`; then
+ return 0;
+ fi
+ fi
+ return 1;
+}
+
+restart_daemon() {
+ kill_daemon
+ start_daemon
+}
+
+condrestart_daemon() {
+ if get_status_daemon; then
+ echo "reporter ("`cat "$pidfile"`") is running"
+ exit 0
+ fi
+ start_daemon
+ exit 0
+}
+
+status_daemon() {
+ if get_status_daemon; then
+ echo "reporter ("`cat "$pidfile"`") is running"
+ exit 0
+ fi
+ echo "reporter is not running"
+ exit 1
+}
+
+case "$1" in
+ rundaemon)
+ reporter_daemon
+ ;;
+ start)
+ start_daemon
+ ;;
+ stop)
+ kill_daemon
+ ;;
+ restart)
+ restart_daemon
+ ;;
+ condrestart)
+ condrestart_daemon
+ ;;
+ status)
+ status_daemon
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart|condrestart|status}"
+ exit 2
+ ;;
+esac
+exit $?
diff --git a/contrib/unbound/contrib/warmup.cmd b/contrib/unbound/contrib/warmup.cmd
new file mode 100644
index 0000000..b3895a8
--- /dev/null
+++ b/contrib/unbound/contrib/warmup.cmd
@@ -0,0 +1,153 @@
+@echo off
+
+rem --------------------------------------------------------------
+rem -- Warm up DNS cache script by your own MRU domains or from
+rem -- file when it specified as script argument.
+rem --
+rem -- Version 1.1
+rem -- By Yuri Voinov (c) 2014
+rem --------------------------------------------------------------
+
+rem DNS host address
+set address="127.0.0.1"
+
+rem Check dig installed
+for /f "delims=" %%a in ('where dig') do @set dig=%%a
+if /I "%dig%"=="" echo Dig not found. If installed, add path to PATH environment variable. & exit 1
+echo Dig found: %dig%
+
+set arg=%1%
+
+if defined %arg% (goto builtin) else (goto from_file)
+
+:builtin
+echo Warming up cache by MRU domains...
+for %%a in (
+2gis.ru
+admir.kz
+adobe.com
+agent.mail.ru
+aimp.ru
+akamai.com
+akamai.net
+almaty.tele2.kz
+aol.com
+apple.com
+arin.com
+artlebedev.ru
+auto.mail.ru
+beeline.kz
+bing.com
+blogspot.com
+comodo.com
+dnscrypt.org
+drive.google.com
+drive.mail.ru
+facebook.com
+farmanager.com
+fb.com
+firefox.com
+forum.farmanager.com
+gazeta.ru
+getsharex.com
+gismeteo.ru
+google.com
+google.kz
+google.ru
+googlevideo.com
+goto.kz
+iana.org
+icq.com
+imap.mail.ru
+instagram.com
+intel.com
+irr.kz
+java.com
+kaspersky.com
+kaspersky.ru
+kcell.kz
+krisha.kz
+lady.mail.ru
+lenta.ru
+libreoffice.org
+linkedin.com
+livejournal.com
+mail.google.com
+mail.ru
+microsoft.com
+mozilla.org
+mra.mail.ru
+munin-monitoring.org
+my.mail.ru
+news.bbcimg.co.uk
+news.mail.ru
+newsimg.bbc.net.uk
+nvidia.com
+odnoklassniki.ru
+ok.ru
+opencsw.org
+opendns.com
+opendns.org
+opennet.ru
+opera.com
+oracle.com
+peerbet.ru
+piriform.com
+plugring.farmanager.com
+privoxy.org
+qip.ru
+raidcall.com
+rambler.ru
+reddit.com
+ru.wikipedia.org
+shallalist.de
+skype.com
+snob.ru
+squid-cache.org
+squidclamav.darold.net
+squidguard.org
+ssl.comodo.com
+ssl.verisign.com
+symantec.com
+symantecliveupdate.com
+tele2.kz
+tengrinews.kz
+thunderbird.com
+torproject.org
+torstatus.blutmagie.de
+translate.google.com
+unbound.net
+verisign.com
+vk.com
+vk.me
+vk.ru
+vkontakte.com
+vkontakte.ru
+vlc.org
+watsapp.net
+weather.mail.ru
+windowsupdate.com
+www.baidu.com
+www.bbc.co.uk
+www.internic.net
+www.opennet.ru
+www.topgear.com
+ya.ru
+yahoo.com
+yandex.com
+yandex.ru
+youtube.com
+ytimg.com
+) do "%dig%" %%a @%address% 1>nul 2>nul
+goto end
+
+:from_file
+echo Warming up cache from %1% file...
+%dig% -f %arg% @%address% 1>nul 2>nul
+
+:end
+echo Saving cache...
+if exist unbound_cache.cmd unbound_cache.cmd -s
+echo Done.
+
+exit 0 \ No newline at end of file
diff --git a/contrib/unbound/contrib/warmup.sh b/contrib/unbound/contrib/warmup.sh
new file mode 100755
index 0000000..b4d9135
--- /dev/null
+++ b/contrib/unbound/contrib/warmup.sh
@@ -0,0 +1,150 @@
+#!/bin/sh
+
+# --------------------------------------------------------------
+# -- Warm up DNS cache script by your own MRU domains or from
+# -- file when it specified as script argument.
+# --
+# -- Version 1.1
+# -- By Yuri Voinov (c) 2014
+# --------------------------------------------------------------
+
+# Default DNS host address
+address="127.0.0.1"
+
+cat=`which cat`
+dig=`which dig`
+
+if [ -z "$1" ]; then
+echo "Warming up cache by MRU domains..."
+$dig -f - @$address >/dev/null 2>&1 <<EOT
+2gis.ru
+admir.kz
+adobe.com
+agent.mail.ru
+aimp.ru
+akamai.com
+akamai.net
+almaty.tele2.kz
+aol.com
+apple.com
+arin.com
+artlebedev.ru
+auto.mail.ru
+beeline.kz
+bing.com
+blogspot.com
+clamav.net
+comodo.com
+dnscrypt.org
+drive.google.com
+drive.mail.ru
+facebook.com
+farmanager.com
+fb.com
+firefox.com
+forum.farmanager.com
+gazeta.ru
+getsharex.com
+gismeteo.ru
+google.com
+google.kz
+google.ru
+googlevideo.com
+goto.kz
+iana.org
+icq.com
+imap.mail.ru
+instagram.com
+instagram.com
+intel.com
+irr.kz
+java.com
+kaspersky.com
+kaspersky.ru
+kcell.kz
+krisha.kz
+lady.mail.ru
+lenta.ru
+libreoffice.org
+linkedin.com
+livejournal.com
+mail.google.com
+mail.ru
+microsoft.com
+mozilla.org
+mra.mail.ru
+munin-monitoring.org
+my.mail.ru
+news.bbcimg.co.uk
+news.mail.ru
+newsimg.bbc.net.uk
+nvidia.com
+odnoklassniki.ru
+ok.ru
+opencsw.org
+opendns.com
+opendns.org
+opennet.ru
+opera.com
+oracle.com
+peerbet.ru
+piriform.com
+plugring.farmanager.com
+privoxy.org
+qip.ru
+raidcall.com
+rambler.ru
+reddit.com
+ru.wikipedia.org
+shallalist.de
+skype.com
+snob.ru
+squid-cache.org
+squidclamav.darold.net
+squidguard.org
+ssl.comodo.com
+ssl.verisign.com
+symantec.com
+symantecliveupdate.com
+tele2.kz
+tengrinews.kz
+thunderbird.com
+torproject.org
+torstatus.blutmagie.de
+translate.google.com
+unbound.net
+verisign.com
+vk.com
+vk.me
+vk.ru
+vkontakte.com
+vkontakte.ru
+vlc.org
+watsapp.net
+weather.mail.ru
+windowsupdate.com
+www.baidu.com
+www.bbc.co.uk
+www.internic.net
+www.opennet.ru
+www.topgear.com
+ya.ru
+yahoo.com
+yandex.com
+yandex.ru
+youtube.com
+ytimg.com
+EOT
+else
+ echo "Warming up cache from $1 file..."
+ $cat $1 | $dig -f - @$address >/dev/null 2>&1
+fi
+
+echo "Done."
+
+echo "Saving cache..."
+script=`which unbound_cache.sh`
+[ -f "$script" ] && $script -s
+echo "Done."
+
+exit 0
diff --git a/contrib/unbound/daemon/acl_list.c b/contrib/unbound/daemon/acl_list.c
index 84d099c..d09b46e 100644
--- a/contrib/unbound/daemon/acl_list.c
+++ b/contrib/unbound/daemon/acl_list.c
@@ -45,6 +45,8 @@
#include "util/log.h"
#include "util/config_file.h"
#include "util/net_help.h"
+#include "services/localzone.h"
+#include "sldns/str2wire.h"
struct acl_list*
acl_list_create(void)
@@ -71,21 +73,21 @@ acl_list_delete(struct acl_list* acl)
}
/** insert new address into acl_list structure */
-static int
+static struct acl_addr*
acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
socklen_t addrlen, int net, enum acl_access control,
int complain_duplicates)
{
- struct acl_addr* node = regional_alloc(acl->region,
+ struct acl_addr* node = regional_alloc_zero(acl->region,
sizeof(struct acl_addr));
if(!node)
- return 0;
+ return NULL;
node->control = control;
if(!addr_tree_insert(&acl->tree, &node->node, addr, addrlen, net)) {
if(complain_duplicates)
verbose(VERB_QUERY, "duplicate acl address ignored.");
}
- return 1;
+ return node;
}
/** apply acl_list string */
@@ -125,6 +127,156 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
return 1;
}
+/** find or create node (NULL on parse or error) */
+static struct acl_addr*
+acl_find_or_create(struct acl_list* acl, const char* str)
+{
+ struct acl_addr* node;
+ struct sockaddr_storage addr;
+ int net;
+ socklen_t addrlen;
+ if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
+ log_err("cannot parse netblock: %s", str);
+ return NULL;
+ }
+ /* find or create node */
+ if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, &addr,
+ addrlen, net))) {
+ /* create node, type 'allow' since otherwise tags are
+ * pointless, can override with specific access-control: cfg */
+ if(!(node=(struct acl_addr*)acl_list_insert(acl, &addr,
+ addrlen, net, acl_allow, 1))) {
+ log_err("out of memory");
+ return NULL;
+ }
+ }
+ return node;
+}
+
+/** apply acl_tag string */
+static int
+acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap,
+ size_t bitmaplen)
+{
+ struct acl_addr* node;
+ if(!(node=acl_find_or_create(acl, str)))
+ return 0;
+ node->taglen = bitmaplen;
+ node->taglist = regional_alloc_init(acl->region, bitmap, bitmaplen);
+ if(!node->taglist) {
+ log_err("out of memory");
+ return 0;
+ }
+ return 1;
+}
+
+/** apply acl_tag_action string */
+static int
+acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg,
+ const char* str, const char* tag, const char* action)
+{
+ struct acl_addr* node;
+ int tagid;
+ enum localzone_type t;
+ if(!(node=acl_find_or_create(acl, str)))
+ return 0;
+ /* allocate array if not yet */
+ if(!node->tag_actions) {
+ node->tag_actions = (uint8_t*)regional_alloc_zero(acl->region,
+ sizeof(*node->tag_actions)*cfg->num_tags);
+ if(!node->tag_actions) {
+ log_err("out of memory");
+ return 0;
+ }
+ node->tag_actions_size = (size_t)cfg->num_tags;
+ }
+ /* parse tag */
+ if((tagid=find_tag_id(cfg, tag)) == -1) {
+ log_err("cannot parse tag (define-tag it): %s %s", str, tag);
+ return 0;
+ }
+ if((size_t)tagid >= node->tag_actions_size) {
+ log_err("tagid too large for array %s %s", str, tag);
+ return 0;
+ }
+ if(!local_zone_str2type(action, &t)) {
+ log_err("cannot parse access control action type: %s %s %s",
+ str, tag, action);
+ return 0;
+ }
+ node->tag_actions[tagid] = (uint8_t)t;
+ return 1;
+}
+
+/** check wire data parse */
+static int
+check_data(const char* data)
+{
+ char buf[65536];
+ uint8_t rr[LDNS_RR_BUF_SIZE];
+ size_t len = sizeof(rr);
+ int res;
+ snprintf(buf, sizeof(buf), "%s %s", "example.com.", data);
+ res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, NULL, 0,
+ NULL, 0);
+ if(res == 0)
+ return 1;
+ log_err("rr data [char %d] parse error %s",
+ (int)LDNS_WIREPARSE_OFFSET(res)-13,
+ sldns_get_errorstr_parse(res));
+ return 0;
+}
+
+/** apply acl_tag_data string */
+static int
+acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg,
+ const char* str, const char* tag, const char* data)
+{
+ struct acl_addr* node;
+ int tagid;
+ char* dupdata;
+ if(!(node=acl_find_or_create(acl, str)))
+ return 0;
+ /* allocate array if not yet */
+ if(!node->tag_datas) {
+ node->tag_datas = (struct config_strlist**)regional_alloc_zero(
+ acl->region, sizeof(*node->tag_datas)*cfg->num_tags);
+ if(!node->tag_datas) {
+ log_err("out of memory");
+ return 0;
+ }
+ node->tag_datas_size = (size_t)cfg->num_tags;
+ }
+ /* parse tag */
+ if((tagid=find_tag_id(cfg, tag)) == -1) {
+ log_err("cannot parse tag (define-tag it): %s %s", str, tag);
+ return 0;
+ }
+ if((size_t)tagid >= node->tag_datas_size) {
+ log_err("tagid too large for array %s %s", str, tag);
+ return 0;
+ }
+
+ /* check data? */
+ if(!check_data(data)) {
+ log_err("cannot parse access-control-tag data: %s %s '%s'",
+ str, tag, data);
+ return 0;
+ }
+
+ dupdata = regional_strdup(acl->region, data);
+ if(!dupdata) {
+ log_err("out of memory");
+ return 0;
+ }
+ if(!cfg_region_strlist_insert(acl->region,
+ &(node->tag_datas[tagid]), dupdata)) {
+ log_err("out of memory");
+ return 0;
+ }
+ return 1;
+}
+
/** read acl_list config */
static int
read_acl_list(struct acl_list* acl, struct config_file* cfg)
@@ -138,6 +290,77 @@ read_acl_list(struct acl_list* acl, struct config_file* cfg)
return 1;
}
+/** read acl tags config */
+static int
+read_acl_tags(struct acl_list* acl, struct config_file* cfg)
+{
+ struct config_strbytelist* np, *p = cfg->acl_tags;
+ cfg->acl_tags = NULL;
+ while(p) {
+ log_assert(p->str && p->str2);
+ if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len)) {
+ config_del_strbytelist(p);
+ return 0;
+ }
+ /* free the items as we go to free up memory */
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p);
+ p = np;
+ }
+ return 1;
+}
+
+/** read acl tag actions config */
+static int
+read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg)
+{
+ struct config_str3list* p, *np;
+ p = cfg->acl_tag_actions;
+ cfg->acl_tag_actions = NULL;
+ while(p) {
+ log_assert(p->str && p->str2 && p->str3);
+ if(!acl_list_tag_action_cfg(acl, cfg, p->str, p->str2,
+ p->str3)) {
+ config_deltrplstrlist(p);
+ return 0;
+ }
+ /* free the items as we go to free up memory */
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p->str3);
+ free(p);
+ p = np;
+ }
+ return 1;
+}
+
+/** read acl tag datas config */
+static int
+read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg)
+{
+ struct config_str3list* p, *np;
+ p = cfg->acl_tag_datas;
+ cfg->acl_tag_datas = NULL;
+ while(p) {
+ log_assert(p->str && p->str2 && p->str3);
+ if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3)) {
+ config_deltrplstrlist(p);
+ return 0;
+ }
+ /* free the items as we go to free up memory */
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p->str3);
+ free(p);
+ p = np;
+ }
+ return 1;
+}
+
int
acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
{
@@ -145,6 +368,12 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
addr_tree_init(&acl->tree);
if(!read_acl_list(acl, cfg))
return 0;
+ if(!read_acl_tags(acl, cfg))
+ return 0;
+ if(!read_acl_tag_actions(acl, cfg))
+ return 0;
+ if(!read_acl_tag_datas(acl, cfg))
+ return 0;
/* insert defaults, with '0' to ignore them if they are duplicates */
if(!acl_list_str_cfg(acl, "0.0.0.0/0", "refuse", 0))
return 0;
@@ -163,13 +392,18 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
}
enum acl_access
-acl_list_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
+acl_get_control(struct acl_addr* acl)
+{
+ if(acl) return acl->control;
+ return acl_deny;
+}
+
+struct acl_addr*
+acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
socklen_t addrlen)
{
- struct acl_addr* r = (struct acl_addr*)addr_tree_lookup(&acl->tree,
+ return (struct acl_addr*)addr_tree_lookup(&acl->tree,
addr, addrlen);
- if(r) return r->control;
- return acl_deny;
}
size_t
diff --git a/contrib/unbound/daemon/acl_list.h b/contrib/unbound/daemon/acl_list.h
index 2323697..fc0e9ca 100644
--- a/contrib/unbound/daemon/acl_list.h
+++ b/contrib/unbound/daemon/acl_list.h
@@ -87,6 +87,19 @@ struct acl_addr {
struct addr_tree_node node;
/** access control on this netblock */
enum acl_access control;
+ /** tag bitlist */
+ uint8_t* taglist;
+ /** length of the taglist (in bytes) */
+ size_t taglen;
+ /** array per tagnumber of localzonetype(in one byte). NULL if none. */
+ uint8_t* tag_actions;
+ /** size of the tag_actions_array */
+ size_t tag_actions_size;
+ /** array per tagnumber, with per tag a list of rdata strings.
+ * NULL if none. strings are like 'A 127.0.0.1' 'AAAA ::1' */
+ struct config_strlist** tag_datas;
+ /** size of the tag_datas array */
+ size_t tag_datas_size;
};
/**
@@ -110,14 +123,22 @@ void acl_list_delete(struct acl_list* acl);
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg);
/**
- * Lookup address to see its access control status.
+ * Lookup access control status for acl structure.
+ * @param acl: structure for acl storage.
+ * @return: what to do with message from this address.
+ */
+enum acl_access acl_get_control(struct acl_addr* acl);
+
+/**
+ * Lookup address to see its acl structure
* @param acl: structure for address storage.
* @param addr: address to check
* @param addrlen: length of addr.
- * @return: what to do with message from this address.
+ * @return: acl structure from this address.
*/
-enum acl_access acl_list_lookup(struct acl_list* acl,
- struct sockaddr_storage* addr, socklen_t addrlen);
+struct acl_addr*
+acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
+ socklen_t addrlen);
/**
* Get memory used by acl structure.
diff --git a/contrib/unbound/daemon/daemon.c b/contrib/unbound/daemon/daemon.c
index e763f72..2ed9af8f 100644
--- a/contrib/unbound/daemon/daemon.c
+++ b/contrib/unbound/daemon/daemon.c
@@ -204,20 +204,29 @@ daemon_init(void)
signal_handling_record();
checklock_start();
#ifdef HAVE_SSL
+# ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
ERR_load_crypto_strings();
- ERR_load_SSL_strings();
-# ifdef HAVE_OPENSSL_CONFIG
- OPENSSL_config("unbound");
# endif
+ ERR_load_SSL_strings();
# ifdef USE_GOST
(void)sldns_key_EVP_load_gost_id();
# endif
+# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
OpenSSL_add_all_algorithms();
+# else
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
+ | OPENSSL_INIT_ADD_ALL_DIGESTS
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+# endif
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
/* grab the COMP method ptr because openssl leaks it */
comp_meth = (void*)SSL_COMP_get_compression_methods();
# endif
+# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
+# else
+ (void)OPENSSL_init_ssl(0, NULL);
+# endif
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
if(!ub_openssl_lock_init())
fatal_exit("could not init openssl locks");
@@ -407,6 +416,8 @@ daemon_create_workers(struct daemon* daemon)
}
daemon->workers = (struct worker**)calloc((size_t)daemon->num,
sizeof(struct worker*));
+ if(!daemon->workers)
+ fatal_exit("out of memory during daemon init");
if(daemon->cfg->dnstap) {
#ifdef USE_DNSTAP
daemon->dtenv = dt_create(daemon->cfg->dnstap_socket_path,
@@ -589,13 +600,12 @@ daemon_cleanup(struct daemon* daemon)
log_thread_set(NULL);
/* clean up caches because
* a) RRset IDs will be recycled after a reload, causing collisions
- * b) validation config can change, thus rrset, msg, keycache clear
- * The infra cache is kept, the timing and edns info is still valid */
+ * b) validation config can change, thus rrset, msg, keycache clear */
slabhash_clear(&daemon->env->rrset_cache->table);
slabhash_clear(daemon->env->msg_cache);
local_zones_delete(daemon->local_zones);
daemon->local_zones = NULL;
- /* key cache is cleared by module desetup during next daemon_init() */
+ /* key cache is cleared by module desetup during next daemon_fork() */
daemon_remote_clear(daemon->rc);
for(i=0; i<daemon->num; i++)
worker_delete(daemon->workers[i]);
@@ -647,18 +657,27 @@ 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
+# ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */
- ERR_remove_state(0);
+# endif
+# ifdef HAVE_ERR_FREE_STRINGS
ERR_free_strings();
+# endif
+# if OPENSSL_VERSION_NUMBER < 0x10100000
RAND_cleanup();
+# endif
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
ub_openssl_lock_delete();
# endif
diff --git a/contrib/unbound/daemon/daemon.h b/contrib/unbound/daemon/daemon.h
index 86ddab1..48c0b4f 100644
--- a/contrib/unbound/daemon/daemon.h
+++ b/contrib/unbound/daemon/daemon.h
@@ -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;
diff --git a/contrib/unbound/daemon/remote.c b/contrib/unbound/daemon/remote.c
index c2112de..3fe6650 100644
--- a/contrib/unbound/daemon/remote.c
+++ b/contrib/unbound/daemon/remote.c
@@ -46,9 +46,12 @@
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
#endif
-#ifndef HEADER_DH_H
+#ifdef HAVE_OPENSSL_DH_H
#include <openssl/dh.h>
#endif
+#ifdef HAVE_OPENSSL_BN_H
+#include <openssl/bn.h>
+#endif
#include <ctype.h>
#include "daemon/remote.h"
@@ -140,47 +143,64 @@ 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()
-{
- 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 DH *get_dh2048(void)
+{
+ 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);
- if ((dh->p == NULL) || (dh->g == NULL))
- { DH_free(dh); return(NULL); }
- dh->length = 160;
- return(dh);
+ DH *dh = NULL;
+ BIGNUM *p = NULL, *g = NULL;
+
+ dh = DH_new();
+ p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
+ g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
+ if (!dh || !p || !g)
+ goto err;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
+ dh->p = p;
+ dh->g = g;
+#else
+ if (!DH_set0_pqg(dh, p, NULL, g))
+ goto err;
+#endif
+ return dh;
+err:
+ if (p)
+ BN_free(p);
+ if (g)
+ BN_free(g);
+ if (dh)
+ DH_free(dh);
+ return NULL;
}
#endif /* SPLINT */
@@ -225,14 +245,16 @@ daemon_remote_create(struct config_file* cfg)
/* No certificates are requested */
if(!SSL_CTX_set_cipher_list(rc->ctx, "aNULL")) {
log_crypto_err("Failed to set aNULL cipher list");
+ daemon_remote_delete(rc);
return NULL;
}
/* 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");
+ daemon_remote_delete(rc);
return NULL;
}
return rc;
@@ -359,8 +381,12 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
if(fd != -1) {
#ifdef HAVE_CHOWN
if (cfg->username && cfg->username[0] &&
- cfg_uid != (uid_t)-1)
- chown(ip, cfg_uid, cfg_gid);
+ cfg_uid != (uid_t)-1) {
+ if(chown(ip, cfg_uid, cfg_gid) == -1)
+ log_err("cannot chown %u.%u %s: %s",
+ (unsigned)cfg_uid, (unsigned)cfg_gid,
+ ip, strerror(errno));
+ }
chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
#else
(void)cfg;
@@ -389,7 +415,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);
}
diff --git a/contrib/unbound/daemon/remote.h b/contrib/unbound/daemon/remote.h
index b25bfb1..190286d 100644
--- a/contrib/unbound/daemon/remote.h
+++ b/contrib/unbound/daemon/remote.h
@@ -56,8 +56,8 @@ struct comm_reply;
struct comm_point;
struct daemon_remote;
-/** number of seconds timeout on incoming remote control handshake */
-#define REMOTE_CONTROL_TCP_TIMEOUT 120
+/** number of milliseconds timeout on incoming remote control handshake */
+#define REMOTE_CONTROL_TCP_TIMEOUT 120000
/**
* a busy control command connection, SSL state
diff --git a/contrib/unbound/daemon/unbound.c b/contrib/unbound/daemon/unbound.c
index a981f49..73e9fcb 100644
--- a/contrib/unbound/daemon/unbound.c
+++ b/contrib/unbound/daemon/unbound.c
@@ -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,59 +92,14 @@
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()
+static void usage(void)
{
const char** m;
const char *evnm="event", *evsys="", *evmethod="";
+ time_t t;
+ struct timeval now;
+ struct ub_event_base* base;
printf("usage: unbound [options]\n");
printf(" start unbound daemon DNS resolver.\n");
printf("-h this help\n");
@@ -173,11 +113,16 @@ 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);
+ base = ub_default_event_base(0,&t,&now);
+ ub_get_event_sys(base, &evnm, &evsys, &evmethod);
printf("linked libs: %s %s (it uses %s), %s\n",
evnm, evsys, evmethod,
#ifdef HAVE_SSL
+# ifdef SSLEAY_VERSION
SSLeay_version(SSLEAY_VERSION)
+# else
+ OpenSSL_version(OPENSSL_VERSION)
+# endif
#elif defined(HAVE_NSS)
NSS_GetVersion()
#elif defined(HAVE_NETTLE)
@@ -190,6 +135,7 @@ static void usage()
printf("\n");
printf("BSD licensed, see LICENSE in source package for details.\n");
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
+ ub_event_base_free(base);
}
#ifndef unbound_testbound
@@ -230,7 +176,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 +190,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");
@@ -602,7 +548,9 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
log_warn("unable to initgroups %s: %s",
cfg->username, strerror(errno));
# endif /* HAVE_INITGROUPS */
+# ifdef HAVE_ENDPWENT
endpwent();
+# endif
#ifdef HAVE_SETRESGID
if(setresgid(cfg_gid,cfg_gid,cfg_gid) != 0)
diff --git a/contrib/unbound/daemon/worker.c b/contrib/unbound/daemon/worker.c
index a74931f..70d07ba 100644
--- a/contrib/unbound/daemon/worker.c
+++ b/contrib/unbound/daemon/worker.c
@@ -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;
@@ -768,6 +773,8 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_REFUSED);
+ sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
+ sldns_buffer_flip(c->buffer);
return 1;
}
@@ -799,6 +806,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
struct query_info qinfo;
struct edns_data edns;
enum acl_access acl;
+ struct acl_addr* acladdr;
int rc = 0;
if(error != NETEVENT_NOERROR) {
@@ -811,8 +819,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
dt_msg_send_client_query(&worker->dtenv, &repinfo->addr, c->type,
c->buffer);
#endif
- acl = acl_list_lookup(worker->daemon->acl, &repinfo->addr,
+ acladdr = acl_addr_lookup(worker->daemon->acl, &repinfo->addr,
repinfo->addrlen);
+ acl = acl_get_control(acladdr);
if((ret=deny_refuse_all(c, acl, worker, repinfo)) != -1)
{
if(ret == 1)
@@ -865,7 +874,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 +885,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 +894,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 +930,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,10 +941,15 @@ 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,
- c->buffer, worker->scratchpad, repinfo)) {
+ c->buffer, worker->scratchpad, repinfo,
+ acladdr->taglist, acladdr->taglen, acladdr->tag_actions,
+ acladdr->tag_actions_size, acladdr->tag_datas,
+ acladdr->tag_datas_size, worker->daemon->cfg->tagname,
+ worker->daemon->cfg->num_tags)) {
regional_free_all(worker->scratchpad);
if(sldns_buffer_limit(c->buffer) == 0) {
comm_point_drop_reply(repinfo);
@@ -945,6 +963,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 +980,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 +1004,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 +1019,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 +1040,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 +1379,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 +1391,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 +1437,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))
{
diff --git a/contrib/unbound/dns64/dns64.c b/contrib/unbound/dns64/dns64.c
index 0de3f66..5fa2096 100644
--- a/contrib/unbound/dns64/dns64.c
+++ b/contrib/unbound/dns64/dns64.c
@@ -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,
@@ -871,7 +872,7 @@ static struct module_func_block dns64_block = {
* Function for returning the above function block.
*/
struct module_func_block *
-dns64_get_funcblock()
+dns64_get_funcblock(void)
{
return &dns64_block;
}
diff --git a/contrib/unbound/dnstap/dnstap.c b/contrib/unbound/dnstap/dnstap.c
index 8c9c4ca..6df2fef 100644
--- a/contrib/unbound/dnstap/dnstap.c
+++ b/contrib/unbound/dnstap/dnstap.c
@@ -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);
}
diff --git a/contrib/unbound/doc/Changelog b/contrib/unbound/doc/Changelog
index 6bcc32a..039eade 100644
--- a/contrib/unbound/doc/Changelog
+++ b/contrib/unbound/doc/Changelog
@@ -1,3 +1,367 @@
+20 September 2016: Wouter
+ - iana portlist update.
+ - Fix #835: fix --disable-dsa with nettle verify.
+ - tag for 1.5.10rc1 release.
+
+15 September 2016: Wouter
+ - Fix 883: error for duplicate local zone entry.
+ - Test for openssl init_crypto and init_ssl functions.
+
+15 September 2016: Ralph
+ - fix potential memory leak in daemon/remote.c and nullpointer
+ dereference in validator/autotrust.
+ - iana portlist update.
+
+13 September 2016: Wouter
+ - Silenced flex-generated sign-unsigned warning print with gcc
+ diagnostic pragma.
+ - Fix for new splint on FreeBSD. Fix cast for sockaddr_un.sun_len.
+
+9 September 2016: Wouter
+ - Fix #831: workaround for spurious fread_chk warning against petal.c
+
+5 September 2016: Ralph
+ - Take configured minimum TTL into consideration when reducing TTL
+ to original TTL from RRSIG.
+
+5 September 2016: Wouter
+ - Fix #829: doc of sldns_wire2str_rdata_buf() return value has an
+ off-by-one typo, from Jinmei Tatuya (Infoblox).
+ - Fix incomplete prototypes reported by Dag-Erling Smørgrav.
+ - Fix #828: missing type in access-control-tag-action redirect results
+ in NXDOMAIN.
+
+2 September 2016: Wouter
+ - Fix compile with openssl 1.1.0 with api=1.1.0.
+
+1 September 2016: Wouter
+ - RFC 7958 is now out, updated docs for unbound-anchor.
+ - Fix for compile without warnings with openssl 1.1.0.
+ - Fix #826: Fix refuse_non_local could result in a broken response.
+ - iana portlist update.
+
+29 August 2016: Wouter
+ - Fix #777: OpenSSL 1.1.0 compatibility, patch from Sebastian A.
+ Siewior.
+ - Add default root hints for IPv6 E.ROOT-SERVERS.NET, 2001:500:a8::e.
+
+25 August 2016: Ralph
+ - Clarify local-zone-override entry in unbound.conf.5
+
+25 August 2016: Wouter
+ - 64bit build option for makedist windows compile, -w64.
+
+24 August 2016: Ralph
+ - Fix #820: set sldns_str2wire_rr_buf() dual meaning len parameter
+ in each iteration in find_tag_datas().
+ - unbound.conf.5 entries for define-tag, access-control-tag,
+ access-control-tag-action, access-control-tag-data, local-zone-tag,
+ and local-zone-override.
+
+23 August 2016: Wouter
+ - Fix #804: unbound stops responding after outage. Fixes queries
+ that attempt to wait for an empty list of subqueries.
+ - Fix #804: lower num_target_queries for iterator also for failed
+ lookups.
+
+8 August 2016: Wouter
+ - Note that OPENPGPKEY type is RFC 7929.
+
+4 August 2016: Wouter
+ - Fix #807: workaround for possible some "unused" function parameters
+ in test code, from Jinmei Tatuya.
+
+3 August 2016: Wouter
+ - use sendmsg instead of sendto for TFO.
+
+28 July 2016: Wouter
+ - Fix #806: wrong comment removed.
+
+26 July 2016: Wouter
+ - nicer ratelimit-below-domain explanation.
+
+22 July 2016: Wouter
+ - Fix #801: missing error condition handling in
+ daemon_create_workers().
+ - Fix #802: workaround for function parameters that are "unused"
+ without log_assert.
+ - Fix #803: confusing (and incorrect) code comment in daemon_cleanup().
+
+20 July 2016: Wouter
+ - Fix typo in unbound.conf.
+
+18 July 2016: Wouter
+ - Fix #798: Client-side TCP fast open fails (Linux).
+
+14 July 2016: Wouter
+ - TCP Fast open patch from Sara Dickinson.
+ - Fixed unbound.doxygen for 1.8.11.
+
+7 July 2016: Wouter
+ - access-control-tag-data implemented. verbose(4) prints tag debug.
+
+5 July 2016: Wouter
+ - Fix dynamic link of anchor-update.exe on windows.
+ - Fix detect of mingw for MXE package build.
+ - Fixes for 64bit windows compile.
+ - Fix #788 for nettle 3.0: Failed to build with Nettle >= 3.0 and
+ --with-libunbound-only --with-nettle.
+
+4 July 2016: Wouter
+ - For #787: prefer-ip6 option for unbound.conf prefers to send
+ upstream queries to ipv6 servers.
+ - Fix #787: outgoing-interface netblock/64 ipv6 option to use linux
+ freebind to use 64bits of entropy for every query with random local
+ part.
+
+30 June 2016: Wouter
+ - Document always_transparent, always_refuse, always_nxdomain types.
+
+29 June 2016: Wouter
+ - Fix static compile on windows missing gdi32.
+
+28 June 2016: Wouter
+ - Create a pkg-config file for libunbound in contrib.
+
+27 June 2016: Wouter
+ - Fix #784: Build configure assumess that having getpwnam means there
+ is endpwent function available.
+ - Updated repository with newer flex and bison output.
+
+24 June 2016: Ralph
+ - Possibility to specify local-zone type for an acl/tag pair
+ - Possibility to specify (override) local-zone type for a source address
+ block
+16 June 2016: Ralph
+ - Decrease dp attempts at each QNAME minimisation iteration
+
+16 June 2016: Wouter
+ - Fix tcp timeouts in tv.usec.
+
+15 June 2016: Wouter
+ - TCP_TIMEOUT is specified in milliseconds.
+ - If more than half of tcp connections are in use, a shorter timeout
+ is used (200 msec, vs 2 minutes) to pressure tcp for new connects.
+
+14 June 2016: Ralph
+ - QNAME minimisation unit test for dropped QTYPE=A queries.
+
+14 June 2016: Wouter
+ - Fix 775: unbound-host and unbound-anchor crash on windows, ignore
+ null delete for wsaevent.
+ - Fix spelling in freebind option man page text.
+ - Fix windows link of ssl with crypt32.
+ - Fix 779: Union casting is non-portable.
+ - Fix 780: MAP_ANON not defined in HP-UX 11.31.
+ - Fix 781: prealloc() is an HP-UX system library call.
+
+13 June 2016: Ralph
+ - Use QTYPE=A for QNAME minimisation.
+ - Keep track of number of time-outs when performing QNAME minimisation.
+ Stop minimising when number of time-outs for a QNAME/QTYPE pair is
+ more than three.
+
+13 June 2016: Wouter
+ - Fix #778: unbound 1.5.9: -h segfault (null deref).
+ - Fix directory: fix for unbound-checkconf, it restores cwd.
+
+10 June 2016: Wouter
+ - And delete service.conf.shipped on uninstall.
+ - In unbound.conf directory: dir immediately changes to that directory,
+ so that include: file below that is relative to that directory.
+ With chroot, make the directory an absolute path inside chroot.
+ - keep debug symbols in windows build.
+ - do not delete service.conf on windows uninstall.
+ - document directory immediate fix and allow EXECUTABLE syntax in it
+ on windows.
+
+9 June 2016: Wouter
+ - Trunk is called 1.5.10 (with previous fixes already in there to 2
+ june).
+ - Revert fix for NetworkService account on windows due to breakage
+ it causes.
+ - Fix that windows install will not overwrite existing service.conf
+ file (and ignore gui config choices if it exists).
+
+7 June 2016: Ralph
+ - Lookup localzones by taglist from acl.
+ - Possibility to lookup local_zone, regardless the taglist.
+ - Added local_zone/taglist/acl unit test.
+
+7 June 2016: Wouter
+ - Fix #773: Non-standard Python location build failure with pyunbound.
+ - Improve threadsafety for openssl 0.9.8 ecdsa dnssec signatures.
+
+6 June 2016: Wouter
+ - Better help text from -h (from Ray Griffith).
+ - access-control-tag config directive.
+ - local-zone-override config directive.
+ - access-control-tag-action and access-control-tag-data config
+ directives.
+ - free acl-tags, acltag-action and acltag-data config lists during
+ initialisation to free up memory for more entries.
+
+3 June 2016: Wouter
+ - Fix to not ignore return value of chown() in daemon startup.
+
+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.
+ - tag for release 1.5.9rc1.
+ And this also became release 1.5.9.
+ - Fix (for 1.5.10): Fix unbound-anchor.exe file location defaults to
+ Program Files with (x86) appended.
+ - re-documented localzone tags in example.conf.
+
+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.
diff --git a/contrib/unbound/doc/README b/contrib/unbound/doc/README
index c87c62e..66e2f34 100644
--- a/contrib/unbound/doc/README
+++ b/contrib/unbound/doc/README
@@ -1,4 +1,4 @@
-README for Unbound 1.5.8
+README for Unbound 1.5.10
Copyright 2007 NLnet Labs
http://unbound.net
diff --git a/contrib/unbound/doc/example.conf b/contrib/unbound/doc/example.conf
index 3b2267d..80c0f3e 100644
--- a/contrib/unbound/doc/example.conf
+++ b/contrib/unbound/doc/example.conf
@@ -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.10.
#
# this is a comment.
@@ -52,6 +52,15 @@ server:
# outgoing-interface: 192.0.2.153
# outgoing-interface: 2001:DB8::5
# outgoing-interface: 2001:DB8::6
+
+ # Specify a netblock to use remainder 64 bits as random bits for
+ # upstream queries. Uses freebind option (Linux).
+ # outgoing-interface: 2001:DB8::/64
+ # Also (Linux:) ip -6 addr add 2001:db8::/64 dev lo
+ # And: ip -6 route add local 2001:db8::/64 dev lo
+ # And set prefer-ip6: yes to use the ip6 randomness from a netblock.
+ # Set this to yes to prefer ipv6 upstream servers over ipv4.
+ # prefer-ip6: no
# number of ports to allocate per thread, determines the size of the
# port range that can be open simultaneously. About double the
@@ -93,6 +102,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
@@ -157,6 +171,10 @@ server:
# the maximum number of hosts that are cached (roundtrip, EDNS, lame).
# infra-cache-numhosts: 10000
+
+ # define a number of tags here, use with local-zone, access-control.
+ # repeat the define-tag statement to add additional tags.
+ # define-tag: "tag1 tag2 tag3"
# Enable IPv4, "yes" or "no".
# do-ip4: yes
@@ -198,6 +216,20 @@ server:
# access-control: ::1 allow
# access-control: ::ffff:127.0.0.1 allow
+ # tag access-control with list of tags (in "" with spaces between)
+ # Clients using this access control element use localzones that
+ # are tagged with one of these tags.
+ # access-control-tag: 192.0.2.0/24 "tag2 tag3"
+
+ # set action for particular tag for given access control element
+ # if you have multiple tag values, the tag used to lookup the action
+ # is the first tag match between access-control-tag and local-zone-tag
+ # where "first" comes from the order of the define-tag values.
+ # access-control-tag-action: 192.0.2.0/24 tag3 refuse
+
+ # set redirect data for particular tag for access control element
+ # access-control-tag-data: 192.0.2.0/24 tag2 "A 127.0.0.1"
+
# if given, a chroot(2) is done to the given directory.
# i.e. you can chroot to the working directory, for example,
# for extra security, but make sure all files are in that directory.
@@ -231,6 +263,8 @@ server:
# the working directory. The relative files in this config are
# relative to this directory. If you give "" the working directory
# is not changed.
+ # If you give a server: directory: dir before include: file statements
+ # then those includes can be relative to the working directory.
# directory: "/var/unbound"
# the log file, "" means log to stderr.
@@ -317,6 +351,7 @@ server:
# Domains (and domains in them) without support for dns-0x20 and
# the fallback fails because they keep sending different answers.
# caps-whitelist: "licdn.com"
+ # caps-whitelist: "senderbase.org"
# Enforce privacy of these addresses. Strips them away from answers.
# It may cause DNSSEC validation to additionally mark it as bogus.
@@ -364,6 +399,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 +497,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.
@@ -541,6 +580,8 @@ server:
# o typetransparent resolves normally for other types and other names
# o inform resolves normally, but logs client IP address
# o inform_deny drops queries and logs client IP address
+ # o always_transparent, always_refuse, always_nxdomain, resolve in
+ # that way but ignore local data for that name.
#
# defaults are localhost address, reverse for 127.0.0.1 and ::1
# and nxdomain for AS112 zones. If you configure one of these zones
@@ -567,6 +608,12 @@ server:
# you need to do the reverse notation yourself.
# local-data-ptr: "192.0.2.3 www.example.com"
+ # tag a localzone with a list of tag names (in "" with spaces between)
+ # local-zone-tag: "example.com" "tag2 tag3"
+
+ # add a netblock specific override to a localzone, with zone type
+ # local-zone-override: "example.com" 192.0.2.0/24 refuse
+
# service clients over SSL (on the TCP sockets), with plain DNS inside
# the SSL stream. Give the certificate to use and private key.
# default is "" (disabled). requires restart to take effect.
@@ -600,7 +647,7 @@ server:
# ratelimit-for-domain: example.com 1000
# override the ratelimits for all domains below a domain name
# can give this multiple times, the name closest to the zone is used.
- # ratelimit-below-domain: example 1000
+ # ratelimit-below-domain: com 1000
# Python config section. To enable:
# o use --with-pythonmodule to configure before compiling.
diff --git a/contrib/unbound/doc/example.conf.in b/contrib/unbound/doc/example.conf.in
index b5cc1c9..c520c88 100644
--- a/contrib/unbound/doc/example.conf.in
+++ b/contrib/unbound/doc/example.conf.in
@@ -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.10.
#
# this is a comment.
@@ -52,6 +52,15 @@ server:
# outgoing-interface: 192.0.2.153
# outgoing-interface: 2001:DB8::5
# outgoing-interface: 2001:DB8::6
+
+ # Specify a netblock to use remainder 64 bits as random bits for
+ # upstream queries. Uses freebind option (Linux).
+ # outgoing-interface: 2001:DB8::/64
+ # Also (Linux:) ip -6 addr add 2001:db8::/64 dev lo
+ # And: ip -6 route add local 2001:db8::/64 dev lo
+ # And set prefer-ip6: yes to use the ip6 randomness from a netblock.
+ # Set this to yes to prefer ipv6 upstream servers over ipv4.
+ # prefer-ip6: no
# number of ports to allocate per thread, determines the size of the
# port range that can be open simultaneously. About double the
@@ -93,6 +102,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
@@ -157,6 +171,10 @@ server:
# the maximum number of hosts that are cached (roundtrip, EDNS, lame).
# infra-cache-numhosts: 10000
+
+ # define a number of tags here, use with local-zone, access-control.
+ # repeat the define-tag statement to add additional tags.
+ # define-tag: "tag1 tag2 tag3"
# Enable IPv4, "yes" or "no".
# do-ip4: yes
@@ -198,6 +216,20 @@ server:
# access-control: ::1 allow
# access-control: ::ffff:127.0.0.1 allow
+ # tag access-control with list of tags (in "" with spaces between)
+ # Clients using this access control element use localzones that
+ # are tagged with one of these tags.
+ # access-control-tag: 192.0.2.0/24 "tag2 tag3"
+
+ # set action for particular tag for given access control element
+ # if you have multiple tag values, the tag used to lookup the action
+ # is the first tag match between access-control-tag and local-zone-tag
+ # where "first" comes from the order of the define-tag values.
+ # access-control-tag-action: 192.0.2.0/24 tag3 refuse
+
+ # set redirect data for particular tag for access control element
+ # access-control-tag-data: 192.0.2.0/24 tag2 "A 127.0.0.1"
+
# if given, a chroot(2) is done to the given directory.
# i.e. you can chroot to the working directory, for example,
# for extra security, but make sure all files are in that directory.
@@ -231,6 +263,8 @@ server:
# the working directory. The relative files in this config are
# relative to this directory. If you give "" the working directory
# is not changed.
+ # If you give a server: directory: dir before include: file statements
+ # then those includes can be relative to the working directory.
# directory: "@UNBOUND_RUN_DIR@"
# the log file, "" means log to stderr.
@@ -317,6 +351,7 @@ server:
# Domains (and domains in them) without support for dns-0x20 and
# the fallback fails because they keep sending different answers.
# caps-whitelist: "licdn.com"
+ # caps-whitelist: "senderbase.org"
# Enforce privacy of these addresses. Strips them away from answers.
# It may cause DNSSEC validation to additionally mark it as bogus.
@@ -364,6 +399,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 +497,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.
@@ -541,6 +580,8 @@ server:
# o typetransparent resolves normally for other types and other names
# o inform resolves normally, but logs client IP address
# o inform_deny drops queries and logs client IP address
+ # o always_transparent, always_refuse, always_nxdomain, resolve in
+ # that way but ignore local data for that name.
#
# defaults are localhost address, reverse for 127.0.0.1 and ::1
# and nxdomain for AS112 zones. If you configure one of these zones
@@ -567,6 +608,12 @@ server:
# you need to do the reverse notation yourself.
# local-data-ptr: "192.0.2.3 www.example.com"
+ # tag a localzone with a list of tag names (in "" with spaces between)
+ # local-zone-tag: "example.com" "tag2 tag3"
+
+ # add a netblock specific override to a localzone, with zone type
+ # local-zone-override: "example.com" 192.0.2.0/24 refuse
+
# service clients over SSL (on the TCP sockets), with plain DNS inside
# the SSL stream. Give the certificate to use and private key.
# default is "" (disabled). requires restart to take effect.
@@ -600,7 +647,7 @@ server:
# ratelimit-for-domain: example.com 1000
# override the ratelimits for all domains below a domain name
# can give this multiple times, the name closest to the zone is used.
- # ratelimit-below-domain: example 1000
+ # ratelimit-below-domain: com 1000
# Python config section. To enable:
# o use --with-pythonmodule to configure before compiling.
diff --git a/contrib/unbound/doc/libunbound.3 b/contrib/unbound/doc/libunbound.3
index df4b8fd..1bf3fc2 100644
--- a/contrib/unbound/doc/libunbound.3
+++ b/contrib/unbound/doc/libunbound.3
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "libunbound" "3" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" 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.10 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
diff --git a/contrib/unbound/doc/libunbound.3.in b/contrib/unbound/doc/libunbound.3.in
index df4b8fd..1bf3fc2 100644
--- a/contrib/unbound/doc/libunbound.3.in
+++ b/contrib/unbound/doc/libunbound.3.in
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "libunbound" "3" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" 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.10 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
diff --git a/contrib/unbound/doc/unbound-anchor.8 b/contrib/unbound/doc/unbound-anchor.8
index c5d9d7f..fbc7e20 100644
--- a/contrib/unbound/doc/unbound-anchor.8
+++ b/contrib/unbound/doc/unbound-anchor.8
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound-anchor" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
@@ -16,6 +16,8 @@
.SH "DESCRIPTION"
.B Unbound\-anchor
performs setup or update of the root trust anchor for DNSSEC validation.
+The program fetches the trust anchor with the method from RFC7958 when
+regular RFC5011 update fails to bring it up to date.
It can be run (as root) from the commandline, or run as part of startup
scripts. Before you start the \fIunbound\fR(8) DNS server.
.P
@@ -39,8 +41,8 @@ update certificate files.
.P
It tests if the root anchor file works, and if not, and an update is possible,
attempts to update the root anchor using the root update certificate.
-It performs a https fetch of root-anchors.xml and checks the results, if
-all checks are successful, it updates the root anchor file. Otherwise
+It performs a https fetch of root-anchors.xml and checks the results (RFC7958),
+if all checks are successful, it updates the root anchor file. Otherwise
the root anchor file is unchanged. It performs RFC5011 tracking if the
DNSSEC information available via the DNS makes that possible.
.P
diff --git a/contrib/unbound/doc/unbound-anchor.8.in b/contrib/unbound/doc/unbound-anchor.8.in
index de283e5..7403caa 100644
--- a/contrib/unbound/doc/unbound-anchor.8.in
+++ b/contrib/unbound/doc/unbound-anchor.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound-anchor" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
@@ -16,6 +16,8 @@
.SH "DESCRIPTION"
.B Unbound\-anchor
performs setup or update of the root trust anchor for DNSSEC validation.
+The program fetches the trust anchor with the method from RFC7958 when
+regular RFC5011 update fails to bring it up to date.
It can be run (as root) from the commandline, or run as part of startup
scripts. Before you start the \fIunbound\fR(8) DNS server.
.P
@@ -39,8 +41,8 @@ update certificate files.
.P
It tests if the root anchor file works, and if not, and an update is possible,
attempts to update the root anchor using the root update certificate.
-It performs a https fetch of root-anchors.xml and checks the results, if
-all checks are successful, it updates the root anchor file. Otherwise
+It performs a https fetch of root-anchors.xml and checks the results (RFC7958),
+if all checks are successful, it updates the root anchor file. Otherwise
the root anchor file is unchanged. It performs RFC5011 tracking if the
DNSSEC information available via the DNS makes that possible.
.P
diff --git a/contrib/unbound/doc/unbound-checkconf.8 b/contrib/unbound/doc/unbound-checkconf.8
index f166720..3c8198b 100644
--- a/contrib/unbound/doc/unbound-checkconf.8
+++ b/contrib/unbound/doc/unbound-checkconf.8
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound-checkconf" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
diff --git a/contrib/unbound/doc/unbound-checkconf.8.in b/contrib/unbound/doc/unbound-checkconf.8.in
index 92be13f..03f5b3c 100644
--- a/contrib/unbound/doc/unbound-checkconf.8.in
+++ b/contrib/unbound/doc/unbound-checkconf.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound-checkconf" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
diff --git a/contrib/unbound/doc/unbound-control.8 b/contrib/unbound/doc/unbound-control.8
index 75219d2..892bbeb 100644
--- a/contrib/unbound/doc/unbound-control.8
+++ b/contrib/unbound/doc/unbound-control.8
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound-control" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
diff --git a/contrib/unbound/doc/unbound-control.8.in b/contrib/unbound/doc/unbound-control.8.in
index 0e814b8..9089db9 100644
--- a/contrib/unbound/doc/unbound-control.8.in
+++ b/contrib/unbound/doc/unbound-control.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound-control" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
diff --git a/contrib/unbound/doc/unbound-host.1 b/contrib/unbound/doc/unbound-host.1
index 28a50a8..ef1eaed 100644
--- a/contrib/unbound/doc/unbound-host.1
+++ b/contrib/unbound/doc/unbound-host.1
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound\-host" "1" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
diff --git a/contrib/unbound/doc/unbound-host.1.in b/contrib/unbound/doc/unbound-host.1.in
index 65253ad..04d19ad 100644
--- a/contrib/unbound/doc/unbound-host.1.in
+++ b/contrib/unbound/doc/unbound-host.1.in
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound\-host" "1" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
diff --git a/contrib/unbound/doc/unbound.8 b/contrib/unbound/doc/unbound.8
index d8c5494..26abc06 100644
--- a/contrib/unbound/doc/unbound.8
+++ b/contrib/unbound/doc/unbound.8
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" 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.10.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
diff --git a/contrib/unbound/doc/unbound.8.in b/contrib/unbound/doc/unbound.8.in
index 4b752bb..78e497d 100644
--- a/contrib/unbound/doc/unbound.8.in
+++ b/contrib/unbound/doc/unbound.8.in
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound" "8" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" 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.10.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
diff --git a/contrib/unbound/doc/unbound.conf.5 b/contrib/unbound/doc/unbound.conf.5
index 569bd26..6897761 100644
--- a/contrib/unbound/doc/unbound.conf.5
+++ b/contrib/unbound/doc/unbound.conf.5
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound.conf" "5" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@@ -72,7 +72,8 @@ Processing continues as if the text from the included file was copied into
the config file at that point. If also using chroot, using full path names
for the included files works, relative pathnames for the included names work
if the directory where the daemon is started equals its chroot/working
-directory. Wildcards can be used to include multiple files, see \fIglob\fR(7).
+directory or is specified before the include statement with directory: dir.
+Wildcards can be used to include multiple files, see \fIglob\fR(7).
.SS "Server Options"
These options are part of the
.B server:
@@ -126,7 +127,7 @@ Detect source interface on UDP queries and copy them to replies. This
feature is experimental, and needs support in your OS for particular socket
options. Default value is no.
.TP
-.B outgoing\-interface: \fI<ip address>
+.B outgoing\-interface: \fI<ip address or ip6 netblock>
Interface to use to connect to the network. This interface is used to send
queries to authoritative servers and receive their replies. Can be given
multiple times to work on several interfaces. If none are given the
@@ -136,12 +137,28 @@ and
.B outgoing\-interface:
lines, the interfaces are then used for both purposes. Outgoing queries are
sent via a random outgoing interface to counter spoofing.
+.IP
+If an IPv6 netblock is specified instead of an individual IPv6 address,
+outgoing UDP queries will use a randomised source address taken from the
+netblock to counter spoofing. Requires the IPv6 netblock to be routed to the
+host running unbound, and requires OS support for unprivileged non-local binds
+(currently only supported on Linux). Several netblocks may be specified with
+multiple
+.B outgoing\-interface:
+options, but do not specify both an individual IPv6 address and an IPv6
+netblock, or the randomisation will be compromised. Consider combining with
+.B prefer\-ip6: yes
+to increase the likelihood of IPv6 nameservers being selected for queries.
+On Linux you need these two commands to be able to use the freebind socket
+option to receive traffic for the ip6 netblock:
+ip -6 addr add mynetblock/64 dev lo &&
+ip -6 route add local mynetblock/64 dev lo
.TP
.B outgoing\-range: \fI<number>
Number of ports to open. This number of file descriptors can be opened per
thread. Must be at least 1. Default depends on compile options. Larger
numbers need extra resources from the operating system. For performance a
-a very large value is best, use libevent to make this possible.
+very large value is best, use libevent to make this possible.
.TP
.B outgoing\-port\-permit: \fI<port number or range>
Permit unbound to open this port or range of ports for use to send queries.
@@ -277,6 +294,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 address 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
@@ -322,6 +346,10 @@ Lower limit for dynamic retransmit timeout calculation in infrastructure
cache. Default is 50 milliseconds. Increase this value if using forwarders
needing more time to do recursive name resolution.
.TP
+.B define\-tag: \fI<"list of tags">
+Define the tags that can be used with local\-zone and access\-control.
+Enclose the list between quotes ("") and put spaces between tags.
+.TP
.B do\-ip4: \fI<yes or no>
Enable or disable whether ip4 queries are answered or issued. Default is yes.
.TP
@@ -332,6 +360,10 @@ IPv6 to the internet nameservers. With this option you can disable the
ipv6 transport for sending DNS traffic, it does not impact the contents of
the DNS traffic, which may have ip4 and ip6 addresses in it.
.TP
+.B prefer\-ip6: \fI<yes or no>
+If enabled, prefer IPv6 transport for sending DNS queries to internet
+nameservers. Default is no.
+.TP
.B do\-udp: \fI<yes or no>
Enable or disable whether UDP queries are answered or issued. Default is yes.
.TP
@@ -425,6 +457,23 @@ allowed full recursion but only the static data. With deny_non_local,
messages that are disallowed are dropped, with refuse_non_local they
receive error code REFUSED.
.TP
+.B access\-control\-tag: \fI<IP netblock> <"list of tags">
+Assign tags to access-control elements. Clients using this access control
+element use localzones that are tagged with one of these tags. Tags must be
+defined in \fIdefine\-tags\fR. Enclose list of tags in quotes ("") and put
+spaces between tags. If access\-control\-tag is configured for a netblock that
+does not have an access\-control, an access\-control element with action
+\fIallow\fR is configured for this netblock.
+.TP
+.B access\-control\-tag\-action: \fI<IP netblock> <tag> <action>
+Set action for particular tag for given access control element. If you have
+multiple tag values, the tag used to lookup the action is the first tag match
+between access\-control\-tag and local\-zone\-tag where "first" comes from the
+order of the define-tag values.
+.TP
+.B access\-control\-tag\-data: \fI<IP netblock> <tag> <"resource record string">
+Set redirect data for particular tag for given access control element.
+.TP
.B chroot: \fI<directory>
If chroot is enabled, you should pass the configfile (from the
commandline) as a full path from the original root. After the
@@ -462,6 +511,8 @@ requires privileges, then a reload will fail; a restart is needed.
Sets the working directory for the program. Default is "/var/unbound".
On Windows the string "%EXECUTABLE%" tries to change to the directory
that unbound.exe resides in.
+If you give a server: directory: dir before include: file statements
+then those includes can be relative to the working directory.
.TP
.B logfile: \fI<filename>
If "" is given, logging goes to stderr, or nowhere once daemonized.
@@ -570,6 +621,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 +725,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 +750,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
@@ -866,6 +927,7 @@ address space are not validated. This is usually required whenever
Configure a local zone. The type determines the answer to give if
there is no match from local\-data. The types are deny, refuse, static,
transparent, redirect, nodefault, typetransparent, inform, inform_deny,
+always_transparent, always_refuse, always_nxdomain,
and are explained below. After that the default settings are listed. Use
local\-data: to enter data into the local zone. Answers for local zones
are authoritative DNS answers. By default the zones are class IN.
@@ -926,6 +988,15 @@ logged, eg. to run antivirus on them.
The query is dropped, like 'deny', and logged, like 'inform'. Ie. find
infected machines without answering the queries.
.TP 10
+\h'5'\fIalways_transparent\fR
+Like transparent, but ignores local data and resolves normally.
+.TP 10
+\h'5'\fIalways_refuse\fR
+Like refuse, but ignores local data and refuses the query.
+.TP 10
+\h'5'\fIalways_nxdomain\fR
+Like static, but ignores local data and returns nxdomain for the query.
+.TP 10
\h'5'\fInodefault\fR
Used to turn off default contents for AS112 zones. The other types
also turn off default contents for the zone. The 'nodefault' option
@@ -1043,6 +1114,18 @@ Configure local data shorthand for a PTR record with the reversed IPv4 or
IPv6 address and the host name. For example "192.0.2.4 www.example.com".
TTL can be inserted like this: "2001:DB8::4 7200 www.example.com"
.TP 5
+.B local\-zone\-tag: \fI<zone> <"list of tags">
+Assign tags to localzones. Tagged localzones will only be applied when the
+used access-control element has a matching tag. Tags must be defined in
+\fIdefine\-tags\fR. Enclose list of tags in quotes ("") and put spaces between
+tags.
+.TP 5
+.B local\-zone\-override: \fI<zone> <IP netblock> <type>
+Override the localzone type for queries from addresses matching netblock.
+Use this localzone type, regardless the type configured for the local-zone
+(both tagged and untagged) and regardless the type configured using
+access\-control\-tag\-action.
+.TP 5
.B ratelimit: \fI<number or 0>
Enable ratelimiting of queries sent to nameserver for performing recursion.
If 0, the default, it is disabled. This option is experimental at this time.
diff --git a/contrib/unbound/doc/unbound.conf.5.in b/contrib/unbound/doc/unbound.conf.5.in
index 3f84cac..f813c44 100644
--- a/contrib/unbound/doc/unbound.conf.5.in
+++ b/contrib/unbound/doc/unbound.conf.5.in
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Mar 2, 2016" "NLnet Labs" "unbound 1.5.8"
+.TH "unbound.conf" "5" "Sep 27, 2016" "NLnet Labs" "unbound 1.5.10"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@@ -72,7 +72,8 @@ Processing continues as if the text from the included file was copied into
the config file at that point. If also using chroot, using full path names
for the included files works, relative pathnames for the included names work
if the directory where the daemon is started equals its chroot/working
-directory. Wildcards can be used to include multiple files, see \fIglob\fR(7).
+directory or is specified before the include statement with directory: dir.
+Wildcards can be used to include multiple files, see \fIglob\fR(7).
.SS "Server Options"
These options are part of the
.B server:
@@ -126,7 +127,7 @@ Detect source interface on UDP queries and copy them to replies. This
feature is experimental, and needs support in your OS for particular socket
options. Default value is no.
.TP
-.B outgoing\-interface: \fI<ip address>
+.B outgoing\-interface: \fI<ip address or ip6 netblock>
Interface to use to connect to the network. This interface is used to send
queries to authoritative servers and receive their replies. Can be given
multiple times to work on several interfaces. If none are given the
@@ -136,12 +137,28 @@ and
.B outgoing\-interface:
lines, the interfaces are then used for both purposes. Outgoing queries are
sent via a random outgoing interface to counter spoofing.
+.IP
+If an IPv6 netblock is specified instead of an individual IPv6 address,
+outgoing UDP queries will use a randomised source address taken from the
+netblock to counter spoofing. Requires the IPv6 netblock to be routed to the
+host running unbound, and requires OS support for unprivileged non-local binds
+(currently only supported on Linux). Several netblocks may be specified with
+multiple
+.B outgoing\-interface:
+options, but do not specify both an individual IPv6 address and an IPv6
+netblock, or the randomisation will be compromised. Consider combining with
+.B prefer\-ip6: yes
+to increase the likelihood of IPv6 nameservers being selected for queries.
+On Linux you need these two commands to be able to use the freebind socket
+option to receive traffic for the ip6 netblock:
+ip -6 addr add mynetblock/64 dev lo &&
+ip -6 route add local mynetblock/64 dev lo
.TP
.B outgoing\-range: \fI<number>
Number of ports to open. This number of file descriptors can be opened per
thread. Must be at least 1. Default depends on compile options. Larger
numbers need extra resources from the operating system. For performance a
-a very large value is best, use libevent to make this possible.
+very large value is best, use libevent to make this possible.
.TP
.B outgoing\-port\-permit: \fI<port number or range>
Permit unbound to open this port or range of ports for use to send queries.
@@ -277,6 +294,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 address 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
@@ -322,6 +346,10 @@ Lower limit for dynamic retransmit timeout calculation in infrastructure
cache. Default is 50 milliseconds. Increase this value if using forwarders
needing more time to do recursive name resolution.
.TP
+.B define\-tag: \fI<"list of tags">
+Define the tags that can be used with local\-zone and access\-control.
+Enclose the list between quotes ("") and put spaces between tags.
+.TP
.B do\-ip4: \fI<yes or no>
Enable or disable whether ip4 queries are answered or issued. Default is yes.
.TP
@@ -332,6 +360,10 @@ IPv6 to the internet nameservers. With this option you can disable the
ipv6 transport for sending DNS traffic, it does not impact the contents of
the DNS traffic, which may have ip4 and ip6 addresses in it.
.TP
+.B prefer\-ip6: \fI<yes or no>
+If enabled, prefer IPv6 transport for sending DNS queries to internet
+nameservers. Default is no.
+.TP
.B do\-udp: \fI<yes or no>
Enable or disable whether UDP queries are answered or issued. Default is yes.
.TP
@@ -425,6 +457,23 @@ allowed full recursion but only the static data. With deny_non_local,
messages that are disallowed are dropped, with refuse_non_local they
receive error code REFUSED.
.TP
+.B access\-control\-tag: \fI<IP netblock> <"list of tags">
+Assign tags to access-control elements. Clients using this access control
+element use localzones that are tagged with one of these tags. Tags must be
+defined in \fIdefine\-tags\fR. Enclose list of tags in quotes ("") and put
+spaces between tags. If access\-control\-tag is configured for a netblock that
+does not have an access\-control, an access\-control element with action
+\fIallow\fR is configured for this netblock.
+.TP
+.B access\-control\-tag\-action: \fI<IP netblock> <tag> <action>
+Set action for particular tag for given access control element. If you have
+multiple tag values, the tag used to lookup the action is the first tag match
+between access\-control\-tag and local\-zone\-tag where "first" comes from the
+order of the define-tag values.
+.TP
+.B access\-control\-tag\-data: \fI<IP netblock> <tag> <"resource record string">
+Set redirect data for particular tag for given access control element.
+.TP
.B chroot: \fI<directory>
If chroot is enabled, you should pass the configfile (from the
commandline) as a full path from the original root. After the
@@ -462,6 +511,8 @@ requires privileges, then a reload will fail; a restart is needed.
Sets the working directory for the program. Default is "@UNBOUND_RUN_DIR@".
On Windows the string "%EXECUTABLE%" tries to change to the directory
that unbound.exe resides in.
+If you give a server: directory: dir before include: file statements
+then those includes can be relative to the working directory.
.TP
.B logfile: \fI<filename>
If "" is given, logging goes to stderr, or nowhere once daemonized.
@@ -570,6 +621,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 +725,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 +750,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
@@ -866,6 +927,7 @@ address space are not validated. This is usually required whenever
Configure a local zone. The type determines the answer to give if
there is no match from local\-data. The types are deny, refuse, static,
transparent, redirect, nodefault, typetransparent, inform, inform_deny,
+always_transparent, always_refuse, always_nxdomain,
and are explained below. After that the default settings are listed. Use
local\-data: to enter data into the local zone. Answers for local zones
are authoritative DNS answers. By default the zones are class IN.
@@ -926,6 +988,15 @@ logged, eg. to run antivirus on them.
The query is dropped, like 'deny', and logged, like 'inform'. Ie. find
infected machines without answering the queries.
.TP 10
+\h'5'\fIalways_transparent\fR
+Like transparent, but ignores local data and resolves normally.
+.TP 10
+\h'5'\fIalways_refuse\fR
+Like refuse, but ignores local data and refuses the query.
+.TP 10
+\h'5'\fIalways_nxdomain\fR
+Like static, but ignores local data and returns nxdomain for the query.
+.TP 10
\h'5'\fInodefault\fR
Used to turn off default contents for AS112 zones. The other types
also turn off default contents for the zone. The 'nodefault' option
@@ -1043,6 +1114,18 @@ Configure local data shorthand for a PTR record with the reversed IPv4 or
IPv6 address and the host name. For example "192.0.2.4 www.example.com".
TTL can be inserted like this: "2001:DB8::4 7200 www.example.com"
.TP 5
+.B local\-zone\-tag: \fI<zone> <"list of tags">
+Assign tags to localzones. Tagged localzones will only be applied when the
+used access-control element has a matching tag. Tags must be defined in
+\fIdefine\-tags\fR. Enclose list of tags in quotes ("") and put spaces between
+tags.
+.TP 5
+.B local\-zone\-override: \fI<zone> <IP netblock> <type>
+Override the localzone type for queries from addresses matching netblock.
+Use this localzone type, regardless the type configured for the local-zone
+(both tagged and untagged) and regardless the type configured using
+access\-control\-tag\-action.
+.TP 5
.B ratelimit: \fI<number or 0>
Enable ratelimiting of queries sent to nameserver for performing recursion.
If 0, the default, it is disabled. This option is experimental at this time.
diff --git a/contrib/unbound/doc/unbound.doxygen b/contrib/unbound/doc/unbound.doxygen
index 43f2e38..fe39876 100644
--- a/contrib/unbound/doc/unbound.doxygen
+++ b/contrib/unbound/doc/unbound.doxygen
@@ -623,7 +623,9 @@ EXCLUDE = ./build \
pythonmod/examples/resip.py \
libunbound/python/unbound.py \
libunbound/python/libunbound_wrap.c \
- ./ldns-src
+ ./ldns-src \
+ doc/control_proto_spec.txt \
+ doc/requirements.txt
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
# directories that are symbolic links (a Unix filesystem feature) are excluded
diff --git a/contrib/unbound/iterator/iter_fwd.c b/contrib/unbound/iterator/iter_fwd.c
index 0feee03..3e580ca 100644
--- a/contrib/unbound/iterator/iter_fwd.c
+++ b/contrib/unbound/iterator/iter_fwd.c
@@ -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);
diff --git a/contrib/unbound/iterator/iter_hints.c b/contrib/unbound/iterator/iter_hints.c
index 217dfa2..5fd9017 100644
--- a/contrib/unbound/iterator/iter_hints.c
+++ b/contrib/unbound/iterator/iter_hints.c
@@ -147,6 +147,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:84::b")) goto failed;
if(!ah(dp, "C.ROOT-SERVERS.NET.", "2001:500:2::c")) goto failed;
if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
+ if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed;
if(!ah(dp, "F.ROOT-SERVERS.NET.", "2001:500:2f::f")) goto failed;
if(!ah(dp, "H.ROOT-SERVERS.NET.", "2001:500:1::53")) goto failed;
if(!ah(dp, "I.ROOT-SERVERS.NET.", "2001:7fe::53")) goto failed;
diff --git a/contrib/unbound/iterator/iter_utils.c b/contrib/unbound/iterator/iter_utils.c
index 58e62fb..874dd68 100644
--- a/contrib/unbound/iterator/iter_utils.c
+++ b/contrib/unbound/iterator/iter_utils.c
@@ -360,6 +360,39 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
}
}
*selected_rtt = low_rtt;
+
+ if (env->cfg->prefer_ip6) {
+ int got_num6 = 0;
+ int low_rtt6 = 0;
+ int i;
+ prev = NULL;
+ a = dp->result_list;
+ for(i = 0; i < got_num; i++) {
+ swap_to_front = 0;
+ if(a->addr.ss_family == AF_INET6) {
+ got_num6++;
+ swap_to_front = 1;
+ if(low_rtt6 == 0 || a->sel_rtt < low_rtt6) {
+ low_rtt6 = a->sel_rtt;
+ }
+ }
+ /* swap to front if IPv6, or move to next result */
+ if(swap_to_front && prev) {
+ n = a->next_result;
+ prev->next_result = n;
+ a->next_result = dp->result_list;
+ dp->result_list = a;
+ a = n;
+ } else {
+ prev = a;
+ a = a->next_result;
+ }
+ }
+ if(got_num6 > 0) {
+ got_num = got_num6;
+ *selected_rtt = low_rtt6;
+ }
+ }
return got_num;
}
@@ -590,6 +623,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)
diff --git a/contrib/unbound/iterator/iter_utils.h b/contrib/unbound/iterator/iter_utils.h
index 3a4df3e..50c5fc0 100644
--- a/contrib/unbound/iterator/iter_utils.h
+++ b/contrib/unbound/iterator/iter_utils.h
@@ -174,6 +174,18 @@ 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,
* and delegation message (DS RRset) to determine this.
diff --git a/contrib/unbound/iterator/iterator.c b/contrib/unbound/iterator/iterator.c
index b1bf902..cc7e937 100644
--- a/contrib/unbound/iterator/iterator.c
+++ b/contrib/unbound/iterator/iterator.c
@@ -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,8 @@ 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;
+ iq->minimise_timeout_count = 0;
if (qstate->env->cfg->qname_minimisation)
iq->minimisation_state = INIT_MINIMISE_STATE;
else
@@ -229,6 +216,7 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) {
/* mark address as failed. */
struct delegpt_ns* dpns = NULL;
+ super_iq->num_target_queries--;
if(super_iq->dp)
dpns = delegpt_find_ns(super_iq->dp,
qstate->qinfo.qname, qstate->qinfo.qname_len);
@@ -248,7 +236,6 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
log_err("out of memory adding missing");
}
dpns->resolved = 1; /* mark as failed */
- super_iq->num_target_queries--;
}
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS) {
/* prime failed to get delegation */
@@ -1800,6 +1787,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 +1998,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)
@@ -2019,30 +2009,52 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
iq->dp->name))) {
iq->qinfo_out.qname = iq->dp->name;
iq->qinfo_out.qname_len = iq->dp->namelen;
- iq->qinfo_out.qtype = LDNS_RR_TYPE_NS;
+ iq->qinfo_out.qtype = LDNS_RR_TYPE_A;
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++;
+ iq->minimise_timeout_count = 0;
- /* 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;
+ iter_dec_attempts(iq->dp, 1);
+
+ /* 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) {
@@ -2051,8 +2063,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
&iq->qinfo_out.qname_len,
labdiff-1);
}
- if(labdiff < 1 ||
- (labdiff < 2 && iq->qchase.qtype == LDNS_RR_TYPE_DS))
+ if(labdiff < 1 || (labdiff < 2
+ && (iq->qchase.qtype == LDNS_RR_TYPE_DS
+ || iq->qchase.qtype == LDNS_RR_TYPE_A)))
/* Stop minimising this query, resolve "as usual" */
iq->minimisation_state = DONOT_MINIMISE_STATE;
else {
@@ -2068,12 +2081,18 @@ 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
- * iteration */
- iq->minimisation_state = MINIMISE_STATE;
+ if(iq->minimisation_state == SKIP_MINIMISE_STATE) {
+ iq->minimise_timeout_count++;
+ if(iq->minimise_timeout_count < MAX_MINIMISE_TIMEOUT_COUNT)
+ /* Do not increment qname, continue incrementing next
+ * iteration */
+ iq->minimisation_state = MINIMISE_STATE;
+ else
+ /* Too many time-outs detected for this QNAME and QTYPE.
+ * We give up, disable QNAME minimisation. */
+ iq->minimisation_state = DONOT_MINIMISE_STATE;
+ }
if(iq->minimisation_state == DONOT_MINIMISE_STATE)
iq->qinfo_out = iq->qchase;
@@ -2090,10 +2109,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);
@@ -2145,7 +2170,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iq->num_current_queries--;
if(iq->response == NULL) {
/* Don't increment qname when QNAME minimisation is enabled */
- if (qstate->env->cfg->qname_minimisation)
+ if(qstate->env->cfg->qname_minimisation)
iq->minimisation_state = SKIP_MINIMISE_STATE;
iq->chase_to_rd = 0;
iq->dnssec_lame_query = 0;
@@ -2161,8 +2186,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 +2277,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);
@@ -2605,6 +2661,10 @@ processTargetResponse(struct module_qstate* qstate, int id,
log_query_info(VERB_ALGO, "processTargetResponse", &qstate->qinfo);
log_query_info(VERB_ALGO, "processTargetResponse super", &forq->qinfo);
+ /* Tell the originating event that this target query has finished
+ * (regardless if it succeeded or not). */
+ foriq->num_target_queries--;
+
/* check to see if parent event is still interested (in orig name). */
if(!foriq->dp) {
verbose(VERB_ALGO, "subq: parent not interested, was reset");
@@ -2620,10 +2680,6 @@ processTargetResponse(struct module_qstate* qstate, int id,
return;
}
- /* Tell the originating event that this target query has finished
- * (regardless if it succeeded or not). */
- foriq->num_target_queries--;
-
/* if iq->query_for_pside_glue then add the pside_glue (marked lame) */
if(iq->pside_glue) {
/* if the pside_glue is NULL, then it could not be found,
@@ -3082,7 +3138,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;
diff --git a/contrib/unbound/iterator/iterator.h b/contrib/unbound/iterator/iterator.h
index b7aa82e..5585f57 100644
--- a/contrib/unbound/iterator/iterator.h
+++ b/contrib/unbound/iterator/iterator.h
@@ -61,6 +61,23 @@ 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
+/* max number of time-outs for minimised query. Prevents resolving failures
+ * when the QNAME minimisation QTYPE is blocked. */
+#define MAX_MINIMISE_TIMEOUT_COUNT 3
+/**
+ * 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 +366,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 +374,17 @@ 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;
+
+ /**
+ * Count number of time-outs. Used to prevent resolving failures when
+ * the QNAME minimisation QTYPE is blocked. */
+ int minimise_timeout_count;
};
/**
diff --git a/contrib/unbound/libunbound/context.h b/contrib/unbound/libunbound/context.h
index 31ca09c..d32c0b0 100644
--- a/contrib/unbound/libunbound/context.h
+++ b/contrib/unbound/libunbound/context.h
@@ -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;
diff --git a/contrib/unbound/libunbound/libunbound.c b/contrib/unbound/libunbound/libunbound.c
index 992509e..69ccb08 100644
--- a/contrib/unbound/libunbound/libunbound.c
+++ b/contrib/unbound/libunbound/libunbound.c
@@ -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"
@@ -170,6 +171,20 @@ ub_ctx_create(void)
}
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)
{
struct ub_ctx* ctx = ub_ctx_create_nopipe();
@@ -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;
}
diff --git a/contrib/unbound/libunbound/libworker.c b/contrib/unbound/libunbound/libworker.c
index ad1f84c..6f53541 100644
--- a/contrib/unbound/libunbound/libworker.c
+++ b/contrib/unbound/libunbound/libworker.c
@@ -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);
@@ -607,7 +608,8 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
if(local_zones_answer(ctx->local_zones, &qinfo, &edns,
- w->back->udp_buff, w->env->scratch, NULL)) {
+ w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0,
+ NULL, 0, NULL, 0)) {
regional_free_all(w->env->scratch);
libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
w->back->udp_buff, sec_status_insecure, NULL);
@@ -677,7 +679,8 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
if(local_zones_answer(ctx->local_zones, &qinfo, &edns,
- w->back->udp_buff, w->env->scratch, NULL)) {
+ w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0,
+ NULL, 0, NULL, 0)) {
regional_free_all(w->env->scratch);
free(qinfo.qname);
libworker_event_done_cb(q, LDNS_RCODE_NOERROR,
@@ -797,7 +800,8 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
sldns_buffer_write_u16_at(w->back->udp_buff, 0, qid);
sldns_buffer_write_u16_at(w->back->udp_buff, 2, qflags);
if(local_zones_answer(w->ctx->local_zones, &qinfo, &edns,
- w->back->udp_buff, w->env->scratch, NULL)) {
+ w->back->udp_buff, w->env->scratch, NULL, NULL, 0, NULL, 0,
+ NULL, 0, NULL, 0)) {
regional_free_all(w->env->scratch);
q->msg_security = sec_status_insecure;
add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL);
@@ -822,9 +826,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 +838,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 +959,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))
{
diff --git a/contrib/unbound/libunbound/libworker.h b/contrib/unbound/libunbound/libworker.h
index 0103b5d..0014347 100644
--- a/contrib/unbound/libunbound/libworker.h
+++ b/contrib/unbound/libunbound/libworker.h
@@ -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.
diff --git a/contrib/unbound/libunbound/python/libunbound.i b/contrib/unbound/libunbound/python/libunbound.i
index 50a9b67..84a5369 100644
--- a/contrib/unbound/libunbound/python/libunbound.i
+++ b/contrib/unbound/libunbound/python/libunbound.i
@@ -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
diff --git a/contrib/unbound/libunbound/ubsyms.def b/contrib/unbound/libunbound/ubsyms.def
index d03a84b..0d8e6af 100644
--- a/contrib/unbound/libunbound/ubsyms.def
+++ b/contrib/unbound/libunbound/ubsyms.def
@@ -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
diff --git a/contrib/unbound/libunbound/unbound-event.h b/contrib/unbound/libunbound/unbound-event.h
index b80de38..432750d 100644
--- a/contrib/unbound/libunbound/unbound-event.h
+++ b/contrib/unbound/libunbound/unbound-event.h
@@ -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
diff --git a/contrib/unbound/libunbound/worker.h b/contrib/unbound/libunbound/worker.h
index a531501..b8d8dd8 100644
--- a/contrib/unbound/libunbound/worker.h
+++ b/contrib/unbound/libunbound/worker.h
@@ -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
diff --git a/contrib/unbound/services/cache/dns.c b/contrib/unbound/services/cache/dns.c
index e14e636..84db7a7 100644
--- a/contrib/unbound/services/cache/dns.c
+++ b/contrib/unbound/services/cache/dns.c
@@ -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 */
diff --git a/contrib/unbound/services/listen_dnsport.c b/contrib/unbound/services/listen_dnsport.c
index be63439..6637483 100644
--- a/contrib/unbound/services/listen_dnsport.c
+++ b/contrib/unbound/services/listen_dnsport.c
@@ -43,6 +43,9 @@
# include <sys/types.h>
#endif
#include <sys/time.h>
+#ifdef USE_TCP_FASTOPEN
+#include <netinet/tcp.h>
+#endif
#include "services/listen_dnsport.h"
#include "services/outside_network.h"
#include "util/netevent.h"
@@ -96,10 +99,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
@@ -117,6 +121,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
#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;
#ifndef USE_WINSOCK
@@ -190,12 +197,21 @@ 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 */
}
+#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 */
if(rcv) {
#ifdef SO_RCVBUF
int got;
@@ -490,15 +506,21 @@ 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
+#ifdef USE_TCP_FASTOPEN
+ int qlen;
+#endif
+#if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY)
(void)transparent;
#endif
+#if !defined(IP_FREEBIND)
+ (void)freebind;
+#endif
verbose_print_addr(addr);
*noproto = 0;
if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
@@ -553,6 +575,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 +628,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 */
@@ -638,6 +675,22 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
#endif
return -1;
}
+#ifdef USE_TCP_FASTOPEN
+ /* qlen specifies how many outstanding TFO requests to allow. Limit is a defense
+ against IP spoofing attacks as suggested in RFC7413 */
+#ifdef __APPLE__
+ /* OS X implementation only supports qlen of 1 via this call. Actual
+ value is configured by the net.inet.tcp.fastopen_backlog kernel parm. */
+ qlen = 1;
+#else
+ /* 5 is recommended on linux */
+ qlen = 5;
+#endif
+ if ((setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &qlen,
+ sizeof(qlen))) == -1 ) {
+ log_err("Setting TCP Fast Open as server failed: %s", strerror(errno));
+ }
+#endif
return s;
}
@@ -651,7 +704,7 @@ create_local_accept_sock(const char *path, int* noproto)
verbose(VERB_ALGO, "creating unix socket %s", path);
#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
/* this member exists on BSDs, not Linux */
- usock.sun_len = (socklen_t)sizeof(usock);
+ usock.sun_len = (unsigned)sizeof(usock);
#endif
usock.sun_family = AF_LOCAL;
/* length is 92-108, 104 on FreeBSD */
@@ -704,7 +757,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 +785,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 +793,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 +806,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 +828,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 +927,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 +942,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 +970,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 +991,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 +1150,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 +1163,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 +1178,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 +1191,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;
}
diff --git a/contrib/unbound/services/listen_dnsport.h b/contrib/unbound/services/listen_dnsport.h
index 3a46e41..fbaa483 100644
--- a/contrib/unbound/services/listen_dnsport.h
+++ b/contrib/unbound/services/listen_dnsport.h
@@ -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
diff --git a/contrib/unbound/services/localzone.c b/contrib/unbound/services/localzone.c
index 1fcac97..9bc2609 100644
--- a/contrib/unbound/services/localzone.c
+++ b/contrib/unbound/services/localzone.c
@@ -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;
}
@@ -182,8 +184,11 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len,
log_warn("duplicate local-zone");
lock_rw_unlock(&z->lock);
local_zone_delete(z);
+ /* find the correct zone, so not an error for duplicate */
+ z = local_zones_find(zones, nm, len, labs, c);
+ lock_rw_wrlock(&z->lock);
lock_rw_unlock(&zones->lock);
- return NULL;
+ return z;
}
lock_rw_unlock(&zones->lock);
return z;
@@ -506,6 +511,123 @@ 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_find(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;
+}
+
+/** enter override into zone */
+static int
+lz_enter_override(struct local_zones* zones, char* zname, char* netblock,
+ char* type, uint16_t rr_class)
+{
+ uint8_t dname[LDNS_MAX_DOMAINLEN+1];
+ size_t dname_len = sizeof(dname);
+ int dname_labs;
+ struct sockaddr_storage addr;
+ int net;
+ socklen_t addrlen;
+ struct local_zone* z;
+ enum localzone_type t;
+
+ /* parse zone name */
+ if(sldns_str2wire_dname_buf(zname, dname, &dname_len) != 0) {
+ log_err("cannot parse zone name in local-zone-override: %s %s",
+ zname, netblock);
+ return 0;
+ }
+ dname_labs = dname_count_labels(dname);
+
+ /* parse netblock */
+ if(!netblockstrtoaddr(netblock, UNBOUND_DNS_PORT, &addr, &addrlen,
+ &net)) {
+ log_err("cannot parse netblock in local-zone-override: %s %s",
+ zname, netblock);
+ return 0;
+ }
+
+ /* parse zone type */
+ if(!local_zone_str2type(type, &t)) {
+ log_err("cannot parse type in local-zone-override: %s %s %s",
+ zname, netblock, type);
+ return 0;
+ }
+
+ /* find localzone entry */
+ lock_rw_rdlock(&zones->lock);
+ z = local_zones_find(zones, dname, dname_len, dname_labs, rr_class);
+ if(!z) {
+ lock_rw_unlock(&zones->lock);
+ log_err("no local-zone for local-zone-override %s", zname);
+ return 0;
+ }
+ lock_rw_wrlock(&z->lock);
+ lock_rw_unlock(&zones->lock);
+
+ /* create netblock addr_tree if not present yet */
+ if(!z->override_tree) {
+ z->override_tree = (struct rbtree_t*)regional_alloc_zero(
+ z->region, sizeof(*z->override_tree));
+ if(!z->override_tree) {
+ lock_rw_unlock(&z->lock);
+ log_err("out of memory");
+ return 0;
+ }
+ addr_tree_init(z->override_tree);
+ }
+ /* add new elem to tree */
+ if(z->override_tree) {
+ struct local_zone_override* n;
+ n = (struct local_zone_override*)regional_alloc_zero(
+ z->region, sizeof(*n));
+ if(!n) {
+ lock_rw_unlock(&z->lock);
+ log_err("out of memory");
+ return 0;
+ }
+ n->type = t;
+ if(!addr_tree_insert(z->override_tree,
+ (struct addr_tree_node*)n, &addr, addrlen, net)) {
+ lock_rw_unlock(&z->lock);
+ log_err("duplicate local-zone-override %s %s",
+ zname, netblock);
+ return 1;
+ }
+ }
+
+ lock_rw_unlock(&z->lock);
+ return 1;
+}
+
/** parse local-zone: statements */
static int
lz_enter_zones(struct local_zones* zones, struct config_file* cfg)
@@ -684,6 +806,19 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg)
return 1;
}
+/** parse local-zone-override: statements */
+static int
+lz_enter_overrides(struct local_zones* zones, struct config_file* cfg)
+{
+ struct config_str3list* p;
+ for(p = cfg->local_zone_overrides; p; p = p->next) {
+ if(!lz_enter_override(zones, p->str, p->str2, p->str3,
+ LDNS_RR_CLASS_IN))
+ return 0;
+ }
+ return 1;
+}
+
/** setup parent pointers, so that a lookup can be done for closest match */
static void
init_parents(struct local_zones* zones)
@@ -713,6 +848,9 @@ init_parents(struct local_zones* zones)
break;
}
prev = node;
+
+ if(node->override_tree)
+ addr_tree_init_parents(node->override_tree);
lock_rw_unlock(&node->lock);
}
lock_rw_unlock(&zones->lock);
@@ -800,6 +938,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)
@@ -835,6 +989,10 @@ local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
if(!lz_enter_defaults(zones, cfg)) {
return 0;
}
+ /* enter local zone overrides */
+ if(!lz_enter_overrides(zones, cfg)) {
+ return 0;
+ }
/* create implicit transparent zone from data. */
if(!lz_setup_implicit(zones, cfg)) {
return 0;
@@ -842,6 +1000,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;
@@ -855,33 +1017,41 @@ struct local_zone*
local_zones_lookup(struct local_zones* zones,
uint8_t* name, size_t len, int labs, uint16_t dclass)
{
+ return local_zones_tags_lookup(zones, name, len, labs,
+ dclass, NULL, 0, 1);
+}
+
+struct local_zone*
+local_zones_tags_lookup(struct local_zones* zones,
+ uint8_t* name, size_t len, int labs, uint16_t dclass,
+ uint8_t* taglist, size_t taglen, int ignoretags)
+{
rbnode_t* res = NULL;
struct local_zone *result;
struct local_zone key;
+ int m;
key.node.key = &key;
key.dclass = dclass;
key.name = name;
key.namelen = len;
key.namelabs = labs;
- if(rbtree_find_less_equal(&zones->ztree, &key, &res)) {
- /* exact */
- return (struct local_zone*)res;
- } else {
- /* smaller element (or no element) */
- int m;
- result = (struct local_zone*)res;
- if(!result || result->dclass != dclass)
- return NULL;
- /* count number of labels matched */
- (void)dname_lab_cmp(result->name, result->namelabs, key.name,
- key.namelabs, &m);
- while(result) { /* go up until qname is subdomain of zone */
- if(result->namelabs <= m)
- break;
- result = result->parent;
- }
- return result;
- }
+ rbtree_find_less_equal(&zones->ztree, &key, &res);
+ result = (struct local_zone*)res;
+ /* exact or smaller element (or no element) */
+ if(!result || result->dclass != dclass)
+ return NULL;
+ /* count number of labels matched */
+ (void)dname_lab_cmp(result->name, result->namelabs, key.name,
+ key.namelabs, &m);
+ while(result) { /* go up until qname is zone or subdomain of zone */
+ if(result->namelabs <= m)
+ if(ignoretags || !result->taglist ||
+ taglist_intersect(result->taglist,
+ result->taglen, taglist, taglen))
+ break;
+ result = result->parent;
+ }
+ return result;
}
struct local_zone*
@@ -953,6 +1123,18 @@ void local_zones_print(struct local_zones* zones)
log_nametypeclass(0, "inform_deny zone",
z->name, 0, z->dclass);
break;
+ case local_zone_always_transparent:
+ log_nametypeclass(0, "always_transparent zone",
+ z->name, 0, z->dclass);
+ break;
+ case local_zone_always_refuse:
+ log_nametypeclass(0, "always_refuse zone",
+ z->name, 0, z->dclass);
+ break;
+ case local_zone_always_nxdomain:
+ log_nametypeclass(0, "always_nxdomain zone",
+ z->name, 0, z->dclass);
+ break;
default:
log_nametypeclass(0, "badtyped zone",
z->name, 0, z->dclass);
@@ -986,7 +1168,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,
@@ -997,11 +1180,99 @@ local_encode(struct query_info* qinfo, struct edns_data* edns,
return 1;
}
+/** find local data tag string match for the given type in the list */
+static int
+find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
+ struct ub_packed_rrset_key* r, struct regional* temp,
+ uint8_t* zname, size_t zlen)
+{
+ struct config_strlist* p;
+ char buf[65536];
+ uint8_t rr[LDNS_RR_BUF_SIZE];
+ size_t len;
+ int res;
+ struct packed_rrset_data* d;
+ for(p=list; p; p=p->next) {
+ len = sizeof(rr);
+ /* does this element match the type? */
+ snprintf(buf, sizeof(buf), ". %s", p->str);
+ res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600,
+ zname, zlen, NULL, 0);
+ if(res != 0)
+ /* parse errors are already checked before, in
+ * acllist check_data, skip this for robustness */
+ continue;
+ if(len < 1 /* . */ + 8 /* typeclassttl*/ + 2 /*rdatalen*/)
+ continue;
+ if(sldns_wirerr_get_type(rr, len, 1) != qinfo->qtype)
+ continue;
+
+ /* do we have entries already? if not setup key */
+ if(r->rk.dname == NULL) {
+ r->entry.key = r;
+ r->rk.dname = qinfo->qname;
+ r->rk.dname_len = qinfo->qname_len;
+ r->rk.type = htons(qinfo->qtype);
+ r->rk.rrset_class = htons(qinfo->qclass);
+ r->rk.flags = 0;
+ d = (struct packed_rrset_data*)regional_alloc_zero(
+ temp, sizeof(struct packed_rrset_data)
+ + sizeof(size_t) + sizeof(uint8_t*) +
+ sizeof(time_t));
+ if(!d) return 0; /* out of memory */
+ r->entry.data = d;
+ d->ttl = sldns_wirerr_get_ttl(rr, len, 1);
+ d->rr_len = (size_t*)((uint8_t*)d +
+ sizeof(struct packed_rrset_data));
+ d->rr_data = (uint8_t**)&(d->rr_len[1]);
+ d->rr_ttl = (time_t*)&(d->rr_data[1]);
+ }
+ d = (struct packed_rrset_data*)r->entry.data;
+ /* add entry to the data */
+ if(d->count != 0) {
+ size_t* oldlen = d->rr_len;
+ uint8_t** olddata = d->rr_data;
+ time_t* oldttl = d->rr_ttl;
+ /* increase arrays for lookup */
+ /* this is of course slow for very many records,
+ * but most redirects are expected with few records */
+ d->rr_len = (size_t*)regional_alloc_zero(temp,
+ (d->count+1)*sizeof(size_t));
+ d->rr_data = (uint8_t**)regional_alloc_zero(temp,
+ (d->count+1)*sizeof(uint8_t*));
+ d->rr_ttl = (time_t*)regional_alloc_zero(temp,
+ (d->count+1)*sizeof(time_t));
+ if(!d->rr_len || !d->rr_data || !d->rr_ttl)
+ return 0; /* out of memory */
+ /* first one was allocated after struct d, but new
+ * ones get their own array increment alloc, so
+ * copy old content */
+ memmove(d->rr_len, oldlen, d->count*sizeof(size_t));
+ memmove(d->rr_data, olddata, d->count*sizeof(uint8_t*));
+ memmove(d->rr_ttl, oldttl, d->count*sizeof(time_t));
+ }
+
+ d->rr_len[d->count] = sldns_wirerr_get_rdatalen(rr, len, 1)+2;
+ d->rr_ttl[d->count] = sldns_wirerr_get_ttl(rr, len, 1);
+ d->rr_data[d->count] = regional_alloc_init(temp,
+ sldns_wirerr_get_rdatawl(rr, len, 1),
+ d->rr_len[d->count]);
+ if(!d->rr_data[d->count])
+ if(!d) return 0; /* out of memory */
+ d->count++;
+ }
+ if(r->rk.dname)
+ return 1;
+ return 0;
+}
+
/** answer local data match */
static int
local_data_answer(struct local_zone* z, struct query_info* qinfo,
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
- int labs, struct local_data** ldp)
+ int labs, struct local_data** ldp, enum localzone_type lz_type,
+ int tag, struct config_strlist** tag_datas, size_t tag_datas_size,
+ char** tagname, int num_tags)
{
struct local_data key;
struct local_data* ld;
@@ -1010,10 +1281,21 @@ local_data_answer(struct local_zone* z, struct query_info* qinfo,
key.name = qinfo->qname;
key.namelen = qinfo->qname_len;
key.namelabs = labs;
- if(z->type == local_zone_redirect) {
+ if(lz_type == local_zone_redirect) {
key.name = z->name;
key.namelen = z->namelen;
key.namelabs = z->namelabs;
+ if(tag != -1 && (size_t)tag<tag_datas_size && tag_datas[tag]) {
+ struct ub_packed_rrset_key r;
+ memset(&r, 0, sizeof(r));
+ if(find_tag_datas(qinfo, tag_datas[tag], &r, temp,
+ z->name, z->namelen)) {
+ verbose(VERB_ALGO, "redirect with tag data [%d] %s",
+ tag, (tag<num_tags?tagname[tag]:"null"));
+ return local_encode(qinfo, edns, buf, temp,
+ &r, 1, LDNS_RCODE_NOERROR);
+ }
+ }
}
ld = (struct local_data*)rbtree_search(&z->data, &key.node);
*ldp = ld;
@@ -1023,7 +1305,7 @@ local_data_answer(struct local_zone* z, struct query_info* qinfo,
lr = local_data_find_type(ld, qinfo->qtype);
if(!lr)
return 0;
- if(z->type == local_zone_redirect) {
+ if(lz_type == local_zone_redirect) {
/* convert rrset name to query name; like a wildcard */
struct ub_packed_rrset_key r = *lr->rrset;
r.rk.dname = qinfo->qname;
@@ -1043,25 +1325,28 @@ local_data_answer(struct local_zone* z, struct query_info* qinfo,
* @param buf: buffer for answer.
* @param temp: temp region for encoding
* @param ld: local data, if NULL, no such name exists in localdata.
+ * @param lz_type: type of the local zone
* @return 1 if a reply is to be sent, 0 if not.
*/
static int
lz_zone_answer(struct local_zone* z, struct query_info* qinfo,
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
- struct local_data* ld)
+ struct local_data* ld, enum localzone_type lz_type)
{
- if(z->type == local_zone_deny || z->type == local_zone_inform_deny) {
+ if(lz_type == local_zone_deny || lz_type == local_zone_inform_deny) {
/** no reply at all, signal caller by clearing buffer. */
sldns_buffer_clear(buf);
sldns_buffer_flip(buf);
return 1;
- } else if(z->type == local_zone_refuse) {
+ } else if(lz_type == local_zone_refuse
+ || lz_type == local_zone_always_refuse) {
error_encode(buf, (LDNS_RCODE_REFUSED|BIT_AA), qinfo,
*(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2), edns);
return 1;
- } else if(z->type == local_zone_static ||
- z->type == local_zone_redirect) {
+ } else if(lz_type == local_zone_static ||
+ lz_type == local_zone_redirect ||
+ lz_type == local_zone_always_nxdomain) {
/* for static, reply nodata or nxdomain
* for redirect, reply nodata */
/* no additional section processing,
@@ -1069,7 +1354,8 @@ lz_zone_answer(struct local_zone* z, struct query_info* qinfo,
* or using closest match for NSEC.
* or using closest match for returning delegation downwards
*/
- int rcode = ld?LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
+ int rcode = (ld || lz_type == local_zone_redirect)?
+ LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
if(z->soa)
return local_encode(qinfo, edns, buf, temp,
z->soa, 0, rcode);
@@ -1077,11 +1363,12 @@ lz_zone_answer(struct local_zone* z, struct query_info* qinfo,
*(uint16_t*)sldns_buffer_begin(buf),
sldns_buffer_read_u16_at(buf, 2), edns);
return 1;
- } else if(z->type == local_zone_typetransparent) {
+ } else if(lz_type == local_zone_typetransparent
+ || lz_type == local_zone_always_transparent) {
/* no NODATA or NXDOMAINS for this zone type */
return 0;
}
- /* else z->type == local_zone_transparent */
+ /* else lz_type == local_zone_transparent */
/* if the zone is transparent and the name exists, but the type
* does not, then we should make this noerror/nodata */
@@ -1115,21 +1402,70 @@ lz_inform_print(struct local_zone* z, struct query_info* qinfo,
log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
}
+static enum localzone_type
+lz_type(uint8_t *taglist, size_t taglen, uint8_t *taglist2, size_t taglen2,
+ uint8_t *tagactions, size_t tagactionssize, enum localzone_type lzt,
+ struct comm_reply* repinfo, struct rbtree_t* override_tree, int* tag,
+ char** tagname, int num_tags)
+{
+ size_t i, j;
+ uint8_t tagmatch;
+ struct local_zone_override* lzo;
+ if(repinfo && override_tree) {
+ lzo = (struct local_zone_override*)addr_tree_lookup(
+ override_tree, &repinfo->addr, repinfo->addrlen);
+ if(lzo && lzo->type) {
+ verbose(VERB_ALGO, "local zone override to type %s",
+ local_zone_type2str(lzo->type));
+ return lzo->type;
+ }
+ }
+ if(!taglist || !taglist2)
+ return lzt;
+ for(i=0; i<taglen && i<taglen2; i++) {
+ tagmatch = (taglist[i] & taglist2[i]);
+ for(j=0; j<8 && tagmatch>0; j++) {
+ if((tagmatch & 0x1)) {
+ *tag = (int)(i*8+j);
+ verbose(VERB_ALGO, "matched tag [%d] %s",
+ *tag, (*tag<num_tags?tagname[*tag]:"null"));
+ /* does this tag have a tag action? */
+ if(i*8+j < tagactionssize && tagactions
+ && tagactions[i*8+j] != 0) {
+ verbose(VERB_ALGO, "tag action [%d] %s to type %s",
+ *tag, (*tag<num_tags?tagname[*tag]:"null"),
+ local_zone_type2str(
+ (enum localzone_type)
+ tagactions[i*8+j]));
+ return (enum localzone_type)tagactions[i*8+j];
+ }
+ return lzt;
+ }
+ tagmatch >>= 1;
+ }
+ }
+ return lzt;
+}
+
int
local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
- struct comm_reply* repinfo)
+ struct comm_reply* repinfo, uint8_t* taglist, size_t taglen,
+ uint8_t* tagactions, size_t tagactionssize,
+ struct config_strlist** tag_datas, size_t tag_datas_size,
+ char** tagname, int num_tags)
{
/* see if query is covered by a zone,
* if so: - try to match (exact) local data
* - look at zone type for negative response. */
int labs = dname_count_labels(qinfo->qname);
- struct local_data* ld;
+ struct local_data* ld = NULL;
struct local_zone* z;
- int r;
+ enum localzone_type lzt;
+ int r, tag = -1;
lock_rw_rdlock(&zones->lock);
- z = local_zones_lookup(zones, qinfo->qname,
- qinfo->qname_len, labs, qinfo->qclass);
+ z = local_zones_tags_lookup(zones, qinfo->qname,
+ qinfo->qname_len, labs, qinfo->qclass, taglist, taglen, 0);
if(!z) {
lock_rw_unlock(&zones->lock);
return 0;
@@ -1137,15 +1473,22 @@ local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
lock_rw_rdlock(&z->lock);
lock_rw_unlock(&zones->lock);
- if((z->type == local_zone_inform || z->type == local_zone_inform_deny)
+ lzt = lz_type(taglist, taglen, z->taglist, z->taglen, tagactions,
+ tagactionssize, z->type, repinfo, z->override_tree, &tag,
+ tagname, num_tags);
+
+ if((lzt == local_zone_inform || lzt == local_zone_inform_deny)
&& repinfo)
lz_inform_print(z, qinfo, repinfo);
- if(local_data_answer(z, qinfo, edns, buf, temp, labs, &ld)) {
+ if(lzt != local_zone_always_refuse && lzt != local_zone_always_transparent
+ && lzt != local_zone_always_nxdomain
+ && local_data_answer(z, qinfo, edns, buf, temp, labs, &ld, lzt,
+ tag, tag_datas, tag_datas_size, tagname, num_tags)) {
lock_rw_unlock(&z->lock);
return 1;
}
- r = lz_zone_answer(z, qinfo, edns, buf, temp, ld);
+ r = lz_zone_answer(z, qinfo, edns, buf, temp, ld, lzt);
lock_rw_unlock(&z->lock);
return r;
}
@@ -1162,6 +1505,9 @@ const char* local_zone_type2str(enum localzone_type t)
case local_zone_nodefault: return "nodefault";
case local_zone_inform: return "inform";
case local_zone_inform_deny: return "inform_deny";
+ case local_zone_always_transparent: return "always_transparent";
+ case local_zone_always_refuse: return "always_refuse";
+ case local_zone_always_nxdomain: return "always_nxdomain";
}
return "badtyped";
}
@@ -1184,6 +1530,12 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
*t = local_zone_inform;
else if(strcmp(type, "inform_deny") == 0)
*t = local_zone_inform_deny;
+ else if(strcmp(type, "always_transparent") == 0)
+ *t = local_zone_always_transparent;
+ else if(strcmp(type, "always_refuse") == 0)
+ *t = local_zone_always_refuse;
+ else if(strcmp(type, "always_nxdomain") == 0)
+ *t = local_zone_always_nxdomain;
else return 0;
return 1;
}
@@ -1220,7 +1572,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 */
diff --git a/contrib/unbound/services/localzone.h b/contrib/unbound/services/localzone.h
index 3d62a69..69fdbee 100644
--- a/contrib/unbound/services/localzone.h
+++ b/contrib/unbound/services/localzone.h
@@ -43,6 +43,7 @@
#define SERVICES_LOCALZONE_H
#include "util/rbtree.h"
#include "util/locks.h"
+#include "util/storage/dnstree.h"
struct ub_packed_rrset_key;
struct regional;
struct config_file;
@@ -50,6 +51,7 @@ struct edns_data;
struct query_info;
struct sldns_buffer;
struct comm_reply;
+struct config_strlist;
/**
* Local zone type
@@ -75,7 +77,13 @@ enum localzone_type {
/** log client address, but no block (transparent) */
local_zone_inform,
/** log client address, and block (drop) */
- local_zone_inform_deny
+ local_zone_inform_deny,
+ /** resolve normally, even when there is local data */
+ local_zone_always_transparent,
+ /** answer with error, even when there is local data */
+ local_zone_always_refuse,
+ /** answer with nxdomain, even when there is local data */
+ local_zone_always_nxdomain
};
/**
@@ -115,6 +123,13 @@ 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;
+ /** netblock addr_tree with struct local_zone_override information
+ * or NULL if there are no override elements */
+ struct rbtree_t* override_tree;
/** in this region the zone's data is allocated.
* the struct local_zone itself is malloced. */
@@ -154,6 +169,16 @@ struct local_rrset {
};
/**
+ * Local zone override information
+ */
+struct local_zone_override {
+ /** node in addrtree */
+ struct addr_tree_node node;
+ /** override for local zone type */
+ enum localzone_type type;
+};
+
+/**
* Create local zones storage
* @return new struct or NULL on error.
*/
@@ -198,6 +223,24 @@ int local_data_cmp(const void* d1, const void* d2);
void local_zone_delete(struct local_zone* z);
/**
+ * Lookup zone that contains the given name, class and taglist.
+ * User must lock the tree or result zone.
+ * @param zones: the zones tree
+ * @param name: dname to lookup
+ * @param len: length of name.
+ * @param labs: labelcount of name.
+ * @param dclass: class to lookup.
+ * @param taglist: taglist to lookup.
+ * @param taglen: lenth of taglist.
+ * @param ignoretags: lookup zone by name and class, regardless the
+ * local-zone's tags.
+ * @return closest local_zone or NULL if no covering zone is found.
+ */
+struct local_zone* local_zones_tags_lookup(struct local_zones* zones,
+ uint8_t* name, size_t len, int labs, uint16_t dclass,
+ uint8_t* taglist, size_t taglen, int ignoretags);
+
+/**
* Lookup zone that contains the given name, class.
* User must lock the tree or result zone.
* @param zones: the zones tree
@@ -226,13 +269,24 @@ void local_zones_print(struct local_zones* zones);
* @param buf: buffer with query ID and flags, also for reply.
* @param temp: temporary storage region.
* @param repinfo: source address for checks. may be NULL.
+ * @param taglist: taglist for checks. May be NULL.
+ * @param taglen: length of the taglist.
+ * @param tagactions: local zone actions for tags. May be NULL.
+ * @param tagactionssize: length of the tagactions.
+ * @param tag_datas: array per tag of strlist with rdata strings. or NULL.
+ * @param tag_datas_size: size of tag_datas array.
+ * @param tagname: array of tag name strings (for debug output).
+ * @param num_tags: number of items in tagname array.
* @return true if answer is in buffer. false if query is not answered
* by authority data. If the reply should be dropped altogether, the return
* value is true, but the buffer is cleared (empty).
*/
int local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
struct edns_data* edns, struct sldns_buffer* buf, struct regional* temp,
- struct comm_reply* repinfo);
+ struct comm_reply* repinfo, uint8_t* taglist, size_t taglen,
+ uint8_t* tagactions, size_t tagactionssize,
+ struct config_strlist** tag_datas, size_t tag_datas_size,
+ char** tagname, int num_tags);
/**
* Parse the string into localzone type.
diff --git a/contrib/unbound/services/mesh.c b/contrib/unbound/services/mesh.c
index 8076874..b0434b3 100644
--- a/contrib/unbound/services/mesh.c
+++ b/contrib/unbound/services/mesh.c
@@ -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;
-
}
/**
@@ -1050,6 +1069,12 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
*ev = module_event_pass;
return 1;
}
+ if(s == module_wait_subquery && mstate->sub_set.count == 0) {
+ log_err("module cannot wait for subquery, subquery list empty");
+ log_query_info(VERB_QUERY, "pass error for qstate",
+ &mstate->s.qinfo);
+ s = module_error;
+ }
if(s == module_error && mstate->s.return_rcode == LDNS_RCODE_NOERROR) {
/* error is bad, handle pass back up below */
mstate->s.return_rcode = LDNS_RCODE_SERVFAIL;
diff --git a/contrib/unbound/services/modstack.c b/contrib/unbound/services/modstack.c
index 49bb2fd..70e0666 100644
--- a/contrib/unbound/services/modstack.c
+++ b/contrib/unbound/services/modstack.c
@@ -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
@@ -121,6 +124,9 @@ module_list_avail(void)
#ifdef WITH_PYTHONMODULE
"python",
#endif
+#ifdef USE_CACHEDB
+ "cachedb",
+#endif
"validator",
"iterator",
NULL};
@@ -139,6 +145,9 @@ module_funcs_avail(void)
#ifdef WITH_PYTHONMODULE
&pythonmod_get_funcblock,
#endif
+#ifdef USE_CACHEDB
+ &cachedb_get_funcblock,
+#endif
&val_get_funcblock,
&iter_get_funcblock,
NULL};
diff --git a/contrib/unbound/services/outside_network.c b/contrib/unbound/services/outside_network.c
index b5e0b2d..dd25ab3 100644
--- a/contrib/unbound/services/outside_network.c
+++ b/contrib/unbound/services/outside_network.c
@@ -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);
}
@@ -241,7 +243,33 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
return 0;
fd_set_nonblock(s);
+#ifdef USE_OSX_MSG_FASTOPEN
+ /* API for fast open is different here. We use a connectx() function and
+ then writes can happen as normal even using SSL.*/
+ /* connectx requires that the len be set in the sockaddr struct*/
+ struct sockaddr_in *addr_in = (struct sockaddr_in *)&w->addr;
+ addr_in->sin_len = w->addrlen;
+ sa_endpoints_t endpoints;
+ endpoints.sae_srcif = 0;
+ endpoints.sae_srcaddr = NULL;
+ endpoints.sae_srcaddrlen = 0;
+ endpoints.sae_dstaddr = (struct sockaddr *)&w->addr;
+ endpoints.sae_dstaddrlen = w->addrlen;
+ if (connectx(s, &endpoints, SAE_ASSOCID_ANY,
+ CONNECT_DATA_IDEMPOTENT | CONNECT_RESUME_ON_READ_WRITE,
+ NULL, 0, NULL, NULL) == -1) {
+#else /* USE_OSX_MSG_FASTOPEN*/
+#ifdef USE_MSG_FASTOPEN
+ pend->c->tcp_do_fastopen = 1;
+ /* Only do TFO for TCP in which case no connect() is required here.
+ Don't combine client TFO with SSL, since OpenSSL can't
+ currently support doing a handshake on fd that already isn't connected*/
+ if (w->outnet->sslctx && w->ssl_upstream) {
+ if(connect(s, (struct sockaddr*)&w->addr, w->addrlen) == -1) {
+#else /* USE_MSG_FASTOPEN*/
if(connect(s, (struct sockaddr*)&w->addr, w->addrlen) == -1) {
+#endif /* USE_MSG_FASTOPEN*/
+#endif /* USE_OSX_MSG_FASTOPEN*/
#ifndef USE_WINSOCK
#ifdef EINPROGRESS
if(errno != EINPROGRESS) {
@@ -261,6 +289,9 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
return 0;
}
}
+#ifdef USE_MSG_FASTOPEN
+ }
+#endif /* USE_MSG_FASTOPEN */
if(w->outnet->sslctx && w->ssl_upstream) {
pend->c->ssl = outgoing_ssl_fd(w->outnet->sslctx, s);
if(!pend->c->ssl) {
@@ -589,7 +620,9 @@ static int setup_if(struct port_if* pif, const char* addrstr,
pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int));
if(!pif->avail_ports)
return 0;
- if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen))
+ if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) &&
+ !netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT,
+ &pif->addr, &pif->addrlen, &pif->pfxlen))
return 0;
pif->maxout = (int)numfd;
pif->inuse = 0;
@@ -757,6 +790,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);
@@ -890,32 +924,55 @@ pending_delete(struct outside_network* outnet, struct pending* p)
free(p);
}
+static void
+sai6_putrandom(struct sockaddr_in6 *sa, int pfxlen, struct ub_randstate *rnd)
+{
+ int i, last;
+ if(!(pfxlen > 0 && pfxlen < 128))
+ return;
+ for(i = 0; i < (128 - pfxlen) / 8; i++) {
+ sa->sin6_addr.s6_addr[15-i] = (uint8_t)ub_random_max(rnd, 256);
+ }
+ last = pfxlen & 7;
+ if(last != 0) {
+ sa->sin6_addr.s6_addr[15-i] |=
+ ((0xFF >> last) & ub_random_max(rnd, 256));
+ }
+}
+
/**
* Try to open a UDP socket for outgoing communication.
* Sets sockets options as needed.
* @param addr: socket address.
* @param addrlen: length of address.
+ * @param pfxlen: length of network prefix (for address randomisation).
* @param port: port override for addr.
* @param inuse: if -1 is returned, this bool means the port was in use.
+ * @param rnd: random state (for address randomisation).
* @return fd or -1
*/
static int
-udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int port,
- int* inuse)
+udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen,
+ int port, int* inuse, struct ub_randstate* rnd)
{
int fd, noproto;
if(addr_is_ip6(addr, addrlen)) {
- struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
- sa->sin6_port = (in_port_t)htons((uint16_t)port);
+ int freebind = 0;
+ struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
+ sa.sin6_port = (in_port_t)htons((uint16_t)port);
+ if(pfxlen != 0) {
+ freebind = 1;
+ sai6_putrandom(&sa, pfxlen, rnd);
+ }
fd = create_udp_sock(AF_INET6, SOCK_DGRAM,
- (struct sockaddr*)addr, addrlen, 1, inuse, &noproto,
- 0, 0, 0, NULL, 0);
+ (struct sockaddr*)&sa, addrlen, 1, inuse, &noproto,
+ 0, 0, 0, NULL, 0, freebind);
} 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;
}
@@ -975,7 +1032,8 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
/* try to open new port, if fails, loop to try again */
log_assert(pif->inuse < pif->maxout);
portno = pif->avail_ports[my_port - pif->inuse];
- fd = udp_sockport(&pif->addr, pif->addrlen, portno, &inuse);
+ fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
+ portno, &inuse, outnet->rnd);
if(fd == -1 && !inuse) {
/* nonrecoverable error making socket */
return 0;
@@ -1219,7 +1277,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 +1288,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 +1297,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 +1327,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;
@@ -1346,6 +1416,7 @@ serviced_perturb_qname(struct ub_randstate* rnd, uint8_t* qbuf, size_t len)
long int random = 0;
int bits = 0;
log_assert(len >= 10 + 5 /* offset qname, root, qtype, qclass */);
+ (void)len;
lablen = *d++;
while(lablen) {
while(lablen--) {
@@ -1394,6 +1465,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 +1599,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 +1783,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 +1891,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 +1988,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 +2006,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 +2063,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);
}
}
diff --git a/contrib/unbound/services/outside_network.h b/contrib/unbound/services/outside_network.h
index 36f798d..d6a448c 100644
--- a/contrib/unbound/services/outside_network.h
+++ b/contrib/unbound/services/outside_network.h
@@ -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.
@@ -164,6 +165,10 @@ struct port_if {
/** length of addr field */
socklen_t addrlen;
+ /** prefix length of network address (in bits), for randomisation.
+ * if 0, no randomisation. */
+ int pfxlen;
+
/** the available ports array. These are unused.
* Only the first total-inuse part is filled. */
int* avail_ports;
@@ -367,6 +372,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 +484,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 +501,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);
/**
diff --git a/contrib/unbound/sldns/keyraw.c b/contrib/unbound/sldns/keyraw.c
index 59e8000..e8f2da0 100644
--- a/contrib/unbound/sldns/keyraw.c
+++ b/contrib/unbound/sldns/keyraw.c
@@ -23,6 +23,15 @@
#ifdef HAVE_OPENSSL_ENGINE_H
# include <openssl/engine.h>
#endif
+#ifdef HAVE_OPENSSL_BN_H
+#include <openssl/bn.h>
+#endif
+#ifdef HAVE_OPENSSL_RSA_H
+#include <openssl/rsa.h>
+#endif
+#ifdef HAVE_OPENSSL_DSA_H
+#include <openssl/dsa.h>
+#endif
#endif /* HAVE_SSL */
size_t
@@ -206,7 +215,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())) {
@@ -216,6 +224,7 @@ sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
BN_free(Y);
return NULL;
}
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
#ifndef S_SPLINT_S
dsa->p = P;
dsa->q = Q;
@@ -223,6 +232,25 @@ sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
dsa->pub_key = Y;
#endif /* splint */
+#else /* OPENSSL_VERSION_NUMBER */
+ if (!DSA_set0_pqg(dsa, P, Q, G)) {
+ /* QPG not yet attached, need to free */
+ BN_free(Q);
+ BN_free(P);
+ BN_free(G);
+
+ DSA_free(dsa);
+ BN_free(Y);
+ return NULL;
+ }
+ if (!DSA_set0_key(dsa, Y, NULL)) {
+ /* QPG attached, cleaned up by DSA_fre() */
+ DSA_free(dsa);
+ BN_free(Y);
+ return NULL;
+ }
+#endif
+
return dsa;
}
@@ -274,11 +302,21 @@ sldns_key_buf2rsa_raw(unsigned char* key, size_t len)
BN_free(modulus);
return NULL;
}
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
#ifndef S_SPLINT_S
rsa->n = modulus;
rsa->e = exponent;
#endif /* splint */
+#else /* OPENSSL_VERSION_NUMBER */
+ if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
+ BN_free(exponent);
+ BN_free(modulus);
+ RSA_free(rsa);
+ return NULL;
+ }
+#endif
+
return rsa;
}
diff --git a/contrib/unbound/sldns/parseutil.c b/contrib/unbound/sldns/parseutil.c
index 2a2ebbb..3271761 100644
--- a/contrib/unbound/sldns/parseutil.c
+++ b/contrib/unbound/sldns/parseutil.c
@@ -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:
diff --git a/contrib/unbound/sldns/rrdef.h b/contrib/unbound/sldns/rrdef.h
index d9302ec..00c01e6 100644
--- a/contrib/unbound/sldns/rrdef.h
+++ b/contrib/unbound/sldns/rrdef.h
@@ -195,7 +195,7 @@ enum sldns_enum_rr_type
LDNS_RR_TYPE_TALINK = 58,
LDNS_RR_TYPE_CDS = 59, /** RFC 7344 */
LDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */
- LDNS_RR_TYPE_OPENPGPKEY = 61, /* draft-ietf-dane-openpgpkey */
+ LDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */
LDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */
LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */
@@ -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;
diff --git a/contrib/unbound/sldns/str2wire.c b/contrib/unbound/sldns/str2wire.c
index c541083..e624e26 100644
--- a/contrib/unbound/sldns/str2wire.c
+++ b/contrib/unbound/sldns/str2wire.c
@@ -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;
}
diff --git a/contrib/unbound/sldns/wire2str.c b/contrib/unbound/sldns/wire2str.c
index 5cbd78e..639f56f 100644
--- a/contrib/unbound/sldns/wire2str.c
+++ b/contrib/unbound/sldns/wire2str.c
@@ -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);
diff --git a/contrib/unbound/sldns/wire2str.h b/contrib/unbound/sldns/wire2str.h
index 67f5435..c477f06 100644
--- a/contrib/unbound/sldns/wire2str.h
+++ b/contrib/unbound/sldns/wire2str.h
@@ -118,7 +118,7 @@ int sldns_str_print(char** str, size_t* slen, const char* format, ...)
* @param str_len: the size of the string buffer. If more is needed, it'll
* silently truncate the output to fit in the buffer.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_pkt_buf(uint8_t* data, size_t data_len, char* str,
size_t str_len);
@@ -351,7 +351,7 @@ int sldns_wire2str_edns_option_code_print(char** str, size_t* str_len,
* @param str_len: the size of the string buffer. If more is needed, it'll
* silently truncate the output to fit in the buffer.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str,
size_t str_len);
@@ -369,7 +369,7 @@ int sldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str,
* @param str_len: the size of the string buffer. If more is needed, it'll
* silently truncate the output to fit in the buffer.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_rr_unknown_buf(uint8_t* rr, size_t rr_len, char* str,
size_t str_len);
@@ -389,7 +389,7 @@ int sldns_wire2str_rr_unknown_buf(uint8_t* rr, size_t rr_len, char* str,
* @param str_len: the size of the string buffer. If more is needed, it'll
* silently truncate the output to fit in the buffer.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rr_len, size_t dname_len,
char* str, size_t str_len);
@@ -406,7 +406,7 @@ int sldns_wire2str_rr_comment_buf(uint8_t* rr, size_t rr_len, size_t dname_len,
* silently truncate the output to fit in the buffer.
* @param rrtype: rr type of the data
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str,
size_t str_len, uint16_t rrtype);
@@ -417,7 +417,7 @@ int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str,
* @param str: the string to write to.
* @param len: length of str.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_type_buf(uint16_t rrtype, char* str, size_t len);
@@ -427,7 +427,7 @@ int sldns_wire2str_type_buf(uint16_t rrtype, char* str, size_t len);
* @param str: the string to write to.
* @param len: length of str.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len);
@@ -437,7 +437,7 @@ int sldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len);
* @param str: the string to write to.
* @param len: length of str.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_rcode_buf(int rcode, char* str, size_t len);
@@ -448,7 +448,7 @@ int sldns_wire2str_rcode_buf(int rcode, char* str, size_t len);
* @param str: the string to write to.
* @param len: length of string.
* @return the number of characters for this element, excluding zerobyte.
- * Is larger than str_len if output was truncated.
+ * Is larger or equal than str_len if output was truncated.
*/
int sldns_wire2str_dname_buf(uint8_t* dname, size_t dname_len, char* str,
size_t len);
diff --git a/contrib/unbound/smallapp/unbound-anchor.c b/contrib/unbound/smallapp/unbound-anchor.c
index 81bb896..68e8e40 100644
--- a/contrib/unbound/smallapp/unbound-anchor.c
+++ b/contrib/unbound/smallapp/unbound-anchor.c
@@ -37,7 +37,8 @@
* \file
*
* This file checks to see that the current 5011 keys work to prime the
- * current root anchor. If not a certificate is used to update the anchor.
+ * current root anchor. If not a certificate is used to update the anchor,
+ * with RFC7958 https xml fetch.
*
* This is a concept solution for distribution of the DNSSEC root
* trust anchor. It is a small tool, called "unbound-anchor", that
@@ -47,7 +48,7 @@
* Management-Abstract:
* * first run: fill root.key file with hardcoded DS record.
* * mostly: use RFC5011 tracking, quick . DNSKEY UDP query.
- * * failover: use builtin certificate, do https and update.
+ * * failover: use RFC7958 builtin certificate, do https and update.
* Special considerations:
* * 30-days RFC5011 timer saves a lot of https traffic.
* * DNSKEY probe must be NOERROR, saves a lot of https traffic.
@@ -77,7 +78,7 @@
* the file contains a list of normal DNSKEY/DS records, and uses that to
* bootstrap 5011 (the KSK is made VALID).
*
- * The certificate update is done by fetching root-anchors.xml and
+ * The certificate RFC7958 update is done by fetching root-anchors.xml and
* root-anchors.p7s via SSL. The HTTPS certificate can be logged but is
* not validated (https for channel security; the security comes from the
* certificate). The 'data.iana.org' domain name A and AAAA are resolved
@@ -171,7 +172,7 @@ struct ip_list {
/** Give unbound-anchor usage, and exit (1). */
static void
-usage()
+usage(void)
{
printf("Usage: unbound-anchor [opts]\n");
printf(" Setup or update root anchor. "
@@ -419,7 +420,7 @@ read_builtin_cert(void)
{
const char* builtin_cert = get_builtin_cert();
STACK_OF(X509)* sk;
- BIO *bio = BIO_new_mem_buf((void*)builtin_cert,
+ BIO *bio = BIO_new_mem_buf(builtin_cert,
(int)strlen(builtin_cert));
if(!bio) {
if(verb) printf("out of memory\n");
@@ -1836,7 +1837,7 @@ write_unsigned_root(const char* root_anchor_file)
#ifdef HAVE_FSYNC
fsync(fileno(out));
#else
- FlushFileBuffers((HANDLE)_fileno(out));
+ FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
#endif
fclose(out);
}
@@ -1868,7 +1869,7 @@ write_root_anchor(const char* root_anchor_file, BIO* ds)
#ifdef HAVE_FSYNC
fsync(fileno(out));
#else
- FlushFileBuffers((HANDLE)_fileno(out));
+ FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
#endif
fclose(out);
}
@@ -2310,10 +2311,22 @@ int main(int argc, char* argv[])
if(argc != 0)
usage();
+#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
ERR_load_crypto_strings();
+#endif
ERR_load_SSL_strings();
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
OpenSSL_add_all_algorithms();
+#else
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
+ | OPENSSL_INIT_ADD_ALL_DIGESTS
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
+#else
+ (void)OPENSSL_init_ssl(0, NULL);
+#endif
if(dolist) do_list_builtin();
diff --git a/contrib/unbound/smallapp/unbound-checkconf.c b/contrib/unbound/smallapp/unbound-checkconf.c
index ec07713..51f8e64 100644
--- a/contrib/unbound/smallapp/unbound-checkconf.c
+++ b/contrib/unbound/smallapp/unbound-checkconf.c
@@ -72,7 +72,7 @@
/** Give checkconf usage, and exit (1). */
static void
-usage()
+usage(void)
{
printf("Usage: unbound-checkconf [file]\n");
printf(" Checks unbound configuration file for errors.\n");
@@ -161,6 +161,7 @@ warn_hosts(const char* typ, struct config_stub* list)
static void
interfacechecks(struct config_file* cfg)
{
+ int d;
struct sockaddr_storage a;
socklen_t alen;
int i, j;
@@ -177,8 +178,8 @@ interfacechecks(struct config_file* cfg)
}
}
for(i=0; i<cfg->num_out_ifs; i++) {
- if(!ipstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT,
- &a, &alen)) {
+ if(!ipstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, &a, &alen) &&
+ !netblockstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, &a, &alen, &d)) {
fatal_exit("cannot parse outgoing-interface "
"specified as '%s'", cfg->out_ifs[i]);
}
@@ -330,6 +331,8 @@ morechecks(struct config_file* cfg, const char* fname)
fatal_exit("num_threads value weird");
if(!cfg->do_ip4 && !cfg->do_ip6)
fatal_exit("ip4 and ip6 are both disabled, pointless");
+ if(!cfg->do_ip6 && cfg->prefer_ip6)
+ fatal_exit("cannot prefer and disable ip6, pointless");
if(!cfg->do_udp && !cfg->do_tcp)
fatal_exit("udp and tcp are both disabled, pointless");
if(cfg->edns_buffer_size > cfg->msg_buffer_size)
@@ -412,6 +415,21 @@ morechecks(struct config_file* cfg, const char* fname)
&& 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",
cfg->module_conf);
@@ -421,7 +439,9 @@ morechecks(struct config_file* cfg, const char* fname)
if(cfg->username && cfg->username[0]) {
if(getpwnam(cfg->username) == NULL)
fatal_exit("user '%s' does not exist.", cfg->username);
+# ifdef HAVE_ENDPWENT
endpwent();
+# endif
}
#endif
if(cfg->remote_control_enable && cfg->remote_control_use_cert) {
@@ -466,14 +486,22 @@ check_hints(struct config_file* cfg)
static void
checkconf(const char* cfgfile, const char* opt, int final)
{
+ char oldwd[PATH_MAX];
struct config_file* cfg = config_create();
if(!cfg)
fatal_exit("out of memory");
+ oldwd[0] = 0;
+ if(!getcwd(oldwd, sizeof(oldwd))) {
+ log_err("cannot getcwd: %s", strerror(errno));
+ oldwd[0] = 0;
+ }
if(!config_read(cfg, cfgfile, NULL)) {
/* config_read prints messages to stderr */
config_delete(cfg);
exit(1);
}
+ if(oldwd[0] && chdir(oldwd) == -1)
+ log_err("cannot chdir(%s): %s", oldwd, strerror(errno));
if(opt) {
print_option(cfg, opt, final);
config_delete(cfg);
diff --git a/contrib/unbound/smallapp/unbound-control.c b/contrib/unbound/smallapp/unbound-control.c
index fac73b0..19268ed 100644
--- a/contrib/unbound/smallapp/unbound-control.c
+++ b/contrib/unbound/smallapp/unbound-control.c
@@ -65,7 +65,7 @@
/** Give unbound-control usage, and exit (1). */
static void
-usage()
+usage(void)
{
printf("Usage: unbound-control [options] command\n");
printf(" Remote control utility for unbound server.\n");
@@ -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");
@@ -212,7 +212,7 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
struct sockaddr_un* usock = (struct sockaddr_un *) &addr;
usock->sun_family = AF_LOCAL;
#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
- usock->sun_len = (socklen_t)sizeof(usock);
+ usock->sun_len = (unsigned)sizeof(usock);
#endif
(void)strlcpy(usock->sun_path, svr, sizeof(usock->sun_path));
addrlen = (socklen_t)sizeof(struct sockaddr_un);
@@ -418,10 +418,22 @@ int main(int argc, char* argv[])
cfgfile = CONFIGFILE;
#endif
+#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
ERR_load_crypto_strings();
+#endif
ERR_load_SSL_strings();
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
OpenSSL_add_all_algorithms();
+#else
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
+ | OPENSSL_INIT_ADD_ALL_DIGESTS
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
+#else
+ (void)OPENSSL_init_ssl(0, NULL);
+#endif
if(!RAND_status()) {
/* try to seed it */
diff --git a/contrib/unbound/smallapp/unbound-host.c b/contrib/unbound/smallapp/unbound-host.c
index 30fef51..d7a36a2 100644
--- a/contrib/unbound/smallapp/unbound-host.c
+++ b/contrib/unbound/smallapp/unbound-host.c
@@ -72,7 +72,7 @@ static int verb = 0;
/** Give unbound-host usage, and exit (1). */
static void
-usage()
+usage(void)
{
printf("Usage: unbound-host [-vdhr46] [-c class] [-t type] hostname\n");
printf(" [-y key] [-f keyfile] [-F namedkeyfile]\n");
@@ -91,7 +91,7 @@ usage()
printf(" -F keyfile read named.conf-style trust anchors.\n");
printf(" -C config use the specified unbound.conf (none read by default)\n");
printf(" -r read forwarder information from /etc/resolv.conf\n");
- printf(" breaks validation if the fwder does not do DNSSEC.\n");
+ printf(" breaks validation if the forwarder does not do DNSSEC.\n");
printf(" -v be more verbose, shows nodata and security.\n");
printf(" -d debug, traces the action, -d -d shows more.\n");
printf(" -4 use ipv4 network, avoid ipv6.\n");
diff --git a/contrib/unbound/smallapp/worker_cb.c b/contrib/unbound/smallapp/worker_cb.c
index 8193bec..fd8488a 100644
--- a/contrib/unbound/smallapp/worker_cb.c
+++ b/contrib/unbound/smallapp/worker_cb.c
@@ -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))
{
@@ -223,8 +225,8 @@ struct order_id {
int order_lock_cmp(const void* e1, const void* e2)
{
- struct order_id* o1 = (struct order_id*)e1;
- struct order_id* o2 = (struct order_id*)e2;
+ const struct order_id* o1 = e1;
+ const struct order_id* o2 = e2;
if(o1->thr < o2->thr) return -1;
if(o1->thr > o2->thr) return 1;
if(o1->instance < o2->instance) return -1;
@@ -235,7 +237,7 @@ int order_lock_cmp(const void* e1, const void* e2)
int
codeline_cmp(const void* a, const void* b)
{
- return strcmp((const char*)a, (const char*)b);
+ return strcmp(a, b);
}
int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
diff --git a/contrib/unbound/util/alloc.c b/contrib/unbound/util/alloc.c
index 05d2fa3..a1152a7 100644
--- a/contrib/unbound/util/alloc.c
+++ b/contrib/unbound/util/alloc.c
@@ -64,7 +64,7 @@ alloc_setup_special(alloc_special_t* t)
* @param alloc: the structure to fill up.
*/
static void
-prealloc(struct alloc_cache* alloc)
+prealloc_setup(struct alloc_cache* alloc)
{
alloc_special_t* p;
int i;
@@ -216,7 +216,7 @@ alloc_special_obtain(struct alloc_cache* alloc)
}
}
/* allocate new */
- prealloc(alloc);
+ prealloc_setup(alloc);
if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t)))) {
log_err("alloc_special_obtain: out of memory");
return NULL;
diff --git a/contrib/unbound/util/config_file.c b/contrib/unbound/util/config_file.c
index 420dc71..688211c 100644
--- a/contrib/unbound/util/config_file.c
+++ b/contrib/unbound/util/config_file.c
@@ -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;
@@ -211,6 +212,7 @@ config_create(void)
cfg->local_zones = NULL;
cfg->local_zones_nodefault = NULL;
cfg->local_data = NULL;
+ cfg->local_zone_overrides = NULL;
cfg->unblock_lan_zones = 0;
cfg->insecure_lan_zones = 0;
cfg->python_script = NULL;
@@ -237,6 +239,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 +396,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 +477,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 +486,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 +511,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 +636,31 @@ 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 list option */
+#define O_LS3(opt, name, lst) if(strcmp(opt, name)==0) { \
+ struct config_str3list* p = cfg->lst; \
+ for(p = cfg->lst; p; p = p->next) { \
+ snprintf(buf, len, "%s %s %s", p->str, p->str2, p->str3); \
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 +694,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 +781,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 +791,12 @@ 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)
+ else O_LTG(opt, "access-control-tag", acl_tags)
+ else O_LS3(opt, "local-zone-override", local_zone_overrides)
+ else O_LS3(opt, "access-control-tag-action", acl_tag_actions)
+ else O_LS3(opt, "access-control-tag-data", acl_tag_datas)
/* not here:
* outgoing-permit, outgoing-avoid - have list of ports
* local-zone - zones and nodefault variables
@@ -911,6 +949,20 @@ config_deldblstrlist(struct config_str2list* p)
}
void
+config_deltrplstrlist(struct config_str3list* p)
+{
+ struct config_str3list *np;
+ while(p) {
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p->str3);
+ free(p);
+ p = np;
+ }
+}
+
+void
config_delstub(struct config_stub* p)
{
if(!p) return;
@@ -931,6 +983,32 @@ 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);
+}
+
+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 +1021,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 +1046,12 @@ config_delete(struct config_file* cfg)
config_deldblstrlist(cfg->local_zones);
config_delstrlist(cfg->local_zones_nodefault);
config_delstrlist(cfg->local_data);
+ config_deltrplstrlist(cfg->local_zone_overrides);
+ config_del_strarray(cfg->tagname, cfg->num_tags);
+ config_del_strbytelist(cfg->local_zone_tags);
+ config_del_strbytelist(cfg->acl_tags);
+ config_deltrplstrlist(cfg->acl_tag_actions);
+ config_deltrplstrlist(cfg->acl_tag_datas);
config_delstrlist(cfg->control_ifs);
free(cfg->server_key_file);
free(cfg->server_cert_file);
@@ -1136,6 +1210,23 @@ int cfg_strlist_append(struct config_strlist_head* list, char* item)
}
int
+cfg_region_strlist_insert(struct regional* region,
+ struct config_strlist** head, char* item)
+{
+ struct config_strlist *s;
+ if(!item || !head)
+ return 0;
+ s = (struct config_strlist*)regional_alloc_zero(region,
+ sizeof(struct config_strlist));
+ if(!s)
+ return 0;
+ s->str = item;
+ s->next = *head;
+ *head = s;
+ return 1;
+}
+
+int
cfg_strlist_insert(struct config_strlist** head, char* item)
{
struct config_strlist *s;
@@ -1166,6 +1257,42 @@ cfg_str2list_insert(struct config_str2list** head, char* item, char* i2)
return 1;
}
+int
+cfg_str3list_insert(struct config_str3list** head, char* item, char* i2,
+ char* i3)
+{
+ struct config_str3list *s;
+ if(!item || !i2 || !i3 || !head)
+ return 0;
+ s = (struct config_str3list*)calloc(1, sizeof(struct config_str3list));
+ if(!s)
+ return 0;
+ s->str = item;
+ s->str2 = i2;
+ s->str3 = i3;
+ s->next = *head;
+ *head = s;
+ 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 +1397,123 @@ 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);
+ (void)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)
{
diff --git a/contrib/unbound/util/config_file.h b/contrib/unbound/util/config_file.h
index ef823fb..07edff7 100644
--- a/contrib/unbound/util/config_file.h
+++ b/contrib/unbound/util/config_file.h
@@ -44,9 +44,12 @@
struct config_stub;
struct config_strlist;
struct config_str2list;
+struct config_str3list;
+struct config_strbytelist;
struct module_qstate;
struct sock_list;
struct ub_packed_rrset_key;
+struct regional;
/**
* The configuration options.
@@ -72,6 +75,8 @@ struct config_file {
int do_ip4;
/** do ip6 query support. */
int do_ip6;
+ /** prefer ip6 upstream queries. */
+ int prefer_ip6;
/** do udp query support. */
int do_udp;
/** do tcp query support. */
@@ -142,6 +147,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;
@@ -289,10 +296,24 @@ struct config_file {
struct config_strlist* local_zones_nodefault;
/** local data RRs configured */
struct config_strlist* local_data;
+ /** local zone override types per netblock */
+ struct config_str3list* local_zone_overrides;
/** unblock lan zones (reverse lookups for AS112 zones) */
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;
+ /** list of aclname, tagbitlist */
+ struct config_strbytelist* acl_tags;
+ /** list of aclname, tagname, localzonetype */
+ struct config_str3list* acl_tag_actions;
+ /** list of aclname, tagname, redirectdata */
+ struct config_str3list* acl_tag_datas;
+ /** 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 +379,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 +445,34 @@ struct config_str2list {
char* str2;
};
+/**
+ * List of three strings for config options
+ */
+struct config_str3list {
+ /** next item in list */
+ struct config_str3list* next;
+ /** first string */
+ char* str;
+ /** second string */
+ char* str2;
+ /** third string */
+ char* str3;
+};
+
+
+/**
+ * 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 */
@@ -550,6 +602,10 @@ int cfg_strlist_append(struct config_strlist_head* list, char* item);
*/
int cfg_strlist_insert(struct config_strlist** head, char* item);
+/** insert with region for allocation. */
+int cfg_region_strlist_insert(struct regional* region,
+ struct config_strlist** head, char* item);
+
/**
* Insert string into str2list.
* @param head: pointer to str2list head variable.
@@ -560,6 +616,28 @@ 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 str3list.
+ * @param head: pointer to str3list 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 i3: 3rd string, malloced by caller. If NULL the insertion fails.
+ * @return: true on success.
+ */
+int cfg_str3list_insert(struct config_str3list** head, char* item, char* i2,
+ char* i3);
+
+/**
+ * Insert string into strbytelist.
+ * @param head: pointer to strbytelist 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,
* if the stub is found, on exit, the value contains a pointer to the
@@ -583,6 +661,15 @@ void config_delstrlist(struct config_strlist* list);
void config_deldblstrlist(struct config_str2list* list);
/**
+ * Delete items in config triple string list.
+ * @param list: list.
+ */
+void config_deltrplstrlist(struct config_str3list* list);
+
+/** delete stringbytelist */
+void config_del_strbytelist(struct config_strbytelist* list);
+
+/**
* Delete a stub item
* @param p: stub item
*/
@@ -625,6 +712,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.
* @param val: argument strings to local-zone, "example.com nodefault".
diff --git a/contrib/unbound/util/configlexer.lex b/contrib/unbound/util/configlexer.lex
index ad49e37..a8d4a96 100644
--- a/contrib/unbound/util/configlexer.lex
+++ b/contrib/unbound/util/configlexer.lex
@@ -9,6 +9,9 @@
*/
#include "config.h"
+/* because flex keeps having sign-unsigned compare problems that are unfixed*/
+#pragma GCC diagnostic ignored "-Wsign-compare"
+
#include <ctype.h>
#include <string.h>
#include <strings.h>
@@ -218,6 +221,7 @@ outgoing-num-tcp{COLON} { YDVAR(1, VAR_OUTGOING_NUM_TCP) }
incoming-num-tcp{COLON} { YDVAR(1, VAR_INCOMING_NUM_TCP) }
do-ip4{COLON} { YDVAR(1, VAR_DO_IP4) }
do-ip6{COLON} { YDVAR(1, VAR_DO_IP6) }
+prefer-ip6{COLON} { YDVAR(1, VAR_PREFER_IP6) }
do-udp{COLON} { YDVAR(1, VAR_DO_UDP) }
do-tcp{COLON} { YDVAR(1, VAR_DO_TCP) }
tcp-upstream{COLON} { YDVAR(1, VAR_TCP_UPSTREAM) }
@@ -236,6 +240,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 +349,12 @@ 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) }
+access-control-tag{COLON} { YDVAR(2, VAR_ACCESS_CONTROL_TAG) }
+access-control-tag-action{COLON} { YDVAR(3, VAR_ACCESS_CONTROL_TAG_ACTION) }
+access-control-tag-data{COLON} { YDVAR(3, VAR_ACCESS_CONTROL_TAG_DATA) }
+local-zone-override{COLON} { YDVAR(3, VAR_LOCAL_ZONE_OVERRIDE) }
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 +374,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) }
diff --git a/contrib/unbound/util/configparser.y b/contrib/unbound/util/configparser.y
index ea7acdb..7240ee4 100644
--- a/contrib/unbound/util/configparser.y
+++ b/contrib/unbound/util/configparser.y
@@ -69,7 +69,7 @@ extern struct config_parser_state* cfg_parser;
%token <str> STRING_ARG
%token VAR_SERVER VAR_VERBOSITY VAR_NUM_THREADS VAR_PORT
%token VAR_OUTGOING_RANGE VAR_INTERFACE
-%token VAR_DO_IP4 VAR_DO_IP6 VAR_DO_UDP VAR_DO_TCP
+%token VAR_DO_IP4 VAR_DO_IP6 VAR_PREFER_IP6 VAR_DO_UDP VAR_DO_TCP
%token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS
%token VAR_CHROOT VAR_USERNAME VAR_DIRECTORY VAR_LOGFILE VAR_PIDFILE
%token VAR_MSG_CACHE_SIZE VAR_MSG_CACHE_SLABS VAR_NUM_QUERIES_PER_THREAD
@@ -121,10 +121,13 @@ 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
+%token VAR_ACCESS_CONTROL_TAG VAR_LOCAL_ZONE_OVERRIDE
+%token VAR_ACCESS_CONTROL_TAG_ACTION VAR_ACCESS_CONTROL_TAG_DATA
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -143,7 +146,8 @@ contents_server: contents_server content_server
| ;
content_server: server_num_threads | server_verbosity | server_port |
server_outgoing_range | server_do_ip4 |
- server_do_ip6 | server_do_udp | server_do_tcp |
+ server_do_ip6 | server_prefer_ip6 |
+ server_do_udp | server_do_tcp |
server_tcp_mss | server_outgoing_tcp_mss |
server_interface | server_chroot | server_username |
server_directory | server_logfile | server_pidfile |
@@ -191,7 +195,11 @@ 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 | server_access_control_tag |
+ server_local_zone_override | server_access_control_tag_action |
+ server_access_control_tag_data
;
stubstart: VAR_STUB_ZONE
{
@@ -399,6 +407,15 @@ server_do_tcp: VAR_DO_TCP STRING_ARG
free($2);
}
;
+server_prefer_ip6: VAR_PREFER_IP6 STRING_ARG
+ {
+ OUTYY(("P(server_prefer_ip6:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->prefer_ip6 = (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
server_tcp_mss: VAR_TCP_MSS STRING_ARG
{
OUTYY(("P(server_tcp_mss:%s)\n", $2));
@@ -518,6 +535,23 @@ server_directory: VAR_DIRECTORY STRING_ARG
OUTYY(("P(server_directory:%s)\n", $2));
free(cfg_parser->cfg->directory);
cfg_parser->cfg->directory = $2;
+ /* change there right away for includes relative to this */
+ if($2[0]) {
+ char* d;
+#ifdef UB_ON_WINDOWS
+ w_config_adjust_directory(cfg_parser->cfg);
+#endif
+ d = cfg_parser->cfg->directory;
+ /* adjust directory if we have already chroot,
+ * like, we reread after sighup */
+ if(cfg_parser->chroot && cfg_parser->chroot[0] &&
+ strncmp(d, cfg_parser->chroot, strlen(
+ cfg_parser->chroot)) == 0)
+ d += strlen(cfg_parser->chroot);
+ if(chdir(d))
+ log_err("cannot chdir to directory: %s (%s)",
+ d, strerror(errno));
+ }
}
;
server_logfile: VAR_LOGFILE STRING_ARG
@@ -662,6 +696,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));
@@ -1203,12 +1247,16 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
if(strcmp($3, "static")!=0 && strcmp($3, "deny")!=0 &&
strcmp($3, "refuse")!=0 && strcmp($3, "redirect")!=0 &&
strcmp($3, "transparent")!=0 && strcmp($3, "nodefault")!=0
- && strcmp($3, "typetransparent")!=0 &&
- strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0)
+ && strcmp($3, "typetransparent")!=0
+ && strcmp($3, "always_transparent")!=0
+ && strcmp($3, "always_refuse")!=0
+ && strcmp($3, "always_nxdomain")!=0
+ && strcmp($3, "inform")!=0 && strcmp($3, "inform_deny")!=0)
yyerror("local-zone type: expected static, deny, "
"refuse, redirect, transparent, "
- "typetransparent, inform, inform_deny "
- "or nodefault");
+ "typetransparent, inform, inform_deny, "
+ "always_transparent, always_refuse, "
+ "always_nxdomain or nodefault");
else if(strcmp($3, "nodefault")==0) {
if(!cfg_strlist_insert(&cfg_parser->cfg->
local_zones_nodefault, $2))
@@ -1286,6 +1334,94 @@ 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_access_control_tag: VAR_ACCESS_CONTROL_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_access_control_tag:%s)\n", $2));
+ if(!bitlist)
+ yyerror("could not parse tags, (define-tag them first)");
+ if(bitlist) {
+ if(!cfg_strbytelist_insert(
+ &cfg_parser->cfg->acl_tags,
+ $2, bitlist, len)) {
+ yyerror("out of memory");
+ free($2);
+ }
+ }
+ }
+ ;
+server_access_control_tag_action: VAR_ACCESS_CONTROL_TAG_ACTION STRING_ARG STRING_ARG STRING_ARG
+ {
+ OUTYY(("P(server_access_control_tag_action:%s %s %s)\n", $2, $3, $4));
+ if(!cfg_str3list_insert(&cfg_parser->cfg->acl_tag_actions,
+ $2, $3, $4)) {
+ yyerror("out of memory");
+ free($2);
+ free($3);
+ free($4);
+ }
+ }
+ ;
+server_access_control_tag_data: VAR_ACCESS_CONTROL_TAG_DATA STRING_ARG STRING_ARG STRING_ARG
+ {
+ OUTYY(("P(server_access_control_tag_data:%s %s %s)\n", $2, $3, $4));
+ if(!cfg_str3list_insert(&cfg_parser->cfg->acl_tag_datas,
+ $2, $3, $4)) {
+ yyerror("out of memory");
+ free($2);
+ free($3);
+ free($4);
+ }
+ }
+ ;
+server_local_zone_override: VAR_LOCAL_ZONE_OVERRIDE STRING_ARG STRING_ARG STRING_ARG
+ {
+ OUTYY(("P(server_local_zone_override:%s %s %s)\n", $2, $3, $4));
+ if(!cfg_str3list_insert(&cfg_parser->cfg->local_zone_overrides,
+ $2, $3, $4)) {
+ yyerror("out of memory");
+ free($2);
+ free($3);
+ free($4);
+ }
+ }
+ ;
server_ratelimit: VAR_RATELIMIT STRING_ARG
{
OUTYY(("P(server_ratelimit:%s)\n", $2));
@@ -1643,6 +1779,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 */
diff --git a/contrib/unbound/util/data/dname.c b/contrib/unbound/util/data/dname.c
index 79bf52a..8fc475f 100644
--- a/contrib/unbound/util/data/dname.c
+++ b/contrib/unbound/util/data/dname.c
@@ -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++;
}
diff --git a/contrib/unbound/util/data/msgencode.c b/contrib/unbound/util/data/msgencode.c
index 43464e9..034bb24 100644
--- a/contrib/unbound/util/data/msgencode.c
+++ b/contrib/unbound/util/data/msgencode.c
@@ -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);
}
diff --git a/contrib/unbound/util/data/msgparse.c b/contrib/unbound/util/data/msgparse.c
index 108c9da..1d565c1 100644
--- a/contrib/unbound/util/data/msgparse.c
+++ b/contrib/unbound/util/data/msgparse.c
@@ -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;
}
diff --git a/contrib/unbound/util/data/msgparse.h b/contrib/unbound/util/data/msgparse.h
index 44497c8..cae988f 100644
--- a/contrib/unbound/util/data/msgparse.h
+++ b/contrib/unbound/util/data/msgparse.h
@@ -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.
diff --git a/contrib/unbound/util/data/msgreply.c b/contrib/unbound/util/data/msgreply.c
index 06593ff..f8a2491 100644
--- a/contrib/unbound/util/data/msgreply.c
+++ b/contrib/unbound/util/data/msgreply.c
@@ -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;
+}
diff --git a/contrib/unbound/util/data/msgreply.h b/contrib/unbound/util/data/msgreply.h
index 7088979..b542b75 100644
--- a/contrib/unbound/util/data/msgreply.h
+++ b/contrib/unbound/util/data/msgreply.h
@@ -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 */
diff --git a/contrib/unbound/util/fptr_wlist.c b/contrib/unbound/util/fptr_wlist.c
index 1397e9c..80a23f2 100644
--- a/contrib/unbound/util/fptr_wlist.c
+++ b/contrib/unbound/util/fptr_wlist.c
@@ -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;
@@ -315,6 +318,9 @@ fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id))
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_init) return 1;
#endif
+#ifdef USE_CACHEDB
+ else if(fptr == &cachedb_init) return 1;
+#endif
return 0;
}
@@ -327,6 +333,9 @@ fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id))
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_deinit) return 1;
#endif
+#ifdef USE_CACHEDB
+ else if(fptr == &cachedb_deinit) return 1;
+#endif
return 0;
}
@@ -340,6 +349,9 @@ fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate,
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_operate) return 1;
#endif
+#ifdef USE_CACHEDB
+ else if(fptr == &cachedb_operate) return 1;
+#endif
return 0;
}
@@ -353,6 +365,9 @@ fptr_whitelist_mod_inform_super(void (*fptr)(
#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;
}
@@ -366,6 +381,9 @@ fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate,
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_clear) return 1;
#endif
+#ifdef USE_CACHEDB
+ else if(fptr == &cachedb_clear) return 1;
+#endif
return 0;
}
@@ -378,6 +396,9 @@ fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id))
#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;
}
diff --git a/contrib/unbound/util/fptr_wlist.h b/contrib/unbound/util/fptr_wlist.h
index 10de5d8..98ca21b 100644
--- a/contrib/unbound/util/fptr_wlist.h
+++ b/contrib/unbound/util/fptr_wlist.h
@@ -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));
diff --git a/contrib/unbound/util/iana_ports.inc b/contrib/unbound/util/iana_ports.inc
index df5a560..0ac3efb 100644
--- a/contrib/unbound/util/iana_ports.inc
+++ b/contrib/unbound/util/iana_ports.inc
@@ -1186,6 +1186,7 @@
1525,
1526,
1527,
+1528,
1529,
1530,
1531,
@@ -3844,6 +3845,8 @@
4412,
4413,
4416,
+4418,
+4420,
4425,
4426,
4430,
@@ -3904,6 +3907,7 @@
4599,
4600,
4601,
+4621,
4658,
4659,
4660,
@@ -4222,6 +4226,7 @@
5436,
5437,
5443,
+5450,
5453,
5454,
5455,
@@ -4522,7 +4527,6 @@
6786,
6787,
6788,
-6789,
6790,
6791,
6801,
@@ -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,
@@ -5418,6 +5425,7 @@
44900,
45000,
45054,
+45514,
45678,
45825,
45966,
diff --git a/contrib/unbound/util/module.h b/contrib/unbound/util/module.h
index b9dde36..c3ce8a4 100644
--- a/contrib/unbound/util/module.h
+++ b/contrib/unbound/util/module.h
@@ -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.
diff --git a/contrib/unbound/util/net_help.c b/contrib/unbound/util/net_help.c
index eb03cd0..2485989 100644
--- a/contrib/unbound/util/net_help.c
+++ b/contrib/unbound/util/net_help.c
@@ -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) && OPENSSL_VERSION_NUMBER < 0x10100000L
/** 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) && OPENSSL_VERSION_NUMBER < 0x10100000L
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) && OPENSSL_VERSION_NUMBER < 0x10100000L
int i;
if(!ub_openssl_locks)
return;
diff --git a/contrib/unbound/util/netevent.c b/contrib/unbound/util/netevent.c
index b827e65..8960b36 100644
--- a/contrib/unbound/util/netevent.c
+++ b/contrib/unbound/util/netevent.c
@@ -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"
@@ -79,8 +80,10 @@
# endif
#endif
-/** The TCP reading or writing query timeout in seconds */
-#define TCP_QUERY_TIMEOUT 120
+/** The TCP reading or writing query timeout in milliseconds */
+#define TCP_QUERY_TIMEOUT 120000
+/** The TCP timeout in msec for fast queries, above half are used */
+#define TCP_QUERY_TIMEOUT_FAST 200
#ifndef NONBLOCKING_IS_BROKEN
/** number of UDP reads to perform per read indication from select */
@@ -89,48 +92,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 +123,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 +137,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 +150,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 +164,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 +189,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 +199,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 +216,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 +237,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 +246,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 +259,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 +581,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 +669,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);
@@ -779,14 +712,20 @@ comm_point_udp_callback(int fd, short event, void* arg)
/** Use a new tcp handler for new query fd, set to read query */
static void
-setup_tcp_handler(struct comm_point* c, int fd)
+setup_tcp_handler(struct comm_point* c, int fd, int cur, int max)
{
log_assert(c->type == comm_tcp);
log_assert(c->fd == -1);
sldns_buffer_clear(c->buffer);
c->tcp_is_reading = 1;
c->tcp_byte_count = 0;
- comm_point_start_listening(c, fd, TCP_QUERY_TIMEOUT);
+ c->tcp_timeout_msec = TCP_QUERY_TIMEOUT;
+ /* if more than half the tcp handlers are in use, use a shorter
+ * timeout for this TCP connection, we need to make space for
+ * other connections to be able to get attention */
+ if(cur > max/2)
+ c->tcp_timeout_msec = TCP_QUERY_TIMEOUT_FAST;
+ comm_point_start_listening(c, fd, c->tcp_timeout_msec);
}
void comm_base_handle_slow_accept(int ATTR_UNUSED(fd),
@@ -838,16 +777,17 @@ int comm_point_perform_accept(struct comm_point* c,
(*b->stop_accept)(b->cb_arg);
/* 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,
+ tv.tv_usec = (NETEVENT_SLOW_ACCEPT_TIME%1000)*1000;
+ 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 +801,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 +825,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 +845,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 +857,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");
@@ -930,6 +870,7 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
/* accept incoming connection. */
c_hdl = c->tcp_free;
log_assert(fd != -1);
+ (void)fd;
new_fd = comm_point_perform_accept(c, &c_hdl->repinfo.addr,
&c_hdl->repinfo.addrlen);
if(new_fd == -1)
@@ -954,7 +895,7 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
/* stop accepting incoming queries for now. */
comm_point_stop_listening(c);
}
- setup_tcp_handler(c_hdl, new_fd);
+ setup_tcp_handler(c_hdl, new_fd, c->cur_tcp_count, c->max_tcp_count);
}
/** Make tcp handler free for next assignment */
@@ -1008,7 +949,7 @@ tcp_callback_reader(struct comm_point* c)
comm_point_stop_listening(c);
fptr_ok(fptr_whitelist_comm_point(c->callback));
if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo) ) {
- comm_point_start_listening(c, -1, TCP_QUERY_TIMEOUT);
+ comm_point_start_listening(c, -1, c->tcp_timeout_msec);
}
}
@@ -1297,7 +1238,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 +1284,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 +1343,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;
@@ -1415,6 +1357,59 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
if(c->ssl)
return ssl_handle_it(c);
+#ifdef USE_MSG_FASTOPEN
+ /* Only try this on first use of a connection that uses tfo,
+ otherwise fall through to normal write */
+ /* Also, TFO support on WINDOWS not implemented at the moment */
+ if(c->tcp_do_fastopen == 1) {
+ /* this form of sendmsg() does both a connect() and send() so need to
+ look for various flavours of error*/
+ uint16_t len = htons(sldns_buffer_limit(c->buffer));
+ struct msghdr msg;
+ struct iovec iov[2];
+ c->tcp_do_fastopen = 0;
+ memset(&msg, 0, sizeof(msg));
+ iov[0].iov_base = (uint8_t*)&len + c->tcp_byte_count;
+ iov[0].iov_len = sizeof(uint16_t) - c->tcp_byte_count;
+ iov[1].iov_base = sldns_buffer_begin(c->buffer);
+ iov[1].iov_len = sldns_buffer_limit(c->buffer);
+ log_assert(iov[0].iov_len > 0);
+ log_assert(iov[1].iov_len > 0);
+ msg.msg_name = &c->repinfo.addr;
+ msg.msg_namelen = c->repinfo.addrlen;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 2;
+ r = sendmsg(fd, &msg, MSG_FASTOPEN);
+ if (r == -1) {
+#if defined(EINPROGRESS) && defined(EWOULDBLOCK)
+ /* Handshake is underway, maybe because no TFO cookie available.
+ Come back to write the messsage*/
+ if(errno == EINPROGRESS || errno == EWOULDBLOCK)
+ return 1;
+#endif
+ if(errno == EINTR || errno == EAGAIN)
+ return 1;
+ /* Not handling EISCONN here as shouldn't ever hit that case.*/
+ if(errno != 0 && verbosity < 2)
+ return 0; /* silence lots of chatter in the logs */
+ else if(errno != 0)
+ log_err_addr("tcp sendmsg", strerror(errno),
+ &c->repinfo.addr, c->repinfo.addrlen);
+ return 0;
+ } else {
+ c->tcp_byte_count += r;
+ if(c->tcp_byte_count < sizeof(uint16_t))
+ return 1;
+ sldns_buffer_set_position(c->buffer, c->tcp_byte_count -
+ sizeof(uint16_t));
+ if(sldns_buffer_remaining(c->buffer) == 0) {
+ tcp_callback_writer(c);
+ return 1;
+ }
+ }
+ }
+#endif /* USE_MSG_FASTOPEN */
+
if(c->tcp_byte_count < sizeof(uint16_t)) {
uint16_t len = htons(sldns_buffer_limit(c->buffer));
#ifdef HAVE_WRITEV
@@ -1451,7 +1446,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 +1479,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 +1501,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 +1515,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 +1527,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 +1544,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 +1563,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);
@@ -1606,18 +1602,22 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer,
c->do_not_close = 0;
c->tcp_do_toggle_rw = 0;
c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
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;
@@ -1658,17 +1658,21 @@ comm_point_create_udp_ancil(struct comm_base *base, int fd,
c->inuse = 0;
c->tcp_do_toggle_rw = 0;
c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
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;
@@ -1719,16 +1723,20 @@ comm_point_create_tcp_handler(struct comm_base *base,
c->do_not_close = 0;
c->tcp_do_toggle_rw = 1;
c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
c->repinfo.c = c;
c->callback = callback;
c->cb_arg = callback_arg;
/* 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;
@@ -1778,19 +1786,25 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num, size_t bufsize,
c->do_not_close = 0;
c->tcp_do_toggle_rw = 0;
c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
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,
@@ -1840,14 +1854,18 @@ comm_point_create_tcp_out(struct comm_base *base, size_t bufsize,
c->do_not_close = 0;
c->tcp_do_toggle_rw = 1;
c->tcp_check_nb_connect = 1;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 1;
+#endif
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);
@@ -1893,16 +1911,24 @@ comm_point_create_local(struct comm_base *base, int fd, size_t bufsize,
c->do_not_close = 1;
c->tcp_do_toggle_rw = 0;
c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
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;
@@ -1941,18 +1967,26 @@ comm_point_create_raw(struct comm_base* base, int fd, int writing,
c->do_not_close = 1;
c->tcp_do_toggle_rw = 0;
c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
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 +2000,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 +2036,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);
}
@@ -2031,7 +2066,8 @@ comm_point_send_reply(struct comm_reply *repinfo)
dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv,
&repinfo->addr, repinfo->c->type, repinfo->c->buffer);
#endif
- comm_point_start_listening(repinfo->c, -1, TCP_QUERY_TIMEOUT);
+ comm_point_start_listening(repinfo->c, -1,
+ repinfo->c->tcp_timeout_msec);
}
}
@@ -2051,13 +2087,13 @@ 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");
}
}
void
-comm_point_start_listening(struct comm_point* c, int newfd, int sec)
+comm_point_start_listening(struct comm_point* c, int newfd, int msec)
{
verbose(VERB_ALGO, "comm point start listening %d",
c->fd==-1?newfd:c->fd);
@@ -2065,7 +2101,7 @@ comm_point_start_listening(struct comm_point* c, int newfd, int sec)
/* no use to start listening no free slots. */
return;
}
- if(sec != -1 && sec != 0) {
+ if(msec != -1 && msec != 0) {
if(!c->timeout) {
c->timeout = (struct timeval*)malloc(sizeof(
struct timeval));
@@ -2074,17 +2110,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;
+ c->timeout->tv_sec = msec/1000;
+ c->timeout->tv_usec = (msec%1000)*1000;
#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 +2131,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, msec==0?NULL:c->timeout) != 0) {
log_err("event_add failed. in cpsl.");
}
}
@@ -2105,13 +2141,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 +2173,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 +2198,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 +2208,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 +2220,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 +2246,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 +2272,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 +2290,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 +2318,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;
}
diff --git a/contrib/unbound/util/netevent.h b/contrib/unbound/util/netevent.h
index 4b87cdb..1d7ac0b 100644
--- a/contrib/unbound/util/netevent.h
+++ b/contrib/unbound/util/netevent.h
@@ -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,
@@ -225,9 +225,17 @@ struct comm_point {
So that when that is done the callback is called. */
int tcp_do_toggle_rw;
+ /** timeout in msec for TCP wait times for this connection */
+ int tcp_timeout_msec;
+
/** if set, checks for pending error from nonblocking connect() call.*/
int tcp_check_nb_connect;
+#ifdef USE_MSG_FASTOPEN
+ /** used to track if the sendto() call should be done when using TFO. */
+ int tcp_do_fastopen;
+#endif
+
/** number of queries outstanding on this socket, used by
* outside network for udp ports */
int inuse;
@@ -265,7 +273,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 +309,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 +365,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.
@@ -496,9 +504,10 @@ void comm_point_stop_listening(struct comm_point* c);
* Start listening again for input on the comm point.
* @param c: commpoint to enable again.
* @param newfd: new fd, or -1 to leave fd be.
- * @param sec: timeout in seconds, or -1 for no (change to the) timeout.
+ * @param msec: timeout in milliseconds, or -1 for no (change to the) timeout.
+ * So seconds*1000.
*/
-void comm_point_start_listening(struct comm_point* c, int newfd, int sec);
+void comm_point_start_listening(struct comm_point* c, int newfd, int msec);
/**
* Stop listening and start listening again for reading or writing.
diff --git a/contrib/unbound/util/storage/dnstree.c b/contrib/unbound/util/storage/dnstree.c
index 0df490e..7664c47 100644
--- a/contrib/unbound/util/storage/dnstree.c
+++ b/contrib/unbound/util/storage/dnstree.c
@@ -231,6 +231,19 @@ struct addr_tree_node* addr_tree_lookup(rbtree_t* tree,
return result;
}
+struct addr_tree_node* addr_tree_find(rbtree_t* tree,
+ struct sockaddr_storage* addr, socklen_t addrlen, int net)
+{
+ rbnode_t* res = NULL;
+ struct addr_tree_node key;
+ key.node.key = &key;
+ memcpy(&key.addr, addr, addrlen);
+ key.addrlen = addrlen;
+ key.net = net;
+ res = rbtree_search(tree, &key);
+ return (struct addr_tree_node*)res;
+}
+
int
name_tree_next_root(rbtree_t* tree, uint16_t* dclass)
{
diff --git a/contrib/unbound/util/storage/dnstree.h b/contrib/unbound/util/storage/dnstree.h
index ec81891..b4595e1 100644
--- a/contrib/unbound/util/storage/dnstree.h
+++ b/contrib/unbound/util/storage/dnstree.h
@@ -183,6 +183,17 @@ void addr_tree_init_parents(rbtree_t* tree);
struct addr_tree_node* addr_tree_lookup(rbtree_t* tree,
struct sockaddr_storage* addr, socklen_t addrlen);
+/**
+ * Find element in addr tree. (search a netblock, not a match for an address)
+ * @param tree: addr tree
+ * @param addr: netblock to lookup.
+ * @param addrlen: length of addr
+ * @param net: size of subnet
+ * @return addr tree element, or NULL if not found.
+ */
+struct addr_tree_node* addr_tree_find(rbtree_t* tree,
+ struct sockaddr_storage* addr, socklen_t addrlen, int net);
+
/** compare name tree nodes */
int name_tree_compare(const void* k1, const void* k2);
diff --git a/contrib/unbound/util/storage/lookup3.c b/contrib/unbound/util/storage/lookup3.c
index ddcb56e..e9b05af 100644
--- a/contrib/unbound/util/storage/lookup3.c
+++ b/contrib/unbound/util/storage/lookup3.c
@@ -820,7 +820,7 @@ uint32_t hashbig( const void *key, size_t length, uint32_t initval)
#ifdef SELF_TEST
/* used for timings */
-void driver1()
+void driver1(void)
{
uint8_t buf[256];
uint32_t i;
@@ -842,7 +842,7 @@ void driver1()
#define HASHLEN 1
#define MAXPAIR 60
#define MAXLEN 70
-void driver2()
+void driver2(void)
{
uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1];
uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z;
@@ -912,7 +912,7 @@ void driver2()
}
/* Check for reading beyond the end of the buffer and alignment problems */
-void driver3()
+void driver3(void)
{
uint8_t buf[MAXLEN+20], *b;
uint32_t len;
@@ -1003,7 +1003,7 @@ void driver3()
}
/* check for problems with nulls */
- void driver4()
+ void driver4(void)
{
uint8_t buf[1];
uint32_t h,i,state[HASHSTATE];
@@ -1020,7 +1020,7 @@ void driver3()
}
-int main()
+int main(void)
{
driver1(); /* test that the key is hashed: used for timings */
driver2(); /* test that whole key is hashed thoroughly */
diff --git a/contrib/unbound/util/tube.c b/contrib/unbound/util/tube.c
index 0535474..e525f1c 100644
--- a/contrib/unbound/util/tube.c
+++ b/contrib/unbound/util/tube.c
@@ -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),
diff --git a/contrib/unbound/util/tube.h b/contrib/unbound/util/tube.h
index 6cc6050..7971b77 100644
--- a/contrib/unbound/util/tube.h
+++ b/contrib/unbound/util/tube.h
@@ -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;
diff --git a/contrib/unbound/util/ub_event.c b/contrib/unbound/util/ub_event.c
new file mode 100644
index 0000000..3b92be1
--- /dev/null
+++ b/contrib/unbound/util/ub_event.c
@@ -0,0 +1,444 @@
+/*
+ * 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) ((struct event_base*)x)
+#define AS_UB_EVENT_BASE(x) ((struct ub_event_base*)x)
+#define AS_EVENT(x) ((struct event*)x)
+#define AS_UB_EVENT(x) ((struct ub_event*)x)
+
+const char* ub_event_get_version(void)
+{
+ 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 */
+}
+
diff --git a/contrib/unbound/util/ub_event.h b/contrib/unbound/util/ub_event.h
new file mode 100644
index 0000000..9739e6d
--- /dev/null
+++ b/contrib/unbound/util/ub_event.h
@@ -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 */
diff --git a/contrib/unbound/util/ub_event_pluggable.c b/contrib/unbound/util/ub_event_pluggable.c
new file mode 100644
index 0000000..4a94512
--- /dev/null
+++ b/contrib/unbound/util/ub_event_pluggable.c
@@ -0,0 +1,692 @@
+/*
+ * 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) ((struct my_event_base*)x)
+#define AS_MY_EVENT(x) ((struct my_event*)x)
+
+const char* ub_event_get_version(void)
+{
+ 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 && 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 && 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 && 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 && 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;
+}
+
diff --git a/contrib/unbound/util/winsock_event.c b/contrib/unbound/util/winsock_event.c
index 40b7982..9aad27e 100644
--- a/contrib/unbound/util/winsock_event.c
+++ b/contrib/unbound/util/winsock_event.c
@@ -262,8 +262,9 @@ static int handle_select(struct event_base* base, struct timeval* wait)
break; /* sanity check */
}
log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS);
- verbose(VERB_CLIENT, "winsock_event bmax=%d numwait=%d wait=%x "
- "timeout=%d", base->max, numwait, (int)wait, (int)timeout);
+ verbose(VERB_CLIENT, "winsock_event bmax=%d numwait=%d wait=%s "
+ "timeout=%d", base->max, numwait, (wait?"<wait>":"<null>"),
+ (int)timeout);
/* do the wait */
if(numwait == 0) {
diff --git a/contrib/unbound/validator/autotrust.c b/contrib/unbound/validator/autotrust.c
index f8c9c8c..da8829c 100644
--- a/contrib/unbound/validator/autotrust.c
+++ b/contrib/unbound/validator/autotrust.c
@@ -430,6 +430,8 @@ find_add_tp(struct val_anchors* anchors, uint8_t* rr, size_t rr_len,
}
tp = autr_tp_create(anchors, rr, dname_len, sldns_wirerr_get_class(rr,
rr_len, dname_len));
+ if(!tp)
+ return NULL;
lock_basic_lock(&tp->lock);
return tp;
}
@@ -1201,7 +1203,7 @@ void autr_write_file(struct module_env* env, struct trust_anchor* tp)
if(fsync(fileno(out)) != 0)
log_err("could not fsync(%s): %s", fname, strerror(errno));
#else
- FlushFileBuffers((HANDLE)_fileno(out));
+ FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
#endif
if(fclose(out) != 0) {
fatal_exit("could not complete write: %s: %s",
@@ -2333,6 +2335,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;
diff --git a/contrib/unbound/validator/val_anchor.c b/contrib/unbound/validator/val_anchor.c
index bc9f8b8..4d470b6 100644
--- a/contrib/unbound/validator/val_anchor.c
+++ b/contrib/unbound/validator/val_anchor.c
@@ -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;
diff --git a/contrib/unbound/validator/val_secalgo.c b/contrib/unbound/validator/val_secalgo.c
index baa4dae..e3a1555 100644
--- a/contrib/unbound/validator/val_secalgo.c
+++ b/contrib/unbound/validator/val_secalgo.c
@@ -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,36 +291,82 @@ 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 */
+#ifdef USE_ECDSA_EVP_WORKAROUND
+static EVP_MD ecdsa_evp_256_md;
+static EVP_MD ecdsa_evp_384_md;
+void ecdsa_evp_workaround_init(void)
+{
+ /* openssl before 1.0.0 fixes RSA with the SHA256
+ * hash in EVP. We create one for ecdsa_sha256 */
+ ecdsa_evp_256_md = *EVP_sha256();
+ ecdsa_evp_256_md.required_pkey_type[0] = EVP_PKEY_EC;
+ ecdsa_evp_256_md.verify = (void*)ECDSA_verify;
+
+ ecdsa_evp_384_md = *EVP_sha384();
+ ecdsa_evp_384_md.required_pkey_type[0] = EVP_PKEY_EC;
+ ecdsa_evp_384_md.verify = (void*)ECDSA_verify;
+}
+#endif /* USE_ECDSA_EVP_WORKAROUND */
+
/**
* Setup key and digest for verification. Adjust sig if necessary.
*
@@ -325,10 +381,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 +409,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)
@@ -435,20 +495,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
return 0;
}
#ifdef USE_ECDSA_EVP_WORKAROUND
- /* openssl before 1.0.0 fixes RSA with the SHA256
- * hash in EVP. We create one for ecdsa_sha256 */
- {
- static int md_ecdsa_256_done = 0;
- static EVP_MD md;
- if(!md_ecdsa_256_done) {
- EVP_MD m = *EVP_sha256();
- md_ecdsa_256_done = 1;
- m.required_pkey_type[0] = (*evp_key)->type;
- m.verify = (void*)ECDSA_verify;
- md = m;
- }
- *digest_type = &md;
- }
+ *digest_type = &ecdsa_evp_256_md;
#else
*digest_type = EVP_sha256();
#endif
@@ -462,20 +509,7 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
return 0;
}
#ifdef USE_ECDSA_EVP_WORKAROUND
- /* openssl before 1.0.0 fixes RSA with the SHA384
- * hash in EVP. We create one for ecdsa_sha384 */
- {
- static int md_ecdsa_384_done = 0;
- static EVP_MD md;
- if(!md_ecdsa_384_done) {
- EVP_MD m = *EVP_sha384();
- md_ecdsa_384_done = 1;
- m.required_pkey_type[0] = (*evp_key)->type;
- m.verify = (void*)ECDSA_verify;
- md = m;
- }
- *digest_type = &md;
- }
+ *digest_type = &ecdsa_evp_384_md;
#else
*digest_type = EVP_sha384();
#endif
@@ -508,8 +542,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 +552,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 +562,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 +582,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) OPENSSL_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");
+ 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) OPENSSL_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");
+ 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) OPENSSL_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) OPENSSL_free(sigblock);
if(res == 1) {
return sec_status_secure;
@@ -620,6 +675,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 +739,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 +983,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 +994,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 +1111,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 +1134,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 */
@@ -1131,6 +1198,9 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
#include "macros.h"
#include "rsa.h"
#include "dsa.h"
+#ifdef HAVE_NETTLE_DSA_COMPAT_H
+#include "dsa-compat.h"
+#endif
#include "asn1.h"
#ifdef USE_ECDSA
#include "ecdsa.h"
@@ -1206,6 +1276,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 +1339,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
@@ -1283,6 +1361,7 @@ dnskey_algo_id_is_supported(int id)
}
}
+#ifdef USE_DSA
static char *
_verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
@@ -1370,6 +1449,7 @@ _verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
else
return NULL;
}
+#endif /* USE_DSA */
static char *
_verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock,
@@ -1541,6 +1621,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 +1629,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:
diff --git a/contrib/unbound/validator/val_secalgo.h b/contrib/unbound/validator/val_secalgo.h
index 589f1f1..52aaeb9 100644
--- a/contrib/unbound/validator/val_secalgo.h
+++ b/contrib/unbound/validator/val_secalgo.h
@@ -60,6 +60,14 @@ int secalgo_nsec3_hash(int algo, unsigned char* buf, size_t len,
unsigned char* res);
/**
+ * Calculate the sha256 hash for the data buffer into the result.
+ * @param buf: buffer to digest.
+ * @param len: length of the buffer to digest.
+ * @param res: result is stored here (space 256/8 bytes).
+ */
+void secalgo_hash_sha256(unsigned char* buf, size_t len, unsigned char* res);
+
+/**
* Return size of DS digest according to its hash algorithm.
* @param algo: DS digest algo.
* @return size in bytes of digest, or 0 if not supported.
diff --git a/contrib/unbound/validator/val_sigcrypt.c b/contrib/unbound/validator/val_sigcrypt.c
index 1dd07b4..e60f3f9 100644
--- a/contrib/unbound/validator/val_sigcrypt.c
+++ b/contrib/unbound/validator/val_sigcrypt.c
@@ -1283,15 +1283,23 @@ adjust_ttl(struct val_env* ve, uint32_t unow,
/* so now:
* d->ttl: rrset ttl read from message or cache. May be reduced
* origttl: original TTL from signature, authoritative TTL max.
+ * MIN_TTL: minimum TTL from config.
* expittl: TTL until the signature expires.
*
- * Use the smallest of these.
+ * Use the smallest of these, but don't let origttl set the TTL
+ * below the minimum.
*/
- if(d->ttl > (time_t)origttl) {
- verbose(VERB_QUERY, "rrset TTL larger than original TTL,"
- " adjusting TTL downwards");
+ if(MIN_TTL > (time_t)origttl && d->ttl > MIN_TTL) {
+ verbose(VERB_QUERY, "rrset TTL larger than original and minimum"
+ " TTL, adjusting TTL downwards to mimimum ttl");
+ d->ttl = MIN_TTL;
+ }
+ else if(MIN_TTL <= origttl && d->ttl > (time_t)origttl) {
+ verbose(VERB_QUERY, "rrset TTL larger than original TTL, "
+ "adjusting TTL downwards to original ttl");
d->ttl = origttl;
}
+
if(expittl > 0 && d->ttl > (time_t)expittl) {
verbose(VERB_ALGO, "rrset TTL larger than sig expiration ttl,"
" adjusting TTL downwards");
diff --git a/contrib/unbound/validator/validator.c b/contrib/unbound/validator/validator.c
index db4383b..f9b6a98 100644
--- a/contrib/unbound/validator/validator.c
+++ b/contrib/unbound/validator/validator.c
@@ -156,6 +156,9 @@ val_apply_cfg(struct module_env* env, struct val_env* val_env,
return 1;
}
+#ifdef USE_ECDSA_EVP_WORKAROUND
+void ecdsa_evp_workaround_init(void);
+#endif
int
val_init(struct module_env* env, int id)
{
@@ -171,6 +174,9 @@ val_init(struct module_env* env, int id)
lock_basic_init(&val_env->bogus_lock);
lock_protect(&val_env->bogus_lock, &val_env->num_rrset_bogus,
sizeof(val_env->num_rrset_bogus));
+#ifdef USE_ECDSA_EVP_WORKAROUND
+ ecdsa_evp_workaround_init();
+#endif
if(!val_apply_cfg(env, val_env, env->cfg)) {
log_err("validator: could not apply configuration settings.");
return 0;
diff --git a/lib/libunbound/Makefile b/lib/libunbound/Makefile
index aeb59095..a30bfc7 100644
--- a/lib/libunbound/Makefile
+++ b/lib/libunbound/Makefile
@@ -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
diff --git a/usr.sbin/unbound/checkconf/Makefile b/usr.sbin/unbound/checkconf/Makefile
index 98ac3bb..e63be80 100644
--- a/usr.sbin/unbound/checkconf/Makefile
+++ b/usr.sbin/unbound/checkconf/Makefile
@@ -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
diff --git a/usr.sbin/unbound/control/Makefile b/usr.sbin/unbound/control/Makefile
index 9aab04a..928c7e9 100644
--- a/usr.sbin/unbound/control/Makefile
+++ b/usr.sbin/unbound/control/Makefile
@@ -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
diff --git a/usr.sbin/unbound/daemon/Makefile b/usr.sbin/unbound/daemon/Makefile
index af42975..fb614fa 100644
--- a/usr.sbin/unbound/daemon/Makefile
+++ b/usr.sbin/unbound/daemon/Makefile
@@ -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
OpenPOWER on IntegriCloud