mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-05 00:55:24 +00:00
Split and simplify the use of EDE list implementation
Instead of mixing the dns_resolver and dns_validator units directly with the EDE code, split-out the dns_ede functionality into own separate compilation unit and hide the implementation details behind abstraction. Additionally, the EDE codes are directly copied into the ns_client buffers by passing the EDE context to dns_resolver_createfetch(). This makes the dns_ede implementation simpler to use, although sligtly more complicated on the inside. Co-authored-by: Colin Vidal <colin@isc.org> Co-authored-by: Ondřej Surý <ondrej@isc.org>
This commit is contained in:
100
lib/ns/client.c
100
lib/ns/client.c
@@ -218,92 +218,6 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
|
||||
/* XXXWPK TODO use netmgr to set timeout */
|
||||
}
|
||||
|
||||
static void
|
||||
client_extendederror_reset(ns_client_t *client) {
|
||||
for (size_t i = 0; i < DNS_EDE_MAX_ERRORS; i++) {
|
||||
if (client->ede[i]) {
|
||||
dns_ednsopt_t *ede = client->ede[i];
|
||||
|
||||
isc_mem_put(client->manager->mctx, ede->value,
|
||||
ede->length);
|
||||
isc_mem_put(client->manager->mctx, ede, sizeof(*ede));
|
||||
client->ede[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ns_client_extendederror(ns_client_t *client, uint16_t code, const char *text) {
|
||||
uint16_t becode;
|
||||
const uint16_t becodelen = sizeof(becode);
|
||||
uint16_t textlen = 0;
|
||||
size_t pos = 0;
|
||||
unsigned char *ede = NULL;
|
||||
dns_ednsopt_t *edns = NULL;
|
||||
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
|
||||
/*
|
||||
* As ede will be directly put in the DNS message we need to make sure
|
||||
* the code is in big-endian format
|
||||
*/
|
||||
becode = htobe16(code);
|
||||
|
||||
for (pos = 0; pos < DNS_EDE_MAX_ERRORS; pos++) {
|
||||
edns = client->ede[pos];
|
||||
|
||||
if (edns == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (memcmp(&becode, edns->value, becodelen) == 0) {
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
|
||||
"ignoring duplicate ede %u %s", code,
|
||||
text == NULL ? "(null)" : text);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos >= DNS_EDE_MAX_ERRORS) {
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
|
||||
"too many ede, ignoring %u %s", code,
|
||||
text == NULL ? "(null)" : text);
|
||||
return;
|
||||
}
|
||||
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
|
||||
ISC_LOG_DEBUG(1), "set ede: info-code %u extra-text %s",
|
||||
code, text == NULL ? "(null)" : text);
|
||||
|
||||
if (text != NULL && strlen(text) > 0) {
|
||||
textlen = strlen(text);
|
||||
|
||||
if (textlen > DNS_EDE_EXTRATEXT_LEN) {
|
||||
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
|
||||
"truncate EDE code %hu text: %s", code,
|
||||
text);
|
||||
textlen = DNS_EDE_EXTRATEXT_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
ede = isc_mem_get(client->manager->mctx, becodelen + textlen);
|
||||
|
||||
memcpy(ede, &becode, sizeof(code));
|
||||
if (textlen > 0) {
|
||||
memcpy(ede + becodelen, text, textlen);
|
||||
}
|
||||
|
||||
edns = isc_mem_get(client->manager->mctx, sizeof(*edns));
|
||||
*edns = (dns_ednsopt_t){ .code = DNS_OPT_EDE,
|
||||
.length = becodelen + textlen,
|
||||
.value = ede };
|
||||
|
||||
client->ede[pos] = edns;
|
||||
}
|
||||
|
||||
static void
|
||||
ns_client_endrequest(ns_client_t *client) {
|
||||
INSIST(client->state == NS_CLIENTSTATE_WORKING ||
|
||||
@@ -344,7 +258,6 @@ ns_client_endrequest(ns_client_t *client) {
|
||||
dns_message_puttemprdataset(client->message, &client->opt);
|
||||
}
|
||||
|
||||
client_extendederror_reset(client);
|
||||
client->signer = NULL;
|
||||
client->udpsize = 512;
|
||||
client->extflags = 0;
|
||||
@@ -1267,7 +1180,7 @@ no_nsid:
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < DNS_EDE_MAX_ERRORS; i++) {
|
||||
dns_ednsopt_t *ede = client->ede[i];
|
||||
dns_ednsopt_t *ede = client->edectx.ede[i];
|
||||
|
||||
if (ede == NULL) {
|
||||
break;
|
||||
@@ -1798,7 +1711,7 @@ ns__client_put_cb(void *client0) {
|
||||
* Call this first because it requires a valid client.
|
||||
*/
|
||||
ns_query_free(client);
|
||||
client_extendederror_reset(client);
|
||||
dns_ede_invalidate(&client->edectx);
|
||||
|
||||
client->magic = 0;
|
||||
|
||||
@@ -2263,7 +2176,7 @@ ns_client_request_continue(void *arg) {
|
||||
"no matching view in class");
|
||||
}
|
||||
|
||||
ns_client_extendederror(client, DNS_EDE_PROHIBITED, NULL);
|
||||
dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL);
|
||||
ns_client_error(client, DNS_R_REFUSED);
|
||||
|
||||
goto cleanup;
|
||||
@@ -2594,6 +2507,8 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
*/
|
||||
client->magic = NS_CLIENT_MAGIC;
|
||||
ns_query_init(client);
|
||||
|
||||
dns_ede_init(client->manager->mctx, &client->edectx);
|
||||
} else {
|
||||
REQUIRE(NS_CLIENT_VALID(client));
|
||||
REQUIRE(client->manager->tid == isc_tid());
|
||||
@@ -2606,8 +2521,11 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
|
||||
.magic = 0,
|
||||
.manager = client->manager,
|
||||
.message = client->message,
|
||||
.edectx = client->edectx,
|
||||
.query = client->query,
|
||||
};
|
||||
|
||||
dns_ede_reset(&client->edectx);
|
||||
}
|
||||
|
||||
client->query.attributes &= ~NS_QUERYATTR_ANSWERED;
|
||||
@@ -2783,7 +2701,7 @@ ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
|
||||
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
|
||||
"%s approved", opname);
|
||||
} else {
|
||||
ns_client_extendederror(client, DNS_EDE_PROHIBITED, NULL);
|
||||
dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL);
|
||||
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
|
||||
NS_LOGMODULE_CLIENT, log_level, "%s denied",
|
||||
opname);
|
||||
|
@@ -180,7 +180,7 @@ struct ns_client {
|
||||
size_t tcpbuf_size;
|
||||
dns_message_t *message;
|
||||
dns_rdataset_t *opt;
|
||||
dns_ednsopt_t *ede[DNS_EDE_MAX_ERRORS];
|
||||
dns_edectx_t edectx;
|
||||
uint16_t udpsize;
|
||||
uint16_t extflags;
|
||||
int16_t ednsversion; /* -1 noedns */
|
||||
@@ -304,12 +304,6 @@ ns_client_error(ns_client_t *client, isc_result_t result);
|
||||
* will have an RCODE determined by 'result'.
|
||||
*/
|
||||
|
||||
void
|
||||
ns_client_extendederror(ns_client_t *client, uint16_t code, const char *text);
|
||||
/*%<
|
||||
* Set extended error with INFO-CODE <code> and EXTRA-TEXT <text>.
|
||||
*/
|
||||
|
||||
void
|
||||
ns_client_drop(ns_client_t *client, isc_result_t result);
|
||||
/*%<
|
||||
|
@@ -42,6 +42,7 @@
|
||||
#include <dns/dlz.h>
|
||||
#include <dns/dns64.h>
|
||||
#include <dns/dnssec.h>
|
||||
#include <dns/ede.h>
|
||||
#include <dns/keytable.h>
|
||||
#include <dns/message.h>
|
||||
#include <dns/ncache.h>
|
||||
@@ -899,7 +900,7 @@ ns_query_init(ns_client_t *client) {
|
||||
ISC_LIST_INIT(client->query.namebufs);
|
||||
ISC_LIST_INIT(client->query.activeversions);
|
||||
ISC_LIST_INIT(client->query.freeversions);
|
||||
memset(client->ede, 0, sizeof(dns_ednsopt_t *) * DNS_EDE_MAX_ERRORS);
|
||||
|
||||
/*
|
||||
* This mutex is destroyed when the client is destroyed in
|
||||
* exit_check().
|
||||
@@ -982,8 +983,7 @@ query_checkcacheaccess(ns_client_t *client, const dns_name_t *name,
|
||||
* since it is cleared by query_reset(), before query
|
||||
* processing starts.
|
||||
*/
|
||||
ns_client_extendederror(client, DNS_EDE_PROHIBITED,
|
||||
NULL);
|
||||
dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL);
|
||||
|
||||
if (!options.nolog) {
|
||||
ns_client_aclmsg("query (cache)", name, qtype,
|
||||
@@ -1122,8 +1122,7 @@ query_validatezonedb(ns_client_t *client, const dns_name_t *name,
|
||||
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
|
||||
NS_LOGMODULE_QUERY, ISC_LOG_INFO,
|
||||
"%s denied", msg);
|
||||
ns_client_extendederror(client, DNS_EDE_PROHIBITED,
|
||||
NULL);
|
||||
dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1153,8 +1152,7 @@ query_validatezonedb(ns_client_t *client, const dns_name_t *name,
|
||||
result = ns_client_checkaclsilent(client, &client->destaddr,
|
||||
queryonacl, true);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_client_extendederror(client, DNS_EDE_PROHIBITED,
|
||||
NULL);
|
||||
dns_ede_add(&client->edectx, DNS_EDE_PROHIBITED, NULL);
|
||||
}
|
||||
if (!options.nolog && result != ISC_R_SUCCESS) {
|
||||
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
|
||||
@@ -2503,8 +2501,8 @@ validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
|
||||
isc_buffer_putstr(&buffer, " (cached)");
|
||||
isc_buffer_putuint8(&buffer, 0);
|
||||
|
||||
ns_client_extendederror(client, DNS_EDE_DNSKEYALG,
|
||||
isc_buffer_base(&buffer));
|
||||
dns_ede_add(&client->edectx, DNS_EDE_DNSKEYALG,
|
||||
isc_buffer_base(&buffer));
|
||||
continue;
|
||||
}
|
||||
if (!dns_name_issubdomain(name, &rrsig.signer)) {
|
||||
@@ -2813,7 +2811,7 @@ fetch_and_forget(ns_client_t *client, dns_name_t *qname, dns_rdatatype_t qtype,
|
||||
client->view->resolver, qname, qtype, NULL, NULL, NULL,
|
||||
peeraddr, client->message->id, options, 0, NULL,
|
||||
client->query.qc, client->manager->loop, cb, client,
|
||||
tmprdataset, NULL, fetchp);
|
||||
&client->edectx, tmprdataset, NULL, fetchp);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ns_client_putrdataset(client, &tmprdataset);
|
||||
isc_nmhandle_detach(handlep);
|
||||
@@ -5937,8 +5935,8 @@ query_lookup(query_ctx_t *qctx) {
|
||||
stale_found ? "used" : "unavailable",
|
||||
isc_result_totext(result));
|
||||
if (stale_found) {
|
||||
ns_client_extendederror(qctx->client, ede,
|
||||
"resolver failure");
|
||||
dns_ede_add(&qctx->client->edectx, ede,
|
||||
"resolver failure");
|
||||
} else if (!answer_found) {
|
||||
/*
|
||||
* Resolver failure, no stale data, nothing more we
|
||||
@@ -5961,9 +5959,8 @@ query_lookup(query_ctx_t *qctx) {
|
||||
isc_result_totext(result));
|
||||
|
||||
if (stale_found) {
|
||||
ns_client_extendederror(
|
||||
qctx->client, ede,
|
||||
"query within stale refresh time window");
|
||||
dns_ede_add(&qctx->client->edectx, ede,
|
||||
"query within stale refresh time window");
|
||||
} else if (!answer_found) {
|
||||
/*
|
||||
* During the stale refresh window explicitly do not try
|
||||
@@ -6007,8 +6004,8 @@ query_lookup(query_ctx_t *qctx) {
|
||||
namebuf, typebuf);
|
||||
qctx->refresh_rrset = STALE(qctx->rdataset);
|
||||
if (stale_found) {
|
||||
ns_client_extendederror(
|
||||
qctx->client, ede,
|
||||
dns_ede_add(
|
||||
&qctx->client->edectx, ede,
|
||||
"stale data prioritized over "
|
||||
"lookup");
|
||||
}
|
||||
@@ -6156,13 +6153,6 @@ fetch_callback(void *arg) {
|
||||
client->query.attributes &= ~NS_QUERYATTR_RECURSING;
|
||||
client->state = NS_CLIENTSTATE_WORKING;
|
||||
|
||||
for (dns_ede_t *ede = ISC_LIST_HEAD(resp->edelist); ede != NULL;
|
||||
ede = ISC_LIST_NEXT(ede, link))
|
||||
{
|
||||
ns_client_extendederror(client, ede->info_code,
|
||||
ede->extra_text);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a new qctx and use it to either resume from
|
||||
* recursion or clean up after cancelation. Transfer
|
||||
@@ -6380,7 +6370,7 @@ ns_query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
|
||||
client->view->resolver, qname, qtype, qdomain, nameservers,
|
||||
NULL, peeraddr, client->message->id, client->query.fetchoptions,
|
||||
0, NULL, client->query.qc, client->manager->loop,
|
||||
fetch_callback, client, rdataset, sigrdataset,
|
||||
fetch_callback, client, &client->edectx, rdataset, sigrdataset,
|
||||
&FETCH_RECTYPE_NORMAL(client));
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
release_recursionquota(client);
|
||||
@@ -7247,8 +7237,8 @@ query_checkrpz(query_ctx_t *qctx, isc_result_t result) {
|
||||
if (qctx->rpz_st->m.rpz->ede != 0 &&
|
||||
qctx->rpz_st->m.rpz->ede != UINT16_MAX)
|
||||
{
|
||||
ns_client_extendederror(qctx->client,
|
||||
qctx->rpz_st->m.rpz->ede, NULL);
|
||||
dns_ede_add(&qctx->client->edectx,
|
||||
qctx->rpz_st->m.rpz->ede, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -11448,8 +11438,8 @@ ns_query_done(query_ctx_t *qctx) {
|
||||
*/
|
||||
partial_result_with_servfail = true;
|
||||
|
||||
ns_client_extendederror(qctx->client, 0,
|
||||
"max. restarts reached");
|
||||
dns_ede_add(&qctx->client->edectx, 0,
|
||||
"max. restarts reached");
|
||||
ns_client_log(qctx->client, NS_LOGCATEGORY_CLIENT,
|
||||
NS_LOGMODULE_QUERY, ISC_LOG_INFO,
|
||||
"query iterations limit reached");
|
||||
|
Reference in New Issue
Block a user