]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
check size ratio when responding to IXFR requests
authorEvan Hunt <each@isc.org>
Sat, 22 Feb 2020 01:22:06 +0000 (17:22 -0800)
committerEvan Hunt <each@isc.org>
Fri, 6 Mar 2020 01:20:16 +0000 (17:20 -0800)
lib/ns/xfrout.c

index eb8b49103317f1b8bfbda8ea999fcb254bc59992..4178f9293ec7d4a59cf444f6613d2c9de6f15ae5 100644 (file)
@@ -227,10 +227,10 @@ static rrstream_methods_t ixfr_rrstream_methods;
 
 static isc_result_t
 ixfr_rrstream_create(isc_mem_t *mctx, const char *journal_filename,
-                    uint32_t begin_serial, uint32_t end_serial,
+                    uint32_t begin_serial, uint32_t end_serial, size_t *sizep,
                     rrstream_t **sp) {
-       ixfr_rrstream_t *s;
        isc_result_t result;
+       ixfr_rrstream_t *s = NULL;
 
        INSIST(sp != NULL && *sp == NULL);
 
@@ -243,7 +243,7 @@ ixfr_rrstream_create(isc_mem_t *mctx, const char *journal_filename,
        CHECK(dns_journal_open(mctx, journal_filename, DNS_JOURNAL_READ,
                               &s->journal));
        CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial,
-                                   NULL));
+                                   sizep));
 
        *sp = (rrstream_t *)s;
        return (ISC_R_SUCCESS);
@@ -963,6 +963,9 @@ got_soa:
 
        current_serial = dns_soa_getserial(&current_soa_tuple->rdata);
        if (reqtype == dns_rdatatype_ixfr) {
+               size_t jsize;
+               uint64_t dbsize;
+
                /*
                 * Outgoing IXFR may have been disabled for this peer
                 * or globally.
@@ -1008,7 +1011,7 @@ got_soa:
                if (journalfile != NULL) {
                        result = ixfr_rrstream_create(
                                mctx, journalfile, begin_serial, current_serial,
-                               &data_stream);
+                               &jsize, &data_stream);
                } else {
                        result = ISC_R_NOTFOUND;
                }
@@ -1021,6 +1024,32 @@ got_soa:
                        goto axfr_fallback;
                }
                CHECK(result);
+
+               result = dns_db_getsize(db, ver, NULL, &dbsize);
+               if (result == ISC_R_SUCCESS) {
+                       uint32_t ratio = dns_zone_getixfrratio(zone);
+                       if (ratio != 0 && ((100 * jsize) / dbsize) > ratio) {
+                               data_stream->methods->destroy(&data_stream);
+                               data_stream = NULL;
+                               xfrout_log1(client, question_name,
+                                           question_class, ISC_LOG_DEBUG(4),
+                                           "IXFR delta size (%zu bytes) "
+                                           "exceeds the maximum ratio to "
+                                           "database size "
+                                           "(%" PRIu64 " bytes), "
+                                           "falling back to AXFR",
+                                           jsize, dbsize);
+                               mnemonic = "AXFR-style IXFR";
+                               goto axfr_fallback;
+                       } else {
+                               xfrout_log1(client, question_name,
+                                           question_class, ISC_LOG_DEBUG(4),
+                                           "IXFR delta size (%zu bytes); "
+                                           "database size "
+                                           "(%" PRIu64 " bytes)",
+                                           jsize, dbsize);
+                       }
+               }
                is_ixfr = true;
        } else {
        axfr_fallback: