MFV r361322:
Update unbound 1.9.6 --> 1.10.1. Bug Fixes: - CVE-2020-12662 Unbound can be tricked into amplifying an incoming query into a large number of queries directed to a target. - CVE-2020-12663 Malformed answers from upstream name servers can be used to make Unbound unresponsive. Reported by: emaste MFC after: 3 days Relnotes: yes Security: CVE-2020-12662, CVE-2020-12663
This commit is contained in:
commit
51112a15b9
12
contrib/unbound/.github/FUNDING.yml
vendored
Normal file
12
contrib/unbound/.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: ['https://nlnetlabs.nl/funding/']
|
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@ Unbound is a validating, recursive, caching DNS resolver. It is designed to be
|
||||
fast and lean and incorporates modern features based on open standards. If you
|
||||
have any feedback, we would love to hear from you. Don’t hesitate to
|
||||
[create an issue on Github](https://github.com/NLnetLabs/unbound/issues/new)
|
||||
or post a message on the [Unbound mailing list](https://nlnetlabs.nl/mailman/listinfo/unbound-users).
|
||||
or post a message on the [Unbound mailing list](https://lists.nlnetlabs.nl/mailman/listinfo/unbound-users).
|
||||
You can lean more about Unbound by reading our
|
||||
[documentation](https://nlnetlabs.nl/documentation/unbound/).
|
||||
|
||||
|
115
contrib/unbound/aclocal.m4
vendored
115
contrib/unbound/aclocal.m4
vendored
@ -1,6 +1,6 @@
|
||||
# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
|
||||
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@ -736,6 +736,7 @@ _LT_CONFIG_SAVE_COMMANDS([
|
||||
cat <<_LT_EOF >> "$cfgfile"
|
||||
#! $SHELL
|
||||
# Generated automatically by $as_me ($PACKAGE) $VERSION
|
||||
# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
|
||||
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
|
||||
|
||||
# Provide generalized library-building support services.
|
||||
@ -2872,6 +2873,9 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
|
||||
# before this can be enabled.
|
||||
hardcode_into_libs=yes
|
||||
|
||||
# Add ABI-specific directories to the system library path.
|
||||
sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
|
||||
|
||||
# Ideally, we could use ldconfig to report *all* directores which are
|
||||
# searched for libraries, however this is still not possible. Aside from not
|
||||
# being certain /sbin/ldconfig is available, command
|
||||
@ -2880,7 +2884,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
|
||||
# appending ld.so.conf contents (and includes) to the search path.
|
||||
if test -f /etc/ld.so.conf; then
|
||||
lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
|
||||
sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
|
||||
sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
|
||||
fi
|
||||
|
||||
# We used to test for /lib/ld.so.1 and disable shared libraries on
|
||||
@ -2892,18 +2896,6 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
|
||||
dynamic_linker='GNU/Linux ld.so'
|
||||
;;
|
||||
|
||||
netbsdelf*-gnu)
|
||||
version_type=linux
|
||||
need_lib_prefix=no
|
||||
need_version=no
|
||||
library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
|
||||
soname_spec='${libname}${release}${shared_ext}$major'
|
||||
shlibpath_var=LD_LIBRARY_PATH
|
||||
shlibpath_overrides_runpath=no
|
||||
hardcode_into_libs=yes
|
||||
dynamic_linker='NetBSD ld.elf_so'
|
||||
;;
|
||||
|
||||
netbsd*)
|
||||
version_type=sunos
|
||||
need_lib_prefix=no
|
||||
@ -3563,7 +3555,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
|
||||
lt_cv_deplibs_check_method=pass_all
|
||||
;;
|
||||
|
||||
netbsd* | netbsdelf*-gnu)
|
||||
netbsd*)
|
||||
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
|
||||
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
|
||||
else
|
||||
@ -4441,7 +4433,7 @@ m4_if([$1], [CXX], [
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
netbsd* | netbsdelf*-gnu)
|
||||
netbsd*)
|
||||
;;
|
||||
*qnx* | *nto*)
|
||||
# QNX uses GNU C++, but need to define -shared option too, otherwise
|
||||
@ -4953,9 +4945,6 @@ m4_if([$1], [CXX], [
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
linux* | k*bsd*-gnu | gnu*)
|
||||
_LT_TAGVAR(link_all_deplibs, $1)=no
|
||||
;;
|
||||
*)
|
||||
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
|
||||
;;
|
||||
@ -5018,9 +5007,6 @@ dnl Note also adjust exclude_expsyms for C++ above.
|
||||
openbsd* | bitrig*)
|
||||
with_gnu_ld=no
|
||||
;;
|
||||
linux* | k*bsd*-gnu | gnu*)
|
||||
_LT_TAGVAR(link_all_deplibs, $1)=no
|
||||
;;
|
||||
esac
|
||||
|
||||
_LT_TAGVAR(ld_shlibs, $1)=yes
|
||||
@ -5275,7 +5261,7 @@ _LT_EOF
|
||||
fi
|
||||
;;
|
||||
|
||||
netbsd* | netbsdelf*-gnu)
|
||||
netbsd*)
|
||||
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
|
||||
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
|
||||
wlarc=
|
||||
@ -5796,7 +5782,6 @@ _LT_EOF
|
||||
if test yes = "$lt_cv_irix_exported_symbol"; then
|
||||
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
|
||||
fi
|
||||
_LT_TAGVAR(link_all_deplibs, $1)=no
|
||||
else
|
||||
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
|
||||
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
|
||||
@ -5818,7 +5803,7 @@ _LT_EOF
|
||||
esac
|
||||
;;
|
||||
|
||||
netbsd* | netbsdelf*-gnu)
|
||||
netbsd*)
|
||||
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
|
||||
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
|
||||
else
|
||||
@ -9059,9 +9044,9 @@ m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
|
||||
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
|
||||
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
|
||||
|
||||
dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||
dnl serial 11 (pkg-config-0.29.1)
|
||||
dnl
|
||||
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||
# serial 11 (pkg-config-0.29.1)
|
||||
|
||||
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
|
||||
dnl
|
||||
@ -9335,9 +9320,77 @@ AS_VAR_COPY([$1], [pkg_cv_][$1])
|
||||
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
||||
])dnl PKG_CHECK_VAR
|
||||
|
||||
dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||
dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],
|
||||
dnl [DESCRIPTION], [DEFAULT])
|
||||
dnl ------------------------------------------
|
||||
dnl
|
||||
dnl Prepare a "--with-" configure option using the lowercase
|
||||
dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and
|
||||
dnl PKG_CHECK_MODULES in a single macro.
|
||||
AC_DEFUN([PKG_WITH_MODULES],
|
||||
[
|
||||
m4_pushdef([with_arg], m4_tolower([$1]))
|
||||
|
||||
m4_pushdef([description],
|
||||
[m4_default([$5], [build with ]with_arg[ support])])
|
||||
|
||||
m4_pushdef([def_arg], [m4_default([$6], [auto])])
|
||||
m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])
|
||||
m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])
|
||||
|
||||
m4_case(def_arg,
|
||||
[yes],[m4_pushdef([with_without], [--without-]with_arg)],
|
||||
[m4_pushdef([with_without],[--with-]with_arg)])
|
||||
|
||||
AC_ARG_WITH(with_arg,
|
||||
AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,
|
||||
[AS_TR_SH([with_]with_arg)=def_arg])
|
||||
|
||||
AS_CASE([$AS_TR_SH([with_]with_arg)],
|
||||
[yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
|
||||
[auto],[PKG_CHECK_MODULES([$1],[$2],
|
||||
[m4_n([def_action_if_found]) $3],
|
||||
[m4_n([def_action_if_not_found]) $4])])
|
||||
|
||||
m4_popdef([with_arg])
|
||||
m4_popdef([description])
|
||||
m4_popdef([def_arg])
|
||||
|
||||
])dnl PKG_WITH_MODULES
|
||||
|
||||
dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||
dnl [DESCRIPTION], [DEFAULT])
|
||||
dnl -----------------------------------------------
|
||||
dnl
|
||||
dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES
|
||||
dnl check._[VARIABLE-PREFIX] is exported as make variable.
|
||||
AC_DEFUN([PKG_HAVE_WITH_MODULES],
|
||||
[
|
||||
PKG_WITH_MODULES([$1],[$2],,,[$3],[$4])
|
||||
|
||||
AM_CONDITIONAL([HAVE_][$1],
|
||||
[test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"])
|
||||
])dnl PKG_HAVE_WITH_MODULES
|
||||
|
||||
dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
|
||||
dnl [DESCRIPTION], [DEFAULT])
|
||||
dnl ------------------------------------------------------
|
||||
dnl
|
||||
dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after
|
||||
dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make
|
||||
dnl and preprocessor variable.
|
||||
AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],
|
||||
[
|
||||
PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])
|
||||
|
||||
AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
|
||||
[AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
|
||||
])dnl PKG_HAVE_DEFINE_WITH_MODULES
|
||||
|
||||
# AM_CONDITIONAL -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1997-2018 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@ -9368,7 +9421,7 @@ AC_CONFIG_COMMANDS_PRE(
|
||||
Usually this means the macro was only invoked conditionally.]])
|
||||
fi])])
|
||||
|
||||
# Copyright (C) 2006-2017 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2006-2018 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
|
@ -64,26 +64,26 @@
|
||||
#ifdef HAVE_SYS_ENDIAN_H
|
||||
# include <sys/endian.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIBKERN_OSBYTEORDER_H
|
||||
/* In practice this is specific to MacOS X. We assume it doesn't have
|
||||
* htobe64/be64toh but has alternatives with a different name. */
|
||||
# include <libkern/OSByteOrder.h>
|
||||
# define htobe64(x) OSSwapHostToBigInt64(x)
|
||||
# define be64toh(x) OSSwapBigToHostInt64(x)
|
||||
#endif
|
||||
|
||||
/* Some compilers do not define __BYTE_ORDER__, like IBM XLC on AIX */
|
||||
#ifndef be64toh
|
||||
#if defined(__sun) || defined(_AIX)
|
||||
# if __BIG_ENDIAN__
|
||||
# define be64toh(n) (n)
|
||||
# define htobe64(n) (n)
|
||||
#ifndef HAVE_HTOBE64
|
||||
# ifdef HAVE_LIBKERN_OSBYTEORDER_H
|
||||
/* In practice this is specific to MacOS X. We assume it doesn't have
|
||||
* htobe64/be64toh but has alternatives with a different name. */
|
||||
# include <libkern/OSByteOrder.h>
|
||||
# define htobe64(x) OSSwapHostToBigInt64(x)
|
||||
# define be64toh(x) OSSwapBigToHostInt64(x)
|
||||
# else
|
||||
# define be64toh(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
|
||||
# define htobe64(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
|
||||
# endif
|
||||
#endif
|
||||
#endif /* be64toh */
|
||||
/* not OSX */
|
||||
/* Some compilers do not define __BYTE_ORDER__, like IBM XLC on AIX */
|
||||
# if __BIG_ENDIAN__
|
||||
# define be64toh(n) (n)
|
||||
# define htobe64(n) (n)
|
||||
# else
|
||||
# define be64toh(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
|
||||
# define htobe64(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
|
||||
# endif /* _ENDIAN */
|
||||
# endif /* HAVE_LIBKERN_OSBYTEORDER_H */
|
||||
#endif /* HAVE_BE64TOH */
|
||||
|
||||
/** the unit test testframe for cachedb, its module state contains
|
||||
* a cache for a couple queries (in memory). */
|
||||
@ -218,10 +218,6 @@ static int
|
||||
cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
|
||||
{
|
||||
const char* backend_str = cfg->cachedb_backend;
|
||||
|
||||
/* If unspecified we use the in-memory test DB. */
|
||||
if(!backend_str)
|
||||
backend_str = "testframe";
|
||||
cachedb_env->backend = cachedb_find_backend(backend_str);
|
||||
if(!cachedb_env->backend) {
|
||||
log_err("cachedb: cannot find backend name '%s'", backend_str);
|
||||
@ -259,6 +255,15 @@ cachedb_init(struct module_env* env, int id)
|
||||
return 0;
|
||||
}
|
||||
cachedb_env->enabled = 1;
|
||||
if(env->cfg->serve_expired_reply_ttl)
|
||||
log_warn(
|
||||
"cachedb: serve-expired-reply-ttl is set but not working for data "
|
||||
"originating from the external cache; 0 TLL is used for those.");
|
||||
if(env->cfg->serve_expired_client_timeout)
|
||||
log_warn(
|
||||
"cachedb: serve-expired-client-timeout is set but not working for "
|
||||
"data originating from the external cache; expired data are used "
|
||||
"in the reply without first trying to refresh the data.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -329,8 +334,7 @@ calc_hash(struct module_qstate* qstate, char* buf, size_t len)
|
||||
size_t clen = 0;
|
||||
uint8_t hash[CACHEDB_HASHSIZE/8];
|
||||
const char* hex = "0123456789ABCDEF";
|
||||
const char* secret = qstate->env->cfg->cachedb_secret ?
|
||||
qstate->env->cfg->cachedb_secret : "default";
|
||||
const char* secret = qstate->env->cfg->cachedb_secret;
|
||||
size_t i;
|
||||
|
||||
/* copy the hash info into the clear buffer */
|
||||
@ -433,8 +437,14 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
&expiry, sizeof(expiry));
|
||||
expiry = be64toh(expiry);
|
||||
|
||||
/* Check if we are allowed to return expired entries:
|
||||
* - serve_expired needs to be set
|
||||
* - if SERVE_EXPIRED_TTL is set make sure that the record is not older
|
||||
* than that. */
|
||||
if((time_t)expiry < *qstate->env->now &&
|
||||
!qstate->env->cfg->serve_expired)
|
||||
(!qstate->env->cfg->serve_expired ||
|
||||
(SERVE_EXPIRED_TTL &&
|
||||
*qstate->env->now - (time_t)expiry > SERVE_EXPIRED_TTL)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@ -445,15 +455,15 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
static void
|
||||
packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract)
|
||||
{
|
||||
size_t i;
|
||||
size_t total = data->count + data->rrsig_count;
|
||||
size_t i;
|
||||
size_t total = data->count + data->rrsig_count;
|
||||
if(subtract >= 0 && data->ttl > subtract)
|
||||
data->ttl -= subtract;
|
||||
else data->ttl = 0;
|
||||
for(i=0; i<total; i++) {
|
||||
for(i=0; i<total; i++) {
|
||||
if(subtract >= 0 && data->rr_ttl[i] > subtract)
|
||||
data->rr_ttl[i] -= subtract;
|
||||
else data->rr_ttl[i] = 0;
|
||||
data->rr_ttl[i] -= subtract;
|
||||
else data->rr_ttl[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -465,7 +475,8 @@ adjust_msg_ttl(struct dns_msg* msg, time_t adjust)
|
||||
size_t i;
|
||||
if(adjust >= 0 && msg->rep->ttl > adjust)
|
||||
msg->rep->ttl -= adjust;
|
||||
else msg->rep->ttl = 0;
|
||||
else
|
||||
msg->rep->ttl = 0;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
|
||||
@ -673,7 +684,8 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
return;
|
||||
}
|
||||
|
||||
/* lookup inside unbound's internal cache */
|
||||
/* lookup inside unbound's internal cache.
|
||||
* This does not look for expired entries. */
|
||||
if(cachedb_intcache_lookup(qstate)) {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
if(qstate->return_msg->rep)
|
||||
@ -681,8 +693,9 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
else log_info("cachedb internal cache lookup: rcode %s",
|
||||
sldns_lookup_by_id(sldns_rcodes, qstate->return_rcode)?
|
||||
sldns_lookup_by_id(sldns_rcodes, qstate->return_rcode)->name:"??");
|
||||
sldns_lookup_by_id(sldns_rcodes, qstate->return_rcode)
|
||||
?sldns_lookup_by_id(sldns_rcodes, qstate->return_rcode)->name
|
||||
:"??");
|
||||
}
|
||||
/* we are done with the query */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
@ -697,6 +710,19 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
qstate->return_msg->rep);
|
||||
/* store this result in internal cache */
|
||||
cachedb_intcache_store(qstate);
|
||||
/* In case we have expired data but there is a client timer for expired
|
||||
* answers, pass execution to next module in order to try updating the
|
||||
* data first.
|
||||
* TODO: this needs revisit. The expired data stored from cachedb has
|
||||
* 0 TTL which is picked up by iterator later when looking in the cache.
|
||||
* Document that ext cachedb does not work properly with
|
||||
* serve_stale_reply_ttl yet. */
|
||||
if(qstate->need_refetch && qstate->serve_expired_data &&
|
||||
qstate->serve_expired_data->timer) {
|
||||
qstate->return_msg = NULL;
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
/* we are done with the query */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: getentropy_solaris.c,v 1.13 2018/11/20 08:04:28 deraadt Exp $ */
|
||||
/* $OpenBSD: getentropy_solaris.c,v 1.4 2014/07/12 20:41:47 wouter Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
|
||||
@ -15,12 +15,9 @@
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Emulation of getentropy(2) as documented at:
|
||||
* http://man.openbsd.org/getentropy.2
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
@ -37,7 +34,6 @@
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <link.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
@ -71,14 +67,17 @@
|
||||
|
||||
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
|
||||
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
|
||||
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
|
||||
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
|
||||
|
||||
int getentropy(void *buf, size_t len);
|
||||
|
||||
#ifdef CAN_REFERENCE_MAIN
|
||||
extern int main(int, char *argv[]);
|
||||
#endif
|
||||
static int gotdata(char *buf, size_t len);
|
||||
static int getentropy_urandom(void *buf, size_t len, const char *path,
|
||||
int devfscheck);
|
||||
static int getentropy_fallback(void *buf, size_t len);
|
||||
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
|
||||
|
||||
int
|
||||
getentropy(void *buf, size_t len)
|
||||
@ -87,7 +86,7 @@ getentropy(void *buf, size_t len)
|
||||
|
||||
if (len > 256) {
|
||||
errno = EIO;
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -154,6 +153,22 @@ getentropy(void *buf, size_t len)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic sanity checking; wish we could do better.
|
||||
*/
|
||||
static int
|
||||
gotdata(char *buf, size_t len)
|
||||
{
|
||||
char any_set = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
any_set |= buf[i];
|
||||
if (any_set == 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
|
||||
{
|
||||
@ -200,11 +215,13 @@ getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
|
||||
i += ret;
|
||||
}
|
||||
close(fd);
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
if (gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return 0; /* satisfied */
|
||||
}
|
||||
nodevrandom:
|
||||
errno = EIO;
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const int cl[] = {
|
||||
@ -232,15 +249,6 @@ static const int cl[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int
|
||||
getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
|
||||
{
|
||||
SHA512_CTX *ctx = data;
|
||||
|
||||
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
getentropy_fallback(void *buf, size_t len)
|
||||
{
|
||||
@ -278,8 +286,6 @@ getentropy_fallback(void *buf, size_t len)
|
||||
cnt += (int)tv.tv_usec;
|
||||
}
|
||||
|
||||
dl_iterate_phdr(getentropy_phdr, &ctx);
|
||||
|
||||
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
|
||||
HX(clock_gettime(cl[ii], &ts) == -1, ts);
|
||||
|
||||
@ -300,6 +306,9 @@ getentropy_fallback(void *buf, size_t len)
|
||||
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
|
||||
sigset);
|
||||
|
||||
#ifdef CAN_REFERENCE_MAIN
|
||||
HF(main); /* an addr in program */
|
||||
#endif
|
||||
HF(getentropy); /* an addr in this library */
|
||||
HF(printf); /* an addr in libc */
|
||||
p = (char *)&p;
|
||||
@ -422,8 +431,11 @@ getentropy_fallback(void *buf, size_t len)
|
||||
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
|
||||
i += min(sizeof(results), len - i);
|
||||
}
|
||||
explicit_bzero(&ctx, sizeof ctx);
|
||||
explicit_bzero(results, sizeof results);
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
memset(results, 0, sizeof results);
|
||||
if (gotdata(buf, len) == 0) {
|
||||
errno = save_errno;
|
||||
return 0; /* satisfied */
|
||||
}
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
586
contrib/unbound/config.guess
vendored
586
contrib/unbound/config.guess
vendored
File diff suppressed because it is too large
Load Diff
@ -63,6 +63,15 @@
|
||||
/* Whether the C compiler accepts the "weak" attribute */
|
||||
#undef HAVE_ATTR_WEAK
|
||||
|
||||
/* If we have be64toh */
|
||||
#undef HAVE_BE64TOH
|
||||
|
||||
/* Define to 1 if you have the <bsd/stdlib.h> header file. */
|
||||
#undef HAVE_BSD_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <bsd/string.h> header file. */
|
||||
#undef HAVE_BSD_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `chown' function. */
|
||||
#undef HAVE_CHOWN
|
||||
|
||||
@ -284,6 +293,9 @@
|
||||
/* If you have HMAC_Update */
|
||||
#undef HAVE_HMAC_UPDATE
|
||||
|
||||
/* If we have htobe64 */
|
||||
#undef HAVE_HTOBE64
|
||||
|
||||
/* Define to 1 if you have the `inet_aton' function. */
|
||||
#undef HAVE_INET_ATON
|
||||
|
||||
@ -311,6 +323,9 @@
|
||||
/* Define to 1 if you have the `kill' function. */
|
||||
#undef HAVE_KILL
|
||||
|
||||
/* Use portable libbsd functions */
|
||||
#undef HAVE_LIBBSD
|
||||
|
||||
/* Define to 1 if you have the <libkern/OSByteOrder.h> header file. */
|
||||
#undef HAVE_LIBKERN_OSBYTEORDER_H
|
||||
|
||||
@ -1231,6 +1246,11 @@ char *strptime(const char *s, const char *format, struct tm *tm);
|
||||
void *reallocarray(void *ptr, size_t nmemb, size_t size);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBBSD
|
||||
#include <bsd/string.h>
|
||||
#include <bsd/stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBRESSL
|
||||
# if !HAVE_DECL_STRLCPY
|
||||
size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
|
262
contrib/unbound/config.sub
vendored
262
contrib/unbound/config.sub
vendored
@ -1,8 +1,8 @@
|
||||
#! /bin/sh
|
||||
#!/usr/bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright 1992-2018 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2018-02-22'
|
||||
timestamp='2016-09-05'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@ -15,7 +15,7 @@ timestamp='2018-02-22'
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
@ -33,7 +33,7 @@ timestamp='2018-02-22'
|
||||
# Otherwise, we print the canonical config type on stdout and succeed.
|
||||
|
||||
# You can get the latest version of this script from:
|
||||
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
|
||||
|
||||
# This file is supposed to be the same for all GNU packages
|
||||
# and recognize all the CPU types, system types and aliases
|
||||
@ -57,7 +57,7 @@ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
|
||||
|
||||
Canonicalize a configuration name.
|
||||
|
||||
Options:
|
||||
Operation modes:
|
||||
-h, --help print this help, then exit
|
||||
-t, --time-stamp print date of last modification, then exit
|
||||
-v, --version print version number, then exit
|
||||
@ -67,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright 1992-2018 Free Software Foundation, Inc.
|
||||
Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@ -94,7 +94,7 @@ while test $# -gt 0 ; do
|
||||
|
||||
*local*)
|
||||
# First pass through any local machine types.
|
||||
echo "$1"
|
||||
echo $1
|
||||
exit ;;
|
||||
|
||||
* )
|
||||
@ -112,7 +112,7 @@ esac
|
||||
|
||||
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
||||
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||
@ -120,16 +120,16 @@ case $maybe_os in
|
||||
kopensolaris*-gnu* | cloudabi*-eabi* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
android-linux)
|
||||
os=-linux-android
|
||||
basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
|
||||
;;
|
||||
*)
|
||||
basic_machine=`echo "$1" | sed 's/-[^-]*$//'`
|
||||
if [ "$basic_machine" != "$1" ]
|
||||
then os=`echo "$1" | sed 's/.*-/-/'`
|
||||
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
|
||||
if [ $basic_machine != $1 ]
|
||||
then os=`echo $1 | sed 's/.*-/-/'`
|
||||
else os=; fi
|
||||
;;
|
||||
esac
|
||||
@ -178,44 +178,44 @@ case $os in
|
||||
;;
|
||||
-sco6)
|
||||
os=-sco5v6
|
||||
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco5)
|
||||
os=-sco3.2v5
|
||||
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco4)
|
||||
os=-sco3.2v4
|
||||
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco3.2.[4-9]*)
|
||||
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
|
||||
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco3.2v[4-9]*)
|
||||
# Don't forget version if it is 3.2v4 or newer.
|
||||
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco5v6*)
|
||||
# Don't forget version if it is 3.2v4 or newer.
|
||||
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco*)
|
||||
os=-sco3.2v2
|
||||
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-udk*)
|
||||
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-isc)
|
||||
os=-isc2.2
|
||||
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-clix*)
|
||||
basic_machine=clipper-intergraph
|
||||
;;
|
||||
-isc*)
|
||||
basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-lynx*178)
|
||||
os=-lynxos178
|
||||
@ -227,7 +227,10 @@ case $os in
|
||||
os=-lynxos
|
||||
;;
|
||||
-ptx*)
|
||||
basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
|
||||
;;
|
||||
-windowsnt*)
|
||||
os=`echo $os | sed -e 's/windowsnt/winnt/'`
|
||||
;;
|
||||
-psos*)
|
||||
os=-psos
|
||||
@ -260,7 +263,7 @@ case $basic_machine in
|
||||
| fido | fr30 | frv | ft32 \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| hexagon \
|
||||
| i370 | i860 | i960 | ia16 | ia64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| k1om \
|
||||
| le32 | le64 \
|
||||
@ -296,9 +299,8 @@ case $basic_machine in
|
||||
| nios | nios2 | nios2eb | nios2el \
|
||||
| ns16k | ns32k \
|
||||
| open8 | or1k | or1knd | or32 \
|
||||
| pdp10 | pj | pjl \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle \
|
||||
| pru \
|
||||
| pyramid \
|
||||
| riscv32 | riscv64 \
|
||||
| rl78 | rx \
|
||||
@ -312,7 +314,7 @@ case $basic_machine in
|
||||
| ubicom32 \
|
||||
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
|
||||
| visium \
|
||||
| wasm32 \
|
||||
| we32k \
|
||||
| x86 | xc16x | xstormy16 | xtensa \
|
||||
| z8k | z80)
|
||||
basic_machine=$basic_machine-unknown
|
||||
@ -333,7 +335,7 @@ case $basic_machine in
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
|
||||
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
|
||||
;;
|
||||
ms1)
|
||||
basic_machine=mt-unknown
|
||||
@ -362,7 +364,7 @@ case $basic_machine in
|
||||
;;
|
||||
# Object if more than one company name word.
|
||||
*-*-*)
|
||||
echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
|
||||
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
|
||||
exit 1
|
||||
;;
|
||||
# Recognize the basic CPU types with company name.
|
||||
@ -385,7 +387,7 @@ case $basic_machine in
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| hexagon-* \
|
||||
| i*86-* | i860-* | i960-* | ia16-* | ia64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| k1om-* \
|
||||
| le32-* | le64-* \
|
||||
@ -426,7 +428,6 @@ case $basic_machine in
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
||||
| pru-* \
|
||||
| pyramid-* \
|
||||
| riscv32-* | riscv64-* \
|
||||
| rl78-* | romp-* | rs6000-* | rx-* \
|
||||
@ -443,7 +444,6 @@ case $basic_machine in
|
||||
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
|
||||
| vax-* \
|
||||
| visium-* \
|
||||
| wasm32-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
@ -457,7 +457,7 @@ case $basic_machine in
|
||||
# Recognize the various machine names and aliases which stand
|
||||
# for a CPU type and a company and sometimes even an OS.
|
||||
386bsd)
|
||||
basic_machine=i386-pc
|
||||
basic_machine=i386-unknown
|
||||
os=-bsd
|
||||
;;
|
||||
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
|
||||
@ -491,7 +491,7 @@ case $basic_machine in
|
||||
basic_machine=x86_64-pc
|
||||
;;
|
||||
amd64-*)
|
||||
basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
amdahl)
|
||||
basic_machine=580-amdahl
|
||||
@ -536,7 +536,7 @@ case $basic_machine in
|
||||
os=-linux
|
||||
;;
|
||||
blackfin-*)
|
||||
basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
bluegene*)
|
||||
@ -544,13 +544,13 @@ case $basic_machine in
|
||||
os=-cnk
|
||||
;;
|
||||
c54x-*)
|
||||
basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c55x-*)
|
||||
basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c6x-*)
|
||||
basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
@ -639,7 +639,7 @@ case $basic_machine in
|
||||
basic_machine=rs6000-bull
|
||||
os=-bosx
|
||||
;;
|
||||
dpx2*)
|
||||
dpx2* | dpx2*-bull)
|
||||
basic_machine=m68k-bull
|
||||
os=-sysv3
|
||||
;;
|
||||
@ -648,7 +648,7 @@ case $basic_machine in
|
||||
os=$os"spe"
|
||||
;;
|
||||
e500v[12]-*)
|
||||
basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=$os"spe"
|
||||
;;
|
||||
ebmon29k)
|
||||
@ -740,6 +740,9 @@ case $basic_machine in
|
||||
hp9k8[0-9][0-9] | hp8[0-9][0-9])
|
||||
basic_machine=hppa1.0-hp
|
||||
;;
|
||||
hppa-next)
|
||||
os=-nextstep3
|
||||
;;
|
||||
hppaosf)
|
||||
basic_machine=hppa1.1-hp
|
||||
os=-osf
|
||||
@ -752,26 +755,26 @@ case $basic_machine in
|
||||
basic_machine=i370-ibm
|
||||
;;
|
||||
i*86v32)
|
||||
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv32
|
||||
;;
|
||||
i*86v4*)
|
||||
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv4
|
||||
;;
|
||||
i*86v)
|
||||
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv
|
||||
;;
|
||||
i*86sol2)
|
||||
basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-solaris2
|
||||
;;
|
||||
i386mach)
|
||||
basic_machine=i386-mach
|
||||
os=-mach
|
||||
;;
|
||||
vsta)
|
||||
i386-vsta | vsta)
|
||||
basic_machine=i386-unknown
|
||||
os=-vsta
|
||||
;;
|
||||
@ -790,16 +793,19 @@ case $basic_machine in
|
||||
os=-sysv
|
||||
;;
|
||||
leon-*|leon[3-9]-*)
|
||||
basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'`
|
||||
basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
|
||||
;;
|
||||
m68knommu)
|
||||
basic_machine=m68k-unknown
|
||||
os=-linux
|
||||
;;
|
||||
m68knommu-*)
|
||||
basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
m88k-omron*)
|
||||
basic_machine=m88k-omron
|
||||
;;
|
||||
magnum | m3230)
|
||||
basic_machine=mips-mips
|
||||
os=-sysv
|
||||
@ -831,10 +837,10 @@ case $basic_machine in
|
||||
os=-mint
|
||||
;;
|
||||
mips3*-*)
|
||||
basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
|
||||
;;
|
||||
mips3*)
|
||||
basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
||||
;;
|
||||
monitor)
|
||||
basic_machine=m68k-rom68k
|
||||
@ -853,7 +859,7 @@ case $basic_machine in
|
||||
os=-msdos
|
||||
;;
|
||||
ms1-*)
|
||||
basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'`
|
||||
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
|
||||
;;
|
||||
msys)
|
||||
basic_machine=i686-pc
|
||||
@ -895,7 +901,7 @@ case $basic_machine in
|
||||
basic_machine=v70-nec
|
||||
os=-sysv
|
||||
;;
|
||||
next | m*-next)
|
||||
next | m*-next )
|
||||
basic_machine=m68k-next
|
||||
case $os in
|
||||
-nextstep* )
|
||||
@ -940,12 +946,6 @@ case $basic_machine in
|
||||
nsr-tandem)
|
||||
basic_machine=nsr-tandem
|
||||
;;
|
||||
nsv-tandem)
|
||||
basic_machine=nsv-tandem
|
||||
;;
|
||||
nsx-tandem)
|
||||
basic_machine=nsx-tandem
|
||||
;;
|
||||
op50n-* | op60c-*)
|
||||
basic_machine=hppa1.1-oki
|
||||
os=-proelf
|
||||
@ -978,7 +978,7 @@ case $basic_machine in
|
||||
os=-linux
|
||||
;;
|
||||
parisc-*)
|
||||
basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
pbd)
|
||||
@ -994,7 +994,7 @@ case $basic_machine in
|
||||
basic_machine=i386-pc
|
||||
;;
|
||||
pc98-*)
|
||||
basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentium | p5 | k5 | k6 | nexgen | viac3)
|
||||
basic_machine=i586-pc
|
||||
@ -1009,16 +1009,16 @@ case $basic_machine in
|
||||
basic_machine=i786-pc
|
||||
;;
|
||||
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
|
||||
basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumpro-* | p6-* | 6x86-* | athlon-*)
|
||||
basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
|
||||
basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentium4-*)
|
||||
basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pn)
|
||||
basic_machine=pn-gould
|
||||
@ -1028,23 +1028,23 @@ case $basic_machine in
|
||||
ppc | ppcbe) basic_machine=powerpc-unknown
|
||||
;;
|
||||
ppc-* | ppcbe-*)
|
||||
basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppcle | powerpclittle)
|
||||
basic_machine=powerpcle-unknown
|
||||
;;
|
||||
ppcle-* | powerpclittle-*)
|
||||
basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppc64) basic_machine=powerpc64-unknown
|
||||
;;
|
||||
ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppc64le | powerpc64little)
|
||||
basic_machine=powerpc64le-unknown
|
||||
;;
|
||||
ppc64le-* | powerpc64little-*)
|
||||
basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ps2)
|
||||
basic_machine=i386-ibm
|
||||
@ -1098,10 +1098,17 @@ case $basic_machine in
|
||||
sequent)
|
||||
basic_machine=i386-sequent
|
||||
;;
|
||||
sh)
|
||||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sh5el)
|
||||
basic_machine=sh5le-unknown
|
||||
;;
|
||||
simso-wrs)
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
sparclite-wrs | simso-wrs)
|
||||
basic_machine=sparclite-wrs
|
||||
os=-vxworks
|
||||
;;
|
||||
@ -1120,7 +1127,7 @@ case $basic_machine in
|
||||
os=-sysv4
|
||||
;;
|
||||
strongarm-* | thumb-*)
|
||||
basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'`
|
||||
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
sun2)
|
||||
basic_machine=m68000-sun
|
||||
@ -1242,9 +1249,6 @@ case $basic_machine in
|
||||
basic_machine=hppa1.1-winbond
|
||||
os=-proelf
|
||||
;;
|
||||
x64)
|
||||
basic_machine=x86_64-pc
|
||||
;;
|
||||
xbox)
|
||||
basic_machine=i686-pc
|
||||
os=-mingw32
|
||||
@ -1253,12 +1257,20 @@ case $basic_machine in
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
xscale-* | xscalee[bl]-*)
|
||||
basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'`
|
||||
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
|
||||
;;
|
||||
ymp)
|
||||
basic_machine=ymp-cray
|
||||
os=-unicos
|
||||
;;
|
||||
z8k-*-coff)
|
||||
basic_machine=z8k-unknown
|
||||
os=-sim
|
||||
;;
|
||||
z80-*-coff)
|
||||
basic_machine=z80-unknown
|
||||
os=-sim
|
||||
;;
|
||||
none)
|
||||
basic_machine=none-none
|
||||
os=-none
|
||||
@ -1287,6 +1299,10 @@ case $basic_machine in
|
||||
vax)
|
||||
basic_machine=vax-dec
|
||||
;;
|
||||
pdp10)
|
||||
# there are many clones, so DEC is not a safe bet
|
||||
basic_machine=pdp10-unknown
|
||||
;;
|
||||
pdp11)
|
||||
basic_machine=pdp11-dec
|
||||
;;
|
||||
@ -1296,6 +1312,9 @@ case $basic_machine in
|
||||
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
basic_machine=sh-unknown
|
||||
;;
|
||||
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
|
||||
basic_machine=sparc-sun
|
||||
;;
|
||||
cydra)
|
||||
basic_machine=cydra-cydrome
|
||||
;;
|
||||
@ -1315,7 +1334,7 @@ case $basic_machine in
|
||||
# Make sure to match an already-canonicalized machine name.
|
||||
;;
|
||||
*)
|
||||
echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
|
||||
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@ -1323,10 +1342,10 @@ esac
|
||||
# Here we canonicalize certain aliases for manufacturers.
|
||||
case $basic_machine in
|
||||
*-digital*)
|
||||
basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'`
|
||||
basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
|
||||
;;
|
||||
*-commodore*)
|
||||
basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'`
|
||||
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
@ -1337,8 +1356,8 @@ esac
|
||||
if [ x"$os" != x"" ]
|
||||
then
|
||||
case $os in
|
||||
# First match some system type aliases that might get confused
|
||||
# with valid system types.
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# -solaris* is a basic system type, with this one exception.
|
||||
-auroraux)
|
||||
os=-auroraux
|
||||
@ -1349,19 +1368,18 @@ case $os in
|
||||
-solaris)
|
||||
os=-solaris2
|
||||
;;
|
||||
-svr4*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-unixware*)
|
||||
os=-sysv4.2uw
|
||||
;;
|
||||
-gnu/linux*)
|
||||
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
|
||||
;;
|
||||
# es1800 is here to avoid being matched by es* (a different OS)
|
||||
-es1800*)
|
||||
os=-ose
|
||||
;;
|
||||
# Now accept the basic system types.
|
||||
# First accept the basic system types.
|
||||
# The portable systems comes first.
|
||||
# Each alternative MUST end in a * to match a version number.
|
||||
# Each alternative MUST END IN A *, to match a version number.
|
||||
# -sysv* is not here because it comes later, after sysvr4.
|
||||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
|
||||
@ -1371,26 +1389,25 @@ case $os in
|
||||
| -aos* | -aros* | -cloudabi* | -sortix* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
| -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
|
||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
|
||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
||||
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -windiss* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
|
||||
| -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \
|
||||
| -midnightbsd*)
|
||||
| -onefs* | -tirtos* | -phoenix*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@ -1407,12 +1424,12 @@ case $os in
|
||||
-nto*)
|
||||
os=`echo $os | sed -e 's|nto|nto-qnx|'`
|
||||
;;
|
||||
-sim | -xray | -os68k* | -v88r* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* \
|
||||
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
|
||||
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
||||
;;
|
||||
-mac*)
|
||||
os=`echo "$os" | sed -e 's|mac|macos|'`
|
||||
os=`echo $os | sed -e 's|mac|macos|'`
|
||||
;;
|
||||
-linux-dietlibc)
|
||||
os=-linux-dietlibc
|
||||
@ -1421,10 +1438,10 @@ case $os in
|
||||
os=`echo $os | sed -e 's|linux|linux-gnu|'`
|
||||
;;
|
||||
-sunos5*)
|
||||
os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
|
||||
os=`echo $os | sed -e 's|sunos5|solaris2|'`
|
||||
;;
|
||||
-sunos6*)
|
||||
os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
|
||||
os=`echo $os | sed -e 's|sunos6|solaris3|'`
|
||||
;;
|
||||
-opened*)
|
||||
os=-openedition
|
||||
@ -1435,6 +1452,12 @@ case $os in
|
||||
-wince*)
|
||||
os=-wince
|
||||
;;
|
||||
-osfrose*)
|
||||
os=-osfrose
|
||||
;;
|
||||
-osf*)
|
||||
os=-osf
|
||||
;;
|
||||
-utek*)
|
||||
os=-bsd
|
||||
;;
|
||||
@ -1459,7 +1482,7 @@ case $os in
|
||||
-nova*)
|
||||
os=-rtmk-nova
|
||||
;;
|
||||
-ns2)
|
||||
-ns2 )
|
||||
os=-nextstep2
|
||||
;;
|
||||
-nsk*)
|
||||
@ -1481,7 +1504,7 @@ case $os in
|
||||
-oss*)
|
||||
os=-sysv3
|
||||
;;
|
||||
-svr4*)
|
||||
-svr4)
|
||||
os=-sysv4
|
||||
;;
|
||||
-svr3)
|
||||
@ -1496,28 +1519,24 @@ case $os in
|
||||
-ose*)
|
||||
os=-ose
|
||||
;;
|
||||
-es1800*)
|
||||
os=-ose
|
||||
;;
|
||||
-xenix)
|
||||
os=-xenix
|
||||
;;
|
||||
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
|
||||
os=-mint
|
||||
;;
|
||||
-aros*)
|
||||
os=-aros
|
||||
;;
|
||||
-zvmoe)
|
||||
os=-zvmoe
|
||||
;;
|
||||
-dicos*)
|
||||
os=-dicos
|
||||
;;
|
||||
-pikeos*)
|
||||
# Until real need of OS specific support for
|
||||
# particular features comes up, bare metal
|
||||
# configurations are quite functional.
|
||||
case $basic_machine in
|
||||
arm*)
|
||||
os=-eabi
|
||||
;;
|
||||
*)
|
||||
os=-elf
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-nacl*)
|
||||
;;
|
||||
-ios)
|
||||
@ -1527,7 +1546,7 @@ case $os in
|
||||
*)
|
||||
# Get rid of the `-' at the beginning of $os.
|
||||
os=`echo $os | sed 's/[^-]*-//'`
|
||||
echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
|
||||
echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@ -1617,12 +1636,12 @@ case $basic_machine in
|
||||
sparc-* | *-sun)
|
||||
os=-sunos4.1.1
|
||||
;;
|
||||
pru-*)
|
||||
os=-elf
|
||||
;;
|
||||
*-be)
|
||||
os=-beos
|
||||
;;
|
||||
*-haiku)
|
||||
os=-haiku
|
||||
;;
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
@ -1662,7 +1681,7 @@ case $basic_machine in
|
||||
m88k-omron*)
|
||||
os=-luna
|
||||
;;
|
||||
*-next)
|
||||
*-next )
|
||||
os=-nextstep
|
||||
;;
|
||||
*-sequent)
|
||||
@ -1677,6 +1696,9 @@ case $basic_machine in
|
||||
i370-*)
|
||||
os=-mvs
|
||||
;;
|
||||
*-next)
|
||||
os=-nextstep3
|
||||
;;
|
||||
*-gould)
|
||||
os=-sysv
|
||||
;;
|
||||
@ -1786,15 +1808,15 @@ case $basic_machine in
|
||||
vendor=stratus
|
||||
;;
|
||||
esac
|
||||
basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"`
|
||||
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$basic_machine$os"
|
||||
echo $basic_machine$os
|
||||
exit
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-functions 'time-stamp)
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "timestamp='"
|
||||
# time-stamp-format: "%:y-%02m-%02d"
|
||||
# time-stamp-end: "'"
|
||||
|
261
contrib/unbound/configure
vendored
261
contrib/unbound/configure
vendored
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.9.6.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.10.1.
|
||||
#
|
||||
# Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>.
|
||||
#
|
||||
@ -591,8 +591,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='unbound'
|
||||
PACKAGE_TARNAME='unbound'
|
||||
PACKAGE_VERSION='1.9.6'
|
||||
PACKAGE_STRING='unbound 1.9.6'
|
||||
PACKAGE_VERSION='1.10.1'
|
||||
PACKAGE_STRING='unbound 1.10.1'
|
||||
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
|
||||
PACKAGE_URL=''
|
||||
|
||||
@ -673,8 +673,10 @@ UNBOUND_EVENT_UNINSTALL
|
||||
UNBOUND_EVENT_INSTALL
|
||||
SUBNET_HEADER
|
||||
SUBNET_OBJ
|
||||
PC_LIBBSD_DEPENDENCY
|
||||
SSLLIB
|
||||
HAVE_SSL
|
||||
PC_CRYPTO_DEPENDENCY
|
||||
CONFIG_DATE
|
||||
NETBSD_LINTFLAGS
|
||||
PYUNBOUND_UNINSTALL
|
||||
@ -801,7 +803,6 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@ -860,6 +861,7 @@ enable_swig_version_check
|
||||
with_nss
|
||||
with_nettle
|
||||
with_ssl
|
||||
with_libbsd
|
||||
enable_sha1
|
||||
enable_sha2
|
||||
enable_subnet
|
||||
@ -948,7 +950,6 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
@ -1201,15 +1202,6 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@ -1347,7 +1339,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir runstatedir
|
||||
libdir localedir mandir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@ -1460,7 +1452,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures unbound 1.9.6 to adapt to many kinds of systems.
|
||||
\`configure' configures unbound 1.10.1 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@ -1500,7 +1492,6 @@ Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
@ -1526,7 +1517,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of unbound 1.9.6:";;
|
||||
short | recursive ) echo "Configuration of unbound 1.10.1:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@ -1632,6 +1623,7 @@ Optional Packages:
|
||||
--with-ssl=pathname enable SSL (will check /usr/local/ssl /usr/lib/ssl
|
||||
/usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw
|
||||
/usr)
|
||||
--with-libbsd Use portable libbsd functions
|
||||
--with-libevent=pathname
|
||||
use libevent (will check /usr/local /opt/local
|
||||
/usr/lib /usr/pkg /usr/sfw /usr or you can specify
|
||||
@ -1748,7 +1740,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unbound configure 1.9.6
|
||||
unbound configure 1.10.1
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@ -2457,7 +2449,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by unbound $as_me 1.9.6, which was
|
||||
It was created by unbound $as_me 1.10.1, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@ -2807,13 +2799,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
UNBOUND_VERSION_MAJOR=1
|
||||
|
||||
UNBOUND_VERSION_MINOR=9
|
||||
UNBOUND_VERSION_MINOR=10
|
||||
|
||||
UNBOUND_VERSION_MICRO=6
|
||||
UNBOUND_VERSION_MICRO=1
|
||||
|
||||
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=6
|
||||
LIBUNBOUND_REVISION=8
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@ -2887,6 +2879,8 @@ LIBUNBOUND_AGE=1
|
||||
# 1.9.4 had 9:4:1
|
||||
# 1.9.5 had 9:5:1
|
||||
# 1.9.6 had 9:6:1
|
||||
# 1.10.0 had 9:7:1
|
||||
# 1.10.1 had 9:8:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@ -8061,7 +8055,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
|
||||
lt_cv_deplibs_check_method=pass_all
|
||||
;;
|
||||
|
||||
netbsd* | netbsdelf*-gnu)
|
||||
netbsd*)
|
||||
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
|
||||
lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
|
||||
else
|
||||
@ -11526,9 +11520,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie
|
||||
openbsd* | bitrig*)
|
||||
with_gnu_ld=no
|
||||
;;
|
||||
linux* | k*bsd*-gnu | gnu*)
|
||||
link_all_deplibs=no
|
||||
;;
|
||||
esac
|
||||
|
||||
ld_shlibs=yes
|
||||
@ -11783,7 +11774,7 @@ _LT_EOF
|
||||
fi
|
||||
;;
|
||||
|
||||
netbsd* | netbsdelf*-gnu)
|
||||
netbsd*)
|
||||
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
|
||||
archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
|
||||
wlarc=
|
||||
@ -12453,7 +12444,6 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; }
|
||||
if test yes = "$lt_cv_irix_exported_symbol"; then
|
||||
archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
|
||||
fi
|
||||
link_all_deplibs=no
|
||||
else
|
||||
archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
|
||||
archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
|
||||
@ -12475,7 +12465,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; }
|
||||
esac
|
||||
;;
|
||||
|
||||
netbsd* | netbsdelf*-gnu)
|
||||
netbsd*)
|
||||
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
|
||||
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
|
||||
else
|
||||
@ -13570,6 +13560,9 @@ fi
|
||||
# before this can be enabled.
|
||||
hardcode_into_libs=yes
|
||||
|
||||
# Add ABI-specific directories to the system library path.
|
||||
sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
|
||||
|
||||
# Ideally, we could use ldconfig to report *all* directores which are
|
||||
# searched for libraries, however this is still not possible. Aside from not
|
||||
# being certain /sbin/ldconfig is available, command
|
||||
@ -13578,7 +13571,7 @@ fi
|
||||
# appending ld.so.conf contents (and includes) to the search path.
|
||||
if test -f /etc/ld.so.conf; then
|
||||
lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
|
||||
sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
|
||||
sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
|
||||
fi
|
||||
|
||||
# We used to test for /lib/ld.so.1 and disable shared libraries on
|
||||
@ -13590,18 +13583,6 @@ fi
|
||||
dynamic_linker='GNU/Linux ld.so'
|
||||
;;
|
||||
|
||||
netbsdelf*-gnu)
|
||||
version_type=linux
|
||||
need_lib_prefix=no
|
||||
need_version=no
|
||||
library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
|
||||
soname_spec='${libname}${release}${shared_ext}$major'
|
||||
shlibpath_var=LD_LIBRARY_PATH
|
||||
shlibpath_overrides_runpath=no
|
||||
hardcode_into_libs=yes
|
||||
dynamic_linker='NetBSD ld.elf_so'
|
||||
;;
|
||||
|
||||
netbsd*)
|
||||
version_type=sunos
|
||||
need_lib_prefix=no
|
||||
@ -15668,7 +15649,7 @@ else
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@ -15714,7 +15695,7 @@ else
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@ -15738,7 +15719,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@ -15783,7 +15764,7 @@ else
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@ -15807,7 +15788,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
We can't simply define LARGE_OFF_T to be 9223372036854775807,
|
||||
since some C++ compilers masquerading as C compilers
|
||||
incorrectly reject 9223372036854775807. */
|
||||
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
|
||||
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
|
||||
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
|
||||
&& LARGE_OFF_T % 2147483647 == 1)
|
||||
? 1 : -1];
|
||||
@ -17783,6 +17764,8 @@ $as_echo "#define HAVE_NSS 1" >>confdefs.h
|
||||
fi
|
||||
LIBS="$LIBS -lnss3 -lnspr4"
|
||||
SSLLIB=""
|
||||
PC_CRYPTO_DEPENDENCY="nss nspr"
|
||||
|
||||
|
||||
|
||||
fi
|
||||
@ -17826,6 +17809,8 @@ done
|
||||
fi
|
||||
LIBS="$LIBS -lhogweed -lnettle -lgmp"
|
||||
SSLLIB=""
|
||||
PC_CRYPTO_DEPENDENCY="hogweed nettle"
|
||||
|
||||
|
||||
|
||||
fi
|
||||
@ -18176,6 +18161,9 @@ rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
SSLLIB="-lssl"
|
||||
|
||||
PC_CRYPTO_DEPENDENCY="libcrypto libssl"
|
||||
|
||||
|
||||
# check if -lcrypt32 is needed because CAPIENG needs that. (on windows)
|
||||
BAKLIBS="$LIBS"
|
||||
LIBS="-lssl $LIBS"
|
||||
@ -18466,6 +18454,96 @@ fi
|
||||
fi
|
||||
|
||||
|
||||
# libbsd
|
||||
|
||||
# Check whether --with-libbsd was given.
|
||||
if test "${with_libbsd+set}" = set; then :
|
||||
withval=$with_libbsd;
|
||||
for ac_header in bsd/string.h bsd/stdlib.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
|
||||
"
|
||||
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
if test "x$ac_cv_header_bsd_string_h" = xyes -a "x$ac_cv_header_bsd_stdlib_h" = xyes; then
|
||||
for func in strlcpy strlcat arc4random arc4random_uniform reallocarray; do
|
||||
as_ac_Search=`$as_echo "ac_cv_search_$func" | $as_tr_sh`
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing $func" >&5
|
||||
$as_echo_n "checking for library containing $func... " >&6; }
|
||||
if eval \${$as_ac_Search+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_func_search_save_LIBS=$LIBS
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char $func ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return $func ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
for ac_lib in '' bsd; do
|
||||
if test -z "$ac_lib"; then
|
||||
ac_res="none required"
|
||||
else
|
||||
ac_res=-l$ac_lib
|
||||
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
|
||||
fi
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
eval "$as_ac_Search=\$ac_res"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext
|
||||
if eval \${$as_ac_Search+:} false; then :
|
||||
break
|
||||
fi
|
||||
done
|
||||
if eval \${$as_ac_Search+:} false; then :
|
||||
|
||||
else
|
||||
eval "$as_ac_Search=no"
|
||||
fi
|
||||
rm conftest.$ac_ext
|
||||
LIBS=$ac_func_search_save_LIBS
|
||||
fi
|
||||
eval ac_res=\$$as_ac_Search
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||
$as_echo "$ac_res" >&6; }
|
||||
eval ac_res=\$$as_ac_Search
|
||||
if test "$ac_res" != no; then :
|
||||
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
|
||||
|
||||
|
||||
$as_echo "#define HAVE_LIBBSD 1" >>confdefs.h
|
||||
|
||||
PC_LIBBSD_DEPENDENCY=libbsd
|
||||
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-sha1 was given.
|
||||
if test "${enable_sha1+set}" = set; then :
|
||||
@ -18769,9 +18847,7 @@ fi
|
||||
|
||||
use_dsa="no"
|
||||
case "$enable_dsa" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
yes)
|
||||
# detect if DSA is supported, and turn it off if not.
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
ac_fn_c_check_func "$LINENO" "DSA_SIG_new" "ac_cv_func_DSA_SIG_new"
|
||||
@ -18824,6 +18900,10 @@ _ACEOF
|
||||
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# disable dsa by default, RFC 8624 section 3.1, validators MUST NOT
|
||||
# support DSA for DNSSEC Validation.
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check whether --enable-ed25519 was given.
|
||||
@ -19948,6 +20028,75 @@ _ACEOF
|
||||
|
||||
fi
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for htobe64" >&5
|
||||
$as_echo_n "checking for htobe64... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_ENDIAN_H
|
||||
# include <endian.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ENDIAN_H
|
||||
# include <sys/endian.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
unsigned long long x = htobe64(0); printf("%u", (unsigned)x);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
$as_echo "#define HAVE_HTOBE64 1" >>confdefs.h
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for be64toh" >&5
|
||||
$as_echo_n "checking for be64toh... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_ENDIAN_H
|
||||
# include <endian.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ENDIAN_H
|
||||
# include <sys/endian.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
unsigned long long x = be64toh(0); printf("%u", (unsigned)x);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
$as_echo "#define HAVE_BE64TOH 1" >>confdefs.h
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing setusercontext" >&5
|
||||
$as_echo_n "checking for library containing setusercontext... " >&6; }
|
||||
if ${ac_cv_search_setusercontext+:} false; then :
|
||||
@ -21450,12 +21599,12 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
version=1.9.6
|
||||
version=1.10.1
|
||||
|
||||
date=`date +'%b %e, %Y'`
|
||||
|
||||
|
||||
ac_config_files="$ac_config_files Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service"
|
||||
ac_config_files="$ac_config_files Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service contrib/unbound_portable.service"
|
||||
|
||||
ac_config_headers="$ac_config_headers config.h"
|
||||
|
||||
@ -21969,7 +22118,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by unbound $as_me 1.9.6, which was
|
||||
This file was extended by unbound $as_me 1.10.1, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@ -22035,7 +22184,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
unbound config.status 1.9.6
|
||||
unbound config.status 1.10.1
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
@ -22461,6 +22610,7 @@ do
|
||||
"contrib/libunbound.pc") CONFIG_FILES="$CONFIG_FILES contrib/libunbound.pc" ;;
|
||||
"contrib/unbound.socket") CONFIG_FILES="$CONFIG_FILES contrib/unbound.socket" ;;
|
||||
"contrib/unbound.service") CONFIG_FILES="$CONFIG_FILES contrib/unbound.service" ;;
|
||||
"contrib/unbound_portable.service") CONFIG_FILES="$CONFIG_FILES contrib/unbound_portable.service" ;;
|
||||
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
|
||||
|
||||
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
||||
@ -23027,6 +23177,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
|
||||
cat <<_LT_EOF >> "$cfgfile"
|
||||
#! $SHELL
|
||||
# Generated automatically by $as_me ($PACKAGE) $VERSION
|
||||
# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
|
||||
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
|
||||
|
||||
# Provide generalized library-building support services.
|
||||
|
@ -10,15 +10,15 @@ sinclude(dnscrypt/dnscrypt.m4)
|
||||
|
||||
# must be numbers. ac_defun because of later processing
|
||||
m4_define([VERSION_MAJOR],[1])
|
||||
m4_define([VERSION_MINOR],[9])
|
||||
m4_define([VERSION_MICRO],[6])
|
||||
m4_define([VERSION_MINOR],[10])
|
||||
m4_define([VERSION_MICRO],[1])
|
||||
AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues, unbound)
|
||||
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
|
||||
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=6
|
||||
LIBUNBOUND_REVISION=8
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@ -92,6 +92,8 @@ LIBUNBOUND_AGE=1
|
||||
# 1.9.4 had 9:4:1
|
||||
# 1.9.5 had 9:5:1
|
||||
# 1.9.6 had 9:6:1
|
||||
# 1.10.0 had 9:7:1
|
||||
# 1.10.1 had 9:8:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@ -760,6 +762,8 @@ AC_ARG_WITH([nss], AC_HELP_STRING([--with-nss=path],
|
||||
fi
|
||||
LIBS="$LIBS -lnss3 -lnspr4"
|
||||
SSLLIB=""
|
||||
PC_CRYPTO_DEPENDENCY="nss nspr"
|
||||
AC_SUBST(PC_CRYPTO_DEPENDENCY)
|
||||
]
|
||||
)
|
||||
|
||||
@ -780,6 +784,8 @@ AC_ARG_WITH([nettle], AC_HELP_STRING([--with-nettle=path],
|
||||
fi
|
||||
LIBS="$LIBS -lhogweed -lnettle -lgmp"
|
||||
SSLLIB=""
|
||||
PC_CRYPTO_DEPENDENCY="hogweed nettle"
|
||||
AC_SUBST(PC_CRYPTO_DEPENDENCY)
|
||||
]
|
||||
)
|
||||
|
||||
@ -789,6 +795,9 @@ ACX_WITH_SSL
|
||||
ACX_LIB_SSL
|
||||
SSLLIB="-lssl"
|
||||
|
||||
PC_CRYPTO_DEPENDENCY="libcrypto libssl"
|
||||
AC_SUBST(PC_CRYPTO_DEPENDENCY)
|
||||
|
||||
# check if -lcrypt32 is needed because CAPIENG needs that. (on windows)
|
||||
BAKLIBS="$LIBS"
|
||||
LIBS="-lssl $LIBS"
|
||||
@ -880,6 +889,19 @@ fi
|
||||
fi
|
||||
AC_SUBST(SSLLIB)
|
||||
|
||||
# libbsd
|
||||
AC_ARG_WITH([libbsd], AC_HELP_STRING([--with-libbsd], [Use portable libbsd functions]), [
|
||||
AC_CHECK_HEADERS([bsd/string.h bsd/stdlib.h],,, [AC_INCLUDES_DEFAULT])
|
||||
if test "x$ac_cv_header_bsd_string_h" = xyes -a "x$ac_cv_header_bsd_stdlib_h" = xyes; then
|
||||
for func in strlcpy strlcat arc4random arc4random_uniform reallocarray; do
|
||||
AC_SEARCH_LIBS([$func], [bsd], [
|
||||
AC_DEFINE(HAVE_LIBBSD, 1, [Use portable libbsd functions])
|
||||
PC_LIBBSD_DEPENDENCY=libbsd
|
||||
AC_SUBST(PC_LIBBSD_DEPENDENCY)
|
||||
])
|
||||
done
|
||||
fi
|
||||
])
|
||||
|
||||
AC_ARG_ENABLE(sha1, AC_HELP_STRING([--disable-sha1], [Disable SHA1 RRSIG support, does not disable nsec3 support]))
|
||||
case "$enable_sha1" in
|
||||
@ -1064,9 +1086,7 @@ esac
|
||||
AC_ARG_ENABLE(dsa, AC_HELP_STRING([--disable-dsa], [Disable DSA support]))
|
||||
use_dsa="no"
|
||||
case "$enable_dsa" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
yes)
|
||||
# detect if DSA is supported, and turn it off if not.
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_FUNC(DSA_SIG_new, [
|
||||
@ -1097,6 +1117,10 @@ AC_INCLUDES_DEFAULT
|
||||
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# disable dsa by default, RFC 8624 section 3.1, validators MUST NOT
|
||||
# support DSA for DNSSEC Validation.
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(ed25519, AC_HELP_STRING([--disable-ed25519], [Disable ED25519 support]))
|
||||
@ -1467,6 +1491,35 @@ AC_INCLUDES_DEFAULT
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([for htobe64])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_ENDIAN_H
|
||||
# include <endian.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ENDIAN_H
|
||||
# include <sys/endian.h>
|
||||
#endif
|
||||
], [unsigned long long x = htobe64(0); printf("%u", (unsigned)x);])],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_HTOBE64, 1, [If we have htobe64]),
|
||||
AC_MSG_RESULT(no))
|
||||
|
||||
AC_MSG_CHECKING([for be64toh])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_ENDIAN_H
|
||||
# include <endian.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ENDIAN_H
|
||||
# include <sys/endian.h>
|
||||
#endif
|
||||
], [unsigned long long x = be64toh(0); printf("%u", (unsigned)x);])],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_BE64TOH, 1, [If we have be64toh]),
|
||||
AC_MSG_RESULT(no))
|
||||
|
||||
AC_SEARCH_LIBS([setusercontext], [util])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4])
|
||||
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
|
||||
@ -1945,6 +1998,11 @@ char *strptime(const char *s, const char *format, struct tm *tm);
|
||||
void *reallocarray(void *ptr, size_t nmemb, size_t size);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBBSD
|
||||
#include <bsd/string.h>
|
||||
#include <bsd/stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBRESSL
|
||||
# if !HAVE_DECL_STRLCPY
|
||||
size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
@ -2046,6 +2104,6 @@ dnl if this is a distro tarball, that was already done by makedist.sh
|
||||
AC_SUBST(version, [VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO])
|
||||
AC_SUBST(date, [`date +'%b %e, %Y'`])
|
||||
|
||||
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service])
|
||||
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service contrib/unbound_portable.service])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
AC_OUTPUT
|
||||
|
@ -27,10 +27,12 @@ distribution but may be helpful.
|
||||
works like the BIND feature (removes AAAA records unless AAAA-only domain).
|
||||
Useful for certain 'broken IPv6 default route' scenarios.
|
||||
Patch from Stephane Lapie for ASAHI Net.
|
||||
* unbound_smf22.tar.gz: Solaris SMF installation/removal scripts.
|
||||
* unbound_smf23.tar.gz: Solaris SMF installation/removal scripts.
|
||||
Contributed by Yuri Voinov.
|
||||
* unbound.socket and unbound.service: systemd files for unbound, install them
|
||||
in /usr/lib/systemd/system. Contributed by Sami Kerola and Pavel Odintsov.
|
||||
* unbound_portable.service.in: systemd file for use unbound as portable service,
|
||||
see comments in the file. Contributed by Frzk.
|
||||
* redirect-bogus.patch: Return configured address for bogus A and AAAA answers,
|
||||
instead of SERVFAIL. Contributed by SIDN.
|
||||
* fastrpz.patch: fastrpz support from Farsight Security.
|
||||
@ -49,3 +51,5 @@ distribution but may be helpful.
|
||||
compile. From Saksham Manchanda (Secure64). Please note that we think
|
||||
this will drop DNSKEY and DS lookups for tlds and hence break DNSSEC
|
||||
lookups for downstream clients.
|
||||
* drop2rpz: perl script that converts the Spamhaus DROP-List in RPZ-Format,
|
||||
contributed by Andreas Schulze.
|
||||
|
39
contrib/unbound/contrib/drop2rpz
Normal file
39
contrib/unbound/contrib/drop2rpz
Normal file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# usage: curl --silent https://www.spamhaus.org/drop/drop.txt | $0 > /path/to/spamhaus-drop.rpz.local
|
||||
#
|
||||
# unbound.conf:
|
||||
# rpz:
|
||||
# name: "spamhaus-drop.rpz.local."
|
||||
# zonefile: "/path/tp/spamhaus-drop.rpz.local"
|
||||
# rpz-log: yes
|
||||
# rpz-log-name: "spamhaus-drop"
|
||||
#
|
||||
|
||||
use strict;
|
||||
use vars qw{$o1 $o2 $o3 $o4 $m};
|
||||
|
||||
# trailing dots required
|
||||
my $origin = 'drop.spamhaus.org.rpz.local.';
|
||||
my $mname = 'localhost.';
|
||||
my $rname = 'root.localhost.';
|
||||
my $ns = $mname;
|
||||
|
||||
my $rpz_action = '.'; # return NXDOMAIN
|
||||
#my $rpz_action = '*.'; # return NODATA
|
||||
#my $rpz_action = 'rpz-drop.'; # drop the query
|
||||
|
||||
print "$origin SOA $mname $rname 1 43200 7200 2419200 3600\n";
|
||||
print "$origin NS $ns\n";
|
||||
while(<>) {
|
||||
if(($o1, $o2, $o3, $o4, $m) = m{(\d+)\.(\d+)\.(\d+)\.(\d+)/(\d+)}) {
|
||||
print "$m.$o4.$o3.$o2.$o1.rpz-ip.$origin CNAME $rpz_action\n";
|
||||
} else {
|
||||
print "$_";
|
||||
}
|
||||
}
|
||||
|
||||
# add a testpoint: ask for "dns.google"
|
||||
# print "32.8.8.8.8.rpz-ip.$origin CNAME $rpz_action\n";
|
||||
|
||||
exit;
|
@ -2,7 +2,7 @@ Description: based on the included patch contrib/fastrpz.patch
|
||||
Author: fastrpz@farsightsecurity.com
|
||||
---
|
||||
diff --git a/Makefile.in b/Makefile.in
|
||||
index 721c01b6..56bfb560 100644
|
||||
index a20058cc..495779cc 100644
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -23,6 +23,8 @@ CHECKLOCK_SRC=testcode/checklocks.c
|
||||
@ -14,7 +14,7 @@ index 721c01b6..56bfb560 100644
|
||||
DNSCRYPT_SRC=@DNSCRYPT_SRC@
|
||||
DNSCRYPT_OBJ=@DNSCRYPT_OBJ@
|
||||
WITH_PYTHONMODULE=@WITH_PYTHONMODULE@
|
||||
@@ -126,7 +128,7 @@ validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \
|
||||
@@ -127,7 +129,7 @@ validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \
|
||||
edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \
|
||||
edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \
|
||||
cachedb/cachedb.c cachedb/redis.c respip/respip.c $(CHECKLOCK_SRC) \
|
||||
@ -23,7 +23,7 @@ index 721c01b6..56bfb560 100644
|
||||
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
|
||||
as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
|
||||
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
|
||||
@@ -139,7 +141,7 @@ autotrust.lo val_anchor.lo \
|
||||
@@ -140,7 +142,7 @@ autotrust.lo val_anchor.lo rpz.lo \
|
||||
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
|
||||
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo redis.lo authzone.lo \
|
||||
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
|
||||
@ -32,7 +32,7 @@ index 721c01b6..56bfb560 100644
|
||||
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
|
||||
outside_network.lo
|
||||
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
|
||||
@@ -409,6 +411,11 @@ dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \
|
||||
@@ -410,6 +412,11 @@ dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/netevent.h
|
||||
|
||||
@ -45,10 +45,10 @@ index 721c01b6..56bfb560 100644
|
||||
pythonmod.lo pythonmod.o: $(srcdir)/pythonmod/pythonmod.c config.h \
|
||||
pythonmod/interface.h \
|
||||
diff --git a/config.h.in b/config.h.in
|
||||
index 8c2aa3b9..efaf6450 100644
|
||||
index 78d47fed..e33073e4 100644
|
||||
--- a/config.h.in
|
||||
+++ b/config.h.in
|
||||
@@ -1325,4 +1325,11 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
@@ -1345,4 +1345,11 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
/** the version of unbound-control that this software implements */
|
||||
#define UNBOUND_CONTROL_VERSION 1
|
||||
|
||||
@ -62,7 +62,7 @@ index 8c2aa3b9..efaf6450 100644
|
||||
+/** turn on fastrpz response policy zones */
|
||||
+#undef ENABLE_FASTRPZ
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 5276d441..9d74592e 100644
|
||||
index 2b91dd3c..e6063d17 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -6,6 +6,7 @@ sinclude(ax_pthread.m4)
|
||||
@ -73,7 +73,7 @@ index 5276d441..9d74592e 100644
|
||||
sinclude(dnscrypt/dnscrypt.m4)
|
||||
|
||||
# must be numbers. ac_defun because of later processing
|
||||
@@ -1726,6 +1727,9 @@ case "$enable_ipset" in
|
||||
@@ -1778,6 +1779,9 @@ case "$enable_ipset" in
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -84,7 +84,7 @@ index 5276d441..9d74592e 100644
|
||||
# on openBSD, the implicit rule make $< work.
|
||||
# on Solaris, it does not work ($? is changed sources, $^ lists dependencies).
|
||||
diff --git a/daemon/daemon.c b/daemon/daemon.c
|
||||
index 0b1200a2..5857c18b 100644
|
||||
index 8b0fc348..7ffb9221 100644
|
||||
--- a/daemon/daemon.c
|
||||
+++ b/daemon/daemon.c
|
||||
@@ -91,6 +91,9 @@
|
||||
@ -112,7 +112,7 @@ index 0b1200a2..5857c18b 100644
|
||||
#endif
|
||||
}
|
||||
for(i=0; i<daemon->num; i++) {
|
||||
@@ -724,6 +735,9 @@ daemon_cleanup(struct daemon* daemon)
|
||||
@@ -731,6 +742,9 @@ daemon_cleanup(struct daemon* daemon)
|
||||
#ifdef USE_DNSCRYPT
|
||||
dnsc_delete(daemon->dnscenv);
|
||||
daemon->dnscenv = NULL;
|
||||
@ -123,10 +123,10 @@ index 0b1200a2..5857c18b 100644
|
||||
daemon->cfg = NULL;
|
||||
}
|
||||
diff --git a/daemon/daemon.h b/daemon/daemon.h
|
||||
index 5749dbef..64ce230f 100644
|
||||
index 3effbafb..4d4c34da 100644
|
||||
--- a/daemon/daemon.h
|
||||
+++ b/daemon/daemon.h
|
||||
@@ -136,6 +136,11 @@ struct daemon {
|
||||
@@ -138,6 +138,11 @@ struct daemon {
|
||||
/** the dnscrypt environment */
|
||||
struct dnsc_env* dnscenv;
|
||||
#endif
|
||||
@ -139,10 +139,10 @@ index 5749dbef..64ce230f 100644
|
||||
|
||||
/**
|
||||
diff --git a/daemon/worker.c b/daemon/worker.c
|
||||
index e2ce0e87..f031c656 100644
|
||||
index eb7fdf2f..1982228d 100644
|
||||
--- a/daemon/worker.c
|
||||
+++ b/daemon/worker.c
|
||||
@@ -75,6 +75,9 @@
|
||||
@@ -76,6 +76,9 @@
|
||||
#include "libunbound/context.h"
|
||||
#include "libunbound/libworker.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
@ -152,7 +152,7 @@ index e2ce0e87..f031c656 100644
|
||||
#include "sldns/wire2str.h"
|
||||
#include "util/shm_side/shm_main.h"
|
||||
#include "dnscrypt/dnscrypt.h"
|
||||
@@ -533,8 +536,27 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
@@ -534,8 +537,27 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
/* not secure */
|
||||
secure = 0;
|
||||
break;
|
||||
@ -180,10 +180,10 @@ index e2ce0e87..f031c656 100644
|
||||
/* return this delegation from the cache */
|
||||
edns_bak = *edns;
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
@@ -699,6 +721,23 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
secure = 0;
|
||||
@@ -710,6 +732,23 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
*is_secure_answer = 0;
|
||||
}
|
||||
} else secure = 0;
|
||||
} else *is_secure_answer = 0;
|
||||
+#ifdef ENABLE_FASTRPZ
|
||||
+ if(repinfo->rpz) {
|
||||
+ /* Scan the cached answer for RPZ hits.
|
||||
@ -204,7 +204,7 @@ index e2ce0e87..f031c656 100644
|
||||
|
||||
edns_bak = *edns;
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
@@ -1410,6 +1449,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
@@ -1435,6 +1474,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
goto send_reply;
|
||||
@ -220,14 +220,14 @@ index e2ce0e87..f031c656 100644
|
||||
}
|
||||
|
||||
/* If we've found a local alias, replace the qname with the alias
|
||||
@@ -1458,12 +1506,21 @@ lookup_cache:
|
||||
@@ -1485,12 +1533,21 @@ lookup_cache:
|
||||
h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
|
||||
if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) {
|
||||
/* answer from cache - we have acquired a readlock on it */
|
||||
- if(answer_from_cache(worker, &qinfo,
|
||||
+ ret = answer_from_cache(worker, &qinfo,
|
||||
cinfo, &need_drop, &alias_rrset, &partial_rep,
|
||||
(struct reply_info*)e->data,
|
||||
cinfo, &need_drop, &is_expired_answer, &is_secure_answer,
|
||||
&alias_rrset, &partial_rep, (struct reply_info*)e->data,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
|
||||
- &edns)) {
|
||||
@ -244,7 +244,7 @@ index e2ce0e87..f031c656 100644
|
||||
/* prefetch it if the prefetch TTL expired.
|
||||
* Note that if there is more than one pass
|
||||
* its qname must be that used for cache
|
||||
@@ -1518,11 +1575,19 @@ lookup_cache:
|
||||
@@ -1547,11 +1604,19 @@ lookup_cache:
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) {
|
||||
@ -267,10 +267,10 @@ index e2ce0e87..f031c656 100644
|
||||
}
|
||||
verbose(VERB_ALGO, "answer norec from cache -- "
|
||||
diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
|
||||
index 4bdfcd56..69e70627 100644
|
||||
index 38c2d298..3b07f392 100644
|
||||
--- a/doc/unbound.conf.5.in
|
||||
+++ b/doc/unbound.conf.5.in
|
||||
@@ -1801,6 +1801,81 @@ List domain for which the AAAA records are ignored and the A record is
|
||||
@@ -1828,6 +1828,81 @@ List domain for which the AAAA records are ignored and the A record is
|
||||
used by dns64 processing instead. Can be entered multiple times, list a
|
||||
new domain for which it applies, one per line. Applies also to names
|
||||
underneath the name given.
|
||||
@ -3106,10 +3106,10 @@ index a2f1b570..e1e4a738 100644
|
||||
* Count number of time-outs. Used to prevent resolving failures when
|
||||
* the QNAME minimisation QTYPE is blocked. */
|
||||
diff --git a/services/cache/dns.c b/services/cache/dns.c
|
||||
index aa4efec7..5dd3412e 100644
|
||||
index 2a5bca4a..6de8863a 100644
|
||||
--- a/services/cache/dns.c
|
||||
+++ b/services/cache/dns.c
|
||||
@@ -945,6 +945,14 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
@@ -967,6 +967,14 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
struct regional* region, uint32_t flags)
|
||||
{
|
||||
struct reply_info* rep = NULL;
|
||||
@ -3125,10 +3125,10 @@ index aa4efec7..5dd3412e 100644
|
||||
rep = reply_info_copy(msgrep, env->alloc, NULL);
|
||||
if(!rep)
|
||||
diff --git a/services/mesh.c b/services/mesh.c
|
||||
index d4f814d5..624a9d95 100644
|
||||
index 9114ef4c..3dc518e5 100644
|
||||
--- a/services/mesh.c
|
||||
+++ b/services/mesh.c
|
||||
@@ -60,6 +60,9 @@
|
||||
@@ -61,6 +61,9 @@
|
||||
#include "sldns/wire2str.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/data/dname.h"
|
||||
@ -3138,7 +3138,7 @@ index d4f814d5..624a9d95 100644
|
||||
#include "respip/respip.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
|
||||
@@ -1076,6 +1079,13 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
@@ -1195,6 +1198,13 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
else secure = 0;
|
||||
if(!rep && rcode == LDNS_RCODE_NOERROR)
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
@ -3152,7 +3152,7 @@ index d4f814d5..624a9d95 100644
|
||||
/* send the reply */
|
||||
/* We don't reuse the encoded answer if either the previous or current
|
||||
* response has a local alias. We could compare the alias records
|
||||
@@ -1255,6 +1265,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
@@ -1415,6 +1425,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
key.s.is_valrec = valrec;
|
||||
key.s.qinfo = *qinfo;
|
||||
key.s.query_flags = qflags;
|
||||
@ -3160,7 +3160,7 @@ index d4f814d5..624a9d95 100644
|
||||
/* We are searching for a similar mesh state when we DO want to
|
||||
* aggregate the state. Thus unique is set to NULL. (default when we
|
||||
* desire aggregation).*/
|
||||
@@ -1301,6 +1312,10 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
@@ -1461,6 +1472,10 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
if(!r)
|
||||
return 0;
|
||||
r->query_reply = *rep;
|
||||
@ -3172,10 +3172,10 @@ index d4f814d5..624a9d95 100644
|
||||
if(edns->opt_list) {
|
||||
r->edns.opt_list = edns_opt_copy_region(edns->opt_list,
|
||||
diff --git a/util/config_file.c b/util/config_file.c
|
||||
index 119b2223..ce43a234 100644
|
||||
index 52ca5a18..0660248f 100644
|
||||
--- a/util/config_file.c
|
||||
+++ b/util/config_file.c
|
||||
@@ -1434,6 +1434,8 @@ config_delete(struct config_file* cfg)
|
||||
@@ -1460,6 +1460,8 @@ config_delete(struct config_file* cfg)
|
||||
free(cfg->dnstap_socket_path);
|
||||
free(cfg->dnstap_identity);
|
||||
free(cfg->dnstap_version);
|
||||
@ -3185,10 +3185,10 @@ index 119b2223..ce43a234 100644
|
||||
config_deldblstrlist(cfg->ratelimit_below_domain);
|
||||
config_delstrlist(cfg->python_script);
|
||||
diff --git a/util/config_file.h b/util/config_file.h
|
||||
index b3ef930a..56173b80 100644
|
||||
index 8739ca2a..a2dcf215 100644
|
||||
--- a/util/config_file.h
|
||||
+++ b/util/config_file.h
|
||||
@@ -494,6 +494,11 @@ struct config_file {
|
||||
@@ -499,6 +499,11 @@ struct config_file {
|
||||
/** true to disable DNSSEC lameness check in iterator */
|
||||
int disable_dnssec_lame_check;
|
||||
|
||||
@ -3201,10 +3201,10 @@ index b3ef930a..56173b80 100644
|
||||
int ip_ratelimit;
|
||||
/** number of slabs for ip_ratelimit cache */
|
||||
diff --git a/util/configlexer.lex b/util/configlexer.lex
|
||||
index a86ddf55..b56bcfb4 100644
|
||||
index deedffa5..301458a3 100644
|
||||
--- a/util/configlexer.lex
|
||||
+++ b/util/configlexer.lex
|
||||
@@ -438,6 +438,10 @@ dnstap-log-forwarder-query-messages{COLON} {
|
||||
@@ -446,6 +446,10 @@ dnstap-log-forwarder-query-messages{COLON} {
|
||||
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) }
|
||||
dnstap-log-forwarder-response-messages{COLON} {
|
||||
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) }
|
||||
@ -3216,7 +3216,7 @@ index a86ddf55..b56bcfb4 100644
|
||||
ip-ratelimit{COLON} { YDVAR(1, VAR_IP_RATELIMIT) }
|
||||
ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) }
|
||||
diff --git a/util/configparser.y b/util/configparser.y
|
||||
index 10227a2f..cdbcf7cd 100644
|
||||
index d471babe..cb6b1d63 100644
|
||||
--- a/util/configparser.y
|
||||
+++ b/util/configparser.y
|
||||
@@ -125,6 +125,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
@ -3227,7 +3227,7 @@ index 10227a2f..cdbcf7cd 100644
|
||||
%token VAR_RESPONSE_IP_TAG VAR_RESPONSE_IP VAR_RESPONSE_IP_DATA
|
||||
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
|
||||
%token VAR_DISABLE_DNSSEC_LAME_CHECK
|
||||
@@ -171,7 +172,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
@@ -173,7 +174,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
@ -3236,7 +3236,7 @@ index 10227a2f..cdbcf7cd 100644
|
||||
forwardstart contents_forward | pythonstart contents_py |
|
||||
rcstart contents_rc | dtstart contents_dt | viewstart contents_view |
|
||||
dnscstart contents_dnsc | cachedbstart contents_cachedb |
|
||||
@@ -2726,6 +2727,50 @@ dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MES
|
||||
@@ -2837,6 +2838,50 @@ dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MES
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
@ -3288,10 +3288,10 @@ index 10227a2f..cdbcf7cd 100644
|
||||
{
|
||||
OUTYY(("\nP(python:)\n"));
|
||||
diff --git a/util/data/msgencode.c b/util/data/msgencode.c
|
||||
index a51a4b9b..475dfce9 100644
|
||||
index be69f628..f10773aa 100644
|
||||
--- a/util/data/msgencode.c
|
||||
+++ b/util/data/msgencode.c
|
||||
@@ -590,6 +590,35 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
||||
@@ -592,6 +592,35 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
||||
return RETVAL_OK;
|
||||
}
|
||||
|
||||
@ -3327,7 +3327,7 @@ index a51a4b9b..475dfce9 100644
|
||||
/** store query section in wireformat buffer, return RETVAL */
|
||||
static int
|
||||
insert_query(struct query_info* qinfo, struct compress_tree_node** tree,
|
||||
@@ -777,6 +806,19 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||
@@ -779,6 +808,19 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||
}
|
||||
sldns_buffer_write_u16_at(buffer, 10, arcount);
|
||||
}
|
||||
@ -3348,10 +3348,10 @@ index a51a4b9b..475dfce9 100644
|
||||
sldns_buffer_flip(buffer);
|
||||
return 1;
|
||||
diff --git a/util/data/packed_rrset.c b/util/data/packed_rrset.c
|
||||
index 7b9d5494..e44b2ce5 100644
|
||||
index 4b0294f9..3b3838f6 100644
|
||||
--- a/util/data/packed_rrset.c
|
||||
+++ b/util/data/packed_rrset.c
|
||||
@@ -255,6 +255,10 @@ sec_status_to_string(enum sec_status s)
|
||||
@@ -256,6 +256,10 @@ sec_status_to_string(enum sec_status s)
|
||||
case sec_status_insecure: return "sec_status_insecure";
|
||||
case sec_status_secure_sentinel_fail: return "sec_status_secure_sentinel_fail";
|
||||
case sec_status_secure: return "sec_status_secure";
|
||||
@ -3363,7 +3363,7 @@ index 7b9d5494..e44b2ce5 100644
|
||||
return "unknown_sec_status_value";
|
||||
}
|
||||
diff --git a/util/data/packed_rrset.h b/util/data/packed_rrset.h
|
||||
index 3a5335dd..20113217 100644
|
||||
index 729877ba..ccd1a0c2 100644
|
||||
--- a/util/data/packed_rrset.h
|
||||
+++ b/util/data/packed_rrset.h
|
||||
@@ -193,7 +193,15 @@ enum sec_status {
|
||||
@ -3384,7 +3384,7 @@ index 3a5335dd..20113217 100644
|
||||
|
||||
/**
|
||||
diff --git a/util/netevent.c b/util/netevent.c
|
||||
index 980bb8be..d537d288 100644
|
||||
index 9fe5da2d..037e70d1 100644
|
||||
--- a/util/netevent.c
|
||||
+++ b/util/netevent.c
|
||||
@@ -57,6 +57,9 @@
|
||||
@ -3427,7 +3427,7 @@ index 980bb8be..d537d288 100644
|
||||
if(!rep.c || rep.c->fd != fd) /* commpoint closed to -1 or reused for
|
||||
another UDP port. Note rep.c cannot be reused with TCP fd. */
|
||||
break;
|
||||
@@ -3184,6 +3196,9 @@ comm_point_send_reply(struct comm_reply *repinfo)
|
||||
@@ -3192,6 +3204,9 @@ comm_point_send_reply(struct comm_reply *repinfo)
|
||||
repinfo->c->tcp_timeout_msec);
|
||||
}
|
||||
}
|
||||
@ -3437,7 +3437,7 @@ index 980bb8be..d537d288 100644
|
||||
}
|
||||
|
||||
void
|
||||
@@ -3193,6 +3208,9 @@ comm_point_drop_reply(struct comm_reply* repinfo)
|
||||
@@ -3201,6 +3216,9 @@ comm_point_drop_reply(struct comm_reply* repinfo)
|
||||
return;
|
||||
log_assert(repinfo->c);
|
||||
log_assert(repinfo->c->type != comm_tcp_accept);
|
||||
@ -3447,7 +3447,7 @@ index 980bb8be..d537d288 100644
|
||||
if(repinfo->c->type == comm_udp)
|
||||
return;
|
||||
if(repinfo->c->tcp_req_info)
|
||||
@@ -3214,6 +3232,9 @@ comm_point_start_listening(struct comm_point* c, int newfd, int msec)
|
||||
@@ -3222,6 +3240,9 @@ comm_point_start_listening(struct comm_point* c, int newfd, int msec)
|
||||
{
|
||||
verbose(VERB_ALGO, "comm point start listening %d (%d msec)",
|
||||
c->fd==-1?newfd:c->fd, msec);
|
||||
@ -3473,10 +3473,10 @@ index d80c72b3..0233292f 100644
|
||||
uint8_t client_nonce[crypto_box_HALF_NONCEBYTES];
|
||||
uint8_t nmkey[crypto_box_BEFORENMBYTES];
|
||||
diff --git a/validator/validator.c b/validator/validator.c
|
||||
index 4c560a8e..71de3760 100644
|
||||
index c3ca0a27..15251988 100644
|
||||
--- a/validator/validator.c
|
||||
+++ b/validator/validator.c
|
||||
@@ -2755,6 +2755,12 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
@@ -2761,6 +2761,12 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
default:
|
||||
/* NSEC proof did not work, try next */
|
||||
break;
|
||||
@ -3489,7 +3489,7 @@ index 4c560a8e..71de3760 100644
|
||||
}
|
||||
|
||||
sec = nsec3_prove_nods(qstate->env, ve,
|
||||
@@ -2788,6 +2794,12 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
@@ -2794,6 +2800,12 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
||||
default:
|
||||
/* NSEC3 proof did not work */
|
||||
break;
|
||||
|
@ -7,8 +7,8 @@ Name: unbound
|
||||
Description: Library with validating, recursive, and caching DNS resolver
|
||||
URL: http://www.unbound.net
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires: libcrypto libssl @PC_LIBEVENT_DEPENDENCY@
|
||||
Requires.private: @PC_PY_DEPENDENCY@
|
||||
Libs: -L${libdir} -lunbound -lssl -lcrypto
|
||||
Requires: @PC_CRYPTO_DEPENDENCY@ @PC_LIBEVENT_DEPENDENCY@
|
||||
Requires.private: @PC_PY_DEPENDENCY@ @PC_LIBBSD_DEPENDENCY@
|
||||
Libs: -L${libdir} -lunbound
|
||||
Libs.private: @SSLLIB@ @LIBS@
|
||||
Cflags: -I${includedir}
|
||||
Cflags: -I${includedir}
|
||||
|
@ -1,3 +1,44 @@
|
||||
; For further details about the directives used in this unit file, including
|
||||
; the below, please refer to systemd's official documentation, available at
|
||||
; https://www.freedesktop.org/software/systemd/man/systemd.exec.html.
|
||||
;
|
||||
;
|
||||
; - `ProtectSystem=strict` implies we mount the entire file system hierarchy
|
||||
; read-only for the processes invoked by the unit except for the API file
|
||||
; system subtrees /dev, /proc and /sys (which are protected by
|
||||
; PrivateDevices=, ProtectKernelTunables=, ProtectControlGroups=).
|
||||
;
|
||||
; - `PrivateTmp=yes` secures access to temporary files of the process, and
|
||||
; makes sharing between processes via /tmp or /var/tmp impossible.
|
||||
;
|
||||
; - `ProtectHome=yes` makes the directories /home, /root, and /run/user
|
||||
; inaccessible and empty for processes invoked by the unit.
|
||||
;
|
||||
; - `ProtectControlGroups=yes` makes the Linux Control Groups hierarchies
|
||||
; (accessible through /sys/fs/cgroup) read-only to all processes invoked by
|
||||
; the unit. It also implies `MountAPIVFS=yes`.
|
||||
;
|
||||
; - `RuntimeDirectory=unbound` creates a /run/unbound directory, owned by the
|
||||
; unit User and Group with read-write permissions (0755) as soon as the
|
||||
; unit starts. This allows unbound to store its pidfile. The directory and
|
||||
; its content are automatically removed by systemd when the unit stops.
|
||||
;
|
||||
; - `NoNewPrivileges=yes` ensures that the service process and all its
|
||||
; children can never gain new privileges through execve().
|
||||
;
|
||||
; - `RestrictSUIDSGID=yes` ensures that any attempts to set the set-user-ID
|
||||
; (SUID) or set-group-ID (SGID) bits on files or directories will be denied.
|
||||
;
|
||||
; - `RestrictRealTime=yes` ensures that any attempts to enable realtime
|
||||
; scheduling in a process invoked by the unit will be denied.
|
||||
;
|
||||
; - `RestrictNamespaces=yes` ensures that access to any kind of namespacing
|
||||
; is prohibited.
|
||||
;
|
||||
; - `LockPersonality=yes` locks down the personality system call so that the
|
||||
; kernel execution domain may not be changed from the default.
|
||||
;
|
||||
;
|
||||
[Unit]
|
||||
Description=Validating, recursive, and caching DNS resolver
|
||||
Documentation=man:unbound(8)
|
||||
@ -10,10 +51,10 @@ WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecReload=+/bin/kill -HUP $MAINPID
|
||||
ExecStart=@UNBOUND_SBIN_DIR@/unbound -d
|
||||
ExecStart=@UNBOUND_SBIN_DIR@/unbound -d -p
|
||||
NotifyAccess=main
|
||||
Type=notify
|
||||
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_RAW
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_RAW
|
||||
MemoryDenyWriteExecute=true
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=true
|
||||
@ -22,13 +63,9 @@ ProtectHome=true
|
||||
ProtectControlGroups=true
|
||||
ProtectKernelModules=true
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=/run @UNBOUND_RUN_DIR@ @UNBOUND_CHROOT_DIR@
|
||||
TemporaryFileSystem=@UNBOUND_CHROOT_DIR@/dev:ro
|
||||
TemporaryFileSystem=@UNBOUND_CHROOT_DIR@/run:ro
|
||||
BindReadOnlyPaths=-/run/systemd/notify:@UNBOUND_CHROOT_DIR@/run/systemd/notify
|
||||
BindPaths=-@UNBOUND_PIDFILE@:@UNBOUND_CHROOT_DIR@@UNBOUND_PIDFILE@
|
||||
BindReadOnlyPaths=-/dev/urandom:@UNBOUND_CHROOT_DIR@/dev/urandom
|
||||
BindPaths=-/dev/log:@UNBOUND_CHROOT_DIR@/dev/log
|
||||
RuntimeDirectory=unbound
|
||||
ConfigurationDirectory=unbound
|
||||
StateDirectory=unbound
|
||||
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
||||
RestrictRealtime=true
|
||||
SystemCallArchitectures=native
|
||||
@ -36,3 +73,12 @@ SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module mount @obsolete
|
||||
RestrictNamespaces=yes
|
||||
LockPersonality=yes
|
||||
RestrictSUIDSGID=yes
|
||||
ReadWritePaths=@UNBOUND_RUN_DIR@ @UNBOUND_CHROOT_DIR@
|
||||
|
||||
# Below rules are needed when chroot is enabled (usually it's enabled by default).
|
||||
# If chroot is disabled like chrooot: "" then they may be safely removed.
|
||||
TemporaryFileSystem=@UNBOUND_CHROOT_DIR@/dev:ro
|
||||
TemporaryFileSystem=@UNBOUND_CHROOT_DIR@/run:ro
|
||||
BindReadOnlyPaths=-/run/systemd/notify:@UNBOUND_CHROOT_DIR@/run/systemd/notify
|
||||
BindReadOnlyPaths=-/dev/urandom:@UNBOUND_CHROOT_DIR@/dev/urandom
|
||||
BindPaths=-/dev/log:@UNBOUND_CHROOT_DIR@/dev/log
|
||||
|
@ -242,6 +242,8 @@ if test "$1" = "config" ; then
|
||||
p_config "total.num.prefetch" "cache prefetch" "ABSOLUTE"
|
||||
p_config "num.query.tcp" "TCP queries" "ABSOLUTE"
|
||||
p_config "num.query.tcpout" "TCP out queries" "ABSOLUTE"
|
||||
p_config "num.query.tls" "TLS queries" "ABSOLUTE"
|
||||
p_config "num.query.tls.resume" "TLS resumes" "ABSOLUTE"
|
||||
p_config "num.query.ipv6" "IPv6 queries" "ABSOLUTE"
|
||||
p_config "unwanted.queries" "queries that failed acl" "ABSOLUTE"
|
||||
p_config "unwanted.replies" "unwanted or unsolicited replies" "ABSOLUTE"
|
||||
@ -443,7 +445,8 @@ hits)
|
||||
for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
|
||||
sed -e 's/=.*//'` total.num.queries \
|
||||
total.num.cachehits total.num.prefetch num.query.tcp \
|
||||
num.query.tcpout num.query.ipv6 unwanted.queries \
|
||||
num.query.tcpout num.query.tls num.query.tls.resume \
|
||||
num.query.ipv6 unwanted.queries \
|
||||
unwanted.replies; do
|
||||
if grep "^"$x"=" $state >/dev/null 2>&1; then
|
||||
print_value $x
|
||||
|
49
contrib/unbound/contrib/unbound_portable.service.in
Normal file
49
contrib/unbound/contrib/unbound_portable.service.in
Normal file
@ -0,0 +1,49 @@
|
||||
; This unit file is provided to run unbound as portable service.
|
||||
; https://systemd.io/PORTABLE_SERVICES/
|
||||
;
|
||||
; To use this unit file, please make sure you either compile unbound with the
|
||||
; following options:
|
||||
;
|
||||
; - --with-chroot-dir=""
|
||||
;
|
||||
; Or put the following options in your unbound configuration file:
|
||||
;
|
||||
; - chroot: ""
|
||||
;
|
||||
;
|
||||
[Unit]
|
||||
Description=Validating, recursive, and caching DNS resolver
|
||||
Documentation=man:unbound(8)
|
||||
After=network.target
|
||||
Before=network-online.target nss-lookup.target
|
||||
Wants=nss-lookup.target
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecReload=+/bin/kill -HUP $MAINPID
|
||||
ExecStart=@UNBOUND_SBIN_DIR@/unbound -d -p
|
||||
NotifyAccess=main
|
||||
Type=notify
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_RAW
|
||||
MemoryDenyWriteExecute=true
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=true
|
||||
PrivateTmp=true
|
||||
ProtectHome=true
|
||||
ProtectControlGroups=true
|
||||
ProtectKernelModules=true
|
||||
ProtectSystem=strict
|
||||
RuntimeDirectory=unbound
|
||||
ConfigurationDirectory=unbound
|
||||
StateDirectory=unbound
|
||||
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
|
||||
RestrictRealtime=true
|
||||
SystemCallArchitectures=native
|
||||
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module mount @obsolete @resources
|
||||
RestrictNamespaces=yes
|
||||
LockPersonality=yes
|
||||
RestrictSUIDSGID=yes
|
||||
BindPaths=/run/systemd/notify
|
||||
BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout
|
Binary file not shown.
BIN
contrib/unbound/contrib/unbound_smf23.tar.gz
Normal file
BIN
contrib/unbound/contrib/unbound_smf23.tar.gz
Normal file
Binary file not shown.
@ -617,7 +617,8 @@ daemon_fork(struct daemon* daemon)
|
||||
have_view_respip_cfg;
|
||||
|
||||
/* read auth zonefiles */
|
||||
if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1))
|
||||
if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1,
|
||||
&daemon->use_rpz))
|
||||
fatal_exit("auth_zones could not be setup");
|
||||
|
||||
/* setup modules */
|
||||
@ -629,6 +630,12 @@ daemon_fork(struct daemon* daemon)
|
||||
if(daemon->use_response_ip &&
|
||||
modstack_find(&daemon->mods, "respip") < 0)
|
||||
fatal_exit("response-ip options require respip module");
|
||||
/* RPZ response ip triggers don't work as expected without the respip
|
||||
* module. To avoid run-time operational surprise we reject such
|
||||
* configuration. */
|
||||
if(daemon->use_rpz &&
|
||||
modstack_find(&daemon->mods, "respip") < 0)
|
||||
fatal_exit("RPZ requires the respip module");
|
||||
|
||||
/* first create all the worker structures, so we can pass
|
||||
* them to the newly created threads.
|
||||
|
@ -132,6 +132,8 @@ struct daemon {
|
||||
struct respip_set* respip_set;
|
||||
/** some response-ip tags or actions are configured if true */
|
||||
int use_response_ip;
|
||||
/** some RPZ policies are configured */
|
||||
int use_rpz;
|
||||
#ifdef USE_DNSCRYPT
|
||||
/** the dnscrypt environment */
|
||||
struct dnsc_env* dnscenv;
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include "services/mesh.h"
|
||||
#include "services/localzone.h"
|
||||
#include "services/authzone.h"
|
||||
#include "services/rpz.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/data/dname.h"
|
||||
@ -719,8 +720,8 @@ print_stats(RES* ssl, const char* nm, struct ub_stats_info* s)
|
||||
(unsigned long)s->svr.num_queries_missed_cache)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.prefetch"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries_prefetch)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.zero_ttl"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.zero_ttl_responses)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.expired"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.ans_expired)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.recursivereplies"SQ"%lu\n", nm,
|
||||
(unsigned long)s->mesh_replies_sent)) return 0;
|
||||
#ifdef USE_DNSCRYPT
|
||||
@ -1045,6 +1046,16 @@ print_ext(RES* ssl, struct ub_stats_info* s)
|
||||
(unsigned)s->svr.infra_cache_count)) return 0;
|
||||
if(!ssl_printf(ssl, "key.cache.count"SQ"%u\n",
|
||||
(unsigned)s->svr.key_cache_count)) return 0;
|
||||
/* applied RPZ actions */
|
||||
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;
|
||||
if(!ssl_printf(ssl, "num.rpz.action.%s"SQ"%lu\n",
|
||||
rpz_action_to_string(i),
|
||||
(unsigned long)s->svr.rpz_action[i])) return 0;
|
||||
}
|
||||
#ifdef USE_DNSCRYPT
|
||||
if(!ssl_printf(ssl, "dnscrypt_shared_secret.cache.count"SQ"%u\n",
|
||||
(unsigned)s->svr.shared_secret_cache_count)) return 0;
|
||||
@ -1479,6 +1490,27 @@ do_view_data_remove(RES* ssl, struct worker* worker, char* arg)
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
/** Remove RR data from stdin from view */
|
||||
static void
|
||||
do_view_datas_remove(RES* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
struct view* v;
|
||||
v = views_find_view(worker->daemon->views,
|
||||
arg, 1 /* get write lock*/);
|
||||
if(!v) {
|
||||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
if(!v->local_zones){
|
||||
lock_rw_unlock(&v->lock);
|
||||
ssl_printf(ssl, "removed 0 datas\n");
|
||||
return;
|
||||
}
|
||||
|
||||
do_datas_remove(ssl, v->local_zones);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
/** cache lookup of nameservers */
|
||||
static void
|
||||
do_lookup(RES* ssl, struct worker* worker, char* arg)
|
||||
@ -2506,8 +2538,10 @@ do_auth_zone_transfer(RES* ssl, struct worker* worker, char* arg)
|
||||
if(!az || !auth_zones_startprobesequence(az, &worker->env, nm, nmlen,
|
||||
LDNS_RR_CLASS_IN)) {
|
||||
(void)ssl_printf(ssl, "error zone xfr task not found %s\n", arg);
|
||||
free(nm);
|
||||
return;
|
||||
}
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
@ -2989,6 +3023,8 @@ execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
|
||||
do_view_zone_add(ssl, worker, skipwhite(p+15));
|
||||
} else if(cmdcmp(p, "view_local_data_remove", 22)) {
|
||||
do_view_data_remove(ssl, worker, skipwhite(p+22));
|
||||
} else if(cmdcmp(p, "view_local_datas_remove", 23)){
|
||||
do_view_datas_remove(ssl, worker, skipwhite(p+23));
|
||||
} else if(cmdcmp(p, "view_local_data", 15)) {
|
||||
do_view_data_add(ssl, worker, skipwhite(p+15));
|
||||
} else if(cmdcmp(p, "view_local_datas", 16)) {
|
||||
|
@ -271,8 +271,10 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
s->svr.ans_secure += (long long)worker->env.mesh->ans_secure;
|
||||
s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus;
|
||||
s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata;
|
||||
for(i=0; i<16; i++)
|
||||
for(i=0; i<UB_STATS_RCODE_NUM; i++)
|
||||
s->svr.ans_rcode[i] += (long long)worker->env.mesh->ans_rcode[i];
|
||||
for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++)
|
||||
s->svr.rpz_action[i] += (long long)worker->env.mesh->rpz_action[i];
|
||||
timehist_export(worker->env.mesh->histogram, s->svr.hist,
|
||||
NUM_BUCKETS_HIST);
|
||||
/* values from outside network */
|
||||
@ -398,6 +400,7 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
|
||||
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
|
||||
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
|
||||
total->svr.ans_expired += a->svr.ans_expired;
|
||||
#ifdef USE_DNSCRYPT
|
||||
total->svr.num_query_dnscrypt_crypted += a->svr.num_query_dnscrypt_crypted;
|
||||
total->svr.num_query_dnscrypt_cert += a->svr.num_query_dnscrypt_cert;
|
||||
@ -430,7 +433,6 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
total->svr.qEDNS += a->svr.qEDNS;
|
||||
total->svr.qEDNS_DO += a->svr.qEDNS_DO;
|
||||
total->svr.ans_rcode_nodata += a->svr.ans_rcode_nodata;
|
||||
total->svr.zero_ttl_responses += a->svr.zero_ttl_responses;
|
||||
total->svr.ans_secure += a->svr.ans_secure;
|
||||
total->svr.ans_bogus += a->svr.ans_bogus;
|
||||
total->svr.unwanted_replies += a->svr.unwanted_replies;
|
||||
@ -446,6 +448,8 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
total->svr.ans_rcode[i] += a->svr.ans_rcode[i];
|
||||
for(i=0; i<NUM_BUCKETS_HIST; i++)
|
||||
total->svr.hist[i] += a->svr.hist[i];
|
||||
for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++)
|
||||
total->svr.rpz_action[i] += a->svr.rpz_action[i];
|
||||
}
|
||||
|
||||
total->mesh_num_states += a->mesh_num_states;
|
||||
|
@ -259,21 +259,10 @@ checkrlimits(struct config_file* cfg)
|
||||
#endif /* S_SPLINT_S */
|
||||
}
|
||||
|
||||
/** set default logfile identity based on value from argv[0] at startup **/
|
||||
static void
|
||||
log_ident_set_fromdefault(struct config_file* cfg,
|
||||
const char *log_default_identity)
|
||||
{
|
||||
if(cfg->log_identity == NULL || cfg->log_identity[0] == 0)
|
||||
log_ident_set(log_default_identity);
|
||||
else
|
||||
log_ident_set(cfg->log_identity);
|
||||
}
|
||||
|
||||
/** set verbosity, check rlimits, cache settings */
|
||||
static void
|
||||
apply_settings(struct daemon* daemon, struct config_file* cfg,
|
||||
int cmdline_verbose, int debug_mode, const char* log_default_identity)
|
||||
apply_settings(struct daemon* daemon, struct config_file* cfg,
|
||||
int cmdline_verbose, int debug_mode)
|
||||
{
|
||||
/* apply if they have changed */
|
||||
verbosity = cmdline_verbose + cfg->verbosity;
|
||||
@ -289,7 +278,7 @@ apply_settings(struct daemon* daemon, struct config_file* cfg,
|
||||
log_warn("use-systemd and do-daemonize should not be enabled at the same time");
|
||||
}
|
||||
|
||||
log_ident_set_fromdefault(cfg, log_default_identity);
|
||||
log_ident_set_or_default(cfg->log_identity);
|
||||
}
|
||||
|
||||
#ifdef HAVE_KILL
|
||||
@ -639,11 +628,10 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
* @param cmdline_verbose: verbosity resulting from commandline -v.
|
||||
* These increase verbosity as specified in the config file.
|
||||
* @param debug_mode: if set, do not daemonize.
|
||||
* @param log_default_identity: Default identity to report in logs
|
||||
* @param need_pidfile: if false, no pidfile is checked or created.
|
||||
*/
|
||||
static void
|
||||
run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* log_default_identity, int need_pidfile)
|
||||
run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pidfile)
|
||||
{
|
||||
struct config_file* cfg = NULL;
|
||||
struct daemon* daemon = NULL;
|
||||
@ -667,7 +655,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char*
|
||||
"or unbound-checkconf", cfgfile);
|
||||
log_warn("Continuing with default config settings");
|
||||
}
|
||||
apply_settings(daemon, cfg, cmdline_verbose, debug_mode, log_default_identity);
|
||||
apply_settings(daemon, cfg, cmdline_verbose, debug_mode);
|
||||
if(!done_setup)
|
||||
config_lookup_uid(cfg);
|
||||
|
||||
@ -733,6 +721,7 @@ main(int argc, char* argv[])
|
||||
|
||||
log_init(NULL, 0, NULL);
|
||||
log_ident_default = strrchr(argv[0],'/')?strrchr(argv[0],'/')+1:argv[0];
|
||||
log_ident_set_default(log_ident_default);
|
||||
log_ident_set(log_ident_default);
|
||||
/* parse the options */
|
||||
while( (c=getopt(argc, argv, "c:dhpvw:V")) != -1) {
|
||||
@ -783,7 +772,7 @@ main(int argc, char* argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
run_daemon(cfgfile, cmdline_verbose, debug_mode, log_ident_default, need_pidfile);
|
||||
run_daemon(cfgfile, cmdline_verbose, debug_mode, need_pidfile);
|
||||
log_init(NULL, 0, NULL); /* close logfile */
|
||||
#ifndef unbound_testbound
|
||||
if(log_get_lock()) {
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include "services/authzone.h"
|
||||
#include "services/mesh.h"
|
||||
#include "services/localzone.h"
|
||||
#include "services/rpz.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/data/msgencode.h"
|
||||
#include "util/data/dname.h"
|
||||
@ -572,9 +573,10 @@ static int
|
||||
apply_respip_action(struct worker* worker, const struct query_info* qinfo,
|
||||
struct respip_client_info* cinfo, struct reply_info* rep,
|
||||
struct comm_reply* repinfo, struct ub_packed_rrset_key** alias_rrset,
|
||||
struct reply_info** encode_repp)
|
||||
struct reply_info** encode_repp, struct auth_zones* az)
|
||||
{
|
||||
struct respip_action_info actinfo = {respip_none, NULL};
|
||||
struct respip_action_info actinfo = {0};
|
||||
actinfo.action = respip_none;
|
||||
|
||||
if(qinfo->qtype != LDNS_RR_TYPE_A &&
|
||||
qinfo->qtype != LDNS_RR_TYPE_AAAA &&
|
||||
@ -582,7 +584,7 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
|
||||
return 1;
|
||||
|
||||
if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo,
|
||||
alias_rrset, 0, worker->scratchpad))
|
||||
alias_rrset, 0, worker->scratchpad, az))
|
||||
return 0;
|
||||
|
||||
/* xxx_deny actions mean dropping the reply, unless the original reply
|
||||
@ -595,9 +597,19 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
|
||||
/* If address info is returned, it means the action should be an
|
||||
* 'inform' variant and the information should be logged. */
|
||||
if(actinfo.addrinfo) {
|
||||
respip_inform_print(actinfo.addrinfo, qinfo->qname,
|
||||
respip_inform_print(&actinfo, qinfo->qname,
|
||||
qinfo->qtype, qinfo->qclass, qinfo->local_alias,
|
||||
repinfo);
|
||||
|
||||
if(worker->stats.extended && actinfo.rpz_used) {
|
||||
if(actinfo.rpz_disabled)
|
||||
worker->stats.rpz_action[RPZ_DISABLED_ACTION]++;
|
||||
if(actinfo.rpz_cname_override)
|
||||
worker->stats.rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
|
||||
else
|
||||
worker->stats.rpz_action[
|
||||
respip_action_to_rpz_action(actinfo.action)]++;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -613,10 +625,10 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
|
||||
* be completely dropped, '*need_drop' will be set to 1. */
|
||||
static int
|
||||
answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
struct respip_client_info* cinfo, int* need_drop,
|
||||
struct ub_packed_rrset_key** alias_rrset,
|
||||
struct respip_client_info* cinfo, int* need_drop, int* is_expired_answer,
|
||||
int* is_secure_answer, struct ub_packed_rrset_key** alias_rrset,
|
||||
struct reply_info** partial_repp,
|
||||
struct reply_info* rep, uint16_t id, uint16_t flags,
|
||||
struct reply_info* rep, uint16_t id, uint16_t flags,
|
||||
struct comm_reply* repinfo, struct edns_data* edns)
|
||||
{
|
||||
struct edns_data edns_bak;
|
||||
@ -624,38 +636,37 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
uint16_t udpsize = edns->udp_size;
|
||||
struct reply_info* encode_rep = rep;
|
||||
struct reply_info* partial_rep = *partial_repp;
|
||||
int secure;
|
||||
int must_validate = (!(flags&BIT_CD) || worker->env.cfg->ignore_cd)
|
||||
&& worker->env.need_to_validate;
|
||||
*partial_repp = NULL; /* avoid accidental further pass */
|
||||
if(worker->env.cfg->serve_expired) {
|
||||
if(worker->env.cfg->serve_expired_ttl &&
|
||||
rep->serve_expired_ttl < timenow)
|
||||
return 0;
|
||||
if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
|
||||
return 0;
|
||||
/* below, rrsets with ttl before timenow become TTL 0 in
|
||||
* the response */
|
||||
/* This response was served with zero TTL */
|
||||
if (timenow >= rep->ttl) {
|
||||
worker->stats.zero_ttl_responses++;
|
||||
}
|
||||
} else {
|
||||
/* see if it is possible */
|
||||
if(rep->ttl < timenow) {
|
||||
*partial_repp = NULL; /* avoid accidental further pass */
|
||||
|
||||
/* Check TTL */
|
||||
if(rep->ttl < timenow) {
|
||||
/* Check if we need to serve expired now */
|
||||
if(worker->env.cfg->serve_expired &&
|
||||
!worker->env.cfg->serve_expired_client_timeout) {
|
||||
if(worker->env.cfg->serve_expired_ttl &&
|
||||
rep->serve_expired_ttl < timenow)
|
||||
return 0;
|
||||
if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
|
||||
return 0;
|
||||
*is_expired_answer = 1;
|
||||
} else {
|
||||
/* the rrsets may have been updated in the meantime.
|
||||
* we will refetch the message format from the
|
||||
* authoritative server
|
||||
* authoritative server
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if(!rrset_array_lock(rep->ref, rep->rrset_count, timenow))
|
||||
return 0;
|
||||
/* locked and ids and ttls are OK. */
|
||||
}
|
||||
/* locked and ids and ttls are OK. */
|
||||
|
||||
/* check CNAME chain (if any) */
|
||||
if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type ==
|
||||
htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type ==
|
||||
if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type ==
|
||||
htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type ==
|
||||
htons(LDNS_RR_TYPE_DNAME))) {
|
||||
if(!reply_check_cname_chain(qinfo, rep)) {
|
||||
/* cname chain invalid, redo iterator steps */
|
||||
@ -674,31 +685,31 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep,
|
||||
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
|
||||
goto bail_out;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, id, flags, edns);
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache,
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache,
|
||||
worker->scratchpad, rep->ref, rep->rrset_count);
|
||||
if(worker->stats.extended) {
|
||||
worker->stats.ans_bogus ++;
|
||||
worker->stats.ans_rcode[LDNS_RCODE_SERVFAIL] ++;
|
||||
}
|
||||
return 1;
|
||||
} else if( rep->security == sec_status_unchecked && must_validate) {
|
||||
} else if(rep->security == sec_status_unchecked && must_validate) {
|
||||
verbose(VERB_ALGO, "Cache reply: unchecked entry needs "
|
||||
"validation");
|
||||
goto bail_out; /* need to validate cache entry first */
|
||||
} else if(rep->security == sec_status_secure) {
|
||||
if(reply_all_rrsets_secure(rep))
|
||||
secure = 1;
|
||||
else {
|
||||
if(reply_all_rrsets_secure(rep)) {
|
||||
*is_secure_answer = 1;
|
||||
} else {
|
||||
if(must_validate) {
|
||||
verbose(VERB_ALGO, "Cache reply: secure entry"
|
||||
" changed status");
|
||||
goto bail_out; /* rrset changed, re-verify */
|
||||
}
|
||||
secure = 0;
|
||||
*is_secure_answer = 0;
|
||||
}
|
||||
} else secure = 0;
|
||||
} else *is_secure_answer = 0;
|
||||
|
||||
edns_bak = *edns;
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
@ -709,17 +720,21 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
(int)(flags&LDNS_RCODE_MASK), edns, repinfo, worker->scratchpad))
|
||||
goto bail_out;
|
||||
*alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */
|
||||
if(worker->daemon->use_response_ip && !partial_rep &&
|
||||
!apply_respip_action(worker, qinfo, cinfo, rep, repinfo, alias_rrset,
|
||||
&encode_rep)) {
|
||||
if((worker->daemon->use_response_ip || worker->daemon->use_rpz) &&
|
||||
!partial_rep && !apply_respip_action(worker, qinfo, cinfo, rep,
|
||||
repinfo, alias_rrset,
|
||||
&encode_rep, worker->env.auth_zones)) {
|
||||
goto bail_out;
|
||||
} else if(partial_rep &&
|
||||
!respip_merge_cname(partial_rep, qinfo, rep, cinfo,
|
||||
must_validate, &encode_rep, worker->scratchpad)) {
|
||||
must_validate, &encode_rep, worker->scratchpad,
|
||||
worker->env.auth_zones)) {
|
||||
goto bail_out;
|
||||
}
|
||||
if(encode_rep != rep)
|
||||
secure = 0; /* if rewritten, it can't be considered "secure" */
|
||||
if(encode_rep != rep) {
|
||||
/* if rewritten, it can't be considered "secure" */
|
||||
*is_secure_answer = 0;
|
||||
}
|
||||
if(!encode_rep || *alias_rrset) {
|
||||
if(!encode_rep)
|
||||
*need_drop = 1;
|
||||
@ -736,7 +751,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
repinfo->c, worker->scratchpad) ||
|
||||
!reply_info_answer_encode(qinfo, encode_rep, id, flags,
|
||||
repinfo->c->buffer, timenow, 1, worker->scratchpad,
|
||||
udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
|
||||
udpsize, edns, (int)(edns->bits & EDNS_DO), *is_secure_answer)) {
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
|
||||
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
|
||||
edns->opt_list = NULL;
|
||||
@ -747,10 +762,6 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
* is bad while holding locks. */
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache, worker->scratchpad,
|
||||
rep->ref, rep->rrset_count);
|
||||
if(worker->stats.extended) {
|
||||
if(secure) worker->stats.ans_secure++;
|
||||
server_stats_insrcode(&worker->stats, repinfo->c->buffer);
|
||||
}
|
||||
/* go and return this buffer to the client */
|
||||
return 1;
|
||||
|
||||
@ -1085,6 +1096,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
struct acl_addr* acladdr;
|
||||
int rc = 0;
|
||||
int need_drop = 0;
|
||||
int is_expired_answer = 0;
|
||||
int is_secure_answer = 0;
|
||||
/* We might have to chase a CNAME chain internally, in which case
|
||||
* we'll have up to two replies and combine them to build a complete
|
||||
* answer. These variables control this case. */
|
||||
@ -1364,6 +1377,18 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
goto send_reply;
|
||||
}
|
||||
if(worker->env.auth_zones &&
|
||||
rpz_apply_qname_trigger(worker->env.auth_zones,
|
||||
&worker->env, &qinfo, &edns, c->buffer, worker->scratchpad,
|
||||
repinfo, acladdr->taglist, acladdr->taglen, &worker->stats)) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
if(sldns_buffer_limit(c->buffer) == 0) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
goto send_reply;
|
||||
}
|
||||
if(worker->env.auth_zones &&
|
||||
auth_zones_answer(worker->env.auth_zones, &worker->env,
|
||||
&qinfo, &edns, repinfo, c->buffer, worker->scratchpad)) {
|
||||
@ -1434,7 +1459,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
/* If we may apply IP-based actions to the answer, build the client
|
||||
* information. As this can be expensive, skip it if there is
|
||||
* absolutely no possibility of it. */
|
||||
if(worker->daemon->use_response_ip &&
|
||||
if((worker->daemon->use_response_ip || worker->daemon->use_rpz) &&
|
||||
(qinfo.qtype == LDNS_RR_TYPE_A ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_AAAA ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_ANY)) {
|
||||
@ -1455,12 +1480,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
* each pass. We should still pass the original qinfo to
|
||||
* answer_from_cache(), however, since it's used to build the reply. */
|
||||
if(!edns_bypass_cache_stage(edns.opt_list, &worker->env)) {
|
||||
is_expired_answer = 0;
|
||||
is_secure_answer = 0;
|
||||
h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
|
||||
if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) {
|
||||
/* answer from cache - we have acquired a readlock on it */
|
||||
if(answer_from_cache(worker, &qinfo,
|
||||
cinfo, &need_drop, &alias_rrset, &partial_rep,
|
||||
(struct reply_info*)e->data,
|
||||
cinfo, &need_drop, &is_expired_answer, &is_secure_answer,
|
||||
&alias_rrset, &partial_rep, (struct reply_info*)e->data,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
|
||||
&edns)) {
|
||||
@ -1468,9 +1495,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
* Note that if there is more than one pass
|
||||
* its qname must be that used for cache
|
||||
* lookup. */
|
||||
if((worker->env.cfg->prefetch || worker->env.cfg->serve_expired)
|
||||
&& *worker->env.now >=
|
||||
((struct reply_info*)e->data)->prefetch_ttl) {
|
||||
if((worker->env.cfg->prefetch && *worker->env.now >=
|
||||
((struct reply_info*)e->data)->prefetch_ttl) ||
|
||||
(worker->env.cfg->serve_expired &&
|
||||
*worker->env.now >= ((struct reply_info*)e->data)->ttl)) {
|
||||
|
||||
time_t leeway = ((struct reply_info*)e->
|
||||
data)->ttl - *worker->env.now;
|
||||
if(((struct reply_info*)e->data)->ttl
|
||||
@ -1555,6 +1584,13 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
if(is_expired_answer) {
|
||||
worker->stats.ans_expired++;
|
||||
}
|
||||
if(worker->stats.extended) {
|
||||
if(is_secure_answer) worker->stats.ans_secure++;
|
||||
server_stats_insrcode(&worker->stats, repinfo->c->buffer);
|
||||
}
|
||||
#ifdef USE_DNSTAP
|
||||
if(worker->dtenv.log_client_response_messages)
|
||||
dt_msg_send_client_response(&worker->dtenv, &repinfo->addr,
|
||||
@ -1830,6 +1866,10 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
return 0;
|
||||
}
|
||||
worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env);
|
||||
/* Pass on daemon variables that we would need in the mesh area */
|
||||
worker->env.mesh->use_response_ip = worker->daemon->use_response_ip;
|
||||
worker->env.mesh->use_rpz = worker->daemon->use_rpz;
|
||||
|
||||
worker->env.detach_subs = &mesh_detach_subs;
|
||||
worker->env.attach_sub = &mesh_attach_sub;
|
||||
worker->env.add_sub = &mesh_add_sub;
|
||||
|
@ -1,6 +1,175 @@
|
||||
20 February 2020: Wouter
|
||||
- Updated contrib/unbound_smf23.tar.gz with Solaris SMF service for
|
||||
Unbound from Yuri Voinov.
|
||||
|
||||
17 February 2020: Ralph
|
||||
- Add respip to supported module-config options in unbound-checkconf.
|
||||
|
||||
17 February 2020: George
|
||||
- Remove unused variable.
|
||||
|
||||
17 February 2020: Wouter
|
||||
- contrib/drop2rpz: perl script that converts the Spamhaus DROP-List
|
||||
in RPZ-Format, contributed by Andreas Schulze.
|
||||
|
||||
14 February 2020: Wouter
|
||||
- Fix spelling in unbound.conf.5.in.
|
||||
- Stop unbound-checkconf from insisting that auth-zone and rpz
|
||||
zonefiles have to exist. They can not exist, and download later.
|
||||
|
||||
13 February 2020: Wouter
|
||||
- tag for 1.10.0rc1 release.
|
||||
|
||||
12 February 2020: Wouter
|
||||
- Fix with libnettle make test with dsa disabled.
|
||||
- Fix contrib/fastrpz.patch to apply cleanly. Fix for serve-stale
|
||||
fixes, but it does not compile, conflicts with new rpz code.
|
||||
- Fix to clean memory leak of respip_addr.lock when ip_tree deleted.
|
||||
- Fix compile warning when threads disabled.
|
||||
- updated version number to 1.10.0.
|
||||
|
||||
10 February 2020: George
|
||||
- Document 'ub_result.was_ratelimited' in libunbound.
|
||||
- Fix use after free on log-identity after a reload; Fixes #163.
|
||||
|
||||
6 February 2020: George
|
||||
- Fix num_reply_states and num_detached_states counting with
|
||||
serve_expired_callback.
|
||||
- Cleaner code in mesh_serve_expired_lookup.
|
||||
- Document in unbound.conf manpage that configuration clauses can be
|
||||
repeated in the configuration file.
|
||||
|
||||
6 February 2020: Wouter
|
||||
- Fix num_reply_addr counting in mesh and tcp drop due to size
|
||||
after serve_stale commit.
|
||||
- Fix to create and destroy rpz_lock in auth_zones structure.
|
||||
- Fix to lock zone before adding rpz qname trigger.
|
||||
- Fix to lock and release once in mesh_serve_expired_lookup.
|
||||
- Fix to put braces around empty if body when threading is disabled.
|
||||
|
||||
5 February 2020: George
|
||||
- Added serve-stale functionality as described in
|
||||
draft-ietf-dnsop-serve-stale-10. `serve-expired-*` options can be used
|
||||
to configure the behavior.
|
||||
- Updated cachedb to honor `serve-expired-ttl`; Fixes #107.
|
||||
- Renamed statistic `num.zero_ttl` to `num.expired` as expired replies
|
||||
come with a configurable TTL value (`serve-expired-reply-ttl`).
|
||||
- Fixed stats when replying with cached, cname-aliased records.
|
||||
- Added missing default values for redis cachedb backend.
|
||||
|
||||
3 February 2020: Ralph
|
||||
- Add assertion to please static analyzer
|
||||
|
||||
31 January 2020: Wouter
|
||||
- Fix fclose on error in TLS session ticket code.
|
||||
|
||||
30 January 2020: Ralph
|
||||
- Fix memory leak in error condition remote.c
|
||||
- Fix double free in error condition view.c
|
||||
- Fix memory leak in do_auth_zone_transfer on success
|
||||
- Merge RPZ support into master. Only QNAME and Response IP triggers are
|
||||
supported.
|
||||
- Stop working on socket when socket() call returns an error.
|
||||
- Check malloc return values in TLS session ticket code
|
||||
|
||||
30 January 2020: Wouter
|
||||
- Fix subnet tests for disabled DSA algorithm by default.
|
||||
- Update contrib/fastrpz.patch for clean diff with current code.
|
||||
- Merge PR#151: Fixes for systemd units, by Maryse47, Edmonds
|
||||
and Frzk. Updates the unbound.service systemd file and adds
|
||||
a portable systemd service file.
|
||||
- updated .gitignore for added contrib file.
|
||||
- Add build rule for ipset to Makefile
|
||||
- Add getentropy_freebsd.o to Makefile dependencies.
|
||||
|
||||
29 January 2020: Ralph
|
||||
- Merge PR#156 from Alexander Berkes; Added unbound-control
|
||||
view_local_datas_remove command.
|
||||
|
||||
29 January 2020: Wouter
|
||||
- Fix #157: undefined reference to `htobe64'.
|
||||
|
||||
28 January 2020: Ralph
|
||||
- Merge PR#147; change rfc reference for reserved top level dns names.
|
||||
|
||||
28 January 2020: Wouter
|
||||
- iana portlist updated.
|
||||
- Fix to silence the tls handshake errors for broken pipe and reset
|
||||
by peer, unless verbosity is set to 2 or higher.
|
||||
|
||||
27 January 2020: Ralph
|
||||
- Merge PR#154; Allow use of libbsd functions with configure option
|
||||
--with-libbsd. By Robert Edmonds and Steven Chamberlain.
|
||||
- Merge PR#148; Add some TLS stats to unbound_munin_. By Fredrik Pettai.
|
||||
|
||||
27 January 2020: Wouter
|
||||
- Merge PR#155 from Robert Edmonds: contrib/libunbound.pc.in: Fixes
|
||||
to Libs/Requires for crypto library dependencies.
|
||||
- Fix #153: Disable validation for DSA algorithms. RFC 8624
|
||||
compliance.
|
||||
|
||||
23 January 2020: Wouter
|
||||
- Merge PR#150 from Frzk: Systemd unit without chroot. It add
|
||||
contrib/unbound_nochroot.service.in, a systemd file for use with
|
||||
chroot: "", see comments in the file, it uses systemd protections
|
||||
instead.
|
||||
|
||||
14 January 2020: Wouter
|
||||
- Removed the dnscrypt_queries and dnscrypt_queries_chacha tests,
|
||||
because dnscrypt-proxy (2.0.36) does not support the test setup
|
||||
any more, and also the config file format does not seem to have
|
||||
the appropriate keys to recreate that setup.
|
||||
- Fix crash after reload where a stats lookup could reference old key
|
||||
cache and neg cache structures.
|
||||
- Fix for memory leak when edns subnet config options are read when
|
||||
compiled without edns subnet support.
|
||||
- Fix auth zone support for NSEC3 records without salt.
|
||||
|
||||
10 January 2020: Wouter
|
||||
- Fix the relationship between serve-expired and prefetch options,
|
||||
patch from Saksham Manchanda from Secure64.
|
||||
- Fix unreachable code in ssl set options code.
|
||||
|
||||
8 January 2020: Ralph
|
||||
- Fix #138: stop binding pidfile inside chroot dir in systemd service
|
||||
file.
|
||||
|
||||
8 January 2020: Wouter
|
||||
- Fix 'make test' to work for --disable-sha1 configure option.
|
||||
- Fix out-of-bounds null-byte write in sldns_bget_token_par while
|
||||
parsing type WKS, reported by Luis Merino from X41 D-Sec.
|
||||
- Updated sldns_bget_token_par fix for also space for the zero
|
||||
delimiter after the character. And update for more spare space.
|
||||
|
||||
6 January 2020: George
|
||||
- Downgrade compat/getentropy_solaris.c to version 1.4 from OpenBSD.
|
||||
The dl_iterate_phdr() function introduced in newer versions raises
|
||||
compilation errors on solaris 10.
|
||||
- Changes to compat/getentropy_solaris.c for,
|
||||
ifdef stdint.h inclusion for older systems.
|
||||
ifdef sha2.h inclusion for older systems.
|
||||
|
||||
6 January 2020: Wouter
|
||||
- Merge #135 from Florian Obser: Use passed in neg and key cache
|
||||
if non-NULL.
|
||||
- Fix #140: Document slave not downloading new zonefile upon update.
|
||||
|
||||
16 December 2019: George
|
||||
- Update mailing list URL.
|
||||
|
||||
12 December 2019: Ralph
|
||||
- Master is 1.9.7 in development.
|
||||
- Fix typo to let serve-expired-ttl work with ub_ctx_set_option(), by
|
||||
Florian Obser
|
||||
|
||||
10 December 2019: Wouter
|
||||
- Fix to make auth zone IXFR to fallback to AXFR if a single
|
||||
response RR is received over TCP with the SOA in it.
|
||||
|
||||
6 December 2019: Wouter
|
||||
- Fix ipsecmod compile.
|
||||
- Fix Makefile.in for ipset module compile, from Adi Prasaja.
|
||||
- release-1.9.6 tag, which became the 1.9.6 release
|
||||
|
||||
5 December 2019: Wouter
|
||||
- unbound-fuzzers.tar.bz2: three programs for fuzzing, that are 1:1
|
||||
|
@ -1,4 +1,4 @@
|
||||
README for Unbound 1.9.6
|
||||
README for Unbound 1.10.1
|
||||
Copyright 2007 NLnet Labs
|
||||
http://unbound.net
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Example configuration file.
|
||||
#
|
||||
# See unbound.conf(5) man page, version 1.9.6.
|
||||
# See unbound.conf(5) man page, version 1.10.1.
|
||||
#
|
||||
# this is a comment.
|
||||
|
||||
@ -558,8 +558,8 @@ server:
|
||||
# that set CD but cannot validate themselves.
|
||||
# ignore-cd-flag: no
|
||||
|
||||
# Serve expired responses from cache, with TTL 0 in the response,
|
||||
# and then attempt to fetch the data afresh.
|
||||
# Serve expired responses from cache, with serve-expired-reply-ttl in
|
||||
# the response, and then attempt to fetch the data afresh.
|
||||
# serve-expired: no
|
||||
#
|
||||
# Limit serving of expired responses to configured seconds after
|
||||
@ -571,6 +571,16 @@ server:
|
||||
# that the expired records will be served as long as there are queries
|
||||
# for it.
|
||||
# serve-expired-ttl-reset: no
|
||||
#
|
||||
# TTL value to use when replying with expired data.
|
||||
# serve-expired-reply-ttl: 30
|
||||
#
|
||||
# Time in milliseconds before replying to the client with expired data.
|
||||
# This essentially enables the serve-stale behavior as specified in
|
||||
# draft-ietf-dnsop-serve-stale-10 that first tries to resolve before
|
||||
# immediately responding with expired data. 0 disables this behavior.
|
||||
# A recommended value is 1800.
|
||||
# serve-expired-client-timeout: 0
|
||||
|
||||
# Have the validator log failed validations for your diagnosis.
|
||||
# 0: off. 1: A line per failed user query. 2: With reason and bad IP.
|
||||
@ -1006,3 +1016,20 @@ remote-control:
|
||||
# name-v6: "list-v6"
|
||||
#
|
||||
|
||||
# Response Policy Zones
|
||||
# RPZ policies. Applied in order of configuration. QNAME and Response IP
|
||||
# Address trigger are the only supported triggers. Supported actions are:
|
||||
# NXDOMAIN, NODATA, PASSTHRU, DROP and Local Data. Policies can be loaded from
|
||||
# file, using zone transfer, or using HTTP. The respip module needs to be added
|
||||
# to the module-config, e.g.: module-config: "respip validator iterator".
|
||||
# rpz:
|
||||
# name: "rpz.example.com"
|
||||
# zonefile: "rpz.example.com"
|
||||
# master: 192.0.2.0
|
||||
# allow-notify: 192.0.2.0/32
|
||||
# url: http://www.example.com/rpz.example.org.zone
|
||||
# rpz-action-override: cname
|
||||
# rpz-cname-override: www.example.org
|
||||
# rpz-log: yes
|
||||
# rpz-log-name: "example policy"
|
||||
# tags: "example"
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "libunbound" "3" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
|
||||
.TH "libunbound" "3" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
|
||||
.\"
|
||||
.\" libunbound.3 -- unbound library functions manual
|
||||
.\"
|
||||
@ -44,7 +44,7 @@
|
||||
.B ub_ctx_zone_remove,
|
||||
.B ub_ctx_data_add,
|
||||
.B ub_ctx_data_remove
|
||||
\- Unbound DNS validating resolver 1.9.6 functions.
|
||||
\- Unbound DNS validating resolver 1.10.1 functions.
|
||||
.SH "SYNOPSIS"
|
||||
.B #include <unbound.h>
|
||||
.LP
|
||||
@ -396,12 +396,13 @@ The result of the DNS resolution and validation is returned as
|
||||
char* canonname; /* canonical name of result */
|
||||
int rcode; /* additional error code in case of no data */
|
||||
void* answer_packet; /* full network format answer packet */
|
||||
int answer_len; /* length of packet in octets */
|
||||
int answer_len; /* length of packet in octets */
|
||||
int havedata; /* true if there is data */
|
||||
int nxdomain; /* true if nodata because name does not exist */
|
||||
int secure; /* true if result is secure */
|
||||
int bogus; /* true if a security failure happened */
|
||||
int secure; /* true if result is secure */
|
||||
int bogus; /* true if a security failure happened */
|
||||
char* why_bogus; /* string with error if bogus */
|
||||
int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */
|
||||
int ttl; /* number of seconds the result is valid */
|
||||
};
|
||||
.fi
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "unbound-anchor" "8" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
|
||||
.TH "unbound-anchor" "8" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
|
||||
.\"
|
||||
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
|
||||
.\"
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "unbound-checkconf" "8" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
|
||||
.TH "unbound-checkconf" "8" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
|
||||
.\"
|
||||
.\" unbound-checkconf.8 -- unbound configuration checker manual
|
||||
.\"
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "unbound-control" "8" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
|
||||
.TH "unbound-control" "8" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
|
||||
.\"
|
||||
.\" unbound-control.8 -- unbound remote control manual
|
||||
.\"
|
||||
@ -323,6 +323,9 @@ serial check). And then the zone is transferred for a newer zone version.
|
||||
.B view_local_data_remove \fIview\fR \fIname
|
||||
\fIlocal_data_remove\fR for given view.
|
||||
.TP
|
||||
.B view_local_datas_remove \fIview\fR
|
||||
Remove a list of \fIlocal_data\fR for given view from stdin. Like local_datas_remove.
|
||||
.TP
|
||||
.B view_local_datas \fIview\fR
|
||||
Add a list of \fIlocal_data\fR for given view from stdin. Like local_datas.
|
||||
.SH "EXIT CODE"
|
||||
@ -379,8 +382,8 @@ and resulted in recursive processing, taking a slot in the requestlist.
|
||||
Not part of the recursivereplies (or the histogram thereof) or cachemiss,
|
||||
as a cache response was sent.
|
||||
.TP
|
||||
.I threadX.num.zero_ttl
|
||||
number of replies with ttl zero, because they served an expired cache entry.
|
||||
.I threadX.num.expired
|
||||
number of replies that served an expired cache entry.
|
||||
.TP
|
||||
.I threadX.num.recursivereplies
|
||||
The number of replies sent to queries that needed recursive processing. Could be smaller than threadX.num.cachemiss if due to timeouts no replies were sent for some queries.
|
||||
@ -443,7 +446,7 @@ summed over threads.
|
||||
.I total.num.prefetch
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.zero_ttl
|
||||
.I total.num.expired
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.recursivereplies
|
||||
@ -660,6 +663,11 @@ Number of queries that got an answer that contained EDNS client subnet data.
|
||||
Number of queries answered from the edns client subnet cache. These are
|
||||
counted as cachemiss by the main counters, but hit the client subnet
|
||||
specific cache, after getting processed by the edns client subnet module.
|
||||
.TP
|
||||
.I num.rpz.action.<rpz_action>
|
||||
Number of queries answered using configured RPZ policy, per RPZ action type.
|
||||
Possible actions are: nxdomain, nodata, passthru, drop, local_data, disabled,
|
||||
and cname_override.
|
||||
.SH "FILES"
|
||||
.TP
|
||||
.I @ub_conf_file@
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "unbound\-host" "1" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
|
||||
.TH "unbound\-host" "1" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
|
||||
.\"
|
||||
.\" unbound-host.1 -- unbound DNS lookup utility
|
||||
.\"
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "unbound" "8" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
|
||||
.TH "unbound" "8" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
|
||||
.\"
|
||||
.\" unbound.8 -- unbound manual
|
||||
.\"
|
||||
@ -9,7 +9,7 @@
|
||||
.\"
|
||||
.SH "NAME"
|
||||
.B unbound
|
||||
\- Unbound DNS validating resolver 1.9.6.
|
||||
\- Unbound DNS validating resolver 1.10.1.
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound
|
||||
.RB [ \-h ]
|
||||
|
@ -1,4 +1,4 @@
|
||||
.TH "unbound.conf" "5" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
|
||||
.TH "unbound.conf" "5" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
|
||||
.\"
|
||||
.\" unbound.conf.5 -- unbound.conf manual
|
||||
.\"
|
||||
@ -63,8 +63,10 @@ server:
|
||||
access\-control: 2001:DB8::/64 allow
|
||||
.fi
|
||||
.SH "FILE FORMAT"
|
||||
There must be whitespace between keywords. Attribute keywords end with a colon ':'.
|
||||
An attribute is followed by its containing attributes, or a value.
|
||||
There must be whitespace between keywords. Attribute keywords end with a
|
||||
colon ':'. An attribute is followed by a value, or its containing attributes
|
||||
in which case it is referred to as a clause. Clauses can be repeated throughout
|
||||
the file (or included files) to group attributes under the same clause.
|
||||
.P
|
||||
Files can be included using the
|
||||
.B include:
|
||||
@ -1070,20 +1072,35 @@ The default value is "no".
|
||||
.TP
|
||||
.B serve\-expired: \fI<yes or no>
|
||||
If enabled, unbound attempts to serve old responses from cache with a
|
||||
TTL of 0 in the response without waiting for the actual resolution to finish.
|
||||
The actual resolution answer ends up in the cache later on. Default is "no".
|
||||
TTL of \fBserve\-expired\-reply\-ttl\fR in the response without waiting for the
|
||||
actual resolution to finish. The actual resolution answer ends up in the cache
|
||||
later on. Default is "no".
|
||||
.TP
|
||||
.B serve\-expired\-ttl: \fI<seconds>
|
||||
Limit serving of expired responses to configured seconds after expiration. 0
|
||||
disables the limit. This option only applies when \fBserve\-expired\fR is
|
||||
enabled. The default is 0.
|
||||
disables the limit. This option only applies when \fBserve\-expired\fR is
|
||||
enabled. A suggested value per draft-ietf-dnsop-serve-stale-10 is between
|
||||
86400 (1 day) and 259200 (3 days). The default is 0.
|
||||
.TP
|
||||
.B serve\-expired\-ttl\-reset: \fI<yes or no>
|
||||
Set the TTL of expired records to the \fBserve\-expired\-ttl\fR value after a
|
||||
failed attempt to retrieve the record from upstream. This makes sure that the
|
||||
expired records will be served as long as there are queries for it. Default is
|
||||
failed attempt to retrieve the record from upstream. This makes sure that the
|
||||
expired records will be served as long as there are queries for it. Default is
|
||||
"no".
|
||||
.TP
|
||||
.B serve\-expired\-reply\-ttl: \fI<seconds>
|
||||
TTL value to use when replying with expired data. If
|
||||
\fBserve\-expired\-client\-timeout\fR is also used then it is RECOMMENDED to
|
||||
use 30 as the value (draft-ietf-dnsop-serve-stale-10). The default is 30.
|
||||
.TP
|
||||
.B serve\-expired\-client\-timeout: \fI<msec>
|
||||
Time in milliseconds before replying to the client with expired data. This
|
||||
essentially enables the serve-stale behavior as specified in
|
||||
draft-ietf-dnsop-serve-stale-10 that first tries to resolve before immediately
|
||||
responding with expired data. A recommended value per
|
||||
draft-ietf-dnsop-serve-stale-10 is 1800. Setting this to 0 will disable this
|
||||
behavior. Default is 0.
|
||||
.TP
|
||||
.B val\-nsec3\-keysize\-iterations: \fI<"list of values">
|
||||
List of keysize and iteration count values, separated by spaces, surrounded
|
||||
by quotes. Default is "1024 150 2048 500 4096 2500". This determines the
|
||||
@ -1296,7 +1313,7 @@ local\-data: "onion. 10800 IN
|
||||
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
|
||||
.fi
|
||||
.TP 10
|
||||
\h'5'\fItest (RFC 2606)\fR
|
||||
\h'5'\fItest (RFC 6761)\fR
|
||||
Default content:
|
||||
.nf
|
||||
local\-zone: "test." static
|
||||
@ -1305,7 +1322,7 @@ local\-data: "test. 10800 IN
|
||||
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
|
||||
.fi
|
||||
.TP 10
|
||||
\h'5'\fIinvalid (RFC 2606)\fR
|
||||
\h'5'\fIinvalid (RFC 6761)\fR
|
||||
Default content:
|
||||
.nf
|
||||
local\-zone: "invalid." static
|
||||
@ -1680,6 +1697,12 @@ Name of the authority zone.
|
||||
Where to download a copy of the zone from, with AXFR and IXFR. Multiple
|
||||
masters can be specified. They are all tried if one fails.
|
||||
With the "ip#name" notation a AXFR over TLS can be used.
|
||||
If you point it at another Unbound instance, it would not work because
|
||||
that does not support AXFR/IXFR for the zone, but if you used \fBurl:\fR to download
|
||||
the zonefile as a text file from a webserver that would work.
|
||||
If you specify the hostname, you cannot use the domain from the zonefile,
|
||||
because it may not have that when retrieving that data, instead use a plain
|
||||
IP address to avoid a circular dependency on retrieving that IP address.
|
||||
.TP
|
||||
.B url: \fI<url to zonefile>
|
||||
Where to download a zonefile for the zone. With http or https. An example
|
||||
@ -1691,6 +1714,10 @@ see if the SOA serial number has changed, reducing the number of downloads.
|
||||
If none of the urls work, the masters are tried with IXFR and AXFR.
|
||||
For https, the \fBtls\-cert\-bundle\fR and the hostname from the url are used
|
||||
to authenticate the connection.
|
||||
If you specify a hostname in the URL, you cannot use the domain from the
|
||||
zonefile, because it may not have that when retrieving that data, instead
|
||||
use a plain IP address to avoid a circular dependency on retrieving that IP
|
||||
address. Avoid dependencies on name lookups by using a notation like "http://192.0.2.1/unbound-master/example.com.zone", with an explicit IP address.
|
||||
.TP
|
||||
.B allow\-notify: \fI<IP address or host name or netblockIP/prefix>
|
||||
With allow\-notify you can specify additional sources of notifies.
|
||||
@ -2014,6 +2041,13 @@ to the query without performing iterative DNS resolution.
|
||||
If Unbound cannot even find an answer in the backend, it resolves the
|
||||
query as usual, and stores the answer in the backend.
|
||||
.P
|
||||
This module interacts with the \fBserve\-expired\-*\fR options and will reply
|
||||
with expired data if unbound is configured for that. Currently the use
|
||||
of \fBserve\-expired\-client\-timeout:\fR and
|
||||
\fBserve\-expired\-reply\-ttl:\fR is not consistent for data originating from
|
||||
the external cache as these will result in a reply with 0 TTL without trying to
|
||||
update the data first, ignoring the configured values.
|
||||
.P
|
||||
If Unbound was built with
|
||||
\fB\-\-with\-libhiredis\fR
|
||||
on a system that has installed the hiredis C client library of Redis,
|
||||
@ -2080,6 +2114,70 @@ If this timeout expires Unbound closes the connection, treats it as
|
||||
if the Redis server does not have the requested data, and will try to
|
||||
re-establish a new connection later.
|
||||
This option defaults to 100 milliseconds.
|
||||
.SS Response Policy Zone Options
|
||||
.LP
|
||||
Response Policy Zones are configured with \fBrpz:\fR, and each one must have a
|
||||
\fBname:\fR. There can be multiple ones, by listing multiple rpz clauses, each
|
||||
with a different name. RPZ clauses are applied in order of configuration. The
|
||||
\fBrespip\fR module needs to be added to the \fBmodule-config\fR, e.g.:
|
||||
\fBmodule-config: "respip validator iterator"\fR.
|
||||
.P
|
||||
Only the QNAME and Response IP Address triggers are supported. The supported RPZ
|
||||
actions are: NXDOMAIN, NODATA, PASSTHRU, DROP and Local Data. RPZ QNAME triggers
|
||||
are applied after
|
||||
\fBlocal-zones\fR and before \fBauth-zones\fR.
|
||||
.TP
|
||||
.B name: \fI<zone name>
|
||||
Name of the authority zone.
|
||||
.TP
|
||||
.B master: \fI<IP address or host name>
|
||||
Where to download a copy of the zone from, with AXFR and IXFR. Multiple
|
||||
masters can be specified. They are all tried if one fails.
|
||||
.TP
|
||||
.B url: \fI<url to zonefile>
|
||||
Where to download a zonefile for the zone. With http or https. An example
|
||||
for the url is "http://www.example.com/example.org.zone". Multiple url
|
||||
statements can be given, they are tried in turn. If only urls are given
|
||||
the SOA refresh timer is used to wait for making new downloads. If also
|
||||
masters are listed, the masters are first probed with UDP SOA queries to
|
||||
see if the SOA serial number has changed, reducing the number of downloads.
|
||||
If none of the urls work, the masters are tried with IXFR and AXFR.
|
||||
For https, the \fBtls\-cert\-bundle\fR and the hostname from the url are used
|
||||
to authenticate the connection.
|
||||
.TP
|
||||
.B allow\-notify: \fI<IP address or host name or netblockIP/prefix>
|
||||
With allow\-notify you can specify additional sources of notifies.
|
||||
When notified, the server attempts to first probe and then zone transfer.
|
||||
If the notify is from a master, it first attempts that master. Otherwise
|
||||
other masters are attempted. If there are no masters, but only urls, the
|
||||
file is downloaded when notified. The masters from master: statements are
|
||||
allowed notify by default.
|
||||
.TP
|
||||
.B zonefile: \fI<filename>
|
||||
The filename where the zone is stored. If not given then no zonefile is used.
|
||||
If the file does not exist or is empty, unbound will attempt to fetch zone
|
||||
data (eg. from the master servers).
|
||||
.TP
|
||||
.B rpz\-action\-override: \fI<action>
|
||||
Always use this RPZ action for matching triggers from this zone. Possible action
|
||||
are: nxdomain, nodata, passthru, drop, disabled and cname.
|
||||
.TP
|
||||
.B rpz\-cname\-override: \fI<domain>
|
||||
The CNAME target domain to use if the cname action is configured for
|
||||
\fBrpz\-action\-override\fR.
|
||||
.TP
|
||||
.B rpz\-log: \fI<yes or no>
|
||||
Log all applied RPZ actions for this RPZ zone. Default is no.
|
||||
.TP
|
||||
.B rpz\-log\-name: \fI<name>
|
||||
Specify a string to be part of the log line, for easy referencing.
|
||||
.TP
|
||||
.B tags: \fI<list of tags>
|
||||
Limit the policies from this RPZ clause to clients with a matching tag. Tags
|
||||
need to be defined in \fBdefine\-tag\fR and can be assigned to client addresses
|
||||
using \fBaccess\-control\-tag\fR. Enclose list of tags in quotes ("") and put
|
||||
spaces between tags. If no tags are specified the policies from this clause will
|
||||
be applied for all clients.
|
||||
.SH "MEMORY CONTROL EXAMPLE"
|
||||
In the example config settings below memory usage is reduced. Some service
|
||||
levels are lower, notable very large data and a high TCP load are no longer
|
||||
|
@ -431,7 +431,7 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
}
|
||||
|
||||
qstate->return_msg = tomsg(NULL, &qstate->qinfo,
|
||||
(struct reply_info *)node->elem, qstate->region, *env->now,
|
||||
(struct reply_info *)node->elem, qstate->region, *env->now, 0,
|
||||
env->scratch);
|
||||
scope = (uint8_t)node->scope;
|
||||
lock_rw_unlock(&e->lock);
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
#!/usr/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2014-09-12.12; # UTC
|
||||
scriptversion=2013-12-25.23; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
@ -324,41 +324,34 @@ do
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
# $RANDOM is not portable (e.g. dash); use it when possible to
|
||||
# lower collision chance
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
# As "mkdir -p" follows symlinks and we work in /tmp possibly; so
|
||||
# create the $tmpdir first (and fail if unsuccessful) to make sure
|
||||
# that nobody tries to guess the $tmpdir name.
|
||||
if (umask $mkdir_umask &&
|
||||
$mkdirprog $mkdir_mode "$tmpdir" &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
test_tmpdir="$tmpdir/a"
|
||||
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
|
@ -84,7 +84,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
|
||||
}
|
||||
for(a = dp->target_list; a; a = a->next_target) {
|
||||
if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen,
|
||||
a->bogus, a->lame, a->tls_auth_name))
|
||||
a->bogus, a->lame, a->tls_auth_name, NULL))
|
||||
return NULL;
|
||||
}
|
||||
return copy;
|
||||
@ -161,7 +161,7 @@ delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
int
|
||||
delegpt_add_target(struct delegpt* dp, struct regional* region,
|
||||
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame)
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame, int* additions)
|
||||
{
|
||||
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
@ -176,13 +176,14 @@ delegpt_add_target(struct delegpt* dp, struct regional* region,
|
||||
if(ns->got4 && ns->got6)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL);
|
||||
return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL,
|
||||
additions);
|
||||
}
|
||||
|
||||
int
|
||||
delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus,
|
||||
uint8_t lame, char* tls_auth_name)
|
||||
uint8_t lame, char* tls_auth_name, int* additions)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
@ -194,6 +195,8 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
a->lame = 0;
|
||||
return 1;
|
||||
}
|
||||
if(additions)
|
||||
*additions = 1;
|
||||
|
||||
a = (struct delegpt_addr*)regional_alloc(region,
|
||||
sizeof(struct delegpt_addr));
|
||||
@ -382,10 +385,10 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)
|
||||
continue;
|
||||
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) {
|
||||
if(!delegpt_add_rrset_A(dp, region, s, 0))
|
||||
if(!delegpt_add_rrset_A(dp, region, s, 0, NULL))
|
||||
return NULL;
|
||||
} else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, s, 0))
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, s, 0, NULL))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -416,7 +419,7 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
|
||||
|
||||
int
|
||||
delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
|
||||
struct ub_packed_rrset_key* ak, uint8_t lame)
|
||||
struct ub_packed_rrset_key* ak, uint8_t lame, int* additions)
|
||||
{
|
||||
struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
|
||||
size_t i;
|
||||
@ -432,7 +435,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
|
||||
memmove(&sa.sin_addr, d->rr_data[i]+2, INET_SIZE);
|
||||
if(!delegpt_add_target(dp, region, ak->rk.dname,
|
||||
ak->rk.dname_len, (struct sockaddr_storage*)&sa,
|
||||
len, (d->security==sec_status_bogus), lame))
|
||||
len, (d->security==sec_status_bogus), lame, additions))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@ -440,7 +443,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
|
||||
|
||||
int
|
||||
delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,
|
||||
struct ub_packed_rrset_key* ak, uint8_t lame)
|
||||
struct ub_packed_rrset_key* ak, uint8_t lame, int* additions)
|
||||
{
|
||||
struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
|
||||
size_t i;
|
||||
@ -456,7 +459,7 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,
|
||||
memmove(&sa.sin6_addr, d->rr_data[i]+2, INET6_SIZE);
|
||||
if(!delegpt_add_target(dp, region, ak->rk.dname,
|
||||
ak->rk.dname_len, (struct sockaddr_storage*)&sa,
|
||||
len, (d->security==sec_status_bogus), lame))
|
||||
len, (d->security==sec_status_bogus), lame, additions))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@ -464,20 +467,33 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,
|
||||
|
||||
int
|
||||
delegpt_add_rrset(struct delegpt* dp, struct regional* region,
|
||||
struct ub_packed_rrset_key* rrset, uint8_t lame)
|
||||
struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions)
|
||||
{
|
||||
if(!rrset)
|
||||
return 1;
|
||||
if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS)
|
||||
return delegpt_rrset_add_ns(dp, region, rrset, lame);
|
||||
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A)
|
||||
return delegpt_add_rrset_A(dp, region, rrset, lame);
|
||||
return delegpt_add_rrset_A(dp, region, rrset, lame, additions);
|
||||
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA)
|
||||
return delegpt_add_rrset_AAAA(dp, region, rrset, lame);
|
||||
return delegpt_add_rrset_AAAA(dp, region, rrset, lame,
|
||||
additions);
|
||||
log_warn("Unknown rrset type added to delegpt");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void delegpt_mark_neg(struct delegpt_ns* ns, uint16_t qtype)
|
||||
{
|
||||
if(ns) {
|
||||
if(qtype == LDNS_RR_TYPE_A)
|
||||
ns->got4 = 2;
|
||||
else if(qtype == LDNS_RR_TYPE_AAAA)
|
||||
ns->got6 = 2;
|
||||
if(ns->got4 && ns->got6)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg)
|
||||
{
|
||||
struct reply_info* rep = (struct reply_info*)msg->entry.data;
|
||||
@ -487,14 +503,7 @@ void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg)
|
||||
if(FLAGS_GET_RCODE(rep->flags) != 0 || rep->an_numrrsets == 0) {
|
||||
struct delegpt_ns* ns = delegpt_find_ns(dp, msg->key.qname,
|
||||
msg->key.qname_len);
|
||||
if(ns) {
|
||||
if(msg->key.qtype == LDNS_RR_TYPE_A)
|
||||
ns->got4 = 1;
|
||||
else if(msg->key.qtype == LDNS_RR_TYPE_AAAA)
|
||||
ns->got6 = 1;
|
||||
if(ns->got4 && ns->got6)
|
||||
ns->resolved = 1;
|
||||
}
|
||||
delegpt_mark_neg(ns, msg->key.qtype);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,9 +106,10 @@ struct delegpt_ns {
|
||||
* and marked true if got4 and got6 are both true.
|
||||
*/
|
||||
int resolved;
|
||||
/** if the ipv4 address is in the delegpt */
|
||||
/** if the ipv4 address is in the delegpt, 0=not, 1=yes 2=negative,
|
||||
* negative means it was done, but no content. */
|
||||
uint8_t got4;
|
||||
/** if the ipv6 address is in the delegpt */
|
||||
/** if the ipv6 address is in the delegpt, 0=not, 1=yes 2=negative */
|
||||
uint8_t got6;
|
||||
/**
|
||||
* If the name is parent-side only and thus dispreferred.
|
||||
@ -215,11 +216,12 @@ int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional,
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: security status for the address, pass true if bogus.
|
||||
* @param lame: address is lame.
|
||||
* @param additions: will be set to 1 if a new address is added
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_target(struct delegpt* dp, struct regional* regional,
|
||||
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame);
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame, int* additions);
|
||||
|
||||
/**
|
||||
* Add A RRset to delegpt.
|
||||
@ -227,10 +229,11 @@ int delegpt_add_target(struct delegpt* dp, struct regional* regional,
|
||||
* @param regional: where to allocate the info.
|
||||
* @param rrset: RRset A to add.
|
||||
* @param lame: rrset is lame, disprefer it.
|
||||
* @param additions: will be set to 1 if a new address is added
|
||||
* @return 0 on alloc error.
|
||||
*/
|
||||
int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional,
|
||||
struct ub_packed_rrset_key* rrset, uint8_t lame);
|
||||
struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions);
|
||||
|
||||
/**
|
||||
* Add AAAA RRset to delegpt.
|
||||
@ -238,10 +241,11 @@ int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional,
|
||||
* @param regional: where to allocate the info.
|
||||
* @param rrset: RRset AAAA to add.
|
||||
* @param lame: rrset is lame, disprefer it.
|
||||
* @param additions: will be set to 1 if a new address is added
|
||||
* @return 0 on alloc error.
|
||||
*/
|
||||
int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional,
|
||||
struct ub_packed_rrset_key* rrset, uint8_t lame);
|
||||
struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions);
|
||||
|
||||
/**
|
||||
* Add any RRset to delegpt.
|
||||
@ -250,10 +254,11 @@ int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional,
|
||||
* @param regional: where to allocate the info.
|
||||
* @param rrset: RRset to add, NS, A, AAAA.
|
||||
* @param lame: rrset is lame, disprefer it.
|
||||
* @param additions: will be set to 1 if a new address is added
|
||||
* @return 0 on alloc error.
|
||||
*/
|
||||
int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
|
||||
struct ub_packed_rrset_key* rrset, uint8_t lame);
|
||||
struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions);
|
||||
|
||||
/**
|
||||
* Add address to the delegation point. No servername is associated or checked.
|
||||
@ -264,11 +269,12 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
|
||||
* @param bogus: if address is bogus.
|
||||
* @param lame: if address is lame.
|
||||
* @param tls_auth_name: TLS authentication name (or NULL).
|
||||
* @param additions: will be set to 1 if a new address is added
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t bogus, uint8_t lame, char* tls_auth_name);
|
||||
uint8_t bogus, uint8_t lame, char* tls_auth_name, int* additions);
|
||||
|
||||
/**
|
||||
* Find NS record in name list of delegation point.
|
||||
@ -341,6 +347,14 @@ size_t delegpt_count_targets(struct delegpt* dp);
|
||||
struct delegpt* delegpt_from_message(struct dns_msg* msg,
|
||||
struct regional* regional);
|
||||
|
||||
/**
|
||||
* Mark negative return in delegation point for specific nameserver.
|
||||
* sets the got4 or got6 to negative, updates the ns->resolved.
|
||||
* @param ns: the nameserver in the delegpt.
|
||||
* @param qtype: A or AAAA (host order).
|
||||
*/
|
||||
void delegpt_mark_neg(struct delegpt_ns* ns, uint16_t qtype);
|
||||
|
||||
/**
|
||||
* Add negative message to delegation point.
|
||||
* @param dp: delegation point.
|
||||
|
@ -185,8 +185,9 @@ mark_additional_rrset(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
/** Get target name of a CNAME */
|
||||
static int
|
||||
parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname,
|
||||
size_t* snamelen)
|
||||
size_t* snamelen, sldns_buffer* pkt)
|
||||
{
|
||||
size_t oldpos, dlen;
|
||||
if(rrset->rr_count != 1) {
|
||||
struct rr_parse* sig;
|
||||
verbose(VERB_ALGO, "Found CNAME rrset with "
|
||||
@ -204,6 +205,19 @@ parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname,
|
||||
*sname = rrset->rr_first->ttl_data + sizeof(uint32_t)
|
||||
+ sizeof(uint16_t); /* skip ttl, rdatalen */
|
||||
*snamelen = rrset->rr_first->size - sizeof(uint16_t);
|
||||
|
||||
if(rrset->rr_first->outside_packet) {
|
||||
if(!dname_valid(*sname, *snamelen))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
oldpos = sldns_buffer_position(pkt);
|
||||
sldns_buffer_set_position(pkt, (size_t)(*sname - sldns_buffer_begin(pkt)));
|
||||
dlen = pkt_dname_len(pkt);
|
||||
sldns_buffer_set_position(pkt, oldpos);
|
||||
if(dlen == 0)
|
||||
return 0; /* parse fail on the rdata name */
|
||||
*snamelen = dlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -215,7 +229,7 @@ synth_cname(uint8_t* qname, size_t qnamelen, struct rrset_parse* dname_rrset,
|
||||
/* we already know that sname is a strict subdomain of DNAME owner */
|
||||
uint8_t* dtarg = NULL;
|
||||
size_t dtarglen;
|
||||
if(!parse_get_cname_target(dname_rrset, &dtarg, &dtarglen))
|
||||
if(!parse_get_cname_target(dname_rrset, &dtarg, &dtarglen, pkt))
|
||||
return 0;
|
||||
if(qnamelen <= dname_rrset->dname_len)
|
||||
return 0;
|
||||
@ -388,7 +402,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
/* check next cname */
|
||||
uint8_t* t = NULL;
|
||||
size_t tlen = 0;
|
||||
if(!parse_get_cname_target(nx, &t, &tlen))
|
||||
if(!parse_get_cname_target(nx, &t, &tlen, pkt))
|
||||
return 0;
|
||||
if(dname_pkt_compare(pkt, alias, t) == 0) {
|
||||
/* it's OK and better capitalized */
|
||||
@ -439,7 +453,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
size_t tlen = 0;
|
||||
if(synth_cname(sname, snamelen, nx, alias,
|
||||
&aliaslen, pkt) &&
|
||||
parse_get_cname_target(rrset, &t, &tlen) &&
|
||||
parse_get_cname_target(rrset, &t, &tlen, pkt) &&
|
||||
dname_pkt_compare(pkt, alias, t) == 0) {
|
||||
/* the synthesized CNAME equals the
|
||||
* current CNAME. This CNAME is the
|
||||
@ -460,7 +474,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
}
|
||||
|
||||
/* move to next name in CNAME chain */
|
||||
if(!parse_get_cname_target(rrset, &sname, &snamelen))
|
||||
if(!parse_get_cname_target(rrset, &sname, &snamelen, pkt))
|
||||
return 0;
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
|
@ -1142,7 +1142,7 @@ int iter_lookup_parent_glue_from_cache(struct module_env* env,
|
||||
log_rrset_key(VERB_ALGO, "found parent-side", akey);
|
||||
ns->done_pside4 = 1;
|
||||
/* a negative-cache-element has no addresses it adds */
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, 1))
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, 1, NULL))
|
||||
log_err("malloc failure in lookup_parent_glue");
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
}
|
||||
@ -1154,7 +1154,7 @@ int iter_lookup_parent_glue_from_cache(struct module_env* env,
|
||||
log_rrset_key(VERB_ALGO, "found parent-side", akey);
|
||||
ns->done_pside6 = 1;
|
||||
/* a negative-cache-element has no addresses it adds */
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, 1))
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, 1, NULL))
|
||||
log_err("malloc failure in lookup_parent_glue");
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
}
|
||||
|
@ -72,6 +72,8 @@
|
||||
/* in msec */
|
||||
int UNKNOWN_SERVER_NICENESS = 376;
|
||||
|
||||
static void target_count_increase_nx(struct iter_qstate* iq, int num);
|
||||
|
||||
int
|
||||
iter_init(struct module_env* env, int id)
|
||||
{
|
||||
@ -150,6 +152,7 @@ iter_new(struct module_qstate* qstate, int id)
|
||||
iq->sent_count = 0;
|
||||
iq->ratelimit_ok = 0;
|
||||
iq->target_count = NULL;
|
||||
iq->dp_target_count = 0;
|
||||
iq->wait_priming_stub = 0;
|
||||
iq->refetch_glue = 0;
|
||||
iq->dnssec_expected = 0;
|
||||
@ -221,6 +224,7 @@ final_state(struct iter_qstate* iq)
|
||||
static void
|
||||
error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
|
||||
{
|
||||
struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id];
|
||||
struct iter_qstate* super_iq = (struct iter_qstate*)super->minfo[id];
|
||||
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
|
||||
@ -246,7 +250,11 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
|
||||
super->region, super_iq->dp))
|
||||
log_err("out of memory adding missing");
|
||||
}
|
||||
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
|
||||
dpns->resolved = 1; /* mark as failed */
|
||||
if((dpns->got4 == 2 || !ie->supports_ipv4) &&
|
||||
(dpns->got6 == 2 || !ie->supports_ipv6))
|
||||
target_count_increase_nx(super_iq, 1);
|
||||
}
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS) {
|
||||
/* prime failed to get delegation */
|
||||
@ -621,7 +629,7 @@ static void
|
||||
target_count_create(struct iter_qstate* iq)
|
||||
{
|
||||
if(!iq->target_count) {
|
||||
iq->target_count = (int*)calloc(2, sizeof(int));
|
||||
iq->target_count = (int*)calloc(3, sizeof(int));
|
||||
/* if calloc fails we simply do not track this number */
|
||||
if(iq->target_count)
|
||||
iq->target_count[0] = 1;
|
||||
@ -634,6 +642,15 @@ target_count_increase(struct iter_qstate* iq, int num)
|
||||
target_count_create(iq);
|
||||
if(iq->target_count)
|
||||
iq->target_count[1] += num;
|
||||
iq->dp_target_count++;
|
||||
}
|
||||
|
||||
static void
|
||||
target_count_increase_nx(struct iter_qstate* iq, int num)
|
||||
{
|
||||
target_count_create(iq);
|
||||
if(iq->target_count)
|
||||
iq->target_count[2] += num;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -656,13 +673,15 @@ target_count_increase(struct iter_qstate* iq, int num)
|
||||
* @param subq_ret: if newly allocated, the subquerystate, or NULL if it does
|
||||
* not need initialisation.
|
||||
* @param v: if true, validation is done on the subquery.
|
||||
* @param detached: true if this qstate should not attach to the subquery
|
||||
* @return false on error (malloc).
|
||||
*/
|
||||
static int
|
||||
generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
uint16_t qclass, struct module_qstate* qstate, int id,
|
||||
struct iter_qstate* iq, enum iter_state initial_state,
|
||||
enum iter_state finalstate, struct module_qstate** subq_ret, int v)
|
||||
enum iter_state finalstate, struct module_qstate** subq_ret, int v,
|
||||
int detached)
|
||||
{
|
||||
struct module_qstate* subq = NULL;
|
||||
struct iter_qstate* subiq = NULL;
|
||||
@ -689,11 +708,23 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
valrec = 1;
|
||||
}
|
||||
|
||||
/* attach subquery, lookup existing or make a new one */
|
||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||
if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, valrec,
|
||||
&subq)) {
|
||||
return 0;
|
||||
if(detached) {
|
||||
struct mesh_state* sub = NULL;
|
||||
fptr_ok(fptr_whitelist_modenv_add_sub(
|
||||
qstate->env->add_sub));
|
||||
if(!(*qstate->env->add_sub)(qstate, &qinf,
|
||||
qflags, prime, valrec, &subq, &sub)){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* attach subquery, lookup existing or make a new one */
|
||||
fptr_ok(fptr_whitelist_modenv_attach_sub(
|
||||
qstate->env->attach_sub));
|
||||
if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime,
|
||||
valrec, &subq)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*subq_ret = subq;
|
||||
if(subq) {
|
||||
@ -716,6 +747,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
subiq->target_count = iq->target_count;
|
||||
if(iq->target_count)
|
||||
iq->target_count[0] ++; /* extra reference */
|
||||
subiq->dp_target_count = 0;
|
||||
subiq->num_current_queries = 0;
|
||||
subiq->depth = iq->depth+1;
|
||||
outbound_list_init(&subiq->outlist);
|
||||
@ -759,7 +791,7 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
||||
* the normal INIT state logic (which would cause an infloop). */
|
||||
if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS,
|
||||
qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE,
|
||||
&subq, 0)) {
|
||||
&subq, 0, 0)) {
|
||||
verbose(VERB_ALGO, "could not prime root");
|
||||
return 0;
|
||||
}
|
||||
@ -850,7 +882,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
|
||||
* redundant INIT state processing. */
|
||||
if(!generate_sub_request(stub_dp->name, stub_dp->namelen,
|
||||
LDNS_RR_TYPE_NS, qclass, qstate, id, iq,
|
||||
QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0)) {
|
||||
QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 0)) {
|
||||
verbose(VERB_ALGO, "could not prime stub");
|
||||
errinf(qstate, "could not generate lookup for stub prime");
|
||||
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
@ -1025,7 +1057,7 @@ generate_a_aaaa_check(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(!generate_sub_request(s->rk.dname, s->rk.dname_len,
|
||||
ntohs(s->rk.type), ntohs(s->rk.rrset_class),
|
||||
qstate, id, iq,
|
||||
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
|
||||
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) {
|
||||
verbose(VERB_ALGO, "could not generate addr check");
|
||||
return;
|
||||
}
|
||||
@ -1069,7 +1101,7 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
iq->dp->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
|
||||
if(!generate_sub_request(iq->dp->name, iq->dp->namelen,
|
||||
LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq,
|
||||
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
|
||||
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) {
|
||||
verbose(VERB_ALGO, "could not generate ns check");
|
||||
return;
|
||||
}
|
||||
@ -1126,7 +1158,7 @@ generate_dnskey_prefetch(struct module_qstate* qstate,
|
||||
iq->dp->name, LDNS_RR_TYPE_DNSKEY, iq->qchase.qclass);
|
||||
if(!generate_sub_request(iq->dp->name, iq->dp->namelen,
|
||||
LDNS_RR_TYPE_DNSKEY, iq->qchase.qclass, qstate, id, iq,
|
||||
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) {
|
||||
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) {
|
||||
/* we'll be slower, but it'll work */
|
||||
verbose(VERB_ALGO, "could not generate dnskey prefetch");
|
||||
return;
|
||||
@ -1315,6 +1347,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->refetch_glue = 0;
|
||||
iq->query_restart_count++;
|
||||
iq->sent_count = 0;
|
||||
iq->dp_target_count = 0;
|
||||
sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region);
|
||||
if(qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||
@ -1693,7 +1726,7 @@ generate_parentside_target_query(struct module_qstate* qstate,
|
||||
{
|
||||
struct module_qstate* subq;
|
||||
if(!generate_sub_request(name, namelen, qtype, qclass, qstate,
|
||||
id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0))
|
||||
id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0))
|
||||
return 0;
|
||||
if(subq) {
|
||||
struct iter_qstate* subiq =
|
||||
@ -1744,7 +1777,7 @@ generate_target_query(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
{
|
||||
struct module_qstate* subq;
|
||||
if(!generate_sub_request(name, namelen, qtype, qclass, qstate,
|
||||
id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0))
|
||||
id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0))
|
||||
return 0;
|
||||
log_nametypeclass(VERB_QUERY, "new target", name, qtype, qclass);
|
||||
return 1;
|
||||
@ -1783,6 +1816,14 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
"number of glue fetches %d", s, iq->target_count[1]);
|
||||
return 0;
|
||||
}
|
||||
if(iq->dp_target_count > MAX_DP_TARGET_COUNT) {
|
||||
char s[LDNS_MAX_DOMAINLEN+1];
|
||||
dname_str(qstate->qinfo.qname, s);
|
||||
verbose(VERB_QUERY, "request %s has exceeded the maximum "
|
||||
"number of glue fetches %d to a single delegation point",
|
||||
s, iq->dp_target_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iter_mark_cycle_targets(qstate, iq->dp);
|
||||
missing = (int)delegpt_count_missing_targets(iq->dp);
|
||||
@ -1896,7 +1937,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
for(a = p->target_list; a; a=a->next_target) {
|
||||
(void)delegpt_add_addr(iq->dp, qstate->region,
|
||||
&a->addr, a->addrlen, a->bogus,
|
||||
a->lame, a->tls_auth_name);
|
||||
a->lame, a->tls_auth_name, NULL);
|
||||
}
|
||||
}
|
||||
iq->dp->has_parent_side_NS = 1;
|
||||
@ -1913,6 +1954,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->refetch_glue = 1;
|
||||
iq->query_restart_count++;
|
||||
iq->sent_count = 0;
|
||||
iq->dp_target_count = 0;
|
||||
if(qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||
return next_state(iq, INIT_REQUEST_STATE);
|
||||
@ -2078,7 +2120,7 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
iq->dsns_point, LDNS_RR_TYPE_NS, iq->qchase.qclass);
|
||||
if(!generate_sub_request(iq->dsns_point, iq->dsns_point_len,
|
||||
LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq,
|
||||
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) {
|
||||
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) {
|
||||
errinf_dname(qstate, "for DS query parent-child nameserver search, could not generate NS lookup for", iq->dsns_point);
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
@ -2136,6 +2178,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
errinf(qstate, "exceeded the maximum number of sends");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(iq->target_count && iq->target_count[2] > MAX_TARGET_NX) {
|
||||
verbose(VERB_QUERY, "request has exceeded the maximum "
|
||||
" number of nxdomain nameserver lookups with %d",
|
||||
iq->target_count[2]);
|
||||
errinf(qstate, "exceeded the maximum nameserver nxdomains");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
/* Make sure we have a delegation point, otherwise priming failed
|
||||
* or another failure occurred */
|
||||
@ -2240,12 +2289,41 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->qinfo_out.qtype, iq->qinfo_out.qclass,
|
||||
qstate->query_flags, qstate->region,
|
||||
qstate->env->scratch, 0);
|
||||
if(msg && msg->rep->an_numrrsets == 0
|
||||
&& FLAGS_GET_RCODE(msg->rep->flags) ==
|
||||
if(msg && FLAGS_GET_RCODE(msg->rep->flags) ==
|
||||
LDNS_RCODE_NOERROR)
|
||||
/* no need to send query if it is already
|
||||
* cached as NOERROR/NODATA */
|
||||
* cached as NOERROR */
|
||||
return 1;
|
||||
if(msg && FLAGS_GET_RCODE(msg->rep->flags) ==
|
||||
LDNS_RCODE_NXDOMAIN &&
|
||||
qstate->env->need_to_validate &&
|
||||
qstate->env->cfg->harden_below_nxdomain) {
|
||||
if(msg->rep->security == sec_status_secure) {
|
||||
iq->response = msg;
|
||||
return final_state(iq);
|
||||
}
|
||||
if(msg->rep->security == sec_status_unchecked) {
|
||||
struct module_qstate* subq = NULL;
|
||||
if(!generate_sub_request(
|
||||
iq->qinfo_out.qname,
|
||||
iq->qinfo_out.qname_len,
|
||||
iq->qinfo_out.qtype,
|
||||
iq->qinfo_out.qclass,
|
||||
qstate, id, iq,
|
||||
INIT_REQUEST_STATE,
|
||||
FINISHED_STATE, &subq, 1, 1))
|
||||
verbose(VERB_ALGO,
|
||||
"could not validate NXDOMAIN "
|
||||
"response");
|
||||
}
|
||||
}
|
||||
if(msg && FLAGS_GET_RCODE(msg->rep->flags) ==
|
||||
LDNS_RCODE_NXDOMAIN) {
|
||||
/* return and add a label in the next
|
||||
* minimisation iteration.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(iq->minimisation_state == SKIP_MINIMISE_STATE) {
|
||||
@ -2321,6 +2399,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* generated query will immediately be discarded due to depth and
|
||||
* that servfail is cached, which is not good as opportunism goes. */
|
||||
if(iq->depth < ie->max_dependency_depth
|
||||
&& iq->num_target_queries == 0
|
||||
&& (!iq->target_count || iq->target_count[2]==0)
|
||||
&& iq->sent_count < TARGET_FETCH_STOP) {
|
||||
tf_policy = ie->target_fetch_policy[iq->depth];
|
||||
}
|
||||
@ -2366,6 +2446,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->num_current_queries++; /* RespState decrements it*/
|
||||
iq->referral_count++; /* make sure we don't loop */
|
||||
iq->sent_count = 0;
|
||||
iq->dp_target_count = 0;
|
||||
iq->state = QUERY_RESP_STATE;
|
||||
return 1;
|
||||
}
|
||||
@ -2453,6 +2534,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->num_current_queries++; /* RespState decrements it*/
|
||||
iq->referral_count++; /* make sure we don't loop */
|
||||
iq->sent_count = 0;
|
||||
iq->dp_target_count = 0;
|
||||
iq->state = QUERY_RESP_STATE;
|
||||
return 1;
|
||||
}
|
||||
@ -2747,7 +2829,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* Make subrequest to validate intermediate
|
||||
* NXDOMAIN if harden-below-nxdomain is
|
||||
* enabled. */
|
||||
if(qstate->env->cfg->harden_below_nxdomain) {
|
||||
if(qstate->env->cfg->harden_below_nxdomain &&
|
||||
qstate->env->need_to_validate) {
|
||||
struct module_qstate* subq = NULL;
|
||||
log_query_info(VERB_QUERY,
|
||||
"schedule NXDOMAIN validation:",
|
||||
@ -2759,16 +2842,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->response->qinfo.qclass,
|
||||
qstate, id, iq,
|
||||
INIT_REQUEST_STATE,
|
||||
FINISHED_STATE, &subq, 1))
|
||||
FINISHED_STATE, &subq, 1, 1))
|
||||
verbose(VERB_ALGO,
|
||||
"could not validate NXDOMAIN "
|
||||
"response");
|
||||
outbound_list_clear(&iq->outlist);
|
||||
iq->num_current_queries = 0;
|
||||
fptr_ok(fptr_whitelist_modenv_detach_subs(
|
||||
qstate->env->detach_subs));
|
||||
(*qstate->env->detach_subs)(qstate);
|
||||
iq->num_target_queries = 0;
|
||||
}
|
||||
}
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
@ -2852,6 +2929,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* Count this as a referral. */
|
||||
iq->referral_count++;
|
||||
iq->sent_count = 0;
|
||||
iq->dp_target_count = 0;
|
||||
/* see if the next dp is a trust anchor, or a DS was sent
|
||||
* along, indicating dnssec is expected for next zone */
|
||||
iq->dnssec_expected = iter_indicates_dnssec(qstate->env,
|
||||
@ -2928,6 +3006,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->dsns_point = NULL;
|
||||
iq->auth_zone_response = 0;
|
||||
iq->sent_count = 0;
|
||||
iq->dp_target_count = 0;
|
||||
if(iq->minimisation_state != MINIMISE_STATE)
|
||||
/* Only count as query restart when it is not an extra
|
||||
* query as result of qname minimisation. */
|
||||
@ -3120,7 +3199,7 @@ processPrimeResponse(struct module_qstate* qstate, int id)
|
||||
if(!generate_sub_request(qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, qstate->qinfo.qtype,
|
||||
qstate->qinfo.qclass, qstate, id, iq,
|
||||
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
|
||||
INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) {
|
||||
verbose(VERB_ALGO, "could not generate prime check");
|
||||
}
|
||||
generate_a_aaaa_check(qstate, iq, id);
|
||||
@ -3148,6 +3227,7 @@ static void
|
||||
processTargetResponse(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* forq)
|
||||
{
|
||||
struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id];
|
||||
struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id];
|
||||
struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id];
|
||||
struct ub_packed_rrset_key* rrset;
|
||||
@ -3185,7 +3265,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
|
||||
log_rrset_key(VERB_ALGO, "add parentside glue to dp",
|
||||
iq->pside_glue);
|
||||
if(!delegpt_add_rrset(foriq->dp, forq->region,
|
||||
iq->pside_glue, 1))
|
||||
iq->pside_glue, 1, NULL))
|
||||
log_err("out of memory adding pside glue");
|
||||
}
|
||||
|
||||
@ -3196,6 +3276,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
|
||||
* response type was ANSWER. */
|
||||
rrset = reply_find_answer_rrset(&iq->qchase, qstate->return_msg->rep);
|
||||
if(rrset) {
|
||||
int additions = 0;
|
||||
/* if CNAMEs have been followed - add new NS to delegpt. */
|
||||
/* BTW. RFC 1918 says NS should not have got CNAMEs. Robust. */
|
||||
if(!delegpt_find_ns(foriq->dp, rrset->rk.dname,
|
||||
@ -3207,13 +3288,23 @@ processTargetResponse(struct module_qstate* qstate, int id,
|
||||
}
|
||||
/* if dpns->lame then set the address(es) lame too */
|
||||
if(!delegpt_add_rrset(foriq->dp, forq->region, rrset,
|
||||
dpns->lame))
|
||||
dpns->lame, &additions))
|
||||
log_err("out of memory adding targets");
|
||||
if(!additions) {
|
||||
/* no new addresses, increase the nxns counter, like
|
||||
* this could be a list of wildcards with no new
|
||||
* addresses */
|
||||
target_count_increase_nx(foriq, 1);
|
||||
}
|
||||
verbose(VERB_ALGO, "added target response");
|
||||
delegpt_log(VERB_ALGO, foriq->dp);
|
||||
} else {
|
||||
verbose(VERB_ALGO, "iterator TargetResponse failed");
|
||||
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
|
||||
dpns->resolved = 1; /* fail the target */
|
||||
if((dpns->got4 == 2 || !ie->supports_ipv4) &&
|
||||
(dpns->got6 == 2 || !ie->supports_ipv6))
|
||||
target_count_increase_nx(foriq, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3387,7 +3478,7 @@ processCollectClass(struct module_qstate* qstate, int id)
|
||||
qstate->qinfo.qname_len, qstate->qinfo.qtype,
|
||||
c, qstate, id, iq, INIT_REQUEST_STATE,
|
||||
FINISHED_STATE, &subq,
|
||||
(int)!(qstate->query_flags&BIT_CD))) {
|
||||
(int)!(qstate->query_flags&BIT_CD), 0)) {
|
||||
errinf(qstate, "could not generate class ANY"
|
||||
" lookup query");
|
||||
return error_response(qstate, id,
|
||||
|
@ -55,6 +55,11 @@ struct rbtree_type;
|
||||
|
||||
/** max number of targets spawned for a query and its subqueries */
|
||||
#define MAX_TARGET_COUNT 64
|
||||
/** max number of target lookups per qstate, per delegation point */
|
||||
#define MAX_DP_TARGET_COUNT 16
|
||||
/** max number of nxdomains allowed for target lookups for a query and
|
||||
* its subqueries */
|
||||
#define MAX_TARGET_NX 5
|
||||
/** max number of query restarts. Determines max number of CNAME chain. */
|
||||
#define MAX_RESTART_COUNT 8
|
||||
/** max number of referrals. Makes sure resolver does not run away */
|
||||
@ -305,9 +310,14 @@ struct iter_qstate {
|
||||
int sent_count;
|
||||
|
||||
/** number of target queries spawned in [1], for this query and its
|
||||
* subqueries, the malloced-array is shared, [0] refcount. */
|
||||
* subqueries, the malloced-array is shared, [0] refcount.
|
||||
* in [2] the number of nxdomains is counted. */
|
||||
int* target_count;
|
||||
|
||||
/** number of target lookups per delegation point. Reset to 0 after
|
||||
* receiving referral answer. Not shared with subqueries. */
|
||||
int dp_target_count;
|
||||
|
||||
/** if true, already tested for ratelimiting and passed the test */
|
||||
int ratelimit_ok;
|
||||
|
||||
|
@ -55,6 +55,7 @@
|
||||
int
|
||||
context_finalize(struct ub_ctx* ctx)
|
||||
{
|
||||
int is_rpz = 0;
|
||||
struct config_file* cfg = ctx->env->cfg;
|
||||
verbosity = cfg->verbosity;
|
||||
if(ctx_logfile_overridden && !ctx->logfile_override) {
|
||||
@ -76,7 +77,7 @@ context_finalize(struct ub_ctx* ctx)
|
||||
return UB_NOMEM;
|
||||
if(!local_zones_apply_cfg(ctx->local_zones, cfg))
|
||||
return UB_INITFAIL;
|
||||
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1))
|
||||
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz))
|
||||
return UB_INITFAIL;
|
||||
if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
|
||||
cfg->msg_cache_slabs)) {
|
||||
|
@ -561,7 +561,6 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q,
|
||||
if(!qinfo->qname) {
|
||||
return 0;
|
||||
}
|
||||
qinfo->local_alias = NULL;
|
||||
edns->edns_present = 1;
|
||||
edns->ext_rcode = 0;
|
||||
edns->edns_version = 0;
|
||||
|
@ -204,8 +204,9 @@ struct ub_result {
|
||||
char* why_bogus;
|
||||
|
||||
/**
|
||||
* If the query or one of its subqueries was ratelimited. Useful if
|
||||
* ratelimiting is enabled and answer is SERVFAIL.
|
||||
* If the query or one of its subqueries was ratelimited. Useful if
|
||||
* ratelimiting is enabled and answer to the client is SERVFAIL as a
|
||||
* result.
|
||||
*/
|
||||
int was_ratelimited;
|
||||
|
||||
@ -654,6 +655,8 @@ struct ub_shm_stat_info {
|
||||
#define UB_STATS_OPCODE_NUM 16
|
||||
/** number of histogram buckets */
|
||||
#define UB_STATS_BUCKET_NUM 40
|
||||
/** number of RPZ actions */
|
||||
#define UB_STATS_RPZ_ACTION_NUM 10
|
||||
|
||||
/** per worker statistics. */
|
||||
struct ub_server_stats {
|
||||
@ -733,8 +736,8 @@ struct ub_server_stats {
|
||||
long long unwanted_queries;
|
||||
/** usage of tcp accept list */
|
||||
long long tcp_accept_usage;
|
||||
/** answers served from expired cache */
|
||||
long long zero_ttl_responses;
|
||||
/** expired answers served from cache */
|
||||
long long ans_expired;
|
||||
/** histogram data exported to array
|
||||
* if the array is the same size, no data is lost, and
|
||||
* if all histograms are same size (is so by default) then
|
||||
@ -785,6 +788,8 @@ struct ub_server_stats {
|
||||
long long mem_stream_wait;
|
||||
/** number of TLS connection resume */
|
||||
long long qtls_resume;
|
||||
/** RPZ action stats */
|
||||
long long rpz_action[UB_STATS_RPZ_ACTION_NUM];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "services/localzone.h"
|
||||
#include "services/authzone.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "sldns/str2wire.h"
|
||||
#include "util/config_file.h"
|
||||
@ -25,30 +26,6 @@
|
||||
#include "services/view.h"
|
||||
#include "sldns/rrdef.h"
|
||||
|
||||
/**
|
||||
* Conceptual set of IP addresses for response AAAA or A records that should
|
||||
* trigger special actions.
|
||||
*/
|
||||
struct respip_set {
|
||||
struct regional* region;
|
||||
struct rbtree_type ip_tree;
|
||||
char* const* tagname; /* shallow copy of tag names, for logging */
|
||||
int num_tags; /* number of tagname entries */
|
||||
};
|
||||
|
||||
/** An address span with response control information */
|
||||
struct resp_addr {
|
||||
/** node in address tree */
|
||||
struct addr_tree_node node;
|
||||
/** tag bitlist */
|
||||
uint8_t* taglist;
|
||||
/** length of the taglist (in bytes) */
|
||||
size_t taglen;
|
||||
/** action for this address span */
|
||||
enum respip_action action;
|
||||
/** "local data" for this node */
|
||||
struct ub_packed_rrset_key* data;
|
||||
};
|
||||
|
||||
/** Subset of resp_addr.node, used for inform-variant logging */
|
||||
struct respip_addr_info {
|
||||
@ -88,14 +65,28 @@ respip_set_create(void)
|
||||
return NULL;
|
||||
}
|
||||
addr_tree_init(&set->ip_tree);
|
||||
lock_rw_init(&set->lock);
|
||||
return set;
|
||||
}
|
||||
|
||||
/** helper traverse to delete resp_addr nodes */
|
||||
static void
|
||||
resp_addr_del(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct resp_addr* r = (struct resp_addr*)n->key;
|
||||
lock_rw_destroy(&r->lock);
|
||||
#ifdef THREADS_DISABLED
|
||||
(void)r;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
respip_set_delete(struct respip_set* set)
|
||||
{
|
||||
if(!set)
|
||||
return;
|
||||
lock_rw_destroy(&set->lock);
|
||||
traverse_postorder(&set->ip_tree, resp_addr_del, NULL);
|
||||
regional_destroy(set->region);
|
||||
free(set);
|
||||
}
|
||||
@ -108,12 +99,49 @@ respip_set_get_tree(struct respip_set* set)
|
||||
return &set->ip_tree;
|
||||
}
|
||||
|
||||
struct resp_addr*
|
||||
respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int net, int create, const char* ipstr)
|
||||
{
|
||||
struct resp_addr* node;
|
||||
node = (struct resp_addr*)addr_tree_find(&set->ip_tree, addr, addrlen, net);
|
||||
if(!node && create) {
|
||||
node = regional_alloc_zero(set->region, sizeof(*node));
|
||||
if(!node) {
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
lock_rw_init(&node->lock);
|
||||
node->action = respip_none;
|
||||
if(!addr_tree_insert(&set->ip_tree, &node->node, addr,
|
||||
addrlen, net)) {
|
||||
/* We know we didn't find it, so this should be
|
||||
* impossible. */
|
||||
log_warn("unexpected: duplicate address: %s", ipstr);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node)
|
||||
{
|
||||
struct resp_addr* prev;
|
||||
prev = (struct resp_addr*)rbtree_previous((struct rbnode_type*)node);
|
||||
lock_rw_destroy(&node->lock);
|
||||
rbtree_delete(&set->ip_tree, node);
|
||||
/* no free'ing, all allocated in region */
|
||||
if(!prev)
|
||||
addr_tree_init_parents((rbtree_type*)set);
|
||||
else
|
||||
addr_tree_init_parents_node(&prev->node);
|
||||
}
|
||||
|
||||
/** returns the node in the address tree for the specified netblock string;
|
||||
* non-existent node will be created if 'create' is true */
|
||||
static struct resp_addr*
|
||||
respip_find_or_create(struct respip_set* set, const char* ipstr, int create)
|
||||
{
|
||||
struct resp_addr* node;
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
@ -122,22 +150,8 @@ respip_find_or_create(struct respip_set* set, const char* ipstr, int create)
|
||||
log_err("cannot parse netblock: '%s'", ipstr);
|
||||
return NULL;
|
||||
}
|
||||
node = (struct resp_addr*)addr_tree_find(&set->ip_tree, &addr, addrlen, net);
|
||||
if(!node && create) {
|
||||
node = regional_alloc_zero(set->region, sizeof(*node));
|
||||
if(!node) {
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
node->action = respip_none;
|
||||
if(!addr_tree_insert(&set->ip_tree, &node->node, &addr,
|
||||
addrlen, net)) {
|
||||
/* We know we didn't find it, so this should be
|
||||
* impossible. */
|
||||
log_warn("unexpected: duplicate address: %s", ipstr);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
return respip_sockaddr_find_or_create(set, &addr, addrlen, net, create,
|
||||
ipstr);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -191,6 +205,10 @@ respip_action_cfg(struct respip_set* set, const char* ipstr,
|
||||
action = respip_always_refuse;
|
||||
else if(strcmp(actnstr, "always_nxdomain") == 0)
|
||||
action = respip_always_nxdomain;
|
||||
else if(strcmp(actnstr, "always_nodata") == 0)
|
||||
action = respip_always_nodata;
|
||||
else if(strcmp(actnstr, "always_deny") == 0)
|
||||
action = respip_always_deny;
|
||||
else {
|
||||
log_err("unknown response-ip action %s", actnstr);
|
||||
return 0;
|
||||
@ -232,8 +250,43 @@ new_rrset(struct regional* region, uint16_t rrtype, uint16_t rrclass)
|
||||
}
|
||||
|
||||
/** enter local data as resource records into a response-ip node */
|
||||
static int
|
||||
|
||||
int
|
||||
respip_enter_rr(struct regional* region, struct resp_addr* raddr,
|
||||
uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata,
|
||||
size_t rdata_len, const char* rrstr, const char* netblockstr)
|
||||
{
|
||||
struct packed_rrset_data* pd;
|
||||
struct sockaddr* sa;
|
||||
sa = (struct sockaddr*)&raddr->node.addr;
|
||||
if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data) {
|
||||
log_err("CNAME response-ip data (%s) can not co-exist with other "
|
||||
"response-ip data for netblock %s", rrstr, netblockstr);
|
||||
return 0;
|
||||
} else if (raddr->data &&
|
||||
raddr->data->rk.type == htons(LDNS_RR_TYPE_CNAME)) {
|
||||
log_err("response-ip data (%s) can not be added; CNAME response-ip "
|
||||
"data already in place for netblock %s", rrstr, netblockstr);
|
||||
return 0;
|
||||
} else if((rrtype != LDNS_RR_TYPE_CNAME) &&
|
||||
((sa->sa_family == AF_INET && rrtype != LDNS_RR_TYPE_A) ||
|
||||
(sa->sa_family == AF_INET6 && rrtype != LDNS_RR_TYPE_AAAA))) {
|
||||
log_err("response-ip data %s record type does not correspond "
|
||||
"to netblock %s address family", rrstr, netblockstr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!raddr->data) {
|
||||
raddr->data = new_rrset(region, rrtype, rrclass);
|
||||
if(!raddr->data)
|
||||
return 0;
|
||||
}
|
||||
pd = raddr->data->entry.data;
|
||||
return rrset_insert_rr(region, pd, rdata, rdata_len, ttl, rrstr);
|
||||
}
|
||||
|
||||
static int
|
||||
respip_enter_rrstr(struct regional* region, struct resp_addr* raddr,
|
||||
const char* rrstr, const char* netblock)
|
||||
{
|
||||
uint8_t* nm;
|
||||
@ -244,8 +297,6 @@ respip_enter_rr(struct regional* region, struct resp_addr* raddr,
|
||||
size_t rdata_len = 0;
|
||||
char buf[65536];
|
||||
char bufshort[64];
|
||||
struct packed_rrset_data* pd;
|
||||
struct sockaddr* sa;
|
||||
int ret;
|
||||
if(raddr->action != respip_redirect
|
||||
&& raddr->action != respip_inform_redirect) {
|
||||
@ -265,31 +316,8 @@ respip_enter_rr(struct regional* region, struct resp_addr* raddr,
|
||||
return 0;
|
||||
}
|
||||
free(nm);
|
||||
sa = (struct sockaddr*)&raddr->node.addr;
|
||||
if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data) {
|
||||
log_err("CNAME response-ip data (%s) can not co-exist with other "
|
||||
"response-ip data for netblock %s", rrstr, netblock);
|
||||
return 0;
|
||||
} else if (raddr->data &&
|
||||
raddr->data->rk.type == htons(LDNS_RR_TYPE_CNAME)) {
|
||||
log_err("response-ip data (%s) can not be added; CNAME response-ip "
|
||||
"data already in place for netblock %s", rrstr, netblock);
|
||||
return 0;
|
||||
} else if((rrtype != LDNS_RR_TYPE_CNAME) &&
|
||||
((sa->sa_family == AF_INET && rrtype != LDNS_RR_TYPE_A) ||
|
||||
(sa->sa_family == AF_INET6 && rrtype != LDNS_RR_TYPE_AAAA))) {
|
||||
log_err("response-ip data %s record type does not correspond "
|
||||
"to netblock %s address family", rrstr, netblock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!raddr->data) {
|
||||
raddr->data = new_rrset(region, rrtype, rrclass);
|
||||
if(!raddr->data)
|
||||
return 0;
|
||||
}
|
||||
pd = raddr->data->entry.data;
|
||||
return rrset_insert_rr(region, pd, rdata, rdata_len, ttl, rrstr);
|
||||
return respip_enter_rr(region, raddr, rrtype, rrclass, ttl, rdata,
|
||||
rdata_len, rrstr, netblock);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -303,7 +331,7 @@ respip_data_cfg(struct respip_set* set, const char* ipstr, const char* rrstr)
|
||||
"response-ip node for %s not found", rrstr, ipstr);
|
||||
return 0;
|
||||
}
|
||||
return respip_enter_rr(set->region, node, rrstr, ipstr);
|
||||
return respip_enter_rrstr(set->region, node, rrstr, ipstr);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -564,9 +592,10 @@ rdata2sockaddr(const struct packed_rrset_data* rd, uint16_t rtype, size_t i,
|
||||
* rep->rrsets for the RRset that contains the matching IP address record
|
||||
* (the index is normally 0, but can be larger than that if this is a CNAME
|
||||
* chain or type-ANY response).
|
||||
* Returns resp_addr holding read lock.
|
||||
*/
|
||||
static const struct resp_addr*
|
||||
respip_addr_lookup(const struct reply_info *rep, struct rbtree_type* iptree,
|
||||
static struct resp_addr*
|
||||
respip_addr_lookup(const struct reply_info *rep, struct respip_set* rs,
|
||||
size_t* rrset_id)
|
||||
{
|
||||
size_t i;
|
||||
@ -574,6 +603,7 @@ respip_addr_lookup(const struct reply_info *rep, struct rbtree_type* iptree,
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t addrlen;
|
||||
|
||||
lock_rw_rdlock(&rs->lock);
|
||||
for(i=0; i<rep->an_numrrsets; i++) {
|
||||
size_t j;
|
||||
const struct packed_rrset_data* rd;
|
||||
@ -585,15 +615,17 @@ respip_addr_lookup(const struct reply_info *rep, struct rbtree_type* iptree,
|
||||
for(j = 0; j < rd->count; j++) {
|
||||
if(!rdata2sockaddr(rd, rtype, j, &ss, &addrlen))
|
||||
continue;
|
||||
ra = (struct resp_addr*)addr_tree_lookup(iptree, &ss,
|
||||
addrlen);
|
||||
ra = (struct resp_addr*)addr_tree_lookup(&rs->ip_tree,
|
||||
&ss, addrlen);
|
||||
if(ra) {
|
||||
*rrset_id = i;
|
||||
lock_rw_rdlock(&ra->lock);
|
||||
lock_rw_unlock(&rs->lock);
|
||||
return ra;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lock_rw_unlock(&rs->lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -642,8 +674,8 @@ make_new_reply_info(const struct reply_info* rep, struct regional* region,
|
||||
* Note that this function distinguishes error conditions from "success but
|
||||
* not overridden". This is because we want to avoid accidentally applying
|
||||
* the "no data" action in case of error.
|
||||
* @param raddr: address span that requires an action
|
||||
* @param action: action to apply
|
||||
* @param data: RRset to use for override
|
||||
* @param qtype: original query type
|
||||
* @param rep: original reply message
|
||||
* @param rrset_id: the rrset ID in 'rep' to which the action should apply
|
||||
@ -658,14 +690,15 @@ make_new_reply_info(const struct reply_info* rep, struct regional* region,
|
||||
* @return 1 if overridden, 0 if not overridden, -1 on error.
|
||||
*/
|
||||
static int
|
||||
respip_data_answer(const struct resp_addr* raddr, enum respip_action action,
|
||||
respip_data_answer(enum respip_action action,
|
||||
struct ub_packed_rrset_key* data,
|
||||
uint16_t qtype, const struct reply_info* rep,
|
||||
size_t rrset_id, struct reply_info** new_repp, int tag,
|
||||
struct config_strlist** tag_datas, size_t tag_datas_size,
|
||||
char* const* tagname, int num_tags,
|
||||
struct ub_packed_rrset_key** redirect_rrsetp, struct regional* region)
|
||||
{
|
||||
struct ub_packed_rrset_key* rp = raddr->data;
|
||||
struct ub_packed_rrset_key* rp = data;
|
||||
struct reply_info* new_rep;
|
||||
*redirect_rrsetp = NULL;
|
||||
|
||||
@ -703,7 +736,7 @@ respip_data_answer(const struct resp_addr* raddr, enum respip_action action,
|
||||
* to replace the rrset's dname. Note that, unlike local data, we
|
||||
* rename the dname for other actions than redirect. This is because
|
||||
* response-ip-data isn't associated to any specific name. */
|
||||
if(rp == raddr->data) {
|
||||
if(rp == data) {
|
||||
rp = copy_rrset(rp, region);
|
||||
if(!rp)
|
||||
return -1;
|
||||
@ -761,6 +794,7 @@ respip_nodata_answer(uint16_t qtype, enum respip_action action,
|
||||
return 1;
|
||||
} else if(action == respip_static || action == respip_redirect ||
|
||||
action == respip_always_nxdomain ||
|
||||
action == respip_always_nodata ||
|
||||
action == respip_inform_redirect) {
|
||||
/* Since we don't know about other types of the owner name,
|
||||
* we generally return NOERROR/NODATA unless an NXDOMAIN action
|
||||
@ -794,16 +828,22 @@ populate_action_info(struct respip_action_info* actinfo,
|
||||
enum respip_action action, const struct resp_addr* raddr,
|
||||
const struct ub_packed_rrset_key* ATTR_UNUSED(rrset),
|
||||
int ATTR_UNUSED(tag), const struct respip_set* ATTR_UNUSED(ipset),
|
||||
int ATTR_UNUSED(action_only), struct regional* region)
|
||||
int ATTR_UNUSED(action_only), struct regional* region, int rpz_used,
|
||||
int rpz_log, char* log_name, int rpz_cname_override)
|
||||
{
|
||||
if(action == respip_none || !raddr)
|
||||
return 1;
|
||||
actinfo->action = action;
|
||||
actinfo->rpz_used = rpz_used;
|
||||
actinfo->rpz_log = rpz_log;
|
||||
actinfo->log_name = log_name;
|
||||
actinfo->rpz_cname_override = rpz_cname_override;
|
||||
|
||||
/* for inform variants, make a copy of the matched address block for
|
||||
* later logging. We make a copy to proactively avoid disruption if
|
||||
* and when we allow a dynamic update to the respip tree. */
|
||||
if(action == respip_inform || action == respip_inform_deny) {
|
||||
if(action == respip_inform || action == respip_inform_deny ||
|
||||
rpz_used) {
|
||||
struct respip_addr_info* a =
|
||||
regional_alloc_zero(region, sizeof(*a));
|
||||
if(!a) {
|
||||
@ -819,12 +859,39 @@ populate_action_info(struct respip_action_info* actinfo,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
respip_use_rpz(struct resp_addr* raddr, struct rpz* r,
|
||||
enum respip_action* action,
|
||||
struct ub_packed_rrset_key** data, int* rpz_log, char** log_name,
|
||||
int* rpz_cname_override, struct regional* region, int* is_rpz)
|
||||
{
|
||||
if(r->action_override == RPZ_DISABLED_ACTION) {
|
||||
*is_rpz = 0;
|
||||
return 1;
|
||||
}
|
||||
else if(r->action_override == RPZ_NO_OVERRIDE_ACTION)
|
||||
*action = raddr->action;
|
||||
else
|
||||
*action = rpz_action_to_respip_action(r->action_override);
|
||||
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION &&
|
||||
r->cname_override) {
|
||||
*data = r->cname_override;
|
||||
*rpz_cname_override = 1;
|
||||
}
|
||||
*rpz_log = r->log;
|
||||
if(r->log_name)
|
||||
if(!(*log_name = regional_strdup(region, r->log_name)))
|
||||
return 0;
|
||||
*is_rpz = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
respip_rewrite_reply(const struct query_info* qinfo,
|
||||
const struct respip_client_info* cinfo, const struct reply_info* rep,
|
||||
struct reply_info** new_repp, struct respip_action_info* actinfo,
|
||||
struct ub_packed_rrset_key** alias_rrset, int search_only,
|
||||
struct regional* region)
|
||||
struct regional* region, struct auth_zones* az)
|
||||
{
|
||||
const uint8_t* ctaglist;
|
||||
size_t ctaglen;
|
||||
@ -837,9 +904,15 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
size_t rrset_id = 0;
|
||||
enum respip_action action = respip_none;
|
||||
int tag = -1;
|
||||
const struct resp_addr* raddr = NULL;
|
||||
struct resp_addr* raddr = NULL;
|
||||
int ret = 1;
|
||||
struct ub_packed_rrset_key* redirect_rrset = NULL;
|
||||
struct rpz* r;
|
||||
struct ub_packed_rrset_key* data = NULL;
|
||||
int rpz_used = 0;
|
||||
int rpz_log = 0;
|
||||
int rpz_cname_override = 0;
|
||||
char* log_name = NULL;
|
||||
|
||||
if(!cinfo)
|
||||
goto done;
|
||||
@ -852,6 +925,8 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
view = cinfo->view;
|
||||
ipset = cinfo->respip_set;
|
||||
|
||||
log_assert(ipset);
|
||||
|
||||
/** Try to use response-ip config from the view first; use
|
||||
* global response-ip config if we don't have the view or we don't
|
||||
* have the matching per-view config (and the view allows the use
|
||||
@ -866,7 +941,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
lock_rw_rdlock(&view->lock);
|
||||
if(view->respip_set) {
|
||||
if((raddr = respip_addr_lookup(rep,
|
||||
&view->respip_set->ip_tree, &rrset_id))) {
|
||||
view->respip_set, &rrset_id))) {
|
||||
/** for per-view respip directives the action
|
||||
* can only be direct (i.e. not tag-based) */
|
||||
action = raddr->action;
|
||||
@ -875,7 +950,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
if(!raddr && !view->isfirst)
|
||||
goto done;
|
||||
}
|
||||
if(!raddr && ipset && (raddr = respip_addr_lookup(rep, &ipset->ip_tree,
|
||||
if(!raddr && (raddr = respip_addr_lookup(rep, ipset,
|
||||
&rrset_id))) {
|
||||
action = (enum respip_action)local_data_find_tag_action(
|
||||
raddr->taglist, raddr->taglen, ctaglist, ctaglen,
|
||||
@ -883,6 +958,29 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
(enum localzone_type)raddr->action, &tag,
|
||||
ipset->tagname, ipset->num_tags);
|
||||
}
|
||||
lock_rw_rdlock(&az->rpz_lock);
|
||||
for(r = az->rpz_first; r && !raddr; r = r->next) {
|
||||
if(!r->taglist || taglist_intersect(r->taglist,
|
||||
r->taglistlen, ctaglist, ctaglen)) {
|
||||
if((raddr = respip_addr_lookup(rep,
|
||||
r->respip_set, &rrset_id))) {
|
||||
if(!respip_use_rpz(raddr, r, &action, &data,
|
||||
&rpz_log, &log_name, &rpz_cname_override,
|
||||
region, &rpz_used)) {
|
||||
log_err("out of memory");
|
||||
lock_rw_unlock(&raddr->lock);
|
||||
lock_rw_unlock(&az->rpz_lock);
|
||||
return 0;
|
||||
}
|
||||
if(!rpz_used) {
|
||||
lock_rw_unlock(&raddr->lock);
|
||||
raddr = NULL;
|
||||
actinfo->rpz_disabled++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lock_rw_unlock(&az->rpz_lock);
|
||||
if(raddr && !search_only) {
|
||||
int result = 0;
|
||||
|
||||
@ -891,10 +989,13 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
if(action != respip_always_refuse
|
||||
&& action != respip_always_transparent
|
||||
&& action != respip_always_nxdomain
|
||||
&& (result = respip_data_answer(raddr, action,
|
||||
qinfo->qtype, rep, rrset_id, new_repp, tag, tag_datas,
|
||||
tag_datas_size, ipset->tagname, ipset->num_tags,
|
||||
&redirect_rrset, region)) < 0) {
|
||||
&& action != respip_always_nodata
|
||||
&& action != respip_always_deny
|
||||
&& (result = respip_data_answer(action,
|
||||
(data) ? data : raddr->data, qinfo->qtype, rep,
|
||||
rrset_id, new_repp, tag, tag_datas, tag_datas_size,
|
||||
ipset->tagname, ipset->num_tags, &redirect_rrset,
|
||||
region)) < 0) {
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
@ -925,7 +1026,11 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
*alias_rrset = redirect_rrset;
|
||||
/* on success, populate respip result structure */
|
||||
ret = populate_action_info(actinfo, action, raddr,
|
||||
redirect_rrset, tag, ipset, search_only, region);
|
||||
redirect_rrset, tag, ipset, search_only, region,
|
||||
rpz_used, rpz_log, log_name, rpz_cname_override);
|
||||
}
|
||||
if(raddr) {
|
||||
lock_rw_unlock(&raddr->lock);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -981,14 +1086,15 @@ respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA ||
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_ANY) &&
|
||||
qstate->return_msg && qstate->return_msg->rep) {
|
||||
struct respip_action_info actinfo = {respip_none, NULL};
|
||||
struct reply_info* new_rep = qstate->return_msg->rep;
|
||||
struct ub_packed_rrset_key* alias_rrset = NULL;
|
||||
struct respip_action_info actinfo = {0};
|
||||
actinfo.action = respip_none;
|
||||
|
||||
if(!respip_rewrite_reply(&qstate->qinfo,
|
||||
qstate->client_info, qstate->return_msg->rep,
|
||||
&new_rep, &actinfo, &alias_rrset, 0,
|
||||
qstate->region)) {
|
||||
qstate->region, qstate->env->auth_zones)) {
|
||||
goto servfail;
|
||||
}
|
||||
if(actinfo.action != respip_none) {
|
||||
@ -1004,9 +1110,10 @@ respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
} else {
|
||||
qstate->respip_action_info = NULL;
|
||||
}
|
||||
if (new_rep == qstate->return_msg->rep &&
|
||||
if (actinfo.action == respip_always_deny ||
|
||||
(new_rep == qstate->return_msg->rep &&
|
||||
(actinfo.action == respip_deny ||
|
||||
actinfo.action == respip_inform_deny)) {
|
||||
actinfo.action == respip_inform_deny))) {
|
||||
/* for deny-variant actions (unless response-ip
|
||||
* data is applied), mark the query state so
|
||||
* the response will be dropped for all
|
||||
@ -1034,14 +1141,16 @@ int
|
||||
respip_merge_cname(struct reply_info* base_rep,
|
||||
const struct query_info* qinfo, const struct reply_info* tgt_rep,
|
||||
const struct respip_client_info* cinfo, int must_validate,
|
||||
struct reply_info** new_repp, struct regional* region)
|
||||
struct reply_info** new_repp, struct regional* region,
|
||||
struct auth_zones* az)
|
||||
{
|
||||
struct reply_info* new_rep;
|
||||
struct reply_info* tmp_rep = NULL; /* just a placeholder */
|
||||
struct ub_packed_rrset_key* alias_rrset = NULL; /* ditto */
|
||||
uint16_t tgt_rcode;
|
||||
size_t i, j;
|
||||
struct respip_action_info actinfo = {respip_none, NULL};
|
||||
struct respip_action_info actinfo = {0};
|
||||
actinfo.action = respip_none;
|
||||
|
||||
/* If the query for the CNAME target would result in an unusual rcode,
|
||||
* we generally translate it as a failure for the base query
|
||||
@ -1060,7 +1169,7 @@ respip_merge_cname(struct reply_info* base_rep,
|
||||
|
||||
/* see if the target reply would be subject to a response-ip action. */
|
||||
if(!respip_rewrite_reply(qinfo, cinfo, tgt_rep, &tmp_rep, &actinfo,
|
||||
&alias_rrset, 1, region))
|
||||
&alias_rrset, 1, region, az))
|
||||
return 0;
|
||||
if(actinfo.action != respip_none) {
|
||||
log_info("CNAME target of redirect response-ip action would "
|
||||
@ -1112,7 +1221,8 @@ respip_inform_super(struct module_qstate* qstate, int id,
|
||||
|
||||
if(!respip_merge_cname(super->return_msg->rep, &qstate->qinfo,
|
||||
qstate->return_msg->rep, super->client_info,
|
||||
super->env->need_to_validate, &new_rep, super->region))
|
||||
super->env->need_to_validate, &new_rep, super->region,
|
||||
qstate->env->auth_zones))
|
||||
goto fail;
|
||||
super->return_msg->rep = new_rep;
|
||||
return;
|
||||
@ -1171,12 +1281,15 @@ respip_set_is_empty(const struct respip_set* set)
|
||||
}
|
||||
|
||||
void
|
||||
respip_inform_print(struct respip_addr_info* respip_addr, uint8_t* qname,
|
||||
respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
|
||||
uint16_t qtype, uint16_t qclass, struct local_rrset* local_alias,
|
||||
struct comm_reply* repinfo)
|
||||
{
|
||||
char srcip[128], respip[128], txt[512];
|
||||
unsigned port;
|
||||
struct respip_addr_info* respip_addr = respip_actinfo->addrinfo;
|
||||
size_t txtlen = 0;
|
||||
const char* actionstr = NULL;
|
||||
|
||||
if(local_alias)
|
||||
qname = local_alias->rrset->rk.dname;
|
||||
@ -1186,7 +1299,23 @@ respip_inform_print(struct respip_addr_info* respip_addr, uint8_t* qname,
|
||||
addr_to_str(&repinfo->addr, repinfo->addrlen, srcip, sizeof(srcip));
|
||||
addr_to_str(&respip_addr->addr, respip_addr->addrlen,
|
||||
respip, sizeof(respip));
|
||||
snprintf(txt, sizeof(txt), "%s/%d inform %s@%u", respip,
|
||||
respip_addr->net, srcip, port);
|
||||
if(respip_actinfo->rpz_log) {
|
||||
txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen, "%s",
|
||||
"RPZ applied ");
|
||||
if(respip_actinfo->rpz_cname_override)
|
||||
actionstr = rpz_action_to_string(
|
||||
RPZ_CNAME_OVERRIDE_ACTION);
|
||||
else
|
||||
actionstr = rpz_action_to_string(
|
||||
respip_action_to_rpz_action(
|
||||
respip_actinfo->action));
|
||||
}
|
||||
if(respip_actinfo->log_name) {
|
||||
txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen,
|
||||
"[%s] ", respip_actinfo->log_name);
|
||||
}
|
||||
snprintf(txt+txtlen, sizeof(txt)-txtlen,
|
||||
"%s/%d %s %s@%u", respip, respip_addr->net,
|
||||
(actionstr) ? actionstr : "inform", srcip, port);
|
||||
log_nametypeclass(NO_VERBOSE, txt, qname, qtype, qclass);
|
||||
}
|
||||
|
@ -14,23 +14,42 @@
|
||||
|
||||
#include "util/module.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/locks.h"
|
||||
|
||||
/**
|
||||
* Set of response IP addresses with associated actions and tags.
|
||||
* Forward declaration only here. Actual definition is hidden within the
|
||||
* module.
|
||||
* Conceptual set of IP addresses for response AAAA or A records that should
|
||||
* trigger special actions.
|
||||
*/
|
||||
struct respip_set;
|
||||
struct respip_set {
|
||||
struct regional* region;
|
||||
struct rbtree_type ip_tree;
|
||||
lock_rw_type lock; /* lock on the respip tree */
|
||||
char* const* tagname; /* shallow copy of tag names, for logging */
|
||||
int num_tags; /* number of tagname entries */
|
||||
};
|
||||
|
||||
|
||||
/** An address span with response control information */
|
||||
struct resp_addr {
|
||||
/** node in address tree */
|
||||
struct addr_tree_node node;
|
||||
/** lock on the node item */
|
||||
lock_rw_type lock;
|
||||
/** tag bitlist */
|
||||
uint8_t* taglist;
|
||||
/** length of the taglist (in bytes) */
|
||||
size_t taglen;
|
||||
/** action for this address span */
|
||||
enum respip_action action;
|
||||
/** "local data" for this node */
|
||||
struct ub_packed_rrset_key* data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Forward declaration for the structure that represents a node in the
|
||||
* respip_set address tree
|
||||
*/
|
||||
struct resp_addr;
|
||||
|
||||
/**
|
||||
* Forward declaration for the structure that represents a tree of view data.
|
||||
*/
|
||||
|
||||
struct views;
|
||||
|
||||
struct respip_addr_info;
|
||||
@ -60,6 +79,11 @@ struct respip_client_info {
|
||||
*/
|
||||
struct respip_action_info {
|
||||
enum respip_action action;
|
||||
int rpz_used;
|
||||
int rpz_log;
|
||||
int rpz_disabled;
|
||||
char* log_name;
|
||||
int rpz_cname_override;
|
||||
struct respip_addr_info* addrinfo; /* set only for inform variants */
|
||||
};
|
||||
|
||||
@ -124,12 +148,14 @@ int respip_views_apply_cfg(struct views* vs, struct config_file* cfg,
|
||||
* @param new_repp: pointer placeholder for the merged reply. will be intact
|
||||
* on error.
|
||||
* @param region: allocator to build *new_repp.
|
||||
* @param az: auth zones containing RPZ information.
|
||||
* @return 1 on success, 0 on error.
|
||||
*/
|
||||
int respip_merge_cname(struct reply_info* base_rep,
|
||||
const struct query_info* qinfo, const struct reply_info* tgt_rep,
|
||||
const struct respip_client_info* cinfo, int must_validate,
|
||||
struct reply_info** new_repp, struct regional* region);
|
||||
struct reply_info** new_repp, struct regional* region,
|
||||
struct auth_zones* az);
|
||||
|
||||
/**
|
||||
* See if any IP-based action should apply to any IP address of AAAA/A answer
|
||||
@ -148,6 +174,7 @@ int respip_merge_cname(struct reply_info* base_rep,
|
||||
* @param alias_rrset: must not be NULL.
|
||||
* @param search_only: if true, only check if an action would apply. actionp
|
||||
* will be set (or intact) accordingly but the modified reply won't be built.
|
||||
* @param az: auth zones containing RPZ information.
|
||||
* @param region: allocator to build *new_repp.
|
||||
* @return 1 on success, 0 on error.
|
||||
*/
|
||||
@ -156,7 +183,7 @@ int respip_rewrite_reply(const struct query_info* qinfo,
|
||||
const struct reply_info *rep, struct reply_info** new_repp,
|
||||
struct respip_action_info* actinfo,
|
||||
struct ub_packed_rrset_key** alias_rrset,
|
||||
int search_only, struct regional* region);
|
||||
int search_only, struct regional* region, struct auth_zones* az);
|
||||
|
||||
/**
|
||||
* Get the response-ip function block.
|
||||
@ -213,7 +240,7 @@ int respip_set_is_empty(const struct respip_set* set);
|
||||
/**
|
||||
* print log information for a query subject to an inform or inform-deny
|
||||
* response-ip action.
|
||||
* @param respip_addr: response-ip information that causes the action
|
||||
* @param respip_actinfo: response-ip information that causes the action
|
||||
* @param qname: query name in the context, will be ignored if local_alias is
|
||||
* non-NULL.
|
||||
* @param qtype: query type, in host byte order.
|
||||
@ -223,8 +250,48 @@ int respip_set_is_empty(const struct respip_set* set);
|
||||
* query name.
|
||||
* @param repinfo: reply info containing the client's source address and port.
|
||||
*/
|
||||
void respip_inform_print(struct respip_addr_info* respip_addr, uint8_t* qname,
|
||||
uint16_t qtype, uint16_t qclass, struct local_rrset* local_alias,
|
||||
struct comm_reply* repinfo);
|
||||
void respip_inform_print(struct respip_action_info* respip_actinfo,
|
||||
uint8_t* qname, uint16_t qtype, uint16_t qclass,
|
||||
struct local_rrset* local_alias, struct comm_reply* repinfo);
|
||||
|
||||
/**
|
||||
* Find resp_addr in tree, create and add to tree if it does not exist.
|
||||
* @param set: struct containing the tree and region to alloc new node on.
|
||||
* should hold write lock.
|
||||
* @param addr: address to look up.
|
||||
* @param addrlen: length of addr.
|
||||
* @param net: netblock to lookup.
|
||||
* @param create: create node if it does not exist when 1.
|
||||
* @param ipstr: human redable ip string, for logging.
|
||||
* @return newly created of found node, not holding lock.
|
||||
*/
|
||||
struct resp_addr*
|
||||
respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int net, int create, const char* ipstr);
|
||||
|
||||
/**
|
||||
* Add RR to resp_addr's RRset. Create RRset if not existing.
|
||||
* @param region: region to alloc RR(set).
|
||||
* @param raddr: resp_addr containing RRset. Must hold write lock.
|
||||
* @param rrtype: RR type.
|
||||
* @param rrclass: RR class.
|
||||
* @param ttl: TTL.
|
||||
* @param rdata: RDATA.
|
||||
* @param rdata_len: length of rdata.
|
||||
* @param rrstr: RR as string, for logging
|
||||
* @param netblockstr: netblock as string, for logging
|
||||
* @return 0 on error
|
||||
*/
|
||||
int
|
||||
respip_enter_rr(struct regional* region, struct resp_addr* raddr,
|
||||
uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata,
|
||||
size_t rdata_len, const char* rrstr, const char* netblockstr);
|
||||
|
||||
/**
|
||||
* Delete resp_addr node from tree.
|
||||
* @param set: struct containing tree. Must hold write lock.
|
||||
* @param node: node to delete. Not locked.
|
||||
*/
|
||||
void
|
||||
respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node);
|
||||
#endif /* RESPIP_RESPIP_H */
|
||||
|
@ -299,6 +299,8 @@ struct auth_zones* auth_zones_create(void)
|
||||
lock_protect(&az->lock, &az->ztree, sizeof(az->ztree));
|
||||
lock_protect(&az->lock, &az->xtree, sizeof(az->xtree));
|
||||
/* also lock protects the rbnode's in struct auth_zone, auth_xfer */
|
||||
lock_rw_init(&az->rpz_lock);
|
||||
lock_protect(&az->rpz_lock, &az->rpz_first, sizeof(az->rpz_first));
|
||||
return az;
|
||||
}
|
||||
|
||||
@ -381,11 +383,25 @@ auth_data_del(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
|
||||
/** delete an auth zone structure (tree remove must be done elsewhere) */
|
||||
static void
|
||||
auth_zone_delete(struct auth_zone* z)
|
||||
auth_zone_delete(struct auth_zone* z, struct auth_zones* az)
|
||||
{
|
||||
if(!z) return;
|
||||
lock_rw_destroy(&z->lock);
|
||||
traverse_postorder(&z->data, auth_data_del, NULL);
|
||||
|
||||
if(az && z->rpz) {
|
||||
/* keep RPZ linked list intact */
|
||||
lock_rw_wrlock(&az->rpz_lock);
|
||||
if(z->rpz->prev)
|
||||
z->rpz->prev->next = z->rpz->next;
|
||||
else
|
||||
az->rpz_first = z->rpz->next;
|
||||
if(z->rpz->next)
|
||||
z->rpz->next->prev = z->rpz->prev;
|
||||
lock_rw_unlock(&az->rpz_lock);
|
||||
}
|
||||
if(z->rpz)
|
||||
rpz_delete(z->rpz);
|
||||
free(z->name);
|
||||
free(z->zonefile);
|
||||
free(z);
|
||||
@ -415,7 +431,7 @@ auth_zone_create(struct auth_zones* az, uint8_t* nm, size_t nmlen,
|
||||
/* z lock protects all, except rbtree itself, which is az->lock */
|
||||
if(!rbtree_insert(&az->ztree, &z->node)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
auth_zone_delete(z);
|
||||
auth_zone_delete(z, NULL);
|
||||
log_warn("duplicate auth zone");
|
||||
return NULL;
|
||||
}
|
||||
@ -660,23 +676,6 @@ domain_remove_rrset(struct auth_data* node, uint16_t rr_type)
|
||||
}
|
||||
}
|
||||
|
||||
/** find an rr index in the rrset. returns true if found */
|
||||
static int
|
||||
az_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
|
||||
size_t* index)
|
||||
{
|
||||
size_t i;
|
||||
for(i=0; i<d->count; i++) {
|
||||
if(d->rr_len[i] != len)
|
||||
continue;
|
||||
if(memcmp(d->rr_data[i], rdata, len) == 0) {
|
||||
*index = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** find an rrsig index in the rrset. returns true if found */
|
||||
static int
|
||||
az_rrset_find_rrsig(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
|
||||
@ -1178,6 +1177,12 @@ az_insert_rr(struct auth_zone* z, uint8_t* rr, size_t rr_len,
|
||||
log_err("cannot add RR to domain");
|
||||
return 0;
|
||||
}
|
||||
if(z->rpz) {
|
||||
if(!(rpz_insert_rr(z->rpz, z->namelen, dname, dname_len,
|
||||
rr_type, rr_class, rr_ttl, rdata, rdatalen, rr,
|
||||
rr_len)))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1192,7 +1197,7 @@ az_domain_remove_rr(struct auth_data* node, uint16_t rr_type,
|
||||
|
||||
/* find the plain RR of the given type */
|
||||
if((rrset=az_domain_rrset(node, rr_type))!= NULL) {
|
||||
if(az_rrset_find_rr(rrset->data, rdata, rdatalen, &index)) {
|
||||
if(packed_rrset_find_rr(rrset->data, rdata, rdatalen, &index)) {
|
||||
if(rrset->data->count == 1 &&
|
||||
rrset->data->rrsig_count == 0) {
|
||||
/* last RR, delete the rrset */
|
||||
@ -1293,6 +1298,10 @@ az_remove_rr(struct auth_zone* z, uint8_t* rr, size_t rr_len,
|
||||
(void)rbtree_delete(&z->data, node);
|
||||
auth_data_delete(node);
|
||||
}
|
||||
if(z->rpz) {
|
||||
rpz_remove_rr(z->rpz, z->namelen, dname, dname_len, rr_type,
|
||||
rr_class, rdata, rdatalen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1585,6 +1594,9 @@ auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg)
|
||||
/* clear the data tree */
|
||||
traverse_postorder(&z->data, auth_data_del, NULL);
|
||||
rbtree_init(&z->data, &auth_data_cmp);
|
||||
/* clear the RPZ policies */
|
||||
if(z->rpz)
|
||||
rpz_clear(z->rpz);
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
/* default TTL to 3600 */
|
||||
@ -1604,6 +1616,9 @@ auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg)
|
||||
return 0;
|
||||
}
|
||||
fclose(in);
|
||||
|
||||
if(z->rpz)
|
||||
rpz_finish_config(z->rpz);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1877,6 +1892,18 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
|
||||
z->for_downstream = c->for_downstream;
|
||||
z->for_upstream = c->for_upstream;
|
||||
z->fallback_enabled = c->fallback_enabled;
|
||||
if(c->isrpz && !z->rpz){
|
||||
if(!(z->rpz = rpz_create(c))){
|
||||
fatal_exit("Could not setup RPZ zones");
|
||||
return 0;
|
||||
}
|
||||
lock_rw_wrlock(&az->rpz_lock);
|
||||
z->rpz->next = az->rpz_first;
|
||||
if(az->rpz_first)
|
||||
az->rpz_first->prev = z->rpz;
|
||||
az->rpz_first = z->rpz;
|
||||
lock_rw_unlock(&az->rpz_lock);
|
||||
}
|
||||
|
||||
/* xfer zone */
|
||||
if(x) {
|
||||
@ -1947,14 +1974,14 @@ az_delete_deleted_zones(struct auth_zones* az)
|
||||
auth_xfer_delete(xfr);
|
||||
}
|
||||
(void)rbtree_delete(&az->ztree, &z->node);
|
||||
auth_zone_delete(z);
|
||||
auth_zone_delete(z, az);
|
||||
z = next;
|
||||
}
|
||||
lock_rw_unlock(&az->lock);
|
||||
}
|
||||
|
||||
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
|
||||
int setup)
|
||||
int setup, int* is_rpz)
|
||||
{
|
||||
struct config_auth* p;
|
||||
az_setall_deleted(az);
|
||||
@ -1963,6 +1990,7 @@ int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
|
||||
log_warn("auth-zone without a name, skipped");
|
||||
continue;
|
||||
}
|
||||
*is_rpz = (*is_rpz || p->isrpz);
|
||||
if(!auth_zones_cfg(az, p)) {
|
||||
log_err("cannot config auth zone %s", p->name);
|
||||
return 0;
|
||||
@ -2063,7 +2091,7 @@ static void
|
||||
auth_zone_del(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct auth_zone* z = (struct auth_zone*)n->key;
|
||||
auth_zone_delete(z);
|
||||
auth_zone_delete(z, NULL);
|
||||
}
|
||||
|
||||
/** helper traverse to delete xfer zones */
|
||||
@ -2078,6 +2106,7 @@ void auth_zones_delete(struct auth_zones* az)
|
||||
{
|
||||
if(!az) return;
|
||||
lock_rw_destroy(&az->lock);
|
||||
lock_rw_destroy(&az->rpz_lock);
|
||||
traverse_postorder(&az->ztree, auth_zone_del, NULL);
|
||||
traverse_postorder(&az->xtree, auth_xfer_del, NULL);
|
||||
free(az);
|
||||
@ -2586,12 +2615,14 @@ az_nsec3_hash(uint8_t* buf, size_t buflen, uint8_t* nm, size_t nmlen,
|
||||
/* hashfunc(name, salt) */
|
||||
memmove(p, nm, nmlen);
|
||||
query_dname_tolower(p);
|
||||
memmove(p+nmlen, salt, saltlen);
|
||||
if(salt && saltlen > 0)
|
||||
memmove(p+nmlen, salt, saltlen);
|
||||
(void)secalgo_nsec3_hash(algo, p, nmlen+saltlen, (unsigned char*)buf);
|
||||
for(i=0; i<iter; i++) {
|
||||
/* hashfunc(hash, salt) */
|
||||
memmove(p, buf, hlen);
|
||||
memmove(p+hlen, salt, saltlen);
|
||||
if(salt && saltlen > 0)
|
||||
memmove(p+hlen, salt, saltlen);
|
||||
(void)secalgo_nsec3_hash(algo, p, hlen+saltlen,
|
||||
(unsigned char*)buf);
|
||||
}
|
||||
@ -4688,6 +4719,10 @@ apply_axfr(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
/* clear the data tree */
|
||||
traverse_postorder(&z->data, auth_data_del, NULL);
|
||||
rbtree_init(&z->data, &auth_data_cmp);
|
||||
/* clear the RPZ policies */
|
||||
if(z->rpz)
|
||||
rpz_clear(z->rpz);
|
||||
|
||||
xfr->have_zone = 0;
|
||||
xfr->serial = 0;
|
||||
|
||||
@ -4784,6 +4819,10 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
/* clear the data tree */
|
||||
traverse_postorder(&z->data, auth_data_del, NULL);
|
||||
rbtree_init(&z->data, &auth_data_cmp);
|
||||
/* clear the RPZ policies */
|
||||
if(z->rpz)
|
||||
rpz_clear(z->rpz);
|
||||
|
||||
xfr->have_zone = 0;
|
||||
xfr->serial = 0;
|
||||
|
||||
@ -4969,6 +5008,9 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env,
|
||||
if(xfr->have_zone)
|
||||
xfr->lease_time = *env->now;
|
||||
|
||||
if(z->rpz)
|
||||
rpz_finish_config(z->rpz);
|
||||
|
||||
/* unlock */
|
||||
lock_rw_unlock(&z->lock);
|
||||
|
||||
@ -5530,9 +5572,12 @@ check_xfer_packet(sldns_buffer* pkt, struct auth_xfer* xfr,
|
||||
xfr->task_transfer->rr_scan_num == 0 &&
|
||||
LDNS_ANCOUNT(wire)==1) {
|
||||
verbose(VERB_ALGO, "xfr to %s ended, "
|
||||
"IXFR reply that zone has serial %u",
|
||||
"IXFR reply that zone has serial %u,"
|
||||
" fallback from IXFR to AXFR",
|
||||
xfr->task_transfer->master->host,
|
||||
(unsigned)serial);
|
||||
xfr->task_transfer->ixfr_fail = 1;
|
||||
*gonextonfail = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "util/rbtree.h"
|
||||
#include "util/locks.h"
|
||||
#include "services/mesh.h"
|
||||
#include "services/rpz.h"
|
||||
struct ub_packed_rrset_key;
|
||||
struct regional;
|
||||
struct config_file;
|
||||
@ -81,6 +82,11 @@ struct auth_zones {
|
||||
size_t num_query_up;
|
||||
/** number of queries downstream */
|
||||
size_t num_query_down;
|
||||
/** first rpz item in linked list */
|
||||
struct rpz* rpz_first;
|
||||
/** rw lock for rpz linked list, needed when iterating or editing linked
|
||||
* list. */
|
||||
lock_rw_type rpz_lock;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -126,6 +132,8 @@ struct auth_zone {
|
||||
/** for upstream: this zone answers queries that unbound intends to
|
||||
* send upstream. */
|
||||
int for_upstream;
|
||||
/** RPZ zones */
|
||||
struct rpz* rpz;
|
||||
/** zone has been deleted */
|
||||
int zone_deleted;
|
||||
/** deletelist pointer, unused normally except during delete */
|
||||
@ -460,10 +468,11 @@ struct auth_zones* auth_zones_create(void);
|
||||
* @param az: auth zones structure
|
||||
* @param cfg: config to apply.
|
||||
* @param setup: if true, also sets up values in the auth zones structure
|
||||
* @param is_rpz: set to 1 if at least one RPZ zone is configured.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
|
||||
int setup);
|
||||
int setup, int* is_rpz);
|
||||
|
||||
/** initial pick up of worker timeouts, ties events to worker event loop
|
||||
* @param az: auth zones structure
|
||||
|
130
contrib/unbound/services/cache/dns.c
vendored
130
contrib/unbound/services/cache/dns.c
vendored
@ -45,6 +45,7 @@
|
||||
#include "validator/val_utils.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/packed_rrset.h"
|
||||
#include "util/data/dname.h"
|
||||
@ -73,15 +74,15 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
time_t leeway, int pside, struct reply_info* qrep,
|
||||
struct regional* region)
|
||||
{
|
||||
size_t i;
|
||||
/* see if rrset already exists in cache, if not insert it. */
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
/* update ref if it was in the cache */
|
||||
size_t i;
|
||||
/* see if rrset already exists in cache, if not insert it. */
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
/* update ref if it was in the cache */
|
||||
switch(rrset_cache_update(env->rrset_cache, &rep->ref[i],
|
||||
env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)==
|
||||
LDNS_RR_TYPE_NS && !pside)?0:leeway))) {
|
||||
env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)==
|
||||
LDNS_RR_TYPE_NS && !pside)?0:leeway))) {
|
||||
case 0: /* ref unchanged, item inserted */
|
||||
break;
|
||||
case 2: /* ref updated, cache is superior */
|
||||
@ -104,9 +105,9 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
* the fallthrough warning */
|
||||
/* fallthrough */
|
||||
case 1: /* ref updated, item inserted */
|
||||
rep->rrsets[i] = rep->ref[i].key;
|
||||
rep->rrsets[i] = rep->ref[i].key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** delete message from message cache */
|
||||
@ -272,7 +273,7 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, 0)) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, 0, NULL)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
@ -292,7 +293,7 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, 0)) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, 0, NULL)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
@ -326,7 +327,8 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, ns->lame)) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, ns->lame,
|
||||
NULL)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
@ -346,7 +348,8 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, ns->lame)) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, ns->lame,
|
||||
NULL)) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
@ -532,31 +535,51 @@ gen_dns_msg(struct regional* region, struct query_info* q, size_t num)
|
||||
}
|
||||
|
||||
struct dns_msg*
|
||||
tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
struct regional* region, time_t now, struct regional* scratch)
|
||||
tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
struct regional* region, time_t now, int allow_expired,
|
||||
struct regional* scratch)
|
||||
{
|
||||
struct dns_msg* msg;
|
||||
size_t i;
|
||||
if(now > r->ttl)
|
||||
return NULL;
|
||||
int is_expired = 0;
|
||||
time_t now_control = now;
|
||||
if(now > r->ttl) {
|
||||
/* Check if we are allowed to serve expired */
|
||||
if(allow_expired) {
|
||||
if(env->cfg->serve_expired_ttl &&
|
||||
r->serve_expired_ttl < now) {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
/* Change the current time so we can pass the below TTL checks when
|
||||
* serving expired data. */
|
||||
now_control = r->ttl - env->cfg->serve_expired_reply_ttl;
|
||||
is_expired = 1;
|
||||
}
|
||||
|
||||
msg = gen_dns_msg(region, q, r->rrset_count);
|
||||
if(!msg)
|
||||
return NULL;
|
||||
if(!msg) return NULL;
|
||||
msg->rep->flags = r->flags;
|
||||
msg->rep->qdcount = r->qdcount;
|
||||
msg->rep->ttl = r->ttl - now;
|
||||
msg->rep->ttl = is_expired
|
||||
?SERVE_EXPIRED_REPLY_TTL
|
||||
:r->ttl - now;
|
||||
if(r->prefetch_ttl > now)
|
||||
msg->rep->prefetch_ttl = r->prefetch_ttl - now;
|
||||
else msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
else
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
msg->rep->security = r->security;
|
||||
msg->rep->an_numrrsets = r->an_numrrsets;
|
||||
msg->rep->ns_numrrsets = r->ns_numrrsets;
|
||||
msg->rep->ar_numrrsets = r->ar_numrrsets;
|
||||
msg->rep->rrset_count = r->rrset_count;
|
||||
msg->rep->authoritative = r->authoritative;
|
||||
if(!rrset_array_lock(r->ref, r->rrset_count, now))
|
||||
msg->rep->authoritative = r->authoritative;
|
||||
if(!rrset_array_lock(r->ref, r->rrset_count, now_control)) {
|
||||
return NULL;
|
||||
}
|
||||
if(r->an_numrrsets > 0 && (r->rrsets[0]->rk.type == htons(
|
||||
LDNS_RR_TYPE_CNAME) || r->rrsets[0]->rk.type == htons(
|
||||
LDNS_RR_TYPE_DNAME)) && !reply_check_cname_chain(q, r)) {
|
||||
@ -570,7 +593,7 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
return NULL;
|
||||
}
|
||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
||||
msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i],
|
||||
msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i],
|
||||
region, now);
|
||||
if(!msg->rep->rrsets[i]) {
|
||||
rrset_array_unlock(r->ref, r->rrset_count);
|
||||
@ -797,7 +820,7 @@ dns_cache_lookup(struct module_env* env,
|
||||
if(e) {
|
||||
struct msgreply_entry* key = (struct msgreply_entry*)e->key;
|
||||
struct reply_info* data = (struct reply_info*)e->data;
|
||||
struct dns_msg* msg = tomsg(env, &key->key, data, region, now,
|
||||
struct dns_msg* msg = tomsg(env, &key->key, data, region, now, 0,
|
||||
scratch);
|
||||
if(msg) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
@ -899,37 +922,38 @@ dns_cache_lookup(struct module_env* env,
|
||||
* Empty nonterminals are NOERROR, so an NXDOMAIN for foo
|
||||
* means bla.foo also does not exist. The DNSSEC proofs are
|
||||
* the same. We search upwards for NXDOMAINs. */
|
||||
if(env->cfg->harden_below_nxdomain)
|
||||
while(!dname_is_root(k.qname)) {
|
||||
dname_remove_label(&k.qname, &k.qname_len);
|
||||
h = query_info_hash(&k, flags);
|
||||
e = slabhash_lookup(env->msg_cache, h, &k, 0);
|
||||
if(!e && k.qtype != LDNS_RR_TYPE_A &&
|
||||
env->cfg->qname_minimisation) {
|
||||
k.qtype = LDNS_RR_TYPE_A;
|
||||
if(env->cfg->harden_below_nxdomain) {
|
||||
while(!dname_is_root(k.qname)) {
|
||||
dname_remove_label(&k.qname, &k.qname_len);
|
||||
h = query_info_hash(&k, flags);
|
||||
e = slabhash_lookup(env->msg_cache, h, &k, 0);
|
||||
}
|
||||
if(e) {
|
||||
struct reply_info* data = (struct reply_info*)e->data;
|
||||
struct dns_msg* msg;
|
||||
if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN
|
||||
&& data->security == sec_status_secure
|
||||
&& (data->an_numrrsets == 0 ||
|
||||
ntohs(data->rrsets[0]->rk.type) != LDNS_RR_TYPE_CNAME)
|
||||
&& (msg=tomsg(env, &k, data, region, now, scratch))){
|
||||
lock_rw_unlock(&e->lock);
|
||||
msg->qinfo.qname=qname;
|
||||
msg->qinfo.qname_len=qnamelen;
|
||||
/* check that DNSSEC really works out */
|
||||
msg->rep->security = sec_status_unchecked;
|
||||
iter_scrub_nxdomain(msg);
|
||||
return msg;
|
||||
if(!e && k.qtype != LDNS_RR_TYPE_A &&
|
||||
env->cfg->qname_minimisation) {
|
||||
k.qtype = LDNS_RR_TYPE_A;
|
||||
h = query_info_hash(&k, flags);
|
||||
e = slabhash_lookup(env->msg_cache, h, &k, 0);
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
if(e) {
|
||||
struct reply_info* data = (struct reply_info*)e->data;
|
||||
struct dns_msg* msg;
|
||||
if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN
|
||||
&& data->security == sec_status_secure
|
||||
&& (data->an_numrrsets == 0 ||
|
||||
ntohs(data->rrsets[0]->rk.type) != LDNS_RR_TYPE_CNAME)
|
||||
&& (msg=tomsg(env, &k, data, region, now, 0, scratch))) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
msg->qinfo.qname=qname;
|
||||
msg->qinfo.qname_len=qnamelen;
|
||||
/* check that DNSSEC really works out */
|
||||
msg->rep->security = sec_status_unchecked;
|
||||
iter_scrub_nxdomain(msg);
|
||||
return msg;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
k.qtype = qtype;
|
||||
}
|
||||
k.qtype = qtype;
|
||||
}
|
||||
}
|
||||
|
||||
/* fill common RR types for ANY response to avoid requery */
|
||||
if(qtype == LDNS_RR_TYPE_ANY) {
|
||||
|
7
contrib/unbound/services/cache/dns.h
vendored
7
contrib/unbound/services/cache/dns.h
vendored
@ -143,11 +143,14 @@ struct delegpt* dns_cache_find_delegation(struct module_env* env,
|
||||
* @param r: reply info that, together with qname, will make up the dns message.
|
||||
* @param region: where to allocate dns message.
|
||||
* @param now: the time now, for check if TTL on cache entry is ok.
|
||||
* @param allow_expired: if true and serve-expired is enabled, it will allow
|
||||
* for expired dns_msg to be generated based on the configured serve-expired
|
||||
* logic.
|
||||
* @param scratch: where to allocate temporary data.
|
||||
* */
|
||||
struct dns_msg* tomsg(struct module_env* env, struct query_info* q,
|
||||
struct reply_info* r, struct regional* region, time_t now,
|
||||
struct regional* scratch);
|
||||
int allow_expired, struct regional* scratch);
|
||||
|
||||
/**
|
||||
* Find cached message
|
||||
@ -160,7 +163,7 @@ struct dns_msg* tomsg(struct module_env* env, struct query_info* q,
|
||||
* @param region: where to allocate result.
|
||||
* @param scratch: where to allocate temporary data.
|
||||
* @param no_partial: if true, only complete messages and not a partial
|
||||
* one (with only the start of the CNAME chain and not the rest).
|
||||
* one (with only the start of the CNAME chain and not the rest).
|
||||
* @return new response message (alloced in region, rrsets do not have IDs).
|
||||
* or NULL on error or if not found in cache.
|
||||
* TTLs are made relative to the current time.
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include "config.h"
|
||||
#include "services/localzone.h"
|
||||
#include "sldns/str2wire.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/dname.h"
|
||||
@ -395,9 +394,30 @@ rrset_insert_rr(struct regional* region, struct packed_rrset_data* pd,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** find a data node by exact name */
|
||||
static struct local_data*
|
||||
lz_find_node(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs)
|
||||
/** Delete RR from local-zone RRset, wastes memory as the deleted RRs cannot be
|
||||
* free'd (regionally alloc'd) */
|
||||
int
|
||||
local_rrset_remove_rr(struct packed_rrset_data* pd, size_t index)
|
||||
{
|
||||
log_assert(pd->count > 0);
|
||||
if(index >= pd->count) {
|
||||
log_warn("Trying to remove RR with out of bound index");
|
||||
return 0;
|
||||
}
|
||||
if(index + 1 < pd->count) {
|
||||
/* not removing last element */
|
||||
size_t nexti = index + 1;
|
||||
size_t num = pd->count - nexti;
|
||||
memmove(pd->rr_len+index, pd->rr_len+nexti, sizeof(*pd->rr_len)*num);
|
||||
memmove(pd->rr_ttl+index, pd->rr_ttl+nexti, sizeof(*pd->rr_ttl)*num);
|
||||
memmove(pd->rr_data+index, pd->rr_data+nexti, sizeof(*pd->rr_data)*num);
|
||||
}
|
||||
pd->count--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct local_data*
|
||||
local_zone_find_data(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs)
|
||||
{
|
||||
struct local_data key;
|
||||
key.node.key = &key;
|
||||
@ -412,7 +432,7 @@ static int
|
||||
lz_find_create_node(struct local_zone* z, uint8_t* nm, size_t nmlen,
|
||||
int nmlabs, struct local_data** res)
|
||||
{
|
||||
struct local_data* ld = lz_find_node(z, nm, nmlen, nmlabs);
|
||||
struct local_data* ld = local_zone_find_data(z, nm, nmlen, nmlabs);
|
||||
if(!ld) {
|
||||
/* create a domain name to store rr. */
|
||||
ld = (struct local_data*)regional_alloc_zero(z->region,
|
||||
@ -443,42 +463,19 @@ lz_find_create_node(struct local_zone* z, uint8_t* nm, size_t nmlen,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** enter data RR into auth zone */
|
||||
static int
|
||||
lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
|
||||
int
|
||||
local_zone_enter_rr(struct local_zone* z, uint8_t* nm, size_t nmlen,
|
||||
int nmlabs, uint16_t rrtype, uint16_t rrclass, time_t ttl,
|
||||
uint8_t* rdata, size_t rdata_len, const char* rrstr)
|
||||
{
|
||||
uint8_t* nm;
|
||||
size_t nmlen;
|
||||
int nmlabs;
|
||||
struct local_data* node;
|
||||
struct local_rrset* rrset;
|
||||
struct packed_rrset_data* pd;
|
||||
uint16_t rrtype = 0, rrclass = 0;
|
||||
time_t ttl = 0;
|
||||
uint8_t rr[LDNS_RR_BUF_SIZE];
|
||||
uint8_t* rdata;
|
||||
size_t rdata_len;
|
||||
if(!rrstr_get_rr_content(rrstr, &nm, &rrtype, &rrclass, &ttl, rr,
|
||||
sizeof(rr), &rdata, &rdata_len)) {
|
||||
log_err("bad local-data: %s", rrstr);
|
||||
return 0;
|
||||
}
|
||||
log_assert(z->dclass == rrclass);
|
||||
if((z->type == local_zone_redirect ||
|
||||
z->type == local_zone_inform_redirect) &&
|
||||
query_dname_compare(z->name, nm) != 0) {
|
||||
log_err("local-data in redirect zone must reside at top of zone"
|
||||
", not at %s", rrstr);
|
||||
free(nm);
|
||||
return 0;
|
||||
}
|
||||
nmlabs = dname_count_size_labels(nm, &nmlen);
|
||||
|
||||
if(!lz_find_create_node(z, nm, nmlen, nmlabs, &node)) {
|
||||
free(nm);
|
||||
return 0;
|
||||
}
|
||||
log_assert(node);
|
||||
free(nm);
|
||||
|
||||
/* Reject it if we would end up having CNAME and other data (including
|
||||
* another CNAME) for a redirect zone. */
|
||||
@ -520,6 +517,39 @@ lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
|
||||
return rrset_insert_rr(z->region, pd, rdata, rdata_len, ttl, rrstr);
|
||||
}
|
||||
|
||||
/** enter data RR into auth zone */
|
||||
int
|
||||
lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
|
||||
{
|
||||
uint8_t* nm;
|
||||
size_t nmlen;
|
||||
int nmlabs, ret;
|
||||
uint16_t rrtype = 0, rrclass = 0;
|
||||
time_t ttl = 0;
|
||||
uint8_t rr[LDNS_RR_BUF_SIZE];
|
||||
uint8_t* rdata;
|
||||
size_t rdata_len;
|
||||
if(!rrstr_get_rr_content(rrstr, &nm, &rrtype, &rrclass, &ttl, rr,
|
||||
sizeof(rr), &rdata, &rdata_len)) {
|
||||
log_err("bad local-data: %s", rrstr);
|
||||
return 0;
|
||||
}
|
||||
log_assert(z->dclass == rrclass);
|
||||
if((z->type == local_zone_redirect ||
|
||||
z->type == local_zone_inform_redirect) &&
|
||||
query_dname_compare(z->name, nm) != 0) {
|
||||
log_err("local-data in redirect zone must reside at top of zone"
|
||||
", not at %s", rrstr);
|
||||
free(nm);
|
||||
return 0;
|
||||
}
|
||||
nmlabs = dname_count_size_labels(nm, &nmlen);
|
||||
ret = local_zone_enter_rr(z, nm, nmlen, nmlabs, rrtype, rrclass, ttl,
|
||||
rdata, rdata_len, rrstr);
|
||||
free(nm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** enter a data RR into auth data; a zone for it must exist */
|
||||
static int
|
||||
lz_enter_rr_str(struct local_zones* zones, const char* rr)
|
||||
@ -823,12 +853,12 @@ int local_zone_enter_defaults(struct local_zones* zones, struct config_file* cfg
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* test. zone (RFC 7686) */
|
||||
/* test. zone (RFC 6761) */
|
||||
if(!add_empty_default(zones, cfg, "test.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* invalid. zone (RFC 7686) */
|
||||
/* invalid. zone (RFC 6761) */
|
||||
if(!add_empty_default(zones, cfg, "invalid.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
@ -1113,6 +1143,22 @@ local_zones_find(struct local_zones* zones,
|
||||
return (struct local_zone*)rbtree_search(&zones->ztree, &key);
|
||||
}
|
||||
|
||||
struct local_zone*
|
||||
local_zones_find_le(struct local_zones* zones,
|
||||
uint8_t* name, size_t len, int labs, uint16_t dclass,
|
||||
int* exact)
|
||||
{
|
||||
struct local_zone key;
|
||||
rbnode_type *node;
|
||||
key.node.key = &key;
|
||||
key.dclass = dclass;
|
||||
key.name = name;
|
||||
key.namelen = len;
|
||||
key.namelabs = labs;
|
||||
*exact = rbtree_find_less_equal(&zones->ztree, &key, &node);
|
||||
return (struct local_zone*)node;
|
||||
}
|
||||
|
||||
/** print all RRsets in local zone */
|
||||
static void
|
||||
local_zone_out(struct local_zone* z)
|
||||
@ -1309,8 +1355,7 @@ find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
|
||||
return result;
|
||||
}
|
||||
|
||||
/** answer local data match */
|
||||
static int
|
||||
int
|
||||
local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns,
|
||||
struct comm_reply* repinfo, sldns_buffer* buf,
|
||||
@ -1362,16 +1407,69 @@ local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
lz_type == local_zone_inform_redirect) &&
|
||||
qinfo->qtype != LDNS_RR_TYPE_CNAME &&
|
||||
lr->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME)) {
|
||||
uint8_t* ctarget;
|
||||
size_t ctargetlen = 0;
|
||||
|
||||
qinfo->local_alias =
|
||||
regional_alloc_zero(temp, sizeof(struct local_rrset));
|
||||
if(!qinfo->local_alias)
|
||||
return 0; /* out of memory */
|
||||
qinfo->local_alias->rrset =
|
||||
regional_alloc_init(temp, lr->rrset, sizeof(*lr->rrset));
|
||||
qinfo->local_alias->rrset = regional_alloc_init(
|
||||
temp, lr->rrset, sizeof(*lr->rrset));
|
||||
if(!qinfo->local_alias->rrset)
|
||||
return 0; /* out of memory */
|
||||
qinfo->local_alias->rrset->rk.dname = qinfo->qname;
|
||||
qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
|
||||
get_cname_target(lr->rrset, &ctarget, &ctargetlen);
|
||||
if(!ctargetlen)
|
||||
return 0; /* invalid cname */
|
||||
if(dname_is_wild(ctarget)) {
|
||||
/* synthesize cname target */
|
||||
struct packed_rrset_data* d;
|
||||
/* -3 for wildcard label and root label from qname */
|
||||
size_t newtargetlen = qinfo->qname_len + ctargetlen - 3;
|
||||
|
||||
log_assert(ctargetlen >= 3);
|
||||
log_assert(qinfo->qname_len >= 1);
|
||||
|
||||
if(newtargetlen > LDNS_MAX_DOMAINLEN) {
|
||||
qinfo->local_alias = NULL;
|
||||
local_error_encode(qinfo, env, edns, repinfo,
|
||||
buf, temp, LDNS_RCODE_YXDOMAIN,
|
||||
(LDNS_RCODE_YXDOMAIN|BIT_AA));
|
||||
return 1;
|
||||
}
|
||||
memset(&qinfo->local_alias->rrset->entry, 0,
|
||||
sizeof(qinfo->local_alias->rrset->entry));
|
||||
qinfo->local_alias->rrset->entry.key =
|
||||
qinfo->local_alias->rrset;
|
||||
qinfo->local_alias->rrset->entry.hash =
|
||||
rrset_key_hash(&qinfo->local_alias->rrset->rk);
|
||||
d = (struct packed_rrset_data*)regional_alloc_zero(temp,
|
||||
sizeof(struct packed_rrset_data) + sizeof(size_t) +
|
||||
sizeof(uint8_t*) + sizeof(time_t) + sizeof(uint16_t)
|
||||
+ newtargetlen);
|
||||
if(!d)
|
||||
return 0; /* out of memory */
|
||||
qinfo->local_alias->rrset->entry.data = d;
|
||||
d->ttl = 0; /* 0 for synthesized CNAME TTL */
|
||||
d->count = 1;
|
||||
d->rrsig_count = 0;
|
||||
d->trust = rrset_trust_ans_noAA;
|
||||
d->rr_len = (size_t*)((uint8_t*)d +
|
||||
sizeof(struct packed_rrset_data));
|
||||
d->rr_len[0] = newtargetlen + sizeof(uint16_t);
|
||||
packed_rrset_ptr_fixup(d);
|
||||
d->rr_ttl[0] = d->ttl;
|
||||
sldns_write_uint16(d->rr_data[0], newtargetlen);
|
||||
/* write qname */
|
||||
memmove(d->rr_data[0] + sizeof(uint16_t), qinfo->qname,
|
||||
qinfo->qname_len - 1);
|
||||
/* write cname target wilcard wildcard label */
|
||||
memmove(d->rr_data[0] + sizeof(uint16_t) +
|
||||
qinfo->qname_len - 1, ctarget + 2,
|
||||
ctargetlen - 2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if(lz_type == local_zone_redirect ||
|
||||
@ -1416,26 +1514,15 @@ local_zone_does_not_cover(struct local_zone* z, struct query_info* qinfo,
|
||||
return (lr == NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Answer in case where no exact match is found.
|
||||
* @param z: zone for query.
|
||||
* @param env: module environment.
|
||||
* @param qinfo: query.
|
||||
* @param edns: edns from query.
|
||||
* @param repinfo: source address for checks. may be NULL.
|
||||
* @param buf: buffer for answer.
|
||||
* @param temp: temp region for encoding.
|
||||
* @param ld: local data, if NULL, no such name exists in localdata.
|
||||
* @param lz_type: type of the local zone.
|
||||
* @return 1 if a reply is to be sent, 0 if not.
|
||||
*/
|
||||
static int
|
||||
lz_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
int
|
||||
local_zones_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns,
|
||||
struct comm_reply* repinfo, sldns_buffer* buf, struct regional* temp,
|
||||
struct local_data* ld, enum localzone_type lz_type)
|
||||
{
|
||||
if(lz_type == local_zone_deny || lz_type == local_zone_inform_deny) {
|
||||
if(lz_type == local_zone_deny ||
|
||||
lz_type == local_zone_always_deny ||
|
||||
lz_type == local_zone_inform_deny) {
|
||||
/** no reply at all, signal caller by clearing buffer. */
|
||||
sldns_buffer_clear(buf);
|
||||
sldns_buffer_flip(buf);
|
||||
@ -1448,7 +1535,8 @@ lz_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
} else if(lz_type == local_zone_static ||
|
||||
lz_type == local_zone_redirect ||
|
||||
lz_type == local_zone_inform_redirect ||
|
||||
lz_type == local_zone_always_nxdomain) {
|
||||
lz_type == local_zone_always_nxdomain ||
|
||||
lz_type == local_zone_always_nodata) {
|
||||
/* for static, reply nodata or nxdomain
|
||||
* for redirect, reply nodata */
|
||||
/* no additional section processing,
|
||||
@ -1457,7 +1545,8 @@ lz_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
* or using closest match for returning delegation downwards
|
||||
*/
|
||||
int rcode = (ld || lz_type == local_zone_redirect ||
|
||||
lz_type == local_zone_inform_redirect)?
|
||||
lz_type == local_zone_inform_redirect ||
|
||||
lz_type == local_zone_always_nodata)?
|
||||
LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
|
||||
if(z->soa)
|
||||
return local_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
@ -1640,6 +1729,8 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
if(lzt != local_zone_always_refuse
|
||||
&& lzt != local_zone_always_transparent
|
||||
&& lzt != local_zone_always_nxdomain
|
||||
&& lzt != local_zone_always_nodata
|
||||
&& lzt != local_zone_always_deny
|
||||
&& local_data_answer(z, env, qinfo, edns, repinfo, buf, temp, labs,
|
||||
&ld, lzt, tag, tag_datas, tag_datas_size, tagname, num_tags)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
@ -1647,7 +1738,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
* a local alias. */
|
||||
return !qinfo->local_alias;
|
||||
}
|
||||
r = lz_zone_answer(z, env, qinfo, edns, repinfo, buf, temp, ld, lzt);
|
||||
r = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp, ld, lzt);
|
||||
lock_rw_unlock(&z->lock);
|
||||
return r && !qinfo->local_alias; /* see above */
|
||||
}
|
||||
@ -1669,7 +1760,10 @@ const char* local_zone_type2str(enum localzone_type t)
|
||||
case local_zone_always_transparent: return "always_transparent";
|
||||
case local_zone_always_refuse: return "always_refuse";
|
||||
case local_zone_always_nxdomain: return "always_nxdomain";
|
||||
case local_zone_always_nodata: return "always_nodata";
|
||||
case local_zone_always_deny: return "always_deny";
|
||||
case local_zone_noview: return "noview";
|
||||
case local_zone_invalid: return "invalid";
|
||||
}
|
||||
return "badtyped";
|
||||
}
|
||||
@ -1700,6 +1794,10 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
|
||||
*t = local_zone_always_refuse;
|
||||
else if(strcmp(type, "always_nxdomain") == 0)
|
||||
*t = local_zone_always_nxdomain;
|
||||
else if(strcmp(type, "always_nodata") == 0)
|
||||
*t = local_zone_always_nodata;
|
||||
else if(strcmp(type, "always_deny") == 0)
|
||||
*t = local_zone_always_deny;
|
||||
else if(strcmp(type, "noview") == 0)
|
||||
*t = local_zone_noview;
|
||||
else if(strcmp(type, "nodefault") == 0)
|
||||
@ -1843,7 +1941,7 @@ del_empty_term(struct local_zone* z, struct local_data* d,
|
||||
return;
|
||||
dname_remove_label(&name, &len);
|
||||
labs--;
|
||||
d = lz_find_node(z, name, len, labs);
|
||||
d = local_zone_find_data(z, name, len, labs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1876,7 +1974,7 @@ void local_zones_del_data(struct local_zones* zones,
|
||||
z = local_zones_lookup(zones, name, len, labs, dclass, LDNS_RR_TYPE_DS);
|
||||
if(z) {
|
||||
lock_rw_wrlock(&z->lock);
|
||||
d = lz_find_node(z, name, len, labs);
|
||||
d = local_zone_find_data(z, name, len, labs);
|
||||
if(d) {
|
||||
del_local_rrset(d, LDNS_RR_TYPE_DS);
|
||||
del_empty_term(z, d, name, len, labs);
|
||||
@ -1897,7 +1995,7 @@ void local_zones_del_data(struct local_zones* zones,
|
||||
lock_rw_unlock(&zones->lock);
|
||||
|
||||
/* find the domain */
|
||||
d = lz_find_node(z, name, len, labs);
|
||||
d = local_zone_find_data(z, name, len, labs);
|
||||
if(d) {
|
||||
/* no memory recycling for zone deletions ... */
|
||||
d->rrsets = NULL;
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "util/module.h"
|
||||
#include "services/view.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
struct packed_rrset_data;
|
||||
struct ub_packed_rrset_key;
|
||||
struct regional;
|
||||
@ -91,8 +92,14 @@ enum localzone_type {
|
||||
local_zone_always_refuse,
|
||||
/** answer with nxdomain, even when there is local data */
|
||||
local_zone_always_nxdomain,
|
||||
/** answer with noerror/nodata, even when there is local data */
|
||||
local_zone_always_nodata,
|
||||
/** drop query, even when there is local data */
|
||||
local_zone_always_deny,
|
||||
/** answer not from the view, but global or no-answer */
|
||||
local_zone_noview
|
||||
local_zone_noview,
|
||||
/** Invalid type, cannot be used to generate answer */
|
||||
local_zone_invalid
|
||||
};
|
||||
|
||||
/**
|
||||
@ -310,6 +317,25 @@ int local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
struct config_strlist** tag_datas, size_t tag_datas_size,
|
||||
char** tagname, int num_tags, struct view* view);
|
||||
|
||||
/**
|
||||
* Answer using the local zone only (not local data used).
|
||||
* @param z: zone for query.
|
||||
* @param env: module environment.
|
||||
* @param qinfo: query.
|
||||
* @param edns: edns from query.
|
||||
* @param repinfo: source address for checks. may be NULL.
|
||||
* @param buf: buffer for answer.
|
||||
* @param temp: temp region for encoding.
|
||||
* @param ld: local data, if NULL, no such name exists in localdata.
|
||||
* @param lz_type: type of the local zone.
|
||||
* @return 1 if a reply is to be sent, 0 if not.
|
||||
*/
|
||||
int
|
||||
local_zones_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns,
|
||||
struct comm_reply* repinfo, sldns_buffer* buf, struct regional* temp,
|
||||
struct local_data* ld, enum localzone_type lz_type);
|
||||
|
||||
/**
|
||||
* Parse the string into localzone type.
|
||||
*
|
||||
@ -340,6 +366,22 @@ const char* local_zone_type2str(enum localzone_type t);
|
||||
struct local_zone* local_zones_find(struct local_zones* zones,
|
||||
uint8_t* name, size_t len, int labs, uint16_t dclass);
|
||||
|
||||
/**
|
||||
* Find zone that with exactly or smaller name/class
|
||||
* User must lock the tree or result zone.
|
||||
* @param zones: the zones tree
|
||||
* @param name: dname to lookup
|
||||
* @param len: length of name.
|
||||
* @param labs: labelcount of name.
|
||||
* @param dclass: class to lookup.
|
||||
* @param exact: 1 on return is this is an exact match.
|
||||
* @return the exact or smaller local_zone or NULL.
|
||||
*/
|
||||
struct local_zone*
|
||||
local_zones_find_le(struct local_zones* zones,
|
||||
uint8_t* name, size_t len, int labs, uint16_t dclass,
|
||||
int* exact);
|
||||
|
||||
/**
|
||||
* Add a new zone. Caller must hold the zones lock.
|
||||
* Adjusts the other zones as well (parent pointers) after insertion.
|
||||
@ -473,6 +515,15 @@ int rrstr_get_rr_content(const char* str, uint8_t** nm, uint16_t* type,
|
||||
int rrset_insert_rr(struct regional* region, struct packed_rrset_data* pd,
|
||||
uint8_t* rdata, size_t rdata_len, time_t ttl, const char* rrstr);
|
||||
|
||||
/**
|
||||
* Remove RR from rrset that is created using localzone's rrset_insert_rr.
|
||||
* @param pd: the RRset containing the RR to remove
|
||||
* @param index: index of RR to remove
|
||||
* @return: 1 on success; 0 otherwise.
|
||||
*/
|
||||
int
|
||||
local_rrset_remove_rr(struct packed_rrset_data* pd, size_t index);
|
||||
|
||||
/**
|
||||
* Valid response ip actions for the IP-response-driven-action feature;
|
||||
* defined here instead of in the respip module to enable sharing of enum
|
||||
@ -501,6 +552,10 @@ enum respip_action {
|
||||
respip_always_refuse = local_zone_always_refuse,
|
||||
/** answer with 'no such domain' response */
|
||||
respip_always_nxdomain = local_zone_always_nxdomain,
|
||||
/** answer with nodata response */
|
||||
respip_always_nodata = local_zone_always_nodata,
|
||||
/** answer with nodata response */
|
||||
respip_always_deny = local_zone_always_deny,
|
||||
|
||||
/* The rest of the values are only possible as
|
||||
* access-control-tag-action */
|
||||
@ -513,6 +568,64 @@ enum respip_action {
|
||||
respip_transparent = local_zone_transparent,
|
||||
/** gives response data (if any), else nodata answer. */
|
||||
respip_typetransparent = local_zone_typetransparent,
|
||||
/** type invalid */
|
||||
respip_invalid = local_zone_invalid,
|
||||
};
|
||||
|
||||
/**
|
||||
* Get local data from local zone and encode answer.
|
||||
* @param z: local zone to use
|
||||
* @param env: module env
|
||||
* @param qinfo: qinfo
|
||||
* @param edns: edns data, for message encoding
|
||||
* @param repinfo: reply info, for message encoding
|
||||
* @param buf: commpoint buffer
|
||||
* @param temp: scratchpad region
|
||||
* @param labs: number of labels in qname
|
||||
* @param ldp: where to store local data
|
||||
* @param lz_type: type of local zone
|
||||
* @param tag: matching tag index
|
||||
* @param tag_datas: alc specific tag data list
|
||||
* @param tag_datas_size: size of tag_datas
|
||||
* @param tagname: list of names of tags, for logging purpose
|
||||
* @param num_tags: number of tags
|
||||
* @return 1 on success
|
||||
*/
|
||||
int
|
||||
local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns,
|
||||
struct comm_reply* repinfo, sldns_buffer* buf,
|
||||
struct regional* temp, int labs, struct local_data** ldp,
|
||||
enum localzone_type lz_type, int tag, struct config_strlist** tag_datas,
|
||||
size_t tag_datas_size, char** tagname, int num_tags);
|
||||
|
||||
/**
|
||||
* Add RR to local zone.
|
||||
* @param z: local zone to add RR to
|
||||
* @param nm: dname of RR
|
||||
* @param nmlen: length of nm
|
||||
* @param nmlabs: number of labels of nm
|
||||
* @param rrtype: RR type
|
||||
* @param rrclass: RR class
|
||||
* @param ttl: TTL of RR to add
|
||||
* @param rdata: RDATA of RR to add
|
||||
* @param rdata_len: length of rdata
|
||||
* @param rrstr: RR in string format, for logging
|
||||
* @return: 1 on success
|
||||
*/
|
||||
int
|
||||
local_zone_enter_rr(struct local_zone* z, uint8_t* nm, size_t nmlen,
|
||||
int nmlabs, uint16_t rrtype, uint16_t rrclass, time_t ttl,
|
||||
uint8_t* rdata, size_t rdata_len, const char* rrstr);
|
||||
|
||||
/**
|
||||
* Find a data node by exact name for a local zone
|
||||
* @param z: local_zone containing data tree
|
||||
* @param nm: name of local-data element to find
|
||||
* @param nmlen: length of nm
|
||||
* @param nmlabs: labs of nm
|
||||
* @return local_data on exact match, NULL otherwise.
|
||||
*/
|
||||
struct local_data*
|
||||
local_zone_find_data(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs);
|
||||
#endif /* SERVICES_LOCALZONE_H */
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "services/mesh.h"
|
||||
#include "services/outbound_list.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "util/log.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/module.h"
|
||||
@ -127,7 +128,7 @@ timeval_smaller(const struct timeval* x, const struct timeval* y)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Compare two response-ip client info entries for the purpose of mesh state
|
||||
* compare. It returns 0 if ci_a and ci_b are considered equal; otherwise
|
||||
* 1 or -1 (they mean 'ci_a is larger/smaller than ci_b', respectively, but
|
||||
@ -250,6 +251,7 @@ mesh_create(struct module_stack* stack, struct module_env* env)
|
||||
mesh->num_forever_states = 0;
|
||||
mesh->stats_jostled = 0;
|
||||
mesh->stats_dropped = 0;
|
||||
mesh->ans_expired = 0;
|
||||
mesh->max_reply_states = env->cfg->num_queries_per_thread;
|
||||
mesh->max_forever_states = (mesh->max_reply_states+1)/2;
|
||||
#ifndef S_SPLINT_S
|
||||
@ -345,6 +347,97 @@ int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dns_msg*
|
||||
mesh_serve_expired_lookup(struct module_qstate* qstate,
|
||||
struct query_info* lookup_qinfo)
|
||||
{
|
||||
hashvalue_type h;
|
||||
struct lruhash_entry* e;
|
||||
struct dns_msg* msg;
|
||||
struct reply_info* data;
|
||||
struct msgreply_entry* key;
|
||||
time_t timenow = *qstate->env->now;
|
||||
int must_validate = (!(qstate->query_flags&BIT_CD)
|
||||
|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
|
||||
/* Lookup cache */
|
||||
h = query_info_hash(lookup_qinfo, qstate->query_flags);
|
||||
e = slabhash_lookup(qstate->env->msg_cache, h, lookup_qinfo, 0);
|
||||
if(!e) return NULL;
|
||||
|
||||
key = (struct msgreply_entry*)e->key;
|
||||
data = (struct reply_info*)e->data;
|
||||
msg = tomsg(qstate->env, &key->key, data, qstate->region, timenow,
|
||||
qstate->env->cfg->serve_expired, qstate->env->scratch);
|
||||
if(!msg)
|
||||
goto bail_out;
|
||||
|
||||
/* Check CNAME chain (if any)
|
||||
* This is part of tomsg above; no need to check now. */
|
||||
|
||||
/* Check security status of the cached answer.
|
||||
* tomsg above has a subset of these checks, so we are leaving
|
||||
* these as is.
|
||||
* In case of bogus or revalidation we don't care to reply here. */
|
||||
if(must_validate && (msg->rep->security == sec_status_bogus ||
|
||||
msg->rep->security == sec_status_secure_sentinel_fail)) {
|
||||
verbose(VERB_ALGO, "Serve expired: bogus answer found in cache");
|
||||
goto bail_out;
|
||||
} else if(msg->rep->security == sec_status_unchecked && must_validate) {
|
||||
verbose(VERB_ALGO, "Serve expired: unchecked entry needs "
|
||||
"validation");
|
||||
goto bail_out; /* need to validate cache entry first */
|
||||
} else if(msg->rep->security == sec_status_secure &&
|
||||
!reply_all_rrsets_secure(msg->rep) && must_validate) {
|
||||
verbose(VERB_ALGO, "Serve expired: secure entry"
|
||||
" changed status");
|
||||
goto bail_out; /* rrset changed, re-verify */
|
||||
}
|
||||
|
||||
lock_rw_unlock(&e->lock);
|
||||
return msg;
|
||||
|
||||
bail_out:
|
||||
lock_rw_unlock(&e->lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/** Init the serve expired data structure */
|
||||
static int
|
||||
mesh_serve_expired_init(struct mesh_state* mstate, int timeout)
|
||||
{
|
||||
struct timeval t;
|
||||
|
||||
/* Create serve_expired_data if not there yet */
|
||||
if(!mstate->s.serve_expired_data) {
|
||||
mstate->s.serve_expired_data = (struct serve_expired_data*)
|
||||
regional_alloc_zero(
|
||||
mstate->s.region, sizeof(struct serve_expired_data));
|
||||
if(!mstate->s.serve_expired_data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Don't overwrite the function if already set */
|
||||
mstate->s.serve_expired_data->get_cached_answer =
|
||||
mstate->s.serve_expired_data->get_cached_answer?
|
||||
mstate->s.serve_expired_data->get_cached_answer:
|
||||
mesh_serve_expired_lookup;
|
||||
|
||||
/* In case this timer already popped, start it again */
|
||||
if(!mstate->s.serve_expired_data->timer) {
|
||||
mstate->s.serve_expired_data->timer = comm_timer_create(
|
||||
mstate->s.env->worker_base, mesh_serve_expired_callback, mstate);
|
||||
if(!mstate->s.serve_expired_data->timer)
|
||||
return 0;
|
||||
#ifndef S_SPLINT_S
|
||||
t.tv_sec = timeout/1000;
|
||||
t.tv_usec = (timeout%1000)*1000;
|
||||
#endif
|
||||
comm_timer_set(mstate->s.serve_expired_data->timer, &t);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
struct respip_client_info* cinfo, uint16_t qflags,
|
||||
struct edns_data* edns, struct comm_reply* rep, uint16_t qid)
|
||||
@ -354,6 +447,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
int was_detached = 0;
|
||||
int was_noreply = 0;
|
||||
int added = 0;
|
||||
int timeout = mesh->env->cfg->serve_expired?
|
||||
mesh->env->cfg->serve_expired_client_timeout:0;
|
||||
struct sldns_buffer* r_buffer = rep->c->buffer;
|
||||
if(rep->c->tcp_req_info) {
|
||||
r_buffer = rep->c->tcp_req_info->spool_buffer;
|
||||
@ -366,7 +461,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
verbose(VERB_ALGO, "Too many queries. dropping "
|
||||
"incoming query.");
|
||||
comm_point_drop_reply(rep);
|
||||
mesh->stats_dropped ++;
|
||||
mesh->stats_dropped++;
|
||||
return;
|
||||
}
|
||||
/* for this new reply state, the reply address is free,
|
||||
@ -376,8 +471,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
if(mesh->num_reply_addrs > mesh->max_reply_states*16) {
|
||||
verbose(VERB_ALGO, "Too many requests queued. "
|
||||
"dropping incoming query.");
|
||||
mesh->stats_dropped++;
|
||||
comm_point_drop_reply(rep);
|
||||
mesh->stats_dropped++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -427,23 +522,16 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
mesh->num_detached_states++;
|
||||
added = 1;
|
||||
}
|
||||
if(!s->reply_list && !s->cb_list && s->super_set.count == 0)
|
||||
was_detached = 1;
|
||||
if(!s->reply_list && !s->cb_list)
|
||||
if(!s->reply_list && !s->cb_list) {
|
||||
was_noreply = 1;
|
||||
if(s->super_set.count == 0) {
|
||||
was_detached = 1;
|
||||
}
|
||||
}
|
||||
/* add reply to s */
|
||||
if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo)) {
|
||||
log_err("mesh_new_client: out of memory; SERVFAIL");
|
||||
servfail_mem:
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s,
|
||||
NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
comm_point_send_reply(rep);
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
return;
|
||||
log_err("mesh_new_client: out of memory; SERVFAIL");
|
||||
goto servfail_mem;
|
||||
}
|
||||
if(rep->c->tcp_req_info) {
|
||||
if(!tcp_req_info_add_meshstate(rep->c->tcp_req_info, mesh, s)) {
|
||||
@ -451,6 +539,11 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
goto servfail_mem;
|
||||
}
|
||||
}
|
||||
/* add serve expired timer if required and not already there */
|
||||
if(timeout && !mesh_serve_expired_init(s, timeout)) {
|
||||
log_err("mesh_new_client: out of memory initializing serve expired");
|
||||
goto servfail_mem;
|
||||
}
|
||||
/* update statistics */
|
||||
if(was_detached) {
|
||||
log_assert(mesh->num_detached_states > 0);
|
||||
@ -475,6 +568,18 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
}
|
||||
if(added)
|
||||
mesh_run(mesh, s, module_event_new, NULL);
|
||||
return;
|
||||
|
||||
servfail_mem:
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s,
|
||||
NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
comm_point_send_reply(rep);
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
@ -484,6 +589,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
{
|
||||
struct mesh_state* s = NULL;
|
||||
int unique = unique_mesh_state(edns->opt_list, mesh->env);
|
||||
int timeout = mesh->env->cfg->serve_expired?
|
||||
mesh->env->cfg->serve_expired_client_timeout:0;
|
||||
int was_detached = 0;
|
||||
int was_noreply = 0;
|
||||
int added = 0;
|
||||
@ -522,15 +629,21 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
mesh->num_detached_states++;
|
||||
added = 1;
|
||||
}
|
||||
if(!s->reply_list && !s->cb_list && s->super_set.count == 0)
|
||||
was_detached = 1;
|
||||
if(!s->reply_list && !s->cb_list)
|
||||
if(!s->reply_list && !s->cb_list) {
|
||||
was_noreply = 1;
|
||||
if(s->super_set.count == 0) {
|
||||
was_detached = 1;
|
||||
}
|
||||
}
|
||||
/* add reply to s */
|
||||
if(!mesh_state_add_cb(s, edns, buf, cb, cb_arg, qid, qflags)) {
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
}
|
||||
/* add serve expired timer if not already there */
|
||||
if(timeout && !mesh_serve_expired_init(s, timeout)) {
|
||||
return 0;
|
||||
}
|
||||
/* update statistics */
|
||||
if(was_detached) {
|
||||
@ -546,15 +659,6 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void mesh_schedule_prefetch(struct mesh_area* mesh,
|
||||
struct query_info* qinfo, uint16_t qflags, time_t leeway, int run);
|
||||
|
||||
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, time_t leeway)
|
||||
{
|
||||
mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1);
|
||||
}
|
||||
|
||||
/* Internal backend routine of mesh_new_prefetch(). It takes one additional
|
||||
* parameter, 'run', which controls whether to run the prefetch state
|
||||
* immediately. When this function is called internally 'run' could be
|
||||
@ -631,6 +735,12 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
|
||||
mesh_run(mesh, s, module_event_new, NULL);
|
||||
}
|
||||
|
||||
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, time_t leeway)
|
||||
{
|
||||
mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1);
|
||||
}
|
||||
|
||||
void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
|
||||
struct comm_reply* reply, int what)
|
||||
{
|
||||
@ -703,6 +813,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
mstate->s.env = env;
|
||||
mstate->s.mesh_info = mstate;
|
||||
mstate->s.prefetch_leeway = 0;
|
||||
mstate->s.serve_expired_data = NULL;
|
||||
mstate->s.no_cache_lookup = 0;
|
||||
mstate->s.no_cache_store = 0;
|
||||
mstate->s.need_refetch = 0;
|
||||
@ -742,6 +853,11 @@ mesh_state_cleanup(struct mesh_state* mstate)
|
||||
if(!mstate)
|
||||
return;
|
||||
mesh = mstate->s.env->mesh;
|
||||
/* Stop and delete the serve expired timer */
|
||||
if(mstate->s.serve_expired_data && mstate->s.serve_expired_data->timer) {
|
||||
comm_timer_delete(mstate->s.serve_expired_data->timer);
|
||||
mstate->s.serve_expired_data->timer = NULL;
|
||||
}
|
||||
/* drop unsent replies */
|
||||
if(!mstate->replies_sent) {
|
||||
struct mesh_reply* rep = mstate->reply_list;
|
||||
@ -752,6 +868,7 @@ mesh_state_cleanup(struct mesh_state* mstate)
|
||||
mstate->reply_list = NULL;
|
||||
for(; rep; rep=rep->next) {
|
||||
comm_point_drop_reply(&rep->query_reply);
|
||||
log_assert(mesh->num_reply_addrs > 0);
|
||||
mesh->num_reply_addrs--;
|
||||
}
|
||||
while((cb = mstate->cb_list)!=NULL) {
|
||||
@ -759,6 +876,7 @@ mesh_state_cleanup(struct mesh_state* mstate)
|
||||
fptr_ok(fptr_whitelist_mesh_cb(cb->cb));
|
||||
(*cb->cb)(cb->cb_arg, LDNS_RCODE_SERVFAIL, NULL,
|
||||
sec_status_unchecked, NULL, 0);
|
||||
log_assert(mesh->num_reply_addrs > 0);
|
||||
mesh->num_reply_addrs--;
|
||||
}
|
||||
}
|
||||
@ -826,7 +944,7 @@ find_in_subsub(struct mesh_state* m, struct mesh_state* tofind, size_t *c)
|
||||
}
|
||||
|
||||
/** find cycle for already looked up mesh_state */
|
||||
static int
|
||||
static int
|
||||
mesh_detect_cycle_found(struct module_qstate* qstate, struct mesh_state* dep_m)
|
||||
{
|
||||
struct mesh_state* cyc_m = qstate->mesh_info;
|
||||
@ -1038,6 +1156,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
}
|
||||
}
|
||||
free(reason);
|
||||
log_assert(m->s.env->mesh->num_reply_addrs > 0);
|
||||
m->s.env->mesh->num_reply_addrs--;
|
||||
}
|
||||
|
||||
@ -1139,6 +1258,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
}
|
||||
/* account */
|
||||
log_assert(m->s.env->mesh->num_reply_addrs > 0);
|
||||
m->s.env->mesh->num_reply_addrs--;
|
||||
end_time = *m->s.env->now_tv;
|
||||
timeval_subtract(&duration, &end_time, &r->start_time);
|
||||
@ -1164,37 +1284,76 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
|
||||
void mesh_query_done(struct mesh_state* mstate)
|
||||
{
|
||||
struct mesh_reply* r;
|
||||
struct mesh_reply* r, *reply_list = NULL;
|
||||
struct mesh_reply* prev = NULL;
|
||||
struct sldns_buffer* prev_buffer = NULL;
|
||||
struct mesh_cb* c;
|
||||
struct reply_info* rep = (mstate->s.return_msg?
|
||||
mstate->s.return_msg->rep:NULL);
|
||||
if((mstate->s.return_rcode == LDNS_RCODE_SERVFAIL ||
|
||||
(rep && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_SERVFAIL))
|
||||
/* No need for the serve expired timer anymore; we are going to reply. */
|
||||
if(mstate->s.serve_expired_data) {
|
||||
comm_timer_delete(mstate->s.serve_expired_data->timer);
|
||||
mstate->s.serve_expired_data->timer = NULL;
|
||||
}
|
||||
if(mstate->s.return_rcode == LDNS_RCODE_SERVFAIL ||
|
||||
(rep && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_SERVFAIL)) {
|
||||
/* we are SERVFAILing; check for expired asnwer here */
|
||||
mesh_serve_expired_callback(mstate);
|
||||
if((mstate->reply_list || mstate->cb_list)
|
||||
&& mstate->s.env->cfg->log_servfail
|
||||
&& !mstate->s.env->cfg->val_log_squelch) {
|
||||
char* err = errinf_to_str_servfail(&mstate->s);
|
||||
if(err)
|
||||
log_err("%s", err);
|
||||
free(err);
|
||||
char* err = errinf_to_str_servfail(&mstate->s);
|
||||
if(err)
|
||||
log_err("%s", err);
|
||||
free(err);
|
||||
}
|
||||
}
|
||||
for(r = mstate->reply_list; r; r = r->next) {
|
||||
if(mstate->reply_list) {
|
||||
/* set the reply_list to NULL during the mesh_query_done
|
||||
* processing, so that calls back into the mesh from
|
||||
* tcp_req_info (deciding to drop the reply and thus
|
||||
* unregister the mesh_reply from the mstate) are stopped
|
||||
* because the list is empty.
|
||||
* The mstate is then likely not a reply_state, and maybe
|
||||
* also a detached_state.
|
||||
*/
|
||||
reply_list = mstate->reply_list;
|
||||
mstate->reply_list = NULL;
|
||||
if(!mstate->reply_list && !mstate->cb_list) {
|
||||
/* was a reply state, not anymore */
|
||||
log_assert(mstate->s.env->mesh->num_reply_states > 0);
|
||||
mstate->s.env->mesh->num_reply_states--;
|
||||
}
|
||||
if(!mstate->reply_list && !mstate->cb_list &&
|
||||
mstate->super_set.count == 0)
|
||||
mstate->s.env->mesh->num_detached_states++;
|
||||
}
|
||||
for(r = reply_list; r; r = r->next) {
|
||||
/* if a response-ip address block has been stored the
|
||||
* information should be logged for each client. */
|
||||
if(mstate->s.respip_action_info &&
|
||||
mstate->s.respip_action_info->addrinfo) {
|
||||
respip_inform_print(mstate->s.respip_action_info->addrinfo,
|
||||
respip_inform_print(mstate->s.respip_action_info,
|
||||
r->qname, mstate->s.qinfo.qtype,
|
||||
mstate->s.qinfo.qclass, r->local_alias,
|
||||
&r->query_reply);
|
||||
if(mstate->s.env->cfg->stat_extended &&
|
||||
mstate->s.respip_action_info->rpz_used) {
|
||||
if(mstate->s.respip_action_info->rpz_disabled)
|
||||
mstate->s.env->mesh->rpz_action[RPZ_DISABLED_ACTION]++;
|
||||
if(mstate->s.respip_action_info->rpz_cname_override)
|
||||
mstate->s.env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
|
||||
else
|
||||
mstate->s.env->mesh->rpz_action[respip_action_to_rpz_action(
|
||||
mstate->s.respip_action_info->action)]++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if this query is determined to be dropped during the
|
||||
* mesh processing, this is the point to take that action. */
|
||||
if(mstate->s.is_drop)
|
||||
if(mstate->s.is_drop) {
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
else {
|
||||
} else {
|
||||
struct sldns_buffer* r_buffer = r->query_reply.c->buffer;
|
||||
if(r->query_reply.c->tcp_req_info) {
|
||||
r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;
|
||||
@ -1216,6 +1375,7 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
* changed, eg. by adds from the callback routine */
|
||||
if(!mstate->reply_list && mstate->cb_list && !c->next) {
|
||||
/* was a reply state, not anymore */
|
||||
log_assert(mstate->s.env->mesh->num_reply_states > 0);
|
||||
mstate->s.env->mesh->num_reply_states--;
|
||||
}
|
||||
mstate->cb_list = c->next;
|
||||
@ -1581,7 +1741,9 @@ mesh_stats_clear(struct mesh_area* mesh)
|
||||
timehist_clear(mesh->histogram);
|
||||
mesh->ans_secure = 0;
|
||||
mesh->ans_bogus = 0;
|
||||
memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*16);
|
||||
mesh->ans_expired = 0;
|
||||
memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*UB_STATS_RCODE_NUM);
|
||||
memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM);
|
||||
mesh->ans_nodata = 0;
|
||||
}
|
||||
|
||||
@ -1647,6 +1809,7 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
||||
if(prev) prev->next = n->next;
|
||||
else m->reply_list = n->next;
|
||||
/* delete it, but allocated in m region */
|
||||
log_assert(mesh->num_reply_addrs > 0);
|
||||
mesh->num_reply_addrs--;
|
||||
|
||||
/* prev = prev; */
|
||||
@ -1667,3 +1830,176 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
||||
mesh->num_reply_states--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
apply_respip_action(struct module_qstate* qstate,
|
||||
const struct query_info* qinfo, struct respip_client_info* cinfo,
|
||||
struct respip_action_info* actinfo, struct reply_info* rep,
|
||||
struct ub_packed_rrset_key** alias_rrset,
|
||||
struct reply_info** encode_repp, struct auth_zones* az)
|
||||
{
|
||||
if(qinfo->qtype != LDNS_RR_TYPE_A &&
|
||||
qinfo->qtype != LDNS_RR_TYPE_AAAA &&
|
||||
qinfo->qtype != LDNS_RR_TYPE_ANY)
|
||||
return 1;
|
||||
|
||||
if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, actinfo,
|
||||
alias_rrset, 0, qstate->region, az))
|
||||
return 0;
|
||||
|
||||
/* xxx_deny actions mean dropping the reply, unless the original reply
|
||||
* was redirected to response-ip data. */
|
||||
if((actinfo->action == respip_deny ||
|
||||
actinfo->action == respip_inform_deny) &&
|
||||
*encode_repp == rep)
|
||||
*encode_repp = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
mesh_serve_expired_callback(void* arg)
|
||||
{
|
||||
struct mesh_state* mstate = (struct mesh_state*) arg;
|
||||
struct module_qstate* qstate = &mstate->s;
|
||||
struct mesh_reply* r;
|
||||
struct mesh_area* mesh = qstate->env->mesh;
|
||||
struct dns_msg* msg;
|
||||
struct mesh_cb* c;
|
||||
struct mesh_reply* prev = NULL;
|
||||
struct sldns_buffer* prev_buffer = NULL;
|
||||
struct sldns_buffer* r_buffer = NULL;
|
||||
struct reply_info* partial_rep = NULL;
|
||||
struct ub_packed_rrset_key* alias_rrset = NULL;
|
||||
struct reply_info* encode_rep = NULL;
|
||||
struct respip_action_info actinfo;
|
||||
struct query_info* lookup_qinfo = &qstate->qinfo;
|
||||
struct query_info qinfo_tmp;
|
||||
int must_validate = (!(qstate->query_flags&BIT_CD)
|
||||
|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
|
||||
if(!qstate->serve_expired_data) return;
|
||||
verbose(VERB_ALGO, "Serve expired: Trying to reply with expired data");
|
||||
comm_timer_delete(qstate->serve_expired_data->timer);
|
||||
qstate->serve_expired_data->timer = NULL;
|
||||
if(qstate->blacklist || qstate->no_cache_lookup || qstate->is_drop) {
|
||||
verbose(VERB_ALGO,
|
||||
"Serve expired: Not allowed to look into cache for stale");
|
||||
return;
|
||||
}
|
||||
/* The following while is used instead of the `goto lookup_cache`
|
||||
* like in the worker. */
|
||||
while(1) {
|
||||
fptr_ok(fptr_whitelist_serve_expired_lookup(
|
||||
qstate->serve_expired_data->get_cached_answer));
|
||||
msg = qstate->serve_expired_data->get_cached_answer(qstate,
|
||||
lookup_qinfo);
|
||||
if(!msg)
|
||||
return;
|
||||
/* Reset these in case we pass a second time from here. */
|
||||
encode_rep = msg->rep;
|
||||
memset(&actinfo, 0, sizeof(actinfo));
|
||||
actinfo.action = respip_none;
|
||||
alias_rrset = NULL;
|
||||
if((mesh->use_response_ip || mesh->use_rpz) &&
|
||||
!partial_rep && !apply_respip_action(qstate, &qstate->qinfo,
|
||||
qstate->client_info, &actinfo, msg->rep, &alias_rrset, &encode_rep,
|
||||
qstate->env->auth_zones)) {
|
||||
return;
|
||||
} else if(partial_rep &&
|
||||
!respip_merge_cname(partial_rep, &qstate->qinfo, msg->rep,
|
||||
qstate->client_info, must_validate, &encode_rep, qstate->region,
|
||||
qstate->env->auth_zones)) {
|
||||
return;
|
||||
}
|
||||
if(!encode_rep || alias_rrset) {
|
||||
if(!encode_rep) {
|
||||
/* Needs drop */
|
||||
return;
|
||||
} else {
|
||||
/* A partial CNAME chain is found. */
|
||||
partial_rep = encode_rep;
|
||||
}
|
||||
}
|
||||
/* We've found a partial reply ending with an
|
||||
* alias. Replace the lookup qinfo for the
|
||||
* alias target and lookup the cache again to
|
||||
* (possibly) complete the reply. As we're
|
||||
* passing the "base" reply, there will be no
|
||||
* more alias chasing. */
|
||||
if(partial_rep) {
|
||||
memset(&qinfo_tmp, 0, sizeof(qinfo_tmp));
|
||||
get_cname_target(alias_rrset, &qinfo_tmp.qname,
|
||||
&qinfo_tmp.qname_len);
|
||||
if(!qinfo_tmp.qname) {
|
||||
log_err("Serve expired: unexpected: invalid answer alias");
|
||||
return;
|
||||
}
|
||||
qinfo_tmp.qtype = qstate->qinfo.qtype;
|
||||
qinfo_tmp.qclass = qstate->qinfo.qclass;
|
||||
lookup_qinfo = &qinfo_tmp;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
|
||||
|
||||
r = mstate->reply_list;
|
||||
mstate->reply_list = NULL;
|
||||
if(!mstate->reply_list && !mstate->cb_list) {
|
||||
log_assert(mesh->num_reply_states > 0);
|
||||
mesh->num_reply_states--;
|
||||
if(mstate->super_set.count == 0) {
|
||||
mesh->num_detached_states++;
|
||||
}
|
||||
}
|
||||
for(; r; r = r->next) {
|
||||
/* If address info is returned, it means the action should be an
|
||||
* 'inform' variant and the information should be logged. */
|
||||
if(actinfo.addrinfo) {
|
||||
respip_inform_print(&actinfo, r->qname,
|
||||
qstate->qinfo.qtype, qstate->qinfo.qclass,
|
||||
r->local_alias, &r->query_reply);
|
||||
|
||||
if(qstate->env->cfg->stat_extended && actinfo.rpz_used) {
|
||||
if(actinfo.rpz_disabled)
|
||||
qstate->env->mesh->rpz_action[RPZ_DISABLED_ACTION]++;
|
||||
if(actinfo.rpz_cname_override)
|
||||
qstate->env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
|
||||
else
|
||||
qstate->env->mesh->rpz_action[
|
||||
respip_action_to_rpz_action(actinfo.action)]++;
|
||||
}
|
||||
}
|
||||
|
||||
r_buffer = r->query_reply.c->buffer;
|
||||
if(r->query_reply.c->tcp_req_info)
|
||||
r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;
|
||||
mesh_send_reply(mstate, LDNS_RCODE_NOERROR, msg->rep,
|
||||
r, r_buffer, prev, prev_buffer);
|
||||
if(r->query_reply.c->tcp_req_info)
|
||||
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
|
||||
prev = r;
|
||||
prev_buffer = r_buffer;
|
||||
|
||||
/* Account for each reply sent. */
|
||||
mesh->ans_expired++;
|
||||
|
||||
}
|
||||
while((c = mstate->cb_list) != NULL) {
|
||||
/* take this cb off the list; so that the list can be
|
||||
* changed, eg. by adds from the callback routine */
|
||||
if(!mstate->reply_list && mstate->cb_list && !c->next) {
|
||||
/* was a reply state, not anymore */
|
||||
log_assert(qstate->env->mesh->num_reply_states > 0);
|
||||
qstate->env->mesh->num_reply_states--;
|
||||
}
|
||||
mstate->cb_list = c->next;
|
||||
if(!mstate->reply_list && !mstate->cb_list &&
|
||||
mstate->super_set.count == 0)
|
||||
qstate->env->mesh->num_detached_states++;
|
||||
mesh_do_callback(mstate, LDNS_RCODE_NOERROR, msg->rep, c);
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,8 @@
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/module.h"
|
||||
#include "services/modstack.h"
|
||||
#include "services/rpz.h"
|
||||
#include "libunbound/unbound.h"
|
||||
struct sldns_buffer;
|
||||
struct mesh_state;
|
||||
struct mesh_reply;
|
||||
@ -110,6 +112,8 @@ struct mesh_area {
|
||||
size_t stats_jostled;
|
||||
/** stats, cumulative number of incoming client msgs dropped */
|
||||
size_t stats_dropped;
|
||||
/** stats, number of expired replies sent */
|
||||
size_t ans_expired;
|
||||
/** number of replies sent */
|
||||
size_t replies_sent;
|
||||
/** sum of waiting times for the replies */
|
||||
@ -121,9 +125,11 @@ struct mesh_area {
|
||||
/** (extended stats) bogus replies */
|
||||
size_t ans_bogus;
|
||||
/** (extended stats) rcodes in replies */
|
||||
size_t ans_rcode[16];
|
||||
size_t ans_rcode[UB_STATS_RCODE_NUM];
|
||||
/** (extended stats) rcode nodata in replies */
|
||||
size_t ans_nodata;
|
||||
/** (extended stats) type of applied RPZ action */
|
||||
size_t rpz_action[UB_STATS_RPZ_ACTION_NUM];
|
||||
|
||||
/** backup of query if other operations recurse and need the
|
||||
* network buffers */
|
||||
@ -142,6 +148,11 @@ struct mesh_area {
|
||||
struct mesh_state* jostle_last;
|
||||
/** timeout for jostling. if age is lower, it does not get jostled. */
|
||||
struct timeval jostle_max;
|
||||
|
||||
/** If we need to use response ip (value passed from daemon)*/
|
||||
int use_response_ip;
|
||||
/** If we need to use RPZ (value passed from daemon) */
|
||||
int use_rpz;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -643,4 +654,22 @@ void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp,
|
||||
void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
||||
struct comm_point* cp);
|
||||
|
||||
/** Callback for when the serve expired client timer has run out. Tries to
|
||||
* find an expired answer in the cache and reply that to the client.
|
||||
* @param arg: the argument passed to the callback.
|
||||
*/
|
||||
void mesh_serve_expired_callback(void* arg);
|
||||
|
||||
/**
|
||||
* Try to get a (expired) cached answer.
|
||||
* This needs to behave like the worker's answer_from_cache() in order to have
|
||||
* the same behavior as when replying from cache.
|
||||
* @param qstate: the module qstate.
|
||||
* @param lookup_qinfo: the query info to look for in the cache.
|
||||
* @return dns_msg if a cached answer was found, otherwise NULL.
|
||||
*/
|
||||
struct dns_msg*
|
||||
mesh_serve_expired_lookup(struct module_qstate* qstate,
|
||||
struct query_info* lookup_qinfo);
|
||||
|
||||
#endif /* SERVICES_MESH_H */
|
||||
|
@ -293,6 +293,9 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
/* open socket */
|
||||
s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss);
|
||||
|
||||
if(s == -1)
|
||||
return 0;
|
||||
|
||||
if(!pick_outgoing_tcp(w, s))
|
||||
return 0;
|
||||
|
||||
@ -1971,7 +1974,6 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
|
||||
sq->pending = NULL; /* removed after callback */
|
||||
if(error == NETEVENT_TIMEOUT) {
|
||||
int rto = 0;
|
||||
if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000) {
|
||||
/* fallback to 1480/1280 */
|
||||
sq->status = serviced_query_UDP_EDNS_FRAG;
|
||||
@ -1987,9 +1989,9 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
sq->status = serviced_query_UDP_EDNS;
|
||||
}
|
||||
sq->retry++;
|
||||
if(!(rto=infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
|
||||
sq->zone, sq->zonelen, sq->qtype, -1, sq->last_rtt,
|
||||
(time_t)now.tv_sec)))
|
||||
(time_t)now.tv_sec))
|
||||
log_err("out of memory in UDP exponential backoff");
|
||||
if(sq->retry < OUTBOUND_UDP_RETRY) {
|
||||
log_name_addr(VERB_ALGO, "retry query", sq->qbuf+10,
|
||||
|
1015
contrib/unbound/services/rpz.c
Normal file
1015
contrib/unbound/services/rpz.c
Normal file
File diff suppressed because it is too large
Load Diff
201
contrib/unbound/services/rpz.h
Normal file
201
contrib/unbound/services/rpz.h
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* services/rpz.h - rpz service
|
||||
*
|
||||
* Copyright (c) 2019, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains functions to enable RPZ service.
|
||||
*/
|
||||
|
||||
#ifndef SERVICES_RPZ_H
|
||||
#define SERVICES_RPZ_H
|
||||
|
||||
#include "services/localzone.h"
|
||||
#include "util/locks.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "services/authzone.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "daemon/stats.h"
|
||||
#include "respip/respip.h"
|
||||
|
||||
/**
|
||||
* RPZ triggers, only the QNAME trigger is currently supported in Unbound.
|
||||
*/
|
||||
enum rpz_trigger {
|
||||
RPZ_QNAME_TRIGGER = 0,
|
||||
/* unsupported triggers */
|
||||
RPZ_CLIENT_IP_TRIGGER, /* rpz-client-ip */
|
||||
RPZ_RESPONSE_IP_TRIGGER, /* rpz-ip */
|
||||
RPZ_NSDNAME_TRIGGER, /* rpz-nsdname */
|
||||
RPZ_NSIP_TRIGGER, /* rpz-nsip */
|
||||
RPZ_INVALID_TRIGGER, /* dname does not contain valid trigger */
|
||||
};
|
||||
|
||||
/**
|
||||
* RPZ actions.
|
||||
*/
|
||||
enum rpz_action {
|
||||
RPZ_NXDOMAIN_ACTION = 0,/* CNAME . */
|
||||
RPZ_NODATA_ACTION, /* CNAME *. */
|
||||
RPZ_PASSTHRU_ACTION, /* CNAME rpz-passthru. */
|
||||
RPZ_DROP_ACTION, /* CNAME rpz-drop. */
|
||||
RPZ_TCP_ONLY_ACTION, /* CNAME rpz-tcp-only. */
|
||||
RPZ_INVALID_ACTION, /* CNAME with (child of) TLD starting with
|
||||
"rpz-" in target, SOA, NS, DNAME and
|
||||
DNSSEC-related records. */
|
||||
RPZ_LOCAL_DATA_ACTION, /* anything else */
|
||||
/* RPZ override actions */
|
||||
RPZ_DISABLED_ACTION, /* RPZ action disabled using override */
|
||||
RPZ_NO_OVERRIDE_ACTION, /* RPZ action no override*/
|
||||
RPZ_CNAME_OVERRIDE_ACTION, /* RPZ CNAME action override*/
|
||||
};
|
||||
|
||||
/**
|
||||
* RPZ containing policies. Pointed to from corresponding auth-zone. Part of a
|
||||
* linked list to keep configuration order. Iterating or changing the linked
|
||||
* list requires the rpz_lock from struct auth_zones.
|
||||
*/
|
||||
struct rpz {
|
||||
struct local_zones* local_zones;
|
||||
struct respip_set* respip_set;
|
||||
uint8_t* taglist;
|
||||
size_t taglistlen;
|
||||
enum rpz_action action_override;
|
||||
struct ub_packed_rrset_key* cname_override;
|
||||
int log;
|
||||
char* log_name;
|
||||
struct rpz* next;
|
||||
struct rpz* prev;
|
||||
struct regional* region;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create policy from RR and add to this RPZ.
|
||||
* @param r: the rpz to add the policy to.
|
||||
* @param aznamelen: the length of the auth-zone name
|
||||
* @param dname: dname of the RR
|
||||
* @param dnamelen: length of the dname
|
||||
* @param rr_type: RR type of the RR
|
||||
* @param rr_class: RR class of the RR
|
||||
* @param rr_ttl: TTL of the RR
|
||||
* @param rdatawl: rdata of the RR, prepended with the rdata size
|
||||
* @param rdatalen: length if the RR, including the prepended rdata size
|
||||
* @param rr: the complete RR, for logging purposes
|
||||
* @param rr_len: the length of the complete RR
|
||||
* @return: 0 on error
|
||||
*/
|
||||
int rpz_insert_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
|
||||
size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
|
||||
uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len);
|
||||
|
||||
/**
|
||||
* Delete policy matching RR, used for IXFR.
|
||||
* @param r: the rpz to add the policy to.
|
||||
* @param aznamelen: the length of the auth-zone name
|
||||
* @param dname: dname of the RR
|
||||
* @param dnamelen: length of the dname
|
||||
* @param rr_type: RR type of the RR
|
||||
* @param rr_class: RR class of the RR
|
||||
* @param rdatawl: rdata of the RR, prepended with the rdata size
|
||||
* @param rdatalen: length if the RR, including the prepended rdata size
|
||||
*/
|
||||
void rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
|
||||
size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl,
|
||||
size_t rdatalen);
|
||||
|
||||
/**
|
||||
* Walk over the RPZ zones to find and apply a QNAME trigger policy.
|
||||
* @param az: auth_zones struct, containing first RPZ item and RPZ lock
|
||||
* @param env: module env
|
||||
* @param qinfo: qinfo containing qname and qtype
|
||||
* @param edns: edns data
|
||||
* @param buf: buffer to write answer to
|
||||
* @param temp: scratchpad
|
||||
* @param repinfo: reply info
|
||||
* @param taglist: taglist to lookup.
|
||||
* @param taglen: lenth of taglist.
|
||||
* @param stats: worker stats struct
|
||||
* @return: 1 if client answer is ready, 0 to continue resolving
|
||||
*/
|
||||
int rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
|
||||
struct regional* temp, struct comm_reply* repinfo,
|
||||
uint8_t* taglist, size_t taglen, struct ub_server_stats* stats);
|
||||
|
||||
/**
|
||||
* Delete RPZ
|
||||
* @param r: RPZ struct to delete
|
||||
*/
|
||||
void rpz_delete(struct rpz* r);
|
||||
|
||||
/**
|
||||
* Clear local-zones and respip data in RPZ, used after reloading file or
|
||||
* AXFR/HTTP transfer.
|
||||
* @param r: RPZ to use
|
||||
*/
|
||||
int rpz_clear(struct rpz* r);
|
||||
|
||||
/**
|
||||
* Create RPZ. RPZ must be added to linked list after creation.
|
||||
* @return: the newly created RPZ
|
||||
*/
|
||||
struct rpz* rpz_create(struct config_auth* p);
|
||||
|
||||
/**
|
||||
* String for RPZ action enum
|
||||
* @param a: RPZ action to get string for
|
||||
* @return: string for RPZ action
|
||||
*/
|
||||
const char* rpz_action_to_string(enum rpz_action a);
|
||||
|
||||
enum rpz_action
|
||||
respip_action_to_rpz_action(enum respip_action a);
|
||||
|
||||
/**
|
||||
* Prepare RPZ after procesing feed content.
|
||||
* @param r: RPZ to use
|
||||
*/
|
||||
void rpz_finish_config(struct rpz* r);
|
||||
|
||||
/**
|
||||
* Classify respip action for RPZ action
|
||||
* @param a: RPZ action
|
||||
* @return: the respip action
|
||||
*/
|
||||
enum respip_action
|
||||
rpz_action_to_respip_action(enum rpz_action a);
|
||||
|
||||
#endif /* SERVICES_RPZ_H */
|
@ -198,8 +198,6 @@ views_apply_cfg(struct views* vs, struct config_file* cfg)
|
||||
log_err("failed to insert "
|
||||
"default zones into "
|
||||
"local-zone list");
|
||||
free(nd_str);
|
||||
free(nd_type);
|
||||
lock_rw_unlock(&v->lock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
|
||||
if (line_nr) {
|
||||
*line_nr = *line_nr + 1;
|
||||
}
|
||||
if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
|
||||
if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) {
|
||||
*t = '\0';
|
||||
return -1;
|
||||
}
|
||||
@ -141,7 +141,8 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
|
||||
if (c != '\0' && c != '\n') {
|
||||
i++;
|
||||
}
|
||||
if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
|
||||
/* is there space for the character and the zero after it */
|
||||
if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) {
|
||||
*t = '\0';
|
||||
return -1;
|
||||
}
|
||||
@ -326,8 +327,8 @@ sldns_bget_token_par(sldns_buffer *b, char *token, const char *delim,
|
||||
/* in parentheses */
|
||||
/* do not write ' ' if we want to skip spaces */
|
||||
if(!(skipw && (strchr(skipw, c)||strchr(skipw, ' ')))) {
|
||||
/* check for space for the space character */
|
||||
if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
|
||||
/* check for space for the space character and a zero delimiter after that. */
|
||||
if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) {
|
||||
*t = '\0';
|
||||
return -1;
|
||||
}
|
||||
@ -354,7 +355,7 @@ sldns_bget_token_par(sldns_buffer *b, char *token, const char *delim,
|
||||
}
|
||||
|
||||
i++;
|
||||
if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
|
||||
if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) {
|
||||
*t = '\0';
|
||||
return -1;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ static int sldns_str2wire_dname_buf_rel(const char* str, uint8_t* buf,
|
||||
for (s = str; *s; s++, q++) {
|
||||
if (q >= buf + *olen)
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf);
|
||||
if (q > buf + LDNS_MAX_DOMAINLEN)
|
||||
if (q >= buf + LDNS_MAX_DOMAINLEN)
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf);
|
||||
switch (*s) {
|
||||
case '.':
|
||||
@ -117,7 +117,7 @@ static int sldns_str2wire_dname_buf_rel(const char* str, uint8_t* buf,
|
||||
if(rel) *rel = 1;
|
||||
if (q >= buf + *olen)
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf);
|
||||
if (q > buf + LDNS_MAX_DOMAINLEN) {
|
||||
if (q >= buf + LDNS_MAX_DOMAINLEN) {
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf);
|
||||
}
|
||||
if (label_len > LDNS_MAX_LABELLEN) {
|
||||
|
@ -548,10 +548,7 @@ morechecks(struct config_file* cfg)
|
||||
/* check that the modules listed in module_conf exist */
|
||||
check_modules_exist(cfg->module_conf);
|
||||
|
||||
/* There should be no reason for 'respip' module not to work with
|
||||
* dns64, but it's not explicitly confirmed, so the combination is
|
||||
* excluded below. It's simply unknown yet for the combination of
|
||||
* respip and other modules. */
|
||||
/* Respip is known to *not* work with dns64. */
|
||||
if(strcmp(cfg->module_conf, "iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 validator iterator") != 0
|
||||
@ -560,7 +557,9 @@ morechecks(struct config_file* cfg)
|
||||
&& strcmp(cfg->module_conf, "respip validator iterator") != 0
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
&& strcmp(cfg->module_conf, "python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python respip iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python respip validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "validator python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 python validator iterator") != 0
|
||||
@ -570,7 +569,9 @@ morechecks(struct config_file* cfg)
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
&& strcmp(cfg->module_conf, "validator cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip validator cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 validator cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 cachedb iterator") != 0
|
||||
#endif
|
||||
@ -580,39 +581,61 @@ morechecks(struct config_file* cfg)
|
||||
&& strcmp(cfg->module_conf, "dns64 python cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 python validator cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python respip cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python validator cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python respip validator cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "cachedb python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip cachedb python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "validator cachedb python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip validator cachedb python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "validator python cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip validator python cachedb iterator") != 0
|
||||
#endif
|
||||
#ifdef CLIENT_SUBNET
|
||||
&& strcmp(cfg->module_conf, "subnetcache iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip subnetcache iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip subnetcache validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 subnetcache iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 subnetcache validator iterator") != 0
|
||||
#endif
|
||||
#if defined(WITH_PYTHONMODULE) && defined(CLIENT_SUBNET)
|
||||
&& strcmp(cfg->module_conf, "python subnetcache iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python respip subnetcache iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip subnetcache python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python subnetcache validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python respip subnetcache validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache python validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip subnetcache python validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache validator python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip subnetcache validator python iterator") != 0
|
||||
#endif
|
||||
#ifdef USE_IPSECMOD
|
||||
&& strcmp(cfg->module_conf, "ipsecmod iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipsecmod respip iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipsecmod validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipsecmod respip validator iterator") != 0
|
||||
#endif
|
||||
#if defined(WITH_PYTHONMODULE) && defined(USE_IPSECMOD)
|
||||
&& strcmp(cfg->module_conf, "python ipsecmod iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python ipsecmod respip iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipsecmod python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipsecmod python respip iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipsecmod validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipsecmod respip validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python ipsecmod validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python ipsecmod respip validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipsecmod python validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipsecmod python respip validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipsecmod validator python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipsecmod respip validator python iterator") != 0
|
||||
#endif
|
||||
#ifdef USE_IPSET
|
||||
&& strcmp(cfg->module_conf, "validator ipset iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "validator ipset respip iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipset iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "ipset respip iterator") != 0
|
||||
#endif
|
||||
) {
|
||||
fatal_exit("module conf '%s' is not known to work",
|
||||
@ -676,8 +699,9 @@ check_hints(struct config_file* cfg)
|
||||
static void
|
||||
check_auth(struct config_file* cfg)
|
||||
{
|
||||
int is_rpz = 0;
|
||||
struct auth_zones* az = auth_zones_create();
|
||||
if(!az || !auth_zones_apply_cfg(az, cfg, 0)) {
|
||||
if(!az || !auth_zones_apply_cfg(az, cfg, 0i, &is_rpz)) {
|
||||
fatal_exit("Could not setup authority zones");
|
||||
}
|
||||
auth_zones_delete(az);
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include "daemon/stats.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/pkthdr.h"
|
||||
#include "services/rpz.h"
|
||||
|
||||
#ifdef HAVE_SYS_IPC_H
|
||||
#include "sys/ipc.h"
|
||||
@ -157,6 +158,8 @@ usage(void)
|
||||
printf(" view_local_datas view add list of local-data to view\n");
|
||||
printf(" one entry per line read from stdin\n");
|
||||
printf(" view_local_data_remove view name remove local-data in view\n");
|
||||
printf(" view_local_datas_remove view remove list of local-data from view\n");
|
||||
printf(" one entry per line read from stdin\n");
|
||||
printf("Version %s\n", PACKAGE_VERSION);
|
||||
printf("BSD licensed, see LICENSE in source package for details.\n");
|
||||
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
|
||||
@ -208,7 +211,7 @@ static void pr_stats(const char* nm, struct ub_stats_info* s)
|
||||
s->svr.num_queries - s->svr.num_queries_missed_cache);
|
||||
PR_UL_NM("num.cachemiss", s->svr.num_queries_missed_cache);
|
||||
PR_UL_NM("num.prefetch", s->svr.num_queries_prefetch);
|
||||
PR_UL_NM("num.zero_ttl", s->svr.zero_ttl_responses);
|
||||
PR_UL_NM("num.expired", s->svr.ans_expired);
|
||||
PR_UL_NM("num.recursivereplies", s->mesh_replies_sent);
|
||||
#ifdef USE_DNSCRYPT
|
||||
PR_UL_NM("num.dnscrypt.crypted", s->svr.num_query_dnscrypt_crypted);
|
||||
@ -372,6 +375,14 @@ static void print_extended(struct ub_stats_info* s)
|
||||
PR_UL("rrset.cache.count", s->svr.rrset_cache_count);
|
||||
PR_UL("infra.cache.count", s->svr.infra_cache_count);
|
||||
PR_UL("key.cache.count", s->svr.key_cache_count);
|
||||
/* applied RPZ actions */
|
||||
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;
|
||||
PR_UL_SUB("num.rpz.action", rpz_action_to_string(i), s->svr.rpz_action[i]);
|
||||
}
|
||||
#ifdef USE_DNSCRYPT
|
||||
PR_UL("dnscrypt_shared_secret.cache.count",
|
||||
s->svr.shared_secret_cache_count);
|
||||
@ -493,9 +504,11 @@ setup_ctx(struct config_file* cfg)
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
if(!ctx)
|
||||
ssl_err("could not allocate SSL_CTX pointer");
|
||||
#if SSL_OP_NO_SSLv2 != 0
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
|
||||
!= SSL_OP_NO_SSLv2)
|
||||
ssl_err("could not set SSL_OP_NO_SSLv2");
|
||||
#endif
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
|
||||
!= SSL_OP_NO_SSLv3)
|
||||
ssl_err("could not set SSL_OP_NO_SSLv3");
|
||||
@ -704,7 +717,8 @@ check_args_for_listcmd(int argc, char* argv[])
|
||||
fatal_exit("too many arguments for command '%s', "
|
||||
"content is piped in from stdin", argv[0]);
|
||||
}
|
||||
if(argc >= 1 && strcmp(argv[0], "view_local_datas") == 0 &&
|
||||
if(argc >= 1 && (strcmp(argv[0], "view_local_datas") == 0 ||
|
||||
strcmp(argv[0], "view_local_datas_remove") == 0) &&
|
||||
argc >= 3) {
|
||||
fatal_exit("too many arguments for command '%s', "
|
||||
"content is piped in from stdin", argv[0]);
|
||||
@ -753,7 +767,8 @@ go_cmd(SSL* ssl, int fd, int quiet, int argc, char* argv[])
|
||||
strcmp(argv[0], "local_zones_remove") == 0 ||
|
||||
strcmp(argv[0], "local_datas") == 0 ||
|
||||
strcmp(argv[0], "view_local_datas") == 0 ||
|
||||
strcmp(argv[0], "local_datas_remove") == 0)) {
|
||||
strcmp(argv[0], "local_datas_remove") == 0 ||
|
||||
strcmp(argv[0], "view_local_datas_remove") == 0)) {
|
||||
send_file(ssl, fd, stdin, buf, sizeof(buf));
|
||||
send_eof(ssl, fd);
|
||||
}
|
||||
|
@ -246,6 +246,8 @@ config_create(void)
|
||||
cfg->serve_expired = 0;
|
||||
cfg->serve_expired_ttl = 0;
|
||||
cfg->serve_expired_ttl_reset = 0;
|
||||
cfg->serve_expired_reply_ttl = 30;
|
||||
cfg->serve_expired_client_timeout = 0;
|
||||
cfg->add_holddown = 30*24*3600;
|
||||
cfg->del_holddown = 30*24*3600;
|
||||
cfg->keep_missing = 366*24*3600; /* one year plus a little leeway */
|
||||
@ -327,9 +329,14 @@ config_create(void)
|
||||
cfg->ipsecmod_strict = 0;
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
cfg->cachedb_backend = NULL;
|
||||
cfg->cachedb_secret = NULL;
|
||||
#endif
|
||||
if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit;
|
||||
if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit;
|
||||
#ifdef USE_REDIS
|
||||
if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
|
||||
cfg->redis_timeout = 100;
|
||||
cfg->redis_server_port = 6379;
|
||||
#endif /* USE_REDIS */
|
||||
#endif /* USE_CACHEDB */
|
||||
#ifdef USE_IPSET
|
||||
cfg->ipset_name_v4 = NULL;
|
||||
cfg->ipset_name_v6 = NULL;
|
||||
@ -581,10 +588,15 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
||||
else S_YNO("val-permissive-mode:", val_permissive_mode)
|
||||
else S_YNO("aggressive-nsec:", aggressive_nsec)
|
||||
else S_YNO("ignore-cd-flag:", ignore_cd)
|
||||
else S_YNO("serve-expired:", serve_expired)
|
||||
else if(strcmp(opt, "serve_expired_ttl:") == 0)
|
||||
else if(strcmp(opt, "serve-expired:") == 0)
|
||||
{ IS_YES_OR_NO; cfg->serve_expired = (strcmp(val, "yes") == 0);
|
||||
SERVE_EXPIRED = cfg->serve_expired; }
|
||||
else if(strcmp(opt, "serve-expired-ttl:") == 0)
|
||||
{ IS_NUMBER_OR_ZERO; cfg->serve_expired_ttl = atoi(val); SERVE_EXPIRED_TTL=(time_t)cfg->serve_expired_ttl;}
|
||||
else S_YNO("serve-expired-ttl-reset:", serve_expired_ttl_reset)
|
||||
else if(strcmp(opt, "serve-expired-reply-ttl:") == 0)
|
||||
{ IS_NUMBER_OR_ZERO; cfg->serve_expired_reply_ttl = atoi(val); SERVE_EXPIRED_REPLY_TTL=(time_t)cfg->serve_expired_reply_ttl;}
|
||||
else S_NUMBER_OR_ZERO("serve-expired-client-timeout:", serve_expired_client_timeout)
|
||||
else S_STR("val-nsec3-keysize-iterations:", val_nsec3_key_iterations)
|
||||
else S_UNSIGNED_OR_ZERO("add-holddown:", add_holddown)
|
||||
else S_UNSIGNED_OR_ZERO("del-holddown:", del_holddown)
|
||||
@ -977,6 +989,8 @@ config_get_option(struct config_file* cfg, const char* opt,
|
||||
else O_YNO(opt, "serve-expired", serve_expired)
|
||||
else O_DEC(opt, "serve-expired-ttl", serve_expired_ttl)
|
||||
else O_YNO(opt, "serve-expired-ttl-reset", serve_expired_ttl_reset)
|
||||
else O_DEC(opt, "serve-expired-reply-ttl", serve_expired_reply_ttl)
|
||||
else O_DEC(opt, "serve-expired-client-timeout", serve_expired_client_timeout)
|
||||
else O_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations)
|
||||
else O_UNS(opt, "add-holddown", add_holddown)
|
||||
else O_UNS(opt, "del-holddown", del_holddown)
|
||||
@ -1098,7 +1112,12 @@ config_get_option(struct config_file* cfg, const char* opt,
|
||||
#ifdef USE_CACHEDB
|
||||
else O_STR(opt, "backend", cachedb_backend)
|
||||
else O_STR(opt, "secret-seed", cachedb_secret)
|
||||
#endif
|
||||
#ifdef USE_REDIS
|
||||
else O_STR(opt, "redis-server-host", redis_server_host)
|
||||
else O_DEC(opt, "redis-server-port", redis_server_port)
|
||||
else O_DEC(opt, "redis-timeout", redis_timeout)
|
||||
#endif /* USE_REDIS */
|
||||
#endif /* USE_CACHEDB */
|
||||
#ifdef USE_IPSET
|
||||
else O_STR(opt, "name-v4", ipset_name_v4)
|
||||
else O_STR(opt, "name-v6", ipset_name_v6)
|
||||
@ -1279,6 +1298,10 @@ config_delauth(struct config_auth* p)
|
||||
config_delstrlist(p->urls);
|
||||
config_delstrlist(p->allow_notify);
|
||||
free(p->zonefile);
|
||||
free(p->rpz_taglist);
|
||||
free(p->rpz_action_override);
|
||||
free(p->rpz_cname);
|
||||
free(p->rpz_log_name);
|
||||
free(p);
|
||||
}
|
||||
|
||||
@ -1381,7 +1404,10 @@ config_delete(struct config_file* cfg)
|
||||
config_delstrlist(cfg->tls_session_ticket_keys.first);
|
||||
free(cfg->tls_ciphers);
|
||||
free(cfg->tls_ciphersuites);
|
||||
free(cfg->log_identity);
|
||||
if(cfg->log_identity) {
|
||||
log_ident_revert_to_default();
|
||||
free(cfg->log_identity);
|
||||
}
|
||||
config_del_strarray(cfg->ifs, cfg->num_ifs);
|
||||
config_del_strarray(cfg->out_ifs, cfg->num_out_ifs);
|
||||
config_delstubs(cfg->stubs);
|
||||
@ -1444,7 +1470,10 @@ config_delete(struct config_file* cfg)
|
||||
#ifdef USE_CACHEDB
|
||||
free(cfg->cachedb_backend);
|
||||
free(cfg->cachedb_secret);
|
||||
#endif
|
||||
#ifdef USE_REDIS
|
||||
free(cfg->redis_server_host);
|
||||
#endif /* USE_REDIS */
|
||||
#endif /* USE_CACHEDB */
|
||||
#ifdef USE_IPSET
|
||||
free(cfg->ipset_name_v4);
|
||||
free(cfg->ipset_name_v6);
|
||||
@ -1942,7 +1971,7 @@ char* config_taglist2str(struct config_file* cfg, uint8_t* taglist,
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
int taglist_intersect(uint8_t* list1, size_t list1len, uint8_t* list2,
|
||||
int taglist_intersect(uint8_t* list1, size_t list1len, const uint8_t* list2,
|
||||
size_t list2len)
|
||||
{
|
||||
size_t i;
|
||||
@ -1960,7 +1989,9 @@ config_apply(struct config_file* config)
|
||||
{
|
||||
MAX_TTL = (time_t)config->max_ttl;
|
||||
MIN_TTL = (time_t)config->min_ttl;
|
||||
SERVE_EXPIRED = config->serve_expired;
|
||||
SERVE_EXPIRED_TTL = (time_t)config->serve_expired_ttl;
|
||||
SERVE_EXPIRED_REPLY_TTL = (time_t)config->serve_expired_reply_ttl;
|
||||
MAX_NEG_TTL = (time_t)config->max_negative_ttl;
|
||||
RTT_MIN_TIMEOUT = config->infra_cache_min_rtt;
|
||||
EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size;
|
||||
|
@ -362,6 +362,11 @@ struct config_file {
|
||||
int serve_expired_ttl;
|
||||
/** reset serve expired TTL after failed update attempt */
|
||||
int serve_expired_ttl_reset;
|
||||
/** TTL for the serve expired replies */
|
||||
int serve_expired_reply_ttl;
|
||||
/** serve expired entries only after trying to update the entries and this
|
||||
* timeout (in milliseconds) is reached */
|
||||
int serve_expired_client_timeout;
|
||||
/** nsec3 maximum iterations per key size, string */
|
||||
char* val_nsec3_key_iterations;
|
||||
/** autotrust add holddown time, in seconds */
|
||||
@ -641,6 +646,21 @@ struct config_auth {
|
||||
/** fallback to recursion to authorities if zone expired and other
|
||||
* reasons perhaps (like, query bogus) */
|
||||
int fallback_enabled;
|
||||
/** this zone is used to create local-zone policies */
|
||||
int isrpz;
|
||||
/** rpz tags (or NULL) */
|
||||
uint8_t* rpz_taglist;
|
||||
/** length of the taglist (in bytes) */
|
||||
size_t rpz_taglistlen;
|
||||
/** Override RPZ action for this zone, regardless of zone content */
|
||||
char* rpz_action_override;
|
||||
/** Log when this RPZ policy is applied */
|
||||
int rpz_log;
|
||||
/** Display this name in the log when RPZ policy is applied */
|
||||
char* rpz_log_name;
|
||||
/** Always reply with this CNAME target if the cname override action is
|
||||
* used */
|
||||
char* rpz_cname;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1043,7 +1063,7 @@ char* config_taglist2str(struct config_file* cfg, uint8_t* taglist,
|
||||
* @param list2len: length in bytes of second list.
|
||||
* @return true if there are tags in common, 0 if not.
|
||||
*/
|
||||
int taglist_intersect(uint8_t* list1, size_t list1len, uint8_t* list2,
|
||||
int taglist_intersect(uint8_t* list1, size_t list1len, const uint8_t* list2,
|
||||
size_t list2len);
|
||||
|
||||
/**
|
||||
|
@ -317,6 +317,12 @@ forward-no-cache{COLON} { YDVAR(1, VAR_FORWARD_NO_CACHE) }
|
||||
forward-ssl-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) }
|
||||
forward-tls-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) }
|
||||
auth-zone{COLON} { YDVAR(0, VAR_AUTH_ZONE) }
|
||||
rpz{COLON} { YDVAR(0, VAR_RPZ) }
|
||||
tags{COLON} { YDVAR(1, VAR_TAGS) }
|
||||
rpz-action-override{COLON} { YDVAR(1, VAR_RPZ_ACTION_OVERRIDE) }
|
||||
rpz-cname-override{COLON} { YDVAR(1, VAR_RPZ_CNAME_OVERRIDE) }
|
||||
rpz-log{COLON} { YDVAR(1, VAR_RPZ_LOG) }
|
||||
rpz-log-name{COLON} { YDVAR(1, VAR_RPZ_LOG_NAME) }
|
||||
zonefile{COLON} { YDVAR(1, VAR_ZONEFILE) }
|
||||
master{COLON} { YDVAR(1, VAR_MASTER) }
|
||||
url{COLON} { YDVAR(1, VAR_URL) }
|
||||
@ -364,6 +370,8 @@ ignore-cd-flag{COLON} { YDVAR(1, VAR_IGNORE_CD_FLAG) }
|
||||
serve-expired{COLON} { YDVAR(1, VAR_SERVE_EXPIRED) }
|
||||
serve-expired-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL) }
|
||||
serve-expired-ttl-reset{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL_RESET) }
|
||||
serve-expired-reply-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_REPLY_TTL) }
|
||||
serve-expired-client-timeout{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_CLIENT_TIMEOUT) }
|
||||
fake-dsa{COLON} { YDVAR(1, VAR_FAKE_DSA) }
|
||||
fake-sha1{COLON} { YDVAR(1, VAR_FAKE_SHA1) }
|
||||
val-log-level{COLON} { YDVAR(1, VAR_VAL_LOG_LEVEL) }
|
||||
|
@ -143,10 +143,11 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_LOCAL_ZONE_OVERRIDE VAR_ACCESS_CONTROL_TAG_ACTION
|
||||
%token VAR_ACCESS_CONTROL_TAG_DATA VAR_VIEW VAR_ACCESS_CONTROL_VIEW
|
||||
%token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_SERVE_EXPIRED_TTL
|
||||
%token VAR_SERVE_EXPIRED_TTL_RESET VAR_FAKE_DSA VAR_FAKE_SHA1
|
||||
%token VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR VAR_TRUST_ANCHOR_SIGNALING
|
||||
%token VAR_AGGRESSIVE_NSEC VAR_USE_SYSTEMD VAR_SHM_ENABLE VAR_SHM_KEY
|
||||
%token VAR_ROOT_KEY_SENTINEL
|
||||
%token VAR_SERVE_EXPIRED_TTL_RESET VAR_SERVE_EXPIRED_REPLY_TTL
|
||||
%token VAR_SERVE_EXPIRED_CLIENT_TIMEOUT VAR_FAKE_DSA
|
||||
%token VAR_FAKE_SHA1 VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR
|
||||
%token VAR_TRUST_ANCHOR_SIGNALING VAR_AGGRESSIVE_NSEC VAR_USE_SYSTEMD
|
||||
%token VAR_SHM_ENABLE VAR_SHM_KEY VAR_ROOT_KEY_SENTINEL
|
||||
%token VAR_DNSCRYPT VAR_DNSCRYPT_ENABLE VAR_DNSCRYPT_PORT VAR_DNSCRYPT_PROVIDER
|
||||
%token VAR_DNSCRYPT_SECRET_KEY VAR_DNSCRYPT_PROVIDER_CERT
|
||||
%token VAR_DNSCRYPT_PROVIDER_CERT_ROTATED
|
||||
@ -166,8 +167,9 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE VAR_LOG_SERVFAIL VAR_DENY_ANY
|
||||
%token VAR_UNKNOWN_SERVER_TIME_LIMIT VAR_LOG_TAG_QUERYREPLY
|
||||
%token VAR_STREAM_WAIT_SIZE VAR_TLS_CIPHERS VAR_TLS_CIPHERSUITES
|
||||
%token VAR_TLS_SESSION_TICKET_KEYS
|
||||
%token VAR_IPSET VAR_IPSET_NAME_V4 VAR_IPSET_NAME_V6
|
||||
%token VAR_TLS_SESSION_TICKET_KEYS VAR_RPZ VAR_TAGS VAR_RPZ_ACTION_OVERRIDE
|
||||
%token VAR_RPZ_CNAME_OVERRIDE VAR_RPZ_LOG VAR_RPZ_LOG_NAME
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
@ -175,7 +177,8 @@ toplevelvar: serverstart contents_server | stubstart contents_stub |
|
||||
forwardstart contents_forward | pythonstart contents_py |
|
||||
rcstart contents_rc | dtstart contents_dt | viewstart contents_view |
|
||||
dnscstart contents_dnsc | cachedbstart contents_cachedb |
|
||||
ipsetstart contents_ipset | authstart contents_auth
|
||||
ipsetstart contents_ipset | authstart contents_auth |
|
||||
rpzstart contents_rpz
|
||||
;
|
||||
|
||||
/* server: declaration */
|
||||
@ -254,6 +257,7 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||||
server_access_control_tag_data | server_access_control_view |
|
||||
server_qname_minimisation_strict | server_serve_expired |
|
||||
server_serve_expired_ttl | server_serve_expired_ttl_reset |
|
||||
server_serve_expired_reply_ttl | server_serve_expired_client_timeout |
|
||||
server_fake_dsa | server_log_identity | server_use_systemd |
|
||||
server_response_ip_tag | server_response_ip | server_response_ip_data |
|
||||
server_shm_enable | server_shm_key | server_fake_sha1 |
|
||||
@ -335,6 +339,7 @@ authstart: VAR_AUTH_ZONE
|
||||
s->for_downstream = 1;
|
||||
s->for_upstream = 1;
|
||||
s->fallback_enabled = 0;
|
||||
s->isrpz = 0;
|
||||
} else
|
||||
yyerror("out of memory");
|
||||
}
|
||||
@ -345,6 +350,92 @@ content_auth: auth_name | auth_zonefile | auth_master | auth_url |
|
||||
auth_for_downstream | auth_for_upstream | auth_fallback_enabled |
|
||||
auth_allow_notify
|
||||
;
|
||||
|
||||
rpz_tag: VAR_TAGS STRING_ARG
|
||||
{
|
||||
uint8_t* bitlist;
|
||||
size_t len = 0;
|
||||
OUTYY(("P(server_local_zone_tag:%s)\n", $2));
|
||||
bitlist = config_parse_taglist(cfg_parser->cfg, $2,
|
||||
&len);
|
||||
free($2);
|
||||
if(!bitlist) {
|
||||
yyerror("could not parse tags, (define-tag them first)");
|
||||
}
|
||||
if(bitlist) {
|
||||
cfg_parser->cfg->auths->rpz_taglist = bitlist;
|
||||
cfg_parser->cfg->auths->rpz_taglistlen = len;
|
||||
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
rpz_action_override: VAR_RPZ_ACTION_OVERRIDE STRING_ARG
|
||||
{
|
||||
OUTYY(("P(rpz_action_override:%s)\n", $2));
|
||||
if(strcmp($2, "nxdomain")!=0 && strcmp($2, "nodata")!=0 &&
|
||||
strcmp($2, "passthru")!=0 && strcmp($2, "drop")!=0 &&
|
||||
strcmp($2, "cname")!=0 && strcmp($2, "disabled")!=0) {
|
||||
yyerror("rpz-action-override action: expected nxdomain, "
|
||||
"nodata, passthru, drop, cname or disabled");
|
||||
free($2);
|
||||
cfg_parser->cfg->auths->rpz_action_override = NULL;
|
||||
}
|
||||
else {
|
||||
cfg_parser->cfg->auths->rpz_action_override = $2;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
rpz_cname_override: VAR_RPZ_CNAME_OVERRIDE STRING_ARG
|
||||
{
|
||||
OUTYY(("P(rpz_cname_override:%s)\n", $2));
|
||||
free(cfg_parser->cfg->auths->rpz_cname);
|
||||
cfg_parser->cfg->auths->rpz_cname = $2;
|
||||
}
|
||||
;
|
||||
|
||||
rpz_log: VAR_RPZ_LOG STRING_ARG
|
||||
{
|
||||
OUTYY(("P(rpz_log:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->auths->rpz_log = (strcmp($2, "yes")==0);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
|
||||
rpz_log_name: VAR_RPZ_LOG_NAME STRING_ARG
|
||||
{
|
||||
OUTYY(("P(rpz_log_name:%s)\n", $2));
|
||||
free(cfg_parser->cfg->auths->rpz_log_name);
|
||||
cfg_parser->cfg->auths->rpz_log_name = $2;
|
||||
}
|
||||
;
|
||||
|
||||
rpzstart: VAR_RPZ
|
||||
{
|
||||
struct config_auth* s;
|
||||
OUTYY(("\nP(rpz:)\n"));
|
||||
s = (struct config_auth*)calloc(1, sizeof(struct config_auth));
|
||||
if(s) {
|
||||
s->next = cfg_parser->cfg->auths;
|
||||
cfg_parser->cfg->auths = s;
|
||||
/* defaults for RPZ auth zone */
|
||||
s->for_downstream = 0;
|
||||
s->for_upstream = 0;
|
||||
s->fallback_enabled = 0;
|
||||
s->isrpz = 1;
|
||||
} else
|
||||
yyerror("out of memory");
|
||||
}
|
||||
;
|
||||
contents_rpz: contents_rpz content_rpz
|
||||
| ;
|
||||
content_rpz: auth_name | auth_zonefile | rpz_tag | auth_master | auth_url |
|
||||
auth_allow_notify | rpz_action_override | rpz_cname_override |
|
||||
rpz_log | rpz_log_name
|
||||
;
|
||||
server_num_threads: VAR_NUM_THREADS STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_num_threads:%s)\n", $2));
|
||||
@ -429,6 +520,7 @@ server_send_client_subnet: VAR_SEND_CLIENT_SUBNET STRING_ARG
|
||||
fatal_exit("out of memory adding client-subnet");
|
||||
#else
|
||||
OUTYY(("P(Compiled without edns subnet option, ignoring)\n"));
|
||||
free($2);
|
||||
#endif
|
||||
}
|
||||
;
|
||||
@ -441,6 +533,7 @@ server_client_subnet_zone: VAR_CLIENT_SUBNET_ZONE STRING_ARG
|
||||
fatal_exit("out of memory adding client-subnet-zone");
|
||||
#else
|
||||
OUTYY(("P(Compiled without edns subnet option, ignoring)\n"));
|
||||
free($2);
|
||||
#endif
|
||||
}
|
||||
;
|
||||
@ -1666,12 +1759,30 @@ server_serve_expired_ttl_reset: VAR_SERVE_EXPIRED_TTL_RESET STRING_ARG
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_serve_expired_reply_ttl: VAR_SERVE_EXPIRED_REPLY_TTL STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_serve_expired_reply_ttl:%s)\n", $2));
|
||||
if(atoi($2) == 0 && strcmp($2, "0") != 0)
|
||||
yyerror("number expected");
|
||||
else cfg_parser->cfg->serve_expired_reply_ttl = atoi($2);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_serve_expired_client_timeout: VAR_SERVE_EXPIRED_CLIENT_TIMEOUT STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_serve_expired_client_timeout:%s)\n", $2));
|
||||
if(atoi($2) == 0 && strcmp($2, "0") != 0)
|
||||
yyerror("number expected");
|
||||
else cfg_parser->cfg->serve_expired_client_timeout = atoi($2);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_fake_dsa: VAR_FAKE_DSA STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_fake_dsa:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
#ifdef HAVE_SSL
|
||||
#if defined(HAVE_SSL) || defined(HAVE_NETTLE)
|
||||
else fake_dsa = (strcmp($2, "yes")==0);
|
||||
if(fake_dsa)
|
||||
log_warn("test option fake_dsa is enabled");
|
||||
@ -1684,7 +1795,7 @@ server_fake_sha1: VAR_FAKE_SHA1 STRING_ARG
|
||||
OUTYY(("P(server_fake_sha1:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
#ifdef HAVE_SSL
|
||||
#if defined(HAVE_SSL) || defined(HAVE_NETTLE)
|
||||
else fake_sha1 = (strcmp($2, "yes")==0);
|
||||
if(fake_sha1)
|
||||
log_warn("test option fake_sha1 is enabled");
|
||||
@ -2898,9 +3009,6 @@ cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
|
||||
{
|
||||
#ifdef USE_CACHEDB
|
||||
OUTYY(("P(backend:%s)\n", $2));
|
||||
if(cfg_parser->cfg->cachedb_backend)
|
||||
yyerror("cachedb backend override, there must be one "
|
||||
"backend");
|
||||
free(cfg_parser->cfg->cachedb_backend);
|
||||
cfg_parser->cfg->cachedb_backend = $2;
|
||||
#else
|
||||
@ -2913,9 +3021,6 @@ cachedb_secret_seed: VAR_CACHEDB_SECRETSEED STRING_ARG
|
||||
{
|
||||
#ifdef USE_CACHEDB
|
||||
OUTYY(("P(secret-seed:%s)\n", $2));
|
||||
if(cfg_parser->cfg->cachedb_secret)
|
||||
yyerror("cachedb secret-seed override, there must be "
|
||||
"only one secret");
|
||||
free(cfg_parser->cfg->cachedb_secret);
|
||||
cfg_parser->cfg->cachedb_secret = $2;
|
||||
#else
|
||||
|
@ -233,17 +233,28 @@ int
|
||||
dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2)
|
||||
{
|
||||
uint8_t len1, len2;
|
||||
int count1 = 0, count2 = 0;
|
||||
log_assert(pkt && d1 && d2);
|
||||
len1 = *d1++;
|
||||
len2 = *d2++;
|
||||
while( len1 != 0 || len2 != 0 ) {
|
||||
/* resolve ptrs */
|
||||
if(LABEL_IS_PTR(len1)) {
|
||||
if((size_t)PTR_OFFSET(len1, *d1)
|
||||
>= sldns_buffer_limit(pkt))
|
||||
return -1;
|
||||
if(count1++ > MAX_COMPRESS_PTRS)
|
||||
return -1;
|
||||
d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1));
|
||||
len1 = *d1++;
|
||||
continue;
|
||||
}
|
||||
if(LABEL_IS_PTR(len2)) {
|
||||
if((size_t)PTR_OFFSET(len2, *d2)
|
||||
>= sldns_buffer_limit(pkt))
|
||||
return 1;
|
||||
if(count2++ > MAX_COMPRESS_PTRS)
|
||||
return 1;
|
||||
d2 = sldns_buffer_at(pkt, PTR_OFFSET(len2, *d2));
|
||||
len2 = *d2++;
|
||||
continue;
|
||||
@ -302,12 +313,18 @@ dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h)
|
||||
uint8_t labuf[LDNS_MAX_LABELLEN+1];
|
||||
uint8_t lablen;
|
||||
int i;
|
||||
int count = 0;
|
||||
|
||||
/* preserve case of query, make hash label by label */
|
||||
lablen = *dname++;
|
||||
while(lablen) {
|
||||
if(LABEL_IS_PTR(lablen)) {
|
||||
/* follow pointer */
|
||||
if((size_t)PTR_OFFSET(lablen, *dname)
|
||||
>= sldns_buffer_limit(pkt))
|
||||
return h;
|
||||
if(count++ > MAX_COMPRESS_PTRS)
|
||||
return h;
|
||||
dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
|
||||
lablen = *dname++;
|
||||
continue;
|
||||
@ -341,6 +358,9 @@ void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname)
|
||||
return;
|
||||
}
|
||||
/* follow pointer */
|
||||
if((size_t)PTR_OFFSET(lablen, *dname)
|
||||
>= sldns_buffer_limit(pkt))
|
||||
return;
|
||||
dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
|
||||
lablen = *dname++;
|
||||
continue;
|
||||
@ -369,6 +389,7 @@ void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname)
|
||||
void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname)
|
||||
{
|
||||
uint8_t lablen;
|
||||
int count = 0;
|
||||
if(!out) out = stdout;
|
||||
if(!dname) return;
|
||||
|
||||
@ -382,6 +403,15 @@ void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname)
|
||||
fputs("??compressionptr??", out);
|
||||
return;
|
||||
}
|
||||
if((size_t)PTR_OFFSET(lablen, *dname)
|
||||
>= sldns_buffer_limit(pkt)) {
|
||||
fputs("??compressionptr??", out);
|
||||
return;
|
||||
}
|
||||
if(count++ > MAX_COMPRESS_PTRS) {
|
||||
fputs("??compressionptr??", out);
|
||||
return;
|
||||
}
|
||||
dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
|
||||
lablen = *dname++;
|
||||
continue;
|
||||
@ -558,6 +588,34 @@ dname_lab_startswith(uint8_t* label, char* prefix, char** endptr)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
dname_has_label(uint8_t* dname, size_t dnamelen, uint8_t* label)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
/* 1 byte needed for the label length */
|
||||
if(dnamelen < 1)
|
||||
return 0;
|
||||
|
||||
len = *dname;
|
||||
while(len <= dnamelen) {
|
||||
if(!(*dname)) {
|
||||
if(*dname == *label)
|
||||
return 1; /* empty label match */
|
||||
/* termination label found, stop iterating */
|
||||
return 0;
|
||||
}
|
||||
if(*dname == *label && *label &&
|
||||
memlowercmp(dname+1, label+1, *dname) == 0)
|
||||
return 1;
|
||||
len += *dname;
|
||||
dname += *dname;
|
||||
dname++;
|
||||
len++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dname_buffer_write(sldns_buffer* pkt, uint8_t* dname)
|
||||
{
|
||||
|
@ -196,6 +196,15 @@ int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs);
|
||||
*/
|
||||
int dname_lab_startswith(uint8_t* label, char* prefix, char** endptr);
|
||||
|
||||
/**
|
||||
* Check if dname contains label
|
||||
* @param dname: dname
|
||||
* @param dnamelen: length of dname
|
||||
* @param label: label to be checked for presence in dname
|
||||
* @return: 1 if dname has this label, 0 otherwise
|
||||
*/
|
||||
int dname_has_label(uint8_t* dname, size_t dnamelen, uint8_t* label);
|
||||
|
||||
/**
|
||||
* See if domain name d1 is a strict subdomain of d2.
|
||||
* That is a subdomain, but not equal.
|
||||
|
@ -480,7 +480,8 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
|
||||
sldns_buffer_write(pkt, &key->rk.type, 2);
|
||||
sldns_buffer_write(pkt, &key->rk.rrset_class, 2);
|
||||
if(data->rr_ttl[j] < timenow)
|
||||
sldns_buffer_write_u32(pkt, 0);
|
||||
sldns_buffer_write_u32(pkt,
|
||||
SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0);
|
||||
else sldns_buffer_write_u32(pkt,
|
||||
data->rr_ttl[j]-timenow);
|
||||
if(c) {
|
||||
@ -517,7 +518,8 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
|
||||
sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_RRSIG);
|
||||
sldns_buffer_write(pkt, &key->rk.rrset_class, 2);
|
||||
if(data->rr_ttl[i] < timenow)
|
||||
sldns_buffer_write_u32(pkt, 0);
|
||||
sldns_buffer_write_u32(pkt,
|
||||
SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0);
|
||||
else sldns_buffer_write_u32(pkt,
|
||||
data->rr_ttl[i]-timenow);
|
||||
/* rrsig rdata cannot be compressed, perform 100+ byte
|
||||
|
@ -55,7 +55,11 @@ smart_compare(sldns_buffer* pkt, uint8_t* dnow,
|
||||
{
|
||||
if(LABEL_IS_PTR(*dnow)) {
|
||||
/* ptr points to a previous dname */
|
||||
uint8_t* p = sldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1]));
|
||||
uint8_t* p;
|
||||
if((size_t)PTR_OFFSET(dnow[0], dnow[1])
|
||||
>= sldns_buffer_limit(pkt))
|
||||
return -1;
|
||||
p = sldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1]));
|
||||
if( p == dprfirst || p == dprlast )
|
||||
return 0;
|
||||
/* prev dname is also a ptr, both ptrs are the same. */
|
||||
|
@ -79,8 +79,12 @@ extern time_t MAX_TTL;
|
||||
extern time_t MIN_TTL;
|
||||
/** Maximum Negative TTL that is allowed */
|
||||
extern time_t MAX_NEG_TTL;
|
||||
/** If we serve expired entries and prefetch them */
|
||||
extern int SERVE_EXPIRED;
|
||||
/** Time to serve records after expiration */
|
||||
extern time_t SERVE_EXPIRED_TTL;
|
||||
/** TTL to use for expired records */
|
||||
extern time_t SERVE_EXPIRED_REPLY_TTL;
|
||||
/** Negative cache time (for entries without any RRs.) */
|
||||
#define NORR_TTL 5 /* seconds */
|
||||
|
||||
|
@ -61,8 +61,12 @@ time_t MAX_TTL = 3600 * 24 * 10; /* ten days */
|
||||
time_t MIN_TTL = 0;
|
||||
/** MAX Negative TTL, for SOA records in authority section */
|
||||
time_t MAX_NEG_TTL = 3600; /* one hour */
|
||||
/** If we serve expired entries and prefetch them */
|
||||
int SERVE_EXPIRED = 0;
|
||||
/** Time to serve records after expiration */
|
||||
time_t SERVE_EXPIRED_TTL = 0;
|
||||
/** TTL to use for expired records */
|
||||
time_t SERVE_EXPIRED_REPLY_TTL = 30;
|
||||
|
||||
/** allocate qinfo, return 0 on error */
|
||||
static int
|
||||
|
@ -40,6 +40,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/data/packed_rrset.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
@ -351,11 +352,11 @@ packed_rrset_copy_region(struct ub_packed_rrset_key* key,
|
||||
/* make TTLs relative - once per rrset */
|
||||
for(i=0; i<d->count + d->rrsig_count; i++) {
|
||||
if(d->rr_ttl[i] < now)
|
||||
d->rr_ttl[i] = 0;
|
||||
d->rr_ttl[i] = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0;
|
||||
else d->rr_ttl[i] -= now;
|
||||
}
|
||||
if(d->ttl < now)
|
||||
d->ttl = 0;
|
||||
d->ttl = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0;
|
||||
else d->ttl -= now;
|
||||
return ck;
|
||||
}
|
||||
@ -386,3 +387,19 @@ packed_rrset_copy_alloc(struct ub_packed_rrset_key* key,
|
||||
packed_rrset_ttl_add(dd, now);
|
||||
return dk;
|
||||
}
|
||||
|
||||
int
|
||||
packed_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
|
||||
size_t* index)
|
||||
{
|
||||
size_t i;
|
||||
for(i=0; i<d->count; i++) {
|
||||
if(d->rr_len[i] != len)
|
||||
continue;
|
||||
if(memcmp(d->rr_data[i], rdata, len) == 0) {
|
||||
*index = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -446,4 +446,17 @@ struct ub_packed_rrset_key* packed_rrset_copy_alloc(
|
||||
struct ub_packed_rrset_key* key, struct alloc_cache* alloc,
|
||||
time_t now);
|
||||
|
||||
/**
|
||||
* Find RR index in packed rrset
|
||||
* Raw comparison, does not canonicalize RDATA
|
||||
* @param d: packed rrset
|
||||
* @param rdata: RDATA of RR to find
|
||||
* @param len: length of rdata
|
||||
* @param index: pointer to int to store index of found RR
|
||||
* @return 1 if RR found, 0 otherwise
|
||||
*/
|
||||
int
|
||||
packed_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
|
||||
size_t* index);
|
||||
|
||||
#endif /* UTIL_DATA_PACKED_RRSET_H */
|
||||
|
@ -131,6 +131,7 @@ fptr_whitelist_comm_timer(void (*fptr)(void*))
|
||||
else if(fptr == &auth_xfer_timer) return 1;
|
||||
else if(fptr == &auth_xfer_probe_timer_callback) return 1;
|
||||
else if(fptr == &auth_xfer_transfer_timer_callback) return 1;
|
||||
else if(fptr == &mesh_serve_expired_callback) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -619,3 +620,9 @@ int fptr_whitelist_inplace_cb_query_response(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fptr_whitelist_serve_expired_lookup(serve_expired_lookup_func_type* fptr)
|
||||
{
|
||||
if(fptr == &mesh_serve_expired_lookup)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -377,6 +377,13 @@ int fptr_whitelist_inplace_cb_edns_back_parsed(
|
||||
int fptr_whitelist_inplace_cb_query_response(
|
||||
inplace_cb_query_response_func_type* fptr);
|
||||
|
||||
/**
|
||||
* Check function pointer whitelist for serve_expired_lookup func values.
|
||||
* @param fptr: function pointer to check.
|
||||
* @return false if not in whitelist.
|
||||
*/
|
||||
int fptr_whitelist_serve_expired_lookup(serve_expired_lookup_func_type* fptr);
|
||||
|
||||
/** Due to module breakage by fptr wlist, these test app declarations
|
||||
* are presented here */
|
||||
/**
|
||||
|
@ -3904,6 +3904,7 @@
|
||||
4600,
|
||||
4601,
|
||||
4621,
|
||||
4646,
|
||||
4658,
|
||||
4659,
|
||||
4660,
|
||||
|
@ -74,6 +74,7 @@ static lock_basic_type log_lock;
|
||||
#endif
|
||||
/** the identity of this executable/process */
|
||||
static const char* ident="unbound";
|
||||
static const char* default_ident="unbound";
|
||||
#if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS)
|
||||
/** are we using syslog(3) to log to */
|
||||
static int logging_to_syslog = 0;
|
||||
@ -181,6 +182,24 @@ void log_ident_set(const char* id)
|
||||
ident = id;
|
||||
}
|
||||
|
||||
void log_ident_set_default(const char* id)
|
||||
{
|
||||
default_ident = id;
|
||||
}
|
||||
|
||||
void log_ident_revert_to_default()
|
||||
{
|
||||
ident = default_ident;
|
||||
}
|
||||
|
||||
void log_ident_set_or_default(const char* identity)
|
||||
{
|
||||
if(identity == NULL || identity[0] == 0)
|
||||
log_ident_set(default_ident);
|
||||
else
|
||||
log_ident_set(identity);
|
||||
}
|
||||
|
||||
void log_set_time_asc(int use_asc)
|
||||
{
|
||||
log_time_asc = use_asc;
|
||||
|
@ -107,11 +107,29 @@ void log_thread_set(int* num);
|
||||
int log_thread_get(void);
|
||||
|
||||
/**
|
||||
* Set identity to print, default is 'unbound'.
|
||||
* Set identity to print, default is 'unbound'.
|
||||
* @param id: string to print. Name of executable.
|
||||
*/
|
||||
void log_ident_set(const char* id);
|
||||
|
||||
/**
|
||||
* Set default identity to print, default is 'unbound'.
|
||||
* @param id: string to print. Name of executable.
|
||||
*/
|
||||
void log_ident_set_default(const char* id);
|
||||
|
||||
/**
|
||||
* Revert identity to print, back to the recorded default value.
|
||||
*/
|
||||
void log_ident_revert_to_default(void);
|
||||
|
||||
/**
|
||||
* Set identity to print if there is an identity, otherwise
|
||||
* set the default.
|
||||
* @param identity: the identity to set.
|
||||
*/
|
||||
void log_ident_set_or_default(const char* identity);
|
||||
|
||||
/**
|
||||
* Set if the time value is printed ascii or decimal in log entries.
|
||||
* @param use_asc: if true, ascii is printed, otherwise decimal.
|
||||
|
@ -306,6 +306,17 @@ typedef int inplace_cb_edns_back_parsed_func_type(struct module_qstate* qstate,
|
||||
typedef int inplace_cb_query_response_func_type(struct module_qstate* qstate,
|
||||
struct dns_msg* response, int id, void* cb_args);
|
||||
|
||||
/**
|
||||
* Function called when looking for (expired) cached answers during the serve
|
||||
* expired logic.
|
||||
* Called as func(qstate, lookup_qinfo)
|
||||
* Where:
|
||||
* qstate: the query state.
|
||||
* lookup_qinfo: the qinfo to lookup for.
|
||||
*/
|
||||
typedef struct dns_msg* serve_expired_lookup_func_type(
|
||||
struct module_qstate* qstate, struct query_info* lookup_qinfo);
|
||||
|
||||
/**
|
||||
* Module environment.
|
||||
* Services and data provided to the module.
|
||||
@ -571,6 +582,14 @@ struct sock_list {
|
||||
|
||||
struct respip_action_info;
|
||||
|
||||
/**
|
||||
* Struct to hold relevant data for serve expired
|
||||
*/
|
||||
struct serve_expired_data {
|
||||
struct comm_timer* timer;
|
||||
serve_expired_lookup_func_type* get_cached_answer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Module state, per query.
|
||||
*/
|
||||
@ -612,6 +631,8 @@ struct module_qstate {
|
||||
struct mesh_state* mesh_info;
|
||||
/** how many seconds before expiry is this prefetched (0 if not) */
|
||||
time_t prefetch_leeway;
|
||||
/** serve expired data */
|
||||
struct serve_expired_data* serve_expired_data;
|
||||
|
||||
/** incoming edns options from the front end */
|
||||
struct edns_option* edns_opts_front_in;
|
||||
|
@ -284,6 +284,113 @@ int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* RPZ format address dname to network byte order address */
|
||||
static int ipdnametoaddr(uint8_t* dname, size_t dnamelen,
|
||||
struct sockaddr_storage* addr, socklen_t* addrlen, int* af)
|
||||
{
|
||||
uint8_t* ia;
|
||||
size_t dnamelabs = dname_count_labels(dname);
|
||||
uint8_t lablen;
|
||||
char* e = NULL;
|
||||
int z = 0;
|
||||
size_t len = 0;
|
||||
int i;
|
||||
*af = AF_INET;
|
||||
|
||||
/* need 1 byte for label length */
|
||||
if(dnamelen < 1)
|
||||
return 0;
|
||||
|
||||
if(dnamelabs > 6 ||
|
||||
dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) {
|
||||
*af = AF_INET6;
|
||||
}
|
||||
len = *dname;
|
||||
lablen = *dname++;
|
||||
i = (*af == AF_INET) ? 3 : 15;
|
||||
if(*af == AF_INET6) {
|
||||
struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
|
||||
*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
|
||||
memset(sa, 0, *addrlen);
|
||||
sa->sin6_family = AF_INET6;
|
||||
ia = (uint8_t*)&sa->sin6_addr;
|
||||
} else { /* ip4 */
|
||||
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
|
||||
*addrlen = (socklen_t)sizeof(struct sockaddr_in);
|
||||
memset(sa, 0, *addrlen);
|
||||
sa->sin_family = AF_INET;
|
||||
ia = (uint8_t*)&sa->sin_addr;
|
||||
}
|
||||
while(lablen && i >= 0 && len <= dnamelen) {
|
||||
char buff[LDNS_MAX_LABELLEN+1];
|
||||
uint16_t chunk; /* big enough to not overflow on IPv6 hextet */
|
||||
if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) ||
|
||||
(*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) {
|
||||
return 0;
|
||||
}
|
||||
if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) {
|
||||
/* Add one or more 0 labels. Address is initialised at
|
||||
* 0, so just skip the zero part. */
|
||||
int zl = 11 - dnamelabs;
|
||||
if(z || zl < 0)
|
||||
return 0;
|
||||
z = 1;
|
||||
i -= (zl*2);
|
||||
} else {
|
||||
memcpy(buff, dname, lablen);
|
||||
buff[lablen] = '\0';
|
||||
chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16);
|
||||
if(!e || *e != '\0' || (*af == AF_INET && chunk > 255))
|
||||
return 0;
|
||||
if(*af == AF_INET) {
|
||||
log_assert(i < 4 && i >= 0);
|
||||
ia[i] = (uint8_t)chunk;
|
||||
i--;
|
||||
} else {
|
||||
log_assert(i < 16 && i >= 1);
|
||||
/* ia in network byte order */
|
||||
ia[i-1] = (uint8_t)(chunk >> 8);
|
||||
ia[i] = (uint8_t)(chunk & 0x00FF);
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
dname += lablen;
|
||||
lablen = *dname++;
|
||||
len += lablen;
|
||||
}
|
||||
if(i != -1)
|
||||
/* input too short */
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int netblockdnametoaddr(uint8_t* dname, size_t dnamelen,
|
||||
struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af)
|
||||
{
|
||||
char buff[3 /* 3 digit netblock */ + 1];
|
||||
size_t nlablen;
|
||||
if(dnamelen < 1 || *dname > 3)
|
||||
/* netblock invalid */
|
||||
return 0;
|
||||
nlablen = *dname;
|
||||
|
||||
if(dnamelen < 1 + nlablen)
|
||||
return 0;
|
||||
|
||||
memcpy(buff, dname+1, nlablen);
|
||||
buff[nlablen] = '\0';
|
||||
*net = atoi(buff);
|
||||
if(*net == 0 && strcmp(buff, "0") != 0)
|
||||
return 0;
|
||||
dname += nlablen;
|
||||
dname++;
|
||||
if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af))
|
||||
return 0;
|
||||
if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
|
||||
socklen_t* addrlen, char** auth_name)
|
||||
{
|
||||
@ -728,11 +835,13 @@ listen_sslctx_setup(void* ctxt)
|
||||
#ifdef HAVE_SSL
|
||||
SSL_CTX* ctx = (SSL_CTX*)ctxt;
|
||||
/* no SSLv2, SSLv3 because has defects */
|
||||
#if SSL_OP_NO_SSLv2 != 0
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
|
||||
!= SSL_OP_NO_SSLv2){
|
||||
log_crypto_err("could not set SSL_OP_NO_SSLv2");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
|
||||
!= SSL_OP_NO_SSLv3){
|
||||
log_crypto_err("could not set SSL_OP_NO_SSLv3");
|
||||
@ -968,12 +1077,14 @@ void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert)
|
||||
log_crypto_err("could not allocate SSL_CTX pointer");
|
||||
return NULL;
|
||||
}
|
||||
#if SSL_OP_NO_SSLv2 != 0
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
|
||||
!= SSL_OP_NO_SSLv2) {
|
||||
log_crypto_err("could not set SSL_OP_NO_SSLv2");
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
|
||||
!= SSL_OP_NO_SSLv3) {
|
||||
log_crypto_err("could not set SSL_OP_NO_SSLv3");
|
||||
@ -1160,13 +1271,21 @@ int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_ses
|
||||
s++;
|
||||
}
|
||||
keys = calloc(s, sizeof(struct tls_session_ticket_key));
|
||||
if(!keys)
|
||||
return 0;
|
||||
memset(keys, 0, s*sizeof(*keys));
|
||||
ticket_keys = keys;
|
||||
|
||||
for(p = tls_session_ticket_keys; p; p = p->next) {
|
||||
size_t n;
|
||||
unsigned char *data = (unsigned char *)malloc(80);
|
||||
FILE *f = fopen(p->str, "r");
|
||||
unsigned char *data;
|
||||
FILE *f;
|
||||
|
||||
data = (unsigned char *)malloc(80);
|
||||
if(!data)
|
||||
return 0;
|
||||
|
||||
f = fopen(p->str, "r");
|
||||
if(!f) {
|
||||
log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno));
|
||||
free(data);
|
||||
|
@ -471,4 +471,19 @@ int tls_session_ticket_key_cb(void *s, unsigned char* key_name,unsigned char* iv
|
||||
/** Free memory used for TLS session ticket keys */
|
||||
void listen_sslctx_delete_ticket_keys(void);
|
||||
|
||||
/**
|
||||
* RPZ format netblock to network byte order address and netblock
|
||||
* example RPZ netblock format dnames:
|
||||
* - 24.10.100.51.198.rpz-ip -> 198.51.100.10/24
|
||||
* - 32.10.zz.db8.2001.rpz-ip -> 2001:db8:0:0:0:0:0:10/32
|
||||
* @param dname: the dname containing RPZ format netblock
|
||||
* @param dnamelen: length of dname
|
||||
* @param addr: where to store sockaddr.
|
||||
* @param addrlen: length of stored sockaddr is returned.
|
||||
* @param net: where to store netmask
|
||||
* @param af: where to store address family.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int netblockdnametoaddr(uint8_t* dname, size_t dnamelen,
|
||||
struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af);
|
||||
#endif /* NET_HELP_H */
|
||||
|
@ -1120,6 +1120,14 @@ ssl_handshake(struct comm_point* c)
|
||||
return 0; /* closed */
|
||||
} else if(want == SSL_ERROR_SYSCALL) {
|
||||
/* SYSCALL and errno==0 means closed uncleanly */
|
||||
#ifdef EPIPE
|
||||
if(errno == EPIPE && verbosity < 2)
|
||||
return 0; /* silence 'broken pipe' */
|
||||
#endif
|
||||
#ifdef ECONNRESET
|
||||
if(errno == ECONNRESET && verbosity < 2)
|
||||
return 0; /* silence reset by peer */
|
||||
#endif
|
||||
if(errno != 0)
|
||||
log_err("SSL_handshake syscall: %s",
|
||||
strerror(errno));
|
||||
|
@ -78,7 +78,7 @@
|
||||
*/
|
||||
#define MAX_VALUE 0x7fffffff
|
||||
|
||||
#if defined(HAVE_SSL)
|
||||
#if defined(HAVE_SSL) || defined(HAVE_LIBBSD)
|
||||
struct ub_randstate*
|
||||
ub_initstate(struct ub_randstate* ATTR_UNUSED(from))
|
||||
{
|
||||
@ -183,10 +183,10 @@ long int ub_random(struct ub_randstate* s)
|
||||
}
|
||||
return x & MAX_VALUE;
|
||||
}
|
||||
#endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */
|
||||
#endif /* HAVE_SSL or HAVE_LIBBSD or HAVE_NSS or HAVE_NETTLE */
|
||||
|
||||
|
||||
#if defined(HAVE_NSS) || defined(HAVE_NETTLE)
|
||||
#if defined(HAVE_NSS) || defined(HAVE_NETTLE) && !defined(HAVE_LIBBSD)
|
||||
long int
|
||||
ub_random_max(struct ub_randstate* state, long int x)
|
||||
{
|
||||
@ -198,7 +198,7 @@ ub_random_max(struct ub_randstate* state, long int x)
|
||||
v = ub_random(state);
|
||||
return (v % x);
|
||||
}
|
||||
#endif /* HAVE_NSS or HAVE_NETTLE */
|
||||
#endif /* HAVE_NSS or HAVE_NETTLE and !HAVE_LIBBSD */
|
||||
|
||||
void
|
||||
ub_randfree(struct ub_randstate* s)
|
||||
|
@ -104,11 +104,12 @@ int addr_tree_insert(rbtree_type* tree, struct addr_tree_node* node,
|
||||
return rbtree_insert(tree, &node->node) != NULL;
|
||||
}
|
||||
|
||||
void addr_tree_init_parents(rbtree_type* tree)
|
||||
void addr_tree_init_parents_node(struct addr_tree_node* node)
|
||||
{
|
||||
struct addr_tree_node* node, *prev = NULL, *p;
|
||||
struct addr_tree_node* prev = NULL, *p;
|
||||
int m;
|
||||
RBTREE_FOR(node, struct addr_tree_node*, tree) {
|
||||
for(; (rbnode_type*)node != RBTREE_NULL;
|
||||
node = (struct addr_tree_node*)rbtree_next((rbnode_type*)node)) {
|
||||
node->parent = NULL;
|
||||
if(!prev || prev->addrlen != node->addrlen) {
|
||||
prev = node;
|
||||
@ -130,6 +131,12 @@ void addr_tree_init_parents(rbtree_type* tree)
|
||||
}
|
||||
}
|
||||
|
||||
void addr_tree_init_parents(rbtree_type* tree)
|
||||
{
|
||||
addr_tree_init_parents_node(
|
||||
(struct addr_tree_node*)rbtree_first(tree));
|
||||
}
|
||||
|
||||
void name_tree_init_parents(rbtree_type* tree)
|
||||
{
|
||||
struct name_tree_node* node, *prev = NULL, *p;
|
||||
|
@ -173,6 +173,13 @@ int addr_tree_insert(rbtree_type* tree, struct addr_tree_node* node,
|
||||
*/
|
||||
void addr_tree_init_parents(rbtree_type* tree);
|
||||
|
||||
/**
|
||||
* Initialize parent pointers in partial addr tree.
|
||||
* Reinitialize pointer for part of tree, used after node deletion
|
||||
* @param node: node to start parent pointer initialization for.
|
||||
*/
|
||||
void addr_tree_init_parents_node(struct addr_tree_node* node);
|
||||
|
||||
/**
|
||||
* Lookup closest encloser in addr tree.
|
||||
* @param tree: addr tree
|
||||
|
@ -54,6 +54,11 @@
|
||||
#error "Need crypto library to do digital signature cryptography"
|
||||
#endif
|
||||
|
||||
/** fake DSA support for unit tests */
|
||||
int fake_dsa = 0;
|
||||
/** fake SHA1 support for unit tests */
|
||||
int fake_sha1 = 0;
|
||||
|
||||
/* OpenSSL implementation */
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
@ -72,11 +77,6 @@
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
|
||||
/** fake DSA support for unit tests */
|
||||
int fake_dsa = 0;
|
||||
/** fake SHA1 support for unit tests */
|
||||
int fake_sha1 = 0;
|
||||
|
||||
/**
|
||||
* Output a libcrypto openssl error to the logfile.
|
||||
* @param str: string to add to it.
|
||||
@ -1509,13 +1509,21 @@ dnskey_algo_id_is_supported(int id)
|
||||
{
|
||||
/* uses libnettle */
|
||||
switch(id) {
|
||||
#if defined(USE_DSA) && defined(USE_SHA1)
|
||||
case LDNS_DSA:
|
||||
case LDNS_DSA_NSEC3:
|
||||
#if defined(USE_DSA) && defined(USE_SHA1)
|
||||
return 1;
|
||||
#else
|
||||
if(fake_dsa || fake_sha1) return 1;
|
||||
return 0;
|
||||
#endif
|
||||
#ifdef USE_SHA1
|
||||
case LDNS_RSASHA1:
|
||||
case LDNS_RSASHA1_NSEC3:
|
||||
#ifdef USE_SHA1
|
||||
return 1;
|
||||
#else
|
||||
if(fake_sha1) return 1;
|
||||
return 0;
|
||||
#endif
|
||||
#ifdef USE_SHA2
|
||||
case LDNS_RSASHA256:
|
||||
@ -1820,6 +1828,15 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
|
||||
return sec_status_bogus;
|
||||
}
|
||||
|
||||
#ifndef USE_DSA
|
||||
if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1))
|
||||
return sec_status_secure;
|
||||
#endif
|
||||
#ifndef USE_SHA1
|
||||
if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3))
|
||||
return sec_status_secure;
|
||||
#endif
|
||||
|
||||
switch(algo) {
|
||||
#if defined(USE_DSA) && defined(USE_SHA1)
|
||||
case LDNS_DSA:
|
||||
|
@ -121,6 +121,8 @@ val_apply_cfg(struct module_env* env, struct val_env* val_env,
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
if (env->key_cache)
|
||||
val_env->kcache = env->key_cache;
|
||||
if(!val_env->kcache)
|
||||
val_env->kcache = key_cache_create(cfg);
|
||||
if(!val_env->kcache) {
|
||||
@ -146,6 +148,8 @@ val_apply_cfg(struct module_env* env, struct val_env* val_env,
|
||||
log_err("validator: cannot apply nsec3 key iterations");
|
||||
return 0;
|
||||
}
|
||||
if (env->neg_cache)
|
||||
val_env->neg_cache = env->neg_cache;
|
||||
if(!val_env->neg_cache)
|
||||
val_env->neg_cache = val_neg_create(cfg,
|
||||
val_env->nsec3_maxiter[val_env->nsec3_keyiter_count-1]);
|
||||
@ -196,7 +200,9 @@ val_deinit(struct module_env* env, int id)
|
||||
anchors_delete(env->anchors);
|
||||
env->anchors = NULL;
|
||||
key_cache_delete(val_env->kcache);
|
||||
env->key_cache = NULL;
|
||||
neg_cache_delete(val_env->neg_cache);
|
||||
env->neg_cache = NULL;
|
||||
free(val_env->nsec3_keysize);
|
||||
free(val_env->nsec3_maxiter);
|
||||
free(val_env);
|
||||
|
@ -24,13 +24,13 @@ SRCS= alloc.c as112.c authzone.c autotrust.c cachedb.c config_file.c \
|
||||
mesh.c mini_event.c modstack.c module.c msgencode.c msgparse.c \
|
||||
msgreply.c net_help.c netevent.c outbound_list.c outside_network.c \
|
||||
packed_rrset.c parse.c parseutil.c random.c rbtree.c redis.c \
|
||||
regional.c respip.c rrdef.c rrset.c rtt.c sbuffer.c slabhash.c \
|
||||
regional.c respip.c rpz.c rrdef.c rrset.c rtt.c sbuffer.c slabhash.c \
|
||||
str2wire.c tcp_conn_limit.c timehist.c tube.c ub_event_pluggable.c \
|
||||
val_anchor.c val_kcache.c val_kentry.c val_neg.c val_nsec.c \
|
||||
val_nsec3.c val_secalgo.c val_sigcrypt.c val_utils.c validator.c \
|
||||
view.c winsock_event.c wire2str.c
|
||||
|
||||
WARNS?= 3
|
||||
WARNS?= 2
|
||||
NO_WTHREAD_SAFETY= true
|
||||
|
||||
LIBADD= ssl crypto pthread
|
||||
|
Loading…
Reference in New Issue
Block a user