From a1982cf1bb95c818aa7b58988b5611dec80f2408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Thu, 14 Nov 2024 10:37:29 +0100 Subject: [PATCH] Limit the additional processing for large RDATA sets Limit the number of records appended to ADDITIONAL section to the names that have less than 14 records in the RDATA. This limits the number of the lookups into the database(s) during single client query. Also don't append any additional data to ANY queries. The answer to ANY is already big enough. --- lib/dns/include/dns/rdataset.h | 10 +++++++++- lib/dns/qpzone.c | 2 +- lib/dns/rdataset.c | 7 ++++++- lib/dns/resolver.c | 17 ++++++++++------- lib/ns/query.c | 5 +++-- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h index ae835b961d..89518b0ebf 100644 --- a/lib/dns/include/dns/rdataset.h +++ b/lib/dns/include/dns/rdataset.h @@ -53,6 +53,8 @@ #include #include +#define DNS_RDATASET_MAXADDITIONAL 13 + /* Fixed RRSet helper macros */ #define DNS_RDATASET_LENGTH 2; @@ -503,7 +505,8 @@ dns_rdataset_towirepartial(dns_rdataset_t *rdataset, isc_result_t dns_rdataset_additionaldata(dns_rdataset_t *rdataset, const dns_name_t *owner_name, - dns_additionaldatafunc_t add, void *arg); + dns_additionaldatafunc_t add, void *arg, + size_t limit); /*%< * For each rdata in rdataset, call 'add' for each name and type in the * rdata which is subject to additional section processing. @@ -522,10 +525,15 @@ dns_rdataset_additionaldata(dns_rdataset_t *rdataset, *\li If a call to dns_rdata_additionaldata() is not successful, the * result returned will be the result of dns_rdataset_additionaldata(). * + *\li If the 'limit' is non-zero and the number of the rdatasets is larger + * than the 'limit', no additional data will be generated. + * * Returns: * *\li #ISC_R_SUCCESS * + *\li #DNS_R_TOOMANYRECORDS in case rdataset count is larger than 'limit' + * *\li Any error that dns_rdata_additionaldata() can return. */ diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index 7847d260f1..fadc3bc9c2 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -5261,7 +5261,7 @@ create_gluelist(qpzonedb_t *qpdb, qpz_version_t *version, qpznode_t *node, */ (void)dns_rdataset_additionaldata(rdataset, dns_rootname, - glue_nsdname_cb, &ctx); + glue_nsdname_cb, &ctx, 0); CMM_STORE_SHARED(gluelist->glue, ctx.glue); diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c index b09ff3cf29..dc6fc4d867 100644 --- a/lib/dns/rdataset.c +++ b/lib/dns/rdataset.c @@ -479,7 +479,8 @@ dns_rdataset_towire(dns_rdataset_t *rdataset, const dns_name_t *owner_name, isc_result_t dns_rdataset_additionaldata(dns_rdataset_t *rdataset, const dns_name_t *owner_name, - dns_additionaldatafunc_t add, void *arg) { + dns_additionaldatafunc_t add, void *arg, + size_t limit) { dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; @@ -491,6 +492,10 @@ dns_rdataset_additionaldata(dns_rdataset_t *rdataset, REQUIRE(DNS_RDATASET_VALID(rdataset)); REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0); + if (limit != 0 && dns_rdataset_count(rdataset) > limit) { + return DNS_R_TOOMANYRECORDS; + } + result = dns_rdataset_first(rdataset); if (result != ISC_R_SUCCESS) { return result; diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 70900c4cc0..6497582bea 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -8576,9 +8576,6 @@ rctx_answer_any(respctx_t *rctx) { rdataset->attributes |= DNS_RDATASETATTR_ANSWER; rdataset->attributes |= DNS_RDATASETATTR_CACHE; rdataset->trust = rctx->trust; - - (void)dns_rdataset_additionaldata(rdataset, rctx->aname, - check_related, rctx); } return ISC_R_SUCCESS; @@ -8626,7 +8623,8 @@ rctx_answer_match(respctx_t *rctx) { rctx->ardataset->attributes |= DNS_RDATASETATTR_CACHE; rctx->ardataset->trust = rctx->trust; (void)dns_rdataset_additionaldata(rctx->ardataset, rctx->aname, - check_related, rctx); + check_related, rctx, + DNS_RDATASET_MAXADDITIONAL); for (sigrdataset = ISC_LIST_HEAD(rctx->aname->list); sigrdataset != NULL; @@ -8833,7 +8831,8 @@ rctx_authority_positive(respctx_t *rctx) { */ (void)dns_rdataset_additionaldata( rdataset, name, check_related, - rctx); + rctx, + DNS_RDATASET_MAXADDITIONAL); done = true; } } @@ -9340,8 +9339,11 @@ rctx_referral(respctx_t *rctx) { */ INSIST(rctx->ns_rdataset != NULL); FCTX_ATTR_SET(fctx, FCTX_ATTR_GLUING); + /* + * We want to append **all** the GLUE records here. + */ (void)dns_rdataset_additionaldata(rctx->ns_rdataset, rctx->ns_name, - check_related, rctx); + check_related, rctx, 0); #if CHECK_FOR_GLUE_IN_ANSWER /* * Look in the answer section for "glue" that is incorrectly @@ -9456,7 +9458,8 @@ again: if (CHASE(rdataset)) { rdataset->attributes &= ~DNS_RDATASETATTR_CHASE; (void)dns_rdataset_additionaldata( - rdataset, name, check_related, rctx); + rdataset, name, check_related, rctx, + DNS_RDATASET_MAXADDITIONAL); rescan = true; } } diff --git a/lib/ns/query.c b/lib/ns/query.c index 8464e782d9..9757a25622 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -2143,7 +2143,8 @@ addname: if (trdataset != NULL && dns_rdatatype_followadditional(type)) { if (client->additionaldepth++ < client->view->max_restarts) { eresult = dns_rdataset_additionaldata( - trdataset, fname, query_additional_cb, qctx); + trdataset, fname, query_additional_cb, qctx, + DNS_RDATASET_MAXADDITIONAL); } client->additionaldepth--; } @@ -2240,7 +2241,7 @@ regular: * We don't care if dns_rdataset_additionaldata() fails. */ (void)dns_rdataset_additionaldata(rdataset, name, query_additional_cb, - qctx); + qctx, DNS_RDATASET_MAXADDITIONAL); CTRACE(ISC_LOG_DEBUG(3), "query_additional: done"); }