mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Merge branch '3842-delv-ns' into 'main'
implement "delv +ns" Closes #3842 See merge request isc-projects/bind9!7477
This commit is contained in:
commit
bd7f85c7e1
29 changed files with 756 additions and 171 deletions
10
CHANGES
10
CHANGES
|
|
@ -1,3 +1,13 @@
|
|||
6130. [func] The new "delv +ns" option activates name server mode,
|
||||
in which delv sets up an internal recursive
|
||||
resolver and uses that, rather than an external
|
||||
server, to look up the requested data. All messages
|
||||
sent and received during the resolution and
|
||||
validation process are logged. This can be used in
|
||||
place of "dig +trace"; it more accurately
|
||||
replicates the behavior of named when resolving
|
||||
a query. [GL #3842]
|
||||
|
||||
6129. [cleanup] Value stored to 'source' during its initialization is
|
||||
never read. [GL #3965]
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ AM_CPPFLAGS += \
|
|||
-I$(top_builddir)/include \
|
||||
$(LIBISC_CFLAGS) \
|
||||
$(LIBDNS_CFLAGS) \
|
||||
$(LIBNS_CFLAGS) \
|
||||
$(LIBISCCFG_CFLAGS)
|
||||
|
||||
AM_CPPFLAGS += \
|
||||
|
|
@ -17,4 +18,5 @@ delv_SOURCES = \
|
|||
delv_LDADD = \
|
||||
$(LIBISC_LIBS) \
|
||||
$(LIBDNS_LIBS) \
|
||||
$(LIBNS_LIBS) \
|
||||
$(LIBISCCFG_LIBS)
|
||||
|
|
|
|||
541
bin/delv/delv.c
541
bin/delv/delv.c
|
|
@ -35,6 +35,7 @@
|
|||
#include <isc/mem.h>
|
||||
#include <isc/netmgr.h>
|
||||
#include <isc/parseint.h>
|
||||
#include <isc/random.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/sockaddr.h>
|
||||
#include <isc/string.h>
|
||||
|
|
@ -42,20 +43,28 @@
|
|||
#include <isc/tls.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/acl.h>
|
||||
#include <dns/byaddr.h>
|
||||
#include <dns/cache.h>
|
||||
#include <dns/client.h>
|
||||
#include <dns/dispatch.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/keytable.h>
|
||||
#include <dns/keyvalues.h>
|
||||
#include <dns/log.h>
|
||||
#include <dns/masterdump.h>
|
||||
#include <dns/message.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/rdataclass.h>
|
||||
#include <dns/rdataset.h>
|
||||
#include <dns/rdatastruct.h>
|
||||
#include <dns/rdatatype.h>
|
||||
#include <dns/request.h>
|
||||
#include <dns/result.h>
|
||||
#include <dns/rootns.h>
|
||||
#include <dns/secalg.h>
|
||||
#include <dns/stats.h>
|
||||
#include <dns/view.h>
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
|
@ -63,6 +72,10 @@
|
|||
#include <isccfg/log.h>
|
||||
#include <isccfg/namedconf.h>
|
||||
|
||||
#include <ns/client.h>
|
||||
#include <ns/interfacemgr.h>
|
||||
#include <ns/server.h>
|
||||
|
||||
#include <irs/resconf.h>
|
||||
|
||||
#define CHECK(r) \
|
||||
|
|
@ -75,13 +88,24 @@
|
|||
#define MAXNAME (DNS_NAME_MAXTEXT + 1)
|
||||
|
||||
/* Variables used internally by delv. */
|
||||
char *progname;
|
||||
char *progname = NULL;
|
||||
static isc_mem_t *mctx = NULL;
|
||||
static isc_log_t *lctx = NULL;
|
||||
static dns_view_t *view = NULL;
|
||||
static ns_server_t *sctx = NULL;
|
||||
static ns_interface_t *ifp = NULL;
|
||||
static dns_dispatch_t *dispatch = NULL;
|
||||
static dns_db_t *roothints = NULL;
|
||||
static isc_stats_t *resstats = NULL;
|
||||
static dns_stats_t *resquerystats = NULL;
|
||||
static FILE *logfp = NULL;
|
||||
|
||||
/* Managers */
|
||||
static isc_nm_t *netmgr = NULL;
|
||||
static isc_loopmgr_t *loopmgr = NULL;
|
||||
static dns_dispatchmgr_t *dispatchmgr = NULL;
|
||||
static dns_requestmgr_t *requestmgr = NULL;
|
||||
static ns_interfacemgr_t *interfacemgr = NULL;
|
||||
|
||||
/* TLS */
|
||||
static isc_tlsctx_cache_t *tlsctx_client_cache = NULL;
|
||||
|
|
@ -89,26 +113,29 @@ static isc_tlsctx_cache_t *tlsctx_client_cache = NULL;
|
|||
/* Configurables */
|
||||
static char *server = NULL;
|
||||
static const char *port = "53";
|
||||
static uint32_t destport = 53;
|
||||
static isc_sockaddr_t *srcaddr4 = NULL, *srcaddr6 = NULL;
|
||||
static isc_sockaddr_t a4, a6;
|
||||
static char *curqname = NULL, *qname = NULL;
|
||||
static bool classset = false;
|
||||
static dns_rdatatype_t qtype = dns_rdatatype_none;
|
||||
static bool typeset = false;
|
||||
static const char *hintfile = NULL;
|
||||
|
||||
static unsigned int styleflags = 0;
|
||||
static uint32_t splitwidth = 0xffffffff;
|
||||
static bool showcomments = true, showdnssec = true, showtrust = true,
|
||||
rrcomments = true, noclass = false, nocrypto = false, nottl = false,
|
||||
multiline = false, short_form = false, print_unknown_format = false,
|
||||
yaml = false;
|
||||
yaml = false, fulltrace = false;
|
||||
|
||||
static bool resolve_trace = false, validator_trace = false,
|
||||
message_trace = false;
|
||||
message_trace = false, send_trace = false;
|
||||
|
||||
static bool use_ipv4 = true, use_ipv6 = true;
|
||||
|
||||
static bool cdflag = false, no_sigs = false, root_validation = true;
|
||||
static bool qmin = false, qmin_strict = false;
|
||||
|
||||
static bool use_tcp = false;
|
||||
|
||||
|
|
@ -189,8 +216,12 @@ usage(void) {
|
|||
"records)\n"
|
||||
" +[no]mtrace (Trace messages "
|
||||
"received)\n"
|
||||
" +[no]ns (Run internal name "
|
||||
"server)\n"
|
||||
" +[no]multiline (Print records in an "
|
||||
"expanded format)\n"
|
||||
" +[no]qmin[=mode] (QNAME minimization: "
|
||||
"relaxed or strict)\n"
|
||||
" +[no]root (DNSSEC validation trust "
|
||||
"anchor)\n"
|
||||
" +[no]rrcomments (Control display of "
|
||||
|
|
@ -201,6 +232,8 @@ usage(void) {
|
|||
" +[no]short (Short form answer)\n"
|
||||
" +[no]split=## (Split hex/base64 fields "
|
||||
"into chunks)\n"
|
||||
" +[no]strace (Trace messages "
|
||||
"sent)\n"
|
||||
" +[no]tcp (TCP mode)\n"
|
||||
" +[no]ttl (Control display of ttls "
|
||||
"in records)\n"
|
||||
|
|
@ -280,6 +313,7 @@ setup_logging(FILE *errout) {
|
|||
isc_result_t result;
|
||||
isc_logdestination_t destination;
|
||||
isc_logconfig_t *logconfig = NULL;
|
||||
int packetlevel = 10;
|
||||
|
||||
isc_log_create(mctx, &lctx, &logconfig);
|
||||
isc_log_registercategories(lctx, categories);
|
||||
|
|
@ -332,9 +366,12 @@ setup_logging(FILE *errout) {
|
|||
}
|
||||
}
|
||||
|
||||
if (message_trace && loglevel < 10) {
|
||||
if (send_trace) {
|
||||
packetlevel = 11;
|
||||
}
|
||||
if ((message_trace || send_trace) && loglevel < packetlevel) {
|
||||
isc_log_createchannel(logconfig, "messages", ISC_LOG_TOFILEDESC,
|
||||
ISC_LOG_DEBUG(10), &destination,
|
||||
ISC_LOG_DEBUG(packetlevel), &destination,
|
||||
ISC_LOG_PRINTPREFIX);
|
||||
|
||||
result = isc_log_usechannel(logconfig, "messages",
|
||||
|
|
@ -424,7 +461,7 @@ print_status(dns_rdataset_t *rdataset) {
|
|||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
static void
|
||||
printdata(dns_rdataset_t *rdataset, dns_name_t *owner) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
static dns_trust_t trust;
|
||||
|
|
@ -437,12 +474,13 @@ printdata(dns_rdataset_t *rdataset, dns_name_t *owner) {
|
|||
if (!dns_rdataset_isassociated(rdataset)) {
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
dns_name_format(owner, namebuf, sizeof(namebuf));
|
||||
delv_log(ISC_LOG_DEBUG(4), "WARN: empty rdataset %s", namebuf);
|
||||
return (ISC_R_SUCCESS);
|
||||
delv_log(ISC_LOG_DEBUG(4), "warning: empty rdataset %s",
|
||||
namebuf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!showdnssec && rdataset->type == dns_rdatatype_rrsig) {
|
||||
return (ISC_R_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (first || rdataset->trust != trust) {
|
||||
|
|
@ -516,8 +554,6 @@ cleanup:
|
|||
if (t != NULL) {
|
||||
isc_mem_put(mctx, t, len);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
|
|
@ -570,7 +606,7 @@ static isc_result_t
|
|||
convert_name(dns_fixedname_t *fn, dns_name_t **name, const char *text) {
|
||||
isc_result_t result;
|
||||
isc_buffer_t b;
|
||||
dns_name_t *n;
|
||||
dns_name_t *n = NULL;
|
||||
unsigned int len;
|
||||
|
||||
REQUIRE(fn != NULL && name != NULL && text != NULL);
|
||||
|
|
@ -582,7 +618,7 @@ convert_name(dns_fixedname_t *fn, dns_name_t **name, const char *text) {
|
|||
|
||||
result = dns_name_fromtext(n, &b, dns_rootname, 0, NULL);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
delv_log(ISC_LOG_ERROR, "failed to convert QNAME %s: %s", text,
|
||||
delv_log(ISC_LOG_ERROR, "failed to convert name %s: %s", text,
|
||||
isc_result_totext(result));
|
||||
return (result);
|
||||
}
|
||||
|
|
@ -592,7 +628,7 @@ convert_name(dns_fixedname_t *fn, dns_name_t **name, const char *text) {
|
|||
}
|
||||
|
||||
static isc_result_t
|
||||
key_fromconfig(const cfg_obj_t *key, dns_client_t *client) {
|
||||
key_fromconfig(const cfg_obj_t *key, dns_client_t *client, dns_view_t *toview) {
|
||||
dns_rdata_dnskey_t dnskey;
|
||||
dns_rdata_ds_t ds;
|
||||
uint32_t rdata1, rdata2, rdata3;
|
||||
|
|
@ -615,6 +651,8 @@ key_fromconfig(const cfg_obj_t *key, dns_client_t *client) {
|
|||
} anchortype;
|
||||
const cfg_obj_t *obj;
|
||||
|
||||
REQUIRE(client != NULL || toview != NULL);
|
||||
|
||||
keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
|
||||
CHECK(convert_name(&fkeyname, &keyname, keynamestr));
|
||||
|
||||
|
|
@ -708,9 +746,15 @@ key_fromconfig(const cfg_obj_t *key, dns_client_t *client) {
|
|||
CHECK(dns_rdata_fromstruct(NULL, dnskey.common.rdclass,
|
||||
dnskey.common.rdtype, &dnskey,
|
||||
&rrdatabuf));
|
||||
CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in,
|
||||
dns_rdatatype_dnskey, keyname,
|
||||
&rrdatabuf));
|
||||
if (client != NULL) {
|
||||
CHECK(dns_client_addtrustedkey(
|
||||
client, dns_rdataclass_in, dns_rdatatype_dnskey,
|
||||
keyname, &rrdatabuf));
|
||||
} else if (toview != NULL) {
|
||||
CHECK(dns_view_addtrustedkey(toview,
|
||||
dns_rdatatype_dnskey,
|
||||
keyname, &rrdatabuf));
|
||||
}
|
||||
break;
|
||||
case INITIAL_DS:
|
||||
case STATIC_DS:
|
||||
|
|
@ -751,9 +795,14 @@ key_fromconfig(const cfg_obj_t *key, dns_client_t *client) {
|
|||
|
||||
CHECK(dns_rdata_fromstruct(NULL, ds.common.rdclass,
|
||||
ds.common.rdtype, &ds, &rrdatabuf));
|
||||
CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in,
|
||||
dns_rdatatype_ds, keyname,
|
||||
&rrdatabuf));
|
||||
if (client != NULL) {
|
||||
CHECK(dns_client_addtrustedkey(
|
||||
client, dns_rdataclass_in, dns_rdatatype_ds,
|
||||
keyname, &rrdatabuf));
|
||||
} else if (toview != NULL) {
|
||||
CHECK(dns_view_addtrustedkey(toview, dns_rdatatype_ds,
|
||||
keyname, &rrdatabuf));
|
||||
}
|
||||
}
|
||||
|
||||
num_keys++;
|
||||
|
|
@ -777,7 +826,7 @@ cleanup:
|
|||
}
|
||||
|
||||
static isc_result_t
|
||||
load_keys(const cfg_obj_t *keys, dns_client_t *client) {
|
||||
load_keys(const cfg_obj_t *keys, dns_client_t *client, dns_view_t *toview) {
|
||||
const cfg_listelt_t *elt, *elt2;
|
||||
const cfg_obj_t *key, *keylist;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
|
@ -790,7 +839,7 @@ load_keys(const cfg_obj_t *keys, dns_client_t *client) {
|
|||
elt2 = cfg_list_next(elt2))
|
||||
{
|
||||
key = cfg_listelt_value(elt2);
|
||||
CHECK(key_fromconfig(key, client));
|
||||
CHECK(key_fromconfig(key, client, toview));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -802,7 +851,7 @@ cleanup:
|
|||
}
|
||||
|
||||
static isc_result_t
|
||||
setup_dnsseckeys(dns_client_t *client) {
|
||||
setup_dnsseckeys(dns_client_t *client, dns_view_t *toview) {
|
||||
isc_result_t result;
|
||||
cfg_parser_t *parser = NULL;
|
||||
const cfg_obj_t *trusted_keys = NULL;
|
||||
|
|
@ -853,13 +902,13 @@ setup_dnsseckeys(dns_client_t *client) {
|
|||
cfg_map_get(bindkeys, "trust-anchors", &trust_anchors);
|
||||
|
||||
if (trusted_keys != NULL) {
|
||||
CHECK(load_keys(trusted_keys, client));
|
||||
CHECK(load_keys(trusted_keys, client, toview));
|
||||
}
|
||||
if (managed_keys != NULL) {
|
||||
CHECK(load_keys(managed_keys, client));
|
||||
CHECK(load_keys(managed_keys, client, toview));
|
||||
}
|
||||
if (trust_anchors != NULL) {
|
||||
CHECK(load_keys(trust_anchors, client));
|
||||
CHECK(load_keys(trust_anchors, client, toview));
|
||||
}
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
|
|
@ -883,21 +932,15 @@ cleanup:
|
|||
|
||||
static isc_result_t
|
||||
addserver(dns_client_t *client) {
|
||||
struct addrinfo hints, *res, *cur;
|
||||
struct addrinfo hints, *res = NULL, *cur = NULL;
|
||||
int gaierror;
|
||||
struct in_addr in4;
|
||||
struct in6_addr in6;
|
||||
isc_sockaddr_t *sa;
|
||||
isc_sockaddr_t *sa = NULL;
|
||||
isc_sockaddrlist_t servers;
|
||||
uint32_t destport;
|
||||
isc_result_t result;
|
||||
dns_name_t *name = NULL;
|
||||
|
||||
result = parse_uint(&destport, port, 0xffff, "port");
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("Couldn't parse port number");
|
||||
}
|
||||
|
||||
ISC_LIST_INIT(servers);
|
||||
|
||||
if (inet_pton(AF_INET, server, &in4) == 1) {
|
||||
|
|
@ -975,13 +1018,7 @@ findserver(dns_client_t *client) {
|
|||
isc_result_t result;
|
||||
irs_resconf_t *resconf = NULL;
|
||||
isc_sockaddrlist_t *nameservers;
|
||||
isc_sockaddr_t *sa, *next;
|
||||
uint32_t destport;
|
||||
|
||||
result = parse_uint(&destport, port, 0xffff, "port");
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("Couldn't parse port number");
|
||||
}
|
||||
isc_sockaddr_t *sa = NULL, *next = NULL;
|
||||
|
||||
result = irs_resconf_load(mctx, "/etc/resolv.conf", &resconf);
|
||||
if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
|
||||
|
|
@ -1135,9 +1172,26 @@ plus_option(char *option) {
|
|||
goto invalid_option;
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
switch (cmd[1]) {
|
||||
case 'i': /* hint */
|
||||
if (state) {
|
||||
if (value == NULL) {
|
||||
fatal("+hint: must specify hint file");
|
||||
}
|
||||
hintfile = value;
|
||||
} else {
|
||||
hintfile = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
switch (cmd[1]) {
|
||||
case 't': /* mtrace */
|
||||
FULLCHECK("mtrace");
|
||||
message_trace = state;
|
||||
if (state) {
|
||||
resolve_trace = state;
|
||||
|
|
@ -1151,6 +1205,41 @@ plus_option(char *option) {
|
|||
goto invalid_option;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
switch (cmd[1]) {
|
||||
case 's': /* ns */
|
||||
FULLCHECK("ns");
|
||||
fulltrace = state;
|
||||
if (state) {
|
||||
message_trace = state;
|
||||
send_trace = state;
|
||||
resolve_trace = state;
|
||||
logfp = stdout;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
break;
|
||||
case 'q': /* qmin */
|
||||
FULLCHECK("qmin");
|
||||
if (state) {
|
||||
if (value == NULL || strcasecmp(value, "relaxed") == 0)
|
||||
{
|
||||
qmin = true;
|
||||
} else if (strcasecmp(value, "strict") == 0) {
|
||||
qmin = true;
|
||||
qmin_strict = true;
|
||||
} else {
|
||||
fatal("Invalid qmin option '%s': "
|
||||
"use 'relaxed' or 'strict'\n",
|
||||
value);
|
||||
}
|
||||
} else {
|
||||
qmin = false;
|
||||
qmin_strict = false;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
switch (cmd[1]) {
|
||||
case 'o': /* root */
|
||||
|
|
@ -1220,6 +1309,13 @@ plus_option(char *option) {
|
|||
fatal("Couldn't parse split");
|
||||
}
|
||||
break;
|
||||
case 't': /* strace */
|
||||
FULLCHECK("strace");
|
||||
send_trace = state;
|
||||
if (state) {
|
||||
message_trace = state;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
|
|
@ -1234,9 +1330,20 @@ plus_option(char *option) {
|
|||
FULLCHECK("tcp");
|
||||
use_tcp = state;
|
||||
break;
|
||||
case 'r': /* trust */
|
||||
FULLCHECK("trust");
|
||||
showtrust = state;
|
||||
case 'r':
|
||||
switch (cmd[2]) {
|
||||
case 'a': /* trace */
|
||||
FULLCHECK("trace");
|
||||
fatal("Invalid argument +trace. For "
|
||||
"delegation path tracing, use +ns.");
|
||||
break;
|
||||
case 'u': /* trust */
|
||||
FULLCHECK("trust");
|
||||
showtrust = state;
|
||||
break;
|
||||
default:
|
||||
goto invalid_option;
|
||||
}
|
||||
break;
|
||||
case 't': /* ttl */
|
||||
FULLCHECK("ttl");
|
||||
|
|
@ -1269,6 +1376,10 @@ plus_option(char *option) {
|
|||
fprintf(stderr, "Invalid option: +%s\n", option);
|
||||
usage();
|
||||
}
|
||||
|
||||
if (qmin && !fulltrace) {
|
||||
fatal("'+qmin' cannot be used without '+ns'");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1420,6 +1531,10 @@ dash_option(char *option, char *next, bool *open_type_class) {
|
|||
return (value_from_next);
|
||||
case 'p':
|
||||
port = value;
|
||||
result = parse_uint(&destport, port, 0xffff, "port");
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("Couldn't parse port number");
|
||||
}
|
||||
return (value_from_next);
|
||||
case 'q':
|
||||
if (curqname != NULL) {
|
||||
|
|
@ -1735,10 +1850,7 @@ resolve_cb(dns_client_t *client, const dns_name_t *query_name,
|
|||
for (rdataset = ISC_LIST_HEAD(response_name->list);
|
||||
rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link))
|
||||
{
|
||||
result = printdata(rdataset, response_name);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
delv_log(ISC_LOG_ERROR, "print data failed");
|
||||
}
|
||||
printdata(rdataset, response_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1751,12 +1863,14 @@ resolve_cb(dns_client_t *client, const dns_name_t *query_name,
|
|||
}
|
||||
|
||||
static void
|
||||
resolve(void *arg) {
|
||||
dns_client_t *client = arg;
|
||||
dns_namelist_t *namelist;
|
||||
run_resolve(void *arg) {
|
||||
dns_client_t *client = NULL;
|
||||
dns_namelist_t *namelist = NULL;
|
||||
unsigned int resopt;
|
||||
isc_result_t result;
|
||||
dns_name_t *query_name;
|
||||
dns_name_t *query_name = NULL;
|
||||
|
||||
UNUSED(arg);
|
||||
|
||||
namelist = isc_mem_get(mctx, sizeof(*namelist));
|
||||
ISC_LIST_INIT(*namelist);
|
||||
|
|
@ -1779,14 +1893,22 @@ resolve(void *arg) {
|
|||
resopt |= DNS_CLIENTRESOPT_TCP;
|
||||
}
|
||||
|
||||
/* Perform resolution */
|
||||
result = dns_client_resolve(client, query_name, dns_rdataclass_in,
|
||||
qtype, resopt, namelist, resolve_cb);
|
||||
/* Create client */
|
||||
CHECK(dns_client_create(mctx, loopmgr, netmgr, 0, tlsctx_client_cache,
|
||||
&client, srcaddr4, srcaddr6));
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
/* Set the nameserver */
|
||||
if (server != NULL) {
|
||||
addserver(client);
|
||||
} else {
|
||||
findserver(client);
|
||||
}
|
||||
|
||||
CHECK(setup_dnsseckeys(client, NULL));
|
||||
|
||||
/* Perform resolution */
|
||||
CHECK(dns_client_resolve(client, query_name, dns_rdataclass_in, qtype,
|
||||
resopt, namelist, resolve_cb));
|
||||
return;
|
||||
cleanup:
|
||||
if (!yaml) {
|
||||
|
|
@ -1800,18 +1922,278 @@ cleanup:
|
|||
dns_client_detach(&client);
|
||||
}
|
||||
|
||||
static void
|
||||
shutdown_server(void) {
|
||||
if (requestmgr != NULL) {
|
||||
dns_requestmgr_detach(&requestmgr);
|
||||
}
|
||||
if (interfacemgr != NULL) {
|
||||
ns_interfacemgr_shutdown(interfacemgr);
|
||||
ns_interfacemgr_detach(&interfacemgr);
|
||||
}
|
||||
if (dispatch != NULL) {
|
||||
dns_dispatch_detach(&dispatch);
|
||||
}
|
||||
if (dispatchmgr != NULL) {
|
||||
dns_dispatchmgr_detach(&dispatchmgr);
|
||||
}
|
||||
if (sctx != NULL) {
|
||||
ns_server_detach(&sctx);
|
||||
}
|
||||
|
||||
isc_loopmgr_shutdown(loopmgr);
|
||||
}
|
||||
|
||||
static void
|
||||
recvresponse(void *arg) {
|
||||
dns_request_t *request = (dns_request_t *)arg;
|
||||
dns_message_t *query = dns_request_getarg(request);
|
||||
isc_result_t result = dns_request_getresult(request);
|
||||
dns_message_t *response = NULL;
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("request event result: %s", isc_result_totext(result));
|
||||
}
|
||||
|
||||
dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
|
||||
|
||||
result = dns_request_getresponse(request, response,
|
||||
DNS_MESSAGEPARSE_PRESERVEORDER);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
fatal("request response failed: %s", isc_result_totext(result));
|
||||
}
|
||||
if (response->rcode != dns_rcode_noerror) {
|
||||
result = dns_result_fromrcode(response->rcode);
|
||||
delv_log(ISC_LOG_INFO, "response code: %s",
|
||||
isc_result_totext(result));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (result = dns_message_firstname(response, DNS_SECTION_ANSWER);
|
||||
result == ISC_R_SUCCESS;
|
||||
result = dns_message_nextname(response, DNS_SECTION_ANSWER))
|
||||
{
|
||||
dns_name_t *name = NULL;
|
||||
dns_rdataset_t *rdataset = NULL;
|
||||
|
||||
dns_message_currentname(response, DNS_SECTION_ANSWER, &name);
|
||||
for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
|
||||
rdataset = ISC_LIST_NEXT(rdataset, link))
|
||||
{
|
||||
dns_rdataset_t rds, sigs;
|
||||
int options = 0;
|
||||
|
||||
/*
|
||||
* The response message contains the answer the
|
||||
* resolver found, but it doesn't contain the
|
||||
* trust status; so if we're displaying that, we
|
||||
* need to look up each rdataset in the cache and
|
||||
* print that version instead. but if not, we
|
||||
* can just print the rdatasets from the message.
|
||||
*/
|
||||
if (!showtrust) {
|
||||
printdata(rdataset, name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* do the cache lookup */
|
||||
if (rdataset->type == dns_rdatatype_rrsig) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dns_rdataset_init(&rds);
|
||||
dns_rdataset_init(&sigs);
|
||||
|
||||
if (cdflag) {
|
||||
options |= DNS_DBFIND_PENDINGOK;
|
||||
}
|
||||
result = dns_view_simplefind(view, name, rdataset->type,
|
||||
0, options, false, &rds,
|
||||
&sigs);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
printdata(&rds, name);
|
||||
dns_rdataset_disassociate(&rds);
|
||||
if (dns_rdataset_isassociated(&sigs)) {
|
||||
printdata(&sigs, name);
|
||||
dns_rdataset_disassociate(&sigs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
dns_message_detach(&query);
|
||||
dns_message_detach(&response);
|
||||
dns_request_destroy(&request);
|
||||
|
||||
dns_view_detach(&view);
|
||||
shutdown_server();
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
accept_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
UNUSED(handle);
|
||||
UNUSED(arg);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
sendquery(void *arg) {
|
||||
isc_nmsocket_t *sock = (isc_nmsocket_t *)arg;
|
||||
isc_sockaddr_t peer = isc_nmsocket_getaddr(sock);
|
||||
isc_result_t result;
|
||||
dns_message_t *message = NULL;
|
||||
dns_name_t *query_name = NULL, *mname = NULL;
|
||||
dns_rdataset_t *mrdataset = NULL;
|
||||
dns_rdataset_t *opt = NULL;
|
||||
dns_request_t *request = NULL;
|
||||
|
||||
/* Construct query message */
|
||||
CHECK(convert_name(&qfn, &query_name, qname));
|
||||
|
||||
dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
|
||||
message->opcode = dns_opcode_query;
|
||||
message->flags = DNS_MESSAGEFLAG_RD | DNS_MESSAGEFLAG_AD;
|
||||
if (cdflag) {
|
||||
message->flags |= DNS_MESSAGEFLAG_CD;
|
||||
}
|
||||
message->rdclass = dns_rdataclass_in;
|
||||
message->id = (dns_messageid_t)isc_random16();
|
||||
|
||||
dns_message_gettempname(message, &mname);
|
||||
dns_message_gettemprdataset(message, &mrdataset);
|
||||
dns_name_clone(query_name, mname);
|
||||
dns_rdataset_makequestion(mrdataset, dns_rdataclass_in, qtype);
|
||||
ISC_LIST_APPEND(mname->list, mrdataset, link);
|
||||
dns_message_addname(message, mname, DNS_SECTION_QUESTION);
|
||||
mrdataset = NULL;
|
||||
mname = NULL;
|
||||
|
||||
CHECK(dns_message_buildopt(message, &opt, 0, 0, DNS_MESSAGEEXTFLAG_DO,
|
||||
NULL, 0));
|
||||
CHECK(dns_message_setopt(message, opt));
|
||||
|
||||
CHECK(dns_requestmgr_create(mctx, dispatchmgr, NULL, NULL,
|
||||
&requestmgr));
|
||||
|
||||
dns_view_attach(view, &(dns_view_t *){ NULL });
|
||||
CHECK(dns_request_create(requestmgr, message, NULL, &peer, NULL, NULL,
|
||||
DNS_REQUESTOPT_TCP, NULL, 1, 0, 0,
|
||||
isc_loop_current(loopmgr), recvresponse,
|
||||
message, &request));
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
if (message != NULL) {
|
||||
if (mname != NULL) {
|
||||
dns_message_puttempname(message, &mname);
|
||||
}
|
||||
if (mrdataset != NULL) {
|
||||
dns_message_puttemprdataset(message, &mrdataset);
|
||||
}
|
||||
dns_message_detach(&message);
|
||||
}
|
||||
|
||||
shutdown_server();
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
matchview(isc_netaddr_t *srcaddr, isc_netaddr_t *destaddr,
|
||||
dns_message_t *message, dns_aclenv_t *env, isc_result_t *sigresultp,
|
||||
dns_view_t **viewp) {
|
||||
UNUSED(srcaddr);
|
||||
UNUSED(destaddr);
|
||||
UNUSED(message);
|
||||
UNUSED(env);
|
||||
UNUSED(sigresultp);
|
||||
|
||||
*viewp = view;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
run_server(void *arg) {
|
||||
isc_result_t result;
|
||||
dns_cache_t *cache = NULL;
|
||||
isc_sockaddr_t addr, any;
|
||||
struct in_addr in;
|
||||
|
||||
UNUSED(arg);
|
||||
|
||||
inet_pton(AF_INET, "127.0.0.1", &in);
|
||||
isc_sockaddr_fromin(&addr, &in, 0);
|
||||
|
||||
CHECK(ns_server_create(mctx, matchview, &sctx));
|
||||
|
||||
CHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr));
|
||||
isc_sockaddr_any(&any);
|
||||
CHECK(dns_dispatch_createudp(dispatchmgr, &any, &dispatch));
|
||||
CHECK(ns_interfacemgr_create(mctx, sctx, loopmgr, netmgr, dispatchmgr,
|
||||
NULL, false, &interfacemgr));
|
||||
|
||||
CHECK(dns_view_create(mctx, dns_rdataclass_in, "_default", &view));
|
||||
CHECK(dns_cache_create(loopmgr, dns_rdataclass_in, "", &cache));
|
||||
dns_view_setcache(view, cache, false);
|
||||
dns_cache_detach(&cache);
|
||||
dns_view_setdstport(view, destport);
|
||||
|
||||
CHECK(dns_rootns_create(mctx, dns_rdataclass_in, hintfile, &roothints));
|
||||
dns_view_sethints(view, roothints);
|
||||
dns_db_detach(&roothints);
|
||||
|
||||
view->qminimization = qmin;
|
||||
view->qmin_strict = qmin_strict;
|
||||
|
||||
CHECK(dns_view_initsecroots(view, mctx));
|
||||
CHECK(setup_dnsseckeys(NULL, view));
|
||||
|
||||
dns_view_setdispatchmgr(view, dispatchmgr);
|
||||
CHECK(dns_view_createresolver(view, loopmgr, 1, netmgr, 0,
|
||||
tlsctx_client_cache, dispatch, NULL));
|
||||
|
||||
CHECK(isc_stats_create(mctx, &resstats, dns_resstatscounter_max));
|
||||
dns_resolver_setstats(view->resolver, resstats);
|
||||
isc_stats_detach(&resstats);
|
||||
|
||||
CHECK(dns_rdatatypestats_create(mctx, &resquerystats));
|
||||
dns_resolver_setquerystats(view->resolver, resquerystats);
|
||||
dns_stats_detach(&resquerystats);
|
||||
|
||||
dns_view_freeze(view);
|
||||
|
||||
ns_interface_create(interfacemgr, &addr, NULL, &ifp);
|
||||
|
||||
CHECK(isc_nm_listenstreamdns(netmgr, ISC_NM_LISTEN_ONE, &addr,
|
||||
ns_client_request, ifp, accept_cb, ifp, 10,
|
||||
NULL, NULL, &ifp->tcplistensocket));
|
||||
ifp->flags |= NS_INTERFACEFLAG_LISTENING;
|
||||
isc_job_run(loopmgr, sendquery, ifp->tcplistensocket);
|
||||
|
||||
return;
|
||||
|
||||
cleanup:
|
||||
if (view != NULL) {
|
||||
dns_view_detach(&view);
|
||||
}
|
||||
shutdown_server();
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
dns_client_t *client = NULL;
|
||||
isc_result_t result;
|
||||
isc_loop_t *loop = NULL;
|
||||
|
||||
progname = argv[0];
|
||||
logfp = stderr;
|
||||
|
||||
preparse_args(argc, argv);
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
isc_managers_create(&mctx, 1, &loopmgr, &netmgr);
|
||||
loop = isc_loop_main(loopmgr);
|
||||
|
||||
result = dst_lib_init(mctx, NULL);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -1822,33 +2204,30 @@ main(int argc, char *argv[]) {
|
|||
|
||||
CHECK(setup_style());
|
||||
|
||||
setup_logging(stderr);
|
||||
setup_logging(logfp);
|
||||
|
||||
if (!fulltrace && hintfile != NULL) {
|
||||
delv_log(ISC_LOG_WARNING,
|
||||
"WARNING: not using internal name server mode, "
|
||||
"hint file will be ignored");
|
||||
}
|
||||
|
||||
if (fulltrace && server != NULL) {
|
||||
delv_log(ISC_LOG_WARNING,
|
||||
"WARNING: using internal name server mode: "
|
||||
"'@%s' will be ignored",
|
||||
server);
|
||||
}
|
||||
|
||||
/* Create client */
|
||||
isc_tlsctx_cache_create(mctx, &tlsctx_client_cache);
|
||||
result = dns_client_create(mctx, loopmgr, netmgr, 0,
|
||||
tlsctx_client_cache, &client, srcaddr4,
|
||||
srcaddr6);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
delv_log(ISC_LOG_ERROR, "dns_client_create: %s",
|
||||
isc_result_totext(result));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Set the nameserver */
|
||||
if (server != NULL) {
|
||||
addserver(client);
|
||||
} else {
|
||||
findserver(client);
|
||||
}
|
||||
|
||||
CHECK(setup_dnsseckeys(client));
|
||||
|
||||
isc_loop_setup(isc_loop_main(loopmgr), resolve, client);
|
||||
|
||||
isc_loop_setup(loop, fulltrace ? run_server : run_resolve, NULL);
|
||||
isc_loopmgr_run(loopmgr);
|
||||
|
||||
cleanup:
|
||||
if (tlsctx_client_cache != NULL) {
|
||||
isc_tlsctx_cache_detach(&tlsctx_client_cache);
|
||||
}
|
||||
if (trust_anchor != NULL) {
|
||||
isc_mem_free(mctx, trust_anchor);
|
||||
}
|
||||
|
|
@ -1861,12 +2240,8 @@ cleanup:
|
|||
if (style != NULL) {
|
||||
dns_master_styledestroy(&style, mctx);
|
||||
}
|
||||
if (tlsctx_client_cache != NULL) {
|
||||
isc_tlsctx_cache_detach(&tlsctx_client_cache);
|
||||
}
|
||||
|
||||
isc_log_destroy(&lctx);
|
||||
|
||||
dst_lib_destroy();
|
||||
|
||||
isc_managers_destroy(&mctx, &loopmgr, &netmgr);
|
||||
|
|
|
|||
|
|
@ -230,6 +230,36 @@ assign values to options like the timeout interval. They have the form
|
|||
This option controls whether to display the CLASS when printing a record. The
|
||||
default is to display the CLASS.
|
||||
|
||||
.. option:: +hint=FILE, +nohint
|
||||
|
||||
This option specifies a filename from which to load root hints;
|
||||
this will be used to find the root name servers when name server
|
||||
mode (``delv +ns``) is in use. If the option is not specified,
|
||||
built-in root hints will be used.
|
||||
|
||||
.. option:: +ns, +nons
|
||||
|
||||
This option toggles name server mode. When this option is in use,
|
||||
the ``delv`` process instantiates a full recursive resolver, and uses
|
||||
that to look up the requested query name and type. Turning on this
|
||||
option also activates ``+mtrace``, ``+strace`` and ``+rtrace``, so that
|
||||
every iterative query will be logged, including the full response messages
|
||||
from each authoritatve server. These logged messages will be written
|
||||
to ``stdout`` rather than ``stderr`` as usual, so that the full trace
|
||||
can be captured more easily.
|
||||
|
||||
This is intended to be similar to the behavior of ``dig +trace``, but
|
||||
because it uses the same code as ``named``, it much more accurately
|
||||
replicates the behavior of a recursive name server with a cold cache
|
||||
that is processing a recursive query.
|
||||
|
||||
.. option:: +qmin[=MODE], +noqmin
|
||||
|
||||
When used with ``+ns``, this option enables QNAME minimization mode.
|
||||
Valid options of MODE are ``relaxed`` and ``strict``. By default,
|
||||
QNAME minimization is disabled. If ``+qmin`` is specified but MODE
|
||||
is omitted, then ``relaxed`` mode will be used.
|
||||
|
||||
.. option:: +ttl, +nottl
|
||||
|
||||
This option controls whether to display the TTL when printing a record. The
|
||||
|
|
@ -237,11 +267,11 @@ assign values to options like the timeout interval. They have the form
|
|||
|
||||
.. option:: +rtrace, +nortrace
|
||||
|
||||
This option toggles resolver fetch logging. This reports the name and type of each
|
||||
query sent by :program:`delv` in the process of carrying out the resolution
|
||||
and validation process, including the original query
|
||||
and all subsequent queries to follow CNAMEs and to establish a chain
|
||||
of trust for DNSSEC validation.
|
||||
This option toggles resolver fetch logging. This reports the name and
|
||||
type of each query sent by :program:`delv` in the process of carrying
|
||||
out the resolution and validation process, including the original query
|
||||
and all subsequent queries to follow CNAMEs and to establish a chain of
|
||||
trust for DNSSEC validation.
|
||||
|
||||
This is equivalent to setting the debug level to 1 in the "resolver"
|
||||
logging category. Setting the systemwide debug level to 1 using the
|
||||
|
|
@ -250,15 +280,27 @@ assign values to options like the timeout interval. They have the form
|
|||
|
||||
.. option:: +mtrace, +nomtrace
|
||||
|
||||
This option toggles message logging. This produces a detailed dump of the
|
||||
responses received by :program:`delv` in the process of carrying out the
|
||||
resolution and validation process.
|
||||
This option toggles logging of messages received. This produces
|
||||
a detailed dump of the responses received by :program:`delv` in the
|
||||
process of carrying out the resolution and validation process.
|
||||
|
||||
This is equivalent to setting the debug level to 10 for the "packets"
|
||||
module of the "resolver" logging category. Setting the systemwide
|
||||
debug level to 10 using the :option:`-d` option produces the same
|
||||
output, but affects other logging categories as well.
|
||||
|
||||
.. option:: +strace, +nostrace
|
||||
|
||||
This option toggles logging of messages sent. This produces a detailed
|
||||
dump of the queries sent by :program:`delv` in the process of carrying
|
||||
out the resolution and validation process. Turning on this option
|
||||
also activates ``+mtrace``.
|
||||
|
||||
This is equivalent to setting the debug level to 11 for the "packets"
|
||||
module of the "resolver" logging category. Setting the systemwide
|
||||
debug level to 11 using the :option:`-d` option produces the same
|
||||
output, but affects other logging categories as well.
|
||||
|
||||
.. option:: +vtrace, +novtrace
|
||||
|
||||
This option toggles validation logging. This shows the internal process of the
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
set -e
|
||||
|
||||
rm -f ./*/anchor.*
|
||||
rm -f ./anchor.* ./*/anchor.*
|
||||
rm -f ./*/named.conf
|
||||
rm -f ./*/named.memstats
|
||||
rm -f ./*/named.run
|
||||
|
|
@ -28,9 +28,10 @@ rm -f ./dig.out.nn.*
|
|||
rm -f ./host.out.test*
|
||||
rm -f ./ns*/managed-keys.bind*
|
||||
rm -f ./ns*/named.lock
|
||||
rm -f ./ns2/dsset-example.
|
||||
rm -f ./ns2/dsset-example.tld.
|
||||
rm -f ./ns2/example.db ./ns2/K* ./ns2/keyid ./ns2/keydata
|
||||
rm -f ./ns*/K* ./ns*/keyid ./ns*/keydata
|
||||
rm -f ./ns1/root.db
|
||||
rm -f ./ns*/dsset-*
|
||||
rm -f ./ns2/example.db
|
||||
rm -f ./ns2/example.tld.db
|
||||
rm -f ./nslookup.out.test*
|
||||
rm -f ./nsupdate.out.test*
|
||||
|
|
|
|||
31
bin/tests/system/digdelv/ns1/sign.sh
Normal file
31
bin/tests/system/digdelv/ns1/sign.sh
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# shellcheck source=conf.sh
|
||||
. ../../conf.sh
|
||||
|
||||
set -e
|
||||
|
||||
(cd ../ns2 && $SHELL sign.sh )
|
||||
|
||||
cp "../ns2/dsset-example." .
|
||||
|
||||
ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone .)
|
||||
|
||||
cp root.db.in root.db
|
||||
|
||||
"$SIGNER" -Sgz -f root.db -o . root.db.in > /dev/null 2>&1
|
||||
|
||||
keyfile_to_key_id "$ksk" > keyid
|
||||
grep -Ev '^;' < "$ksk.key" | cut -f 7- -d ' ' > keydata
|
||||
keyfile_to_initial_keys "$ksk" > anchor.dnskey
|
||||
|
|
@ -20,4 +20,4 @@ copy_setports ns1/named.conf.in ns1/named.conf
|
|||
copy_setports ns2/named.conf.in ns2/named.conf
|
||||
copy_setports ns3/named.conf.in ns3/named.conf
|
||||
|
||||
cd ns2 && $SHELL sign.sh
|
||||
cd ns1 && $SHELL sign.sh
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ check_ttl_range() {
|
|||
return $result
|
||||
}
|
||||
|
||||
# using delv insecure mode as not testing dnssec here
|
||||
# use delv insecure mode by default, as we're mostly not testing dnssec
|
||||
delv_with_opts() {
|
||||
"$DELV" +noroot -p "$PORT" "$@"
|
||||
}
|
||||
|
|
@ -1404,6 +1404,42 @@ if [ -x "$DELV" ] ; then
|
|||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "checking delv +ns (no validation) ($n)"
|
||||
ret=0
|
||||
delv_with_opts -i +ns +hint=../common/root.hint a a.example > delv.out.test$n || ret=1
|
||||
grep -q '; authoritative' delv.out.test$n || ret=1
|
||||
grep -q '_.example' delv.out.test$n && ret=1
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "checking delv +ns +qmin (no validation) ($n)"
|
||||
ret=0
|
||||
delv_with_opts -i +ns +qmin +hint=../common/root.hint a a.example > delv.out.test$n || ret=1
|
||||
grep -q '; authoritative' delv.out.test$n || ret=1
|
||||
grep -q '_.example' delv.out.test$n || ret=1
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "checking delv +ns (with validation) ($n)"
|
||||
ret=0
|
||||
delv_with_opts -a ns1/anchor.dnskey +root +ns +hint=../common/root.hint a a.example > delv.out.test$n || ret=1
|
||||
grep -q '; fully validated' delv.out.test$n || ret=1
|
||||
grep -q '_.example' delv.out.test$n && ret=1
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "checking delv +ns +qmin (with validation) ($n)"
|
||||
ret=0
|
||||
delv_with_opts -a ns1/anchor.dnskey +root +ns +qmin +hint=../common/root.hint a a.example > delv.out.test$n || ret=1
|
||||
grep -q '; fully validated' delv.out.test$n || ret=1
|
||||
grep -q '_.example' delv.out.test$n || ret=1
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
else
|
||||
echo_i "$DELV is needed, so skipping these delv tests"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -23,6 +23,17 @@ New Features
|
|||
- BIND now depends on ``liburcu``, Userspace RCU, for lock-free data
|
||||
structures. :gl:`#3934`
|
||||
|
||||
- The new ``delv +ns`` option activates name server mode, in which ``delv``
|
||||
sets up an internal recursive resolver and uses that, rather than an
|
||||
external server, to look up the requested query name and type. All messages
|
||||
sent and received during the resolution and validation process are logged.
|
||||
This can be used in place of ``dig +trace``: it more accurately
|
||||
reproduces the behavior of ``named`` when resolving a query.
|
||||
|
||||
The log message ``resolver priming query complete`` was moved from the
|
||||
INFO log level to the DEBUG(1) log level, to prevent ``delv`` from
|
||||
emitting that message when setting up its internal resolver. :gl:`#3842`
|
||||
|
||||
Removed Features
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -1074,45 +1074,8 @@ isc_result_t
|
|||
dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
|
||||
dns_rdatatype_t rdtype, const dns_name_t *keyname,
|
||||
isc_buffer_t *databuf) {
|
||||
isc_result_t result;
|
||||
dns_keytable_t *secroots = NULL;
|
||||
dns_name_t *name = NULL;
|
||||
char rdatabuf[DST_KEY_MAXSIZE];
|
||||
unsigned char digest[ISC_MAX_MD_SIZE];
|
||||
dns_rdata_ds_t ds;
|
||||
dns_rdata_t rdata;
|
||||
isc_buffer_t b;
|
||||
|
||||
REQUIRE(DNS_CLIENT_VALID(client));
|
||||
REQUIRE(rdclass == dns_rdataclass_in);
|
||||
|
||||
CHECK(dns_view_getsecroots(client->view, &secroots));
|
||||
|
||||
DE_CONST(keyname, name);
|
||||
|
||||
if (rdtype != dns_rdatatype_dnskey && rdtype != dns_rdatatype_ds) {
|
||||
result = ISC_R_NOTIMPLEMENTED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
|
||||
dns_rdata_init(&rdata);
|
||||
isc_buffer_setactive(databuf, isc_buffer_usedlength(databuf));
|
||||
CHECK(dns_rdata_fromwire(&rdata, rdclass, rdtype, databuf,
|
||||
DNS_DECOMPRESS_NEVER, &b));
|
||||
|
||||
if (rdtype == dns_rdatatype_ds) {
|
||||
CHECK(dns_rdata_tostruct(&rdata, &ds, NULL));
|
||||
} else {
|
||||
CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
|
||||
digest, &ds));
|
||||
}
|
||||
|
||||
CHECK(dns_keytable_add(secroots, false, false, name, &ds, NULL, NULL));
|
||||
|
||||
cleanup:
|
||||
if (secroots != NULL) {
|
||||
dns_keytable_detach(&secroots);
|
||||
}
|
||||
return (result);
|
||||
return (dns_view_addtrustedkey(client->view, rdtype, keyname, databuf));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -279,10 +279,11 @@ dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
|
|||
dns_rdatatype_t rdtype, const dns_name_t *keyname,
|
||||
isc_buffer_t *keydatabuf);
|
||||
/*%<
|
||||
* Add a DNSSEC trusted key for the 'rdclass' class. A view for the 'rdclass'
|
||||
* class must be created beforehand. 'rdtype' is the type of the RR data
|
||||
* for the key, either DNSKEY or DS. 'keyname' is the DNS name of the key,
|
||||
* and 'keydatabuf' stores the RR data.
|
||||
* Add a DNSSEC trusted key for the 'rdclass' class (only class 'IN' is
|
||||
* currently supported). A view for the 'rdclass' class must be created
|
||||
* beforehand. 'rdtype' is the type of the RR data for the key, either
|
||||
* DNSKEY or DS. 'keyname' is the DNS name of the key, and 'keydatabuf'
|
||||
* stores the RR data.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1262,4 +1262,29 @@ dns_view_getdispatchmgr(dns_view_t *view);
|
|||
* by the resolver and request managers to send and receive DNS
|
||||
* messages.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_view_addtrustedkey(dns_view_t *view, dns_rdatatype_t rdtype,
|
||||
const dns_name_t *keyname, isc_buffer_t *databuf);
|
||||
/*%<
|
||||
* Add a DNSSEC trusted key to a view of class 'IN'. 'rdtype' is the type
|
||||
* of the RR data for the key, either DNSKEY or DS. 'keyname' is the DNS
|
||||
* name of the key, and 'databuf' stores the RR data.
|
||||
|
||||
* Requires:
|
||||
*
|
||||
*\li 'view' is a valid view.
|
||||
|
||||
*\li 'view' is class 'IN'.
|
||||
*
|
||||
*\li 'keyname' is a valid name.
|
||||
*
|
||||
*\li 'keydatabuf' is a valid buffer.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
*\li #ISC_R_SUCCESS On success.
|
||||
*
|
||||
*\li Anything else Failure.
|
||||
*/
|
||||
ISC_LANG_ENDDECLS
|
||||
|
|
|
|||
|
|
@ -921,7 +921,7 @@ req_connected(isc_result_t eresult, isc_region_t *region, void *arg) {
|
|||
req_send(request);
|
||||
} else {
|
||||
request_cancel(request);
|
||||
req_sendevent(request, ISC_R_CANCELED);
|
||||
req_sendevent(request, eresult);
|
||||
}
|
||||
UNLOCK(&request->requestmgr->locks[request->hash]);
|
||||
|
||||
|
|
|
|||
|
|
@ -9974,7 +9974,7 @@ prime_done(void *arg) {
|
|||
REQUIRE(VALID_RESOLVER(res));
|
||||
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
|
||||
DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(1),
|
||||
"resolver priming query complete: %s",
|
||||
isc_result_totext(resp->result));
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <isc/file.h>
|
||||
#include <isc/hash.h>
|
||||
#include <isc/lex.h>
|
||||
#include <isc/md.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/stats.h>
|
||||
#include <isc/string.h>
|
||||
|
|
@ -2323,3 +2324,44 @@ dns_view_getdispatchmgr(dns_view_t *view) {
|
|||
REQUIRE(DNS_VIEW_VALID(view));
|
||||
return (view->dispatchmgr);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_view_addtrustedkey(dns_view_t *view, dns_rdatatype_t rdtype,
|
||||
const dns_name_t *keyname, isc_buffer_t *databuf) {
|
||||
isc_result_t result;
|
||||
dns_name_t *name = NULL;
|
||||
char rdatabuf[DST_KEY_MAXSIZE];
|
||||
unsigned char digest[ISC_MAX_MD_SIZE];
|
||||
dns_rdata_ds_t ds;
|
||||
dns_rdata_t rdata;
|
||||
isc_buffer_t b;
|
||||
|
||||
REQUIRE(DNS_VIEW_VALID(view));
|
||||
REQUIRE(view->rdclass == dns_rdataclass_in);
|
||||
|
||||
DE_CONST(keyname, name);
|
||||
|
||||
if (rdtype != dns_rdatatype_dnskey && rdtype != dns_rdatatype_ds) {
|
||||
result = ISC_R_NOTIMPLEMENTED;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
|
||||
dns_rdata_init(&rdata);
|
||||
isc_buffer_setactive(databuf, isc_buffer_usedlength(databuf));
|
||||
CHECK(dns_rdata_fromwire(&rdata, view->rdclass, rdtype, databuf,
|
||||
DNS_DECOMPRESS_NEVER, &b));
|
||||
|
||||
if (rdtype == dns_rdatatype_ds) {
|
||||
CHECK(dns_rdata_tostruct(&rdata, &ds, NULL));
|
||||
} else {
|
||||
CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
|
||||
digest, &ds));
|
||||
}
|
||||
|
||||
CHECK(dns_keytable_add(view->secroots_priv, false, false, name, &ds,
|
||||
NULL, NULL));
|
||||
|
||||
cleanup:
|
||||
return (result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -729,3 +729,9 @@ isc_nmhandle_set_tcp_nodelay(isc_nmhandle_t *handle, const bool value);
|
|||
*
|
||||
* \li 'handle' is a valid netmgr handle object.
|
||||
*/
|
||||
|
||||
isc_sockaddr_t
|
||||
isc_nmsocket_getaddr(isc_nmsocket_t *sock);
|
||||
/*%<
|
||||
* Return the local address of 'sock'.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -479,7 +479,6 @@ struct isc_nmsocket {
|
|||
isc_nmsocket_type type;
|
||||
isc__networker_t *worker;
|
||||
|
||||
isc_mutex_t lock;
|
||||
isc_barrier_t listen_barrier;
|
||||
isc_barrier_t stop_barrier;
|
||||
|
||||
|
|
|
|||
|
|
@ -2538,6 +2538,12 @@ isc_nmhandle_set_tcp_nodelay(isc_nmhandle_t *handle, const bool value) {
|
|||
return (result);
|
||||
}
|
||||
|
||||
isc_sockaddr_t
|
||||
isc_nmsocket_getaddr(isc_nmsocket_t *sock) {
|
||||
REQUIRE(VALID_NMSOCK(sock));
|
||||
return (sock->iface);
|
||||
}
|
||||
|
||||
#if ISC_NETMGR_TRACE
|
||||
/*
|
||||
* Dump all active sockets in netmgr. We output to stderr
|
||||
|
|
|
|||
|
|
@ -748,6 +748,11 @@ isc_nm_listenstreamdns(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface,
|
|||
return (result);
|
||||
}
|
||||
|
||||
/* copy the actual port we're listening on into sock->iface */
|
||||
if (isc_sockaddr_getport(iface) == 0) {
|
||||
listener->iface = listener->outer->iface;
|
||||
}
|
||||
|
||||
listener->result = result;
|
||||
atomic_store(&listener->active, true);
|
||||
atomic_store(&listener->listening, true);
|
||||
|
|
|
|||
|
|
@ -350,10 +350,10 @@ start_tcp_child_job(void *arg) {
|
|||
REQUIRE(sock->tid == isc_tid());
|
||||
|
||||
sa_family_t sa_family = sock->iface.type.sa.sa_family;
|
||||
int r;
|
||||
int flags = 0;
|
||||
int r, flags = 0;
|
||||
isc_result_t result = ISC_R_UNSET;
|
||||
isc_loop_t *loop = sock->worker->loop;
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
(void)isc__nm_socket_min_mtu(sock->fd, sa_family);
|
||||
(void)isc__nm_socket_tcp_maxseg(sock->fd, NM_MAXSEG);
|
||||
|
|
@ -418,8 +418,25 @@ start_tcp_child_job(void *arg) {
|
|||
|
||||
atomic_store(&sock->listening, true);
|
||||
|
||||
if (sock->tid == 0) {
|
||||
r = uv_tcp_getsockname(&sock->uv_handle.tcp,
|
||||
(struct sockaddr *)&ss,
|
||||
&(int){ sizeof(ss) });
|
||||
if (r != 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = isc_sockaddr_fromsockaddr(&sock->parent->iface,
|
||||
(struct sockaddr *)&ss);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto done_result;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
result = isc_uverr2result(r);
|
||||
|
||||
done_result:
|
||||
atomic_fetch_add(&sock->parent->rchildren, 1);
|
||||
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
|
|||
|
|
@ -937,6 +937,11 @@ isc_nm_listentls(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface,
|
|||
return (result);
|
||||
}
|
||||
|
||||
/* copy the actual port we're listening on into sock->iface */
|
||||
if (isc_sockaddr_getport(iface) == 0) {
|
||||
tlssock->iface = tlssock->outer->iface;
|
||||
}
|
||||
|
||||
/* wait for listen result */
|
||||
isc__nmsocket_attach(tlssock->outer, &tsock);
|
||||
tlssock->result = result;
|
||||
|
|
|
|||
|
|
@ -491,9 +491,9 @@ isc_sockaddr_fromsockaddr(isc_sockaddr_t *isa, const struct sockaddr *sa) {
|
|||
return (ISC_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
memset(isa, 0, sizeof(isc_sockaddr_t));
|
||||
*isa = (isc_sockaddr_t){ .length = length,
|
||||
.link = ISC_LINK_INITIALIZER };
|
||||
memmove(isa, sa, length);
|
||||
isa->length = length;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1680,8 +1680,8 @@ ns__client_put_cb(void *client0) {
|
|||
* or tcpmsg (TCP case).
|
||||
*/
|
||||
void
|
||||
ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
isc_region_t *region, void *arg) {
|
||||
ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
isc_region_t *region, void *arg) {
|
||||
ns_client_t *client = NULL;
|
||||
isc_result_t result;
|
||||
isc_result_t sigresult = ISC_R_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -445,8 +445,8 @@ ns_client_addopt(ns_client_t *client, dns_message_t *message,
|
|||
*/
|
||||
|
||||
void
|
||||
ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
isc_region_t *region, void *arg);
|
||||
ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
isc_region_t *region, void *arg);
|
||||
|
||||
/*%<
|
||||
* Handle client requests.
|
||||
|
|
|
|||
|
|
@ -193,3 +193,11 @@ ns_interfacemgr_dynamic_updates_are_reliable(void);
|
|||
* disabled. That is the case on the platforms where kernel-based
|
||||
* mechanisms for tracking networking interface states is reliable enough.
|
||||
*/
|
||||
|
||||
void
|
||||
ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
const char *name, ns_interface_t **ifpret);
|
||||
/*%<
|
||||
* Create an interface 'name' associated with address 'addr'. If
|
||||
* 'name' is NULL then it is set to "default".
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -443,16 +443,20 @@ ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name,
|
||||
ns_interface_t **ifpret) {
|
||||
void
|
||||
ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
|
||||
const char *name, ns_interface_t **ifpret) {
|
||||
ns_interface_t *ifp = NULL;
|
||||
const char *default_name = "default";
|
||||
|
||||
REQUIRE(NS_INTERFACEMGR_VALID(mgr));
|
||||
|
||||
ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
|
||||
*ifp = (ns_interface_t){ .generation = mgr->generation, .addr = *addr };
|
||||
|
||||
if (name == NULL) {
|
||||
name = default_name;
|
||||
}
|
||||
strlcpy(ifp->name, name, sizeof(ifp->name));
|
||||
|
||||
isc_mutex_init(&ifp->lock);
|
||||
|
|
@ -478,7 +482,7 @@ ns_interface_listenudp(ns_interface_t *ifp) {
|
|||
|
||||
/* Reserve space for an ns_client_t with the netmgr handle */
|
||||
result = isc_nm_listenudp(ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr,
|
||||
ns__client_request, ifp,
|
||||
ns_client_request, ifp,
|
||||
&ifp->udplistensocket);
|
||||
return (result);
|
||||
}
|
||||
|
|
@ -488,7 +492,7 @@ ns_interface_listentcp(ns_interface_t *ifp) {
|
|||
isc_result_t result;
|
||||
|
||||
result = isc_nm_listenstreamdns(
|
||||
ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr, ns__client_request,
|
||||
ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr, ns_client_request,
|
||||
ifp, ns__client_tcpconn, ifp, ifp->mgr->backlog,
|
||||
&ifp->mgr->sctx->tcpquota, NULL, &ifp->tcplistensocket);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -521,7 +525,7 @@ ns_interface_listentls(ns_interface_t *ifp, isc_tlsctx_t *sslctx) {
|
|||
isc_result_t result;
|
||||
|
||||
result = isc_nm_listenstreamdns(
|
||||
ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr, ns__client_request,
|
||||
ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr, ns_client_request,
|
||||
ifp, ns__client_tcpconn, ifp, ifp->mgr->backlog,
|
||||
&ifp->mgr->sctx->tcpquota, sslctx, &ifp->tcplistensocket);
|
||||
|
||||
|
|
@ -555,7 +559,7 @@ load_http_endpoints(isc_nm_http_endpoints_t *epset, ns_interface_t *ifp,
|
|||
|
||||
for (size_t i = 0; i < neps; i++) {
|
||||
result = isc_nm_http_endpoints_add(epset, eps[i],
|
||||
ns__client_request, ifp);
|
||||
ns_client_request, ifp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -651,7 +655,7 @@ interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name,
|
|||
ifp = *ifpret;
|
||||
|
||||
if (ifp == NULL) {
|
||||
interface_create(mgr, addr, name, &ifp);
|
||||
ns_interface_create(mgr, addr, name, &ifp);
|
||||
} else {
|
||||
REQUIRE(!LISTENING(ifp));
|
||||
}
|
||||
|
|
@ -1193,8 +1197,8 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) {
|
|||
mgr->aclenv, &match, NULL);
|
||||
if (match <= 0) {
|
||||
ns_interface_t *new = NULL;
|
||||
interface_create(mgr, &listen_sockaddr,
|
||||
interface.name, &new);
|
||||
ns_interface_create(mgr, &listen_sockaddr,
|
||||
interface.name, &new);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -456,7 +456,7 @@ ns_test_qctx_create(const ns_test_qctx_create_params_t *params,
|
|||
|
||||
/*
|
||||
* Allow recursion for the client. As NS_CLIENTATTR_RA normally gets
|
||||
* set in ns__client_request(), i.e. earlier than the unit tests hook
|
||||
* set in ns_client_request(), i.e. earlier than the unit tests hook
|
||||
* into the call chain, just set it manually.
|
||||
*/
|
||||
client->attributes |= NS_CLIENTATTR_RA;
|
||||
|
|
|
|||
|
|
@ -247,19 +247,15 @@ typedef struct {
|
|||
dns_rdatatype_t qtype; /* QTYPE */
|
||||
unsigned int qflags; /* query flags */
|
||||
bool disable_name_checks; /* if set to true, owner
|
||||
* name
|
||||
* checks will
|
||||
* name checks will
|
||||
* be disabled for the
|
||||
* view created
|
||||
* */
|
||||
* view created
|
||||
*/
|
||||
bool recursive_service; /* if set to true, the view
|
||||
* created will
|
||||
* have a cache
|
||||
* database
|
||||
* attached */
|
||||
* created will have a cache
|
||||
* database attached */
|
||||
const char *auth_zone_origin; /* origin name of the zone
|
||||
* the
|
||||
* created view will be
|
||||
* the created view will be
|
||||
* authoritative for */
|
||||
const char *auth_zone_path; /* path to load the
|
||||
* authoritative
|
||||
|
|
|
|||
Loading…
Reference in a new issue