mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-10-14 12:35:11 +02:00
Compare commits
72
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 |
+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 \
|
||||
|
||||
+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;
|
||||
|
||||
+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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -22165,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
|
||||
@@ -22174,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
|
||||
@@ -23264,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" "
|
||||
@@ -25102,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}
|
||||
|
||||
@@ -1498,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
|
||||
@@ -1505,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
|
||||
@@ -1769,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
|
||||
@@ -2080,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"];
|
||||
|
||||
+294
-11
@@ -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;
|
||||
}
|
||||
|
||||
@@ -737,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 */
|
||||
@@ -829,6 +1108,12 @@ daemon_fork(struct daemon* daemon)
|
||||
* 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 */
|
||||
@@ -918,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)
|
||||
@@ -960,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);
|
||||
@@ -983,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 */
|
||||
+272
-51
@@ -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) {
|
||||
@@ -890,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,
|
||||
@@ -1244,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;
|
||||
@@ -4633,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 */
|
||||
@@ -4936,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
|
||||
@@ -5047,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) {
|
||||
@@ -5257,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);
|
||||
@@ -5295,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);
|
||||
@@ -5528,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,
|
||||
@@ -5535,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;
|
||||
@@ -5812,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. */
|
||||
@@ -6104,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);
|
||||
@@ -6186,6 +6356,15 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
|
||||
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 */
|
||||
|
||||
@@ -6411,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)
|
||||
@@ -7607,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)
|
||||
@@ -7622,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;
|
||||
@@ -7692,6 +7912,7 @@ 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);
|
||||
|
||||
@@ -255,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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -611,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.*/
|
||||
|
||||
+39
-5
@@ -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) {
|
||||
@@ -1675,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.");
|
||||
@@ -2124,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);
|
||||
}
|
||||
}
|
||||
@@ -2249,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 */
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
+127
@@ -1,3 +1,130 @@
|
||||
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.
|
||||
|
||||
|
||||
+21
-4
@@ -662,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.
|
||||
#
|
||||
@@ -722,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
|
||||
@@ -971,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
|
||||
|
||||
@@ -1159,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.
|
||||
|
||||
@@ -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
|
||||
|
||||
+62
-3
@@ -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
|
||||
@@ -2272,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
|
||||
@@ -3010,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
|
||||
@@ -3068,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
|
||||
@@ -4756,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
|
||||
|
||||
+116
-7
@@ -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>*
|
||||
@@ -2012,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
|
||||
@@ -2662,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>`.
|
||||
@@ -2701,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
|
||||
@@ -3387,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
|
||||
@@ -3411,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
|
||||
@@ -4161,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:
|
||||
|
||||
+14
-2
@@ -483,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));
|
||||
|
||||
@@ -515,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;
|
||||
@@ -570,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));
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
+20
-7
@@ -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;
|
||||
@@ -455,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;
|
||||
@@ -502,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;
|
||||
|
||||
@@ -525,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 */
|
||||
@@ -972,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 */
|
||||
|
||||
+29
-3
@@ -308,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 */
|
||||
@@ -1527,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);
|
||||
|
||||
+17
-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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
+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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -1052,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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
+10
-2
@@ -675,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);
|
||||
|
||||
+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),
|
||||
|
||||
+4
-1
@@ -1774,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;
|
||||
}
|
||||
|
||||
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
|
||||
@@ -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-----
|
||||
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
|
||||
+55
-1
@@ -62,6 +62,9 @@
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/parseutil.h"
|
||||
#include "iterator/iterator.h"
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_GLOB_H
|
||||
# include <glob.h>
|
||||
#endif
|
||||
@@ -71,6 +74,9 @@
|
||||
#ifdef HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#ifndef USE_SYSTEM_TLS
|
||||
#define USE_SYSTEM_TLS 0
|
||||
#endif
|
||||
|
||||
/** from cfg username, after daemonize setup performed */
|
||||
uid_t cfg_uid = (uid_t)-1;
|
||||
@@ -129,7 +135,7 @@ config_create(void)
|
||||
cfg->tls_cert_bundle = NULL;
|
||||
cfg->tls_win_cert = 0;
|
||||
cfg->tls_use_sni = 1;
|
||||
cfg->tls_use_system_policy_versions = 0;
|
||||
cfg->tls_use_system_policy_versions = USE_SYSTEM_TLS;
|
||||
cfg->https_port = UNBOUND_DNS_OVER_HTTPS_PORT;
|
||||
if(!(cfg->http_endpoint = strdup("/dns-query"))) goto error_exit;
|
||||
cfg->http_max_streams = 100;
|
||||
@@ -340,6 +346,14 @@ config_create(void)
|
||||
cfg->dnstap_bidirectional = 1;
|
||||
cfg->dnstap_tls = 1;
|
||||
cfg->disable_dnssec_lame_check = 0;
|
||||
#ifdef USE_METRICS
|
||||
cfg->metrics_enable = 0;
|
||||
cfg->metrics_ifs.first = NULL;
|
||||
cfg->metrics_ifs.last = NULL;
|
||||
cfg->metrics_port = UNBOUND_METRICS_PORT;
|
||||
if(!(cfg->metrics_path = strdup("/metrics")))
|
||||
goto error_exit;
|
||||
#endif /* USE_METRICS */
|
||||
cfg->ip_ratelimit_cookie = 0;
|
||||
cfg->ip_ratelimit = 0;
|
||||
cfg->ratelimit = 0;
|
||||
@@ -839,6 +853,12 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
||||
else S_YNO("dnstap-log-forwarder-response-messages:",
|
||||
dnstap_log_forwarder_response_messages)
|
||||
#endif
|
||||
#ifdef USE_METRICS
|
||||
else S_YNO("metrics-enable:", metrics_enable)
|
||||
else S_STRLIST_APPEND("metrics-interface:", metrics_ifs)
|
||||
else S_NUMBER_NONZERO("metrics-port:", metrics_port)
|
||||
else S_STR("metrics-path:", metrics_path)
|
||||
#endif /* USE_METRICS */
|
||||
#ifdef USE_DNSCRYPT
|
||||
else S_YNO("dnscrypt-enable:", dnscrypt)
|
||||
else S_NUMBER_NONZERO("dnscrypt-port:", dnscrypt_port)
|
||||
@@ -1332,6 +1352,12 @@ config_get_option(struct config_file* cfg, const char* opt,
|
||||
else O_YNO(opt, "dnstap-log-forwarder-response-messages",
|
||||
dnstap_log_forwarder_response_messages)
|
||||
#endif
|
||||
#ifdef USE_METRICS
|
||||
else O_YNO(opt, "metrics-enable", metrics_enable)
|
||||
else O_LST(opt, "metrics-interface", metrics_ifs.first)
|
||||
else O_DEC(opt, "metrics-port", metrics_port)
|
||||
else O_STR(opt, "metrics-path", metrics_path)
|
||||
#endif /* USE_METRICS */
|
||||
#ifdef USE_DNSCRYPT
|
||||
else O_YNO(opt, "dnscrypt-enable", dnscrypt)
|
||||
else O_DEC(opt, "dnscrypt-port", dnscrypt_port)
|
||||
@@ -1829,6 +1855,10 @@ config_delete(struct config_file* cfg)
|
||||
free(cfg->dnstap_tls_client_cert_file);
|
||||
free(cfg->dnstap_identity);
|
||||
free(cfg->dnstap_version);
|
||||
#ifdef USE_METRICS
|
||||
config_delstrlist(cfg->metrics_ifs.first);
|
||||
free(cfg->metrics_path);
|
||||
#endif /* USE_METRICS */
|
||||
config_deldblstrlist(cfg->ratelimit_for_domain);
|
||||
config_deldblstrlist(cfg->ratelimit_below_domain);
|
||||
config_delstrlist(cfg->python_script);
|
||||
@@ -2981,3 +3011,27 @@ cfg_has_quic(struct config_file* cfg)
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
file_get_mtime(const char* file, time_t* mtime, long* ns, int* nonexist)
|
||||
{
|
||||
struct stat s;
|
||||
if(stat(file, &s) != 0) {
|
||||
*mtime = 0;
|
||||
*ns = 0;
|
||||
if(nonexist)
|
||||
*nonexist = (errno == ENOENT);
|
||||
return 0;
|
||||
}
|
||||
if(nonexist)
|
||||
*nonexist = 0;
|
||||
*mtime = s.st_mtime;
|
||||
#ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
|
||||
*ns = s.st_mtimensec;
|
||||
#elif defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
|
||||
*ns = s.st_mtim.tv_nsec;
|
||||
#else
|
||||
*ns = 0;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -625,6 +625,17 @@ struct config_file {
|
||||
/** true to disable DNSSEC lameness check in iterator */
|
||||
int disable_dnssec_lame_check;
|
||||
|
||||
#ifdef USE_METRICS
|
||||
/** metrics section. enable toggle. */
|
||||
int metrics_enable;
|
||||
/** the interfaces the metrics endpoint should listen on */
|
||||
struct config_strlist_head metrics_ifs;
|
||||
/** port number for the metrics endpoint */
|
||||
int metrics_port;
|
||||
/** HTTP path for the metrics endpoint */
|
||||
char* metrics_path;
|
||||
#endif /* USE_METRICS */
|
||||
|
||||
/** ratelimit for ip addresses. 0 is off, otherwise qps (unless overridden) */
|
||||
int ip_ratelimit;
|
||||
/** ratelimit for ip addresses with a valid DNS Cookie. 0 is off,
|
||||
@@ -1493,4 +1504,7 @@ size_t getmem_str(char* str);
|
||||
*/
|
||||
int cfg_ports_list_contains(char* ports, int p);
|
||||
|
||||
/** get the file mtime stat (or error, with errno and nonexist) */
|
||||
int file_get_mtime(const char* file, time_t* mtime, long* ns, int* nonexist);
|
||||
|
||||
#endif /* UTIL_CONFIG_FILE_H */
|
||||
|
||||
@@ -491,6 +491,10 @@ interface-tag-action{COLON} { YDVAR(3, VAR_INTERFACE_TAG_ACTION) }
|
||||
interface-tag-data{COLON} { YDVAR(3, VAR_INTERFACE_TAG_DATA) }
|
||||
interface-view{COLON} { YDVAR(2, VAR_INTERFACE_VIEW) }
|
||||
local-zone-override{COLON} { YDVAR(3, VAR_LOCAL_ZONE_OVERRIDE) }
|
||||
metrics-enable{COLON} { YDVAR(1, VAR_METRICS_ENABLE) }
|
||||
metrics-interface{COLON} { YDVAR(1, VAR_METRICS_INTERFACE) }
|
||||
metrics-port{COLON} { YDVAR(1, VAR_METRICS_PORT) }
|
||||
metrics-path{COLON} { YDVAR(1, VAR_METRICS_PATH) }
|
||||
dnstap{COLON} { YDVAR(0, VAR_DNSTAP) }
|
||||
dnstap-enable{COLON} { YDVAR(1, VAR_DNSTAP_ENABLE) }
|
||||
dnstap-bidirectional{COLON} { YDVAR(1, VAR_DNSTAP_BIDIRECTIONAL) }
|
||||
|
||||
+52
-2
@@ -126,6 +126,8 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_INFRA_CACHE_MIN_RTT VAR_INFRA_CACHE_MAX_RTT VAR_INFRA_KEEP_PROBING
|
||||
%token VAR_DNS64_PREFIX VAR_DNS64_SYNTHALL VAR_DNS64_IGNORE_AAAA
|
||||
%token VAR_NAT64_PREFIX
|
||||
%token VAR_METRICS_ENABLE VAR_METRICS_INTERFACE VAR_METRICS_PORT
|
||||
%token VAR_METRICS_PATH
|
||||
%token VAR_DNSTAP VAR_DNSTAP_ENABLE VAR_DNSTAP_SOCKET_PATH VAR_DNSTAP_IP
|
||||
%token VAR_DNSTAP_TLS VAR_DNSTAP_TLS_SERVER_NAME VAR_DNSTAP_TLS_CERT_BUNDLE
|
||||
%token VAR_DNSTAP_TLS_CLIENT_KEY_FILE VAR_DNSTAP_TLS_CLIENT_CERT_FILE
|
||||
@@ -359,7 +361,9 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||||
server_harden_unknown_additional | server_disable_edns_do |
|
||||
server_log_destaddr | server_cookie_secret_file |
|
||||
server_iter_scrub_ns | server_iter_scrub_cname | server_max_global_quota |
|
||||
server_harden_unverified_glue | server_log_time_iso | server_iter_scrub_promiscuous
|
||||
server_harden_unverified_glue | server_log_time_iso | server_iter_scrub_promiscuous |
|
||||
server_metrics_enable | server_metrics_interface |
|
||||
server_metrics_port | server_metrics_path
|
||||
;
|
||||
stub_clause: stubstart contents_stub
|
||||
{
|
||||
@@ -2399,7 +2403,7 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
|
||||
yyerror("local-zone type: expected static, deny, "
|
||||
"refuse, redirect, transparent, "
|
||||
"typetransparent, inform, inform_deny, "
|
||||
"inform_redirect, always_transparent, block_a,"
|
||||
"inform_redirect, always_transparent, block_a, "
|
||||
"always_refuse, always_nxdomain, "
|
||||
"always_nodata, always_deny, always_null, "
|
||||
"noview, nodefault or ipset");
|
||||
@@ -2748,6 +2752,52 @@ server_response_ip_tag: VAR_RESPONSE_IP_TAG STRING_ARG STRING_ARG
|
||||
}
|
||||
}
|
||||
;
|
||||
server_metrics_enable: VAR_METRICS_ENABLE STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_metrics_enable:%s)\n", $2));
|
||||
#ifdef USE_METRICS
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->metrics_enable = (strcmp($2, "yes")==0);
|
||||
#else
|
||||
if(strcmp($2, "yes")==0)
|
||||
log_warn("%s:%d the server is not compiled with "
|
||||
"prometheus metrics.", cfg_parser->filename,
|
||||
cfg_parser->line);
|
||||
#endif
|
||||
free($2);
|
||||
};
|
||||
server_metrics_interface: VAR_METRICS_INTERFACE STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_metrics_interface:%s)\n", $2));
|
||||
#ifdef USE_METRICS
|
||||
if(!cfg_strlist_append(&cfg_parser->cfg->metrics_ifs, $2))
|
||||
yyerror("out of memory");
|
||||
#else
|
||||
free($2);
|
||||
#endif
|
||||
};
|
||||
server_metrics_port: VAR_METRICS_PORT STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_metrics_port:%s)\n", $2));
|
||||
#ifdef USE_METRICS
|
||||
if(atoi($2) == 0 && strcmp($2,"0")!=0)
|
||||
yyerror("port number expected");
|
||||
else
|
||||
cfg_parser->cfg->metrics_port = atoi($2);
|
||||
#endif
|
||||
free($2);
|
||||
};
|
||||
server_metrics_path: VAR_METRICS_PATH STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_metrics_path:%s)\n", $2));
|
||||
#ifdef USE_METRICS
|
||||
free(cfg_parser->cfg->metrics_path);
|
||||
cfg_parser->cfg->metrics_path = $2;
|
||||
#else
|
||||
free($2);
|
||||
#endif
|
||||
};
|
||||
server_ip_ratelimit: VAR_IP_RATELIMIT STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_ip_ratelimit:%s)\n", $2));
|
||||
|
||||
@@ -1366,7 +1366,9 @@ msgparse_rrset_remove_rr(const char* str, sldns_buffer* pkt, struct rrset_parse*
|
||||
time_t debug_expired_reply_ttl_calc(time_t ttl, time_t ttl_add) {
|
||||
/* Check that we are serving expired when this is called */
|
||||
/* ttl (absolute) should be later than ttl_add */
|
||||
log_assert(SERVE_EXPIRED && ttl_add <= ttl);
|
||||
/* It is also called during the grace period for type DNAME,
|
||||
* and then the 'SERVE_EXPIRED' boolean may not be on. */
|
||||
log_assert(ttl_add <= ttl);
|
||||
return (SERVE_EXPIRED_REPLY_TTL < (ttl) - (ttl_add) ?
|
||||
SERVE_EXPIRED_REPLY_TTL : (ttl) - (ttl_add));
|
||||
}
|
||||
|
||||
@@ -3978,6 +3978,7 @@
|
||||
4791,
|
||||
4792,
|
||||
4793,
|
||||
4794,
|
||||
4800,
|
||||
4801,
|
||||
4802,
|
||||
@@ -4947,6 +4948,7 @@
|
||||
9162,
|
||||
9163,
|
||||
9164,
|
||||
9183,
|
||||
9191,
|
||||
9200,
|
||||
9201,
|
||||
@@ -5431,6 +5433,8 @@
|
||||
34962,
|
||||
34963,
|
||||
34964,
|
||||
34965,
|
||||
34966,
|
||||
34980,
|
||||
35001,
|
||||
35004,
|
||||
|
||||
+9
-5
@@ -1799,7 +1799,7 @@ void ub_openssl_lock_delete(void)
|
||||
#endif /* OPENSSL_THREADS */
|
||||
}
|
||||
|
||||
int listen_sslctx_setup_ticket_keys(struct config_strlist* tls_session_ticket_keys) {
|
||||
int listen_sslctx_setup_ticket_keys(struct config_strlist* tls_session_ticket_keys, char* chroot) {
|
||||
#ifdef HAVE_SSL
|
||||
size_t s = 1;
|
||||
struct config_strlist* p;
|
||||
@@ -1817,14 +1817,18 @@ int listen_sslctx_setup_ticket_keys(struct config_strlist* tls_session_ticket_ke
|
||||
size_t n;
|
||||
unsigned char *data;
|
||||
FILE *f;
|
||||
char* fstr;
|
||||
|
||||
data = (unsigned char *)malloc(80);
|
||||
if(!data)
|
||||
return 0;
|
||||
|
||||
f = fopen(p->str, "rb");
|
||||
fstr = p->str;
|
||||
if(chroot && strncmp(fstr, chroot, strlen(chroot)) == 0)
|
||||
fstr += strlen(chroot);
|
||||
f = fopen(fstr, "rb");
|
||||
if(!f) {
|
||||
log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno));
|
||||
log_err("could not read tls-session-ticket-key %s: %s", fstr, strerror(errno));
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
@@ -1832,11 +1836,11 @@ int listen_sslctx_setup_ticket_keys(struct config_strlist* tls_session_ticket_ke
|
||||
fclose(f);
|
||||
|
||||
if(n != 80) {
|
||||
log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", p->str, (int)n);
|
||||
log_err("tls-session-ticket-key %s is %d bytes, must be 80 bytes", fstr, (int)n);
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
verbose(VERB_OPS, "read tls-session-ticket-key: %s", p->str);
|
||||
verbose(VERB_OPS, "read tls-session-ticket-key: %s", fstr);
|
||||
|
||||
keys->key_name = data;
|
||||
keys->aes_key = data + 16;
|
||||
|
||||
+3
-1
@@ -567,9 +567,11 @@ void ub_openssl_lock_delete(void);
|
||||
/**
|
||||
* setup TLS session ticket
|
||||
* @param tls_session_ticket_keys: TLS ticket secret filenames
|
||||
* @param chroot: if not NULL, the chroot that is in use.
|
||||
* @return false on failure (alloc failure).
|
||||
*/
|
||||
int listen_sslctx_setup_ticket_keys(struct config_strlist* tls_session_ticket_keys);
|
||||
int listen_sslctx_setup_ticket_keys(
|
||||
struct config_strlist* tls_session_ticket_keys, char* chroot);
|
||||
|
||||
/** Free memory used for TLS session ticket keys */
|
||||
void listen_sslctx_delete_ticket_keys(void);
|
||||
|
||||
+19
-4
@@ -4870,8 +4870,17 @@ http_process_initial_header(struct comm_point* c)
|
||||
return 0;
|
||||
}
|
||||
} else if(strncasecmp(line, "Content-Length: ", 16) == 0) {
|
||||
if(!c->http_is_chunked)
|
||||
c->tcp_byte_count = (size_t)atoi(line+16);
|
||||
if(!c->http_is_chunked) {
|
||||
char* end = NULL;
|
||||
long long cl;
|
||||
errno = 0;
|
||||
cl = strtoll(line+16, &end, 10);
|
||||
if(end == line+16 || errno != 0 || cl < 0) {
|
||||
verbose(VERB_ALGO, "http invalid Content-Length: " ARG_LL "d", cl);
|
||||
return 0; /* reject */
|
||||
}
|
||||
c->tcp_byte_count = (size_t)cl;
|
||||
}
|
||||
} else if(strncasecmp(line, "Transfer-Encoding: chunked", 19+7) == 0) {
|
||||
c->tcp_byte_count = 0;
|
||||
c->http_is_chunked = 1;
|
||||
@@ -4927,9 +4936,15 @@ http_process_chunk_header(struct comm_point* c)
|
||||
if(c->http_in_chunk_headers == 1) {
|
||||
/* read chunked start line */
|
||||
char* end = NULL;
|
||||
c->tcp_byte_count = (size_t)strtol(line, &end, 16);
|
||||
if(end == line)
|
||||
long chunk_sz;
|
||||
errno = 0;
|
||||
chunk_sz = strtol(line, &end, 16);
|
||||
if(end == line || errno != 0 || chunk_sz < 0) {
|
||||
verbose(VERB_ALGO, "http invalid chunk size: %ld",
|
||||
chunk_sz);
|
||||
return 0;
|
||||
}
|
||||
c->tcp_byte_count = (size_t)chunk_sz;
|
||||
c->http_in_chunk_headers = 0;
|
||||
/* remove header text from front of buffer */
|
||||
http_moveover_buffer(c->buffer);
|
||||
|
||||
+122
-62
@@ -185,6 +185,16 @@ int shm_main_init(struct daemon* daemon)
|
||||
shm_stat = daemon->shm_info->ptr_ctl;
|
||||
shm_stat->num_threads = daemon->num;
|
||||
|
||||
lock_basic_init(&daemon->shm_info->lock);
|
||||
daemon->shm_info->volley_in_progress = 0;
|
||||
daemon->shm_info->thread_volley = (int*)calloc(
|
||||
daemon->num, sizeof(int));
|
||||
if(!daemon->shm_info->thread_volley) {
|
||||
log_err("shm fail: malloc failure");
|
||||
free(daemon->shm_info);
|
||||
daemon->shm_info = NULL;
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
(void)daemon;
|
||||
#endif /* HAVE_SHMGET */
|
||||
@@ -214,6 +224,9 @@ void shm_main_shutdown(struct daemon* daemon)
|
||||
if (daemon->shm_info->ptr_arr)
|
||||
shmdt(daemon->shm_info->ptr_arr);
|
||||
|
||||
lock_basic_destroy(&daemon->shm_info->lock);
|
||||
free(daemon->shm_info->thread_volley);
|
||||
|
||||
free(daemon->shm_info);
|
||||
daemon->shm_info = NULL;
|
||||
#else
|
||||
@@ -221,13 +234,90 @@ void shm_main_shutdown(struct daemon* daemon)
|
||||
#endif /* HAVE_SHMGET */
|
||||
}
|
||||
|
||||
/** Copy general info into the stat structure. */
|
||||
static void
|
||||
shm_general_info(struct worker* worker)
|
||||
{
|
||||
struct ub_shm_stat_info *shm_stat;
|
||||
/* Point to data into SHM */
|
||||
#ifndef S_SPLINT_S
|
||||
shm_stat = worker->daemon->shm_info->ptr_ctl;
|
||||
shm_stat->time.now_sec = (long long)worker->env.now_tv->tv_sec;
|
||||
shm_stat->time.now_usec = (long long)worker->env.now_tv->tv_usec;
|
||||
#endif
|
||||
|
||||
stat_timeval_subtract(&shm_stat->time.up_sec, &shm_stat->time.up_usec, worker->env.now_tv, &worker->daemon->time_boot);
|
||||
stat_timeval_subtract(&shm_stat->time.elapsed_sec, &shm_stat->time.elapsed_usec, worker->env.now_tv, &worker->daemon->time_last_stat);
|
||||
|
||||
/* subnet mem value is available in shm, also when not enabled,
|
||||
* to make the struct easier to memmap by other applications,
|
||||
* independent of the configuration of unbound */
|
||||
/* ipsecmod mem value is available in shm, also when not enabled,
|
||||
* to make the struct easier to memmap by other applications,
|
||||
* independent of the configuration of unbound */
|
||||
stats_get_mem_info(worker, &shm_stat->mem);
|
||||
}
|
||||
|
||||
/** See if the thread is first. Caller has lock. */
|
||||
static int
|
||||
shm_thread_is_first(struct shm_main_info* shm_info, int thread_num,
|
||||
struct daemon* daemon)
|
||||
{
|
||||
/* The usual method, all threads executed last time, and there
|
||||
* is no statistics callback in progress. */
|
||||
if(!shm_info->volley_in_progress)
|
||||
return 1;
|
||||
/* See if we are already active, if so, the timer seems to have fired
|
||||
* twice for this thread which means other thread(s) have not gone
|
||||
* through their stats callbacks yet.
|
||||
* (There should have been a last thread to reset
|
||||
* shm_info->volley_in_progress and shm_info->thread_volley)
|
||||
* The other thread(s) are not yet active during this statistics round,
|
||||
* so this thread must be the first of this new round disregarding the
|
||||
* other busy thread(s).
|
||||
* When the other thread(s) have time again, they will process their
|
||||
* stats callback and hopefully properly end a stats round where all
|
||||
* threads got to calculate their statistics. */
|
||||
if(shm_info->thread_volley[thread_num] != 0) {
|
||||
/* The new round starts and zeroes the total. The previous
|
||||
* partial total is discarded. That means while other thread(s)
|
||||
* are performing a long task, eg. loading a large zone
|
||||
* perhaps, the total is not updated and stays the same in the
|
||||
* shared memory area. Once that other thread(s) perform the
|
||||
* statistic callback again, the total is updated again.
|
||||
*
|
||||
* The threads busy with long tasks have 0 in the array.
|
||||
* The array is inited for a new round. */
|
||||
memset(shm_info->thread_volley, 0,
|
||||
((size_t)daemon->num) * sizeof(int));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** See if the thread is last. Caller has lock. */
|
||||
static int
|
||||
shm_thread_is_last(struct daemon* daemon)
|
||||
{
|
||||
/* Being last means that all threads have been active for this stats
|
||||
* round and this thread is the last one; also active. All the
|
||||
* thread_volley values should be true then. */
|
||||
int i;
|
||||
for(i=0; i<daemon->num; i++) {
|
||||
if(!daemon->shm_info->thread_volley[i])
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void shm_main_run(struct worker *worker)
|
||||
{
|
||||
#ifdef HAVE_SHMGET
|
||||
struct ub_shm_stat_info *shm_stat;
|
||||
struct ub_stats_info *stat_total;
|
||||
struct ub_stats_info *stat_info;
|
||||
int offset;
|
||||
double total_mesh_time_median;
|
||||
struct shm_main_info* shm_info = worker->daemon->shm_info;
|
||||
|
||||
#ifndef S_SPLINT_S
|
||||
verbose(VERB_DETAIL, "SHM run - worker [%d] - daemon [%p] - timenow(%u) - timeboot(%u)",
|
||||
@@ -235,73 +325,43 @@ void shm_main_run(struct worker *worker)
|
||||
#endif
|
||||
|
||||
offset = worker->thread_num + 1;
|
||||
stat_total = worker->daemon->shm_info->ptr_arr;
|
||||
stat_info = worker->daemon->shm_info->ptr_arr + offset;
|
||||
stat_total = shm_info->ptr_arr;
|
||||
stat_info = shm_info->ptr_arr + offset;
|
||||
|
||||
/* Copy data to the current position */
|
||||
server_stats_compile(worker, stat_info, 0);
|
||||
|
||||
/* First thread, zero fill total, and copy general info */
|
||||
if (worker->thread_num == 0) {
|
||||
|
||||
/* Copy data to the current position */
|
||||
memset(stat_total, 0, sizeof(struct ub_stats_info));
|
||||
|
||||
/* Point to data into SHM */
|
||||
#ifndef S_SPLINT_S
|
||||
shm_stat = worker->daemon->shm_info->ptr_ctl;
|
||||
shm_stat->time.now_sec = (long long)worker->env.now_tv->tv_sec;
|
||||
shm_stat->time.now_usec = (long long)worker->env.now_tv->tv_usec;
|
||||
#endif
|
||||
|
||||
stat_timeval_subtract(&shm_stat->time.up_sec, &shm_stat->time.up_usec, worker->env.now_tv, &worker->daemon->time_boot);
|
||||
stat_timeval_subtract(&shm_stat->time.elapsed_sec, &shm_stat->time.elapsed_usec, worker->env.now_tv, &worker->daemon->time_last_stat);
|
||||
|
||||
shm_stat->mem.msg = (long long)slabhash_get_mem(worker->env.msg_cache);
|
||||
shm_stat->mem.rrset = (long long)slabhash_get_mem(&worker->env.rrset_cache->table);
|
||||
shm_stat->mem.dnscrypt_shared_secret = 0;
|
||||
#ifdef USE_DNSCRYPT
|
||||
if(worker->daemon->dnscenv) {
|
||||
shm_stat->mem.dnscrypt_shared_secret = (long long)slabhash_get_mem(
|
||||
worker->daemon->dnscenv->shared_secrets_cache);
|
||||
shm_stat->mem.dnscrypt_nonce = (long long)slabhash_get_mem(
|
||||
worker->daemon->dnscenv->nonces_cache);
|
||||
}
|
||||
#endif
|
||||
shm_stat->mem.val = (long long)mod_get_mem(&worker->env,
|
||||
"validator");
|
||||
shm_stat->mem.iter = (long long)mod_get_mem(&worker->env,
|
||||
"iterator");
|
||||
shm_stat->mem.respip = (long long)mod_get_mem(&worker->env,
|
||||
"respip");
|
||||
|
||||
/* subnet mem value is available in shm, also when not enabled,
|
||||
* to make the struct easier to memmap by other applications,
|
||||
* independent of the configuration of unbound */
|
||||
shm_stat->mem.subnet = 0;
|
||||
#ifdef CLIENT_SUBNET
|
||||
shm_stat->mem.subnet = (long long)mod_get_mem(&worker->env,
|
||||
"subnetcache");
|
||||
#endif
|
||||
/* ipsecmod mem value is available in shm, also when not enabled,
|
||||
* to make the struct easier to memmap by other applications,
|
||||
* independent of the configuration of unbound */
|
||||
shm_stat->mem.ipsecmod = 0;
|
||||
#ifdef USE_IPSECMOD
|
||||
shm_stat->mem.ipsecmod = (long long)mod_get_mem(&worker->env,
|
||||
"ipsecmod");
|
||||
#endif
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
shm_stat->mem.dynlib = (long long)mod_get_mem(&worker->env,
|
||||
"dynlib");
|
||||
#endif
|
||||
/* Lock the lock and see if this thread is first or last of the
|
||||
* stat threads. It can then zero value or sum up values. */
|
||||
lock_basic_lock(&shm_info->lock);
|
||||
if(shm_thread_is_first(shm_info, worker->thread_num, worker->daemon)) {
|
||||
/* First thread, zero fill total. */
|
||||
memset(&shm_info->total_in_progress, 0,
|
||||
sizeof(struct ub_stats_info));
|
||||
shm_info->volley_in_progress = 1;
|
||||
}
|
||||
shm_info->thread_volley[worker->thread_num] = 1;
|
||||
if(worker->thread_num == 0) {
|
||||
/* Thread 0, copy general info. */
|
||||
shm_general_info(worker);
|
||||
}
|
||||
/* Add thread data to the total */
|
||||
total_mesh_time_median = shm_info->total_in_progress.mesh_time_median;
|
||||
server_stats_add(&shm_info->total_in_progress, stat_info);
|
||||
/* By adding the value/num per stat thread, for the median,
|
||||
* it is going to add up to the sum/num. */
|
||||
shm_info->total_in_progress.mesh_time_median = total_mesh_time_median +
|
||||
(stat_info->mesh_time_median/(double)worker->daemon->num);
|
||||
|
||||
server_stats_add(stat_total, stat_info);
|
||||
|
||||
/* print the thread statistics */
|
||||
stat_total->mesh_time_median /= (double)worker->daemon->num;
|
||||
|
||||
if(shm_thread_is_last(worker->daemon)) {
|
||||
/* Copy over the total */
|
||||
memcpy(stat_total, &shm_info->total_in_progress,
|
||||
sizeof(struct ub_stats_info));
|
||||
shm_info->volley_in_progress = 0;
|
||||
memset(shm_info->thread_volley, 0,
|
||||
((size_t)worker->daemon->num) * sizeof(int));
|
||||
}
|
||||
lock_basic_unlock(&shm_info->lock);
|
||||
#else
|
||||
(void)worker;
|
||||
#endif /* HAVE_SHMGET */
|
||||
|
||||
@@ -47,6 +47,8 @@ struct worker;
|
||||
/* get struct ub_shm_stat_info */
|
||||
#include "libunbound/unbound.h"
|
||||
|
||||
#include "util/locks.h"
|
||||
|
||||
/**
|
||||
* The SHM info.
|
||||
*/
|
||||
@@ -59,6 +61,19 @@ struct shm_main_info {
|
||||
int key;
|
||||
int id_ctl;
|
||||
int id_arr;
|
||||
|
||||
/** This mutex is on the volley information. */
|
||||
lock_basic_type lock;
|
||||
/** If there is a volley, a number of stat timer callbacks by the
|
||||
* threads, in progress. If not, there is no volley in progress and the
|
||||
* previous stat run has terminated succesfully for all threads.
|
||||
* Usually activated by the first thread and deactivated by the last
|
||||
* thread that starts its stat callback. */
|
||||
int volley_in_progress;
|
||||
/** Per thread, if they have put in stats. 0 if not. */
|
||||
int* thread_volley;
|
||||
/** The total stats of the thread stat timers, it is in progress */
|
||||
struct ub_stats_info total_in_progress;
|
||||
};
|
||||
|
||||
int shm_main_init(struct daemon* daemon);
|
||||
|
||||
@@ -1289,6 +1289,8 @@ neg_nsec3_proof_ds(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len,
|
||||
if(!(msg = dns_msg_create(qname, qname_len,
|
||||
LDNS_RR_TYPE_DS, zone->dclass, region, 1)))
|
||||
return NULL;
|
||||
/* The cache response means recursion is available. */
|
||||
msg->rep->flags |= BIT_RA;
|
||||
/* TTL reduced in grab_nsec */
|
||||
if(!dns_msg_authadd(msg, region, ce_rrset, 0))
|
||||
return NULL;
|
||||
@@ -1323,6 +1325,8 @@ neg_nsec3_proof_ds(struct val_neg_zone* zone, uint8_t* qname, size_t qname_len,
|
||||
if(!(msg = dns_msg_create(qname, qname_len,
|
||||
LDNS_RR_TYPE_DS, zone->dclass, region, 3)))
|
||||
return NULL;
|
||||
/* The cache response means recursion is available. */
|
||||
msg->rep->flags |= BIT_RA;
|
||||
/* now=0 because TTL was reduced in grab_nsec */
|
||||
if(!dns_msg_authadd(msg, region, ce_rrset, 0))
|
||||
return NULL;
|
||||
@@ -1413,6 +1417,8 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo,
|
||||
if(!(msg = dns_msg_create(qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qtype, qinfo->qclass, region, 2)))
|
||||
return NULL;
|
||||
/* The cache response means recursion is available. */
|
||||
msg->rep->flags |= BIT_RA;
|
||||
if(!dns_msg_authadd(msg, region, nsec, 0))
|
||||
return NULL;
|
||||
if(addsoa && !add_soa(rrset_cache, now, region, msg, NULL))
|
||||
@@ -1426,6 +1432,8 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo,
|
||||
if(!(msg = dns_msg_create(qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qtype, qinfo->qclass, region, 3)))
|
||||
return NULL;
|
||||
/* The cache response means recursion is available. */
|
||||
msg->rep->flags |= BIT_RA;
|
||||
if(!(ce = nsec_closest_encloser(qinfo->qname, nsec)))
|
||||
return NULL;
|
||||
dname_count_size_labels(ce, &ce_len);
|
||||
|
||||
@@ -2699,7 +2699,9 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
if(!needs_validation(qstate, qstate->return_rcode,
|
||||
qstate->return_msg)) {
|
||||
/* no need to validate this */
|
||||
if(qstate->return_msg)
|
||||
/* For valrec responses, leave at sec_status_unchecked,
|
||||
* no security status has been requested for it. */
|
||||
if(qstate->return_msg && !qstate->is_valrec)
|
||||
qstate->return_msg->rep->security =
|
||||
sec_status_indeterminate;
|
||||
qstate->ext_state[id] = module_finished;
|
||||
|
||||
Reference in New Issue
Block a user