]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Limit the additional processing for large RDATA sets
authorOndřej Surý <ondrej@isc.org>
Thu, 14 Nov 2024 09:37:29 +0000 (10:37 +0100)
committerNicki Křížek <nicki@isc.org>
Mon, 20 Jan 2025 16:05:38 +0000 (17:05 +0100)
When answering queries, don't add data to the additional section if
the answer has more than 13 names in the RDATA.  This limits the
number of lookups into the database(s) during a single client query,
reducing query processing load.

Also, don't append any additional data to type=ANY queries. The
answer to ANY is already big enough.

(cherry picked from commit a1982cf1bb95c818aa7b58988b5611dec80f2408)

bin/tests/system/additional/tests.sh
lib/dns/include/dns/rdataset.h
lib/dns/rbtdb.c
lib/dns/rdataset.c
lib/dns/resolver.c
lib/ns/query.c

index 3701790678f40c6f789e22bc6018392a733fb688..bf7b082f9afbac607964322dc16c3da01326ee52 100644 (file)
@@ -278,7 +278,7 @@ n=$(expr $n + 1)
 echo_i "testing with 'minimal-any no;' ($n)"
 ret=0
 $DIG $DIGOPTS -t ANY www.rt.example @10.53.0.1 >dig.out.$n || ret=1
-grep "ANSWER: 3, AUTHORITY: 2, ADDITIONAL: 2" dig.out.$n >/dev/null || ret=1
+grep "ANSWER: 3, AUTHORITY: 2, ADDITIONAL: 1" dig.out.$n >/dev/null || ret=1
 if [ $ret -eq 1 ]; then
   echo_i "failed"
   status=$((status + 1))
index de3f638f895fc777d24f63e81b97676df4b178eb..b7f0f8f05515c059d75cda3f443586efe37d58a9 100644 (file)
@@ -55,6 +55,8 @@
 #include <dns/rdatastruct.h>
 #include <dns/types.h>
 
