aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2020-11-28 18:09:16 +0000
committerCy Schubert <cy@FreeBSD.org>2020-11-28 18:09:16 +0000
commit2f0116b4bf0637b99f27a2b5c2bc3e9dedd931cf (patch)
tree001ea9ecba2ab8a879b5ad83779271dcab9b01ce
parent78fc4e72413bbbffd5963e953e33f1e374318c01 (diff)
downloadsrc-2f0116b4bf0637b99f27a2b5c2bc3e9dedd931cf.tar.gz
src-2f0116b4bf0637b99f27a2b5c2bc3e9dedd931cf.zip
MFC r367094:
MFV r367082: Update unbound 1.11.0 --> 1.12.0.
Notes
Notes: svn path=/stable/11/; revision=368129
-rw-r--r--contrib/unbound/Makefile.in55
-rw-r--r--contrib/unbound/README.md2
-rw-r--r--contrib/unbound/acx_nlnetlabs.m437
-rwxr-xr-xcontrib/unbound/config.guess40
-rw-r--r--contrib/unbound/config.h.in33
-rwxr-xr-xcontrib/unbound/config.sub16
-rwxr-xr-xcontrib/unbound/configure131
-rw-r--r--contrib/unbound/configure.ac50
-rw-r--r--contrib/unbound/contrib/aaaa-filter-iterator.patch164
-rw-r--r--contrib/unbound/contrib/unbound.service.in6
-rwxr-xr-xcontrib/unbound/contrib/unbound_munin_4
-rw-r--r--contrib/unbound/daemon/daemon.c26
-rw-r--r--contrib/unbound/daemon/remote.c43
-rw-r--r--contrib/unbound/daemon/stats.c8
-rw-r--r--contrib/unbound/daemon/unbound.c2
-rw-r--r--contrib/unbound/daemon/worker.c32
-rw-r--r--contrib/unbound/dnstap/dnstap.c14
-rw-r--r--contrib/unbound/dnstap/dnstap.h3
-rw-r--r--contrib/unbound/dnstap/dtstream.c152
-rw-r--r--contrib/unbound/dnstap/dtstream.h15
-rw-r--r--contrib/unbound/dnstap/unbound-dnstap-socket.c70
-rw-r--r--contrib/unbound/doc/Changelog130
-rw-r--r--contrib/unbound/doc/README2
-rw-r--r--contrib/unbound/doc/example.conf.in85
-rw-r--r--contrib/unbound/doc/libunbound.3.in4
-rw-r--r--contrib/unbound/doc/unbound-anchor.8.in2
-rw-r--r--contrib/unbound/doc/unbound-checkconf.8.in2
-rw-r--r--contrib/unbound/doc/unbound-control.8.in15
-rw-r--r--contrib/unbound/doc/unbound-host.1.in2
-rw-r--r--contrib/unbound/doc/unbound.8.in4
-rw-r--r--contrib/unbound/doc/unbound.conf.5.in178
-rw-r--r--contrib/unbound/dynlibmod/dynlibmod.c5
-rw-r--r--contrib/unbound/iterator/iterator.c2
-rw-r--r--contrib/unbound/libunbound/context.c3
-rw-r--r--contrib/unbound/libunbound/libunbound.c16
-rw-r--r--contrib/unbound/libunbound/libworker.c2
-rw-r--r--contrib/unbound/libunbound/unbound.h6
-rw-r--r--contrib/unbound/services/cache/dns.c5
-rw-r--r--contrib/unbound/services/listen_dnsport.c1295
-rw-r--r--contrib/unbound/services/listen_dnsport.h70
-rw-r--r--contrib/unbound/services/mesh.c12
-rw-r--r--contrib/unbound/services/mesh.h2
-rw-r--r--contrib/unbound/services/outside_network.c35
-rw-r--r--contrib/unbound/services/rpz.c14
-rw-r--r--contrib/unbound/sldns/parseutil.c99
-rw-r--r--contrib/unbound/sldns/parseutil.h5
-rw-r--r--contrib/unbound/sldns/rrdef.h3
-rw-r--r--contrib/unbound/smallapp/unbound-checkconf.c2
-rw-r--r--contrib/unbound/smallapp/unbound-control.c29
-rw-r--r--contrib/unbound/util/config_file.c45
-rw-r--r--contrib/unbound/util/config_file.h29
-rw-r--r--contrib/unbound/util/configlexer.lex11
-rw-r--r--contrib/unbound/util/configparser.y100
-rw-r--r--contrib/unbound/util/edns.c81
-rw-r--r--contrib/unbound/util/edns.h57
-rw-r--r--contrib/unbound/util/fptr_wlist.c3
-rw-r--r--contrib/unbound/util/iana_ports.inc2
-rw-r--r--contrib/unbound/util/mini_event.h4
-rw-r--r--contrib/unbound/util/module.h2
-rw-r--r--contrib/unbound/util/net_help.c59
-rw-r--r--contrib/unbound/util/net_help.h6
-rw-r--r--contrib/unbound/util/netevent.c610
-rw-r--r--contrib/unbound/util/netevent.h143
-rw-r--r--contrib/unbound/validator/val_anchor.c33
-rw-r--r--contrib/unbound/validator/val_anchor.h2
-rw-r--r--contrib/unbound/validator/val_neg.c102
-rw-r--r--contrib/unbound/validator/val_neg.h20
-rw-r--r--contrib/unbound/validator/val_nsec.c83
-rw-r--r--contrib/unbound/validator/val_nsec.h13
-rw-r--r--contrib/unbound/validator/validator.c382
-rw-r--r--contrib/unbound/validator/validator.h23
-rw-r--r--usr.sbin/unbound/config.h80
72 files changed, 3316 insertions, 1506 deletions
diff --git a/contrib/unbound/Makefile.in b/contrib/unbound/Makefile.in
index bac212df2170..d2600e71f0cf 100644
--- a/contrib/unbound/Makefile.in
+++ b/contrib/unbound/Makefile.in
@@ -231,6 +231,10 @@ STREAMTCP_SRC=testcode/streamtcp.c
STREAMTCP_OBJ=streamtcp.lo
STREAMTCP_OBJ_LINK=$(STREAMTCP_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \
$(SLDNS_OBJ)
+DOHCLIENT_SRC=testcode/dohclient.c
+DOHCLIENT_OBJ=dohclient.lo
+DOHCLIENT_OBJ_LINK=$(DOHCLIENT_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \
+$(SLDNS_OBJ)
PERF_SRC=testcode/perf.c
PERF_OBJ=perf.lo
PERF_OBJ_LINK=$(PERF_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) $(SLDNS_OBJ)
@@ -272,7 +276,8 @@ ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \
$(ASYNCLOOK_SRC) $(STREAMTCP_SRC) $(PERF_SRC) $(DELAYER_SRC) \
$(CONTROL_SRC) $(UBANCHOR_SRC) $(PETAL_SRC) $(DNSTAP_SOCKET_SRC)\
$(PYTHONMOD_SRC) $(PYUNBOUND_SRC) $(WIN_DAEMON_THE_SRC) \
- $(SVCINST_SRC) $(SVCUNINST_SRC) $(ANCHORUPD_SRC) $(SLDNS_SRC)
+ $(SVCINST_SRC) $(SVCUNINST_SRC) $(ANCHORUPD_SRC) $(SLDNS_SRC) \
+ $(DOHCLIENT_SRC)
ALL_OBJ=$(COMMON_OBJ) $(UNITTEST_OBJ) $(DAEMON_OBJ) \
$(TESTBOUND_OBJ) $(LOCKVERIFY_OBJ) $(PKTVIEW_OBJ) \
@@ -280,7 +285,8 @@ ALL_OBJ=$(COMMON_OBJ) $(UNITTEST_OBJ) $(DAEMON_OBJ) \
$(ASYNCLOOK_OBJ) $(STREAMTCP_OBJ) $(PERF_OBJ) $(DELAYER_OBJ) \
$(CONTROL_OBJ) $(UBANCHOR_OBJ) $(PETAL_OBJ) $(DNSTAP_SOCKET_OBJ)\
$(COMPAT_OBJ) $(PYUNBOUND_OBJ) \
- $(SVCINST_OBJ) $(SVCUNINST_OBJ) $(ANCHORUPD_OBJ) $(SLDNS_OBJ)
+ $(SVCINST_OBJ) $(SVCUNINST_OBJ) $(ANCHORUPD_OBJ) $(SLDNS_OBJ) \
+ $(DOHCLIENT_OBJ)
COMPILE=$(LIBTOOL) --tag=CC --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) @PTHREAD_CFLAGS_ONLY@
LINK=$(LIBTOOL) --tag=CC --mode=link $(CC) $(staticexe) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
@@ -317,7 +323,7 @@ rsrc_unbound_checkconf.o: $(srcdir)/winrc/rsrc_unbound_checkconf.rc config.h
TEST_BIN=asynclook$(EXEEXT) delayer$(EXEEXT) \
lock-verify$(EXEEXT) memstats$(EXEEXT) perf$(EXEEXT) \
petal$(EXEEXT) pktview$(EXEEXT) streamtcp$(EXEEXT) \
- unbound-dnstap-socket$(EXEEXT) \
+ unbound-dnstap-socket$(EXEEXT) dohclient$(EXEEXT) \
testbound$(EXEEXT) unittest$(EXEEXT)
tests: all $(TEST_BIN)
@@ -387,6 +393,9 @@ asynclook$(EXEEXT): $(ASYNCLOOK_OBJ_LINK) libunbound.la
streamtcp$(EXEEXT): $(STREAMTCP_OBJ_LINK)
$(LINK) -o $@ $(STREAMTCP_OBJ_LINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
+dohclient$(EXEEXT): $(DOHCLIENT_OBJ_LINK)
+ $(LINK) -o $@ $(DOHCLIENT_OBJ_LINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
+
perf$(EXEEXT): $(PERF_OBJ_LINK)
$(LINK) -o $@ $(PERF_OBJ_LINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
@@ -672,7 +681,7 @@ dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_de
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/validator/val_utils.h $(srcdir)/sldns/pkthdr.h $(srcdir)/services/cache/dns.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/dname.h $(srcdir)/util/module.h \
$(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h
infra.lo infra.o: $(srcdir)/services/cache/infra.c config.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/services/cache/infra.h \
@@ -713,10 +722,11 @@ msgreply.lo msgreply.o: $(srcdir)/util/data/msgreply.c config.h $(srcdir)/util/d
$(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \
$(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/respip/respip.h
-packed_rrset.lo packed_rrset.o: $(srcdir)/util/data/packed_rrset.c config.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/regional.h \
- $(srcdir)/util/net_help.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h
+packed_rrset.lo packed_rrset.o: $(srcdir)/util/data/packed_rrset.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/packed_rrset.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h
iterator.lo iterator.o: $(srcdir)/iterator/iterator.c config.h $(srcdir)/iterator/iterator.h \
$(srcdir)/services/outbound_list.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/module.h \
@@ -785,7 +795,7 @@ listen_dnsport.lo listen_dnsport.o: $(srcdir)/services/listen_dnsport.c config.h
$(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/log.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h $(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
@@ -808,10 +818,10 @@ mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(s
$(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \
$(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/dns.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/regional.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
- $(srcdir)/util/alloc.h $(srcdir)/util/edns.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/data/dname.h \
- $(srcdir)/services/listen_dnsport.h
+ $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \
+ $(srcdir)/util/data/msgencode.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/alloc.h \
+ $(srcdir)/util/edns.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/data/dname.h $(srcdir)/services/listen_dnsport.h
modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/services/modstack.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 \
@@ -1204,7 +1214,8 @@ testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcod
$(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
unitldns.lo unitldns.o: $(srcdir)/testcode/unitldns.c config.h $(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h \
+ $(srcdir)/sldns/parseutil.h
unitecs.lo unitecs.o: $(srcdir)/testcode/unitecs.c config.h
unitauth.lo unitauth.o: $(srcdir)/testcode/unitauth.c config.h $(srcdir)/services/authzone.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \
@@ -1310,7 +1321,8 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
$(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/edns.h \
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \
$(srcdir)/validator/val_anchor.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound-event.h \
- $(srcdir)/libunbound/libworker.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h
+ $(srcdir)/libunbound/libworker.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h \
+ $(srcdir)/dnstap/dtstream.h
testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/testcode/testpkts.h \
$(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h \
@@ -1344,7 +1356,8 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
$(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/edns.h \
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \
$(srcdir)/validator/val_anchor.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound-event.h \
- $(srcdir)/libunbound/libworker.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h
+ $(srcdir)/libunbound/libworker.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h \
+ $(srcdir)/dnstap/dtstream.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)/services/view.h $(srcdir)/util/locks.h \
$(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
@@ -1507,6 +1520,12 @@ unbound-control.lo unbound-control.o: $(srcdir)/smallapp/unbound-control.c confi
unbound-anchor.lo unbound-anchor.o: $(srcdir)/smallapp/unbound-anchor.c config.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h
petal.lo petal.o: $(srcdir)/testcode/petal.c config.h
+unbound-dnstap-socket.lo unbound-dnstap-socket.o: $(srcdir)/dnstap/unbound-dnstap-socket.c config.h \
+ $(srcdir)/dnstap/dtstream.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/dnstap/dnstap_fstrm.h \
+ $(srcdir)/util/ub_event.h $(srcdir)/util/net_help.h $(srcdir)/services/listen_dnsport.h \
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h
pythonmod_utils.lo pythonmod_utils.o: $(srcdir)/pythonmod/pythonmod_utils.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 \
@@ -1542,6 +1561,10 @@ parseutil.lo parseutil.o: $(srcdir)/sldns/parseutil.c config.h $(srcdir)/sldns/p
rrdef.lo rrdef.o: $(srcdir)/sldns/rrdef.c config.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h
str2wire.lo str2wire.o: $(srcdir)/sldns/str2wire.c config.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h \
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parse.h $(srcdir)/sldns/parseutil.h
+dohclient.lo dohclient.o: $(srcdir)/testcode/dohclient.c config.h $(srcdir)/sldns/wire2str.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.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/net_help.h
ctime_r.lo ctime_r.o: $(srcdir)/compat/ctime_r.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
fake-rfc2553.lo fake-rfc2553.o: $(srcdir)/compat/fake-rfc2553.c $(srcdir)/compat/fake-rfc2553.h config.h
gmtime_r.lo gmtime_r.o: $(srcdir)/compat/gmtime_r.c config.h
diff --git a/contrib/unbound/README.md b/contrib/unbound/README.md
index 7120d486f732..3e11ce58ce0d 100644
--- a/contrib/unbound/README.md
+++ b/contrib/unbound/README.md
@@ -9,7 +9,7 @@ fast and lean and incorporates modern features based on open standards. If you
have any feedback, we would love to hear from you. Don’t hesitate to
[create an issue on Github](https://github.com/NLnetLabs/unbound/issues/new)
or post a message on the [Unbound mailing list](https://lists.nlnetlabs.nl/mailman/listinfo/unbound-users).
-You can lean more about Unbound by reading our
+You can learn more about Unbound by reading our
[documentation](https://nlnetlabs.nl/documentation/unbound/).
## Compiling
diff --git a/contrib/unbound/acx_nlnetlabs.m4 b/contrib/unbound/acx_nlnetlabs.m4
index 8eccc15b0d80..31e43d67e875 100644
--- a/contrib/unbound/acx_nlnetlabs.m4
+++ b/contrib/unbound/acx_nlnetlabs.m4
@@ -2,7 +2,8 @@
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
# BSD licensed.
#
-# Version 34
+# Version 35
+# 2020-08-24 Use EVP_sha256 instead of HMAC_Update (for openssl-3.0.0).
# 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
@@ -673,16 +674,16 @@ AC_DEFUN([ACX_SSL_CHECKS], [
ACX_RUNTIME_PATH_ADD([$ssldir/lib])
fi
- AC_MSG_CHECKING([for HMAC_Update in -lcrypto])
+ AC_MSG_CHECKING([for EVP_sha256 in -lcrypto])
LIBS="$LIBS -lcrypto"
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
AC_TRY_LINK(, [
- int HMAC_Update(void);
- (void)HMAC_Update();
+ int EVP_sha256(void);
+ (void)EVP_sha256();
], [
AC_MSG_RESULT(yes)
- AC_DEFINE([HAVE_HMAC_UPDATE], 1,
- [If you have HMAC_Update])
+ AC_DEFINE([HAVE_EVP_SHA256], 1,
+ [If you have EVP_sha256])
], [
AC_MSG_RESULT(no)
# check if -lwsock32 or -lgdi32 are needed.
@@ -692,11 +693,11 @@ AC_DEFUN([ACX_SSL_CHECKS], [
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32"
AC_MSG_CHECKING([if -lcrypto needs -lgdi32])
AC_TRY_LINK([], [
- int HMAC_Update(void);
- (void)HMAC_Update();
+ int EVP_sha256(void);
+ (void)EVP_sha256();
],[
- AC_DEFINE([HAVE_HMAC_UPDATE], 1,
- [If you have HMAC_Update])
+ AC_DEFINE([HAVE_EVP_SHA256], 1,
+ [If you have EVP_sha256])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
@@ -706,11 +707,11 @@ AC_DEFUN([ACX_SSL_CHECKS], [
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
AC_MSG_CHECKING([if -lcrypto needs -ldl])
AC_TRY_LINK([], [
- int HMAC_Update(void);
- (void)HMAC_Update();
+ int EVP_sha256(void);
+ (void)EVP_sha256();
],[
- AC_DEFINE([HAVE_HMAC_UPDATE], 1,
- [If you have HMAC_Update])
+ AC_DEFINE([HAVE_EVP_SHA256], 1,
+ [If you have EVP_sha256])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
@@ -720,11 +721,11 @@ AC_DEFUN([ACX_SSL_CHECKS], [
LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
AC_TRY_LINK([], [
- int HMAC_Update(void);
- (void)HMAC_Update();
+ int EVP_sha256(void);
+ (void)EVP_sha256();
],[
- AC_DEFINE([HAVE_HMAC_UPDATE], 1,
- [If you have HMAC_Update])
+ AC_DEFINE([HAVE_EVP_SHA256], 1,
+ [If you have EVP_sha256])
AC_MSG_RESULT(yes)
],[
AC_MSG_RESULT(no)
diff --git a/contrib/unbound/config.guess b/contrib/unbound/config.guess
index e94095c5fbe8..8d70ec2b2633 100755
--- a/contrib/unbound/config.guess
+++ b/contrib/unbound/config.guess
@@ -2,7 +2,7 @@
# Attempt to guess a canonical system name.
# Copyright 1992-2020 Free Software Foundation, Inc.
-timestamp='2020-07-12'
+timestamp='2020-09-19'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -150,17 +150,15 @@ Linux|GNU|GNU/*)
#elif defined(__dietlibc__)
LIBC=dietlibc
#else
+ #include <stdarg.h>
+ #ifdef __DEFINED_va_list
+ LIBC=musl
+ #else
LIBC=gnu
#endif
+ #endif
EOF
eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
-
- # If ldd exists, use it to detect musl libc.
- if command -v ldd >/dev/null && \
- ldd --version 2>&1 | grep -q ^musl
- then
- LIBC=musl
- fi
;;
esac
@@ -404,7 +402,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
- if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
@@ -544,10 +542,10 @@ EOF
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
- if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
+ if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
then
- if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
- [ "$TARGET_BINARY_INTERFACE"x = x ]
+ if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
+ test "$TARGET_BINARY_INTERFACE"x = x
then
echo m88k-dg-dgux"$UNAME_RELEASE"
else
@@ -580,7 +578,7 @@ EOF
echo i386-ibm-aix
exit ;;
ia64:AIX:*:*)
- if [ -x /usr/bin/oslevel ] ; then
+ if test -x /usr/bin/oslevel ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
@@ -620,7 +618,7 @@ EOF
else
IBM_ARCH=powerpc
fi
- if [ -x /usr/bin/lslpp ] ; then
+ if test -x /usr/bin/lslpp ; then
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
@@ -655,7 +653,7 @@ EOF
9000/31?) HP_ARCH=m68000 ;;
9000/[34]??) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
- if [ -x /usr/bin/getconf ]; then
+ if test -x /usr/bin/getconf; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "$sc_cpu_version" in
@@ -669,7 +667,7 @@ EOF
esac ;;
esac
fi
- if [ "$HP_ARCH" = "" ]; then
+ if test "$HP_ARCH" = ""; then
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
@@ -708,7 +706,7 @@ EOF
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
- if [ "$HP_ARCH" = hppa2.0w ]
+ if test "$HP_ARCH" = hppa2.0w
then
set_cc_for_build
@@ -782,7 +780,7 @@ EOF
echo hppa1.0-hp-osf
exit ;;
i*86:OSF1:*:*)
- if [ -x /usr/sbin/sysversion ] ; then
+ if test -x /usr/sbin/sysversion ; then
echo "$UNAME_MACHINE"-unknown-osf1mk
else
echo "$UNAME_MACHINE"-unknown-osf1
@@ -1097,7 +1095,7 @@ EOF
x86_64:Linux:*:*)
set_cc_for_build
LIBCABI=$LIBC
- if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_X32 >/dev/null
@@ -1294,7 +1292,7 @@ EOF
echo mips-sony-newsos6
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
- if [ -d /usr/nec ]; then
+ if test -d /usr/nec; then
echo mips-nec-sysv"$UNAME_RELEASE"
else
echo mips-unknown-sysv"$UNAME_RELEASE"
@@ -1359,7 +1357,7 @@ EOF
else
set_cc_for_build
fi
- if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
diff --git a/contrib/unbound/config.h.in b/contrib/unbound/config.h.in
index f7a4095ed348..f993b81b021a 100644
--- a/contrib/unbound/config.h.in
+++ b/contrib/unbound/config.h.in
@@ -113,6 +113,10 @@
don't. */
#undef HAVE_DECL_INET_PTON
+/* Define to 1 if you have the declaration of `nghttp2_session_server_new',
+ and to 0 if you don't. */
+#undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW
+
/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
don't. */
#undef HAVE_DECL_NID_ED25519
@@ -221,6 +225,9 @@
/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
#undef HAVE_EVP_ENCRYPTINIT_EX
+/* Define to 1 if you have the `EVP_MAC_CTX_set_params' function. */
+#undef HAVE_EVP_MAC_CTX_SET_PARAMS
+
/* Define to 1 if you have the `EVP_MD_CTX_new' function. */
#undef HAVE_EVP_MD_CTX_NEW
@@ -269,6 +276,9 @@
/* Define to 1 if you have the `getentropy' function. */
#undef HAVE_GETENTROPY
+/* Define to 1 if you have the `getifaddrs' function. */
+#undef HAVE_GETIFADDRS
+
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
@@ -296,12 +306,12 @@
/* Define to 1 if you have the `HMAC_Init_ex' function. */
#undef HAVE_HMAC_INIT_EX
-/* If you have HMAC_Update */
-#undef HAVE_HMAC_UPDATE
-
/* If we have htobe64 */
#undef HAVE_HTOBE64
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#undef HAVE_IFADDRS_H
+
/* Define to 1 if you have the `inet_aton' function. */
#undef HAVE_INET_ATON
@@ -371,6 +381,15 @@
/* Define to 1 if you have the <nettle/eddsa.h> header file. */
#undef HAVE_NETTLE_EDDSA_H
+/* Define to 1 if you have the <net/if.h> header file. */
+#undef HAVE_NET_IF_H
+
+/* Define this to use nghttp2 client. */
+#undef HAVE_NGHTTP2
+
+/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
+#undef HAVE_NGHTTP2_NGHTTP2_H
+
/* Use libnss for crypto */
#undef HAVE_NSS
@@ -497,6 +516,9 @@
/* Define if you have the SSL libraries installed. */
#undef HAVE_SSL
+/* Define to 1 if you have the `SSL_CTX_set_alpn_select_cb' function. */
+#undef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
+
/* Define to 1 if you have the `SSL_CTX_set_ciphersuites' function. */
#undef HAVE_SSL_CTX_SET_CIPHERSUITES
@@ -573,6 +595,9 @@
/* Define to 1 if you have the <sys/resource.h> header file. */
#undef HAVE_SYS_RESOURCE_H
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
/* Define to 1 if you have the <sys/sha2.h> header file. */
#undef HAVE_SYS_SHA2_H
@@ -1358,6 +1383,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
#define UNBOUND_DNS_PORT 53
/** default port for DNS over TLS traffic. */
#define UNBOUND_DNS_OVER_TLS_PORT 853
+/** default port for DNS over HTTPS traffic. */
+#define UNBOUND_DNS_OVER_HTTPS_PORT 443
/** default port for unbound control traffic, registered port with IANA,
ub-dns-control 8953/tcp unbound dns nameserver control */
#define UNBOUND_CONTROL_PORT 8953
diff --git a/contrib/unbound/config.sub b/contrib/unbound/config.sub
index 3d9a8dc3d5a7..9bc49a7e9223 100755
--- a/contrib/unbound/config.sub
+++ b/contrib/unbound/config.sub
@@ -2,7 +2,7 @@
# Configuration validation subroutine script.
# Copyright 1992-2020 Free Software Foundation, Inc.
-timestamp='2020-07-10'
+timestamp='2020-09-08'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -1278,7 +1278,7 @@ esac
# Decode manufacturer-specific aliases for certain operating systems.
-if [ x$basic_os != x ]
+if test x$basic_os != x
then
# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just
@@ -1367,13 +1367,7 @@ case $os in
os=psos
;;
qnx*)
- case $cpu in
- x86 | i*86)
- ;;
- *)
- os=nto-$os
- ;;
- esac
+ os=qnx
;;
hiux*)
os=hiuxwe2
@@ -1722,7 +1716,7 @@ case $os in
| skyos* | haiku* | rdos* | toppers* | drops* | es* \
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
- | nsk* | powerunix* | genode* | zvmoe* )
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
@@ -1741,6 +1735,8 @@ esac
case $kernel-$os in
linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* )
;;
+ uclinux-uclibc* )
+ ;;
-dietlibc* | -newlib* | -musl* | -uclibc* )
# These are just libc implementations, not actual OSes, and thus
# require a kernel.
diff --git a/contrib/unbound/configure b/contrib/unbound/configure
index ed66e853047d..69bc15f97fda 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.11.0.
+# Generated by GNU Autoconf 2.69 for unbound 1.12.0.
#
# Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>.
#
@@ -591,8 +591,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unbound'
PACKAGE_TARNAME='unbound'
-PACKAGE_VERSION='1.11.0'
-PACKAGE_STRING='unbound 1.11.0'
+PACKAGE_VERSION='1.12.0'
+PACKAGE_STRING='unbound 1.12.0'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
PACKAGE_URL=''
@@ -882,6 +882,7 @@ enable_tfo_server
with_libevent
with_libexpat
with_libhiredis
+with_libnghttp2
enable_static_exe
enable_fully_static
enable_lock_checks
@@ -1458,7 +1459,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.11.0 to adapt to many kinds of systems.
+\`configure' configures unbound 1.12.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1523,7 +1524,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of unbound 1.11.0:";;
+ short | recursive ) echo "Configuration of unbound 1.12.0:";;
esac
cat <<\_ACEOF
@@ -1642,6 +1643,7 @@ Optional Packages:
outgoing port ranges.
--with-libexpat=path specify explicit path for libexpat.
--with-libhiredis=path specify explicit path for libhiredis.
+ --with-libnghttp2=path specify explicit path for libnghttp2.
--with-dnstap-socket-path=pathname
set default dnstap socket path
--with-protobuf-c=path Path where protobuf-c is installed, for dnstap
@@ -1750,7 +1752,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-unbound configure 1.11.0
+unbound configure 1.12.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2459,7 +2461,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.11.0, which was
+It was created by unbound $as_me 1.12.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2809,13 +2811,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
UNBOUND_VERSION_MAJOR=1
-UNBOUND_VERSION_MINOR=11
+UNBOUND_VERSION_MINOR=12
UNBOUND_VERSION_MICRO=0
LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=9
+LIBUNBOUND_REVISION=10
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -2892,6 +2894,7 @@ LIBUNBOUND_AGE=1
# 1.10.0 had 9:7:1
# 1.10.1 had 9:8:1
# 1.11.0 had 9:9:1
+# 1.12.0 had 9:10:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -14725,7 +14728,7 @@ $as_echo "no" >&6; }
fi
# Checks for header files.
-for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h
+for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h net/if.h
do :
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
@@ -17942,8 +17945,8 @@ $as_echo "found in $ssldir" >&6; }
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HMAC_Update in -lcrypto" >&5
-$as_echo_n "checking for HMAC_Update in -lcrypto... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_sha256 in -lcrypto" >&5
+$as_echo_n "checking for EVP_sha256 in -lcrypto... " >&6; }
LIBS="$LIBS -lcrypto"
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -17953,8 +17956,8 @@ int
main ()
{
- int HMAC_Update(void);
- (void)HMAC_Update();
+ int EVP_sha256(void);
+ (void)EVP_sha256();
;
return 0;
@@ -17965,7 +17968,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_UPDATE 1" >>confdefs.h
+$as_echo "#define HAVE_EVP_SHA256 1" >>confdefs.h
else
@@ -17986,8 +17989,8 @@ int
main ()
{
- int HMAC_Update(void);
- (void)HMAC_Update();
+ int EVP_sha256(void);
+ (void)EVP_sha256();
;
return 0;
@@ -17996,7 +17999,7 @@ _ACEOF
if ac_fn_c_try_link "$LINENO"; then :
-$as_echo "#define HAVE_HMAC_UPDATE 1" >>confdefs.h
+$as_echo "#define HAVE_EVP_SHA256 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -18018,8 +18021,8 @@ int
main ()
{
- int HMAC_Update(void);
- (void)HMAC_Update();
+ int EVP_sha256(void);
+ (void)EVP_sha256();
;
return 0;
@@ -18028,7 +18031,7 @@ _ACEOF
if ac_fn_c_try_link "$LINENO"; then :
-$as_echo "#define HAVE_HMAC_UPDATE 1" >>confdefs.h
+$as_echo "#define HAVE_EVP_SHA256 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -18050,8 +18053,8 @@ int
main ()
{
- int HMAC_Update(void);
- (void)HMAC_Update();
+ int EVP_sha256(void);
+ (void)EVP_sha256();
;
return 0;
@@ -18060,7 +18063,7 @@ _ACEOF
if ac_fn_c_try_link "$LINENO"; then :
-$as_echo "#define HAVE_HMAC_UPDATE 1" >>confdefs.h
+$as_echo "#define HAVE_EVP_SHA256 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
@@ -18245,11 +18248,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char HMAC_Update ();
+char EVP_sha256 ();
int
main ()
{
-return HMAC_Update ();
+return EVP_sha256 ();
;
return 0;
}
@@ -18340,7 +18343,7 @@ fi
done
-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 ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback
+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 ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params
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"
@@ -18356,7 +18359,7 @@ done
# these check_funcs need -lssl
BAKLIBS="$LIBS"
LIBS="-lssl $LIBS"
-for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_tlsext_ticket_key_evp_cb
+for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_tlsext_ticket_key_evp_cb SSL_CTX_set_alpn_select_cb
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"
@@ -19668,6 +19671,70 @@ _ACEOF
fi
+# nghttp2
+
+# Check whether --with-libnghttp2 was given.
+if test "${with_libnghttp2+set}" = set; then :
+ withval=$with_libnghttp2;
+else
+ withval="no"
+fi
+
+found_libnghttp2="no"
+if test x_$withval = x_yes -o x_$withval != x_no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libnghttp2" >&5
+$as_echo_n "checking for libnghttp2... " >&6; }
+ if test x_$withval = x_ -o x_$withval = x_yes; then
+ withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
+ fi
+ for dir in $withval ; do
+ if test -f "$dir/include/nghttp2/nghttp2.h"; then
+ found_libnghttp2="yes"
+ if test "$dir" != "/usr"; then
+ CPPFLAGS="$CPPFLAGS -I$dir/include"
+ LDFLAGS="$LDFLAGS -L$dir/lib"
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5
+$as_echo "found in $dir" >&6; }
+
+$as_echo "#define HAVE_NGHTTP2 1" >>confdefs.h
+
+ LIBS="$LIBS -lnghttp2"
+ break;
+ fi
+ done
+ if test x_$found_libnghttp2 != x_yes; then
+ as_fn_error $? "Could not find libnghttp2, nghttp2.h" "$LINENO" 5
+ fi
+ for ac_header in nghttp2/nghttp2.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "nghttp2/nghttp2.h" "ac_cv_header_nghttp2_nghttp2_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_nghttp2_nghttp2_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_NGHTTP2_NGHTTP2_H 1
+_ACEOF
+
+fi
+
+done
+
+ ac_fn_c_check_decl "$LINENO" "nghttp2_session_server_new" "ac_cv_have_decl_nghttp2_session_server_new" "$ac_includes_default
+ #include <nghttp2/nghttp2.h>
+
+"
+if test "x$ac_cv_have_decl_nghttp2_session_server_new" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW $ac_have_decl
+_ACEOF
+
+fi
+
# set static linking for uninstalled libraries if requested
staticexe=""
@@ -20223,7 +20290,7 @@ if test "$ac_res" != no; then :
fi
-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 shmget accept4
+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 shmget accept4 getifaddrs
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"
@@ -21619,7 +21686,7 @@ _ACEOF
-version=1.11.0
+version=1.12.0
date=`date +'%b %e, %Y'`
@@ -22138,7 +22205,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.11.0, which was
+This file was extended by unbound $as_me 1.12.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -22204,7 +22271,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.11.0
+unbound config.status 1.12.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/contrib/unbound/configure.ac b/contrib/unbound/configure.ac
index 1d16dce72bf8..7d987929469a 100644
--- a/contrib/unbound/configure.ac
+++ b/contrib/unbound/configure.ac
@@ -10,7 +10,7 @@ sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
-m4_define([VERSION_MINOR],[11])
+m4_define([VERSION_MINOR],[12])
m4_define([VERSION_MICRO],[0])
AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues, unbound)
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
@@ -18,7 +18,7 @@ AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=9
+LIBUNBOUND_REVISION=10
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -95,6 +95,7 @@ LIBUNBOUND_AGE=1
# 1.10.0 had 9:7:1
# 1.10.1 had 9:8:1
# 1.11.0 had 9:9:1
+# 1.12.0 had 9:10:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -398,7 +399,7 @@ ACX_LIBTOOL_C_ONLY
PKG_PROG_PKG_CONFIG
# Checks for header files.
-AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h],,, [AC_INCLUDES_DEFAULT])
+AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h net/if.h],,, [AC_INCLUDES_DEFAULT])
# Check for Apple header. This uncovers TARGET_OS_IPHONE, TARGET_OS_TV or TARGET_OS_WATCH
AC_CHECK_HEADERS([TargetConditionals.h])
@@ -831,7 +832,7 @@ AC_SUBST(PC_CRYPTO_DEPENDENCY)
BAKLIBS="$LIBS"
LIBS="-lssl $LIBS"
AC_MSG_CHECKING([if libssl needs -lcrypt32])
-AC_TRY_LINK_FUNC([HMAC_Update], [
+AC_TRY_LINK_FUNC([EVP_sha256], [
AC_MSG_RESULT([no])
LIBS="$BAKLIBS"
], [
@@ -851,12 +852,12 @@ else
AC_MSG_RESULT([no])
fi
AC_CHECK_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h openssl/core_names.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 ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback])
+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 ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params])
# these check_funcs need -lssl
BAKLIBS="$LIBS"
LIBS="-lssl $LIBS"
-AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_tlsext_ticket_key_evp_cb])
+AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_tlsext_ticket_key_evp_cb SSL_CTX_set_alpn_select_cb])
LIBS="$BAKLIBS"
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
@@ -1395,6 +1396,39 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
])
fi
+# nghttp2
+AC_ARG_WITH(libnghttp2, AC_HELP_STRING([--with-libnghttp2=path],
+ [specify explicit path for libnghttp2.]),
+ [ ],[ withval="no" ])
+found_libnghttp2="no"
+if test x_$withval = x_yes -o x_$withval != x_no; then
+ AC_MSG_CHECKING(for libnghttp2)
+ if test x_$withval = x_ -o x_$withval = x_yes; then
+ withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
+ fi
+ for dir in $withval ; do
+ if test -f "$dir/include/nghttp2/nghttp2.h"; then
+ found_libnghttp2="yes"
+ dnl assume /usr is in default path.
+ if test "$dir" != "/usr"; then
+ CPPFLAGS="$CPPFLAGS -I$dir/include"
+ LDFLAGS="$LDFLAGS -L$dir/lib"
+ fi
+ AC_MSG_RESULT(found in $dir)
+ AC_DEFINE([HAVE_NGHTTP2], [1], [Define this to use nghttp2 client.])
+ LIBS="$LIBS -lnghttp2"
+ break;
+ fi
+ done
+ if test x_$found_libnghttp2 != x_yes; then
+ AC_ERROR([Could not find libnghttp2, nghttp2.h])
+ fi
+ AC_CHECK_HEADERS([nghttp2/nghttp2.h],,, [AC_INCLUDES_DEFAULT])
+ AC_CHECK_DECLS([nghttp2_session_server_new], [], [], [AC_INCLUDES_DEFAULT
+ #include <nghttp2/nghttp2.h>
+ ])
+fi
+
# set static linking for uninstalled libraries if requested
AC_SUBST(staticexe)
staticexe=""
@@ -1551,7 +1585,7 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([
AC_MSG_RESULT(no))
AC_SEARCH_LIBS([setusercontext], [util])
-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 shmget accept4])
+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 shmget accept4 getifaddrs])
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
@@ -2131,6 +2165,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
#define UNBOUND_DNS_PORT 53
/** default port for DNS over TLS traffic. */
#define UNBOUND_DNS_OVER_TLS_PORT 853
+/** default port for DNS over HTTPS traffic. */
+#define UNBOUND_DNS_OVER_HTTPS_PORT 443
/** default port for unbound control traffic, registered port with IANA,
ub-dns-control 8953/tcp unbound dns nameserver control */
#define UNBOUND_CONTROL_PORT 8953
diff --git a/contrib/unbound/contrib/aaaa-filter-iterator.patch b/contrib/unbound/contrib/aaaa-filter-iterator.patch
index 9881bde892ad..f51de2a40d9b 100644
--- a/contrib/unbound/contrib/aaaa-filter-iterator.patch
+++ b/contrib/unbound/contrib/aaaa-filter-iterator.patch
@@ -1,10 +1,10 @@
-Index: trunk/doc/unbound.conf.5.in
-===================================================================
---- trunk/doc/unbound.conf.5.in (revision 4357)
-+++ trunk/doc/unbound.conf.5.in (working copy)
-@@ -701,6 +701,13 @@
+diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
+index f426ac5f..147fbfa9 100644
+--- a/doc/unbound.conf.5.in
++++ b/doc/unbound.conf.5.in
+@@ -872,6 +872,13 @@ potentially broken nameservers. A lot of domains will not be resolvable when
this option in enabled. Only use if you know what you are doing.
- This option only has effect when qname-minimisation is enabled. Default is off.
+ This option only has effect when qname-minimisation is enabled. Default is no.
.TP
+.B aaaa\-filter: \fI<yes or no>
+Activate behavior similar to BIND's AAAA-filter.
@@ -16,14 +16,15 @@ Index: trunk/doc/unbound.conf.5.in
.B aggressive\-nsec: \fI<yes or no>
Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
and other denials, using information from previous NXDOMAINs answers.
-Index: trunk/iterator/iter_scrub.c
-===================================================================
---- trunk/iterator/iter_scrub.c (revision 4357)
-+++ trunk/iterator/iter_scrub.c (working copy)
-@@ -617,6 +617,32 @@
+diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c
+index aae934dd..55c55de0 100644
+--- a/iterator/iter_scrub.c
++++ b/iterator/iter_scrub.c
+@@ -667,6 +667,32 @@ static int sanitize_nsec_is_overreach(struct rrset_parse* rrset,
+ return 0;
}
- /**
++/**
+ * ASN: Lookup A records from rrset cache.
+ * @param qinfo: the question originally asked.
+ * @param env: module environment with config and cache.
@@ -49,11 +50,10 @@ Index: trunk/iterator/iter_scrub.c
+ 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 @@
+@@ -686,6 +712,7 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
struct iter_env* ie)
{
@@ -61,7 +61,7 @@ Index: trunk/iterator/iter_scrub.c
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 @@
+@@ -721,6 +748,13 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
rrset = rrset->rrset_all_next;
}
@@ -75,11 +75,10 @@ Index: trunk/iterator/iter_scrub.c
/* 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
-@@ -680,6 +714,24 @@
- prev = NULL;
+@@ -732,6 +766,24 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
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
@@ -97,14 +96,15 @@ Index: trunk/iterator/iter_scrub.c
+ LDNS_RR_TYPE_AAAA, qinfo->qclass);
+ }
+ /* ASN: End of added code */
-
++
/* remove private addresses */
if( (rrset->type == LDNS_RR_TYPE_A ||
-Index: trunk/iterator/iter_utils.c
-===================================================================
---- trunk/iterator/iter_utils.c (revision 4357)
-+++ trunk/iterator/iter_utils.c (working copy)
-@@ -175,6 +175,7 @@
+ rrset->type == LDNS_RR_TYPE_AAAA)) {
+diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
+index 7bc67da6..e10f547a 100644
+--- a/iterator/iter_utils.c
++++ b/iterator/iter_utils.c
+@@ -175,6 +175,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
}
iter_env->supports_ipv6 = cfg->do_ip6;
iter_env->supports_ipv4 = cfg->do_ip4;
@@ -112,11 +112,11 @@ Index: trunk/iterator/iter_utils.c
return 1;
}
-Index: trunk/iterator/iterator.c
-===================================================================
---- trunk/iterator/iterator.c (revision 4357)
-+++ trunk/iterator/iterator.c (working copy)
-@@ -1847,6 +1847,53 @@
+diff --git a/iterator/iterator.c b/iterator/iterator.c
+index 23b07ea9..ca29b48c 100644
+--- a/iterator/iterator.c
++++ b/iterator/iterator.c
+@@ -2127,6 +2127,53 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
return 0;
}
@@ -170,7 +170,7 @@ Index: trunk/iterator/iterator.c
/**
* This is the request event state where the request will be sent to one of
-@@ -1894,6 +1941,13 @@
+@@ -2186,6 +2233,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
@@ -184,7 +184,7 @@ Index: trunk/iterator/iterator.c
/* Make sure we have a delegation point, otherwise priming failed
* or another failure occurred */
if(!iq->dp) {
-@@ -3095,6 +3149,61 @@
+@@ -3574,6 +3628,61 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
return 0;
}
@@ -246,7 +246,7 @@ Index: trunk/iterator/iterator.c
/*
* Return priming query results to interested super querystates.
*
-@@ -3114,6 +3223,9 @@
+@@ -3593,6 +3702,9 @@ iter_inform_super(struct module_qstate* qstate, int id,
else if(super->qinfo.qtype == LDNS_RR_TYPE_DS && ((struct iter_qstate*)
super->minfo[id])->state == DSNS_FIND_STATE)
processDSNSResponse(qstate, id, super);
@@ -256,7 +256,7 @@ Index: trunk/iterator/iterator.c
else if(qstate->return_rcode != LDNS_RCODE_NOERROR)
error_supers(qstate, id, super);
else if(qstate->is_priming)
-@@ -3151,6 +3263,9 @@
+@@ -3630,6 +3742,9 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq,
case INIT_REQUEST_3_STATE:
cont = processInitRequest3(qstate, iq, id);
break;
@@ -266,7 +266,7 @@ Index: trunk/iterator/iterator.c
case QUERYTARGETS_STATE:
cont = processQueryTargets(qstate, iq, ie, id);
break;
-@@ -3460,6 +3575,8 @@
+@@ -3961,6 +4076,8 @@ iter_state_to_string(enum iter_state state)
return "INIT REQUEST STATE (stage 2)";
case INIT_REQUEST_3_STATE:
return "INIT REQUEST STATE (stage 3)";
@@ -275,7 +275,7 @@ Index: trunk/iterator/iterator.c
case QUERYTARGETS_STATE :
return "QUERY TARGETS STATE";
case PRIME_RESP_STATE :
-@@ -3484,6 +3601,7 @@
+@@ -3985,6 +4102,7 @@ iter_state_is_responsestate(enum iter_state s)
case INIT_REQUEST_STATE :
case INIT_REQUEST_2_STATE :
case INIT_REQUEST_3_STATE :
@@ -283,11 +283,11 @@ Index: trunk/iterator/iterator.c
case QUERYTARGETS_STATE :
case COLLECT_CLASS_STATE :
return 0;
-Index: trunk/iterator/iterator.h
-===================================================================
---- trunk/iterator/iterator.h (revision 4357)
-+++ trunk/iterator/iterator.h (working copy)
-@@ -130,6 +130,9 @@
+diff --git a/iterator/iterator.h b/iterator/iterator.h
+index 342ac207..731948d1 100644
+--- a/iterator/iterator.h
++++ b/iterator/iterator.h
+@@ -135,6 +135,9 @@ struct iter_env {
*/
int* target_fetch_policy;
@@ -297,10 +297,11 @@ Index: trunk/iterator/iterator.h
/** lock on ratelimit counter */
lock_basic_type queries_ratelimit_lock;
/** number of queries that have been ratelimited */
-@@ -182,6 +185,14 @@
+@@ -186,6 +189,14 @@ enum iter_state {
+ */
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
@@ -308,29 +309,28 @@ Index: trunk/iterator/iterator.h
+ */
+ 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 responsible for iterating through a list of
-@@ -364,6 +375,13 @@
- * be used when creating the state. A higher one will be attempted.
+@@ -375,6 +386,13 @@ struct iter_qstate {
*/
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 4357)
-+++ trunk/pythonmod/interface.i (working copy)
-@@ -851,6 +851,7 @@
+
+diff --git a/pythonmod/interface.i b/pythonmod/interface.i
+index f08b575d..47f1bb2e 100644
+--- a/pythonmod/interface.i
++++ b/pythonmod/interface.i
+@@ -975,6 +975,7 @@ struct config_file {
int harden_dnssec_stripped;
int harden_referral_path;
int use_caps_bits_for_id;
@@ -338,11 +338,11 @@ Index: trunk/pythonmod/interface.i
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 4357)
-+++ trunk/util/config_file.c (working copy)
-@@ -195,6 +195,7 @@
+diff --git a/util/config_file.c b/util/config_file.c
+index 0ab8614a..729fb147 100644
+--- a/util/config_file.c
++++ b/util/config_file.c
+@@ -218,6 +218,7 @@ config_create(void)
cfg->harden_referral_path = 0;
cfg->harden_algo_downgrade = 0;
cfg->use_caps_bits_for_id = 0;
@@ -350,11 +350,11 @@ Index: trunk/util/config_file.c
cfg->caps_whitelist = NULL;
cfg->private_address = NULL;
cfg->private_domain = NULL;
-Index: trunk/util/config_file.h
-===================================================================
---- trunk/util/config_file.h (revision 4357)
-+++ trunk/util/config_file.h (working copy)
-@@ -209,6 +209,8 @@
+diff --git a/util/config_file.h b/util/config_file.h
+index e61257a3..dabaa7bb 100644
+--- a/util/config_file.h
++++ b/util/config_file.h
+@@ -260,6 +260,8 @@ struct config_file {
int harden_algo_downgrade;
/** use 0x20 bits in query as random ID bits */
int use_caps_bits_for_id;
@@ -363,11 +363,11 @@ Index: trunk/util/config_file.h
/** 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 4357)
-+++ trunk/util/configlexer.lex (working copy)
-@@ -279,6 +279,7 @@
+diff --git a/util/configlexer.lex b/util/configlexer.lex
+index 79a0edca..4eaec678 100644
+--- a/util/configlexer.lex
++++ b/util/configlexer.lex
+@@ -304,6 +304,7 @@ harden-algo-downgrade{COLON} { YDVAR(1, VAR_HARDEN_ALGO_DOWNGRADE) }
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) }
@@ -375,11 +375,11 @@ Index: trunk/util/configlexer.lex
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 4357)
-+++ trunk/util/configparser.y (working copy)
-@@ -95,6 +95,7 @@
+diff --git a/util/configparser.y b/util/configparser.y
+index 1d0e8658..f284dd43 100644
+--- a/util/configparser.y
++++ b/util/configparser.y
+@@ -97,6 +97,7 @@ extern struct config_parser_state* cfg_parser;
%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
@@ -387,7 +387,7 @@ Index: trunk/util/configparser.y
%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
-@@ -203,6 +204,7 @@
+@@ -233,6 +234,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size |
server_harden_referral_path | server_private_address |
server_private_domain | server_extended_statistics |
@@ -395,12 +395,10 @@ Index: trunk/util/configparser.y
server_local_data_ptr | server_jostle_timeout |
server_unwanted_reply_threshold | server_log_time_ascii |
server_domain_insecure | server_val_sig_skew_min |
-@@ -1183,6 +1185,15 @@
- OUTYY(("P(server_caps_whitelist:%s)\n", $2));
- if(!cfg_strlist_insert(&cfg_parser->cfg->caps_whitelist, $2))
+@@ -1563,6 +1565,15 @@ server_caps_whitelist: VAR_CAPS_WHITELIST STRING_ARG
yyerror("out of memory");
-+ }
-+ ;
+ }
+ ;
+server_aaaa_filter: VAR_AAAA_FILTER STRING_ARG
+ {
+ OUTYY(("P(server_aaaa_filter:%s)\n", $2));
@@ -408,6 +406,8 @@ Index: trunk/util/configparser.y
+ 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/unbound.service.in b/contrib/unbound/contrib/unbound.service.in
index 8ebe529c9ab6..c95ab94b343a 100644
--- a/contrib/unbound/contrib/unbound.service.in
+++ b/contrib/unbound/contrib/unbound.service.in
@@ -42,9 +42,9 @@
[Unit]
Description=Validating, recursive, and caching DNS resolver
Documentation=man:unbound(8)
-After=network.target
-Before=network-online.target nss-lookup.target
-Wants=nss-lookup.target
+After=network-online.target
+Before=nss-lookup.target
+Wants=network-online.target nss-lookup.target
[Install]
WantedBy=multi-user.target
diff --git a/contrib/unbound/contrib/unbound_munin_ b/contrib/unbound/contrib/unbound_munin_
index 2839cd8b5365..defca291c649 100755
--- a/contrib/unbound/contrib/unbound_munin_
+++ b/contrib/unbound/contrib/unbound_munin_
@@ -174,11 +174,11 @@ get_state ( ) {
if test "$1" = "autoconf" ; then
if test ! -f $conf; then
echo no "($conf does not exist)"
- exit 1
+ exit 0
fi
if test ! -d `dirname $state`; then
echo no "(`dirname $state` directory does not exist)"
- exit 1
+ exit 0
fi
echo yes
exit 0
diff --git a/contrib/unbound/daemon/daemon.c b/contrib/unbound/daemon/daemon.c
index 5d4279259ed6..f480c94e61f6 100644
--- a/contrib/unbound/daemon/daemon.c
+++ b/contrib/unbound/daemon/daemon.c
@@ -77,6 +77,7 @@
#include "util/storage/lookup3.h"
#include "util/storage/slabhash.h"
#include "util/tcp_conn_limit.h"
+#include "util/edns.h"
#include "services/listen_dnsport.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
@@ -290,6 +291,15 @@ daemon_init(void)
free(daemon);
return NULL;
}
+ if(!(daemon->env->edns_tags = edns_tags_create())) {
+ auth_zones_delete(daemon->env->auth_zones);
+ acl_list_delete(daemon->acl);
+ tcl_list_delete(daemon->tcl);
+ edns_known_options_delete(daemon->env);
+ free(daemon->env);
+ free(daemon);
+ return NULL;
+ }
return daemon;
}
@@ -298,6 +308,8 @@ daemon_open_shared_ports(struct daemon* daemon)
{
log_assert(daemon);
if(daemon->cfg->port != daemon->listening_port) {
+ char** resif = NULL;
+ int num_resif = 0;
size_t i;
struct listen_port* p0;
daemon->reuseport = 0;
@@ -308,15 +320,18 @@ daemon_open_shared_ports(struct daemon* daemon)
free(daemon->ports);
daemon->ports = NULL;
}
+ if(!resolve_interface_names(daemon->cfg, &resif, &num_resif))
+ return 0;
/* see if we want to reuseport */
#ifdef SO_REUSEPORT
if(daemon->cfg->so_reuseport && daemon->cfg->num_threads > 0)
daemon->reuseport = 1;
#endif
/* try to use reuseport */
- p0 = listening_ports_open(daemon->cfg, &daemon->reuseport);
+ p0 = listening_ports_open(daemon->cfg, resif, num_resif, &daemon->reuseport);
if(!p0) {
listening_ports_free(p0);
+ config_del_strarray(resif, num_resif);
return 0;
}
if(daemon->reuseport) {
@@ -330,6 +345,7 @@ daemon_open_shared_ports(struct daemon* daemon)
if(!(daemon->ports = (struct listen_port**)calloc(
daemon->num_ports, sizeof(*daemon->ports)))) {
listening_ports_free(p0);
+ config_del_strarray(resif, num_resif);
return 0;
}
daemon->ports[0] = p0;
@@ -338,16 +354,19 @@ daemon_open_shared_ports(struct daemon* daemon)
for(i=1; i<daemon->num_ports; i++) {
if(!(daemon->ports[i]=
listening_ports_open(daemon->cfg,
+ resif, num_resif,
&daemon->reuseport))
|| !daemon->reuseport ) {
for(i=0; i<daemon->num_ports; i++)
listening_ports_free(daemon->ports[i]);
free(daemon->ports);
daemon->ports = NULL;
+ config_del_strarray(resif, num_resif);
return 0;
}
}
}
+ config_del_strarray(resif, num_resif);
daemon->listening_port = daemon->cfg->port;
}
if(!daemon->cfg->remote_control_enable && daemon->rc_port) {
@@ -619,6 +638,10 @@ daemon_fork(struct daemon* daemon)
&daemon->use_rpz))
fatal_exit("auth_zones could not be setup");
+ /* Set-up EDNS tags */
+ if(!edns_tags_apply_cfg(daemon->env->edns_tags, daemon->cfg))
+ fatal_exit("Could not set up EDNS tags");
+
/* setup modules */
daemon_setup_modules(daemon);
@@ -750,6 +773,7 @@ daemon_delete(struct daemon* daemon)
rrset_cache_delete(daemon->env->rrset_cache);
infra_delete(daemon->env->infra_cache);
edns_known_options_delete(daemon->env);
+ edns_tags_delete(daemon->env->edns_tags);
auth_zones_delete(daemon->env->auth_zones);
}
ub_randfree(daemon->rand);
diff --git a/contrib/unbound/daemon/remote.c b/contrib/unbound/daemon/remote.c
index aa263d074c64..8324e1901f3e 100644
--- a/contrib/unbound/daemon/remote.c
+++ b/contrib/unbound/daemon/remote.c
@@ -329,7 +329,8 @@ 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_freebind, cfg->use_systemd, cfg->ip_dscp);
+ cfg->ip_transparent, 0, 0, cfg->ip_freebind,
+ cfg->use_systemd, cfg->ip_dscp);
freeaddrinfo(res);
}
@@ -348,11 +349,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
/* alloc */
n = (struct listen_port*)calloc(1, sizeof(*n));
if(!n) {
-#ifndef USE_WINSOCK
- close(fd);
-#else
- closesocket(fd);
-#endif
+ sock_close(fd);
log_err("out of memory");
return 0;
}
@@ -461,11 +458,7 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
if(rc->active >= rc->max_active) {
log_warn("drop incoming remote control: too many connections");
close_exit:
-#ifndef USE_WINSOCK
- close(newfd);
-#else
- closesocket(newfd);
-#endif
+ sock_close(newfd);
return 0;
}
@@ -574,11 +567,8 @@ ssl_print_text(RES* res, const char* text)
if(r == -1) {
if(errno == EAGAIN || errno == EINTR)
continue;
-#ifndef USE_WINSOCK
- log_err("could not send: %s", strerror(errno));
-#else
- log_err("could not send: %s", wsa_strerror(WSAGetLastError()));
-#endif
+ log_err("could not send: %s",
+ sock_strerror(errno));
return 0;
}
at += r;
@@ -635,11 +625,8 @@ ssl_read_line(RES* res, char* buf, size_t max)
}
if(errno == EINTR || errno == EAGAIN)
continue;
-#ifndef USE_WINSOCK
- log_err("could not recv: %s", strerror(errno));
-#else
- log_err("could not recv: %s", wsa_strerror(WSAGetLastError()));
-#endif
+ log_err("could not recv: %s",
+ sock_strerror(errno));
return 0;
}
break;
@@ -862,6 +849,12 @@ print_mem(RES* ssl, struct worker* worker, struct daemon* daemon,
if(!print_longnum(ssl, "mem.streamwait"SQ,
(size_t)s->svr.mem_stream_wait))
return 0;
+ if(!print_longnum(ssl, "mem.http.query_buffer"SQ,
+ (size_t)s->svr.mem_http2_query_buffer))
+ return 0;
+ if(!print_longnum(ssl, "mem.http.response_buffer"SQ,
+ (size_t)s->svr.mem_http2_response_buffer))
+ return 0;
return 1;
}
@@ -988,6 +981,8 @@ print_ext(RES* ssl, struct ub_stats_info* s)
(unsigned long)s->svr.qtls_resume)) return 0;
if(!ssl_printf(ssl, "num.query.ipv6"SQ"%lu\n",
(unsigned long)s->svr.qipv6)) return 0;
+ if(!ssl_printf(ssl, "num.query.https"SQ"%lu\n",
+ (unsigned long)s->svr.qhttps)) return 0;
/* flags */
if(!ssl_printf(ssl, "num.query.flags.QR"SQ"%lu\n",
(unsigned long)s->svr.qbit_QR)) return 0;
@@ -3116,11 +3111,7 @@ handle_req(struct daemon_remote* rc, struct rc_state* s, RES* res)
if(rr == 0) return;
if(errno == EINTR || errno == EAGAIN)
continue;
-#ifndef USE_WINSOCK
- log_err("could not recv: %s", strerror(errno));
-#else
- log_err("could not recv: %s", wsa_strerror(WSAGetLastError()));
-#endif
+ log_err("could not recv: %s", sock_strerror(errno));
return;
}
r = (int)rr;
diff --git a/contrib/unbound/daemon/stats.c b/contrib/unbound/daemon/stats.c
index a568ba070a57..8720a52d6c6e 100644
--- a/contrib/unbound/daemon/stats.c
+++ b/contrib/unbound/daemon/stats.c
@@ -271,6 +271,7 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
s->svr.ans_secure += (long long)worker->env.mesh->ans_secure;
s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus;
s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata;
+ s->svr.ans_expired += (long long)worker->env.mesh->ans_expired;
for(i=0; i<UB_STATS_RCODE_NUM; i++)
s->svr.ans_rcode[i] += (long long)worker->env.mesh->ans_rcode[i];
for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++)
@@ -335,6 +336,10 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
}
s->svr.mem_stream_wait =
(long long)tcp_req_info_get_stream_buffer_size();
+ s->svr.mem_http2_query_buffer =
+ (long long)http2_get_query_buffer_size();
+ s->svr.mem_http2_response_buffer =
+ (long long)http2_get_response_buffer_size();
/* Set neg cache usage numbers */
set_neg_cache_stats(worker, &s->svr, reset);
@@ -421,6 +426,7 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
total->svr.qtcp_outgoing += a->svr.qtcp_outgoing;
total->svr.qtls += a->svr.qtls;
total->svr.qtls_resume += a->svr.qtls_resume;
+ total->svr.qhttps += a->svr.qhttps;
total->svr.qipv6 += a->svr.qipv6;
total->svr.qbit_QR += a->svr.qbit_QR;
total->svr.qbit_AA += a->svr.qbit_AA;
@@ -484,6 +490,8 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
if(SSL_session_reused(c->ssl))
stats->qtls_resume++;
#endif
+ if(c->type == comm_http)
+ stats->qhttps++;
}
}
if(repinfo && addr_is_ip6(&repinfo->addr, repinfo->addrlen))
diff --git a/contrib/unbound/daemon/unbound.c b/contrib/unbound/daemon/unbound.c
index 3f96603c4307..cd0fd69f2ca4 100644
--- a/contrib/unbound/daemon/unbound.c
+++ b/contrib/unbound/daemon/unbound.c
@@ -92,7 +92,7 @@
#include <TargetConditionals.h>
#endif
-#if defined(TARGET_OS_TV) || defined(TARGET_OS_WATCH)
+#if (defined(TARGET_OS_TV) && TARGET_OS_TV) || (defined(TARGET_OS_WATCH) && TARGET_OS_WATCH)
#undef HAVE_FORK
#endif
diff --git a/contrib/unbound/daemon/worker.c b/contrib/unbound/daemon/worker.c
index 23e3244c5041..5ad8ce4e4094 100644
--- a/contrib/unbound/daemon/worker.c
+++ b/contrib/unbound/daemon/worker.c
@@ -1109,7 +1109,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
struct respip_client_info* cinfo = NULL, cinfo_tmp;
memset(&qinfo, 0, sizeof(qinfo));
- if(error != NETEVENT_NOERROR || !repinfo) {
+ if((error != NETEVENT_NOERROR && error != NETEVENT_DONE)|| !repinfo) {
/* some bad tcp query DNS formats give these error calls */
verbose(VERB_ALGO, "handle request called with err=%d", error);
return 0;
@@ -1219,7 +1219,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
- server_stats_insrcode(&worker->stats, c->buffer);
goto send_reply;
}
if(worker->env.cfg->log_queries) {
@@ -1237,7 +1236,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
LDNS_RCODE_REFUSED);
if(worker->stats.extended) {
worker->stats.qtype[qinfo.qtype]++;
- server_stats_insrcode(&worker->stats, c->buffer);
}
goto send_reply;
}
@@ -1259,7 +1257,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
LDNS_RCODE_FORMERR);
if(worker->stats.extended) {
worker->stats.qtype[qinfo.qtype]++;
- server_stats_insrcode(&worker->stats, c->buffer);
}
goto send_reply;
}
@@ -1275,7 +1272,6 @@ 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), &reply_edns);
regional_free_all(worker->scratchpad);
- server_stats_insrcode(&worker->stats, c->buffer);
goto send_reply;
}
if(edns.edns_present) {
@@ -1354,7 +1350,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
edns.udp_size = 65535; /* max size for TCP replies */
if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo,
&edns, repinfo, c->buffer)) {
- server_stats_insrcode(&worker->stats, c->buffer);
regional_free_all(worker->scratchpad);
goto send_reply;
}
@@ -1375,7 +1370,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
comm_point_drop_reply(repinfo);
return 0;
}
- server_stats_insrcode(&worker->stats, c->buffer);
goto send_reply;
}
if(worker->env.auth_zones &&
@@ -1387,7 +1381,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
comm_point_drop_reply(repinfo);
return 0;
}
- server_stats_insrcode(&worker->stats, c->buffer);
goto send_reply;
}
if(worker->env.auth_zones &&
@@ -1403,7 +1396,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
if(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer)) &&
acl != acl_deny_non_local && acl != acl_refuse_non_local)
LDNS_RA_SET(sldns_buffer_begin(c->buffer));
- server_stats_insrcode(&worker->stats, c->buffer);
goto send_reply;
}
@@ -1432,7 +1424,6 @@ 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), NULL);
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);
goto send_reply;
@@ -1588,9 +1579,9 @@ send_reply_rc:
if(is_expired_answer) {
worker->stats.ans_expired++;
}
+ server_stats_insrcode(&worker->stats, c->buffer);
if(worker->stats.extended) {
if(is_secure_answer) worker->stats.ans_secure++;
- server_stats_insrcode(&worker->stats, repinfo->c->buffer);
}
#ifdef USE_DNSTAP
if(worker->dtenv.log_client_response_messages)
@@ -1726,14 +1717,6 @@ worker_create(struct daemon* daemon, int id, int* ports, int n)
return NULL;
}
explicit_bzero(&seed, sizeof(seed));
-#ifdef USE_DNSTAP
- if(daemon->cfg->dnstap) {
- log_assert(daemon->dtenv != NULL);
- memcpy(&worker->dtenv, daemon->dtenv, sizeof(struct dt_env));
- if(!dt_init(&worker->dtenv))
- fatal_exit("dt_init failed");
- }
-#endif
return worker;
}
@@ -1792,12 +1775,21 @@ worker_init(struct worker* worker, struct config_file *cfg,
} else { /* !do_sigs */
worker->comsig = NULL;
}
+#ifdef USE_DNSTAP
+ if(cfg->dnstap) {
+ log_assert(worker->daemon->dtenv != NULL);
+ memcpy(&worker->dtenv, worker->daemon->dtenv, sizeof(struct dt_env));
+ if(!dt_init(&worker->dtenv, worker->base))
+ fatal_exit("dt_init failed");
+ }
+#endif
worker->front = listen_create(worker->base, ports,
cfg->msg_buffer_size, (int)cfg->incoming_num_tcp,
cfg->do_tcp_keepalive
? cfg->tcp_keepalive_timeout
: cfg->tcp_idle_timeout,
- worker->daemon->tcl,
+ cfg->harden_large_queries, cfg->http_max_streams,
+ cfg->http_endpoint, worker->daemon->tcl,
worker->daemon->listen_sslctx,
dtenv, worker_handle_request, worker);
if(!worker->front) {
diff --git a/contrib/unbound/dnstap/dnstap.c b/contrib/unbound/dnstap/dnstap.c
index cc5449dff4a1..0c8c6c4d462a 100644
--- a/contrib/unbound/dnstap/dnstap.c
+++ b/contrib/unbound/dnstap/dnstap.c
@@ -134,9 +134,15 @@ dt_create(struct config_file* cfg)
if(cfg->dnstap && cfg->dnstap_socket_path && cfg->dnstap_socket_path[0] &&
(cfg->dnstap_ip==NULL || cfg->dnstap_ip[0]==0)) {
+ char* p = fname_after_chroot(cfg->dnstap_socket_path, cfg, 1);
+ if(!p) {
+ log_err("malloc failure");
+ return NULL;
+ }
verbose(VERB_OPS, "attempting to connect to dnstap socket %s",
- cfg->dnstap_socket_path);
- check_socket_file(cfg->dnstap_socket_path);
+ p);
+ check_socket_file(p);
+ free(p);
}
env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
@@ -240,9 +246,9 @@ dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
}
int
-dt_init(struct dt_env *env)
+dt_init(struct dt_env *env, struct comm_base* base)
{
- env->msgqueue = dt_msg_queue_create();
+ env->msgqueue = dt_msg_queue_create(base);
if(!env->msgqueue) {
log_err("malloc failure");
return 0;
diff --git a/contrib/unbound/dnstap/dnstap.h b/contrib/unbound/dnstap/dnstap.h
index cfef6fc420b9..783b8c51430a 100644
--- a/contrib/unbound/dnstap/dnstap.h
+++ b/contrib/unbound/dnstap/dnstap.h
@@ -101,10 +101,11 @@ dt_apply_cfg(struct dt_env *env, struct config_file *cfg);
/**
* Initialize per-worker state in dnstap environment object.
* @param env: dnstap environment object to initialize, created with dt_create().
+ * @param base: event base for wakeup timer.
* @return: true on success, false on failure.
*/
int
-dt_init(struct dt_env *env);
+dt_init(struct dt_env *env, struct comm_base* base);
/**
* Deletes the per-worker state created by dt_init
diff --git a/contrib/unbound/dnstap/dtstream.c b/contrib/unbound/dnstap/dtstream.c
index dda3ef1ff485..b0918c52cc63 100644
--- a/contrib/unbound/dnstap/dtstream.c
+++ b/contrib/unbound/dnstap/dtstream.c
@@ -68,6 +68,8 @@
#define DTIO_RECONNECT_TIMEOUT_MAX 1000
/** the msec to wait for reconnect slow, to stop busy spinning on reconnect */
#define DTIO_RECONNECT_TIMEOUT_SLOW 1000
+/** number of messages before wakeup of thread */
+#define DTIO_MSG_FOR_WAKEUP 32
/** maximum length of received frame */
#define DTIO_RECV_FRAME_MAX_LEN 1000
@@ -99,13 +101,18 @@ static int dtio_enable_brief_write(struct dt_io_thread* dtio);
#endif
struct dt_msg_queue*
-dt_msg_queue_create(void)
+dt_msg_queue_create(struct comm_base* base)
{
struct dt_msg_queue* mq = calloc(1, sizeof(*mq));
if(!mq) return NULL;
mq->maxsize = 1*1024*1024; /* set max size of buffer, per worker,
about 1 M should contain 64K messages with some overhead,
or a whole bunch smaller ones */
+ mq->wakeup_timer = comm_timer_create(base, mq_wakeup_cb, mq);
+ if(!mq->wakeup_timer) {
+ free(mq);
+ return NULL;
+ }
lock_basic_init(&mq->lock);
lock_protect(&mq->lock, mq, sizeof(*mq));
return mq;
@@ -125,6 +132,7 @@ dt_msg_queue_clear(struct dt_msg_queue* mq)
mq->first = NULL;
mq->last = NULL;
mq->cursize = 0;
+ mq->msgcount = 0;
}
void
@@ -133,6 +141,7 @@ dt_msg_queue_delete(struct dt_msg_queue* mq)
if(!mq) return;
lock_basic_destroy(&mq->lock);
dt_msg_queue_clear(mq);
+ comm_timer_delete(mq->wakeup_timer);
free(mq);
}
@@ -149,15 +158,14 @@ static void dtio_wakeup(struct dt_io_thread* dtio)
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
continue;
- log_err("dnstap io wakeup: write: %s", strerror(errno));
#else
if(WSAGetLastError() == WSAEINPROGRESS)
continue;
if(WSAGetLastError() == WSAEWOULDBLOCK)
continue;
- log_err("dnstap io stop: write: %s",
- wsa_strerror(WSAGetLastError()));
#endif
+ log_err("dnstap io wakeup: write: %s",
+ sock_strerror(errno));
break;
}
break;
@@ -165,9 +173,56 @@ static void dtio_wakeup(struct dt_io_thread* dtio)
}
void
+mq_wakeup_cb(void* arg)
+{
+ struct dt_msg_queue* mq = (struct dt_msg_queue*)arg;
+ /* even if the dtio is already active, because perhaps much
+ * traffic suddenly, we leave the timer running to save on
+ * managing it, the once a second timer is less work then
+ * starting and stopping the timer frequently */
+ lock_basic_lock(&mq->dtio->wakeup_timer_lock);
+ mq->dtio->wakeup_timer_enabled = 0;
+ lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
+ dtio_wakeup(mq->dtio);
+}
+
+/** start timer to wakeup dtio because there is content in the queue */
+static void
+dt_msg_queue_start_timer(struct dt_msg_queue* mq)
+{
+ struct timeval tv;
+ /* Start a timer to process messages to be logged.
+ * If we woke up the dtio thread for every message, the wakeup
+ * messages take up too much processing power. If the queue
+ * fills up the wakeup happens immediately. The timer wakes it up
+ * if there are infrequent messages to log. */
+
+ /* we cannot start a timer in dtio thread, because it is a different
+ * thread and its event base is in use by the other thread, it would
+ * give race conditions if we tried to modify its event base,
+ * and locks would wait until it woke up, and this is what we do. */
+
+ /* do not start the timer if a timer already exists, perhaps
+ * in another worker. So this variable is protected by a lock in
+ * dtio */
+ lock_basic_lock(&mq->dtio->wakeup_timer_lock);
+ if(mq->dtio->wakeup_timer_enabled) {
+ lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
+ return;
+ }
+ mq->dtio->wakeup_timer_enabled = 1; /* we are going to start one */
+ lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
+
+ /* start the timer, in mq, in the event base of our worker */
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ comm_timer_set(mq->wakeup_timer, &tv);
+}
+
+void
dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len)
{
- int wakeup = 0;
+ int wakeupnow = 0, wakeupstarttimer = 0;
struct dt_msg_entry* entry;
/* check conditions */
@@ -198,9 +253,15 @@ dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len)
/* aqcuire lock */
lock_basic_lock(&mq->lock);
- /* list was empty, wakeup dtio */
+ /* if list was empty, start timer for (eventual) wakeup */
if(mq->first == NULL)
- wakeup = 1;
+ wakeupstarttimer = 1;
+ /* if list contains more than wakeupnum elements, wakeup now,
+ * or if list is (going to be) almost full */
+ if(mq->msgcount == DTIO_MSG_FOR_WAKEUP ||
+ (mq->cursize < mq->maxsize * 9 / 10 &&
+ mq->cursize+len >= mq->maxsize * 9 / 10))
+ wakeupnow = 1;
/* see if it is going to fit */
if(mq->cursize + len > mq->maxsize) {
/* buffer full, or congested. */
@@ -211,6 +272,7 @@ dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len)
return;
}
mq->cursize += len;
+ mq->msgcount ++;
/* append to list */
if(mq->last) {
mq->last->next = entry;
@@ -221,13 +283,19 @@ dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len)
/* release lock */
lock_basic_unlock(&mq->lock);
- if(wakeup)
+ if(wakeupnow) {
dtio_wakeup(mq->dtio);
+ } else if(wakeupstarttimer) {
+ dt_msg_queue_start_timer(mq);
+ }
}
struct dt_io_thread* dt_io_thread_create(void)
{
struct dt_io_thread* dtio = calloc(1, sizeof(*dtio));
+ lock_basic_init(&dtio->wakeup_timer_lock);
+ lock_protect(&dtio->wakeup_timer_lock, &dtio->wakeup_timer_enabled,
+ sizeof(dtio->wakeup_timer_enabled));
return dtio;
}
@@ -235,6 +303,7 @@ void dt_io_thread_delete(struct dt_io_thread* dtio)
{
struct dt_io_list_item* item, *nextitem;
if(!dtio) return;
+ lock_basic_destroy(&dtio->wakeup_timer_lock);
item=dtio->io_list;
while(item) {
nextitem = item->next;
@@ -279,7 +348,8 @@ int dt_io_thread_apply_cfg(struct dt_io_thread* dtio, struct config_file *cfg)
return 0;
}
free(dtio->socket_path);
- dtio->socket_path = strdup(cfg->dnstap_socket_path);
+ dtio->socket_path = fname_after_chroot(cfg->dnstap_socket_path,
+ cfg, 1);
if(!dtio->socket_path) {
log_err("dnstap setup: malloc failure");
return 0;
@@ -416,6 +486,7 @@ static int dt_msg_queue_pop(struct dt_msg_queue* mq, void** buf,
mq->first = entry->next;
if(!entry->next) mq->last = NULL;
mq->cursize -= entry->len;
+ mq->msgcount --;
lock_basic_unlock(&mq->lock);
*buf = entry->buf;
@@ -587,11 +658,7 @@ static void dtio_del_output_event(struct dt_io_thread* dtio)
/** close dtio socket and set it to -1 */
static void dtio_close_fd(struct dt_io_thread* dtio)
{
-#ifndef USE_WINSOCK
- close(dtio->fd);
-#else
- closesocket(dtio->fd);
-#endif
+ sock_close(dtio->fd);
dtio->fd = -1;
}
@@ -659,13 +726,8 @@ static int dtio_check_nb_connect(struct dt_io_thread* dtio)
char* to = dtio->socket_path;
if(!to) to = dtio->ip_str;
if(!to) to = "";
-#ifndef USE_WINSOCK
log_err("dnstap io: failed to connect to \"%s\": %s",
- to, strerror(error));
-#else
- log_err("dnstap io: failed to connect to \"%s\": %s",
- to, wsa_strerror(error));
-#endif
+ to, sock_strerror(error));
return -1; /* error, close it */
}
@@ -742,7 +804,6 @@ static int dtio_write_buf(struct dt_io_thread* dtio, uint8_t* buf,
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
return 0;
- log_err("dnstap io: failed send: %s", strerror(errno));
#else
if(WSAGetLastError() == WSAEINPROGRESS)
return 0;
@@ -752,9 +813,8 @@ static int dtio_write_buf(struct dt_io_thread* dtio, uint8_t* buf,
UB_EV_WRITE);
return 0;
}
- log_err("dnstap io: failed send: %s",
- wsa_strerror(WSAGetLastError()));
#endif
+ log_err("dnstap io: failed send: %s", sock_strerror(errno));
return -1;
}
return ret;
@@ -778,7 +838,6 @@ static int dtio_write_with_writev(struct dt_io_thread* dtio)
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
return 0;
- log_err("dnstap io: failed writev: %s", strerror(errno));
#else
if(WSAGetLastError() == WSAEINPROGRESS)
return 0;
@@ -788,9 +847,8 @@ static int dtio_write_with_writev(struct dt_io_thread* dtio)
UB_EV_WRITE);
return 0;
}
- log_err("dnstap io: failed writev: %s",
- wsa_strerror(WSAGetLastError()));
#endif
+ log_err("dnstap io: failed writev: %s", sock_strerror(errno));
/* close the channel */
dtio_del_output_event(dtio);
dtio_close_output(dtio);
@@ -1115,6 +1173,8 @@ static int dtio_read_accept_frame(struct dt_io_thread* dtio)
goto close_connection;
}
dtio->accept_frame_received = 1;
+ if(!dtio_add_output_event_write(dtio))
+ goto close_connection;
return 1;
} else {
/* unknow content type */
@@ -1482,15 +1542,13 @@ void dtio_cmd_cb(int fd, short ATTR_UNUSED(bits), void* arg)
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
return; /* ignore this */
- log_err("dnstap io: failed to read: %s", strerror(errno));
#else
if(WSAGetLastError() == WSAEINPROGRESS)
return;
if(WSAGetLastError() == WSAEWOULDBLOCK)
return;
- log_err("dnstap io: failed to read: %s",
- wsa_strerror(WSAGetLastError()));
#endif
+ log_err("dnstap io: failed to read: %s", sock_strerror(errno));
/* and then fall through to quit the thread */
} else if(r == 0) {
verbose(VERB_ALGO, "dnstap io: cmd channel closed");
@@ -1852,13 +1910,8 @@ static int dtio_open_output_local(struct dt_io_thread* dtio)
struct sockaddr_un s;
dtio->fd = socket(AF_LOCAL, SOCK_STREAM, 0);
if(dtio->fd == -1) {
-#ifndef USE_WINSOCK
- log_err("dnstap io: failed to create socket: %s",
- strerror(errno));
-#else
log_err("dnstap io: failed to create socket: %s",
- wsa_strerror(WSAGetLastError()));
-#endif
+ sock_strerror(errno));
return 0;
}
memset(&s, 0, sizeof(s));
@@ -1873,13 +1926,13 @@ static int dtio_open_output_local(struct dt_io_thread* dtio)
if(connect(dtio->fd, (struct sockaddr*)&s, (socklen_t)sizeof(s))
== -1) {
char* to = dtio->socket_path;
-#ifndef USE_WINSOCK
- log_err("dnstap io: failed to connect to \"%s\": %s",
- to, strerror(errno));
-#else
+ if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MIN &&
+ verbosity < 4) {
+ dtio_close_fd(dtio);
+ return 0; /* no log retries on low verbosity */
+ }
log_err("dnstap io: failed to connect to \"%s\": %s",
- to, wsa_strerror(WSAGetLastError()));
-#endif
+ to, sock_strerror(errno));
dtio_close_fd(dtio);
return 0;
}
@@ -1904,18 +1957,18 @@ static int dtio_open_output_tcp(struct dt_io_thread* dtio)
}
dtio->fd = socket(addr.ss_family, SOCK_STREAM, 0);
if(dtio->fd == -1) {
-#ifndef USE_WINSOCK
- log_err("can't create socket: %s", strerror(errno));
-#else
- log_err("can't create socket: %s",
- wsa_strerror(WSAGetLastError()));
-#endif
+ log_err("can't create socket: %s", sock_strerror(errno));
return 0;
}
fd_set_nonblock(dtio->fd);
if(connect(dtio->fd, (struct sockaddr*)&addr, addrlen) == -1) {
if(errno == EINPROGRESS)
return 1; /* wait until connect done*/
+ if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MIN &&
+ verbosity < 4) {
+ dtio_close_fd(dtio);
+ return 0; /* no log retries on low verbosity */
+ }
#ifndef USE_WINSOCK
if(tcp_connect_errno_needs_log(
(struct sockaddr *)&addr, addrlen)) {
@@ -2097,15 +2150,14 @@ void dt_io_thread_stop(struct dt_io_thread* dtio)
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
continue;
- log_err("dnstap io stop: write: %s", strerror(errno));
#else
if(WSAGetLastError() == WSAEINPROGRESS)
continue;
if(WSAGetLastError() == WSAEWOULDBLOCK)
continue;
- log_err("dnstap io stop: write: %s",
- wsa_strerror(WSAGetLastError()));
#endif
+ log_err("dnstap io stop: write: %s",
+ sock_strerror(errno));
break;
}
break;
diff --git a/contrib/unbound/dnstap/dtstream.h b/contrib/unbound/dnstap/dtstream.h
index ede491f30d3e..f87d6dc8d386 100644
--- a/contrib/unbound/dnstap/dtstream.h
+++ b/contrib/unbound/dnstap/dtstream.h
@@ -49,6 +49,7 @@ struct dt_msg_entry;
struct dt_io_list_item;
struct dt_io_thread;
struct config_file;
+struct comm_base;
/**
* A message buffer with dnstap messages queued up. It is per-worker.
@@ -68,11 +69,15 @@ struct dt_msg_queue {
/** current size of the buffer, in bytes. data bytes of messages.
* If a new message make it more than maxsize, the buffer is full */
size_t cursize;
+ /** number of messages in the queue */
+ int msgcount;
/** list of messages. The messages are added to the back and taken
* out from the front. */
struct dt_msg_entry* first, *last;
/** reference to the io thread to wakeup */
struct dt_io_thread* dtio;
+ /** the wakeup timer for dtio, on worker event base */
+ struct comm_timer* wakeup_timer;
};
/**
@@ -166,6 +171,10 @@ struct dt_io_thread {
* for the current message length that precedes the frame */
size_t cur_msg_len_done;
+ /** lock on wakeup_timer_enabled */
+ lock_basic_type wakeup_timer_lock;
+ /** if wakeup timer is enabled in some thread */
+ int wakeup_timer_enabled;
/** command pipe that stops the pipe if closed. Used to quit
* the program. [0] is read, [1] is written to. */
int commandpipe[2];
@@ -233,9 +242,10 @@ struct dt_io_list_item {
/**
* Create new (empty) worker message queue. Limit set to default on max.
+ * @param base: event base for wakeup timer.
* @return NULL on malloc failure or a new queue (not locked).
*/
-struct dt_msg_queue* dt_msg_queue_create(void);
+struct dt_msg_queue* dt_msg_queue_create(struct comm_base* base);
/**
* Delete a worker message queue. It has to be unlinked from access,
@@ -258,6 +268,9 @@ void dt_msg_queue_delete(struct dt_msg_queue* mq);
*/
void dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len);
+/** timer callback to wakeup dtio thread to process messages */
+void mq_wakeup_cb(void* arg);
+
/**
* Create IO thread.
* @return new io thread object. not yet started. or NULL malloc failure.
diff --git a/contrib/unbound/dnstap/unbound-dnstap-socket.c b/contrib/unbound/dnstap/unbound-dnstap-socket.c
index 44a0eda95994..3ebe2b4e4124 100644
--- a/contrib/unbound/dnstap/unbound-dnstap-socket.c
+++ b/contrib/unbound/dnstap/unbound-dnstap-socket.c
@@ -278,57 +278,31 @@ static int make_tcp_accept(char* ip)
}
if((s = socket(addr.ss_family, SOCK_STREAM, 0)) == -1) {
-#ifndef USE_WINSOCK
- log_err("can't create socket: %s", strerror(errno));
-#else
- log_err("can't create socket: %s",
- wsa_strerror(WSAGetLastError()));
-#endif
+ log_err("can't create socket: %s", sock_strerror(errno));
return -1;
}
#ifdef SO_REUSEADDR
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
-#ifndef USE_WINSOCK
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
- strerror(errno));
- close(s);
-#else
- log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
- wsa_strerror(WSAGetLastError()));
- closesocket(s);
-#endif
+ sock_strerror(errno));
+ sock_close(s);
return -1;
}
#endif /* SO_REUSEADDR */
if(bind(s, (struct sockaddr*)&addr, len) != 0) {
-#ifndef USE_WINSOCK
- log_err_addr("can't bind socket", strerror(errno),
+ log_err_addr("can't bind socket", sock_strerror(errno),
&addr, len);
- close(s);
-#else
- log_err_addr("can't bind socket",
- wsa_strerror(WSAGetLastError()), &addr, len);
- closesocket(s);
-#endif
+ sock_close(s);
return -1;
}
if(!fd_set_nonblock(s)) {
-#ifndef USE_WINSOCK
- close(s);
-#else
- closesocket(s);
-#endif
+ sock_close(s);
return -1;
}
if(listen(s, LISTEN_BACKLOG) == -1) {
-#ifndef USE_WINSOCK
- log_err("can't listen: %s", strerror(errno));
- close(s);
-#else
- log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
- closesocket(s);
-#endif
+ log_err("can't listen: %s", sock_strerror(errno));
+ sock_close(s);
return -1;
}
return s;
@@ -654,7 +628,6 @@ static ssize_t receive_bytes(struct tap_data* data, int fd, void* buf,
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
return -1;
- log_err("could not recv: %s", strerror(errno));
#else /* USE_WINSOCK */
if(WSAGetLastError() == WSAEINPROGRESS)
return -1;
@@ -662,9 +635,8 @@ static ssize_t receive_bytes(struct tap_data* data, int fd, void* buf,
ub_winsock_tcp_wouldblock(data->ev, UB_EV_READ);
return -1;
}
- log_err("could not recv: %s",
- wsa_strerror(WSAGetLastError()));
#endif
+ log_err("could not recv: %s", sock_strerror(errno));
if(verbosity) log_info("dnstap client stream closed from %s",
(data->id?data->id:""));
return 0;
@@ -796,12 +768,7 @@ static int reply_with_accept(struct tap_data* data)
}
} else {
if(send(data->fd, acceptframe, len, 0) == -1) {
-#ifndef USE_WINSOCK
- log_err("send failed: %s", strerror(errno));
-#else
- log_err("send failed: %s",
- wsa_strerror(WSAGetLastError()));
-#endif
+ log_err("send failed: %s", sock_strerror(errno));
fd_set_nonblock(data->fd);
free(acceptframe);
return 0;
@@ -834,11 +801,7 @@ static int reply_with_finish(int fd)
fd_set_block(fd);
if(send(fd, finishframe, len, 0) == -1) {
-#ifndef USE_WINSOCK
- log_err("send failed: %s", strerror(errno));
-#else
- log_err("send failed: %s", wsa_strerror(WSAGetLastError()));
-#endif
+ log_err("send failed: %s", sock_strerror(errno));
fd_set_nonblock(fd);
free(finishframe);
return 0;
@@ -1094,7 +1057,6 @@ void dtio_mainfdcallback(int fd, short ATTR_UNUSED(bits), void* arg)
#endif /* EPROTO */
)
return;
- log_err_addr("accept failed", strerror(errno), &addr, addrlen);
#else /* USE_WINSOCK */
if(WSAGetLastError() == WSAEINPROGRESS ||
WSAGetLastError() == WSAECONNRESET)
@@ -1103,9 +1065,9 @@ void dtio_mainfdcallback(int fd, short ATTR_UNUSED(bits), void* arg)
ub_winsock_tcp_wouldblock(maindata->ev, UB_EV_READ);
return;
}
- log_err_addr("accept failed", wsa_strerror(WSAGetLastError()),
- &addr, addrlen);
#endif
+ log_err_addr("accept failed", sock_strerror(errno), &addr,
+ addrlen);
return;
}
fd_set_nonblock(s);
@@ -1205,8 +1167,10 @@ int sig_quit = 0;
static RETSIGTYPE main_sigh(int sig)
{
verbose(VERB_ALGO, "exit on signal %d\n", sig);
- if(sig_base)
+ if(sig_base) {
ub_event_base_loopexit(sig_base);
+ sig_base = NULL;
+ }
sig_quit = 1;
}
@@ -1247,9 +1211,9 @@ setup_and_run(struct config_strlist_head* local_list,
if(verbosity) log_info("start of service");
ub_event_base_dispatch(base);
+ sig_base = NULL;
if(verbosity) log_info("end of service");
- sig_base = NULL;
tap_socket_list_delete(maindata->acceptlist);
ub_event_base_free(base);
free(maindata);
diff --git a/contrib/unbound/doc/Changelog b/contrib/unbound/doc/Changelog
index 3339e77b30c6..87f796398993 100644
--- a/contrib/unbound/doc/Changelog
+++ b/contrib/unbound/doc/Changelog
@@ -1,3 +1,133 @@
+1 October 2020: Wouter
+ - Current repo is version 1.12.0 for release. Tag for 1.12.0rc1.
+
+30 September 2020: Wouter
+ - Fix doh tests when not compiled in.
+ - Add dohclient test executable to gitignore.
+ - Fix stream_ssl, ssl_req_order and ssl_req_timeout tests for
+ alloc check debug output.
+ - Easier kill of unbound-dnstap-socket tool in test.
+ - Fix memory leak of edns tags at libunbound context delete.
+ - Fix double loopexit for unbound-dnstap-socket after sigterm.
+
+29 September 2020: Ralph
+ - DNS Flag Day 2020: change edns-buffer-size default to 1232.
+
+28 September 2020: Wouter
+ - Fix unit test for dnstap changes, so that it waits for the timer.
+
+23 September 2020: Wouter
+ - Fix #305: dnstap logging significantly affects unbound performance
+ (regression in 1.11).
+ - Fix #305: only wake up thread when threshold reached.
+ - Fix to ifdef fptr wlist item for dnstap.
+
+23 September 2020: Ralph
+ - Fix edns-client-tags get_option typo
+ - Add edns-client-tag-opcode option
+ - Use inclusive language in configuration
+
+21 September 2020: Ralph
+ - Fix #304: dnstap logging not recovering after dnstap process restarts
+
+21 September 2020: Wouter
+ - Merge PR #311 by luismerino: Dynlibmod leak.
+ - Error message is logged for dynlibmod malloc failures.
+ - iana portlist updated.
+
+18 September 2020: Wouter
+ - Fix that prefer-ip4 and prefer-ip6 can be get and set with
+ unbound-control, with libunbound and the unbound-checkconf option
+ output function.
+ - iana portlist updated.
+
+15 September 2020: George
+ - Introduce test for statistics.
+
+15 September 2020: Wouter
+ - Spelling fix.
+
+11 September 2020: Wouter
+ - Remove x file mode on ipset/ipset.c and h files.
+
+9 September 2020: Wouter
+ - Fix num.expired statistics output.
+
+31 August 2020: Wouter
+ - Merge PR #293: Add missing prototype. Also refactor to use the new
+ shorthand function to clean up the code.
+ - Refactor to use sock_strerr shorthand function.
+ - Fix #296: systemd nss-lookup.target is reached before unbound can
+ successfully answer queries. Changed contrib/unbound.service.in.
+
+27 August 2020: Wouter
+ - Similar to NSD PR#113, implement that interface names can be used,
+ eg. something like interface: eth0 is resolved at server start and
+ uses the IP addresses for that named interface.
+ - Review fix, doxygen and assign null in case of error free.
+
+26 August 2020: George
+ - Update documentation in python example code.
+
+24 August 2020: Wouter
+ - Fix that dnstap reconnects do not spam the log with the repeated
+ attempts. Attempts on the timer are only logged on high verbosity,
+ if they produce a connection failure error.
+ - Fix to apply chroot to dnstap-socket-path, if chroot is enabled.
+ - Change configure to use EVP_sha256 instead of HMAC_Update for
+ openssl-3.0.0.
+
+20 August 2020: Ralph
+ - Fix stats double count issue (#289).
+
+13 August 2020: Ralph
+ - Create and init edns tags data for libunbound.
+
+10 August 2020: Ralph
+ - Merge (modified) PR #277, use EVP_MAC_CTX_set_params if available,
+ by Vítězslav Čížek.
+
+10 August 2020: Wouter
+ - Fix #287: doc typo: "Additionaly".
+ - Rerun autoconf
+
+6 August 2020: Wouter
+ - Merge PR #284 and Fix #246: Remove DLV entirely from Unbound.
+ The DLV has been decommisioned and in unbound 1.5.4, in 2015, there
+ was advise to stop using it. The current code base does not contain
+ DLV code any more. The use of dlv options displays a warning.
+
+5 August 2020: Wouter
+ - contrib/aaaa-filter-iterator.patch file renewed diff content to
+ apply cleanly to the current coderepo for the current code version.
+
+5 August 2020: Ralph
+ - Merge PR #272: Add EDNS client tag functionality.
+
+4 August 2020: George
+ - Improve error log message when inserting rpz RR.
+ - Merge PR #280, Make tvOS & watchOS checks verify truthiness as well as
+ definedness, by Felipe Gasper.
+
+4 August 2020: Wouter
+ - Fix mini_event.h on OpenBSD cannot find fd_set.
+
+31 July 2020: Wouter
+ - Fix doxygen comment for no ssl for tls session ticket key callback
+ routine.
+
+27 July 2020: George
+ - Merge PR #268, draft-ietf-dnsop-serve-stale-10 has become RFC 8767 on
+ March 2020, by and0x000.
+
+27 July 2020: Ralph
+ - Merge PR #269, Fix python module len() implementations, by Torbjörn
+ Lönnemark
+
+27 July 2020: Wouter
+ - branch now named 1.11.1. 1.11.0rc1 became the 1.11.0 release.
+ - Merge PR #270 from cgzones: munin plugin: always exit 0 in autoconf
+
20 July 2020: Wouter
- Fix streamtcp to print packet data to stdout. This makes the
stdout and stderr not mix together lines, when parsing its output.
diff --git a/contrib/unbound/doc/README b/contrib/unbound/doc/README
index 6bd9a4c5fdae..c6ff31a6fac3 100644
--- a/contrib/unbound/doc/README
+++ b/contrib/unbound/doc/README
@@ -1,4 +1,4 @@
-README for Unbound 1.11.0
+README for Unbound 1.12.0
Copyright 2007 NLnet Labs
http://unbound.net
diff --git a/contrib/unbound/doc/example.conf.in b/contrib/unbound/doc/example.conf.in
index 4f6411033e69..2fe9a2c7e7a7 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.11.0.
+# See unbound.conf(5) man page, version 1.12.0.
#
# this is a comment.
@@ -129,8 +129,8 @@ server:
# ip-dscp: 0
# EDNS reassembly buffer to advertise to UDP peers (the actual buffer
- # is set with msg-buffer-size). 1472 can solve fragmentation (timeouts)
- # edns-buffer-size: 4096
+ # is set with msg-buffer-size).
+ # edns-buffer-size: 1232
# Maximum UDP response size (not applied to TCP response).
# Suggested values are 512 to 4096. Default is 4096. 65536 disables it.
@@ -431,8 +431,8 @@ 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"
+ # caps-exempt: "licdn.com"
+ # caps-exempt: "senderbase.org"
# Enforce privacy of these addresses. Strips them away from answers.
# It may cause DNSSEC validation to additionally mark it as bogus.
@@ -509,11 +509,6 @@ server:
# Root key trust anchor sentinel (draft-ietf-dnsop-kskroll-sentinel)
# root-key-sentinel: yes
- # File with DLV trusted keys. Same format as trust-anchor-file.
- # There can be only one DLV configured, it is trusted from root down.
- # DLV is going to be decommissioned. Please do not use it any more.
- # dlv-anchor-file: "dlv.isc.org.key"
-
# File with trusted keys for validation. Specify more than one file
# with several entries, one file per entry.
# Zone file format, with DS and DNSKEY entries.
@@ -589,7 +584,7 @@ server:
#
# Time in milliseconds before replying to the client with expired data.
# This essentially enables the serve-stale behavior as specified in
- # draft-ietf-dnsop-serve-stale-10 that first tries to resolve before
+ # RFC 8767 that first tries to resolve before
# immediately responding with expired data. 0 disables this behavior.
# A recommended value is 1800.
# serve-expired-client-timeout: 0
@@ -627,7 +622,7 @@ server:
# more slabs reduce lock contention, but fragment memory usage.
# key-cache-slabs: 4
- # the amount of memory to use for the negative cache (used for DLV).
+ # the amount of memory to use for the negative cache.
# plain value in bytes or you can append k, m or G. default is "1Mb".
# neg-cache-size: 1m
@@ -738,12 +733,14 @@ server:
# 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 TLS (on the TCP sockets), with plain DNS inside
- # the TLS stream. Give the certificate to use and private key.
+ # service clients over TLS (on the TCP sockets) with plain DNS inside
+ # the TLS stream, and over HTTPS using HTTP/2 as specified in RFC8484.
+ # Give the certificate to use and private key.
# default is "" (disabled). requires restart to take effect.
# tls-service-key: "path/to/privatekeyfile.key"
# tls-service-pem: "path/to/publiccertfile.pem"
# tls-port: 853
+ # https-port: 443
# cipher setting for TLSv1.2
# tls-ciphers: "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256"
@@ -775,6 +772,22 @@ server:
# Also serve tls on these port numbers (eg. 443, ...), by listing
# tls-additional-port: portno for each of the port numbers.
+ # HTTP endpoint to provide DNS-over-HTTPS service on.
+ # http-endpoint: "/dns-query"
+
+ # HTTP/2 SETTINGS_MAX_CONCURRENT_STREAMS value to use.
+ # http-max-streams: 100
+
+ # Maximum number of bytes used for all HTTP/2 query buffers.
+ # http-query-buffer-size: 4m
+
+ # Maximum number of bytes used for all HTTP/2 response buffers.
+ # http-response-buffer-size: 4m
+
+ # Set TCP_NODELAY socket option on sockets used for DNS-over-HTTPS
+ # service.
+ # http-nodelay: yes
+
# DNS64 prefix. Must be specified when DNS64 is use.
# Enable dns64 in module-config. Used to synthesize IPv6 from IPv4.
# dns64-prefix: 64:ff9b::0/96
@@ -848,9 +861,9 @@ server:
# ipsecmod-ignore-bogus: no
#
# Domains for which ipsecmod will be triggered. If not defined (default)
- # all domains are treated as being whitelisted.
- # ipsecmod-whitelist: "example.com"
- # ipsecmod-whitelist: "nlnetlabs.nl"
+ # all domains are treated as being allowed.
+ # ipsecmod-allow: "example.com"
+ # ipsecmod-allow: "nlnetlabs.nl"
# Python config section. To enable:
@@ -948,27 +961,27 @@ remote-control:
# upstream (which saves a lookup to the upstream). The first example
# has a copy of the root for local usage. The second serves example.org
# authoritatively. zonefile: reads from file (and writes to it if you also
-# download it), master: fetches with AXFR and IXFR, or url to zonefile.
-# With allow-notify: you can give additional (apart from masters) sources of
+# download it), primary: fetches with AXFR and IXFR, or url to zonefile.
+# With allow-notify: you can give additional (apart from primaries) sources of
# notifies.
# auth-zone:
# name: "."
-# master: 199.9.14.201 # b.root-servers.net
-# master: 192.33.4.12 # c.root-servers.net
-# master: 199.7.91.13 # d.root-servers.net
-# master: 192.5.5.241 # f.root-servers.net
-# master: 192.112.36.4 # g.root-servers.net
-# master: 193.0.14.129 # k.root-servers.net
-# master: 192.0.47.132 # xfr.cjr.dns.icann.org
-# master: 192.0.32.132 # xfr.lax.dns.icann.org
-# master: 2001:500:200::b # b.root-servers.net
-# master: 2001:500:2::c # c.root-servers.net
-# master: 2001:500:2d::d # d.root-servers.net
-# master: 2001:500:2f::f # f.root-servers.net
-# master: 2001:500:12::d0d # g.root-servers.net
-# master: 2001:7fd::1 # k.root-servers.net
-# master: 2620:0:2830:202::132 # xfr.cjr.dns.icann.org
-# master: 2620:0:2d0:202::132 # xfr.lax.dns.icann.org
+# primary: 199.9.14.201 # b.root-servers.net
+# primary: 192.33.4.12 # c.root-servers.net
+# primary: 199.7.91.13 # d.root-servers.net
+# primary: 192.5.5.241 # f.root-servers.net
+# primary: 192.112.36.4 # g.root-servers.net
+# primary: 193.0.14.129 # k.root-servers.net
+# primary: 192.0.47.132 # xfr.cjr.dns.icann.org
+# primary: 192.0.32.132 # xfr.lax.dns.icann.org
+# primary: 2001:500:200::b # b.root-servers.net
+# primary: 2001:500:2::c # c.root-servers.net
+# primary: 2001:500:2d::d # d.root-servers.net
+# primary: 2001:500:2f::f # f.root-servers.net
+# primary: 2001:500:12::d0d # g.root-servers.net
+# primary: 2001:7fd::1 # k.root-servers.net
+# primary: 2620:0:2830:202::132 # xfr.cjr.dns.icann.org
+# primary: 2620:0:2d0:202::132 # xfr.lax.dns.icann.org
# fallback-enabled: yes
# for-downstream: no
# for-upstream: yes
@@ -1088,7 +1101,7 @@ remote-control:
# rpz:
# name: "rpz.example.com"
# zonefile: "rpz.example.com"
-# master: 192.0.2.0
+# primary: 192.0.2.0
# allow-notify: 192.0.2.0/32
# url: http://www.example.com/rpz.example.org.zone
# rpz-action-override: cname
diff --git a/contrib/unbound/doc/libunbound.3.in b/contrib/unbound/doc/libunbound.3.in
index 10bda1614b26..34778ee5c09e 100644
--- a/contrib/unbound/doc/libunbound.3.in
+++ b/contrib/unbound/doc/libunbound.3.in
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
+.TH "libunbound" "3" "Oct 8, 2020" "NLnet Labs" "unbound 1.12.0"
.\"
.\" libunbound.3 -- unbound library functions manual
.\"
@@ -44,7 +44,7 @@
.B ub_ctx_zone_remove,
.B ub_ctx_data_add,
.B ub_ctx_data_remove
-\- Unbound DNS validating resolver 1.11.0 functions.
+\- Unbound DNS validating resolver 1.12.0 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
diff --git a/contrib/unbound/doc/unbound-anchor.8.in b/contrib/unbound/doc/unbound-anchor.8.in
index 1c7799ca11d8..21f12ebeff1c 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" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
+.TH "unbound-anchor" "8" "Oct 8, 2020" "NLnet Labs" "unbound 1.12.0"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
diff --git a/contrib/unbound/doc/unbound-checkconf.8.in b/contrib/unbound/doc/unbound-checkconf.8.in
index 025795462bb6..55abe6004027 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" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
+.TH "unbound-checkconf" "8" "Oct 8, 2020" "NLnet Labs" "unbound 1.12.0"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
diff --git a/contrib/unbound/doc/unbound-control.8.in b/contrib/unbound/doc/unbound-control.8.in
index 154450303366..f82b62d3d9b6 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" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
+.TH "unbound-control" "8" "Oct 8, 2020" "NLnet Labs" "unbound 1.12.0"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
@@ -506,6 +506,14 @@ negative cache.
Memory in bytes in used by the TCP and TLS stream wait buffers. These are
answers waiting to be written back to the clients.
.TP
+.I mem.http.query_buffer
+Memory in bytes used by the HTTP/2 query buffers. Containing (partial) DNS
+queries waiting for request stream completion.
+.TP
+.I mem.http.response_buffer
+Memory in bytes used by the HTTP/2 response buffers. Containing DNS responses
+waiting to be written back to the clients.
+.TP
.I histogram.<sec>.<usec>.to.<sec>.<usec>
Shows a histogram, summed over all threads. Every element counts the
recursive queries whose reply time fit between the lower and upper bound.
@@ -545,6 +553,11 @@ These are also counted in num.query.tcp, because TLS uses TCP.
Number of TLS session resumptions, these are queries over TLS towards
the unbound server where the client negotiated a TLS session resumption key.
.TP
+.I num.query.https
+Number of queries that were made using HTTPS towards the unbound server.
+These are also counted in num.query.tcp and num.query.tls, because HTTPS
+uses TLS and TCP.
+.TP
.I num.query.ipv6
Number of queries that were made using IPv6 towards the unbound server.
.TP
diff --git a/contrib/unbound/doc/unbound-host.1.in b/contrib/unbound/doc/unbound-host.1.in
index cae708d66b12..d3b502d92657 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" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
+.TH "unbound\-host" "1" "Oct 8, 2020" "NLnet Labs" "unbound 1.12.0"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
diff --git a/contrib/unbound/doc/unbound.8.in b/contrib/unbound/doc/unbound.8.in
index fcdb3d833406..44a9879e5872 100644
--- a/contrib/unbound/doc/unbound.8.in
+++ b/contrib/unbound/doc/unbound.8.in
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
+.TH "unbound" "8" "Oct 8, 2020" "NLnet Labs" "unbound 1.12.0"
.\"
.\" unbound.8 -- unbound manual
.\"
@@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
-\- Unbound DNS validating resolver 1.11.0.
+\- Unbound DNS validating resolver 1.12.0.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
diff --git a/contrib/unbound/doc/unbound.conf.5.in b/contrib/unbound/doc/unbound.conf.5.in
index 04dca3561ea2..bcbc9f205333 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" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
+.TH "unbound.conf" "5" "Oct 8, 2020" "NLnet Labs" "unbound 1.12.0"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@@ -122,7 +122,8 @@ The port number, default 53, on which the server responds to queries.
Interface to use to connect to the network. This interface is listened to
for queries from clients, and answers to clients are given from it.
Can be given multiple times to work on several interfaces. If none are
-given the default is to listen to localhost.
+given the default is to listen to localhost. If an interface name is used
+instead of an ip address, the list of ip addresses on that interface are used.
The interfaces are not changed on a reload (kill \-HUP) but only on restart.
A port number can be specified with @port (without spaces between
interface and port number), if not specified the default port (from
@@ -206,12 +207,11 @@ accepted. For larger installations increasing this value is a good idea.
Number of bytes size to advertise as the EDNS reassembly buffer size.
This is the value put into datagrams over UDP towards peers. The actual
buffer size is determined by msg\-buffer\-size (both for TCP and UDP). Do
-not set higher than that value. Default is 4096 which is RFC recommended.
-If you have fragmentation reassembly problems, usually seen as timeouts,
-then a value of 1472 can fix it. Setting to 512 bypasses even the most
-stringent path MTU problems, but is seen as extreme, since the amount
-of TCP fallback generated is excessive (probably also for this resolver,
-consider tuning the outgoing tcp number).
+not set higher than that value. Default is 1232 which is the DNS Flag Day 2020
+recommendation. Setting to 512 bypasses even the most stringent path MTU
+problems, but is seen as extreme, since the amount of TCP fallback generated is
+excessive (probably also for this resolver, consider tuning the outgoing tcp
+number).
.TP
.B max\-udp\-size: \fI<number>
Maximum UDP response size (not applied to TCP response). 65536 disables the
@@ -484,15 +484,16 @@ Alternate syntax for \fBtls\-upstream\fR. If both are present in the config
file the last is used.
.TP
.B tls\-service\-key: \fI<file>
-If enabled, the server provides TLS service on the TCP ports marked
-implicitly or explicitly for TLS service with tls\-port. The file must
-contain the private key for the TLS session, the public certificate is in
-the tls\-service\-pem file and it must also be specified if tls\-service\-key
-is specified. The default is "", turned off. Enabling or disabling
-this service requires a restart (a reload is not enough), because the
-key is read while root permissions are held and before chroot (if any).
-The ports enabled implicitly or explicitly via \fBtls\-port:\fR do not provide
-normal DNS TCP service.
+If enabled, the server provides DNS-over-TLS or DNS-over-HTTPS service on the
+TCP ports marked implicitly or explicitly for these services with tls\-port or
+https\-port. The file must contain the private key for the TLS session, the
+public certificate is in the tls\-service\-pem file and it must also be
+specified if tls\-service\-key is specified. The default is "", turned off.
+Enabling or disabling this service requires a restart (a reload is not enough),
+because the key is read while root permissions are held and before chroot (if any).
+The ports enabled implicitly or explicitly via \fBtls\-port:\fR and
+\fBhttps\-port:\fR do not provide normal DNS TCP service. Unbound needs to be
+compiled with libnghttp2 in order to provide DNS-over-HTTPS.
.TP
.B ssl\-service\-key: \fI<file>
Alternate syntax for \fBtls\-service\-key\fR.
@@ -557,6 +558,35 @@ Enable or disable sending the SNI extension on TLS connections.
Default is yes.
Changing the value requires a reload.
.TP
+.B https\-port: \fI<number>
+The port number on which to provide DNS-over-HTTPS service, default 443, only
+interfaces configured with that port number as @number get the HTTPS service.
+.TP
+.B http\-endpoint: \fI<endpoint string>
+The HTTP endpoint to provide DNS-over-HTTPS service on. Default "/dns-query".
+.TP
+.B http\-max\-streams: \fI<number of streams>
+Number used in the SETTINGS_MAX_CONCURRENT_STREAMS parameter in the HTTP/2
+SETTINGS frame for DNS-over-HTTPS connections. Default 100.
+.TP
+.B http\-query\-buffer\-size: \fI<size in bytes>
+Maximum number of bytes used for all HTTP/2 query buffers combined. These
+buffers contain (partial) DNS queries waiting for request stream completion.
+An RST_STREAM frame will be send to streams exceeding this limit. Default is 4
+megabytes. A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes,
+megabytes or gigabytes (1024*1024 bytes in a megabyte).
+.TP
+.B http\-response\-buffer\-size: \fI<size in bytes>
+Maximum number of bytes used for all HTTP/2 response buffers combined. These
+buffers contain DNS responses waiting to be written back to the clients.
+An RST_STREAM frame will be send to streams exceeding this limit. Default is 4
+megabytes. A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes,
+megabytes or gigabytes (1024*1024 bytes in a megabyte).
+.TP
+.B http\-nodelay: \fI<yes or no>
+Set TCP_NODELAY socket option on sockets used to provide DNS-over-HTTPS service.
+Ignored if the option is not available. Default is yes.
+.TP
.B use\-systemd: \fI<yes or no>
Enable or disable systemd socket activation.
Default is no.
@@ -853,12 +883,15 @@ authority servers and checks if the reply still has the correct casing.
Disabled by default.
This feature is an experimental implementation of draft dns\-0x20.
.TP
-.B caps\-whitelist: \fI<domain>
-Whitelist the domain so that it does not receive caps\-for\-id perturbed
+.B caps\-exempt: \fI<domain>
+Exempt the domain so that it does not receive caps\-for\-id perturbed
queries. For domains that do not support 0x20 and also fail with fallback
because they keep sending different answers, like some load balancers.
Can be given multiple times, for different domains.
.TP
+.B caps\-whitelist: \fI<yes or no>
+Alternate syntax for \fBcaps\-exempt\fR.
+.TP
.B qname\-minimisation: \fI<yes or no>
Send minimum amount of information to upstream servers to enhance privacy.
Only send minimum required labels of the QNAME and set QTYPE to A when
@@ -1010,26 +1043,11 @@ Send RFC8145 key tag query after trust anchor priming. Default is yes.
.B root\-key\-sentinel: \fI<yes or no>
Root key trust anchor sentinel. Default is yes.
.TP
-.B dlv\-anchor\-file: \fI<filename>
-This option was used during early days DNSSEC deployment when no parent-side
-DS record registrations were easily available. Nowadays, it is best to have
-DS records registered with the parent zone (many top level zones are signed).
-File with trusted keys for DLV (DNSSEC Lookaside Validation). Both DS and
-DNSKEY entries can be used in the file, in the same format as for
-\fItrust\-anchor\-file:\fR statements. Only one DLV can be configured, more
-would be slow. The DLV configured is used as a root trusted DLV, this
-means that it is a lookaside for the root. Default is "", or no dlv anchor
-file. DLV is going to be decommissioned. Please do not use it any more.
-.TP
-.B dlv\-anchor: \fI<"Resource Record">
-Much like trust\-anchor, this is a DLV anchor with the DS or DNSKEY inline.
-DLV is going to be decommissioned. Please do not use it any more.
-.TP
.B domain\-insecure: \fI<domain name>
Sets domain name to be insecure, DNSSEC chain of trust is ignored towards
the domain name. So a trust anchor above the domain name can not make the
domain secure with a DS record, such a DS record is then ignored.
-Also keys from DLV are ignored for the domain. Can be given multiple times
+Can be given multiple times
to specify multiple domains that are treated as if unsigned. If you set
trust anchors for the domain they override this setting (and the domain
is secured).
@@ -1108,7 +1126,7 @@ later on. Default is "no".
.B serve\-expired\-ttl: \fI<seconds>
Limit serving of expired responses to configured seconds after expiration. 0
disables the limit. This option only applies when \fBserve\-expired\fR is
-enabled. A suggested value per draft-ietf-dnsop-serve-stale-10 is between
+enabled. A suggested value per RFC 8767 is between
86400 (1 day) and 259200 (3 days). The default is 0.
.TP
.B serve\-expired\-ttl\-reset: \fI<yes or no>
@@ -1120,14 +1138,14 @@ expired records will be served as long as there are queries for it. Default is
.B serve\-expired\-reply\-ttl: \fI<seconds>
TTL value to use when replying with expired data. If
\fBserve\-expired\-client\-timeout\fR is also used then it is RECOMMENDED to
-use 30 as the value (draft-ietf-dnsop-serve-stale-10). The default is 30.
+use 30 as the value (RFC 8767). The default is 30.
.TP
.B serve\-expired\-client\-timeout: \fI<msec>
Time in milliseconds before replying to the client with expired data. This
essentially enables the serve-stale behavior as specified in
-draft-ietf-dnsop-serve-stale-10 that first tries to resolve before immediately
+RFC 8767 that first tries to resolve before immediately
responding with expired data. A recommended value per
-draft-ietf-dnsop-serve-stale-10 is 1800. Setting this to 0 will disable this
+RFC 8767 is 1800. Setting this to 0 will disable this
behavior. Default is 0.
.TP
.B val\-nsec3\-keysize\-iterations: \fI<"list of values">
@@ -1516,6 +1534,16 @@ servers set. The default for fast\-server\-permil is 0.
Set the number of servers that should be used for fast server selection. Only
use the fastest specified number of servers with the fast\-server\-permil
option, that turns this on or off. The default is to use the fastest 3 servers.
+.TP 5
+.B edns\-client\-tag: \fI<IP netblock> <tag data>
+Include an edns-client-tag option in queries with destination address matching
+the configured IP netblock. This configuration option can be used multiple
+times. The most specific match will be used. The tag data is configured in
+decimal format, from 0 to 65535.
+.TP 5
+.B edns\-client\-tag\-opcode: \fI<opcode>
+EDNS0 option code for the edns-client-tag option, from 0 to 65535. Default is
+16, as assigned by IANA.
.SS "Remote Control Options"
In the
.B remote\-control:
@@ -1718,16 +1746,16 @@ uses the SOA timer values and performs SOA UDP queries to detect zone changes.
If the update fetch fails, the timers in the SOA record are used to time
another fetch attempt. Until the SOA expiry timer is reached. Then the
zone is expired. When a zone is expired, queries are SERVFAIL, and
-any new serial number is accepted from the master (even if older), and if
+any new serial number is accepted from the primary (even if older), and if
fallback is enabled, the fallback activates to fetch from the upstream instead
of the SERVFAIL.
.TP
.B name: \fI<zone name>
Name of the authority zone.
.TP
-.B master: \fI<IP address or host name>
+.B primary: \fI<IP address or host name>
Where to download a copy of the zone from, with AXFR and IXFR. Multiple
-masters can be specified. They are all tried if one fails.
+primaries can be specified. They are all tried if one fails.
With the "ip#name" notation a AXFR over TLS can be used.
If you point it at another Unbound instance, it would not work because
that does not support AXFR/IXFR for the zone, but if you used \fBurl:\fR to download
@@ -1736,27 +1764,31 @@ If you specify the hostname, you cannot use the domain from the zonefile,
because it may not have that when retrieving that data, instead use a plain
IP address to avoid a circular dependency on retrieving that IP address.
.TP
+.B master: \fI<IP address or host name>
+Alternate syntax for \fBprimary\fR.
+.TP
.B url: \fI<url to zonefile>
Where to download a zonefile for the zone. With http or https. An example
for the url is "http://www.example.com/example.org.zone". Multiple url
statements can be given, they are tried in turn. If only urls are given
the SOA refresh timer is used to wait for making new downloads. If also
-masters are listed, the masters are first probed with UDP SOA queries to
+primaries are listed, the primaries are first probed with UDP SOA queries to
see if the SOA serial number has changed, reducing the number of downloads.
-If none of the urls work, the masters are tried with IXFR and AXFR.
+If none of the urls work, the primaries are tried with IXFR and AXFR.
For https, the \fBtls\-cert\-bundle\fR and the hostname from the url are used
to authenticate the connection.
If you specify a hostname in the URL, you cannot use the domain from the
zonefile, because it may not have that when retrieving that data, instead
use a plain IP address to avoid a circular dependency on retrieving that IP
-address. Avoid dependencies on name lookups by using a notation like "http://192.0.2.1/unbound-master/example.com.zone", with an explicit IP address.
+address. Avoid dependencies on name lookups by using a notation like
+"http://192.0.2.1/unbound-primaries/example.com.zone", with an explicit IP address.
.TP
.B allow\-notify: \fI<IP address or host name or netblockIP/prefix>
With allow\-notify you can specify additional sources of notifies.
When notified, the server attempts to first probe and then zone transfer.
-If the notify is from a master, it first attempts that master. Otherwise
-other masters are attempted. If there are no masters, but only urls, the
-file is downloaded when notified. The masters from master: statements are
+If the notify is from a primary, it first attempts that primary. Otherwise
+other primaries are attempted. If there are no primaries, but only urls, the
+file is downloaded when notified. The primaries from primary: statements are
allowed notify by default.
.TP
.B fallback\-enabled: \fI<yes or no>
@@ -1784,7 +1816,7 @@ downstream clients, and use the zone data as a local copy to speed up lookups.
.B zonefile: \fI<filename>
The filename where the zone is stored. If not given then no zonefile is used.
If the file does not exist or is empty, unbound will attempt to fetch zone
-data (eg. from the master servers).
+data (eg. from the primary servers).
.SS "View Options"
.LP
There may be multiple
@@ -1951,14 +1983,16 @@ The ECS module must be configured in the \fBmodule\-config:\fR "subnetcache
validator iterator" directive and be compiled into the daemon to be
enabled. These settings go in the \fBserver:\fR section.
.LP
-If the destination address is whitelisted with Unbound will add the EDNS0
-option to the query containing the relevant part of the client's address. When
-an answer contains the ECS option the response and the option are placed in a
-specialized cache. If the authority indicated no support, the response is
+If the destination address is allowed in the configuration Unbound will add the
+EDNS0 option to the query containing the relevant part of the client's address.
+When an answer contains the ECS option the response and the option are placed in
+a specialized cache. If the authority indicated no support, the response is
stored in the regular cache.
.LP
Additionally, when a client includes the option in its queries, Unbound will
-forward the option to the authority if present in the whitelist, or
+forward the option when sending the query to addresses that are explicitly
+allowed in the configuration using \fBsend\-client\-subnet\fR. The option will
+always be forwarded, regardless the allowed addresses, if
\fBclient\-subnet\-always\-forward\fR is set to yes. In this case the lookup in
the regular cache is skipped.
.LP
@@ -1979,11 +2013,11 @@ given multiple times. Zones not listed will not receive edns-subnet information,
unless hosted by authority specified in \fBsend\-client\-subnet\fR.
.TP
.B client\-subnet\-always\-forward: \fI<yes or no>\fR
-Specify whether the ECS whitelist check (configured using
+Specify whether the ECS address check (configured using
\fBsend\-client\-subnet\fR) is applied for all queries, even if the triggering
query contains an ECS record, or only for queries for which the ECS record is
generated using the querier address (and therefore did not contain ECS data in
-the client query). If enabled, the whitelist check is skipped when the client
+the client query). If enabled, the address check is skipped when the client
query contains an ECS record. Default is no.
.TP
.B max\-client\-subnet\-ipv6: \fI<number>\fR
@@ -2073,10 +2107,13 @@ to yes, the hook will be called and the A/AAAA answer will be returned to the
client. If set to no, the hook will not be called and the answer to the
A/AAAA query will be SERVFAIL. Mainly used for testing. Defaults to no.
.TP
-.B ipsecmod\-whitelist: \fI<domain>\fR
-Whitelist the domain so that the module logic will be executed. Can
-be given multiple times, for different domains. If the option is not
-specified, all domains are treated as being whitelisted (default).
+.B ipsecmod\-allow: \fI<domain>\fR
+Allow the ipsecmod functionality for the domain so that the module logic will be
+executed. Can be given multiple times, for different domains. If the option is
+not specified, all domains are treated as being allowed (default).
+.TP
+.B ipsecmod\-whitelist: \fI<yes or no>
+Alternate syntax for \fBipsecmod\-allow\fR.
.SS "Cache DB Module Options"
.LP
The Cache DB module must be configured in the \fBmodule\-config:\fR
@@ -2110,7 +2147,7 @@ even if some data have expired in terms of DNS TTL or the Redis server has
cached too much data;
if necessary the Redis server must be configured to limit the cache size,
preferably with some kind of least-recently-used eviction policy.
-Additionaly, the \fBredis\-expire\-records\fR option can be used in order to
+Additionally, the \fBredis\-expire\-records\fR option can be used in order to
set the relative DNS TTL of the message as timeout to the Redis records; keep
in mind that some additional memory is used per key and that the expire
information is stored as absolute Unix timestamps in Redis (computer time must
@@ -2273,33 +2310,36 @@ are applied after
.B name: \fI<zone name>
Name of the authority zone.
.TP
-.B master: \fI<IP address or host name>
+.B primary: \fI<IP address or host name>
Where to download a copy of the zone from, with AXFR and IXFR. Multiple
-masters can be specified. They are all tried if one fails.
+primaries can be specified. They are all tried if one fails.
+.TP
+.B master: \fI<IP address or host name>
+Alternate syntax for \fBprimary\fR.
.TP
.B url: \fI<url to zonefile>
Where to download a zonefile for the zone. With http or https. An example
for the url is "http://www.example.com/example.org.zone". Multiple url
statements can be given, they are tried in turn. If only urls are given
the SOA refresh timer is used to wait for making new downloads. If also
-masters are listed, the masters are first probed with UDP SOA queries to
+primaries are listed, the primaries are first probed with UDP SOA queries to
see if the SOA serial number has changed, reducing the number of downloads.
-If none of the urls work, the masters are tried with IXFR and AXFR.
+If none of the urls work, the primaries are tried with IXFR and AXFR.
For https, the \fBtls\-cert\-bundle\fR and the hostname from the url are used
to authenticate the connection.
.TP
.B allow\-notify: \fI<IP address or host name or netblockIP/prefix>
With allow\-notify you can specify additional sources of notifies.
When notified, the server attempts to first probe and then zone transfer.
-If the notify is from a master, it first attempts that master. Otherwise
-other masters are attempted. If there are no masters, but only urls, the
-file is downloaded when notified. The masters from master: statements are
+If the notify is from a primary, it first attempts that primary. Otherwise
+other primaries are attempted. If there are no primaries, but only urls, the
+file is downloaded when notified. The primaries from primary: statements are
allowed notify by default.
.TP
.B zonefile: \fI<filename>
The filename where the zone is stored. If not given then no zonefile is used.
If the file does not exist or is empty, unbound will attempt to fetch zone
-data (eg. from the master servers).
+data (eg. from the primary servers).
.TP
.B rpz\-action\-override: \fI<action>
Always use this RPZ action for matching triggers from this zone. Possible action
diff --git a/contrib/unbound/dynlibmod/dynlibmod.c b/contrib/unbound/dynlibmod/dynlibmod.c
index f9751d8c6f73..3bf9d1acb0b8 100644
--- a/contrib/unbound/dynlibmod/dynlibmod.c
+++ b/contrib/unbound/dynlibmod/dynlibmod.c
@@ -242,6 +242,10 @@ int
inplace_cb_register_wrapped(void* cb, enum inplace_cb_list_type type, void* cbarg,
struct module_env* env, int id) {
struct cb_pair* cb_pair = malloc(sizeof(struct cb_pair));
+ if(cb_pair == NULL) {
+ log_err("dynlibmod[%d]: malloc failure", id);
+ return 0;
+ }
cb_pair->cb = cb;
cb_pair->cb_arg = cbarg;
if(type >= inplace_cb_reply && type <= inplace_cb_reply_servfail) {
@@ -253,6 +257,7 @@ inplace_cb_register_wrapped(void* cb, enum inplace_cb_list_type type, void* cbar
} else if(type == inplace_cb_edns_back_parsed) {
return inplace_cb_register(&dynlib_inplace_cb_edns_back_parsed, type, (void*) cb_pair, env, id);
} else {
+ free(cb_pair);
return 0;
}
}
diff --git a/contrib/unbound/iterator/iterator.c b/contrib/unbound/iterator/iterator.c
index 23b07ea9095b..99d020117842 100644
--- a/contrib/unbound/iterator/iterator.c
+++ b/contrib/unbound/iterator/iterator.c
@@ -3191,7 +3191,7 @@ processPrimeResponse(struct module_qstate* qstate, int id)
/* validate the root or stub after priming (if enabled).
* This is the same query as the prime query, but with validation.
* Now that we are primed, the additional queries that validation
- * may need can be resolved, such as DLV. */
+ * may need can be resolved. */
if(qstate->env->cfg->harden_referral_path) {
struct module_qstate* subq = NULL;
log_nametypeclass(VERB_ALGO, "schedule prime validation",
diff --git a/contrib/unbound/libunbound/context.c b/contrib/unbound/libunbound/context.c
index 6d62e32b50fd..713259c718ce 100644
--- a/contrib/unbound/libunbound/context.c
+++ b/contrib/unbound/libunbound/context.c
@@ -50,6 +50,7 @@
#include "services/authzone.h"
#include "util/data/msgreply.h"
#include "util/storage/slabhash.h"
+#include "util/edns.h"
#include "sldns/sbuffer.h"
int
@@ -79,6 +80,8 @@ context_finalize(struct ub_ctx* ctx)
return UB_INITFAIL;
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz))
return UB_INITFAIL;
+ if(!edns_tags_apply_cfg(ctx->env->edns_tags, cfg))
+ return UB_INITFAIL;
if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
cfg->msg_cache_slabs)) {
slabhash_delete(ctx->env->msg_cache);
diff --git a/contrib/unbound/libunbound/libunbound.c b/contrib/unbound/libunbound/libunbound.c
index 3b30419b315e..3922eb0417f8 100644
--- a/contrib/unbound/libunbound/libunbound.c
+++ b/contrib/unbound/libunbound/libunbound.c
@@ -58,6 +58,7 @@
#include "util/net_help.h"
#include "util/tube.h"
#include "util/ub_event.h"
+#include "util/edns.h"
#include "services/modstack.h"
#include "services/localzone.h"
#include "services/cache/infra.h"
@@ -153,6 +154,18 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
errno = ENOMEM;
return NULL;
}
+ ctx->env->edns_tags = edns_tags_create();
+ if(!ctx->env->edns_tags) {
+ auth_zones_delete(ctx->env->auth_zones);
+ edns_known_options_delete(ctx->env);
+ config_delete(ctx->env->cfg);
+ free(ctx->env);
+ ub_randfree(ctx->seed_rnd);
+ free(ctx);
+ errno = ENOMEM;
+ return NULL;
+ }
+
ctx->env->alloc = &ctx->superalloc;
ctx->env->worker = NULL;
ctx->env->need_to_validate = 0;
@@ -173,6 +186,7 @@ ub_ctx_create(void)
config_delete(ctx->env->cfg);
modstack_desetup(&ctx->mods, ctx->env);
edns_known_options_delete(ctx->env);
+ edns_tags_delete(ctx->env->edns_tags);
free(ctx->env);
free(ctx);
errno = e;
@@ -185,6 +199,7 @@ ub_ctx_create(void)
config_delete(ctx->env->cfg);
modstack_desetup(&ctx->mods, ctx->env);
edns_known_options_delete(ctx->env);
+ edns_tags_delete(ctx->env->edns_tags);
free(ctx->env);
free(ctx);
errno = e;
@@ -323,6 +338,7 @@ ub_ctx_delete(struct ub_ctx* ctx)
infra_delete(ctx->env->infra_cache);
config_delete(ctx->env->cfg);
edns_known_options_delete(ctx->env);
+ edns_tags_delete(ctx->env->edns_tags);
auth_zones_delete(ctx->env->auth_zones);
free(ctx->env);
}
diff --git a/contrib/unbound/libunbound/libworker.c b/contrib/unbound/libunbound/libworker.c
index 44b8d790561f..bd42462e1be6 100644
--- a/contrib/unbound/libunbound/libworker.c
+++ b/contrib/unbound/libunbound/libworker.c
@@ -78,7 +78,7 @@
#include <TargetConditionals.h>
#endif
-#if defined(TARGET_OS_TV) || defined(TARGET_OS_WATCH)
+#if (defined(TARGET_OS_TV) && TARGET_OS_TV) || (defined(TARGET_OS_WATCH) && TARGET_OS_WATCH)
#undef HAVE_FORK
#endif
diff --git a/contrib/unbound/libunbound/unbound.h b/contrib/unbound/libunbound/unbound.h
index b53426c76d54..945c17a8fb5b 100644
--- a/contrib/unbound/libunbound/unbound.h
+++ b/contrib/unbound/libunbound/unbound.h
@@ -697,6 +697,8 @@ struct ub_server_stats {
long long qtcp_outgoing;
/** number of queries over (DNS over) TLS */
long long qtls;
+ /** number of queries over (DNS over) HTTPS */
+ long long qhttps;
/** number of queries over IPv6 */
long long qipv6;
/** number of queries with QR bit */
@@ -787,6 +789,10 @@ struct ub_server_stats {
long long num_query_subnet_cache;
/** number of bytes in the stream wait buffers */
long long mem_stream_wait;
+ /** number of bytes in the HTTP2 query buffers */
+ long long mem_http2_query_buffer;
+ /** number of bytes in the HTTP2 response buffers */
+ long long mem_http2_response_buffer;
/** number of TLS connection resume */
long long qtls_resume;
/** RPZ action stats */
diff --git a/contrib/unbound/services/cache/dns.c b/contrib/unbound/services/cache/dns.c
index 7b6e142c9915..f3149b614b54 100644
--- a/contrib/unbound/services/cache/dns.c
+++ b/contrib/unbound/services/cache/dns.c
@@ -890,9 +890,8 @@ dns_cache_lookup(struct module_env* env,
lock_rw_unlock(&rrset->entry.lock);
}
- /* construct DS, DNSKEY, DLV messages from rrset cache. */
- if((qtype == LDNS_RR_TYPE_DS || qtype == LDNS_RR_TYPE_DNSKEY ||
- qtype == LDNS_RR_TYPE_DLV) &&
+ /* construct DS, DNSKEY messages from rrset cache. */
+ if((qtype == LDNS_RR_TYPE_DS || qtype == LDNS_RR_TYPE_DNSKEY) &&
(rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen,
qtype, qclass, 0, now, 0))) {
/* if the rrset is from the additional section, and the
diff --git a/contrib/unbound/services/listen_dnsport.c b/contrib/unbound/services/listen_dnsport.c
index cc56d3fd3167..3a98c264297a 100644
--- a/contrib/unbound/services/listen_dnsport.c
+++ b/contrib/unbound/services/listen_dnsport.c
@@ -53,6 +53,7 @@
#include "util/config_file.h"
#include "util/net_help.h"
#include "sldns/sbuffer.h"
+#include "sldns/parseutil.h"
#include "services/mesh.h"
#include "util/fptr_wlist.h"
#include "util/locks.h"
@@ -70,6 +71,13 @@
#include <systemd/sd-daemon.h>
#endif
+#ifdef HAVE_IFADDRS_H
+#include <ifaddrs.h>
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
/** number of queued TCP connections for listen() */
#define TCP_BACKLOG 256
@@ -79,11 +87,23 @@
#ifndef THREADS_DISABLED
/** lock on the counter of stream buffer memory */
static lock_basic_type stream_wait_count_lock;
+/** lock on the counter of HTTP2 query buffer memory */
+static lock_basic_type http2_query_buffer_count_lock;
+/** lock on the counter of HTTP2 response buffer memory */
+static lock_basic_type http2_response_buffer_count_lock;
#endif
/** size (in bytes) of stream wait buffers */
static size_t stream_wait_count = 0;
/** is the lock initialised for stream wait buffers */
static int stream_wait_lock_inited = 0;
+/** size (in bytes) of HTTP2 query buffers */
+static size_t http2_query_buffer_count = 0;
+/** is the lock initialised for HTTP2 query buffers */
+static int http2_query_buffer_lock_inited = 0;
+/** size (in bytes) of HTTP2 response buffers */
+static size_t http2_response_buffer_count = 0;
+/** is the lock initialised for HTTP2 response buffers */
+static int http2_response_buffer_lock_inited = 0;
/**
* Debug print of the getaddrinfo returned address.
@@ -221,16 +241,14 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
*noproto = 1;
return -1;
}
- log_err("can't create socket: %s", strerror(errno));
#else
if(WSAGetLastError() == WSAEAFNOSUPPORT ||
WSAGetLastError() == WSAEPROTONOSUPPORT) {
*noproto = 1;
return -1;
}
- log_err("can't create socket: %s",
- wsa_strerror(WSAGetLastError()));
#endif
+ log_err("can't create socket: %s", sock_strerror(errno));
*noproto = 0;
return -1;
}
@@ -243,9 +261,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
#ifdef SO_REUSEADDR
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
-#ifndef USE_WINSOCK
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
- strerror(errno));
+ sock_strerror(errno));
+#ifndef USE_WINSOCK
if(errno != ENOSYS) {
close(s);
*noproto = 0;
@@ -253,8 +271,6 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
return -1;
}
#else
- log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
- wsa_strerror(WSAGetLastError()));
closesocket(s);
*noproto = 0;
*inuse = 0;
@@ -346,16 +362,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv,
(socklen_t)sizeof(rcv)) < 0) {
if(errno != EPERM) {
-# ifndef USE_WINSOCK
- log_err("setsockopt(..., SO_RCVBUFFORCE, "
- "...) failed: %s", strerror(errno));
- close(s);
-# else
log_err("setsockopt(..., SO_RCVBUFFORCE, "
- "...) failed: %s",
- wsa_strerror(WSAGetLastError()));
- closesocket(s);
-# endif
+ "...) failed: %s", sock_strerror(errno));
+ sock_close(s);
*noproto = 0;
*inuse = 0;
return -1;
@@ -363,16 +372,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
# endif /* SO_RCVBUFFORCE */
if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv,
(socklen_t)sizeof(rcv)) < 0) {
-# ifndef USE_WINSOCK
log_err("setsockopt(..., SO_RCVBUF, "
- "...) failed: %s", strerror(errno));
- close(s);
-# else
- log_err("setsockopt(..., SO_RCVBUF, "
- "...) failed: %s",
- wsa_strerror(WSAGetLastError()));
- closesocket(s);
-# endif
+ "...) failed: %s", sock_strerror(errno));
+ sock_close(s);
*noproto = 0;
*inuse = 0;
return -1;
@@ -405,16 +407,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd,
(socklen_t)sizeof(snd)) < 0) {
if(errno != EPERM) {
-# ifndef USE_WINSOCK
log_err("setsockopt(..., SO_SNDBUFFORCE, "
- "...) failed: %s", strerror(errno));
- close(s);
-# else
- log_err("setsockopt(..., SO_SNDBUFFORCE, "
- "...) failed: %s",
- wsa_strerror(WSAGetLastError()));
- closesocket(s);
-# endif
+ "...) failed: %s", sock_strerror(errno));
+ sock_close(s);
*noproto = 0;
*inuse = 0;
return -1;
@@ -422,16 +417,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
# endif /* SO_SNDBUFFORCE */
if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd,
(socklen_t)sizeof(snd)) < 0) {
-# ifndef USE_WINSOCK
- log_err("setsockopt(..., SO_SNDBUF, "
- "...) failed: %s", strerror(errno));
- close(s);
-# else
log_err("setsockopt(..., SO_SNDBUF, "
- "...) failed: %s",
- wsa_strerror(WSAGetLastError()));
- closesocket(s);
-# endif
+ "...) failed: %s", sock_strerror(errno));
+ sock_close(s);
*noproto = 0;
*inuse = 0;
return -1;
@@ -461,16 +449,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
int val=(v6only==2)?0:1;
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
(void*)&val, (socklen_t)sizeof(val)) < 0) {
-#ifndef USE_WINSOCK
log_err("setsockopt(..., IPV6_V6ONLY"
- ", ...) failed: %s", strerror(errno));
- close(s);
-#else
- log_err("setsockopt(..., IPV6_V6ONLY"
- ", ...) failed: %s",
- wsa_strerror(WSAGetLastError()));
- closesocket(s);
-#endif
+ ", ...) failed: %s", sock_strerror(errno));
+ sock_close(s);
*noproto = 0;
*inuse = 0;
return -1;
@@ -488,16 +469,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
*/
if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
(void*)&on, (socklen_t)sizeof(on)) < 0) {
-# ifndef USE_WINSOCK
- log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
- "...) failed: %s", strerror(errno));
- close(s);
-# else
log_err("setsockopt(..., IPV6_USE_MIN_MTU, "
- "...) failed: %s",
- wsa_strerror(WSAGetLastError()));
- closesocket(s);
-# endif
+ "...) failed: %s", sock_strerror(errno));
+ sock_close(s);
*noproto = 0;
*inuse = 0;
return -1;
@@ -510,15 +484,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
*/
if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU,
(void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
-# ifndef USE_WINSOCK
- log_err("setsockopt(..., IPV6_MTU, ...) failed: %s",
- strerror(errno));
- close(s);
-# else
log_err("setsockopt(..., IPV6_MTU, ...) failed: %s",
- wsa_strerror(WSAGetLastError()));
- closesocket(s);
-# endif
+ sock_strerror(errno));
+ sock_close(s);
*noproto = 0;
*inuse = 0;
return -1;
@@ -542,12 +510,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
if (errno != EINVAL) {
log_err("setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_OMIT...) failed: %s",
strerror(errno));
-
-# ifndef USE_WINSOCK
- close(s);
-# else
- closesocket(s);
-# endif
+ sock_close(s);
*noproto = 0;
*inuse = 0;
return -1;
@@ -564,11 +527,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
&action, (socklen_t)sizeof(action)) < 0) {
log_err("setsockopt(..., IP_MTU_DISCOVER, IP_PMTUDISC_DONT...) failed: %s",
strerror(errno));
-# ifndef USE_WINSOCK
- close(s);
-# else
- closesocket(s);
-# endif
+ sock_close(s);
*noproto = 0;
*inuse = 0;
return -1;
@@ -580,11 +539,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
&off, (socklen_t)sizeof(off)) < 0) {
log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
strerror(errno));
-# ifndef USE_WINSOCK
- close(s);
-# else
- closesocket(s);
-# endif
+ sock_close(s);
*noproto = 0;
*inuse = 0;
return -1;
@@ -614,7 +569,6 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
(struct sockaddr_storage*)addr, addrlen);
}
#endif /* EADDRINUSE */
- close(s);
#else /* USE_WINSOCK */
if(WSAGetLastError() != WSAEADDRINUSE &&
WSAGetLastError() != WSAEADDRNOTAVAIL &&
@@ -623,18 +577,14 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
wsa_strerror(WSAGetLastError()),
(struct sockaddr_storage*)addr, addrlen);
}
- closesocket(s);
#endif /* USE_WINSOCK */
+ sock_close(s);
return -1;
}
if(!fd_set_nonblock(s)) {
*noproto = 0;
*inuse = 0;
-#ifndef USE_WINSOCK
- close(s);
-#else
- closesocket(s);
-#endif
+ sock_close(s);
return -1;
}
return s;
@@ -642,7 +592,8 @@ 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 freebind, int use_systemd, int dscp)
+ int* reuseport, int transparent, int mss, int nodelay, int freebind,
+ int use_systemd, int dscp)
{
int s;
char* err;
@@ -678,29 +629,38 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
*noproto = 1;
return -1;
}
- log_err("can't create socket: %s", strerror(errno));
#else
if(WSAGetLastError() == WSAEAFNOSUPPORT ||
WSAGetLastError() == WSAEPROTONOSUPPORT) {
*noproto = 1;
return -1;
}
- log_err("can't create socket: %s",
- wsa_strerror(WSAGetLastError()));
#endif
+ log_err("can't create socket: %s", sock_strerror(errno));
return -1;
}
- if (mss > 0) {
-#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
- if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, (void*)&mss,
- (socklen_t)sizeof(mss)) < 0) {
+ if(nodelay) {
+#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
+ if(setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void*)&on,
+ (socklen_t)sizeof(on)) < 0) {
#ifndef USE_WINSOCK
- log_err(" setsockopt(.. TCP_MAXSEG ..) failed: %s",
+ log_err(" setsockopt(.. TCP_NODELAY ..) failed: %s",
strerror(errno));
#else
- log_err(" setsockopt(.. TCP_MAXSEG ..) failed: %s",
+ log_err(" setsockopt(.. TCP_NODELAY ..) failed: %s",
wsa_strerror(WSAGetLastError()));
#endif
+ }
+#else
+ log_warn(" setsockopt(TCP_NODELAY) unsupported");
+#endif /* defined(IPPROTO_TCP) && defined(TCP_NODELAY) */
+ }
+ if (mss > 0) {
+#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
+ if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, (void*)&mss,
+ (socklen_t)sizeof(mss)) < 0) {
+ log_err(" setsockopt(.. TCP_MAXSEG ..) failed: %s",
+ sock_strerror(errno));
} else {
verbose(VERB_ALGO,
" tcp socket mss set to %d", mss);
@@ -717,15 +677,9 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
#ifdef SO_REUSEADDR
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
-#ifndef USE_WINSOCK
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
- strerror(errno));
- close(s);
-#else
- log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
- wsa_strerror(WSAGetLastError()));
- closesocket(s);
-#endif
+ sock_strerror(errno));
+ sock_close(s);
return -1;
}
#endif /* SO_REUSEADDR */
@@ -760,15 +714,9 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
if(addr->ai_family == AF_INET6 && v6only) {
if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
(void*)&on, (socklen_t)sizeof(on)) < 0) {
-#ifndef USE_WINSOCK
log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
- strerror(errno));
- close(s);
-#else
- log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
- wsa_strerror(WSAGetLastError()));
- closesocket(s);
-#endif
+ sock_strerror(errno));
+ sock_close(s);
return -1;
}
}
@@ -815,32 +763,22 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
(struct sockaddr_storage*)addr->ai_addr,
addr->ai_addrlen);
}
- close(s);
#else
log_err_addr("can't bind socket",
wsa_strerror(WSAGetLastError()),
(struct sockaddr_storage*)addr->ai_addr,
addr->ai_addrlen);
- closesocket(s);
#endif
+ sock_close(s);
return -1;
}
if(!fd_set_nonblock(s)) {
-#ifndef USE_WINSOCK
- close(s);
-#else
- closesocket(s);
-#endif
+ sock_close(s);
return -1;
}
if(listen(s, TCP_BACKLOG) == -1) {
-#ifndef USE_WINSOCK
- log_err("can't listen: %s", strerror(errno));
- close(s);
-#else
- log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
- closesocket(s);
-#endif
+ log_err("can't listen: %s", sock_strerror(errno));
+ sock_close(s);
return -1;
}
#ifdef USE_TCP_FASTOPEN
@@ -895,34 +833,6 @@ set_ip_dscp(int socket, int addrfamily, int dscp)
return NULL;
}
-# ifndef USE_WINSOCK
-char*
-sock_strerror(int errn)
-{
- return strerror(errn);
-}
-
-void
-sock_close(int socket)
-{
- close(socket);
-}
-
-# else
-char*
-sock_strerror(int ATTR_UNUSED(errn))
-{
- return wsa_strerror(WSAGetLastError());
-}
-
-void
-sock_close(int socket)
-{
- closesocket(socket);
-}
-
-# endif /* USE_WINSOCK */
-
int
create_local_accept_sock(const char *path, int* noproto, int use_systemd)
{
@@ -983,11 +893,7 @@ create_local_accept_sock(const char *path, int* noproto, int use_systemd)
return s;
err:
-#ifndef USE_WINSOCK
- close(s);
-#else
- closesocket(s);
-#endif
+ sock_close(s);
return -1;
#ifdef HAVE_SYSTEMD
@@ -1009,7 +915,8 @@ err:
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 freebind, int use_systemd, int dscp)
+ int* reuseport, int transparent, int tcp_mss, int nodelay, int freebind,
+ int use_systemd, int dscp)
{
struct addrinfo *res = NULL;
int r, s, inuse, noproto;
@@ -1045,7 +952,8 @@ make_sock(int stype, const char* ifname, const char* port,
}
} else {
s = create_tcp_accept_sock(res, v6only, &noproto, reuseport,
- transparent, tcp_mss, freebind, use_systemd, dscp);
+ transparent, tcp_mss, nodelay, freebind, use_systemd,
+ dscp);
if(s == -1 && noproto && hints->ai_family == AF_INET6){
*noip6 = 1;
}
@@ -1058,7 +966,8 @@ 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 freebind, int use_systemd, int dscp)
+ int* reuseport, int transparent, int tcp_mss, int nodelay, int freebind,
+ int use_systemd, int dscp)
{
char* s = strchr(ifname, '@');
if(s) {
@@ -1079,11 +988,13 @@ make_sock_port(int stype, const char* ifname, const char* port,
newif[s-ifname] = 0;
(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, freebind, use_systemd, dscp);
+ return make_sock(stype, newif, p, hints, v6only, noip6, rcv,
+ snd, reuseport, transparent, tcp_mss, nodelay, freebind,
+ use_systemd, dscp);
}
return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd,
- reuseport, transparent, tcp_mss, freebind, use_systemd, dscp);
+ reuseport, transparent, tcp_mss, nodelay, freebind, use_systemd,
+ dscp);
}
/**
@@ -1182,6 +1093,18 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
return 0;
}
+/** see if interface is https, its port number == the https port number */
+static int
+if_is_https(const char* ifname, const char* port, int https_port)
+{
+ char* p = strchr(ifname, '@');
+ if(!p && atoi(port) == https_port)
+ return 1;
+ if(p && atoi(p+1) == https_port)
+ return 1;
+ return 0;
+}
+
/**
* Helper for ports_open. Creates one interface (or NULL for default).
* @param ifname: The interface ip address.
@@ -1196,11 +1119,13 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
* @param snd: send buffer size for UDP
* @param ssl_port: ssl service port number
* @param tls_additional_port: list of additional ssl service port numbers.
+ * @param https_port: DoH service port number
* @param reuseport: try to set SO_REUSEPORT if nonNULL and true.
* 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.
+ * @param http2_nodelay: set TCP_NODELAY on HTTP/2 connection
* @param use_systemd: if true, fetch sockets from systemd.
* @param dnscrypt_port: dnscrypt service port number
* @param dscp: DSCP to use.
@@ -1210,11 +1135,13 @@ 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,
- struct config_strlist* tls_additional_port, int* reuseport,
- int transparent, int tcp_mss, int freebind, int use_systemd,
- int dnscrypt_port, int dscp)
+ struct config_strlist* tls_additional_port, int https_port,
+ int* reuseport, int transparent, int tcp_mss, int freebind,
+ int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp)
{
int s, noip6=0;
+ int is_https = if_is_https(ifname, port, https_port);
+ int nodelay = is_https && http2_nodelay;
#ifdef USE_DNSCRYPT
int is_dnscrypt = ((strchr(ifname, '@') &&
atoi(strchr(ifname, '@')+1) == dnscrypt_port) ||
@@ -1229,7 +1156,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, freebind, use_systemd, dscp)) == -1) {
+ tcp_mss, nodelay, freebind, use_systemd, dscp)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
@@ -1238,27 +1165,19 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
/* getting source addr packet info is highly non-portable */
if(!set_recvpktinfo(s, hints->ai_family)) {
-#ifndef USE_WINSOCK
- close(s);
-#else
- closesocket(s);
-#endif
+ sock_close(s);
return 0;
}
if(!port_insert(list, s,
is_dnscrypt?listen_type_udpancil_dnscrypt:listen_type_udpancil)) {
-#ifndef USE_WINSOCK
- close(s);
-#else
- closesocket(s);
-#endif
+ sock_close(s);
return 0;
}
} else if(do_udp) {
/* regular udp socket */
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
- tcp_mss, freebind, use_systemd, dscp)) == -1) {
+ tcp_mss, nodelay, freebind, use_systemd, dscp)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
@@ -1267,19 +1186,24 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
if(!port_insert(list, s,
is_dnscrypt?listen_type_udp_dnscrypt:listen_type_udp)) {
-#ifndef USE_WINSOCK
- close(s);
-#else
- closesocket(s);
-#endif
+ sock_close(s);
return 0;
}
}
if(do_tcp) {
int is_ssl = if_is_ssl(ifname, port, ssl_port,
tls_additional_port);
+ enum listen_type port_type;
+ if(is_ssl)
+ port_type = listen_type_ssl;
+ else if(is_https)
+ port_type = listen_type_http;
+ else if(is_dnscrypt)
+ port_type = listen_type_tcp_dnscrypt;
+ else
+ port_type = listen_type_tcp;
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
- &noip6, 0, 0, reuseport, transparent, tcp_mss,
+ &noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay,
freebind, use_systemd, dscp)) == -1) {
if(noip6) {
/*log_warn("IPv6 protocol not available");*/
@@ -1289,13 +1213,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
if(is_ssl)
verbose(VERB_ALGO, "setup TCP for SSL service");
- if(!port_insert(list, s, is_ssl?listen_type_ssl:
- (is_dnscrypt?listen_type_tcp_dnscrypt:listen_type_tcp))) {
-#ifndef USE_WINSOCK
- close(s);
-#else
- closesocket(s);
-#endif
+ if(!port_insert(list, s, port_type)) {
+ sock_close(s);
return 0;
}
}
@@ -1324,7 +1243,8 @@ listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ports,
size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
- struct tcl_list* tcp_conn_limit, void* sslctx,
+ int harden_large_queries, uint32_t http_max_streams,
+ char* http_endpoint, struct tcl_list* tcp_conn_limit, void* sslctx,
struct dt_env* dtenv, comm_point_callback_type* cb, void *cb_arg)
{
struct listen_dnsport* front = (struct listen_dnsport*)
@@ -1344,6 +1264,14 @@ listen_create(struct comm_base* base, struct listen_port* ports,
lock_basic_init(&stream_wait_count_lock);
stream_wait_lock_inited = 1;
}
+ if(!http2_query_buffer_lock_inited) {
+ lock_basic_init(&http2_query_buffer_count_lock);
+ http2_query_buffer_lock_inited = 1;
+ }
+ if(!http2_response_buffer_lock_inited) {
+ lock_basic_init(&http2_response_buffer_count_lock);
+ http2_response_buffer_lock_inited = 1;
+ }
/* create comm points as needed */
while(ports) {
@@ -1356,14 +1284,36 @@ listen_create(struct comm_base* base, struct listen_port* ports,
ports->ftype == listen_type_tcp_dnscrypt)
cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, tcp_idle_timeout,
+ harden_large_queries, 0, NULL,
tcp_conn_limit, bufsize, front->udp_buff,
- cb, cb_arg);
- else if(ports->ftype == listen_type_ssl) {
+ ports->ftype, cb, cb_arg);
+ else if(ports->ftype == listen_type_ssl ||
+ ports->ftype == listen_type_http) {
cp = comm_point_create_tcp(base, ports->fd,
tcp_accept_count, tcp_idle_timeout,
+ harden_large_queries,
+ http_max_streams, http_endpoint,
tcp_conn_limit, bufsize, front->udp_buff,
- cb, cb_arg);
+ ports->ftype, cb, cb_arg);
cp->ssl = sslctx;
+ if(ports->ftype == listen_type_http) {
+ if(!sslctx) {
+ log_warn("HTTPS port configured, but no TLS "
+ "tls-service-key or tls-service-pem "
+ "set");
+ }
+#ifndef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
+ log_warn("Unbound is not compiled with an "
+ "OpenSSL version supporting ALPN "
+ " (OpenSSL >= 1.0.2). This is required "
+ "to use DNS-over-HTTPS");
+#endif
+#ifndef HAVE_NGHTTP2_NGHTTP2_H
+ log_warn("Unbound is not compiled with "
+ "nghttp2. This is required to use "
+ "DNS-over-HTTPS.");
+#endif
+ }
} else if(ports->ftype == listen_type_udpancil ||
ports->ftype == listen_type_udpancil_dnscrypt)
cp = comm_point_create_udp_ancil(base, ports->fd,
@@ -1437,10 +1387,173 @@ listen_delete(struct listen_dnsport* front)
stream_wait_lock_inited = 0;
lock_basic_destroy(&stream_wait_count_lock);
}
+ if(http2_query_buffer_lock_inited) {
+ http2_query_buffer_lock_inited = 0;
+ lock_basic_destroy(&http2_query_buffer_count_lock);
+ }
+ if(http2_response_buffer_lock_inited) {
+ http2_response_buffer_lock_inited = 0;
+ lock_basic_destroy(&http2_response_buffer_count_lock);
+ }
+}
+
+#ifdef HAVE_GETIFADDRS
+static int
+resolve_ifa_name(struct ifaddrs *ifas, const char *search_ifa, char ***ip_addresses, int *ip_addresses_size)
+{
+ struct ifaddrs *ifa;
+ int last_ip_addresses_size = *ip_addresses_size;
+
+ for(ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) {
+ sa_family_t family;
+ const char* atsign;
+#ifdef INET6 /* | address ip | % | ifa name | @ | port | nul */
+ char addr_buf[INET6_ADDRSTRLEN + 1 + IF_NAMESIZE + 1 + 16 + 1];
+#else
+ char addr_buf[INET_ADDRSTRLEN + 1 + 16 + 1];
+#endif
+
+ if((atsign=strrchr(search_ifa, '@')) != NULL) {
+ if(strlen(ifa->ifa_name) != (size_t)(atsign-search_ifa)
+ || strncmp(ifa->ifa_name, search_ifa,
+ atsign-search_ifa) != 0)
+ continue;
+ } else {
+ if(strcmp(ifa->ifa_name, search_ifa) != 0)
+ continue;
+ atsign = "";
+ }
+
+ if(ifa->ifa_addr == NULL)
+ continue;
+
+ family = ifa->ifa_addr->sa_family;
+ if(family == AF_INET) {
+ char a4[INET_ADDRSTRLEN + 1];
+ struct sockaddr_in *in4 = (struct sockaddr_in *)
+ ifa->ifa_addr;
+ if(!inet_ntop(family, &in4->sin_addr, a4, sizeof(a4))) {
+ log_err("inet_ntop failed");
+ return 0;
+ }
+ snprintf(addr_buf, sizeof(addr_buf), "%s%s",
+ a4, atsign);
+ }
+#ifdef INET6
+ else if(family == AF_INET6) {
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)
+ ifa->ifa_addr;
+ char a6[INET6_ADDRSTRLEN + 1];
+ char if_index_name[IF_NAMESIZE + 1];
+ if_index_name[0] = 0;
+ if(!inet_ntop(family, &in6->sin6_addr, a6, sizeof(a6))) {
+ log_err("inet_ntop failed");
+ return 0;
+ }
+ if_indextoname(in6->sin6_scope_id,
+ (char *)if_index_name);
+ if (strlen(if_index_name) != 0) {
+ snprintf(addr_buf, sizeof(addr_buf),
+ "%s%%%s%s", a6, if_index_name, atsign);
+ } else {
+ snprintf(addr_buf, sizeof(addr_buf), "%s%s",
+ a6, atsign);
+ }
+ }
+#endif
+ else {
+ continue;
+ }
+ verbose(4, "interface %s has address %s", search_ifa, addr_buf);
+
+ *ip_addresses = realloc(*ip_addresses, sizeof(char *) * (*ip_addresses_size + 1));
+ if(!*ip_addresses) {
+ log_err("realloc failed: out of memory");
+ return 0;
+ }
+ (*ip_addresses)[*ip_addresses_size] = strdup(addr_buf);
+ if(!(*ip_addresses)[*ip_addresses_size]) {
+ log_err("strdup failed: out of memory");
+ return 0;
+ }
+ (*ip_addresses_size)++;
+ }
+
+ if (*ip_addresses_size == last_ip_addresses_size) {
+ *ip_addresses = realloc(*ip_addresses, sizeof(char *) * (*ip_addresses_size + 1));
+ if(!*ip_addresses) {
+ log_err("realloc failed: out of memory");
+ return 0;
+ }
+ (*ip_addresses)[*ip_addresses_size] = strdup(search_ifa);
+ if(!(*ip_addresses)[*ip_addresses_size]) {
+ log_err("strdup failed: out of memory");
+ return 0;
+ }
+ (*ip_addresses_size)++;
+ }
+ return 1;
+}
+#endif /* HAVE_GETIFADDRS */
+
+int resolve_interface_names(struct config_file* cfg, char*** resif,
+ int* num_resif)
+{
+#ifdef HAVE_GETIFADDRS
+ int i;
+ struct ifaddrs *addrs = NULL;
+ if(cfg->num_ifs == 0) {
+ *resif = NULL;
+ *num_resif = 0;
+ return 1;
+ }
+ if(getifaddrs(&addrs) == -1) {
+ log_err("failed to list interfaces: getifaddrs: %s",
+ strerror(errno));
+ freeifaddrs(addrs);
+ return 0;
+ }
+ for(i=0; i<cfg->num_ifs; i++) {
+ if(!resolve_ifa_name(addrs, cfg->ifs[i], resif, num_resif)) {
+ freeifaddrs(addrs);
+ config_del_strarray(*resif, *num_resif);
+ *resif = NULL;
+ *num_resif = 0;
+ return 0;
+ }
+ }
+ freeifaddrs(addrs);
+ return 1;
+#else
+ int i;
+ if(cfg->num_ifs == 0) {
+ *resif = NULL;
+ *num_resif = 0;
+ return 1;
+ }
+ *num_resif = cfg->num_ifs;
+ *resif = calloc(*num_resif, sizeof(**resif));
+ if(!*resif) {
+ log_err("out of memory");
+ return 0;
+ }
+ for(i=0; i<*num_resif; i++) {
+ (*resif)[i] = strdup(cfg->ifs[i]);
+ if(!((*resif)[i])) {
+ log_err("out of memory");
+ config_del_strarray(*resif, *num_resif);
+ *resif = NULL;
+ *num_resif = 0;
+ return 0;
+ }
+ }
+ return 1;
+#endif /* HAVE_GETIFADDRS */
}
struct listen_port*
-listening_ports_open(struct config_file* cfg, int* reuseport)
+listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
+ int* reuseport)
{
struct listen_port* list = NULL;
struct addrinfo hints;
@@ -1459,7 +1572,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
/* no name lookups on our listening ports */
- if(cfg->num_ifs > 0)
+ if(num_ifs > 0)
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_family = AF_UNSPEC;
#ifndef INET6
@@ -1469,7 +1582,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
return NULL;
}
/* create ip4 and ip6 ports so that return addresses are nice. */
- if(do_auto || cfg->num_ifs == 0) {
+ if(do_auto || num_ifs == 0) {
if(do_ip6) {
hints.ai_family = AF_INET6;
if(!ports_create_if(do_auto?"::0":"::1",
@@ -1477,8 +1590,9 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
- reuseport, cfg->ip_transparent,
- cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
+ cfg->https_port, reuseport, cfg->ip_transparent,
+ cfg->tcp_mss, cfg->ip_freebind,
+ cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
@@ -1491,24 +1605,26 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
- reuseport, cfg->ip_transparent,
- cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
+ cfg->https_port, reuseport, cfg->ip_transparent,
+ cfg->tcp_mss, cfg->ip_freebind,
+ cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
}
- } else for(i = 0; i<cfg->num_ifs; i++) {
- if(str_is_ip6(cfg->ifs[i])) {
+ } else for(i = 0; i<num_ifs; i++) {
+ if(str_is_ip6(ifs[i])) {
if(!do_ip6)
continue;
hints.ai_family = AF_INET6;
- if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
+ if(!ports_create_if(ifs[i], 0, cfg->do_udp,
do_tcp, &hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
- reuseport, cfg->ip_transparent,
- cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
+ cfg->https_port, reuseport, cfg->ip_transparent,
+ cfg->tcp_mss, cfg->ip_freebind,
+ cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
@@ -1517,12 +1633,13 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
if(!do_ip4)
continue;
hints.ai_family = AF_INET;
- if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
+ if(!ports_create_if(ifs[i], 0, cfg->do_udp,
do_tcp, &hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
cfg->ssl_port, cfg->tls_additional_port,
- reuseport, cfg->ip_transparent,
- cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
+ cfg->https_port, reuseport, cfg->ip_transparent,
+ cfg->tcp_mss, cfg->ip_freebind,
+ cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
@@ -1538,11 +1655,7 @@ void listening_ports_free(struct listen_port* list)
while(list) {
nx = list->next;
if(list->fd != -1) {
-#ifndef USE_WINSOCK
- close(list->fd);
-#else
- closesocket(list->fd);
-#endif
+ sock_close(list->fd);
}
free(list);
list = nx;
@@ -1964,3 +2077,739 @@ size_t tcp_req_info_get_stream_buffer_size(void)
lock_basic_unlock(&stream_wait_count_lock);
return s;
}
+
+size_t http2_get_query_buffer_size(void)
+{
+ size_t s;
+ if(!http2_query_buffer_lock_inited)
+ return http2_query_buffer_count;
+ lock_basic_lock(&http2_query_buffer_count_lock);
+ s = http2_query_buffer_count;
+ lock_basic_unlock(&http2_query_buffer_count_lock);
+ return s;
+}
+
+size_t http2_get_response_buffer_size(void)
+{
+ size_t s;
+ if(!http2_response_buffer_lock_inited)
+ return http2_response_buffer_count;
+ lock_basic_lock(&http2_response_buffer_count_lock);
+ s = http2_response_buffer_count;
+ lock_basic_unlock(&http2_response_buffer_count_lock);
+ return s;
+}
+
+#ifdef HAVE_NGHTTP2
+/** nghttp2 callback. Used to copy response from rbuffer to nghttp2 session */
+static ssize_t http2_submit_response_read_callback(
+ nghttp2_session* ATTR_UNUSED(session),
+ int32_t stream_id, uint8_t* buf, size_t length, uint32_t* data_flags,
+ nghttp2_data_source* source, void* ATTR_UNUSED(cb_arg))
+{
+ struct http2_stream* h2_stream;
+ struct http2_session* h2_session = source->ptr;
+ size_t copylen = length;
+ if(!(h2_stream = nghttp2_session_get_stream_user_data(
+ h2_session->session, stream_id))) {
+ verbose(VERB_QUERY, "http2: cannot get stream data, closing "
+ "stream");
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+ if(!h2_stream->rbuffer ||
+ sldns_buffer_remaining(h2_stream->rbuffer) == 0) {
+ verbose(VERB_QUERY, "http2: cannot submit buffer. No data "
+ "available in rbuffer");
+ /* rbuffer will be free'd in frame close cb */
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+
+ if(copylen > sldns_buffer_remaining(h2_stream->rbuffer))
+ copylen = sldns_buffer_remaining(h2_stream->rbuffer);
+ if(copylen > SSIZE_MAX)
+ copylen = SSIZE_MAX; /* will probably never happen */
+
+ memcpy(buf, sldns_buffer_current(h2_stream->rbuffer), copylen);
+ sldns_buffer_skip(h2_stream->rbuffer, copylen);
+
+ if(sldns_buffer_remaining(h2_stream->rbuffer) == 0) {
+ *data_flags |= NGHTTP2_DATA_FLAG_EOF;
+ lock_basic_lock(&http2_response_buffer_count_lock);
+ http2_response_buffer_count -=
+ sldns_buffer_capacity(h2_stream->rbuffer);
+ lock_basic_unlock(&http2_response_buffer_count_lock);
+ sldns_buffer_free(h2_stream->rbuffer);
+ h2_stream->rbuffer = NULL;
+ }
+
+ return copylen;
+}
+
+/**
+ * Send RST_STREAM frame for stream.
+ * @param h2_session: http2 session to submit frame to
+ * @param h2_stream: http2 stream containing frame ID to use in RST_STREAM
+ * @return 0 on error, 1 otherwise
+ */
+static int http2_submit_rst_stream(struct http2_session* h2_session,
+ struct http2_stream* h2_stream)
+{
+ int ret = nghttp2_submit_rst_stream(h2_session->session,
+ NGHTTP2_FLAG_NONE, h2_stream->stream_id,
+ NGHTTP2_INTERNAL_ERROR);
+ if(ret) {
+ verbose(VERB_QUERY, "http2: nghttp2_submit_rst_stream failed, "
+ "error: %s", nghttp2_strerror(ret));
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * DNS response ready to be submitted to nghttp2, to be prepared for sending
+ * out. Response is stored in c->buffer. Copy to rbuffer because the c->buffer
+ * might be used before this will be sent out.
+ * @param h2_session: http2 session, containing c->buffer which contains answer
+ * @return 0 on error, 1 otherwise
+ */
+int http2_submit_dns_response(struct http2_session* h2_session)
+{
+ int ret;
+ nghttp2_data_provider data_prd;
+ char status[4];
+ nghttp2_nv headers[2];
+ struct http2_stream* h2_stream = h2_session->c->h2_stream;
+ size_t rlen;
+
+ if(h2_stream->rbuffer) {
+ log_err("http2 submit response error: rbuffer already "
+ "exists");
+ return 0;
+ }
+ if(sldns_buffer_remaining(h2_session->c->buffer) == 0) {
+ log_err("http2 submit response error: c->buffer not complete");
+ return 0;
+ }
+
+ if(snprintf(status, 4, "%d", h2_stream->status) != 3) {
+ verbose(VERB_QUERY, "http2: submit response error: "
+ "invalid status");
+ return 0;
+ }
+
+ rlen = sldns_buffer_remaining(h2_session->c->buffer);
+ lock_basic_lock(&http2_response_buffer_count_lock);
+ if(http2_response_buffer_count + rlen > http2_response_buffer_max) {
+ lock_basic_unlock(&http2_response_buffer_count_lock);
+ verbose(VERB_ALGO, "reset HTTP2 stream, no space left, "
+ "in https-response-buffer-size");
+ return http2_submit_rst_stream(h2_session, h2_stream);
+ }
+ http2_response_buffer_count += rlen;
+ lock_basic_unlock(&http2_response_buffer_count_lock);
+
+ if(!(h2_stream->rbuffer = sldns_buffer_new(rlen))) {
+ lock_basic_lock(&http2_response_buffer_count_lock);
+ http2_response_buffer_count -= rlen;
+ lock_basic_unlock(&http2_response_buffer_count_lock);
+ log_err("http2 submit response error: malloc failure");
+ return 0;
+ }
+
+ headers[0].name = (uint8_t*)":status";
+ headers[0].namelen = 7;
+ headers[0].value = (uint8_t*)status;
+ headers[0].valuelen = 3;
+ headers[0].flags = NGHTTP2_NV_FLAG_NONE;
+
+ headers[1].name = (uint8_t*)"content-type";
+ headers[1].namelen = 12;
+ headers[1].value = (uint8_t*)"application/dns-message";
+ headers[1].valuelen = 23;
+ headers[1].flags = NGHTTP2_NV_FLAG_NONE;
+
+ /*TODO be nice and add the content-length header
+ headers[2].name = (uint8_t*)"content-length";
+ headers[2].namelen = 14;
+ headers[2].value =
+ headers[2].valuelen =
+ headers[2].flags = NGHTTP2_NV_FLAG_NONE;
+ */
+
+ sldns_buffer_write(h2_stream->rbuffer,
+ sldns_buffer_current(h2_session->c->buffer),
+ sldns_buffer_remaining(h2_session->c->buffer));
+ sldns_buffer_flip(h2_stream->rbuffer);
+
+ data_prd.source.ptr = h2_session;
+ data_prd.read_callback = http2_submit_response_read_callback;
+ ret = nghttp2_submit_response(h2_session->session, h2_stream->stream_id,
+ headers, 2, &data_prd);
+ if(ret) {
+ verbose(VERB_QUERY, "http2: set_stream_user_data failed, "
+ "error: %s", nghttp2_strerror(ret));
+ return 0;
+ }
+ return 1;
+}
+#else
+int http2_submit_dns_response(void* ATTR_UNUSED(v))
+{
+ return 0;
+}
+#endif
+
+#ifdef HAVE_NGHTTP2
+/** HTTP status to descriptive string */
+static char* http_status_to_str(enum http_status s)
+{
+ switch(s) {
+ case HTTP_STATUS_OK:
+ return "OK";
+ case HTTP_STATUS_BAD_REQUEST:
+ return "Bad Request";
+ case HTTP_STATUS_NOT_FOUND:
+ return "Not Found";
+ case HTTP_STATUS_PAYLOAD_TOO_LARGE:
+ return "Payload Too Large";
+ case HTTP_STATUS_URI_TOO_LONG:
+ return "URI Too Long";
+ case HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE:
+ return "Unsupported Media Type";
+ case HTTP_STATUS_NOT_IMPLEMENTED:
+ return "Not Implemented";
+ }
+ return "Status Unknown";
+}
+
+/** nghttp2 callback. Used to copy error message to nghttp2 session */
+static ssize_t http2_submit_error_read_callback(
+ nghttp2_session* ATTR_UNUSED(session),
+ int32_t stream_id, uint8_t* buf, size_t length, uint32_t* data_flags,
+ nghttp2_data_source* source, void* ATTR_UNUSED(cb_arg))
+{
+ struct http2_stream* h2_stream;
+ struct http2_session* h2_session = source->ptr;
+ char* msg;
+ if(!(h2_stream = nghttp2_session_get_stream_user_data(
+ h2_session->session, stream_id))) {
+ verbose(VERB_QUERY, "http2: cannot get stream data, closing "
+ "stream");
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+ *data_flags |= NGHTTP2_DATA_FLAG_EOF;
+ msg = http_status_to_str(h2_stream->status);
+ if(length < strlen(msg))
+ return 0; /* not worth trying over multiple frames */
+ memcpy(buf, msg, strlen(msg));
+ return strlen(msg);
+
+}
+
+/**
+ * HTTP error response ready to be submitted to nghttp2, to be prepared for
+ * sending out. Message body will contain descriptive string for HTTP status.
+ * @param h2_session: http2 session to submit to
+ * @param h2_stream: http2 stream containing HTTP status to use for error
+ * @return 0 on error, 1 otherwise
+ */
+static int http2_submit_error(struct http2_session* h2_session,
+ struct http2_stream* h2_stream)
+{
+ int ret;
+ char status[4];
+ nghttp2_data_provider data_prd;
+ nghttp2_nv headers[1]; /* will be copied by nghttp */
+ if(snprintf(status, 4, "%d", h2_stream->status) != 3) {
+ verbose(VERB_QUERY, "http2: submit error failed, "
+ "invalid status");
+ return 0;
+ }
+ headers[0].name = (uint8_t*)":status";
+ headers[0].namelen = 7;
+ headers[0].value = (uint8_t*)status;
+ headers[0].valuelen = 3;
+ headers[0].flags = NGHTTP2_NV_FLAG_NONE;
+
+ data_prd.source.ptr = h2_session;
+ data_prd.read_callback = http2_submit_error_read_callback;
+
+ ret = nghttp2_submit_response(h2_session->session, h2_stream->stream_id,
+ headers, 1, &data_prd);
+ if(ret) {
+ verbose(VERB_QUERY, "http2: submit error failed, "
+ "error: %s", nghttp2_strerror(ret));
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * Start query handling. Query is stored in the stream, and will be free'd here.
+ * @param h2_session: http2 session, containing comm point
+ * @param h2_stream: stream containing buffered query
+ * @return: -1 on error, 1 if answer is stored in c->buffer, 0 if there is no
+ * reply available (yet).
+ */
+static int http2_query_read_done(struct http2_session* h2_session,
+ struct http2_stream* h2_stream)
+{
+ log_assert(h2_stream->qbuffer);
+
+ if(h2_session->c->h2_stream) {
+ verbose(VERB_ALGO, "http2_query_read_done failure: shared "
+ "buffer already assigned to stream");
+ return -1;
+ }
+ if(sldns_buffer_remaining(h2_session->c->buffer) <
+ sldns_buffer_remaining(h2_stream->qbuffer)) {
+ /* qbuffer will be free'd in frame close cb */
+ sldns_buffer_clear(h2_session->c->buffer);
+ verbose(VERB_ALGO, "http2_query_read_done failure: can't fit "
+ "qbuffer in c->buffer");
+ return -1;
+ }
+
+ sldns_buffer_write(h2_session->c->buffer,
+ sldns_buffer_current(h2_stream->qbuffer),
+ sldns_buffer_remaining(h2_stream->qbuffer));
+
+ lock_basic_lock(&http2_query_buffer_count_lock);
+ http2_query_buffer_count -= sldns_buffer_capacity(h2_stream->qbuffer);
+ lock_basic_unlock(&http2_query_buffer_count_lock);
+ sldns_buffer_free(h2_stream->qbuffer);
+ h2_stream->qbuffer = NULL;
+
+ sldns_buffer_flip(h2_session->c->buffer);
+ h2_session->c->h2_stream = h2_stream;
+ fptr_ok(fptr_whitelist_comm_point(h2_session->c->callback));
+ if((*h2_session->c->callback)(h2_session->c, h2_session->c->cb_arg,
+ NETEVENT_NOERROR, &h2_session->c->repinfo)) {
+ return 1; /* answer in c->buffer */
+ }
+ sldns_buffer_clear(h2_session->c->buffer);
+ h2_session->c->h2_stream = NULL;
+ return 0; /* mesh state added, or dropped */
+}
+
+/** nghttp2 callback. Used to check if the received frame indicates the end of a
+ * stream. Gather collected request data and start query handling. */
+static int http2_req_frame_recv_cb(nghttp2_session* session,
+ const nghttp2_frame* frame, void* cb_arg)
+{
+ struct http2_session* h2_session = (struct http2_session*)cb_arg;
+ struct http2_stream* h2_stream;
+ int query_read_done;
+
+ if((frame->hd.type != NGHTTP2_DATA &&
+ frame->hd.type != NGHTTP2_HEADERS) ||
+ !(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
+ return 0;
+ }
+
+ if(!(h2_stream = nghttp2_session_get_stream_user_data(
+ session, frame->hd.stream_id)))
+ return 0;
+
+ if(h2_stream->invalid_endpoint) {
+ h2_stream->status = HTTP_STATUS_NOT_FOUND;
+ goto submit_http_error;
+ }
+
+ if(h2_stream->invalid_content_type) {
+ h2_stream->status = HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE;
+ goto submit_http_error;
+ }
+
+ if(h2_stream->http_method != HTTP_METHOD_GET &&
+ h2_stream->http_method != HTTP_METHOD_POST) {
+ h2_stream->status = HTTP_STATUS_NOT_IMPLEMENTED;
+ goto submit_http_error;
+ }
+
+ if(h2_stream->query_too_large) {
+ if(h2_stream->http_method == HTTP_METHOD_POST)
+ h2_stream->status = HTTP_STATUS_PAYLOAD_TOO_LARGE;
+ else
+ h2_stream->status = HTTP_STATUS_URI_TOO_LONG;
+ goto submit_http_error;
+ }
+
+ if(!h2_stream->qbuffer) {
+ h2_stream->status = HTTP_STATUS_BAD_REQUEST;
+ goto submit_http_error;
+ }
+
+ if(h2_stream->status) {
+submit_http_error:
+ verbose(VERB_QUERY, "http2 request invalid, returning :status="
+ "%d", h2_stream->status);
+ if(!http2_submit_error(h2_session, h2_stream)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ return 0;
+ }
+ h2_stream->status = HTTP_STATUS_OK;
+
+ sldns_buffer_flip(h2_stream->qbuffer);
+ h2_session->postpone_drop = 1;
+ query_read_done = http2_query_read_done(h2_session, h2_stream);
+ if(query_read_done < 0)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ else if(!query_read_done) {
+ if(h2_session->is_drop) {
+ /* connection needs to be closed. Return failure to make
+ * sure no other action are taken anymore on comm point.
+ * failure will result in reclaiming (and closing)
+ * of comm point. */
+ verbose(VERB_QUERY, "http2 query dropped in worker cb");
+ h2_session->postpone_drop = 0;
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ /* nothing to submit right now, query added to mesh. */
+ h2_session->postpone_drop = 0;
+ return 0;
+ }
+ if(!http2_submit_dns_response(h2_session)) {
+ sldns_buffer_clear(h2_session->c->buffer);
+ h2_session->c->h2_stream = NULL;
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ verbose(VERB_QUERY, "http2 query submitted to session");
+ sldns_buffer_clear(h2_session->c->buffer);
+ h2_session->c->h2_stream = NULL;
+ return 0;
+}
+
+/** nghttp2 callback. Used to detect start of new streams. */
+static int http2_req_begin_headers_cb(nghttp2_session* session,
+ const nghttp2_frame* frame, void* cb_arg)
+{
+ struct http2_session* h2_session = (struct http2_session*)cb_arg;
+ struct http2_stream* h2_stream;
+ int ret;
+ if(frame->hd.type != NGHTTP2_HEADERS ||
+ frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
+ /* only interrested in request headers */
+ return 0;
+ }
+ if(!(h2_stream = http2_stream_create(frame->hd.stream_id))) {
+ log_err("malloc failure while creating http2 stream");
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ http2_session_add_stream(h2_session, h2_stream);
+ ret = nghttp2_session_set_stream_user_data(session,
+ frame->hd.stream_id, h2_stream);
+ if(ret) {
+ /* stream does not exist */
+ verbose(VERB_QUERY, "http2: set_stream_user_data failed, "
+ "error: %s", nghttp2_strerror(ret));
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+/**
+ * base64url decode, store in qbuffer
+ * @param h2_session: http2 session
+ * @param h2_stream: http2 stream
+ * @param start: start of the base64 string
+ * @param length: length of the base64 string
+ * @return: 0 on error, 1 otherwise. query will be stored in h2_stream->qbuffer,
+ * buffer will be NULL is unparseble.
+ */
+static int http2_buffer_uri_query(struct http2_session* h2_session,
+ struct http2_stream* h2_stream, const uint8_t* start, size_t length)
+{
+ size_t expectb64len;
+ int b64len;
+ if(h2_stream->http_method == HTTP_METHOD_POST)
+ return 1;
+ if(length == 0)
+ return 1;
+ if(h2_stream->qbuffer) {
+ verbose(VERB_ALGO, "http2_req_header fail, "
+ "qbuffer already set");
+ return 0;
+ }
+
+ /* calculate size, might be a bit bigger than the real
+ * decoded buffer size */
+ expectb64len = sldns_b64_pton_calculate_size(length);
+ log_assert(expectb64len > 0);
+ if(expectb64len >
+ h2_session->c->http2_stream_max_qbuffer_size) {
+ h2_stream->query_too_large = 1;
+ return 1;
+ }
+
+ lock_basic_lock(&http2_query_buffer_count_lock);
+ if(http2_query_buffer_count + expectb64len > http2_query_buffer_max) {
+ lock_basic_unlock(&http2_query_buffer_count_lock);
+ verbose(VERB_ALGO, "reset HTTP2 stream, no space left, "
+ "in http2-query-buffer-size");
+ return http2_submit_rst_stream(h2_session, h2_stream);
+ }
+ http2_query_buffer_count += expectb64len;
+ lock_basic_unlock(&http2_query_buffer_count_lock);
+ if(!(h2_stream->qbuffer = sldns_buffer_new(expectb64len))) {
+ lock_basic_lock(&http2_query_buffer_count_lock);
+ http2_query_buffer_count -= expectb64len;
+ lock_basic_unlock(&http2_query_buffer_count_lock);
+ log_err("http2_req_header fail, qbuffer "
+ "malloc failure");
+ return 0;
+ }
+
+ if(!(b64len = sldns_b64url_pton(
+ (char const *)start, length,
+ sldns_buffer_current(h2_stream->qbuffer),
+ expectb64len)) || b64len < 0) {
+ lock_basic_lock(&http2_query_buffer_count_lock);
+ http2_query_buffer_count -= expectb64len;
+ lock_basic_unlock(&http2_query_buffer_count_lock);
+ sldns_buffer_free(h2_stream->qbuffer);
+ h2_stream->qbuffer = NULL;
+ /* return without error, method can be an
+ * unknown POST */
+ return 1;
+ }
+ sldns_buffer_skip(h2_stream->qbuffer, (size_t)b64len);
+ return 1;
+}
+
+/** nghttp2 callback. Used to parse headers from HEADER frames. */
+static int http2_req_header_cb(nghttp2_session* session,
+ const nghttp2_frame* frame, const uint8_t* name, size_t namelen,
+ const uint8_t* value, size_t valuelen, uint8_t ATTR_UNUSED(flags),
+ void* cb_arg)
+{
+ struct http2_stream* h2_stream = NULL;
+ struct http2_session* h2_session = (struct http2_session*)cb_arg;
+ /* nghttp2 deals with CONTINUATION frames and provides them as part of
+ * the HEADER */
+ if(frame->hd.type != NGHTTP2_HEADERS ||
+ frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
+ /* only interrested in request headers */
+ return 0;
+ }
+ if(!(h2_stream = nghttp2_session_get_stream_user_data(session,
+ frame->hd.stream_id)))
+ return 0;
+
+ /* earlier checks already indicate we can stop handling this query */
+ if(h2_stream->http_method == HTTP_METHOD_UNSUPPORTED ||
+ h2_stream->invalid_content_type ||
+ h2_stream->invalid_endpoint)
+ return 0;
+
+
+ /* nghttp2 performs some sanity checks in the headers, including:
+ * name and value are guaranteed to be null terminated
+ * name is guaranteed to be lowercase
+ * content-length value is guaranteed to contain digits
+ */
+
+ if(!h2_stream->http_method && namelen == 7 &&
+ memcmp(":method", name, namelen) == 0) {
+ /* Case insensitive check on :method value to be on the safe
+ * side. I failed to find text about case sensitivity in specs.
+ */
+ if(valuelen == 3 && strcasecmp("GET", (const char*)value) == 0)
+ h2_stream->http_method = HTTP_METHOD_GET;
+ else if(valuelen == 4 &&
+ strcasecmp("POST", (const char*)value) == 0) {
+ h2_stream->http_method = HTTP_METHOD_POST;
+ if(h2_stream->qbuffer) {
+ /* POST method uses query from DATA frames */
+ lock_basic_lock(&http2_query_buffer_count_lock);
+ http2_query_buffer_count -=
+ sldns_buffer_capacity(h2_stream->qbuffer);
+ lock_basic_unlock(&http2_query_buffer_count_lock);
+ sldns_buffer_free(h2_stream->qbuffer);
+ h2_stream->qbuffer = NULL;
+ }
+ } else
+ h2_stream->http_method = HTTP_METHOD_UNSUPPORTED;
+ return 0;
+ }
+ if(namelen == 5 && memcmp(":path", name, namelen) == 0) {
+ /* :path may contain DNS query, depending on method. Method might
+ * not be known yet here, so check after finishing receiving
+ * stream. */
+#define HTTP_QUERY_PARAM "?dns="
+ size_t el = strlen(h2_session->c->http_endpoint);
+ size_t qpl = strlen(HTTP_QUERY_PARAM);
+
+ if(valuelen < el || memcmp(h2_session->c->http_endpoint,
+ value, el) != 0) {
+ h2_stream->invalid_endpoint = 1;
+ return 0;
+ }
+ /* larger than endpoint only allowed if it is for the query
+ * parameter */
+ if(valuelen <= el+qpl ||
+ memcmp(HTTP_QUERY_PARAM, value+el, qpl) != 0) {
+ if(valuelen != el)
+ h2_stream->invalid_endpoint = 1;
+ return 0;
+ }
+
+ if(!http2_buffer_uri_query(h2_session, h2_stream,
+ value+(el+qpl), valuelen-(el+qpl))) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ return 0;
+ }
+ /* Content type is a SHOULD (rfc7231#section-3.1.1.5) when using POST,
+ * and not needed when using GET. Don't enfore.
+ * If set only allow lowercase "application/dns-message".
+ *
+ * Clients SHOULD (rfc8484#section-4.1) set an accept header, but MUST
+ * be able to handle "application/dns-message". Since that is the only
+ * content-type supported we can ignore the accept header.
+ */
+ if((namelen == 12 && memcmp("content-type", name, namelen) == 0)) {
+ if(valuelen != 23 || memcmp("application/dns-message", value,
+ valuelen) != 0) {
+ h2_stream->invalid_content_type = 1;
+ }
+ }
+
+ /* Only interested in content-lentg for POST (on not yet known) method.
+ */
+ if((!h2_stream->http_method ||
+ h2_stream->http_method == HTTP_METHOD_POST) &&
+ !h2_stream->content_length && namelen == 14 &&
+ memcmp("content-length", name, namelen) == 0) {
+ if(valuelen > 5) {
+ h2_stream->query_too_large = 1;
+ return 0;
+ }
+ /* guaranteed to only contian digits and be null terminated */
+ h2_stream->content_length = atoi((const char*)value);
+ if(h2_stream->content_length >
+ h2_session->c->http2_stream_max_qbuffer_size) {
+ h2_stream->query_too_large = 1;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/** nghttp2 callback. Used to get data from DATA frames, which can contain
+ * queries in POST requests. */
+static int http2_req_data_chunk_recv_cb(nghttp2_session* ATTR_UNUSED(session),
+ uint8_t ATTR_UNUSED(flags), int32_t stream_id, const uint8_t* data,
+ size_t len, void* cb_arg)
+{
+ struct http2_session* h2_session = (struct http2_session*)cb_arg;
+ struct http2_stream* h2_stream;
+ size_t qlen = 0;
+
+ if(!(h2_stream = nghttp2_session_get_stream_user_data(
+ h2_session->session, stream_id))) {
+ return 0;
+ }
+
+ if(h2_stream->query_too_large)
+ return 0;
+
+ if(!h2_stream->qbuffer) {
+ if(h2_stream->content_length) {
+ if(h2_stream->content_length < len)
+ /* getting more data in DATA frame than
+ * advertised in content-length header. */
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ qlen = h2_stream->content_length;
+ } else if(len <= h2_session->c->http2_stream_max_qbuffer_size) {
+ /* setting this to msg-buffer-size can result in a lot
+ * of memory consuption. Most queries should fit in a
+ * single DATA frame, and most POST queries will
+ * containt content-length which does not impose this
+ * limit. */
+ qlen = len;
+ }
+ }
+ if(!h2_stream->qbuffer && qlen) {
+ lock_basic_lock(&http2_query_buffer_count_lock);
+ if(http2_query_buffer_count + qlen > http2_query_buffer_max) {
+ lock_basic_unlock(&http2_query_buffer_count_lock);
+ verbose(VERB_ALGO, "reset HTTP2 stream, no space left, "
+ "in http2-query-buffer-size");
+ return http2_submit_rst_stream(h2_session, h2_stream);
+ }
+ http2_query_buffer_count += qlen;
+ lock_basic_unlock(&http2_query_buffer_count_lock);
+ if(!(h2_stream->qbuffer = sldns_buffer_new(qlen))) {
+ lock_basic_lock(&http2_query_buffer_count_lock);
+ http2_query_buffer_count -= qlen;
+ lock_basic_unlock(&http2_query_buffer_count_lock);
+ }
+ }
+
+ if(!h2_stream->qbuffer ||
+ sldns_buffer_remaining(h2_stream->qbuffer) < len) {
+ verbose(VERB_ALGO, "http2 data_chunck_recv failed. Not enough "
+ "buffer space for POST query. Can happen on multi "
+ "frame requests without content-length header");
+ h2_stream->query_too_large = 1;
+ return 0;
+ }
+
+ sldns_buffer_write(h2_stream->qbuffer, data, len);
+
+ return 0;
+}
+
+void http2_req_stream_clear(struct http2_stream* h2_stream)
+{
+ if(h2_stream->qbuffer) {
+ lock_basic_lock(&http2_query_buffer_count_lock);
+ http2_query_buffer_count -=
+ sldns_buffer_capacity(h2_stream->qbuffer);
+ lock_basic_unlock(&http2_query_buffer_count_lock);
+ sldns_buffer_free(h2_stream->qbuffer);
+ h2_stream->qbuffer = NULL;
+ }
+ if(h2_stream->rbuffer) {
+ lock_basic_lock(&http2_response_buffer_count_lock);
+ http2_response_buffer_count -=
+ sldns_buffer_capacity(h2_stream->rbuffer);
+ lock_basic_unlock(&http2_response_buffer_count_lock);
+ sldns_buffer_free(h2_stream->rbuffer);
+ h2_stream->rbuffer = NULL;
+ }
+}
+
+nghttp2_session_callbacks* http2_req_callbacks_create()
+{
+ nghttp2_session_callbacks *callbacks;
+ if(nghttp2_session_callbacks_new(&callbacks) == NGHTTP2_ERR_NOMEM) {
+ log_err("failed to initialize nghttp2 callback");
+ return NULL;
+ }
+ /* reception of header block started, used to create h2_stream */
+ nghttp2_session_callbacks_set_on_begin_headers_callback(callbacks,
+ http2_req_begin_headers_cb);
+ /* complete frame received, used to get data from stream if frame
+ * has end stream flag, and start processing query */
+ nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
+ http2_req_frame_recv_cb);
+ /* get request info from headers */
+ nghttp2_session_callbacks_set_on_header_callback(callbacks,
+ http2_req_header_cb);
+ /* get data from DATA frames, containing POST query */
+ nghttp2_session_callbacks_set_on_data_chunk_recv_callback(callbacks,
+ http2_req_data_chunk_recv_cb);
+
+ /* generic HTTP2 callbacks */
+ nghttp2_session_callbacks_set_recv_callback(callbacks, http2_recv_cb);
+ nghttp2_session_callbacks_set_send_callback(callbacks, http2_send_cb);
+ nghttp2_session_callbacks_set_on_stream_close_callback(callbacks,
+ http2_stream_close_cb);
+
+ return callbacks;
+}
+#endif /* HAVE_NGHTTP2 */
diff --git a/contrib/unbound/services/listen_dnsport.h b/contrib/unbound/services/listen_dnsport.h
index ddd1b63a4d95..4bbde0691fec 100644
--- a/contrib/unbound/services/listen_dnsport.h
+++ b/contrib/unbound/services/listen_dnsport.h
@@ -43,6 +43,9 @@
#define LISTEN_DNSPORT_H
#include "util/netevent.h"
+#ifdef HAVE_NGHTTP2_NGHTTP2_H
+#include <nghttp2/nghttp2.h>
+#endif
struct listen_list;
struct config_file;
struct addrinfo;
@@ -94,8 +97,9 @@ enum listen_type {
/** tcp type + dnscrypt */
listen_type_tcp_dnscrypt,
/** udp ipv6 (v4mapped) for use with ancillary data + dnscrypt*/
- listen_type_udpancil_dnscrypt
-
+ listen_type_udpancil_dnscrypt,
+ /** HTTP(2) over TLS over TCP */
+ listen_type_http
};
/**
@@ -117,13 +121,15 @@ struct listen_port {
* interfaces for IP4 and/or IP6, for UDP and/or TCP.
* On the given port number. It creates the sockets.
* @param cfg: settings on what ports to open.
+ * @param ifs: interfaces to open, array of IP addresses, "ip[@port]".
+ * @param num_ifs: length of ifs.
* @param reuseport: set to true if you want reuseport, or NULL to not have it,
* set to false on exit if reuseport failed to apply (because of no
* kernel support).
* @return: linked list of ports or NULL on error.
*/
struct listen_port* listening_ports_open(struct config_file* cfg,
- int* reuseport);
+ char** ifs, int num_ifs, int* reuseport);
/**
* Close and delete the (list of) listening ports.
@@ -131,6 +137,17 @@ struct listen_port* listening_ports_open(struct config_file* cfg,
void listening_ports_free(struct listen_port* list);
/**
+ * Resolve interface names in config and store result IP addresses
+ * @param cfg: config
+ * @param resif: string array (malloced array of malloced strings) with
+ * result. NULL if cfg has none.
+ * @param num_resif: length of resif. Zero if cfg has zero num_ifs.
+ * @return 0 on failure.
+ */
+int resolve_interface_names(struct config_file* cfg, char*** resif,
+ int* num_resif);
+
+/**
* Create commpoints with for this thread for the shared ports.
* @param base: the comm_base that provides event functionality.
* for default all ifs.
@@ -139,6 +156,9 @@ void listening_ports_free(struct listen_port* list);
* @param tcp_accept_count: max number of simultaneous TCP connections
* from clients.
* @param tcp_idle_timeout: idle timeout for TCP connections in msec.
+ * @param harden_large_queries: whether query size should be limited.
+ * @param http_max_streams: maximum number of HTTP/2 streams per connection.
+ * @param http_endpoint: HTTP endpoint to service queries on
* @param tcp_conn_limit: TCP connection limit info.
* @param sslctx: nonNULL if ssl context.
* @param dtenv: nonNULL if dnstap enabled.
@@ -147,11 +167,12 @@ void listening_ports_free(struct listen_port* list);
* @param cb_arg: user data argument for callback function.
* @return: the malloced listening structure, ready for use. NULL on error.
*/
-struct listen_dnsport* listen_create(struct comm_base* base,
- struct listen_port* ports, size_t bufsize,
- int tcp_accept_count, int tcp_idle_timeout,
- struct tcl_list* tcp_conn_limit, void* sslctx,
- struct dt_env *dtenv, comm_point_callback_type* cb, void* cb_arg);
+struct listen_dnsport*
+listen_create(struct comm_base* base, struct listen_port* ports,
+ size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
+ int harden_large_queries, uint32_t http_max_streams,
+ char* http_endpoint, struct tcl_list* tcp_conn_limit, void* sslctx,
+ struct dt_env* dtenv, comm_point_callback_type* cb, void *cb_arg);
/**
* delete the listening structure
@@ -221,13 +242,15 @@ 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 nodelay: if true set TCP_NODELAY and TCP_QUICKACK socket options.
* @param freebind: set IP_FREEBIND socket option.
* @param use_systemd: if true, fetch sockets from systemd.
* @param dscp: DSCP to use.
* @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 freebind, int use_systemd, int dscp);
+ int* reuseport, int transparent, int mss, int nodelay, int freebind,
+ int use_systemd, int dscp);
/**
* Create and bind local listening socket
@@ -369,7 +392,34 @@ int tcp_req_info_handle_read_close(struct tcp_req_info* req);
/** get the size of currently used tcp stream wait buffers (in bytes) */
size_t tcp_req_info_get_stream_buffer_size(void);
+/** get the size of currently used HTTP2 query buffers (in bytes) */
+size_t http2_get_query_buffer_size(void);
+/** get the size of currently used HTTP2 response buffers (in bytes) */
+size_t http2_get_response_buffer_size(void);
+
+#ifdef HAVE_NGHTTP2
+/**
+ * Create nghttp2 callbacks to handle HTTP2 requests.
+ * @return malloc'ed struct, NULL on failure
+ */
+nghttp2_session_callbacks* http2_req_callbacks_create();
+
+/** Free http2 stream buffers and decrease buffer counters */
+void http2_req_stream_clear(struct http2_stream* h2_stream);
+
+/**
+ * DNS response ready to be submitted to nghttp2, to be prepared for sending
+ * out. Response is stored in c->buffer. Copy to rbuffer because the c->buffer
+ * might be used before this will be send out.
+ * @param h2_session: http2 session, containing c->buffer which contains answer
+ * @param h2_stream: http2 stream, containing buffer to store answer in
+ * @return 0 on error, 1 otherwise
+ */
+int http2_submit_dns_response(struct http2_session* h2_session);
+#else
+int http2_submit_dns_response(void* v);
+#endif /* HAVE_NGHTTP2 */
+
char* set_ip_dscp(int socket, int addrfamily, int ds);
-char* sock_strerror(int errn);
#endif /* LISTEN_DNSPORT_H */
diff --git a/contrib/unbound/services/mesh.c b/contrib/unbound/services/mesh.c
index 4b0c5db418f7..52ff97e4a2e8 100644
--- a/contrib/unbound/services/mesh.c
+++ b/contrib/unbound/services/mesh.c
@@ -551,6 +551,9 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
goto servfail_mem;
}
}
+ if(rep->c->use_h2) {
+ http2_stream_add_meshstate(rep->c->h2_stream, mesh, s);
+ }
/* add serve expired timer if required and not already there */
if(timeout && !mesh_serve_expired_init(s, timeout)) {
log_err("mesh_new_client: out of memory initializing serve expired");
@@ -1207,6 +1210,13 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
else secure = 0;
if(!rep && rcode == LDNS_RCODE_NOERROR)
rcode = LDNS_RCODE_SERVFAIL;
+ if(r->query_reply.c->use_h2) {
+ r->query_reply.c->h2_stream = r->h2_stream;
+ /* Mesh reply won't exist for long anymore. Make it impossible
+ * for HTTP/2 stream to refer to mesh state, in case
+ * connection gets cleanup before HTTP/2 stream close. */
+ r->h2_stream->mesh_state = NULL;
+ }
/* send the reply */
/* We don't reuse the encoded answer if either the previous or current
* response has a local alias. We could compare the alias records
@@ -1495,6 +1505,8 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
s->s.qinfo.qname_len);
if(!r->qname)
return 0;
+ if(rep->c->use_h2)
+ r->h2_stream = rep->c->h2_stream;
/* Data related to local alias stored in 'qinfo' (if any) is ephemeral
* and can be different for different original queries (even if the
diff --git a/contrib/unbound/services/mesh.h b/contrib/unbound/services/mesh.h
index df2972ac3306..d0a4b5fb3d0d 100644
--- a/contrib/unbound/services/mesh.h
+++ b/contrib/unbound/services/mesh.h
@@ -230,6 +230,8 @@ struct mesh_reply {
uint8_t* qname;
/** same as that in query_info. */
struct local_rrset* local_alias;
+ /** send query to this http2 stream, if set */
+ struct http2_stream* h2_stream;
};
/**
diff --git a/contrib/unbound/services/outside_network.c b/contrib/unbound/services/outside_network.c
index 44e01d7450cb..41a1d83f1454 100644
--- a/contrib/unbound/services/outside_network.c
+++ b/contrib/unbound/services/outside_network.c
@@ -58,6 +58,7 @@
#include "util/net_help.h"
#include "util/random.h"
#include "util/fptr_wlist.h"
+#include "util/edns.h"
#include "sldns/sbuffer.h"
#include "dnstap/dnstap.h"
#ifdef HAVE_OPENSSL_SSL_H
@@ -165,11 +166,7 @@ pick_outgoing_tcp(struct waiting_tcp* w, int s)
if(num == 0) {
log_err("no TCP outgoing interfaces of family");
log_addr(VERB_OPS, "for addr", &w->addr, w->addrlen);
-#ifndef USE_WINSOCK
- close(s);
-#else
- closesocket(s);
-#endif
+ sock_close(s);
return 0;
}
#ifdef INET6
@@ -188,14 +185,8 @@ pick_outgoing_tcp(struct waiting_tcp* w, int s)
((struct sockaddr_in6*)&pi->addr)->sin6_port = 0;
else ((struct sockaddr_in*)&pi->addr)->sin_port = 0;
if(bind(s, (struct sockaddr*)&pi->addr, pi->addrlen) != 0) {
-#ifndef USE_WINSOCK
- log_err("outgoing tcp: bind: %s", strerror(errno));
- close(s);
-#else
- log_err("outgoing tcp: bind: %s",
- wsa_strerror(WSAGetLastError()));
- closesocket(s);
-#endif
+ log_err("outgoing tcp: bind: %s", sock_strerror(errno));
+ sock_close(s);
return 0;
}
log_addr(VERB_ALGO, "tcp bound to src", &pi->addr, pi->addrlen);
@@ -225,13 +216,8 @@ outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss,
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
}
if(s == -1) {
-#ifndef USE_WINSOCK
- log_err_addr("outgoing tcp: socket", strerror(errno),
+ log_err_addr("outgoing tcp: socket", sock_strerror(errno),
addr, addrlen);
-#else
- log_err_addr("outgoing tcp: socket",
- wsa_strerror(WSAGetLastError()), addr, addrlen);
-#endif
return -1;
}
@@ -2111,9 +2097,20 @@ outnet_serviced_query(struct outside_network* outnet,
{
struct serviced_query* sq;
struct service_callback* cb;
+ struct edns_tag_addr* client_tag_addr;
+
if(!inplace_cb_query_call(env, qinfo, flags, addr, addrlen, zone, zonelen,
qstate, qstate->region))
return NULL;
+
+ if((client_tag_addr = edns_tag_addr_lookup(&env->edns_tags->client_tags,
+ addr, addrlen))) {
+ uint16_t client_tag = htons(client_tag_addr->tag_data);
+ edns_opt_list_append(&qstate->edns_opts_back_out,
+ env->edns_tags->client_tag_opcode, 2,
+ (uint8_t*)&client_tag, qstate->region);
+ }
+
serviced_gen_query(buff, qinfo->qname, qinfo->qname_len, qinfo->qtype,
qinfo->qclass, flags);
sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen,
diff --git a/contrib/unbound/services/rpz.c b/contrib/unbound/services/rpz.c
index 105f238d0a6d..ba5dd186daad 100644
--- a/contrib/unbound/services/rpz.c
+++ b/contrib/unbound/services/rpz.c
@@ -597,8 +597,18 @@ rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
uint8_t* policydname;
if(!dname_subdomain_c(dname, azname)) {
- log_err("RPZ: name of record to insert into RPZ is not a "
- "subdomain of the configured name of the RPZ zone");
+ char* dname_str = sldns_wire2str_dname(dname, dnamelen);
+ char* azname_str = sldns_wire2str_dname(azname, aznamelen);
+ if(dname_str && azname_str) {
+ log_err("RPZ: name of record (%s) to insert into RPZ is not a "
+ "subdomain of the configured name of the RPZ zone (%s)",
+ dname_str, azname_str);
+ } else {
+ log_err("RPZ: name of record to insert into RPZ is not a "
+ "subdomain of the configured name of the RPZ zone");
+ }
+ free(dname_str);
+ free(azname_str);
return 0;
}
diff --git a/contrib/unbound/sldns/parseutil.c b/contrib/unbound/sldns/parseutil.c
index 3515d64c5d10..9f289d3596c3 100644
--- a/contrib/unbound/sldns/parseutil.c
+++ b/contrib/unbound/sldns/parseutil.c
@@ -619,13 +619,18 @@ size_t sldns_b64_ntop_calculate_size(size_t srcsize)
*
* This routine does not insert spaces or linebreaks after 76 characters.
*/
-int sldns_b64_ntop(uint8_t const *src, size_t srclength,
- char *target, size_t targsize)
+static int sldns_b64_ntop_base(uint8_t const *src, size_t srclength,
+ char *target, size_t targsize, int base64url, int padding)
{
- const char* b64 =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ char* b64;
const char pad64 = '=';
size_t i = 0, o = 0;
+ if(base64url)
+ b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123"
+ "456789-_";
+ else
+ b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123"
+ "456789+/";
if(targsize < sldns_b64_ntop_calculate_size(srclength))
return -1;
/* whole chunks: xxxxxxyy yyyyzzzz zzwwwwww */
@@ -645,18 +650,26 @@ int sldns_b64_ntop(uint8_t const *src, size_t srclength,
target[o] = b64[src[i] >> 2];
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; */
- o += 4;
+ if(padding) {
+ target[o+3] = pad64;
+ /* i += 2; */
+ o += 4;
+ } else {
+ o += 3;
+ }
break;
case 1:
/* one at end, converted into A B = = */
target[o] = b64[src[i] >> 2];
target[o+1] = b64[ ((src[i]&0x03)<<4) ];
- target[o+2] = pad64;
- target[o+3] = pad64;
- /* i += 1; */
- o += 4;
+ if(padding) {
+ target[o+2] = pad64;
+ target[o+3] = pad64;
+ /* i += 1; */
+ o += 4;
+ } else {
+ o += 2;
+ }
break;
case 0:
default:
@@ -669,19 +682,36 @@ int sldns_b64_ntop(uint8_t const *src, size_t srclength,
return (int)o;
}
+int sldns_b64_ntop(uint8_t const *src, size_t srclength, char *target,
+ size_t targsize)
+{
+ return sldns_b64_ntop_base(src, srclength, target, targsize,
+ 0 /* no base64url */, 1 /* padding */);
+}
+
+int sldns_b64url_ntop(uint8_t const *src, size_t srclength, char *target,
+ size_t targsize)
+{
+ return sldns_b64_ntop_base(src, srclength, target, targsize,
+ 1 /* base64url */, 0 /* no padding */);
+}
+
size_t sldns_b64_pton_calculate_size(size_t srcsize)
{
return (((((srcsize + 3) / 4) * 3)) + 1);
}
-int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
+/* padding not required if srcsize is set */
+static int sldns_b64_pton_base(char const *src, size_t srcsize, uint8_t *target,
+ size_t targsize, int base64url)
{
const uint8_t pad64 = 64; /* is 64th in the b64 array */
const char* s = src;
uint8_t in[4];
size_t o = 0, incount = 0;
+ int check_padding = (srcsize) ? 0 : 1;
- while(*s) {
+ while(*s && (check_padding || srcsize)) {
/* skip any character that is not base64 */
/* conceptually we do:
const char* b64 = pad'=' is appended to array
@@ -690,30 +720,43 @@ int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
and use d-b64;
*/
char d = *s++;
+ srcsize--;
if(d <= 'Z' && d >= 'A')
d -= 'A';
else if(d <= 'z' && d >= 'a')
d = d - 'a' + 26;
else if(d <= '9' && d >= '0')
d = d - '0' + 52;
- else if(d == '+')
+ else if(!base64url && d == '+')
d = 62;
- else if(d == '/')
+ else if(base64url && d == '-')
+ d = 62;
+ else if(!base64url && d == '/')
+ d = 63;
+ else if(base64url && d == '_')
d = 63;
- else if(d == '=')
+ else if(d == '=') {
+ if(!check_padding)
+ continue;
d = 64;
- else continue;
+ } else continue;
+
in[incount++] = (uint8_t)d;
- if(incount != 4)
+ /* work on block of 4, unless padding is not used and there are
+ * less than 4 chars left */
+ if(incount != 4 && (check_padding || srcsize))
continue;
+ assert(!check_padding || incount==4);
/* process whole block of 4 characters into 3 output bytes */
- if(in[3] == pad64 && in[2] == pad64) { /* A B = = */
+ if((incount == 2 ||
+ (incount == 4 && in[3] == pad64 && in[2] == pad64))) { /* A B = = */
if(o+1 > targsize)
return -1;
target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
o += 1;
break; /* we are done */
- } else if(in[3] == pad64) { /* A B C = */
+ } else if(incount == 3 ||
+ (incount == 4 && in[3] == pad64)) { /* A B C = */
if(o+2 > targsize)
return -1;
target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
@@ -721,7 +764,7 @@ int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
o += 2;
break; /* we are done */
} else {
- if(o+3 > targsize)
+ if(incount != 4 || o+3 > targsize)
return -1;
/* write xxxxxxyy yyyyzzzz zzwwwwww */
target[o] = (in[0]<<2) | ((in[1]&0x30)>>4);
@@ -733,3 +776,17 @@ int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
}
return (int)o;
}
+
+int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize)
+{
+ return sldns_b64_pton_base(src, 0, target, targsize, 0);
+}
+
+int sldns_b64url_pton(char const *src, size_t srcsize, uint8_t *target,
+ size_t targsize)
+{
+ if(!srcsize) {
+ return 0;
+ }
+ return sldns_b64_pton_base(src, srcsize, target, targsize, 1);
+}
diff --git a/contrib/unbound/sldns/parseutil.h b/contrib/unbound/sldns/parseutil.h
index 10a2630a9733..7eb23317f285 100644
--- a/contrib/unbound/sldns/parseutil.h
+++ b/contrib/unbound/sldns/parseutil.h
@@ -92,13 +92,16 @@ size_t sldns_b64_ntop_calculate_size(size_t srcsize);
int sldns_b64_ntop(uint8_t const *src, size_t srclength,
char *target, size_t targsize);
+int sldns_b64url_ntop(uint8_t const *src, size_t srclength, char *target,
+ size_t targsize);
/**
* calculates the size needed to store the result of sldns_b64_pton
*/
size_t sldns_b64_pton_calculate_size(size_t srcsize);
-
int sldns_b64_pton(char const *src, uint8_t *target, size_t targsize);
+int sldns_b64url_pton(char const *src, size_t srcsize, uint8_t *target,
+ size_t targsize);
/**
* calculates the size needed to store the result of b32_ntop
diff --git a/contrib/unbound/sldns/rrdef.h b/contrib/unbound/sldns/rrdef.h
index 4e7fef5745f2..e084f354a8a1 100644
--- a/contrib/unbound/sldns/rrdef.h
+++ b/contrib/unbound/sldns/rrdef.h
@@ -426,7 +426,8 @@ enum sldns_enum_edns_option
LDNS_EDNS_N3U = 7, /* RFC6975 */
LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */
LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/
- LDNS_EDNS_PADDING = 12 /* RFC7830 */
+ LDNS_EDNS_PADDING = 12, /* RFC7830 */
+ LDNS_EDNS_CLIENT_TAG = 16 /* draft-bellis-dnsop-edns-tags-01 */
};
typedef enum sldns_enum_edns_option sldns_edns_option;
diff --git a/contrib/unbound/smallapp/unbound-checkconf.c b/contrib/unbound/smallapp/unbound-checkconf.c
index eddd406a8067..e4c0ea8c7e7a 100644
--- a/contrib/unbound/smallapp/unbound-checkconf.c
+++ b/contrib/unbound/smallapp/unbound-checkconf.c
@@ -624,8 +624,6 @@ morechecks(struct config_file* cfg)
cfg->auto_trust_anchor_file_list, cfg->chrootdir, cfg);
check_chroot_filelist_wild("trusted-keys-file",
cfg->trusted_keys_file_list, cfg->chrootdir, cfg);
- check_chroot_string("dlv-anchor-file", &cfg->dlv_anchor_file,
- cfg->chrootdir, cfg);
#ifdef USE_IPSECMOD
if(cfg->ipsecmod_enabled && strstr(cfg->module_conf, "ipsecmod")) {
/* only check hook if enabled */
diff --git a/contrib/unbound/smallapp/unbound-control.c b/contrib/unbound/smallapp/unbound-control.c
index ce5f0e04d4c5..3fe6068be560 100644
--- a/contrib/unbound/smallapp/unbound-control.c
+++ b/contrib/unbound/smallapp/unbound-control.c
@@ -278,6 +278,8 @@ static void print_mem(struct ub_shm_stat_info* shm_stat,
shm_stat->mem.dnscrypt_nonce);
#endif
PR_LL("mem.streamwait", s->svr.mem_stream_wait);
+ PR_LL("mem.http.query_buffer", s->svr.mem_http2_query_buffer);
+ PR_LL("mem.http.response_buffer", s->svr.mem_http2_response_buffer);
}
/** print histogram */
@@ -342,6 +344,7 @@ static void print_extended(struct ub_stats_info* s)
PR_UL("num.query.tls", s->svr.qtls);
PR_UL("num.query.tls_resume", s->svr.qtls_resume);
PR_UL("num.query.ipv6", s->svr.qipv6);
+ PR_UL("num.query.https", s->svr.qhttps);
/* flags */
PR_UL("num.query.flags.QR", s->svr.qbit_QR);
@@ -593,11 +596,7 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
addrfamily = addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET;
fd = socket(addrfamily, SOCK_STREAM, proto);
if(fd == -1) {
-#ifndef USE_WINSOCK
- fatal_exit("socket: %s", strerror(errno));
-#else
- fatal_exit("socket: %s", wsa_strerror(WSAGetLastError()));
-#endif
+ fatal_exit("socket: %s", sock_strerror(errno));
}
if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
#ifndef USE_WINSOCK
@@ -681,11 +680,7 @@ remote_read(SSL* ssl, int fd, char* buf, size_t len)
/* EOF */
return 0;
}
-#ifndef USE_WINSOCK
- fatal_exit("could not recv: %s", strerror(errno));
-#else
- fatal_exit("could not recv: %s", wsa_strerror(WSAGetLastError()));
-#endif
+ fatal_exit("could not recv: %s", sock_strerror(errno));
}
buf[rr] = 0;
}
@@ -701,11 +696,7 @@ remote_write(SSL* ssl, int fd, const char* buf, size_t len)
ssl_err("could not SSL_write");
} else {
if(send(fd, buf, len, 0) < (ssize_t)len) {
-#ifndef USE_WINSOCK
- fatal_exit("could not send: %s", strerror(errno));
-#else
- fatal_exit("could not send: %s", wsa_strerror(WSAGetLastError()));
-#endif
+ fatal_exit("could not send: %s", sock_strerror(errno));
}
}
}
@@ -824,11 +815,7 @@ go(const char* cfgfile, char* svr, int quiet, int argc, char* argv[])
ret = go_cmd(ssl, fd, quiet, argc, argv);
if(ssl) SSL_free(ssl);
-#ifndef USE_WINSOCK
- close(fd);
-#else
- closesocket(fd);
-#endif
+ sock_close(fd);
if(ctx) SSL_CTX_free(ctx);
config_delete(cfg);
return ret;
@@ -886,7 +873,7 @@ int main(int argc, char* argv[])
if(argc == 0)
usage();
if(argc >= 1 && strcmp(argv[0], "start")==0) {
-#if defined(TARGET_OS_TV) || defined(TARGET_OS_WATCH)
+#if (defined(TARGET_OS_TV) && TARGET_OS_TV) || (defined(TARGET_OS_WATCH) && TARGET_OS_WATCH)
fatal_exit("could not exec unbound: %s",
strerror(ENOSYS));
#else
diff --git a/contrib/unbound/util/config_file.c b/contrib/unbound/util/config_file.c
index f0d600617eef..acc0d1804c83 100644
--- a/contrib/unbound/util/config_file.c
+++ b/contrib/unbound/util/config_file.c
@@ -78,6 +78,8 @@ gid_t cfg_gid = (gid_t)-1;
int autr_permit_small_holddown = 0;
/** size (in bytes) of stream wait buffers max */
size_t stream_wait_max = 4 * 1024 * 1024;
+size_t http2_query_buffer_max = 4 * 1024 * 1024;
+size_t http2_response_buffer_max = 4 * 1024 * 1024;
/** global config during parsing */
struct config_parser_state* cfg_parser = 0;
@@ -117,6 +119,12 @@ config_create(void)
cfg->tls_cert_bundle = NULL;
cfg->tls_win_cert = 0;
cfg->tls_use_sni = 1;
+ cfg->https_port = UNBOUND_DNS_OVER_HTTPS_PORT;
+ if(!(cfg->http_endpoint = strdup("/dns-query"))) goto error_exit;
+ cfg->http_max_streams = 100;
+ cfg->http_query_buffer_size = 4*1024*1024;
+ cfg->http_response_buffer_size = 4*1024*1024;
+ cfg->http_nodelay = 1;
cfg->use_syslog = 1;
cfg->log_identity = NULL; /* changed later with argv[0] */
cfg->log_time_ascii = 0;
@@ -144,7 +152,7 @@ config_create(void)
cfg->incoming_num_tcp = 2;
#endif
cfg->stream_wait_size = 4 * 1024 * 1024;
- cfg->edns_buffer_size = 4096; /* 4k from rfc recommendation */
+ cfg->edns_buffer_size = 1232; /* from DNS flagday recommendation */
cfg->msg_buffer_size = 65552; /* 64 k + a small margin */
cfg->msg_cache_size = 4 * 1024 * 1024;
cfg->msg_cache_slabs = 4;
@@ -233,8 +241,6 @@ config_create(void)
cfg->trusted_keys_file_list = NULL;
cfg->trust_anchor_signaling = 1;
cfg->root_key_sentinel = 1;
- cfg->dlv_anchor_file = NULL;
- cfg->dlv_anchor_list = NULL;
cfg->domain_insecure = NULL;
cfg->val_date_override = 0;
cfg->val_sig_skew_min = 3600; /* at least daylight savings trouble */
@@ -315,6 +321,8 @@ config_create(void)
cfg->qname_minimisation_strict = 0;
cfg->shm_enable = 0;
cfg->shm_key = 11777;
+ cfg->edns_client_tags = NULL;
+ cfg->edns_client_tag_opcode = LDNS_EDNS_CLIENT_TAG;
cfg->dnscrypt = 0;
cfg->dnscrypt_port = 0;
cfg->dnscrypt_provider = NULL;
@@ -490,6 +498,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("do-ip6:", do_ip6)
else S_YNO("do-udp:", do_udp)
else S_YNO("do-tcp:", do_tcp)
+ else S_YNO("prefer-ip4:", prefer_ip4)
+ else S_YNO("prefer-ip6:", prefer_ip6)
else S_YNO("tcp-upstream:", tcp_upstream)
else S_YNO("udp-upstream-without-downstream:",
udp_upstream_without_downstream)
@@ -511,6 +521,12 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("tls-ciphers:", tls_ciphers)
else S_STR("tls-ciphersuites:", tls_ciphersuites)
else S_YNO("tls-use-sni:", tls_use_sni)
+ else S_NUMBER_NONZERO("https-port:", https_port)
+ else S_STR("http-endpoint", http_endpoint)
+ else S_NUMBER_NONZERO("http-max-streams", http_max_streams)
+ else S_MEMSIZE("http-query-buffer-size", http_query_buffer_size)
+ else S_MEMSIZE("http-response-buffer-size", http_response_buffer_size)
+ else S_YNO("http-nodelay", http_nodelay)
else S_YNO("interface-automatic:", if_automatic)
else S_YNO("use-systemd:", use_systemd)
else S_YNO("do-daemonize:", do_daemonize)
@@ -581,8 +597,6 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STRLIST("trusted-keys-file:", trusted_keys_file_list)
else S_YNO("trust-anchor-signaling:", trust_anchor_signaling)
else S_YNO("root-key-sentinel:", root_key_sentinel)
- else S_STR("dlv-anchor-file:", dlv_anchor_file)
- else S_STRLIST("dlv-anchor:", dlv_anchor_list)
else S_STRLIST("domain-insecure:", domain_insecure)
else S_NUMBER_OR_ZERO("val-bogus-ttl:", bogus_ttl)
else S_YNO("val-clean-additional:", val_clean_additional)
@@ -950,6 +964,8 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "do-ip6", do_ip6)
else O_YNO(opt, "do-udp", do_udp)
else O_YNO(opt, "do-tcp", do_tcp)
+ else O_YNO(opt, "prefer-ip4", prefer_ip4)
+ else O_YNO(opt, "prefer-ip6", prefer_ip6)
else O_YNO(opt, "tcp-upstream", tcp_upstream)
else O_YNO(opt, "udp-upstream-without-downstream", udp_upstream_without_downstream)
else O_DEC(opt, "tcp-mss", tcp_mss)
@@ -968,6 +984,12 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_STR(opt, "tls-ciphers", tls_ciphers)
else O_STR(opt, "tls-ciphersuites", tls_ciphersuites)
else O_YNO(opt, "tls-use-sni", tls_use_sni)
+ else O_DEC(opt, "https-port", https_port)
+ else O_STR(opt, "http-endpoint", http_endpoint)
+ else O_UNS(opt, "http-max-streams", http_max_streams)
+ else O_MEM(opt, "http-query-buffer-size", http_query_buffer_size)
+ else O_MEM(opt, "http-response-buffer-size", http_response_buffer_size)
+ else O_YNO(opt, "http-nodelay", http_nodelay)
else O_YNO(opt, "use-systemd", use_systemd)
else O_YNO(opt, "do-daemonize", do_daemonize)
else O_STR(opt, "chroot", chrootdir)
@@ -998,7 +1020,6 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_DEC(opt, "unwanted-reply-threshold", unwanted_threshold)
else O_YNO(opt, "do-not-query-localhost", donotquery_localhost)
else O_STR(opt, "module-config", module_conf)
- else O_STR(opt, "dlv-anchor-file", dlv_anchor_file)
else O_DEC(opt, "val-bogus-ttl", bogus_ttl)
else O_YNO(opt, "val-clean-additional", val_clean_additional)
else O_DEC(opt, "val-log-level", val_log_level)
@@ -1036,7 +1057,6 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_LST(opt, "trusted-keys-file", trusted_keys_file_list)
else O_YNO(opt, "trust-anchor-signaling", trust_anchor_signaling)
else O_YNO(opt, "root-key-sentinel", root_key_sentinel)
- else O_LST(opt, "dlv-anchor", dlv_anchor_list)
else O_LST(opt, "control-interface", control_ifs.first)
else O_LST(opt, "domain-insecure", domain_insecure)
else O_UNS(opt, "val-override-date", val_date_override)
@@ -1130,6 +1150,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_LS3(opt, "access-control-tag-action", acl_tag_actions)
else O_LS3(opt, "access-control-tag-data", acl_tag_datas)
else O_LS2(opt, "access-control-view", acl_view)
+ else O_LS2(opt, "edns-client-tags", edns_client_tags)
#ifdef USE_IPSECMOD
else O_YNO(opt, "ipsecmod-enabled", ipsecmod_enabled)
else O_YNO(opt, "ipsecmod-ignore-bogus", ipsecmod_ignore_bogus)
@@ -1391,8 +1412,8 @@ config_delviews(struct config_view* p)
p = np;
}
}
-/** delete string array */
-static void
+
+void
config_del_strarray(char** array, int num)
{
int i;
@@ -1434,6 +1455,7 @@ config_delete(struct config_file* cfg)
config_delstrlist(cfg->tls_session_ticket_keys.first);
free(cfg->tls_ciphers);
free(cfg->tls_ciphersuites);
+ free(cfg->http_endpoint);
if(cfg->log_identity) {
log_ident_revert_to_default();
free(cfg->log_identity);
@@ -1462,8 +1484,6 @@ config_delete(struct config_file* cfg)
config_delstrlist(cfg->trusted_keys_file_list);
config_delstrlist(cfg->trust_anchor_list);
config_delstrlist(cfg->domain_insecure);
- free(cfg->dlv_anchor_file);
- config_delstrlist(cfg->dlv_anchor_list);
config_deldblstrlist(cfg->acls);
config_deldblstrlist(cfg->tcp_connection_limits);
free(cfg->val_nsec3_key_iterations);
@@ -1499,6 +1519,7 @@ config_delete(struct config_file* cfg)
config_deldblstrlist(cfg->ratelimit_below_domain);
config_delstrlist(cfg->python_script);
config_delstrlist(cfg->dynlib_file);
+ config_deldblstrlist(cfg->edns_client_tags);
#ifdef USE_IPSECMOD
free(cfg->ipsecmod_hook);
config_delstrlist(cfg->ipsecmod_whitelist);
@@ -2043,6 +2064,8 @@ config_apply(struct config_file* config)
log_set_time_asc(config->log_time_ascii);
autr_permit_small_holddown = config->permit_small_holddown;
stream_wait_max = config->stream_wait_size;
+ http2_query_buffer_max = config->http_query_buffer_size;
+ http2_response_buffer_max = config->http_response_buffer_size;
}
void config_lookup_uid(struct config_file* cfg)
diff --git a/contrib/unbound/util/config_file.h b/contrib/unbound/util/config_file.h
index 66e5025d05b2..7750eaa0e6b0 100644
--- a/contrib/unbound/util/config_file.h
+++ b/contrib/unbound/util/config_file.h
@@ -131,6 +131,19 @@ struct config_file {
/** if SNI is to be used */
int tls_use_sni;
+ /** port on which to provide DNS over HTTPS service */
+ int https_port;
+ /** endpoint for HTTP service */
+ char* http_endpoint;
+ /** MAX_CONCURRENT_STREAMS HTTP/2 setting */
+ uint32_t http_max_streams;
+ /** maximum size of all HTTP2 query buffers combined. */
+ size_t http_query_buffer_size;
+ /** maximum size of all HTTP2 response buffers combined. */
+ size_t http_response_buffer_size;
+ /** set TCP_NODELAY option for http sockets */
+ int http_nodelay;
+
/** outgoing port range number of ports (per thread) */
int outgoing_num_ports;
/** number of outgoing tcp buffers per (per thread) */
@@ -331,10 +344,6 @@ struct config_file {
struct config_strlist* auto_trust_anchor_file_list;
/** files with trusted DNSKEYs in named.conf format, list */
struct config_strlist* trusted_keys_file_list;
- /** DLV anchor file */
- char* dlv_anchor_file;
- /** DLV anchor inline */
- struct config_strlist* dlv_anchor_list;
/** insecure domain list */
struct config_strlist* domain_insecure;
/** send key tag query */
@@ -553,6 +562,11 @@ struct config_file {
/** SHM data - key for the shm */
int shm_key;
+ /** list of EDNS client tag entries, linked list */
+ struct config_str2list* edns_client_tags;
+ /** EDNS opcode to use for EDNS client tags */
+ uint16_t edns_client_tag_opcode;
+
/** DNSCrypt */
/** true to enable dnscrypt */
int dnscrypt;
@@ -625,6 +639,10 @@ extern gid_t cfg_gid;
extern int autr_permit_small_holddown;
/** size (in bytes) of stream wait buffers max */
extern size_t stream_wait_max;
+/** size (in bytes) of all total HTTP2 query buffers max */
+extern size_t http2_query_buffer_max;
+/** size (in bytes) of all total HTTP2 response buffers max */
+extern size_t http2_response_buffer_max;
/**
* Stub config options
@@ -970,6 +988,9 @@ void config_deldblstrlist(struct config_str2list* list);
*/
void config_deltrplstrlist(struct config_str3list* list);
+/** delete string array */
+void config_del_strarray(char** array, int num);
+
/** delete stringbytelist */
void config_del_strbytelist(struct config_strbytelist* list);
diff --git a/contrib/unbound/util/configlexer.lex b/contrib/unbound/util/configlexer.lex
index f548e7324f34..8bf18b03bef9 100644
--- a/contrib/unbound/util/configlexer.lex
+++ b/contrib/unbound/util/configlexer.lex
@@ -257,6 +257,12 @@ tls-session-ticket-keys{COLON} { YDVAR(1, VAR_TLS_SESSION_TICKET_KEYS) }
tls-ciphers{COLON} { YDVAR(1, VAR_TLS_CIPHERS) }
tls-ciphersuites{COLON} { YDVAR(1, VAR_TLS_CIPHERSUITES) }
tls-use-sni{COLON} { YDVAR(1, VAR_TLS_USE_SNI) }
+https-port{COLON} { YDVAR(1, VAR_HTTPS_PORT) }
+http-endpoint{COLON} { YDVAR(1, VAR_HTTP_ENDPOINT) }
+http-max-streams{COLON} { YDVAR(1, VAR_HTTP_MAX_STREAMS) }
+http-query-buffer-size{COLON} { YDVAR(1, VAR_HTTP_QUERY_BUFFER_SIZE) }
+http-response-buffer-size{COLON} { YDVAR(1, VAR_HTTP_RESPONSE_BUFFER_SIZE) }
+http-nodelay{COLON} { YDVAR(1, VAR_HTTP_NODELAY) }
use-systemd{COLON} { YDVAR(1, VAR_USE_SYSTEMD) }
do-daemonize{COLON} { YDVAR(1, VAR_DO_DAEMONIZE) }
interface{COLON} { YDVAR(1, VAR_INTERFACE) }
@@ -304,6 +310,7 @@ harden-referral-path{COLON} { YDVAR(1, VAR_HARDEN_REFERRAL_PATH) }
harden-algo-downgrade{COLON} { YDVAR(1, VAR_HARDEN_ALGO_DOWNGRADE) }
use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
+caps-exempt{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
private-address{COLON} { YDVAR(1, VAR_PRIVATE_ADDRESS) }
private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) }
@@ -335,6 +342,7 @@ rpz-log{COLON} { YDVAR(1, VAR_RPZ_LOG) }
rpz-log-name{COLON} { YDVAR(1, VAR_RPZ_LOG_NAME) }
zonefile{COLON} { YDVAR(1, VAR_ZONEFILE) }
master{COLON} { YDVAR(1, VAR_MASTER) }
+primary{COLON} { YDVAR(1, VAR_MASTER) }
url{COLON} { YDVAR(1, VAR_URL) }
allow-notify{COLON} { YDVAR(1, VAR_ALLOW_NOTIFY) }
for-downstream{COLON} { YDVAR(1, VAR_FOR_DOWNSTREAM) }
@@ -505,6 +513,7 @@ ipsecmod-ignore-bogus{COLON} { YDVAR(1, VAR_IPSECMOD_IGNORE_BOGUS) }
ipsecmod-hook{COLON} { YDVAR(1, VAR_IPSECMOD_HOOK) }
ipsecmod-max-ttl{COLON} { YDVAR(1, VAR_IPSECMOD_MAX_TTL) }
ipsecmod-whitelist{COLON} { YDVAR(1, VAR_IPSECMOD_WHITELIST) }
+ipsecmod-allow{COLON} { YDVAR(1, VAR_IPSECMOD_WHITELIST) }
ipsecmod-strict{COLON} { YDVAR(1, VAR_IPSECMOD_STRICT) }
cachedb{COLON} { YDVAR(0, VAR_CACHEDB) }
backend{COLON} { YDVAR(1, VAR_CACHEDB_BACKEND) }
@@ -518,6 +527,8 @@ name-v4{COLON} { YDVAR(1, VAR_IPSET_NAME_V4) }
name-v6{COLON} { YDVAR(1, VAR_IPSET_NAME_V6) }
udp-upstream-without-downstream{COLON} { YDVAR(1, VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM) }
tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) }
+edns-client-tag{COLON} { YDVAR(2, VAR_EDNS_CLIENT_TAG) }
+edns-client-tag-opcode{COLON} { YDVAR(1, VAR_EDNS_CLIENT_TAG_OPCODE) }
<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
/* Quoted strings. Strip leading and ending quotes */
diff --git a/contrib/unbound/util/configparser.y b/contrib/unbound/util/configparser.y
index fe600a999d45..43a886f2403a 100644
--- a/contrib/unbound/util/configparser.y
+++ b/contrib/unbound/util/configparser.y
@@ -112,6 +112,9 @@ extern struct config_parser_state* cfg_parser;
%token VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM
%token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST
%token VAR_STUB_SSL_UPSTREAM VAR_FORWARD_SSL_UPSTREAM VAR_TLS_CERT_BUNDLE
+%token VAR_HTTPS_PORT VAR_HTTP_ENDPOINT VAR_HTTP_MAX_STREAMS
+%token VAR_HTTP_QUERY_BUFFER_SIZE VAR_HTTP_RESPONSE_BUFFER_SIZE
+%token VAR_HTTP_NODELAY
%token VAR_STUB_FIRST VAR_MINIMAL_RESPONSES VAR_RRSET_ROUNDROBIN
%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE
%token VAR_UNBLOCK_LAN_ZONES VAR_INSECURE_LAN_ZONES
@@ -175,7 +178,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_IPSET VAR_IPSET_NAME_V4 VAR_IPSET_NAME_V6
%token VAR_TLS_SESSION_TICKET_KEYS VAR_RPZ VAR_TAGS VAR_RPZ_ACTION_OVERRIDE
%token VAR_RPZ_CNAME_OVERRIDE VAR_RPZ_LOG VAR_RPZ_LOG_NAME
-%token VAR_DYNLIB VAR_DYNLIB_FILE
+%token VAR_DYNLIB VAR_DYNLIB_FILE VAR_EDNS_CLIENT_TAG VAR_EDNS_CLIENT_TAG_OPCODE
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -244,6 +247,9 @@ content_server: server_num_threads | server_verbosity | server_port |
server_log_queries | server_log_replies | server_tcp_upstream | server_ssl_upstream |
server_log_local_actions |
server_ssl_service_key | server_ssl_service_pem | server_ssl_port |
+ server_https_port | server_http_endpoint | server_http_max_streams |
+ server_http_query_buffer_size | server_http_response_buffer_size |
+ server_http_nodelay |
server_minimal_responses | server_rrset_roundrobin | server_max_udp_size |
server_so_reuseport | server_delay_close |
server_unblock_lan_zones | server_insecure_lan_zones |
@@ -285,7 +291,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_unknown_server_time_limit | server_log_tag_queryreply |
server_stream_wait_size | server_tls_ciphers |
server_tls_ciphersuites | server_tls_session_ticket_keys |
- server_tls_use_sni
+ server_tls_use_sni | server_edns_client_tag |
+ server_edns_client_tag_opcode
;
stubstart: VAR_STUB_ZONE
{
@@ -969,6 +976,61 @@ server_tls_use_sni: VAR_TLS_USE_SNI STRING_ARG
free($2);
}
;
+server_https_port: VAR_HTTPS_PORT STRING_ARG
+ {
+ OUTYY(("P(server_https_port:%s)\n", $2));
+ if(atoi($2) == 0)
+ yyerror("port number expected");
+ else cfg_parser->cfg->https_port = atoi($2);
+ };
+server_http_endpoint: VAR_HTTP_ENDPOINT STRING_ARG
+ {
+ OUTYY(("P(server_http_endpoint:%s)\n", $2));
+ free(cfg_parser->cfg->http_endpoint);
+ if($2 && $2[0] != '/') {
+ cfg_parser->cfg->http_endpoint = malloc(strlen($2)+2);
+ if(!cfg_parser->cfg->http_endpoint)
+ yyerror("out of memory");
+ cfg_parser->cfg->http_endpoint[0] = '/';
+ memmove(cfg_parser->cfg->http_endpoint+1, $2,
+ strlen($2)+1);
+ free($2);
+ } else {
+ cfg_parser->cfg->http_endpoint = $2;
+ }
+ };
+server_http_max_streams: VAR_HTTP_MAX_STREAMS STRING_ARG
+ {
+ OUTYY(("P(server_http_max_streams:%s)\n", $2));
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
+ yyerror("number expected");
+ else cfg_parser->cfg->http_max_streams = atoi($2);
+ free($2);
+ };
+server_http_query_buffer_size: VAR_HTTP_QUERY_BUFFER_SIZE STRING_ARG
+ {
+ OUTYY(("P(server_http_query_buffer_size:%s)\n", $2));
+ if(!cfg_parse_memsize($2,
+ &cfg_parser->cfg->http_query_buffer_size))
+ yyerror("memory size expected");
+ free($2);
+ };
+server_http_response_buffer_size: VAR_HTTP_RESPONSE_BUFFER_SIZE STRING_ARG
+ {
+ OUTYY(("P(server_http_response_buffer_size:%s)\n", $2));
+ if(!cfg_parse_memsize($2,
+ &cfg_parser->cfg->http_response_buffer_size))
+ yyerror("memory size expected");
+ free($2);
+ };
+server_http_nodelay: VAR_HTTP_NODELAY STRING_ARG
+ {
+ OUTYY(("P(server_http_nodelay:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->http_nodelay = (strcmp($2, "yes")==0);
+ free($2);
+ };
server_use_systemd: VAR_USE_SYSTEMD STRING_ARG
{
OUTYY(("P(server_use_systemd:%s)\n", $2));
@@ -1120,15 +1182,15 @@ server_root_hints: VAR_ROOT_HINTS STRING_ARG
server_dlv_anchor_file: VAR_DLV_ANCHOR_FILE STRING_ARG
{
OUTYY(("P(server_dlv_anchor_file:%s)\n", $2));
- free(cfg_parser->cfg->dlv_anchor_file);
- cfg_parser->cfg->dlv_anchor_file = $2;
+ log_warn("option dlv-anchor-file ignored: DLV is decommissioned");
+ free($2);
}
;
server_dlv_anchor: VAR_DLV_ANCHOR STRING_ARG
{
OUTYY(("P(server_dlv_anchor:%s)\n", $2));
- if(!cfg_strlist_insert(&cfg_parser->cfg->dlv_anchor_list, $2))
- yyerror("out of memory");
+ log_warn("option dlv-anchor ignored: DLV is decommissioned");
+ free($2);
}
;
server_auto_trust_anchor_file: VAR_AUTO_TRUST_ANCHOR_FILE STRING_ARG
@@ -2403,6 +2465,32 @@ server_ipsecmod_strict: VAR_IPSECMOD_STRICT STRING_ARG
#endif
}
;
+server_edns_client_tag: VAR_EDNS_CLIENT_TAG STRING_ARG STRING_ARG
+ {
+ int tag_data;
+ OUTYY(("P(server_edns_client_tag:%s %s)\n", $2, $3));
+ tag_data = atoi($3);
+ if(tag_data > 65535 || tag_data < 0 ||
+ (tag_data == 0 && (strlen($3) != 1 || $3[0] != '0')))
+ yyerror("edns-client-tag data invalid, needs to be a "
+ "number from 0 to 65535");
+ if(!cfg_str2list_insert(
+ &cfg_parser->cfg->edns_client_tags, $2, $3))
+ fatal_exit("out of memory adding "
+ "edns-client-tag");
+ }
+ ;
+server_edns_client_tag_opcode: VAR_EDNS_CLIENT_TAG_OPCODE STRING_ARG
+ {
+ OUTYY(("P(edns_client_tag_opcode:%s)\n", $2));
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
+ yyerror("option code expected");
+ else if(atoi($2) > 65535 || atoi($2) < 0)
+ yyerror("option code must be in interval [0, 65535]");
+ else cfg_parser->cfg->edns_client_tag_opcode = atoi($2);
+
+ }
+ ;
stub_name: VAR_NAME STRING_ARG
{
OUTYY(("P(name:%s)\n", $2));
diff --git a/contrib/unbound/util/edns.c b/contrib/unbound/util/edns.c
index 9c540913efdc..6a7e4f8cf55a 100644
--- a/contrib/unbound/util/edns.c
+++ b/contrib/unbound/util/edns.c
@@ -43,11 +43,92 @@
#include "util/edns.h"
#include "util/config_file.h"
#include "util/netevent.h"
+#include "util/net_help.h"
#include "util/regional.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
+#if 0
+/* XXX: remove me */
#include "edns.h"
+#endif
+
+struct edns_tags* edns_tags_create(void)
+{
+ struct edns_tags* edns_tags = calloc(1, sizeof(struct edns_tags));
+ if(!edns_tags)
+ return NULL;
+ if(!(edns_tags->region = regional_create())) {
+ edns_tags_delete(edns_tags);
+ return NULL;
+ }
+ return edns_tags;
+}
+
+void edns_tags_delete(struct edns_tags* edns_tags)
+{
+ if(!edns_tags)
+ return;
+ regional_destroy(edns_tags->region);
+ free(edns_tags);
+}
+
+static int
+edns_tags_client_insert(struct edns_tags* edns_tags,
+ struct sockaddr_storage* addr, socklen_t addrlen, int net,
+ uint16_t tag_data)
+{
+ struct edns_tag_addr* eta = regional_alloc_zero(edns_tags->region,
+ sizeof(struct edns_tag_addr));
+ if(!eta)
+ return 0;
+ eta->tag_data = tag_data;
+ if(!addr_tree_insert(&edns_tags->client_tags, &eta->node, addr, addrlen,
+ net)) {
+ verbose(VERB_QUERY, "duplicate EDNS client tag ignored.");
+ }
+ return 1;
+}
+
+int edns_tags_apply_cfg(struct edns_tags* edns_tags,
+ struct config_file* config)
+{
+ struct config_str2list* c;
+ regional_free_all(edns_tags->region);
+ addr_tree_init(&edns_tags->client_tags);
+
+ for(c=config->edns_client_tags; c; c=c->next) {
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ int net;
+ uint16_t tag_data;
+ log_assert(c->str && c->str2);
+
+ if(!netblockstrtoaddr(c->str, UNBOUND_DNS_PORT, &addr, &addrlen,
+ &net)) {
+ log_err("cannot parse EDNS client tag IP netblock: %s",
+ c->str);
+ return 0;
+ }
+ tag_data = atoi(c->str2); /* validated in config parser */
+ if(!edns_tags_client_insert(edns_tags, &addr, addrlen, net,
+ tag_data)) {
+ log_err("out of memory while adding EDNS tags");
+ return 0;
+ }
+ }
+ edns_tags->client_tag_opcode = config->edns_client_tag_opcode;
+
+ addr_tree_init_parents(&edns_tags->client_tags);
+ return 1;
+}
+
+struct edns_tag_addr*
+edns_tag_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
+ socklen_t addrlen)
+{
+ return (struct edns_tag_addr*)addr_tree_lookup(tree, addr, addrlen);
+}
static int edns_keepalive(struct edns_data* edns_out, struct edns_data* edns_in,
struct comm_point* c, struct regional* region)
diff --git a/contrib/unbound/util/edns.h b/contrib/unbound/util/edns.h
index a4ee7def634c..cf9f8707e808 100644
--- a/contrib/unbound/util/edns.h
+++ b/contrib/unbound/util/edns.h
@@ -42,12 +42,69 @@
#ifndef UTIL_EDNS_H
#define UTIL_EDNS_H
+#include "util/storage/dnstree.h"
+
struct edns_data;
struct config_file;
struct comm_point;
struct regional;
/**
+ * Structure containing all EDNS tags.
+ */
+struct edns_tags {
+ /** Tree of EDNS client tags to use in upstream queries, per address
+ * prefix. Contains nodes of type edns_tag_addr. */
+ rbtree_type client_tags;
+ /** EDNS opcode to use for client tags */
+ uint16_t client_tag_opcode;
+ /** region to allocate tree nodes in */
+ struct regional* region;
+};
+
+/**
+ * EDNS tag. Node of rbtree, containing tag and prefix.
+ */
+struct edns_tag_addr {
+ /** node in address tree, used for tree lookups. Need to be the first
+ * member of this struct. */
+ struct addr_tree_node node;
+ /** tag data, in host byte ordering */
+ uint16_t tag_data;
+};
+
+/**
+ * Create structure to hold EDNS tags
+ * @return: newly created edns_tags, NULL on alloc failure.
+ */
+struct edns_tags* edns_tags_create(void);
+
+/** Delete EDNS tags structure
+ * @param edns_tags: struct to delete
+ */
+void edns_tags_delete(struct edns_tags* edns_tags);
+
+/**
+ * Add configured EDNS tags
+ * @param edns_tags: edns tags to apply config to
+ * @param config: struct containing EDNS tags configuration
+ * @return 0 on error
+ */
+int edns_tags_apply_cfg(struct edns_tags* edns_tags,
+ struct config_file* config);
+
+/**
+ * Find tag for address.
+ * @param tree: tree containing EDNS tags per address prefix.
+ * @param addr: address to use for tree lookup
+ * @param addrlen: length of address
+ * @return: matching tree node, NULL otherwise
+ */
+struct edns_tag_addr*
+edns_tag_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
+ socklen_t addrlen);
+
+/**
* Apply common EDNS options.
*
* @param edns_out: initialised edns information with outbound edns.
diff --git a/contrib/unbound/util/fptr_wlist.c b/contrib/unbound/util/fptr_wlist.c
index aa275ed534b7..7d15d107561a 100644
--- a/contrib/unbound/util/fptr_wlist.c
+++ b/contrib/unbound/util/fptr_wlist.c
@@ -138,6 +138,9 @@ fptr_whitelist_comm_timer(void (*fptr)(void*))
else if(fptr == &auth_xfer_probe_timer_callback) return 1;
else if(fptr == &auth_xfer_transfer_timer_callback) return 1;
else if(fptr == &mesh_serve_expired_callback) return 1;
+#ifdef USE_DNSTAP
+ else if(fptr == &mq_wakeup_cb) return 1;
+#endif
return 0;
}
diff --git a/contrib/unbound/util/iana_ports.inc b/contrib/unbound/util/iana_ports.inc
index 79488f49a2c9..fa25869d3b56 100644
--- a/contrib/unbound/util/iana_ports.inc
+++ b/contrib/unbound/util/iana_ports.inc
@@ -4516,6 +4516,7 @@
6679,
6689,
6696,
+6699,
6701,
6702,
6703,
@@ -4744,6 +4745,7 @@
8023,
8025,
8026,
+8027,
8032,
8033,
8034,
diff --git a/contrib/unbound/util/mini_event.h b/contrib/unbound/util/mini_event.h
index 1734ca574c60..fa71ca3d123e 100644
--- a/contrib/unbound/util/mini_event.h
+++ b/contrib/unbound/util/mini_event.h
@@ -54,6 +54,10 @@
#if defined(USE_MINI_EVENT) && !defined(USE_WINSOCK)
+#ifdef HAVE_SYS_SELECT_H
+/* for fd_set on OpenBSD */
+#include <sys/select.h>
+#endif
#include <sys/time.h>
#ifndef HAVE_EVENT_BASE_FREE
diff --git a/contrib/unbound/util/module.h b/contrib/unbound/util/module.h
index fa89c647e370..1eed213008c2 100644
--- a/contrib/unbound/util/module.h
+++ b/contrib/unbound/util/module.h
@@ -520,6 +520,8 @@ struct module_env {
struct edns_known_option* edns_known_options;
/* Number of known edns options */
size_t edns_known_options_num;
+ /** EDNS client tag information */
+ struct edns_tags* edns_tags;
/* Make every mesh state unique, do not aggregate mesh states. */
int unique_mesh;
diff --git a/contrib/unbound/util/net_help.c b/contrib/unbound/util/net_help.c
index f59a4d65370d..c5216bc2d8c6 100644
--- a/contrib/unbound/util/net_help.c
+++ b/contrib/unbound/util/net_help.c
@@ -61,6 +61,9 @@
#ifdef USE_WINSOCK
#include <wincrypt.h>
#endif
+#ifdef HAVE_NGHTTP2_NGHTTP2_H
+#include <nghttp2/nghttp2.h>
+#endif
/** max length of an IP address (the address portion) that we allow */
#define MAX_ADDR_STRLEN 128 /* characters */
@@ -82,6 +85,7 @@ static struct tls_session_ticket_key {
unsigned char *hmac_key;
} *ticket_keys;
+#ifdef HAVE_SSL
/**
* callback TLS session ticket encrypt and decrypt
* For use with SSL_CTX_set_tlsext_ticket_key_cb or
@@ -97,7 +101,6 @@ static struct tls_session_ticket_key {
* @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket
* (the ticket is decrypt only). and <0 for failures.
*/
-#ifdef HAVE_SSL
int tls_session_ticket_key_cb(SSL *s, unsigned char* key_name,
unsigned char* iv, EVP_CIPHER_CTX *evp_ctx,
#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
@@ -884,6 +887,21 @@ log_cert(unsigned level, const char* str, void* cert)
}
#endif /* HAVE_SSL */
+#if defined(HAVE_SSL) && defined(HAVE_NGHTTP2)
+static int alpn_select_cb(SSL* ATTR_UNUSED(ssl), const unsigned char** out,
+ unsigned char* outlen, const unsigned char* in, unsigned int inlen,
+ void* ATTR_UNUSED(arg))
+{
+ int rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in,
+ inlen);
+ if(rv == -1) {
+ return SSL_TLSEXT_ERR_NOACK;
+ }
+ /* either http/1.1 or h2 selected */
+ return SSL_TLSEXT_ERR_OK;
+}
+#endif
+
int
listen_sslctx_setup(void* ctxt)
{
@@ -942,6 +960,9 @@ listen_sslctx_setup(void* ctxt)
#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
SSL_CTX_set_security_level(ctx, 0);
#endif
+#if defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB) && defined(HAVE_NGHTTP2)
+ SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, NULL);
+#endif
#else
(void)ctxt;
#endif /* HAVE_SSL */
@@ -1478,7 +1499,11 @@ int tls_session_ticket_key_cb(SSL *ATTR_UNUSED(sslctx), unsigned char* key_name,
params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
"sha256", 0);
params[2] = OSSL_PARAM_construct_end();
+#ifdef HAVE_EVP_MAC_CTX_SET_PARAMS
+ EVP_MAC_CTX_set_params(hmac_ctx, params);
+#else
EVP_MAC_set_ctx_params(hmac_ctx, params);
+#endif
#elif !defined(HMAC_INIT_EX_RETURNS_VOID)
if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) {
verbose(VERB_CLIENT, "HMAC_Init_ex failed");
@@ -1509,7 +1534,11 @@ int tls_session_ticket_key_cb(SSL *ATTR_UNUSED(sslctx), unsigned char* key_name,
params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
"sha256", 0);
params[2] = OSSL_PARAM_construct_end();
+#ifdef HAVE_EVP_MAC_CTX_SET_PARAMS
+ EVP_MAC_CTX_set_params(hmac_ctx, params);
+#else
EVP_MAC_set_ctx_params(hmac_ctx, params);
+#endif
#elif !defined(HMAC_INIT_EX_RETURNS_VOID)
if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) {
verbose(VERB_CLIENT, "HMAC_Init_ex failed");
@@ -1554,3 +1583,31 @@ listen_sslctx_delete_ticket_keys(void)
free(ticket_keys);
ticket_keys = NULL;
}
+
+# ifndef USE_WINSOCK
+char*
+sock_strerror(int errn)
+{
+ return strerror(errn);
+}
+
+void
+sock_close(int socket)
+{
+ close(socket);
+}
+
+# else
+char*
+sock_strerror(int ATTR_UNUSED(errn))
+{
+ return wsa_strerror(WSAGetLastError());
+}
+
+void
+sock_close(int socket)
+{
+ closesocket(socket);
+}
+
+# endif /* USE_WINSOCK */
diff --git a/contrib/unbound/util/net_help.h b/contrib/unbound/util/net_help.h
index 29943ada090f..45b607a430d5 100644
--- a/contrib/unbound/util/net_help.h
+++ b/contrib/unbound/util/net_help.h
@@ -496,4 +496,10 @@ void listen_sslctx_delete_ticket_keys(void);
*/
int netblockdnametoaddr(uint8_t* dname, size_t dnamelen,
struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af);
+
+/** Return strerror or wsastrerror for socket error printout */
+char* sock_strerror(int errn);
+/** close the socket with close, or wsa closesocket */
+void sock_close(int socket);
+
#endif /* NET_HELP_H */
diff --git a/contrib/unbound/util/netevent.c b/contrib/unbound/util/netevent.c
index 3e7a433e5021..545f09742c7c 100644
--- a/contrib/unbound/util/netevent.c
+++ b/contrib/unbound/util/netevent.c
@@ -373,12 +373,7 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
if(sent == -1) {
if(!udp_send_errno_needs_log(addr, addrlen))
return 0;
-#ifndef USE_WINSOCK
- verbose(VERB_OPS, "sendto failed: %s", strerror(errno));
-#else
- verbose(VERB_OPS, "sendto failed: %s",
- wsa_strerror(WSAGetLastError()));
-#endif
+ verbose(VERB_OPS, "sendto failed: %s", sock_strerror(errno));
log_addr(VERB_OPS, "remote address is",
(struct sockaddr_storage*)addr, addrlen);
return 0;
@@ -739,7 +734,7 @@ static void
setup_tcp_handler(struct comm_point* c, int fd, int cur, int max)
{
int handler_usage;
- log_assert(c->type == comm_tcp);
+ log_assert(c->type == comm_tcp || c->type == comm_http);
log_assert(c->fd == -1);
sldns_buffer_clear(c->buffer);
#ifdef USE_DNSCRYPT
@@ -845,7 +840,6 @@ int comm_point_perform_accept(struct comm_point* c,
return -1;
}
#endif
- log_err_addr("accept failed", strerror(errno), addr, *addrlen);
#else /* USE_WINSOCK */
if(WSAGetLastError() == WSAEINPROGRESS ||
WSAGetLastError() == WSAECONNRESET)
@@ -854,9 +848,9 @@ int comm_point_perform_accept(struct comm_point* c,
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
return -1;
}
- log_err_addr("accept failed", wsa_strerror(WSAGetLastError()),
- addr, *addrlen);
#endif
+ log_err_addr("accept failed", sock_strerror(errno), addr,
+ *addrlen);
return -1;
}
if(c->tcp_conn_limit && c->type == comm_tcp_accept) {
@@ -914,6 +908,42 @@ comm_point_tcp_win_bio_cb(struct comm_point* c, void* thessl)
}
#endif
+#ifdef HAVE_NGHTTP2
+/** Create http2 session server. Per connection, after TCP accepted.*/
+static int http2_session_server_create(struct http2_session* h2_session)
+{
+ log_assert(h2_session->callbacks);
+ h2_session->is_drop = 0;
+ if(nghttp2_session_server_new(&h2_session->session,
+ h2_session->callbacks,
+ h2_session) == NGHTTP2_ERR_NOMEM) {
+ log_err("failed to create nghttp2 session server");
+ return 0;
+ }
+
+ return 1;
+}
+
+/** Submit http2 setting to session. Once per session. */
+static int http2_submit_settings(struct http2_session* h2_session)
+{
+ int ret;
+ nghttp2_settings_entry settings[1] = {
+ {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
+ h2_session->c->http2_max_streams}};
+
+ ret = nghttp2_submit_settings(h2_session->session, NGHTTP2_FLAG_NONE,
+ settings, 1);
+ if(ret) {
+ verbose(VERB_QUERY, "http2: submit_settings failed, "
+ "error: %s", nghttp2_strerror(ret));
+ return 0;
+ }
+ return 1;
+}
+#endif /* HAVE_NGHTTP2 */
+
+
void
comm_point_tcp_accept_callback(int fd, short event, void* arg)
{
@@ -935,7 +965,28 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
/* clear leftover flags from previous use, and then set the
* correct event base for the event structure for libevent */
ub_event_free(c_hdl->ev->ev);
- c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1, UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT, comm_point_tcp_handle_callback, c_hdl);
+
+ if(c_hdl->type == comm_http) {
+#ifdef HAVE_NGHTTP2
+ if(!c_hdl->h2_session ||
+ !http2_session_server_create(c_hdl->h2_session)) {
+ log_warn("failed to create nghttp2");
+ return;
+ }
+ if(!c_hdl->h2_session ||
+ !http2_submit_settings(c_hdl->h2_session)) {
+ log_warn("failed to submit http2 settings");
+ return;
+ }
+#endif
+ c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1,
+ UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT,
+ comm_point_http_handle_callback, c_hdl);
+ } else {
+ c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1,
+ UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT,
+ comm_point_tcp_handle_callback, c_hdl);
+ }
if(!c_hdl->ev->ev) {
log_warn("could not ub_event_new, dropped tcp");
return;
@@ -1169,6 +1220,18 @@ ssl_handshake(struct comm_point* c)
c->repinfo.addrlen);
}
+ /* check if http2 use is negotiated */
+ if(c->type == comm_http && c->h2_session) {
+ const unsigned char *alpn;
+ unsigned int alpnlen = 0;
+ SSL_get0_alpn_selected(c->ssl, &alpn, &alpnlen);
+ if(alpnlen == 2 && memcmp("h2", alpn, 2) == 0) {
+ /* connection upgraded to HTTP2 */
+ c->tcp_do_toggle_rw = 0;
+ c->use_h2 = 1;
+ }
+ }
+
/* setup listen rw correctly */
if(c->tcp_is_reading) {
if(c->ssl_shake_state != comm_ssl_shake_read)
@@ -1435,8 +1498,6 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
if(errno == ECONNRESET && verbosity < 2)
return 0; /* silence reset by peer */
#endif
- log_err_addr("read (in tcp s)", strerror(errno),
- &c->repinfo.addr, c->repinfo.addrlen);
#else /* USE_WINSOCK */
if(WSAGetLastError() == WSAECONNRESET)
return 0;
@@ -1447,10 +1508,9 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
UB_EV_READ);
return 1;
}
- log_err_addr("read (in tcp s)",
- wsa_strerror(WSAGetLastError()),
- &c->repinfo.addr, c->repinfo.addrlen);
#endif
+ log_err_addr("read (in tcp s)", sock_strerror(errno),
+ &c->repinfo.addr, c->repinfo.addrlen);
return 0;
}
c->tcp_byte_count += r;
@@ -1483,8 +1543,6 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
return 1;
- log_err_addr("read (in tcp r)", strerror(errno),
- &c->repinfo.addr, c->repinfo.addrlen);
#else /* USE_WINSOCK */
if(WSAGetLastError() == WSAECONNRESET)
return 0;
@@ -1494,10 +1552,9 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
return 1;
}
- log_err_addr("read (in tcp r)",
- wsa_strerror(WSAGetLastError()),
- &c->repinfo.addr, c->repinfo.addrlen);
#endif
+ log_err_addr("read (in tcp r)", sock_strerror(errno),
+ &c->repinfo.addr, c->repinfo.addrlen);
return 0;
}
sldns_buffer_skip(c->buffer, r);
@@ -1716,8 +1773,6 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
if(errno == ECONNRESET && verbosity < 2)
return 0; /* silence reset by peer */
#endif
- log_err_addr("tcp send r", strerror(errno),
- &c->repinfo.addr, c->repinfo.addrlen);
#else
if(WSAGetLastError() == WSAEINPROGRESS)
return 1;
@@ -1727,9 +1782,9 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
}
if(WSAGetLastError() == WSAECONNRESET && verbosity < 2)
return 0; /* silence reset by peer */
- log_err_addr("tcp send r", wsa_strerror(WSAGetLastError()),
- &c->repinfo.addr, c->repinfo.addrlen);
#endif
+ log_err_addr("tcp send r", sock_strerror(errno),
+ &c->repinfo.addr, c->repinfo.addrlen);
return 0;
}
sldns_buffer_skip(buffer, r);
@@ -1914,8 +1969,6 @@ http_read_more(int fd, struct comm_point* c)
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
return 1;
- log_err_addr("read (in http r)", strerror(errno),
- &c->repinfo.addr, c->repinfo.addrlen);
#else /* USE_WINSOCK */
if(WSAGetLastError() == WSAECONNRESET)
return 0;
@@ -1925,10 +1978,9 @@ http_read_more(int fd, struct comm_point* c)
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
return 1;
}
- log_err_addr("read (in http r)",
- wsa_strerror(WSAGetLastError()),
- &c->repinfo.addr, c->repinfo.addrlen);
#endif
+ log_err_addr("read (in http r)", sock_strerror(errno),
+ &c->repinfo.addr, c->repinfo.addrlen);
return 0;
}
sldns_buffer_skip(c->buffer, r);
@@ -2186,11 +2238,209 @@ http_chunked_segment(struct comm_point* c)
return 1;
}
+#ifdef HAVE_NGHTTP2
+/** Create new http2 session. Called when creating handling comm point. */
+struct http2_session* http2_session_create(struct comm_point* c)
+{
+ struct http2_session* session = calloc(1, sizeof(*session));
+ if(!session) {
+ log_err("malloc failure while creating http2 session");
+ return NULL;
+ }
+ session->c = c;
+
+ return session;
+}
+#endif
+
+/** Delete http2 session. After closing connection or on error */
+void http2_session_delete(struct http2_session* h2_session)
+{
+#ifdef HAVE_NGHTTP2
+ if(h2_session->callbacks)
+ nghttp2_session_callbacks_del(h2_session->callbacks);
+ free(h2_session);
+#else
+ (void)h2_session;
+#endif
+}
+
+#ifdef HAVE_NGHTTP2
+struct http2_stream* http2_stream_create(int32_t stream_id)
+{
+ struct http2_stream* h2_stream = calloc(1, sizeof(*h2_stream));
+ if(!h2_stream) {
+ log_err("malloc failure while creating http2 stream");
+ return NULL;
+ }
+ h2_stream->stream_id = stream_id;
+ return h2_stream;
+}
+
+/** Delete http2 stream. After session delete or stream close callback */
+static void http2_stream_delete(struct http2_session* h2_session,
+ struct http2_stream* h2_stream)
+{
+ if(h2_stream->mesh_state) {
+ mesh_state_remove_reply(h2_stream->mesh, h2_stream->mesh_state,
+ h2_session->c);
+ h2_stream->mesh_state = NULL;
+ }
+ http2_req_stream_clear(h2_stream);
+ free(h2_stream);
+}
+#endif
+
+void http2_stream_add_meshstate(struct http2_stream* h2_stream,
+ struct mesh_area* mesh, struct mesh_state* m)
+{
+ h2_stream->mesh = mesh;
+ h2_stream->mesh_state = m;
+}
+
+/** delete http2 session server. After closing connection. */
+static void http2_session_server_delete(struct http2_session* h2_session)
+{
+#ifdef HAVE_NGHTTP2
+ struct http2_stream* h2_stream, *next;
+ nghttp2_session_del(h2_session->session); /* NULL input is fine */
+ h2_session->session = NULL;
+ for(h2_stream = h2_session->first_stream; h2_stream;) {
+ next = h2_stream->next;
+ http2_stream_delete(h2_session, h2_stream);
+ h2_stream = next;
+ }
+ h2_session->first_stream = NULL;
+ h2_session->is_drop = 0;
+ h2_session->postpone_drop = 0;
+ h2_session->c->h2_stream = NULL;
+#endif
+ (void)h2_session;
+}
+
+#ifdef HAVE_NGHTTP2
+void http2_session_add_stream(struct http2_session* h2_session,
+ struct http2_stream* h2_stream)
+{
+ if(h2_session->first_stream)
+ h2_session->first_stream->prev = h2_stream;
+ h2_stream->next = h2_session->first_stream;
+ h2_session->first_stream = h2_stream;
+}
+
+/** remove stream from session linked list. After stream close callback or
+ * closing connection */
+void http2_session_remove_stream(struct http2_session* h2_session,
+ struct http2_stream* h2_stream)
+{
+ if(h2_stream->prev)
+ h2_stream->prev->next = h2_stream->next;
+ else
+ h2_session->first_stream = h2_stream->next;
+ if(h2_stream->next)
+ h2_stream->next->prev = h2_stream->prev;
+
+}
+
+int http2_stream_close_cb(nghttp2_session* ATTR_UNUSED(session),
+ int32_t stream_id, uint32_t ATTR_UNUSED(error_code), void* cb_arg)
+{
+ struct http2_stream* h2_stream;
+ struct http2_session* h2_session = (struct http2_session*)cb_arg;
+ if(!(h2_stream = nghttp2_session_get_stream_user_data(
+ h2_session->session, stream_id))) {
+ return 0;
+ }
+ http2_session_remove_stream(h2_session, h2_stream);
+ http2_stream_delete(h2_session, h2_stream);
+ return 0;
+}
+
+ssize_t http2_recv_cb(nghttp2_session* ATTR_UNUSED(session), uint8_t* buf,
+ size_t len, int ATTR_UNUSED(flags), void* cb_arg)
+{
+#ifdef HAVE_SSL
+ struct http2_session* h2_session = (struct http2_session*)cb_arg;
+ int r;
+
+ log_assert(h2_session->c->type == comm_http);
+ log_assert(h2_session->c->h2_session);
+
+ if(!h2_session->c->ssl)
+ return 0;
+
+ ERR_clear_error();
+ r = SSL_read(h2_session->c->ssl, buf, len);
+ if(r <= 0) {
+ int want = SSL_get_error(h2_session->c->ssl, r);
+ if(want == SSL_ERROR_ZERO_RETURN) {
+ return NGHTTP2_ERR_EOF;
+ } else if(want == SSL_ERROR_WANT_READ) {
+ return NGHTTP2_ERR_WOULDBLOCK;
+ } else if(want == SSL_ERROR_WANT_WRITE) {
+ h2_session->c->ssl_shake_state = comm_ssl_shake_hs_write;
+ comm_point_listen_for_rw(h2_session->c, 0, 1);
+ return NGHTTP2_ERR_WOULDBLOCK;
+ } else if(want == SSL_ERROR_SYSCALL) {
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+#endif
+ if(errno != 0)
+ log_err("SSL_read syscall: %s",
+ strerror(errno));
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ log_crypto_err("could not SSL_read");
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ return r;
+#else
+ (void)buf;
+ (void)len;
+ (void)cb_arg;
+ return -1;
+#endif
+}
+#endif /* HAVE_NGHTTP2 */
+
+/** Handle http2 read */
+static int
+comm_point_http2_handle_read(int ATTR_UNUSED(fd), struct comm_point* c)
+{
+#ifdef HAVE_NGHTTP2
+ int ret;
+ log_assert(c->h2_session);
+ log_assert(c->ssl);
+
+ /* reading until recv cb returns NGHTTP2_ERR_WOULDBLOCK */
+ ret = nghttp2_session_recv(c->h2_session->session);
+ if(ret) {
+ if(ret != NGHTTP2_ERR_EOF &&
+ ret != NGHTTP2_ERR_CALLBACK_FAILURE) {
+ verbose(VERB_QUERY, "http2: session_recv failed, "
+ "error: %s", nghttp2_strerror(ret));
+ }
+ return 0;
+ }
+ if(nghttp2_session_want_write(c->h2_session->session)) {
+ c->tcp_is_reading = 0;
+ comm_point_stop_listening(c);
+ comm_point_start_listening(c, -1, c->tcp_timeout_msec);
+ } else if(!nghttp2_session_want_read(c->h2_session->session))
+ return 0; /* connection can be closed */
+ return 1;
+#else
+ (void)c;
+ return 0;
+#endif
+}
+
/**
- * Handle http reading callback.
+ * Handle http reading callback.
* @param fd: file descriptor of socket.
* @param c: comm point to read from into buffer.
- * @return: 0 on error
+ * @return: 0 on error
*/
static int
comm_point_http_handle_read(int fd, struct comm_point* c)
@@ -2210,6 +2460,18 @@ comm_point_http_handle_read(int fd, struct comm_point* c)
if(!c->tcp_is_reading)
return 1;
+
+ if(c->use_h2) {
+ return comm_point_http2_handle_read(fd, c);
+ }
+
+ /* http version is <= http/1.1 */
+
+ if(c->http_min_version >= http_version_2) {
+ /* HTTP/2 failed, not allowed to use lower version. */
+ return 0;
+ }
+
/* read more data */
if(c->ssl) {
if(!ssl_http_read_more(c))
@@ -2220,7 +2482,9 @@ comm_point_http_handle_read(int fd, struct comm_point* c)
}
sldns_buffer_flip(c->buffer);
+
while(sldns_buffer_remaining(c->buffer) > 0) {
+ /* Handle HTTP/1.x data */
/* if we are reading headers, read more headers */
if(c->http_in_headers || c->http_in_chunk_headers) {
/* if header is done, process the header */
@@ -2364,8 +2628,6 @@ http_write_more(int fd, struct comm_point* c)
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
return 1;
- log_err_addr("http send r", strerror(errno),
- &c->repinfo.addr, c->repinfo.addrlen);
#else
if(WSAGetLastError() == WSAEINPROGRESS)
return 1;
@@ -2373,15 +2635,92 @@ http_write_more(int fd, struct comm_point* c)
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1;
}
- log_err_addr("http send r", wsa_strerror(WSAGetLastError()),
- &c->repinfo.addr, c->repinfo.addrlen);
#endif
+ log_err_addr("http send r", sock_strerror(errno),
+ &c->repinfo.addr, c->repinfo.addrlen);
return 0;
}
sldns_buffer_skip(c->buffer, r);
return 1;
}
+#ifdef HAVE_NGHTTP2
+ssize_t http2_send_cb(nghttp2_session* ATTR_UNUSED(session), const uint8_t* buf,
+ size_t len, int ATTR_UNUSED(flags), void* cb_arg)
+{
+#ifdef HAVE_SSL
+ int r;
+ struct http2_session* h2_session = (struct http2_session*)cb_arg;
+ log_assert(h2_session->c->type == comm_http);
+ log_assert(h2_session->c->h2_session);
+
+ if(!h2_session->c->ssl)
+ return 0;
+
+ ERR_clear_error();
+ r = SSL_write(h2_session->c->ssl, buf, len);
+ if(r <= 0) {
+ int want = SSL_get_error(h2_session->c->ssl, r);
+ if(want == SSL_ERROR_ZERO_RETURN) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ } else if(want == SSL_ERROR_WANT_READ) {
+ h2_session->c->ssl_shake_state = comm_ssl_shake_hs_read;
+ comm_point_listen_for_rw(h2_session->c, 1, 0);
+ return NGHTTP2_ERR_WOULDBLOCK;
+ } else if(want == SSL_ERROR_WANT_WRITE) {
+ return NGHTTP2_ERR_WOULDBLOCK;
+ } else if(want == SSL_ERROR_SYSCALL) {
+#ifdef EPIPE
+ if(errno == EPIPE && verbosity < 2)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+#endif
+ if(errno != 0)
+ log_err("SSL_write syscall: %s",
+ strerror(errno));
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ log_crypto_err("could not SSL_write");
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ return r;
+#else
+ (void)buf;
+ (void)len;
+ (void)cb_arg;
+ return -1;
+#endif
+}
+#endif /* HAVE_NGHTTP2 */
+
+/** Handle http2 writing */
+static int
+comm_point_http2_handle_write(int ATTR_UNUSED(fd), struct comm_point* c)
+{
+#ifdef HAVE_NGHTTP2
+ int ret;
+ log_assert(c->h2_session);
+ log_assert(c->ssl);
+
+ ret = nghttp2_session_send(c->h2_session->session);
+ if(ret) {
+ verbose(VERB_QUERY, "http2: session_send failed, "
+ "error: %s", nghttp2_strerror(ret));
+ return 0;
+ }
+
+ if(nghttp2_session_want_read(c->h2_session->session)) {
+ c->tcp_is_reading = 1;
+ comm_point_stop_listening(c);
+ comm_point_start_listening(c, -1, c->tcp_timeout_msec);
+ } else if(!nghttp2_session_want_write(c->h2_session->session))
+ return 0; /* connection can be closed */
+ return 1;
+#else
+ (void)c;
+ return 0;
+#endif
+}
+
/**
* Handle http writing callback.
* @param fd: file descriptor of socket.
@@ -2413,6 +2752,18 @@ comm_point_http_handle_write(int fd, struct comm_point* c)
#endif /* HAVE_SSL */
if(c->tcp_is_reading)
return 1;
+
+ if(c->use_h2) {
+ return comm_point_http2_handle_write(fd, c);
+ }
+
+ /* http version is <= http/1.1 */
+
+ if(c->http_min_version >= http_version_2) {
+ /* HTTP/2 failed, not allowed to use lower version. */
+ return 0;
+ }
+
/* if we are writing, write more */
if(c->ssl) {
if(!ssl_http_write_more(c))
@@ -2724,11 +3075,129 @@ comm_point_create_tcp_handler(struct comm_base *base,
return c;
}
+static struct comm_point*
+comm_point_create_http_handler(struct comm_base *base,
+ struct comm_point* parent, size_t bufsize, int harden_large_queries,
+ uint32_t http_max_streams, char* http_endpoint,
+ comm_point_callback_type* callback, void* callback_arg)
+{
+ struct comm_point* c = (struct comm_point*)calloc(1,
+ sizeof(struct comm_point));
+ short evbits;
+ if(!c)
+ return NULL;
+ c->ev = (struct internal_event*)calloc(1,
+ sizeof(struct internal_event));
+ if(!c->ev) {
+ free(c);
+ return NULL;
+ }
+ c->ev->base = base;
+ c->fd = -1;
+ c->buffer = sldns_buffer_new(bufsize);
+ if(!c->buffer) {
+ free(c->ev);
+ free(c);
+ return NULL;
+ }
+ c->timeout = (struct timeval*)malloc(sizeof(struct timeval));
+ if(!c->timeout) {
+ sldns_buffer_free(c->buffer);
+ free(c->ev);
+ free(c);
+ return NULL;
+ }
+ c->tcp_is_reading = 0;
+ c->tcp_byte_count = 0;
+ c->tcp_parent = parent;
+ c->tcp_timeout_msec = parent->tcp_timeout_msec;
+ c->tcp_conn_limit = parent->tcp_conn_limit;
+ c->tcl_addr = NULL;
+ c->tcp_keepalive = 0;
+ c->max_tcp_count = 0;
+ c->cur_tcp_count = 0;
+ c->tcp_handlers = NULL;
+ c->tcp_free = NULL;
+ c->type = comm_http;
+ c->tcp_do_close = 1;
+ c->do_not_close = 0;
+ c->tcp_do_toggle_rw = 1; /* will be set to 0 after http2 upgrade */
+ c->tcp_check_nb_connect = 0;
+#ifdef USE_MSG_FASTOPEN
+ c->tcp_do_fastopen = 0;
+#endif
+#ifdef USE_DNSCRYPT
+ c->dnscrypt = 0;
+ c->dnscrypt_buffer = NULL;
+#endif
+ c->repinfo.c = c;
+ c->callback = callback;
+ c->cb_arg = callback_arg;
+
+ c->http_min_version = http_version_2;
+ c->http2_stream_max_qbuffer_size = bufsize;
+ if(harden_large_queries && bufsize > 512)
+ c->http2_stream_max_qbuffer_size = 512;
+ c->http2_max_streams = http_max_streams;
+ if(!(c->http_endpoint = strdup(http_endpoint))) {
+ log_err("could not strdup http_endpoint");
+ sldns_buffer_free(c->buffer);
+ free(c->timeout);
+ free(c->ev);
+ free(c);
+ return NULL;
+ }
+ c->use_h2 = 0;
+#ifdef HAVE_NGHTTP2
+ if(!(c->h2_session = http2_session_create(c))) {
+ log_err("could not create http2 session");
+ free(c->http_endpoint);
+ sldns_buffer_free(c->buffer);
+ free(c->timeout);
+ free(c->ev);
+ free(c);
+ return NULL;
+ }
+ if(!(c->h2_session->callbacks = http2_req_callbacks_create())) {
+ log_err("could not create http2 callbacks");
+ http2_session_delete(c->h2_session);
+ free(c->http_endpoint);
+ sldns_buffer_free(c->buffer);
+ free(c->timeout);
+ free(c->ev);
+ free(c);
+ return NULL;
+ }
+#endif
+
+ /* add to parent free list */
+ c->tcp_free = parent->tcp_free;
+ parent->tcp_free = c;
+ /* 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_http_handle_callback, c);
+ if(c->ev->ev == NULL)
+ {
+ log_err("could not set http handler event");
+ parent->tcp_free = c->tcp_free;
+ http2_session_delete(c->h2_session);
+ sldns_buffer_free(c->buffer);
+ free(c->timeout);
+ free(c->ev);
+ free(c);
+ return NULL;
+ }
+ return c;
+}
+
struct comm_point*
comm_point_create_tcp(struct comm_base *base, int fd, int num,
- int idle_timeout, struct tcl_list* tcp_conn_limit, size_t bufsize,
- struct sldns_buffer* spoolbuf, comm_point_callback_type* callback,
- void* callback_arg)
+ int idle_timeout, int harden_large_queries,
+ uint32_t http_max_streams, char* http_endpoint,
+ struct tcl_list* tcp_conn_limit, size_t bufsize,
+ struct sldns_buffer* spoolbuf, enum listen_type port_type,
+ comm_point_callback_type* callback, void* callback_arg)
{
struct comm_point* c = (struct comm_point*)calloc(1,
sizeof(struct comm_point));
@@ -2792,10 +3261,24 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num,
comm_point_delete(c);
return NULL;
}
- /* now prealloc the tcp handlers */
+ /* now prealloc the handlers */
for(i=0; i<num; i++) {
- c->tcp_handlers[i] = comm_point_create_tcp_handler(base,
- c, bufsize, spoolbuf, callback, callback_arg);
+ if(port_type == listen_type_tcp ||
+ port_type == listen_type_ssl ||
+ port_type == listen_type_tcp_dnscrypt) {
+ c->tcp_handlers[i] = comm_point_create_tcp_handler(base,
+ c, bufsize, spoolbuf, callback, callback_arg);
+ } else if(port_type == listen_type_http) {
+ c->tcp_handlers[i] = comm_point_create_http_handler(
+ base, c, bufsize, harden_large_queries,
+ http_max_streams, http_endpoint,
+ callback, callback_arg);
+ }
+ else {
+ log_err("could not create tcp handler, unknown listen "
+ "type");
+ return NULL;
+ }
if(!c->tcp_handlers[i]) {
comm_point_delete(c);
return NULL;
@@ -3079,6 +3562,9 @@ comm_point_close(struct comm_point* c)
tcl_close_connection(c->tcl_addr);
if(c->tcp_req_info)
tcp_req_info_clear(c->tcp_req_info);
+ if(c->h2_session)
+ http2_session_server_delete(c->h2_session);
+
/* close fd after removing from event lists, or epoll.. is messed up */
if(c->fd != -1 && !c->do_not_close) {
if(c->type == comm_tcp || c->type == comm_http) {
@@ -3087,11 +3573,7 @@ comm_point_close(struct comm_point* c)
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
}
verbose(VERB_ALGO, "close fd %d", c->fd);
-#ifndef USE_WINSOCK
- close(c->fd);
-#else
- closesocket(c->fd);
-#endif
+ sock_close(c->fd);
}
c->fd = -1;
}
@@ -3107,6 +3589,10 @@ comm_point_delete(struct comm_point* c)
SSL_free(c->ssl);
#endif
}
+ if(c->type == comm_http && c->http_endpoint) {
+ free(c->http_endpoint);
+ c->http_endpoint = NULL;
+ }
comm_point_close(c);
if(c->tcp_handlers) {
int i;
@@ -3125,6 +3611,9 @@ comm_point_delete(struct comm_point* c)
if(c->tcp_req_info) {
tcp_req_info_delete(c->tcp_req_info);
}
+ if(c->h2_session) {
+ http2_session_delete(c->h2_session);
+ }
}
ub_event_free(c->ev->ev);
free(c->ev);
@@ -3170,6 +3659,17 @@ comm_point_send_reply(struct comm_reply *repinfo)
#endif
if(repinfo->c->tcp_req_info) {
tcp_req_info_send_reply(repinfo->c->tcp_req_info);
+ } else if(repinfo->c->use_h2) {
+ if(!http2_submit_dns_response(repinfo->c->h2_session)) {
+ comm_point_drop_reply(repinfo);
+ return;
+ }
+ repinfo->c->h2_stream = NULL;
+ repinfo->c->tcp_is_reading = 0;
+ comm_point_stop_listening(repinfo->c);
+ comm_point_start_listening(repinfo->c, -1,
+ repinfo->c->tcp_timeout_msec);
+ return;
} else {
comm_point_start_listening(repinfo->c, -1,
repinfo->c->tcp_timeout_msec);
@@ -3188,6 +3688,16 @@ comm_point_drop_reply(struct comm_reply* repinfo)
return;
if(repinfo->c->tcp_req_info)
repinfo->c->tcp_req_info->is_drop = 1;
+ if(repinfo->c->type == comm_http) {
+ if(repinfo->c->h2_session) {
+ repinfo->c->h2_session->is_drop = 1;
+ if(!repinfo->c->h2_session->postpone_drop)
+ reclaim_http_handler(repinfo->c);
+ return;
+ }
+ reclaim_http_handler(repinfo->c);
+ return;
+ }
reclaim_tcp_handler(repinfo->c);
}
@@ -3232,11 +3742,7 @@ comm_point_start_listening(struct comm_point* c, int newfd, int msec)
}
if(newfd != -1) {
if(c->fd != -1) {
-#ifndef USE_WINSOCK
- close(c->fd);
-#else
- closesocket(c->fd);
-#endif
+ sock_close(c->fd);
}
c->fd = newfd;
ub_event_set_fd(c->ev->ev, c->fd);
diff --git a/contrib/unbound/util/netevent.h b/contrib/unbound/util/netevent.h
index bb2cd1e53732..6986f881b38a 100644
--- a/contrib/unbound/util/netevent.h
+++ b/contrib/unbound/util/netevent.h
@@ -61,6 +61,9 @@
#define NET_EVENT_H
#include "dnscrypt/dnscrypt.h"
+#ifdef HAVE_NGHTTP2_NGHTTP2_H
+#include <nghttp2/nghttp2.h>
+#endif
struct sldns_buffer;
struct comm_point;
@@ -68,11 +71,16 @@ struct comm_reply;
struct tcl_list;
struct ub_event_base;
+struct mesh_state;
+struct mesh_area;
+
/* internal event notification data storage structure. */
struct internal_event;
struct internal_base;
struct internal_timer; /* A sub struct of the comm_timer super struct */
+enum listen_type;
+
/** callback from communication point function type */
typedef int comm_point_callback_type(struct comm_point*, void*, int,
struct comm_reply*);
@@ -205,6 +213,15 @@ struct comm_point {
} ssl_shake_state;
/* -------- HTTP ------- */
+ /** Do not allow connection to use HTTP version lower than this. 0=no
+ * minimum. */
+ enum {
+ http_version_none = 0,
+ http_version_2 = 2
+ } http_min_version;
+ /** http endpoint */
+ char* http_endpoint;
+ /* -------- HTTP/1.1 ------- */
/** Currently reading in http headers */
int http_in_headers;
/** Currently reading in chunk headers, 0=not, 1=firstline, 2=unused
@@ -216,6 +233,18 @@ struct comm_point {
struct sldns_buffer* http_temp;
/** http stored content in buffer */
size_t http_stored;
+ /* -------- HTTP/2 ------- */
+ /** http2 session */
+ struct http2_session* h2_session;
+ /** set to 1 if h2 is negotiated to be used (using alpn) */
+ int use_h2;
+ /** stream currently being handled */
+ struct http2_stream* h2_stream;
+ /** maximum allowed query buffer size, per stream */
+ size_t http2_stream_max_qbuffer_size;
+ /** maximum number of HTTP/2 streams per connection. Send in HTTP/2
+ * SETTINGS frame. */
+ uint32_t http2_max_streams;
/* -------- dnstap ------- */
/** the dnstap environment */
@@ -456,10 +485,15 @@ struct comm_point* comm_point_create_udp_ancil(struct comm_base* base,
* @param num: becomes max_tcp_count, the routine allocates that
* many tcp handler commpoints.
* @param idle_timeout: TCP idle timeout in ms.
+ * @param harden_large_queries: whether query size should be limited.
+ * @param http_max_streams: maximum number of HTTP/2 streams per connection.
+ * @param http_endpoint: HTTP endpoint to service queries on
* @param tcp_conn_limit: TCP connection limit info.
* @param bufsize: size of buffer to create for handlers.
* @param spoolbuf: shared spool buffer for tcp_req_info structures.
* or NULL to not create those structures in the tcp handlers.
+ * @param port_type: the type of port we are creating a TCP listener for. Used
+ * to select handler type to use.
* @param callback: callback function pointer for TCP handlers.
* @param callback_arg: will be passed to your callback function.
* @return: returns the TCP listener commpoint. You can find the
@@ -468,8 +502,11 @@ struct comm_point* comm_point_create_udp_ancil(struct comm_base* base,
* Inits timeout to NULL. All handlers are on the free list.
*/
struct comm_point* comm_point_create_tcp(struct comm_base* base,
- int fd, int num, int idle_timeout, struct tcl_list* tcp_conn_limit,
+ int fd, int num, int idle_timeout, int harden_large_queries,
+ uint32_t http_max_streams, char* http_endpoint,
+ struct tcl_list* tcp_conn_limit,
size_t bufsize, struct sldns_buffer* spoolbuf,
+ enum listen_type port_type,
comm_point_callback_type* callback, void* callback_arg);
/**
@@ -724,6 +761,110 @@ void comm_point_tcp_handle_callback(int fd, short event, void* arg);
void comm_point_http_handle_callback(int fd, short event, void* arg);
/**
+ * HTTP2 session. HTTP2 related info per comm point.
+ */
+struct http2_session {
+ /** first item in list of streams */
+ struct http2_stream* first_stream;
+#ifdef HAVE_NGHTTP2
+ /** nghttp2 session */
+ nghttp2_session *session;
+ /** store nghttp2 callbacks for easy reuse */
+ nghttp2_session_callbacks* callbacks;
+#endif
+ /** comm point containing buffer used to build answer in worker or
+ * module */
+ struct comm_point* c;
+ /** session is instructed to get dropped (comm port will be closed) */
+ int is_drop;
+ /** postpone dropping the session, can be used to prevent dropping
+ * while being in a callback */
+ int postpone_drop;
+};
+
+/** enum of HTTP status */
+enum http_status {
+ HTTP_STATUS_OK = 200,
+ HTTP_STATUS_BAD_REQUEST = 400,
+ HTTP_STATUS_NOT_FOUND = 404,
+ HTTP_STATUS_PAYLOAD_TOO_LARGE = 413,
+ HTTP_STATUS_URI_TOO_LONG = 414,
+ HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415,
+ HTTP_STATUS_NOT_IMPLEMENTED = 501
+};
+
+/**
+ * HTTP stream. Part of list of HTTP2 streams per session.
+ */
+struct http2_stream {
+ /** next stream in list per session */
+ struct http2_stream* next;
+ /** previous stream in list per session */
+ struct http2_stream* prev;
+ /** HTTP2 stream ID is an unsigned 31-bit integer */
+ int32_t stream_id;
+ /** HTTP method used for this stream */
+ enum {
+ HTTP_METHOD_POST = 1,
+ HTTP_METHOD_GET,
+ HTTP_METHOD_UNSUPPORTED
+ } http_method;
+ /** message contains invalid content type */
+ int invalid_content_type;
+ /** message body content type */
+ size_t content_length;
+ /** HTTP response status */
+ enum http_status status;
+ /** request for non existing endpoint */
+ int invalid_endpoint;
+ /** query in request is too large */
+ int query_too_large;
+ /** buffer to store query into. Can't use session shared buffer as query
+ * can arrive in parts, intertwined with frames for other queries. */
+ struct sldns_buffer* qbuffer;
+ /** buffer to store response into. Can't use shared buffer as a next
+ * query read callback can overwrite it before it is send out. */
+ struct sldns_buffer* rbuffer;
+ /** mesh area containing mesh state */
+ struct mesh_area* mesh;
+ /** mesh state for query. Used to remove mesh reply before closing
+ * stream. */
+ struct mesh_state* mesh_state;
+};
+
+#ifdef HAVE_NGHTTP2
+/** nghttp2 receive cb. Read from SSL connection into nghttp2 buffer */
+ssize_t http2_recv_cb(nghttp2_session* session, uint8_t* buf,
+ size_t len, int flags, void* cb_arg);
+/** nghttp2 send callback. Send from nghttp2 buffer to ssl socket */
+ssize_t http2_send_cb(nghttp2_session* session, const uint8_t* buf,
+ size_t len, int flags, void* cb_arg);
+/** nghttp2 callback on closing stream */
+int http2_stream_close_cb(nghttp2_session* session, int32_t stream_id,
+ uint32_t error_code, void* cb_arg);
+#endif
+
+/**
+ * Create new http2 stream
+ * @param stream_id: ID for stream to create.
+ * @return malloc'ed stream, NULL on error
+ */
+struct http2_stream* http2_stream_create(int32_t stream_id);
+
+/**
+ * Add new stream to session linked list
+ * @param h2_session: http2 session to add stream to
+ * @param h2_stream: stream to add to session list
+ */
+void http2_session_add_stream(struct http2_session* h2_session,
+ struct http2_stream* h2_stream);
+
+/** Add mesh state to stream. To be able to remove mesh reply on stream closure
+ */
+void http2_stream_add_meshstate(struct http2_stream* h2_stream,
+ struct mesh_area* mesh, struct mesh_state* m);
+
+/**
* This routine is published for checks and tests, and is only used internally.
* handle libevent callback for timer comm.
* @param fd: file descriptor (always -1).
diff --git a/contrib/unbound/validator/val_anchor.c b/contrib/unbound/validator/val_anchor.c
index 7224f00a21b6..9b6574c5d24a 100644
--- a/contrib/unbound/validator/val_anchor.c
+++ b/contrib/unbound/validator/val_anchor.c
@@ -1030,8 +1030,6 @@ 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;
@@ -1103,37 +1101,6 @@ anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg)
return 0;
}
}
- if(cfg->dlv_anchor_file && cfg->dlv_anchor_file[0] != 0) {
- struct trust_anchor* dlva;
- nm = cfg->dlv_anchor_file;
- if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
- cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
- nm += strlen(cfg->chrootdir);
- if(!(dlva = anchor_read_file(anchors, parsebuf,
- nm, 1))) {
- log_err("error reading dlv-anchor-file: %s",
- cfg->dlv_anchor_file);
- sldns_buffer_free(parsebuf);
- return 0;
- }
- lock_basic_lock(&anchors->lock);
- anchors->dlv_anchor = dlva;
- lock_basic_unlock(&anchors->lock);
- }
- for(f = cfg->dlv_anchor_list; f; f = f->next) {
- struct trust_anchor* dlva;
- if(!f->str || f->str[0] == 0) /* empty "" */
- continue;
- if(!(dlva = anchor_store_str(
- anchors, parsebuf, f->str))) {
- log_err("error in dlv-anchor: \"%s\"", f->str);
- sldns_buffer_free(parsebuf);
- return 0;
- }
- lock_basic_lock(&anchors->lock);
- anchors->dlv_anchor = dlva;
- lock_basic_unlock(&anchors->lock);
- }
/* do autr last, so that it sees what anchors are filled by other
* means can can print errors about double config for the name */
for(f = cfg->auto_trust_anchor_file_list; f; f = f->next) {
diff --git a/contrib/unbound/validator/val_anchor.h b/contrib/unbound/validator/val_anchor.h
index a2a795d093d2..1597a7d62fbe 100644
--- a/contrib/unbound/validator/val_anchor.h
+++ b/contrib/unbound/validator/val_anchor.h
@@ -67,8 +67,6 @@ struct val_anchors {
* contents of type trust_anchor.
*/
rbtree_type* tree;
- /** The DLV trust anchor (if one is configured, else NULL) */
- struct trust_anchor* dlv_anchor;
/** Autotrust global data, anchors sorted by next probe time */
struct autr_global_data* autr;
};
diff --git a/contrib/unbound/validator/val_neg.c b/contrib/unbound/validator/val_neg.c
index 4c08e6bbc92f..67699b1f7c1e 100644
--- a/contrib/unbound/validator/val_neg.c
+++ b/contrib/unbound/validator/val_neg.c
@@ -965,108 +965,6 @@ static int neg_closest_data(struct val_neg_zone* zone,
}
}
-int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
- uint16_t qclass, struct rrset_cache* rrset_cache, time_t now)
-{
- /* lookup closest zone */
- struct val_neg_zone* zone;
- struct val_neg_data* data;
- int labs;
- struct ub_packed_rrset_key* nsec;
- struct packed_rrset_data* d;
- uint32_t flags;
- uint8_t* wc;
- struct query_info qinfo;
- if(!neg) return 0;
-
- log_nametypeclass(VERB_ALGO, "negcache dlvlookup", qname,
- LDNS_RR_TYPE_DLV, qclass);
-
- labs = dname_count_labels(qname);
- lock_basic_lock(&neg->lock);
- zone = neg_closest_zone_parent(neg, qname, len, labs, qclass);
- while(zone && !zone->in_use)
- zone = zone->parent;
- if(!zone) {
- lock_basic_unlock(&neg->lock);
- return 0;
- }
- log_nametypeclass(VERB_ALGO, "negcache zone", zone->name, 0,
- zone->dclass);
-
- /* DLV is defined to use NSEC only */
- if(zone->nsec3_hash) {
- lock_basic_unlock(&neg->lock);
- return 0;
- }
-
- /* lookup closest data record */
- (void)neg_closest_data(zone, qname, len, labs, &data);
- while(data && !data->in_use)
- data = data->parent;
- if(!data) {
- lock_basic_unlock(&neg->lock);
- return 0;
- }
- log_nametypeclass(VERB_ALGO, "negcache rr", data->name,
- LDNS_RR_TYPE_NSEC, zone->dclass);
-
- /* lookup rrset in rrset cache */
- flags = 0;
- if(query_dname_compare(data->name, zone->name) == 0)
- flags = PACKED_RRSET_NSEC_AT_APEX;
- nsec = rrset_cache_lookup(rrset_cache, data->name, data->len,
- LDNS_RR_TYPE_NSEC, zone->dclass, flags, now, 0);
-
- /* check if secure and TTL ok */
- if(!nsec) {
- lock_basic_unlock(&neg->lock);
- return 0;
- }
- d = (struct packed_rrset_data*)nsec->entry.data;
- if(!d || now > d->ttl) {
- lock_rw_unlock(&nsec->entry.lock);
- /* delete data record if expired */
- neg_delete_data(neg, data);
- lock_basic_unlock(&neg->lock);
- return 0;
- }
- if(d->security != sec_status_secure) {
- lock_rw_unlock(&nsec->entry.lock);
- neg_delete_data(neg, data);
- lock_basic_unlock(&neg->lock);
- return 0;
- }
- verbose(VERB_ALGO, "negcache got secure rrset");
-
- /* check NSEC security */
- /* check if NSEC proves no DLV type exists */
- /* check if NSEC proves NXDOMAIN for qname */
- qinfo.qname = qname;
- qinfo.qtype = LDNS_RR_TYPE_DLV;
- qinfo.qclass = qclass;
- qinfo.local_alias = NULL;
- if(!nsec_proves_nodata(nsec, &qinfo, &wc) &&
- !val_nsec_proves_name_error(nsec, qname)) {
- /* the NSEC is not a denial for the DLV */
- lock_rw_unlock(&nsec->entry.lock);
- lock_basic_unlock(&neg->lock);
- verbose(VERB_ALGO, "negcache not proven");
- return 0;
- }
- /* so the NSEC was a NODATA proof, or NXDOMAIN proof. */
-
- /* no need to check for wildcard NSEC; no wildcards in DLV repos */
- /* no need to lookup SOA record for client; no response message */
-
- lock_rw_unlock(&nsec->entry.lock);
- /* if OK touch the LRU for neg_data element */
- neg_lru_touch(neg, data);
- lock_basic_unlock(&neg->lock);
- verbose(VERB_ALGO, "negcache DLV denial proven");
- return 1;
-}
-
void val_neg_addreferral(struct val_neg_cache* neg, struct reply_info* rep,
uint8_t* zone_name)
{
diff --git a/contrib/unbound/validator/val_neg.h b/contrib/unbound/validator/val_neg.h
index 877f5c944747..5643ca3314a7 100644
--- a/contrib/unbound/validator/val_neg.h
+++ b/contrib/unbound/validator/val_neg.h
@@ -219,26 +219,6 @@ void val_neg_addreferral(struct val_neg_cache* neg, struct reply_info* rep,
uint8_t* zone);
/**
- * Perform a DLV style lookup
- * During the lookup, we could find out that data has expired. In that
- * case the neg_cache entries are removed, and lookup fails.
- *
- * @param neg: negative cache.
- * @param qname: name to look for
- * @param len: length of qname.
- * @param qclass: class to look in.
- * @param rrset_cache: the rrset cache, for NSEC lookups.
- * @param now: current time for ttl checks.
- * @return
- * 0 on error
- * 0 if no proof of negative
- * 1 if indeed negative was proven
- * thus, qname DLV qclass does not exist.
- */
-int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
- uint16_t qclass, struct rrset_cache* rrset_cache, time_t now);
-
-/**
* For the given query, try to get a reply out of the negative cache.
* The reply still needs to be validated.
* @param neg: negative cache.
diff --git a/contrib/unbound/validator/val_nsec.c b/contrib/unbound/validator/val_nsec.c
index a795e77339d3..032d2ae03a42 100644
--- a/contrib/unbound/validator/val_nsec.c
+++ b/contrib/unbound/validator/val_nsec.c
@@ -541,86 +541,3 @@ val_nsec_proves_no_wc(struct ub_packed_rrset_key* nsec, uint8_t* qname,
}
return 0;
}
-
-/**
- * Find shared topdomain that exists
- */
-static void
-dlv_topdomain(struct ub_packed_rrset_key* nsec, uint8_t* qname,
- uint8_t** nm, size_t* nm_len)
-{
- /* make sure reply is part of nm */
- /* take shared topdomain with left of NSEC. */
-
- /* because, if empty nonterminal, then right is subdomain of qname.
- * and any shared topdomain would be empty nonterminals.
- *
- * If nxdomain, then the right is bigger, and could have an
- * interesting shared topdomain, but if it does have one, it is
- * an empty nonterminal. An empty nonterminal shared with the left
- * one. */
- int n;
- uint8_t* common = dname_get_shared_topdomain(qname, nsec->rk.dname);
- n = dname_count_labels(*nm) - dname_count_labels(common);
- dname_remove_labels(nm, nm_len, n);
-}
-
-int val_nsec_check_dlv(struct query_info* qinfo,
- struct reply_info* rep, uint8_t** nm, size_t* nm_len)
-{
- uint8_t* next;
- size_t i, nlen;
- int c;
- /* we should now have a NOERROR/NODATA or NXDOMAIN message */
- if(rep->an_numrrsets != 0) {
- return 0;
- }
- /* is this NOERROR ? */
- if(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR) {
- /* it can be a plain NSEC match - go up one more level. */
- /* or its an empty nonterminal - go up to nonempty level */
- for(i=0; i<rep->ns_numrrsets; i++) {
- if(htons(rep->rrsets[i]->rk.type)!=LDNS_RR_TYPE_NSEC ||
- !nsec_get_next(rep->rrsets[i], &next, &nlen))
- continue;
- c = dname_canonical_compare(
- rep->rrsets[i]->rk.dname, qinfo->qname);
- if(c == 0) {
- /* plain match */
- if(nsec_has_type(rep->rrsets[i],
- LDNS_RR_TYPE_DLV))
- return 0;
- dname_remove_label(nm, nm_len);
- return 1;
- } else if(c < 0 &&
- dname_strict_subdomain_c(next, qinfo->qname)) {
- /* ENT */
- dlv_topdomain(rep->rrsets[i], qinfo->qname,
- nm, nm_len);
- return 1;
- }
- }
- return 0;
- }
-
- /* is this NXDOMAIN ? */
- if(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN) {
- /* find the qname denial NSEC record. It can tell us
- * a closest encloser name; or that we not need bother */
- for(i=0; i<rep->ns_numrrsets; i++) {
- if(htons(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_NSEC)
- continue;
- if(val_nsec_proves_name_error(rep->rrsets[i],
- qinfo->qname)) {
- log_nametypeclass(VERB_ALGO, "topdomain on",
- rep->rrsets[i]->rk.dname,
- ntohs(rep->rrsets[i]->rk.type), 0);
- dlv_topdomain(rep->rrsets[i], qinfo->qname,
- nm, nm_len);
- return 1;
- }
- }
- return 0;
- }
- return 0;
-}
diff --git a/contrib/unbound/validator/val_nsec.h b/contrib/unbound/validator/val_nsec.h
index 4e71257bc35a..7117809d60ae 100644
--- a/contrib/unbound/validator/val_nsec.h
+++ b/contrib/unbound/validator/val_nsec.h
@@ -159,19 +159,6 @@ int val_nsec_proves_no_wc(struct ub_packed_rrset_key* nsec, uint8_t* qname,
size_t qnamelen);
/**
- * Determine the DLV result, what to do with NSEC DLV reply.
- * @param qinfo: what was queried for.
- * @param rep: the nonpositive reply.
- * @param nm: dlv lookup name, to adjust for new lookup name (if needed).
- * @param nm_len: length of lookup name.
- * @return 0 on error, 1 if a higher point is found.
- * If the higher point is above the dlv repo anchor, the qname does
- * not exist.
- */
-int val_nsec_check_dlv(struct query_info* qinfo,
- struct reply_info* rep, uint8_t** nm, size_t* nm_len);
-
-/**
* Determine if an nsec proves an insecure delegation towards the qname.
* @param nsec: nsec rrset.
* @param qinfo: what was queries for.
diff --git a/contrib/unbound/validator/validator.c b/contrib/unbound/validator/validator.c
index c3ca0a27da83..e12180b4bbda 100644
--- a/contrib/unbound/validator/validator.c
+++ b/contrib/unbound/validator/validator.c
@@ -390,10 +390,8 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name,
ask.local_alias = NULL;
log_query_info(VERB_ALGO, "generate request", &ask);
/* enable valrec flag to avoid recursion to the same validation
- * routine, this lookup is simply a lookup. DLVs need validation */
- if(qtype == LDNS_RR_TYPE_DLV)
- valrec = 0;
- else valrec = 1;
+ * routine, this lookup is simply a lookup. */
+ valrec = 1;
fptr_ok(fptr_whitelist_modenv_detect_cycle(qstate->env->detect_cycle));
if((*qstate->env->detect_cycle)(qstate, &ask,
@@ -1585,7 +1583,7 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
vq->key_entry = key_cache_obtain(ve->kcache, lookup_name, lookup_len,
vq->qchase.qclass, qstate->region, *qstate->env->now);
- /* there is no key(from DLV) and no trust anchor */
+ /* there is no key and no trust anchor */
if(vq->key_entry == NULL && anchor == NULL) {
/*response isn't under a trust anchor, so we cannot validate.*/
vq->chase_reply->security = sec_status_indeterminate;
@@ -1603,7 +1601,6 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
val_mark_insecure(vq->chase_reply, anchor->name,
qstate->env->rrset_cache, qstate->env);
lock_basic_unlock(&anchor->lock);
- vq->dlv_checked=1; /* skip DLV check */
/* go to finished state to cache this result */
vq->state = VAL_FINISHED_STATE;
return 1;
@@ -1679,9 +1676,8 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
/* We know that state.key_entry is not 0 or bad key -- if it were,
* then previous processing should have directed this event to
* a different state.
- * It could be an isnull key, which signals that a DLV was just
- * done and the DNSKEY after the DLV failed with dnssec-retry state
- * and the DNSKEY has to be performed again. */
+ * It could be an isnull key, which signals the DNSKEY failed
+ * with retry and has to be looked up again. */
log_assert(vq->key_entry && !key_entry_isbad(vq->key_entry));
if(key_entry_isnull(vq->key_entry)) {
if(!generate_request(qstate, id, vq->ds_rrset->rk.dname,
@@ -1986,148 +1982,6 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
}
/**
- * Init DLV check.
- * DLV is going to be decommissioned, but the code is still here for some time.
- *
- * Called when a query is determined by other trust anchors to be insecure
- * (or indeterminate). Then we look if there is a key in the DLV.
- * Performs aggressive negative cache check to see if there is no key.
- * Otherwise, spawns a DLV query, and changes to the DLV wait state.
- *
- * @param qstate: query state.
- * @param vq: validator query state.
- * @param ve: validator shared global environment.
- * @param id: module id.
- * @return true if there is no DLV.
- * false: processing is finished for the validator operate().
- * This function may exit in three ways:
- * o no DLV (aggressive cache), so insecure. (true)
- * o error - stop processing (false)
- * o DLV lookup was started, stop processing (false)
- */
-static int
-val_dlv_init(struct module_qstate* qstate, struct val_qstate* vq,
- struct val_env* ve, int id)
-{
- uint8_t* nm;
- size_t nm_len;
- struct module_qstate* newq = NULL;
- /* there must be a DLV configured */
- log_assert(qstate->env->anchors->dlv_anchor);
- /* this bool is true to avoid looping in the DLV checks */
- log_assert(vq->dlv_checked);
-
- /* init the DLV lookup variables */
- vq->dlv_lookup_name = NULL;
- vq->dlv_lookup_name_len = 0;
- vq->dlv_insecure_at = NULL;
- vq->dlv_insecure_at_len = 0;
-
- /* Determine the name for which we want to lookup DLV.
- * This name is for the current message, or
- * for the current RRset for CNAME, referral subtypes.
- * If there is a signer, use that, otherwise the domain name */
- if(vq->signer_name) {
- nm = vq->signer_name;
- nm_len = vq->signer_len;
- } else {
- /* use qchase */
- nm = vq->qchase.qname;
- nm_len = vq->qchase.qname_len;
- if(vq->qchase.qtype == LDNS_RR_TYPE_DS)
- dname_remove_label(&nm, &nm_len);
- }
- log_nametypeclass(VERB_ALGO, "DLV init look", nm, LDNS_RR_TYPE_DS,
- vq->qchase.qclass);
- log_assert(nm && nm_len);
- /* sanity check: no DLV lookups below the DLV anchor itself.
- * Like, an securely insecure delegation there makes no sense. */
- if(dname_subdomain_c(nm, qstate->env->anchors->dlv_anchor->name)) {
- verbose(VERB_ALGO, "DLV lookup within DLV repository denied");
- return 1;
- }
- /* concat name (minus root label) + dlv name */
- vq->dlv_lookup_name_len = nm_len - 1 +
- qstate->env->anchors->dlv_anchor->namelen;
- vq->dlv_lookup_name = regional_alloc(qstate->region,
- vq->dlv_lookup_name_len);
- if(!vq->dlv_lookup_name) {
- log_err("Out of memory preparing DLV lookup");
- return val_error(qstate, id);
- }
- memmove(vq->dlv_lookup_name, nm, nm_len-1);
- memmove(vq->dlv_lookup_name+nm_len-1,
- qstate->env->anchors->dlv_anchor->name,
- qstate->env->anchors->dlv_anchor->namelen);
- log_nametypeclass(VERB_ALGO, "DLV name", vq->dlv_lookup_name,
- LDNS_RR_TYPE_DLV, vq->qchase.qclass);
-
- /* determine where the insecure point was determined, the DLV must
- * be equal or below that to continue building the trust chain
- * down. May be NULL if no trust chain was built yet */
- nm = NULL;
- if(vq->key_entry && key_entry_isnull(vq->key_entry)) {
- nm = vq->key_entry->name;
- nm_len = vq->key_entry->namelen;
- }
- if(nm) {
- vq->dlv_insecure_at_len = nm_len - 1 +
- qstate->env->anchors->dlv_anchor->namelen;
- vq->dlv_insecure_at = regional_alloc(qstate->region,
- vq->dlv_insecure_at_len);
- if(!vq->dlv_insecure_at) {
- log_err("Out of memory preparing DLV lookup");
- return val_error(qstate, id);
- }
- memmove(vq->dlv_insecure_at, nm, nm_len-1);
- memmove(vq->dlv_insecure_at+nm_len-1,
- qstate->env->anchors->dlv_anchor->name,
- qstate->env->anchors->dlv_anchor->namelen);
- log_nametypeclass(VERB_ALGO, "insecure_at",
- vq->dlv_insecure_at, 0, vq->qchase.qclass);
- }
-
- /* If we can find the name in the aggressive negative cache,
- * give up; insecure is the answer */
- while(val_neg_dlvlookup(ve->neg_cache, vq->dlv_lookup_name,
- vq->dlv_lookup_name_len, vq->qchase.qclass,
- qstate->env->rrset_cache, *qstate->env->now)) {
- /* go up */
- dname_remove_label(&vq->dlv_lookup_name,
- &vq->dlv_lookup_name_len);
- /* too high? */
- if(!dname_subdomain_c(vq->dlv_lookup_name,
- qstate->env->anchors->dlv_anchor->name)) {
- verbose(VERB_ALGO, "ask above dlv repo");
- return 1; /* Above the repo is insecure */
- }
- /* above chain of trust? */
- if(vq->dlv_insecure_at && !dname_subdomain_c(
- vq->dlv_lookup_name, vq->dlv_insecure_at)) {
- verbose(VERB_ALGO, "ask above insecure endpoint");
- return 1;
- }
- }
-
- /* perform a lookup for the DLV; with validation */
- vq->state = VAL_DLVLOOKUP_STATE;
- if(!generate_request(qstate, id, vq->dlv_lookup_name,
- vq->dlv_lookup_name_len, LDNS_RR_TYPE_DLV,
- vq->qchase.qclass, 0, &newq, 0)) {
- return val_error(qstate, id);
- }
-
- /* Find the closest encloser DLV from the repository.
- * then that is used to build another chain of trust
- * This may first require a query 'too low' that has NSECs in
- * the answer, from which we determine the closest encloser DLV.
- * When determine the closest encloser, skip empty nonterminals,
- * since we want a nonempty node in the DLV repository. */
-
- return 0;
-}
-
-/**
* The Finished state. The validation status (good or bad) has been determined.
*
* @param qstate: query state.
@@ -2145,16 +1999,6 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
qstate->query_flags, &qstate->qinfo, &vq->qchase,
vq->orig_msg->rep, vq->rrset_skip);
- /* if the result is insecure or indeterminate and we have not
- * checked the DLV yet, check the DLV */
- if((vq->chase_reply->security == sec_status_insecure ||
- vq->chase_reply->security == sec_status_indeterminate) &&
- qstate->env->anchors->dlv_anchor && !vq->dlv_checked) {
- vq->dlv_checked = 1;
- if(!val_dlv_init(qstate, vq, ve, id))
- return 0;
- }
-
/* store overall validation result in orig_msg */
if(vq->rrset_skip == 0)
vq->orig_msg->rep->security = vq->chase_reply->security;
@@ -2177,7 +2021,6 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
/* and restart for this rrset */
verbose(VERB_ALGO, "validator: go to next rrset");
vq->chase_reply->security = sec_status_unchecked;
- vq->dlv_checked = 0; /* can do DLV for this RR */
vq->state = VAL_INIT_STATE;
return 1;
}
@@ -2195,7 +2038,6 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
log_query_info(VERB_ALGO, "validator: chased to",
&vq->qchase);
vq->chase_reply->security = sec_status_unchecked;
- vq->dlv_checked = 0; /* can do DLV for this RR */
vq->state = VAL_INIT_STATE;
return 1;
}
@@ -2321,119 +2163,6 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
return 0;
}
-/**
- * The DLVLookup state. Process DLV lookups.
- *
- * @param qstate: query state.
- * @param vq: validator query state.
- * @param ve: validator shared global environment.
- * @param id: module id.
- * @return true if the event should be processed further on return, false if
- * not.
- */
-static int
-processDLVLookup(struct module_qstate* qstate, struct val_qstate* vq,
- struct val_env* ve, int id)
-{
- struct module_qstate* newq = NULL;
- /* see if this we are ready to continue normal resolution */
- /* we may need more DLV lookups */
- if(vq->dlv_status==dlv_error)
- verbose(VERB_ALGO, "DLV woke up with status dlv_error");
- else if(vq->dlv_status==dlv_success)
- verbose(VERB_ALGO, "DLV woke up with status dlv_success");
- else if(vq->dlv_status==dlv_ask_higher)
- verbose(VERB_ALGO, "DLV woke up with status dlv_ask_higher");
- else if(vq->dlv_status==dlv_there_is_no_dlv)
- verbose(VERB_ALGO, "DLV woke up with status dlv_there_is_no_dlv");
- else verbose(VERB_ALGO, "DLV woke up with status unknown");
-
- if(vq->dlv_status == dlv_error) {
- verbose(VERB_QUERY, "failed DLV lookup");
- errinf(qstate, "failed DLV lookup");
- return val_error(qstate, id);
- } else if(vq->dlv_status == dlv_success) {
- uint8_t* nm;
- size_t nmlen;
- /* chain continues with DNSKEY, continue in FINDKEY */
- vq->state = VAL_FINDKEY_STATE;
-
- /* strip off the DLV suffix from the name; could result in . */
- log_assert(dname_subdomain_c(vq->ds_rrset->rk.dname,
- qstate->env->anchors->dlv_anchor->name));
- nmlen = vq->ds_rrset->rk.dname_len -
- qstate->env->anchors->dlv_anchor->namelen + 1;
- nm = regional_alloc_init(qstate->region,
- vq->ds_rrset->rk.dname, nmlen);
- if(!nm) {
- log_err("Out of memory in DLVLook");
- return val_error(qstate, id);
- }
- nm[nmlen-1] = 0;
-
- vq->ds_rrset->rk.dname = nm;
- vq->ds_rrset->rk.dname_len = nmlen;
-
- /* create a nullentry for the key so the dnskey lookup
- * can be retried after a validation failure for it */
- vq->key_entry = key_entry_create_null(qstate->region,
- nm, nmlen, vq->qchase.qclass, 0, 0);
- if(!vq->key_entry) {
- log_err("Out of memory in DLVLook");
- return val_error(qstate, id);
- }
-
- if(!generate_request(qstate, id, vq->ds_rrset->rk.dname,
- vq->ds_rrset->rk.dname_len, LDNS_RR_TYPE_DNSKEY,
- vq->qchase.qclass, BIT_CD, &newq, 0)) {
- verbose(VERB_ALGO, "error generating DNSKEY request");
- return val_error(qstate, id);
- }
- return 0;
- } else if(vq->dlv_status == dlv_there_is_no_dlv) {
- /* continue with the insecure result we got */
- vq->state = VAL_FINISHED_STATE;
- return 1;
- }
- log_assert(vq->dlv_status == dlv_ask_higher);
-
- /* ask higher, make sure we stay in DLV repo, below dlv_at */
- if(!dname_subdomain_c(vq->dlv_lookup_name,
- qstate->env->anchors->dlv_anchor->name)) {
- /* just like, there is no DLV */
- verbose(VERB_ALGO, "ask above dlv repo");
- vq->state = VAL_FINISHED_STATE;
- return 1;
- }
- if(vq->dlv_insecure_at && !dname_subdomain_c(vq->dlv_lookup_name,
- vq->dlv_insecure_at)) {
- /* already checked a chain lower than dlv_lookup_name */
- verbose(VERB_ALGO, "ask above insecure endpoint");
- log_nametypeclass(VERB_ALGO, "enpt", vq->dlv_insecure_at, 0, 0);
- vq->state = VAL_FINISHED_STATE;
- return 1;
- }
-
- /* check negative cache before making new request */
- if(val_neg_dlvlookup(ve->neg_cache, vq->dlv_lookup_name,
- vq->dlv_lookup_name_len, vq->qchase.qclass,
- qstate->env->rrset_cache, *qstate->env->now)) {
- /* does not exist, go up one (go higher). */
- dname_remove_label(&vq->dlv_lookup_name,
- &vq->dlv_lookup_name_len);
- /* limit number of labels, limited number of recursion */
- return processDLVLookup(qstate, vq, ve, id);
- }
-
- if(!generate_request(qstate, id, vq->dlv_lookup_name,
- vq->dlv_lookup_name_len, LDNS_RR_TYPE_DLV,
- vq->qchase.qclass, 0, &newq, 0)) {
- return val_error(qstate, id);
- }
-
- return 0;
-}
-
/**
* Handle validator state.
* If a method returns true, the next state is started. If false, then
@@ -2464,9 +2193,6 @@ val_handle(struct module_qstate* qstate, struct val_qstate* vq,
case VAL_FINISHED_STATE:
cont = processFinished(qstate, vq, ve, id);
break;
- case VAL_DLVLOOKUP_STATE:
- cont = processDLVLookup(qstate, vq, ve, id);
- break;
default:
log_warn("validator: invalid state %d",
vq->state);
@@ -3105,99 +2831,6 @@ process_prime_response(struct module_qstate* qstate, struct val_qstate* vq,
/* the qstate will be reactivated after inform_super is done */
}
-/**
- * Process DLV response. Called from inform_supers.
- * Because it is in inform_supers, the mesh itself is busy doing callbacks
- * for a state that is to be deleted soon; don't touch the mesh; instead
- * set a state in the super, as the super will be reactivated soon.
- * Perform processing to determine what state to set in the super.
- *
- * @param qstate: query state that is validating and asked for a DLV.
- * @param vq: validator query state
- * @param id: module id.
- * @param rcode: rcode result value.
- * @param msg: result message (if rcode is OK).
- * @param qinfo: from the sub query state, query info.
- */
-static void
-process_dlv_response(struct module_qstate* qstate, struct val_qstate* vq,
- int id, int rcode, struct dns_msg* msg, struct query_info* qinfo)
-{
- struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
-
- verbose(VERB_ALGO, "process dlv response to super");
- if(rcode != LDNS_RCODE_NOERROR) {
- /* lookup failed, set in vq to give up */
- vq->dlv_status = dlv_error;
- verbose(VERB_ALGO, "response is error");
- return;
- }
- if(msg->rep->security != sec_status_secure) {
- vq->dlv_status = dlv_error;
- verbose(VERB_ALGO, "response is not secure, %s",
- sec_status_to_string(msg->rep->security));
- return;
- }
- /* was the lookup a success? validated DLV? */
- if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NOERROR &&
- msg->rep->an_numrrsets == 1 &&
- msg->rep->security == sec_status_secure &&
- ntohs(msg->rep->rrsets[0]->rk.type) == LDNS_RR_TYPE_DLV &&
- ntohs(msg->rep->rrsets[0]->rk.rrset_class) == qinfo->qclass &&
- query_dname_compare(msg->rep->rrsets[0]->rk.dname,
- vq->dlv_lookup_name) == 0) {
- /* yay! it is just like a DS */
- vq->ds_rrset = (struct ub_packed_rrset_key*)
- regional_alloc_init(qstate->region,
- msg->rep->rrsets[0], sizeof(*vq->ds_rrset));
- if(!vq->ds_rrset) {
- log_err("out of memory in process_dlv");
- return;
- }
- vq->ds_rrset->entry.key = vq->ds_rrset;
- vq->ds_rrset->rk.dname = (uint8_t*)regional_alloc_init(
- qstate->region, vq->ds_rrset->rk.dname,
- vq->ds_rrset->rk.dname_len);
- if(!vq->ds_rrset->rk.dname) {
- log_err("out of memory in process_dlv");
- vq->dlv_status = dlv_error;
- return;
- }
- vq->ds_rrset->entry.data = regional_alloc_init(qstate->region,
- vq->ds_rrset->entry.data,
- packed_rrset_sizeof(vq->ds_rrset->entry.data));
- if(!vq->ds_rrset->entry.data) {
- log_err("out of memory in process_dlv");
- vq->dlv_status = dlv_error;
- return;
- }
- packed_rrset_ptr_fixup(vq->ds_rrset->entry.data);
- /* make vq do a DNSKEY query next up */
- vq->dlv_status = dlv_success;
- return;
- }
- /* store NSECs into negative cache */
- val_neg_addreply(ve->neg_cache, msg->rep);
-
- /* was the lookup a failure?
- * if we have to go up into the DLV for a higher DLV anchor
- * then set this in the vq, so it can make queries when activated.
- * See if the NSECs indicate that we should look for higher DLV
- * or, that there is no DLV securely */
- if(!val_nsec_check_dlv(qinfo, msg->rep, &vq->dlv_lookup_name,
- &vq->dlv_lookup_name_len)) {
- vq->dlv_status = dlv_error;
- verbose(VERB_ALGO, "nsec error");
- return;
- }
- if(!dname_subdomain_c(vq->dlv_lookup_name,
- qstate->env->anchors->dlv_anchor->name)) {
- vq->dlv_status = dlv_there_is_no_dlv;
- return;
- }
- vq->dlv_status = dlv_ask_higher;
-}
-
/*
* inform validator super.
*
@@ -3233,10 +2866,6 @@ val_inform_super(struct module_qstate* qstate, int id,
qstate->return_msg, &qstate->qinfo,
qstate->reply_origin);
return;
- } else if(qstate->qinfo.qtype == LDNS_RR_TYPE_DLV) {
- process_dlv_response(super, vq, id, qstate->return_rcode,
- qstate->return_msg, &qstate->qinfo);
- return;
}
log_err("internal error in validator: no inform_supers possible");
}
@@ -3284,7 +2913,6 @@ val_state_to_string(enum val_state state)
case VAL_FINDKEY_STATE: return "VAL_FINDKEY_STATE";
case VAL_VALIDATE_STATE: return "VAL_VALIDATE_STATE";
case VAL_FINISHED_STATE: return "VAL_FINISHED_STATE";
- case VAL_DLVLOOKUP_STATE: return "VAL_DLVLOOKUP_STATE";
}
return "UNKNOWN VALIDATOR STATE";
}
diff --git a/contrib/unbound/validator/validator.h b/contrib/unbound/validator/validator.h
index 9e4c8a9414a1..35da1920aa39 100644
--- a/contrib/unbound/validator/validator.h
+++ b/contrib/unbound/validator/validator.h
@@ -137,8 +137,6 @@ enum val_state {
VAL_VALIDATE_STATE,
/** finish up */
VAL_FINISHED_STATE,
- /** DLV lookup state, processing DLV queries */
- VAL_DLVLOOKUP_STATE
};
/**
@@ -217,27 +215,6 @@ struct val_qstate {
/** true if this state is waiting to prime a trust anchor */
int wait_prime_ta;
-
- /** have we already checked the DLV? */
- int dlv_checked;
- /** The name for which the DLV is looked up. For the current message
- * or for the current RRset (for CNAME, REFERRAL types).
- * If there is signer name, that may be it, else a domain name */
- uint8_t* dlv_lookup_name;
- /** length of dlv lookup name */
- size_t dlv_lookup_name_len;
- /** Name at which chain of trust stopped with insecure, starting DLV
- * DLV must result in chain going further down */
- uint8_t* dlv_insecure_at;
- /** length of dlv insecure point name */
- size_t dlv_insecure_at_len;
- /** status of DLV lookup. Indication to VAL_DLV_STATE what to do */
- enum dlv_status {
- dlv_error, /* server failure */
- dlv_success, /* got a DLV */
- dlv_ask_higher, /* ask again */
- dlv_there_is_no_dlv /* got no DLV, sure of it */
- } dlv_status;
};
/**
diff --git a/usr.sbin/unbound/config.h b/usr.sbin/unbound/config.h
index 3bfd70094320..350d0670cb68 100644
--- a/usr.sbin/unbound/config.h
+++ b/usr.sbin/unbound/config.h
@@ -30,6 +30,9 @@
/* Whether daemon is deprecated */
/* #undef DEPRECATED_DAEMON */
+/* Define this to enable kernel based UDP source port randomization. */
+/* #undef DISABLE_EXPLICIT_PORT_RANDOMISATION */
+
/* default dnstap socket path */
/* #undef DNSTAP_SOCKET_PATH */
@@ -65,6 +68,15 @@
/* Whether the C compiler accepts the "weak" attribute */
#define HAVE_ATTR_WEAK 1
+/* If we have be64toh */
+/* #undef HAVE_BE64TOH */
+
+/* Define to 1 if you have the <bsd/stdlib.h> header file. */
+/* #undef HAVE_BSD_STDLIB_H */
+
+/* Define to 1 if you have the <bsd/string.h> header file. */
+/* #undef HAVE_BSD_STRING_H */
+
/* Define to 1 if you have the `chown' function. */
#define HAVE_CHOWN 1
@@ -103,6 +115,10 @@
don't. */
#define HAVE_DECL_INET_PTON 1
+/* Define to 1 if you have the declaration of `nghttp2_session_server_new',
+ and to 0 if you don't. */
+/* #undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW */
+
/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
don't. */
#define HAVE_DECL_NID_ED25519 1
@@ -169,6 +185,9 @@
/* Define to 1 if you have the `endservent' function. */
#define HAVE_ENDSERVENT 1
+/* Define to 1 if you have the `ENGINE_cleanup' function. */
+/* #undef HAVE_ENGINE_CLEANUP */
+
/* Define to 1 if you have the `ERR_free_strings' function. */
#define HAVE_ERR_FREE_STRINGS 1
@@ -208,6 +227,9 @@
/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
/* #undef HAVE_EVP_ENCRYPTINIT_EX */
+/* Define to 1 if you have the `EVP_MAC_CTX_set_params' function. */
+/* #undef HAVE_EVP_MAC_CTX_SET_PARAMS */
+
/* Define to 1 if you have the `EVP_MD_CTX_new' function. */
/* #undef HAVE_EVP_MD_CTX_NEW */
@@ -256,6 +278,9 @@
/* Define to 1 if you have the `getentropy' function. */
/* #undef HAVE_GETENTROPY */
+/* Define to 1 if you have the `getifaddrs' function. */
+#define HAVE_GETIFADDRS 1
+
/* Define to 1 if you have the <getopt.h> header file. */
#define HAVE_GETOPT_H 1
@@ -283,8 +308,11 @@
/* Define to 1 if you have the `HMAC_Init_ex' function. */
#define HAVE_HMAC_INIT_EX 1
-/* If you have HMAC_Update */
-#define HAVE_HMAC_UPDATE 1
+/* If we have htobe64 */
+/* #undef HAVE_HTOBE64 */
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#define HAVE_IFADDRS_H 1
/* Define to 1 if you have the `inet_aton' function. */
#define HAVE_INET_ATON 1
@@ -313,6 +341,9 @@
/* Define to 1 if you have the `kill' function. */
#define HAVE_KILL 1
+/* Use portable libbsd functions */
+/* #undef HAVE_LIBBSD */
+
/* Define to 1 if you have the <libkern/OSByteOrder.h> header file. */
/* #undef HAVE_LIBKERN_OSBYTEORDER_H */
@@ -352,6 +383,15 @@
/* Define to 1 if you have the <nettle/eddsa.h> header file. */
/* #undef HAVE_NETTLE_EDDSA_H */
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define this to use nghttp2 client. */
+/* #undef HAVE_NGHTTP2 */
+
+/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
+/* #undef HAVE_NGHTTP2_NGHTTP2_H */
+
/* Use libnss for crypto */
/* #undef HAVE_NSS */
@@ -367,6 +407,9 @@
/* 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/core_names.h> header file. */
+/* #undef HAVE_OPENSSL_CORE_NAMES_H */
+
/* Define to 1 if you have the <openssl/dh.h> header file. */
#define HAVE_OPENSSL_DH_H 1
@@ -475,14 +518,18 @@
/* Define if you have the SSL libraries installed. */
#define HAVE_SSL /**/
+/* Define to 1 if you have the `SSL_CTX_set_alpn_select_cb' function. */
+#define HAVE_SSL_CTX_SET_ALPN_SELECT_CB 1
+
/* Define to 1 if you have the `SSL_CTX_set_ciphersuites' function. */
/* #undef HAVE_SSL_CTX_SET_CIPHERSUITES */
/* Define to 1 if you have the `SSL_CTX_set_security_level' function. */
/* #undef HAVE_SSL_CTX_SET_SECURITY_LEVEL */
-/* Define to 1 if you have the `SSL_CTX_set_tlsext_ticket_key_cb' function. */
-/* #undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_CB */
+/* Define to 1 if you have the `SSL_CTX_set_tlsext_ticket_key_evp_cb'
+ function. */
+/* #undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB */
/* Define to 1 if you have the `SSL_get0_peername' function. */
/* #undef HAVE_SSL_GET0_PEERNAME */
@@ -550,6 +597,9 @@
/* Define to 1 if you have the <sys/resource.h> header file. */
#define HAVE_SYS_RESOURCE_H 1
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
/* Define to 1 if you have the <sys/sha2.h> header file. */
/* #undef HAVE_SYS_SHA2_H */
@@ -577,6 +627,9 @@
/* Define to 1 if you have the <sys/wait.h> header file. */
#define HAVE_SYS_WAIT_H 1
+/* Define to 1 if you have the <TargetConditionals.h> header file. */
+/* #undef HAVE_TARGETCONDITIONALS_H */
+
/* Define to 1 if you have the <time.h> header file. */
#define HAVE_TIME_H 1
@@ -678,7 +731,7 @@
#define PACKAGE_NAME "unbound"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "unbound 1.10.1"
+#define PACKAGE_STRING "unbound 1.12.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "unbound"
@@ -687,7 +740,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.11.0"
+#define PACKAGE_VERSION "1.12.0"
/* default pidfile location */
#define PIDFILE "/var/unbound/unbound.pid"
@@ -709,7 +762,7 @@
#define ROOT_CERT_FILE "/var/unbound/icannbundle.pem"
/* version number for resource files */
-#define RSRC_PACKAGE_VERSION 1,11,0,0
+#define RSRC_PACKAGE_VERSION 1,12,0,0
/* Directory to chdir to */
#define RUN_DIR "/var/unbound"
@@ -800,6 +853,9 @@
/* Define to 1 to use ipset support */
/* #undef USE_IPSET */
+/* Define if you enable libevent */
+#define USE_LIBEVENT 1
+
/* Define if you want to use internal select based events */
#define USE_MINI_EVENT 1
@@ -849,6 +905,9 @@
/* the version of the windows API enabled */
#define WINVER 0x0502
+/* Define if you want dynlib module. */
+/* #undef WITH_DYNLIBMODULE */
+
/* Define if you want Python module. */
/* #undef WITH_PYTHONMODULE */
@@ -1241,6 +1300,11 @@ char *strptime(const char *s, const char *format, struct tm *tm);
void *reallocarray(void *ptr, size_t nmemb, size_t size);
#endif
+#ifdef HAVE_LIBBSD
+#include <bsd/string.h>
+#include <bsd/stdlib.h>
+#endif
+
#ifdef HAVE_LIBRESSL
# if !HAVE_DECL_STRLCPY
size_t strlcpy(char *dst, const char *src, size_t siz);
@@ -1329,6 +1393,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
#define UNBOUND_DNS_PORT 53
/** default port for DNS over TLS traffic. */
#define UNBOUND_DNS_OVER_TLS_PORT 853
+/** default port for DNS over HTTPS traffic. */
+#define UNBOUND_DNS_OVER_HTTPS_PORT 443
/** default port for unbound control traffic, registered port with IANA,
ub-dns-control 8953/tcp unbound dns nameserver control */
#define UNBOUND_CONTROL_PORT 8953