aboutsummaryrefslogtreecommitdiff
path: root/contrib/unbound
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2018-05-12 15:20:39 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2018-05-12 15:20:39 +0000
commit0fb349906ef68608577702ca46e86aafdd7456b2 (patch)
treefe60861b9872307bc1d5cc628519abd19de3bade /contrib/unbound
parent57bddd215c419a01611bca0d1b1d545a64a7e731 (diff)
parent4289761a7b61df4b64c11ada446a187df61e6a1e (diff)
downloadsrc-0fb349906ef68608577702ca46e86aafdd7456b2.tar.gz
src-0fb349906ef68608577702ca46e86aafdd7456b2.zip
Upgrade Unbound to 1.7.1.
Notes
Notes: svn path=/head/; revision=333568
Diffstat (limited to 'contrib/unbound')
-rw-r--r--contrib/unbound/Makefile.in54
-rw-r--r--contrib/unbound/cachedb/cachedb.c23
-rw-r--r--contrib/unbound/cachedb/cachedb.h2
-rw-r--r--contrib/unbound/cachedb/redis.c283
-rw-r--r--contrib/unbound/cachedb/redis.h45
-rw-r--r--contrib/unbound/config.h31
-rw-r--r--contrib/unbound/config.h.in25
-rwxr-xr-xcontrib/unbound/configure139
-rw-r--r--contrib/unbound/configure.ac62
-rw-r--r--contrib/unbound/contrib/README3
-rw-r--r--contrib/unbound/contrib/fastrpz.patch2
-rw-r--r--contrib/unbound/contrib/unbound-querycachedb.py77
-rw-r--r--contrib/unbound/daemon/daemon.c2
-rw-r--r--contrib/unbound/daemon/remote.c56
-rw-r--r--contrib/unbound/daemon/stats.c45
-rw-r--r--contrib/unbound/daemon/worker.c84
-rw-r--r--contrib/unbound/doc/Changelog139
-rw-r--r--contrib/unbound/doc/README2
-rw-r--r--contrib/unbound/doc/example.conf38
-rw-r--r--contrib/unbound/doc/example.conf.in38
-rw-r--r--contrib/unbound/doc/libunbound.34
-rw-r--r--contrib/unbound/doc/libunbound.3.in4
-rw-r--r--contrib/unbound/doc/unbound-anchor.82
-rw-r--r--contrib/unbound/doc/unbound-anchor.8.in2
-rw-r--r--contrib/unbound/doc/unbound-checkconf.82
-rw-r--r--contrib/unbound/doc/unbound-checkconf.8.in2
-rw-r--r--contrib/unbound/doc/unbound-control.829
-rw-r--r--contrib/unbound/doc/unbound-control.8.in29
-rw-r--r--contrib/unbound/doc/unbound-host.12
-rw-r--r--contrib/unbound/doc/unbound-host.1.in2
-rw-r--r--contrib/unbound/doc/unbound.84
-rw-r--r--contrib/unbound/doc/unbound.8.in4
-rw-r--r--contrib/unbound/doc/unbound.conf.5119
-rw-r--r--contrib/unbound/doc/unbound.conf.5.in119
-rw-r--r--contrib/unbound/iterator/iter_delegpt.c34
-rw-r--r--contrib/unbound/iterator/iter_delegpt.h8
-rw-r--r--contrib/unbound/iterator/iter_fwd.c6
-rw-r--r--contrib/unbound/iterator/iter_hints.c6
-rw-r--r--contrib/unbound/iterator/iter_utils.c25
-rw-r--r--contrib/unbound/iterator/iter_utils.h14
-rw-r--r--contrib/unbound/iterator/iterator.c44
-rw-r--r--contrib/unbound/libunbound/libworker.c18
-rw-r--r--contrib/unbound/libunbound/libworker.h2
-rw-r--r--contrib/unbound/libunbound/unbound.h10
-rw-r--r--contrib/unbound/libunbound/worker.h10
-rw-r--r--contrib/unbound/services/authzone.c653
-rw-r--r--contrib/unbound/services/authzone.h50
-rw-r--r--contrib/unbound/services/cache/dns.c48
-rw-r--r--contrib/unbound/services/cache/rrset.c2
-rw-r--r--contrib/unbound/services/listen_dnsport.c48
-rw-r--r--contrib/unbound/services/mesh.c17
-rw-r--r--contrib/unbound/services/outside_network.c39
-rw-r--r--contrib/unbound/services/outside_network.h9
-rw-r--r--contrib/unbound/sldns/keyraw.c29
-rw-r--r--contrib/unbound/sldns/keyraw.h9
-rw-r--r--contrib/unbound/sldns/str2wire.c13
-rw-r--r--contrib/unbound/smallapp/unbound-control.c12
-rw-r--r--contrib/unbound/smallapp/worker_cb.c4
-rw-r--r--contrib/unbound/util/config_file.c32
-rw-r--r--contrib/unbound/util/config_file.h18
-rw-r--r--contrib/unbound/util/configlexer.lex9
-rw-r--r--contrib/unbound/util/configparser.y100
-rw-r--r--contrib/unbound/util/data/dname.c23
-rw-r--r--contrib/unbound/util/data/dname.h11
-rw-r--r--contrib/unbound/util/data/msgparse.c34
-rw-r--r--contrib/unbound/util/data/msgreply.c5
-rw-r--r--contrib/unbound/util/data/packed_rrset.c1
-rw-r--r--contrib/unbound/util/data/packed_rrset.h4
-rw-r--r--contrib/unbound/util/fptr_wlist.c3
-rw-r--r--contrib/unbound/util/fptr_wlist.h3
-rw-r--r--contrib/unbound/util/iana_ports.inc1
-rw-r--r--contrib/unbound/util/module.h4
-rw-r--r--contrib/unbound/util/net_help.c58
-rw-r--r--contrib/unbound/util/net_help.h16
-rw-r--r--contrib/unbound/util/netevent.c22
-rw-r--r--contrib/unbound/util/tube.c10
-rw-r--r--contrib/unbound/util/ub_event.c8
-rw-r--r--contrib/unbound/validator/val_anchor.c41
-rw-r--r--contrib/unbound/validator/val_anchor.h15
-rw-r--r--contrib/unbound/validator/val_neg.c14
-rw-r--r--contrib/unbound/validator/val_neg.h6
-rw-r--r--contrib/unbound/validator/val_secalgo.c16
-rw-r--r--contrib/unbound/validator/validator.c54
-rw-r--r--contrib/unbound/validator/validator.h7
84 files changed, 2828 insertions, 271 deletions
diff --git a/contrib/unbound/Makefile.in b/contrib/unbound/Makefile.in
index 923bb4fd7372..362d6a716612 100644
--- a/contrib/unbound/Makefile.in
+++ b/contrib/unbound/Makefile.in
@@ -112,7 +112,7 @@ iterator/iter_scrub.c iterator/iter_utils.c services/listen_dnsport.c \
services/localzone.c services/mesh.c services/modstack.c services/view.c \
services/outbound_list.c services/outside_network.c util/alloc.c \
util/config_file.c util/configlexer.c util/configparser.c \
-util/shm_side/shm_main.c services/authzone.c\
+util/shm_side/shm_main.c services/authzone.c \
util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \
util/rtt.c util/storage/dnstree.c util/storage/lookup3.c \
@@ -124,7 +124,7 @@ validator/val_nsec3.c validator/val_nsec.c validator/val_secalgo.c \
validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \
edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \
edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \
-cachedb/cachedb.c respip/respip.c $(CHECKLOCK_SRC) \
+cachedb/cachedb.c cachedb/redis.c respip/respip.c $(CHECKLOCK_SRC) \
$(DNSTAP_SRC) $(DNSCRYPT_SRC) $(IPSECMOD_SRC)
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
@@ -135,7 +135,7 @@ fptr_wlist.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \
slabhash.lo timehist.lo tube.lo winsock_event.lo autotrust.lo val_anchor.lo \
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
-val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo authzone.lo\
+val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo redis.lo authzone.lo \
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
$(IPSECMOD_OBJ) respip.lo
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
@@ -645,7 +645,8 @@ infra.lo infra.o: $(srcdir)/services/cache/infra.c config.h $(srcdir)/sldns/rrde
rrset.lo rrset.o: $(srcdir)/services/cache/rrset.c config.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/regional.h $(srcdir)/util/alloc.h
+ $(srcdir)/util/config_file.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/regional.h $(srcdir)/util/alloc.h \
+ $(srcdir)/util/net_help.h
as112.lo as112.o: $(srcdir)/util/as112.c $(srcdir)/util/as112.h
dname.lo dname.o: $(srcdir)/util/data/dname.c config.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.h \
@@ -882,7 +883,7 @@ netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/neteve
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
- $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h $(srcdir)/dnstap/dnstap.h \
+ $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/dnstap/dnstap.h \
\
net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
@@ -960,11 +961,11 @@ validator.lo validator.o: $(srcdir)/validator/validator.c config.h $(srcdir)/val
$(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h $(srcdir)/validator/val_kcache.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_nsec.h \
$(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_neg.h $(srcdir)/validator/val_sigcrypt.h \
- $(srcdir)/validator/autotrust.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/fptr_wlist.h \
- $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h \
- $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
+ $(srcdir)/validator/autotrust.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
+ $(srcdir)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
+ $(srcdir)/services/modstack.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
val_kcache.lo val_kcache.o: $(srcdir)/validator/val_kcache.c config.h $(srcdir)/validator/val_kcache.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/testcode/checklocks.h $(srcdir)/validator/val_kentry.h $(srcdir)/util/config_file.h \
@@ -1054,11 +1055,16 @@ subnet-whitelist.lo subnet-whitelist.o: $(srcdir)/edns-subnet/subnet-whitelist.c
cachedb.lo cachedb.o: $(srcdir)/cachedb/cachedb.c config.h $(srcdir)/cachedb/cachedb.h $(srcdir)/util/module.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/data/msgencode.h $(srcdir)/services/cache/dns.h \
- $(srcdir)/validator/val_neg.h $(srcdir)/util/rbtree.h $(srcdir)/validator/val_secalgo.h \
- $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h $(srcdir)/sldns/parseutil.h \
- $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/sbuffer.h
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/cachedb/redis.h $(srcdir)/util/regional.h \
+ $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/util/data/msgencode.h \
+ $(srcdir)/services/cache/dns.h $(srcdir)/validator/val_neg.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/validator/val_secalgo.h $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h \
+ $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/sbuffer.h
+redis.lo redis.o: $(srcdir)/cachedb/redis.c config.h $(srcdir)/cachedb/redis.h $(srcdir)/cachedb/cachedb.h \
+ $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/testcode/checklocks.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/alloc.h \
+ $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h
respip.lo respip.o: $(srcdir)/respip/respip.c config.h $(srcdir)/services/localzone.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
@@ -1204,12 +1210,12 @@ remote.lo remote.o: $(srcdir)/daemon/remote.c config.h \
$(srcdir)/util/net_help.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \
- $(srcdir)/services/view.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/data/dname.h \
- $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_kcache.h \
- $(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_anchor.h $(srcdir)/iterator/iterator.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
- $(srcdir)/iterator/iter_delegpt.h $(srcdir)/services/outside_network.h $(srcdir)/sldns/str2wire.h \
- $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h
+ $(srcdir)/services/view.h $(srcdir)/services/authzone.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
+ $(srcdir)/util/data/dname.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h \
+ $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_anchor.h \
+ $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
+ $(srcdir)/iterator/iter_hints.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/services/outside_network.h \
+ $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h
stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
$(srcdir)/libunbound/unbound.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
@@ -1222,7 +1228,8 @@ stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(s
$(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h \
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
- $(srcdir)/util/rtt.h $(srcdir)/validator/val_kcache.h
+ $(srcdir)/util/rtt.h $(srcdir)/services/authzone.h $(srcdir)/validator/val_kcache.h \
+ $(srcdir)/validator/val_neg.h
unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.h $(srcdir)/daemon/daemon.h \
$(srcdir)/util/locks.h $(srcdir)/testcode/checklocks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
$(srcdir)/daemon/remote.h \
@@ -1319,7 +1326,8 @@ stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(s
$(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h \
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
- $(srcdir)/util/rtt.h $(srcdir)/validator/val_kcache.h
+ $(srcdir)/util/rtt.h $(srcdir)/services/authzone.h $(srcdir)/validator/val_kcache.h \
+ $(srcdir)/validator/val_neg.h
replay.lo replay.o: $(srcdir)/testcode/replay.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
$(srcdir)/util/config_file.h $(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h \
diff --git a/contrib/unbound/cachedb/cachedb.c b/contrib/unbound/cachedb/cachedb.c
index 80bdc380f3f6..a6a609dcb68d 100644
--- a/contrib/unbound/cachedb/cachedb.c
+++ b/contrib/unbound/cachedb/cachedb.c
@@ -43,6 +43,7 @@
#include "config.h"
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
+#include "cachedb/redis.h"
#include "util/regional.h"
#include "util/net_help.h"
#include "util/config_file.h"
@@ -56,7 +57,20 @@
#include "sldns/wire2str.h"
#include "sldns/sbuffer.h"
-#define CACHEDB_HASHSIZE 256 /* bit hash */
+/* header file for htobe64 */
+#ifdef HAVE_ENDIAN_H
+# include <endian.h>
+#endif
+#ifdef HAVE_SYS_ENDIAN_H
+# include <sys/endian.h>
+#endif
+#ifdef HAVE_LIBKERN_OSBYTEORDER_H
+/* In practice this is specific to MacOS X. We assume it doesn't have
+* htobe64/be64toh but has alternatives with a different name. */
+# include <libkern/OSByteOrder.h>
+# define htobe64(x) OSSwapHostToBigInt64(x)
+# define be64toh(x) OSSwapBigToHostInt64(x)
+#endif
/** the unit test testframe for cachedb, its module state contains
* a cache for a couple queries (in memory). */
@@ -176,6 +190,10 @@ static struct cachedb_backend testframe_backend = { "testframe",
static struct cachedb_backend*
cachedb_find_backend(const char* str)
{
+#ifdef USE_REDIS
+ if(strcmp(str, redis_backend.name) == 0)
+ return &redis_backend;
+#endif
if(strcmp(str, testframe_backend.name) == 0)
return &testframe_backend;
/* TODO add more backends here */
@@ -571,7 +589,8 @@ cachedb_intcache_lookup(struct module_qstate* qstate)
qstate->region, qstate->env->scratch,
1 /* no partial messages with only a CNAME */
);
- if(!msg && qstate->env->neg_cache) {
+ if(!msg && qstate->env->neg_cache &&
+ iter_qname_indicates_dnssec(qstate->env, &qstate->qinfo)) {
/* lookup in negative cache; may result in
* NOERROR/NODATA or NXDOMAIN answers that need validation */
msg = val_neg_getmsg(qstate->env->neg_cache, &qstate->qinfo,
diff --git a/contrib/unbound/cachedb/cachedb.h b/contrib/unbound/cachedb/cachedb.h
index d477e90a7dee..27187dc56dc6 100644
--- a/contrib/unbound/cachedb/cachedb.h
+++ b/contrib/unbound/cachedb/cachedb.h
@@ -87,6 +87,8 @@ struct cachedb_backend {
uint8_t*, size_t);
};
+#define CACHEDB_HASHSIZE 256 /* bit hash */
+
/** Init the cachedb module */
int cachedb_init(struct module_env* env, int id);
/** Deinit the cachedb module */
diff --git a/contrib/unbound/cachedb/redis.c b/contrib/unbound/cachedb/redis.c
new file mode 100644
index 000000000000..3dfbf8f7a25c
--- /dev/null
+++ b/contrib/unbound/cachedb/redis.c
@@ -0,0 +1,283 @@
+/*
+ * cachedb/redis.c - cachedb redis module
+ *
+ * Copyright (c) 2018, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains a module that uses the redis database to cache
+ * dns responses.
+ */
+
+#include "config.h"
+#ifdef USE_CACHEDB
+#include "cachedb/redis.h"
+#include "cachedb/cachedb.h"
+#include "util/alloc.h"
+#include "util/config_file.h"
+#include "sldns/sbuffer.h"
+
+#ifdef USE_REDIS
+#include "hiredis/hiredis.h"
+
+struct redis_moddata {
+ redisContext** ctxs; /* thread-specific redis contexts */
+ int numctxs; /* number of ctx entries */
+ const char* server_host; /* server's IP address or host name */
+ int server_port; /* server's TCP port */
+ struct timeval timeout; /* timeout for connection setup and commands */
+};
+
+static redisContext*
+redis_connect(const struct redis_moddata* moddata)
+{
+ redisContext* ctx;
+
+ ctx = redisConnectWithTimeout(moddata->server_host,
+ moddata->server_port, moddata->timeout);
+ if(!ctx || ctx->err) {
+ const char *errstr = "out of memory";
+ if(ctx)
+ errstr = ctx->errstr;
+ log_err("failed to connect to redis server: %s", errstr);
+ goto fail;
+ }
+ if(redisSetTimeout(ctx, moddata->timeout) != REDIS_OK) {
+ log_err("failed to set redis timeout");
+ goto fail;
+ }
+ return ctx;
+
+ fail:
+ if(ctx)
+ redisFree(ctx);
+ return NULL;
+}
+
+static int
+redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
+{
+ int i;
+ struct redis_moddata* moddata = NULL;
+
+ verbose(VERB_ALGO, "redis_init");
+
+ moddata = calloc(1, sizeof(struct redis_moddata));
+ if(!moddata) {
+ log_err("out of memory");
+ return 0;
+ }
+ moddata->numctxs = env->cfg->num_threads;
+ moddata->ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
+ if(!moddata->ctxs) {
+ log_err("out of memory");
+ free(moddata);
+ return 0;
+ }
+ /* note: server_host is a shallow reference to configured string.
+ * we don't have to free it in this module. */
+ moddata->server_host = env->cfg->redis_server_host;
+ moddata->server_port = env->cfg->redis_server_port;
+ moddata->timeout.tv_sec = env->cfg->redis_timeout / 1000;
+ moddata->timeout.tv_usec = (env->cfg->redis_timeout % 1000) * 1000;
+ for(i = 0; i < moddata->numctxs; i++)
+ moddata->ctxs[i] = redis_connect(moddata);
+ cachedb_env->backend_data = moddata;
+ return 1;
+}
+
+static void
+redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
+{
+ struct redis_moddata* moddata = (struct redis_moddata*)
+ cachedb_env->backend_data;
+ (void)env;
+
+ verbose(VERB_ALGO, "redis_deinit");
+
+ if(!moddata)
+ return;
+ if(moddata->ctxs) {
+ int i;
+ for(i = 0; i < moddata->numctxs; i++) {
+ if(moddata->ctxs[i])
+ redisFree(moddata->ctxs[i]);
+ }
+ free(moddata->ctxs);
+ }
+ free(moddata);
+}
+
+/*
+ * Send a redis command and get a reply. Unified so that it can be used for
+ * both SET and GET. If 'data' is non-NULL the command is supposed to be
+ * SET and GET otherwise, but the implementation of this function is agnostic
+ * about the semantics (except for logging): 'command', 'data', and 'data_len'
+ * are opaquely passed to redisCommand().
+ * This function first checks whether a connection with a redis server has
+ * been established; if not it tries to set up a new one.
+ * It returns redisReply returned from redisCommand() or NULL if some low
+ * level error happens. The caller is responsible to check the return value,
+ * if it's non-NULL, it has to free it with freeReplyObject().
+ */
+static redisReply*
+redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
+ const char* command, const uint8_t* data, size_t data_len)
+{
+ redisContext* ctx;
+ redisReply* rep;
+ struct redis_moddata* d = (struct redis_moddata*)
+ cachedb_env->backend_data;
+
+ /* We assume env->alloc->thread_num is a unique ID for each thread
+ * in [0, num-of-threads). We could treat it as an error condition
+ * if the assumption didn't hold, but it seems to be a fundamental
+ * assumption throughout the unbound architecture, so we simply assert
+ * it. */
+ log_assert(env->alloc->thread_num < d->numctxs);
+ ctx = d->ctxs[env->alloc->thread_num];
+
+ /* If we've not established a connection to the server or we've closed
+ * it on a failure, try to re-establish a new one. Failures will be
+ * logged in redis_connect(). */
+ if(!ctx) {
+ ctx = redis_connect(d);
+ d->ctxs[env->alloc->thread_num] = ctx;
+ }
+ if(!ctx)
+ return NULL;
+
+ /* Send the command and get a reply, synchronously. */
+ rep = (redisReply*)redisCommand(ctx, command, data, data_len);
+ if(!rep) {
+ /* Once an error as a NULL-reply is returned the context cannot
+ * be reused and we'll need to set up a new connection. */
+ log_err("redis_command: failed to receive a reply, "
+ "closing connection: %s", ctx->errstr);
+ redisFree(ctx);
+ d->ctxs[env->alloc->thread_num] = NULL;
+ return NULL;
+ }
+
+ /* Check error in reply to unify logging in that case.
+ * The caller may perform context-dependent checks and logging. */
+ if(rep->type == REDIS_REPLY_ERROR)
+ log_err("redis: %s resulted in an error: %s",
+ data ? "set" : "get", rep->str);
+
+ return rep;
+}
+
+static int
+redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
+ char* key, struct sldns_buffer* result_buffer)
+{
+ redisReply* rep;
+ char cmdbuf[4+(CACHEDB_HASHSIZE/8)*2+1]; /* "GET " + key */
+ int n;
+ int ret = 0;
+
+ verbose(VERB_ALGO, "redis_lookup of %s", key);
+
+ n = snprintf(cmdbuf, sizeof(cmdbuf), "GET %s", key);
+ if(n < 0 || n >= (int)sizeof(cmdbuf)) {
+ log_err("redis_lookup: unexpected failure to build command");
+ return 0;
+ }
+
+ rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0);
+ if(!rep)
+ return 0;
+ switch (rep->type) {
+ case REDIS_REPLY_NIL:
+ verbose(VERB_ALGO, "redis_lookup: no data cached");
+ break;
+ case REDIS_REPLY_STRING:
+ verbose(VERB_ALGO, "redis_lookup found %d bytes",
+ (int)rep->len);
+ if((size_t)rep->len > sldns_buffer_capacity(result_buffer)) {
+ log_err("redis_lookup: replied data too long: %lu",
+ (size_t)rep->len);
+ break;
+ }
+ sldns_buffer_clear(result_buffer);
+ sldns_buffer_write(result_buffer, rep->str, rep->len);
+ sldns_buffer_flip(result_buffer);
+ ret = 1;
+ break;
+ case REDIS_REPLY_ERROR:
+ break; /* already logged */
+ default:
+ log_err("redis_lookup: unexpected type of reply for (%d)",
+ rep->type);
+ break;
+ }
+ freeReplyObject(rep);
+ return ret;
+}
+
+static void
+redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
+ char* key, uint8_t* data, size_t data_len)
+{
+ redisReply* rep;
+ char cmdbuf[4+(CACHEDB_HASHSIZE/8)*2+3+1]; /* "SET " + key + " %b" */
+ int n;
+
+ verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);
+
+ /* build command to set to a binary safe string */
+ n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
+ if(n < 0 || n >= (int)sizeof(cmdbuf)) {
+ log_err("redis_store: unexpected failure to build command");
+ return;
+ }
+
+ rep = redis_command(env, cachedb_env, cmdbuf, data, data_len);
+ if(rep) {
+ verbose(VERB_ALGO, "redis_store set completed");
+ if(rep->type != REDIS_REPLY_STATUS &&
+ rep->type != REDIS_REPLY_ERROR) {
+ log_err("redis_store: unexpected type of reply (%d)",
+ rep->type);
+ }
+ freeReplyObject(rep);
+ }
+}
+
+struct cachedb_backend redis_backend = { "redis",
+ redis_init, redis_deinit, redis_lookup, redis_store
+};
+#endif /* USE_REDIS */
+#endif /* USE_CACHEDB */
diff --git a/contrib/unbound/cachedb/redis.h b/contrib/unbound/cachedb/redis.h
new file mode 100644
index 000000000000..2da2a64f2db9
--- /dev/null
+++ b/contrib/unbound/cachedb/redis.h
@@ -0,0 +1,45 @@
+/*
+ * cachedb/redis.h - cachedb redis module
+ *
+ * Copyright (c) 2018, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains a module that uses the redis database to cache
+ * dns responses.
+ */
+
+/** the redis backend definition, contains callable functions
+ * and name string */
+extern struct cachedb_backend redis_backend;
diff --git a/contrib/unbound/config.h b/contrib/unbound/config.h
index 2c4c98110147..d5a8dbbc86ce 100644
--- a/contrib/unbound/config.h
+++ b/contrib/unbound/config.h
@@ -84,6 +84,10 @@
don't. */
#define HAVE_DECL_NID_ED25519 0
+/* Define to 1 if you have the declaration of `NID_ED448', and to 0 if you
+ don't. */
+#define HAVE_DECL_NID_ED448 0
+
/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
don't. */
#define HAVE_DECL_NID_SECP384R1 1
@@ -96,6 +100,10 @@
don't. */
/* #undef HAVE_DECL_REALLOCARRAY */
+/* Define to 1 if you have the declaration of `redisConnect', and to 0 if you
+ don't. */
+/* #undef HAVE_DECL_REDISCONNECT */
+
/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0
if you don't. */
#define HAVE_DECL_SK_SSL_COMP_POP_FREE 1
@@ -234,6 +242,9 @@
/* Define to 1 if you have the <grp.h> header file. */
#define HAVE_GRP_H 1
+/* Define to 1 if you have the <hiredis/hiredis.h> header file. */
+/* #undef HAVE_HIREDIS_HIREDIS_H */
+
/* If you have HMAC_Update */
#define HAVE_HMAC_UPDATE 1
@@ -264,6 +275,9 @@
/* Define to 1 if you have the `kill' function. */
#define HAVE_KILL 1
+/* Define to 1 if you have the <libkern/OSByteOrder.h> header file. */
+/* #undef HAVE_LIBKERN_OSBYTEORDER_H */
+
/* Define if we have LibreSSL */
/* #undef HAVE_LIBRESSL */
@@ -480,6 +494,9 @@
/* Define to 1 if systemd should be used */
/* #undef HAVE_SYSTEMD */
+/* Define to 1 if you have the <sys/endian.h> header file. */
+#define HAVE_SYS_ENDIAN_H 1
+
/* Define to 1 if you have the <sys/ipc.h> header file. */
#define HAVE_SYS_IPC_H 1
@@ -611,7 +628,7 @@
#define PACKAGE_NAME "unbound"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "unbound 1.7.0"
+#define PACKAGE_STRING "unbound 1.7.1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "unbound"
@@ -620,7 +637,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "1.7.0"
+#define PACKAGE_VERSION "1.7.1"
/* default pidfile location */
#define PIDFILE "/var/unbound/unbound.pid"
@@ -639,7 +656,7 @@
#define ROOT_CERT_FILE "/var/unbound/icannbundle.pem"
/* version number for resource files */
-#define RSRC_PACKAGE_VERSION 1,7,0,0
+#define RSRC_PACKAGE_VERSION 1,7,1,0
/* Directory to chdir to */
#define RUN_DIR "/var/unbound"
@@ -704,6 +721,9 @@
/* Define this to enable ED25519 support. */
/* #undef USE_ED25519 */
+/* Define this to enable ED448 support. */
+/* #undef USE_ED448 */
+
/* Define this to enable GOST support. */
#define USE_GOST 1
@@ -719,6 +739,9 @@
/* Define this to enable client TCP Fast Open. */
/* #undef USE_OSX_MSG_FASTOPEN */
+/* Define this to use hiredis client. */
+/* #undef USE_REDIS */
+
/* Define this to enable SHA1 support. */
#define USE_SHA1 1
@@ -1223,6 +1246,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
/** default port for DNS traffic. */
#define UNBOUND_DNS_PORT 53
+/** default port for DNS over TLS traffic. */
+#define UNBOUND_DNS_OVER_TLS_PORT 853
/** 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.h.in b/contrib/unbound/config.h.in
index e7405603ddad..922389428776 100644
--- a/contrib/unbound/config.h.in
+++ b/contrib/unbound/config.h.in
@@ -83,6 +83,10 @@
don't. */
#undef HAVE_DECL_NID_ED25519
+/* Define to 1 if you have the declaration of `NID_ED448', and to 0 if you
+ don't. */
+#undef HAVE_DECL_NID_ED448
+
/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
don't. */
#undef HAVE_DECL_NID_SECP384R1
@@ -95,6 +99,10 @@
don't. */
#undef HAVE_DECL_REALLOCARRAY
+/* Define to 1 if you have the declaration of `redisConnect', and to 0 if you
+ don't. */
+#undef HAVE_DECL_REDISCONNECT
+
/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0
if you don't. */
#undef HAVE_DECL_SK_SSL_COMP_POP_FREE
@@ -233,6 +241,9 @@
/* Define to 1 if you have the <grp.h> header file. */
#undef HAVE_GRP_H
+/* Define to 1 if you have the <hiredis/hiredis.h> header file. */
+#undef HAVE_HIREDIS_HIREDIS_H
+
/* If you have HMAC_Update */
#undef HAVE_HMAC_UPDATE
@@ -263,6 +274,9 @@
/* Define to 1 if you have the `kill' function. */
#undef HAVE_KILL
+/* Define to 1 if you have the <libkern/OSByteOrder.h> header file. */
+#undef HAVE_LIBKERN_OSBYTEORDER_H
+
/* Define if we have LibreSSL */
#undef HAVE_LIBRESSL
@@ -479,6 +493,9 @@
/* Define to 1 if systemd should be used */
#undef HAVE_SYSTEMD
+/* Define to 1 if you have the <sys/endian.h> header file. */
+#undef HAVE_SYS_ENDIAN_H
+
/* Define to 1 if you have the <sys/ipc.h> header file. */
#undef HAVE_SYS_IPC_H
@@ -703,6 +720,9 @@
/* Define this to enable ED25519 support. */
#undef USE_ED25519
+/* Define this to enable ED448 support. */
+#undef USE_ED448
+
/* Define this to enable GOST support. */
#undef USE_GOST
@@ -718,6 +738,9 @@
/* Define this to enable client TCP Fast Open. */
#undef USE_OSX_MSG_FASTOPEN
+/* Define this to use hiredis client. */
+#undef USE_REDIS
+
/* Define this to enable SHA1 support. */
#undef USE_SHA1
@@ -1222,6 +1245,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
/** default port for DNS traffic. */
#define UNBOUND_DNS_PORT 53
+/** default port for DNS over TLS traffic. */
+#define UNBOUND_DNS_OVER_TLS_PORT 853
/** 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/configure b/contrib/unbound/configure
index 8f830dc15ceb..6535a5a969c2 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.7.0.
+# Generated by GNU Autoconf 2.69 for unbound 1.7.1.
#
# Report bugs to <unbound-bugs@nlnetlabs.nl>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unbound'
PACKAGE_TARNAME='unbound'
-PACKAGE_VERSION='1.7.0'
-PACKAGE_STRING='unbound 1.7.0'
+PACKAGE_VERSION='1.7.1'
+PACKAGE_STRING='unbound 1.7.1'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
PACKAGE_URL=''
@@ -859,11 +859,13 @@ enable_gost
enable_ecdsa
enable_dsa
enable_ed25519
+enable_ed448
enable_event_api
enable_tfo_client
enable_tfo_server
with_libevent
with_libexpat
+with_libhiredis
enable_static_exe
enable_systemd
enable_lock_checks
@@ -1438,7 +1440,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.7.0 to adapt to many kinds of systems.
+\`configure' configures unbound 1.7.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1503,7 +1505,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of unbound 1.7.0:";;
+ short | recursive ) echo "Configuration of unbound 1.7.1:";;
esac
cat <<\_ACEOF
@@ -1544,6 +1546,7 @@ Optional Features:
--disable-ecdsa Disable ECDSA support
--disable-dsa Disable DSA support
--disable-ed25519 Disable ED25519 support
+ --disable-ed448 Disable ED448 support
--enable-event-api Enable (experimental) pluggable event base
libunbound API installed to unbound-event.h
--enable-tfo-client Enable TCP Fast Open for client mode
@@ -1610,6 +1613,7 @@ Optional Packages:
an explicit path). Slower, but allows use of large
outgoing port ranges.
--with-libexpat=path specify explicit path for libexpat.
+ --with-libhiredis=path specify explicit path for libhiredis.
--with-dnstap-socket-path=pathname
set default dnstap socket path
--with-protobuf-c=path Path where protobuf-c is installed, for dnstap
@@ -1718,7 +1722,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-unbound configure 1.7.0
+unbound configure 1.7.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2427,7 +2431,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.7.0, which was
+It was created by unbound $as_me 1.7.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2779,11 +2783,11 @@ UNBOUND_VERSION_MAJOR=1
UNBOUND_VERSION_MINOR=7
-UNBOUND_VERSION_MICRO=0
+UNBOUND_VERSION_MICRO=1
LIBUNBOUND_CURRENT=7
-LIBUNBOUND_REVISION=8
+LIBUNBOUND_REVISION=9
LIBUNBOUND_AGE=5
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -2843,6 +2847,7 @@ LIBUNBOUND_AGE=5
# 1.6.7 had 7:6:5
# 1.6.8 had 7:7:5
# 1.7.0 had 7:8:5
+# 1.7.1 had 7:9:5
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -14477,7 +14482,7 @@ CC=$lt_save_CC
# 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/ipc.h sys/shm.h
+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
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
@@ -18314,6 +18319,50 @@ _ACEOF
;;
esac
+# Check whether --enable-ed448 was given.
+if test "${enable_ed448+set}" = set; then :
+ enableval=$enable_ed448;
+fi
+
+use_ed448="no"
+case "$enable_ed448" in
+ no)
+ ;;
+ *)
+ if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
+ ac_fn_c_check_decl "$LINENO" "NID_ED448" "ac_cv_have_decl_NID_ED448" "$ac_includes_default
+#include <openssl/evp.h>
+
+"
+if test "x$ac_cv_have_decl_NID_ED448" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_NID_ED448 $ac_have_decl
+_ACEOF
+if test $ac_have_decl = 1; then :
+
+ use_ed448="yes"
+
+else
+ if test "x$enable_ed448" = "xyes"; then as_fn_error $? "OpenSSL does not support ED448 and you used --enable-ed448." "$LINENO" 5
+ fi
+fi
+
+ fi
+ if test $use_ed448 = "yes"; then
+
+cat >>confdefs.h <<_ACEOF
+#define USE_ED448 1
+_ACEOF
+
+ fi
+ ;;
+esac
+
# Check whether --enable-event-api was given.
if test "${enable_event_api+set}" = set; then :
enableval=$enable_event_api;
@@ -18810,6 +18859,70 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# hiredis (redis C client for cachedb)
+
+# Check whether --with-libhiredis was given.
+if test "${with_libhiredis+set}" = set; then :
+ withval=$with_libhiredis;
+else
+ withval="no"
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libhiredis" >&5
+$as_echo_n "checking for libhiredis... " >&6; }
+found_libhiredis="no"
+if test x_$withval = x_yes -o x_$withval != x_no; then
+ 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/hiredis/hiredis.h"; then
+ found_libhiredis="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 USE_REDIS 1" >>confdefs.h
+
+ LIBS="$LIBS -lhiredis"
+ break;
+ fi
+ done
+ if test x_$found_libhiredis != x_yes; then
+ as_fn_error $? "Could not find libhiredis, hiredis.h" "$LINENO" 5
+ fi
+ for ac_header in hiredis/hiredis.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "hiredis/hiredis.h" "ac_cv_header_hiredis_hiredis_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_hiredis_hiredis_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_HIREDIS_HIREDIS_H 1
+_ACEOF
+
+fi
+
+done
+
+ ac_fn_c_check_decl "$LINENO" "redisConnect" "ac_cv_have_decl_redisConnect" "$ac_includes_default
+ #include <hiredis/hiredis.h>
+
+"
+if test "x$ac_cv_have_decl_redisConnect" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_REDISCONNECT $ac_have_decl
+_ACEOF
+
+fi
+
# set static linking if requested
staticexe=""
@@ -20928,7 +21041,7 @@ _ACEOF
-version=1.7.0
+version=1.7.1
date=`date +'%b %e, %Y'`
@@ -21447,7 +21560,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.7.0, which was
+This file was extended by unbound $as_me 1.7.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -21513,7 +21626,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.7.0
+unbound config.status 1.7.1
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 5417160fb66d..435147eebdec 100644
--- a/contrib/unbound/configure.ac
+++ b/contrib/unbound/configure.ac
@@ -11,14 +11,14 @@ sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[7])
-m4_define([VERSION_MICRO],[0])
+m4_define([VERSION_MICRO],[1])
AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), unbound-bugs@nlnetlabs.nl, unbound)
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
LIBUNBOUND_CURRENT=7
-LIBUNBOUND_REVISION=8
+LIBUNBOUND_REVISION=9
LIBUNBOUND_AGE=5
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -78,6 +78,7 @@ LIBUNBOUND_AGE=5
# 1.6.7 had 7:6:5
# 1.6.8 had 7:7:5
# 1.7.0 had 7:8:5
+# 1.7.1 had 7:9:5
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -331,7 +332,7 @@ AC_CHECK_TOOL(STRIP, strip)
ACX_LIBTOOL_C_ONLY
# 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/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/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])
# check for types.
# Using own tests for int64* because autoconf builtin only give 32bit.
@@ -992,6 +993,26 @@ case "$enable_ed25519" in
;;
esac
+AC_ARG_ENABLE(ed448, AC_HELP_STRING([--disable-ed448], [Disable ED448 support]))
+use_ed448="no"
+case "$enable_ed448" in
+ no)
+ ;;
+ *)
+ if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
+ AC_CHECK_DECLS([NID_ED448], [
+ use_ed448="yes"
+ ], [ if test "x$enable_ed448" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED448 and you used --enable-ed448.])
+ fi ], [AC_INCLUDES_DEFAULT
+#include <openssl/evp.h>
+ ])
+ fi
+ if test $use_ed448 = "yes"; then
+ AC_DEFINE_UNQUOTED([USE_ED448], [1], [Define this to enable ED448 support.])
+ fi
+ ;;
+esac
+
AC_ARG_ENABLE(event-api, AC_HELP_STRING([--enable-event-api], [Enable (experimental) pluggable event base libunbound API installed to unbound-event.h]))
case "$enable_event_api" in
yes)
@@ -1150,6 +1171,39 @@ AC_CHECK_DECLS([XML_StopParser], [], [], [AC_INCLUDES_DEFAULT
#include <expat.h>
])
+# hiredis (redis C client for cachedb)
+AC_ARG_WITH(libhiredis, AC_HELP_STRING([--with-libhiredis=path],
+ [specify explicit path for libhiredis.]),
+ [ ],[ withval="no" ])
+AC_MSG_CHECKING(for libhiredis)
+found_libhiredis="no"
+if test x_$withval = x_yes -o x_$withval != x_no; then
+ 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/hiredis/hiredis.h"; then
+ found_libhiredis="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([USE_REDIS], [1], [Define this to use hiredis client.])
+ LIBS="$LIBS -lhiredis"
+ break;
+ fi
+ done
+ if test x_$found_libhiredis != x_yes; then
+ AC_ERROR([Could not find libhiredis, hiredis.h])
+ fi
+ AC_CHECK_HEADERS([hiredis/hiredis.h],,, [AC_INCLUDES_DEFAULT])
+ AC_CHECK_DECLS([redisConnect], [], [], [AC_INCLUDES_DEFAULT
+ #include <hiredis/hiredis.h>
+ ])
+fi
+
# set static linking if requested
AC_SUBST(staticexe)
staticexe=""
@@ -1752,6 +1806,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
/** default port for DNS traffic. */
#define UNBOUND_DNS_PORT 53
+/** default port for DNS over TLS traffic. */
+#define UNBOUND_DNS_OVER_TLS_PORT 853
/** 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/README b/contrib/unbound/contrib/README
index 2a59e0330f0d..2b5e754247ac 100644
--- a/contrib/unbound/contrib/README
+++ b/contrib/unbound/contrib/README
@@ -35,3 +35,6 @@ distribution but may be helpful.
instead of SERVFAIL. Contributed by SIDN.
* fastrpz.patch: fastrpz support from Farsight Security.
* libunbound.so.conf: ltrace.conf file, see ltrace.conf(5), for libunbound.
+* unbound-querycachedb.py: utility to show data stored in cachedb backend
+ for a particular query name and type. It requires dnspython and (for
+ redis backend) redis Python modules.
diff --git a/contrib/unbound/contrib/fastrpz.patch b/contrib/unbound/contrib/fastrpz.patch
index 6e78bf1b7cf3..d5edc322405c 100644
--- a/contrib/unbound/contrib/fastrpz.patch
+++ b/contrib/unbound/contrib/fastrpz.patch
@@ -21,7 +21,7 @@ Index: unbound-1.7.0~rc1/Makefile.in
@@ -125,7 +127,7 @@ validator/val_sigcrypt.c validator/val_u
edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \
edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \
- cachedb/cachedb.c respip/respip.c $(CHECKLOCK_SRC) \
+ cachedb/cachedb.c cachedb/redis.c respip/respip.c $(CHECKLOCK_SRC) \
-$(DNSTAP_SRC) $(DNSCRYPT_SRC) $(IPSECMOD_SRC)
+$(DNSTAP_SRC) $(FASTRPZ_SRC) $(DNSCRYPT_SRC) $(IPSECMOD_SRC)
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
diff --git a/contrib/unbound/contrib/unbound-querycachedb.py b/contrib/unbound/contrib/unbound-querycachedb.py
new file mode 100644
index 000000000000..5b4485ba87ad
--- /dev/null
+++ b/contrib/unbound/contrib/unbound-querycachedb.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+
+import hashlib
+import sys
+import struct
+import socket
+import time
+from optparse import OptionParser
+
+import dns.message
+import dns.name
+import dns.rdataclass
+import dns.rdatatype
+
+def _calc_hashkey(qname, secret, qtype):
+ qclass = 'IN' # CLASS is fixed for simplicity
+ hobj = hashlib.sha256()
+ hobj.update(dns.name.from_text(qname).to_wire())
+ hobj.update(struct.pack('HH',
+ socket.htons(dns.rdatatype.from_text(qtype)),
+ socket.htons(dns.rdataclass.from_text(qclass))))
+ hobj.update(secret)
+ return hobj.hexdigest().upper()
+
+def _redis_get(options, key):
+ import redis
+ return redis.Redis(options.address, int(options.port)).get(key)
+
+def _dump_value(options, qname, key, value):
+ print(';; query=%s/IN/%s' % (qname, options.qtype))
+ print(';; key=%s' % key)
+ if value is None:
+ print(';; no value')
+ return
+ if len(value) < 16:
+ print(';; broken value, short length: %d' % len(value))
+ return
+ now = int(time.time())
+ timestamp = struct.unpack('!Q', value[-16:-8])[0]
+ expire = struct.unpack('!Q', value[-8:])[0]
+ print(';; Now=%d, TimeStamp=%d, Expire=%d, TTL=%d' %
+ (now, timestamp, expire, max(expire - now, 0)))
+ print(dns.message.from_wire(value[:-16]))
+
+def main():
+ parser = OptionParser(usage='usage: %prog [options] query_name')
+ parser.add_option("-a", "--address", dest="address", action="store",
+ default='127.0.0.1', help="backend-server address",
+ metavar='ADDRESS')
+ parser.add_option("-b", "--backend", dest="backend", action="store",
+ default='redis', help="backend name",
+ metavar='BACKEND')
+ parser.add_option("-p", "--port", dest="port", action="store",
+ default='6379', help="backend-server port",
+ metavar='PORT')
+ parser.add_option("-s", "--secret", dest="secret", action="store",
+ default='default', help="secret seed", metavar='SECRET')
+ parser.add_option("-t", "--qtype", dest="qtype", action="store",
+ default='A', help="query RR type", metavar='QTYPE')
+
+ (options, args) = parser.parse_args()
+ if len(args) < 1:
+ parser.error('qname is missing')
+ if options.backend == 'redis':
+ get_func = _redis_get
+ else:
+ raise Exception('unknown backend name: %s\n' % options.backend)
+ key = _calc_hashkey(args[0], options.secret, options.qtype)
+ value = get_func(options, key)
+ _dump_value(options, args[0], key, value)
+
+if __name__ == '__main__':
+ try:
+ main()
+ except Exception as e:
+ sys.stderr.write('%s\n' % e)
+ exit(1)
diff --git a/contrib/unbound/daemon/daemon.c b/contrib/unbound/daemon/daemon.c
index f68bd981b01b..85ae1e0a15ac 100644
--- a/contrib/unbound/daemon/daemon.c
+++ b/contrib/unbound/daemon/daemon.c
@@ -706,9 +706,11 @@ daemon_cleanup(struct daemon* daemon)
daemon->num = 0;
#ifdef USE_DNSTAP
dt_delete(daemon->dtenv);
+ daemon->dtenv = NULL;
#endif
#ifdef USE_DNSCRYPT
dnsc_delete(daemon->dnscenv);
+ daemon->dnscenv = NULL;
#endif
daemon->cfg = NULL;
}
diff --git a/contrib/unbound/daemon/remote.c b/contrib/unbound/daemon/remote.c
index 3477340ff578..cfc91eb98b3a 100644
--- a/contrib/unbound/daemon/remote.c
+++ b/contrib/unbound/daemon/remote.c
@@ -68,6 +68,7 @@
#include "services/cache/infra.h"
#include "services/mesh.h"
#include "services/localzone.h"
+#include "services/authzone.h"
#include "util/storage/slabhash.h"
#include "util/fptr_wlist.h"
#include "util/data/dname.h"
@@ -236,10 +237,15 @@ daemon_remote_create(struct config_file* cfg)
if (cfg->remote_control_use_cert == 0) {
/* No certificates are requested */
+#if defined(SSL_OP_NO_TLSv1_3)
+ /* in openssl 1.1.1, negotiation code for tls 1.3 does
+ * not allow the unauthenticated aNULL and eNULL ciphers */
+ SSL_CTX_set_options(rc->ctx, SSL_OP_NO_TLSv1_3);
+#endif
#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
SSL_CTX_set_security_level(rc->ctx, 0);
#endif
- if(!SSL_CTX_set_cipher_list(rc->ctx, "aNULL, eNULL")) {
+ if(!SSL_CTX_set_cipher_list(rc->ctx, "aNULL:eNULL")) {
log_crypto_err("Failed to set aNULL cipher list");
daemon_remote_delete(rc);
return NULL;
@@ -1046,6 +1052,10 @@ print_ext(SSL* ssl, struct ub_stats_info* s)
(unsigned long)s->svr.ans_bogus)) return 0;
if(!ssl_printf(ssl, "num.rrset.bogus"SQ"%lu\n",
(unsigned long)s->svr.rrset_bogus)) return 0;
+ if(!ssl_printf(ssl, "num.query.aggressive.NOERROR"SQ"%lu\n",
+ (unsigned long)s->svr.num_neg_cache_noerror)) return 0;
+ if(!ssl_printf(ssl, "num.query.aggressive.NXDOMAIN"SQ"%lu\n",
+ (unsigned long)s->svr.num_neg_cache_nxdomain)) return 0;
/* threat detection */
if(!ssl_printf(ssl, "unwanted.queries"SQ"%lu\n",
(unsigned long)s->svr.unwanted_queries)) return 0;
@@ -1070,6 +1080,10 @@ print_ext(SSL* ssl, struct ub_stats_info* s)
if(!ssl_printf(ssl, "num.query.dnscrypt.replay"SQ"%lu\n",
(unsigned long)s->svr.num_query_dnscrypt_replay)) return 0;
#endif /* USE_DNSCRYPT */
+ if(!ssl_printf(ssl, "num.query.authzone.up"SQ"%lu\n",
+ (unsigned long)s->svr.num_query_authzone_up)) return 0;
+ if(!ssl_printf(ssl, "num.query.authzone.down"SQ"%lu\n",
+ (unsigned long)s->svr.num_query_authzone_down)) return 0;
return 1;
}
@@ -1644,6 +1658,7 @@ zone_del_msg(struct lruhash_entry* e, void* arg)
struct reply_info* d = (struct reply_info*)e->data;
if(d->ttl > inf->expired) {
d->ttl = inf->expired;
+ d->prefetch_ttl = inf->expired;
inf->num_msgs++;
}
}
@@ -1927,6 +1942,7 @@ parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names)
struct delegpt* dp = delegpt_create_mlc(nm);
struct sockaddr_storage addr;
socklen_t addrlen;
+ char* auth_name;
if(!dp) {
(void)ssl_printf(ssl, "error out of memory\n");
return NULL;
@@ -1939,7 +1955,7 @@ parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names)
p = skipwhite(p); /* position at next spot */
}
/* parse address */
- if(!extstrtoaddr(todo, &addr, &addrlen)) {
+ if(!authextstrtoaddr(todo, &addr, &addrlen, &auth_name)) {
if(allow_names) {
uint8_t* n = NULL;
size_t ln;
@@ -1967,7 +1983,8 @@ parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names)
}
} else {
/* add address */
- if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
+ if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
+ auth_name)) {
(void)ssl_printf(ssl, "error out of memory\n");
delegpt_free_mlc(dp);
return NULL;
@@ -2527,6 +2544,36 @@ do_list_stubs(SSL* ssl, struct worker* worker)
}
}
+/** do the list_auth_zones command */
+static void
+do_list_auth_zones(SSL* ssl, struct auth_zones* az)
+{
+ struct auth_zone* z;
+ char buf[257], buf2[256];
+ lock_rw_rdlock(&az->lock);
+ RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
+ lock_rw_rdlock(&z->lock);
+ dname_str(z->name, buf);
+ if(z->zone_expired)
+ snprintf(buf2, sizeof(buf2), "expired");
+ else {
+ uint32_t serial = 0;
+ if(auth_zone_get_serial(z, &serial))
+ snprintf(buf2, sizeof(buf2), "serial %u",
+ (unsigned)serial);
+ else snprintf(buf2, sizeof(buf2), "no serial");
+ }
+ if(!ssl_printf(ssl, "%s\t%s\n", buf, buf2)) {
+ /* failure to print */
+ lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&az->lock);
+ return;
+ }
+ lock_rw_unlock(&z->lock);
+ }
+ lock_rw_unlock(&az->lock);
+}
+
/** do the list_local_zones command */
static void
do_list_local_zones(SSL* ssl, struct local_zones* zones)
@@ -2787,6 +2834,9 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
} else if(cmdcmp(p, "ip_ratelimit_list", 17)) {
do_ip_ratelimit_list(ssl, worker, p+17);
return;
+ } else if(cmdcmp(p, "list_auth_zones", 15)) {
+ do_list_auth_zones(ssl, worker->env.auth_zones);
+ return;
} else if(cmdcmp(p, "stub_add", 8)) {
/* must always distribute this cmd */
if(rc) distribute_cmd(rc, ssl, cmd);
diff --git a/contrib/unbound/daemon/stats.c b/contrib/unbound/daemon/stats.c
index ed788720846a..6f4feaaad9d0 100644
--- a/contrib/unbound/daemon/stats.c
+++ b/contrib/unbound/daemon/stats.c
@@ -60,7 +60,9 @@
#include "sldns/sbuffer.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
+#include "services/authzone.h"
#include "validator/val_kcache.h"
+#include "validator/val_neg.h"
/** add timers and the values do not overflow or become negative */
static void
@@ -122,6 +124,30 @@ void server_stats_log(struct ub_server_stats* stats, struct worker* worker,
(unsigned)worker->env.mesh->stats_jostled);
}
+/** Set the neg cache stats. */
+static void
+set_neg_cache_stats(struct worker* worker, struct ub_server_stats* svr,
+ int reset)
+{
+ int m = modstack_find(&worker->env.mesh->mods, "validator");
+ struct val_env* ve;
+ struct val_neg_cache* neg;
+ if(m == -1)
+ return;
+ ve = (struct val_env*)worker->env.modinfo[m];
+ if(!ve->neg_cache)
+ return;
+ neg = ve->neg_cache;
+ lock_basic_lock(&neg->lock);
+ svr->num_neg_cache_noerror = (long long)neg->num_neg_cache_noerror;
+ svr->num_neg_cache_nxdomain = (long long)neg->num_neg_cache_nxdomain;
+ if(reset && !worker->env.cfg->stat_cumulative) {
+ neg->num_neg_cache_noerror = 0;
+ neg->num_neg_cache_nxdomain = 0;
+ }
+ lock_basic_unlock(&neg->lock);
+}
+
/** get rrsets bogus number from validator */
static size_t
get_rrset_bogus(struct worker* worker, int reset)
@@ -256,6 +282,25 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
s->svr.nonce_cache_count = 0;
s->svr.num_query_dnscrypt_replay = 0;
#endif /* USE_DNSCRYPT */
+ if(worker->env.auth_zones) {
+ if(reset && !worker->env.cfg->stat_cumulative) {
+ lock_rw_wrlock(&worker->env.auth_zones->lock);
+ } else {
+ lock_rw_rdlock(&worker->env.auth_zones->lock);
+ }
+ s->svr.num_query_authzone_up = (long long)worker->env.
+ auth_zones->num_query_up;
+ s->svr.num_query_authzone_down = (long long)worker->env.
+ auth_zones->num_query_down;
+ if(reset && !worker->env.cfg->stat_cumulative) {
+ worker->env.auth_zones->num_query_up = 0;
+ worker->env.auth_zones->num_query_down = 0;
+ }
+ lock_rw_unlock(&worker->env.auth_zones->lock);
+ }
+
+ /* Set neg cache usage numbers */
+ set_neg_cache_stats(worker, &s->svr, reset);
/* get tcp accept usage */
s->svr.tcp_accept_usage = 0;
diff --git a/contrib/unbound/daemon/worker.c b/contrib/unbound/daemon/worker.c
index 389a1de530ec..6121c7dbe363 100644
--- a/contrib/unbound/daemon/worker.c
+++ b/contrib/unbound/daemon/worker.c
@@ -342,7 +342,8 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker)
verbose(VERB_QUERY, "request bad, has TC bit on");
return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR);
}
- if(LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY) {
+ if(LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY &&
+ LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_NOTIFY) {
verbose(VERB_QUERY, "request unknown opcode %d",
LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)));
return worker_err_ratelimit(worker, LDNS_RCODE_NOTIMPL);
@@ -352,7 +353,9 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker)
LDNS_QDCOUNT(sldns_buffer_begin(pkt)));
return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR);
}
- if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 0) {
+ if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 0 &&
+ (LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 1 ||
+ LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_NOTIFY)) {
verbose(VERB_QUERY, "request wrong nr an=%d",
LDNS_ANCOUNT(sldns_buffer_begin(pkt)));
return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR);
@@ -499,6 +502,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
* let validator do that */
return 0;
case sec_status_bogus:
+ case sec_status_secure_sentinel_fail:
/* some rrsets are bogus, reply servfail */
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
@@ -655,7 +659,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
}
}
/* check security status of the cached answer */
- if( rep->security == sec_status_bogus && must_validate) {
+ if(must_validate && (rep->security == sec_status_bogus ||
+ rep->security == sec_status_secure_sentinel_fail)) {
/* BAD cached */
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
@@ -940,6 +945,66 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
return 0;
}
+/**
+ * Answer notify queries. These are notifies for authoritative zones,
+ * the reply is an ack that the notify has been received. We need to check
+ * access permission here.
+ * @param w: worker
+ * @param qinfo: query info. Pointer into packet buffer.
+ * @param edns: edns info from query.
+ * @param repinfo: reply info with source address.
+ * @param pkt: packet buffer.
+ */
+static void
+answer_notify(struct worker* w, struct query_info* qinfo,
+ struct edns_data* edns, sldns_buffer* pkt, struct comm_reply* repinfo)
+{
+ int refused = 0;
+ int rcode = LDNS_RCODE_NOERROR;
+ uint32_t serial = 0;
+ int has_serial;
+ if(!w->env.auth_zones) return;
+ has_serial = auth_zone_parse_notify_serial(pkt, &serial);
+ if(auth_zones_notify(w->env.auth_zones, &w->env, qinfo->qname,
+ qinfo->qname_len, qinfo->qclass, &repinfo->addr,
+ repinfo->addrlen, has_serial, serial, &refused)) {
+ rcode = LDNS_RCODE_NOERROR;
+ } else {
+ if(refused)
+ rcode = LDNS_RCODE_REFUSED;
+ else rcode = LDNS_RCODE_SERVFAIL;
+ }
+
+ if(verbosity >= VERB_DETAIL) {
+ char buf[380];
+ char zname[255+1];
+ char sr[25];
+ dname_str(qinfo->qname, zname);
+ sr[0]=0;
+ if(has_serial)
+ snprintf(sr, sizeof(sr), "serial %u ",
+ (unsigned)serial);
+ if(rcode == LDNS_RCODE_REFUSED)
+ snprintf(buf, sizeof(buf),
+ "refused NOTIFY %sfor %s from", sr, zname);
+ else if(rcode == LDNS_RCODE_SERVFAIL)
+ snprintf(buf, sizeof(buf),
+ "servfail for NOTIFY %sfor %s from", sr, zname);
+ else snprintf(buf, sizeof(buf),
+ "received NOTIFY %sfor %s from", sr, zname);
+ log_addr(VERB_DETAIL, buf, &repinfo->addr, repinfo->addrlen);
+ }
+ edns->edns_version = EDNS_ADVERTISED_VERSION;
+ edns->udp_size = EDNS_ADVERTISED_SIZE;
+ edns->ext_rcode = 0;
+ edns->bits &= EDNS_DO;
+ edns->opt_list = NULL;
+ error_encode(pkt, rcode, qinfo,
+ *(uint16_t*)(void *)sldns_buffer_begin(pkt),
+ sldns_buffer_read_u16_at(pkt, 2), edns);
+ LDNS_OPCODE_SET(sldns_buffer_begin(pkt), LDNS_PACKET_NOTIFY);
+}
+
static int
deny_refuse(struct comm_point* c, enum acl_access acl,
enum acl_access deny, enum acl_access refuse,
@@ -1238,6 +1303,12 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
regional_free_all(worker->scratchpad);
goto send_reply;
}
+ if(LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ==
+ LDNS_PACKET_NOTIFY) {
+ answer_notify(worker, &qinfo, &edns, c->buffer, repinfo);
+ regional_free_all(worker->scratchpad);
+ goto send_reply;
+ }
if(local_zones_answer(worker->daemon->local_zones, &worker->env, &qinfo,
&edns, c->buffer, worker->scratchpad, repinfo, acladdr->taglist,
acladdr->taglen, acladdr->tag_actions,
@@ -1806,7 +1877,7 @@ struct outbound_entry*
worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
int want_dnssec, int nocaps, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen, int ssl_upstream,
- struct module_qstate* q)
+ char* tls_auth_name, struct module_qstate* q)
{
struct worker* worker = q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@@ -1816,7 +1887,7 @@ worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
e->qstate = q;
e->qsent = outnet_serviced_query(worker->back, qinfo, flags, dnssec,
want_dnssec, nocaps, q->env->cfg->tcp_upstream,
- ssl_upstream, addr, addrlen, zone, zonelen, q,
+ ssl_upstream, tls_auth_name, addr, addrlen, zone, zonelen, q,
worker_handle_service_reply, e, worker->back->udp_buff, q->env);
if(!e->qsent) {
return NULL;
@@ -1863,7 +1934,8 @@ struct outbound_entry* libworker_send_query(
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
- int ATTR_UNUSED(ssl_upstream), struct module_qstate* ATTR_UNUSED(q))
+ int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
+ struct module_qstate* ATTR_UNUSED(q))
{
log_assert(0);
return 0;
diff --git a/contrib/unbound/doc/Changelog b/contrib/unbound/doc/Changelog
index f29935375ba7..b44bdec8371b 100644
--- a/contrib/unbound/doc/Changelog
+++ b/contrib/unbound/doc/Changelog
@@ -1,6 +1,143 @@
+26 April 2018: Wouter
+ - Fix for crash in daemon_cleanup with dnstap during reload,
+ from Saksham Manchanda.
+ - Also that for dnscrypt.
+ - tag for 1.7.1rc1 release.
+
+25 April 2018: Ralph
+ - Fix memory leak when caching wildcard records for aggressive NSEC use
+
+24 April 2018: Wouter
+ - Fix contrib/fastrpz.patch for this release.
+ - Fix auth https for libev.
+
+24 April 2018: Ralph
+ - Added root-key-sentinel support
+
+23 April 2018: Wouter
+ - makedist uses bz2 for expat code, instead of tar.gz.
+ - Fix #4092: libunbound: use-caps-for-id lacks colon in
+ config_set_option.
+ - auth zone http download stores exact copy of downloaded file,
+ including comments in the file.
+ - Fix sldns parse failure for CDS alternate delete syntax empty hex.
+ - Attempt for auth zone fix; add of callback in mesh gets from
+ callback does not skip callback of result.
+ - Fix cname classification with qname minimisation enabled.
+ - list_auth_zones unbound-control command.
+
+20 April 2018: Wouter
+ - man page documentation for dns-over-tls forward-addr '#' notation.
+ - removed free from failed parse case.
+ - Fix #4091: Fix that reload of auth-zone does not merge the zonefile
+ with the previous contents.
+ - Delete auth zone when removed from config.
+
+19 April 2018: Wouter
+ - Can set tls authentication with forward-addr: IP#tls.auth.name
+ And put the public cert bundle in tls-cert-bundle: "ca-bundle.pem".
+ such as forward-addr: 9.9.9.9@853#dns.quad9.net or
+ 1.1.1.1@853#cloudflare-dns.com
+ - Fix #658: unbound using TLS in a forwarding configuration does not
+ verify the server's certificate (RFC 8310 support).
+ - For addr with #authname and no @port notation, the default is 853.
+
+18 April 2018: Wouter
+ - Fix auth-zone retry timer to be on schedule with retry timeout,
+ with backoff. Also time a refresh at the zone expiry.
+
+17 April 2018: Wouter
+ - auth zone notify work.
+ - allow-notify: config statement for auth-zones.
+ - unit test for allow-notify
+
+16 April 2018: Wouter
+ - Fix auth zone target lookup iterator.
+ - auth zone notify with prefix
+ - auth zone notify work.
+
+13 April 2018: Wouter
+ - Fix for max include depth for authzones.
+ - Fix memory free on fail for $INCLUDE in authzone.
+ - Fix that an internal error to look up the wrong rr type for
+ auth zone gets stopped, before trying to send there.
+ - auth zone notify work.
+
+10 April 2018: Ralph
+ - num.query.aggressive.NOERROR and num.query.aggressive.NXDOMAIN
+ statistics counters.
+
+10 April 2018: Wouter
+ - documentation for low-rtt and low-rtt-pct.
+ - auth zone notify work.
+
+9 April 2018: Wouter
+ - Fix that flush_zone sets prefetch ttl expired, so that with
+ serve-expired enabled it'll start prefetching those entries.
+ - num.query.authzone.up and num.query.authzone.down statistics counters.
+ - Fix downstream auth zone, only fallback when auth zone fails to
+ answer and fallback is enabled.
+ - Accept both option names with and without colon for get_option
+ and set_option.
+ - low-rtt and low-rtt-pct in unbound.conf enable the server selection
+ of fast servers for some percentage of the time.
+
+5 April 2018: Wouter
+ - Combine write of tcp length and tcp query for dns over tls.
+ - nitpick fixes in example.conf.
+ - Fix above stub queries for type NS and useless delegation point.
+ - Fix unbound-control over pipe with openssl 1.1.1, the TLSv1.3
+ tls_choose_sigalg routine does not allow the ciphers for the pipe,
+ so use TLSv1.2.
+ - ED448 support.
+
+3 April 2018: Wouter
+ - Fix #4043: make test fails due to v6 presentation issue in macOS.
+ - Fix unable to resolve after new WLAN connection, due to auth-zone
+ failing with a forwarder set. Now, auth-zone is only used for
+ answers (not referrals) when a forwarder is set.
+
+29 March 2018: Ralph
+ - Check "result" in dup_all(), by Florian Obser.
+
+23 March 2018: Ralph
+ - Fix unbound-control get_option aggressive-nsec
+
+21 March 2018: Ralph
+ - Do not use cached NSEC records to generate negative answers for
+ domains under DNSSEC Negative Trust Anchors.
+
+19 March 2018: Wouter
+ - iana port update.
+
+16 March 2018: Wouter
+ - corrected a minor typo in the changelog.
+ - move htobe64/be64toh portability code to cachedb.c.
+
+15 March 2018: Wouter
+ - Add --with-libhiredis, unbound support for a new cachedb backend
+ that uses a Redis server as the storage. This implementation
+ depends on the hiredis client library (https://redislabs.com/lp/hiredis/).
+ And unbound should be built with both --enable-cachedb and
+ --with-libhiredis[=PATH] (where $PATH/include/hiredis/hiredis.h
+ should exist). Patch from Jinmei Tatuya (Infoblox).
+ - Fix #3817: core dump happens in libunbound delete, when queued
+ servfail hits deleted message queue.
+ - Create additional tls service interfaces by opening them on other
+ portnumbers and listing the portnumbers as additional-tls-port: nr.
+
+13 March 2018: Wouter
+ - Fix typo in documentation.
+ - Fix #3736: Fix 0 TTL domains stuck on SERVFAIL unless manually
+ flushed with serve-expired on.
+
12 March 2018: Wouter
- Added documentation for aggressive-nsec: yes.
- - tag 1.7.0rc3.
+ - tag 1.7.0rc3. That became the 1.7.0 release on 15 Mar, trunk
+ now has 1.7.1 in development.
+ - Fix #3727: Protocol name is TLS, options have been renamed but
+ documentation is not consistent.
+ - Check IXFR start serial.
9 March 2018: Wouter
- Fix #3598: Fix swig build issue on rhel6 based system.
diff --git a/contrib/unbound/doc/README b/contrib/unbound/doc/README
index 58cd56fa8095..c8bfd43cd00b 100644
--- a/contrib/unbound/doc/README
+++ b/contrib/unbound/doc/README
@@ -1,4 +1,4 @@
-README for Unbound 1.7.0
+README for Unbound 1.7.1
Copyright 2007 NLnet Labs
http://unbound.net
diff --git a/contrib/unbound/doc/example.conf b/contrib/unbound/doc/example.conf
index a19dcd87a66c..871988b32c74 100644
--- a/contrib/unbound/doc/example.conf
+++ b/contrib/unbound/doc/example.conf
@@ -1,7 +1,7 @@
#
# Example configuration file.
#
-# See unbound.conf(5) man page, version 1.7.0.
+# See unbound.conf(5) man page, version 1.7.1.
#
# this is a comment.
@@ -199,7 +199,7 @@ server:
# upstream connections use TCP only (and no UDP), "yes" or "no"
# useful for tunneling scenarios, default no.
# tcp-upstream: no
-
+
# upstream connections also use UDP (even if do-udp is no).
# useful if if you want UDP upstream, but don't provide UDP downstream.
# udp-upstream-without-downstream: no
@@ -320,7 +320,7 @@ server:
# enable to not answer version.server and version.bind queries.
# hide-version: no
-
+
# enable to not answer trustanchor.unbound queries.
# hide-trustanchor: no
@@ -458,6 +458,9 @@ server:
# trust anchor signaling sends a RFC8145 key tag query after priming.
# trust-anchor-signaling: yes
+
+ # 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.
@@ -630,7 +633,7 @@ server:
# o inform acts like transparent, but logs client IP address
# o inform_deny drops queries and logs client IP address
# o always_transparent, always_refuse, always_nxdomain, resolve in
- # that way but ignore local data for that name.
+ # that way but ignore local data for that name
# o noview breaks out of that view towards global local-zones.
#
# defaults are localhost address, reverse for 127.0.0.1 and ::1
@@ -664,20 +667,23 @@ 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 SSL (on the TCP sockets), with plain DNS inside
- # the SSL stream. Give the certificate to use and private key.
+ # service clients over TLS (on the TCP sockets), with plain DNS inside
+ # the TLS stream. 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
- # request upstream over SSL (with plain DNS inside the SSL stream).
+ # request upstream over TLS (with plain DNS inside the TLS stream).
# Default is no. Can be turned on and off with unbound-control.
# tls-upstream: no
# Certificates used to authenticate connections made upstream.
# tls-cert-bundle: ""
+ # Also serve tls on these port numbers (eg. 443, ...), by listing
+ # additional-tls-port: portno for each of the port numbers.
+
# 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
@@ -715,6 +721,12 @@ server:
# 0 blocks when ip is ratelimited, otherwise let 1/xth traffic through
# ip-ratelimit-factor: 10
+ # what is considered a low rtt (ping time for upstream server), in msec
+ # low-rtt: 45
+ # select low rtt this many times out of 1000. 0 means the fast server
+ # select is disabled. prefetches are not sped up.
+ # low-rtt-pct: 0
+
# Specific options for ipsecmod. unbound needs to be configured with
# --enable-ipsecmod for these to take effect.
#
@@ -823,6 +835,8 @@ remote-control:
# 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
+# notifies.
# auth-zone:
# name: "."
# for-downstream: no
@@ -851,7 +865,7 @@ remote-control:
# name: "viewname"
# local-zone: "example.com" redirect
# local-data: "example.com A 192.0.2.3"
-# local-data-ptr: "192.0.2.3 www.example.com"
+# local-data-ptr: "192.0.2.3 www.example.com"
# view-first: no
# view:
# name: "anotherview"
@@ -886,3 +900,11 @@ remote-control:
# backend: "testframe"
# # secret seed string to calculate hashed keys
# secret-seed: "default"
+#
+# # For "redis" backend:
+# # redis server's IP address or host name
+# redis-server-host: 127.0.0.1
+# # redis server's TCP port
+# redis-server-port: 6379
+# # timeout (in ms) for communication with the redis server
+# redis-timeout: 100
diff --git a/contrib/unbound/doc/example.conf.in b/contrib/unbound/doc/example.conf.in
index 73ed7fde0e5a..2260ba2544ab 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.7.0.
+# See unbound.conf(5) man page, version 1.7.1.
#
# this is a comment.
@@ -199,7 +199,7 @@ server:
# upstream connections use TCP only (and no UDP), "yes" or "no"
# useful for tunneling scenarios, default no.
# tcp-upstream: no
-
+
# upstream connections also use UDP (even if do-udp is no).
# useful if if you want UDP upstream, but don't provide UDP downstream.
# udp-upstream-without-downstream: no
@@ -320,7 +320,7 @@ server:
# enable to not answer version.server and version.bind queries.
# hide-version: no
-
+
# enable to not answer trustanchor.unbound queries.
# hide-trustanchor: no
@@ -458,6 +458,9 @@ server:
# trust anchor signaling sends a RFC8145 key tag query after priming.
# trust-anchor-signaling: yes
+
+ # 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.
@@ -630,7 +633,7 @@ server:
# o inform acts like transparent, but logs client IP address
# o inform_deny drops queries and logs client IP address
# o always_transparent, always_refuse, always_nxdomain, resolve in
- # that way but ignore local data for that name.
+ # that way but ignore local data for that name
# o noview breaks out of that view towards global local-zones.
#
# defaults are localhost address, reverse for 127.0.0.1 and ::1
@@ -664,20 +667,23 @@ 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 SSL (on the TCP sockets), with plain DNS inside
- # the SSL stream. Give the certificate to use and private key.
+ # service clients over TLS (on the TCP sockets), with plain DNS inside
+ # the TLS stream. 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
- # request upstream over SSL (with plain DNS inside the SSL stream).
+ # request upstream over TLS (with plain DNS inside the TLS stream).
# Default is no. Can be turned on and off with unbound-control.
# tls-upstream: no
# Certificates used to authenticate connections made upstream.
# tls-cert-bundle: ""
+ # Also serve tls on these port numbers (eg. 443, ...), by listing
+ # additional-tls-port: portno for each of the port numbers.
+
# 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
@@ -715,6 +721,12 @@ server:
# 0 blocks when ip is ratelimited, otherwise let 1/xth traffic through
# ip-ratelimit-factor: 10
+ # what is considered a low rtt (ping time for upstream server), in msec
+ # low-rtt: 45
+ # select low rtt this many times out of 1000. 0 means the fast server
+ # select is disabled. prefetches are not sped up.
+ # low-rtt-pct: 0
+
# Specific options for ipsecmod. unbound needs to be configured with
# --enable-ipsecmod for these to take effect.
#
@@ -823,6 +835,8 @@ remote-control:
# 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
+# notifies.
# auth-zone:
# name: "."
# for-downstream: no
@@ -851,7 +865,7 @@ remote-control:
# name: "viewname"
# local-zone: "example.com" redirect
# local-data: "example.com A 192.0.2.3"
-# local-data-ptr: "192.0.2.3 www.example.com"
+# local-data-ptr: "192.0.2.3 www.example.com"
# view-first: no
# view:
# name: "anotherview"
@@ -886,3 +900,11 @@ remote-control:
# backend: "testframe"
# # secret seed string to calculate hashed keys
# secret-seed: "default"
+#
+# # For "redis" backend:
+# # redis server's IP address or host name
+# redis-server-host: 127.0.0.1
+# # redis server's TCP port
+# redis-server-port: 6379
+# # timeout (in ms) for communication with the redis server
+# redis-timeout: 100
diff --git a/contrib/unbound/doc/libunbound.3 b/contrib/unbound/doc/libunbound.3
index 357e981fff4b..24dfb9ef7047 100644
--- a/contrib/unbound/doc/libunbound.3
+++ b/contrib/unbound/doc/libunbound.3
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "libunbound" "3" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" libunbound.3 -- unbound library functions manual
.\"
@@ -43,7 +43,7 @@
.B ub_ctx_zone_remove,
.B ub_ctx_data_add,
.B ub_ctx_data_remove
-\- Unbound DNS validating resolver 1.7.0 functions.
+\- Unbound DNS validating resolver 1.7.1 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
diff --git a/contrib/unbound/doc/libunbound.3.in b/contrib/unbound/doc/libunbound.3.in
index 357e981fff4b..24dfb9ef7047 100644
--- a/contrib/unbound/doc/libunbound.3.in
+++ b/contrib/unbound/doc/libunbound.3.in
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "libunbound" "3" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" libunbound.3 -- unbound library functions manual
.\"
@@ -43,7 +43,7 @@
.B ub_ctx_zone_remove,
.B ub_ctx_data_add,
.B ub_ctx_data_remove
-\- Unbound DNS validating resolver 1.7.0 functions.
+\- Unbound DNS validating resolver 1.7.1 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
diff --git a/contrib/unbound/doc/unbound-anchor.8 b/contrib/unbound/doc/unbound-anchor.8
index f4a753f05e18..97ccb3c4d461 100644
--- a/contrib/unbound/doc/unbound-anchor.8
+++ b/contrib/unbound/doc/unbound-anchor.8
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound-anchor" "8" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
diff --git a/contrib/unbound/doc/unbound-anchor.8.in b/contrib/unbound/doc/unbound-anchor.8.in
index f50bf28af3f5..2c8140de8cc4 100644
--- a/contrib/unbound/doc/unbound-anchor.8.in
+++ b/contrib/unbound/doc/unbound-anchor.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound-anchor" "8" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
diff --git a/contrib/unbound/doc/unbound-checkconf.8 b/contrib/unbound/doc/unbound-checkconf.8
index 004f3e279a0d..6888cfca3b35 100644
--- a/contrib/unbound/doc/unbound-checkconf.8
+++ b/contrib/unbound/doc/unbound-checkconf.8
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound-checkconf" "8" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
diff --git a/contrib/unbound/doc/unbound-checkconf.8.in b/contrib/unbound/doc/unbound-checkconf.8.in
index a07124e57a26..a4cddb1aff13 100644
--- a/contrib/unbound/doc/unbound-checkconf.8.in
+++ b/contrib/unbound/doc/unbound-checkconf.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound-checkconf" "8" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
diff --git a/contrib/unbound/doc/unbound-control.8 b/contrib/unbound/doc/unbound-control.8
index 375005bd53c1..b00a2534fa3f 100644
--- a/contrib/unbound/doc/unbound-control.8
+++ b/contrib/unbound/doc/unbound-control.8
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound-control" "8" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
@@ -144,6 +144,9 @@ Remove the name, type information from the cache.
Remove all information at or below the name from the cache.
The rrsets and key entries are removed so that new lookups will be performed.
This needs to walk and inspect the entire cache, and is a slow operation.
+The entries are set to expired in the implementation of this command (so,
+with serve\-expired enabled, it'll serve that information but schedule a
+prefetch for new information).
.TP
.B flush_bogus
Remove all bogus data from the cache.
@@ -286,6 +289,10 @@ estimated qps and qps limit from config. With +a it prints all ips, not
just the ratelimited ips, with their estimated qps. The ratelimited
ips are dropped before checking the cache.
.TP
+.B list_auth_zones
+List the auth zones that are configured. Printed one per line with a
+status, indicating if the zone is expired and current serial number.
+.TP
.B view_list_local_zones \fIview\fR
\fIlist_local_zones\fR for given view.
.TP
@@ -598,6 +605,26 @@ dnscrypt queries replay. The client nonce must be unique for each client public
key/server secret key pair. This cache should be able to host QPS * `replay
window` interval keys to prevent replay of a query during `replay window`
seconds.
+.TP
+.I num.query.authzone.up
+The number of queries answered from auth\-zone data, upstream queries.
+These queries would otherwise have been sent (with fallback enabled) to
+the internet, but are now answered from the auth zone.
+.TP
+.I num.query.authzone.down
+The number of queries for downstream answered from auth\-zone data.
+These queries are from downstream clients, and have had an answer from
+the data in the auth zone.
+.TP
+.I num.query.aggressive.NOERROR
+The number of queries answered using cached NSEC records with NODATA RCODE.
+These queries would otherwise have been sent to the internet, but are now
+answered using cached data.
+.TP
+.I num.query.aggressive.NXDOMAIN
+The number of queries answered using cached NSEC records with NXDOMAIN RCODE.
+These queries would otherwise have been sent to the internet, but are now
+answered using cached data.
.SH "FILES"
.TP
.I /var/unbound/unbound.conf
diff --git a/contrib/unbound/doc/unbound-control.8.in b/contrib/unbound/doc/unbound-control.8.in
index 53af91514eb7..0ff6b8e7e88a 100644
--- a/contrib/unbound/doc/unbound-control.8.in
+++ b/contrib/unbound/doc/unbound-control.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound-control" "8" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
@@ -144,6 +144,9 @@ Remove the name, type information from the cache.
Remove all information at or below the name from the cache.
The rrsets and key entries are removed so that new lookups will be performed.
This needs to walk and inspect the entire cache, and is a slow operation.
+The entries are set to expired in the implementation of this command (so,
+with serve\-expired enabled, it'll serve that information but schedule a
+prefetch for new information).
.TP
.B flush_bogus
Remove all bogus data from the cache.
@@ -286,6 +289,10 @@ estimated qps and qps limit from config. With +a it prints all ips, not
just the ratelimited ips, with their estimated qps. The ratelimited
ips are dropped before checking the cache.
.TP
+.B list_auth_zones
+List the auth zones that are configured. Printed one per line with a
+status, indicating if the zone is expired and current serial number.
+.TP
.B view_list_local_zones \fIview\fR
\fIlist_local_zones\fR for given view.
.TP
@@ -598,6 +605,26 @@ dnscrypt queries replay. The client nonce must be unique for each client public
key/server secret key pair. This cache should be able to host QPS * `replay
window` interval keys to prevent replay of a query during `replay window`
seconds.
+.TP
+.I num.query.authzone.up
+The number of queries answered from auth\-zone data, upstream queries.
+These queries would otherwise have been sent (with fallback enabled) to
+the internet, but are now answered from the auth zone.
+.TP
+.I num.query.authzone.down
+The number of queries for downstream answered from auth\-zone data.
+These queries are from downstream clients, and have had an answer from
+the data in the auth zone.
+.TP
+.I num.query.aggressive.NOERROR
+The number of queries answered using cached NSEC records with NODATA RCODE.
+These queries would otherwise have been sent to the internet, but are now
+answered using cached data.
+.TP
+.I num.query.aggressive.NXDOMAIN
+The number of queries answered using cached NSEC records with NXDOMAIN RCODE.
+These queries would otherwise have been sent to the internet, but are now
+answered using cached data.
.SH "FILES"
.TP
.I @ub_conf_file@
diff --git a/contrib/unbound/doc/unbound-host.1 b/contrib/unbound/doc/unbound-host.1
index efbbb1a2da59..0947a3dde65a 100644
--- a/contrib/unbound/doc/unbound-host.1
+++ b/contrib/unbound/doc/unbound-host.1
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound\-host" "1" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
diff --git a/contrib/unbound/doc/unbound-host.1.in b/contrib/unbound/doc/unbound-host.1.in
index 6842514d287e..ab2f00be9d0a 100644
--- a/contrib/unbound/doc/unbound-host.1.in
+++ b/contrib/unbound/doc/unbound-host.1.in
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound\-host" "1" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
diff --git a/contrib/unbound/doc/unbound.8 b/contrib/unbound/doc/unbound.8
index 6d1691f9cb34..ab7cad4028dc 100644
--- a/contrib/unbound/doc/unbound.8
+++ b/contrib/unbound/doc/unbound.8
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound" "8" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" unbound.8 -- unbound manual
.\"
@@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
-\- Unbound DNS validating resolver 1.7.0.
+\- Unbound DNS validating resolver 1.7.1.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
diff --git a/contrib/unbound/doc/unbound.8.in b/contrib/unbound/doc/unbound.8.in
index 3c5786a79773..cef25e39c750 100644
--- a/contrib/unbound/doc/unbound.8.in
+++ b/contrib/unbound/doc/unbound.8.in
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound" "8" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" unbound.8 -- unbound manual
.\"
@@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
-\- Unbound DNS validating resolver 1.7.0.
+\- Unbound DNS validating resolver 1.7.1.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
diff --git a/contrib/unbound/doc/unbound.conf.5 b/contrib/unbound/doc/unbound.conf.5
index 8703287c9408..3216ec0648ab 100644
--- a/contrib/unbound/doc/unbound.conf.5
+++ b/contrib/unbound/doc/unbound.conf.5
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound.conf" "5" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@@ -288,7 +288,7 @@ silently (unless verbosity 3) without the option.
.B ip\-transparent: \fI<yes or no>
If yes, then use IP_TRANSPARENT socket option on sockets where unbound
is listening for incoming traffic. Default no. Allows you to bind to
-non\-local interfaces. For example for non\-existant IP addresses that
+non\-local interfaces. For example for non\-existent IP addresses that
are going to exist later on, with host failover configuration. This is
a lot like interface\-automatic, but that one services all interfaces
and with this option you can select which (future) interfaces unbound
@@ -399,8 +399,8 @@ change anything. Useful for TLS service providers, that want no udp downstream
but use udp to fetch data upstream.
.TP
.B tls\-upstream: \fI<yes or no>
-Enabled or disable whether the upstream queries use SSL only for transport.
-Default is no. Useful in tunneling scenarios. The SSL contains plain DNS in
+Enabled or disable whether the upstream queries use TLS only for transport.
+Default is no. Useful in tunneling scenarios. The TLS contains plain DNS in
TCP wireformat. The other server must support this (see
\fBtls\-service\-key\fR).
.TP
@@ -409,7 +409,7 @@ 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 provider SSL service on its TCP sockets. The clients
+If enabled, the server provider TLS service on its TCP sockets. The clients
have to use tls\-upstream: yes. The file is the private key for the TLS
session. The public certificate is in the tls\-service\-pem file. Default
is "", turned off. Requires a restart (a reload is not enough) if changed,
@@ -429,8 +429,8 @@ turned off.
Alternate syntax for \fBtls\-service\-pem\fR.
.TP
.B tls\-port: \fI<number>
-The port number on which to provide TCP SSL service, default 853, only
-interfaces configured with that port number as @number get the SSL service.
+The port number on which to provide TCP TLS service, default 853, only
+interfaces configured with that port number as @number get the TLS service.
.TP
.B ssl\-port: \fI<number>
Alternate syntax for \fBtls\-port\fR.
@@ -444,6 +444,11 @@ urls, and also DNS over TLS connections.
.B ssl\-cert\-bundle: \fI<file>
Alternate syntax for \fBtls\-cert\-bundle\fR.
.TP
+.B additional\-tls\-port: \fI<portnr>
+List portnumbers as additional\-tls\-port, and when interfaces are defined,
+eg. with the @port suffix, as this port number, they provide dns over TLS
+service. Can list multiple, each on a new statement.
+.TP
.B use\-systemd: \fI<yes or no>
Enable or disable systemd socket activation.
Default is no.
@@ -728,8 +733,8 @@ This option only has effect when qname-minimisation is enabled. Default is off.
.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.
-Default is off. It helps to reduce the query rate towards targets that get
-a very high nonexistant name lookup rate.
+Default is no. It helps to reduce the query rate towards targets that get
+a very high nonexistent name lookup rate.
.TP
.B private\-address: \fI<IP address or subnet>
Give IPv4 of IPv6 addresses or classless subnets. These are addresses
@@ -844,6 +849,9 @@ expanded on start and on reload.
.B trust\-anchor\-signaling: \fI<yes or no>
Send RFC8145 key tag query after trust anchor priming. Default is on.
.TP
+.B root\-key\-sentinel: \fI<yes or no>
+Root key trust anchor sentinel. Default is on.
+.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
@@ -1304,13 +1312,30 @@ to complete. Default is 10, allowing 1/10 traffic to flow normally.
This can make ordinary queries complete (if repeatedly queried for),
and enter the cache, whilst also mitigating the traffic flow by the
factor given.
+.TP 5
+.B low\-rtt: \fI<msec time>
+Set the time in millisecond that is considere a low ping time for fast
+server selection with the low\-rtt\-pct option, that turns this on or off.
+The default is 45 msec, a number from IPv6 quick response documents.
+.TP 5
+.B low\-rtt\-pct: \fI<number>
+Specify how many times out of 1000 to pick the fast server from the low
+rtt band. 0 turns the feature off. A value of 900 would pick the fast
+server when such fast servers are available 90 percent of the time, and
+the remaining time perform normal exploration of random servers.
+When prefetch is enabled (or serve\-expired), such prefetches are not
+sped up, because there is no one waiting for it, and it presents a good
+moment to perform server exploration. The low\-rtt option can be used
+to specify which servers are picked for fast server selection, servers
+with a ping roundtrip time below that value are considered.
+The default for low\-rtt\-pct is 0.
.SS "Remote Control Options"
In the
.B remote\-control:
clause are the declarations for the remote control facility. If this is
enabled, the \fIunbound\-control\fR(8) utility can be used to send
commands to the running unbound server. The server uses these clauses
-to setup SSLv3 / TLSv1 security for the connection. The
+to setup TLSv1 security for the connection. The
\fIunbound\-control\fR(8) utility also reads the \fBremote\-control\fR
section for options. To setup the correct self\-signed certificates use the
\fIunbound\-control\-setup\fR(8) utility.
@@ -1416,7 +1441,7 @@ the servers are unreachable, instead it is tried without this clause.
The default is no.
.TP
.B stub\-tls\-upstream: \fI<yes or no>
-Enabled or disable whether the queries to this stub use SSL for transport.
+Enabled or disable whether the queries to this stub use TLS for transport.
Default is no.
.TP
.B stub\-ssl\-upstream: \fI<yes or no>
@@ -1448,6 +1473,13 @@ Name of server to forward to. Is itself resolved before it is used.
.B forward\-addr: \fI<IP address>
IP address of server to forward to. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
+If tls is enabled, then you can append a '#' and a name, then it'll check
+the tls authentication certificates with that name. If you combine
+the '@' and '#', the '@' comes first.
+.IP
+At high verbosity it logs the TLS certificate, with TLS enabled.
+If you leave out the '#' and auth name from the forward\-addr, any
+name is accepted. The cert must also match a CA from the tls\-cert\-bundle.
.TP
.B forward\-first: \fI<yes or no>
If enabled, a query is attempted without the forward clause if it fails.
@@ -1456,7 +1488,7 @@ the servers are unreachable, instead it is tried without this clause.
The default is no.
.TP
.B forward\-tls\-upstream: \fI<yes or no>
-Enabled or disable whether the queries to this forwarder use SSL for transport.
+Enabled or disable whether the queries to this forwarder use TLS for transport.
Default is no.
.TP
.B forward\-ssl\-upstream: \fI<yes or no>
@@ -1496,6 +1528,14 @@ If none of the urls work, the masters 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
+allowed notify by default.
+.TP
.B fallback\-enabled: \fI<yes or no>
Default no. If enabled, unbound falls back to querying the internet as
a resolver for this zone when lookups fail. For example for DNSSEC
@@ -1781,15 +1821,42 @@ If it finds a valid answer in the backend, Unbound uses it to respond
to the query without performing iterative DNS resolution.
If Unbound cannot even find an answer in the backend, it resolves the
query as usual, and stores the answer in the backend.
+.P
+If Unbound was built with
+\fB\-\-with\-libhiredis\fR
+on a system that has installed the hiredis C client library of Redis,
+then the "redis" backend can be used.
+This backend communicates with the specified Redis server over a TCP
+connection to store and retrive cache data.
+It can be used as a persistent and/or shared cache backend.
+It should be noted that Unbound never removes data stored in the Redis server,
+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.
+This backend uses synchronous communication with the Redis server
+based on the assumption that the communication is stable and sufficiently
+fast.
+The thread waiting for a response from the Redis server cannot handle
+other DNS queries.
+Although the backend has the ability to reconnect to the server when
+the connection is closed unexpectedly and there is a configurable timeout
+in case the server is overly slow or hangs up, these cases are assumed
+to be very rare.
+If connection close or timeout happens too often, Unbound will be
+effectively unusable with this backend.
+It's the administrator's responsibility to make the assumption hold.
+.P
The
.B cachedb:
clause gives custom settings of the cache DB module.
.TP
.B backend: \fI<backend name>\fR
Specify the backend database name.
-Currently, only the in-memory "testframe" backend is supported.
-As the name suggests this backend is not of any practical use.
-This option defaults to "testframe".
+The default database is the in-memory backend named "testframe", which,
+as the name suggests, is not of any practical use.
+Depending on the build-time configuration, "redis" backend may also be
+used as described above.
.TP
.B secret-seed: \fI<"secret string">\fR
Specify a seed to calculate a hash value from query information.
@@ -1799,6 +1866,28 @@ operationally.
If the backend database is shared by multiple Unbound instances,
all instances must use the same secret seed.
This option defaults to "default".
+.P
+The following
+.B cachedb
+otions are specific to the redis backend.
+.TP
+.B redis-server-host: \fI<server address or name>\fR
+The IP (either v6 or v4) address or domain name of the Redis server.
+In general an IP address should be specified as otherwise Unbound will have to
+resolve the name of the server every time it establishes a connection
+to the server.
+This option defaults to "127.0.0.1".
+.TP
+.B redis-server-port: \fI<port number>\fR
+The TCP port number of the Redis server.
+This option defaults to 6379.
+.TP
+.B redis-timeout: \fI<msec>\fR
+The period until when Unbound waits for a response from the Redis sever.
+If this timeout expires Unbound closes the connection, treats it as
+if the Redis server does not have the requested data, and will try to
+re-establish a new connection later.
+This option defaults to 100 milliseconds.
.SH "MEMORY CONTROL EXAMPLE"
In the example config settings below memory usage is reduced. Some service
levels are lower, notable very large data and a high TCP load are no longer
diff --git a/contrib/unbound/doc/unbound.conf.5.in b/contrib/unbound/doc/unbound.conf.5.in
index 156e3bed5f47..94ddf70e46d6 100644
--- a/contrib/unbound/doc/unbound.conf.5.in
+++ b/contrib/unbound/doc/unbound.conf.5.in
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound.conf" "5" "May 3, 2018" "NLnet Labs" "unbound 1.7.1"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@@ -288,7 +288,7 @@ silently (unless verbosity 3) without the option.
.B ip\-transparent: \fI<yes or no>
If yes, then use IP_TRANSPARENT socket option on sockets where unbound
is listening for incoming traffic. Default no. Allows you to bind to
-non\-local interfaces. For example for non\-existant IP addresses that
+non\-local interfaces. For example for non\-existent IP addresses that
are going to exist later on, with host failover configuration. This is
a lot like interface\-automatic, but that one services all interfaces
and with this option you can select which (future) interfaces unbound
@@ -399,8 +399,8 @@ change anything. Useful for TLS service providers, that want no udp downstream
but use udp to fetch data upstream.
.TP
.B tls\-upstream: \fI<yes or no>
-Enabled or disable whether the upstream queries use SSL only for transport.
-Default is no. Useful in tunneling scenarios. The SSL contains plain DNS in
+Enabled or disable whether the upstream queries use TLS only for transport.
+Default is no. Useful in tunneling scenarios. The TLS contains plain DNS in
TCP wireformat. The other server must support this (see
\fBtls\-service\-key\fR).
.TP
@@ -409,7 +409,7 @@ 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 provider SSL service on its TCP sockets. The clients
+If enabled, the server provider TLS service on its TCP sockets. The clients
have to use tls\-upstream: yes. The file is the private key for the TLS
session. The public certificate is in the tls\-service\-pem file. Default
is "", turned off. Requires a restart (a reload is not enough) if changed,
@@ -429,8 +429,8 @@ turned off.
Alternate syntax for \fBtls\-service\-pem\fR.
.TP
.B tls\-port: \fI<number>
-The port number on which to provide TCP SSL service, default 853, only
-interfaces configured with that port number as @number get the SSL service.
+The port number on which to provide TCP TLS service, default 853, only
+interfaces configured with that port number as @number get the TLS service.
.TP
.B ssl\-port: \fI<number>
Alternate syntax for \fBtls\-port\fR.
@@ -444,6 +444,11 @@ urls, and also DNS over TLS connections.
.B ssl\-cert\-bundle: \fI<file>
Alternate syntax for \fBtls\-cert\-bundle\fR.
.TP
+.B additional\-tls\-port: \fI<portnr>
+List portnumbers as additional\-tls\-port, and when interfaces are defined,
+eg. with the @port suffix, as this port number, they provide dns over TLS
+service. Can list multiple, each on a new statement.
+.TP
.B use\-systemd: \fI<yes or no>
Enable or disable systemd socket activation.
Default is no.
@@ -728,8 +733,8 @@ This option only has effect when qname-minimisation is enabled. Default is off.
.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.
-Default is off. It helps to reduce the query rate towards targets that get
-a very high nonexistant name lookup rate.
+Default is no. It helps to reduce the query rate towards targets that get
+a very high nonexistent name lookup rate.
.TP
.B private\-address: \fI<IP address or subnet>
Give IPv4 of IPv6 addresses or classless subnets. These are addresses
@@ -844,6 +849,9 @@ expanded on start and on reload.
.B trust\-anchor\-signaling: \fI<yes or no>
Send RFC8145 key tag query after trust anchor priming. Default is on.
.TP
+.B root\-key\-sentinel: \fI<yes or no>
+Root key trust anchor sentinel. Default is on.
+.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
@@ -1304,13 +1312,30 @@ to complete. Default is 10, allowing 1/10 traffic to flow normally.
This can make ordinary queries complete (if repeatedly queried for),
and enter the cache, whilst also mitigating the traffic flow by the
factor given.
+.TP 5
+.B low\-rtt: \fI<msec time>
+Set the time in millisecond that is considere a low ping time for fast
+server selection with the low\-rtt\-pct option, that turns this on or off.
+The default is 45 msec, a number from IPv6 quick response documents.
+.TP 5
+.B low\-rtt\-pct: \fI<number>
+Specify how many times out of 1000 to pick the fast server from the low
+rtt band. 0 turns the feature off. A value of 900 would pick the fast
+server when such fast servers are available 90 percent of the time, and
+the remaining time perform normal exploration of random servers.
+When prefetch is enabled (or serve\-expired), such prefetches are not
+sped up, because there is no one waiting for it, and it presents a good
+moment to perform server exploration. The low\-rtt option can be used
+to specify which servers are picked for fast server selection, servers
+with a ping roundtrip time below that value are considered.
+The default for low\-rtt\-pct is 0.
.SS "Remote Control Options"
In the
.B remote\-control:
clause are the declarations for the remote control facility. If this is
enabled, the \fIunbound\-control\fR(8) utility can be used to send
commands to the running unbound server. The server uses these clauses
-to setup SSLv3 / TLSv1 security for the connection. The
+to setup TLSv1 security for the connection. The
\fIunbound\-control\fR(8) utility also reads the \fBremote\-control\fR
section for options. To setup the correct self\-signed certificates use the
\fIunbound\-control\-setup\fR(8) utility.
@@ -1416,7 +1441,7 @@ the servers are unreachable, instead it is tried without this clause.
The default is no.
.TP
.B stub\-tls\-upstream: \fI<yes or no>
-Enabled or disable whether the queries to this stub use SSL for transport.
+Enabled or disable whether the queries to this stub use TLS for transport.
Default is no.
.TP
.B stub\-ssl\-upstream: \fI<yes or no>
@@ -1448,6 +1473,13 @@ Name of server to forward to. Is itself resolved before it is used.
.B forward\-addr: \fI<IP address>
IP address of server to forward to. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
+If tls is enabled, then you can append a '#' and a name, then it'll check
+the tls authentication certificates with that name. If you combine
+the '@' and '#', the '@' comes first.
+.IP
+At high verbosity it logs the TLS certificate, with TLS enabled.
+If you leave out the '#' and auth name from the forward\-addr, any
+name is accepted. The cert must also match a CA from the tls\-cert\-bundle.
.TP
.B forward\-first: \fI<yes or no>
If enabled, a query is attempted without the forward clause if it fails.
@@ -1456,7 +1488,7 @@ the servers are unreachable, instead it is tried without this clause.
The default is no.
.TP
.B forward\-tls\-upstream: \fI<yes or no>
-Enabled or disable whether the queries to this forwarder use SSL for transport.
+Enabled or disable whether the queries to this forwarder use TLS for transport.
Default is no.
.TP
.B forward\-ssl\-upstream: \fI<yes or no>
@@ -1496,6 +1528,14 @@ If none of the urls work, the masters 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
+allowed notify by default.
+.TP
.B fallback\-enabled: \fI<yes or no>
Default no. If enabled, unbound falls back to querying the internet as
a resolver for this zone when lookups fail. For example for DNSSEC
@@ -1781,15 +1821,42 @@ If it finds a valid answer in the backend, Unbound uses it to respond
to the query without performing iterative DNS resolution.
If Unbound cannot even find an answer in the backend, it resolves the
query as usual, and stores the answer in the backend.
+.P
+If Unbound was built with
+\fB\-\-with\-libhiredis\fR
+on a system that has installed the hiredis C client library of Redis,
+then the "redis" backend can be used.
+This backend communicates with the specified Redis server over a TCP
+connection to store and retrive cache data.
+It can be used as a persistent and/or shared cache backend.
+It should be noted that Unbound never removes data stored in the Redis server,
+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.
+This backend uses synchronous communication with the Redis server
+based on the assumption that the communication is stable and sufficiently
+fast.
+The thread waiting for a response from the Redis server cannot handle
+other DNS queries.
+Although the backend has the ability to reconnect to the server when
+the connection is closed unexpectedly and there is a configurable timeout
+in case the server is overly slow or hangs up, these cases are assumed
+to be very rare.
+If connection close or timeout happens too often, Unbound will be
+effectively unusable with this backend.
+It's the administrator's responsibility to make the assumption hold.
+.P
The
.B cachedb:
clause gives custom settings of the cache DB module.
.TP
.B backend: \fI<backend name>\fR
Specify the backend database name.
-Currently, only the in-memory "testframe" backend is supported.
-As the name suggests this backend is not of any practical use.
-This option defaults to "testframe".
+The default database is the in-memory backend named "testframe", which,
+as the name suggests, is not of any practical use.
+Depending on the build-time configuration, "redis" backend may also be
+used as described above.
.TP
.B secret-seed: \fI<"secret string">\fR
Specify a seed to calculate a hash value from query information.
@@ -1799,6 +1866,28 @@ operationally.
If the backend database is shared by multiple Unbound instances,
all instances must use the same secret seed.
This option defaults to "default".
+.P
+The following
+.B cachedb
+otions are specific to the redis backend.
+.TP
+.B redis-server-host: \fI<server address or name>\fR
+The IP (either v6 or v4) address or domain name of the Redis server.
+In general an IP address should be specified as otherwise Unbound will have to
+resolve the name of the server every time it establishes a connection
+to the server.
+This option defaults to "127.0.0.1".
+.TP
+.B redis-server-port: \fI<port number>\fR
+The TCP port number of the Redis server.
+This option defaults to 6379.
+.TP
+.B redis-timeout: \fI<msec>\fR
+The period until when Unbound waits for a response from the Redis sever.
+If this timeout expires Unbound closes the connection, treats it as
+if the Redis server does not have the requested data, and will try to
+re-establish a new connection later.
+This option defaults to 100 milliseconds.
.SH "MEMORY CONTROL EXAMPLE"
In the example config settings below memory usage is reduced. Some service
levels are lower, notable very large data and a high TCP load are no longer
diff --git a/contrib/unbound/iterator/iter_delegpt.c b/contrib/unbound/iterator/iter_delegpt.c
index ecf88b293da1..f88b3e115db3 100644
--- a/contrib/unbound/iterator/iter_delegpt.c
+++ b/contrib/unbound/iterator/iter_delegpt.c
@@ -84,7 +84,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
}
for(a = dp->target_list; a; a = a->next_target) {
if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen,
- a->bogus, a->lame))
+ a->bogus, a->lame, a->tls_auth_name))
return NULL;
}
return copy;
@@ -176,13 +176,13 @@ delegpt_add_target(struct delegpt* dp, struct regional* region,
if(ns->got4 && ns->got6)
ns->resolved = 1;
}
- return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame);
+ return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL);
}
int
delegpt_add_addr(struct delegpt* dp, struct regional* region,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus,
- uint8_t lame)
+ uint8_t lame, char* tls_auth_name)
{
struct delegpt_addr* a;
log_assert(!dp->dp_type_mlc);
@@ -210,6 +210,13 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
a->bogus = bogus;
a->lame = lame;
a->dnsseclame = 0;
+ if(tls_auth_name) {
+ a->tls_auth_name = regional_strdup(region, tls_auth_name);
+ if(!a->tls_auth_name)
+ return 0;
+ } else {
+ a->tls_auth_name = NULL;
+ }
return 1;
}
@@ -276,11 +283,16 @@ void delegpt_log(enum verbosity_value v, struct delegpt* dp)
(ns->done_pside6?" PSIDE_AAAA":""));
}
for(a = dp->target_list; a; a = a->next_target) {
+ char s[128];
const char* str = " ";
if(a->bogus && a->lame) str = " BOGUS ADDR_LAME ";
else if(a->bogus) str = " BOGUS ";
else if(a->lame) str = " ADDR_LAME ";
- log_addr(VERB_ALGO, str, &a->addr, a->addrlen);
+ if(a->tls_auth_name)
+ snprintf(s, sizeof(s), "%s[%s]", str,
+ a->tls_auth_name);
+ else snprintf(s, sizeof(s), "%s", str);
+ log_addr(VERB_ALGO, s, &a->addr, a->addrlen);
}
}
}
@@ -539,6 +551,7 @@ void delegpt_free_mlc(struct delegpt* dp)
a = dp->target_list;
while(a) {
na = a->next_target;
+ free(a->tls_auth_name);
free(a);
a = na;
}
@@ -585,7 +598,7 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame)
}
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t bogus, uint8_t lame)
+ socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name)
{
struct delegpt_addr* a;
log_assert(dp->dp_type_mlc);
@@ -612,6 +625,15 @@ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
a->bogus = bogus;
a->lame = lame;
a->dnsseclame = 0;
+ if(tls_auth_name) {
+ a->tls_auth_name = strdup(tls_auth_name);
+ if(!a->tls_auth_name) {
+ free(a);
+ return 0;
+ }
+ } else {
+ a->tls_auth_name = NULL;
+ }
return 1;
}
@@ -632,7 +654,7 @@ int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
if(ns->got4 && ns->got6)
ns->resolved = 1;
}
- return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame);
+ return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame, NULL);
}
size_t delegpt_get_mem(struct delegpt* dp)
diff --git a/contrib/unbound/iterator/iter_delegpt.h b/contrib/unbound/iterator/iter_delegpt.h
index 24f0574901d9..354bd6177380 100644
--- a/contrib/unbound/iterator/iter_delegpt.h
+++ b/contrib/unbound/iterator/iter_delegpt.h
@@ -151,6 +151,8 @@ struct delegpt_addr {
* option is useful to mark the address dnsseclame.
* This value is not copied in addr-copy and dp-copy. */
uint8_t dnsseclame;
+ /** the TLS authentication name, (if not NULL) to use. */
+ char* tls_auth_name;
};
/**
@@ -259,11 +261,12 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
* @param addrlen: the length of addr.
* @param bogus: if address is bogus.
* @param lame: if address is lame.
+ * @param tls_auth_name: TLS authentication name (or NULL).
* @return false on error.
*/
int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t bogus, uint8_t lame);
+ uint8_t bogus, uint8_t lame, char* tls_auth_name);
/**
* Find NS record in name list of delegation point.
@@ -394,10 +397,11 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame);
* @param addrlen: the length of addr.
* @param bogus: if address is bogus.
* @param lame: if address is lame.
+ * @param tls_auth_name: TLS authentication name (or NULL).
* @return false on error.
*/
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
- socklen_t addrlen, uint8_t bogus, uint8_t lame);
+ socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name);
/**
* Add target address to the delegation point.
diff --git a/contrib/unbound/iterator/iter_fwd.c b/contrib/unbound/iterator/iter_fwd.c
index 0ba6c6ddfa9e..a44f54386dc4 100644
--- a/contrib/unbound/iterator/iter_fwd.c
+++ b/contrib/unbound/iterator/iter_fwd.c
@@ -231,14 +231,16 @@ read_fwds_addr(struct config_stub* s, struct delegpt* dp)
struct config_strlist* p;
struct sockaddr_storage addr;
socklen_t addrlen;
+ char* tls_auth_name;
for(p = s->addrs; p; p = p->next) {
log_assert(p->str);
- if(!extstrtoaddr(p->str, &addr, &addrlen)) {
+ if(!authextstrtoaddr(p->str, &addr, &addrlen, &tls_auth_name)) {
log_err("cannot parse forward %s ip address: '%s'",
s->name, p->str);
return 0;
}
- if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
+ if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
+ tls_auth_name)) {
log_err("out of memory");
return 0;
}
diff --git a/contrib/unbound/iterator/iter_hints.c b/contrib/unbound/iterator/iter_hints.c
index 1d4c228fabc2..e8d09338e974 100644
--- a/contrib/unbound/iterator/iter_hints.c
+++ b/contrib/unbound/iterator/iter_hints.c
@@ -244,14 +244,16 @@ read_stubs_addr(struct config_stub* s, struct delegpt* dp)
struct config_strlist* p;
struct sockaddr_storage addr;
socklen_t addrlen;
+ char* auth_name;
for(p = s->addrs; p; p = p->next) {
log_assert(p->str);
- if(!extstrtoaddr(p->str, &addr, &addrlen)) {
+ if(!authextstrtoaddr(p->str, &addr, &addrlen, &auth_name)) {
log_err("cannot parse stub %s ip address: '%s'",
s->name, p->str);
return 0;
}
- if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
+ if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
+ auth_name)) {
log_err("out of memory");
return 0;
}
diff --git a/contrib/unbound/iterator/iter_utils.c b/contrib/unbound/iterator/iter_utils.c
index 70cab40faa80..752474cd8e6f 100644
--- a/contrib/unbound/iterator/iter_utils.c
+++ b/contrib/unbound/iterator/iter_utils.c
@@ -312,9 +312,9 @@ static int
iter_filter_order(struct iter_env* iter_env, struct module_env* env,
uint8_t* name, size_t namelen, uint16_t qtype, time_t now,
struct delegpt* dp, int* selected_rtt, int open_target,
- struct sock_list* blacklist)
+ struct sock_list* blacklist, time_t prefetch)
{
- int got_num = 0, low_rtt = 0, swap_to_front;
+ int got_num = 0, low_rtt = 0, swap_to_front, rtt_band = RTT_BAND;
struct delegpt_addr* a, *n, *prev=NULL;
/* fillup sel_rtt and find best rtt in the bunch */
@@ -329,6 +329,16 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
return 0 to force the caller to fetch more */
}
+ if(env->cfg->low_rtt_pct != 0 && prefetch == 0 &&
+ low_rtt < env->cfg->low_rtt &&
+ ub_random_max(env->rnd, 1000) < env->cfg->low_rtt_pct) {
+ /* the query is not prefetch, but for a downstream client,
+ * there is a low_rtt (fast) server. We choose that x% of the
+ * time */
+ /* pick rtt numbers from 0..LOWBAND_RTT */
+ rtt_band = env->cfg->low_rtt - low_rtt;
+ }
+
got_num = 0;
a = dp->result_list;
while(a) {
@@ -340,10 +350,10 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
}
/* classify the server address and determine what to do */
swap_to_front = 0;
- if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= RTT_BAND) {
+ if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= rtt_band) {
got_num++;
swap_to_front = 1;
- } else if(a->sel_rtt<low_rtt && low_rtt-a->sel_rtt<=RTT_BAND) {
+ } else if(a->sel_rtt<low_rtt && low_rtt-a->sel_rtt<=rtt_band) {
got_num++;
swap_to_front = 1;
}
@@ -400,13 +410,14 @@ struct delegpt_addr*
iter_server_selection(struct iter_env* iter_env,
struct module_env* env, struct delegpt* dp,
uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_lame,
- int* chase_to_rd, int open_target, struct sock_list* blacklist)
+ int* chase_to_rd, int open_target, struct sock_list* blacklist,
+ time_t prefetch)
{
int sel;
int selrtt;
struct delegpt_addr* a, *prev;
int num = iter_filter_order(iter_env, env, name, namelen, qtype,
- *env->now, dp, &selrtt, open_target, blacklist);
+ *env->now, dp, &selrtt, open_target, blacklist, prefetch);
if(num == 0)
return NULL;
@@ -625,7 +636,7 @@ iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
}
int
-iter_indicates_dnssec_fwd(struct module_env* env, struct query_info *qinfo)
+iter_qname_indicates_dnssec(struct module_env* env, struct query_info *qinfo)
{
struct trust_anchor* a;
if(!env || !env->anchors || !qinfo || !qinfo->qname)
diff --git a/contrib/unbound/iterator/iter_utils.h b/contrib/unbound/iterator/iter_utils.h
index 602fa6db3d0d..e971d930b164 100644
--- a/contrib/unbound/iterator/iter_utils.h
+++ b/contrib/unbound/iterator/iter_utils.h
@@ -87,13 +87,18 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
* @param open_target: number of currently outstanding target queries.
* If we wait for these, perhaps more server addresses become available.
* @param blacklist: the IP blacklist to use.
+ * @param prefetch: if not 0, prefetch is in use for this query.
+ * This means the query can have different timing, because prefetch is
+ * not waited upon by the downstream client, and thus a good time to
+ * perform exploration of other targets.
* @return best target or NULL if no target.
* if not null, that target is removed from the result list in the dp.
*/
struct delegpt_addr* iter_server_selection(struct iter_env* iter_env,
struct module_env* env, struct delegpt* dp, uint8_t* name,
size_t namelen, uint16_t qtype, int* dnssec_lame,
- int* chase_to_rd, int open_target, struct sock_list* blacklist);
+ int* chase_to_rd, int open_target, struct sock_list* blacklist,
+ time_t prefetch);
/**
* Allocate dns_msg from parsed msg, in regional.
@@ -174,15 +179,14 @@ int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
struct delegpt* dp);
/**
- * See if qname has DNSSEC needs in the forwarding case. This is true if
- * there is a trust anchor above it. Whether there is an insecure delegation
- * to the data is unknown, but CD-retry is needed.
+ * See if qname has DNSSEC needs. This is true if there is a trust anchor above
+ * it. Whether there is an insecure delegation to the data is unknown.
* @param env: environment with anchors.
* @param qinfo: query name and class.
* @return true if trust anchor above qname, false if no anchor or insecure
* point above qname.
*/
-int iter_indicates_dnssec_fwd(struct module_env* env,
+int iter_qname_indicates_dnssec(struct module_env* env,
struct query_info *qinfo);
/**
diff --git a/contrib/unbound/iterator/iterator.c b/contrib/unbound/iterator/iterator.c
index 7f3c65737d59..188a623a2bc7 100644
--- a/contrib/unbound/iterator/iterator.c
+++ b/contrib/unbound/iterator/iterator.c
@@ -1206,7 +1206,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
iq->qchase.qname_len, iq->qchase.qtype,
iq->qchase.qclass, qstate->query_flags,
qstate->region, qstate->env->scratch, 0);
- if(!msg && qstate->env->neg_cache) {
+ if(!msg && qstate->env->neg_cache &&
+ iter_qname_indicates_dnssec(qstate->env, &iq->qchase)) {
/* lookup in negative cache; may result in
* NOERROR/NODATA or NXDOMAIN answers that need validation */
msg = val_neg_getmsg(qstate->env->neg_cache, &iq->qchase,
@@ -1298,7 +1299,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
delnamelen = iq->qchase.qname_len;
}
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue ||
- (iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway)) {
+ (iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway
+ && can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass))) {
/* remove first label from delname, root goes to hints,
* but only to fetch glue, not for qtype=DS. */
/* also when prefetching an NS record, fetch it again from
@@ -1414,6 +1416,12 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
*/
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
iq->dp)) {
+ if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass)) {
+ verbose(VERB_ALGO, "useless dp "
+ "but cannot go up, servfail");
+ return error_response(qstate, id,
+ LDNS_RCODE_SERVFAIL);
+ }
if(dname_is_root(iq->dp->name)) {
/* use safety belt */
verbose(VERB_QUERY, "Cache has root NS but "
@@ -1791,7 +1799,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
for(a = p->target_list; a; a=a->next_target) {
(void)delegpt_add_addr(iq->dp, qstate->region,
&a->addr, a->addrlen, a->bogus,
- a->lame);
+ a->lame, a->tls_auth_name);
}
}
iq->dp->has_parent_side_NS = 1;
@@ -2160,11 +2168,18 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
log_dns_msg("msg from auth zone",
&iq->response->qinfo, iq->response->rep);
}
- iq->num_current_queries++;
- iq->chase_to_rd = 0;
- iq->dnssec_lame_query = 0;
- iq->auth_zone_response = 1;
- return next_state(iq, QUERY_RESP_STATE);
+ if((iq->chase_flags&BIT_RD) && !(iq->response->rep->flags&BIT_AA)) {
+ verbose(VERB_ALGO, "forwarder, ignoring referral from auth zone");
+ } else {
+ lock_rw_wrlock(&qstate->env->auth_zones->lock);
+ qstate->env->auth_zones->num_query_up++;
+ lock_rw_unlock(&qstate->env->auth_zones->lock);
+ iq->num_current_queries++;
+ iq->chase_to_rd = 0;
+ iq->dnssec_lame_query = 0;
+ iq->auth_zone_response = 1;
+ return next_state(iq, QUERY_RESP_STATE);
+ }
}
iq->auth_zone_response = 0;
if(auth_fallback == 0) {
@@ -2253,7 +2268,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
target = iter_server_selection(ie, qstate->env, iq->dp,
iq->dp->name, iq->dp->namelen, iq->qchase.qtype,
&iq->dnssec_lame_query, &iq->chase_to_rd,
- iq->num_target_queries, qstate->blacklist);
+ iq->num_target_queries, qstate->blacklist,
+ qstate->prefetch_leeway);
/* If no usable target was selected... */
if(!target) {
@@ -2366,12 +2382,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
* (blacklist nonempty) and no trust-anchors are configured
* above the qname or on the first attempt when dnssec is on */
EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&&
- !qstate->blacklist&&(!iter_indicates_dnssec_fwd(qstate->env,
+ !qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env,
&iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
ie, iq), &target->addr, target->addrlen,
iq->dp->name, iq->dp->namelen,
- (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream), qstate);
+ (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream),
+ target->tls_auth_name, qstate);
if(!outq) {
log_addr(VERB_DETAIL, "error sending query to auth server",
&target->addr, target->addrlen);
@@ -2440,9 +2457,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
}
type = response_type_from_server(
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
- iq->response, &iq->qchase, iq->dp);
+ iq->response, &iq->qinfo_out, iq->dp);
iq->chase_to_rd = 0;
- if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD)) {
+ if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD) &&
+ !iq->auth_zone_response) {
/* When forwarding (RD bit is set), we handle referrals
* differently. No queries should be sent elsewhere */
type = RESPONSE_TYPE_ANSWER;
diff --git a/contrib/unbound/libunbound/libworker.c b/contrib/unbound/libunbound/libworker.c
index 2c7b2cf072ac..4380d69caa6c 100644
--- a/contrib/unbound/libunbound/libworker.c
+++ b/contrib/unbound/libunbound/libworker.c
@@ -365,6 +365,7 @@ libworker_dobg(void* arg)
/* cleanup */
m = UB_LIBCMD_QUIT;
+ w->want_quit = 1;
tube_remove_bg_listen(w->ctx->qq_pipe);
tube_remove_bg_write(w->ctx->rr_pipe);
libworker_delete(w);
@@ -512,7 +513,8 @@ libworker_enter_result(struct ub_result* res, sldns_buffer* buf,
res->nxdomain = 1;
if(msg_security == sec_status_secure)
res->secure = 1;
- if(msg_security == sec_status_bogus)
+ if(msg_security == sec_status_bogus ||
+ msg_security == sec_status_secure_sentinel_fail)
res->bogus = 1;
}
@@ -713,6 +715,10 @@ add_bg_result(struct libworker* w, struct ctx_query* q, sldns_buffer* pkt,
uint8_t* msg = NULL;
uint32_t len = 0;
+ if(w->want_quit) {
+ context_query_delete(q);
+ return;
+ }
/* serialize and delete unneeded q */
if(w->is_bg_thread) {
lock_basic_lock(&w->ctx->cfglock);
@@ -841,7 +847,8 @@ void libworker_alloc_cleanup(void* arg)
struct outbound_entry* libworker_send_query(struct query_info* qinfo,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, int ssl_upstream, struct module_qstate* q)
+ size_t zonelen, int ssl_upstream, char* tls_auth_name,
+ struct module_qstate* q)
{
struct libworker* w = (struct libworker*)q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@@ -851,8 +858,8 @@ struct outbound_entry* libworker_send_query(struct query_info* qinfo,
e->qstate = q;
e->qsent = outnet_serviced_query(w->back, qinfo, flags, dnssec,
want_dnssec, nocaps, q->env->cfg->tcp_upstream, ssl_upstream,
- addr, addrlen, zone, zonelen, q, libworker_handle_service_reply,
- e, w->back->udp_buff, q->env);
+ tls_auth_name, addr, addrlen, zone, zonelen, q,
+ libworker_handle_service_reply, e, w->back->udp_buff, q->env);
if(!e->qsent) {
return NULL;
}
@@ -972,7 +979,8 @@ struct outbound_entry* worker_send_query(struct query_info* ATTR_UNUSED(qinfo),
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
- int ATTR_UNUSED(ssl_upstream), struct module_qstate* ATTR_UNUSED(q))
+ int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
+ struct module_qstate* ATTR_UNUSED(q))
{
log_assert(0);
return 0;
diff --git a/contrib/unbound/libunbound/libworker.h b/contrib/unbound/libunbound/libworker.h
index b546e89f2ca5..42aa5bae3567 100644
--- a/contrib/unbound/libunbound/libworker.h
+++ b/contrib/unbound/libunbound/libworker.h
@@ -75,6 +75,8 @@ struct libworker {
int is_bg;
/** is this a bg worker that is threaded (not forked)? */
int is_bg_thread;
+ /** want to quit, stop handling new content */
+ int want_quit;
/** copy of the module environment with worker local entries. */
struct module_env* env;
diff --git a/contrib/unbound/libunbound/unbound.h b/contrib/unbound/libunbound/unbound.h
index 1b0f54fd2b6b..fbd69cab0e71 100644
--- a/contrib/unbound/libunbound/unbound.h
+++ b/contrib/unbound/libunbound/unbound.h
@@ -747,6 +747,16 @@ struct ub_server_stats {
long long num_query_dnscrypt_replay;
/** number of dnscrypt nonces cache entries */
long long nonce_cache_count;
+ /** number of queries for unbound's auth_zones, upstream query */
+ long long num_query_authzone_up;
+ /** number of queries for unbound's auth_zones, downstream answers */
+ long long num_query_authzone_down;
+ /** number of times neg cache records were used to generate NOERROR
+ * responses. */
+ long long num_neg_cache_noerror;
+ /** number of times neg cache records were used to generate NXDOMAIN
+ * responses. */
+ long long num_neg_cache_nxdomain;
};
/**
diff --git a/contrib/unbound/libunbound/worker.h b/contrib/unbound/libunbound/worker.h
index 88e1cf799d47..7d2ede04ed09 100644
--- a/contrib/unbound/libunbound/worker.h
+++ b/contrib/unbound/libunbound/worker.h
@@ -63,6 +63,8 @@ struct query_info;
* @param zone: delegation point name.
* @param zonelen: length of zone name wireformat dname.
* @param ssl_upstream: use SSL for upstream queries.
+ * @param tls_auth_name: if ssl_upstream, use this name with TLS
+ * authentication.
* @param q: wich query state to reactivate upon return.
* @return: false on failure (memory or socket related). no query was
* sent.
@@ -70,7 +72,8 @@ struct query_info;
struct outbound_entry* libworker_send_query(struct query_info* qinfo,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, int ssl_upstream, struct module_qstate* q);
+ size_t zonelen, int ssl_upstream, char* tls_auth_name,
+ struct module_qstate* q);
/** process incoming replies from the network */
int libworker_handle_reply(struct comm_point* c, void* arg, int error,
@@ -115,6 +118,8 @@ void worker_sighandler(int sig, void* arg);
* @param zone: wireformat dname of the zone.
* @param zonelen: length of zone name.
* @param ssl_upstream: use SSL for upstream queries.
+ * @param tls_auth_name: if ssl_upstream, use this name with TLS
+ * authentication.
* @param q: wich query state to reactivate upon return.
* @return: false on failure (memory or socket related). no query was
* sent.
@@ -122,7 +127,8 @@ void worker_sighandler(int sig, void* arg);
struct outbound_entry* worker_send_query(struct query_info* qinfo,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, int ssl_upstream, struct module_qstate* q);
+ size_t zonelen, int ssl_upstream, char* tls_auth_name,
+ struct module_qstate* q);
/**
* process control messages from the main thread. Frees the control
diff --git a/contrib/unbound/services/authzone.c b/contrib/unbound/services/authzone.c
index 8abc57c4f53d..2208bb2ac0d6 100644
--- a/contrib/unbound/services/authzone.c
+++ b/contrib/unbound/services/authzone.c
@@ -86,13 +86,21 @@
#define AUTH_HTTP_PORT 80
/* auth https port number */
#define AUTH_HTTPS_PORT 443
+/* max depth for nested $INCLUDEs */
+#define MAX_INCLUDE_DEPTH 10
/** pick up nextprobe task to start waiting to perform transfer actions */
static void xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
- int failure);
+ int failure, int lookup_only);
/** move to sending the probe packets, next if fails. task_probe */
static void xfr_probe_send_or_end(struct auth_xfer* xfr,
struct module_env* env);
+/** pick up probe task with specified(or NULL) destination first,
+ * or transfer task if nothing to probe, or false if already in progress */
+static int xfr_start_probe(struct auth_xfer* xfr, struct module_env* env,
+ struct auth_master* spec);
+/** delete xfer structure (not its tree entry) */
+static void auth_xfer_delete(struct auth_xfer* xfr);
/** create new dns_msg */
static struct dns_msg*
@@ -1437,11 +1445,13 @@ az_remove_rr_decompress(struct auth_zone* z, uint8_t* pkt, size_t pktlen,
* @param state: parse state with $ORIGIN, $TTL and 'prev-dname' and so on,
* that is kept between includes.
* The lineno is set at 1 and then increased by the function.
+ * @param fname: file name.
+ * @param depth: recursion depth for includes
* returns false on failure, has printed an error message
*/
static int
az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
- struct sldns_file_parse_state* state)
+ struct sldns_file_parse_state* state, char* fname, int depth)
{
size_t rr_len, dname_len;
int status;
@@ -1459,6 +1469,11 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
FILE* inc;
int lineno_orig = state->lineno;
char* incfile = (char*)rr + 8;
+ if(depth > MAX_INCLUDE_DEPTH) {
+ log_err("%s:%d max include depth"
+ "exceeded", fname, state->lineno);
+ return 0;
+ }
/* skip spaces */
while(*incfile == ' ' || *incfile == '\t')
incfile++;
@@ -1480,11 +1495,12 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
}
/* recurse read that file now */
if(!az_parse_file(z, inc, rr, rrbuflen,
- state)) {
+ state, incfile, depth+1)) {
log_err("%s:%d cannot parse include "
- "file %s", z->zonefile,
+ "file %s", fname,
lineno_orig, incfile);
fclose(inc);
+ free(incfile);
return 0;
}
fclose(inc);
@@ -1496,7 +1512,7 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
continue;
}
if(status != 0) {
- log_err("parse error %s %d:%d: %s", z->zonefile,
+ log_err("parse error %s %d:%d: %s", fname,
state->lineno, LDNS_WIREPARSE_OFFSET(status),
sldns_get_errorstr_parse(status));
return 0;
@@ -1511,7 +1527,7 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
sldns_wire2str_type_buf(sldns_wirerr_get_type(rr,
rr_len, dname_len), buf, sizeof(buf));
log_err("%s:%d cannot insert RR of type %s",
- z->zonefile, state->lineno, buf);
+ fname, state->lineno, buf);
return 0;
}
}
@@ -1546,6 +1562,11 @@ auth_zone_read_zonefile(struct auth_zone* z)
free(n);
return 0;
}
+
+ /* clear the data tree */
+ traverse_postorder(&z->data, auth_data_del, NULL);
+ rbtree_init(&z->data, &auth_data_cmp);
+
memset(&state, 0, sizeof(state));
/* default TTL to 3600 */
state.default_ttl = 3600;
@@ -1555,7 +1576,7 @@ auth_zone_read_zonefile(struct auth_zone* z)
state.origin_len = z->namelen;
}
/* parse the (toplevel) file */
- if(!az_parse_file(z, in, rr, sizeof(rr), &state)) {
+ if(!az_parse_file(z, in, rr, sizeof(rr), &state, z->zonefile, 0)) {
char* n = sldns_wire2str_dname(z->name, z->namelen);
log_err("error parsing zonefile %s for %s",
z->zonefile, n?n:"error");
@@ -1569,9 +1590,9 @@ auth_zone_read_zonefile(struct auth_zone* z)
/** write buffer to file and check return codes */
static int
-write_out(FILE* out, const char* str)
+write_out(FILE* out, const char* str, size_t len)
{
- size_t r, len = strlen(str);
+ size_t r;
if(len == 0)
return 1;
r = fwrite(str, 1, len, out);
@@ -1634,7 +1655,7 @@ auth_zone_write_rrset(struct auth_zone* z, struct auth_data* node,
verbose(VERB_ALGO, "failed to rr2str rr %d", (int)i);
continue;
}
- if(!write_out(out, buf))
+ if(!write_out(out, buf, strlen(buf)))
return 0;
}
return 1;
@@ -1703,6 +1724,24 @@ auth_zones_read_zones(struct auth_zones* az)
return 1;
}
+/** find serial number of zone or false if none */
+int
+auth_zone_get_serial(struct auth_zone* z, uint32_t* serial)
+{
+ struct auth_data* apex;
+ struct auth_rrset* soa;
+ struct packed_rrset_data* d;
+ apex = az_find_name(z, z->name, z->namelen);
+ if(!apex) return 0;
+ soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA);
+ if(!soa || soa->data->count==0)
+ return 0; /* no RRset or no RRs in rrset */
+ if(soa->data->rr_len[0] < 2+4*5) return 0; /* SOA too short */
+ d = soa->data;
+ *serial = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-20));
+ return 1;
+}
+
/** Find auth_zone SOA and populate the values in xfr(soa values). */
static int
xfr_find_soa(struct auth_zone* z, struct auth_xfer* xfr)
@@ -1808,6 +1847,7 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
lock_rw_unlock(&az->lock);
/* set options */
+ z->zone_deleted = 0;
if(!auth_zone_set_zonefile(z, c->zonefile)) {
if(x) {
lock_basic_unlock(&x->lock);
@@ -1840,10 +1880,65 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
return 1;
}
+/** set all auth zones deleted, then in auth_zones_cfg, it marks them
+ * as nondeleted (if they are still in the config), and then later
+ * we can find deleted zones */
+static void
+az_setall_deleted(struct auth_zones* az)
+{
+ struct auth_zone* z;
+ lock_rw_wrlock(&az->lock);
+ RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
+ lock_rw_wrlock(&z->lock);
+ z->zone_deleted = 1;
+ lock_rw_unlock(&z->lock);
+ }
+ lock_rw_unlock(&az->lock);
+}
+
+/** find zones that are marked deleted and delete them.
+ * This is called from apply_cfg, and there are no threads and no
+ * workers, so the xfr can just be deleted. */
+static void
+az_delete_deleted_zones(struct auth_zones* az)
+{
+ struct auth_zone* z;
+ struct auth_zone* delete_list = NULL, *next;
+ struct auth_xfer* xfr;
+ lock_rw_wrlock(&az->lock);
+ RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
+ lock_rw_wrlock(&z->lock);
+ if(z->zone_deleted) {
+ /* we cannot alter the rbtree right now, but
+ * we can put it on a linked list and then
+ * delete it */
+ z->delete_next = delete_list;
+ delete_list = z;
+ }
+ lock_rw_unlock(&z->lock);
+ }
+ /* now we are out of the tree loop and we can loop and delete
+ * the zones */
+ z = delete_list;
+ while(z) {
+ next = z->delete_next;
+ xfr = auth_xfer_find(az, z->name, z->namelen, z->dclass);
+ if(xfr) {
+ (void)rbtree_delete(&az->xtree, &xfr->node);
+ auth_xfer_delete(xfr);
+ }
+ (void)rbtree_delete(&az->ztree, &z->node);
+ auth_zone_delete(z);
+ z = next;
+ }
+ lock_rw_unlock(&az->lock);
+}
+
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
int setup)
{
struct config_auth* p;
+ az_setall_deleted(az);
for(p = cfg->auths; p; p = p->next) {
if(!p->name || p->name[0] == 0) {
log_warn("auth-zone without a name, skipped");
@@ -1854,6 +1949,7 @@ int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
return 0;
}
}
+ az_delete_deleted_zones(az);
if(!auth_zones_read_zones(az))
return 0;
if(setup) {
@@ -1937,6 +2033,7 @@ auth_xfer_delete(struct auth_xfer* xfr)
}
free(xfr->task_transfer);
}
+ auth_free_masters(xfr->allow_notify_list);
free(xfr);
}
@@ -3153,10 +3250,13 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
/* answer it from zone z */
r = auth_zone_generate_answer(z, qinfo, temp, &msg, &fallback);
lock_rw_unlock(&z->lock);
- if(fallback) {
+ if(!r && fallback) {
/* fallback to regular answering (recursive) */
return 0;
}
+ lock_rw_wrlock(&az->lock);
+ az->num_query_down++;
+ lock_rw_unlock(&az->lock);
/* encode answer */
if(!r)
@@ -3186,6 +3286,187 @@ int auth_zones_can_fallback(struct auth_zones* az, uint8_t* nm, size_t nmlen,
return r;
}
+int
+auth_zone_parse_notify_serial(sldns_buffer* pkt, uint32_t *serial)
+{
+ struct query_info q;
+ uint16_t rdlen;
+ memset(&q, 0, sizeof(q));
+ sldns_buffer_set_position(pkt, 0);
+ if(!query_info_parse(&q, pkt)) return 0;
+ if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0) return 0;
+ /* skip name of RR in answer section */
+ if(sldns_buffer_remaining(pkt) < 1) return 0;
+ if(pkt_dname_len(pkt) == 0) return 0;
+ /* check type */
+ if(sldns_buffer_remaining(pkt) < 10 /* type,class,ttl,rdatalen*/)
+ return 0;
+ if(sldns_buffer_read_u16(pkt) != LDNS_RR_TYPE_SOA) return 0;
+ sldns_buffer_skip(pkt, 2); /* class */
+ sldns_buffer_skip(pkt, 4); /* ttl */
+ rdlen = sldns_buffer_read_u16(pkt); /* rdatalen */
+ if(sldns_buffer_remaining(pkt) < rdlen) return 0;
+ if(rdlen < 22) return 0; /* bad soa length */
+ sldns_buffer_skip(pkt, (ssize_t)(rdlen-20));
+ *serial = sldns_buffer_read_u32(pkt);
+ /* return true when has serial in answer section */
+ return 1;
+}
+
+/** see if addr appears in the list */
+static int
+addr_in_list(struct auth_addr* list, struct sockaddr_storage* addr,
+ socklen_t addrlen)
+{
+ struct auth_addr* p;
+ for(p=list; p; p=p->next) {
+ if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0)
+ return 1;
+ }
+ return 0;
+}
+
+/** check if an address matches a master specification (or one of its
+ * addresses in the addr list) */
+static int
+addr_matches_master(struct auth_master* master, struct sockaddr_storage* addr,
+ socklen_t addrlen, struct auth_master** fromhost)
+{
+ struct sockaddr_storage a;
+ socklen_t alen = 0;
+ int net = 0;
+ if(addr_in_list(master->list, addr, addrlen)) {
+ *fromhost = master;
+ return 1;
+ }
+ /* compare address (but not port number, that is the destination
+ * port of the master, the port number of the received notify is
+ * allowed to by any port on that master) */
+ if(extstrtoaddr(master->host, &a, &alen) &&
+ sockaddr_cmp_addr(addr, addrlen, &a, alen)==0) {
+ *fromhost = master;
+ return 1;
+ }
+ /* prefixes, addr/len, like 10.0.0.0/8 */
+ /* not http and has a / and there is one / */
+ if(master->allow_notify && !master->http &&
+ strchr(master->host, '/') != NULL &&
+ strchr(master->host, '/') == strrchr(master->host, '/') &&
+ netblockstrtoaddr(master->host, UNBOUND_DNS_PORT, &a, &alen,
+ &net) && alen == addrlen) {
+ if(addr_in_common(addr, (addr_is_ip6(addr, addrlen)?128:32),
+ &a, net, alen) >= net) {
+ *fromhost = NULL; /* prefix does not have destination
+ to send the probe or transfer with */
+ return 1; /* matches the netblock */
+ }
+ }
+ return 0;
+}
+
+/** check access list for notifies */
+static int
+az_xfr_allowed_notify(struct auth_xfer* xfr, struct sockaddr_storage* addr,
+ socklen_t addrlen, struct auth_master** fromhost)
+{
+ struct auth_master* p;
+ for(p=xfr->allow_notify_list; p; p=p->next) {
+ if(addr_matches_master(p, addr, addrlen, fromhost)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/** see if the serial means the zone has to be updated, i.e. the serial
+ * is newer than the zone serial, or we have no zone */
+static int
+xfr_serial_means_update(struct auth_xfer* xfr, uint32_t serial)
+{
+ if(!xfr->have_zone)
+ return 1; /* no zone, anything is better */
+ if(xfr->zone_expired)
+ return 1; /* expired, the sent serial is better than expired
+ data */
+ if(compare_serial(xfr->serial, serial) < 0)
+ return 1; /* our serial is smaller than the sent serial,
+ the data is newer, fetch it */
+ return 0;
+}
+
+/** note notify serial, updates the notify information in the xfr struct */
+static void
+xfr_note_notify_serial(struct auth_xfer* xfr, int has_serial, uint32_t serial)
+{
+ if(xfr->notify_received && xfr->notify_has_serial && has_serial) {
+ /* see if this serial is newer */
+ if(compare_serial(xfr->notify_serial, serial) < 0)
+ xfr->notify_serial = serial;
+ } else if(xfr->notify_received && xfr->notify_has_serial &&
+ !has_serial) {
+ /* remove serial, we have notify without serial */
+ xfr->notify_has_serial = 0;
+ xfr->notify_serial = 0;
+ } else if(xfr->notify_received && !xfr->notify_has_serial) {
+ /* we already have notify without serial, keep it
+ * that way; no serial check when current operation
+ * is done */
+ } else {
+ xfr->notify_received = 1;
+ xfr->notify_has_serial = has_serial;
+ xfr->notify_serial = serial;
+ }
+}
+
+/** process a notify serial, start new probe or note serial. xfr is locked */
+static void
+xfr_process_notify(struct auth_xfer* xfr, struct module_env* env,
+ int has_serial, uint32_t serial, struct auth_master* fromhost)
+{
+ /* if the serial of notify is older than we have, don't fetch
+ * a zone, we already have it */
+ if(has_serial && !xfr_serial_means_update(xfr, serial))
+ return;
+ /* start new probe with this addr src, or note serial */
+ if(!xfr_start_probe(xfr, env, fromhost)) {
+ /* not started because already in progress, note the serial */
+ xfr_note_notify_serial(xfr, has_serial, serial);
+ lock_basic_unlock(&xfr->lock);
+ }
+}
+
+int auth_zones_notify(struct auth_zones* az, struct module_env* env,
+ uint8_t* nm, size_t nmlen, uint16_t dclass,
+ struct sockaddr_storage* addr, socklen_t addrlen, int has_serial,
+ uint32_t serial, int* refused)
+{
+ struct auth_xfer* xfr;
+ struct auth_master* fromhost = NULL;
+ /* see which zone this is */
+ lock_rw_rdlock(&az->lock);
+ xfr = auth_xfer_find(az, nm, nmlen, dclass);
+ if(!xfr) {
+ lock_rw_unlock(&az->lock);
+ /* no such zone, refuse the notify */
+ *refused = 1;
+ return 0;
+ }
+ lock_basic_lock(&xfr->lock);
+ lock_rw_unlock(&az->lock);
+
+ /* check access list for notifies */
+ if(!az_xfr_allowed_notify(xfr, addr, addrlen, &fromhost)) {
+ lock_basic_unlock(&xfr->lock);
+ /* notify not allowed, refuse the notify */
+ *refused = 1;
+ return 0;
+ }
+
+ /* process the notify */
+ xfr_process_notify(xfr, env, has_serial, serial, fromhost);
+ return 1;
+}
+
/** set a zone expired */
static void
auth_xfer_set_expired(struct auth_xfer* xfr, struct module_env* env,
@@ -3239,6 +3520,93 @@ xfr_masterlist_free_addrs(struct auth_master* list)
}
}
+/** copy a list of auth_addrs */
+static struct auth_addr*
+auth_addr_list_copy(struct auth_addr* source)
+{
+ struct auth_addr* list = NULL, *last = NULL;
+ struct auth_addr* p;
+ for(p=source; p; p=p->next) {
+ struct auth_addr* a = (struct auth_addr*)memdup(p, sizeof(*p));
+ if(!a) {
+ log_err("malloc failure");
+ auth_free_master_addrs(list);
+ return NULL;
+ }
+ a->next = NULL;
+ if(last) last->next = a;
+ if(!list) list = a;
+ last = a;
+ }
+ return list;
+}
+
+/** copy a master to a new structure, NULL on alloc failure */
+static struct auth_master*
+auth_master_copy(struct auth_master* o)
+{
+ struct auth_master* m;
+ if(!o) return NULL;
+ m = (struct auth_master*)memdup(o, sizeof(*o));
+ if(!m) {
+ log_err("malloc failure");
+ return NULL;
+ }
+ m->next = NULL;
+ if(m->host) {
+ m->host = strdup(m->host);
+ if(!m->host) {
+ free(m);
+ log_err("malloc failure");
+ return NULL;
+ }
+ }
+ if(m->file) {
+ m->file = strdup(m->file);
+ if(!m->file) {
+ free(m->host);
+ free(m);
+ log_err("malloc failure");
+ return NULL;
+ }
+ }
+ if(m->list) {
+ m->list = auth_addr_list_copy(m->list);
+ if(!m->list) {
+ free(m->file);
+ free(m->host);
+ free(m);
+ return NULL;
+ }
+ }
+ return m;
+}
+
+/** copy the master addresses from the task_probe lookups to the allow_notify
+ * list of masters */
+static void
+probe_copy_masters_for_allow_notify(struct auth_xfer* xfr)
+{
+ struct auth_master* list = NULL, *last = NULL;
+ struct auth_master* p;
+ /* build up new list with copies */
+ for(p = xfr->task_probe->masters; p; p=p->next) {
+ struct auth_master* m = auth_master_copy(p);
+ if(!m) {
+ auth_free_masters(list);
+ /* failed because of malloc failure, use old list */
+ return;
+ }
+ m->next = NULL;
+ if(last) last->next = m;
+ if(!list) list = m;
+ last = m;
+ }
+ /* success, replace list */
+ auth_free_masters(xfr->allow_notify_list);
+ xfr->allow_notify_list = list;
+}
+
/** start the lookups for task_transfer */
static void
xfr_transfer_start_lookups(struct auth_xfer* xfr)
@@ -3400,11 +3768,19 @@ xfr_transfer_nextmaster(struct auth_xfer* xfr)
if(xfr->task_transfer->scan_specific) {
xfr->task_transfer->scan_specific = NULL;
xfr->task_transfer->scan_target = xfr->task_transfer->masters;
+ if(xfr->task_transfer->scan_target && xfr->task_transfer->
+ scan_target->list)
+ xfr->task_transfer->scan_addr =
+ xfr->task_transfer->scan_target->list;
return;
}
if(!xfr->task_transfer->scan_target)
return;
xfr->task_transfer->scan_target = xfr->task_transfer->scan_target->next;
+ if(xfr->task_transfer->scan_target && xfr->task_transfer->
+ scan_target->list)
+ xfr->task_transfer->scan_addr =
+ xfr->task_transfer->scan_target->list;
return;
}
@@ -3422,11 +3798,19 @@ xfr_probe_nextmaster(struct auth_xfer* xfr)
if(xfr->task_probe->scan_specific) {
xfr->task_probe->scan_specific = NULL;
xfr->task_probe->scan_target = xfr->task_probe->masters;
+ if(xfr->task_probe->scan_target && xfr->task_probe->
+ scan_target->list)
+ xfr->task_probe->scan_addr =
+ xfr->task_probe->scan_target->list;
return;
}
if(!xfr->task_probe->scan_target)
return;
xfr->task_probe->scan_target = xfr->task_probe->scan_target->next;
+ if(xfr->task_probe->scan_target && xfr->task_probe->
+ scan_target->list)
+ xfr->task_probe->scan_addr =
+ xfr->task_probe->scan_target->list;
return;
}
@@ -3581,22 +3965,6 @@ check_packet_ok(sldns_buffer* pkt, uint16_t qtype, struct auth_xfer* xfr,
return 1;
}
-/** see if the serial means the zone has to be updated, i.e. the serial
- * is newer than the zone serial, or we have no zone */
-static int
-xfr_serial_means_update(struct auth_xfer* xfr, uint32_t serial)
-{
- if(!xfr->have_zone)
- return 1; /* no zone, anything is better */
- if(xfr->zone_expired)
- return 1; /* expired, the sent serial is better than expired
- data */
- if(compare_serial(xfr->serial, serial) < 0)
- return 1; /* our serial is smaller than the sent serial,
- the data is newer, fetch it */
- return 0;
-}
-
/** read one line from chunks into buffer at current position */
static int
chunkline_get_line(struct auth_chunk** chunk, size_t* chunk_pos,
@@ -3870,6 +4238,11 @@ chunkline_newline_removal(sldns_buffer* buf)
size_t i, end=sldns_buffer_limit(buf);
for(i=0; i<end; i++) {
char c = (char)sldns_buffer_read_u8_at(buf, i);
+ if(c == '\n' && i==end-1) {
+ sldns_buffer_write_u8_at(buf, i, 0);
+ sldns_buffer_set_limit(buf, end-1);
+ return;
+ }
if(c == '\n')
sldns_buffer_write_u8_at(buf, i, (uint8_t)' ');
}
@@ -4032,6 +4405,56 @@ log_rrlist_position(const char* label, struct auth_chunk* rr_chunk,
str, typestr);
}
+/** check that start serial is OK for ixfr. we are at rr_counter == 0,
+ * and we are going to check rr_counter == 1 (has to be type SOA) serial */
+static int
+ixfr_start_serial(struct auth_chunk* rr_chunk, int rr_num, size_t rr_pos,
+ uint8_t* rr_dname, uint16_t rr_type, uint16_t rr_class,
+ uint32_t rr_ttl, uint16_t rr_rdlen, uint8_t* rr_rdata,
+ size_t rr_nextpos, uint32_t transfer_serial, uint32_t xfr_serial)
+{
+ uint32_t startserial;
+ /* move forward on RR */
+ chunk_rrlist_gonext(&rr_chunk, &rr_num, &rr_pos, rr_nextpos);
+ if(chunk_rrlist_end(rr_chunk, rr_num)) {
+ /* no second SOA */
+ verbose(VERB_OPS, "IXFR has no second SOA record");
+ return 0;
+ }
+ if(!chunk_rrlist_get_current(rr_chunk, rr_num, rr_pos,
+ &rr_dname, &rr_type, &rr_class, &rr_ttl, &rr_rdlen,
+ &rr_rdata, &rr_nextpos)) {
+ verbose(VERB_OPS, "IXFR cannot parse second SOA record");
+ /* failed to parse RR */
+ return 0;
+ }
+ if(rr_type != LDNS_RR_TYPE_SOA) {
+ verbose(VERB_OPS, "IXFR second record is not type SOA");
+ return 0;
+ }
+ if(rr_rdlen < 22) {
+ verbose(VERB_OPS, "IXFR, second SOA has short rdlength");
+ return 0; /* bad SOA rdlen */
+ }
+ startserial = sldns_read_uint32(rr_rdata+rr_rdlen-20);
+ if(startserial == transfer_serial) {
+ /* empty AXFR, not an IXFR */
+ verbose(VERB_OPS, "IXFR second serial same as first");
+ return 0;
+ }
+ if(startserial != xfr_serial) {
+ /* wrong start serial, it does not match the serial in
+ * memory */
+ verbose(VERB_OPS, "IXFR is from serial %u to %u but %u "
+ "in memory, rejecting the zone transfer",
+ (unsigned)startserial, (unsigned)transfer_serial,
+ (unsigned)xfr_serial);
+ return 0;
+ }
+ /* everything OK in second SOA serial */
+ return 1;
+}
+
/** apply IXFR to zone in memory. z is locked. false on failure(mallocfail) */
static int
apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z,
@@ -4078,6 +4501,13 @@ apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z,
have_transfer_serial = 1;
transfer_serial = serial;
delmode = 1; /* gets negated below */
+ /* check second RR before going any further */
+ if(!ixfr_start_serial(rr_chunk, rr_num, rr_pos,
+ rr_dname, rr_type, rr_class, rr_ttl,
+ rr_rdlen, rr_rdata, rr_nextpos,
+ transfer_serial, xfr->serial)) {
+ return 0;
+ }
} else if(transfer_serial == serial) {
have_transfer_serial++;
if(rr_counter == 1) {
@@ -4308,6 +4738,28 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z,
return 1;
}
+/** write http chunks to zonefile to create downloaded file */
+static int
+auth_zone_write_chunks(struct auth_xfer* xfr, const char* fname)
+{
+ FILE* out;
+ struct auth_chunk* p;
+ out = fopen(fname, "w");
+ if(!out) {
+ log_err("could not open %s: %s", fname, strerror(errno));
+ return 0;
+ }
+ for(p = xfr->task_transfer->chunks_first; p ; p = p->next) {
+ if(!write_out(out, (char*)p->data, p->len)) {
+ log_err("could not write http download to %s", fname);
+ fclose(out);
+ return 0;
+ }
+ }
+ fclose(out);
+ return 1;
+}
+
/** write to zonefile after zone has been updated */
static void
xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
@@ -4346,7 +4798,13 @@ xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
}
snprintf(tmpfile, sizeof(tmpfile), "%s.tmp%u", z->zonefile,
(unsigned)getpid());
- if(!auth_zone_write_file(z, tmpfile)) {
+ if(xfr->task_transfer->master->http) {
+ /* use the stored chunk list to write them */
+ if(!auth_zone_write_chunks(xfr, tmpfile)) {
+ unlink(tmpfile);
+ lock_rw_unlock(&z->lock);
+ }
+ } else if(!auth_zone_write_file(z, tmpfile)) {
unlink(tmpfile);
lock_rw_unlock(&z->lock);
return;
@@ -4465,6 +4923,9 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
/* not needed, host is in IP addr format */
return 0;
}
+ if(master->allow_notify)
+ return 0; /* allow-notifies are not transferred from, no
+ lookup is needed */
/* use mesh_new_callback to probe for non-addr hosts,
* and then wait for them to be looked up (in cache, or query) */
@@ -4519,6 +4980,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
socklen_t addrlen = 0;
struct auth_master* master = xfr->task_transfer->master;
if(!master) return 0;
+ if(master->allow_notify) return 0; /* only for notify */
/* get master addr */
if(xfr->task_transfer->scan_addr) {
@@ -4623,7 +5085,7 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
xfr_transfer_disown(xfr);
/* pick up the nextprobe task and wait */
- xfr_set_timeout(xfr, env, 1);
+ xfr_set_timeout(xfr, env, 1, 0);
lock_basic_unlock(&xfr->lock);
}
@@ -4635,6 +5097,8 @@ xfr_master_add_addrs(struct auth_master* m, struct ub_packed_rrset_key* rrset,
size_t i;
struct packed_rrset_data* data;
if(!m || !rrset) return;
+ if(rrtype != LDNS_RR_TYPE_A && rrtype != LDNS_RR_TYPE_AAAA)
+ return;
data = (struct packed_rrset_data*)rrset->entry.data;
for(i=0; i<data->count; i++) {
struct auth_addr* a;
@@ -5056,8 +5520,30 @@ process_list_end_transfer(struct auth_xfer* xfr, struct module_env* env)
/* we fetched the zone, move to wait task */
xfr_transfer_disown(xfr);
- /* pick up the nextprobe task and wait (normail wait time) */
- xfr_set_timeout(xfr, env, 0);
+ if(xfr->notify_received && (!xfr->notify_has_serial ||
+ (xfr->notify_has_serial &&
+ xfr_serial_means_update(xfr, xfr->notify_serial)))) {
+ uint32_t sr = xfr->notify_serial;
+ int has_sr = xfr->notify_has_serial;
+ /* we received a notify while probe/transfer was
+ * in progress. start a new probe and transfer */
+ xfr->notify_received = 0;
+ xfr->notify_has_serial = 0;
+ xfr->notify_serial = 0;
+ if(!xfr_start_probe(xfr, env, NULL)) {
+ /* if we couldn't start it, already in
+ * progress; restore notify serial,
+ * while xfr still locked */
+ xfr->notify_received = 1;
+ xfr->notify_has_serial = has_sr;
+ xfr->notify_serial = sr;
+ lock_basic_unlock(&xfr->lock);
+ }
+ return;
+ } else {
+ /* pick up the nextprobe task and wait (normail wait time) */
+ xfr_set_timeout(xfr, env, 0, 0);
+ }
lock_basic_unlock(&xfr->lock);
return;
}
@@ -5248,6 +5734,9 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
/* pick master */
struct auth_master* master = xfr_probe_current_master(xfr);
if(!master) return 0;
+ if(master->allow_notify) return 0; /* only for notify */
+ if(master->http) return 0; /* only masters get SOA UDP probe,
+ not urls, if those are in this list */
/* get master addr */
if(xfr->task_probe->scan_addr) {
@@ -5400,7 +5889,7 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
if(xfr->have_zone)
xfr->lease_time = *env->now;
if(xfr->task_nextprobe->worker == NULL)
- xfr_set_timeout(xfr, env, 0);
+ xfr_set_timeout(xfr, env, 0, 0);
}
/* other tasks are running, we don't do this anymore */
xfr_probe_disown(xfr);
@@ -5445,6 +5934,11 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
/* not needed, host is in IP addr format */
return 0;
}
+ if(master->allow_notify && !master->http &&
+ strchr(master->host, '/') != NULL &&
+ strchr(master->host, '/') == strrchr(master->host, '/')) {
+ return 0; /* is IP/prefix format, not something to look up */
+ }
/* use mesh_new_callback to probe for non-addr hosts,
* and then wait for them to be looked up (in cache, or query) */
@@ -5507,6 +6001,17 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
}
xfr_probe_move_to_next_lookup(xfr, env);
}
+ /* probe of list has ended. Create or refresh the list of of
+ * allow_notify addrs */
+ probe_copy_masters_for_allow_notify(xfr);
+ if(xfr->task_probe->only_lookup) {
+ /* only wanted lookups for copy, stop probe and start wait */
+ xfr->task_probe->only_lookup = 0;
+ xfr_probe_disown(xfr);
+ xfr_set_timeout(xfr, env, 0, 0);
+ lock_basic_unlock(&xfr->lock);
+ return;
+ }
/* send probe packets */
while(!xfr_probe_end_of_list(xfr)) {
@@ -5524,7 +6029,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
xfr_probe_disown(xfr);
/* pick up the nextprobe task and wait */
- xfr_set_timeout(xfr, env, 1);
+ xfr_set_timeout(xfr, env, 1, 0);
lock_basic_unlock(&xfr->lock);
}
@@ -5611,19 +6116,45 @@ auth_xfer_timer(void* arg)
xfr_nextprobe_disown(xfr);
+ if(!xfr_start_probe(xfr, env, NULL)) {
+ /* not started because already in progress */
+ lock_basic_unlock(&xfr->lock);
+ }
+}
+
+/** return true if there are probe (SOA UDP query) targets in the master list*/
+static int
+have_probe_targets(struct auth_master* list)
+{
+ struct auth_master* p;
+ for(p=list; p; p = p->next) {
+ if(!p->allow_notify && p->host)
+ return 1;
+ }
+ return 0;
+}
+
+/** start task_probe if possible, if no masters for probe start task_transfer
+ * returns true if task has been started, and false if the task is already
+ * in progress. */
+static int
+xfr_start_probe(struct auth_xfer* xfr, struct module_env* env,
+ struct auth_master* spec)
+{
/* see if we need to start a probe (or maybe it is already in
* progress (due to notify)) */
if(xfr->task_probe->worker == NULL) {
- if(xfr->task_probe->masters == NULL) {
+ if(!have_probe_targets(xfr->task_probe->masters) &&
+ !(xfr->task_probe->only_lookup &&
+ xfr->task_probe->masters != NULL)) {
/* useless to pick up task_probe, no masters to
* probe. Instead attempt to pick up task transfer */
if(xfr->task_transfer->worker == NULL) {
- xfr_start_transfer(xfr, env, NULL);
- } else {
- /* task transfer already in progress */
- lock_basic_unlock(&xfr->lock);
+ xfr_start_transfer(xfr, env, spec);
+ return 1;
}
- return;
+ /* task transfer already in progress */
+ return 0;
}
/* pick up the probe task ourselves */
@@ -5632,15 +6163,17 @@ auth_xfer_timer(void* arg)
xfr->task_probe->cp = NULL;
/* start the task */
- /* this was a timeout, so no specific first master to scan */
- xfr_probe_start_list(xfr, NULL);
+ /* if this was a timeout, no specific first master to scan */
+ /* otherwise, spec is nonNULL the notified master, scan
+ * first and also transfer first from it */
+ xfr_probe_start_list(xfr, spec);
/* setup to start the lookup of hostnames of masters afresh */
xfr_probe_start_lookups(xfr);
/* send the probe packet or next send, or end task */
xfr_probe_send_or_end(xfr, env);
- } else {
- lock_basic_unlock(&xfr->lock);
+ return 1;
}
+ return 0;
}
/** for task_nextprobe.
@@ -5648,10 +6181,11 @@ auth_xfer_timer(void* arg)
* @param xfr: task structure
* @param env: module environment, with worker and time.
* @param failure: set true if timer should be set for failure retry.
+ * @param lookup_only: only perform lookups when timer done, 0 sec timeout
*/
static void
xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
- int failure)
+ int failure, int lookup_only)
{
struct timeval tv;
log_assert(xfr->task_nextprobe != NULL);
@@ -5661,7 +6195,7 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
* but if expiry is sooner, use that one.
* after a failure, use the retry timer instead. */
xfr->task_nextprobe->next_probe = *env->now;
- if(xfr->lease_time)
+ if(xfr->lease_time && !failure)
xfr->task_nextprobe->next_probe = xfr->lease_time;
if(!failure) {
@@ -5684,6 +6218,12 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
if(failure)
xfr->task_nextprobe->next_probe +=
xfr->task_nextprobe->backoff;
+ /* put the timer exactly on expiry, if possible */
+ if(xfr->lease_time && xfr->lease_time+xfr->expiry <
+ xfr->task_nextprobe->next_probe &&
+ xfr->lease_time+xfr->expiry > *env->now)
+ xfr->task_nextprobe->next_probe =
+ xfr->lease_time+xfr->expiry;
} else {
xfr->task_nextprobe->next_probe +=
xfr->task_nextprobe->backoff;
@@ -5708,6 +6248,13 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
tv.tv_sec = xfr->task_nextprobe->next_probe -
*(xfr->task_nextprobe->env->now);
else tv.tv_sec = 0;
+ if(tv.tv_sec != 0 && lookup_only && xfr->task_probe->masters) {
+ /* don't lookup_only, if lookup timeout is 0 anyway,
+ * or if we don't have masters to lookup */
+ tv.tv_sec = 0;
+ if(xfr->task_probe && xfr->task_probe->worker == NULL)
+ xfr->task_probe->only_lookup = 1;
+ }
if(verbosity >= VERB_ALGO) {
char zname[255+1];
dname_str(xfr->name, zname);
@@ -5731,8 +6278,9 @@ auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env)
* notes the start time when the data was acquired */
if(x->have_zone)
x->lease_time = *env->now;
- if(x->task_nextprobe && x->task_nextprobe->worker == NULL)
- xfr_set_timeout(x, env, 0);
+ if(x->task_nextprobe && x->task_nextprobe->worker == NULL) {
+ xfr_set_timeout(x, env, 0, 1);
+ }
lock_basic_unlock(&x->lock);
}
lock_rw_unlock(&az->lock);
@@ -5889,7 +6437,7 @@ static char*
dup_all(char* str)
{
char* result = strdup(str);
- if(!str) {
+ if(!result) {
log_err("malloc failure");
return NULL;
}
@@ -6006,6 +6554,15 @@ xfer_set_masters(struct auth_master** list, struct config_auth* c,
return 0;
}
}
+ for(p = c->allow_notify; p; p = p->next) {
+ m = auth_master_new(&list);
+ m->allow_notify = 1;
+ m->host = strdup(p->str);
+ if(!m->host) {
+ log_err("malloc failure");
+ return 0;
+ }
+ }
return 1;
}
diff --git a/contrib/unbound/services/authzone.h b/contrib/unbound/services/authzone.h
index d54ef4b96e49..4e06c0654d99 100644
--- a/contrib/unbound/services/authzone.h
+++ b/contrib/unbound/services/authzone.h
@@ -77,6 +77,10 @@ struct auth_zones {
rbtree_type xtree;
/** do we have downstream enabled */
int have_downstream;
+ /** number of queries upstream */
+ size_t num_query_up;
+ /** number of queries downstream */
+ size_t num_query_down;
};
/**
@@ -122,6 +126,10 @@ struct auth_zone {
/** for upstream: this zone answers queries that unbound intends to
* send upstream. */
int for_upstream;
+ /** zone has been deleted */
+ int zone_deleted;
+ /** deletelist pointer, unused normally except during delete */
+ struct auth_zone* delete_next;
};
/**
@@ -214,8 +222,14 @@ struct auth_xfer {
* Hold the lock to access this member (and the serial).
*/
int notify_received;
+ /** true if the notify_received has a serial number */
+ int notify_has_serial;
/** serial number of the notify */
uint32_t notify_serial;
+ /** the list of masters for checking notifies. This list is
+ * empty on start, and a copy of the list from the probe_task when
+ * it is done looking them up. */
+ struct auth_master* allow_notify_list;
/* protected by the lock on the structure, information about
* the loaded authority zone. */
@@ -292,6 +306,9 @@ struct auth_probe {
struct auth_master* lookup_target;
/** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */
int lookup_aaaa;
+ /** we only want to do lookups for making config work (for notify),
+ * don't proceed with UDP SOA probe queries */
+ int only_lookup;
/** once notified, or the timeout has been reached. a scan starts. */
/** the scan specific target (notify source), or NULL if none */
@@ -400,6 +417,9 @@ struct auth_master {
int http;
/** use IXFR for this master */
int ixfr;
+ /** this is an allow notify member, the master can send notifies
+ * to us, but we don't send SOA probes, or zone transfer from it */
+ int allow_notify;
/** use ssl for channel */
int ssl;
/** the port number (for urls) */
@@ -541,9 +561,39 @@ int auth_zone_set_fallback(struct auth_zone* z, char* fallbackstr);
int auth_zones_can_fallback(struct auth_zones* az, uint8_t* nm, size_t nmlen,
uint16_t dclass);
+/** process notify for auth zones.
+ * first checks the access list. Then processes the notify. This starts
+ * the probe sequence or it notes the serial number (if any)
+ * @param az: auth zones structure.
+ * @param env: module env of the worker that is handling the notify. it will
+ * pick up the task probe (or transfer), unless already in progress by
+ * another worker.
+ * @param nm: name of the zone. Uncompressed. from query.
+ * @param nmlen: length of name.
+ * @param dclass: class of zone.
+ * @param addr: source address of notify
+ * @param addrlen: length of addr.
+ * @param has_serial: if true, the notify has a serial attached.
+ * @param serial: the serial number, if has_serial is true.
+ * @param refused: is set to true on failure to note refused access.
+ * @return fail on failures (refused is false) and when access is
+ * denied (refused is true). True when processed.
+ */
+int auth_zones_notify(struct auth_zones* az, struct module_env* env,
+ uint8_t* nm, size_t nmlen, uint16_t dclass,
+ struct sockaddr_storage* addr, socklen_t addrlen, int has_serial,
+ uint32_t serial, int* refused);
+
+/** process notify packet and read serial number from SOA.
+ * returns 0 if no soa record in the notify */
+int auth_zone_parse_notify_serial(struct sldns_buffer* pkt, uint32_t *serial);
+
/** read auth zone from zonefile. caller must lock zone. false on failure */
int auth_zone_read_zonefile(struct auth_zone* z);
+/** find serial number of zone or false if none (no SOA record) */
+int auth_zone_get_serial(struct auth_zone* z, uint32_t* serial);
+
/** compare auth_zones for sorted rbtree */
int auth_zone_cmp(const void* z1, const void* z2);
diff --git a/contrib/unbound/services/cache/dns.c b/contrib/unbound/services/cache/dns.c
index 411793c6c270..35adc35b57ee 100644
--- a/contrib/unbound/services/cache/dns.c
+++ b/contrib/unbound/services/cache/dns.c
@@ -108,6 +108,48 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
}
}
+/** delete message from message cache */
+static void
+msg_cache_remove(struct module_env* env, uint8_t* qname, size_t qnamelen,
+ uint16_t qtype, uint16_t qclass, uint16_t flags)
+{
+ struct query_info k;
+ hashvalue_type h;
+
+ k.qname = qname;
+ k.qname_len = qnamelen;
+ k.qtype = qtype;
+ k.qclass = qclass;
+ k.local_alias = NULL;
+ h = query_info_hash(&k, flags);
+ slabhash_remove(env->msg_cache, h, &k);
+}
+
+/** remove servfail msg cache entry */
+static void
+msg_del_servfail(struct module_env* env, struct query_info* qinfo,
+ uint32_t flags)
+{
+ struct msgreply_entry* e;
+ /* see if the entry is servfail, and then remove it, so that
+ * lookups move from the cacheresponse stage to the recursionresponse
+ * stage */
+ e = msg_cache_lookup(env, qinfo->qname, qinfo->qname_len,
+ qinfo->qtype, qinfo->qclass, flags, 0, 0);
+ if(!e) return;
+ /* we don't check for the ttl here, also expired servfail entries
+ * are removed. If the user uses serve-expired, they would still be
+ * used to answer from cache */
+ if(FLAGS_GET_RCODE(((struct reply_info*)e->entry.data)->flags)
+ != LDNS_RCODE_SERVFAIL) {
+ lock_rw_unlock(&e->entry.lock);
+ return;
+ }
+ lock_rw_unlock(&e->entry.lock);
+ msg_cache_remove(env, qinfo->qname, qinfo->qname_len, qinfo->qtype,
+ qinfo->qclass, flags);
+}
+
void
dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside,
@@ -132,6 +174,12 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
* which could be useful for delegation information */
verbose(VERB_ALGO, "TTL 0: dropped msg from cache");
free(rep);
+ /* if the message is SERVFAIL in cache, remove that SERVFAIL,
+ * so that the TTL 0 response can be returned for future
+ * responses (i.e. don't get answered by the servfail from
+ * cache, but instead go to recursion to get this TTL0
+ * response). */
+ msg_del_servfail(env, qinfo, flags);
return;
}
diff --git a/contrib/unbound/services/cache/rrset.c b/contrib/unbound/services/cache/rrset.c
index 0b41fcd7dc3f..26c1aeb91c62 100644
--- a/contrib/unbound/services/cache/rrset.c
+++ b/contrib/unbound/services/cache/rrset.c
@@ -255,9 +255,11 @@ void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
wc_dname[1] = (uint8_t)'*';
memmove(wc_dname+2, ce, ce_len);
+ free(rrset->rk.dname);
rrset->rk.dname_len = ce_len + 2;
rrset->rk.dname = (uint8_t*)memdup(wc_dname, rrset->rk.dname_len);
if(!rrset->rk.dname) {
+ alloc_special_release(alloc, rrset);
log_err("memdup failure in rrset_cache_update_wildcard");
return;
}
diff --git a/contrib/unbound/services/listen_dnsport.c b/contrib/unbound/services/listen_dnsport.c
index d099ca9449b7..6639fd3fc5cf 100644
--- a/contrib/unbound/services/listen_dnsport.c
+++ b/contrib/unbound/services/listen_dnsport.c
@@ -1056,6 +1056,26 @@ set_recvpktinfo(int s, int family)
return 1;
}
+/** see if interface is ssl, its port number == the ssl port number */
+static int
+if_is_ssl(const char* ifname, const char* port, int ssl_port,
+ struct config_strlist* additional_tls_port)
+{
+ struct config_strlist* s;
+ char* p = strchr(ifname, '@');
+ if(!p && atoi(port) == ssl_port)
+ return 1;
+ if(p && atoi(p+1) == ssl_port)
+ return 1;
+ for(s = additional_tls_port; s; s = s->next) {
+ if(p && atoi(p+1) == atoi(s->str))
+ return 1;
+ if(!p && atoi(port) == atoi(s->str))
+ return 1;
+ }
+ return 0;
+}
+
/**
* Helper for ports_open. Creates one interface (or NULL for default).
* @param ifname: The interface ip address.
@@ -1069,6 +1089,7 @@ set_recvpktinfo(int s, int family)
* @param rcv: receive buffer size for UDP
* @param snd: send buffer size for UDP
* @param ssl_port: ssl service port number
+ * @param additional_tls_port: list of additional ssl service port numbers.
* @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.
@@ -1081,8 +1102,10 @@ set_recvpktinfo(int s, int family)
static int
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
struct addrinfo *hints, const char* port, struct listen_port** list,
- size_t rcv, size_t snd, int ssl_port, int* reuseport, int transparent,
- int tcp_mss, int freebind, int use_systemd, int dnscrypt_port)
+ size_t rcv, size_t snd, int ssl_port,
+ struct config_strlist* additional_tls_port, int* reuseport,
+ int transparent, int tcp_mss, int freebind, int use_systemd,
+ int dnscrypt_port)
{
int s, noip6=0;
#ifdef USE_DNSCRYPT
@@ -1146,9 +1169,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
}
if(do_tcp) {
- int is_ssl = ((strchr(ifname, '@') &&
- atoi(strchr(ifname, '@')+1) == ssl_port) ||
- (!strchr(ifname, '@') && atoi(port) == ssl_port));
+ int is_ssl = if_is_ssl(ifname, port, ssl_port,
+ additional_tls_port);
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
&noip6, 0, 0, reuseport, transparent, tcp_mss,
freebind, use_systemd)) == -1) {
@@ -1334,8 +1356,8 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
- cfg->ssl_port, reuseport,
- cfg->ip_transparent,
+ cfg->ssl_port, cfg->additional_tls_port,
+ reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
cfg->dnscrypt_port)) {
listening_ports_free(list);
@@ -1348,8 +1370,8 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
do_auto, cfg->do_udp, do_tcp,
&hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
- cfg->ssl_port, reuseport,
- cfg->ip_transparent,
+ cfg->ssl_port, cfg->additional_tls_port,
+ reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
cfg->dnscrypt_port)) {
listening_ports_free(list);
@@ -1364,8 +1386,8 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
do_tcp, &hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
- cfg->ssl_port, reuseport,
- cfg->ip_transparent,
+ cfg->ssl_port, cfg->additional_tls_port,
+ reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
cfg->dnscrypt_port)) {
listening_ports_free(list);
@@ -1378,8 +1400,8 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp,
do_tcp, &hints, portbuf, &list,
cfg->so_rcvbuf, cfg->so_sndbuf,
- cfg->ssl_port, reuseport,
- cfg->ip_transparent,
+ cfg->ssl_port, cfg->additional_tls_port,
+ reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
cfg->dnscrypt_port)) {
listening_ports_free(list);
diff --git a/contrib/unbound/services/mesh.c b/contrib/unbound/services/mesh.c
index 3395dc62e674..3027cef00900 100644
--- a/contrib/unbound/services/mesh.c
+++ b/contrib/unbound/services/mesh.c
@@ -736,7 +736,8 @@ mesh_state_cleanup(struct mesh_state* mstate)
comm_point_drop_reply(&rep->query_reply);
mesh->num_reply_addrs--;
}
- for(cb=mstate->cb_list; cb; cb=cb->next) {
+ while((cb = mstate->cb_list)!=NULL) {
+ mstate->cb_list = cb->next;
fptr_ok(fptr_whitelist_mesh_cb(cb->cb));
(*cb->cb)(cb->cb_arg, LDNS_RCODE_SERVFAIL, NULL,
sec_status_unchecked, NULL);
@@ -974,7 +975,8 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
else secure = 0;
if(!rep && rcode == LDNS_RCODE_NOERROR)
rcode = LDNS_RCODE_SERVFAIL;
- if(!rcode && rep->security == sec_status_bogus) {
+ if(!rcode && (rep->security == sec_status_bogus ||
+ rep->security == sec_status_secure_sentinel_fail)) {
if(!(reason = errinf_to_str(&m->s)))
rcode = LDNS_RCODE_SERVFAIL;
}
@@ -1040,7 +1042,8 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
/* examine security status */
if(m->s.env->need_to_validate && (!(r->qflags&BIT_CD) ||
m->s.env->cfg->ignore_cd) && rep &&
- rep->security <= sec_status_bogus) {
+ (rep->security <= sec_status_bogus ||
+ rep->security == sec_status_secure_sentinel_fail)) {
rcode = LDNS_RCODE_SERVFAIL;
if(m->s.env->cfg->stat_extended)
m->s.env->mesh->ans_bogus++;
@@ -1167,7 +1170,13 @@ void mesh_query_done(struct mesh_state* mstate)
}
}
mstate->replies_sent = 1;
- for(c = mstate->cb_list; c; c = c->next) {
+ while((c = mstate->cb_list) != NULL) {
+ /* take this cb off the list; so that the list can be
+ * changed, eg. by adds from the callback routine */
+ mstate->cb_list = c->next;
+ if(!mstate->reply_list && !mstate->cb_list &&
+ mstate->super_set.count == 0)
+ mstate->s.env->mesh->num_detached_states++;
mesh_do_callback(mstate, mstate->s.return_rcode, rep, c);
}
}
diff --git a/contrib/unbound/services/outside_network.c b/contrib/unbound/services/outside_network.c
index 92212be02f0d..63dfe4961183 100644
--- a/contrib/unbound/services/outside_network.c
+++ b/contrib/unbound/services/outside_network.c
@@ -364,6 +364,20 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl);
#endif
pend->c->ssl_shake_state = comm_ssl_shake_write;
+#ifdef HAVE_SSL_SET1_HOST
+ if(w->tls_auth_name) {
+ SSL_set_verify(pend->c->ssl, SSL_VERIFY_PEER, NULL);
+ /* setting the hostname makes openssl verify the
+ * host name in the x509 certificate in the
+ * SSL connection*/
+ if(!SSL_set1_host(pend->c->ssl, w->tls_auth_name)) {
+ log_err("SSL_set1_host failed");
+ pend->c->fd = s;
+ comm_point_close(pend->c);
+ return 0;
+ }
+ }
+#endif /* HAVE_SSL_SET1_HOST */
}
w->pkt = NULL;
w->next_waiting = (void*)pend;
@@ -851,6 +865,7 @@ serviced_node_del(rbnode_type* node, void* ATTR_UNUSED(arg))
struct service_callback* p = sq->cblist, *np;
free(sq->qbuf);
free(sq->zone);
+ free(sq->tls_auth_name);
edns_opt_list_free(sq->opt_list);
while(p) {
np = p->next;
@@ -1284,6 +1299,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
w->cb = callback;
w->cb_arg = callback_arg;
w->ssl_upstream = sq->ssl_upstream;
+ w->tls_auth_name = sq->tls_auth_name;
#ifndef S_SPLINT_S
tv.tv_sec = timeout;
tv.tv_usec = 0;
@@ -1357,8 +1373,8 @@ lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
static struct serviced_query*
serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
int want_dnssec, int nocaps, int tcp_upstream, int ssl_upstream,
- struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, int qtype, struct edns_option* opt_list)
+ char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen,
+ uint8_t* zone, size_t zonelen, int qtype, struct edns_option* opt_list)
{
struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq));
#ifdef UNBOUND_DEBUG
@@ -1386,12 +1402,24 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
sq->nocaps = nocaps;
sq->tcp_upstream = tcp_upstream;
sq->ssl_upstream = ssl_upstream;
+ if(tls_auth_name) {
+ sq->tls_auth_name = strdup(tls_auth_name);
+ if(!sq->tls_auth_name) {
+ free(sq->zone);
+ free(sq->qbuf);
+ free(sq);
+ return NULL;
+ }
+ } else {
+ sq->tls_auth_name = NULL;
+ }
memcpy(&sq->addr, addr, addrlen);
sq->addrlen = addrlen;
sq->opt_list = NULL;
if(opt_list) {
sq->opt_list = edns_opt_copy_alloc(opt_list);
if(!sq->opt_list) {
+ free(sq->tls_auth_name);
free(sq->zone);
free(sq->qbuf);
free(sq);
@@ -2055,7 +2083,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
struct serviced_query*
outnet_serviced_query(struct outside_network* outnet,
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
- int nocaps, int tcp_upstream, int ssl_upstream,
+ int nocaps, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, struct module_qstate* qstate,
comm_point_callback_type* callback, void* callback_arg, sldns_buffer* buff,
@@ -2078,8 +2106,9 @@ outnet_serviced_query(struct outside_network* outnet,
if(!sq) {
/* make new serviced query entry */
sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps,
- tcp_upstream, ssl_upstream, addr, addrlen, zone,
- zonelen, (int)qinfo->qtype, qstate->edns_opts_back_out);
+ tcp_upstream, ssl_upstream, tls_auth_name, addr,
+ addrlen, zone, zonelen, (int)qinfo->qtype,
+ qstate->edns_opts_back_out);
if(!sq) {
free(cb);
return NULL;
diff --git a/contrib/unbound/services/outside_network.h b/contrib/unbound/services/outside_network.h
index 09b2e6cedff6..105f7651363f 100644
--- a/contrib/unbound/services/outside_network.h
+++ b/contrib/unbound/services/outside_network.h
@@ -290,6 +290,8 @@ struct waiting_tcp {
void* cb_arg;
/** if it uses ssl upstream */
int ssl_upstream;
+ /** ref to the tls_auth_name from the serviced_query */
+ char* tls_auth_name;
};
/**
@@ -332,6 +334,9 @@ struct serviced_query {
int nocaps;
/** tcp upstream used, use tcp, or ssl_upstream for SSL */
int tcp_upstream, ssl_upstream;
+ /** the name of the tls authentication name, eg. 'ns.example.com'
+ * or NULL */
+ char* tls_auth_name;
/** where to send it */
struct sockaddr_storage addr;
/** length of addr field in use. */
@@ -484,6 +489,8 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
* @param nocaps: ignore use_caps_for_id and use unperturbed qname.
* @param tcp_upstream: use TCP for upstream queries.
* @param ssl_upstream: use SSL for upstream queries.
+ * @param tls_auth_name: when ssl_upstream is true, use this name to check
+ * the server's peer certificate.
* @param addr: to which server to send the query.
* @param addrlen: length of addr.
* @param zone: name of the zone of the delegation point. wireformat dname.
@@ -501,7 +508,7 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
*/
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
- int nocaps, int tcp_upstream, int ssl_upstream,
+ int nocaps, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, struct module_qstate* qstate,
comm_point_callback_type* callback, void* callback_arg,
diff --git a/contrib/unbound/sldns/keyraw.c b/contrib/unbound/sldns/keyraw.c
index e2f14f2a4e97..2ec225bc5bd8 100644
--- a/contrib/unbound/sldns/keyraw.c
+++ b/contrib/unbound/sldns/keyraw.c
@@ -90,6 +90,14 @@ sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
case LDNS_ECDSAP384SHA384:
return 384;
#endif
+#ifdef USE_ED25519
+ case LDNS_ED25519:
+ return 256;
+#endif
+#ifdef USE_ED448
+ case LDNS_ED448:
+ return 456;
+#endif
default:
return 0;
}
@@ -409,6 +417,27 @@ sldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
}
#endif /* USE_ED25519 */
+#ifdef USE_ED448
+EVP_PKEY*
+sldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
+{
+ /* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
+ uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
+ 0x71, 0x03, 0x3a, 0x00};
+ int pre_len = 12;
+ uint8_t buf[256];
+ EVP_PKEY *evp_key;
+ /* pp gets modified by d2i() */
+ const unsigned char* pp = (unsigned char*)buf;
+ if(keylen != 57 || keylen + pre_len > sizeof(buf))
+ return NULL; /* wrong length */
+ memmove(buf, pre, pre_len);
+ memmove(buf+pre_len, key, keylen);
+ evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
+ return evp_key;
+}
+#endif /* USE_ED448 */
+
int
sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
const EVP_MD* md)
diff --git a/contrib/unbound/sldns/keyraw.h b/contrib/unbound/sldns/keyraw.h
index 19653b46c7ba..989b02ce052e 100644
--- a/contrib/unbound/sldns/keyraw.h
+++ b/contrib/unbound/sldns/keyraw.h
@@ -102,6 +102,15 @@ RSA *sldns_key_buf2rsa_raw(unsigned char* key, size_t len);
EVP_PKEY* sldns_ed255192pkey_raw(const unsigned char* key, size_t len);
/**
+ * Converts a holding buffer with key material to EVP PKEY in openssl.
+ * Only available if ldns was compiled with ED448.
+ * \param[in] key the uncompressed wireformat of the key.
+ * \param[in] len length of key data
+ * \return the key or NULL on error.
+ */
+EVP_PKEY* sldns_ed4482pkey_raw(const unsigned char* key, size_t len);
+
+/**
* Utility function to calculate hash using generic EVP_MD pointer.
* \param[in] data the data to hash.
* \param[in] len length of data.
diff --git a/contrib/unbound/sldns/str2wire.c b/contrib/unbound/sldns/str2wire.c
index fdb355754028..1a51bb695607 100644
--- a/contrib/unbound/sldns/str2wire.c
+++ b/contrib/unbound/sldns/str2wire.c
@@ -1225,6 +1225,17 @@ int sldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len)
return LDNS_WIREPARSE_ERR_OK;
}
+/** see if the string ends, or ends in whitespace */
+static int
+sldns_is_last_of_string(const char* str)
+{
+ if(*str == 0) return 1;
+ while(isspace((unsigned char)*str))
+ str++;
+ if(*str == 0) return 1;
+ return 0;
+}
+
int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len)
{
const char* s = str;
@@ -1234,7 +1245,7 @@ int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len)
s++;
continue;
}
- if(dlen == 0 && *s == '0' && *(s+1) == 0) {
+ if(dlen == 0 && *s == '0' && sldns_is_last_of_string(s+1)) {
*len = 0;
return LDNS_WIREPARSE_ERR_OK;
}
diff --git a/contrib/unbound/smallapp/unbound-control.c b/contrib/unbound/smallapp/unbound-control.c
index 086afa8dddeb..2337e7a73728 100644
--- a/contrib/unbound/smallapp/unbound-control.c
+++ b/contrib/unbound/smallapp/unbound-control.c
@@ -142,6 +142,7 @@ usage(void)
printf(" ratelimit_list [+a] list ratelimited domains\n");
printf(" ip_ratelimit_list [+a] list ratelimited ip addresses\n");
printf(" +a list all, also not ratelimited\n");
+ printf(" list_auth_zones list auth zones\n");
printf(" view_list_local_zones view list local-zones in view\n");
printf(" view_list_local_data view list local-data RRs in view\n");
printf(" view_local_zone view name type add local-zone in view\n");
@@ -349,6 +350,8 @@ static void print_extended(struct ub_stats_info* s)
PR_UL("num.answer.secure", s->svr.ans_secure);
PR_UL("num.answer.bogus", s->svr.ans_bogus);
PR_UL("num.rrset.bogus", s->svr.rrset_bogus);
+ PR_UL("num.query.aggressive.NOERROR", s->svr.num_neg_cache_noerror);
+ PR_UL("num.query.aggressive.NXDOMAIN", s->svr.num_neg_cache_nxdomain);
/* threat detection */
PR_UL("unwanted.queries", s->svr.unwanted_queries);
PR_UL("unwanted.replies", s->svr.unwanted_replies);
@@ -366,6 +369,8 @@ static void print_extended(struct ub_stats_info* s)
PR_UL("num.query.dnscrypt.replay",
s->svr.num_query_dnscrypt_replay);
#endif /* USE_DNSCRYPT */
+ PR_UL("num.query.authzone.up", s->svr.num_query_authzone_up);
+ PR_UL("num.query.authzone.down", s->svr.num_query_authzone_down);
}
/** print statistics out of memory structures */
@@ -476,10 +481,15 @@ setup_ctx(struct config_file* cfg)
free(c_cert);
} else {
/* Use ciphers that don't require authentication */
+#if defined(SSL_OP_NO_TLSv1_3)
+ /* in openssl 1.1.1, negotiation code for tls 1.3 does
+ * not allow the unauthenticated aNULL and eNULL ciphers */
+ SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_3);
+#endif
#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
SSL_CTX_set_security_level(ctx, 0);
#endif
- if(!SSL_CTX_set_cipher_list(ctx, "aNULL, eNULL"))
+ if(!SSL_CTX_set_cipher_list(ctx, "aNULL:eNULL"))
ssl_err("Error setting NULL cipher!");
}
return ctx;
diff --git a/contrib/unbound/smallapp/worker_cb.c b/contrib/unbound/smallapp/worker_cb.c
index e88e8c8d754b..dda94cc670cf 100644
--- a/contrib/unbound/smallapp/worker_cb.c
+++ b/contrib/unbound/smallapp/worker_cb.c
@@ -105,7 +105,7 @@ struct outbound_entry* worker_send_query(
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream),
- struct module_qstate* ATTR_UNUSED(q))
+ char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q))
{
log_assert(0);
return 0;
@@ -137,7 +137,7 @@ struct outbound_entry* libworker_send_query(
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream),
- struct module_qstate* ATTR_UNUSED(q))
+ char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q))
{
log_assert(0);
return 0;
diff --git a/contrib/unbound/util/config_file.c b/contrib/unbound/util/config_file.c
index 465fa35dbb28..9fd6d60a6318 100644
--- a/contrib/unbound/util/config_file.c
+++ b/contrib/unbound/util/config_file.c
@@ -106,7 +106,7 @@ config_create(void)
cfg->outgoing_tcp_mss = 0;
cfg->ssl_service_key = NULL;
cfg->ssl_service_pem = NULL;
- cfg->ssl_port = 853;
+ cfg->ssl_port = UNBOUND_DNS_OVER_TLS_PORT;
cfg->ssl_upstream = 0;
cfg->tls_cert_bundle = NULL;
cfg->use_syslog = 1;
@@ -161,6 +161,8 @@ config_create(void)
if(!(cfg->logfile = strdup(""))) goto error_exit;
if(!(cfg->pidfile = strdup(PIDFILE))) goto error_exit;
if(!(cfg->target_fetch_policy = strdup("3 2 1 0 0"))) goto error_exit;
+ cfg->low_rtt_pct = 0;
+ cfg->low_rtt = 45;
cfg->donotqueryaddrs = NULL;
cfg->donotquery_localhost = 1;
cfg->root_hints = NULL;
@@ -211,6 +213,7 @@ config_create(void)
cfg->trust_anchor_list = NULL;
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;
@@ -386,6 +389,12 @@ struct config_file* config_create_forlib(void)
int config_set_option(struct config_file* cfg, const char* opt,
const char* val)
{
+ char buf[64];
+ if(!opt) return 0;
+ if(opt[strlen(opt)-1] != ':' && strlen(opt)+2<sizeof(buf)) {
+ snprintf(buf, sizeof(buf), "%s:", opt);
+ opt = buf;
+ }
S_NUMBER_OR_ZERO("verbosity:", verbosity)
else if(strcmp(opt, "statistics-interval:") == 0) {
if(strcmp(val, "0") == 0 || strcmp(val, "") == 0)
@@ -446,6 +455,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("ssl-service-pem:", ssl_service_pem)
else S_NUMBER_NONZERO("ssl-port:", ssl_port)
else S_STR("tls-cert-bundle:", tls_cert_bundle)
+ else S_STRLIST("additional-tls-port:", additional_tls_port)
else S_YNO("interface-automatic:", if_automatic)
else S_YNO("use-systemd:", use_systemd)
else S_YNO("do-daemonize:", do_daemonize)
@@ -500,7 +510,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("harden-below-nxdomain:", harden_below_nxdomain)
else S_YNO("harden-referral-path:", harden_referral_path)
else S_YNO("harden-algo-downgrade:", harden_algo_downgrade)
- else S_YNO("use-caps-for-id", use_caps_bits_for_id)
+ else S_YNO("use-caps-for-id:", use_caps_bits_for_id)
else S_STRLIST("caps-whitelist:", caps_whitelist)
else S_SIZET_OR_ZERO("unwanted-reply-threshold:", unwanted_threshold)
else S_STRLIST("private-address:", private_address)
@@ -512,6 +522,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STRLIST("trust-anchor:", trust_anchor_list)
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)
@@ -606,6 +617,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_POW2("ratelimit-slabs:", ratelimit_slabs)
else S_NUMBER_OR_ZERO("ip-ratelimit-factor:", ip_ratelimit_factor)
else S_NUMBER_OR_ZERO("ratelimit-factor:", ratelimit_factor)
+ else S_NUMBER_OR_ZERO("low-rtt:", low_rtt)
+ else S_NUMBER_OR_ZERO("low-rtt-pct:", low_rtt_pct)
else S_YNO("qname-minimisation:", qname_minimisation)
else S_YNO("qname-minimisation-strict:", qname_minimisation_strict)
#ifdef USE_IPSECMOD
@@ -800,8 +813,13 @@ int
config_get_option(struct config_file* cfg, const char* opt,
void (*func)(char*,void*), void* arg)
{
- char buf[1024];
+ char buf[1024], nopt[64];
size_t len = sizeof(buf);
+ if(opt && opt[strlen(opt)-1] == ':' && strlen(opt)<sizeof(nopt)) {
+ memmove(nopt, opt, strlen(opt));
+ nopt[strlen(opt)-1] = 0;
+ opt = nopt;
+ }
fptr_ok(fptr_whitelist_print_func(func));
O_DEC(opt, "verbosity", verbosity)
else O_DEC(opt, "statistics-interval", stat_interval)
@@ -856,6 +874,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_STR(opt, "ssl-service-pem", ssl_service_pem)
else O_DEC(opt, "ssl-port", ssl_port)
else O_STR(opt, "tls-cert-bundle", tls_cert_bundle)
+ else O_LST(opt, "additional-tls-port", additional_tls_port)
else O_YNO(opt, "use-systemd", use_systemd)
else O_YNO(opt, "do-daemonize", do_daemonize)
else O_STR(opt, "chroot", chrootdir)
@@ -888,7 +907,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "val-clean-additional", val_clean_additional)
else O_DEC(opt, "val-log-level", val_log_level)
else O_YNO(opt, "val-permissive-mode", val_permissive_mode)
- else O_YNO(opt, "aggressive-nsec:", aggressive_nsec)
+ else O_YNO(opt, "aggressive-nsec", aggressive_nsec)
else O_YNO(opt, "ignore-cd-flag", ignore_cd)
else O_YNO(opt, "serve-expired", serve_expired)
else O_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations)
@@ -915,6 +934,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_LST(opt, "trust-anchor", trust_anchor_list)
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)
else O_LST(opt, "domain-insecure", domain_insecure)
@@ -980,6 +1000,8 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_LS2(opt, "ratelimit-below-domain", ratelimit_below_domain)
else O_DEC(opt, "ip-ratelimit-factor", ip_ratelimit_factor)
else O_DEC(opt, "ratelimit-factor", ratelimit_factor)
+ else O_DEC(opt, "low-rtt", low_rtt)
+ else O_DEC(opt, "low-rtt-pct", low_rtt_pct)
else O_DEC(opt, "val-sig-skew-min", val_sig_skew_min)
else O_DEC(opt, "val-sig-skew-max", val_sig_skew_max)
else O_YNO(opt, "qname-minimisation", qname_minimisation)
@@ -1178,6 +1200,7 @@ config_delauth(struct config_auth* p)
free(p->name);
config_delstrlist(p->masters);
config_delstrlist(p->urls);
+ config_delstrlist(p->allow_notify);
free(p->zonefile);
free(p);
}
@@ -1274,6 +1297,7 @@ config_delete(struct config_file* cfg)
free(cfg->ssl_service_key);
free(cfg->ssl_service_pem);
free(cfg->tls_cert_bundle);
+ config_delstrlist(cfg->additional_tls_port);
free(cfg->log_identity);
config_del_strarray(cfg->ifs, cfg->num_ifs);
config_del_strarray(cfg->out_ifs, cfg->num_out_ifs);
diff --git a/contrib/unbound/util/config_file.h b/contrib/unbound/util/config_file.h
index 2e1c53ee0733..eba60b9a1356 100644
--- a/contrib/unbound/util/config_file.h
+++ b/contrib/unbound/util/config_file.h
@@ -102,6 +102,8 @@ struct config_file {
int ssl_upstream;
/** cert bundle for outgoing connections */
char* tls_cert_bundle;
+ /** additional tls ports */
+ struct config_strlist* additional_tls_port;
/** outgoing port range number of ports (per thread) */
int outgoing_num_ports;
@@ -141,6 +143,10 @@ struct config_file {
/** the target fetch policy for the iterator */
char* target_fetch_policy;
+ /** percent*10, how many times in 1000 to pick low rtt destinations */
+ int low_rtt_pct;
+ /** what time in msec is a low rtt destination */
+ int low_rtt;
/** automatic interface for incoming messages. Uses ipv6 remapping,
* and recvmsg/sendmsg ancillary data to detect interfaces, boolean */
@@ -285,6 +291,8 @@ struct config_file {
struct config_strlist* domain_insecure;
/** send key tag query */
int trust_anchor_signaling;
+ /** enable root key sentinel */
+ int root_key_sentinel;
/** if not 0, this value is the validation date for RRSIGs */
int32_t val_date_override;
@@ -507,6 +515,14 @@ struct config_file {
char* cachedb_backend;
/** secret seed for hash key calculation */
char* cachedb_secret;
+#ifdef USE_REDIS
+ /** redis server's IP address or host name */
+ char* redis_server_host;
+ /** redis server's TCP port */
+ int redis_server_port;
+ /** timeout (in ms) for communication with the redis server */
+ int redis_timeout;
+#endif
#endif
};
@@ -549,6 +565,8 @@ struct config_auth {
struct config_strlist* masters;
/** list of urls */
struct config_strlist* urls;
+ /** list of allow-notify */
+ struct config_strlist* allow_notify;
/** zonefile (or NULL) */
char* zonefile;
/** provide downstream answers */
diff --git a/contrib/unbound/util/configlexer.lex b/contrib/unbound/util/configlexer.lex
index d7f46aafe7b2..cbf9fffc7f80 100644
--- a/contrib/unbound/util/configlexer.lex
+++ b/contrib/unbound/util/configlexer.lex
@@ -239,6 +239,8 @@ ssl-port{COLON} { YDVAR(1, VAR_SSL_PORT) }
tls-port{COLON} { YDVAR(1, VAR_SSL_PORT) }
ssl-cert-bundle{COLON} { YDVAR(1, VAR_TLS_CERT_BUNDLE) }
tls-cert-bundle{COLON} { YDVAR(1, VAR_TLS_CERT_BUNDLE) }
+additional-ssl-port{COLON} { YDVAR(1, VAR_ADDITIONAL_TLS_PORT) }
+additional-tls-port{COLON} { YDVAR(1, VAR_ADDITIONAL_TLS_PORT) }
use-systemd{COLON} { YDVAR(1, VAR_USE_SYSTEMD) }
do-daemonize{COLON} { YDVAR(1, VAR_DO_DAEMONIZE) }
interface{COLON} { YDVAR(1, VAR_INTERFACE) }
@@ -307,6 +309,7 @@ auth-zone{COLON} { YDVAR(0, VAR_AUTH_ZONE) }
zonefile{COLON} { YDVAR(1, VAR_ZONEFILE) }
master{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) }
for-upstream{COLON} { YDVAR(1, VAR_FOR_UPSTREAM) }
fallback-enabled{COLON} { YDVAR(1, VAR_FALLBACK_ENABLED) }
@@ -334,6 +337,7 @@ auto-trust-anchor-file{COLON} { YDVAR(1, VAR_AUTO_TRUST_ANCHOR_FILE) }
trusted-keys-file{COLON} { YDVAR(1, VAR_TRUSTED_KEYS_FILE) }
trust-anchor{COLON} { YDVAR(1, VAR_TRUST_ANCHOR) }
trust-anchor-signaling{COLON} { YDVAR(1, VAR_TRUST_ANCHOR_SIGNALING) }
+root-key-sentinel{COLON} { YDVAR(1, VAR_ROOT_KEY_SENTINEL) }
val-override-date{COLON} { YDVAR(1, VAR_VAL_OVERRIDE_DATE) }
val-sig-skew-min{COLON} { YDVAR(1, VAR_VAL_SIG_SKEW_MIN) }
val-sig-skew-max{COLON} { YDVAR(1, VAR_VAL_SIG_SKEW_MAX) }
@@ -424,6 +428,8 @@ ratelimit-for-domain{COLON} { YDVAR(2, VAR_RATELIMIT_FOR_DOMAIN) }
ratelimit-below-domain{COLON} { YDVAR(2, VAR_RATELIMIT_BELOW_DOMAIN) }
ip-ratelimit-factor{COLON} { YDVAR(1, VAR_IP_RATELIMIT_FACTOR) }
ratelimit-factor{COLON} { YDVAR(1, VAR_RATELIMIT_FACTOR) }
+low-rtt{COLON} { YDVAR(1, VAR_LOW_RTT) }
+low-rtt-pct{COLON} { YDVAR(1, VAR_LOW_RTT_PCT) }
response-ip-tag{COLON} { YDVAR(2, VAR_RESPONSE_IP_TAG) }
response-ip{COLON} { YDVAR(2, VAR_RESPONSE_IP) }
response-ip-data{COLON} { YDVAR(2, VAR_RESPONSE_IP_DATA) }
@@ -449,6 +455,9 @@ ipsecmod-strict{COLON} { YDVAR(1, VAR_IPSECMOD_STRICT) }
cachedb{COLON} { YDVAR(0, VAR_CACHEDB) }
backend{COLON} { YDVAR(1, VAR_CACHEDB_BACKEND) }
secret-seed{COLON} { YDVAR(1, VAR_CACHEDB_SECRETSEED) }
+redis-server-host{COLON} { YDVAR(1, VAR_CACHEDB_REDISHOST) }
+redis-server-port{COLON} { YDVAR(1, VAR_CACHEDB_REDISPORT) }
+redis-timeout{COLON} { YDVAR(1, VAR_CACHEDB_REDISTIMEOUT) }
udp-upstream-without-downstream{COLON} { YDVAR(1, VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM) }
<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
diff --git a/contrib/unbound/util/configparser.y b/contrib/unbound/util/configparser.y
index 7e23fca16823..a71bf914c762 100644
--- a/contrib/unbound/util/configparser.y
+++ b/contrib/unbound/util/configparser.y
@@ -142,6 +142,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_FAKE_DSA VAR_FAKE_SHA1
%token VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR VAR_TRUST_ANCHOR_SIGNALING
%token VAR_AGGRESSIVE_NSEC VAR_USE_SYSTEMD VAR_SHM_ENABLE VAR_SHM_KEY
+%token VAR_ROOT_KEY_SENTINEL
%token VAR_DNSCRYPT VAR_DNSCRYPT_ENABLE VAR_DNSCRYPT_PORT VAR_DNSCRYPT_PROVIDER
%token VAR_DNSCRYPT_SECRET_KEY VAR_DNSCRYPT_PROVIDER_CERT
%token VAR_DNSCRYPT_PROVIDER_CERT_ROTATED
@@ -152,9 +153,11 @@ extern struct config_parser_state* cfg_parser;
%token VAR_IPSECMOD_ENABLED VAR_IPSECMOD_HOOK VAR_IPSECMOD_IGNORE_BOGUS
%token VAR_IPSECMOD_MAX_TTL VAR_IPSECMOD_WHITELIST VAR_IPSECMOD_STRICT
%token VAR_CACHEDB VAR_CACHEDB_BACKEND VAR_CACHEDB_SECRETSEED
+%token VAR_CACHEDB_REDISHOST VAR_CACHEDB_REDISPORT VAR_CACHEDB_REDISTIMEOUT
%token VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM VAR_FOR_UPSTREAM
%token VAR_AUTH_ZONE VAR_ZONEFILE VAR_MASTER VAR_URL VAR_FOR_DOWNSTREAM
-%token VAR_FALLBACK_ENABLED
+%token VAR_FALLBACK_ENABLED VAR_ADDITIONAL_TLS_PORT VAR_LOW_RTT VAR_LOW_RTT_PCT
+%token VAR_ALLOW_NOTIFY
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -240,11 +243,13 @@ content_server: server_num_threads | server_verbosity | server_port |
server_response_ip_tag | server_response_ip | server_response_ip_data |
server_shm_enable | server_shm_key | server_fake_sha1 |
server_hide_trustanchor | server_trust_anchor_signaling |
+ server_root_key_sentinel |
server_ipsecmod_enabled | server_ipsecmod_hook |
server_ipsecmod_ignore_bogus | server_ipsecmod_max_ttl |
server_ipsecmod_whitelist | server_ipsecmod_strict |
server_udp_upstream_without_downstream | server_aggressive_nsec |
- server_tls_cert_bundle
+ server_tls_cert_bundle | server_additional_tls_port | server_low_rtt |
+ server_low_rtt_pct
;
stubstart: VAR_STUB_ZONE
{
@@ -318,7 +323,8 @@ authstart: VAR_AUTH_ZONE
contents_auth: contents_auth content_auth
| ;
content_auth: auth_name | auth_zonefile | auth_master | auth_url |
- auth_for_downstream | auth_for_upstream | auth_fallback_enabled
+ auth_for_downstream | auth_for_upstream | auth_fallback_enabled |
+ auth_allow_notify
;
server_num_threads: VAR_NUM_THREADS STRING_ARG
{
@@ -682,6 +688,14 @@ server_tls_cert_bundle: VAR_TLS_CERT_BUNDLE STRING_ARG
cfg_parser->cfg->tls_cert_bundle = $2;
}
;
+server_additional_tls_port: VAR_ADDITIONAL_TLS_PORT STRING_ARG
+ {
+ OUTYY(("P(server_additional_tls_port:%s)\n", $2));
+ if(!cfg_strlist_insert(&cfg_parser->cfg->additional_tls_port,
+ $2))
+ yyerror("out of memory");
+ }
+ ;
server_use_systemd: VAR_USE_SYSTEMD STRING_ARG
{
OUTYY(("P(server_use_systemd:%s)\n", $2));
@@ -859,6 +873,17 @@ server_trust_anchor_signaling: VAR_TRUST_ANCHOR_SIGNALING STRING_ARG
free($2);
}
;
+server_root_key_sentinel: VAR_ROOT_KEY_SENTINEL STRING_ARG
+ {
+ OUTYY(("P(server_root_key_sentinel:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else
+ cfg_parser->cfg->root_key_sentinel =
+ (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
server_domain_insecure: VAR_DOMAIN_INSECURE STRING_ARG
{
OUTYY(("P(server_domain_insecure:%s)\n", $2));
@@ -1851,6 +1876,24 @@ server_ratelimit_factor: VAR_RATELIMIT_FACTOR STRING_ARG
free($2);
}
;
+server_low_rtt: VAR_LOW_RTT STRING_ARG
+ {
+ OUTYY(("P(server_low_rtt:%s)\n", $2));
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
+ yyerror("number expected");
+ else cfg_parser->cfg->low_rtt = atoi($2);
+ free($2);
+ }
+ ;
+server_low_rtt_pct: VAR_LOW_RTT_PCT STRING_ARG
+ {
+ OUTYY(("P(server_low_rtt_pct:%s)\n", $2));
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
+ yyerror("number expected");
+ else cfg_parser->cfg->low_rtt_pct = atoi($2);
+ free($2);
+ }
+ ;
server_qname_minimisation: VAR_QNAME_MINIMISATION STRING_ARG
{
OUTYY(("P(server_qname_minimisation:%s)\n", $2));
@@ -2072,6 +2115,14 @@ auth_url: VAR_URL STRING_ARG
yyerror("out of memory");
}
;
+auth_allow_notify: VAR_ALLOW_NOTIFY STRING_ARG
+ {
+ OUTYY(("P(allow-notify:%s)\n", $2));
+ if(!cfg_strlist_insert(&cfg_parser->cfg->auths->allow_notify,
+ $2))
+ yyerror("out of memory");
+ }
+ ;
auth_for_downstream: VAR_FOR_DOWNSTREAM STRING_ARG
{
OUTYY(("P(for-downstream:%s)\n", $2));
@@ -2551,7 +2602,8 @@ cachedbstart: VAR_CACHEDB
;
contents_cachedb: contents_cachedb content_cachedb
| ;
-content_cachedb: cachedb_backend_name | cachedb_secret_seed
+content_cachedb: cachedb_backend_name | cachedb_secret_seed |
+ redis_server_host | redis_server_port | redis_timeout
;
cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
{
@@ -2582,6 +2634,46 @@ cachedb_secret_seed: VAR_CACHEDB_SECRETSEED STRING_ARG
#endif
}
;
+redis_server_host: VAR_CACHEDB_REDISHOST STRING_ARG
+ {
+ #if defined(USE_CACHEDB) && defined(USE_REDIS)
+ OUTYY(("P(redis_server_host:%s)\n", $2));
+ free(cfg_parser->cfg->redis_server_host);
+ cfg_parser->cfg->redis_server_host = $2;
+ #else
+ OUTYY(("P(Compiled without cachedb or redis, ignoring)\n"));
+ free($2);
+ #endif
+ }
+ ;
+redis_server_port: VAR_CACHEDB_REDISPORT STRING_ARG
+ {
+ #if defined(USE_CACHEDB) && defined(USE_REDIS)
+ int port;
+ OUTYY(("P(redis_server_port:%s)\n", $2));
+ port = atoi($2);
+ if(port == 0 || port < 0 || port > 65535)
+ yyerror("valid redis server port number expected");
+ else cfg_parser->cfg->redis_server_port = port;
+ #else
+ OUTYY(("P(Compiled without cachedb or redis, ignoring)\n"));
+ #endif
+ free($2);
+ }
+ ;
+redis_timeout: VAR_CACHEDB_REDISTIMEOUT STRING_ARG
+ {
+ #if defined(USE_CACHEDB) && defined(USE_REDIS)
+ OUTYY(("P(redis_timeout:%s)\n", $2));
+ if(atoi($2) == 0)
+ yyerror("redis timeout value expected");
+ else cfg_parser->cfg->redis_timeout = atoi($2);
+ #else
+ OUTYY(("P(Compiled without cachedb or redis, ignoring)\n"));
+ #endif
+ free($2);
+ }
+ ;
%%
/* parse helper routines could be here */
diff --git a/contrib/unbound/util/data/dname.c b/contrib/unbound/util/data/dname.c
index 517af2843e2c..c7360f75f32a 100644
--- a/contrib/unbound/util/data/dname.c
+++ b/contrib/unbound/util/data/dname.c
@@ -523,6 +523,29 @@ dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs)
return lastdiff;
}
+int
+dname_lab_startswith(uint8_t* label, char* prefix, char** endptr)
+{
+ size_t plen = strlen(prefix);
+ size_t orig_plen = plen;
+ size_t lablen = (size_t)*label;
+ if(plen > lablen)
+ return 0;
+ label++;
+ while(plen--) {
+ if(*prefix != tolower((unsigned char)*label)) {
+ return 0;
+ }
+ prefix++; label++;
+ }
+ if(orig_plen < lablen)
+ *endptr = (char *)label;
+ else
+ /* prefix length == label length */
+ *endptr = NULL;
+ return 1;
+}
+
int
dname_buffer_write(sldns_buffer* pkt, uint8_t* dname)
{
diff --git a/contrib/unbound/util/data/dname.h b/contrib/unbound/util/data/dname.h
index 53b341bf7ef7..53a33c689bc0 100644
--- a/contrib/unbound/util/data/dname.h
+++ b/contrib/unbound/util/data/dname.h
@@ -186,6 +186,17 @@ int dname_count_size_labels(uint8_t* dname, size_t* size);
int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs);
/**
+ * Check if labels starts with given prefix
+ * @param label: dname label
+ * @param prefix: the string to match label with, null terminated.
+ * @param endptr: pointer to location in label after prefix, only if return
+ * value is 1. NULL if nothing in the label after the prefix, i.e. prefix
+ * and label are the same.
+ * @return: 1 if label starts with prefix, else 0
+ */
+int dname_lab_startswith(uint8_t* label, char* prefix, char** endptr);
+
+/**
* See if domain name d1 is a strict subdomain of d2.
* That is a subdomain, but not equal.
* @param d1: domain name, uncompressed wireformat
diff --git a/contrib/unbound/util/data/msgparse.c b/contrib/unbound/util/data/msgparse.c
index 288720068b10..13cad8a26630 100644
--- a/contrib/unbound/util/data/msgparse.c
+++ b/contrib/unbound/util/data/msgparse.c
@@ -1028,6 +1028,32 @@ parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
return 0;
}
+/** skip RR in packet */
+static int
+skip_pkt_rr(sldns_buffer* pkt)
+{
+ if(sldns_buffer_remaining(pkt) < 1) return 0;
+ if(!pkt_dname_len(pkt))
+ return 0;
+ if(sldns_buffer_remaining(pkt) < 4) return 0;
+ sldns_buffer_skip(pkt, 4); /* type and class */
+ if(!skip_ttl_rdata(pkt))
+ return 0;
+ return 1;
+}
+
+/** skip RRs from packet */
+static int
+skip_pkt_rrs(sldns_buffer* pkt, int num)
+{
+ int i;
+ for(i=0; i<num; i++) {
+ if(!skip_pkt_rr(pkt))
+ return 0;
+ }
+ return 1;
+}
+
int
parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
struct regional* region)
@@ -1035,8 +1061,12 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
size_t rdata_len;
uint8_t* rdata_ptr;
log_assert(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) == 1);
- log_assert(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0);
- log_assert(LDNS_NSCOUNT(sldns_buffer_begin(pkt)) == 0);
+ if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 0 ||
+ LDNS_NSCOUNT(sldns_buffer_begin(pkt)) != 0) {
+ if(!skip_pkt_rrs(pkt, ((int)LDNS_ANCOUNT(sldns_buffer_begin(pkt)))+
+ ((int)LDNS_NSCOUNT(sldns_buffer_begin(pkt)))))
+ return 0;
+ }
/* check edns section is present */
if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) > 1) {
return LDNS_RCODE_FORMERR;
diff --git a/contrib/unbound/util/data/msgreply.c b/contrib/unbound/util/data/msgreply.c
index e25b42cc257a..772f5d1f1029 100644
--- a/contrib/unbound/util/data/msgreply.c
+++ b/contrib/unbound/util/data/msgreply.c
@@ -534,8 +534,9 @@ query_info_parse(struct query_info* m, sldns_buffer* query)
/* minimum size: header + \0 + qtype + qclass */
if(sldns_buffer_limit(query) < LDNS_HEADER_SIZE + 5)
return 0;
- if(LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY ||
- LDNS_QDCOUNT(q) != 1 || sldns_buffer_position(query) != 0)
+ if((LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY && LDNS_OPCODE_WIRE(q) !=
+ LDNS_PACKET_NOTIFY) || LDNS_QDCOUNT(q) != 1 ||
+ sldns_buffer_position(query) != 0)
return 0;
sldns_buffer_skip(query, LDNS_HEADER_SIZE);
m->qname = sldns_buffer_current(query);
diff --git a/contrib/unbound/util/data/packed_rrset.c b/contrib/unbound/util/data/packed_rrset.c
index 9944087cbf51..7b9d5494d960 100644
--- a/contrib/unbound/util/data/packed_rrset.c
+++ b/contrib/unbound/util/data/packed_rrset.c
@@ -253,6 +253,7 @@ sec_status_to_string(enum sec_status s)
case sec_status_bogus: return "sec_status_bogus";
case sec_status_indeterminate: return "sec_status_indeterminate";
case sec_status_insecure: return "sec_status_insecure";
+ case sec_status_secure_sentinel_fail: return "sec_status_secure_sentinel_fail";
case sec_status_secure: return "sec_status_secure";
}
return "unknown_sec_status_value";
diff --git a/contrib/unbound/util/data/packed_rrset.h b/contrib/unbound/util/data/packed_rrset.h
index 28f603d6f98f..3a5335ddfa59 100644
--- a/contrib/unbound/util/data/packed_rrset.h
+++ b/contrib/unbound/util/data/packed_rrset.h
@@ -187,6 +187,10 @@ enum sec_status {
* insecure. Generally this means that this RRset is below a trust
* anchor, but also below a verified, insecure delegation. */
sec_status_insecure,
+ /** SECURE_SENTINEL_FAIL means that the object (RRset or message)
+ * validated according to local policy but did not succeed in the root
+ * KSK sentinel test (draft-ietf-dnsop-kskroll-sentinel). */
+ sec_status_secure_sentinel_fail,
/** SECURE means that the object (RRset or message) validated
* according to local policy. */
sec_status_secure
diff --git a/contrib/unbound/util/fptr_wlist.c b/contrib/unbound/util/fptr_wlist.c
index 400a15de2ebb..302b6f7843ea 100644
--- a/contrib/unbound/util/fptr_wlist.c
+++ b/contrib/unbound/util/fptr_wlist.c
@@ -311,7 +311,8 @@ int
fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, int ssl_upstream, struct module_qstate* q))
+ uint8_t* zone, size_t zonelen, int ssl_upstream, char* tls_auth_name,
+ struct module_qstate* q))
{
if(fptr == &worker_send_query) return 1;
else if(fptr == &libworker_send_query) return 1;
diff --git a/contrib/unbound/util/fptr_wlist.h b/contrib/unbound/util/fptr_wlist.h
index 39e3f2d7f21b..03c2b92b45aa 100644
--- a/contrib/unbound/util/fptr_wlist.h
+++ b/contrib/unbound/util/fptr_wlist.h
@@ -212,7 +212,8 @@ int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_type fptr);
int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, int ssl_upstream, struct module_qstate* q));
+ uint8_t* zone, size_t zonelen, int ssl_upstream, char* tls_auth_name,
+ struct module_qstate* q));
/**
* Check function pointer whitelist for module_env detach_subs callback values.
diff --git a/contrib/unbound/util/iana_ports.inc b/contrib/unbound/util/iana_ports.inc
index e44a796dc4ad..b35cf7d29b0c 100644
--- a/contrib/unbound/util/iana_ports.inc
+++ b/contrib/unbound/util/iana_ports.inc
@@ -4890,6 +4890,7 @@
9006,
9007,
9009,
+9011,
9020,
9021,
9022,
diff --git a/contrib/unbound/util/module.h b/contrib/unbound/util/module.h
index 73db994bd7a3..c6e5164de6d6 100644
--- a/contrib/unbound/util/module.h
+++ b/contrib/unbound/util/module.h
@@ -338,6 +338,8 @@ struct module_env {
* @param zone: delegation point name.
* @param zonelen: length of zone name.
* @param ssl_upstream: use SSL for upstream queries.
+ * @param tls_auth_name: if ssl_upstream, use this name with TLS
+ * authentication.
* @param q: wich query state to reactivate upon return.
* @return: false on failure (memory or socket related). no query was
* sent. Or returns an outbound entry with qsent and qstate set.
@@ -348,7 +350,7 @@ struct module_env {
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, int ssl_upstream,
- struct module_qstate* q);
+ char* tls_auth_name, struct module_qstate* q);
/**
* Detach-subqueries.
diff --git a/contrib/unbound/util/net_help.c b/contrib/unbound/util/net_help.c
index fdc8b0558af0..40bfefb6426a 100644
--- a/contrib/unbound/util/net_help.c
+++ b/contrib/unbound/util/net_help.c
@@ -241,7 +241,8 @@ ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
socklen_t* addrlen, int* net)
{
- char* s = NULL;
+ char buf[64];
+ char* s;
*net = (str_is_ip6(str)?128:32);
if((s=strchr(str, '/'))) {
if(atoi(s+1) > *net) {
@@ -253,24 +254,65 @@ int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
log_err("cannot parse netblock: '%s'", str);
return 0;
}
- if(!(s = strdup(str))) {
- log_err("out of memory");
- return 0;
- }
- *strchr(s, '/') = '\0';
+ strlcpy(buf, str, sizeof(buf));
+ s = strchr(buf, '/');
+ if(s) *s = 0;
+ s = buf;
}
if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) {
- free(s);
log_err("cannot parse ip address: '%s'", str);
return 0;
}
if(s) {
- free(s);
addr_mask(addr, *addrlen, *net);
}
return 1;
}
+int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
+ socklen_t* addrlen, char** auth_name)
+{
+ char* s;
+ int port = UNBOUND_DNS_PORT;
+ if((s=strchr(str, '@'))) {
+ char buf[MAX_ADDR_STRLEN];
+ size_t len = (size_t)(s-str);
+ char* hash = strchr(s+1, '#');
+ if(hash) {
+ *auth_name = hash+1;
+ } else {
+ *auth_name = NULL;
+ }
+ if(len >= MAX_ADDR_STRLEN) {
+ return 0;
+ }
+ (void)strlcpy(buf, str, sizeof(buf));
+ buf[len] = 0;
+ port = atoi(s+1);
+ if(port == 0) {
+ if(!hash && strcmp(s+1,"0")!=0)
+ return 0;
+ if(hash && strncmp(s+1,"0#",2)!=0)
+ return 0;
+ }
+ return ipstrtoaddr(buf, port, addr, addrlen);
+ }
+ if((s=strchr(str, '#'))) {
+ char buf[MAX_ADDR_STRLEN];
+ size_t len = (size_t)(s-str);
+ if(len >= MAX_ADDR_STRLEN) {
+ return 0;
+ }
+ (void)strlcpy(buf, str, sizeof(buf));
+ buf[len] = 0;
+ port = UNBOUND_DNS_OVER_TLS_PORT;
+ *auth_name = s+1;
+ return ipstrtoaddr(buf, port, addr, addrlen);
+ }
+ *auth_name = NULL;
+ return ipstrtoaddr(str, port, addr, addrlen);
+}
+
/** store port number into sockaddr structure */
void
sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port)
diff --git a/contrib/unbound/util/net_help.h b/contrib/unbound/util/net_help.h
index 2d6fce91db6e..5e0d3a62936e 100644
--- a/contrib/unbound/util/net_help.h
+++ b/contrib/unbound/util/net_help.h
@@ -190,7 +190,7 @@ int ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
/**
* Convert ip netblock (ip/netsize) string and port to sockaddr.
- * *SLOW*, does a malloc internally to avoid writing over 'ip' string.
+ * performs a copy internally to avoid writing over 'ip' string.
* @param ip: ip4 or ip6 address string.
* @param port: port number, host format.
* @param addr: where to store sockaddr.
@@ -202,6 +202,20 @@ int netblockstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
socklen_t* addrlen, int* net);
/**
+ * Convert address string, with "@port" appendix, to sockaddr.
+ * It can also have an "#tls-auth-name" appendix (after the port).
+ * The returned tls-auth-name string is a pointer into the input string.
+ * Uses DNS port by default.
+ * @param str: the string
+ * @param addr: where to store sockaddr.
+ * @param addrlen: length of stored sockaddr is returned.
+ * @param auth_name: returned pointer to tls_auth_name, or NULL if none.
+ * @return 0 on error.
+ */
+int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
+ socklen_t* addrlen, char** auth_name);
+
+/**
* Store port number into sockaddr structure
* @param addr: sockaddr structure, ip4 or ip6.
* @param addrlen: length of addr.
diff --git a/contrib/unbound/util/netevent.c b/contrib/unbound/util/netevent.c
index fc6f6a9ea8b5..f0d72e038441 100644
--- a/contrib/unbound/util/netevent.c
+++ b/contrib/unbound/util/netevent.c
@@ -46,6 +46,7 @@
#include "util/fptr_wlist.h"
#include "sldns/pkthdr.h"
#include "sldns/sbuffer.h"
+#include "sldns/str2wire.h"
#include "dnstap/dnstap.h"
#include "dnscrypt/dnscrypt.h"
#ifdef HAVE_OPENSSL_SSL_H
@@ -1209,9 +1210,24 @@ ssl_handle_write(struct comm_point* c)
if(c->tcp_byte_count < sizeof(uint16_t)) {
uint16_t len = htons(sldns_buffer_limit(c->buffer));
ERR_clear_error();
- r = SSL_write(c->ssl,
- (void*)(((uint8_t*)&len)+c->tcp_byte_count),
- (int)(sizeof(uint16_t)-c->tcp_byte_count));
+ if(sizeof(uint16_t)+sldns_buffer_remaining(c->buffer) <
+ LDNS_RR_BUF_SIZE) {
+ /* combine the tcp length and the query for write,
+ * this emulates writev */
+ uint8_t buf[LDNS_RR_BUF_SIZE];
+ memmove(buf, &len, sizeof(uint16_t));
+ memmove(buf+sizeof(uint16_t),
+ sldns_buffer_current(c->buffer),
+ sldns_buffer_remaining(c->buffer));
+ r = SSL_write(c->ssl, (void*)(buf+c->tcp_byte_count),
+ (int)(sizeof(uint16_t)+
+ sldns_buffer_remaining(c->buffer)
+ - c->tcp_byte_count));
+ } else {
+ r = SSL_write(c->ssl,
+ (void*)(((uint8_t*)&len)+c->tcp_byte_count),
+ (int)(sizeof(uint16_t)-c->tcp_byte_count));
+ }
if(r <= 0) {
int want = SSL_get_error(c->ssl, r);
if(want == SSL_ERROR_ZERO_RETURN) {
diff --git a/contrib/unbound/util/tube.c b/contrib/unbound/util/tube.c
index f42d22cb3f20..dc6e3c2e7f78 100644
--- a/contrib/unbound/util/tube.c
+++ b/contrib/unbound/util/tube.c
@@ -454,8 +454,9 @@ int tube_setup_bg_write(struct tube* tube, struct comm_base* base)
int tube_queue_item(struct tube* tube, uint8_t* msg, size_t len)
{
- struct tube_res_list* item =
- (struct tube_res_list*)malloc(sizeof(*item));
+ struct tube_res_list* item;
+ if(!tube || !tube->res_com) return 0;
+ item = (struct tube_res_list*)malloc(sizeof(*item));
if(!item) {
free(msg);
log_err("out of memory for async answer");
@@ -687,8 +688,9 @@ int tube_setup_bg_write(struct tube* ATTR_UNUSED(tube),
int tube_queue_item(struct tube* tube, uint8_t* msg, size_t len)
{
- struct tube_res_list* item =
- (struct tube_res_list*)malloc(sizeof(*item));
+ struct tube_res_list* item;
+ if(!tube) return 0;
+ item = (struct tube_res_list*)malloc(sizeof(*item));
verbose(VERB_ALGO, "tube queue_item len %d", (int)len);
if(!item) {
free(msg);
diff --git a/contrib/unbound/util/ub_event.c b/contrib/unbound/util/ub_event.c
index fba2f2488296..78481a982055 100644
--- a/contrib/unbound/util/ub_event.c
+++ b/contrib/unbound/util/ub_event.c
@@ -95,6 +95,7 @@ UB_EV_BITS_CB(comm_timer_callback)
UB_EV_BITS_CB(comm_signal_callback)
UB_EV_BITS_CB(comm_point_local_handle_callback)
UB_EV_BITS_CB(comm_point_raw_handle_callback)
+UB_EV_BITS_CB(comm_point_http_handle_callback)
UB_EV_BITS_CB(tube_handle_signal)
UB_EV_BITS_CB(comm_base_handle_slow_accept)
@@ -116,12 +117,17 @@ static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*)
return my_comm_point_local_handle_callback;
else if(cb == comm_point_raw_handle_callback)
return my_comm_point_raw_handle_callback;
+ else if(cb == comm_point_http_handle_callback)
+ return my_comm_point_http_handle_callback;
else if(cb == tube_handle_signal)
return my_tube_handle_signal;
else if(cb == comm_base_handle_slow_accept)
return my_comm_base_handle_slow_accept;
- else
+ else {
+ log_assert(0); /* this NULL callback pointer should not happen,
+ we should have the necessary routine listed above */
return NULL;
+ }
}
#else
# define NATIVE_BITS(b) (b)
diff --git a/contrib/unbound/validator/val_anchor.c b/contrib/unbound/validator/val_anchor.c
index 6c6322447d6d..8ae9e7f3bce0 100644
--- a/contrib/unbound/validator/val_anchor.c
+++ b/contrib/unbound/validator/val_anchor.c
@@ -1309,3 +1309,44 @@ anchor_list_keytags(struct trust_anchor* ta, uint16_t* list, size_t num)
qsort(list, ret, sizeof(*list), keytag_compare);
return ret;
}
+
+int
+anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs,
+ size_t namelen, uint16_t dclass, uint16_t keytag)
+{
+ uint16_t* taglist;
+ uint16_t* tl;
+ size_t numtag, i;
+ struct trust_anchor* anchor = anchor_find(anchors,
+ name, namelabs, namelen, dclass);
+ if(!anchor)
+ return 0;
+ if(!anchor->numDS && !anchor->numDNSKEY) {
+ lock_basic_unlock(&anchor->lock);
+ return 0;
+ }
+
+ taglist = calloc(anchor->numDS + anchor->numDNSKEY, sizeof(*taglist));
+ if(!taglist) {
+ lock_basic_unlock(&anchor->lock);
+ return 0;
+ }
+
+ numtag = anchor_list_keytags(anchor, taglist,
+ anchor->numDS+anchor->numDNSKEY);
+ lock_basic_unlock(&anchor->lock);
+ if(!numtag) {
+ free(taglist);
+ return 0;
+ }
+ tl = taglist;
+ for(i=0; i<numtag; i++) {
+ if(*tl == keytag) {
+ free(taglist);
+ return 1;
+ }
+ tl++;
+ }
+ free(taglist);
+ return 0;
+}
diff --git a/contrib/unbound/validator/val_anchor.h b/contrib/unbound/validator/val_anchor.h
index 318a2b227cc7..a2a795d093d2 100644
--- a/contrib/unbound/validator/val_anchor.h
+++ b/contrib/unbound/validator/val_anchor.h
@@ -227,4 +227,19 @@ void anchors_delete_insecure(struct val_anchors* anchors, uint16_t c,
*/
size_t anchor_list_keytags(struct trust_anchor* ta, uint16_t* list, size_t num);
+/**
+ * Check if there is a trust anchor for given zone with this keytag.
+ *
+ * @param anchors: anchor storage
+ * @param name: name of trust anchor (wireformat)
+ * @param namelabs: labels in name
+ * @param namelen: length of name
+ * @param dclass: class of trust anchor
+ * @param keytag: keytag
+ * @return 1 if there is a trust anchor in the trustachor store for this zone
+ * and keytag, else 0.
+ */
+int anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs,
+ size_t namelen, uint16_t dclass, uint16_t keytag);
+
#endif /* VALIDATOR_VAL_ANCHOR_H */
diff --git a/contrib/unbound/validator/val_neg.c b/contrib/unbound/validator/val_neg.c
index 541238148307..c494a6be637f 100644
--- a/contrib/unbound/validator/val_neg.c
+++ b/contrib/unbound/validator/val_neg.c
@@ -1515,6 +1515,10 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo,
return NULL;
if(addsoa && !add_soa(rrset_cache, now, region, msg, NULL))
return NULL;
+
+ lock_basic_lock(&neg->lock);
+ neg->num_neg_cache_noerror++;
+ lock_basic_unlock(&neg->lock);
return msg;
} else if(nsec && val_nsec_proves_name_error(nsec, qinfo->qname)) {
if(!(msg = dns_msg_create(qinfo->qname, qinfo->qname_len,
@@ -1578,7 +1582,7 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo,
rcode = LDNS_RCODE_NXDOMAIN;
else if(!nsec_proves_nodata(wcrr, &wc_qinfo,
&nodata_wc) || nodata_wc)
- /* &nodata_wc shoudn't be set, wc_qinfo
+ /* &nodata_wc shouldn't be set, wc_qinfo
* already contains wildcard domain. */
/* NSEC doesn't prove anything for
* wildcard. */
@@ -1595,6 +1599,14 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo,
if(addsoa && !add_soa(rrset_cache, now, region, msg, NULL))
return NULL;
+ /* Increment statistic counters */
+ lock_basic_lock(&neg->lock);
+ if(rcode == LDNS_RCODE_NOERROR)
+ neg->num_neg_cache_noerror++;
+ else if(rcode == LDNS_RCODE_NXDOMAIN)
+ neg->num_neg_cache_nxdomain++;
+ lock_basic_unlock(&neg->lock);
+
FLAGS_SET_RCODE(msg->rep->flags, rcode);
return msg;
}
diff --git a/contrib/unbound/validator/val_neg.h b/contrib/unbound/validator/val_neg.h
index 00dad6df1f5c..877f5c944747 100644
--- a/contrib/unbound/validator/val_neg.h
+++ b/contrib/unbound/validator/val_neg.h
@@ -80,6 +80,12 @@ struct val_neg_cache {
size_t max;
/** max nsec3 iterations allowed */
size_t nsec3_max_iter;
+ /** number of times neg cache records were used to generate NOERROR
+ * responses. */
+ size_t num_neg_cache_noerror;
+ /** number of times neg cache records were used to generate NXDOMAIN
+ * responses. */
+ size_t num_neg_cache_nxdomain;
};
/**
diff --git a/contrib/unbound/validator/val_secalgo.c b/contrib/unbound/validator/val_secalgo.c
index 7f5c5181fd2d..95200a48b61b 100644
--- a/contrib/unbound/validator/val_secalgo.c
+++ b/contrib/unbound/validator/val_secalgo.c
@@ -231,7 +231,10 @@ dnskey_algo_id_is_supported(int id)
#ifdef USE_ED25519
case LDNS_ED25519:
#endif
-#if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA)
+#ifdef USE_ED448
+ case LDNS_ED448:
+#endif
+#if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA) || defined(USE_ED25519) || defined(USE_ED448)
return 1;
#endif
@@ -569,6 +572,17 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
*digest_type = NULL;
break;
#endif /* USE_ED25519 */
+#ifdef USE_ED448
+ case LDNS_ED448:
+ *evp_key = sldns_ed4482pkey_raw(key, keylen);
+ if(!*evp_key) {
+ verbose(VERB_QUERY, "verify: "
+ "sldns_ed4482pkey_raw failed");
+ return 0;
+ }
+ *digest_type = NULL;
+ break;
+#endif /* USE_ED448 */
default:
verbose(VERB_QUERY, "verify: unknown algorithm %d",
algo);
diff --git a/contrib/unbound/validator/validator.c b/contrib/unbound/validator/validator.c
index 5ed45e9bdefd..5777b2932cb4 100644
--- a/contrib/unbound/validator/validator.c
+++ b/contrib/unbound/validator/validator.c
@@ -40,6 +40,7 @@
* According to RFC 4034.
*/
#include "config.h"
+#include <ctype.h>
#include "validator/validator.h"
#include "validator/val_anchor.h"
#include "validator/val_kcache.h"
@@ -478,6 +479,31 @@ generate_keytag_query(struct module_qstate* qstate, int id,
}
/**
+ * Get keytag as uint16_t from string
+ *
+ * @param start: start of string containing keytag
+ * @param keytag: pointer where to store the extracted keytag
+ * @return: 1 if keytag was extracted, else 0.
+ */
+static int
+sentinel_get_keytag(char* start, uint16_t* keytag) {
+ char* keytag_str;
+ char* e = NULL;
+ keytag_str = calloc(1, SENTINEL_KEYTAG_LEN + 1 /* null byte */);
+ if(!keytag_str)
+ return 0;
+ memmove(keytag_str, start, SENTINEL_KEYTAG_LEN);
+ keytag_str[SENTINEL_KEYTAG_LEN] = '\0';
+ *keytag = (uint16_t)strtol(keytag_str, &e, 10);
+ if(!e || *e != '\0') {
+ free(keytag_str);
+ return 0;
+ }
+ free(keytag_str);
+ return 1;
+}
+
+/**
* Prime trust anchor for use.
* Generate and dispatch a priming query for the given trust anchor.
* The trust anchor can be DNSKEY or DS and does not have to be signed.
@@ -2223,6 +2249,34 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
vq->orig_msg->rep->security = sec_status_indeterminate;
}
+ if(vq->orig_msg->rep->security == sec_status_secure &&
+ qstate->env->cfg->root_key_sentinel &&
+ (qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
+ qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA)) {
+ char* keytag_start;
+ uint16_t keytag;
+ if(*qstate->qinfo.qname == strlen(SENTINEL_IS) +
+ SENTINEL_KEYTAG_LEN &&
+ dname_lab_startswith(qstate->qinfo.qname, SENTINEL_IS,
+ &keytag_start)) {
+ if(sentinel_get_keytag(keytag_start, &keytag) &&
+ !anchor_has_keytag(qstate->env->anchors,
+ (uint8_t*)"", 1, 0, vq->qchase.qclass, keytag)) {
+ vq->orig_msg->rep->security =
+ sec_status_secure_sentinel_fail;
+ }
+ } else if(*qstate->qinfo.qname == strlen(SENTINEL_NOT) +
+ SENTINEL_KEYTAG_LEN &&
+ dname_lab_startswith(qstate->qinfo.qname, SENTINEL_NOT,
+ &keytag_start)) {
+ if(sentinel_get_keytag(keytag_start, &keytag) &&
+ anchor_has_keytag(qstate->env->anchors,
+ (uint8_t*)"", 1, 0, vq->qchase.qclass, keytag)) {
+ vq->orig_msg->rep->security =
+ sec_status_secure_sentinel_fail;
+ }
+ }
+ }
/* store results in cache */
if(qstate->query_flags&BIT_RD) {
/* if secure, this will override cache anyway, no need
diff --git a/contrib/unbound/validator/validator.h b/contrib/unbound/validator/validator.h
index 9a591078f71c..9e4c8a9414a1 100644
--- a/contrib/unbound/validator/validator.h
+++ b/contrib/unbound/validator/validator.h
@@ -67,6 +67,13 @@ struct config_strlist;
/** max number of query restarts, number of IPs to probe */
#define VAL_MAX_RESTART_COUNT 5
+/** Root key sentinel is ta preamble */
+#define SENTINEL_IS "root-key-sentinel-is-ta-"
+/** Root key sentinel is not ta preamble */
+#define SENTINEL_NOT "root-key-sentinel-not-ta-"
+/** Root key sentinal keytag length */
+#define SENTINEL_KEYTAG_LEN 5
+
/**
* Global state for the validator.
*/