+#define DNS_RDATASET_MAXADDITIONAL 13
+
 ISC_LANG_BEGINDECLS
 
 typedef enum {
@@ -446,7 +448,8 @@ dns_rdataset_towirepartial(dns_rdataset_t   *rdataset,
 
 isc_result_t
 dns_rdataset_additionaldata(dns_rdataset_t         *rdataset,
-                           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.
@@ -465,10 +468,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 'limit' is non-zero and the number of the rdatasets is larger
+ *     than 'limit', no additional data will be processed.
+ *
  * 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.
  */
 
index 5179f942fb54457e96d1f0f805e3cfc7df5f8aea..24de5891371e53403eca3d881874e2efc00bb757 100644 (file)
@@ -10632,7 +10632,7 @@ no_glue:
        maybe_rehash_gluetable(rbtversion);
        idx = hash_32(hash, rbtversion->glue_table_bits);
 
-       (void)dns_rdataset_additionaldata(rdataset, glue_nsdname_cb, &ctx);
+       (void)dns_rdataset_additionaldata(rdataset, glue_nsdname_cb, &ctx, 0);
 
        cur = isc_mem_get(rbtdb->common.mctx, sizeof(*cur));
 
index 221d7f84a724c2a8aaf7a90c52a18a548bbc11e0..122b197612b7eb62ed555d2f1833e7e0111b3350 100644 (file)
@@ -29,6 +29,7 @@
 #include <dns/ncache.h>
 #include <dns/rdata.h>
 #include <dns/rdataset.h>
+#include <dns/result.h>
 
 static const char *trustnames[] = {
        "none",           "pending-additional",
@@ -578,7 +579,8 @@ dns_rdataset_towire(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
 
 isc_result_t
 dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
-                           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;
 
@@ -590,6 +592,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);
index fe2c464329a0fc86005b76afd33b58c298473710..737f83cdbf50e3a52967bd7869d7de24ce1eb6ba 100644 (file)
@@ -9025,8 +9025,8 @@ rctx_answer_any(respctx_t *rctx) {
                rdataset->attributes |= DNS_RDATASETATTR_CACHE;
                rdataset->trust = rctx->trust;
 
-               (void)dns_rdataset_additionaldata(rdataset, check_related,
-                                                 rctx);
+               (void)dns_rdataset_additionaldata(rdataset, check_related, rctx,
+                                                 0);
        }
 
        return (ISC_R_SUCCESS);
@@ -9073,7 +9073,8 @@ rctx_answer_match(respctx_t *rctx) {
        rctx->ardataset->attributes |= DNS_RDATASETATTR_ANSWER;
        rctx->ardataset->attributes |= DNS_RDATASETATTR_CACHE;
        rctx->ardataset->trust = rctx->trust;
-       (void)dns_rdataset_additionaldata(rctx->ardataset, check_related, rctx);
+       (void)dns_rdataset_additionaldata(rctx->ardataset, check_related, rctx,
+                                         0);
 
        for (sigrdataset = ISC_LIST_HEAD(rctx->aname->list);
             sigrdataset != NULL;
@@ -9279,7 +9280,8 @@ rctx_authority_positive(respctx_t *rctx) {
                                         * to this rdataset.
                                         */
                                        (void)dns_rdataset_additionaldata(
-                                               rdataset, check_related, rctx);
+                                               rdataset, check_related, rctx,
+                                               0);
                                        done = true;
                                }
                        }
@@ -9786,8 +9788,11 @@ rctx_referral(respctx_t *rctx) {
         */
        INSIST(rctx->ns_rdataset != NULL);
        FCTX_ATTR_SET(fctx, FCTX_ATTR_GLUING);
+       /*
+        * Mark the glue records in the additional section to be cached.
+        */
        (void)dns_rdataset_additionaldata(rctx->ns_rdataset, check_related,
-                                         rctx);
+                                         rctx, 0);
 #if CHECK_FOR_GLUE_IN_ANSWER
        /*
         * Look in the answer section for "glue" that is incorrectly
@@ -9800,7 +9805,7 @@ rctx_referral(respctx_t *rctx) {
            (fctx->type == dns_rdatatype_aaaa || fctx->type == dns_rdatatype_a))
        {
                (void)dns_rdataset_additionaldata(rctx->ns_rdataset,
-                                                 check_answer, fctx);
+                                                 check_answer, fctx, 0);
        }
 #endif /* if CHECK_FOR_GLUE_IN_ANSWER */
        FCTX_ATTR_CLR(fctx, FCTX_ATTR_GLUING);
@@ -9910,7 +9915,7 @@ again:
                        if (CHASE(rdataset)) {
                                rdataset->attributes &= ~DNS_RDATASETATTR_CHASE;
                                (void)dns_rdataset_additionaldata(
-                                       rdataset, check_related, rctx);
+                                       rdataset, check_related, rctx, 0);
                                rescan = true;
                        }
                }
index b729d11921564f36bd4532d9c25cbede7361baac..7d80bd9cc9adb17491b954cf774d0c928151e9f5 100644 (file)
@@ -2037,7 +2037,8 @@ addname:
 
        if (trdataset != NULL && dns_rdatatype_followadditional(type)) {
                eresult = dns_rdataset_additionaldata(
-                       trdataset, query_additional_cb, qctx);
+                       trdataset, query_additional_cb, qctx,
+                       DNS_RDATASET_MAXADDITIONAL);
        }
 
 cleanup:
@@ -2128,7 +2129,8 @@ regular:
         * Add other additional data if needed.
         * We don't care if dns_rdataset_additionaldata() fails.
         */
-       (void)dns_rdataset_additionaldata(rdataset, query_additional_cb, qctx);
+       (void)dns_rdataset_additionaldata(rdataset, query_additional_cb, qctx,
+                                         DNS_RDATASET_MAXADDITIONAL);
        CTRACE(ISC_LOG_DEBUG(3), "query_additional: done");
 }
 
@@ -2154,7 +2156,8 @@ query_addrrset(query_ctx_t *qctx, dns_name_t **namep,
         * To the current response for 'client', add the answer RRset
         * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
         * owner name '*namep', to section 'section', unless they are
-        * already there.  Also add any pertinent additional data.
+        * already there.  Also add any pertinent additional data, unless
+        * the query was for type ANY.
         *
         * If 'dbuf' is not NULL, then '*namep' is the name whose data is
         * stored in 'dbuf'.  In this case, query_addrrset() guarantees that
@@ -2209,7 +2212,9 @@ query_addrrset(query_ctx_t *qctx, dns_name_t **namep,
         */
        query_addtoname(mname, rdataset);
        query_setorder(qctx, mname, rdataset);
-       query_additional(qctx, rdataset);
+       if (qctx->qtype != dns_rdatatype_any) {
+               query_additional(qctx, rdataset);
+       }
 
        /*
         * Note: we only add SIGs if we've added the type they cover, so