]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
emit more helpful log for exceeding max-records-per-type
authorJINMEI Tatuya <jtatuya@infoblox.com>
Thu, 29 Aug 2024 07:24:48 +0000 (16:24 +0900)
committerMark Andrews <marka@isc.org>
Wed, 27 Nov 2024 01:34:11 +0000 (12:34 +1100)
The new log message is emitted when adding or updating an RRset
fails due to exceeding the max-records-per-type limit. The log includes
the owner name and type, corresponding zone name, and the limit value.
It will be emitted on loading a zone file, inbound zone transfer
(both AXFR and IXFR), handling a DDNS update, or updating a cache DB.
It's especially helpful in the case of zone transfer, since the
secondary side doesn't have direct access to the offending zone data.

It could also be used for max-types-per-name, but this change
doesn't implement it yet as it's much less likely to happen
in practice.

(cherry picked from commit 4156995431290ed6ac1a96424fc3527a453ffb7c)

lib/dns/db.c
lib/dns/include/dns/db.h
lib/dns/rbtdb.c

index 72614fb8e60e9ffade95ae5d608f6034af7a0fb5..f004cf241a026c10c4569f549eeec4b23bef8395 100644 (file)
@@ -35,6 +35,7 @@
 #include <dns/log.h>
 #include <dns/master.h>
 #include <dns/rdata.h>
+#include <dns/rdataclass.h>
 #include <dns/rdataset.h>
 #include <dns/rdatasetiter.h>
 
@@ -1139,3 +1140,26 @@ dns_db_setmaxtypepername(dns_db_t *db, uint32_t value) {
                (db->methods->setmaxtypepername)(db, value);
        }
 }
+
+void
+dns__db_logtoomanyrecords(dns_db_t *db, const dns_name_t *name,
+                         dns_rdatatype_t type, const char *op,
+                         uint32_t limit) {
+       char namebuf[DNS_NAME_FORMATSIZE];
+       char originbuf[DNS_NAME_FORMATSIZE];
+       char typebuf[DNS_RDATATYPE_FORMATSIZE];
+       char clsbuf[DNS_RDATACLASS_FORMATSIZE];
+
+       dns_name_format(name, namebuf, sizeof(namebuf));
+       dns_name_format(&db->origin, originbuf, sizeof(originbuf));
+       dns_rdatatype_format(type, typebuf, sizeof(typebuf));
+       dns_rdataclass_format(db->rdclass, clsbuf, sizeof(clsbuf));
+
+       isc_log_write(
+               dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_RBTDB,
+               ISC_LOG_ERROR,
+               "error %s '%s/%s' in '%s/%s' (%s): %s (must not exceed %u)", op,
+               namebuf, typebuf, originbuf, clsbuf,
+               (db->attributes & DNS_DBATTR_CACHE) != 0 ? "cache" : "zone",
+               isc_result_totext(DNS_R_TOOMANYRECORDS), limit);
+}
index 07ff9a43d5c20ce688ce46468bb1ce03e3ed5660..5eb2cea58fd2dfe4f49d8efa9d5c615cea01607e 100644 (file)
@@ -1778,4 +1778,13 @@ dns_db_setmaxtypepername(dns_db_t *db, uint32_t value);
  * RR type that would exceed the number of already stored RR types will return
  * ISC_R_NOSPACE.
  */
+
+void
+dns__db_logtoomanyrecords(dns_db_t *db, const dns_name_t *name,
+                         dns_rdatatype_t type, const char *op, uint32_t limit);
+/*
+ * Emit a log message when adding an rdataset of name/type would exceed the
+ * 'maxrrperset' limit. 'op' is 'adding' or 'updating' depending on whether
+ * the addition is to create a new rdataset or to merge to an existing one.
+ */
 ISC_LANG_ENDDECLS
index 0058235d559bb43c88d2a3256200a58e25f066f9..65c66dec6faefd3409d15c4d331172f53431ea23 100644 (file)
@@ -6557,6 +6557,12 @@ find_header:
                                                header->resign_lsb;
                                }
                        } else {
+                               if (result == DNS_R_TOOMANYRECORDS) {
+                                       dns__db_logtoomanyrecords(
+                                               (dns_db_t *)rbtdb, nodename,
+                                               (dns_rdatatype_t)(header->type),
+                                               "updating", rbtdb->maxrrperset);
+                               }
                                free_rdataset(rbtdb, rbtdb->common.mctx,
                                              newheader);
                                return result;
@@ -7057,6 +7063,13 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
                                            &region, sizeof(rdatasetheader_t),
                                            rbtdb->maxrrperset);
        if (result != ISC_R_SUCCESS) {
+               if (result == DNS_R_TOOMANYRECORDS) {
+                       name = dns_fixedname_initname(&fixed);
+                       dns_db_nodefullname(db, node, name);
+                       dns__db_logtoomanyrecords((dns_db_t *)rbtdb, name,
+                                                 rdataset->type, "adding",
+                                                 rbtdb->maxrrperset);
+               }
                return result;
        }
 
@@ -7654,6 +7667,11 @@ loading_addrdataset(void *arg, const dns_name_t *name,
                                            &region, sizeof(rdatasetheader_t),
                                            rbtdb->maxrrperset);
        if (result != ISC_R_SUCCESS) {
+               if (result == DNS_R_TOOMANYRECORDS) {
+                       dns__db_logtoomanyrecords((dns_db_t *)rbtdb, name,
+                                                 rdataset->type, "adding",
+                                                 rbtdb->maxrrperset);
+               }
                return result;
        }
        newheader = (rdatasetheader_t *)region.base;