From 08122316a7aec70b6ddc739de717be0e8263789b Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Thu, 29 Aug 2024 16:24:48 +0900 Subject: [PATCH] emit more helpful log for exceeding max-records-per-type 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 | 24 ++++++++++++++++++++++++ lib/dns/db_p.h | 9 +++++++++ lib/dns/qpcache.c | 5 +++++ lib/dns/qpzone.c | 16 ++++++++++++++++ lib/dns/rbt-zonedb.c | 5 +++++ lib/dns/rbtdb.c | 13 +++++++++++++ 6 files changed, 72 insertions(+) diff --git a/lib/dns/db.c b/lib/dns/db.c index 370feac3cc..5dafc5b576 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -1190,3 +1191,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); +} diff --git a/lib/dns/db_p.h b/lib/dns/db_p.h index 0228536c35..3a982252a6 100644 --- a/lib/dns/db_p.h +++ b/lib/dns/db_p.h @@ -187,4 +187,13 @@ prio_type(dns_typepair_t type) { return false; } +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 diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index 1a4fb543be..7dd90fa276 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -3414,6 +3414,11 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, ®ion, sizeof(dns_slabheader_t), qpdb->maxrrperset); if (result != ISC_R_SUCCESS) { + if (result == DNS_R_TOOMANYRECORDS) { + dns__db_logtoomanyrecords((dns_db_t *)qpdb, + &qpnode->name, rdataset->type, + "adding", qpdb->maxrrperset); + } return result; } diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index 69bafead48..ae416b17ec 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -1875,6 +1875,12 @@ add(qpzonedb_t *qpdb, qpznode_t *node, const dns_name_t *nodename, header->resign_lsb; } } else { + if (result == DNS_R_TOOMANYRECORDS) { + dns__db_logtoomanyrecords( + (dns_db_t *)qpdb, nodename, + (dns_rdatatype_t)header->type, + "updating", qpdb->maxrrperset); + } dns_slabheader_destroy(&newheader); return result; } @@ -2109,6 +2115,11 @@ loading_addrdataset(void *arg, const dns_name_t *name, ®ion, sizeof(dns_slabheader_t), qpdb->maxrrperset); if (result != ISC_R_SUCCESS) { + if (result == DNS_R_TOOMANYRECORDS) { + dns__db_logtoomanyrecords((dns_db_t *)qpdb, name, + rdataset->type, "adding", + qpdb->maxrrperset); + } return result; } @@ -4607,6 +4618,11 @@ addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion, ®ion, sizeof(dns_slabheader_t), qpdb->maxrrperset); if (result != ISC_R_SUCCESS) { + if (result == DNS_R_TOOMANYRECORDS) { + dns__db_logtoomanyrecords((dns_db_t *)qpdb, &node->name, + rdataset->type, "adding", + qpdb->maxrrperset); + } return result; } diff --git a/lib/dns/rbt-zonedb.c b/lib/dns/rbt-zonedb.c index ecd5eb2bde..bed5c29527 100644 --- a/lib/dns/rbt-zonedb.c +++ b/lib/dns/rbt-zonedb.c @@ -1751,6 +1751,11 @@ loading_addrdataset(void *arg, const dns_name_t *name, ®ion, sizeof(dns_slabheader_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 = (dns_slabheader_t *)region.base; diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index a822b35d6c..ffd7801c06 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -2807,6 +2807,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); + } dns_slabheader_destroy(&newheader); return result; } @@ -3305,6 +3311,13 @@ dns__rbtdb_addrdataset(dns_db_t *db, dns_dbnode_t *node, ®ion, sizeof(dns_slabheader_t), rbtdb->maxrrperset); if (result != ISC_R_SUCCESS) { + if (result == DNS_R_TOOMANYRECORDS) { + name = dns_fixedname_initname(&fixed); + dns__rbtdb_nodefullname(db, node, name); + dns__db_logtoomanyrecords((dns_db_t *)rbtdb, name, + rdataset->type, "adding", + rbtdb->maxrrperset); + } return result; }