mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
120
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c66c86e95a | ||
|
|
b2590c2022 | ||
|
|
286494366c | ||
|
|
53724c9e7b | ||
|
|
c5f14dc880 | ||
|
|
a2ace114de | ||
|
|
2e9b880718 | ||
|
|
a0ec6cd946 | ||
|
|
ea36979c40 | ||
|
|
9a01a32176 | ||
|
|
08e4560065 | ||
|
|
86d4414a22 | ||
|
|
315077b9e6 | ||
|
|
535d899bef | ||
|
|
8656cfd4c8 | ||
|
|
8f44ddb7de | ||
|
|
4484dc3954 | ||
|
|
eb3bba0724 | ||
|
|
2eff1d8ab5 | ||
|
|
4672fa5b53 | ||
|
|
18029fc44f | ||
|
|
5c6f56f8f1 | ||
|
|
9af29c3ed1 | ||
|
|
76ef8c5803 | ||
|
|
94ef1a8fee | ||
|
|
683241a2f5 | ||
|
|
92ab54641e | ||
|
|
da3812953a | ||
|
|
1bd7c8dfee | ||
|
|
8f96ae7acf | ||
|
|
1f6e67e653 | ||
|
|
c4f8e60c85 | ||
|
|
b96d80a5d3 | ||
|
|
0b42d5ba13 | ||
|
|
a296b248b0 | ||
|
|
efc0c1e990 | ||
|
|
b0b8a3f144 | ||
|
|
172e4a9edb | ||
|
|
2c5e96f86c | ||
|
|
1ef131299a | ||
|
|
5b58a872ef | ||
|
|
d3902c0e70 | ||
|
|
35e3dcb701 | ||
|
|
415a83e9d5 | ||
|
|
94b04d6d46 | ||
|
|
f1a65eb4e8 | ||
|
|
38e1e3eec3 | ||
|
|
bff3d762ff | ||
|
|
fb322f3e87 | ||
|
|
2feee13735 | ||
|
|
1d36696462 | ||
|
|
aa4e2a9e69 | ||
|
|
8e04d04949 | ||
|
|
c5627dbd52 | ||
|
|
014ed9c5ff | ||
|
|
16e1e6d375 | ||
|
|
1a9a4e4ca1 | ||
|
|
f7f638e18f | ||
|
|
c956aea93d | ||
|
|
4556a4f490 | ||
|
|
19751ec179 | ||
|
|
6468917fb8 | ||
|
|
747ce6ba47 | ||
|
|
1cdddf0fe9 | ||
|
|
567c70dada | ||
|
|
8b4b2a88f7 | ||
|
|
831a805cd4 | ||
|
|
faf40c97fc | ||
|
|
a00cac5094 | ||
|
|
705d180096 | ||
|
|
ece48de2bc | ||
|
|
90c2ca4c55 | ||
|
|
daa016e3e4 | ||
|
|
039f69e735 | ||
|
|
b39009e487 | ||
|
|
933769ee73 | ||
|
|
57bff79627 | ||
|
|
1b5559d534 | ||
|
|
9d271c5343 | ||
|
|
74cc49e6c4 | ||
|
|
d414ebf0c7 | ||
|
|
9b123d1b78 | ||
|
|
37b71261a2 | ||
|
|
4426db4d3d | ||
|
|
fe10bc7682 | ||
|
|
67d2eae28c | ||
|
|
9010a7075e | ||
|
|
cc6dbc9f38 | ||
|
|
4198343dbe | ||
|
|
08600d68e8 | ||
|
|
18e098285e | ||
|
|
f1b35bab4b | ||
|
|
84ed77238d | ||
|
|
adb0374a4d | ||
|
|
b0b634558b | ||
|
|
8546247292 | ||
|
|
44659cb3bf | ||
|
|
a1ac2d0252 | ||
|
|
5c7a26b615 | ||
|
|
09d352b917 | ||
|
|
c0522043f0 | ||
|
|
b858801feb | ||
|
|
588db09928 | ||
|
|
5c66c48a1b | ||
|
|
83336477c6 | ||
|
|
e3e5eb66cf | ||
|
|
00d3b97dbb | ||
|
|
f6269baa60 | ||
|
|
19154c6e58 | ||
|
|
0f43b0ea6c | ||
|
|
e6d92f458f | ||
|
|
a31b9d50e2 | ||
|
|
fceb4e8585 | ||
|
|
98f4257890 | ||
|
|
0a15118aff | ||
|
|
e887a79a92 | ||
|
|
f9b9050ab8 | ||
|
|
94735384fd | ||
|
|
5dab0609e5 | ||
|
|
024c921dbf |
+3
-2
@@ -187,9 +187,9 @@ unittcpreuse.lo unitdoq.lo unitinfra.lo
|
||||
UNITTEST_OBJ_LINK=$(UNITTEST_OBJ) worker_cb.lo $(COMMON_OBJ) $(SLDNS_OBJ) \
|
||||
$(COMPAT_OBJ)
|
||||
DAEMON_SRC=daemon/acl_list.c daemon/cachedump.c daemon/daemon.c \
|
||||
daemon/remote.c daemon/stats.c daemon/unbound.c daemon/worker.c @WIN_DAEMON_SRC@
|
||||
daemon/remote.c daemon/stats.c daemon/metrics.c daemon/unbound.c daemon/worker.c @WIN_DAEMON_SRC@
|
||||
DAEMON_OBJ=acl_list.lo cachedump.lo daemon.lo \
|
||||
shm_main.lo remote.lo stats.lo unbound.lo \
|
||||
shm_main.lo remote.lo stats.lo metrics.lo unbound.lo \
|
||||
worker.lo @WIN_DAEMON_OBJ@
|
||||
DAEMON_OBJ_LINK=$(DAEMON_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \
|
||||
$(COMPAT_OBJ) @WIN_DAEMON_OBJ_LINK@
|
||||
@@ -721,6 +721,7 @@ depend:
|
||||
ipset.lo ipset.o: $(srcdir)/ipset/ipset.c
|
||||
doqclient.lo doqclient.o: $(srcdir)/testcode/doqclient.c
|
||||
unitdoq.lo unitdoq.o: $(srcdir)/testcode/unitdoq.c
|
||||
metrics.lo metrics.o: $(srcdir)/daemon/metrics.c
|
||||
|
||||
# Dependencies
|
||||
dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
|
||||
|
||||
+7
-1
@@ -2,7 +2,9 @@
|
||||
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
|
||||
# BSD licensed.
|
||||
#
|
||||
# Version 50
|
||||
# Version 51
|
||||
# 2025-11-06 Fix ACX_CHECK_NONSTRING_ATTRIBUTE to reject clang, that prints
|
||||
# a warning for 'unknown attribute' when nonstring is used.
|
||||
# 2025-09-29 add ac_cv_func_malloc_0_nonnull as a cache value for the malloc(0)
|
||||
# check by ACX_FUNC_MALLOC.
|
||||
# 2025-09-29 add ACX_CHECK_NONSTRING_ATTRIBUTE, AHX_CONFIG_NONSTRING_ATTRIBUTE.
|
||||
@@ -535,6 +537,9 @@ dnl result in HAVE_ATTR_NONSTRING.
|
||||
dnl Make sure you include AHX_CONFIG_NONSTRING_ATTRIBUTE also.
|
||||
AC_DEFUN([ACX_CHECK_NONSTRING_ATTRIBUTE],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_REQUIRE([ACX_CHECK_ERROR_FLAGS])
|
||||
BAKCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $ERRFLAG"
|
||||
AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "nonstring" attribute)
|
||||
AC_CACHE_VAL(ac_cv_c_nonstring_attribute,
|
||||
[ac_cv_c_nonstring_attribute=no
|
||||
@@ -546,6 +551,7 @@ struct test {
|
||||
struct test t = { "1" };
|
||||
(void) t;
|
||||
]])],[ac_cv_c_nonstring_attribute="yes"],[ac_cv_c_nonstring_attribute="no"])
|
||||
CFLAGS="$BAKCFLAGS"
|
||||
])
|
||||
|
||||
dnl Setup ATTR_NONSTRING config.h parts.
|
||||
|
||||
+11
-4
@@ -754,8 +754,10 @@ cachedb_intcache_store(struct module_qstate* qstate, int msg_expired,
|
||||
"(original ttl: %d)", (int)original_ttl);
|
||||
/* The expired entry does not get checked by the validator
|
||||
* and we need a validation value for it. */
|
||||
/* By setting this to unchecked, bogus data is not returned
|
||||
* as non-bogus. */
|
||||
if(qstate->env->cfg->cachedb_check_when_serve_expired)
|
||||
qstate->return_msg->rep->security = sec_status_insecure;
|
||||
qstate->return_msg->rep->security = sec_status_unchecked;
|
||||
}
|
||||
(void)dns_cache_store(qstate->env, &qstate->qinfo,
|
||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
|
||||
@@ -803,8 +805,11 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
return;
|
||||
}
|
||||
|
||||
if(qstate->blacklist || qstate->no_cache_lookup) {
|
||||
/* cache is blacklisted or we are instructed from edns to not look */
|
||||
if(qstate->blacklist || qstate->no_cache_lookup
|
||||
|| iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL,
|
||||
NULL, 0)) {
|
||||
/* cache is blacklisted or we are instructed from edns to not
|
||||
* look or a forwarder/stub forbids it */
|
||||
/* pass request to next module */
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
@@ -892,7 +897,9 @@ cachedb_handle_response(struct module_qstate* qstate,
|
||||
{
|
||||
qstate->is_cachedb_answer = 0;
|
||||
/* check if we are not enabled or instructed to not cache, and skip */
|
||||
if(!ie->enabled || qstate->no_cache_store) {
|
||||
if(!ie->enabled || qstate->no_cache_store
|
||||
|| iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL,
|
||||
NULL, 0)) {
|
||||
/* we are done with the query */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
#ifndef UB_ON_WINDOWS
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#ifdef __QNX__
|
||||
#include "util/log.h"
|
||||
#endif /* __QNX__ */
|
||||
|
||||
#define KEYSTREAM_ONLY
|
||||
#include "chacha_private.h"
|
||||
@@ -187,7 +190,11 @@ _rs_stir(void)
|
||||
if(errno != ENOSYS ||
|
||||
fallback_getentropy_urandom(rnd, sizeof rnd) == -1) {
|
||||
#ifdef SIGKILL
|
||||
#ifndef __QNX__
|
||||
raise(SIGKILL);
|
||||
#else /* !__QNX__ */
|
||||
fatal_exit("failed to getentropy");
|
||||
#endif /* __QNX__ */
|
||||
#else
|
||||
exit(9); /* windows */
|
||||
#endif
|
||||
|
||||
@@ -29,7 +29,9 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/resource.h>
|
||||
#ifndef __QNX__
|
||||
#include <sys/syscall.h>
|
||||
#endif /* !__QNX__ */
|
||||
#ifdef SYS__sysctl
|
||||
#include <linux/sysctl.h>
|
||||
#endif
|
||||
@@ -42,7 +44,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#ifndef __QNX__
|
||||
#include <link.h>
|
||||
#endif /* __QNX__ */
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
@@ -60,12 +64,14 @@
|
||||
#define SHA512_Final(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r)
|
||||
#endif
|
||||
|
||||
#ifndef __QNX__
|
||||
#include <linux/types.h>
|
||||
#include <linux/random.h>
|
||||
#ifdef HAVE_GETAUXVAL
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
#include <sys/vfs.h>
|
||||
#endif /* !__QNX__ */
|
||||
#ifndef MAP_ANON
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#endif
|
||||
@@ -94,8 +100,10 @@ static int getentropy_urandom(void *buf, size_t len);
|
||||
#ifdef SYS__sysctl
|
||||
static int getentropy_sysctl(void *buf, size_t len);
|
||||
#endif
|
||||
#ifndef __QNX__
|
||||
static int getentropy_fallback(void *buf, size_t len);
|
||||
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
|
||||
#endif /* !__QNX__ */
|
||||
|
||||
int
|
||||
getentropy(void *buf, size_t len)
|
||||
@@ -178,6 +186,7 @@ getentropy(void *buf, size_t len)
|
||||
* sysctl ABI, or consider providing a new failsafe API which
|
||||
* works in a chroot or when file descriptors are exhausted.
|
||||
*/
|
||||
#ifndef __QNX__
|
||||
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
|
||||
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
|
||||
raise(SIGKILL);
|
||||
@@ -185,6 +194,9 @@ getentropy(void *buf, size_t len)
|
||||
ret = getentropy_fallback(buf, len);
|
||||
if (ret != -1)
|
||||
return (ret);
|
||||
#else /* !__QNX__ */
|
||||
fatal_exit("failed to read from /dev/urandom");
|
||||
#endif /* __QNX__ */
|
||||
|
||||
errno = EIO;
|
||||
return (ret);
|
||||
@@ -214,7 +226,11 @@ getentropy_urandom(void *buf, size_t len)
|
||||
{
|
||||
struct stat st;
|
||||
size_t i;
|
||||
#ifndef __QNX__
|
||||
int fd, cnt, flags;
|
||||
#else /* !__QNX__ */
|
||||
int fd, flags;
|
||||
#endif /* __QNX__ */
|
||||
int save_errno = errno;
|
||||
|
||||
start:
|
||||
@@ -241,10 +257,12 @@ start:
|
||||
close(fd);
|
||||
goto nodevrandom;
|
||||
}
|
||||
#ifndef __QNX__
|
||||
if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
|
||||
close(fd);
|
||||
goto nodevrandom;
|
||||
}
|
||||
#endif /* !__QNX__ */
|
||||
for (i = 0; i < len; ) {
|
||||
size_t wanted = len - i;
|
||||
ssize_t ret = read(fd, (char *)buf + i, wanted);
|
||||
@@ -265,6 +283,7 @@ nodevrandom:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#ifndef __QNX__
|
||||
#ifdef SYS__sysctl
|
||||
static int
|
||||
getentropy_sysctl(void *buf, size_t len)
|
||||
@@ -537,3 +556,4 @@ getentropy_fallback(void *buf, size_t len)
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
}
|
||||
#endif /* !__QNX__ */
|
||||
|
||||
+19
@@ -237,6 +237,9 @@
|
||||
/* Define to 1 if you have the <event.h> header file. */
|
||||
#undef HAVE_EVENT_H
|
||||
|
||||
/* Define to 1 if you have the `evhttp_free' function. */
|
||||
#undef HAVE_EVHTTP_FREE
|
||||
|
||||
/* Define to 1 if you have the `EVP_aes_256_cbc' function. */
|
||||
#undef HAVE_EVP_AES_256_CBC
|
||||
|
||||
@@ -735,6 +738,12 @@
|
||||
/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
|
||||
|
||||
/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_MTIMENSEC
|
||||
|
||||
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
|
||||
|
||||
/* Define if you have Swig libraries and header files. */
|
||||
#undef HAVE_SWIG
|
||||
|
||||
@@ -980,6 +989,9 @@
|
||||
/* define this to enable debug checks. */
|
||||
#undef UNBOUND_DEBUG
|
||||
|
||||
/* Define the default metrics HTTP endpoint port. */
|
||||
#undef UNBOUND_METRICS_PORT
|
||||
|
||||
/* Define to 1 to use cachedb support */
|
||||
#undef USE_CACHEDB
|
||||
|
||||
@@ -1027,6 +1039,10 @@
|
||||
distributions) the use of non-ephemeral ports. */
|
||||
#undef USE_LINUX_IP_LOCAL_PORT_RANGE
|
||||
|
||||
/* Define this to expose Unbound statistics via a prometheus metrics HTTP
|
||||
endpoint. */
|
||||
#undef USE_METRICS
|
||||
|
||||
/* Define if you want to use internal select based events */
|
||||
#undef USE_MINI_EVENT
|
||||
|
||||
@@ -1136,6 +1152,9 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Define to 1 to prefer TLS crypto settings from the system. */
|
||||
#undef USE_SYSTEM_TLS
|
||||
|
||||
/* Define this to enable server TCP Fast Open. */
|
||||
#undef USE_TCP_FASTOPEN
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.71 for unbound 1.24.2.
|
||||
# Generated by GNU Autoconf 2.71 for unbound 1.24.3.
|
||||
#
|
||||
# Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>.
|
||||
#
|
||||
@@ -622,8 +622,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='unbound'
|
||||
PACKAGE_TARNAME='unbound'
|
||||
PACKAGE_VERSION='1.24.2'
|
||||
PACKAGE_STRING='unbound 1.24.2'
|
||||
PACKAGE_VERSION='1.24.3'
|
||||
PACKAGE_STRING='unbound 1.24.3'
|
||||
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -669,6 +669,7 @@ SOURCEFILE
|
||||
SOURCEDETERMINE
|
||||
IPSET_OBJ
|
||||
IPSET_SRC
|
||||
SYSTEM_TLS_DEFAULT
|
||||
IPSECMOD_HEADER
|
||||
IPSECMOD_OBJ
|
||||
CACHEDB_OBJ
|
||||
@@ -936,6 +937,7 @@ enable_dnscrypt
|
||||
with_libsodium
|
||||
enable_cachedb
|
||||
enable_ipsecmod
|
||||
enable_system_tls
|
||||
enable_ipset
|
||||
with_libmnl
|
||||
enable_explicit_port_randomisation
|
||||
@@ -1513,7 +1515,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.24.2 to adapt to many kinds of systems.
|
||||
\`configure' configures unbound 1.24.3 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1579,7 +1581,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of unbound 1.24.2:";;
|
||||
short | recursive ) echo "Configuration of unbound 1.24.3:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1641,6 +1643,8 @@ Optional Features:
|
||||
storage
|
||||
--enable-ipsecmod Enable ipsecmod module that facilitates
|
||||
opportunistic IPsec
|
||||
--enable-system-tls Enable preference of system configured TLS socket
|
||||
options
|
||||
--enable-ipset enable ipset module
|
||||
--disable-explicit-port-randomisation
|
||||
disable explicit source port randomisation and rely
|
||||
@@ -1832,7 +1836,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unbound configure 1.24.2
|
||||
unbound configure 1.24.3
|
||||
generated by GNU Autoconf 2.71
|
||||
|
||||
Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
@@ -2489,7 +2493,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.24.2, which was
|
||||
It was created by unbound $as_me 1.24.3, which was
|
||||
generated by GNU Autoconf 2.71. Invocation command line was
|
||||
|
||||
$ $0$ac_configure_args_raw
|
||||
@@ -3253,11 +3257,11 @@ UNBOUND_VERSION_MAJOR=1
|
||||
|
||||
UNBOUND_VERSION_MINOR=24
|
||||
|
||||
UNBOUND_VERSION_MICRO=2
|
||||
UNBOUND_VERSION_MICRO=3
|
||||
|
||||
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=35
|
||||
LIBUNBOUND_REVISION=36
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -3360,6 +3364,7 @@ LIBUNBOUND_AGE=1
|
||||
# 1.24.0 had 9:33:1
|
||||
# 1.24.1 had 9:34:1
|
||||
# 1.24.2 had 9:35:1
|
||||
# 1.24.3 had 9:36:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -6949,6 +6954,9 @@ printf "%s\n" "#define HAVE_ATTR_UNUSED 1" >>confdefs.h
|
||||
fi
|
||||
|
||||
|
||||
|
||||
BAKCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $ERRFLAG"
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler (${CC-cc}) accepts the \"nonstring\" attribute" >&5
|
||||
printf %s "checking whether the C compiler (${CC-cc}) accepts the \"nonstring\" attribute... " >&6; }
|
||||
if test ${ac_cv_c_nonstring_attribute+y}
|
||||
@@ -6981,6 +6989,7 @@ else $as_nop
|
||||
ac_cv_c_nonstring_attribute="no"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||
CFLAGS="$BAKCFLAGS"
|
||||
|
||||
fi
|
||||
|
||||
@@ -7059,7 +7068,14 @@ else $as_nop
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <stdio.h>
|
||||
__attribute__((noreturn)) void f(int x) { printf("%d", x); }
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif
|
||||
__attribute__((noreturn)) void f(int x) { printf("%d", x); exit(1); }
|
||||
|
||||
int
|
||||
main (void)
|
||||
@@ -22153,6 +22169,31 @@ else $as_nop
|
||||
fi
|
||||
printf "%s\n" "#define HAVE_DECL_EVSIGNAL_ASSIGN $ac_have_decl" >>confdefs.h
|
||||
|
||||
# prometheus metrics depend on libevent 2.0 and later, and is therefore
|
||||
# only enabled when the required version is found and used
|
||||
|
||||
for ac_func in evhttp_free
|
||||
do :
|
||||
ac_fn_c_check_func "$LINENO" "evhttp_free" "ac_cv_func_evhttp_free"
|
||||
if test "x$ac_cv_func_evhttp_free" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_EVHTTP_FREE 1" >>confdefs.h
|
||||
|
||||
|
||||
printf "%s\n" "#define USE_METRICS /**/" >>confdefs.h
|
||||
|
||||
|
||||
printf "%s\n" "#define UNBOUND_METRICS_PORT 9101" >>confdefs.h
|
||||
|
||||
|
||||
else $as_nop
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: disabling prometheus metrics" >&5
|
||||
printf "%s\n" "$as_me: disabling prometheus metrics" >&6;}
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
PC_LIBEVENT_DEPENDENCY="libevent"
|
||||
|
||||
if test -n "$BAK_LDFLAGS_SET"; then
|
||||
@@ -22162,6 +22203,8 @@ else
|
||||
|
||||
printf "%s\n" "#define USE_MINI_EVENT 1" >>confdefs.h
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Prometheus metrics are disabled with the builtin libevent alternative" >&5
|
||||
printf "%s\n" "$as_me: Prometheus metrics are disabled with the builtin libevent alternative" >&6;}
|
||||
fi
|
||||
|
||||
# check for libexpat
|
||||
@@ -23252,6 +23295,23 @@ printf "%s\n" "no" >&6; }
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_member "$LINENO" "struct stat" "st_mtimensec" "ac_cv_member_struct_stat_st_mtimensec" "$ac_includes_default"
|
||||
if test "x$ac_cv_member_struct_stat_st_mtimensec" = xyes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define HAVE_STRUCT_STAT_ST_MTIMENSEC 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim.tv_nsec" "ac_cv_member_struct_stat_st_mtim_tv_nsec" "$ac_includes_default"
|
||||
if test "x$ac_cv_member_struct_stat_st_mtim_tv_nsec" = xyes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_member "$LINENO" "struct sockaddr_un" "sun_len" "ac_cv_member_struct_sockaddr_un_sun_len" "
|
||||
@@ -25090,6 +25150,26 @@ printf "%s\n" "#define USE_IPSECMOD 1" >>confdefs.h
|
||||
;;
|
||||
esac
|
||||
|
||||
# check for system TLS preference if requested
|
||||
# Check whether --enable-system-tls was given.
|
||||
if test ${enable_system_tls+y}
|
||||
then :
|
||||
enableval=$enable_system_tls;
|
||||
fi
|
||||
|
||||
case "$enable_system_tls" in
|
||||
yes)
|
||||
|
||||
printf "%s\n" "#define USE_SYSTEM_TLS 1" >>confdefs.h
|
||||
|
||||
SYSTEM_TLS_DEFAULT="yes"
|
||||
;;
|
||||
no|*)
|
||||
SYSTEM_TLS_DEFAULT="no"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# check for ipset if requested
|
||||
# Check whether --enable-ipset was given.
|
||||
if test ${enable_ipset+y}
|
||||
@@ -25357,7 +25437,7 @@ printf "%s\n" "#define MAXSYSLOGMSGLEN 10240" >>confdefs.h
|
||||
|
||||
|
||||
|
||||
version=1.24.2
|
||||
version=1.24.3
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build time" >&5
|
||||
printf %s "checking for build time... " >&6; }
|
||||
@@ -25887,7 +25967,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.24.2, which was
|
||||
This file was extended by unbound $as_me 1.24.3, which was
|
||||
generated by GNU Autoconf 2.71. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -25955,7 +26035,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config='$ac_cs_config_escaped'
|
||||
ac_cs_version="\\
|
||||
unbound config.status 1.24.2
|
||||
unbound config.status 1.24.3
|
||||
configured by $0, generated by GNU Autoconf 2.71,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+34
-3
@@ -12,14 +12,14 @@ sinclude(dnscrypt/dnscrypt.m4)
|
||||
# must be numbers. ac_defun because of later processing
|
||||
m4_define([VERSION_MAJOR],[1])
|
||||
m4_define([VERSION_MINOR],[24])
|
||||
m4_define([VERSION_MICRO],[2])
|
||||
m4_define([VERSION_MICRO],[3])
|
||||
AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound])
|
||||
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
|
||||
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=35
|
||||
LIBUNBOUND_REVISION=36
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -122,6 +122,7 @@ LIBUNBOUND_AGE=1
|
||||
# 1.24.0 had 9:33:1
|
||||
# 1.24.1 had 9:34:1
|
||||
# 1.24.2 had 9:35:1
|
||||
# 1.24.3 had 9:36:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -361,7 +362,14 @@ AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "noreturn" attribu
|
||||
AC_CACHE_VAL(ac_cv_c_noreturn_attribute,
|
||||
[ac_cv_c_noreturn_attribute=no
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h>
|
||||
__attribute__((noreturn)) void f(int x) { printf("%d", x); }
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#endif
|
||||
__attribute__((noreturn)) void f(int x) { printf("%d", x); exit(1); }
|
||||
]], [[
|
||||
f(1);
|
||||
]])],[ac_cv_c_noreturn_attribute="yes"],[ac_cv_c_noreturn_attribute="no"])
|
||||
@@ -1490,6 +1498,14 @@ large outgoing port ranges. ])
|
||||
# include "event2/event.h"
|
||||
#endif
|
||||
])
|
||||
# prometheus metrics depend on libevent 2.0 and later, and is therefore
|
||||
# only enabled when the required version is found and used
|
||||
AC_CHECK_FUNCS([evhttp_free], [
|
||||
AC_DEFINE_UNQUOTED([USE_METRICS], [], [Define this to expose Unbound statistics via a prometheus metrics HTTP endpoint.])
|
||||
AC_DEFINE_UNQUOTED([UNBOUND_METRICS_PORT], [9101], [Define the default metrics HTTP endpoint port.])
|
||||
], [
|
||||
AC_MSG_NOTICE([disabling prometheus metrics])
|
||||
])
|
||||
PC_LIBEVENT_DEPENDENCY="libevent"
|
||||
AC_SUBST(PC_LIBEVENT_DEPENDENCY)
|
||||
if test -n "$BAK_LDFLAGS_SET"; then
|
||||
@@ -1497,6 +1513,7 @@ large outgoing port ranges. ])
|
||||
fi
|
||||
else
|
||||
AC_DEFINE(USE_MINI_EVENT, 1, [Define if you want to use internal select based events])
|
||||
AC_MSG_NOTICE([Prometheus metrics are disabled with the builtin libevent alternative])
|
||||
fi
|
||||
|
||||
# check for libexpat
|
||||
@@ -1761,6 +1778,7 @@ if test $ac_cv_func_daemon = yes; then
|
||||
])
|
||||
fi
|
||||
|
||||
AC_CHECK_MEMBERS([struct stat.st_mtimensec, struct stat.st_mtim.tv_nsec])
|
||||
AC_CHECK_MEMBERS([struct sockaddr_un.sun_len],,,[
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
@@ -2072,6 +2090,19 @@ case "$enable_ipsecmod" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# check for system TLS preference if requested
|
||||
AC_ARG_ENABLE(system-tls, AS_HELP_STRING([--enable-system-tls],[Enable preference of system configured TLS socket options]))
|
||||
case "$enable_system_tls" in
|
||||
yes)
|
||||
AC_DEFINE([USE_SYSTEM_TLS], [1], [Define to 1 to prefer TLS crypto settings from the system.])
|
||||
SYSTEM_TLS_DEFAULT="yes"
|
||||
;;
|
||||
no|*)
|
||||
SYSTEM_TLS_DEFAULT="no"
|
||||
;;
|
||||
esac
|
||||
AC_SUBST([SYSTEM_TLS_DEFAULT])
|
||||
|
||||
# check for ipset if requested
|
||||
AC_ARG_ENABLE(ipset, AS_HELP_STRING([--enable-ipset],[enable ipset module]))
|
||||
case "$enable_ipset" in
|
||||
|
||||
@@ -58,3 +58,5 @@ distribution but may be helpful.
|
||||
* unbound.init_yocto: An init script to start and stop the server. Put it
|
||||
in /etc/init.d/unbound to use it. It is for the Yocto Project, in
|
||||
embedded systems, contributed by beni-sandu.
|
||||
* gost12.patch: adds ECC-GOST12 support for the informational RFC9558.
|
||||
Contributed by Igor V. Ruzanov.
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
diff --git a/sldns/keyraw.c b/sldns/keyraw.c
|
||||
index 42a9262a3..cc6406a56 100644
|
||||
--- a/sldns/keyraw.c
|
||||
+++ b/sldns/keyraw.c
|
||||
@@ -85,7 +85,7 @@ sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
|
||||
}
|
||||
break;
|
||||
#ifdef USE_GOST
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
return 512;
|
||||
#endif
|
||||
#ifdef USE_ECDSA
|
||||
@@ -146,7 +146,7 @@ sldns_key_EVP_load_gost_id(void)
|
||||
if(gost_id) return gost_id;
|
||||
|
||||
/* see if configuration loaded gost implementation from other engine*/
|
||||
- meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
|
||||
+ meth = EVP_PKEY_asn1_find_str(NULL, "gost2012_256", -1);
|
||||
if(meth) {
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
@@ -170,7 +170,7 @@ sldns_key_EVP_load_gost_id(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
|
||||
+ meth = EVP_PKEY_asn1_find_str(&e, "gost2012_256", -1);
|
||||
if(!meth) {
|
||||
/* algo not found */
|
||||
ENGINE_finish(e);
|
||||
@@ -536,12 +536,17 @@ EVP_PKEY* sldns_key_rsa2pkey_raw(unsigned char* key, size_t len)
|
||||
EVP_PKEY*
|
||||
sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
|
||||
{
|
||||
- /* prefix header for X509 encoding */
|
||||
- uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
|
||||
- 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
|
||||
- 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
|
||||
- 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
|
||||
- unsigned char encoded[37+64];
|
||||
+ /* prefix header for X509 encoding
|
||||
+ *
|
||||
+ * note: based on draft-makarenko-gost2012-dnssec-01 (pre-RFC9558 and it DOES work!)
|
||||
+ * ASN1 header described in RFC9558 is not suitable due to d2i_PUBKEY() works with
|
||||
+ * non-compressed public keys (two additional bytes 0x04, 0x40 at the end of header)
|
||||
+ */
|
||||
+ uint8_t asn[32] = { 0x30, 0x5e, 0x30, 0x17, 0x06, 0x08, 0x2a, 0x85,
|
||||
+ 0x03, 0x07, 0x01, 0x01, 0x01, 0x01, 0x30, 0x0b,
|
||||
+ 0x06, 0x09, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x02,
|
||||
+ 0x01, 0x01, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40 };
|
||||
+ unsigned char encoded[32+64];
|
||||
const unsigned char* pp;
|
||||
if(keylen != 64) {
|
||||
/* key wrong size */
|
||||
@@ -549,8 +554,8 @@ sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
|
||||
}
|
||||
|
||||
/* create evp_key */
|
||||
- memmove(encoded, asn, 37);
|
||||
- memmove(encoded+37, key, 64);
|
||||
+ memmove(encoded, asn, 32);
|
||||
+ memmove(encoded+32, key, 64);
|
||||
pp = (unsigned char*)&encoded[0];
|
||||
|
||||
return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
|
||||
diff --git a/sldns/rrdef.h b/sldns/rrdef.h
|
||||
index bbc3d5b86..7d5f3c057 100644
|
||||
--- a/sldns/rrdef.h
|
||||
+++ b/sldns/rrdef.h
|
||||
@@ -384,11 +384,12 @@ enum sldns_enum_algorithm
|
||||
LDNS_RSASHA1_NSEC3 = 7,
|
||||
LDNS_RSASHA256 = 8, /* RFC 5702 */
|
||||
LDNS_RSASHA512 = 10, /* RFC 5702 */
|
||||
- LDNS_ECC_GOST = 12, /* RFC 5933 */
|
||||
+ LDNS_ECC_GOST = 12, /* RFC 5933, deprecated */
|
||||
LDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */
|
||||
LDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */
|
||||
LDNS_ED25519 = 15, /* RFC 8080 */
|
||||
LDNS_ED448 = 16, /* RFC 8080 */
|
||||
+ LDNS_ECC_GOST12 = 23, /* RFC 9558 */
|
||||
LDNS_INDIRECT = 252,
|
||||
LDNS_PRIVATEDNS = 253,
|
||||
LDNS_PRIVATEOID = 254
|
||||
@@ -402,8 +403,9 @@ enum sldns_enum_hash
|
||||
{
|
||||
LDNS_SHA1 = 1, /* RFC 4034 */
|
||||
LDNS_SHA256 = 2, /* RFC 4509 */
|
||||
- LDNS_HASH_GOST = 3, /* RFC 5933 */
|
||||
- LDNS_SHA384 = 4 /* RFC 6605 */
|
||||
+ LDNS_HASH_GOST = 3, /* RFC 5933, deprecated */
|
||||
+ LDNS_SHA384 = 4, /* RFC 6605 */
|
||||
+ LDNS_HASH_GOST12 = 5 /* RFC 9558 */
|
||||
};
|
||||
typedef enum sldns_enum_hash sldns_hash;
|
||||
|
||||
diff --git a/sldns/wire2str.c b/sldns/wire2str.c
|
||||
index 75b8f37b0..b4c4755e6 100644
|
||||
--- a/sldns/wire2str.c
|
||||
+++ b/sldns/wire2str.c
|
||||
@@ -45,11 +45,12 @@ static sldns_lookup_table sldns_algorithms_data[] = {
|
||||
{ LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
|
||||
{ LDNS_RSASHA256, "RSASHA256"},
|
||||
{ LDNS_RSASHA512, "RSASHA512"},
|
||||
- { LDNS_ECC_GOST, "ECC-GOST"},
|
||||
+ { LDNS_ECC_GOST, "ECC-GOST"}, /* deprecated */
|
||||
{ LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
|
||||
{ LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
|
||||
{ LDNS_ED25519, "ED25519"},
|
||||
{ LDNS_ED448, "ED448"},
|
||||
+ { LDNS_ECC_GOST12, "ECC-GOST12"},
|
||||
{ LDNS_INDIRECT, "INDIRECT" },
|
||||
{ LDNS_PRIVATEDNS, "PRIVATEDNS" },
|
||||
{ LDNS_PRIVATEOID, "PRIVATEOID" },
|
||||
@@ -61,8 +62,9 @@ sldns_lookup_table* sldns_algorithms = sldns_algorithms_data;
|
||||
static sldns_lookup_table sldns_hashes_data[] = {
|
||||
{ LDNS_SHA1, "SHA1" },
|
||||
{ LDNS_SHA256, "SHA256" },
|
||||
- { LDNS_HASH_GOST, "HASH-GOST" },
|
||||
+ { LDNS_HASH_GOST, "HASH-GOST" }, /* deprecated */
|
||||
{ LDNS_SHA384, "SHA384" },
|
||||
+ { LDNS_HASH_GOST12, "HASH-GOST12" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
sldns_lookup_table* sldns_hashes = sldns_hashes_data;
|
||||
diff --git a/testcode/unitverify.c b/testcode/unitverify.c
|
||||
index fcf2e2ffe..4a33e9f6a 100644
|
||||
--- a/testcode/unitverify.c
|
||||
+++ b/testcode/unitverify.c
|
||||
@@ -696,7 +696,7 @@ verify_test(void)
|
||||
#endif
|
||||
#ifdef USE_GOST
|
||||
if(sldns_key_EVP_load_gost_id())
|
||||
- verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost", "20090807060504");
|
||||
+ verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost12", "20251226060504");
|
||||
else printf("Warning: skipped GOST, openssl does not provide gost.\n");
|
||||
#endif
|
||||
#ifdef USE_ECDSA
|
||||
diff --git a/testdata/test_sigs.gost12 b/testdata/test_sigs.gost12
|
||||
new file mode 100644
|
||||
index 000000000..72a250cff
|
||||
--- /dev/null
|
||||
+++ b/testdata/test_sigs.gost12
|
||||
@@ -0,0 +1,39 @@
|
||||
+; Signature test file
|
||||
+
|
||||
+; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification.
|
||||
+; later entries are verified with it.
|
||||
+
|
||||
+; Test GOST signatures using algo number 23.
|
||||
+
|
||||
+ENTRY_BEGIN
|
||||
+SECTION QUESTION
|
||||
+nlnetlabs.nl. IN DNSKEY
|
||||
+SECTION ANSWER
|
||||
+nlnetlabs.nl. 3600 IN DNSKEY 256 3 23 cdOtkEcb6NhcdOpIbPYtWyWxdlUiKgtKQbYg3lIjtG7i3fYjUID9zyOgoQEiV9wuGCfrw5cNsnvNw+8HiVFK4g== ;{id = 12301 (zsk), size = 512b}
|
||||
+ENTRY_END
|
||||
+
|
||||
+; entry to test
|
||||
+ENTRY_BEGIN
|
||||
+SECTION QUESTION
|
||||
+open.nlnetlabs.nl. IN A
|
||||
+SECTION ANSWER
|
||||
+open.nlnetlabs.nl. 600 IN A 213.154.224.1
|
||||
+open.nlnetlabs.nl. 600 IN RRSIG A 23 3 600 20260122084903 20251225084903 12301 nlnetlabs.nl. I12wYNs96DxMy26CWx296/sWMJAFg4nNXBo0sw7PnuMbJW5NFAmZYtFWhUdOWn4umaiodYOAmKG8Zg/OKvEtAQ==
|
||||
+ENTRY_END
|
||||
+
|
||||
+ENTRY_BEGIN
|
||||
+SECTION QUESTION
|
||||
+open.nlnetlabs.nl. IN AAAA
|
||||
+SECTION ANSWER
|
||||
+open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::1
|
||||
+open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::53
|
||||
+open.nlnetlabs.nl. 600 IN RRSIG AAAA 23 3 600 20260122084903 20251225084903 12301 nlnetlabs.nl. J0jHa+CP8HM6UDa2+uYgaze2mfpJTh2hkZ2KwMTYb5sfL6iBmxxql0c/403Itk4fMfYBMGn7zfzDQ+CxnCgSWw==
|
||||
+ENTRY_END
|
||||
+
|
||||
+ENTRY_BEGIN
|
||||
+SECTION QUESTION
|
||||
+open.nlnetlabs.nl. IN NSEC
|
||||
+SECTION ANSWER
|
||||
+open.nlnetlabs.nl. 86400 IN NSEC nlnetlabs.nl. A AAAA RRSIG NSEC
|
||||
+open.nlnetlabs.nl. 86400 IN RRSIG NSEC 23 3 86400 20260122084903 20251225084903 12301 nlnetlabs.nl. INCLYe9vAaNYaYx5Ay3Q6QdX+wPW9sMRvVlGt/jUEGgCi+88QlV80CT1oHrhRI66I14Wk6NRAGZRNx1tUPSHSg==
|
||||
+ENTRY_END
|
||||
diff --git a/validator/val_secalgo.c b/validator/val_secalgo.c
|
||||
index be8347b1b..4f621a309 100644
|
||||
--- a/validator/val_secalgo.c
|
||||
+++ b/validator/val_secalgo.c
|
||||
@@ -246,10 +246,10 @@ ds_digest_size_supported(int algo)
|
||||
return SHA256_DIGEST_LENGTH;
|
||||
#endif
|
||||
#ifdef USE_GOST
|
||||
- case LDNS_HASH_GOST:
|
||||
+ case LDNS_HASH_GOST12:
|
||||
/* we support GOST if it can be loaded */
|
||||
(void)sldns_key_EVP_load_gost_id();
|
||||
- if(EVP_get_digestbyname("md_gost94"))
|
||||
+ if(EVP_get_digestbyname("md_gost12_256"))
|
||||
return 32;
|
||||
else return 0;
|
||||
#endif
|
||||
@@ -265,9 +265,9 @@ ds_digest_size_supported(int algo)
|
||||
#ifdef USE_GOST
|
||||
/** Perform GOST hash */
|
||||
static int
|
||||
-do_gost94(unsigned char* data, size_t len, unsigned char* dest)
|
||||
+do_gost12(unsigned char* data, size_t len, unsigned char* dest)
|
||||
{
|
||||
- const EVP_MD* md = EVP_get_digestbyname("md_gost94");
|
||||
+ const EVP_MD* md = EVP_get_digestbyname("md_gost12_256");
|
||||
if(!md)
|
||||
return 0;
|
||||
return sldns_digest_evp(data, (unsigned int)len, dest, md);
|
||||
@@ -302,8 +302,8 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef USE_GOST
|
||||
- case LDNS_HASH_GOST:
|
||||
- if(do_gost94(buf, len, res))
|
||||
+ case LDNS_HASH_GOST12:
|
||||
+ if(do_gost12(buf, len, res))
|
||||
return 1;
|
||||
break;
|
||||
#endif
|
||||
@@ -384,7 +384,7 @@ dnskey_algo_id_is_supported(int id)
|
||||
#endif
|
||||
|
||||
#ifdef USE_GOST
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
/* we support GOST if it can be loaded */
|
||||
return sldns_key_EVP_load_gost_id();
|
||||
#endif
|
||||
@@ -612,17 +612,17 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
|
||||
|
||||
break;
|
||||
#ifdef USE_GOST
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
*evp_key = sldns_gost2pkey_raw(key, keylen);
|
||||
if(!*evp_key) {
|
||||
verbose(VERB_QUERY, "verify: "
|
||||
"sldns_gost2pkey_raw failed");
|
||||
return 0;
|
||||
}
|
||||
- *digest_type = EVP_get_digestbyname("md_gost94");
|
||||
+ *digest_type = EVP_get_digestbyname("md_gost12_256");
|
||||
if(!*digest_type) {
|
||||
verbose(VERB_QUERY, "verify: "
|
||||
- "EVP_getdigest md_gost94 failed");
|
||||
+ "EVP_getdigest md_gost12_256 failed");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@@ -964,7 +964,7 @@ ds_digest_size_supported(int algo)
|
||||
return SHA384_LENGTH;
|
||||
#endif
|
||||
/* GOST not supported in NSS */
|
||||
- case LDNS_HASH_GOST:
|
||||
+ case LDNS_HASH_GOST12:
|
||||
default: break;
|
||||
}
|
||||
return 0;
|
||||
@@ -991,7 +991,7 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
|
||||
return HASH_HashBuf(HASH_AlgSHA384, res, buf, len)
|
||||
== SECSuccess;
|
||||
#endif
|
||||
- case LDNS_HASH_GOST:
|
||||
+ case LDNS_HASH_GOST12:
|
||||
default:
|
||||
verbose(VERB_QUERY, "unknown DS digest algorithm %d",
|
||||
algo);
|
||||
@@ -1031,7 +1031,7 @@ dnskey_algo_id_is_supported(int id)
|
||||
case LDNS_ECDSAP384SHA384:
|
||||
return PK11_TokenExists(CKM_ECDSA);
|
||||
#endif
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -1352,7 +1352,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
|
||||
/* no prefix for DSA verification */
|
||||
break;
|
||||
#endif /* USE_ECDSA */
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
default:
|
||||
verbose(VERB_QUERY, "verify: unknown algorithm %d",
|
||||
algo);
|
||||
@@ -1675,7 +1675,7 @@ ds_digest_size_supported(int algo)
|
||||
return SHA384_DIGEST_SIZE;
|
||||
#endif
|
||||
/* GOST not supported */
|
||||
- case LDNS_HASH_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1700,7 +1700,7 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
|
||||
return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res);
|
||||
|
||||
#endif
|
||||
- case LDNS_HASH_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
default:
|
||||
verbose(VERB_QUERY, "unknown DS digest algorithm %d",
|
||||
algo);
|
||||
@@ -1744,7 +1744,7 @@ dnskey_algo_id_is_supported(int id)
|
||||
return 1;
|
||||
#endif
|
||||
case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -2103,7 +2103,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
|
||||
return sec_status_secure;
|
||||
#endif
|
||||
case LDNS_RSAMD5:
|
||||
- case LDNS_ECC_GOST:
|
||||
+ case LDNS_ECC_GOST12:
|
||||
default:
|
||||
*reason = "unable to verify signature, unknown algorithm";
|
||||
return sec_status_bogus;
|
||||
+8
-8
@@ -2,7 +2,7 @@
|
||||
# and output prometheus metrics style output.
|
||||
# use these options:
|
||||
# server: extended-statistics: yes
|
||||
# statistics-cumulative: no
|
||||
# statistics-cumulative: yes
|
||||
# statistics-interval: 0
|
||||
# remote-control: control-enable: yes
|
||||
# Can use it like unbound-control stats | awk -f "metrics.awk"
|
||||
@@ -17,7 +17,7 @@ BEGIN {
|
||||
# print the output metrics
|
||||
END {
|
||||
print "# HELP unbound_hits_queries Unbound DNS traffic and cache hits"
|
||||
print "# TYPE unbound_hits_queries gauge"
|
||||
print "# TYPE unbound_hits_queries counter"
|
||||
print "unbound_hits_queries{type=\"total.num.queries\"} " val["total.num.queries"];
|
||||
for (x=0; x<99; x++) {
|
||||
if(val["thread" $x ".num.queries"] != "") {
|
||||
@@ -70,7 +70,7 @@ END {
|
||||
print ""
|
||||
|
||||
print "# HELP unbound_by_type_queries Unbound DNS queries by type"
|
||||
print "# TYPE unbound_by_type_queries gauge"
|
||||
print "# TYPE unbound_by_type_queries counter"
|
||||
for(x in val) {
|
||||
if(x ~ /^num.query.type./) {
|
||||
if(val[x] != "") {
|
||||
@@ -82,7 +82,7 @@ END {
|
||||
print ""
|
||||
|
||||
print "# HELP unbound_by_class_queries Unbound DNS queries by class"
|
||||
print "# TYPE unbound_by_class_queries gauge"
|
||||
print "# TYPE unbound_by_class_queries counter"
|
||||
for(x in val) {
|
||||
if(x ~ /^num.query.class./) {
|
||||
if(val[x] != "") {
|
||||
@@ -94,7 +94,7 @@ END {
|
||||
print ""
|
||||
|
||||
print "# HELP unbound_by_opcode_queries Unbound DNS queries by opcode"
|
||||
print "# TYPE unbound_by_opcode_queries gauge"
|
||||
print "# TYPE unbound_by_opcode_queries counter"
|
||||
for(x in val) {
|
||||
if(x ~ /^num.query.opcode./) {
|
||||
if(val[x] != "") {
|
||||
@@ -106,7 +106,7 @@ END {
|
||||
print ""
|
||||
|
||||
print "# HELP unbound_by_rcode_queries Unbound DNS answers by rcode"
|
||||
print "# TYPE unbound_by_rcode_queries gauge"
|
||||
print "# TYPE unbound_by_rcode_queries counter"
|
||||
for(x in val) {
|
||||
if(x ~ /^num.answer.rcode./) {
|
||||
if(val[x] != "") {
|
||||
@@ -118,7 +118,7 @@ END {
|
||||
print ""
|
||||
|
||||
print "# HELP unbound_by_flags_queries Unbound DNS queries by flags"
|
||||
print "# TYPE unbound_by_flags_queries gauge"
|
||||
print "# TYPE unbound_by_flags_queries counter"
|
||||
for(x in val) {
|
||||
if(x ~ /^num.query.flags./) {
|
||||
if(val[x] != "") {
|
||||
@@ -136,7 +136,7 @@ END {
|
||||
print ""
|
||||
|
||||
print "# HELP unbound_histogram_seconds Unbound DNS histogram of reply time"
|
||||
print "# TYPE unbound_histogram_seconds gauge"
|
||||
print "# TYPE unbound_histogram_seconds counter"
|
||||
print "unbound_histogram_seconds{bucket=\"000000.000000.to.000000.000001\"} " val["histogram.000000.000000.to.000000.000001"];
|
||||
print "unbound_histogram_seconds{bucket=\"000000.000001.to.000000.000002\"} " val["histogram.000000.000001.to.000000.000002"];
|
||||
print "unbound_histogram_seconds{bucket=\"000000.000002.to.000000.000004\"} " val["histogram.000000.000002.to.000000.000004"];
|
||||
|
||||
+328
-18
@@ -69,6 +69,7 @@
|
||||
#include "daemon/daemon.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/remote.h"
|
||||
#include "daemon/metrics.h"
|
||||
#include "daemon/acl_list.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
@@ -199,6 +200,244 @@ signal_handling_playback(struct worker* wrk)
|
||||
sig_record_reload = 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
/* setup a listening ssl context, fatal_exit() on any failure */
|
||||
static void
|
||||
setup_listen_sslctx(void** ctx, int is_dot, int is_doh,
|
||||
struct config_file* cfg, char* chroot)
|
||||
{
|
||||
char* key = cfg->ssl_service_key;
|
||||
char* pem = cfg->ssl_service_pem;
|
||||
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
|
||||
key += strlen(chroot);
|
||||
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
|
||||
pem += strlen(chroot);
|
||||
if(!(*ctx = listen_sslctx_create(key, pem, NULL,
|
||||
cfg->tls_ciphers, cfg->tls_ciphersuites,
|
||||
(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0),
|
||||
is_dot, is_doh, cfg->tls_use_system_policy_versions))) {
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
void* daemon_setup_listen_dot_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
void* ctx;
|
||||
(void)setup_listen_sslctx(&ctx, 1, 0, cfg, daemon->chroot);
|
||||
return ctx;
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
void* daemon_setup_listen_doh_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
void* ctx;
|
||||
(void)setup_listen_sslctx(&ctx, 0, 1, cfg, daemon->chroot);
|
||||
return ctx;
|
||||
}
|
||||
#endif /* HAVE_NGHTTP2_NGHTTP2_H */
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef HAVE_NGTCP2
|
||||
void* daemon_setup_listen_quic_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
void* ctx;
|
||||
char* chroot = daemon->chroot;
|
||||
char* key = cfg->ssl_service_key;
|
||||
char* pem = cfg->ssl_service_pem;
|
||||
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
|
||||
key += strlen(chroot);
|
||||
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
|
||||
pem += strlen(chroot);
|
||||
|
||||
if(!(ctx = quic_sslctx_create(key, pem, NULL))) {
|
||||
fatal_exit("could not set up quic SSL_CTX");
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
void* daemon_setup_connect_dot_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
void* ctx;
|
||||
char* bundle, *chroot = daemon->chroot;
|
||||
bundle = cfg->tls_cert_bundle;
|
||||
if(chroot && bundle && strncmp(bundle, chroot, strlen(chroot)) == 0)
|
||||
bundle += strlen(chroot);
|
||||
|
||||
if(!(ctx = connect_sslctx_create(NULL, NULL, bundle,
|
||||
cfg->tls_win_cert)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
return ctx;
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/* setups the needed ssl contexts, fatal_exit() on any failure */
|
||||
void
|
||||
daemon_setup_sslctxs(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
char* chroot = daemon->chroot;
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
char* key = cfg->ssl_service_key;
|
||||
char* pem = cfg->ssl_service_pem;
|
||||
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
|
||||
key += strlen(chroot);
|
||||
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
|
||||
pem += strlen(chroot);
|
||||
|
||||
/* setup the session keys; the callback to use them will be
|
||||
* attached to each sslctx separately */
|
||||
if(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0) {
|
||||
if(!listen_sslctx_setup_ticket_keys(
|
||||
cfg->tls_session_ticket_keys.first, chroot)) {
|
||||
fatal_exit("could not set session ticket SSL_CTX");
|
||||
}
|
||||
}
|
||||
daemon->listen_dot_sslctx = daemon_setup_listen_dot_sslctx(
|
||||
daemon, cfg);
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
if(cfg_has_https(cfg)) {
|
||||
daemon->listen_doh_sslctx =
|
||||
daemon_setup_listen_doh_sslctx(daemon, cfg);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
if(cfg_has_quic(cfg)) {
|
||||
daemon->listen_quic_sslctx =
|
||||
daemon_setup_listen_quic_sslctx(daemon, cfg);
|
||||
}
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
|
||||
/* Store the file name and mtime to detect changes later. */
|
||||
daemon->ssl_service_key = strdup(cfg->ssl_service_key);
|
||||
if(!daemon->ssl_service_key)
|
||||
fatal_exit("could not setup ssl ctx: out of memory");
|
||||
daemon->ssl_service_pem = strdup(cfg->ssl_service_pem);
|
||||
if(!daemon->ssl_service_pem)
|
||||
fatal_exit("could not setup ssl ctx: out of memory");
|
||||
if(!file_get_mtime(key,
|
||||
&daemon->mtime_ssl_service_key,
|
||||
&daemon->mtime_ns_ssl_service_key, NULL))
|
||||
log_err("Could not stat(%s): %s",
|
||||
key, strerror(errno));
|
||||
if(!file_get_mtime(pem,
|
||||
&daemon->mtime_ssl_service_pem,
|
||||
&daemon->mtime_ns_ssl_service_pem, NULL))
|
||||
log_err("Could not stat(%s): %s",
|
||||
pem, strerror(errno));
|
||||
}
|
||||
daemon->connect_dot_sslctx = daemon_setup_connect_dot_sslctx(
|
||||
daemon, cfg);
|
||||
#else /* HAVE_SSL */
|
||||
(void)daemon;(void)cfg;
|
||||
#endif /* HAVE_SSL */
|
||||
}
|
||||
|
||||
/** Delete the ssl ctxs */
|
||||
static void
|
||||
daemon_delete_sslctxs(struct daemon* daemon)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
listen_sslctx_delete_ticket_keys();
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_dot_sslctx);
|
||||
daemon->listen_dot_sslctx = NULL;
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_doh_sslctx);
|
||||
daemon->listen_doh_sslctx = NULL;
|
||||
SSL_CTX_free((SSL_CTX*)daemon->connect_dot_sslctx);
|
||||
daemon->connect_dot_sslctx = NULL;
|
||||
free(daemon->ssl_service_key);
|
||||
daemon->ssl_service_key = NULL;
|
||||
free(daemon->ssl_service_pem);
|
||||
daemon->ssl_service_pem = NULL;
|
||||
#else
|
||||
(void)daemon;
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_quic_sslctx);
|
||||
daemon->listen_quic_sslctx = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
ssl_cert_changed(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
time_t mtime = 0;
|
||||
long ns = 0;
|
||||
char* chroot = daemon->chroot;
|
||||
char* key = cfg->ssl_service_key;
|
||||
char* pem = cfg->ssl_service_pem;
|
||||
log_assert(daemon->ssl_service_key && cfg->ssl_service_key);
|
||||
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
|
||||
key += strlen(chroot);
|
||||
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
|
||||
pem += strlen(chroot);
|
||||
|
||||
if(strcmp(daemon->ssl_service_key, cfg->ssl_service_key) != 0)
|
||||
return 1;
|
||||
if(daemon->ssl_service_pem && cfg->ssl_service_pem &&
|
||||
strcmp(daemon->ssl_service_pem, cfg->ssl_service_pem) != 0)
|
||||
return 1;
|
||||
if(!file_get_mtime(key, &mtime, &ns, NULL)) {
|
||||
log_err("Could not stat(%s): %s",
|
||||
key, strerror(errno));
|
||||
/* It has probably changed, but file read is likely going to
|
||||
* fail. */
|
||||
return 0;
|
||||
}
|
||||
if(mtime != daemon->mtime_ssl_service_key ||
|
||||
ns != daemon->mtime_ns_ssl_service_key)
|
||||
return 1;
|
||||
if(!file_get_mtime(pem, &mtime, &ns, NULL)) {
|
||||
log_err("Could not stat(%s): %s",
|
||||
pem, strerror(errno));
|
||||
/* It has probably changed, but file read is likely going to
|
||||
* fail. */
|
||||
return 0;
|
||||
}
|
||||
if(mtime != daemon->mtime_ssl_service_pem ||
|
||||
ns != daemon->mtime_ns_ssl_service_pem)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Reload the sslctxs if they have changed */
|
||||
static void
|
||||
daemon_reload_sslctxs(struct daemon* daemon)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
if(daemon->cfg->ssl_service_key && daemon->cfg->ssl_service_key[0]) {
|
||||
/* See if changed */
|
||||
if(!daemon->ssl_service_key ||
|
||||
ssl_cert_changed(daemon,daemon->cfg)) {
|
||||
verbose(VERB_ALGO, "Reloading certificates");
|
||||
daemon_delete_sslctxs(daemon);
|
||||
daemon_setup_sslctxs(daemon, daemon->cfg);
|
||||
}
|
||||
} else {
|
||||
/* See if sslctxs are removed from config. */
|
||||
if(daemon->ssl_service_key) {
|
||||
verbose(VERB_ALGO, "Removing certificates");
|
||||
daemon_delete_sslctxs(daemon);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)daemon;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct daemon*
|
||||
daemon_init(void)
|
||||
{
|
||||
@@ -235,7 +474,11 @@ daemon_init(void)
|
||||
# else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
# endif
|
||||
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
|
||||
/* grab the COMP method ptr because openssl leaks it */
|
||||
@@ -244,7 +487,11 @@ daemon_init(void)
|
||||
# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
# else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
# endif
|
||||
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
||||
if(!ub_openssl_lock_init())
|
||||
@@ -301,10 +548,25 @@ daemon_init(void)
|
||||
if(gettimeofday(&daemon->time_boot, NULL) < 0)
|
||||
log_err("gettimeofday: %s", strerror(errno));
|
||||
daemon->time_last_stat = daemon->time_boot;
|
||||
#ifdef USE_METRICS
|
||||
if(!(daemon->metrics = daemon_metrics_create())) {
|
||||
acl_list_delete(daemon->acl_interface);
|
||||
acl_list_delete(daemon->acl);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
daemon->metrics_port = -1;
|
||||
#endif /* USE_METRICS */
|
||||
if((daemon->env->auth_zones = auth_zones_create()) == 0) {
|
||||
acl_list_delete(daemon->acl_interface);
|
||||
acl_list_delete(daemon->acl);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
#ifdef USE_METRICS
|
||||
daemon_metrics_delete(daemon->metrics);
|
||||
#endif
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
@@ -315,6 +577,9 @@ daemon_init(void)
|
||||
acl_list_delete(daemon->acl_interface);
|
||||
acl_list_delete(daemon->acl);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
#ifdef USE_METRICS
|
||||
daemon_metrics_delete(daemon->metrics);
|
||||
#endif
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
@@ -440,6 +705,19 @@ daemon_open_shared_ports(struct daemon* daemon)
|
||||
return 0;
|
||||
daemon->rc_port = daemon->cfg->control_port;
|
||||
}
|
||||
#ifdef USE_METRICS
|
||||
if(!daemon->cfg->metrics_enable && daemon->metrics_port != -1) {
|
||||
daemon_metrics_close_ports(daemon->metrics);
|
||||
daemon->metrics_port = -1;
|
||||
}
|
||||
if(daemon->cfg->metrics_enable &&
|
||||
daemon->cfg->metrics_port != daemon->metrics_port) {
|
||||
daemon_metrics_close_ports(daemon->metrics);
|
||||
if(!daemon_metrics_open_ports(daemon->metrics, daemon->cfg))
|
||||
return 0;
|
||||
daemon->metrics_port = daemon->cfg->metrics_port;
|
||||
}
|
||||
#endif /* USE_METRICS */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -558,9 +836,11 @@ daemon_create_workers(struct daemon* daemon)
|
||||
verbose(VERB_ALGO, "total of %d outgoing ports available", numport);
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
daemon->doq_table = doq_table_create(daemon->cfg, daemon->rand);
|
||||
if(!daemon->doq_table)
|
||||
fatal_exit("could not create doq_table: out of memory");
|
||||
if (cfg_has_quic(daemon->cfg)) {
|
||||
daemon->doq_table = doq_table_create(daemon->cfg, daemon->rand);
|
||||
if(!daemon->doq_table)
|
||||
fatal_exit("could not create doq_table: out of memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1);
|
||||
@@ -631,6 +911,25 @@ static void close_other_pipes(struct daemon* daemon, int thr)
|
||||
}
|
||||
#endif /* THREADS_DISABLED */
|
||||
|
||||
/**
|
||||
* Function to set the thread local log ID.
|
||||
* Either the internal thread number, or the LWP ID on Linux based on
|
||||
* configuration.
|
||||
*/
|
||||
static void
|
||||
set_log_thread_id(struct worker* worker, struct config_file* cfg)
|
||||
{
|
||||
(void)cfg;
|
||||
log_assert(worker);
|
||||
#if defined(HAVE_GETTID) && !defined(THREADS_DISABLED)
|
||||
worker->thread_tid = gettid();
|
||||
if(cfg->log_thread_id)
|
||||
log_thread_set(&worker->thread_tid);
|
||||
else
|
||||
#endif
|
||||
log_thread_set(&worker->thread_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to start one thread.
|
||||
* @param arg: user argument.
|
||||
@@ -641,7 +940,7 @@ thread_start(void* arg)
|
||||
{
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
int port_num = 0;
|
||||
log_thread_set(&worker->thread_num);
|
||||
set_log_thread_id(worker, worker->daemon->cfg);
|
||||
ub_thread_blocksigs();
|
||||
#ifdef THREADS_DISABLED
|
||||
/* close pipe ends used by main */
|
||||
@@ -716,6 +1015,7 @@ daemon_fork(struct daemon* daemon)
|
||||
#endif
|
||||
|
||||
log_assert(daemon);
|
||||
daemon_reload_sslctxs(daemon);
|
||||
if(!(daemon->env->views = views_create()))
|
||||
fatal_exit("Could not create views: out of memory");
|
||||
/* create individual views and their localzone/data trees */
|
||||
@@ -801,9 +1101,19 @@ daemon_fork(struct daemon* daemon)
|
||||
fatal_exit("RPZ requires the respip module");
|
||||
|
||||
/* first create all the worker structures, so we can pass
|
||||
* them to the newly created threads.
|
||||
* them to the newly created threads.
|
||||
*/
|
||||
daemon_create_workers(daemon);
|
||||
/* Set it for the first (main) worker since it does not take part in
|
||||
* the thread_start() procedure.
|
||||
*/
|
||||
set_log_thread_id(daemon->workers[0], daemon->cfg);
|
||||
/* If shm stats need an offset, calculate it */
|
||||
if(daemon->cfg->shm_enable && daemon->cfg->stat_interval > 0) {
|
||||
daemon->stat_time_specific = 1;
|
||||
daemon->stat_time_offset =
|
||||
((int)time(NULL))%daemon->cfg->stat_interval;
|
||||
}
|
||||
|
||||
#if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
|
||||
/* in libev the first inited base gets signals */
|
||||
@@ -893,6 +1203,9 @@ daemon_cleanup(struct daemon* daemon)
|
||||
auth_zones_cleanup(daemon->env->auth_zones);
|
||||
/* key cache is cleared by module deinit during next daemon_fork() */
|
||||
daemon_remote_clear(daemon->rc);
|
||||
#ifdef USE_METRICS
|
||||
daemon_metrics_detach(daemon->metrics);
|
||||
#endif
|
||||
if(daemon->fast_reload_thread)
|
||||
fast_reload_thread_stop(daemon->fast_reload_thread);
|
||||
if(daemon->fast_reload_printq_list)
|
||||
@@ -917,8 +1230,10 @@ daemon_cleanup(struct daemon* daemon)
|
||||
daemon->dnscenv = NULL;
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
doq_table_delete(daemon->doq_table);
|
||||
daemon->doq_table = NULL;
|
||||
if (daemon->doq_table) {
|
||||
doq_table_delete(daemon->doq_table);
|
||||
daemon->doq_table = NULL;
|
||||
}
|
||||
#endif
|
||||
daemon->cfg = NULL;
|
||||
}
|
||||
@@ -933,6 +1248,9 @@ daemon_delete(struct daemon* daemon)
|
||||
modstack_call_destartup(&daemon->mods, daemon->env);
|
||||
modstack_free(&daemon->mods);
|
||||
daemon_remote_delete(daemon->rc);
|
||||
#ifdef USE_METRICS
|
||||
daemon_metrics_delete(daemon->metrics);
|
||||
#endif
|
||||
for(i = 0; i < daemon->num_ports; i++)
|
||||
listening_ports_free(daemon->ports[i]);
|
||||
free(daemon->ports);
|
||||
@@ -956,15 +1274,7 @@ daemon_delete(struct daemon* daemon)
|
||||
free(daemon->pidfile);
|
||||
free(daemon->cfgfile);
|
||||
free(daemon->env);
|
||||
#ifdef HAVE_SSL
|
||||
listen_sslctx_delete_ticket_keys();
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_dot_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_doh_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)daemon->connect_dot_sslctx);
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_quic_sslctx);
|
||||
#endif
|
||||
daemon_delete_sslctxs(daemon);
|
||||
free(daemon);
|
||||
/* lex cleanup */
|
||||
ub_c_lex_destroy();
|
||||
|
||||
@@ -56,6 +56,7 @@ struct local_zones;
|
||||
struct views;
|
||||
struct ub_randstate;
|
||||
struct daemon_remote;
|
||||
struct daemon_metrics;
|
||||
struct respip_set;
|
||||
struct shm_main_info;
|
||||
struct doq_table;
|
||||
@@ -99,6 +100,10 @@ struct daemon {
|
||||
struct listen_port* rc_ports;
|
||||
/** remote control connections management (for first worker) */
|
||||
struct daemon_remote* rc;
|
||||
/** port number for metrics that has ports opened. */
|
||||
int metrics_port;
|
||||
/** metrics endpoint connections management (for first worker) */
|
||||
struct daemon_metrics* metrics;
|
||||
/** ssl context for listening to dnstcp over ssl */
|
||||
void* listen_dot_sslctx;
|
||||
/** ssl context for connecting to dnstcp over ssl */
|
||||
@@ -107,6 +112,18 @@ struct daemon {
|
||||
void* listen_doh_sslctx;
|
||||
/** ssl context for listening to quic */
|
||||
void* listen_quic_sslctx;
|
||||
/** the file name that the ssl context is made with, private key. */
|
||||
char* ssl_service_key;
|
||||
/** the file name that the ssl context is made with, certificate. */
|
||||
char* ssl_service_pem;
|
||||
/** modification time for ssl_service_key, in sec and ns. Like
|
||||
* in a struct timespec, but without that for portability. */
|
||||
time_t mtime_ssl_service_key;
|
||||
long mtime_ns_ssl_service_key;
|
||||
/** modification time for ssl_service_pem, in sec and ns. Like
|
||||
* in a struct timespec, but without that for portability. */
|
||||
time_t mtime_ssl_service_pem;
|
||||
long mtime_ns_ssl_service_pem;
|
||||
/** num threads allocated */
|
||||
int num;
|
||||
/** num threads allocated in the previous config or 0 at first */
|
||||
@@ -143,7 +160,14 @@ struct daemon {
|
||||
/** the dnstap environment master value, copied and changed by threads*/
|
||||
struct dt_env* dtenv;
|
||||
#endif
|
||||
/** The SHM info for shared memory stats. */
|
||||
struct shm_main_info* shm_info;
|
||||
/** if the timeout for statistics is attempted at specific offset.
|
||||
* If it is true, the stat timeout is the interval+offset, and that
|
||||
* picks (roughly) the same time offset every time period. */
|
||||
int stat_time_specific;
|
||||
/** if the timeout is specific, what offset in the period. */
|
||||
int stat_time_offset;
|
||||
/** some response-ip tags or actions are configured if true */
|
||||
int use_response_ip;
|
||||
/** some RPZ policies are configured */
|
||||
@@ -229,4 +253,26 @@ void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg);
|
||||
*/
|
||||
int setup_acl_for_ports(struct acl_list* list, struct listen_port* port_list);
|
||||
|
||||
/* setups the needed ssl contexts, fatal_exit() on any failure */
|
||||
void daemon_setup_sslctxs(struct daemon* daemon, struct config_file* cfg);
|
||||
|
||||
/** See if the SSL cert files have changed */
|
||||
int ssl_cert_changed(struct daemon* daemon, struct config_file* cfg);
|
||||
|
||||
/** Setup the listening DoT SSL_CTX, returns the ssl ctx. */
|
||||
void* daemon_setup_listen_dot_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg);
|
||||
|
||||
/** Setup the listening DoH SSL_CTX, returns the ssl ctx. */
|
||||
void* daemon_setup_listen_doh_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg);
|
||||
|
||||
/** Setup the listening Quic SSL_CTX, returns the ssl ctx */
|
||||
void* daemon_setup_listen_quic_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg);
|
||||
|
||||
/** Setup the connect DoT SSL_CTX, returns the ssl ctx */
|
||||
void* daemon_setup_connect_dot_sslctx(struct daemon* daemon,
|
||||
struct config_file* cfg);
|
||||
|
||||
#endif /* DAEMON_H */
|
||||
|
||||
@@ -0,0 +1,877 @@
|
||||
/*
|
||||
* daemon/metrics.c - prometheus metrics endpoint.
|
||||
*
|
||||
* Copyright (c) 2026, 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
|
||||
*
|
||||
* The statistics output provides metrics to prometheus.
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "daemon/metrics.h"
|
||||
#include "daemon/daemon.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/stats.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/ub_event.h"
|
||||
#include "util/timeval_func.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/rpz.h"
|
||||
#include "sldns/parseutil.h"
|
||||
#include "sldns/wire2str.h"
|
||||
|
||||
/* If there is no metrics enabled, do not add the code. */
|
||||
#ifdef USE_METRICS
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <event2/event.h>
|
||||
#include <event2/http.h>
|
||||
#include <event2/buffer.h>
|
||||
|
||||
/** The prefix for the unbound statistics. */
|
||||
#define METRICS_PREFIX "unbound_"
|
||||
|
||||
/** The callback that handles a metrics http request. */
|
||||
static void metrics_http_callback(struct evhttp_request *req, void *p);
|
||||
|
||||
struct daemon_metrics*
|
||||
daemon_metrics_create(void)
|
||||
{
|
||||
struct daemon_metrics* metrics = (struct daemon_metrics*)calloc(
|
||||
sizeof(*metrics), 1);
|
||||
if(!metrics) {
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
return metrics;
|
||||
}
|
||||
|
||||
void
|
||||
daemon_metrics_delete(struct daemon_metrics* metrics)
|
||||
{
|
||||
if(!metrics) return;
|
||||
daemon_metrics_detach(metrics);
|
||||
daemon_metrics_close_ports(metrics);
|
||||
free(metrics);
|
||||
}
|
||||
|
||||
void
|
||||
daemon_metrics_close_ports(struct daemon_metrics* metrics)
|
||||
{
|
||||
struct metrics_acceptlist *h, *nh;
|
||||
if(!metrics) return;
|
||||
|
||||
/* close listen sockets */
|
||||
h = metrics->accept_list;
|
||||
while(h) {
|
||||
nh = h->next;
|
||||
close(h->accept_fd);
|
||||
free(h->ident);
|
||||
free(h);
|
||||
h = nh;
|
||||
}
|
||||
metrics->accept_list = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
daemon_metrics_detach(struct daemon_metrics* metrics)
|
||||
{
|
||||
if(!metrics) return;
|
||||
if (metrics->http_server) {
|
||||
evhttp_free(metrics->http_server);
|
||||
metrics->http_server = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add and open a new metrics port
|
||||
* @param metrics: metrics with result list.
|
||||
* @param cfg: config options.
|
||||
* @param ip: ip str
|
||||
* @param nr: port nr
|
||||
* @param noproto_is_err: if lack of protocol support is an error.
|
||||
* @return false on failure.
|
||||
*/
|
||||
static int
|
||||
metrics_add_open(struct daemon_metrics* metrics, struct config_file* cfg,
|
||||
const char* ip, int nr, int noproto_is_err)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* res;
|
||||
struct metrics_acceptlist* hl;
|
||||
int noproto = 0;
|
||||
int fd, r;
|
||||
char port[15];
|
||||
snprintf(port, sizeof(port), "%d", nr);
|
||||
port[sizeof(port)-1]=0;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
assert(ip);
|
||||
|
||||
if(ip[0] == '/') {
|
||||
/* This looks like a local socket */
|
||||
fd = create_local_accept_sock(ip, &noproto, cfg->use_systemd);
|
||||
/*
|
||||
* Change socket ownership and permissions so users other
|
||||
* than root can access it provided they are in the same
|
||||
* group as the user we run as.
|
||||
*/
|
||||
if(fd != -1) {
|
||||
#ifdef HAVE_CHOWN
|
||||
if(chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) == -1) {
|
||||
verbose(VERB_QUERY, "cannot chmod metrics socket %s: %s", ip, strerror(errno));
|
||||
}
|
||||
if (cfg->username && cfg->username[0] &&
|
||||
cfg_uid != (uid_t)-1) {
|
||||
if(chown(ip, cfg_uid, cfg_gid) == -1)
|
||||
verbose(VERB_QUERY, "cannot chown metrics socket %u.%u %s: %s",
|
||||
(unsigned)cfg_uid, (unsigned)cfg_gid,
|
||||
ip, strerror(errno));
|
||||
}
|
||||
#else
|
||||
(void)cfg;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
char* s = strchr(ip, '@');
|
||||
char newif[128];
|
||||
if(s) {
|
||||
/* override port with ifspec@port */
|
||||
int portnr;
|
||||
if((size_t)(s-ip) >= sizeof(newif)) {
|
||||
log_err("ifname too long: %s", ip);
|
||||
return -1;
|
||||
}
|
||||
portnr = atoi(s+1);
|
||||
if(portnr < 0 || 0 == portnr || portnr > 65535) {
|
||||
log_err("invalid portnumber in metrics-interface: %s", ip);
|
||||
return -1;
|
||||
}
|
||||
(void)strlcpy(newif, ip, sizeof(newif));
|
||||
newif[s-ip] = 0;
|
||||
ip = newif;
|
||||
snprintf(port, sizeof(port), "%d", portnr);
|
||||
port[sizeof(port)-1]=0;
|
||||
}
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
|
||||
/* if we had no interface ip name, "default" is what we
|
||||
* would do getaddrinfo for. */
|
||||
if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
|
||||
#ifdef USE_WINSOCK
|
||||
if(!noproto_is_err && r == EAI_NONAME) {
|
||||
/* tried to lookup the address as name */
|
||||
return 1; /* return success, but do nothing */
|
||||
}
|
||||
#endif /* USE_WINSOCK */
|
||||
log_err("metrics interface %s:%s getaddrinfo: %s %s",
|
||||
ip, port, gai_strerror(r),
|
||||
#ifdef EAI_SYSTEM
|
||||
r==EAI_SYSTEM?(char*)strerror(errno):""
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* open fd */
|
||||
fd = create_tcp_accept_sock(res, 1, &noproto, 0,
|
||||
cfg->ip_transparent, 0, 0, cfg->ip_freebind,
|
||||
cfg->use_systemd, cfg->ip_dscp, "metrics");
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
|
||||
if(fd == -1 && noproto) {
|
||||
if(!noproto_is_err)
|
||||
return 1; /* return success, but do nothing */
|
||||
log_err("cannot open metrics interface %s %d : "
|
||||
"protocol not supported", ip, nr);
|
||||
return 0;
|
||||
}
|
||||
if(fd == -1) {
|
||||
log_err("cannot open metrics interface %s %d", ip, nr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* alloc */
|
||||
hl = (struct metrics_acceptlist*)calloc(1, sizeof(*hl));
|
||||
if(!hl) {
|
||||
sock_close(fd);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
hl->metrics = metrics;
|
||||
hl->ident = strdup(ip);
|
||||
if(!hl->ident) {
|
||||
log_err("out of memory");
|
||||
sock_close(fd);
|
||||
free(hl);
|
||||
return 0;
|
||||
}
|
||||
hl->next = metrics->accept_list;
|
||||
metrics->accept_list = hl;
|
||||
|
||||
hl->accept_fd = fd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
daemon_metrics_open_ports(struct daemon_metrics* metrics,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
assert(cfg->metrics_enable);
|
||||
if(!cfg->stat_cumulative)
|
||||
log_warn("metrics-enable: yes but statistics-cumulative: no, access to control command 'stats' would reset the stat counters, perhaps set 'statistics-cumulative: yes'.");
|
||||
if(cfg->metrics_ifs.first) {
|
||||
char** rcif = NULL;
|
||||
int i, num_rcif = 0;
|
||||
if(!resolve_interface_names(NULL, 0, cfg->metrics_ifs.first,
|
||||
&rcif, &num_rcif)) {
|
||||
return 0;
|
||||
}
|
||||
for(i=0; i<num_rcif; i++) {
|
||||
if(!metrics_add_open(metrics, cfg, rcif[i],
|
||||
cfg->metrics_port, 1)) {
|
||||
config_del_strarray(rcif, num_rcif);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
config_del_strarray(rcif, num_rcif);
|
||||
} else {
|
||||
/* defaults */
|
||||
if(cfg->do_ip6 && !metrics_add_open(metrics, cfg, "::1",
|
||||
cfg->metrics_port, 0)) {
|
||||
return 0;
|
||||
}
|
||||
if(cfg->do_ip4 &&
|
||||
!metrics_add_open(metrics, cfg, "127.0.0.1",
|
||||
cfg->metrics_port, 1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
daemon_metrics_attach(struct daemon_metrics* metrics, struct worker* worker)
|
||||
{
|
||||
int fd;
|
||||
struct metrics_acceptlist* p;
|
||||
if(!metrics) return 1;
|
||||
metrics->worker = worker;
|
||||
if(!metrics->accept_list)
|
||||
return 1;
|
||||
|
||||
metrics->http_server = evhttp_new(ub_libevent_get_event_base(
|
||||
comm_base_internal(worker->base)));
|
||||
if(!metrics->http_server) {
|
||||
log_err("out of memory, evhttp_new failed");
|
||||
return 0;
|
||||
}
|
||||
for(p = metrics->accept_list; p; p = p->next) {
|
||||
fd = p->accept_fd;
|
||||
if (evhttp_accept_socket(metrics->http_server, fd)) {
|
||||
log_err("metrics: cannot set http server to accept socket");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* only handle requests to metrics_path, anything else returns 404 */
|
||||
evhttp_set_cb(metrics->http_server,
|
||||
worker->daemon->cfg->metrics_path,
|
||||
metrics_http_callback, p);
|
||||
/* evhttp_set_gencb(metrics->http_server, metrics_http_callback_generic, p); */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Add help and type printout of a metric. */
|
||||
static void
|
||||
print_metric_help_and_type(struct evbuffer *buf, char *prefix, char *name,
|
||||
char *help, char *type)
|
||||
{
|
||||
evbuffer_add_printf(buf, "# HELP %s%s %s\n# TYPE %s%s %s\n",
|
||||
prefix, name, help, prefix, name, type);
|
||||
}
|
||||
|
||||
/* print help and type for main list of metrics */
|
||||
static int
|
||||
metrics_print_types(struct evbuffer *reply)
|
||||
{
|
||||
char* prefix = METRICS_PREFIX;
|
||||
print_metric_help_and_type(reply, prefix, "hits_queries",
|
||||
"Unbound DNS traffic and cache hits", "counter");
|
||||
print_metric_help_and_type(reply, prefix, "queue_queries",
|
||||
"Unbound requestlist size", "gauge");
|
||||
print_metric_help_and_type(reply, prefix, "recursion_time",
|
||||
"Unbound recursion time, in seconds", "gauge");
|
||||
print_metric_help_and_type(reply, prefix, "query_queue_time",
|
||||
"Unbound query queue time, in msec", "gauge");
|
||||
print_metric_help_and_type(reply, prefix, "socket_count",
|
||||
"Unbound socket count", "gauge");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* metrics print of stat block */
|
||||
static int
|
||||
metrics_print_stats(struct evbuffer* reply, const char* nm,
|
||||
struct ub_stats_info* s)
|
||||
{
|
||||
char* prefix = METRICS_PREFIX;
|
||||
struct timeval sumwait, avg;
|
||||
|
||||
/* print to reply buffer the stat for prefix mt
|
||||
* of type nm.snm and long long output svar. */
|
||||
#define INFO_STATS(mt, snm, svar) \
|
||||
evbuffer_add_printf(reply, \
|
||||
"%s" mt "{type=\"%s." snm "\"} " ARG_LL "d\n", \
|
||||
prefix, nm, (long long)(svar))
|
||||
|
||||
INFO_STATS("hits_queries", "num.queries", s->svr.num_queries);
|
||||
INFO_STATS("hits_queries", "num.queries_ip_ratelimited",
|
||||
s->svr.num_queries_ip_ratelimited);
|
||||
INFO_STATS("hits_queries", "num.queries_cookie_valid",
|
||||
s->svr.num_queries_cookie_valid);
|
||||
INFO_STATS("hits_queries", "num.queries_cookie_client",
|
||||
s->svr.num_queries_cookie_client);
|
||||
INFO_STATS("hits_queries", "num.queries_cookie_invalid",
|
||||
s->svr.num_queries_cookie_invalid);
|
||||
INFO_STATS("hits_queries", "num.queries_discard_timeout",
|
||||
s->svr.num_queries_discard_timeout);
|
||||
INFO_STATS("hits_queries", "num.queries_replyaddr_limit",
|
||||
s->svr.num_queries_replyaddr_limit);
|
||||
INFO_STATS("hits_queries", "num.queries_wait_limit",
|
||||
s->svr.num_queries_wait_limit);
|
||||
INFO_STATS("hits_queries", "num.cachehits",
|
||||
s->svr.num_queries - s->svr.num_queries_missed_cache);
|
||||
INFO_STATS("hits_queries", "num.cachemiss",
|
||||
s->svr.num_queries_missed_cache);
|
||||
INFO_STATS("hits_queries", "num.prefetch",
|
||||
s->svr.num_queries_prefetch);
|
||||
INFO_STATS("hits_queries", "num.queries_timed_out",
|
||||
s->svr.num_queries_timed_out);
|
||||
INFO_STATS("hits_queries", "num.expired", s->svr.ans_expired);
|
||||
INFO_STATS("hits_queries", "num.recursivereplies",
|
||||
s->mesh_replies_sent);
|
||||
#ifdef USE_DNSCRYPT
|
||||
INFO_STATS("hits_queries", "num.dnscrypt.crypted",
|
||||
s->svr.num_query_dnscrypt_crypted);
|
||||
INFO_STATS("hits_queries", "num.dnscrypt.cert",
|
||||
s->svr.num_query_dnscrypt_cert);
|
||||
INFO_STATS("hits_queries", "num.dnscrypt.cleartext",
|
||||
s->svr.num_query_dnscrypt_cleartext);
|
||||
INFO_STATS("hits_queries", "num.dnscrypt.malformed",
|
||||
s->svr.num_query_dnscrypt_crypted_malformed);
|
||||
#endif
|
||||
INFO_STATS("hits_queries", "num.dns_error_reports",
|
||||
s->svr.num_dns_error_reports);
|
||||
|
||||
evbuffer_add_printf(reply,
|
||||
"%squeue_queries{type=\"%s.requestlist.avg\"} %g\n",
|
||||
prefix, nm,
|
||||
(s->svr.num_queries_missed_cache+s->svr.num_queries_prefetch)?
|
||||
(double)s->svr.sum_query_list_size/
|
||||
(double)(s->svr.num_queries_missed_cache+
|
||||
s->svr.num_queries_prefetch) : 0.0);
|
||||
INFO_STATS("queue_queries", "requestlist.max",
|
||||
s->svr.max_query_list_size);
|
||||
INFO_STATS("queue_queries", "requestlist.overwritten",
|
||||
s->mesh_jostled);
|
||||
INFO_STATS("queue_queries", "requestlist.exceeded",
|
||||
s->mesh_dropped);
|
||||
INFO_STATS("queue_queries", "requestlist.current.all",
|
||||
s->mesh_num_states);
|
||||
INFO_STATS("queue_queries", "requestlist.current.user",
|
||||
s->mesh_num_reply_states);
|
||||
INFO_STATS("queue_queries", "requestlist.current.replies",
|
||||
s->mesh_num_reply_addrs);
|
||||
|
||||
sumwait.tv_sec = s->mesh_replies_sum_wait_sec;
|
||||
sumwait.tv_usec = s->mesh_replies_sum_wait_usec;
|
||||
timeval_divide(&avg, &sumwait, s->mesh_replies_sent);
|
||||
evbuffer_add_printf(reply,
|
||||
"%srecursion_time{type=\"%s.recursion.time.avg\"} " ARG_LL
|
||||
"d.%6.6d\n", prefix, nm,
|
||||
(long long)avg.tv_sec, (int)avg.tv_usec);
|
||||
evbuffer_add_printf(reply,
|
||||
"%srecursion_time{type=\"%s.recursion.time.median\"} %g\n",
|
||||
prefix, nm, s->mesh_time_median);
|
||||
|
||||
INFO_STATS("query_queue_time", "query.queue_time_us.max",
|
||||
s->svr.max_query_time_us);
|
||||
|
||||
INFO_STATS("socket_count", "tcpusage", s->svr.tcp_accept_usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* metrics print of thread stats */
|
||||
static int
|
||||
metrics_print_thread_stats(struct evbuffer* reply, int i,
|
||||
struct ub_stats_info* s)
|
||||
{
|
||||
char nm[32];
|
||||
snprintf(nm, sizeof(nm), "thread%d", i);
|
||||
nm[sizeof(nm)-1]=0;
|
||||
return metrics_print_stats(reply, nm, s);
|
||||
}
|
||||
|
||||
/* metrics print of uptime stats */
|
||||
static int
|
||||
metrics_print_uptime(struct evbuffer* reply, struct worker* worker,
|
||||
struct timeval* stattime, struct timeval* time_last_stat)
|
||||
{
|
||||
char* prefix = METRICS_PREFIX;
|
||||
struct timeval up, dt;
|
||||
timeval_subtract(&up, stattime, &worker->daemon->time_boot);
|
||||
timeval_subtract(&dt, stattime, time_last_stat);
|
||||
|
||||
print_metric_help_and_type(reply, prefix, "time_now_seconds",
|
||||
"Time of the statistics printout, in seconds.", "untyped");
|
||||
evbuffer_add_printf(reply, "%stime_now_seconds " ARG_LL "d.%6.6u\n",
|
||||
prefix, (long long)stattime->tv_sec,
|
||||
(unsigned)stattime->tv_usec);
|
||||
|
||||
print_metric_help_and_type(reply, prefix, "time_up_seconds_total",
|
||||
"Uptime since server boot in seconds.", "counter");
|
||||
evbuffer_add_printf(reply,
|
||||
"%stime_up_seconds_total " ARG_LL "d.%6.6u\n",
|
||||
prefix, (long long)up.tv_sec, (unsigned)up.tv_usec);
|
||||
|
||||
print_metric_help_and_type(reply, prefix, "time_elapsed_seconds",
|
||||
"Time since last statistics printout and "
|
||||
"reset (by unbound-control stats) in seconds.",
|
||||
"untyped");
|
||||
evbuffer_add_printf(reply,
|
||||
"%stime_elapsed_seconds " ARG_LL "d.%6.6u\n",
|
||||
prefix, (long long)dt.tv_sec, (unsigned)dt.tv_usec);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** metrics print of mem stats */
|
||||
static int
|
||||
metrics_print_mem(struct evbuffer* reply, struct worker* worker,
|
||||
struct ub_stats_info* s)
|
||||
{
|
||||
char* prefix = METRICS_PREFIX;
|
||||
struct ub_mem_stat_info mem;
|
||||
stats_get_mem_info(worker, &mem);
|
||||
|
||||
/* print to reply buffer the stat for prefix mt
|
||||
* of type snm and long long output svar. */
|
||||
#define INFO_LL_STATS(mt, snm, svar) \
|
||||
evbuffer_add_printf(reply, \
|
||||
"%s" mt "{type=\"" snm "\"} " ARG_LL "d\n", \
|
||||
prefix, (long long)(svar))
|
||||
|
||||
print_metric_help_and_type(reply, prefix, "memory_bytes",
|
||||
"Unbound memory usage, in bytes", "gauge");
|
||||
INFO_LL_STATS("memory_bytes", "mem.cache.rrset", mem.rrset);
|
||||
INFO_LL_STATS("memory_bytes", "mem.cache.message", mem.msg);
|
||||
INFO_LL_STATS("memory_bytes", "mem.mod.iterator", mem.iter);
|
||||
INFO_LL_STATS("memory_bytes", "mem.mod.validator", mem.val);
|
||||
INFO_LL_STATS("memory_bytes", "mem.mod.respip", mem.respip);
|
||||
#ifdef CLIENT_SUBNET
|
||||
INFO_LL_STATS("memory_bytes", "mem.mod.subnet", mem.subnet);
|
||||
#endif /* CLIENT_SUBNET */
|
||||
#ifdef USE_IPSECMOD
|
||||
INFO_LL_STATS("memory_bytes", "mem.mod.ipsecmod", mem.ipsecmod);
|
||||
#endif /* USE_IPSECMOD */
|
||||
#ifdef USE_DNSCRYPT
|
||||
INFO_LL_STATS("memory_bytes", "mem.cache.dnscrypt_shared_secret",
|
||||
mem.dnscrypt_shared_secret);
|
||||
INFO_LL_STATS("memory_bytes", "mem.cache.dnscrypt_nonce",
|
||||
mem.dnscrypt_nonce);
|
||||
#endif /* USE_DNSCRYPT */
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
INFO_LL_STATS("memory_bytes", "mem.mod.dynlibmod", mem.dynlib);
|
||||
#endif /* WITH_DYNLIBMODULE */
|
||||
INFO_LL_STATS("memory_bytes", "mem.streamwait",
|
||||
s->svr.mem_stream_wait);
|
||||
INFO_LL_STATS("memory_bytes", "mem.http.query_buffer",
|
||||
s->svr.mem_http2_query_buffer);
|
||||
INFO_LL_STATS("memory_bytes", "mem.http.response_buffer",
|
||||
s->svr.mem_http2_response_buffer);
|
||||
#ifdef HAVE_NGTCP2
|
||||
INFO_LL_STATS("memory_bytes", "mem.quic", s->svr.mem_quic);
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* metrics print of histogram */
|
||||
static int
|
||||
metrics_print_hist(struct evbuffer* reply, struct ub_stats_info* s)
|
||||
{
|
||||
char* prefix = METRICS_PREFIX;
|
||||
struct timehist* hist;
|
||||
size_t i;
|
||||
|
||||
print_metric_help_and_type(reply, prefix, "histogram_seconds",
|
||||
"Unbound DNS histogram of reply time", "counter");
|
||||
|
||||
hist = timehist_setup();
|
||||
if(!hist) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
timehist_import(hist, s->svr.hist, NUM_BUCKETS_HIST);
|
||||
for(i=0; i<hist->num; i++) {
|
||||
evbuffer_add_printf(reply, "%shistogram_seconds"
|
||||
"{bucket=\"%6.6d.%6.6d.to.%6.6d.%6.6d\"} %lu\n",
|
||||
prefix,
|
||||
(int)hist->buckets[i].lower.tv_sec,
|
||||
(int)hist->buckets[i].lower.tv_usec,
|
||||
(int)hist->buckets[i].upper.tv_sec,
|
||||
(int)hist->buckets[i].upper.tv_usec,
|
||||
(unsigned long)hist->buckets[i].count);
|
||||
}
|
||||
timehist_delete(hist);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* metrics print of extended stats */
|
||||
static int
|
||||
metrics_print_ext(struct evbuffer* reply, struct ub_stats_info* s,
|
||||
int inhibit_zero)
|
||||
{
|
||||
char* prefix = METRICS_PREFIX;
|
||||
int i;
|
||||
char nm[32];
|
||||
const sldns_rr_descriptor* desc;
|
||||
const sldns_lookup_table* lt;
|
||||
|
||||
/* Print stats for metric mt, where type 'sortnm' is "snm" string,
|
||||
* with value svar. */
|
||||
#define INFO_EXT_STATS(mt, sortnm, snm, svar) \
|
||||
evbuffer_add_printf(reply, "%s%s{%s=\"%s\"} " ARG_LL "d\n", \
|
||||
prefix, mt, sortnm, snm, svar);
|
||||
|
||||
/* TYPE */
|
||||
print_metric_help_and_type(reply, prefix, "by_type_queries",
|
||||
"Unbound DNS queries by type", "counter");
|
||||
for(i=0; i<UB_STATS_QTYPE_NUM; i++) {
|
||||
if(inhibit_zero && s->svr.qtype[i] == 0)
|
||||
continue;
|
||||
desc = sldns_rr_descript((uint16_t)i);
|
||||
if(desc && desc->_name) {
|
||||
snprintf(nm, sizeof(nm), "%s", desc->_name);
|
||||
} else if (i == LDNS_RR_TYPE_IXFR) {
|
||||
snprintf(nm, sizeof(nm), "IXFR");
|
||||
} else if (i == LDNS_RR_TYPE_AXFR) {
|
||||
snprintf(nm, sizeof(nm), "AXFR");
|
||||
} else if (i == LDNS_RR_TYPE_MAILA) {
|
||||
snprintf(nm, sizeof(nm), "MAILA");
|
||||
} else if (i == LDNS_RR_TYPE_MAILB) {
|
||||
snprintf(nm, sizeof(nm), "MAILB");
|
||||
} else if (i == LDNS_RR_TYPE_ANY) {
|
||||
snprintf(nm, sizeof(nm), "ANY");
|
||||
} else {
|
||||
snprintf(nm, sizeof(nm), "TYPE%d", i);
|
||||
}
|
||||
INFO_EXT_STATS("by_type_queries", "type", nm, s->svr.qtype[i]);
|
||||
}
|
||||
if(!inhibit_zero || s->svr.qtype_big) {
|
||||
INFO_EXT_STATS("by_type_queries", "type", "other",
|
||||
s->svr.qtype_big);
|
||||
}
|
||||
|
||||
/* CLASS */
|
||||
print_metric_help_and_type(reply, prefix, "by_class_queries",
|
||||
"Unbound DNS queries by class", "counter");
|
||||
for(i=0; i<UB_STATS_QCLASS_NUM; i++) {
|
||||
if(inhibit_zero && s->svr.qclass[i] == 0)
|
||||
continue;
|
||||
lt = sldns_lookup_by_id(sldns_rr_classes, i);
|
||||
if(lt && lt->name) {
|
||||
snprintf(nm, sizeof(nm), "%s", lt->name);
|
||||
} else {
|
||||
snprintf(nm, sizeof(nm), "CLASS%d", i);
|
||||
}
|
||||
INFO_EXT_STATS("by_class_queries", "class", nm,
|
||||
s->svr.qclass[i]);
|
||||
}
|
||||
if(!inhibit_zero || s->svr.qclass_big) {
|
||||
INFO_EXT_STATS("by_class_queries", "class", "other",
|
||||
s->svr.qclass_big);
|
||||
}
|
||||
|
||||
/* OPCODE */
|
||||
print_metric_help_and_type(reply, prefix, "by_opcode_queries",
|
||||
"Unbound DNS queries by opcode", "counter");
|
||||
for(i=0; i<UB_STATS_OPCODE_NUM; i++) {
|
||||
if(inhibit_zero && s->svr.qopcode[i] == 0)
|
||||
continue;
|
||||
lt = sldns_lookup_by_id(sldns_opcodes, i);
|
||||
if(lt && lt->name) {
|
||||
snprintf(nm, sizeof(nm), "%s", lt->name);
|
||||
} else {
|
||||
snprintf(nm, sizeof(nm), "OPCODE%d", i);
|
||||
}
|
||||
INFO_EXT_STATS("by_opcode_queries", "opcode", nm,
|
||||
s->svr.qopcode[i]);
|
||||
}
|
||||
|
||||
/* RCODE */
|
||||
print_metric_help_and_type(reply, prefix, "by_rcode_queries",
|
||||
"Unbound DNS answers by rcode", "counter");
|
||||
for(i=0; i<UB_STATS_RCODE_NUM; i++) {
|
||||
/* Always include RCODEs 0-5 */
|
||||
if(inhibit_zero && i > LDNS_RCODE_REFUSED && s->svr.ans_rcode[i] == 0)
|
||||
continue;
|
||||
lt = sldns_lookup_by_id(sldns_rcodes, i);
|
||||
if(lt && lt->name) {
|
||||
snprintf(nm, sizeof(nm), "%s", lt->name);
|
||||
} else {
|
||||
snprintf(nm, sizeof(nm), "RCODE%d", i);
|
||||
}
|
||||
INFO_EXT_STATS("by_rcode_queries", "rcode", nm,
|
||||
s->svr.ans_rcode[i]);
|
||||
}
|
||||
if(!inhibit_zero || s->svr.ans_rcode_nodata) {
|
||||
INFO_EXT_STATS("by_rcode_queries", "rcode", "nodata",
|
||||
s->svr.ans_rcode_nodata);
|
||||
}
|
||||
|
||||
/* FLAGS */
|
||||
print_metric_help_and_type(reply, prefix, "by_flags_queries",
|
||||
"Unbound DNS queries by flags", "counter");
|
||||
INFO_EXT_STATS("by_flags_queries", "flag", "QR", s->svr.qbit_QR);
|
||||
INFO_EXT_STATS("by_flags_queries", "flag", "AA", s->svr.qbit_AA);
|
||||
INFO_EXT_STATS("by_flags_queries", "flag", "TC", s->svr.qbit_TC);
|
||||
INFO_EXT_STATS("by_flags_queries", "flag", "RD", s->svr.qbit_RD);
|
||||
INFO_EXT_STATS("by_flags_queries", "flag", "RA", s->svr.qbit_RA);
|
||||
INFO_EXT_STATS("by_flags_queries", "flag", "Z", s->svr.qbit_Z);
|
||||
INFO_EXT_STATS("by_flags_queries", "flag", "AD", s->svr.qbit_AD);
|
||||
INFO_EXT_STATS("by_flags_queries", "flag", "CD", s->svr.qbit_CD);
|
||||
INFO_EXT_STATS("by_flags_queries", "flag", "edns.present",
|
||||
s->svr.qEDNS);
|
||||
INFO_EXT_STATS("by_flags_queries", "flag", "edns.DO",
|
||||
s->svr.qEDNS_DO);
|
||||
|
||||
/* transport */
|
||||
print_metric_help_and_type(reply, prefix, "by_transport_queries",
|
||||
"Unbound DNS queries by transport", "counter");
|
||||
INFO_EXT_STATS("by_transport_queries", "transport", "tcp",
|
||||
s->svr.qtcp);
|
||||
INFO_EXT_STATS("by_transport_queries", "transport", "tcpout",
|
||||
s->svr.qtcp_outgoing);
|
||||
INFO_EXT_STATS("by_transport_queries", "transport", "udpout",
|
||||
s->svr.qudp_outgoing);
|
||||
INFO_EXT_STATS("by_transport_queries", "transport", "tls",
|
||||
s->svr.qtls);
|
||||
INFO_EXT_STATS("by_transport_queries", "transport", "tls.resume",
|
||||
s->svr.qtls_resume);
|
||||
INFO_EXT_STATS("by_transport_queries", "transport", "ipv6",
|
||||
s->svr.qipv6);
|
||||
INFO_EXT_STATS("by_transport_queries", "transport", "https",
|
||||
s->svr.qhttps);
|
||||
#ifdef HAVE_NGTCP2
|
||||
INFO_EXT_STATS("by_transport_queries", "transport", "quic",
|
||||
s->svr.qquic);
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
|
||||
/* iteration */
|
||||
print_metric_help_and_type(reply, prefix, "ratelimited_queries",
|
||||
"Unbound DNS queries ratelimited", "counter");
|
||||
INFO_EXT_STATS("ratelimited_queries", "type", "ratelimited",
|
||||
s->svr.queries_ratelimited);
|
||||
|
||||
/* validation */
|
||||
print_metric_help_and_type(reply, prefix, "validation_queries",
|
||||
"Unbound DNS queries DNSSEC validated", "counter");
|
||||
INFO_EXT_STATS("validation_queries", "type", "secure",
|
||||
s->svr.ans_secure);
|
||||
INFO_EXT_STATS("validation_queries", "type", "bogus",
|
||||
s->svr.ans_bogus);
|
||||
INFO_EXT_STATS("validation_queries", "type", "rrset.bogus",
|
||||
s->svr.rrset_bogus);
|
||||
INFO_EXT_STATS("validation_queries", "type", "valops",
|
||||
s->svr.val_ops);
|
||||
INFO_EXT_STATS("validation_queries", "type", "aggressive.NOERROR",
|
||||
s->svr.num_neg_cache_noerror);
|
||||
INFO_EXT_STATS("validation_queries", "type", "aggressive.NXDOMAIN",
|
||||
s->svr.num_neg_cache_nxdomain);
|
||||
|
||||
/* threat detection */
|
||||
print_metric_help_and_type(reply, prefix, "threat_queries",
|
||||
"Unbound DNS queries threats", "counter");
|
||||
INFO_EXT_STATS("threat_queries", "type", "unwanted.queries",
|
||||
s->svr.unwanted_queries);
|
||||
INFO_EXT_STATS("threat_queries", "type", "unwanted.replies",
|
||||
s->svr.unwanted_replies);
|
||||
|
||||
/* cache counts */
|
||||
print_metric_help_and_type(reply, prefix, "cache_items",
|
||||
"Unbound DNS cache counts", "gauge");
|
||||
INFO_EXT_STATS("cache_items", "count", "msg.cache",
|
||||
s->svr.msg_cache_count);
|
||||
INFO_EXT_STATS("cache_items", "count", "rrset.cache",
|
||||
s->svr.rrset_cache_count);
|
||||
INFO_EXT_STATS("cache_items", "count", "infra.cache",
|
||||
s->svr.infra_cache_count);
|
||||
INFO_EXT_STATS("cache_items", "count", "key.cache",
|
||||
s->svr.key_cache_count);
|
||||
|
||||
/* max collisions */
|
||||
INFO_EXT_STATS("cache_items", "count", "msg.cache.max_collisions",
|
||||
s->svr.msg_cache_max_collisions);
|
||||
INFO_EXT_STATS("cache_items", "count", "rrset.cache.max_collisions",
|
||||
s->svr.rrset_cache_max_collisions);
|
||||
|
||||
/* applied RPZ actions */
|
||||
print_metric_help_and_type(reply, prefix, "rpz_actions",
|
||||
"Unbound DNS RPZ actions", "counter");
|
||||
for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++) {
|
||||
if(i == RPZ_NO_OVERRIDE_ACTION)
|
||||
continue;
|
||||
if(inhibit_zero && s->svr.rpz_action[i] == 0)
|
||||
continue;
|
||||
INFO_EXT_STATS("rpz_actions", "action",
|
||||
rpz_action_to_string(i), s->svr.rpz_action[i]);
|
||||
}
|
||||
|
||||
/* handling mechanism */
|
||||
print_metric_help_and_type(reply, prefix, "handled_queries",
|
||||
"Unbound DNS queries by handling mechanism", "counter");
|
||||
#ifdef USE_DNSCRYPT
|
||||
INFO_EXT_STATS("cache_items", "count", "dnscrypt_shared_secret.cache",
|
||||
s->svr.shared_secret_cache_count);
|
||||
INFO_EXT_STATS("cache_items", "count", "dnscrypt_nonce.cache",
|
||||
s->svr.nonce_cache_count);
|
||||
INFO_EXT_STATS("handled_queries", "type",
|
||||
"dnscrypt.shared_secret.cachemiss",
|
||||
s->svr.num_query_dnscrypt_secret_missed_cache);
|
||||
INFO_EXT_STATS("handled_queries", "type", "dnscrypt.replay",
|
||||
s->svr.num_query_dnscrypt_replay);
|
||||
#endif /* USE_DNSCRYPT */
|
||||
INFO_EXT_STATS("handled_queries", "type", "authzone.up",
|
||||
s->svr.num_query_authzone_up);
|
||||
INFO_EXT_STATS("handled_queries", "type", "authzone.down",
|
||||
s->svr.num_query_authzone_down);
|
||||
#ifdef CLIENT_SUBNET
|
||||
INFO_EXT_STATS("handled_queries", "type", "subnet",
|
||||
s->svr.num_query_subnet);
|
||||
INFO_EXT_STATS("handled_queries", "type", "subnet_cache",
|
||||
s->svr.num_query_subnet_cache);
|
||||
#endif /* CLIENT_SUBNET */
|
||||
#ifdef USE_CACHEDB
|
||||
INFO_EXT_STATS("handled_queries", "type", "cachedb",
|
||||
s->svr.num_query_cachedb);
|
||||
#endif /* USE_CACHEDB */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* process statistics */
|
||||
static void
|
||||
do_metrics_stats(struct evbuffer* reply, struct worker* worker, int reset)
|
||||
{
|
||||
struct daemon* daemon = worker->daemon;
|
||||
struct ub_stats_info total;
|
||||
struct ub_stats_info s;
|
||||
int i;
|
||||
struct timeval stattime, time_last_stat;
|
||||
|
||||
memset(&total, 0, sizeof(total));
|
||||
log_assert(daemon->num > 0);
|
||||
|
||||
if(!metrics_print_types(reply))
|
||||
return;
|
||||
|
||||
/* gather all thread statistics in one place */
|
||||
for(i=0; i<daemon->num; i++) {
|
||||
server_stats_obtain(worker, daemon->workers[i], &s, reset);
|
||||
if(!metrics_print_thread_stats(reply, i, &s))
|
||||
return;
|
||||
if(i == 0)
|
||||
total = s;
|
||||
else server_stats_add(&total, &s);
|
||||
}
|
||||
total.mesh_time_median /= (double)daemon->num;
|
||||
if(gettimeofday(&stattime, NULL) < 0)
|
||||
log_err("gettimeofday: %s", strerror(errno));
|
||||
time_last_stat = worker->daemon->time_last_stat;
|
||||
if(reset) {
|
||||
worker->daemon->time_last_stat = stattime;
|
||||
}
|
||||
|
||||
/* print the statistics */
|
||||
if(!metrics_print_stats(reply, "total", &total))
|
||||
return;
|
||||
if(!metrics_print_uptime(reply, worker, &stattime, &time_last_stat))
|
||||
return;
|
||||
if(daemon->cfg->stat_extended) {
|
||||
if(!metrics_print_mem(reply, worker, &total))
|
||||
return;
|
||||
if(!metrics_print_hist(reply, &total))
|
||||
return;
|
||||
if(!metrics_print_ext(reply, &total,
|
||||
daemon->cfg->stat_inhibit_zero))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Callback for handling the active http request to the specific URI */
|
||||
static void
|
||||
metrics_http_callback(struct evhttp_request *req, void *p)
|
||||
{
|
||||
struct evbuffer *reply = NULL;
|
||||
struct daemon_metrics *metrics = ((struct metrics_acceptlist *)p)->metrics;
|
||||
|
||||
/* currently only GET requests are supported/allowed */
|
||||
enum evhttp_cmd_type cmd = evhttp_request_get_command(req);
|
||||
if (cmd != EVHTTP_REQ_GET /* && cmd != EVHTTP_REQ_HEAD */) {
|
||||
evhttp_send_error(req, HTTP_BADMETHOD, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
reply = evbuffer_new();
|
||||
|
||||
if (!reply) {
|
||||
evhttp_send_error(req, HTTP_INTERNAL, 0);
|
||||
log_err("metrics: failed to allocate reply buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
evhttp_add_header(evhttp_request_get_output_headers(req),
|
||||
"Content-Type", "text/plain; version=0.0.4");
|
||||
do_metrics_stats(reply, metrics->worker, 0 /* no reset */);
|
||||
evhttp_send_reply(req, HTTP_OK, NULL, reply);
|
||||
verbose(VERB_DETAIL, "metrics operation completed, response sent");
|
||||
evbuffer_free(reply);
|
||||
}
|
||||
#endif /* USE_METRICS */
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* daemon/metrics.h - prometheus metrics endpoint.
|
||||
*
|
||||
* Copyright (c) 2026, 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
|
||||
*
|
||||
* The statistics output provides metrics to prometheus.
|
||||
*/
|
||||
|
||||
#ifndef DAEMON_METRICS_H
|
||||
#define DAEMON_METRICS_H
|
||||
struct daemon_metrics;
|
||||
struct config_file;
|
||||
struct worker;
|
||||
struct evhttp;
|
||||
|
||||
/* the metrics daemon needs little backlog */
|
||||
#define TCP_BACKLOG_METRICS 16 /* listen() tcp backlog */
|
||||
|
||||
/**
|
||||
* list of connection accepting file descriptors
|
||||
*/
|
||||
struct metrics_acceptlist {
|
||||
struct metrics_acceptlist* next;
|
||||
int accept_fd;
|
||||
char* ident;
|
||||
struct daemon_metrics* metrics;
|
||||
};
|
||||
|
||||
/**
|
||||
* The metrics daemon state.
|
||||
*/
|
||||
struct daemon_metrics {
|
||||
/** The worker for this metrics endpoint */
|
||||
struct worker* worker;
|
||||
/** commpoints for accepting HTTP connections */
|
||||
struct metrics_acceptlist* accept_list;
|
||||
/** libevent http server */
|
||||
struct evhttp *http_server;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create new metrics endpoint for the daemon.
|
||||
* Does not open the ports, for that call the open ports routine, and
|
||||
* later the attach routine on the worker event base.
|
||||
* @return new state, or NULL on failure.
|
||||
*/
|
||||
struct daemon_metrics* daemon_metrics_create(void);
|
||||
|
||||
/**
|
||||
* Delete metrics daemon and close HTTP listeners.
|
||||
* @param m: daemon to delete.
|
||||
*/
|
||||
void daemon_metrics_delete(struct daemon_metrics* m);
|
||||
|
||||
/**
|
||||
* Close metrics HTTP listener ports.
|
||||
* Does not delete the object itself.
|
||||
* @param m: state to close.
|
||||
*/
|
||||
void daemon_metrics_close_ports(struct daemon_metrics* m);
|
||||
|
||||
/**
|
||||
* Detach the metrics listener from the event base.
|
||||
* Does not delete the object itself.
|
||||
* @param m: state to detach.
|
||||
*/
|
||||
void daemon_metrics_detach(struct daemon_metrics* m);
|
||||
|
||||
/**
|
||||
* Open and create HTTP listeners for metrics daemon.
|
||||
* @param m: metrics state that contains list of accept sockets.
|
||||
* @param cfg: config options.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int daemon_metrics_open_ports(struct daemon_metrics* m,
|
||||
struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Setup HTTP listener.
|
||||
* @param m: state
|
||||
* @param worker: The worker thread that hosts the endpoint.
|
||||
* The HTTP listener is attached to its event base.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int daemon_metrics_attach(struct daemon_metrics* m, struct worker* worker);
|
||||
|
||||
#endif /* DAEMON_METRICS_H */
|
||||
+329
-52
@@ -307,6 +307,26 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
char* s = strchr(ip, '@');
|
||||
char newif[128];
|
||||
if(s) {
|
||||
/* override port with ifspec@port */
|
||||
int portnr;
|
||||
if((size_t)(s-ip) >= sizeof(newif)) {
|
||||
log_err("ifname too long: %s", ip);
|
||||
return -1;
|
||||
}
|
||||
portnr = atoi(s+1);
|
||||
if(portnr < 0 || 0 == portnr || portnr > 65535) {
|
||||
log_err("invalid portnumber in control-interface: %s", ip);
|
||||
return -1;
|
||||
}
|
||||
(void)strlcpy(newif, ip, sizeof(newif));
|
||||
newif[s-ip] = 0;
|
||||
ip = newif;
|
||||
snprintf(port, sizeof(port), "%d", portnr);
|
||||
port[sizeof(port)-1]=0;
|
||||
}
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
|
||||
if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
|
||||
@@ -801,6 +821,8 @@ print_stats(RES* ssl, const char* nm, struct ub_stats_info* s)
|
||||
(unsigned long)s->svr.num_queries_cookie_invalid)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.queries_discard_timeout"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries_discard_timeout)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.queries_replyaddr_limit"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries_replyaddr_limit)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.queries_wait_limit"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries_wait_limit)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.cachehits"SQ"%lu\n", nm,
|
||||
@@ -845,6 +867,8 @@ print_stats(RES* ssl, const char* nm, struct ub_stats_info* s)
|
||||
(unsigned long)s->mesh_num_states)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.requestlist.current.user"SQ"%lu\n", nm,
|
||||
(unsigned long)s->mesh_num_reply_states)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.requestlist.current.replies"SQ"%lu\n", nm,
|
||||
(unsigned long)s->mesh_num_reply_addrs)) return 0;
|
||||
#ifndef S_SPLINT_S
|
||||
sumwait.tv_sec = s->mesh_replies_sum_wait_sec;
|
||||
sumwait.tv_usec = s->mesh_replies_sum_wait_usec;
|
||||
@@ -886,73 +910,39 @@ print_longnum(RES* ssl, const char* desc, size_t x)
|
||||
|
||||
/** print mem stats */
|
||||
static int
|
||||
print_mem(RES* ssl, struct worker* worker, struct daemon* daemon,
|
||||
struct ub_stats_info* s)
|
||||
print_mem(RES* ssl, struct worker* worker, struct ub_stats_info* s)
|
||||
{
|
||||
size_t msg, rrset, val, iter, respip;
|
||||
#ifdef CLIENT_SUBNET
|
||||
size_t subnet = 0;
|
||||
#endif /* CLIENT_SUBNET */
|
||||
#ifdef USE_IPSECMOD
|
||||
size_t ipsecmod = 0;
|
||||
#endif /* USE_IPSECMOD */
|
||||
#ifdef USE_DNSCRYPT
|
||||
size_t dnscrypt_shared_secret = 0;
|
||||
size_t dnscrypt_nonce = 0;
|
||||
#endif /* USE_DNSCRYPT */
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
size_t dynlib = 0;
|
||||
#endif /* WITH_DYNLIBMODULE */
|
||||
msg = slabhash_get_mem(daemon->env->msg_cache);
|
||||
rrset = slabhash_get_mem(&daemon->env->rrset_cache->table);
|
||||
val = mod_get_mem(&worker->env, "validator");
|
||||
iter = mod_get_mem(&worker->env, "iterator");
|
||||
respip = mod_get_mem(&worker->env, "respip");
|
||||
#ifdef CLIENT_SUBNET
|
||||
subnet = mod_get_mem(&worker->env, "subnetcache");
|
||||
#endif /* CLIENT_SUBNET */
|
||||
#ifdef USE_IPSECMOD
|
||||
ipsecmod = mod_get_mem(&worker->env, "ipsecmod");
|
||||
#endif /* USE_IPSECMOD */
|
||||
#ifdef USE_DNSCRYPT
|
||||
if(daemon->dnscenv) {
|
||||
dnscrypt_shared_secret = slabhash_get_mem(
|
||||
daemon->dnscenv->shared_secrets_cache);
|
||||
dnscrypt_nonce = slabhash_get_mem(daemon->dnscenv->nonces_cache);
|
||||
}
|
||||
#endif /* USE_DNSCRYPT */
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
dynlib = mod_get_mem(&worker->env, "dynlib");
|
||||
#endif /* WITH_DYNLIBMODULE */
|
||||
struct ub_mem_stat_info mem;
|
||||
stats_get_mem_info(worker, &mem);
|
||||
|
||||
if(!print_longnum(ssl, "mem.cache.rrset"SQ, rrset))
|
||||
if(!print_longnum(ssl, "mem.cache.rrset"SQ, (size_t)mem.rrset))
|
||||
return 0;
|
||||
if(!print_longnum(ssl, "mem.cache.message"SQ, msg))
|
||||
if(!print_longnum(ssl, "mem.cache.message"SQ, (size_t)mem.msg))
|
||||
return 0;
|
||||
if(!print_longnum(ssl, "mem.mod.iterator"SQ, iter))
|
||||
if(!print_longnum(ssl, "mem.mod.iterator"SQ, (size_t)mem.iter))
|
||||
return 0;
|
||||
if(!print_longnum(ssl, "mem.mod.validator"SQ, val))
|
||||
if(!print_longnum(ssl, "mem.mod.validator"SQ, (size_t)mem.val))
|
||||
return 0;
|
||||
if(!print_longnum(ssl, "mem.mod.respip"SQ, respip))
|
||||
if(!print_longnum(ssl, "mem.mod.respip"SQ, (size_t)mem.respip))
|
||||
return 0;
|
||||
#ifdef CLIENT_SUBNET
|
||||
if(!print_longnum(ssl, "mem.mod.subnet"SQ, subnet))
|
||||
if(!print_longnum(ssl, "mem.mod.subnet"SQ, (size_t)mem.subnet))
|
||||
return 0;
|
||||
#endif /* CLIENT_SUBNET */
|
||||
#ifdef USE_IPSECMOD
|
||||
if(!print_longnum(ssl, "mem.mod.ipsecmod"SQ, ipsecmod))
|
||||
if(!print_longnum(ssl, "mem.mod.ipsecmod"SQ, (size_t)mem.ipsecmod))
|
||||
return 0;
|
||||
#endif /* USE_IPSECMOD */
|
||||
#ifdef USE_DNSCRYPT
|
||||
if(!print_longnum(ssl, "mem.cache.dnscrypt_shared_secret"SQ,
|
||||
dnscrypt_shared_secret))
|
||||
(size_t)mem.dnscrypt_shared_secret))
|
||||
return 0;
|
||||
if(!print_longnum(ssl, "mem.cache.dnscrypt_nonce"SQ,
|
||||
dnscrypt_nonce))
|
||||
(size_t)mem.dnscrypt_nonce))
|
||||
return 0;
|
||||
#endif /* USE_DNSCRYPT */
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
if(!print_longnum(ssl, "mem.mod.dynlibmod"SQ, dynlib))
|
||||
if(!print_longnum(ssl, "mem.mod.dynlibmod"SQ, (size_t)mem.dynlib))
|
||||
return 0;
|
||||
#endif /* WITH_DYNLIBMODULE */
|
||||
if(!print_longnum(ssl, "mem.streamwait"SQ,
|
||||
@@ -1240,7 +1230,7 @@ do_stats(RES* ssl, struct worker* worker, int reset)
|
||||
if(!print_uptime(ssl, worker, reset))
|
||||
return;
|
||||
if(daemon->cfg->stat_extended) {
|
||||
if(!print_mem(ssl, worker, daemon, &total))
|
||||
if(!print_mem(ssl, worker, &total))
|
||||
return;
|
||||
if(!print_hist(ssl, &total))
|
||||
return;
|
||||
@@ -4629,6 +4619,26 @@ fr_init_time(struct timeval* time_start, struct timeval* time_read,
|
||||
* are kept in here. They can then be deleted.
|
||||
*/
|
||||
struct fast_reload_construct {
|
||||
/** ssl context for listening to dnstcp over ssl */
|
||||
void* listen_dot_sslctx;
|
||||
/** ssl context for connecting to dnstcp over ssl */
|
||||
void* connect_dot_sslctx;
|
||||
/** ssl context for listening to DoH */
|
||||
void* listen_doh_sslctx;
|
||||
/** ssl context for listening to quic */
|
||||
void* listen_quic_sslctx;
|
||||
/** the file name that the ssl context is made with, private key. */
|
||||
char* ssl_service_key;
|
||||
/** the file name that the ssl context is made with, certificate. */
|
||||
char* ssl_service_pem;
|
||||
/** modification time for ssl_service_key, in sec and ns. Like
|
||||
* in a struct timespec, but without that for portability. */
|
||||
time_t mtime_ssl_service_key;
|
||||
long mtime_ns_ssl_service_key;
|
||||
/** modification time for ssl_service_pem, in sec and ns. Like
|
||||
* in a struct timespec, but without that for portability. */
|
||||
time_t mtime_ssl_service_pem;
|
||||
long mtime_ns_ssl_service_pem;
|
||||
/** construct for views */
|
||||
struct views* views;
|
||||
/** construct for auth zones */
|
||||
@@ -4932,13 +4942,16 @@ fr_check_compat_cfg(struct fast_reload_thread* fr, struct config_file* newcfg)
|
||||
FR_CHECK_CHANGED_CFG("http_notls_downstream", http_notls_downstream, changed_str);
|
||||
FR_CHECK_CHANGED_CFG("https-port", https_port, changed_str);
|
||||
FR_CHECK_CHANGED_CFG("tls-port", ssl_port, changed_str);
|
||||
FR_CHECK_CHANGED_CFG_STR("tls-service-key", ssl_service_key, changed_str);
|
||||
FR_CHECK_CHANGED_CFG_STR("tls-service-pem", ssl_service_pem, changed_str);
|
||||
FR_CHECK_CHANGED_CFG_STR("tls-cert-bundle", tls_cert_bundle, changed_str);
|
||||
FR_CHECK_CHANGED_CFG_STRLIST("proxy-protocol-port", proxy_protocol_port, changed_str);
|
||||
FR_CHECK_CHANGED_CFG_STRLIST("tls-additional-port", tls_additional_port, changed_str);
|
||||
FR_CHECK_CHANGED_CFG_STR("interface-automatic-ports", if_automatic_ports, changed_str);
|
||||
FR_CHECK_CHANGED_CFG("udp-upstream-without-downstream", udp_upstream_without_downstream, changed_str);
|
||||
#ifdef USE_METRICS
|
||||
FR_CHECK_CHANGED_CFG("metrics-enable", metrics_enable, changed_str);
|
||||
FR_CHECK_CHANGED_CFG("metrics-port", metrics_port, changed_str);
|
||||
FR_CHECK_CHANGED_CFG_STR("metrics-path", metrics_path, changed_str);
|
||||
FR_CHECK_CHANGED_CFG_STRLIST("metrics-interface", metrics_ifs.first, changed_str);
|
||||
#endif
|
||||
|
||||
if(changed_str[0] != 0) {
|
||||
/* The new config changes some items that do not work with
|
||||
@@ -5043,6 +5056,19 @@ fr_construct_clear(struct fast_reload_construct* ct)
|
||||
wait_limits_free(&ct->wait_limits_netblock);
|
||||
wait_limits_free(&ct->wait_limits_cookie_netblock);
|
||||
domain_limits_free(&ct->domain_limits);
|
||||
#ifdef HAVE_SSL
|
||||
/* The SSL contexts can be SSL_CTX_free here. It is reference
|
||||
* counted. So ongoing transfers with can continue.
|
||||
* Once they are done, the context is freed. */
|
||||
SSL_CTX_free((SSL_CTX*)ct->listen_dot_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)ct->connect_dot_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)ct->listen_doh_sslctx);
|
||||
#endif /* HAVE_SSL */
|
||||
#ifdef HAVE_NGTCP2
|
||||
SSL_CTX_free((SSL_CTX*)ct->listen_quic_sslctx);
|
||||
#endif
|
||||
free(ct->ssl_service_key);
|
||||
free(ct->ssl_service_pem);
|
||||
/* Delete the log identity here so that the global value is not
|
||||
* reset by config_delete. */
|
||||
if(ct->oldcfg && ct->oldcfg->log_identity) {
|
||||
@@ -5253,6 +5279,10 @@ config_file_getmem(struct config_file* cfg)
|
||||
m += getmem_str(cfg->dnstap_tls_client_cert_file);
|
||||
m += getmem_str(cfg->dnstap_identity);
|
||||
m += getmem_str(cfg->dnstap_version);
|
||||
#ifdef USE_METRICS
|
||||
m += getmem_config_strlist(cfg->metrics_ifs.first);
|
||||
m += getmem_str(cfg->metrics_path);
|
||||
#endif
|
||||
m += getmem_config_str2list(cfg->ratelimit_for_domain);
|
||||
m += getmem_config_str2list(cfg->ratelimit_below_domain);
|
||||
m += getmem_config_str2list(cfg->edns_client_strings);
|
||||
@@ -5291,6 +5321,8 @@ fr_printmem(struct fast_reload_thread* fr,
|
||||
size_t mem = 0;
|
||||
if(fr_poll_for_quit(fr))
|
||||
return 1;
|
||||
mem += getmem_str(ct->ssl_service_key);
|
||||
mem += getmem_str(ct->ssl_service_pem);
|
||||
mem += views_get_mem(ct->views);
|
||||
mem += respip_set_get_mem(ct->respip_set);
|
||||
mem += auth_zones_get_mem(ct->auth_zones);
|
||||
@@ -5524,6 +5556,96 @@ auth_zones_check_changes(struct fast_reload_thread* fr,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Check if the sslctxs have changed. */
|
||||
static int
|
||||
fr_check_sslctx_change(struct fast_reload_thread* fr,
|
||||
struct config_file* newcfg)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
struct daemon* daemon = fr->worker->daemon;
|
||||
if(newcfg->ssl_service_key && newcfg->ssl_service_key[0]) {
|
||||
if(!daemon->ssl_service_key ||
|
||||
ssl_cert_changed(daemon, newcfg))
|
||||
return 1;
|
||||
} else {
|
||||
if(daemon->ssl_service_key)
|
||||
return 1; /* it is removed */
|
||||
}
|
||||
if((daemon->cfg->tls_cert_bundle && !newcfg->tls_cert_bundle) ||
|
||||
(!daemon->cfg->tls_cert_bundle && newcfg->tls_cert_bundle) ||
|
||||
(daemon->cfg->tls_cert_bundle && newcfg->tls_cert_bundle &&
|
||||
strcmp(daemon->cfg->tls_cert_bundle, newcfg->tls_cert_bundle)!=0))
|
||||
return 1; /* The tls-cert-bundle has changed and return
|
||||
true here makes it reload the connect_dot_sslctx. */
|
||||
#else
|
||||
(void)fr; (void)newcfg;
|
||||
#endif /* HAVE_SSL */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Create the SSL CTXs when they have changed. */
|
||||
static int
|
||||
ct_create_sslctxs(struct fast_reload_construct* ct,
|
||||
struct config_file* newcfg, struct daemon* daemon)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
char* chroot = daemon->chroot;
|
||||
char* key = newcfg->ssl_service_key;
|
||||
char* pem = newcfg->ssl_service_pem;
|
||||
|
||||
if(!(newcfg->ssl_service_key && newcfg->ssl_service_key[0])) {
|
||||
/* Leave listen ctxs and file str at NULL */
|
||||
ct->connect_dot_sslctx = daemon_setup_connect_dot_sslctx(
|
||||
daemon, newcfg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
|
||||
key += strlen(chroot);
|
||||
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
|
||||
pem += strlen(chroot);
|
||||
|
||||
ct->listen_dot_sslctx = daemon_setup_listen_dot_sslctx(daemon, newcfg);
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
if(cfg_has_https(newcfg)) {
|
||||
ct->listen_doh_sslctx = daemon_setup_listen_doh_sslctx(
|
||||
daemon, newcfg);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
if(cfg_has_quic(newcfg)) {
|
||||
ct->listen_quic_sslctx = daemon_setup_listen_quic_sslctx(
|
||||
daemon, newcfg);
|
||||
}
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
ct->connect_dot_sslctx = daemon_setup_connect_dot_sslctx(daemon,
|
||||
newcfg);
|
||||
|
||||
/* Store mtime and names */
|
||||
ct->ssl_service_key = strdup(newcfg->ssl_service_key);
|
||||
if(!ct->ssl_service_key) {
|
||||
log_err("ct_create_sslctxs: out of memory");
|
||||
return 0;
|
||||
}
|
||||
ct->ssl_service_pem = strdup(newcfg->ssl_service_pem);
|
||||
if(!ct->ssl_service_pem) {
|
||||
log_err("ct_create_sslctxs: out of memory");
|
||||
return 0;
|
||||
}
|
||||
if(!file_get_mtime(key, &ct->mtime_ssl_service_key,
|
||||
&ct->mtime_ns_ssl_service_key, NULL))
|
||||
log_err("Could not stat(%s): %s",
|
||||
key, strerror(errno));
|
||||
if(!file_get_mtime(pem, &ct->mtime_ssl_service_pem,
|
||||
&ct->mtime_ns_ssl_service_pem, NULL))
|
||||
log_err("Could not stat(%s): %s",
|
||||
pem, strerror(errno));
|
||||
#else
|
||||
(void)ct; (void)newcfg; (void)daemon;
|
||||
#endif /* HAVE_SSL */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** fast reload thread, construct from config the new items */
|
||||
static int
|
||||
fr_construct_from_config(struct fast_reload_thread* fr,
|
||||
@@ -5531,6 +5653,13 @@ fr_construct_from_config(struct fast_reload_thread* fr,
|
||||
{
|
||||
int have_view_respip_cfg = 0;
|
||||
|
||||
fr->sslctxs_changed = fr_check_sslctx_change(fr, newcfg);
|
||||
if(fr->sslctxs_changed) {
|
||||
if(!ct_create_sslctxs(ct, newcfg, fr->worker->daemon)) {
|
||||
fr_construct_clear(ct);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(!(ct->views = views_create())) {
|
||||
fr_construct_clear(ct);
|
||||
return 0;
|
||||
@@ -5808,6 +5937,44 @@ auth_zones_swap(struct auth_zones* az, struct auth_zones* data)
|
||||
* the xfer elements can continue to be their callbacks. */
|
||||
}
|
||||
|
||||
/** Swap two void* */
|
||||
static void
|
||||
void_ptr_swap(void** a, void **b)
|
||||
{
|
||||
void* tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
/** Swap two char* */
|
||||
static void
|
||||
char_ptr_swap(char** a, char **b)
|
||||
{
|
||||
char* tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
/** Swap and set ssl ctx information */
|
||||
static void
|
||||
sslctxs_swap(struct daemon* daemon, struct fast_reload_construct* ct)
|
||||
{
|
||||
void_ptr_swap(&daemon->listen_dot_sslctx, &ct->listen_dot_sslctx);
|
||||
void_ptr_swap(&daemon->connect_dot_sslctx, &ct->connect_dot_sslctx);
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
void_ptr_swap(&daemon->listen_doh_sslctx, &ct->listen_doh_sslctx);
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
void_ptr_swap(&daemon->listen_quic_sslctx, &ct->listen_quic_sslctx);
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
char_ptr_swap(&daemon->ssl_service_key, &ct->ssl_service_key);
|
||||
char_ptr_swap(&daemon->ssl_service_pem, &ct->ssl_service_pem);
|
||||
daemon->mtime_ssl_service_key = ct->mtime_ssl_service_key;
|
||||
daemon->mtime_ns_ssl_service_key = ct->mtime_ns_ssl_service_key;
|
||||
daemon->mtime_ssl_service_pem = ct->mtime_ssl_service_pem;
|
||||
daemon->mtime_ns_ssl_service_pem = ct->mtime_ns_ssl_service_pem;
|
||||
}
|
||||
|
||||
#if defined(ATOMIC_POINTER_LOCK_FREE) && defined(HAVE_LINK_ATOMIC_STORE)
|
||||
/** Fast reload thread, if atomics are available, copy the config items
|
||||
* one by one with atomic store operations. */
|
||||
@@ -5968,6 +6135,7 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
|
||||
COPY_VAR_int(log_servfail);
|
||||
COPY_VAR_ptr(log_identity);
|
||||
COPY_VAR_int(log_destaddr);
|
||||
COPY_VAR_int(log_thread_id);
|
||||
COPY_VAR_int(hide_identity);
|
||||
COPY_VAR_int(hide_version);
|
||||
COPY_VAR_int(hide_trustanchor);
|
||||
@@ -6099,6 +6267,13 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
|
||||
COPY_VAR_int(dnstap_log_forwarder_query_messages);
|
||||
COPY_VAR_int(dnstap_log_forwarder_response_messages);
|
||||
COPY_VAR_int(disable_dnssec_lame_check);
|
||||
#ifdef USE_METRICS
|
||||
COPY_VAR_int(metrics_enable);
|
||||
COPY_VAR_ptr(metrics_ifs.first);
|
||||
COPY_VAR_ptr(metrics_ifs.last);
|
||||
COPY_VAR_int(metrics_port);
|
||||
COPY_VAR_ptr(metrics_path);
|
||||
#endif
|
||||
COPY_VAR_int(ip_ratelimit);
|
||||
COPY_VAR_int(ip_ratelimit_cookie);
|
||||
COPY_VAR_size_t(ip_ratelimit_slabs);
|
||||
@@ -6177,7 +6352,19 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
|
||||
COPY_VAR_ptr(ipset_name_v6);
|
||||
#endif
|
||||
COPY_VAR_int(ede);
|
||||
COPY_VAR_int(iter_scrub_ns);
|
||||
COPY_VAR_int(iter_scrub_cname);
|
||||
COPY_VAR_int(max_global_quota);
|
||||
COPY_VAR_int(iter_scrub_promiscuous);
|
||||
|
||||
#undef COPY_VAR_int
|
||||
#undef COPY_VAR_ptr
|
||||
#undef COPY_VAR_unsigned_int
|
||||
#undef COPY_VAR_size_t
|
||||
#undef COPY_VAR_uint8_t
|
||||
#undef COPY_VAR_uint16_t
|
||||
#undef COPY_VAR_uint32_t
|
||||
#undef COPY_VAR_int32_t
|
||||
}
|
||||
#endif /* ATOMIC_POINTER_LOCK_FREE && HAVE_LINK_ATOMIC_STORE */
|
||||
|
||||
@@ -6403,6 +6590,9 @@ fr_reload_config(struct fast_reload_thread* fr, struct config_file* newcfg,
|
||||
daemon->env->cachedb_enabled = cachedb_is_enabled(&daemon->mods,
|
||||
daemon->env);
|
||||
#endif
|
||||
if(fr->sslctxs_changed) {
|
||||
sslctxs_swap(daemon, ct);
|
||||
}
|
||||
#ifdef USE_DNSTAP
|
||||
if(env->cfg->dnstap) {
|
||||
if(!fr->fr_nopause)
|
||||
@@ -6627,7 +6817,14 @@ static void* fast_reload_thread_main(void* arg)
|
||||
struct fast_reload_thread* fast_reload_thread = (struct fast_reload_thread*)arg;
|
||||
struct timeval time_start, time_read, time_construct, time_reload,
|
||||
time_end;
|
||||
log_thread_set(&fast_reload_thread->threadnum);
|
||||
|
||||
#if defined(HAVE_GETTID) && !defined(THREADS_DISABLED)
|
||||
fast_reload_thread->thread_tid = gettid();
|
||||
if(fast_reload_thread->thread_tid_log)
|
||||
log_thread_set(&fast_reload_thread->thread_tid);
|
||||
else
|
||||
#endif
|
||||
log_thread_set(&fast_reload_thread->threadnum);
|
||||
|
||||
verbose(VERB_ALGO, "start fast reload thread");
|
||||
if(fast_reload_thread->fr_verb >= 1) {
|
||||
@@ -7015,6 +7212,9 @@ fast_reload_thread_setup(struct worker* worker, int fr_verb, int fr_nopause,
|
||||
lock_basic_init(&fr->fr_output_lock);
|
||||
lock_protect(&fr->fr_output_lock, fr->fr_output,
|
||||
sizeof(*fr->fr_output));
|
||||
#ifdef HAVE_GETTID
|
||||
fr->thread_tid_log = worker->env.cfg->log_thread_id;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -7589,6 +7789,42 @@ fr_worker_pickup_auth_changes(struct worker* worker,
|
||||
}
|
||||
}
|
||||
|
||||
/** Fast reload, the worker picks up changes in listen_dnsport. */
|
||||
static void
|
||||
fr_worker_pickup_listen_dnsport(struct worker* worker)
|
||||
{
|
||||
struct listen_dnsport* front = worker->front;
|
||||
struct daemon* daemon = worker->daemon;
|
||||
if(worker->daemon->fast_reload_thread->sslctxs_changed) {
|
||||
struct listen_list* ll;
|
||||
void* dot_sslctx = daemon->listen_dot_sslctx;
|
||||
void* doh_sslctx = daemon->listen_doh_sslctx;
|
||||
void* quic_sslctx = daemon->listen_quic_sslctx;
|
||||
for(ll = front->cps; ll; ll = ll->next) {
|
||||
struct comm_point* cp = ll->com;
|
||||
if(cp->type == comm_tcp_accept &&
|
||||
cp->tcp_handlers &&
|
||||
cp->max_tcp_count > 0 &&
|
||||
cp->tcp_handlers[0]->type == comm_http) {
|
||||
if(cp->ssl)
|
||||
cp->ssl = doh_sslctx;
|
||||
} else if(cp->type == comm_tcp_accept) {
|
||||
if(cp->ssl)
|
||||
cp->ssl = dot_sslctx;
|
||||
#ifdef HAVE_NGTCP2
|
||||
} else if(cp->type == comm_doq) {
|
||||
if(cp->ssl) {
|
||||
cp->ssl = quic_sslctx;
|
||||
if(cp->doq_socket)
|
||||
cp->doq_socket->ctx =
|
||||
(SSL_CTX*)quic_sslctx;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Fast reload, the worker picks up changes in outside_network. */
|
||||
static void
|
||||
fr_worker_pickup_outside_network(struct worker* worker)
|
||||
@@ -7604,6 +7840,8 @@ fr_worker_pickup_outside_network(struct worker* worker)
|
||||
outnet->tcp_reuse_timeout = cfg->tcp_reuse_timeout;
|
||||
outnet->tcp_auth_query_timeout = cfg->tcp_auth_query_timeout;
|
||||
outnet->delayclose = cfg->delay_close;
|
||||
if(worker->daemon->fast_reload_thread->sslctxs_changed)
|
||||
outnet->sslctx = worker->daemon->connect_dot_sslctx;
|
||||
if(outnet->delayclose) {
|
||||
#ifndef S_SPLINT_S
|
||||
outnet->delay_tv.tv_sec = cfg->delay_close/1000;
|
||||
@@ -7612,6 +7850,41 @@ fr_worker_pickup_outside_network(struct worker* worker)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_DNSTAP
|
||||
/** Fast reload, the worker picks up changes to DNSTAP configuration. */
|
||||
static void
|
||||
fr_worker_pickup_dnstap_changes(struct worker* worker)
|
||||
{
|
||||
struct dt_env* w_dtenv = &worker->dtenv;
|
||||
struct dt_env* d_dtenv = worker->daemon->dtenv;
|
||||
log_assert(d_dtenv != NULL || !worker->daemon->cfg->dnstap);
|
||||
if(d_dtenv == NULL) {
|
||||
/* There is no environment when DNSTAP was not enabled
|
||||
* in the configuration. */
|
||||
return;
|
||||
}
|
||||
w_dtenv->identity = d_dtenv->identity;
|
||||
w_dtenv->len_identity = d_dtenv->len_identity;
|
||||
w_dtenv->version = d_dtenv->version;
|
||||
w_dtenv->len_version = d_dtenv->len_version;
|
||||
w_dtenv->log_resolver_query_messages =
|
||||
d_dtenv->log_resolver_query_messages;
|
||||
w_dtenv->log_resolver_response_messages =
|
||||
d_dtenv->log_resolver_response_messages;
|
||||
w_dtenv->log_client_query_messages =
|
||||
d_dtenv->log_client_query_messages;
|
||||
w_dtenv->log_client_response_messages =
|
||||
d_dtenv->log_client_response_messages;
|
||||
w_dtenv->log_forwarder_query_messages =
|
||||
d_dtenv->log_forwarder_query_messages;
|
||||
w_dtenv->log_forwarder_response_messages =
|
||||
d_dtenv->log_forwarder_response_messages;
|
||||
lock_basic_lock(&d_dtenv->sample_lock);
|
||||
w_dtenv->sample_rate = d_dtenv->sample_rate;
|
||||
lock_basic_unlock(&d_dtenv->sample_lock);
|
||||
}
|
||||
#endif /* USE_DNSTAP */
|
||||
|
||||
void
|
||||
fast_reload_worker_pickup_changes(struct worker* worker)
|
||||
{
|
||||
@@ -7639,7 +7912,11 @@ fast_reload_worker_pickup_changes(struct worker* worker)
|
||||
#ifdef USE_CACHEDB
|
||||
worker->env.cachedb_enabled = worker->daemon->env->cachedb_enabled;
|
||||
#endif
|
||||
fr_worker_pickup_listen_dnsport(worker);
|
||||
fr_worker_pickup_outside_network(worker);
|
||||
#ifdef USE_DNSTAP
|
||||
fr_worker_pickup_dnstap_changes(worker);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** fast reload thread, handle reload_stop notification, send reload stop
|
||||
|
||||
@@ -206,6 +206,12 @@ struct fast_reload_thread {
|
||||
int commpair[2];
|
||||
/** thread id, of the io thread */
|
||||
ub_thread_type tid;
|
||||
#ifdef HAVE_GETTID
|
||||
/** thread tid, the LWP id */
|
||||
pid_t thread_tid;
|
||||
/** if logging should include the LWP id */
|
||||
int thread_tid_log;
|
||||
#endif
|
||||
/** if the io processing has started */
|
||||
int started;
|
||||
/** if the thread has to quit */
|
||||
@@ -249,6 +255,8 @@ struct fast_reload_thread {
|
||||
struct fast_reload_auth_change* auth_zone_change_list;
|
||||
/** the old tree of auth zones, to lookup. */
|
||||
struct auth_zones* old_auth_zones;
|
||||
/** If the ssl ctxs have changed. */
|
||||
int sslctxs_changed;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -262,6 +262,7 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
s->svr = worker->stats;
|
||||
s->mesh_num_states = (long long)worker->env.mesh->all.count;
|
||||
s->mesh_num_reply_states = (long long)worker->env.mesh->num_reply_states;
|
||||
s->mesh_num_reply_addrs = (long long)worker->env.mesh->num_reply_addrs;
|
||||
s->mesh_jostled = (long long)worker->env.mesh->stats_jostled;
|
||||
s->mesh_dropped = (long long)worker->env.mesh->stats_dropped;
|
||||
s->mesh_replies_sent = (long long)worker->env.mesh->replies_sent;
|
||||
@@ -284,6 +285,8 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
NUM_BUCKETS_HIST);
|
||||
s->svr.num_queries_discard_timeout +=
|
||||
(long long)worker->env.mesh->num_queries_discard_timeout;
|
||||
s->svr.num_queries_replyaddr_limit +=
|
||||
(long long)worker->env.mesh->num_queries_replyaddr_limit;
|
||||
s->svr.num_queries_wait_limit +=
|
||||
(long long)worker->env.mesh->num_queries_wait_limit;
|
||||
s->svr.num_dns_error_reports +=
|
||||
@@ -448,6 +451,8 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
total->svr.num_queries_cookie_invalid += a->svr.num_queries_cookie_invalid;
|
||||
total->svr.num_queries_discard_timeout +=
|
||||
a->svr.num_queries_discard_timeout;
|
||||
total->svr.num_queries_replyaddr_limit +=
|
||||
a->svr.num_queries_replyaddr_limit;
|
||||
total->svr.num_queries_wait_limit += a->svr.num_queries_wait_limit;
|
||||
total->svr.num_dns_error_reports += a->svr.num_dns_error_reports;
|
||||
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
|
||||
@@ -519,6 +524,7 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
|
||||
total->mesh_num_states += a->mesh_num_states;
|
||||
total->mesh_num_reply_states += a->mesh_num_reply_states;
|
||||
total->mesh_num_reply_addrs += a->mesh_num_reply_addrs;
|
||||
total->mesh_jostled += a->mesh_jostled;
|
||||
total->mesh_dropped += a->mesh_dropped;
|
||||
total->mesh_replies_sent += a->mesh_replies_sent;
|
||||
@@ -605,3 +611,42 @@ void server_stats_downstream_cookie(struct ub_server_stats* stats,
|
||||
stats->num_queries_cookie_invalid++;
|
||||
}
|
||||
}
|
||||
|
||||
void stats_get_mem_info(struct worker* worker, struct ub_mem_stat_info* mem)
|
||||
{
|
||||
struct daemon* daemon = worker->daemon;
|
||||
mem->msg = slabhash_get_mem(daemon->env->msg_cache);
|
||||
mem->rrset = slabhash_get_mem(&daemon->env->rrset_cache->table);
|
||||
mem->val = mod_get_mem(&worker->env, "validator");
|
||||
mem->iter = mod_get_mem(&worker->env, "iterator");
|
||||
mem->respip = mod_get_mem(&worker->env, "respip");
|
||||
#ifdef CLIENT_SUBNET
|
||||
mem->subnet = mod_get_mem(&worker->env, "subnetcache");
|
||||
#else
|
||||
mem->subnet = 0;
|
||||
#endif /* CLIENT_SUBNET */
|
||||
#ifdef USE_IPSECMOD
|
||||
mem->ipsecmod = mod_get_mem(&worker->env, "ipsecmod");
|
||||
#else
|
||||
mem->ipsecmod = 0;
|
||||
#endif /* USE_IPSECMOD */
|
||||
#ifdef USE_DNSCRYPT
|
||||
if(daemon->dnscenv) {
|
||||
mem->dnscrypt_shared_secret = slabhash_get_mem(
|
||||
daemon->dnscenv->shared_secrets_cache);
|
||||
mem->dnscrypt_nonce = slabhash_get_mem(
|
||||
daemon->dnscenv->nonces_cache);
|
||||
} else {
|
||||
mem->dnscrypt_shared_secret = 0;
|
||||
mem->dnscrypt_nonce = 0;
|
||||
}
|
||||
#else
|
||||
mem->dnscrypt_shared_secret = 0;
|
||||
mem->dnscrypt_nonce = 0;
|
||||
#endif /* USE_DNSCRYPT */
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
mem->dynlib = mod_get_mem(&worker->env, "dynlib");
|
||||
#else
|
||||
mem->dynlib = 0;
|
||||
#endif /* WITH_DYNLIBMODULE */
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ struct comm_point;
|
||||
struct comm_reply;
|
||||
struct edns_data;
|
||||
struct sldns_buffer;
|
||||
struct ub_mem_stat_info;
|
||||
|
||||
/* stats struct */
|
||||
#include "libunbound/unbound.h"
|
||||
@@ -133,4 +134,11 @@ void server_stats_insrcode(struct ub_server_stats* stats, struct sldns_buffer* b
|
||||
*/
|
||||
void server_stats_downstream_cookie(struct ub_server_stats* stats,
|
||||
struct edns_data* edns);
|
||||
|
||||
/** Get the memory statistics for the program.
|
||||
* @param worker: with worker env and ptr to daemon.
|
||||
* @param mem: filled with memory usage value statistics.
|
||||
*/
|
||||
void stats_get_mem_info(struct worker* worker, struct ub_mem_stat_info* mem);
|
||||
|
||||
#endif /* DAEMON_STATS_H */
|
||||
|
||||
+4
-47
@@ -463,57 +463,13 @@ detach(void)
|
||||
#endif /* HAVE_DAEMON */
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
/* setup a listening ssl context, fatal_exit() on any failure */
|
||||
/** setup the remote and ticket keys */
|
||||
static void
|
||||
setup_listen_sslctx(void** ctx, int is_dot, int is_doh, struct config_file* cfg)
|
||||
{
|
||||
if(!(*ctx = listen_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL,
|
||||
cfg->tls_ciphers, cfg->tls_ciphersuites,
|
||||
(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0),
|
||||
is_dot, is_doh, cfg->tls_use_system_policy_versions))) {
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/* setups the needed ssl contexts, fatal_exit() on any failure */
|
||||
static void
|
||||
setup_sslctxs(struct daemon* daemon, struct config_file* cfg)
|
||||
setup_sslctx_remote(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||
fatal_exit("could not set up remote-control");
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
/* setup the session keys; the callback to use them will be
|
||||
* attached to each sslctx separately */
|
||||
if(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0) {
|
||||
if(!listen_sslctx_setup_ticket_keys(
|
||||
cfg->tls_session_ticket_keys.first)) {
|
||||
fatal_exit("could not set session ticket SSL_CTX");
|
||||
}
|
||||
}
|
||||
(void)setup_listen_sslctx(&daemon->listen_dot_sslctx, 1, 0, cfg);
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
if(cfg_has_https(cfg)) {
|
||||
(void)setup_listen_sslctx(&daemon->listen_doh_sslctx, 0, 1, cfg);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
if(cfg_has_quic(cfg)) {
|
||||
if(!(daemon->listen_quic_sslctx = quic_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL))) {
|
||||
fatal_exit("could not set up quic SSL_CTX");
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
}
|
||||
if(!(daemon->connect_dot_sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#else /* HAVE_SSL */
|
||||
(void)daemon;(void)cfg;
|
||||
#endif /* HAVE_SSL */
|
||||
@@ -545,7 +501,8 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
#endif
|
||||
|
||||
/* read ssl keys while superuser and outside chroot */
|
||||
(void)setup_sslctxs(daemon, cfg);
|
||||
setup_sslctx_remote(daemon, cfg);
|
||||
daemon_setup_sslctxs(daemon, cfg);
|
||||
|
||||
/* init syslog (as root) if needed, before daemonize, otherwise
|
||||
* a fork error could not be printed since daemonize closed stderr.*/
|
||||
|
||||
+57
-8
@@ -46,6 +46,7 @@
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/daemon.h"
|
||||
#include "daemon/remote.h"
|
||||
#include "daemon/metrics.h"
|
||||
#include "daemon/acl_list.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/config_file.h"
|
||||
@@ -255,7 +256,8 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error,
|
||||
return 0;
|
||||
}
|
||||
/* sanity check. */
|
||||
if(!LDNS_QR_WIRE(sldns_buffer_begin(c->buffer))
|
||||
if(sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE
|
||||
|| !LDNS_QR_WIRE(sldns_buffer_begin(c->buffer))
|
||||
|| LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) !=
|
||||
LDNS_PACKET_QUERY
|
||||
|| LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) > 1) {
|
||||
@@ -1444,6 +1446,24 @@ check_ip_ratelimit(struct worker* worker, struct sockaddr_storage* addr,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the callback function when a request arrives. It is passed
|
||||
* the packet and user argument. Return true to send a reply.
|
||||
* This is of type comm_point_callback_type. The struct comm_point contains
|
||||
* more comments on the comm_point.callback member about the function.
|
||||
* @param c: the comm_point where the request arrives on.
|
||||
* @param arg: the user argument for the callback, the worker.
|
||||
* @param error: This can be NETEVENT_NOERROR, NETEVENT_TIMEOUT,
|
||||
* NETEVENT_CLOSED or other comm point callback error values.
|
||||
* @param repinfo: The reply info, use it to send a reply. If the reply
|
||||
* is immediate, return 1. If the reply is later on return 0 and save
|
||||
* the repinfo, to call comm_point_send_reply on.
|
||||
* @return 1 to sent a reply straight away, for like cache response so that
|
||||
* no allocation needs to be done. And only internal preallocated buffers
|
||||
* are used. Return 0 and save the repinfo to reply later, for responses
|
||||
* that need to be looked up. Return 0 and call comm_point_drop_reply on
|
||||
* the repinfo to drop the response.
|
||||
*/
|
||||
int
|
||||
worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
struct comm_reply* repinfo)
|
||||
@@ -1657,8 +1677,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
if((ret=parse_edns_from_query_pkt(
|
||||
c->buffer, &edns, worker->env.cfg, c, repinfo,
|
||||
(worker->env.now ? *worker->env.now : time(NULL)),
|
||||
worker->scratchpad,
|
||||
*worker->env.now, worker->scratchpad,
|
||||
worker->daemon->cookie_secrets)) != 0) {
|
||||
struct edns_data reply_edns;
|
||||
verbose(VERB_ALGO, "worker parse edns: formerror.");
|
||||
@@ -2106,10 +2125,37 @@ worker_restart_timer(struct worker* worker)
|
||||
{
|
||||
if(worker->env.cfg->stat_interval > 0) {
|
||||
struct timeval tv;
|
||||
if(worker->daemon->stat_time_specific) {
|
||||
struct timeval dest, now;
|
||||
int interval = worker->env.cfg->stat_interval;
|
||||
int offset = worker->daemon->stat_time_offset;
|
||||
int nows, spec;
|
||||
if(gettimeofday(&now, NULL) < 0)
|
||||
log_err("gettimeofday: %s", strerror(errno));
|
||||
#ifndef S_SPLINT_S
|
||||
tv.tv_sec = worker->env.cfg->stat_interval;
|
||||
tv.tv_usec = 0;
|
||||
nows = (int)now.tv_sec;
|
||||
/* The next time is on the timer interval, at the
|
||||
* specific offset, time value % interval = offset. */
|
||||
/* It relies on the integer division below to drop the
|
||||
* remainder in order to calculate the expected
|
||||
* result. */
|
||||
spec = ((nows-offset)/interval+1)*interval+offset;
|
||||
/* This is instead of an assertion, and should not
|
||||
* be needed. So assert(spec > nows), tv is going to
|
||||
* be positive. */
|
||||
if(spec<=nows) spec += interval;
|
||||
dest.tv_sec = spec;
|
||||
dest.tv_usec = 0;
|
||||
#endif
|
||||
/* Subtract in timeval, so the fractions of a second
|
||||
* are rounded to the whole specific time. */
|
||||
timeval_subtract(&tv, &dest, &now);
|
||||
} else {
|
||||
#ifndef S_SPLINT_S
|
||||
tv.tv_sec = worker->env.cfg->stat_interval;
|
||||
tv.tv_usec = 0;
|
||||
#endif
|
||||
}
|
||||
comm_timer_set(worker->stat_timer, &tv);
|
||||
}
|
||||
}
|
||||
@@ -2184,9 +2230,6 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
struct dt_env* dtenv = &worker->dtenv;
|
||||
#else
|
||||
void* dtenv = NULL;
|
||||
#endif
|
||||
#ifdef HAVE_GETTID
|
||||
worker->thread_tid = gettid();
|
||||
#endif
|
||||
worker->need_to_exit = 0;
|
||||
worker->base = comm_base_create(do_sigs);
|
||||
@@ -2234,6 +2277,12 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
#ifdef USE_METRICS
|
||||
if(!daemon_metrics_attach(worker->daemon->metrics, worker)) {
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
#endif /* USE METRICS */
|
||||
#ifdef UB_ON_WINDOWS
|
||||
wsvc_setup_worker(worker);
|
||||
#endif /* UB_ON_WINDOWS */
|
||||
|
||||
+8
-7
@@ -366,22 +366,23 @@ static int
|
||||
dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* s;
|
||||
verbose(VERB_ALGO, "dns64-prefix: %s", cfg->dns64_prefix);
|
||||
if (!netblockstrtoaddr(cfg->dns64_prefix ? cfg->dns64_prefix :
|
||||
DEFAULT_DNS64_PREFIX, 0, &dns64_env->prefix_addr,
|
||||
const char* dns64_prefix = cfg->dns64_prefix ?
|
||||
cfg->dns64_prefix : DEFAULT_DNS64_PREFIX;
|
||||
verbose(VERB_ALGO, "dns64-prefix: %s", dns64_prefix);
|
||||
if (!netblockstrtoaddr(dns64_prefix, 0, &dns64_env->prefix_addr,
|
||||
&dns64_env->prefix_addrlen, &dns64_env->prefix_net)) {
|
||||
log_err("cannot parse dns64-prefix netblock: %s", cfg->dns64_prefix);
|
||||
log_err("cannot parse dns64-prefix netblock: %s", dns64_prefix);
|
||||
return 0;
|
||||
}
|
||||
if (!addr_is_ip6(&dns64_env->prefix_addr, dns64_env->prefix_addrlen)) {
|
||||
log_err("dns64_prefix is not IPv6: %s", cfg->dns64_prefix);
|
||||
log_err("dns64_prefix is not IPv6: %s", dns64_prefix);
|
||||
return 0;
|
||||
}
|
||||
if (dns64_env->prefix_net != 32 && dns64_env->prefix_net != 40 &&
|
||||
dns64_env->prefix_net != 48 && dns64_env->prefix_net != 56 &&
|
||||
dns64_env->prefix_net != 64 && dns64_env->prefix_net != 96 ) {
|
||||
log_err("dns64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
|
||||
cfg->dns64_prefix);
|
||||
log_err("dns64-prefix length is not 32, 40, 48, 56, 64 or 96: %s",
|
||||
dns64_prefix);
|
||||
return 0;
|
||||
}
|
||||
for(s = cfg->dns64_ignore_aaaa; s; s = s->next) {
|
||||
|
||||
+11
-1
@@ -448,6 +448,9 @@ int dt_io_thread_apply_cfg(struct dt_io_thread* dtio, struct config_file *cfg)
|
||||
dtio->tls_use_sni = cfg->tls_use_sni;
|
||||
#endif /* HAVE_SSL */
|
||||
}
|
||||
#ifdef HAVE_GETTID
|
||||
dtio->thread_tid_log = cfg->log_thread_id;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2130,7 +2133,14 @@ static void* dnstap_io(void* arg)
|
||||
struct dt_io_thread* dtio = (struct dt_io_thread*)arg;
|
||||
time_t secs = 0;
|
||||
struct timeval now;
|
||||
log_thread_set(&dtio->threadnum);
|
||||
|
||||
#if defined(HAVE_GETTID) && !defined(THREADS_DISABLED)
|
||||
dtio->thread_tid = gettid();
|
||||
if(dtio->thread_tid_log)
|
||||
log_thread_set(&dtio->thread_tid);
|
||||
else
|
||||
#endif
|
||||
log_thread_set(&dtio->threadnum);
|
||||
|
||||
/* setup */
|
||||
verbose(VERB_ALGO, "start dnstap io thread");
|
||||
|
||||
@@ -131,6 +131,12 @@ struct dt_io_thread {
|
||||
struct dt_io_list_item* io_list_iter;
|
||||
/** thread id, of the io thread */
|
||||
ub_thread_type tid;
|
||||
#ifdef HAVE_GETTID
|
||||
/** thread tid, the LWP id */
|
||||
pid_t thread_tid;
|
||||
/** if logging should include the LWP id */
|
||||
int thread_tid_log;
|
||||
#endif
|
||||
/** if the io processing has started */
|
||||
int started;
|
||||
/** ssl context for the io thread, for tls connections. type SSL_CTX* */
|
||||
|
||||
@@ -1561,12 +1561,20 @@ int main(int argc, char** argv)
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#endif /* HAVE_SSL */
|
||||
}
|
||||
|
||||
+241
@@ -1,3 +1,244 @@
|
||||
30 March 2026: Wouter
|
||||
- Merge #1408: Fix shared memory stats with threads.
|
||||
|
||||
27 March 2026: Wouter
|
||||
- Fix to allow the control-interface config to use ip@port notation.
|
||||
- Fix test code to allow empty hex answer packets from testbound.
|
||||
- Fix defense in depth for service callback with empty packet.
|
||||
|
||||
24 March 2026: Wouter
|
||||
- Fix to check for invalid http content length and chunk size,
|
||||
and to check the RR rdata field lengths when decompressing and
|
||||
inserting RRs from an authority zone transfer. This stops
|
||||
large memory use and heap buffer-overflow read errors. Thanks
|
||||
to Haruto Kimura (Stella) for the report.
|
||||
|
||||
20 March 2026: Wouter
|
||||
- Fix for testcode pktview to check buffer size and log errors.
|
||||
|
||||
13 March 2026: Yorgos
|
||||
- Fix to ignore out-of-zone DNAME records for CNAME synthesis. Thanks
|
||||
to Yuxiao Wu, Yiyi Wang, Zhang Chao, Baojun Liu, and Haixin Duan from
|
||||
Tsinghua University.
|
||||
|
||||
13 March 2026: Wouter
|
||||
- Fix #278: DoT: complete unbound restart required on certificate
|
||||
renew. Fix so that a reload checks if the files have changed, and
|
||||
if so, reload the contexts. Also for DoH, DoQ and outgoing DoT.
|
||||
- iana portlist updated.
|
||||
- For #278: fast_reload can reload tls-service-key, tls-service-pem
|
||||
and tls-cert-bundle changes. It checks the modification time of
|
||||
the tls-service-key and tls-service-pem files for update.
|
||||
- Fix detection of http listening port in fast_reload.
|
||||
- Fix to add tls-service-key to memory printout for fast_reload.
|
||||
|
||||
9 March 2026: Wouter
|
||||
- Fix compile failure in unbound-checkconf for older gcc compiler.
|
||||
- Merge #1418: Apply cache TTL policy to DNAME and synthesized
|
||||
CNAME on wire path.
|
||||
|
||||
6 March 2026: Wouter
|
||||
- Merge #1415: Add lock unlock for view in memory error handling.
|
||||
|
||||
6 March 2026: Yorgos
|
||||
- Document the suggestion for a higher value for 'outgoing-range';
|
||||
helps when the request list is full.
|
||||
- Warn for unused 'nodefault' local-zone configuration in
|
||||
unbound-checkconf (related to #1416).
|
||||
|
||||
5 March 2026: Wouter
|
||||
- Fix for DNS Rebinding Bypass via SVCB/HTTPS Records in Unbound.
|
||||
Thanks to Kunta Chu, School of Software, Tsinghua University,
|
||||
Taofei Guo, Peking University, and Jianjun Chen, Institute for
|
||||
Network Sciences and Cyberspace, Tsinghua University for the
|
||||
report. The private-address option is fixed to also elide
|
||||
SVCB and HTTPS records that match the filter.
|
||||
- Update generated man pages.
|
||||
|
||||
4 March 2026: Yorgos
|
||||
- For #1411: Introduce a failing case in the rpl test so that it only
|
||||
passes with the fix in place.
|
||||
|
||||
3 March 2026: Wouter
|
||||
- Merge #1411: Allow synthesized DNAME TTL=0 to be served from cache
|
||||
within grace period. The responses are served from cache within
|
||||
a 1-second grace period. Reduces recursion when authoritative
|
||||
servers return DNAME with TTL=0 (RFC 2308). Response
|
||||
still returns TTL=0 to clients. Adds a test for it.
|
||||
- For #1411: Fix that the lookup for DNAME uses flag. Fix assertion
|
||||
in expired calc debug routine.
|
||||
|
||||
27 February 2026: Wouter
|
||||
- Merge #1409: Documentation CNAME in redirect-type local-zone.
|
||||
- Update generated man pages.
|
||||
|
||||
25 February 2026: Wouter
|
||||
- Fix validator to set unchecked when validation recursion
|
||||
requests are passed. The edns subnet module checks if validation
|
||||
is needed for a cache response, and set the validator to protect
|
||||
the cache with validation for non-subnet lookups.
|
||||
|
||||
23 February 2026: Wouter
|
||||
- Fix to have cachedb not return expired bogus data as non-bogus.
|
||||
- Fix to make the cachedb_val_expired.crpl succeed.
|
||||
|
||||
23 February 2026: Yorgos
|
||||
- Fix to disallow cache lookup/store in external cachedb when a
|
||||
forwarder/stub forbids it with the no-cache option.
|
||||
- Fixed some typos reported in #1395 by rezky_nightky.
|
||||
|
||||
17 February 2026: Wouter
|
||||
- Fix to remove unused conditional from cookie timestamp at
|
||||
worker env.
|
||||
- For #1405: local-zone always_refuse also blocks queries of type DS.
|
||||
|
||||
16 February 2026: Yorgos
|
||||
- Fix #1404: Priming the root key fails after loading ipfire.org RPZ
|
||||
zones. Fixed by including the ZONEMD RRtype in the list of types to
|
||||
ignore for RPZ zones. Analysis and patch provided by ummeegge.
|
||||
|
||||
16 February 2026: Wouter
|
||||
- Fix that cachedb aggressive negative responses have the RA flag set.
|
||||
|
||||
11 February 2026: Wouter
|
||||
- Fix #1403: Inconsistency between do-nat64 and do-not-query-address
|
||||
during retries.
|
||||
|
||||
9 February 2026: Wouter
|
||||
- Merge #1401: Add a new build-time option for system TLS.
|
||||
The --enable-system-tls flag enables the
|
||||
tls-use-system-policy-versions setting by default.
|
||||
- Update generated man pages.
|
||||
|
||||
6 February 2026: Yorgos
|
||||
- Fix #1389: [FR] replacement with ECC-GOST12 according to RFC9558.
|
||||
Patch contributed by Igor V. Ruzanov, available in
|
||||
contrib/gost12.patch.
|
||||
|
||||
4 February 2026: Wouter
|
||||
- Fix local privilege escalation on Windows. Thanks to Hao Huang and
|
||||
CrisprXiang with Fudan University for the report. The OpenSSL
|
||||
init calls are set to not load the openssl.cnf file when compiled
|
||||
for Windows.
|
||||
|
||||
3 February 2026: Yorgos
|
||||
- Eagerly remove .skip mark files in between mini_tdir.sh runs in case
|
||||
there has been a change on the environment.
|
||||
|
||||
27 January 2026: Wouter
|
||||
- Add test for allow-notify with a host name.
|
||||
|
||||
26 January 2026: Wouter
|
||||
- Fix that allow-notify entries with hostnames are copied after IPv4
|
||||
and IPv6 lookup.
|
||||
- Fix to not skip allow-notify hostname lookups when there are only
|
||||
urls.
|
||||
|
||||
23 January 2026: Yorgos
|
||||
- Merge #1396: Log Linux thread ID.
|
||||
- On Linux systems log the system-wide unique thread ID instead of
|
||||
Unbound's internal thread counter.
|
||||
- Introduce the 'log-thread-id' configuration option to manage logging
|
||||
the system-wide Linux thread ID for easier debugging with system
|
||||
tools.
|
||||
- Update generated man pages.
|
||||
|
||||
22 January 2026: Wouter
|
||||
- Fix that fast reload copies the iter_scrub_ns, iter_scrub_cname
|
||||
and max_global_quota options.
|
||||
- Fix http test tool petal to not print errors when there is no
|
||||
error.
|
||||
|
||||
21 January 2026: Wouter
|
||||
- Merge #1388: QNX Porting support for unbound.
|
||||
|
||||
19 January 2026: Wouter
|
||||
- Merge #1392: Include "V" (version) option in synopsis.
|
||||
|
||||
15 January 2026: Wouter
|
||||
- Fix documentation for requestlist.overwritten and
|
||||
requestlist.exceeded, it explains which query was dropped.
|
||||
|
||||
8 January 2026: Wouter
|
||||
- Merge #1381: Do not initialize quic_table unless it is enabled.
|
||||
|
||||
6 January 2026: Wouter
|
||||
- Fix edns subnet, that scope zero queries, when there is a
|
||||
subquery without subnet, and the forward-no-cache or
|
||||
stub-no-cache option is set, it is not stored in cache due to
|
||||
the forward or stub option.
|
||||
|
||||
6 January 2026: Yorgos
|
||||
- Merge #1391 from Götz Görisch: Fix documentation to adhere to
|
||||
RFC5952.
|
||||
|
||||
31 December 2025: Yorgos
|
||||
- Update the unbound-anchor man page to note write permissions of the
|
||||
generated file if it is to be used with Unbound's
|
||||
auto-trust-anchor-file option.
|
||||
- Use the same EDE removal logic when encoding errors as when encoding
|
||||
replies.
|
||||
|
||||
30 December 2025: Yorgos
|
||||
- Mark "THROWAWAY" and "(DNSSEC) LAME" responses clearly as Unbound's
|
||||
categorization in the log output.
|
||||
|
||||
24 December 2025: Yorgos
|
||||
- More specific wording in the unbound.conf man page for stub-first
|
||||
and forward-first options.
|
||||
|
||||
3 December 2025: Wouter
|
||||
- Fix http2 drop handling to clear the postpone_drop state so that
|
||||
other streams on the http2 session are not affected by a drop,
|
||||
and can clean up properly if also dropped. Fix http2 send reply
|
||||
so that when there is a send failure is does not recurse into
|
||||
the mesh functions and also does not drop the connection due to
|
||||
the condition of one stream.
|
||||
|
||||
2 December 2025: Wouter
|
||||
- Fix to remove http2 stream mesh state when mesh new request is
|
||||
dropping the new request.
|
||||
|
||||
1 December 2025: Wouter
|
||||
- Fix to add EDNS CO flag to testbound and debug message log.
|
||||
- Fix header comment about EDE reference in validator/val_sigcrypt.h.
|
||||
|
||||
28 November 2025: Yorgos
|
||||
- For #1375, there is no DNSTAP environment if it wasn't configured.
|
||||
|
||||
26 November 2025: Yorgos
|
||||
- Tag for 1.24.2 release.
|
||||
The repository continues with version 1.24.3.
|
||||
|
||||
13 November 2025: Wouter
|
||||
- Merge #1374: Mesh reply counters.
|
||||
This adds the statistics num.queries.replyaddr_limit and
|
||||
requestlist.current.replies.
|
||||
- Merge #1375: Copy DNSTAP changes from daemon to workers after
|
||||
fast_reload.
|
||||
|
||||
12 November 2025: Wouter
|
||||
- Fix that when discard timeout drops packet, they are accounted as
|
||||
less reply addresses in use in the mesh area.
|
||||
- iana portlist updated.
|
||||
|
||||
6 November 2025: Wouter
|
||||
- Fix add comment to worker_handle_request function that explain it.
|
||||
- Fix configure test for noreturn attribute so it compiles without
|
||||
warning.
|
||||
- Fix configure test for nonstring attribute so that it does not
|
||||
accept when the compiler prints a warning about an unknown
|
||||
attribute.
|
||||
|
||||
4 November 2025: Wouter
|
||||
- Fix dns64 log output to log the default instead of a null string.
|
||||
|
||||
1 November 2025: Yorgos
|
||||
- Fix #1366: Infra cache does not work correctly for NAT64, by
|
||||
moving the NAT64 synthesis from the iterator when selecting a target
|
||||
address, to the delegation point itself when adding target
|
||||
addresses.
|
||||
|
||||
27 October 2025: Yorgos
|
||||
- Merge #1331 from Jitka Plesníková: Replace deprecated $function by
|
||||
new $action, for SWIG.
|
||||
|
||||
+3
-3
@@ -13,7 +13,7 @@ If you're not using DNSSEC then you may remove "validator".
|
||||
|
||||
2. The "dns64-prefix" directive indicates your DNS64 prefix. For example:
|
||||
|
||||
dns64-prefix: 64:FF9B::/96
|
||||
dns64-prefix: 64:ff9b::/96
|
||||
|
||||
The prefix must be a /96 or shorter.
|
||||
|
||||
@@ -42,9 +42,9 @@ To enable NAT64 in Unbound, add to unbound.conf's "server" section:
|
||||
do-nat64: yes
|
||||
|
||||
The NAT64 prefix defaults to the DNS64 prefix, which in turn defaults to the
|
||||
standard 64:FF9B::/96 prefix. You can reconfigure it with:
|
||||
standard 64:ff9b::/96 prefix. You can reconfigure it with:
|
||||
|
||||
nat64-prefix: 64:FF9B::/96
|
||||
nat64-prefix: 64:ff9b::/96
|
||||
|
||||
To test NAT64 operation, pick a domain that only has IPv4 reachability for its
|
||||
nameservers and try resolving any names in that domain.
|
||||
|
||||
+30
-9
@@ -54,7 +54,7 @@ server:
|
||||
# interface: 192.0.2.153
|
||||
# interface: 192.0.2.154
|
||||
# interface: 192.0.2.154@5003
|
||||
# interface: 2001:DB8::5
|
||||
# interface: 2001:db8::5
|
||||
# interface: eth0@5003
|
||||
|
||||
# enable this feature to copy the source address of queries to reply.
|
||||
@@ -72,12 +72,12 @@ server:
|
||||
# server from by ip-address. If none, the default (all) interface
|
||||
# is used. Specify every interface on a 'outgoing-interface:' line.
|
||||
# outgoing-interface: 192.0.2.153
|
||||
# outgoing-interface: 2001:DB8::5
|
||||
# outgoing-interface: 2001:DB8::6
|
||||
# outgoing-interface: 2001:db8::5
|
||||
# outgoing-interface: 2001:db8::6
|
||||
|
||||
# Specify a netblock to use remainder 64 bits as random bits for
|
||||
# upstream queries. Uses freebind option (Linux).
|
||||
# outgoing-interface: 2001:DB8::/64
|
||||
# outgoing-interface: 2001:db8::/64
|
||||
# Also (Linux:) ip -6 addr add 2001:db8::/64 dev lo
|
||||
# And: ip -6 route add local 2001:db8::/64 dev lo
|
||||
# And set prefer-ip6: yes to use the ip6 randomness from a netblock.
|
||||
@@ -379,7 +379,7 @@ server:
|
||||
# interface-action: 192.0.2.153 allow
|
||||
# interface-action: 192.0.2.154 allow
|
||||
# interface-action: 192.0.2.154@5003 allow
|
||||
# interface-action: 2001:DB8::5 allow
|
||||
# interface-action: 2001:db8::5 allow
|
||||
# interface-action: eth0@5003 allow
|
||||
|
||||
# Similar to 'access-control-tag:' but for interfaces.
|
||||
@@ -496,6 +496,10 @@ server:
|
||||
# print log lines that say why queries return SERVFAIL to clients.
|
||||
# log-servfail: no
|
||||
|
||||
# log system-wide Linux thread ID, insted of Unbound's internal thread
|
||||
# counter. Only on Linux and only when threads are available.
|
||||
# log-thread-id: no
|
||||
|
||||
# the pid file. Can be an absolute path outside of chroot/work dir.
|
||||
# pidfile: "@UNBOUND_PIDFILE@"
|
||||
|
||||
@@ -658,7 +662,7 @@ server:
|
||||
# or, just before the iterator).
|
||||
# module-config: "validator iterator"
|
||||
|
||||
# File with trusted keys, kept uptodate using RFC5011 probes,
|
||||
# File with trusted keys, kept up-to-date using RFC5011 probes,
|
||||
# initial file like trust-anchor-file, then it stores metadata.
|
||||
# Use several entries, one per domain name, to track multiple zones.
|
||||
#
|
||||
@@ -718,7 +722,7 @@ server:
|
||||
# val-max-restart: 5
|
||||
|
||||
# Should additional section of secure message also be kept clean of
|
||||
# unsecure data. Useful to shield the users of this validator from
|
||||
# non-secure data. Useful to shield the users of this validator from
|
||||
# potential bogus data in the additional section. All unsigned data
|
||||
# in the additional section is removed from secure messages.
|
||||
# val-clean-additional: yes
|
||||
@@ -967,8 +971,8 @@ server:
|
||||
# Allow general-purpose version-flexible TLS server configuration that
|
||||
# may be further restricted by the system's policy.
|
||||
# Use only if you want to support legacy TLS client connections.
|
||||
# Default is no and Unbound will only use the latest available TLS
|
||||
# version.
|
||||
# Default is a compilation choice.
|
||||
# With 'no' Unbound will only use the latest available TLS version.
|
||||
# Changing the value requires a reload.
|
||||
# tls-use-system-policy-versions: no
|
||||
|
||||
@@ -1155,6 +1159,23 @@ server:
|
||||
# Timeout in milliseconds for TCP queries to auth servers.
|
||||
# tcp-auth-query-timeout: 3000
|
||||
|
||||
# Enable the prometheus metrics HTTP endpoint. Default is no.
|
||||
# metrics-enable: no
|
||||
|
||||
# Interfaces to expose the HTTP endpoint on, default is on localhost.
|
||||
# Interfaces can be specified by IP address or interface name.
|
||||
# With an interface name, all IP addresses associated with that
|
||||
# interface are used. Default is 127.0.0.1 and ::1.
|
||||
# metrics-interface: 127.0.0.1
|
||||
# metrics-interface: ::1
|
||||
# metrics-interface: lo
|
||||
|
||||
# Port number for the HTTP metrics endpoint. Default is 9100.
|
||||
# metrics-port: 9100
|
||||
|
||||
# HTTP path for the metrics endpoint. Default is "/metrics".
|
||||
# metrics-path: "/metrics"
|
||||
|
||||
|
||||
# Python config section. To enable:
|
||||
# o use --with-pythonmodule to configure before compiling.
|
||||
|
||||
+1
-1
@@ -416,6 +416,6 @@ on a function return with file read failure.
|
||||
.SH AUTHOR
|
||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
||||
.SH COPYRIGHT
|
||||
1999-2025, NLnet Labs
|
||||
1999-2026, NLnet Labs
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
+13
-4
@@ -39,9 +39,17 @@ unbound-anchor \- Unbound @version@ anchor utility.
|
||||
validation.
|
||||
The program fetches the trust anchor with the method from \fI\%RFC 7958\fP when
|
||||
regular \fI\%RFC 5011\fP update fails to bring it up to date.
|
||||
It can be run (as root) from the commandline, or run as part of startup
|
||||
scripts.
|
||||
Before you start the \fI\%unbound(8)\fP DNS server.
|
||||
It can be run from the commandline, or run as part of startup scripts before
|
||||
you start the \fI\%unbound(8)\fP DNS server.
|
||||
.sp
|
||||
Note that if you want to use \fI\%RFC 5011\fP with Unbound (i.e., the
|
||||
\fI\%auto\-trust\-anchor\-file\fP option) so
|
||||
that trust anchor information is automatically tracked by Unbound during
|
||||
operation, the user that Unbound runs under (by default \(aqunbound\(aq) must have
|
||||
write permissions to the file and the directory the file lives in (for creating
|
||||
temporary files).
|
||||
In this case you would probably want to run this program as the designated
|
||||
Unbound user.
|
||||
.sp
|
||||
Suggested usage:
|
||||
.INDENT 0.0
|
||||
@@ -52,6 +60,7 @@ Suggested usage:
|
||||
# in the init scripts.
|
||||
# provide or update the root anchor (if necessary)
|
||||
unbound\-anchor \-a \(dq@UNBOUND_ROOTKEY_FILE@\(dq
|
||||
|
||||
# Please note usage of this root anchor is at your own risk
|
||||
# and under the terms of our LICENSE (see source).
|
||||
#
|
||||
@@ -295,6 +304,6 @@ Signature on the root key information.
|
||||
.SH AUTHOR
|
||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
||||
.SH COPYRIGHT
|
||||
1999-2025, NLnet Labs
|
||||
1999-2026, NLnet Labs
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
+12
-3
@@ -51,9 +51,17 @@ Description
|
||||
validation.
|
||||
The program fetches the trust anchor with the method from :rfc:`7958` when
|
||||
regular :rfc:`5011` update fails to bring it up to date.
|
||||
It can be run (as root) from the commandline, or run as part of startup
|
||||
scripts.
|
||||
Before you start the :doc:`unbound(8)</manpages/unbound>` DNS server.
|
||||
It can be run from the commandline, or run as part of startup scripts before
|
||||
you start the :doc:`unbound(8)</manpages/unbound>` DNS server.
|
||||
|
||||
Note that if you want to use :rfc:`5011` with Unbound (i.e., the
|
||||
:ref:`auto-trust-anchor-file<unbound.conf.auto-trust-anchor-file>` option) so
|
||||
that trust anchor information is automatically tracked by Unbound during
|
||||
operation, the user that Unbound runs under (by default 'unbound') must have
|
||||
write permissions to the file and the directory the file lives in (for creating
|
||||
temporary files).
|
||||
In this case you would probably want to run this program as the designated
|
||||
Unbound user.
|
||||
|
||||
Suggested usage:
|
||||
|
||||
@@ -62,6 +70,7 @@ Suggested usage:
|
||||
# in the init scripts.
|
||||
# provide or update the root anchor (if necessary)
|
||||
unbound-anchor -a "@UNBOUND_ROOTKEY_FILE@"
|
||||
|
||||
# Please note usage of this root anchor is at your own risk
|
||||
# and under the terms of our LICENSE (see source).
|
||||
#
|
||||
|
||||
@@ -88,6 +88,6 @@ Unbound configuration file.
|
||||
.SH AUTHOR
|
||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
||||
.SH COPYRIGHT
|
||||
1999-2025, NLnet Labs
|
||||
1999-2026, NLnet Labs
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
@@ -880,6 +880,11 @@ number of queries removed due to discard\-timeout by thread
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B threadX.num.queries_replyaddr_limit
|
||||
number of queries removed due to replyaddr limits by thread
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B threadX.num.queries_wait_limit
|
||||
number of queries removed due to wait\-limit by thread
|
||||
.UNINDENT
|
||||
@@ -973,6 +978,10 @@ Number of requests in the request list that were overwritten by newer
|
||||
entries.
|
||||
This happens if there is a flood of queries that recursive processing and
|
||||
the server has a hard time.
|
||||
The counter is increased when during the flood the
|
||||
\fI\%jostle\-timeout\fP
|
||||
allows a query to be removed in favor of a new incoming query.
|
||||
The older query is then dropped to make space.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -980,6 +989,12 @@ the server has a hard time.
|
||||
Queries that were dropped because the request list was full.
|
||||
This happens if a flood of queries need recursive processing, and the
|
||||
server can not keep up.
|
||||
The counter is increased when during the flood there is no space
|
||||
to be made with the jostle out of an older query, and the new query
|
||||
is dropped.
|
||||
Since no older queries are removed, see
|
||||
\fI\%jostle\-timeout\fP setting, there
|
||||
is no space for the new query.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -994,6 +1009,13 @@ Current size of the request list, only the requests from client queries.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B threadX.requestlist.current.replies
|
||||
Current count of the number of reply entries waiting on request list
|
||||
entries. Because a request list entry can send results to multiple reply
|
||||
addresses, this number may be larger than the size of the request list.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B threadX.recursion.time.avg
|
||||
Average time it took to answer queries that needed recursive processing.
|
||||
Note that queries that were answered from the cache are not in this average.
|
||||
@@ -1048,6 +1070,11 @@ summed over threads.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B total.num.queries_replyaddr_limit
|
||||
summed over threads.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B total.num.queries_wait_limit
|
||||
summed over threads.
|
||||
.UNINDENT
|
||||
@@ -1138,6 +1165,16 @@ summed over threads.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B total.requestlist.current.user
|
||||
summed over threads.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B total.requestlist.current.replies
|
||||
summed over threads.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B total.recursion.time.median
|
||||
averaged over threads.
|
||||
.UNINDENT
|
||||
@@ -1543,6 +1580,6 @@ directory with private keys (\fBunbound_server.key\fP and
|
||||
.SH AUTHOR
|
||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
||||
.SH COPYRIGHT
|
||||
1999-2025, NLnet Labs
|
||||
1999-2026, NLnet Labs
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
@@ -170,6 +170,8 @@ There are several commands that the server understands.
|
||||
:ref:`tcp-auth-query-timeout<unbound.conf.tcp-auth-query-timeout>`,
|
||||
:ref:`delay-close<unbound.conf.delay-close>`.
|
||||
:ref:`iter-scrub-promiscuous<unbound.conf.iter-scrub-promiscuous>`.
|
||||
:ref:`tls-service-key<unbound.conf.tls-service-key>`.
|
||||
:ref:`tls-service-pem<unbound.conf.tls-service-pem>`.
|
||||
|
||||
It does not work with
|
||||
:ref:`interface<unbound.conf.interface>` and
|
||||
@@ -815,6 +817,10 @@ number of statistic counters:
|
||||
number of queries removed due to discard-timeout by thread
|
||||
|
||||
|
||||
@@UAHL@unbound-control.stats@threadX.num.queries_replyaddr_limit@@
|
||||
number of queries removed due to replyaddr limits by thread
|
||||
|
||||
|
||||
@@UAHL@unbound-control.stats@threadX.num.queries_wait_limit@@
|
||||
number of queries removed due to wait-limit by thread
|
||||
|
||||
@@ -893,12 +899,22 @@ number of statistic counters:
|
||||
entries.
|
||||
This happens if there is a flood of queries that recursive processing and
|
||||
the server has a hard time.
|
||||
The counter is increased when during the flood the
|
||||
:ref:`jostle-timeout<unbound.conf.jostle-timeout>`
|
||||
allows a query to be removed in favor of a new incoming query.
|
||||
The older query is then dropped to make space.
|
||||
|
||||
|
||||
@@UAHL@unbound-control.stats@threadX.requestlist.exceeded@@
|
||||
Queries that were dropped because the request list was full.
|
||||
This happens if a flood of queries need recursive processing, and the
|
||||
server can not keep up.
|
||||
The counter is increased when during the flood there is no space
|
||||
to be made with the jostle out of an older query, and the new query
|
||||
is dropped.
|
||||
Since no older queries are removed, see
|
||||
:ref:`jostle-timeout<unbound.conf.jostle-timeout>` setting, there
|
||||
is no space for the new query.
|
||||
|
||||
|
||||
@@UAHL@unbound-control.stats@threadX.requestlist.current.all@@
|
||||
@@ -910,6 +926,12 @@ number of statistic counters:
|
||||
Current size of the request list, only the requests from client queries.
|
||||
|
||||
|
||||
@@UAHL@unbound-control.stats@threadX.requestlist.current.replies@@
|
||||
Current count of the number of reply entries waiting on request list
|
||||
entries. Because a request list entry can send results to multiple reply
|
||||
addresses, this number may be larger than the size of the request list.
|
||||
|
||||
|
||||
@@UAHL@unbound-control.stats@threadX.recursion.time.avg@@
|
||||
Average time it took to answer queries that needed recursive processing.
|
||||
Note that queries that were answered from the cache are not in this average.
|
||||
@@ -955,6 +977,10 @@ number of statistic counters:
|
||||
summed over threads.
|
||||
|
||||
|
||||
@@UAHL@unbound-control.stats@total.num.queries_replyaddr_limit@@
|
||||
summed over threads.
|
||||
|
||||
|
||||
@@UAHL@unbound-control.stats@total.num.queries_wait_limit@@
|
||||
summed over threads.
|
||||
|
||||
@@ -1027,6 +1053,14 @@ number of statistic counters:
|
||||
summed over threads.
|
||||
|
||||
|
||||
@@UAHL@unbound-control.stats@total.requestlist.current.user@@
|
||||
summed over threads.
|
||||
|
||||
|
||||
@@UAHL@unbound-control.stats@total.requestlist.current.replies@@
|
||||
summed over threads.
|
||||
|
||||
|
||||
@@UAHL@unbound-control.stats@total.recursion.time.median@@
|
||||
averaged over threads.
|
||||
|
||||
|
||||
@@ -185,6 +185,6 @@ encountered a fatal error.
|
||||
.SH AUTHOR
|
||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
||||
.SH COPYRIGHT
|
||||
1999-2025, NLnet Labs
|
||||
1999-2026, NLnet Labs
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
+2
-2
@@ -32,7 +32,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
unbound \- Unbound DNS validating resolver @version@.
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
\fBunbound\fP [\fB\-hdpv\fP] [\fB\-c <cfgfile>\fP]
|
||||
\fBunbound\fP [\fB\-hdpVv\fP] [\fB\-c <cfgfile>\fP]
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
\fBunbound\fP is a caching DNS resolver.
|
||||
@@ -118,6 +118,6 @@ Show the version number and build options, and exit.
|
||||
.SH AUTHOR
|
||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
||||
.SH COPYRIGHT
|
||||
1999-2025, NLnet Labs
|
||||
1999-2026, NLnet Labs
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
+95
-12
@@ -102,7 +102,7 @@ server:
|
||||
interface: 0.0.0.0
|
||||
interface: ::0
|
||||
access\-control: 10.0.0.0/8 allow
|
||||
access\-control: 2001:DB8::/64 allow
|
||||
access\-control: 2001:db8::/64 allow
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
@@ -382,6 +382,10 @@ Default depends on compile options.
|
||||
Larger numbers need extra resources from the operating system.
|
||||
For performance a very large value is best, use libevent to make this
|
||||
possible.
|
||||
Should be higher (preferably double) than the value of
|
||||
\fI\%num\-queries\-per\-thread\fP to
|
||||
account for cases where the request list is full and avoid file descriptor
|
||||
starvation.
|
||||
.sp
|
||||
Default: 4096 (libevent) / 960 (minievent) / 48 (windows)
|
||||
.UNINDENT
|
||||
@@ -1299,13 +1303,16 @@ Default: yes
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B tls\-use\-system\-policy\-versions: \fI<yes or no>\fP
|
||||
Enable or disable general\-puspose version\-flexible TLS server configuration
|
||||
Enable or disable general\-purpose version\-flexible TLS server configuration
|
||||
when serving TLS.
|
||||
This will allow the whole list of available TLS versions provided by the
|
||||
crypto library, which may have been further restricted by the system\(aqs
|
||||
crypto policy.
|
||||
.sp
|
||||
By default Unbound only uses the latest available TLS version.
|
||||
If disabled Unbound only uses the latest available TLS version.
|
||||
.sp
|
||||
The default depends on a compilation choice, it is set
|
||||
at @SYSTEM_TLS_DEFAULT@ .
|
||||
.sp
|
||||
\fBCAUTION:\fP
|
||||
.INDENT 7.0
|
||||
@@ -1321,7 +1328,7 @@ Changing the value requires a reload.
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
Default: no
|
||||
Default: @SYSTEM_TLS_DEFAULT@
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -1450,6 +1457,9 @@ The port number on which to provide DNS\-over\-QUIC service.
|
||||
Only interfaces configured with that port number as @number get the QUIC
|
||||
service.
|
||||
The interface uses QUIC for the UDP traffic on that port number.
|
||||
If it is set to 0, the server does not init QUIC code, and QUIC is
|
||||
disabled.
|
||||
This is similar to if QUIC is not in use, but then explicitly.
|
||||
.sp
|
||||
Default: 853
|
||||
.UNINDENT
|
||||
@@ -1927,6 +1937,16 @@ Default: no
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B log\-thread\-id: \fI<yes or no>\fP
|
||||
(Only on Linux and only when threads are available)
|
||||
Logs the system\-wide Linux thread ID instead of Unbound\(aqs internal thread
|
||||
counter.
|
||||
Can be useful when debugging with system tools.
|
||||
.sp
|
||||
Default: no
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B pidfile: \fI<filename>\fP
|
||||
The process id is written to the file.
|
||||
Default is \fB\(dq@UNBOUND_PIDFILE@\(dq\fP\&.
|
||||
@@ -2259,6 +2279,11 @@ This protects against so\-called DNS Rebinding, where a user browser is
|
||||
turned into a network proxy, allowing remote access through the browser to
|
||||
other parts of your private network.
|
||||
.sp
|
||||
The option removes resource records of types A, AAAA, SVCB and HTTPS
|
||||
that match the filter.
|
||||
Inside the SVCB and HTTPS records, the svcparams of type ipv4hint
|
||||
and ipv6hint are checked for matches.
|
||||
.sp
|
||||
Some names can be allowed to contain your private addresses, by default all
|
||||
the \fI\%local\-data\fP that you configured is
|
||||
allowed to, and you can specify additional names using
|
||||
@@ -2997,6 +3022,39 @@ local\-data: \(dqexample.com. A 127.0.0.1\(dq
|
||||
queries for \fBwww.example.com\fP and \fBwww.foo.example.com\fP are
|
||||
redirected, so that users with web browsers cannot access sites with
|
||||
suffix example.com.
|
||||
.sp
|
||||
A \fBCNAME\fP record can also be provided via local\-data:
|
||||
.INDENT 7.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
.ft C
|
||||
local\-zone: \(dqexample.com.\(dq redirect
|
||||
local\-data: \(dqexample.com. CNAME www.example.org.\(dq
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
In that case, the \fBCNAME\fP is resolved and the answer
|
||||
includes resolved target records as well.
|
||||
The \fBCNAME\fP record has to be with the zone name of the local\-zone,
|
||||
and there can be one CNAME, not more.
|
||||
The \fBCNAME\fP record has to be at the zone apex of the
|
||||
\fBredirect\fP zone, then it is used for redirection.
|
||||
The resolution proceeds with upstream DNS resolution, and
|
||||
that does not include the lookup in local zones.
|
||||
So the record is not able to point in local zones, but it
|
||||
can point to upstream DNS answers.
|
||||
.sp
|
||||
\fBCNAME\fP resolution is supported only in type \fBredirect\fP
|
||||
local\-zone, and in type \fBinform_redirect\fP local\-zone.
|
||||
.sp
|
||||
As different from \fBCNAME\fP records that are used elsewhere, in
|
||||
the \fBredirect\fP type local\-zone, it is supported that in the target
|
||||
of the record a wildcard label gets expanded to the query name, with
|
||||
for example: \fBexample.com. CNAME *.foo.net.\fP gets expanded
|
||||
to \fBwww.example.com. CNAME www.example.com.foo.net.\fP\&.
|
||||
.UNINDENT
|
||||
.INDENT 7.0
|
||||
.TP
|
||||
@@ -3055,6 +3113,9 @@ use IPv6 protocol and avoid any queries to IPv4.
|
||||
.B always_refuse
|
||||
Like \fI\%refuse\fP, but ignores
|
||||
local data and refuses the query.
|
||||
This type also blocks queries of type DS for the zone name.
|
||||
That can break the DNSSEC chain of trust, but it is refused anyway.
|
||||
The block for type DS assists in more completely blocking the zone.
|
||||
.UNINDENT
|
||||
.INDENT 7.0
|
||||
.TP
|
||||
@@ -3377,7 +3438,7 @@ zone section below.
|
||||
Configure local data shorthand for a PTR record with the reversed IPv4 or
|
||||
IPv6 address and the host name.
|
||||
For example \fB\(dq192.0.2.4 www.example.com\(dq\fP\&.
|
||||
TTL can be inserted like this: \fB\(dq2001:DB8::4 7200 www.example.com\(dq\fP
|
||||
TTL can be inserted like this: \fB\(dq2001:db8::4 7200 www.example.com\(dq\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -4135,6 +4196,9 @@ Default: no
|
||||
If enabled, a query is attempted without this stub section if it fails.
|
||||
The data could not be retrieved and would have caused SERVFAIL because the
|
||||
servers are unreachable, instead it is tried without this stub section.
|
||||
This can lead to using less specific configured forward/stub/auth zones if
|
||||
any, or end up to otherwise normal recursive resolution for that particular
|
||||
query.
|
||||
.sp
|
||||
Default: no
|
||||
.UNINDENT
|
||||
@@ -4255,9 +4319,11 @@ The cert must also match a CA from the
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B forward\-first: \fI<yes or no>\fP
|
||||
If a forwarded query is met with a SERVFAIL error, and this option is
|
||||
enabled, Unbound will fall back to normal recursive resolution for this
|
||||
query as if no query forwarding had been specified.
|
||||
If a forwarded query is met with a SERVFAIL error and this option is
|
||||
enabled Unbound will fall back to less specific resolution.
|
||||
This can lead to using less specific configured forward/stub/auth zones if
|
||||
any, or end up to otherwise normal recursive resolution for that particular
|
||||
query.
|
||||
.sp
|
||||
Default: no
|
||||
.UNINDENT
|
||||
@@ -4370,9 +4436,15 @@ does not support AXFR/IXFR for the zone, but if you used
|
||||
\fI\%url\fP to download the zonefile as a text file
|
||||
from a webserver that would work.
|
||||
.sp
|
||||
If you specify the hostname, you cannot use the domain from the zonefile,
|
||||
because it may not have that when retrieving that data, instead use a plain
|
||||
IP address to avoid a circular dependency on retrieving that IP address.
|
||||
\fBCAUTION:\fP
|
||||
.INDENT 7.0
|
||||
.INDENT 3.5
|
||||
If you specify the hostname, you cannot use the domain from the
|
||||
zonefile, because it may not have that when retrieving that data,
|
||||
instead use a plain IP address to avoid a circular dependency on
|
||||
retrieving that IP address.
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -4732,6 +4804,17 @@ Default: no
|
||||
Use a specific NAT64 prefix to reach IPv4\-only servers.
|
||||
The prefix length must be one of /32, /40, /48, /56, /64 or /96.
|
||||
.sp
|
||||
The NAT64 prefix is allowed by the
|
||||
\fI\%do\-not\-query\-address\fP option,
|
||||
so that there is a clear outcome of addresses in both; the NAT64 prefix
|
||||
is allowed.
|
||||
The IPv4 address could be filtered by the
|
||||
\fI\%do\-not\-query\-address\fP option,
|
||||
if needed.
|
||||
Allowing the NAT64 prefix is useful when using do\-not\-query\-address
|
||||
for a cluster of machines that is IPv6\-only and uses NAT64, but does
|
||||
not have internet access.
|
||||
.sp
|
||||
Default: 64:ff9b::/96 (same as \fI\%dns64\-prefix\fP)
|
||||
.UNINDENT
|
||||
.SH DNSCRYPT OPTIONS
|
||||
@@ -5907,6 +5990,6 @@ Default is to log to \fIsyslog(3)\fP\&.
|
||||
.SH AUTHOR
|
||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
||||
.SH COPYRIGHT
|
||||
1999-2025, NLnet Labs
|
||||
1999-2026, NLnet Labs
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
||||
+138
-12
@@ -102,7 +102,7 @@ all the options.
|
||||
interface: 0.0.0.0
|
||||
interface: ::0
|
||||
access-control: 10.0.0.0/8 allow
|
||||
access-control: 2001:DB8::/64 allow
|
||||
access-control: 2001:db8::/64 allow
|
||||
|
||||
.. _unbound.conf.clauses:
|
||||
|
||||
@@ -247,6 +247,8 @@ These options are part of the ``server:`` section.
|
||||
:doc:`unbound-control(8)</manpages/unbound-control>`.
|
||||
The counters are listed in
|
||||
:doc:`unbound-control(8)</manpages/unbound-control>`.
|
||||
The counters are also available from the metrics interface,
|
||||
:ref:`metrics-enable<unbound.conf.metrics-enable>` .
|
||||
Keeping track of more statistics takes time.
|
||||
|
||||
Default: no
|
||||
@@ -366,6 +368,10 @@ These options are part of the ``server:`` section.
|
||||
Larger numbers need extra resources from the operating system.
|
||||
For performance a very large value is best, use libevent to make this
|
||||
possible.
|
||||
Should be higher (preferably double) than the value of
|
||||
:ref:`num-queries-per-thread<unbound.conf.num-queries-per-thread>` to
|
||||
account for cases where the request list is full and avoid file descriptor
|
||||
starvation.
|
||||
|
||||
Default: 4096 (libevent) / 960 (minievent) / 48 (windows)
|
||||
|
||||
@@ -1044,9 +1050,13 @@ These options are part of the ``server:`` section.
|
||||
certificate is in the :ref:`tls-service-pem<unbound.conf.tls-service-pem>`
|
||||
file and it must also be specified if
|
||||
:ref:`tls-service-key<unbound.conf.tls-service-key>` is specified.
|
||||
Enabling or disabling this service requires a restart (a reload is not
|
||||
enough), because the key is read while root permissions are held and before
|
||||
chroot (if any).
|
||||
If the key is stored with root permissions or outside of chroot, then
|
||||
a change or enabling or disabling requires a restart (a reload is not
|
||||
enough).
|
||||
But if the key file (and tls-service-pem file) are accessible, then they
|
||||
are read in on reload, and fast_reload.
|
||||
The server checks the modification time of the file (and the filename)
|
||||
to see if the file has changed for reload.
|
||||
The ports enabled implicitly or explicitly via
|
||||
:ref:`tls-port<unbound.conf.tls-port>` and
|
||||
:ref:`https-port<unbound.conf.https-port>` do not provide normal DNS TCP
|
||||
@@ -1178,19 +1188,22 @@ These options are part of the ``server:`` section.
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@tls-use-system-policy-versions@@: *<yes or no>*
|
||||
Enable or disable general-puspose version-flexible TLS server configuration
|
||||
Enable or disable general-purpose version-flexible TLS server configuration
|
||||
when serving TLS.
|
||||
This will allow the whole list of available TLS versions provided by the
|
||||
crypto library, which may have been further restricted by the system's
|
||||
crypto policy.
|
||||
|
||||
By default Unbound only uses the latest available TLS version.
|
||||
If disabled Unbound only uses the latest available TLS version.
|
||||
|
||||
The default depends on a compilation choice, it is set
|
||||
at @SYSTEM_TLS_DEFAULT@ .
|
||||
|
||||
.. caution:: Use only if you want to support legacy TLS client connections.
|
||||
|
||||
.. note:: Changing the value requires a reload.
|
||||
|
||||
Default: no
|
||||
Default: @SYSTEM_TLS_DEFAULT@
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@pad-responses@@: *<yes or no>*
|
||||
@@ -1306,6 +1319,9 @@ These options are part of the ``server:`` section.
|
||||
Only interfaces configured with that port number as @number get the QUIC
|
||||
service.
|
||||
The interface uses QUIC for the UDP traffic on that port number.
|
||||
If it is set to 0, the server does not init QUIC code, and QUIC is
|
||||
disabled.
|
||||
This is similar to if QUIC is not in use, but then explicitly.
|
||||
|
||||
Default: 853
|
||||
|
||||
@@ -1714,6 +1730,15 @@ These options are part of the ``server:`` section.
|
||||
Default: no
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@log-thread-id@@: *<yes or no>*
|
||||
(Only on Linux and only when threads are available)
|
||||
Logs the system-wide Linux thread ID instead of Unbound's internal thread
|
||||
counter.
|
||||
Can be useful when debugging with system tools.
|
||||
|
||||
Default: no
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@pidfile@@: *<filename>*
|
||||
The process id is written to the file.
|
||||
Default is :file:`"@UNBOUND_PIDFILE@"`.
|
||||
@@ -2000,6 +2025,11 @@ These options are part of the ``server:`` section.
|
||||
turned into a network proxy, allowing remote access through the browser to
|
||||
other parts of your private network.
|
||||
|
||||
The option removes resource records of types A, AAAA, SVCB and HTTPS
|
||||
that match the filter.
|
||||
Inside the SVCB and HTTPS records, the svcparams of type ipv4hint
|
||||
and ipv6hint are checked for matches.
|
||||
|
||||
Some names can be allowed to contain your private addresses, by default all
|
||||
the :ref:`local-data<unbound.conf.local-data>` that you configured is
|
||||
allowed to, and you can specify additional names using
|
||||
@@ -2650,6 +2680,33 @@ These options are part of the ``server:`` section.
|
||||
redirected, so that users with web browsers cannot access sites with
|
||||
suffix example.com.
|
||||
|
||||
A ``CNAME`` record can also be provided via local-data:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
local-zone: "example.com." redirect
|
||||
local-data: "example.com. CNAME www.example.org."
|
||||
|
||||
In that case, the ``CNAME`` is resolved and the answer
|
||||
includes resolved target records as well.
|
||||
The ``CNAME`` record has to be with the zone name of the local-zone,
|
||||
and there can be one CNAME, not more.
|
||||
The ``CNAME`` record has to be at the zone apex of the
|
||||
``redirect`` zone, then it is used for redirection.
|
||||
The resolution proceeds with upstream DNS resolution, and
|
||||
that does not include the lookup in local zones.
|
||||
So the record is not able to point in local zones, but it
|
||||
can point to upstream DNS answers.
|
||||
|
||||
``CNAME`` resolution is supported only in type ``redirect``
|
||||
local-zone, and in type ``inform_redirect`` local-zone.
|
||||
|
||||
As different from ``CNAME`` records that are used elsewhere, in
|
||||
the ``redirect`` type local-zone, it is supported that in the target
|
||||
of the record a wildcard label gets expanded to the query name, with
|
||||
for example: ``example.com. CNAME *.foo.net.`` gets expanded
|
||||
to ``www.example.com. CNAME www.example.com.foo.net.``.
|
||||
|
||||
@@UAHL@unbound.conf.local-zone.type@inform@@
|
||||
The query is answered normally, same as
|
||||
:ref:`transparent<unbound.conf.local-zone.type.transparent>`.
|
||||
@@ -2689,6 +2746,9 @@ These options are part of the ``server:`` section.
|
||||
@@UAHL@unbound.conf.local-zone.type@always_refuse@@
|
||||
Like :ref:`refuse<unbound.conf.local-zone.type.refuse>`, but ignores
|
||||
local data and refuses the query.
|
||||
This type also blocks queries of type DS for the zone name.
|
||||
That can break the DNSSEC chain of trust, but it is refused anyway.
|
||||
The block for type DS assists in more completely blocking the zone.
|
||||
|
||||
@@UAHL@unbound.conf.local-zone.type@always_nxdomain@@
|
||||
Like :ref:`static<unbound.conf.local-zone.type.static>`, but ignores
|
||||
@@ -2896,7 +2956,7 @@ These options are part of the ``server:`` section.
|
||||
Configure local data shorthand for a PTR record with the reversed IPv4 or
|
||||
IPv6 address and the host name.
|
||||
For example ``"192.0.2.4 www.example.com"``.
|
||||
TTL can be inserted like this: ``"2001:DB8::4 7200 www.example.com"``
|
||||
TTL can be inserted like this: ``"2001:db8::4 7200 www.example.com"``
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@local-zone-tag@@: *<zone> <"list of tags">*
|
||||
@@ -3375,6 +3435,56 @@ These options are part of the ``server:`` section.
|
||||
|
||||
Default: no
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@metrics-enable@@: *<yes or no>*
|
||||
Enable the prometheus metrics HTTP endpoint.
|
||||
It exposes the same statistics as the
|
||||
:ref:`stats_noreset<unbound-control.commands.stats_noreset>`,
|
||||
command, but with metric names
|
||||
following the prometheus specification. (Requires libevent2)
|
||||
|
||||
Use it with settings, extended-statistics: yes that collects more
|
||||
information,
|
||||
:ref:`extended-statistics<unbound.conf.extended-statistics>` .
|
||||
And set statistics-cumulative: yes, because the metrics are
|
||||
defined as cumulative counters for the number of queries,
|
||||
:ref:`statistics-cumulative<unbound.conf.statistics-cumulative>` .
|
||||
|
||||
Access from the metrics endpoint does not reset the statistics.
|
||||
Beware, if statistics-cumulative is disabled, that when using
|
||||
:ref:`stats<unbound-control.commands.stats`
|
||||
(instead of stats_noreset), the statistics will be reset for
|
||||
the HTTP metrics endpoint as well.
|
||||
With statistics-cumulative enabled, the stats (and stats_noreset)
|
||||
command can be used to also get a look at the statistics information.
|
||||
|
||||
Default: no
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@metrics-interface@@: *<ip4 or ip6[@port] | interface name>*
|
||||
Unbound will bind to the listed addresses or interfaces to serve the
|
||||
prometheus metrics.
|
||||
Can be given multiple times to bind multiple ip-addresses.
|
||||
Use 0.0.0.0 and ::0 to bind to the wildcard interface.
|
||||
|
||||
If an interface name is used instead of ip4 or ip6, the list of IP
|
||||
addresses associated with that interface is picked up and used at
|
||||
server start.
|
||||
|
||||
Default is 127.0.0.1 and ::1.
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@metrics-port@@: *<number>*
|
||||
The port number for the HTTP service.
|
||||
|
||||
Default is 9100.
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@metrics-path@@: *<string>*
|
||||
The HTTP path to expose the metrics at.
|
||||
|
||||
Default is "/metrics".
|
||||
|
||||
.. _unbound.conf.remote:
|
||||
|
||||
Remote Control Options
|
||||
@@ -3399,7 +3509,7 @@ To setup the correct self-signed certificates use the
|
||||
Default: no
|
||||
|
||||
|
||||
@@UAHL@unbound.conf.remote@control-interface@@: *<IP address or interface name or path>*
|
||||
@@UAHL@unbound.conf.remote@control-interface@@: *<IP address or interface name[@port] or path>*
|
||||
Give IPv4 or IPv6 addresses or local socket path to listen on for control
|
||||
commands.
|
||||
If an interface name is used instead of an IP address, the list of IP
|
||||
@@ -3587,6 +3697,9 @@ The :ref:`local-zone: nodefault<unbound.conf.local-zone.type.nodefault>` (or
|
||||
If enabled, a query is attempted without this stub section if it fails.
|
||||
The data could not be retrieved and would have caused SERVFAIL because the
|
||||
servers are unreachable, instead it is tried without this stub section.
|
||||
This can lead to using less specific configured forward/stub/auth zones if
|
||||
any, or end up to otherwise normal recursive resolution for that particular
|
||||
query.
|
||||
|
||||
Default: no
|
||||
|
||||
@@ -3699,9 +3812,11 @@ cache).
|
||||
|
||||
|
||||
@@UAHL@unbound.conf.forward@forward-first@@: *<yes or no>*
|
||||
If a forwarded query is met with a SERVFAIL error, and this option is
|
||||
enabled, Unbound will fall back to normal recursive resolution for this
|
||||
query as if no query forwarding had been specified.
|
||||
If a forwarded query is met with a SERVFAIL error and this option is
|
||||
enabled Unbound will fall back to less specific resolution.
|
||||
This can lead to using less specific configured forward/stub/auth zones if
|
||||
any, or end up to otherwise normal recursive resolution for that particular
|
||||
query.
|
||||
|
||||
Default: no
|
||||
|
||||
@@ -4144,6 +4259,17 @@ servers.
|
||||
Use a specific NAT64 prefix to reach IPv4-only servers.
|
||||
The prefix length must be one of /32, /40, /48, /56, /64 or /96.
|
||||
|
||||
The NAT64 prefix is allowed by the
|
||||
:ref:`do-not-query-address<unbound.conf.do-not-query-address>` option,
|
||||
so that there is a clear outcome of addresses in both; the NAT64 prefix
|
||||
is allowed.
|
||||
The IPv4 address could be filtered by the
|
||||
:ref:`do-not-query-address<unbound.conf.do-not-query-address>` option,
|
||||
if needed.
|
||||
Allowing the NAT64 prefix is useful when using do-not-query-address
|
||||
for a cluster of machines that is IPv6-only and uses NAT64, but does
|
||||
not have internet access.
|
||||
|
||||
Default: 64:ff9b::/96 (same as :ref:`dns64-prefix<unbound.conf.dns64.dns64-prefix>`)
|
||||
|
||||
.. _unbound.conf.dnscrypt:
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ unbound(8)
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
**unbound** [``-hdpv``] [``-c <cfgfile>``]
|
||||
**unbound** [``-hdpVv``] [``-c <cfgfile>``]
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
+24
-4
@@ -162,8 +162,15 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
||||
if(!ecs_is_whitelisted(sn_env->whitelist,
|
||||
addr, addrlen, qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qclass)) {
|
||||
verbose(VERB_ALGO, "subnet store subquery global, name and addr have no subnet treatment.");
|
||||
qstate->no_cache_store = 0;
|
||||
/* The stub or forward can have no_cache set.*/
|
||||
if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)) {
|
||||
verbose(VERB_ALGO, "subnet subquery is not stored globally, stuborfwd is no_cache");
|
||||
} else {
|
||||
verbose(VERB_ALGO, "subnet store subquery global, name and addr have no subnet treatment.%s",
|
||||
(sq->started_no_cache_store?
|
||||
" But the subnet module was started with no_cache_store for the super query, and that is still applied to this query":""));
|
||||
qstate->no_cache_store = sq->started_no_cache_store;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
@@ -476,6 +483,8 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq,
|
||||
struct addrtree *tree;
|
||||
struct addrnode *node;
|
||||
uint8_t scope;
|
||||
int must_validate = (!(qstate->query_flags&BIT_CD)
|
||||
|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
|
||||
|
||||
memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out));
|
||||
|
||||
@@ -508,7 +517,14 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq,
|
||||
if (!qstate->return_msg) { /* Failed allocation or expired TTL */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(qstate->return_msg->rep->security == sec_status_unchecked
|
||||
&& must_validate) {
|
||||
/* The message has to be validated first. */
|
||||
verbose(VERB_ALGO, "subnet: unchecked cache entry needs "
|
||||
"validation");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sq->subnet_downstream) { /* relay to interested client */
|
||||
sq->ecs_client_out.subnet_scope_mask = scope;
|
||||
sq->ecs_client_out.subnet_addr_fam = ecs->subnet_addr_fam;
|
||||
@@ -563,7 +579,10 @@ generate_sub_request(struct module_qstate *qstate, int id, struct subnet_qstate*
|
||||
qflags |= BIT_RD;
|
||||
if((qstate->query_flags & BIT_CD)!=0) {
|
||||
qflags |= BIT_CD;
|
||||
valrec = 1;
|
||||
/* The valrec is left off. Leave out: valrec = 1;
|
||||
* So that the cache is protected with DNSSEC validation.
|
||||
* Just like the global cache. DNSSEC validation is performed
|
||||
* regardless of the setting of the querier's CD flag. */
|
||||
}
|
||||
|
||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||
@@ -580,6 +599,7 @@ generate_sub_request(struct module_qstate *qstate, int id, struct subnet_qstate*
|
||||
}
|
||||
subsq = (struct subnet_qstate*)subq->minfo[id];
|
||||
subsq->is_subquery_nonsubnet = 1;
|
||||
subsq->started_no_cache_store = sq->started_no_cache_store;
|
||||
|
||||
/* When the client asks 0.0.0.0/0 and the name is not treated
|
||||
* as subnet, it is to be stored in the global cache.
|
||||
|
||||
+167
-1
@@ -207,6 +207,168 @@ size_t priv_get_mem(struct iter_priv* priv)
|
||||
return sizeof(*priv) + regional_get_mem(priv->region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if svcparam ipv4hint contains a private address.
|
||||
* @param priv: private address lookup struct.
|
||||
* @param d: the data bytes.
|
||||
* @param data_len: number of data bytes in the svcparam.
|
||||
* @param addr: address to return the private address to log in to.
|
||||
* It has space for IPv4 and IPv6 addresses.
|
||||
* @param addrlen: length of the addr. Returns the correct size for the addr.
|
||||
* @return true if the rdata contains a private address.
|
||||
*/
|
||||
static int svcb_ipv4hint_contains_priv_addr(struct iter_priv* priv,
|
||||
uint8_t* d, uint16_t data_len, struct sockaddr_storage* addr,
|
||||
socklen_t* addrlen)
|
||||
{
|
||||
struct sockaddr_in sa;
|
||||
*addrlen = (socklen_t)sizeof(struct sockaddr_in);
|
||||
memset(&sa, 0, sizeof(struct sockaddr_in));
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
|
||||
while(data_len >= LDNS_IP4ADDRLEN) {
|
||||
memmove(&sa.sin_addr, d, LDNS_IP4ADDRLEN);
|
||||
memmove(addr, &sa, *addrlen);
|
||||
if(priv_lookup_addr(priv, addr, *addrlen))
|
||||
return 1;
|
||||
|
||||
d += LDNS_IP4ADDRLEN;
|
||||
data_len -= LDNS_IP4ADDRLEN;
|
||||
}
|
||||
/* if data_len != 0 here, then the svcparam is malformed. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if svcparam ipv6hint contains a private address.
|
||||
* @param priv: private address lookup struct.
|
||||
* @param d: the data bytes.
|
||||
* @param data_len: number of data bytes in the svcparam.
|
||||
* @param addr: address to return the private address to log in to.
|
||||
* It has space for IPv4 and IPv6 addresses.
|
||||
* @param addrlen: length of the addr. Returns the correct size for the addr.
|
||||
* @return true if the rdata contains a private address.
|
||||
*/
|
||||
static int svcb_ipv6hint_contains_priv_addr(struct iter_priv* priv,
|
||||
uint8_t* d, uint16_t data_len, struct sockaddr_storage* addr,
|
||||
socklen_t* addrlen)
|
||||
{
|
||||
struct sockaddr_in6 sa;
|
||||
*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
|
||||
memset(&sa, 0, sizeof(struct sockaddr_in6));
|
||||
sa.sin6_family = AF_INET6;
|
||||
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
|
||||
while(data_len >= LDNS_IP6ADDRLEN) {
|
||||
memmove(&sa.sin6_addr, d, LDNS_IP6ADDRLEN);
|
||||
memmove(addr, &sa, *addrlen);
|
||||
if(priv_lookup_addr(priv, addr, *addrlen))
|
||||
return 1;
|
||||
|
||||
d += LDNS_IP6ADDRLEN;
|
||||
data_len -= LDNS_IP6ADDRLEN;
|
||||
}
|
||||
/* if data_len != 0 here, then the svcparam is malformed. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if type SVCB and HTTPS rdata contains a private address.
|
||||
* @param priv: private address lookup struct.
|
||||
* @param pkt: the packet.
|
||||
* @param rr: the rr with rdata to check.
|
||||
* @param addr: address to return the private address to log in to.
|
||||
* @param addrlen: length of the addr. Initially the total size, on
|
||||
* return the correct size for the addr.
|
||||
* @return true if the rdata contains a private address.
|
||||
*/
|
||||
static int svcb_rr_contains_priv_addr(struct iter_priv* priv,
|
||||
sldns_buffer* pkt, struct rr_parse* rr, struct sockaddr_storage* addr,
|
||||
socklen_t* addrlen)
|
||||
{
|
||||
uint8_t* d = rr->ttl_data;
|
||||
uint16_t svcparamkey, data_len, rdatalen;
|
||||
size_t oldpos, dname_len, dname_start, dname_compr_len;
|
||||
d += 4; /* skip TTL */
|
||||
rdatalen = sldns_read_uint16(d); /* read rdata length */
|
||||
d += 2;
|
||||
|
||||
if(rdatalen < 2 /* priority */ + 1 /* 1 length target */)
|
||||
return 0; /* malformed, too short */
|
||||
d += 2; /* skip priority */
|
||||
rdatalen -= 2;
|
||||
oldpos = sldns_buffer_position(pkt);
|
||||
sldns_buffer_set_position(pkt, (size_t)(d - sldns_buffer_begin(pkt)));
|
||||
dname_start = sldns_buffer_position(pkt);
|
||||
dname_len = pkt_dname_len(pkt);
|
||||
dname_compr_len = sldns_buffer_position(pkt) - dname_start;
|
||||
sldns_buffer_set_position(pkt, oldpos);
|
||||
if(dname_len == 0)
|
||||
return 0; /* dname malformed */
|
||||
if(dname_compr_len > rdatalen)
|
||||
return 0; /* malformed */
|
||||
d += dname_compr_len; /* skip target */
|
||||
rdatalen -= dname_compr_len;
|
||||
|
||||
while(rdatalen >= 4) {
|
||||
svcparamkey = sldns_read_uint16(d);
|
||||
data_len = sldns_read_uint16(d+2);
|
||||
d += 4;
|
||||
rdatalen -= 4;
|
||||
|
||||
/* verify that we have data_len data */
|
||||
if(data_len > rdatalen) {
|
||||
/* It is malformed, but if there are addresses
|
||||
* in there it can be rejected. */
|
||||
data_len = rdatalen;
|
||||
}
|
||||
|
||||
if(!data_len)
|
||||
continue; /* no data for the svcparamkey */
|
||||
|
||||
if(svcparamkey == SVCB_KEY_IPV4HINT) {
|
||||
if(svcb_ipv4hint_contains_priv_addr(priv, d, data_len,
|
||||
addr, addrlen))
|
||||
return 1;
|
||||
} else if(svcparamkey == SVCB_KEY_IPV6HINT) {
|
||||
if(svcb_ipv6hint_contains_priv_addr(priv, d, data_len,
|
||||
addr, addrlen))
|
||||
return 1;
|
||||
}
|
||||
d += data_len;
|
||||
rdatalen -= data_len;
|
||||
}
|
||||
/* If rdatalen != 0 here, then the svcb rdata is malformed. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the SVCB and HTTPS rrset is bad.
|
||||
* @param priv: private address lookup struct.
|
||||
* @param pkt: the packet.
|
||||
* @param rrset: the rrset to check.
|
||||
* @return 1 if the entire rrset has to be removed. 0 if not.
|
||||
* It removes RRs if they have private addresses, and log that.
|
||||
*/
|
||||
static int priv_svcb_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
|
||||
struct rrset_parse* rrset)
|
||||
{
|
||||
struct rr_parse* rr, *prev = NULL;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen = (socklen_t)sizeof(addr);
|
||||
for(rr = rrset->rr_first; rr; rr = rr->next) {
|
||||
if(svcb_rr_contains_priv_addr(priv, pkt, rr, &addr,
|
||||
&addrlen)) {
|
||||
if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, rr, &addr, addrlen))
|
||||
return 1;
|
||||
continue;
|
||||
}
|
||||
prev = rr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
|
||||
struct rrset_parse* rrset)
|
||||
{
|
||||
@@ -268,7 +430,11 @@ int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
|
||||
}
|
||||
prev = rr;
|
||||
}
|
||||
}
|
||||
} else if(rrset->type == LDNS_RR_TYPE_SVCB ||
|
||||
rrset->type == LDNS_RR_TYPE_HTTPS) {
|
||||
if(priv_svcb_rrset_bad(priv, pkt, rrset))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+55
-11
@@ -285,6 +285,17 @@ synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias,
|
||||
return NULL;
|
||||
memmove(cn->rr_first->ttl_data, rrset->rr_first->ttl_data,
|
||||
sizeof(uint32_t)); /* RFC6672: synth CNAME TTL == DNAME TTL */
|
||||
/* Apply cache TTL policy so DNAME and synthesized CNAME stay equal
|
||||
* and respect cache-min-ttl/cache-max-ttl (same as rdata_copy path). */
|
||||
if(!SERVE_ORIGINAL_TTL) {
|
||||
uint32_t ttl = sldns_read_uint32(cn->rr_first->ttl_data);
|
||||
time_t ttl_t = (time_t)ttl;
|
||||
if(ttl_t < MIN_TTL) ttl_t = MIN_TTL;
|
||||
if(ttl_t > MAX_TTL) ttl_t = MAX_TTL;
|
||||
ttl = (uint32_t)ttl_t;
|
||||
sldns_write_uint32(cn->rr_first->ttl_data, ttl);
|
||||
sldns_write_uint32(rrset->rr_first->ttl_data, ttl);
|
||||
}
|
||||
sldns_write_uint16(cn->rr_first->ttl_data+4, aliaslen);
|
||||
memmove(cn->rr_first->ttl_data+6, alias, aliaslen);
|
||||
cn->rr_first->size = sizeof(uint16_t)+aliaslen;
|
||||
@@ -418,12 +429,13 @@ shorten_rrset(sldns_buffer* pkt, struct rrset_parse* rrset, int count)
|
||||
* @param qinfo: original query.
|
||||
* @param region: where to allocate synthesized CNAMEs.
|
||||
* @param env: module env with config options.
|
||||
* @param zonename: name of server zone.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
static int
|
||||
scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, struct regional* region,
|
||||
struct module_env* env)
|
||||
struct module_env* env, uint8_t* zonename)
|
||||
{
|
||||
uint8_t* sname = qinfo->qname;
|
||||
size_t snamelen = qinfo->qname_len;
|
||||
@@ -431,7 +443,8 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
int cname_length = 0; /* number of CNAMEs, or DNAMEs */
|
||||
|
||||
if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR &&
|
||||
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN)
|
||||
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN &&
|
||||
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_YXDOMAIN)
|
||||
return 1;
|
||||
|
||||
/* For the ANSWER section, remove all "irrelevant" records and add
|
||||
@@ -453,8 +466,9 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
if(rrset->type == LDNS_RR_TYPE_DNAME &&
|
||||
pkt_strict_sub(pkt, sname, rrset->dname)) {
|
||||
if(rrset->type == LDNS_RR_TYPE_DNAME &&
|
||||
pkt_strict_sub(pkt, sname, rrset->dname) &&
|
||||
pkt_sub(pkt, rrset->dname, zonename)) {
|
||||
/* check if next rrset is correct CNAME. else,
|
||||
* synthesize a CNAME */
|
||||
struct rrset_parse* nx = rrset->rrset_all_next;
|
||||
@@ -470,6 +484,11 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
&aliaslen, pkt)) {
|
||||
verbose(VERB_ALGO, "synthesized CNAME "
|
||||
"too long");
|
||||
if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_YXDOMAIN) {
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
cname_length++;
|
||||
@@ -495,8 +514,6 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
log_err("out of memory synthesizing CNAME");
|
||||
return 0;
|
||||
}
|
||||
/* FIXME: resolve the conflict between synthesized
|
||||
* CNAME ttls and the cache. */
|
||||
rrset = nx;
|
||||
continue;
|
||||
|
||||
@@ -518,7 +535,8 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
if(nx && nx->section == LDNS_SECTION_ANSWER &&
|
||||
nx->type == LDNS_RR_TYPE_DNAME &&
|
||||
nx->rr_count == 1 &&
|
||||
pkt_strict_sub(pkt, sname, nx->dname)) {
|
||||
pkt_strict_sub(pkt, sname, nx->dname) &&
|
||||
pkt_sub(pkt, nx->dname, zonename)) {
|
||||
/* there is a DNAME after this CNAME, it
|
||||
* is in the ANSWER section, and the DNAME
|
||||
* applies to the name we cover */
|
||||
@@ -650,6 +668,29 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
/* Also delete promiscuous NS for other RCODEs */
|
||||
if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR
|
||||
&& env->cfg->iter_scrub_promiscuous) {
|
||||
remove_rrset("normalize: removing promiscuous "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
/* Also delete promiscuous NS for NOERROR with nodata
|
||||
* for authoritative answers, not for delegations.
|
||||
* NOERROR with an_rrsets!=0 already handled.
|
||||
* Also NOERROR and soa_in_auth already handled.
|
||||
* NOERROR with an_rrsets==0, and not a referral.
|
||||
* referral is (NS not the zonename, noSOA).
|
||||
*/
|
||||
if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR
|
||||
&& msg->an_rrsets == 0
|
||||
&& !(dname_pkt_compare(pkt, rrset->dname,
|
||||
zonename) != 0 && !soa_in_auth(msg))
|
||||
&& env->cfg->iter_scrub_promiscuous) {
|
||||
remove_rrset("normalize: removing promiscuous "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
if(nsset == NULL) {
|
||||
nsset = rrset;
|
||||
} else {
|
||||
@@ -942,8 +983,10 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
}
|
||||
|
||||
/* remove private addresses */
|
||||
if( (rrset->type == LDNS_RR_TYPE_A ||
|
||||
rrset->type == LDNS_RR_TYPE_AAAA)) {
|
||||
if(rrset->type == LDNS_RR_TYPE_A ||
|
||||
rrset->type == LDNS_RR_TYPE_AAAA ||
|
||||
rrset->type == LDNS_RR_TYPE_SVCB ||
|
||||
rrset->type == LDNS_RR_TYPE_HTTPS) {
|
||||
|
||||
/* do not set servfail since this leads to too
|
||||
* many drops of other people using rfc1918 space */
|
||||
@@ -1060,7 +1103,8 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
/* this is not required for basic operation but is a forgery
|
||||
* resistance (security) feature */
|
||||
if((FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR ||
|
||||
FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN) &&
|
||||
FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN ||
|
||||
FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_YXDOMAIN) &&
|
||||
msg->qdcount == 0)
|
||||
return 0;
|
||||
|
||||
@@ -1074,7 +1118,7 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
}
|
||||
|
||||
/* normalize the response, this cleans up the additional. */
|
||||
if(!scrub_normalize(pkt, msg, qinfo, region, env))
|
||||
if(!scrub_normalize(pkt, msg, qinfo, region, env, zonename))
|
||||
return 0;
|
||||
/* delete all out-of-zone information */
|
||||
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate))
|
||||
|
||||
+46
-4
@@ -253,7 +253,9 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** filter out unsuitable targets
|
||||
/** filter out unsuitable targets.
|
||||
* Applies NAT64 if needed as well by replacing the IPv4 with the synthesized
|
||||
* IPv6 address.
|
||||
* @param iter_env: iterator environment with ipv6-support flag.
|
||||
* @param env: module environment with infra cache.
|
||||
* @param name: zone name
|
||||
@@ -306,9 +308,30 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
if(a->bogus)
|
||||
return -1; /* address of server is bogus */
|
||||
if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) {
|
||||
log_addr(VERB_ALGO, "skip addr on the donotquery list",
|
||||
&a->addr, a->addrlen);
|
||||
return -1; /* server is on the donotquery list */
|
||||
if(iter_env->nat64.use_nat64 &&
|
||||
addr_is_ip6(&a->addr, a->addrlen) &&
|
||||
a->addrlen == iter_env->nat64.nat64_prefix_addrlen &&
|
||||
addr_in_common(&a->addr, 128,
|
||||
&iter_env->nat64.nat64_prefix_addr,
|
||||
iter_env->nat64.nat64_prefix_net,
|
||||
iter_env->nat64.nat64_prefix_addrlen) ==
|
||||
iter_env->nat64.nat64_prefix_net) {
|
||||
/* The NAT64 is enabled, and address is IPv6, it is
|
||||
* in the NAT64 prefix. It is allowed.
|
||||
* So that in an IPv6-only cluster without internet
|
||||
* access, that makes the NAT64 translation continue
|
||||
* to work. The NAT64 prefix is allowed. */
|
||||
/* Otherwise, after a timeout, the already NAT64
|
||||
* translated address would be treated differently,
|
||||
* and that causes confusion. */
|
||||
log_addr(VERB_ALGO, "the addr is on the donotquery "
|
||||
"list, but allowed because it is NAT64",
|
||||
&a->addr, a->addrlen);
|
||||
} else {
|
||||
log_addr(VERB_ALGO, "skip addr on the donotquery list",
|
||||
&a->addr, a->addrlen);
|
||||
return -1; /* server is on the donotquery list */
|
||||
}
|
||||
}
|
||||
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) {
|
||||
return -1; /* there is no ip6 available */
|
||||
@@ -317,6 +340,20 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
!addr_is_ip6(&a->addr, a->addrlen)) {
|
||||
return -1; /* there is no ip4 available */
|
||||
}
|
||||
if(iter_env->nat64.use_nat64 && !addr_is_ip6(&a->addr, a->addrlen)) {
|
||||
struct sockaddr_storage real_addr;
|
||||
socklen_t real_addrlen;
|
||||
addr_to_nat64(&a->addr, &iter_env->nat64.nat64_prefix_addr,
|
||||
iter_env->nat64.nat64_prefix_addrlen,
|
||||
iter_env->nat64.nat64_prefix_net,
|
||||
&real_addr, &real_addrlen);
|
||||
log_name_addr(VERB_QUERY, "NAT64 apply: from: ",
|
||||
name, &a->addr, a->addrlen);
|
||||
log_name_addr(VERB_QUERY, "NAT64 apply: to: ",
|
||||
name, &real_addr, real_addrlen);
|
||||
a->addr = real_addr;
|
||||
a->addrlen = real_addrlen;
|
||||
}
|
||||
/* check lameness - need zone , class info */
|
||||
if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen,
|
||||
name, namelen, qtype, &lame, &dnsseclame, &reclame,
|
||||
@@ -1511,6 +1548,11 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
||||
struct delegpt *dp;
|
||||
int nolock = 1;
|
||||
|
||||
log_assert((retdpname && retdpnamelen
|
||||
&& dpname_storage && dpname_storage_len > 0) ||
|
||||
(retdpname == NULL && retdpnamelen == NULL
|
||||
&& dpname_storage == NULL && dpname_storage_len == 0));
|
||||
|
||||
/* Check for stub. */
|
||||
/* Lock both forwards and hints for atomic read. */
|
||||
lock_rw_rdlock(&qstate->env->fwds->lock);
|
||||
|
||||
@@ -84,6 +84,7 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
|
||||
/**
|
||||
* Select a valid, nice target to send query to.
|
||||
* Sorting and removing unsuitable targets is combined.
|
||||
* Adds records to the infra cache if not already there.
|
||||
*
|
||||
* @param iter_env: iterator module global state, with ip6 enabled and
|
||||
* do-not-query-addresses.
|
||||
|
||||
+4
-17
@@ -2436,8 +2436,6 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
int tf_policy;
|
||||
struct delegpt_addr* target;
|
||||
struct outbound_entry* outq;
|
||||
struct sockaddr_storage real_addr;
|
||||
socklen_t real_addrlen;
|
||||
int auth_fallback = 0;
|
||||
uint8_t* qout_orig = NULL;
|
||||
size_t qout_orig_len = 0;
|
||||
@@ -3060,17 +3058,6 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->dnssec_lame_query?" but lame_query anyway": "");
|
||||
}
|
||||
|
||||
real_addr = target->addr;
|
||||
real_addrlen = target->addrlen;
|
||||
|
||||
if(ie->nat64.use_nat64 && target->addr.ss_family == AF_INET) {
|
||||
addr_to_nat64(&target->addr, &ie->nat64.nat64_prefix_addr,
|
||||
ie->nat64.nat64_prefix_addrlen, ie->nat64.nat64_prefix_net,
|
||||
&real_addr, &real_addrlen);
|
||||
log_name_addr(VERB_QUERY, "applied NAT64:",
|
||||
iq->dp->name, &real_addr, real_addrlen);
|
||||
}
|
||||
|
||||
fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query));
|
||||
outq = (*qstate->env->send_query)(&iq->qinfo_out,
|
||||
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0),
|
||||
@@ -3082,7 +3069,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
!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), sq_check_ratelimit, &real_addr, real_addrlen,
|
||||
ie, iq), sq_check_ratelimit, &target->addr, target->addrlen,
|
||||
iq->dp->name, iq->dp->namelen,
|
||||
(iq->dp->tcp_upstream || qstate->env->cfg->tcp_upstream),
|
||||
(iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream),
|
||||
@@ -3099,7 +3086,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
log_addr(VERB_QUERY, "error sending query to auth server",
|
||||
&real_addr, real_addrlen);
|
||||
&target->addr, target->addrlen);
|
||||
if(qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = SKIP_MINIMISE_STATE;
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
@@ -3616,7 +3603,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return next_state(iq, INIT_REQUEST_STATE);
|
||||
} else if(type == RESPONSE_TYPE_LAME) {
|
||||
/* Cache the LAMEness. */
|
||||
verbose(VERB_DETAIL, "query response was %sLAME",
|
||||
verbose(VERB_DETAIL, "query response was categorized as %sLAME",
|
||||
dnsseclame?"DNSSEC ":"");
|
||||
if(!dname_subdomain_c(iq->qchase.qname, iq->dp->name)) {
|
||||
log_err("mark lame: mismatch in qname and dpname");
|
||||
@@ -3655,7 +3642,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* In this case, the event is just sent directly back to
|
||||
* the QUERYTARGETS_STATE without resetting anything,
|
||||
* because, clearly, the next target must be tried. */
|
||||
verbose(VERB_DETAIL, "query response was THROWAWAY");
|
||||
verbose(VERB_DETAIL, "query response was categorized as THROWAWAY");
|
||||
} else {
|
||||
log_warn("A query response came back with an unknown type: %d",
|
||||
(int)type);
|
||||
|
||||
+21
-12
@@ -649,6 +649,22 @@ int ub_ctx_data_remove(struct ub_ctx* ctx, const char *data);
|
||||
*/
|
||||
const char* ub_version(void);
|
||||
|
||||
/**
|
||||
* Memory statistics values. The values describe memory usage (in bytes).
|
||||
*/
|
||||
struct ub_mem_stat_info {
|
||||
long long msg;
|
||||
long long rrset;
|
||||
long long val;
|
||||
long long iter;
|
||||
long long subnet;
|
||||
long long ipsecmod;
|
||||
long long respip;
|
||||
long long dnscrypt_shared_secret;
|
||||
long long dnscrypt_nonce;
|
||||
long long dynlib;
|
||||
};
|
||||
|
||||
/**
|
||||
* Some global statistics that are not in struct stats_info,
|
||||
* this struct is shared on a shm segment (shm-key in unbound.conf)
|
||||
@@ -662,18 +678,7 @@ struct ub_shm_stat_info {
|
||||
long long elapsed_sec, elapsed_usec;
|
||||
} time;
|
||||
|
||||
struct {
|
||||
long long msg;
|
||||
long long rrset;
|
||||
long long val;
|
||||
long long iter;
|
||||
long long subnet;
|
||||
long long ipsecmod;
|
||||
long long respip;
|
||||
long long dnscrypt_shared_secret;
|
||||
long long dnscrypt_nonce;
|
||||
long long dynlib;
|
||||
} mem;
|
||||
struct ub_mem_stat_info mem;
|
||||
};
|
||||
|
||||
/** number of qtype that is stored for in array */
|
||||
@@ -853,6 +858,8 @@ struct ub_server_stats {
|
||||
long long qquic;
|
||||
/** number of queries removed due to discard-timeout */
|
||||
long long num_queries_discard_timeout;
|
||||
/** number of queries removed due to replyaddr limit */
|
||||
long long num_queries_replyaddr_limit;
|
||||
/** number of queries removed due to wait-limit */
|
||||
long long num_queries_wait_limit;
|
||||
/** number of dns error reports generated */
|
||||
@@ -872,6 +879,8 @@ struct ub_stats_info {
|
||||
long long mesh_num_states;
|
||||
/** mesh stats: current number of reply (user) states */
|
||||
long long mesh_num_reply_states;
|
||||
/** mesh stats: current number of reply entries */
|
||||
long long mesh_num_reply_addrs;
|
||||
/** mesh stats: number of reply states overwritten with a new one */
|
||||
long long mesh_jostled;
|
||||
/** mesh stats: number of incoming queries dropped */
|
||||
|
||||
@@ -973,6 +973,9 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
lock_rw_unlock(&raddr->lock);
|
||||
lock_rw_unlock(&a->lock);
|
||||
lock_rw_unlock(&az->rpz_lock);
|
||||
if(view) {
|
||||
lock_rw_unlock(&view->lock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(rpz_used) {
|
||||
|
||||
+63
-20
@@ -1384,6 +1384,9 @@ decompress_rr_into_buffer(struct sldns_buffer* buf, uint8_t* pkt,
|
||||
len = 0;
|
||||
break;
|
||||
case LDNS_RDF_TYPE_STR:
|
||||
/* Check rdlen for resilience, because it is
|
||||
* checked above, that rdlen > 0 */
|
||||
if(rdlen < 1) return 0; /* malformed */
|
||||
len = rd[0] + 1;
|
||||
break;
|
||||
default:
|
||||
@@ -1391,6 +1394,8 @@ decompress_rr_into_buffer(struct sldns_buffer* buf, uint8_t* pkt,
|
||||
break;
|
||||
}
|
||||
if(len) {
|
||||
if(len > rdlen)
|
||||
return 0; /* malformed */
|
||||
if(!sldns_buffer_available(buf, len))
|
||||
return 0; /* too long for buffer */
|
||||
sldns_buffer_write(buf, rd, len);
|
||||
@@ -3990,6 +3995,22 @@ auth_master_copy(struct auth_master* o)
|
||||
return m;
|
||||
}
|
||||
|
||||
/** append the master to the copied list. */
|
||||
static int
|
||||
auth_master_copy_and_append(struct auth_master* p, struct auth_master** list,
|
||||
struct auth_master** last)
|
||||
{
|
||||
struct auth_master* m = auth_master_copy(p);
|
||||
if(!m) {
|
||||
return 0;
|
||||
}
|
||||
m->next = NULL;
|
||||
if(*last) (*last)->next = m;
|
||||
if(!*list) *list = m;
|
||||
*last = m;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** copy the master addresses from the task_probe lookups to the allow_notify
|
||||
* list of masters */
|
||||
static void
|
||||
@@ -3998,17 +4019,27 @@ 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_transfer->masters; p; p=p->next) {
|
||||
struct auth_master* m = auth_master_copy(p);
|
||||
if(!m) {
|
||||
/* The list in task probe has been looked up before the list in
|
||||
* task transfer. */
|
||||
for(p = xfr->task_probe->masters; p; p=p->next) {
|
||||
if(!auth_master_copy_and_append(p, &list, &last)) {
|
||||
auth_free_masters(list);
|
||||
/* failed because of malloc failure, use old list */
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* The list in task transfer also contains the http entries. */
|
||||
for(p = xfr->task_transfer->masters; p; p=p->next) {
|
||||
/* Copy the http entries from this lookup. The allow_notify
|
||||
* entries are not looked up from this list. The other
|
||||
* ones are already in from the probe lookups. */
|
||||
if(!p->http)
|
||||
continue;
|
||||
if(!auth_master_copy_and_append(p, &list, &last)) {
|
||||
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);
|
||||
@@ -6669,6 +6700,18 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
/** 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)
|
||||
@@ -6708,6 +6751,16 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
|
||||
verbose(VERB_ALGO, "auth zone %s probe: finished only_lookup", zname);
|
||||
}
|
||||
xfr_probe_disown(xfr);
|
||||
if(!have_probe_targets(xfr->task_probe->masters)) {
|
||||
/* If there are no masters to probe, go to transfer. */
|
||||
if(xfr->task_transfer->worker == NULL) {
|
||||
xfr_start_transfer(xfr, env, NULL);
|
||||
return;
|
||||
}
|
||||
/* The transfer is already in progress. */
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
return;
|
||||
}
|
||||
if(xfr->task_nextprobe->worker == NULL)
|
||||
xfr_set_timeout(xfr, env, 0, 0);
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
@@ -6864,18 +6917,6 @@ auth_xfer_timer(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
/** 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. */
|
||||
@@ -6887,7 +6928,9 @@ xfr_start_probe(struct auth_xfer* xfr, struct module_env* env,
|
||||
* progress (due to notify)) */
|
||||
if(xfr->task_probe->worker == NULL) {
|
||||
if(!have_probe_targets(xfr->task_probe->masters) &&
|
||||
!(xfr->task_probe->only_lookup &&
|
||||
xfr->task_probe->masters != NULL)
|
||||
xfr->task_probe->only_lookup = 1;
|
||||
if(!(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 */
|
||||
|
||||
Vendored
+20
-6
@@ -232,8 +232,15 @@ find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
||||
|
||||
/* snip off front part of qname until the type is found */
|
||||
while(qnamelen > 0) {
|
||||
if((rrset = rrset_cache_lookup(env->rrset_cache, qname,
|
||||
qnamelen, searchtype, qclass, 0, now, 0))) {
|
||||
rrset = rrset_cache_lookup(env->rrset_cache, qname,
|
||||
qnamelen, searchtype, qclass, 0, now, 0);
|
||||
if(!rrset && searchtype == LDNS_RR_TYPE_DNAME)
|
||||
/* If not found, for type DNAME, try 0TTL stored,
|
||||
* for its grace period. */
|
||||
rrset = rrset_cache_lookup(env->rrset_cache, qname,
|
||||
qnamelen, searchtype, qclass,
|
||||
PACKED_RRSET_UPSTREAM_0TTL, now, 0);
|
||||
if(rrset) {
|
||||
uint8_t* origqname = qname;
|
||||
size_t origqnamelen = qnamelen;
|
||||
if(!noexpiredabove)
|
||||
@@ -766,8 +773,15 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
rrset->entry.data;
|
||||
uint8_t* newname, *dtarg = NULL;
|
||||
size_t newlen, dtarglen;
|
||||
if(TTL_IS_EXPIRED(d->ttl, now))
|
||||
return NULL;
|
||||
time_t rr_ttl;
|
||||
if(TTL_IS_EXPIRED(d->ttl, now)) {
|
||||
/* Allow TTL=0 DNAME from upstream within grace period */
|
||||
if(!(rrset->rk.flags & PACKED_RRSET_UPSTREAM_0TTL))
|
||||
return NULL;
|
||||
rr_ttl = 0;
|
||||
} else {
|
||||
rr_ttl = d->ttl - now;
|
||||
}
|
||||
/* only allow validated (with DNSSEC) DNAMEs used from cache
|
||||
* for insecure DNAMEs, query again. */
|
||||
*sec_status = d->security;
|
||||
@@ -779,7 +793,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
msg->rep->flags = BIT_QR; /* reply, no AA, no error */
|
||||
msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */
|
||||
msg->rep->qdcount = 1;
|
||||
msg->rep->ttl = d->ttl - now;
|
||||
msg->rep->ttl = rr_ttl;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
msg->rep->serve_expired_norec_ttl = 0;
|
||||
@@ -831,7 +845,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
if(!newd)
|
||||
return NULL;
|
||||
ck->entry.data = newd;
|
||||
newd->ttl = d->ttl - now; /* RFC6672: synth CNAME TTL == DNAME TTL */
|
||||
newd->ttl = rr_ttl; /* RFC6672: synth CNAME TTL == DNAME TTL */
|
||||
newd->count = 1;
|
||||
newd->rrsig_count = 0;
|
||||
newd->trust = rrset_trust_ans_noAA;
|
||||
|
||||
Vendored
+15
-3
@@ -278,6 +278,10 @@ void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
|
||||
(void)rrset_cache_update(rrset_cache, &ref, alloc, timenow);
|
||||
}
|
||||
|
||||
/** Grace period in seconds for TTL=0 DNAME rrsets (RFC 2308: do not cache).
|
||||
* Allows synthesis from cache within this window to reduce recursion load. */
|
||||
#define DNAME_TTL0_GRACE_SECONDS 1
|
||||
|
||||
struct ub_packed_rrset_key*
|
||||
rrset_cache_lookup(struct rrset_cache* r, uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint32_t flags, time_t timenow,
|
||||
@@ -300,12 +304,20 @@ rrset_cache_lookup(struct rrset_cache* r, uint8_t* qname, size_t qnamelen,
|
||||
/* check TTL */
|
||||
struct packed_rrset_data* data =
|
||||
(struct packed_rrset_data*)e->data;
|
||||
struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)e->key;
|
||||
if(TTL_IS_EXPIRED(data->ttl, timenow)) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return NULL;
|
||||
/* Allow TTL=0 DNAME within grace period for synthesis */
|
||||
if(qtype == LDNS_RR_TYPE_DNAME &&
|
||||
(k->rk.flags & PACKED_RRSET_UPSTREAM_0TTL) &&
|
||||
(timenow - data->ttl_add) <= DNAME_TTL0_GRACE_SECONDS) {
|
||||
/* within grace: allow for synthesis */
|
||||
} else {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* we're done */
|
||||
return (struct ub_packed_rrset_key*)e->key;
|
||||
return k;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1564,7 +1564,7 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
cp = comm_point_create_udp(base, ports->fd,
|
||||
front->udp_buff, ports->pp2_enabled, cb,
|
||||
cb_arg, ports->socket);
|
||||
} else if(ports->ftype == listen_type_doq) {
|
||||
} else if(ports->ftype == listen_type_doq && doq_table) {
|
||||
#ifndef HAVE_NGTCP2
|
||||
log_warn("Unbound is not compiled with "
|
||||
"ngtcp2. This is required to use DNS "
|
||||
@@ -2884,6 +2884,7 @@ submit_http_error:
|
||||
sldns_buffer_flip(h2_stream->qbuffer);
|
||||
h2_session->postpone_drop = 1;
|
||||
query_read_done = http2_query_read_done(h2_session, h2_stream);
|
||||
h2_session->postpone_drop = 0;
|
||||
if(query_read_done < 0)
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
else if(!query_read_done) {
|
||||
@@ -2893,11 +2894,9 @@ submit_http_error:
|
||||
* failure will result in reclaiming (and closing)
|
||||
* of comm point. */
|
||||
verbose(VERB_QUERY, "http2 query dropped in worker cb");
|
||||
h2_session->postpone_drop = 0;
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
/* nothing to submit right now, query added to mesh. */
|
||||
h2_session->postpone_drop = 0;
|
||||
return 0;
|
||||
}
|
||||
if(!http2_submit_dns_response(h2_session)) {
|
||||
@@ -3275,14 +3274,18 @@ nghttp2_session_callbacks* http2_req_callbacks_create(void)
|
||||
struct doq_table*
|
||||
doq_table_create(struct config_file* cfg, struct ub_randstate* rnd)
|
||||
{
|
||||
struct doq_table* table = calloc(1, sizeof(*table));
|
||||
struct doq_table* table;
|
||||
|
||||
if (!cfg->quic_port)
|
||||
return NULL;
|
||||
table = calloc(1, sizeof(*table));
|
||||
if(!table)
|
||||
return NULL;
|
||||
#ifdef USE_NGTCP2_CRYPTO_OSSL
|
||||
/* Initialize the ossl crypto, it is harmless to call twice,
|
||||
* and this is before use of doq connections. */
|
||||
if(ngtcp2_crypto_ossl_init() != 0) {
|
||||
log_err("ngtcp2_crypto_oss_init failed");
|
||||
log_err("ngtcp2_crypto_ossl_init failed");
|
||||
free(table);
|
||||
return NULL;
|
||||
}
|
||||
@@ -3354,7 +3357,7 @@ conn_tree_del(rbnode_type* node, void* arg)
|
||||
{
|
||||
struct doq_table* table = (struct doq_table*)arg;
|
||||
struct doq_conn* conn;
|
||||
if(!node)
|
||||
if(!node || !table)
|
||||
return;
|
||||
conn = (struct doq_conn*)node->key;
|
||||
if(conn->timer.timer_in_list) {
|
||||
@@ -3413,6 +3416,7 @@ doq_timer_find_time(struct doq_table* table, struct timeval* tv)
|
||||
{
|
||||
struct doq_timer key;
|
||||
struct rbnode_type* node;
|
||||
log_assert(table != NULL);
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.time.tv_sec = tv->tv_sec;
|
||||
key.time.tv_usec = tv->tv_usec;
|
||||
@@ -4922,6 +4926,7 @@ doq_conid_find(struct doq_table* table, const uint8_t* data, size_t datalen)
|
||||
key.node.key = &key;
|
||||
key.cid = (void*)data;
|
||||
key.cidlen = datalen;
|
||||
log_assert(table != NULL);
|
||||
node = rbtree_search(table->conid_tree, &key);
|
||||
if(node)
|
||||
return (struct doq_conid*)node->key;
|
||||
@@ -5662,6 +5667,8 @@ doq_table_quic_size_available(struct doq_table* table,
|
||||
struct config_file* cfg, size_t mem)
|
||||
{
|
||||
size_t cur;
|
||||
if (!table)
|
||||
return 0;
|
||||
lock_basic_lock(&table->size_lock);
|
||||
cur = table->current_size;
|
||||
lock_basic_unlock(&table->size_lock);
|
||||
|
||||
+106
-75
@@ -56,6 +56,24 @@
|
||||
* with 16 bytes for an A record, a 64K packet has about 4000 max */
|
||||
#define LOCALZONE_RRSET_COUNT_MAX 4096
|
||||
|
||||
static const char* default_zones_reverse_array[] = {
|
||||
"127.in-addr.arpa.", /* reverse ip4 zone */
|
||||
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", /* reverse ip6 zone */
|
||||
0
|
||||
};
|
||||
const char** local_zones_default_reverse = default_zones_reverse_array;
|
||||
|
||||
static const char* default_zones_special_array[] = {
|
||||
"test.", /* RFC 6761 */
|
||||
"invalid.", /* RFC 6761 */
|
||||
"onion.", /* RFC 7686 */
|
||||
"home.arpa.", /* RFC 8375 */
|
||||
"resolver.arpa.", /* RFC 9462 */
|
||||
"service.arpa.", /* RFC 9665 */
|
||||
0
|
||||
};
|
||||
const char** local_zones_default_special = default_zones_special_array;
|
||||
|
||||
/** print all RRsets in local zone */
|
||||
static void
|
||||
local_zone_out(struct local_zone* z)
|
||||
@@ -650,7 +668,7 @@ lz_enter_rr_str(struct local_zones* zones, const char* rr)
|
||||
}
|
||||
labs = dname_count_size_labels(rr_name, &len);
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type);
|
||||
z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type, 1);
|
||||
if(!z) {
|
||||
lock_rw_unlock(&zones->lock);
|
||||
fatal_exit("internal error: no zone for rr %s", rr);
|
||||
@@ -834,7 +852,7 @@ lz_nodefault(struct config_file* cfg, const char* name)
|
||||
|
||||
for(p = cfg->local_zones_nodefault; p; p = p->next) {
|
||||
/* compare zone name, lowercase, compare without ending . */
|
||||
if(strncasecmp(p->str, name, len) == 0 &&
|
||||
if(strncasecmp(p->str, name, len) == 0 &&
|
||||
(strlen(p->str) == len || (strlen(p->str)==len+1 &&
|
||||
p->str[len] == '.')))
|
||||
return 1;
|
||||
@@ -842,6 +860,45 @@ lz_nodefault(struct config_file* cfg, const char* name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** enter reverse default zone */
|
||||
static int
|
||||
add_reverse_default(struct local_zones* zones, struct config_file* cfg,
|
||||
const char* name)
|
||||
{
|
||||
struct local_zone* z;
|
||||
char str[1024]; /* known long enough */
|
||||
if(lz_exists(zones, name) || lz_nodefault(cfg, name))
|
||||
return 1; /* do not enter default content */
|
||||
if(!(z=lz_enter_zone(zones, name, "static", LDNS_RR_CLASS_IN)))
|
||||
return 0;
|
||||
snprintf(str, sizeof(str), "%s 10800 IN SOA localhost. "
|
||||
"nobody.invalid. 1 3600 1200 604800 10800", name);
|
||||
if(!lz_enter_rr_into_zone(z, str)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
snprintf(str, sizeof(str), "%s 10800 IN NS localhost. ", name);
|
||||
if(!lz_enter_rr_into_zone(z, str)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
if(strncasecmp("127.in-addr.arpa.", name, 17) == 0) {
|
||||
if(!lz_enter_rr_into_zone(z,
|
||||
"1.0.0.127.in-addr.arpa. 10800 IN PTR localhost.")) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
} else if(strncasecmp("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", name, 73) == 0) {
|
||||
snprintf(str, sizeof(str), "%s 10800 IN PTR localhost.", name);
|
||||
if(!lz_enter_rr_into_zone(z, str)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** enter (AS112) empty default zone */
|
||||
static int
|
||||
add_empty_default(struct local_zones* zones, struct config_file* cfg,
|
||||
@@ -902,72 +959,23 @@ int local_zone_enter_defaults(struct local_zones* zones, struct config_file* cfg
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
/* reverse ip4 zone */
|
||||
if(!lz_exists(zones, "127.in-addr.arpa.") &&
|
||||
!lz_nodefault(cfg, "127.in-addr.arpa.")) {
|
||||
if(!(z=lz_enter_zone(zones, "127.in-addr.arpa.", "static",
|
||||
LDNS_RR_CLASS_IN)) ||
|
||||
!lz_enter_rr_into_zone(z,
|
||||
"127.in-addr.arpa. 10800 IN NS localhost.") ||
|
||||
!lz_enter_rr_into_zone(z,
|
||||
"127.in-addr.arpa. 10800 IN SOA localhost. "
|
||||
"nobody.invalid. 1 3600 1200 604800 10800") ||
|
||||
!lz_enter_rr_into_zone(z,
|
||||
"1.0.0.127.in-addr.arpa. 10800 IN PTR localhost.")) {
|
||||
|
||||
/* ip4 and ip6 reverse */
|
||||
for(zstr = local_zones_default_reverse; *zstr; zstr++) {
|
||||
if(!add_reverse_default(zones, cfg, *zstr)) {
|
||||
log_err("out of memory adding default zone");
|
||||
if(z) { lock_rw_unlock(&z->lock); }
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
/* reverse ip6 zone */
|
||||
if(!lz_exists(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.") &&
|
||||
!lz_nodefault(cfg, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.")) {
|
||||
if(!(z=lz_enter_zone(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", "static",
|
||||
LDNS_RR_CLASS_IN)) ||
|
||||
!lz_enter_rr_into_zone(z,
|
||||
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN NS localhost.") ||
|
||||
!lz_enter_rr_into_zone(z,
|
||||
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN SOA localhost. "
|
||||
"nobody.invalid. 1 3600 1200 604800 10800") ||
|
||||
!lz_enter_rr_into_zone(z,
|
||||
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN PTR localhost.")) {
|
||||
|
||||
/* special-use zones */
|
||||
for(zstr = local_zones_default_special; *zstr; zstr++) {
|
||||
if(!add_empty_default(zones, cfg, *zstr)) {
|
||||
log_err("out of memory adding default zone");
|
||||
if(z) { lock_rw_unlock(&z->lock); }
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
/* home.arpa. zone (RFC 8375) */
|
||||
if(!add_empty_default(zones, cfg, "home.arpa.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* resolver.arpa. zone (RFC 9462) */
|
||||
if(!add_empty_default(zones, cfg, "resolver.arpa.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* service.arpa. zone (draft-ietf-dnssd-srp-25) */
|
||||
if(!add_empty_default(zones, cfg, "service.arpa.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* onion. zone (RFC 7686) */
|
||||
if(!add_empty_default(zones, cfg, "onion.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* test. zone (RFC 6761) */
|
||||
if(!add_empty_default(zones, cfg, "test.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* invalid. zone (RFC 6761) */
|
||||
if(!add_empty_default(zones, cfg, "invalid.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* block AS112 zones, unless asked not to */
|
||||
if(!cfg->unblock_lan_zones) {
|
||||
for(zstr = as112_zones; *zstr; zstr++) {
|
||||
@@ -1062,14 +1070,15 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
|
||||
labs = dname_count_size_labels(rr_name, &len);
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
if(!local_zones_lookup(zones, rr_name, len, labs, rr_class,
|
||||
rr_type)) {
|
||||
rr_type, 1)) {
|
||||
/* Check if there is a zone that this could go
|
||||
* under but for different class; created zones are
|
||||
* always for LDNS_RR_CLASS_IN. Create the zone with
|
||||
* a different class but the same configured
|
||||
* local_zone_type. */
|
||||
struct local_zone* z = local_zones_lookup(zones,
|
||||
rr_name, len, labs, LDNS_RR_CLASS_IN, rr_type);
|
||||
rr_name, len, labs, LDNS_RR_CLASS_IN, rr_type,
|
||||
1);
|
||||
if(z) {
|
||||
uint8_t* name = memdup(z->name, z->namelen);
|
||||
size_t znamelen = z->namelen;
|
||||
@@ -1231,28 +1240,48 @@ local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
|
||||
|
||||
struct local_zone*
|
||||
local_zones_lookup(struct local_zones* zones,
|
||||
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype)
|
||||
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype,
|
||||
int foradd)
|
||||
{
|
||||
return local_zones_tags_lookup(zones, name, len, labs,
|
||||
dclass, dtype, NULL, 0, 1);
|
||||
dclass, dtype, NULL, 0, 1, foradd);
|
||||
}
|
||||
|
||||
struct local_zone*
|
||||
local_zones_tags_lookup(struct local_zones* zones,
|
||||
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype,
|
||||
uint8_t* taglist, size_t taglen, int ignoretags)
|
||||
uint8_t* taglist, size_t taglen, int ignoretags, int foradd)
|
||||
{
|
||||
rbnode_type* res = NULL;
|
||||
struct local_zone *result;
|
||||
struct local_zone key;
|
||||
int m;
|
||||
/* for type DS use a zone higher when on a zonecut */
|
||||
if(dtype == LDNS_RR_TYPE_DS && !dname_is_root(name)) {
|
||||
dname_remove_label(&name, &len);
|
||||
labs--;
|
||||
}
|
||||
key.node.key = &key;
|
||||
key.dclass = dclass;
|
||||
/* for type DS use a zone higher when on a zonecut */
|
||||
if(dtype == LDNS_RR_TYPE_DS && !dname_is_root(name)) {
|
||||
/* If this is at a zone cut, of a local-zone, and it is
|
||||
* of type always_refuse. Then also refuse the type DS
|
||||
* for it. That could make it DNSSEC bogus, but it is
|
||||
* REFUSED anyway. It stops CNAME type answers in the
|
||||
* type DS lookup. */
|
||||
key.name = name;
|
||||
key.namelen = len;
|
||||
key.namelabs = labs;
|
||||
/* For additions and removals, use the ordinary rule,
|
||||
* to remove a label for type DS to locate the parent zone.
|
||||
* That is where the DS RR needs to be put. */
|
||||
if(!foradd &&
|
||||
(result=(struct local_zone*)rbtree_search(
|
||||
&zones->ztree, &key)) != NULL &&
|
||||
result->type == local_zone_always_refuse) {
|
||||
/* The type DS does not go up one label. */
|
||||
return result;
|
||||
} else {
|
||||
dname_remove_label(&name, &len);
|
||||
labs--;
|
||||
}
|
||||
}
|
||||
key.name = name;
|
||||
key.namelen = len;
|
||||
key.namelabs = labs;
|
||||
@@ -1863,7 +1892,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
if(view->local_zones &&
|
||||
(z = local_zones_lookup(view->local_zones,
|
||||
qinfo->qname, qinfo->qname_len, labs,
|
||||
qinfo->qclass, qinfo->qtype))) {
|
||||
qinfo->qclass, qinfo->qtype, 0))) {
|
||||
lock_rw_rdlock(&z->lock);
|
||||
lzt = z->type;
|
||||
}
|
||||
@@ -1897,7 +1926,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
if(!(z = local_zones_tags_lookup(zones, qinfo->qname,
|
||||
qinfo->qname_len, labs, qinfo->qclass, qinfo->qtype,
|
||||
taglist, taglen, 0))) {
|
||||
taglist, taglen, 0, 0))) {
|
||||
lock_rw_unlock(&zones->lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -2102,7 +2131,8 @@ local_zones_add_RR(struct local_zones* zones, const char* rr)
|
||||
/* could first try readlock then get writelock if zone does not exist,
|
||||
* but we do not add enough RRs (from multiple threads) to optimize */
|
||||
lock_rw_wrlock(&zones->lock);
|
||||
z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type);
|
||||
z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type,
|
||||
1);
|
||||
if(!z) {
|
||||
z = local_zones_add_zone(zones, rr_name, len, labs, rr_class,
|
||||
local_zone_transparent);
|
||||
@@ -2180,7 +2210,8 @@ void local_zones_del_data(struct local_zones* zones,
|
||||
|
||||
/* remove DS */
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
z = local_zones_lookup(zones, name, len, labs, dclass, LDNS_RR_TYPE_DS);
|
||||
z = local_zones_lookup(zones, name, len, labs, dclass, LDNS_RR_TYPE_DS,
|
||||
1);
|
||||
if(z) {
|
||||
lock_rw_wrlock(&z->lock);
|
||||
d = local_zone_find_data(z, name, len, labs);
|
||||
@@ -2194,7 +2225,7 @@ void local_zones_del_data(struct local_zones* zones,
|
||||
|
||||
/* remove other types */
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
z = local_zones_lookup(zones, name, len, labs, dclass, 0);
|
||||
z = local_zones_lookup(zones, name, len, labs, dclass, 0, 1);
|
||||
if(!z) {
|
||||
/* no such zone, we're done */
|
||||
lock_rw_unlock(&zones->lock);
|
||||
|
||||
+10
-2
@@ -57,6 +57,9 @@ struct sldns_buffer;
|
||||
struct comm_reply;
|
||||
struct config_strlist;
|
||||
|
||||
extern const char** local_zones_default_special;
|
||||
extern const char** local_zones_default_reverse;
|
||||
|
||||
/**
|
||||
* Local zone type
|
||||
* This type determines processing for queries that did not match
|
||||
@@ -262,11 +265,13 @@ void local_zone_delete(struct local_zone* z);
|
||||
* @param taglen: length of taglist.
|
||||
* @param ignoretags: lookup zone by name and class, regardless the
|
||||
* local-zone's tags.
|
||||
* @param foradd: if the lookup is for addition or removal of the type.
|
||||
* Used for type DS. The lookup for answers turns this off.
|
||||
* @return closest local_zone or NULL if no covering zone is found.
|
||||
*/
|
||||
struct local_zone* local_zones_tags_lookup(struct local_zones* zones,
|
||||
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype,
|
||||
uint8_t* taglist, size_t taglen, int ignoretags);
|
||||
uint8_t* taglist, size_t taglen, int ignoretags, int foradd);
|
||||
|
||||
/**
|
||||
* Lookup zone that contains the given name, class.
|
||||
@@ -278,10 +283,13 @@ struct local_zone* local_zones_tags_lookup(struct local_zones* zones,
|
||||
* @param dclass: class to lookup.
|
||||
* @param dtype: type of the record, if type DS then a zone higher up is found
|
||||
* pass 0 to just plain find a zone for a name.
|
||||
* @param foradd: if the lookup is for addition or removal of the type.
|
||||
* Used for type DS. The lookup for answers turns this off.
|
||||
* @return closest local_zone or NULL if no covering zone is found.
|
||||
*/
|
||||
struct local_zone* local_zones_lookup(struct local_zones* zones,
|
||||
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype);
|
||||
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype,
|
||||
int foradd);
|
||||
|
||||
/**
|
||||
* Debug helper. Print all zones
|
||||
|
||||
+11
-1
@@ -231,6 +231,7 @@ mesh_create(struct module_stack* stack, struct module_env* env)
|
||||
mesh->ans_expired = 0;
|
||||
mesh->ans_cachedb = 0;
|
||||
mesh->num_queries_discard_timeout = 0;
|
||||
mesh->num_queries_replyaddr_limit = 0;
|
||||
mesh->num_queries_wait_limit = 0;
|
||||
mesh->num_dns_error_reports = 0;
|
||||
mesh->max_reply_states = env->cfg->num_queries_per_thread;
|
||||
@@ -462,6 +463,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
if(!mesh_make_new_space(mesh, rep->c->buffer)) {
|
||||
verbose(VERB_ALGO, "Too many queries. dropping "
|
||||
"incoming query.");
|
||||
if(rep->c->use_h2)
|
||||
http2_stream_remove_mesh_state(rep->c->h2_stream);
|
||||
comm_point_drop_reply(rep);
|
||||
mesh->stats_dropped++;
|
||||
return;
|
||||
@@ -473,8 +476,10 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
if(mesh->num_reply_addrs > mesh->max_reply_states*16) {
|
||||
verbose(VERB_ALGO, "Too many requests queued. "
|
||||
"dropping incoming query.");
|
||||
if(rep->c->use_h2)
|
||||
http2_stream_remove_mesh_state(rep->c->h2_stream);
|
||||
comm_point_drop_reply(rep);
|
||||
mesh->stats_dropped++;
|
||||
mesh->num_queries_replyaddr_limit++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1765,6 +1770,8 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
http2_stream_remove_mesh_state(r->h2_stream);
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
mstate->reply_list = reply_list;
|
||||
log_assert(mstate->s.env->mesh->num_reply_addrs > 0);
|
||||
mstate->s.env->mesh->num_reply_addrs--;
|
||||
mstate->s.env->mesh->num_queries_discard_timeout++;
|
||||
continue;
|
||||
}
|
||||
@@ -1801,6 +1808,8 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
}
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
mstate->reply_list = reply_list;
|
||||
log_assert(mstate->s.env->mesh->num_reply_addrs > 0);
|
||||
mstate->s.env->mesh->num_reply_addrs--;
|
||||
} else {
|
||||
struct sldns_buffer* r_buffer = r->query_reply.c->buffer;
|
||||
if(r->query_reply.c->tcp_req_info) {
|
||||
@@ -2291,6 +2300,7 @@ mesh_stats_clear(struct mesh_area* mesh)
|
||||
memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM);
|
||||
mesh->ans_nodata = 0;
|
||||
mesh->num_queries_discard_timeout = 0;
|
||||
mesh->num_queries_replyaddr_limit = 0;
|
||||
mesh->num_queries_wait_limit = 0;
|
||||
mesh->num_dns_error_reports = 0;
|
||||
}
|
||||
|
||||
@@ -141,6 +141,8 @@ struct mesh_area {
|
||||
size_t rpz_action[UB_STATS_RPZ_ACTION_NUM];
|
||||
/** stats, number of queries removed due to discard-timeout */
|
||||
size_t num_queries_discard_timeout;
|
||||
/** stats, number of queries removed due to replyaddr limit */
|
||||
size_t num_queries_replyaddr_limit;
|
||||
/** stats, number of queries removed due to wait-limit */
|
||||
size_t num_queries_wait_limit;
|
||||
/** stats, number of dns error reports generated */
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
#include "util/regional.h"
|
||||
#include "util/netevent.h"
|
||||
#include "dnstap/dnstap_config.h"
|
||||
#ifdef __QNX__
|
||||
/* For struct timeval */
|
||||
#include <sys/time.h>
|
||||
#endif /* __QNX__ */
|
||||
struct pending;
|
||||
struct pending_timeout;
|
||||
struct ub_randstate;
|
||||
|
||||
@@ -153,6 +153,7 @@ rpz_type_ignored(uint16_t rr_type)
|
||||
case LDNS_RR_TYPE_SOA:
|
||||
case LDNS_RR_TYPE_NS:
|
||||
case LDNS_RR_TYPE_DNAME:
|
||||
case LDNS_RR_TYPE_ZONEMD:
|
||||
/* all DNSSEC-related RRs must be ignored */
|
||||
case LDNS_RR_TYPE_DNSKEY:
|
||||
case LDNS_RR_TYPE_DS:
|
||||
|
||||
@@ -486,6 +486,7 @@ enum sldns_enum_ede_code
|
||||
typedef enum sldns_enum_ede_code sldns_ede_code;
|
||||
|
||||
#define LDNS_EDNS_MASK_DO_BIT 0x8000
|
||||
#define LDNS_EDNS_MASK_CO_BIT 0x4000
|
||||
|
||||
/** TSIG and TKEY extended rcodes (16bit), 0-15 are the normal rcodes. */
|
||||
#define LDNS_TSIG_ERROR_NOERROR 0
|
||||
|
||||
@@ -2486,6 +2486,8 @@ int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str,
|
||||
w += sldns_str_print(str, str_len, " flags:");
|
||||
if((edns_bits & LDNS_EDNS_MASK_DO_BIT))
|
||||
w += sldns_str_print(str, str_len, " do");
|
||||
if((edns_bits & LDNS_EDNS_MASK_CO_BIT))
|
||||
w += sldns_str_print(str, str_len, " co");
|
||||
/* the extended rcode is the value set, shifted four bits,
|
||||
* and or'd with the original rcode */
|
||||
if(ext_rcode) {
|
||||
|
||||
@@ -2430,12 +2430,20 @@ int main(int argc, char* argv[])
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
|
||||
if(dolist) do_list_builtin();
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include <ctype.h>
|
||||
#include "util/as112.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/module.h"
|
||||
@@ -188,11 +189,56 @@ donotquerylocalhostcheck(struct config_file* cfg)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nodefaultzonescheck(struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* d;
|
||||
const char** zstr;
|
||||
size_t len;
|
||||
|
||||
#define COMPARE_ZONE_NAME(confname, builtname, len) \
|
||||
(strncasecmp(confname, builtname, (len)) == 0 && \
|
||||
(strlen(confname) == (len) || \
|
||||
(strlen(confname) == (len) + 1 \
|
||||
&& confname[(len)] == '.')))
|
||||
|
||||
for(d = cfg->local_zones_nodefault; d; d = d->next) {
|
||||
if(!cfg->unblock_lan_zones) {
|
||||
for(zstr = as112_zones; *zstr; zstr++) {
|
||||
len = strlen(*zstr) - 1; /* trailing '.' */
|
||||
if(COMPARE_ZONE_NAME(d->str, *zstr, len))
|
||||
goto default_continue;
|
||||
}
|
||||
}
|
||||
for(zstr = local_zones_default_special; *zstr; zstr++) {
|
||||
len = strlen(*zstr) - 1; /* trailing '.' */
|
||||
if(COMPARE_ZONE_NAME(d->str, *zstr, len))
|
||||
goto default_continue;
|
||||
}
|
||||
for(zstr = local_zones_default_reverse; *zstr; zstr++) {
|
||||
len = strlen(*zstr) - 1; /* trailing '.' */
|
||||
if(COMPARE_ZONE_NAME(d->str, *zstr, len))
|
||||
goto default_continue;
|
||||
}
|
||||
if(COMPARE_ZONE_NAME(d->str, "localhost.", 10 - 1))
|
||||
goto default_continue;
|
||||
fprintf(stderr, "unbound-checkconf: warning: local-zone: '%s' "
|
||||
"is configured as 'nodefault' but there is no such "
|
||||
"default local-zone. Check the unbound.conf "
|
||||
"documentation for default configured local-zones.\n",
|
||||
d->str);
|
||||
default_continue:
|
||||
; /* statement to jump to, for older gcc. */
|
||||
}
|
||||
#undef COMPARE_ZONE_NAME
|
||||
}
|
||||
|
||||
/** check localzones */
|
||||
static void
|
||||
localzonechecks(struct config_file* cfg)
|
||||
{
|
||||
struct local_zones* zs;
|
||||
nodefaultzonescheck(cfg);
|
||||
if(!(zs = local_zones_create()))
|
||||
fatal_exit("out of memory");
|
||||
if(!local_zones_apply_cfg(zs, cfg))
|
||||
|
||||
@@ -236,6 +236,8 @@ static void pr_stats(const char* nm, struct ub_stats_info* s)
|
||||
s->svr.num_queries_cookie_invalid);
|
||||
PR_UL_NM("num.queries_discard_timeout",
|
||||
s->svr.num_queries_discard_timeout);
|
||||
PR_UL_NM("num.queries_replyaddr_limit",
|
||||
s->svr.num_queries_replyaddr_limit);
|
||||
PR_UL_NM("num.queries_wait_limit", s->svr.num_queries_wait_limit);
|
||||
PR_UL_NM("num.cachehits",
|
||||
s->svr.num_queries - s->svr.num_queries_missed_cache);
|
||||
@@ -263,6 +265,7 @@ static void pr_stats(const char* nm, struct ub_stats_info* s)
|
||||
PR_UL_NM("requestlist.exceeded", s->mesh_dropped);
|
||||
PR_UL_NM("requestlist.current.all", s->mesh_num_states);
|
||||
PR_UL_NM("requestlist.current.user", s->mesh_num_reply_states);
|
||||
PR_UL_NM("requestlist.current.replies", s->mesh_num_reply_addrs);
|
||||
#ifndef S_SPLINT_S
|
||||
sumwait.tv_sec = s->mesh_replies_sum_wait_sec;
|
||||
sumwait.tv_usec = s->mesh_replies_sum_wait_usec;
|
||||
@@ -1049,12 +1052,20 @@ int main(int argc, char* argv[])
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
|
||||
if(!RAND_status()) {
|
||||
|
||||
+10
-2
@@ -521,12 +521,20 @@ int main(int argc, char* argv[])
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#endif /* HAVE_SSL */
|
||||
#ifdef HAVE_NSS
|
||||
|
||||
+10
-2
@@ -488,12 +488,20 @@ int main(int argc, char** argv)
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
|
||||
+10
-2
@@ -642,12 +642,20 @@ int main(int argc, char** argv)
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
}
|
||||
run(h2_session, port, no_tls, argc, argv);
|
||||
|
||||
@@ -2255,7 +2255,7 @@ create_doq_client_data(const char* svr, int port, struct ub_event_base* base,
|
||||
/* Initialize the ossl crypto, it is harmless to call twice,
|
||||
* and this is before use of doq connections. */
|
||||
if(ngtcp2_crypto_ossl_init() != 0)
|
||||
fatal_exit("ngtcp2_crypto_oss_init failed");
|
||||
fatal_exit("ngtcp2_crypto_ossl_init failed");
|
||||
#elif defined(HAVE_NGTCP2_CRYPTO_QUICTLS_INIT)
|
||||
if(ngtcp2_crypto_quictls_init() != 0)
|
||||
fatal_exit("ngtcp2_crypto_quictls_init failed");
|
||||
|
||||
@@ -141,6 +141,13 @@ if test -f $done; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# always clear the skip mark file in case something changed in the environment
|
||||
# in between runs
|
||||
if test -f $skip; then
|
||||
echo "minitdir $skip exists; removing."
|
||||
rm $skip
|
||||
fi
|
||||
|
||||
# Copy
|
||||
if test $quiet = 0; then
|
||||
echo "minitdir copy $1 to $dir"
|
||||
|
||||
+14
-4
@@ -222,7 +222,8 @@ read_http_headers(SSL* ssl, char* file, size_t flen, char* host, size_t hlen,
|
||||
if(verb>=2) printf("read: %s\n", buf);
|
||||
if(buf[0] == 0) {
|
||||
int e = ERR_peek_error();
|
||||
printf("error string: %s\n", ERR_reason_error_string(e));
|
||||
if(e)
|
||||
printf("error string: %s\n", ERR_reason_error_string(e));
|
||||
return 1;
|
||||
}
|
||||
if(!process_one_header(buf, file, flen, host, hlen, vs))
|
||||
@@ -246,7 +247,8 @@ setup_ctx(char* key, char* cert)
|
||||
#endif
|
||||
if(!SSL_CTX_use_certificate_chain_file(ctx, cert)) {
|
||||
int e = ERR_peek_error();
|
||||
printf("error string: %s\n", ERR_reason_error_string(e));
|
||||
if(e)
|
||||
printf("error string: %s\n", ERR_reason_error_string(e));
|
||||
print_exit("cannot read cert");
|
||||
}
|
||||
if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM))
|
||||
@@ -673,12 +675,20 @@ int main(int argc, char* argv[])
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
|
||||
do_service(addr, port, key, cert);
|
||||
|
||||
+12
-2
@@ -59,12 +59,16 @@ static void usage(char* argv[])
|
||||
/** read hex input */
|
||||
static void read_input(sldns_buffer* pkt, FILE* in)
|
||||
{
|
||||
char buf[102400];
|
||||
/* Buffer for 64Kib packet, in hex, with spaces and comments. */
|
||||
char buf[1024000];
|
||||
char* np = buf;
|
||||
while(fgets(np, (int)sizeof(buf) - (np-buf), in)) {
|
||||
if(buf[0] == ';') /* comment */
|
||||
continue;
|
||||
np = &np[strlen(np)];
|
||||
if((size_t)(np-buf) >= sizeof(buf)-1)
|
||||
fatal_exit("input too large (%lu bytes)",
|
||||
(unsigned long)sizeof(buf));
|
||||
}
|
||||
hex_to_buf(pkt, buf);
|
||||
}
|
||||
@@ -188,10 +192,16 @@ static void analyze(sldns_buffer* pkt)
|
||||
/** main program for pktview */
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
sldns_buffer* pkt = sldns_buffer_new(65553);
|
||||
sldns_buffer* pkt;
|
||||
|
||||
log_init(NULL, 0, NULL);
|
||||
log_ident_set("pktview");
|
||||
|
||||
if(argc != 1) {
|
||||
usage(argv);
|
||||
}
|
||||
|
||||
pkt = sldns_buffer_new(65553);
|
||||
if(!pkt) fatal_exit("out of memory");
|
||||
|
||||
read_input(pkt, stdin);
|
||||
|
||||
@@ -142,6 +142,10 @@
|
||||
#include "util/netevent.h"
|
||||
#include "testcode/testpkts.h"
|
||||
#include "util/rbtree.h"
|
||||
#ifdef __QNX__
|
||||
/* For struct timeval */
|
||||
#include <sys/time.h>
|
||||
#endif /* __QNX__ */
|
||||
struct replay_answer;
|
||||
struct replay_moment;
|
||||
struct replay_range;
|
||||
|
||||
+10
-2
@@ -652,12 +652,20 @@ int main(int argc, char** argv)
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
||||
# endif
|
||||
, NULL);
|
||||
#endif
|
||||
}
|
||||
send_em(svr, pp2_client, udp, usessl, noanswer, onarrival, delay, argc, argv);
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "daemon/remote.h"
|
||||
#include "libunbound/worker.h"
|
||||
#include "daemon/worker.h"
|
||||
#include "daemon/metrics.h"
|
||||
#include "util/config_file.h"
|
||||
#include "sldns/keyraw.h"
|
||||
#ifdef UB_ON_WINDOWS
|
||||
@@ -664,6 +665,42 @@ void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
/* fake metrics */
|
||||
struct daemon_metrics* daemon_metrics_create(void)
|
||||
{
|
||||
return (struct daemon_metrics*)calloc(1, sizeof(struct daemon_metrics));
|
||||
}
|
||||
|
||||
void daemon_metrics_delete(struct daemon_metrics* m)
|
||||
{
|
||||
if(!m) return;
|
||||
free(m);
|
||||
}
|
||||
|
||||
void daemon_metrics_close_ports(struct daemon_metrics* ATTR_UNUSED(m))
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void daemon_metrics_detach(struct daemon_metrics* ATTR_UNUSED(m))
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
int daemon_metrics_open_ports(struct daemon_metrics* ATTR_UNUSED(m),
|
||||
struct config_file* ATTR_UNUSED(cfg))
|
||||
{
|
||||
/* nothing */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int daemon_metrics_attach(struct daemon_metrics* ATTR_UNUSED(m),
|
||||
struct worker* ATTR_UNUSED(worker))
|
||||
{
|
||||
/* nothing */
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef UB_ON_WINDOWS
|
||||
void wsvc_command_option(const char* ATTR_UNUSED(wopt),
|
||||
const char* ATTR_UNUSED(cfgfile), int ATTR_UNUSED(v),
|
||||
|
||||
+41
-9
@@ -135,6 +135,8 @@ static void matchline(char* line, struct entry* e)
|
||||
e->match_ttl = 1;
|
||||
} else if(str_keyword(&parse, "DO")) {
|
||||
e->match_do = 1;
|
||||
} else if(str_keyword(&parse, "CO")) {
|
||||
e->match_co = 1;
|
||||
} else if(str_keyword(&parse, "noedns")) {
|
||||
e->match_noedns = 1;
|
||||
} else if(str_keyword(&parse, "ednsdata")) {
|
||||
@@ -178,7 +180,7 @@ static void matchline(char* line, struct entry* e)
|
||||
|
||||
/** parse REPLY line */
|
||||
static void replyline(char* line, uint8_t* reply, size_t reply_len,
|
||||
int* do_flag)
|
||||
int* do_flag, int* co_flag)
|
||||
{
|
||||
char* parse = line;
|
||||
if(reply_len < LDNS_HEADER_SIZE) error("packet too short for header");
|
||||
@@ -236,6 +238,8 @@ static void replyline(char* line, uint8_t* reply, size_t reply_len,
|
||||
LDNS_AD_SET(reply);
|
||||
} else if(str_keyword(&parse, "DO")) {
|
||||
*do_flag = 1;
|
||||
} else if(str_keyword(&parse, "CO")) {
|
||||
*co_flag = 1;
|
||||
} else {
|
||||
error("could not parse REPLY: '%s'", parse);
|
||||
}
|
||||
@@ -289,6 +293,7 @@ static struct entry* new_entry(void)
|
||||
e->match_all_noedns = 0;
|
||||
e->match_ttl = 0;
|
||||
e->match_do = 0;
|
||||
e->match_co = 0;
|
||||
e->match_noedns = 0;
|
||||
e->match_serial = 0;
|
||||
e->ixfr_soa_serial = 0;
|
||||
@@ -521,15 +526,17 @@ static void add_rr(char* rrstr, uint8_t* pktbuf, size_t pktsize,
|
||||
|
||||
/* add EDNS 4096 opt record */
|
||||
static void
|
||||
add_edns(uint8_t* pktbuf, size_t pktsize, int do_flag, uint8_t *ednsdata,
|
||||
uint16_t ednslen, size_t* pktlen)
|
||||
add_edns(uint8_t* pktbuf, size_t pktsize, int do_flag, int co_flag,
|
||||
uint8_t *ednsdata, uint16_t ednslen, size_t* pktlen)
|
||||
{
|
||||
uint8_t edns[] = {0x00, /* root label */
|
||||
0x00, LDNS_RR_TYPE_OPT, /* type */
|
||||
0x04, 0xD0, /* class is UDPSIZE 1232 */
|
||||
0x00, /* TTL[0] is ext rcode */
|
||||
0x00, /* TTL[1] is edns version */
|
||||
(uint8_t)(do_flag?0x80:0x00), 0x00, /* TTL[2-3] is edns flags, DO */
|
||||
(uint8_t)(do_flag?0x80:0x00)
|
||||
| (uint8_t)(co_flag?0x40:0x00)
|
||||
, 0x00, /* TTL[2-3] is edns flags, DO */
|
||||
(uint8_t)((ednslen >> 8) & 0xff),
|
||||
(uint8_t)(ednslen & 0xff), /* rdatalength */
|
||||
};
|
||||
@@ -561,6 +568,7 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
|
||||
uint8_t pktbuf[MAX_PACKETLEN];
|
||||
size_t pktlen = LDNS_HEADER_SIZE;
|
||||
int do_flag = 0; /* DO flag in EDNS */
|
||||
int co_flag = 0; /* CO flag in EDNS */
|
||||
memset(pktbuf, 0, pktlen); /* ID = 0, FLAGS="", and rr counts 0 */
|
||||
|
||||
while(fgets(line, (int)sizeof(line), in) != NULL) {
|
||||
@@ -598,7 +606,7 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
|
||||
if(str_keyword(&parse, "MATCH")) {
|
||||
matchline(parse, current);
|
||||
} else if(str_keyword(&parse, "REPLY")) {
|
||||
replyline(parse, pktbuf, pktlen, &do_flag);
|
||||
replyline(parse, pktbuf, pktlen, &do_flag, &co_flag);
|
||||
} else if(str_keyword(&parse, "ADJUST")) {
|
||||
adjustline(parse, current, cur_reply);
|
||||
} else if(str_keyword(&parse, "EXTRA_PACKET")) {
|
||||
@@ -654,15 +662,16 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
|
||||
if(hex_ednsdata_buffer)
|
||||
sldns_buffer_free(hex_ednsdata_buffer);
|
||||
if(pktlen != 0) {
|
||||
if(do_flag || cur_reply->raw_ednsdata) {
|
||||
if(do_flag || co_flag
|
||||
|| cur_reply->raw_ednsdata) {
|
||||
if(cur_reply->raw_ednsdata &&
|
||||
sldns_buffer_limit(cur_reply->raw_ednsdata))
|
||||
add_edns(pktbuf, sizeof(pktbuf), do_flag,
|
||||
add_edns(pktbuf, sizeof(pktbuf), do_flag, co_flag,
|
||||
sldns_buffer_begin(cur_reply->raw_ednsdata),
|
||||
(uint16_t)sldns_buffer_limit(cur_reply->raw_ednsdata),
|
||||
&pktlen);
|
||||
else
|
||||
add_edns(pktbuf, sizeof(pktbuf), do_flag,
|
||||
add_edns(pktbuf, sizeof(pktbuf), do_flag, co_flag,
|
||||
NULL, 0, &pktlen);
|
||||
}
|
||||
cur_reply->reply_pkt = memdup(pktbuf, pktlen);
|
||||
@@ -909,6 +918,22 @@ get_do_flag(uint8_t* pkt, size_t len)
|
||||
return (int)(edns_bits&LDNS_EDNS_MASK_DO_BIT);
|
||||
}
|
||||
|
||||
/** return true if the CO flag is set */
|
||||
static int
|
||||
get_co_flag(uint8_t* pkt, size_t len)
|
||||
{
|
||||
uint16_t edns_bits;
|
||||
uint8_t* walk = pkt;
|
||||
size_t walk_len = len;
|
||||
if(!pkt_find_edns_opt(&walk, &walk_len)) {
|
||||
return 0;
|
||||
}
|
||||
if(walk_len < 6)
|
||||
return 0; /* malformed */
|
||||
edns_bits = sldns_read_uint16(walk+4);
|
||||
return (int)(edns_bits&LDNS_EDNS_MASK_CO_BIT);
|
||||
}
|
||||
|
||||
/** Snips the specified EDNS option out of the OPT record and puts it in the
|
||||
* provided buffer. The buffer should be able to hold any opt data ie 65535.
|
||||
* Returns the length of the option written,
|
||||
@@ -1654,6 +1679,10 @@ find_match(struct entry* entries, uint8_t* query_pkt, size_t len,
|
||||
verbose(3, "no DO bit set\n");
|
||||
continue;
|
||||
}
|
||||
if(p->match_co && !get_co_flag(query_pkt, len)) {
|
||||
verbose(3, "no CO bit set\n");
|
||||
continue;
|
||||
}
|
||||
if(p->match_noedns && get_has_edns(query_pkt, len)) {
|
||||
verbose(3, "bad; EDNS OPT present\n");
|
||||
continue;
|
||||
@@ -1745,11 +1774,14 @@ adjust_packet(struct entry* match, uint8_t** answer_pkt, size_t *answer_len,
|
||||
memmove(res+LDNS_HEADER_SIZE+dlen+4,
|
||||
orig+LDNS_HEADER_SIZE+olen+4,
|
||||
reslen-(LDNS_HEADER_SIZE+dlen+4));
|
||||
} else if(origlen == 0) {
|
||||
res = NULL;
|
||||
reslen = 0;
|
||||
} else {
|
||||
res = memdup(orig, origlen);
|
||||
reslen = origlen;
|
||||
}
|
||||
if(!res) {
|
||||
if(!res && reslen > 0) {
|
||||
verbose(1, "out of memory; send without adjust\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -218,6 +218,8 @@ struct entry {
|
||||
uint8_t match_ttl;
|
||||
/** match DO bit */
|
||||
uint8_t match_do;
|
||||
/** match CO bit */
|
||||
uint8_t match_co;
|
||||
/** match absence of EDNS OPT record in query */
|
||||
uint8_t match_noedns;
|
||||
/** match edns data field given in hex */
|
||||
|
||||
@@ -207,7 +207,11 @@ rr_test_file(const char* input, const char* check)
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
||||
#ifndef __QNX__
|
||||
#define SRCDIRSTR xstr(SRCDIR)
|
||||
#else /* !__QNX__ */
|
||||
#define SRCDIRSTR "."
|
||||
#endif /* __QNX__ */
|
||||
|
||||
/** read rrs to and from string, to and from wireformat */
|
||||
static void
|
||||
|
||||
+1
-1
@@ -283,7 +283,7 @@ net_test(void)
|
||||
unit_assert(strcmp(astr, "1.2.3.0") == 0);
|
||||
unit_assert(ntohs(((struct sockaddr_in*)&a)->sin_port)==53);
|
||||
|
||||
res = netblockstrtoaddr("2001:DB8:33:44::/64", 53,
|
||||
res = netblockstrtoaddr("2001:db8:33:44::/64", 53,
|
||||
&a, &alen, &net);
|
||||
unit_assert(res!=0 && net == 64);
|
||||
addr_to_str(&a, alen, astr, sizeof(astr));
|
||||
|
||||
@@ -498,7 +498,11 @@ testfromdrillfile(sldns_buffer* pkt, struct alloc_cache* alloc,
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
||||
#ifndef __QNX__
|
||||
#define SRCDIRSTR xstr(SRCDIR)
|
||||
#else /* !__QNX__ */
|
||||
#define SRCDIRSTR "."
|
||||
#endif /* __QNX__ */
|
||||
|
||||
void msgparse_test(void)
|
||||
{
|
||||
|
||||
@@ -513,8 +513,11 @@ nsec3_hash_test(const char* fname)
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
||||
#ifndef __QNX__
|
||||
#define SRCDIRSTR xstr(SRCDIR)
|
||||
|
||||
#else /* !__QNX__ */
|
||||
#define SRCDIRSTR "."
|
||||
#endif /* __QNX__ */
|
||||
#if defined(HAVE_SSL) && defined(USE_SHA1)
|
||||
/* Detect if openssl is configured to disable RSASHA1 signatures,
|
||||
* with the rh-allow-sha1-signatures disabled. */
|
||||
|
||||
@@ -50,7 +50,11 @@
|
||||
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
#ifndef __QNX__
|
||||
#define SRCDIRSTR xstr(SRCDIR)
|
||||
#else /* !__QNX__ */
|
||||
#define SRCDIRSTR "."
|
||||
#endif /* __QNX__ */
|
||||
|
||||
/** Add zone from file for testing */
|
||||
struct auth_zone* authtest_addzone(struct auth_zones* az, const char* name,
|
||||
|
||||
Vendored
+1
-1
@@ -24,7 +24,7 @@ server:
|
||||
# specify every interface on a new 'interface:' labelled line.
|
||||
interface: 192.0.2.153
|
||||
interface: 192.0.2.154
|
||||
interface: 2001:DB8::5
|
||||
interface: 2001:db8::5
|
||||
|
||||
# port to answer queries from
|
||||
port: 53
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ server:
|
||||
# specify every interface on a new 'interface:' labelled line.
|
||||
interface: 192.0.2.153
|
||||
interface: 192.0.2.154
|
||||
interface: 2001:DB8::5
|
||||
interface: 2001:db8::5
|
||||
interface: 0.0.0.0@5353
|
||||
|
||||
# config
|
||||
|
||||
Vendored
+341
@@ -0,0 +1,341 @@
|
||||
; config options
|
||||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
access-control: 1.2.3.0/24 allow
|
||||
|
||||
auth-zone:
|
||||
name: "example.com."
|
||||
## zonefile (or none).
|
||||
## zonefile: "example.com.zone"
|
||||
## master by IP address or hostname
|
||||
## can list multiple masters, each on one line.
|
||||
## master:
|
||||
master: 1.2.3.44
|
||||
## this is as a hostname, to test the hostname lookup.
|
||||
allow-notify: svr.example.org
|
||||
## url for http fetch
|
||||
## url:
|
||||
## queries from downstream clients get authoritative answers.
|
||||
## for-downstream: yes
|
||||
for-downstream: yes
|
||||
## queries are used to fetch authoritative answers from this zone,
|
||||
## instead of unbound itself sending queries there.
|
||||
## for-upstream: yes
|
||||
for-upstream: yes
|
||||
## on failures with for-upstream, fallback to sending queries to
|
||||
## the authority servers
|
||||
## fallback-enabled: no
|
||||
|
||||
## this line generates zonefile: \n"/tmp/xxx.example.com"\n
|
||||
zonefile:
|
||||
TEMPFILE_NAME example.com
|
||||
## this is the inline file /tmp/xxx.example.com
|
||||
## the tempfiles are deleted when the testrun is over.
|
||||
TEMPFILE_CONTENTS example.com
|
||||
example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||
TEMPFILE_END
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test authority zone with lookup for a NOTIFY
|
||||
; The allow-notify is specified as a hostname.
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
com. IN NS
|
||||
SECTION AUTHORITY
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
org. IN NS
|
||||
SECTION AUTHORITY
|
||||
org. IN NS ns.org.
|
||||
SECTION ADDITIONAL
|
||||
ns.org. IN A 1.2.3.45
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.gtld-servers.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
com. IN NS
|
||||
SECTION ANSWER
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN NS
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.44
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.org
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.45
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
org. IN NS
|
||||
SECTION ANSWER
|
||||
org. IN NS ns.org.
|
||||
SECTION ADDITIONAL
|
||||
ns.org. IN A 1.2.3.45
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.org. IN NS
|
||||
SECTION AUTHORITY
|
||||
example.org. IN NS ns.example.org.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.org. IN A 1.2.3.46
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.example.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.44
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.net. IN NS
|
||||
SECTION ANSWER
|
||||
example.net. IN NS ns.example.net.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.net. IN A 1.2.3.44
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
ns.example.net. IN A
|
||||
SECTION ANSWER
|
||||
ns.example.net. IN A 1.2.3.44
|
||||
SECTION AUTHORITY
|
||||
example.net. IN NS ns.example.net.
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
ns.example.net. IN AAAA
|
||||
SECTION AUTHORITY
|
||||
example.net. IN NS ns.example.net.
|
||||
SECTION ADDITIONAL
|
||||
www.example.net. IN A 1.2.3.44
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN NS
|
||||
SECTION ANSWER
|
||||
example.com. IN NS ns.example.net.
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN A 10.20.30.40
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN SOA
|
||||
SECTION ANSWER
|
||||
; serial, refresh, retry, expire, minimum
|
||||
example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOTIMPL
|
||||
SECTION QUESTION
|
||||
example.com. IN IXFR
|
||||
SECTION ANSWER
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN AXFR
|
||||
SECTION ANSWER
|
||||
example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
|
||||
example.com. IN NS ns.example.net.
|
||||
EXTRA_PACKET
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN AXFR
|
||||
SECTION ANSWER
|
||||
www.example.com. IN A 1.2.3.4
|
||||
example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.example.org.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.46
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
example.org. IN NS
|
||||
SECTION ANSWER
|
||||
example.org. IN NS ns.example.org.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.org. IN A 1.2.3.46
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
svr.example.org. IN A
|
||||
SECTION ANSWER
|
||||
svr.example.org. IN A 1.2.3.47
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
svr.example.org. IN AAAA
|
||||
SECTION AUTHORITY
|
||||
example.org. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; lookups for notify hostnames.
|
||||
STEP 1 TIME_PASSES ELAPSE 0
|
||||
|
||||
; now the query
|
||||
STEP 2 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 20 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR AA RD RA NXDOMAIN
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
|
||||
ENTRY_END
|
||||
|
||||
; NOTIFY example.com
|
||||
STEP 30 QUERY ADDRESS 1.2.3.47
|
||||
ENTRY_BEGIN
|
||||
REPLY NOTIFY
|
||||
SECTION QUESTION
|
||||
example.com. IN SOA
|
||||
ENTRY_END
|
||||
; notify reply
|
||||
STEP 40 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RA NOTIFY NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN SOA
|
||||
SECTION ANSWER
|
||||
ENTRY_END
|
||||
|
||||
STEP 50 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 60 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR AA RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
; the zonefile was updated with new contents
|
||||
STEP 70 CHECK_TEMPFILE example.com
|
||||
FILE_BEGIN
|
||||
example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
|
||||
example.com. 3600 IN NS ns.example.net.
|
||||
www.example.com. 3600 IN A 1.2.3.4
|
||||
FILE_END
|
||||
|
||||
SCENARIO_END
|
||||
Vendored
+10
-4
@@ -226,6 +226,7 @@ STEP 150 TIME_PASSES ELAPSE 200
|
||||
STEP 160 FLUSH_MESSAGE www.example.com. IN A
|
||||
|
||||
; cache has no answer, cachedb is expired
|
||||
; but it needs to be validated.
|
||||
STEP 170 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD DO
|
||||
@@ -235,12 +236,14 @@ ENTRY_END
|
||||
|
||||
STEP 180 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl ede=3
|
||||
MATCH all ttl
|
||||
;ede=3
|
||||
REPLY QR RD RA DO NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 123 IN A 1.2.3.4
|
||||
;www.example.com. 123 IN A 1.2.3.4
|
||||
www.example.com. 200 IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
STEP 190 TRAFFIC
|
||||
@@ -298,14 +301,17 @@ SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
; but it needs to be validated
|
||||
STEP 280 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl ede=3
|
||||
MATCH all ttl
|
||||
;ede=3
|
||||
REPLY QR RD RA DO NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. 123 IN A 1.2.3.4
|
||||
;www.example.com. 123 IN A 1.2.3.4
|
||||
www.example.com. 200 IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
STEP 290 TRAFFIC
|
||||
|
||||
Vendored
+272
@@ -0,0 +1,272 @@
|
||||
; config options
|
||||
; Test DNAME TTL=0 grace period: synthesis from cache within 1 second
|
||||
; Island of trust at example.com, DNSSEC signed DNAME with TTL=0 (RFC 2308)
|
||||
server:
|
||||
trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
|
||||
trust-anchor: "example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}"
|
||||
val-override-date: "20070916134226"
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
qname-minimisation: "no"
|
||||
fake-sha1: yes
|
||||
trust-anchor-signaling: no
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test DNAME TTL=0: signed DNAME with TTL=0 and RRSIG Original TTL=0.
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
com. IN NS
|
||||
SECTION AUTHORITY
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
net. IN A
|
||||
SECTION AUTHORITY
|
||||
net. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.gtld-servers.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
com. IN NS
|
||||
SECTION ANSWER
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
net. IN NS
|
||||
SECTION ANSWER
|
||||
net. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN NS
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.net. IN A
|
||||
SECTION AUTHORITY
|
||||
example.net. IN NS ns.example.net.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.net. IN A 1.2.3.5
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.example.com. - DNAME with TTL=0 (RRSIG Original TTL=0)
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.4
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN NS
|
||||
SECTION ANSWER
|
||||
example.com. IN NS ns.example.com.
|
||||
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN DNSKEY
|
||||
SECTION ANSWER
|
||||
example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
|
||||
example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854}
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
|
||||
ENTRY_END
|
||||
|
||||
; DNAME with TTL=0, RRSIG Original TTL=0 (signed with ldns-signzone)
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
foo.test-dname.example.com. IN A
|
||||
SECTION ANSWER
|
||||
test-dname.example.com. 0 IN DNAME example.net.
|
||||
test-dname.example.com. 0 IN RRSIG DNAME 3 3 0 20070926135752 20070829135752 2854 example.com. ADRb2Jl5SCTF2a9/5QFOCfwFzh4Cpt90pJptwrKc+vBHnlivGyPShrU=
|
||||
foo.test-dname.example.com. 0 IN CNAME foo.example.net.
|
||||
ENTRY_END
|
||||
|
||||
RANGE_END
|
||||
|
||||
; ns.example.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.5
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.net. IN NS
|
||||
SECTION ANSWER
|
||||
example.net. IN NS ns.example.net.
|
||||
example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
|
||||
SECTION ADDITIONAL
|
||||
ns.example.net. IN A 1.2.3.5
|
||||
ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.net. IN DNSKEY
|
||||
SECTION ANSWER
|
||||
example.net. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
|
||||
example.net. 3600 IN RRSIG DNSKEY RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. hiFzlQ8VoYgCuvIsfVuxC3mfJDqsTh0yc6abs5xMx5uEcIjb0dndFQx7INOM+imlzveEN73Hqp4OLFpFhsWLlw== ;{id = 30899}
|
||||
SECTION AUTHORITY
|
||||
example.net. IN NS ns.example.net.
|
||||
example.net. 3600 IN RRSIG NS RSASHA1 2 3600 20070926134150 20070829134150 30899 example.net. E8JX0l4B+cSR5bkHQwOJy1pBmlLMTYCJ8EwfNMU/eCv0YhKwo26rHhn52FGisgv+Nwp7/NbhHqQ+kJgoZC94XA== ;{id = 30899}
|
||||
SECTION ADDITIONAL
|
||||
ns.example.net. IN A 1.2.3.5
|
||||
ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
foo.example.net. IN A
|
||||
SECTION ANSWER
|
||||
foo.example.net. IN A 11.12.13.15
|
||||
foo.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. X6T6SE9UzxAD/4zKpwGOxEDyE4g7lfYYw3lvw533uwRN8mWTcBvSva0/jjyhrogJcuLO32jPHK6zGb93w2xnuA==
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
foo2.example.net. IN A
|
||||
SECTION ANSWER
|
||||
foo2.example.net. IN A 11.12.13.16
|
||||
foo2.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. BZm+GljD8m9N+pNJN8D+LlSyHqM+InNUe0+heKILR9be+Goqv6SEb7LKtX6+kj3239Y5by7u+/Cuk8kkWistEQ==
|
||||
SECTION AUTHORITY
|
||||
SECTION ADDITIONAL
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 TIME_PASSES ELAPSE 10
|
||||
; First query: get DNAME TTL=0 into cache
|
||||
STEP 10 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD DO
|
||||
SECTION QUESTION
|
||||
foo.test-dname.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 20 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl
|
||||
REPLY QR RD RA AD DO NOERROR
|
||||
SECTION QUESTION
|
||||
foo.test-dname.example.com. IN A
|
||||
SECTION ANSWER
|
||||
test-dname.example.com. 0 IN DNAME example.net.
|
||||
test-dname.example.com. 0 IN RRSIG DNAME 3 3 0 20070926135752 20070829135752 2854 example.com. ADRb2Jl5SCTF2a9/5QFOCfwFzh4Cpt90pJptwrKc+vBHnlivGyPShrU=
|
||||
foo.test-dname.example.com. 0 IN CNAME foo.example.net.
|
||||
foo.example.net. IN A 11.12.13.15
|
||||
foo.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. X6T6SE9UzxAD/4zKpwGOxEDyE4g7lfYYw3lvw533uwRN8mWTcBvSva0/jjyhrogJcuLO32jPHK6zGb93w2xnuA==
|
||||
ENTRY_END
|
||||
|
||||
STEP 29 TIME_PASSES ELAPSE 1
|
||||
|
||||
; Second query: within grace period (TIME_PASSES 1 above)
|
||||
; With cache grace: synthesis from cached TTL=0 DNAME
|
||||
STEP 30 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD DO
|
||||
SECTION QUESTION
|
||||
foo2.test-dname.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
; foo2.test-dname.example.com is not answered upstream
|
||||
; so this reply is synthesized by the cached (1 second grace period) DNAME
|
||||
STEP 40 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl
|
||||
REPLY QR RD RA AD DO NOERROR
|
||||
SECTION QUESTION
|
||||
foo2.test-dname.example.com. IN A
|
||||
SECTION ANSWER
|
||||
test-dname.example.com. 0 IN DNAME example.net.
|
||||
test-dname.example.com. 0 IN RRSIG DNAME 3 3 0 20070926135752 20070829135752 2854 example.com. ADRb2Jl5SCTF2a9/5QFOCfwFzh4Cpt90pJptwrKc+vBHnlivGyPShrU=
|
||||
foo2.test-dname.example.com. 0 IN CNAME foo2.example.net.
|
||||
foo2.example.net. 3600 IN A 11.12.13.16
|
||||
foo2.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. BZm+GljD8m9N+pNJN8D+LlSyHqM+InNUe0+heKILR9be+Goqv6SEb7LKtX6+kj3239Y5by7u+/Cuk8kkWistEQ==
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
Vendored
+192
@@ -0,0 +1,192 @@
|
||||
; config options
|
||||
server:
|
||||
do-nat64: yes
|
||||
nat64-prefix: 2001:db8:1234::/96
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
|
||||
; This is like a machine that is part of a cluster of hosts that
|
||||
; is IPv6-only, and uses NAT64. The cluster has no internet access.
|
||||
do-not-query-address: ::0/0
|
||||
|
||||
qname-minimisation: no
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
; Pick an address in the NAT64 prefix, so it is allowed.
|
||||
; other addresses would not be allowed. Or without the bugfix,
|
||||
; allowed depending on state machine activation sequence.
|
||||
stub-addr: 2001:db8:1234::1
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test NAT64 transport for v4-only with do-not-query-addresses.
|
||||
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 2001:db8:1234::1
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS FAKE.ROOT.
|
||||
SECTION ADDITIONAL
|
||||
FAKE.ROOT. IN AAAA 2001:db8:1234::1
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
v4only. IN NS
|
||||
SECTION AUTHORITY
|
||||
v4only. IN NS ns.v4only.
|
||||
SECTION ADDITIONAL
|
||||
ns.v4only. IN A 192.0.2.1
|
||||
ENTRY_END
|
||||
|
||||
RANGE_END
|
||||
|
||||
; replies from NS over "NAT64"
|
||||
|
||||
RANGE_BEGIN 0 20
|
||||
ADDRESS 2001:db8:1234::c000:0201
|
||||
|
||||
; A over NAT64
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY AA QR NOERROR
|
||||
SECTION QUESTION
|
||||
ns.v4only. IN A
|
||||
SECTION ANSWER
|
||||
ns.v4only. IN A 192.0.2.1
|
||||
SECTION AUTHORITY
|
||||
v4only. IN NS ns.v4only.
|
||||
ENTRY_END
|
||||
|
||||
; no AAAA
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY AA QR NOERROR
|
||||
SECTION QUESTION
|
||||
ns.v4only. IN AAAA
|
||||
SECTION AUTHORITY
|
||||
v4only. IN SOA ns.v4only. host. 1 3600 300 48000 3600
|
||||
v4only. IN NS ns.v4only.
|
||||
SECTION ADDITIONAL
|
||||
ns.v4only. IN A 192.0.2.1
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY AA QR NOERROR
|
||||
SECTION QUESTION
|
||||
v4only. IN NS
|
||||
SECTION ANSWER
|
||||
v4only. IN NS ns.v4only.
|
||||
SECTION ADDITIONAL
|
||||
ns.v4only. IN A 192.0.2.1
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY AA QR NOERROR
|
||||
SECTION QUESTION
|
||||
test.v4only. IN A
|
||||
SECTION ANSWER
|
||||
test.v4only. IN A 192.0.2.2
|
||||
SECTION AUTHORITY
|
||||
v4only. IN NS ns.v4only.
|
||||
SECTION ADDITIONAL
|
||||
ns.v4only. IN A 192.0.2.1
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
RANGE_BEGIN 50 100
|
||||
ADDRESS 2001:db8:1234::c000:0201
|
||||
; no AAAA
|
||||
; The last resort lookup of the AAAA is blocked here,
|
||||
; the last resort processing is not desired, it should resolve test2
|
||||
; straight away.
|
||||
;ENTRY_BEGIN
|
||||
;MATCH opcode qtype qname
|
||||
;ADJUST copy_id
|
||||
;REPLY AA QR NOERROR
|
||||
;SECTION QUESTION
|
||||
;ns.v4only. IN AAAA
|
||||
;SECTION AUTHORITY
|
||||
;v4only. IN SOA ns.v4only. host. 1 3600 300 48000 3600
|
||||
;v4only. IN NS ns.v4only.
|
||||
;SECTION ADDITIONAL
|
||||
;ns.v4only. IN A 192.0.2.1
|
||||
;ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY AA QR NOERROR
|
||||
SECTION QUESTION
|
||||
ns.v4only. IN A
|
||||
SECTION ANSWER
|
||||
ns.v4only. IN A 192.0.2.1
|
||||
SECTION AUTHORITY
|
||||
v4only. IN NS ns.v4only.
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY AA QR NOERROR
|
||||
SECTION QUESTION
|
||||
test2.v4only. IN A
|
||||
SECTION ANSWER
|
||||
test2.v4only. IN A 192.0.2.3
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
test.v4only. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 20 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
test.v4only. IN A
|
||||
SECTION ANSWER
|
||||
test.v4only. IN A 192.0.2.2
|
||||
ENTRY_END
|
||||
|
||||
; for a query where the upstream nameserver has a timeout.
|
||||
STEP 30 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
test2.v4only. IN A
|
||||
ENTRY_END
|
||||
|
||||
; Only the test2 query is there, and it has a timeout.
|
||||
; The address is already NAT64 translated, so now that it is
|
||||
; attempted again, it is looked up in dotnotq as the ipv6 address.
|
||||
STEP 40 TIMEOUT
|
||||
|
||||
STEP 50 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
test2.v4only. IN A
|
||||
SECTION ANSWER
|
||||
test2.v4only. IN A 192.0.2.3
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
Vendored
+283
@@ -0,0 +1,283 @@
|
||||
; config options
|
||||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
qname-minimisation: no
|
||||
minimal-responses: yes
|
||||
iter-scrub-promiscuous: yes
|
||||
|
||||
private-address: 10.0.0.0/8
|
||||
private-address: 172.16.0.0/12
|
||||
private-address: 192.168.0.0/16
|
||||
private-address: 169.254.0.0/16
|
||||
private-address: fd00::/8
|
||||
private-address: fe80::/10
|
||||
|
||||
private-domain: "example.net"
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test iterator scrubber with private addresses in SVCB.
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
com. IN A
|
||||
SECTION AUTHORITY
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
; root server authoritative for example.net too.
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
mail.example.net. IN SVCB
|
||||
SECTION ANSWER
|
||||
mail.example.net. IN SVCB 1 foo.example.net. ipv4hint=10.20.30.40
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.gtld-servers.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
com. IN NS
|
||||
SECTION ANSWER
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.example.com.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.4
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN NS
|
||||
SECTION ANSWER
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
ns.example.com. IN A
|
||||
SECTION ANSWER
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
ns.example.com. IN AAAA
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
example.com. IN SOA ns.example.com. root.example.com. 4 14400 3600 604800 3600
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN SVCB
|
||||
SECTION ANSWER
|
||||
www.example.com. IN SVCB 1 foo.example.com. ipv4hint=192.20.30.40
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
mail.example.com. IN SVCB
|
||||
SECTION ANSWER
|
||||
mail.example.com. IN SVCB 1 foo.example.com. ipv6hint=fe80::15
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
foo.example.com. IN SVCB
|
||||
SECTION ANSWER
|
||||
foo.example.com. IN SVCB 1 foo.example.com. ipv4hint=10.20.30.40
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
toss.example.com. IN SVCB
|
||||
SECTION ANSWER
|
||||
toss.example.com. IN SVCB 1 foo.example.com. ipv4hint=10.20.30.40
|
||||
toss.example.com. IN SVCB 1 foo.example.com. ipv4hint=10.20.30.40
|
||||
toss.example.com. IN SVCB 1 foo.example.com. ipv4hint=1.2.3.4
|
||||
toss.example.com. IN SVCB 1 foo.example.com. ipv6hint=fe80::15
|
||||
toss.example.com. IN SVCB 1 foo.example.com. ipv4hint=10.20.30.41
|
||||
toss.example.com. IN SVCB 1 foo.example.com. ipv4hint=192.0.2.1,10.20.30.42,192.0.2.2
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; public address is not scrubbed
|
||||
STEP 1 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
www.example.com. IN SVCB
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 2 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN SVCB
|
||||
SECTION ANSWER
|
||||
www.example.com. IN SVCB 1 foo.example.com. ipv4hint=192.20.30.40
|
||||
ENTRY_END
|
||||
|
||||
; IPv4 address is scrubbed
|
||||
STEP 3 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
foo.example.com. IN SVCB
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 10 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
foo.example.com. IN SVCB
|
||||
SECTION ANSWER
|
||||
; scrubbed away
|
||||
ENTRY_END
|
||||
|
||||
; IPv6 address is scrubbed
|
||||
STEP 20 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
mail.example.com. IN SVCB
|
||||
ENTRY_END
|
||||
|
||||
STEP 30 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
mail.example.com. IN SVCB
|
||||
SECTION ANSWER
|
||||
ENTRY_END
|
||||
|
||||
; allowed domain is not scrubbed.
|
||||
STEP 40 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
mail.example.net. IN SVCB
|
||||
ENTRY_END
|
||||
|
||||
STEP 50 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
mail.example.net. IN SVCB
|
||||
SECTION ANSWER
|
||||
mail.example.net. IN SVCB 1 foo.example.net. ipv4hint=10.20.30.40
|
||||
ENTRY_END
|
||||
|
||||
; rest of RRset intact, only 10/8 tossed away.
|
||||
STEP 60 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
toss.example.com. IN SVCB
|
||||
ENTRY_END
|
||||
|
||||
STEP 70 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
toss.example.com. IN SVCB
|
||||
SECTION ANSWER
|
||||
toss.example.com. IN SVCB 1 foo.example.com. ipv4hint=1.2.3.4
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
; config options
|
||||
server:
|
||||
harden-referral-path: no
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
qname-minimisation: "no"
|
||||
minimal-responses: no
|
||||
iter-scrub-promiscuous: no
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test scrub of out-of-zone DNAME in answer section
|
||||
|
||||
STEP 10 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
x.y.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
; root prime is sent
|
||||
STEP 20 CHECK_OUT_QUERY
|
||||
ENTRY_BEGIN
|
||||
MATCH qname qtype opcode
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
ENTRY_END
|
||||
STEP 30 REPLY
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
; query sent to root server
|
||||
STEP 40 CHECK_OUT_QUERY
|
||||
ENTRY_BEGIN
|
||||
MATCH qname qtype opcode
|
||||
SECTION QUESTION
|
||||
x.y.example.com. IN A
|
||||
ENTRY_END
|
||||
STEP 50 REPLY
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
x.y.example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
; query sent to .com server
|
||||
STEP 60 CHECK_OUT_QUERY
|
||||
ENTRY_BEGIN
|
||||
MATCH qname qtype opcode
|
||||
SECTION QUESTION
|
||||
x.y.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 70 REPLY
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
x.y.example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns1.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns1.example.com. IN A 168.192.2.2
|
||||
ENTRY_END
|
||||
|
||||
STEP 80 CHECK_OUT_QUERY
|
||||
ENTRY_BEGIN
|
||||
MATCH qname qtype opcode
|
||||
SECTION QUESTION
|
||||
x.y.example.com. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 90 REPLY
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
x.y.example.com. IN A
|
||||
SECTION ANSWER
|
||||
com. DNAME z.example.com.
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns1.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns1.example.com. IN A 168.192.2.2
|
||||
ENTRY_END
|
||||
|
||||
; answer to first query
|
||||
; nodata answer since the DNAME is ignored for synthesis and scrubbed
|
||||
; all together.
|
||||
STEP 120 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ttl
|
||||
REPLY QR RD RA
|
||||
SECTION QUESTION
|
||||
x.y.example.com. IN A
|
||||
SECTION ANSWER
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns1.example.com.
|
||||
SECTION ADDITIONAL
|
||||
ns1.example.com. IN A 168.192.2.2
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
Vendored
+84
@@ -16,6 +16,7 @@ SCENARIO_BEGIN Test iterator with scrub of promiscuous records
|
||||
; The spoofed contents are ns.attacker.mesa and its IPs 5.6.7.8 and 5.6.7.9.
|
||||
; The pollute1.mesa NS, ns.pollute2.mesa A, and test3.atkr.pollute3.mesa NS
|
||||
; with ns.pollute3.mesa A records are tested for cache placement.
|
||||
; pollute4.mesa uses YXDOMAIN.
|
||||
|
||||
; ns.root
|
||||
RANGE_BEGIN 0 400
|
||||
@@ -84,6 +85,18 @@ SECTION ADDITIONAL
|
||||
ns.pollute3.mesa. IN A 1.2.4.3
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
pollute4.mesa. IN NS
|
||||
SECTION AUTHORITY
|
||||
pollute4.mesa. IN NS ns.pollute4.mesa.
|
||||
SECTION ADDITIONAL
|
||||
ns.pollute4.mesa. IN A 1.2.4.4
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode subdomain
|
||||
ADJUST copy_id copy_query
|
||||
@@ -188,6 +201,35 @@ check.pollute3.mesa. IN A 1.8.9.3
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.pollute4.mesa
|
||||
RANGE_BEGIN 0 400
|
||||
ADDRESS 1.2.4.4
|
||||
|
||||
; This is the spoofed answer that is returned.
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA YXDOMAIN
|
||||
SECTION QUESTION
|
||||
test4.atkr.pollute4.mesa. IN A
|
||||
SECTION ANSWER
|
||||
test4.atkr.pollute4.mesa. 86400 IN A 1.2.3.4
|
||||
SECTION AUTHORITY
|
||||
pollute4.mesa. 86400 IN NS ns.attacker.mesa.
|
||||
ENTRY_END
|
||||
|
||||
; correct answer for the check query.
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
check.pollute4.mesa. IN A
|
||||
SECTION ANSWER
|
||||
check.pollute4.mesa. IN A 1.8.9.4
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.attacker.mesa
|
||||
RANGE_BEGIN 0 400
|
||||
ADDRESS 5.6.7.8
|
||||
@@ -370,4 +412,46 @@ check.pollute3.mesa. IN A 1.8.9.3
|
||||
;check.pollute3.mesa. IN A 5.6.7.9
|
||||
ENTRY_END
|
||||
|
||||
; Test query 4
|
||||
STEP 120 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
test4.atkr.pollute4.mesa. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 130 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA YXDOMAIN
|
||||
SECTION QUESTION
|
||||
test4.atkr.pollute4.mesa. IN A
|
||||
SECTION ANSWER
|
||||
test4.atkr.pollute4.mesa. 86400 IN A 1.2.3.4
|
||||
SECTION AUTHORITY
|
||||
; removed record
|
||||
;pollute4.mesa. 0 IN NS ns.attacker.mesa.
|
||||
ENTRY_END
|
||||
|
||||
; Check the cache contents, for query 4.
|
||||
STEP 140 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD
|
||||
SECTION QUESTION
|
||||
check.pollute4.mesa. IN A
|
||||
ENTRY_END
|
||||
|
||||
STEP 150 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all
|
||||
REPLY QR RD RA NOERROR
|
||||
SECTION QUESTION
|
||||
check.pollute4.mesa. IN A
|
||||
SECTION ANSWER
|
||||
; good answer
|
||||
check.pollute4.mesa. IN A 1.8.9.4
|
||||
; bad answer
|
||||
;check.pollute4.mesa. IN A 5.6.7.9
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
server:
|
||||
verbosity: 5
|
||||
num-threads: 1
|
||||
interface: 127.0.0.1@@PORT@
|
||||
use-syslog: no
|
||||
directory: ""
|
||||
pidfile: "unbound.pid"
|
||||
chroot: ""
|
||||
username: ""
|
||||
do-not-query-localhost: no
|
||||
|
||||
metrics-enable: yes
|
||||
metrics-path: "/metrics"
|
||||
metrics-interface: 127.0.0.1
|
||||
metrics-port: @METRICSPORT@
|
||||
|
||||
statistics-cumulative: yes
|
||||
extended-statistics: yes
|
||||
statistics-inhibit-zero: yes
|
||||
statistics-interval: 0
|
||||
|
||||
local-data: "www.example.com. IN A 192.0.2.10"
|
||||
local-data: 'a.example.com. IN TXT "abcdef text"'
|
||||
|
||||
remote-control:
|
||||
control-enable: yes
|
||||
control-interface: 127.0.0.1
|
||||
# control-interface: ::1
|
||||
control-port: @CONTROL_PORT@
|
||||
server-key-file: "unbound_server.key"
|
||||
server-cert-file: "unbound_server.pem"
|
||||
control-key-file: "unbound_control.key"
|
||||
control-cert-file: "unbound_control.pem"
|
||||
@@ -0,0 +1,16 @@
|
||||
BaseName: prometheus_metrics
|
||||
Version: 1.0
|
||||
Description: Test prometheus metrics
|
||||
CreationDate: Fri 30 Jan 13:22:03 CET 2026
|
||||
Maintainer: dr. Wouter Wijngaards
|
||||
Category:
|
||||
Component:
|
||||
CmdDepends:
|
||||
Depends:
|
||||
Help:
|
||||
Pre: prometheus_metrics.pre
|
||||
Post: prometheus_metrics.post
|
||||
Test: prometheus_metrics.test
|
||||
AuxFiles: prometheus_metrics.conf, prometheus_metrics.zone
|
||||
Passed:
|
||||
Failure:
|
||||
@@ -0,0 +1,11 @@
|
||||
# #-- prometheus_metrics.post --#
|
||||
# source the master var file when it's there
|
||||
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||
# source the test var file when it's there
|
||||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
#
|
||||
# do your teardown here
|
||||
. ../common.sh
|
||||
kill_pid $UNBOUND_PID
|
||||
cat unbound.log
|
||||
exit 0
|
||||
@@ -0,0 +1,33 @@
|
||||
# #-- prometheus_metrics.pre--#
|
||||
# source the master var file when it's there
|
||||
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||
# use .tpkg.var.test for in test variable passing
|
||||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
. ../common.sh
|
||||
PRE="../.."
|
||||
if grep "define USE_METRICS" $PRE/config.h; then echo test enabled; else skip_test "test skipped"; fi
|
||||
# Is curl available
|
||||
if test -f "$(which curl 2>&1)"; then
|
||||
echo "curl available, do test"
|
||||
else
|
||||
skip_test "curl not available, skip test"
|
||||
fi
|
||||
|
||||
get_random_port 3
|
||||
UNBOUND_PORT=$RND_PORT
|
||||
CONTROL_PORT=$(($RND_PORT + 1))
|
||||
METRICS_PORT=$(($RND_PORT + 2))
|
||||
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
|
||||
echo "CONTROL_PORT=$CONTROL_PORT" >> .tpkg.var.test
|
||||
echo "METRICS_PORT=$METRICS_PORT" >> .tpkg.var.test
|
||||
|
||||
# make config file
|
||||
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@METRICSPORT\@/'$METRICS_PORT'/' -e 's/@CONTROL_PORT\@/'$CONTROL_PORT'/' < prometheus_metrics.conf > ub.conf
|
||||
# start unbound in the background
|
||||
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
|
||||
UNBOUND_PID=$!
|
||||
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
|
||||
|
||||
cat .tpkg.var.test
|
||||
wait_unbound_up unbound.log
|
||||
@@ -0,0 +1,113 @@
|
||||
# #-- prometheus_metrics.test --#
|
||||
# source the master var file when it's there
|
||||
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||
# use .tpkg.var.test for in test variable passing
|
||||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
. ../common.sh
|
||||
PRE="../.."
|
||||
|
||||
NUM_A_QUERIES=5
|
||||
NUM_TXT_QUERIES=3
|
||||
|
||||
# query server a few times
|
||||
for i in $(seq 1 $NUM_A_QUERIES); do
|
||||
dig @127.0.0.1 -p "$UNBOUND_PORT" www.example.com. A IN | tee out2
|
||||
if grep "192.0.2.10" out2; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "data not present"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
for i in $(seq 1 $NUM_TXT_QUERIES); do
|
||||
dig @127.0.0.1 -p "$UNBOUND_PORT" a.example.com. TXT IN | tee out2
|
||||
if grep "abcdef text" out2; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "data not present"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# stats no reset for comparison
|
||||
echo ""
|
||||
echo ">> unbound-control stats"
|
||||
$PRE/unbound-control -c ub.conf stats_noreset | tee stats
|
||||
|
||||
# check metrics
|
||||
if ! curl -Ssi "http://127.0.0.1:$METRICS_PORT/metrics" -o metrics.out; then
|
||||
echo "FAIL curl failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo ">> metrics output"
|
||||
cat metrics.out
|
||||
|
||||
echo ""
|
||||
echo ">> checks"
|
||||
|
||||
# more tests
|
||||
if grep -Fx "unbound_hits_queries{type=\"total.num.queries\"} $((NUM_TXT_QUERIES+NUM_A_QUERIES))" metrics.out; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "FAIL total num"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if grep -Fx "unbound_by_type_queries{type=\"TXT\"} $NUM_TXT_QUERIES" metrics.out; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "FAIL txt num"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if grep -Fx "unbound_by_type_queries{type=\"A\"} $NUM_A_QUERIES" metrics.out; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "FAIL A num"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# and check statistics are the same as metrics
|
||||
if grep "total.num.queries=$((NUM_TXT_QUERIES+NUM_A_QUERIES))" stats; then echo "OK"; else echo "FAIL"; exit 1; fi
|
||||
if grep "num.query.type.TXT=$NUM_TXT_QUERIES" stats; then echo "OK"; else echo "FAIL"; exit 1; fi
|
||||
if grep "num.query.type.A=$NUM_A_QUERIES" stats; then echo "OK"; else echo "FAIL"; exit 1; fi
|
||||
|
||||
# check that metrics shows no reset to stats after using nsd-control stats
|
||||
# check metrics again
|
||||
if ! curl -Ssi "http://127.0.0.1:$METRICS_PORT/metrics" -o metrics.out2; then
|
||||
echo "FAIL to curl again"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo ">> metrics output"
|
||||
cat metrics.out2
|
||||
echo ""
|
||||
echo ">> checks"
|
||||
|
||||
if grep -Fx "unbound_hits_queries{type=\"total.num.queries\"} $((NUM_TXT_QUERIES+NUM_A_QUERIES))" metrics.out2; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "FAIL total num again"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if grep -Fx "unbound_by_flags_queries{flag=\"RD\"} $((NUM_TXT_QUERIES+NUM_A_QUERIES))" metrics.out2; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "FAIL RD num again"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if grep -Fx "unbound_hits_queries{type=\"total.num.cachehits\"} $((NUM_TXT_QUERIES+NUM_A_QUERIES))" metrics.out2; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "FAIL cachehits num again"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,39 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIG4gIBAAKCAYEAstEp+Pyh8XGrtZ77A4FhYjvbeB3dMa7Q2rGWxobzlA9przhA
|
||||
1aChAvUtCOAuM+rB6NTNB8YWfZJbQHawyMNpmC77cg6vXLYCGUQHZyAqidN049RJ
|
||||
F5T7j4N8Vniv17LiRdr0S6swy4PRvEnIPPV43EQHZqC5jVvHsKkhIfmBF/Dj5TXR
|
||||
ypeawWV/m5jeU6/4HRYMfytBZdO1mPXuWLh0lgbQ4SCbgrOUVD3rniMk1yZIbQOm
|
||||
vlDHYqekjDb/vOW2KxUQLG04aZMJ1mWfdbwG0CKQkSjISEDZ1l76vhM6mTM0fwXb
|
||||
IvyFZ9yPPCle1mF5aSlxS2cmGuGVSRQaw8XF9fe3a9ACJJTr33HdSpyaZkKRAUzL
|
||||
cKqLCl323daKv3NwwAT03Tj4iQM416ASMoiyfFa/2GWTKQVjddu8Crar7tGaf5xr
|
||||
lig4DBmrBvdYA3njy72/RD71hLwmlRoCGU7dRuDr9O6KASUm1Ri91ONZ/qdjMvov
|
||||
15l2vj4GV+KXR00dAgMBAAECggGAHepIL1N0dEQkCdpy+/8lH54L9WhpnOo2HqAf
|
||||
LU9eaKK7d4jdr9+TkD8cLaPzltPrZNxVALvu/0sA4SP6J1wpyj/x6P7z73qzly5+
|
||||
Xo5PD4fEwmi9YaiW/UduAblnEZrnp/AddptJKoL/D5T4XtpiQddPtael4zQ7kB57
|
||||
YIexRSQTvEDovA/o3/nvA0TrzOxfgd4ycQP3iOWGN/TMzyLsvjydrUwbOB567iz9
|
||||
whL3Etdgvnwh5Sz2blbFfH+nAR8ctvFFz+osPvuIVR21VMEI6wm7kTpSNnQ6sh/c
|
||||
lrLb/bTADn4g7z/LpIZJ+MrLvyEcoqValrLYeFBhM9CV8woPxvkO2P3pU47HVGax
|
||||
tC7GV6a/kt5RoKFd/TNdiA3OC7NGZtaeXv9VkPf4fVwBtSO9d5ZZXTGEynDD/rUQ
|
||||
U4KFJe6OD23APjse08HiiKqTPhsOneOONU67iqoaTdIkT2R4EdlkVEDpXVtWb+G9
|
||||
Q+IqYzVljlzuyHrhWXLJw/FMa2aBAoHBAOnZbi4gGpH+P6886WDWVgIlTccuXoyc
|
||||
Mg9QQYk9UDeXxL0AizR5bZy49Sduegz9vkHpAiZARQsUnizHjZ8YlRcrmn4t6tx3
|
||||
ahTIKAjdprnxJfYINM580j8CGbXvX5LhIlm3O267D0Op+co3+7Ujy+cjsIuFQrP+
|
||||
1MqMgXSeBjzC1APivmps7HeFE+4w0k2PfN5wSMDNCzLo99PZuUG5XZ93OVOS5dpN
|
||||
b+WskdcD8NOoJy/X/5A08veEI/jYO/DyqQKBwQDDwUQCOWf41ecvJLtBHKmEnHDz
|
||||
ftzHino9DRKG8a9XaN4rmetnoWEaM2vHGX3pf3mwH+dAe8vJdAQueDhBKYeEpm6C
|
||||
TYNOpou1+Zs5s99BilCTNYo8fkMOAyqwRwmz9zgHS6QxXuPwsghKefLJGt6o6RFF
|
||||
tfWVTfLlYJ+I3GQe3ySsk3wjVz4oUTKiyiq5+KzD+HhEkS7u+RQ7Z0ZI2xd2cF8Y
|
||||
aN2hjKDpcOiFf3CDoqka5D1qMNLgIHO52AHww1UCgcA1h7o7AMpURRka6hyaODY0
|
||||
A4oMYEbwdQjYjIyT998W+rzkbu1us6UtzQEBZ760npkgyU/epbOoV63lnkCC/MOU
|
||||
LD0PST+L/CHiY/cWIHb79YG1EifUZKpUFg0Aoq0EGFkepF0MefGCkbRGYA5UZr9U
|
||||
R80wAu9D+L+JJiS0J0BSRF74DL196zUuHt5zFeXuLzxsRtPAnq9DliS08BACRYZy
|
||||
7H3I7cWD9Vn5/0jbKWHFcaaWwyETR6uekTcSzZzbCRECgcBeoE3/xUA9SSk34Mmj
|
||||
7/cB4522Ft0imA3+9RK/qJTZ7Bd5fC4PKjOGNtUiqW/0L2rjeIiQ40bfWvWqgPKw
|
||||
jSK1PL6uvkl6+4cNsFsYyZpiVDoe7wKju2UuoNlB3RUTqa2r2STFuNj2wRjA57I1
|
||||
BIgdnox65jqQsd14g/yaa+75/WP9CE45xzKEyrtvdcqxm0Pod3OrsYK+gikFjiar
|
||||
kT0GQ8u0QPzh2tjt/2ZnIfOBrl+QYERP0MofDZDjhUdq2wECgcB0Lu841+yP5cdR
|
||||
qbJhXO4zJNh7oWNcJlOuQp3ZMNFrA1oHpe9pmLukiROOy01k9WxIMQDzU5GSqRv3
|
||||
VLkYOIcbhJ3kClKAcM3j95SkKbU2H5/RENb3Ck52xtl4pNU1x/3PnVFZfDVuuHO9
|
||||
MZ9YBcIeK98MyP2jr5JtFKnOyPE7xKq0IHIhXadpbc2wjje5FtZ1cUtMyEECCXNa
|
||||
C1TpXebHGyXGpY9WdWXhjdE/1jPvfS+uO5WyuDpYPr339gsdq1g=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -0,0 +1,22 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDszCCAhsCFGD5193whHQ2bVdzbaQfdf1gc4SkMA0GCSqGSIb3DQEBCwUAMBIx
|
||||
EDAOBgNVBAMMB3VuYm91bmQwHhcNMjAwNzA4MTMzMjMwWhcNNDAwMzI1MTMzMjMw
|
||||
WjAaMRgwFgYDVQQDDA91bmJvdW5kLWNvbnRyb2wwggGiMA0GCSqGSIb3DQEBAQUA
|
||||
A4IBjwAwggGKAoIBgQCy0Sn4/KHxcau1nvsDgWFiO9t4Hd0xrtDasZbGhvOUD2mv
|
||||
OEDVoKEC9S0I4C4z6sHo1M0HxhZ9kltAdrDIw2mYLvtyDq9ctgIZRAdnICqJ03Tj
|
||||
1EkXlPuPg3xWeK/XsuJF2vRLqzDLg9G8Scg89XjcRAdmoLmNW8ewqSEh+YEX8OPl
|
||||
NdHKl5rBZX+bmN5Tr/gdFgx/K0Fl07WY9e5YuHSWBtDhIJuCs5RUPeueIyTXJkht
|
||||
A6a+UMdip6SMNv+85bYrFRAsbThpkwnWZZ91vAbQIpCRKMhIQNnWXvq+EzqZMzR/
|
||||
Bdsi/IVn3I88KV7WYXlpKXFLZyYa4ZVJFBrDxcX197dr0AIklOvfcd1KnJpmQpEB
|
||||
TMtwqosKXfbd1oq/c3DABPTdOPiJAzjXoBIyiLJ8Vr/YZZMpBWN127wKtqvu0Zp/
|
||||
nGuWKDgMGasG91gDeePLvb9EPvWEvCaVGgIZTt1G4Ov07ooBJSbVGL3U41n+p2My
|
||||
+i/XmXa+PgZX4pdHTR0CAwEAATANBgkqhkiG9w0BAQsFAAOCAYEAd++Wen6l8Ifj
|
||||
4h3p/y16PhSsWJWuJ4wdNYy3/GM84S26wGjzlEEwiW76HpH6VJzPOiBAeWnFKE83
|
||||
hFyetEIxgJeIPbcs9ZP/Uoh8GZH9tRISBSN9Hgk2Slr9llo4t1H0g/XTgA5HqMQU
|
||||
9YydlBh43G7Vw3FVwh09OM6poNOGQKNc/tq2/QdKeUMtyBbLWpRmjH5XcCT35fbn
|
||||
ZiVOUldqSHD4kKrFO4nJYXZyipRbcXybsLiX9GP0GLemc3IgIvOXyJ2RPp06o/SJ
|
||||
pzlMlkcAfLJaSuEW57xRakhuNK7m051TKKzJzIEX+NFYOVdafFHS8VwGrYsdrFvD
|
||||
72tMfu+Fu55y3awdWWGc6YlaGogZiuMnJkvQphwgn+5qE/7CGEckoKEsH601rqIZ
|
||||
muaIc85+nEcHJeijd/ZlBN9zeltjFoMuqTUENgmv8+tUAdVm/UMY9Vjme6b43ydP
|
||||
uv6DS02+k9z8toxXworLiPr94BGaiGV1NxgwZKLZigYJt/Fi2Qte
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,39 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIG5AIBAAKCAYEAvjSVSN2QMXudpzukdLCqgg/IOhCX8KYkD0FFFfWcQjgKq5wI
|
||||
0x41iG32a6wbGanre4IX7VxaSPu9kkHfnGgynCk5nwDRedE/FLFhAU78PoT0+Nqq
|
||||
GRS7XVQ24vLmIz9Hqc2Ozx1um1BXBTmIT0UfN2e22I0LWQ6a3seZlEDRj45gnk7Z
|
||||
uh9MDgotaBdm+v1JAbupSf6Zis4VEH3JNdvVGE3O1DHEIeuuz/3BDhpf6WBDH+8K
|
||||
WaBe1ca4TZHr9ThL2gEMEfAQl0wXDwRWRoi3NjNMH+mw0L1rjwThI5GXqNIee7o5
|
||||
FzUReSXZuTdFMyGe3Owcx+XoYnwi6cplSNoGsDBu4B9bKKglR9YleJVw4L4Xi8xP
|
||||
q6O9UPj4+nypHk/DOoC7DIM3ufN0yxPBsFo5TVowxfhdjZXJbbftd2TZv7AH8+XL
|
||||
A5UoZgRzXgzECelXSCTBFlMTnT48LfA9pMLydyjAz2UdPHs5Iv+TK5nnI+aJoeaP
|
||||
7kFZSngxdy1+A/bNAgMBAAECggGBALpTOIqQwVg4CFBylL/a8K1IWJTI/I65sklf
|
||||
XxYL7G7SB2HlEJ//z+E+F0+S4Vlao1vyLQ5QkgE82pAUB8FoMWvY1qF0Y8A5wtm6
|
||||
iZSGk4OLK488ZbT8Ii9i+AGKgPe2XbVxsJwj8N4k7Zooqec9hz73Up8ATEWJkRz7
|
||||
2u7oMGG4z91E0PULA64dOi3l/vOQe5w/Aa+CwVbAWtI05o7kMvQEBMDJn6C7CByo
|
||||
MB5op9wueJMnz7PM7hns+U7Dy6oE4ljuolJUy51bDzFWwoM54cRoQqLFNHd8JVQj
|
||||
WxldCkbfF43iyprlsEcUrTyUjtdA+ZeiG39vg/mtdmgNpGmdupHJZQvSuG8IcVlz
|
||||
O+eMSeQS1QXPD6Ik8UK4SU0h+zOl8xIWtRrsxQuh4fnTN40udm/YUWl/6gOebsBI
|
||||
IrVLlKGqJSfB3tMjpCRqdTzJ0dA9keVpkqm2ugZkxEf1+/efq/rFIQ2pUBLCqNTN
|
||||
qpNqruK8y8FphP30I2uI4Ej2UIB8AQKBwQDd2Yptj2FyDyaXCycsyde0wYkNyzGU
|
||||
dRnzdibfHnMZwjgTjwAwgIUBVIS8H0/z7ZJQKN7osJfddMrtjJtYYUk9g/dCpHXs
|
||||
bNh2QSoWah3FdzNGuWd0iRf9+LFxhjAAMo/FS8zFJAJKrFsBdCGTfFUMdsLC0bjr
|
||||
YjiWBuvV72uKf8XIZX5KIZruKdWBBcWukcb21R1UDyFYyXRBsly5XHaIYKZql3km
|
||||
7pV7MKWO0IYgHbHIqGUqPQlzZ/lkunS1jKECgcEA23wHffD6Ou9/x3okPx2AWpTr
|
||||
gh8rgqbyo6hQkBW5Y90Wz824cqaYebZDaBR/xlVx/YwjKkohv8Bde2lpH/ZxRZ1Z
|
||||
5Sk2s6GJ/vU0L9RsJZgCgj4L6Coal1NMxuZtCXAlnOpiCdxSZgfqbshbTVz30KsG
|
||||
ZJG361Cua1ScdAHxlZBxT52/1Sm0zRC2hnxL7h4qo7Idmtzs40LAJvYOKekR0pPN
|
||||
oWeJfra7vgx/jVNvMFWoOoSLpidVO4g+ot4ery6tAoHAdW3rCic1C2zdnmH28Iw+
|
||||
s50l8Lk3mz+I5wgJd1zkzCO0DxZIoWPGA3g7cmCYr6N3KRsZMs4W9NAXgjpFGDkW
|
||||
zYsG3K21BdpvkdjYcFjnPVjlOXB2RIc0vehf9Jl02wXoeCSxVUDEPcaRvWk9RJYx
|
||||
ZpGOchUU7vNkxHURbIJ4yCzuAi9G8/Jp0dsu+kaV5tufF5SjG5WOrzKjaQsCbdN1
|
||||
oqaWMCHRrTvov/Z2C+xwsptFOdN5CSyZzg6hQiI4GMlBAoHAXyb6KINcOEi0YMp3
|
||||
BFXJ23tMTnEs78tozcKeipigcsbaqORK3omS+NEnj+uzKUzJyl4CsMbKstK2tFYS
|
||||
mSTCHqgE3PBtIpsZtEqhgUraR8IK9GPpzZDTTl9ynZgwFTNlWw3RyuyVXF56J+T8
|
||||
kCGJ3hEHCHqT/ZRQyX85BKIDFhA0z4tYKxWVqIFiYBNq56R0X9tMMmMs36mEnF93
|
||||
7Ht6mowxTZQRa7nU0qOgeKh/P7ki4Zus3y+WJ+T9IqahLtlRAoHBAIhqMrcxSAB8
|
||||
RpB9jukJlAnidw2jCMPgrFE8tP0khhVvGrXMldxAUsMKntDIo8dGCnG1KTcWDI0O
|
||||
jepvSPHSsxVLFugL79h0eVIS5z4huW48i9xgU8VlHdgAcgEPIAOFcOw2BCu/s0Vp
|
||||
O+MM/EyUOdo3NsibB3qc/GJI6iNBYS7AljYEVo6rXo5V/MZvZUF4vClen6Obzsre
|
||||
MTTb+4sJjfqleWuvr1XNMeu2mBfXBQkWGZP1byBK0MvD/aQ2PWq92A==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -0,0 +1,22 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDqzCCAhMCFBHWXeQ6ZIa9QcQbXLFfC6tj+KA+MA0GCSqGSIb3DQEBCwUAMBIx
|
||||
EDAOBgNVBAMMB3VuYm91bmQwHhcNMjAwNzA4MTMzMjI5WhcNNDAwMzI1MTMzMjI5
|
||||
WjASMRAwDgYDVQQDDAd1bmJvdW5kMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
|
||||
igKCAYEAvjSVSN2QMXudpzukdLCqgg/IOhCX8KYkD0FFFfWcQjgKq5wI0x41iG32
|
||||
a6wbGanre4IX7VxaSPu9kkHfnGgynCk5nwDRedE/FLFhAU78PoT0+NqqGRS7XVQ2
|
||||
4vLmIz9Hqc2Ozx1um1BXBTmIT0UfN2e22I0LWQ6a3seZlEDRj45gnk7Zuh9MDgot
|
||||
aBdm+v1JAbupSf6Zis4VEH3JNdvVGE3O1DHEIeuuz/3BDhpf6WBDH+8KWaBe1ca4
|
||||
TZHr9ThL2gEMEfAQl0wXDwRWRoi3NjNMH+mw0L1rjwThI5GXqNIee7o5FzUReSXZ
|
||||
uTdFMyGe3Owcx+XoYnwi6cplSNoGsDBu4B9bKKglR9YleJVw4L4Xi8xPq6O9UPj4
|
||||
+nypHk/DOoC7DIM3ufN0yxPBsFo5TVowxfhdjZXJbbftd2TZv7AH8+XLA5UoZgRz
|
||||
XgzECelXSCTBFlMTnT48LfA9pMLydyjAz2UdPHs5Iv+TK5nnI+aJoeaP7kFZSngx
|
||||
dy1+A/bNAgMBAAEwDQYJKoZIhvcNAQELBQADggGBABunf93MKaCUHiZgnoOTinsW
|
||||
84/EgInrgtKzAyH+BhnKkJOhhR0kkIAx5d9BpDlaSiRTACFon9moWCgDIIsK/Ar7
|
||||
JE0Kln9cV//wiiNoFU0O4mnzyGUIMvlaEX6QHMJJQYvL05+w/3AAcf5XmMJtR5ca
|
||||
fJ8FqvGC34b2WxX9lTQoyT52sRt+1KnQikiMEnEyAdKktMG+MwKsFDdOwDXyZhZg
|
||||
XZhRrfX3/NVJolqB6EahjWIGXDeKuSSKZVtCyib6LskyeMzN5lcRfvubKDdlqFVF
|
||||
qlD7rHBsKhQUWK/IO64mGf7y/de+CgHtED5vDvr/p2uj/9sABATfbrOQR3W/Of25
|
||||
sLBj4OEfrJ7lX8hQgFaxkMI3x6VFT3W8dTCp7xnQgb6bgROWB5fNEZ9jk/gjSRmD
|
||||
yIU+r0UbKe5kBk/CmZVFXL2TyJ92V5NYEQh8V4DGy19qZ6u/XKYyNJL4ocs35GGe
|
||||
CA8SBuyrmdhx38h1RHErR2Skzadi1S7MwGf1y431fQ==
|
||||
-----END CERTIFICATE-----
|
||||
+24
-6
@@ -3,13 +3,31 @@ $ORIGIN example.com.
|
||||
$TTL 3600
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype
|
||||
MATCH opcode qname qtype
|
||||
REPLY QR AA NOERROR
|
||||
ADJUST copy_id copy_query
|
||||
ADJUST copy_id
|
||||
SECTION QUESTION
|
||||
wild IN A
|
||||
www1 IN A
|
||||
SECTION ANSWER
|
||||
wild IN A 10.20.30.40
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
www1 IN A 1.1.1.1
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qname qtype
|
||||
REPLY QR AA NOERROR
|
||||
ADJUST copy_id
|
||||
SECTION QUESTION
|
||||
www2 IN A
|
||||
SECTION ANSWER
|
||||
www2 IN A 2.2.2.2
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qname qtype
|
||||
REPLY QR AA NOERROR
|
||||
ADJUST copy_id
|
||||
SECTION QUESTION
|
||||
www3 IN A
|
||||
SECTION ANSWER
|
||||
www3 IN A 3.3.3.3
|
||||
ENTRY_END
|
||||
|
||||
+4
-2
@@ -468,8 +468,10 @@ bring_up_alternate_configuration ub_discard_wait_limit.conf
|
||||
teststep "Check discard-timeout and wait-limit"
|
||||
echo "> dig www.unresponsive"
|
||||
dig @127.0.0.1 -p $UNBOUND_PORT +retry=2 +timeout=1 www.unresponsive. | tee outfile
|
||||
echo "> check answer"
|
||||
if grep "no servers could be reached" outfile; then
|
||||
# Wait for nonresponse servfail, that causes discards.
|
||||
sleep 2
|
||||
if grep "no servers could be reached" outfile ||
|
||||
grep "Too many queries queued up and waiting" outfile; then
|
||||
echo "OK"
|
||||
else
|
||||
end 1
|
||||
|
||||
Vendored
+274
@@ -0,0 +1,274 @@
|
||||
; Test subnet option
|
||||
|
||||
server:
|
||||
trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
|
||||
val-override-date: "20070916134226"
|
||||
trust-anchor-signaling: no
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
send-client-subnet: 1.2.3.4
|
||||
max-client-subnet-ipv4: 17
|
||||
module-config: "subnetcache validator iterator"
|
||||
verbosity: 3
|
||||
fake-sha1: yes
|
||||
fake-dsa: yes
|
||||
qname-minimisation: no
|
||||
minimal-responses: yes
|
||||
iter-scrub-promiscuous: yes
|
||||
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
CONFIG_END
|
||||
|
||||
SCENARIO_BEGIN Test subnet with scopezero bogus response
|
||||
|
||||
; K.ROOT-SERVERS.NET.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 193.0.14.129
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname ednsdata
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
. IN NS
|
||||
SECTION ANSWER
|
||||
. IN NS K.ROOT-SERVERS.NET.
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
;; we expect to receive empty
|
||||
HEX_EDNSDATA_END
|
||||
K.ROOT-SERVERS.NET. IN A 193.0.14.129
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname ednsdata
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
;; we expect to receive empty
|
||||
HEX_EDNSDATA_END
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; a.gtld-servers.net.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 192.5.6.30
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname ednsdata
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
com. IN NS
|
||||
SECTION ANSWER
|
||||
com. IN NS a.gtld-servers.net.
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
;; we expect to receive empty
|
||||
HEX_EDNSDATA_END
|
||||
a.gtld-servers.net. IN A 192.5.6.30
|
||||
ENTRY_END
|
||||
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname ednsdata
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
;; we expect to receive empty
|
||||
HEX_EDNSDATA_END
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; ns.example.com.
|
||||
RANGE_BEGIN 0 100
|
||||
ADDRESS 1.2.3.4
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname ednsdata
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN NS
|
||||
SECTION ANSWER
|
||||
example.com. IN NS ns.example.com.
|
||||
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
;; we expect to receive empty
|
||||
HEX_EDNSDATA_END
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
|
||||
ENTRY_END
|
||||
|
||||
; no data for ns.example.com. AAAA
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname
|
||||
ADJUST copy_id
|
||||
REPLY QR AA NOERROR
|
||||
SECTION QUESTION
|
||||
ns.example.com. IN AAAA
|
||||
SECTION AUTHORITY
|
||||
example.com. IN SOA a. b. 3 28800 7200 604800 3600
|
||||
example.com. 3600 IN RRSIG SOA 3 2 3600 20070926134150 20070829134150 2854 example.com. ACYHmWSLfBwPXwjI23+PW0db/DuqFwgpJYCbHOPeftbLR9nGy3nyEAE=
|
||||
ns.example.com. 3600 IN NSEC op.example.com. A RRSIG NSEC
|
||||
ns.example.com. 3600 IN RRSIG NSEC 3 3 3600 20070926134150 20070829134150 2854 example.com. AHMBw+lDAm9o2xG7v/8oWkYUc3WefUOuHFMHN9qZEp5/kooJqmlj974=
|
||||
ENTRY_END
|
||||
|
||||
; response to DNSKEY priming query
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname ednsdata
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
example.com. IN DNSKEY
|
||||
SECTION ANSWER
|
||||
example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
|
||||
example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
;; we expect to receive empty
|
||||
HEX_EDNSDATA_END
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
|
||||
ENTRY_END
|
||||
|
||||
; response to query of interest
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname ednsdata
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
; to make it bogus, the address is changed.
|
||||
; and also the RRSIG is expired (dated in 2005).
|
||||
;www.example.com. IN A 10.20.30.40
|
||||
;www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
|
||||
www.example.com. IN A 10.20.30.41
|
||||
www.example.com. 3600 IN RRSIG A 3 3 3600 20050926134150 20050829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
; client is 127.0.0.1
|
||||
00 08 ; OPC
|
||||
00 07 ; option length
|
||||
00 01 ; Family
|
||||
11 00 ; source mask, scopemask
|
||||
7f 00 00 ; address
|
||||
HEX_EDNSDATA_END
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
|
||||
ENTRY_END
|
||||
|
||||
; response to query of interest without subnet
|
||||
ENTRY_BEGIN
|
||||
MATCH opcode qtype qname ednsdata
|
||||
ADJUST copy_id
|
||||
REPLY QR NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
; to make it bogus, the address is changed.
|
||||
; and also the RRSIG is expired (dated in 2005).
|
||||
;www.example.com. IN A 10.20.30.40
|
||||
;www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
|
||||
www.example.com. IN A 10.20.30.41
|
||||
www.example.com. 3600 IN RRSIG A 3 3 3600 20050926134150 20050829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
|
||||
SECTION AUTHORITY
|
||||
example.com. IN NS ns.example.com.
|
||||
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
;; we expect to receive empty
|
||||
HEX_EDNSDATA_END
|
||||
ns.example.com. IN A 1.2.3.4
|
||||
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
|
||||
ENTRY_END
|
||||
RANGE_END
|
||||
|
||||
; query for www.example.com 0.0.0.0/0 with CD flag
|
||||
STEP 10 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD CD DO NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
HEX_EDNSDATA_BEGIN
|
||||
; 0.0.0.0/0 scope /0
|
||||
00 08 ; OPC
|
||||
00 04 ; option length
|
||||
00 01 ; Family
|
||||
00 00 ; source mask, scopemask
|
||||
; address
|
||||
HEX_EDNSDATA_END
|
||||
ENTRY_END
|
||||
|
||||
; recursion happens here.
|
||||
STEP 20 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ednsdata
|
||||
REPLY QR RD CD RA DO NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ANSWER
|
||||
www.example.com. IN A 10.20.30.41
|
||||
www.example.com. 3600 IN RRSIG A 3 3 3600 20050926134150 20050829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
; 0.0.0.0/0 scope /0
|
||||
00 08 ; OPC
|
||||
00 04 ; option length
|
||||
00 01 ; Family
|
||||
00 00 ; source mask, scopemask
|
||||
; address
|
||||
HEX_EDNSDATA_END
|
||||
ENTRY_END
|
||||
|
||||
; query for www.example.com 0.0.0.0/0 without CD flag
|
||||
STEP 30 QUERY
|
||||
ENTRY_BEGIN
|
||||
REPLY RD DO NOERROR
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
HEX_EDNSDATA_BEGIN
|
||||
; 0.0.0.0/0 scope /0
|
||||
00 08 ; OPC
|
||||
00 04 ; option length
|
||||
00 01 ; Family
|
||||
00 00 ; source mask, scopemask
|
||||
; address
|
||||
HEX_EDNSDATA_END
|
||||
ENTRY_END
|
||||
|
||||
STEP 40 CHECK_ANSWER
|
||||
ENTRY_BEGIN
|
||||
MATCH all ednsdata
|
||||
REPLY QR RD RA DO SERVFAIL
|
||||
SECTION QUESTION
|
||||
www.example.com. IN A
|
||||
SECTION ADDITIONAL
|
||||
HEX_EDNSDATA_BEGIN
|
||||
; ; 0.0.0.0/0 scope /0
|
||||
; 00 08 ; OPC
|
||||
; 00 04 ; option length
|
||||
; 00 01 ; Family
|
||||
; 00 00 ; source mask, scopemask
|
||||
; ; address
|
||||
HEX_EDNSDATA_END
|
||||
ENTRY_END
|
||||
|
||||
SCENARIO_END
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user