From 399f0c191a9bfb1d2a10ff7f51d3a42af5671d16 Mon Sep 17 00:00:00 2001 From: Alessio Podda Date: Sat, 25 Oct 2025 11:01:27 +0200 Subject: [PATCH 1/6] Clean up ixfr transaction API Make the API tighter. The idea of this commit is to highlight the distinction between a database transaction and a journal transaction, and ensure we run dns_zone_verifydb on error. Done to simplify a later refactor. --- lib/dns/xfrin.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index 60bee11806..f4ef175d40 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -80,6 +80,8 @@ typedef enum { * Incoming zone transfer context. */ +typedef struct dns_ixfr dns_ixfr_t; + struct dns_xfrin { unsigned int magic; isc_mem_t *mctx; @@ -172,7 +174,7 @@ struct dns_xfrin { */ dns_rdatacallbacks_t axfr; - struct { + struct dns_ixfr { uint32_t diffs; uint32_t maxdiffs; uint32_t request_serial; @@ -488,24 +490,22 @@ cleanup: } static isc_result_t -ixfr_begin_transaction(dns_xfrin_t *xfr) { +ixfr_begin_transaction(dns_ixfr_t *ixfr) { isc_result_t result = ISC_R_SUCCESS; - if (xfr->ixfr.journal != NULL) { - CHECK(dns_journal_begin_transaction(xfr->ixfr.journal)); + if (ixfr->journal != NULL) { + CHECK(dns_journal_begin_transaction(ixfr->journal)); } cleanup: return result; } static isc_result_t -ixfr_end_transaction(dns_xfrin_t *xfr) { +ixfr_end_transaction(dns_ixfr_t *ixfr) { isc_result_t result = ISC_R_SUCCESS; - - CHECK(dns_zone_verifydb(xfr->zone, xfr->db, xfr->ver)); /* XXX enter ready-to-commit state here */ - if (xfr->ixfr.journal != NULL) { - CHECK(dns_journal_commit(xfr->ixfr.journal)); + if (ixfr->journal != NULL) { + CHECK(dns_journal_commit(ixfr->journal)); } cleanup: return result; @@ -516,7 +516,7 @@ ixfr_apply_one(dns_xfrin_t *xfr, ixfr_apply_data_t *data) { isc_result_t result = ISC_R_SUCCESS; uint64_t records; - CHECK(ixfr_begin_transaction(xfr)); + CHECK(ixfr_begin_transaction(&xfr->ixfr)); CHECK(dns_diff_apply(&data->diff, xfr->db, xfr->ver)); if (xfr->maxrecords != 0U) { @@ -529,12 +529,14 @@ ixfr_apply_one(dns_xfrin_t *xfr, ixfr_apply_data_t *data) { CHECK(dns_journal_writediff(xfr->ixfr.journal, &data->diff)); } - result = ixfr_end_transaction(xfr); + CHECK(dns_zone_verifydb(xfr->zone, xfr->db, xfr->ver)); + + result = ixfr_end_transaction(&xfr->ixfr); return result; cleanup: /* We need to end the transaction, but keep the previous error */ - (void)ixfr_end_transaction(xfr); + (void)ixfr_end_transaction(&xfr->ixfr); return result; } From 6f726ae3db00e98f063302363b39fa41a5a7a8d3 Mon Sep 17 00:00:00 2001 From: Alessio Podda Date: Tue, 7 Oct 2025 06:00:17 +0200 Subject: [PATCH 2/6] Move setresign to rdataset.c and rename it The setresign method is not diff specific, it only returns the minimum resign time of an rdataset. Move it to rdataset.c to simplify late refactoring. --- lib/dns/diff.c | 37 +------------------------------- lib/dns/include/dns/rdataset.h | 13 ++++++++++++ lib/dns/rdataset.c | 39 ++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 36 deletions(-) diff --git a/lib/dns/diff.c b/lib/dns/diff.c index d873c4365b..a3364c433c 100644 --- a/lib/dns/diff.c +++ b/lib/dns/diff.c @@ -203,41 +203,6 @@ dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuplep) { } } -static isc_stdtime_t -setresign(dns_rdataset_t *modified) { - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdata_rrsig_t sig; - int64_t when; - isc_result_t result; - - result = dns_rdataset_first(modified); - INSIST(result == ISC_R_SUCCESS); - dns_rdataset_current(modified, &rdata); - (void)dns_rdata_tostruct(&rdata, &sig, NULL); - if ((rdata.flags & DNS_RDATA_OFFLINE) != 0) { - when = 0; - } else { - when = dns_time64_from32(sig.timeexpire); - } - dns_rdata_reset(&rdata); - - result = dns_rdataset_next(modified); - while (result == ISC_R_SUCCESS) { - dns_rdataset_current(modified, &rdata); - (void)dns_rdata_tostruct(&rdata, &sig, NULL); - if ((rdata.flags & DNS_RDATA_OFFLINE) != 0) { - goto next_rr; - } - if (when == 0 || dns_time64_from32(sig.timeexpire) < when) { - when = dns_time64_from32(sig.timeexpire); - } - next_rr: - dns_rdata_reset(&rdata); - result = dns_rdataset_next(modified); - } - INSIST(result == ISC_R_NOMORE); - return (isc_stdtime_t)when; -} static void getownercase(dns_rdataset_t *rdataset, dns_name_t *name) { @@ -407,7 +372,7 @@ diff_apply(const dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, op == DNS_DIFFOP_ADDRESIGN)) { isc_stdtime_t resign; - resign = setresign(&ardataset); + resign = dns_rdataset_minresign(&ardataset); dns_db_setsigningtime(db, &ardataset, resign); } diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h index a03897e764..e2917b8675 100644 --- a/lib/dns/include/dns/rdataset.h +++ b/lib/dns/include/dns/rdataset.h @@ -632,6 +632,19 @@ dns_rdataset_getheader(const dns_rdataset_t *rdataset); * \li 'rdataset' is a valid rdataset. */ +isc_stdtime_t +dns_rdataset_minresign(dns_rdataset_t *rdataset); +/*%< + * Return the minimum resign time from an RRSIG rdataset. + * + * This function iterates through all RRSIG records in the rdataset + * and returns the earliest expiration time, which indicates when + * the signatures should be resigned. + * + * Requires: + * \li 'rdataset' is a valid rdataset. + */ + /*% * Returns true if the rdataset is of type 'type', or type RRSIG * and covers 'type'. diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c index c418bed890..533b9b9556 100644 --- a/lib/dns/rdataset.c +++ b/lib/dns/rdataset.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #define MAX_SHUFFLE 100 @@ -597,3 +598,41 @@ dns_rdataset_getheader(const dns_rdataset_t *rdataset) { return NULL; } + +isc_stdtime_t +dns_rdataset_minresign(dns_rdataset_t *rdataset) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_rrsig_t sig; + int64_t when; + isc_result_t result; + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + + result = dns_rdataset_first(rdataset); + INSIST(result == ISC_R_SUCCESS); + dns_rdataset_current(rdataset, &rdata); + (void)dns_rdata_tostruct(&rdata, &sig, NULL); + if ((rdata.flags & DNS_RDATA_OFFLINE) != 0) { + when = 0; + } else { + when = dns_time64_from32(sig.timeexpire); + } + dns_rdata_reset(&rdata); + + result = dns_rdataset_next(rdataset); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(rdataset, &rdata); + (void)dns_rdata_tostruct(&rdata, &sig, NULL); + if ((rdata.flags & DNS_RDATA_OFFLINE) != 0) { + goto next_rr; + } + if (when == 0 || dns_time64_from32(sig.timeexpire) < when) { + when = dns_time64_from32(sig.timeexpire); + } + next_rr: + dns_rdata_reset(&rdata); + result = dns_rdataset_next(rdataset); + } + INSIST(result == ISC_R_NOMORE); + return (isc_stdtime_t)when; +} From e36dc0ca761898ff951d101281bbf39bf2535ec5 Mon Sep 17 00:00:00 2001 From: Alessio Podda Date: Sat, 25 Oct 2025 00:47:42 +0200 Subject: [PATCH 3/6] Abstract updates into a vtable This commit adds a layer of indirection to the apply_diff logic used by IXFR and resigning by having the database updates go through a vtable. We do this in three steps: - We extend dns_rdatacallbacks_t vtable to allow subtraction and resigning. - We add a new set of api (begin|commit|abort)update to the dbmethods vtable, that model an incremental update that can be aborted. - We extract the core logic of diff_apply into a function that satisfies the new interface. - We make diff_apply use this new function, and log the results. The intent of this commit is to allow databases to expose a batch incremental update implementation, just like they expose a custom batch creation implementation through (begin|end)load. --- lib/dns/db.c | 50 +++++++ lib/dns/diff.c | 250 ++++++++++++++++++-------------- lib/dns/include/dns/callbacks.h | 10 +- lib/dns/include/dns/db.h | 85 +++++++++++ lib/dns/include/dns/diff.h | 25 +++- lib/dns/include/dns/types.h | 12 +- lib/dns/master.c | 6 +- lib/dns/qpzone.c | 6 +- lib/dns/xfrin.c | 20 +++ 9 files changed, 337 insertions(+), 127 deletions(-) diff --git a/lib/dns/db.c b/lib/dns/db.c index 80f505d02b..85758bcf2f 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -300,6 +300,56 @@ dns_db_endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { return ISC_R_NOTIMPLEMENTED; } +isc_result_t +dns_db_beginupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { + /* + * Begin updating 'db'. + */ + + REQUIRE(DNS_DB_VALID(db)); + REQUIRE(dns_db_iszone(db)); + REQUIRE(DNS_CALLBACK_VALID(callbacks)); + + if (db->methods->beginupdate != NULL) { + return (db->methods->beginupdate)(db, callbacks); + } + return ISC_R_NOTIMPLEMENTED; +} + +isc_result_t +dns_db_commitupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { + /* + * Commit the update to 'db'. + */ + + REQUIRE(DNS_DB_VALID(db)); + REQUIRE(dns_db_iszone(db)); + REQUIRE(DNS_CALLBACK_VALID(callbacks)); + + if (db->methods->commitupdate != NULL) { + return (db->methods->commitupdate)(db, callbacks); + } + + return ISC_R_NOTIMPLEMENTED; +} + +isc_result_t +dns_db_abortupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { + /* + * Abort the update to 'db'. + */ + + REQUIRE(DNS_DB_VALID(db)); + REQUIRE(dns_db_iszone(db)); + REQUIRE(DNS_CALLBACK_VALID(callbacks)); + + if (db->methods->abortupdate != NULL) { + return (db->methods->abortupdate)(db, callbacks); + } + + return ISC_R_NOTIMPLEMENTED; +} + isc_result_t dns_db_load(dns_db_t *db, const char *filename, dns_masterformat_t format, unsigned int options) { diff --git a/lib/dns/diff.c b/lib/dns/diff.c index a3364c433c..f89d245a67 100644 --- a/lib/dns/diff.c +++ b/lib/dns/diff.c @@ -203,7 +203,6 @@ dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuplep) { } } - static void getownercase(dns_rdataset_t *rdataset, dns_name_t *name) { if (dns_rdataset_isassociated(rdataset)) { @@ -211,6 +210,80 @@ getownercase(dns_rdataset_t *rdataset, dns_name_t *name) { } } +static isc_result_t +update_rdataset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, + dns_rdataset_t *rds, dns_diffop_t op) { + isc_result_t result; + unsigned int options; + dns_rdataset_t ardataset; + dns_dbnode_t *node = NULL; + bool is_resign; + + dns_rdataset_init(&ardataset); + + is_resign = rds->type == dns_rdatatype_rrsig && + (op == DNS_DIFFOP_DELRESIGN || op == DNS_DIFFOP_ADDRESIGN); + + if (rds->type != dns_rdatatype_nsec3 && + rds->covers != dns_rdatatype_nsec3) + { + CHECK(dns_db_findnode(db, name, true, &node)); + } else { + CHECK(dns_db_findnsec3node(db, name, true, &node)); + } + + switch (op) { + case DNS_DIFFOP_ADD: + case DNS_DIFFOP_ADDRESIGN: + options = DNS_DBADD_MERGE | DNS_DBADD_EXACT | + DNS_DBADD_EXACTTTL; + CHECK(dns_db_addrdataset(db, node, ver, 0, rds, options, + &ardataset)); + break; + case DNS_DIFFOP_DEL: + case DNS_DIFFOP_DELRESIGN: + options = DNS_DBSUB_EXACT | DNS_DBSUB_WANTOLD; + result = dns_db_subtractrdataset(db, node, ver, rds, options, + &ardataset); + switch (result) { + case ISC_R_SUCCESS: + case DNS_R_UNCHANGED: + case DNS_R_NXRRSET: + getownercase(&ardataset, name); + CHECK(result); + break; + default: + CHECK(result); + break; + } + break; + default: + UNREACHABLE(); + } + + if (is_resign) { + isc_stdtime_t resign; + resign = dns_rdataset_minresign(&ardataset); + dns_db_setsigningtime(db, &ardataset, resign); + } + +cleanup: + if (node != NULL) { + dns_db_detachnode(&node); + } + if (dns_rdataset_isassociated(&ardataset)) { + dns_rdataset_disassociate(&ardataset); + } + return result; +} + +static isc_result_t +update_callback(void *arg, const dns_name_t *name, dns_rdataset_t *rds, + dns_diffop_t op DNS__DB_FLARG) { + dns_updatectx_t *ctx = arg; + return update_rdataset(ctx->db, ctx->ver, (dns_name_t *)name, rds, op); +} + static const char * optotext(dns_diffop_t op) { switch (op) { @@ -228,23 +301,24 @@ optotext(dns_diffop_t op) { } static isc_result_t -diff_apply(const dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, - bool warn) { +diff_apply(const dns_diff_t *diff, dns_rdatacallbacks_t *callbacks) { dns_difftuple_t *t; - dns_dbnode_t *node = NULL; isc_result_t result; char namebuf[DNS_NAME_FORMATSIZE]; char typebuf[DNS_RDATATYPE_FORMATSIZE]; char classbuf[DNS_RDATACLASS_FORMATSIZE]; + dns_updatectx_t *ctx; REQUIRE(DNS_DIFF_VALID(diff)); - REQUIRE(DNS_DB_VALID(db)); + REQUIRE(callbacks != NULL); + REQUIRE(callbacks->update != NULL); + + ctx = callbacks->add_private; t = ISC_LIST_HEAD(diff->tuples); while (t != NULL) { dns_name_t *name; - INSIST(node == NULL); name = &t->name; /* * Find the node. @@ -261,8 +335,6 @@ diff_apply(const dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, dns_diffop_t op; dns_rdatalist_t rdl; dns_rdataset_t rds; - dns_rdataset_t ardataset; - unsigned int options; op = t->op; type = t->rdata.type; @@ -290,16 +362,6 @@ diff_apply(const dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, rdl.rdclass = t->rdata.rdclass; rdl.ttl = t->ttl; - node = NULL; - if (type != dns_rdatatype_nsec3 && - covers != dns_rdatatype_nsec3) - { - CHECK(dns_db_findnode(db, name, true, &node)); - } else { - CHECK(dns_db_findnsec3node(db, name, true, - &node)); - } - while (t != NULL && dns_name_equal(&t->name, name) && t->op == op && t->rdata.type == type && rdata_covers(&t->rdata) == covers) @@ -309,7 +371,7 @@ diff_apply(const dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, * dns_rdataset_setownercase. */ name = &t->name; - if (t->ttl != rdl.ttl && warn) { + if (t->ttl != rdl.ttl && ctx->warn) { dns_name_format(name, namebuf, sizeof(namebuf)); dns_rdatatype_format(t->rdata.type, @@ -338,7 +400,6 @@ diff_apply(const dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, * Convert the rdatalist into a rdataset. */ dns_rdataset_init(&rds); - dns_rdataset_init(&ardataset); dns_rdatalist_tordataset(&rdl, &rds); dns_rdataset_setownercase(&rds, name); rds.trust = dns_trust_ultimate; @@ -346,42 +407,16 @@ diff_apply(const dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, /* * Merge the rdataset into the database. */ - switch (op) { - case DNS_DIFFOP_ADD: - case DNS_DIFFOP_ADDRESIGN: - options = DNS_DBADD_MERGE | DNS_DBADD_EXACT | - DNS_DBADD_EXACTTTL; - result = dns_db_addrdataset(db, node, ver, 0, - &rds, options, - &ardataset); - break; - case DNS_DIFFOP_DEL: - case DNS_DIFFOP_DELRESIGN: - options = DNS_DBSUB_EXACT | DNS_DBSUB_WANTOLD; - result = dns_db_subtractrdataset(db, node, ver, - &rds, options, - &ardataset); - break; - default: - UNREACHABLE(); - } + result = callbacks->update(callbacks->add_private, name, + &rds, op DNS__DB_FILELINE); - if (result == ISC_R_SUCCESS) { - if (rds.type == dns_rdatatype_rrsig && - (op == DNS_DIFFOP_DELRESIGN || - op == DNS_DIFFOP_ADDRESIGN)) - { - isc_stdtime_t resign; - resign = dns_rdataset_minresign(&ardataset); - dns_db_setsigningtime(db, &ardataset, - resign); - } - if (op == DNS_DIFFOP_DEL || - op == DNS_DIFFOP_DELRESIGN) - { - getownercase(&ardataset, name); - } - } else if (result == DNS_R_UNCHANGED) { + switch (result) { + case ISC_R_SUCCESS: + /* + * OK. + */ + break; + case DNS_R_UNCHANGED: /* * This will not happen when executing a * dynamic update, because that code will @@ -390,13 +425,13 @@ diff_apply(const dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, * from a server that is not as careful. * Issue a warning and continue. */ - if (warn) { - dns_name_format(dns_db_origin(db), + if (ctx->warn) { + dns_name_format(dns_db_origin(ctx->db), namebuf, sizeof(namebuf)); - dns_rdataclass_format(dns_db_class(db), - classbuf, - sizeof(classbuf)); + dns_rdataclass_format( + dns_db_class(ctx->db), classbuf, + sizeof(classbuf)); isc_log_write(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_DIFF, ISC_LOG_WARNING, @@ -404,70 +439,70 @@ diff_apply(const dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, "update with no effect", namebuf, classbuf); } - if (op == DNS_DIFFOP_DEL || - op == DNS_DIFFOP_DELRESIGN) - { - getownercase(&ardataset, name); - } - } else if (result == DNS_R_NXRRSET) { + result = ISC_R_SUCCESS; + break; + case DNS_R_NXRRSET: /* * OK. */ - if (op == DNS_DIFFOP_DEL || - op == DNS_DIFFOP_DELRESIGN) - { - getownercase(&ardataset, name); - } - if (dns_rdataset_isassociated(&ardataset)) { - dns_rdataset_disassociate(&ardataset); - } - } else { - if (result == DNS_R_NOTEXACT) { - dns_name_format(name, namebuf, - sizeof(namebuf)); - dns_rdatatype_format(type, typebuf, - sizeof(typebuf)); - dns_rdataclass_format(rdclass, classbuf, - sizeof(classbuf)); - isc_log_write( - DNS_LOGCATEGORY_GENERAL, - DNS_LOGMODULE_DIFF, - ISC_LOG_ERROR, - "dns_diff_apply: %s/%s/%s: %s " - "%s", - namebuf, typebuf, classbuf, - optotext(op), - isc_result_totext(result)); - } - if (dns_rdataset_isassociated(&ardataset)) { - dns_rdataset_disassociate(&ardataset); - } - CHECK(result); - } - dns_db_detachnode(&node); - if (dns_rdataset_isassociated(&ardataset)) { - dns_rdataset_disassociate(&ardataset); + result = ISC_R_SUCCESS; + break; + case DNS_R_NOTEXACT: + dns_name_format(name, namebuf, sizeof(namebuf)); + dns_rdatatype_format(type, typebuf, + sizeof(typebuf)); + dns_rdataclass_format(rdclass, classbuf, + sizeof(classbuf)); + isc_log_write(DNS_LOGCATEGORY_GENERAL, + DNS_LOGMODULE_DIFF, ISC_LOG_ERROR, + "dns_diff_apply: %s/%s/%s: %s " + "%s", + namebuf, typebuf, classbuf, + optotext(op), + isc_result_totext(result)); + break; + default: + break; } + + CHECK(result); } } return ISC_R_SUCCESS; cleanup: - if (node != NULL) { - dns_db_detachnode(&node); - } return result; } isc_result_t dns_diff_apply(const dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver) { - return diff_apply(diff, db, ver, true); + dns_updatectx_t ctx = { .db = db, .ver = ver, .warn = true }; + dns_rdatacallbacks_t callbacks; + dns_rdatacallbacks_init(&callbacks); + callbacks.update = update_callback; + callbacks.add_private = &ctx; + return diff_apply(diff, &callbacks); } isc_result_t dns_diff_applysilently(const dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver) { - return diff_apply(diff, db, ver, false); + dns_updatectx_t ctx = { .db = db, .ver = ver, .warn = false }; + dns_rdatacallbacks_t callbacks; + dns_rdatacallbacks_init(&callbacks); + callbacks.update = update_callback; + callbacks.add_private = &ctx; + return diff_apply(diff, &callbacks); +} + +isc_result_t +dns_diff_apply_with_callbacks(const dns_diff_t *diff, + dns_rdatacallbacks_t *callbacks) { + REQUIRE(DNS_DIFF_VALID(diff)); + REQUIRE(callbacks != NULL); + REQUIRE(callbacks->update != NULL); + + return diff_apply(diff, callbacks); } /* XXX this duplicates lots of code in diff_apply(). */ @@ -521,8 +556,9 @@ dns_diff_load(const dns_diff_t *diff, dns_rdatacallbacks_t *callbacks) { rds.trust = dns_trust_ultimate; INSIST(op == DNS_DIFFOP_ADD); - result = callbacks->add(callbacks->add_private, name, - &rds DNS__DB_FILELINE); + result = callbacks->update( + callbacks->add_private, name, &rds, + DNS_DIFFOP_ADD DNS__DB_FILELINE); if (result == DNS_R_UNCHANGED) { isc_log_write(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_DIFF, diff --git a/lib/dns/include/dns/callbacks.h b/lib/dns/include/dns/callbacks.h index e9dce8c73a..0ca5a92b39 100644 --- a/lib/dns/include/dns/callbacks.h +++ b/lib/dns/include/dns/callbacks.h @@ -34,18 +34,18 @@ struct dns_rdatacallbacks { unsigned int magic; /*% - * dns_load_master calls 'add' when it has an rdataset to add - * to the database. If defined, it calls 'setup' before and - * 'commit' after adding rdatasets. + * dns_load_master calls 'update' when it has an rdataset to update + * in the database. If defined, it calls 'setup' before and + * 'commit' after updating rdatasets. * * Some database implementations will commit each rdataset as - * soon as it's added, in which case 'setup' and 'commit' need + * soon as it's updated, in which case 'setup' and 'commit' need * not be defined. However, other implementations can be * optimized by grouping rdatasets into a transaction; the * setup and commit functions allow this transaction to be * opened and committed. */ - dns_addrdatasetfunc_t add; + dns_addrdatasetfunc_t update; dns_transactionfunc_t setup; dns_transactionfunc_t commit; diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index 8f0de40c5c..975b0d9132 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -89,6 +89,12 @@ typedef struct dns_db_methods { isc_result_t (*beginload)(dns_db_t *db, dns_rdatacallbacks_t *callbacks); isc_result_t (*endload)(dns_db_t *db, dns_rdatacallbacks_t *callbacks); + isc_result_t (*beginupdate)(dns_db_t *db, + dns_rdatacallbacks_t *callbacks); + isc_result_t (*commitupdate)(dns_db_t *db, + dns_rdatacallbacks_t *callbacks); + isc_result_t (*abortupdate)(dns_db_t *db, + dns_rdatacallbacks_t *callbacks); void (*currentversion)(dns_db_t *db, dns_dbversion_t **versionp); isc_result_t (*newversion)(dns_db_t *db, dns_dbversion_t **versionp); void (*attachversion)(dns_db_t *db, dns_dbversion_t *source, @@ -530,6 +536,85 @@ dns_db_endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks); * implementation used, syntax errors in the master file, etc. */ +isc_result_t +dns_db_beginupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks); +/*%< + * Begin updating 'db'. + * + * Requires: + * + * \li 'db' is a valid database. + * + * \li 'callbacks' is a pointer to an initialized dns_rdatacallbacks_t + * structure. + * + * Ensures: + * + * \li On success, callbacks->add will be a valid dns_addrdatasetfunc_t + * suitable for updating records in 'db' from IXFR operations. + * callbacks->add_private will be a valid DB update context + * which should be used as 'arg' when callbacks->add is called. + * + * Returns: + * + * \li #ISC_R_SUCCESS + * + * \li Other results are possible, depending upon the database + * implementation used. + */ + +isc_result_t +dns_db_commitupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks); +/*%< + * Commit the update to 'db'. Must be safe to double-call or call after + * dns_db_abortupdate. + * + * Requires: + * + * \li 'db' is a valid database that is being updated. + * + * \li 'callbacks' is a valid dns_rdatacallbacks_t structure. + * + * \li callbacks->add_private is not NULL and is a valid database update context. + * + * Ensures: + * + * \li 'callbacks' is returned to its state prior to calling dns_db_beginupdate() + * + * Returns: + * + * \li #ISC_R_SUCCESS + * + * \li Other results are possible, depending upon the database + * implementation used. + */ + +isc_result_t +dns_db_abortupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks); +/*%< + * Abort the update to 'db'. Must be safe to double-call or call after + * dns_db_commitupdate. + * + * Requires: + * + * \li 'db' is a valid database that is being updated. + * + * \li 'callbacks' is a valid dns_rdatacallbacks_t structure. + * + * \li callbacks->add_private is not NULL and is a valid database update context. + * + * Ensures: + * + * \li 'callbacks' is returned to its state prior to calling dns_db_beginupdate() + * + * Returns: + * + * \li #ISC_R_SUCCESS + * + * \li Other results are possible, depending upon the database + * implementation used. + */ + isc_result_t dns_db_load(dns_db_t *db, const char *filename, dns_masterformat_t format, unsigned int options); diff --git a/lib/dns/include/dns/diff.h b/lib/dns/include/dns/diff.h index e108f96f3e..e2073f80bf 100644 --- a/lib/dns/include/dns/diff.h +++ b/lib/dns/include/dns/diff.h @@ -59,13 +59,6 @@ * timeexpire. */ -typedef enum { - DNS_DIFFOP_ADD = 0, /*%< Add an RR. */ - DNS_DIFFOP_DEL = 1, /*%< Delete an RR. */ - DNS_DIFFOP_EXISTS = 2, /*%< Assert RR existence. */ - DNS_DIFFOP_ADDRESIGN = 4, /*%< ADD + RESIGN. */ - DNS_DIFFOP_DELRESIGN = 5 /*%< DEL + RESIGN. */ -} dns_diffop_t; typedef struct dns_difftuple dns_difftuple_t; typedef ISC_LIST(dns_difftuple_t) dns_difftuplelist_t; @@ -259,6 +252,24 @@ dns_diff_applysilently(const dns_diff_t *diff, dns_db_t *db, * */ +typedef struct { + dns_db_t *db; + dns_dbversion_t *ver; + bool warn; +} dns_updatectx_t; + +isc_result_t +dns_diff_apply_with_callbacks(const dns_diff_t *diff, dns_rdatacallbacks_t *callbacks); +/*%< + * Apply 'diff' to the database using the provided callbacks and context. + * The context contains the database, version, and warning flag. + * This allows for custom callback implementations. + * + * Requires: + *\li 'callbacks' points to a valid dns_rdatacallbacks_t structure + *\li 'callbacks->update' is not NULL + */ + isc_result_t dns_diff_load(const dns_diff_t *diff, dns_rdatacallbacks_t *callbacks); /*%< diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 81dc8f95e2..ef1a546154 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -183,6 +183,14 @@ typedef struct dst_gssapi_signverifyctx dst_gssapi_signverifyctx_t; typedef enum { dns_hash_sha1 = 1 } dns_hash_t; +typedef enum { + DNS_DIFFOP_ADD = 0, /*%< Add an RR. */ + DNS_DIFFOP_DEL = 1, /*%< Delete an RR. */ + DNS_DIFFOP_EXISTS = 2, /*%< Assert RR existence. */ + DNS_DIFFOP_ADDRESIGN = 4, /*%< ADD + RESIGN. */ + DNS_DIFFOP_DELRESIGN = 5 /*%< DEL + RESIGN. */ +} dns_diffop_t; + typedef enum { dns_fwdpolicy_none = 0, dns_fwdpolicy_first = 1, @@ -424,8 +432,8 @@ typedef void (*dns_loaddonefunc_t)(void *, isc_result_t); typedef void (*dns_rawdatafunc_t)(dns_zone_t *, dns_masterrawheader_t *); typedef isc_result_t (*dns_addrdatasetfunc_t)(void *arg, const dns_name_t *name, - dns_rdataset_t *rdataset - DNS__DB_FLARG); + dns_rdataset_t *rdataset, + dns_diffop_t op DNS__DB_FLARG); typedef void (*dns_transactionfunc_t)(void *arg); typedef isc_result_t (*dns_additionaldatafunc_t)( diff --git a/lib/dns/master.c b/lib/dns/master.c index ca12731a0b..191b91fc28 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -498,7 +498,7 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx, unsigned int options, REQUIRE(lctxp != NULL && *lctxp == NULL); REQUIRE(callbacks != NULL); - REQUIRE(callbacks->add != NULL); + REQUIRE(callbacks->update != NULL); REQUIRE(callbacks->error != NULL); REQUIRE(callbacks->warn != NULL); REQUIRE(mctx != NULL); @@ -2857,8 +2857,8 @@ commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx, dataset.attributes.resign = true; dataset.resign = resign_fromlist(this, lctx); } - result = callbacks->add(callbacks->add_private, owner, - &dataset DNS__DB_FILELINE); + result = callbacks->update(callbacks->add_private, owner, + &dataset, DNS_DIFFOP_ADD DNS__DB_FILELINE); if (result != ISC_R_SUCCESS) { dns_name_format(owner, namebuf, sizeof(namebuf)); if (source != NULL) { diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index b8a07be51d..f2e1d86cfc 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -2064,7 +2064,7 @@ addwildcards(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name, static isc_result_t loading_addrdataset(void *arg, const dns_name_t *name, - dns_rdataset_t *rdataset DNS__DB_FLARG) { + dns_rdataset_t *rdataset, dns_diffop_t op ISC_ATTR_UNUSED DNS__DB_FLARG) { qpz_load_t *loadctx = arg; qpzonedb_t *qpdb = (qpzonedb_t *)loadctx->db; qpznode_t *node = NULL; @@ -2194,7 +2194,7 @@ beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { RWUNLOCK(&qpdb->lock, isc_rwlocktype_write); - callbacks->add = loading_addrdataset; + callbacks->update = loading_addrdataset; callbacks->setup = loading_setup; callbacks->commit = loading_commit; callbacks->add_private = loadctx; @@ -2229,7 +2229,7 @@ endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { RWUNLOCK(&qpdb->lock, isc_rwlocktype_write); } - callbacks->add = NULL; + callbacks->update = NULL; callbacks->setup = NULL; callbacks->commit = NULL; callbacks->add_private = NULL; diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index f4ef175d40..1464717f0d 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -516,6 +516,11 @@ ixfr_apply_one(dns_xfrin_t *xfr, ixfr_apply_data_t *data) { isc_result_t result = ISC_R_SUCCESS; uint64_t records; + dns_rdatacallbacks_t callbacks; + dns_rdatacallbacks_init(&callbacks); + dns_db_beginupdate(xfr->db, &callbacks); + + CHECK(ixfr_begin_transaction(&xfr->ixfr)); CHECK(dns_diff_apply(&data->diff, xfr->db, xfr->ver)); @@ -529,12 +534,27 @@ ixfr_apply_one(dns_xfrin_t *xfr, ixfr_apply_data_t *data) { CHECK(dns_journal_writediff(xfr->ixfr.journal, &data->diff)); } + /* + * At the moment, rdatacallbacks doesn't offer a way to inspect the + * result of a transaction before committing it. + * + * So we need to commit *before* calling dns_zone_verifydb, and rely + * on closeversion to actually do cleanup. + */ + dns_db_commitupdate(xfr->db, &callbacks); + CHECK(dns_zone_verifydb(xfr->zone, xfr->db, xfr->ver)); result = ixfr_end_transaction(&xfr->ixfr); return result; cleanup: + /* + * For the reason stated above, dns_db_abortupdate must *commit* the + * changes and rely on closeversion to clean them up. + */ + dns_db_abortupdate(xfr->db, &callbacks); + /* We need to end the transaction, but keep the previous error */ (void)ixfr_end_transaction(&xfr->ixfr); From da53708dcbb5932de1bc1b0cf6871f6dae1db13e Mon Sep 17 00:00:00 2001 From: Alessio Podda Date: Sat, 25 Oct 2025 11:01:35 +0200 Subject: [PATCH 4/6] Implement qpzone specific update path This commit implements a batch update function for qpzone. The main reason for this is speed: using addrdataset would cause a qp transaction per rrdataset added, leading to a substantial slowdown compared to RBTDB. The new API results in a qp transaction per applied diff. --- lib/dns/db.c | 4 +- lib/dns/include/dns/db.h | 3 +- lib/dns/qpzone.c | 337 ++++++++++++++++++++++++++++++++++----- lib/dns/xfrin.c | 12 +- tests/dns/master_test.c | 7 +- 5 files changed, 314 insertions(+), 49 deletions(-) diff --git a/lib/dns/db.c b/lib/dns/db.c index 85758bcf2f..36416e402a 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -301,7 +301,7 @@ dns_db_endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { } isc_result_t -dns_db_beginupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { +dns_db_beginupdate(dns_db_t *db, dns_dbversion_t *ver, dns_rdatacallbacks_t *callbacks) { /* * Begin updating 'db'. */ @@ -311,7 +311,7 @@ dns_db_beginupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { REQUIRE(DNS_CALLBACK_VALID(callbacks)); if (db->methods->beginupdate != NULL) { - return (db->methods->beginupdate)(db, callbacks); + return (db->methods->beginupdate)(db, ver, callbacks); } return ISC_R_NOTIMPLEMENTED; } diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index 975b0d9132..92b8149601 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -90,6 +90,7 @@ typedef struct dns_db_methods { dns_rdatacallbacks_t *callbacks); isc_result_t (*endload)(dns_db_t *db, dns_rdatacallbacks_t *callbacks); isc_result_t (*beginupdate)(dns_db_t *db, + dns_dbversion_t *ver, dns_rdatacallbacks_t *callbacks); isc_result_t (*commitupdate)(dns_db_t *db, dns_rdatacallbacks_t *callbacks); @@ -537,7 +538,7 @@ dns_db_endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks); */ isc_result_t -dns_db_beginupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks); +dns_db_beginupdate(dns_db_t *db, dns_dbversion_t *ver, dns_rdatacallbacks_t *callbacks); /*%< * Begin updating 'db'. * diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index f2e1d86cfc..ae3f4a43ce 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,15 @@ typedef struct qpzone_bucket { (sizeof(isc_rwlock_t)) % ISC_OS_CACHELINE_SIZE]; } qpzone_bucket_t; +/* + * Qpzone-specific update context that extends dns_updatectx_t, used in IXFR. + */ +typedef struct qpzone_updatectx { + dns_updatectx_t base; + dns_qp_t *qp; + dns_qpread_t qpr; +} qpzone_updatectx_t; + static qpzone_bucket_t qpzone_buckets_g[1024]; typedef struct qpz_changed { @@ -2430,57 +2440,99 @@ setgluecachestats(dns_db_t *db, isc_stats_t *stats) { return ISC_R_SUCCESS; } -static isc_result_t -findnodeintree(qpzonedb_t *qpdb, const dns_name_t *name, bool create, - bool nsec3, dns_dbnode_t **nodep DNS__DB_FLARG) { - isc_result_t result; - qpznode_t *node = NULL; - dns_namespace_t nspace = nsec3 ? DNS_DBNAMESPACE_NSEC3 - : DNS_DBNAMESPACE_NORMAL; - dns_qpread_t qpr = { 0 }; +static dns_qp_t* +begin_transaction(qpzonedb_t *qpdb, dns_qpread_t *qprp, bool create) { dns_qp_t *qp = NULL; if (create) { dns_qpmulti_write(qpdb->tree, &qp); } else { - dns_qpmulti_query(qpdb->tree, &qpr); - qp = (dns_qp_t *)&qpr; + dns_qpmulti_query(qpdb->tree, qprp); + qp = (dns_qp_t *)qprp; } - result = dns_qp_getname(qp, name, nspace, (void **)&node, NULL); - if (result != ISC_R_SUCCESS) { - if (!create) { - dns_qpread_destroy(qpdb->tree, &qpr); - return result; - } + return qp; +} +static void +end_transaction(qpzonedb_t *qpdb, dns_qp_t *qp, bool create) { + if (create) { + dns_qp_compact(qp, DNS_QPGC_MAYBE); + dns_qpmulti_commit(qpdb->tree, &qp); + } else { + dns_qpread_t *qprp = (dns_qpread_t*) qp; + dns_qpread_destroy(qpdb->tree, qprp); + } +} + +static isc_result_t +findnodeintree(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name, bool create, + bool nsec3, dns_dbnode_t **nodep DNS__DB_FLARG) { + isc_result_t result; + qpznode_t *node = NULL; + dns_namespace_t nspace = nsec3 ? DNS_DBNAMESPACE_NSEC3 + : DNS_DBNAMESPACE_NORMAL; + /* + * findnodeintree is a wrapper around dns_qp_getname that does some + * qpzone-specific bookkeeping before returning the lookup result to the + * caller. + * + * First, we do a lookup ... + */ + result = dns_qp_getname(qp, name, nspace, (void **)&node, NULL); + if (result == ISC_R_SUCCESS) { + /* + * ... if the lookup is successful, we need to increase both the + * internal and external reference count before returning to + * the caller. qpznode_acquire takes care of that. + */ + qpznode_acquire(node DNS__DB_FLARG_PASS); + + INSIST(node->nspace == DNS_DBNAMESPACE_NSEC3 || !nsec3); + } else if (result != ISC_R_SUCCESS && create) { + /* + * ... if the lookup is unsuccesful, but the caller asked us to + * create a new node, create one and insert it into the tree. + */ node = new_qpznode(qpdb, name, nspace); result = dns_qp_insert(qp, node, 0); INSIST(result == ISC_R_SUCCESS); - qpznode_unref(node); + + /* + * The new node now has two internal references: + * - One from new_qpznode, that initializes references at 1. + * - One from attach_leaf, that increases the reference by + * one at insertion in the qp-tree. + * We want the node to have two internal and one external + * reference: + * - One internal reference from the qp-tree. + * - One internal and one external reference from the caller. + * + * So we increase the external reference count by one. + */ + qpznode_erefs_increment(node DNS__DB_FLARG_PASS); if (!nsec3) { + /* + * Add empty non-terminal nodes to help with wildcards. + */ addwildcards(qpdb, qp, name, nspace); if (dns_name_iswildcard(name)) { wildcardmagic(qpdb, qp, name, nspace); } } + + INSIST(node->nspace == DNS_DBNAMESPACE_NSEC3 || !nsec3); } - - INSIST(node->nspace == DNS_DBNAMESPACE_NSEC3 || !nsec3); - - qpznode_acquire(node DNS__DB_FLARG_PASS); - - if (create) { - dns_qp_compact(qp, DNS_QPGC_MAYBE); - dns_qpmulti_commit(qpdb->tree, &qp); - } else { - dns_qpread_destroy(qpdb->tree, &qpr); - } + /* + * ... if the lookup is unsucessful, and the caller didn't ask us + * to create a new node, there is nothing to do. Return the result + * of the lookup to the caller, and set *nodep to NULL + */ *nodep = (dns_dbnode_t *)node; - return ISC_R_SUCCESS; + return result; } static isc_result_t @@ -2492,8 +2544,14 @@ qpzone_findnode(dns_db_t *db, const dns_name_t *name, bool create, REQUIRE(VALID_QPZONE(qpdb)); - return findnodeintree(qpdb, name, create, false, - nodep DNS__DB_FLARG_PASS); + dns_qpread_t qpr = { 0 }; + dns_qp_t *qp = begin_transaction(qpdb, &qpr, create); + + isc_result_t result = findnodeintree(qpdb, qp, name, create, false, nodep DNS__DB_FLARG_PASS); + + end_transaction(qpdb, qp, create); + + return result; } static isc_result_t @@ -2503,8 +2561,14 @@ qpzone_findnsec3node(dns_db_t *db, const dns_name_t *name, bool create, REQUIRE(VALID_QPZONE(qpdb)); - return findnodeintree(qpdb, name, create, true, - nodep DNS__DB_FLARG_PASS); + dns_qpread_t qpr = { 0 }; + dns_qp_t *qp = begin_transaction(qpdb, &qpr, create); + + isc_result_t result = findnodeintree(qpdb, qp, name, create, true, nodep DNS__DB_FLARG_PASS); + + end_transaction(qpdb, qp, create); + + return result; } static bool @@ -4592,12 +4656,22 @@ qpzone_createiterator(dns_db_t *db, unsigned int options, return ISC_R_SUCCESS; } +/* + * Main logic to add a new rdataset to a node. + * + * The reason this is split from qpzone_addrdataset is to allow the reuse of + * the same qp transaction for multiple adds. + * + * qpzone_subtractrdataset doesn't have the same problem since it cannot delete + * nodes, only rdatasets. + */ static isc_result_t -qpzone_addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, +qpzone_addrdataset_inner(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion, isc_stdtime_t now ISC_ATTR_UNUSED, dns_rdataset_t *rdataset, unsigned int options, - dns_rdataset_t *addedrdataset DNS__DB_FLARG) { + dns_rdataset_t *addedrdataset, + dns_qp_t *nsec) { isc_result_t result; qpzonedb_t *qpdb = (qpzonedb_t *)db; qpznode_t *node = (qpznode_t *)dbnode; @@ -4608,7 +4682,6 @@ qpzone_addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, isc_rwlock_t *nlock = NULL; dns_fixedname_t fn; dns_name_t *name = dns_fixedname_initname(&fn); - dns_qp_t *nsec = NULL; REQUIRE(VALID_QPZONE(qpdb)); REQUIRE(version != NULL && version->qpdb == qpdb); @@ -4659,12 +4732,12 @@ qpzone_addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, newheader->resign_lsb = rdataset->resign & 0x1; } + /* * Add to the auxiliary NSEC tree if we're adding an NSEC record. */ - if (!node->havensec && rdataset->type == dns_rdatatype_nsec) { - dns_qpmulti_write(qpdb->tree, &nsec); - } + bool is_nsec = !node->havensec && rdataset->type == dns_rdatatype_nsec; + REQUIRE(!is_nsec || nsec != NULL); /* * If we're adding a delegation type or adding to the auxiliary NSEC @@ -4680,7 +4753,7 @@ qpzone_addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, NODE_WRLOCK(nlock, &nlocktype); result = ISC_R_SUCCESS; - if (nsec != NULL) { + if (is_nsec) { node->havensec = true; /* @@ -4690,6 +4763,10 @@ qpzone_addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, */ qpznode_t *nsecnode = new_qpznode(qpdb, name, DNS_DBNAMESPACE_NSEC); + /* + * We don't need a separate transaction since the NSEC tree and + * the normal tree are part of the same qp-tree. + */ (void)dns_qp_insert(nsec, nsecnode, 0); qpznode_detach(&nsecnode); } @@ -4711,6 +4788,32 @@ qpzone_addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, NODE_UNLOCK(nlock, &nlocktype); + return result; +} + +static isc_result_t +qpzone_addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, + dns_dbversion_t *dbversion, + isc_stdtime_t now ISC_ATTR_UNUSED, dns_rdataset_t *rdataset, + unsigned int options, + dns_rdataset_t *addedrdataset DNS__DB_FLARG) { + qpzonedb_t *qpdb = (qpzonedb_t *)db; + qpznode_t *node = (qpznode_t *)dbnode; + dns_qp_t *nsec = NULL; + + REQUIRE(VALID_QPZONE(qpdb)); + + /* + * Add to the auxiliary NSEC tree if we're adding an NSEC record. + */ + if (!node->havensec && rdataset->type == dns_rdatatype_nsec) { + dns_qpmulti_write(qpdb->tree, &nsec); + } + + isc_result_t result = qpzone_addrdataset_inner(db, dbnode, dbversion, + now, rdataset, options, + addedrdataset, nsec); + if (nsec != NULL) { dns_qpmulti_commit(qpdb->tree, &nsec); } @@ -5270,10 +5373,164 @@ setmaxtypepername(dns_db_t *db, uint32_t value) { qpdb->maxtypepername = value; } +/* + * Qpzone specialization of the update function from dns_rdatacallbacks_t, + * meant to reuse the same qp transaction for multiple operations. + */ +static isc_result_t +qpzone_update_rdataset(qpzonedb_t *qpdb, qpz_version_t *version, dns_qp_t *qp, + dns_name_t *name, dns_rdataset_t *rds, dns_diffop_t op) { + isc_result_t result; + unsigned int options; + dns_rdataset_t ardataset; + dns_dbnode_t *node = NULL; + bool is_nsec3; + + dns_rdataset_init(&ardataset); + + is_nsec3 = (rds->type == dns_rdatatype_nsec3 || rds->covers == dns_rdatatype_nsec3); + + result = findnodeintree(qpdb, qp, name, true, is_nsec3, &node DNS__DB_FLARG_PASS); + + if (result != ISC_R_SUCCESS) { + goto failure; + } + + switch (op) { + case DNS_DIFFOP_ADD: + case DNS_DIFFOP_ADDRESIGN: + /* + * See the comment on qpzone_addrdataset_inner for why we + * cannot use qpzone_addrdataset directly. + */ + options = DNS_DBADD_MERGE | DNS_DBADD_EXACT | + DNS_DBADD_EXACTTTL; + result = qpzone_addrdataset_inner((dns_db_t *)qpdb, node, + (dns_dbversion_t *)version, 0, + rds, options, + &ardataset, qp DNS__DB_FLARG_PASS); + break; + case DNS_DIFFOP_DEL: + case DNS_DIFFOP_DELRESIGN: + options = DNS_DBSUB_EXACT | DNS_DBSUB_WANTOLD; + result = qpzone_subtractrdataset((dns_db_t *)qpdb, node, + (dns_dbversion_t *)version, + rds, options, + &ardataset DNS__DB_FLARG_PASS); + break; + default: + UNREACHABLE(); + } + + bool is_resign = rds->type == dns_rdatatype_rrsig && + (op == DNS_DIFFOP_DELRESIGN || op == DNS_DIFFOP_ADDRESIGN); + + if (result == ISC_R_SUCCESS && is_resign) { + isc_stdtime_t resign; + resign = dns_rdataset_minresign(&ardataset); + dns_db_setsigningtime((dns_db_t *)qpdb, &ardataset, resign); + } + +failure: + if (node != NULL) { + dns_db_detachnode(&node); + } + if (dns_rdataset_isassociated(&ardataset)) { + dns_rdataset_disassociate(&ardataset); + } + return result; +} + +static isc_result_t +qpzone_update_callback(void *arg, const dns_name_t *name, dns_rdataset_t *rds, + dns_diffop_t op DNS__DB_FLARG) { + qpzone_updatectx_t *ctx = arg; + qpzonedb_t *qpdb = (qpzonedb_t *)ctx->base.db; + qpz_version_t *version = (qpz_version_t *)ctx->base.ver; + + return qpzone_update_rdataset(qpdb, version, ctx->qp, (dns_name_t *)name, rds, op); +} + +static isc_result_t +qpzone_beginupdate(dns_db_t *db, dns_dbversion_t *ver, dns_rdatacallbacks_t *callbacks) { + qpzonedb_t *qpdb = (qpzonedb_t *)db; + + REQUIRE(VALID_QPZONE(qpdb)); + REQUIRE(ver != NULL); + REQUIRE(DNS_CALLBACK_VALID(callbacks)); + + qpzone_updatectx_t* ctx = isc_mem_get(qpdb->common.mctx, sizeof(*ctx)); + *ctx = (qpzone_updatectx_t) { + .base.db = db, + .base.ver = ver, + .base.warn = true, + .qpr = (dns_qpread_t){ 0 }, + }; + ctx->qp = begin_transaction(qpdb, &ctx->qpr, true); + + callbacks->update = qpzone_update_callback; + callbacks->add_private = ctx; + + return ISC_R_SUCCESS; +} + +static isc_result_t +qpzone_commitupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { + qpzonedb_t *qpdb = (qpzonedb_t *)db; + qpzone_updatectx_t *ctx; + + REQUIRE(VALID_QPZONE(qpdb)); + REQUIRE(DNS_CALLBACK_VALID(callbacks)); + + ctx = (qpzone_updatectx_t *)callbacks->add_private; + if (ctx != NULL) { + end_transaction(qpdb, ctx->qp, true); + + isc_mem_put(qpdb->common.mctx, ctx, sizeof(*ctx)); + /* + * We need to allow the context to be committed or aborted + * multiple times, so we set the callback data to NULL + * to signal that nothing needs to be done with this context. + */ + callbacks->add_private = NULL; + } + + return ISC_R_SUCCESS; +} + +/* + * For now, abortupdate needs to *commit* the results, so that closeversion + * cleanup might work. + */ +static isc_result_t +qpzone_abortupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { + qpzonedb_t *qpdb = (qpzonedb_t *)db; + qpzone_updatectx_t *ctx; + + REQUIRE(VALID_QPZONE(qpdb)); + REQUIRE(DNS_CALLBACK_VALID(callbacks)); + + ctx = (qpzone_updatectx_t *)callbacks->add_private; + if (ctx != NULL) { + end_transaction(qpdb, ctx->qp, true); + + isc_mem_put(qpdb->common.mctx, ctx, sizeof(*ctx)); + /* + * See qpzone_commitupdate. + */ + callbacks->add_private = NULL; + } + + return ISC_R_SUCCESS; +} + static dns_dbmethods_t qpdb_zonemethods = { .destroy = qpdb_destroy, .beginload = beginload, .endload = endload, + .beginupdate = qpzone_beginupdate, + .commitupdate = qpzone_commitupdate, + .abortupdate = qpzone_abortupdate, .currentversion = currentversion, .newversion = newversion, .attachversion = attachversion, diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index 1464717f0d..783b7d0dd1 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -518,12 +518,12 @@ ixfr_apply_one(dns_xfrin_t *xfr, ixfr_apply_data_t *data) { dns_rdatacallbacks_t callbacks; dns_rdatacallbacks_init(&callbacks); - dns_db_beginupdate(xfr->db, &callbacks); - CHECK(ixfr_begin_transaction(&xfr->ixfr)); - CHECK(dns_diff_apply(&data->diff, xfr->db, xfr->ver)); + dns_db_beginupdate(xfr->db, xfr->ver, &callbacks); + + CHECK(dns_diff_apply_with_callbacks(&data->diff, &callbacks)); if (xfr->maxrecords != 0U) { result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL); if (result == ISC_R_SUCCESS && records > xfr->maxrecords) { @@ -533,6 +533,12 @@ ixfr_apply_one(dns_xfrin_t *xfr, ixfr_apply_data_t *data) { if (xfr->ixfr.journal != NULL) { CHECK(dns_journal_writediff(xfr->ixfr.journal, &data->diff)); } + /* + * In the current implementation, we always commit the results, since + * dns_zone_verifydb doesn't know how to access the in-progress + * transaction. + */ + dns_db_commitupdate(xfr->db, &callbacks); /* * At the moment, rdatacallbacks doesn't offer a way to inspect the diff --git a/tests/dns/master_test.c b/tests/dns/master_test.c index 1d822fed8d..931f7017ca 100644 --- a/tests/dns/master_test.c +++ b/tests/dns/master_test.c @@ -66,12 +66,13 @@ rawdata_callback(dns_zone_t *zone, dns_masterrawheader_t *header); static isc_result_t add_callback(void *arg, const dns_name_t *owner, - dns_rdataset_t *dataset DNS__DB_FLARG) { + dns_rdataset_t *dataset, dns_diffop_t op DNS__DB_FLARG) { char buf[BIGBUFLEN]; isc_buffer_t target; isc_result_t result; UNUSED(arg); + UNUSED(op); isc_buffer_init(&target, buf, BIGBUFLEN); result = dns_rdataset_totext(dataset, owner, false, false, &target); @@ -102,7 +103,7 @@ setup_master(void (*warn)(struct dns_rdatacallbacks *, const char *, ...), RETERR(dns_name_fromtext(dns_origin, &source, dns_rootname, 0)); dns_rdatacallbacks_init_stdio(&callbacks); - callbacks.add = add_callback; + callbacks.update = add_callback; callbacks.rawdata = rawdata_callback; callbacks.zone = NULL; if (warn != NULL) { @@ -125,7 +126,7 @@ test_master(const char *workdir, const char *testfile, RETERR(setup_master(warn, error)); dns_rdatacallbacks_init_stdio(&callbacks); - callbacks.add = add_callback; + callbacks.update = add_callback; callbacks.rawdata = rawdata_callback; callbacks.zone = NULL; if (warn != NULL) { From fb72ebcdd8fbfb94ac6ddb680d778cf754d06ab3 Mon Sep 17 00:00:00 2001 From: Alessio Podda Date: Mon, 27 Oct 2025 15:43:35 +0100 Subject: [PATCH 5/6] Add unit tests --- tests/dns/qpzone_test.c | 283 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 283 insertions(+) diff --git a/tests/dns/qpzone_test.c b/tests/dns/qpzone_test.c index 7f80a238ab..3d6016c779 100644 --- a/tests/dns/qpzone_test.c +++ b/tests/dns/qpzone_test.c @@ -27,6 +27,8 @@ #include #include +#include +#include #include #include #include @@ -46,6 +48,23 @@ #include +/* + * Macro that uses a for loop to execute a cleanup at the end of scope. + */ +#define WITH_NEWVERSION(db, version_var, should_commit) \ + for (dns_dbversion_t *version_var = NULL, \ + *_tmp = ({ \ + isc_result_t _result = dns_db_newversion(db, &version_var); \ + assert_int_equal(_result, ISC_R_SUCCESS); \ + (dns_dbversion_t*)1; \ + }); \ + _tmp != NULL; \ + _tmp = ({ \ + dns_db_closeversion(db, &version_var, should_commit); \ + (dns_dbversion_t*)NULL; \ + })) + + const char *ownercase_vectors[12][2] = { { "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz", @@ -97,6 +116,67 @@ const char *ownercase_vectors[12][2] = { } }; +static unsigned char example_org_data[] = { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'o', 'r', 'g', 0 }; +static dns_name_t example_org_name = DNS_NAME_INITABSOLUTE(example_org_data); + +/* IPv6 test addresses */ +static unsigned char aaaa_test_data[][16] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* ::1 */ + { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 } /* 2001:db8::2 */ +}; + +/* RRSIG test signatures */ +static unsigned char rrsig_signature1[64] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40 +}; + +static unsigned char rrsig_signature2[64] = { + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80 +}; + +/* RRSIG test structures */ +static dns_rdata_rrsig_t rrsig_test_data1 = { + .common = { .rdtype = dns_rdatatype_rrsig, .rdclass = dns_rdataclass_in }, + .covered = dns_rdatatype_a, + .algorithm = DST_ALG_RSASHA256, + .labels = 2, + .originalttl = 300, + .timeexpire = 1695820800, + .timesigned = 1695744000, + .keyid = 0x1234, + .signer = DNS_NAME_INITABSOLUTE(example_org_data), + .siglen = 64, + .signature = rrsig_signature1, +}; + +static dns_rdata_rrsig_t rrsig_test_data2 = { + .common = { .rdtype = dns_rdatatype_rrsig, .rdclass = dns_rdataclass_in }, + .covered = dns_rdatatype_a, + .algorithm = DST_ALG_RSASHA256, + .labels = 2, + .originalttl = 300, + .timeexpire = 1695820800, + .timesigned = 1695744000, + .keyid = 0x5678, + .signer = DNS_NAME_INITABSOLUTE(example_org_data), + .siglen = 64, + .signature = rrsig_signature2, +}; + static bool ownercase_test_one(const char *str1, const char *str2) { isc_result_t result; @@ -160,6 +240,117 @@ ISC_RUN_TEST_IMPL(ownercase) { assert_false(ownercase_test_one("\\216", "\\246")); } +static ssize_t +find_ip_index(const unsigned char *target_ip, unsigned char (*ips)[16], + ssize_t count) { + for (ssize_t i = 0; i < count; i++) { + if (memcmp(target_ip, ips[i], 16) == 0) { + return i; + } + } + return -1; +} + +static isc_result_t +apply_dns_update(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, + dns_rdatatype_t rdtype, dns_rdataclass_t rdclass, uint32_t ttl, + const unsigned char *data, size_t data_len, dns_diffop_t op) { + isc_result_t result; + dns_rdatacallbacks_t callbacks; + dns_rdatalist_t rdatalist; + dns_rdataset_t rdataset; + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdatacallbacks_init(&callbacks); + + result = dns_db_beginupdate(db, version, &callbacks); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Set rdata fields directly without reinitializing */ + rdata.data = (unsigned char *)data; + rdata.length = data_len; + rdata.rdclass = rdclass; + rdata.type = rdtype; + + dns_rdatalist_init(&rdatalist); + rdatalist.ttl = ttl; + rdatalist.type = rdtype; + rdatalist.rdclass = rdclass; + ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); + + dns_rdataset_init(&rdataset); + dns_rdatalist_tordataset(&rdatalist, &rdataset); + + isc_result_t callback_result = callbacks.update(callbacks.add_private, name, &rdataset, op); + assert_int_equal(result, ISC_R_SUCCESS); + + dns_rdataset_disassociate(&rdataset); + + result = dns_db_commitupdate(db, &callbacks); + assert_int_equal(result, ISC_R_SUCCESS); + + return callback_result; +} + +static void +verify_aaaa_records(dns_db_t *db, dns_dbversion_t *version, + const dns_name_t *name, unsigned char (*ips)[16], + ssize_t expected_count, uint32_t expected_ttl) { + isc_result_t result; + dns_dbnode_t *node = NULL; + dns_rdataset_t rdataset; + bool *found_ips = NULL; + dns_fixedname_t found_fname; + dns_name_t *found_name = dns_fixedname_initname(&found_fname); + + /* Allocate zero-initialized found flags array */ + found_ips = isc_mem_cget(isc_g_mctx, (size_t)expected_count, + sizeof(bool)); + + dns_rdataset_init(&rdataset); + + result = dns_db_find(db, name, version, dns_rdatatype_aaaa, 0, 0, &node, + found_name, &rdataset, NULL); + assert_int_equal(result, ISC_R_SUCCESS); + + /* Check rdataset metadata */ + assert_int_equal(rdataset.type, dns_rdatatype_aaaa); + assert_int_equal(rdataset.rdclass, dns_rdataclass_in); + assert_int_equal(rdataset.ttl, expected_ttl); + + /* Iterate through all AAAA records */ + DNS_RDATASET_FOREACH(&rdataset) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(&rdataset, &rdata); + + /* Verify this is a valid IPv6 address */ + assert_int_equal(rdata.length, 16); + + /* + * Find whether the IP is in our expected list, and detect + * duplicates. Index will be -1 if the IP is not found. + */ + ssize_t index = find_ip_index(rdata.data, ips, expected_count); + assert_true(index >= 0); + assert_false(found_ips[index]); + found_ips[index] = true; + } + + /* Count found IPs by summing overt the boolean array */ + ssize_t found_count = 0; + for (ssize_t i = 0; i < expected_count; i++) { + found_count += found_ips[i]; + } + + /* Verify we found exactly the expected number of records */ + assert_int_equal(found_count, expected_count); + + dns_db_detachnode(&node); + dns_rdataset_disassociate(&rdataset); + isc_mem_cput(isc_g_mctx, found_ips, (size_t)expected_count, + sizeof(bool)); +} + ISC_RUN_TEST_IMPL(setownercase) { isc_result_t result; uint8_t qpdb_s[sizeof(qpzonedb_t) + sizeof(qpzone_bucket_t)]; @@ -209,9 +400,101 @@ ISC_RUN_TEST_IMPL(setownercase) { assert_true(dns_name_caseequal(name1, name2)); } +ISC_RUN_TEST_IMPL(diffop_add_sub) { + isc_result_t result; + dns_db_t *db = NULL; + + result = dns__qpzone_create(isc_g_mctx, &example_org_name, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, NULL, &db); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(db); + + WITH_NEWVERSION(db, version, true) { + apply_dns_update(db, version, &example_org_name, dns_rdatatype_aaaa, + dns_rdataclass_in, 300, aaaa_test_data[0], 16, DNS_DIFFOP_ADD); + } + + WITH_NEWVERSION(db, version, true) { + result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_aaaa, + dns_rdataclass_in, 300, aaaa_test_data[1], 16, DNS_DIFFOP_ADD); + assert_int_equal(result, ISC_R_SUCCESS); + + verify_aaaa_records(db, version, &example_org_name, aaaa_test_data, 2, 300); + } + + WITH_NEWVERSION(db, version, true) { + result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_aaaa, + dns_rdataclass_in, 300, aaaa_test_data[0], 16, DNS_DIFFOP_DEL); + assert_int_equal(result, ISC_R_SUCCESS); + + verify_aaaa_records(db, version, &example_org_name, &aaaa_test_data[1], 1, 300); + } + + WITH_NEWVERSION(db, version, false) { + result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_aaaa, + dns_rdataclass_in, 600, aaaa_test_data[0], 16, DNS_DIFFOP_ADD); + assert_int_equal(result, DNS_R_NOTEXACT); + } + + dns_db_detach(&db); + assert_null(db); +} + +ISC_RUN_TEST_IMPL(diffop_addresign) { + isc_result_t result; + dns_db_t *db = NULL; + + /* Create RRSIG structures and convert to wire format */ + dns_rdata_t rdata1 = DNS_RDATA_INIT, rdata2 = DNS_RDATA_INIT; + isc_buffer_t buffer1, buffer2; + unsigned char rrsig_data1[512], rrsig_data2[512]; + + isc_buffer_init(&buffer1, rrsig_data1, sizeof(rrsig_data1)); + result = dns_rdata_fromstruct(&rdata1, dns_rdataclass_in, dns_rdatatype_rrsig, &rrsig_test_data1, &buffer1); + assert_int_equal(result, ISC_R_SUCCESS); + + isc_buffer_init(&buffer2, rrsig_data2, sizeof(rrsig_data2)); + result = dns_rdata_fromstruct(&rdata2, dns_rdataclass_in, dns_rdatatype_rrsig, &rrsig_test_data2, &buffer2); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns__qpzone_create(isc_g_mctx, &example_org_name, dns_dbtype_zone, + dns_rdataclass_in, 0, NULL, NULL, &db); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(db); + + WITH_NEWVERSION(db, version, true) { + result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_rrsig, + dns_rdataclass_in, 300, rdata1.data, rdata1.length, DNS_DIFFOP_ADDRESIGN); + assert_int_equal(result, ISC_R_SUCCESS); + } + + WITH_NEWVERSION(db, version, true) { + result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_rrsig, + dns_rdataclass_in, 300, rdata2.data, rdata2.length, DNS_DIFFOP_ADDRESIGN); + assert_int_equal(result, ISC_R_SUCCESS); + } + + WITH_NEWVERSION(db, version, true) { + result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_rrsig, + dns_rdataclass_in, 300, rdata1.data, rdata1.length, DNS_DIFFOP_DELRESIGN); + assert_int_equal(result, ISC_R_SUCCESS); + } + + WITH_NEWVERSION(db, version, true) { + result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_rrsig, + dns_rdataclass_in, 300, rdata2.data, rdata2.length, DNS_DIFFOP_DELRESIGN); + assert_int_equal(result, DNS_R_NXRRSET); + } + + dns_db_detach(&db); + assert_null(db); +} + ISC_TEST_LIST_START ISC_TEST_ENTRY(ownercase) ISC_TEST_ENTRY(setownercase) +ISC_TEST_ENTRY(diffop_add_sub) +ISC_TEST_ENTRY(diffop_addresign) ISC_TEST_LIST_END ISC_TEST_MAIN From ad0a38209292b04db8bc6202af4cdcbe6e5a8e4a Mon Sep 17 00:00:00 2001 From: Alessio Podda Date: Fri, 5 Dec 2025 16:14:41 +0100 Subject: [PATCH 6/6] Fix formatting Cleanup formatting after IXFR changes. --- lib/dns/db.c | 3 +- lib/dns/diff.c | 2 +- lib/dns/include/dns/db.h | 26 ++++--- lib/dns/include/dns/diff.h | 8 +-- lib/dns/master.c | 3 +- lib/dns/qpzone.c | 61 ++++++++-------- tests/dns/master_test.c | 4 +- tests/dns/qpzone_test.c | 140 ++++++++++++++++++++++--------------- 8 files changed, 140 insertions(+), 107 deletions(-) diff --git a/lib/dns/db.c b/lib/dns/db.c index 36416e402a..aa305d542c 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -301,7 +301,8 @@ dns_db_endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { } isc_result_t -dns_db_beginupdate(dns_db_t *db, dns_dbversion_t *ver, dns_rdatacallbacks_t *callbacks) { +dns_db_beginupdate(dns_db_t *db, dns_dbversion_t *ver, + dns_rdatacallbacks_t *callbacks) { /* * Begin updating 'db'. */ diff --git a/lib/dns/diff.c b/lib/dns/diff.c index f89d245a67..43fc7ca946 100644 --- a/lib/dns/diff.c +++ b/lib/dns/diff.c @@ -238,7 +238,7 @@ update_rdataset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, options = DNS_DBADD_MERGE | DNS_DBADD_EXACT | DNS_DBADD_EXACTTTL; CHECK(dns_db_addrdataset(db, node, ver, 0, rds, options, - &ardataset)); + &ardataset)); break; case DNS_DIFFOP_DEL: case DNS_DIFFOP_DELRESIGN: diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index 92b8149601..069f788cd8 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -89,12 +89,11 @@ typedef struct dns_db_methods { isc_result_t (*beginload)(dns_db_t *db, dns_rdatacallbacks_t *callbacks); isc_result_t (*endload)(dns_db_t *db, dns_rdatacallbacks_t *callbacks); - isc_result_t (*beginupdate)(dns_db_t *db, - dns_dbversion_t *ver, + isc_result_t (*beginupdate)(dns_db_t *db, dns_dbversion_t *ver, dns_rdatacallbacks_t *callbacks); - isc_result_t (*commitupdate)(dns_db_t *db, + isc_result_t (*commitupdate)(dns_db_t *db, dns_rdatacallbacks_t *callbacks); - isc_result_t (*abortupdate)(dns_db_t *db, + isc_result_t (*abortupdate)(dns_db_t *db, dns_rdatacallbacks_t *callbacks); void (*currentversion)(dns_db_t *db, dns_dbversion_t **versionp); isc_result_t (*newversion)(dns_db_t *db, dns_dbversion_t **versionp); @@ -538,7 +537,8 @@ dns_db_endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks); */ isc_result_t -dns_db_beginupdate(dns_db_t *db, dns_dbversion_t *ver, dns_rdatacallbacks_t *callbacks); +dns_db_beginupdate(dns_db_t *db, dns_dbversion_t *ver, + dns_rdatacallbacks_t *callbacks); /*%< * Begin updating 'db'. * @@ -567,7 +567,7 @@ dns_db_beginupdate(dns_db_t *db, dns_dbversion_t *ver, dns_rdatacallbacks_t *cal isc_result_t dns_db_commitupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks); /*%< - * Commit the update to 'db'. Must be safe to double-call or call after + * Commit the update to 'db'. Must be safe to double-call or call after * dns_db_abortupdate. * * Requires: @@ -576,11 +576,13 @@ dns_db_commitupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks); * * \li 'callbacks' is a valid dns_rdatacallbacks_t structure. * - * \li callbacks->add_private is not NULL and is a valid database update context. + * \li callbacks->add_private is not NULL and is a valid database update + * context. * * Ensures: * - * \li 'callbacks' is returned to its state prior to calling dns_db_beginupdate() + * \li 'callbacks' is returned to its state prior to calling + * dns_db_beginupdate() * * Returns: * @@ -593,7 +595,7 @@ dns_db_commitupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks); isc_result_t dns_db_abortupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks); /*%< - * Abort the update to 'db'. Must be safe to double-call or call after + * Abort the update to 'db'. Must be safe to double-call or call after * dns_db_commitupdate. * * Requires: @@ -602,11 +604,13 @@ dns_db_abortupdate(dns_db_t *db, dns_rdatacallbacks_t *callbacks); * * \li 'callbacks' is a valid dns_rdatacallbacks_t structure. * - * \li callbacks->add_private is not NULL and is a valid database update context. + * \li callbacks->add_private is not NULL and is a valid database update + * context. * * Ensures: * - * \li 'callbacks' is returned to its state prior to calling dns_db_beginupdate() + * \li 'callbacks' is returned to its state prior to calling + * dns_db_beginupdate() * * Returns: * diff --git a/lib/dns/include/dns/diff.h b/lib/dns/include/dns/diff.h index e2073f80bf..32e81890de 100644 --- a/lib/dns/include/dns/diff.h +++ b/lib/dns/include/dns/diff.h @@ -59,7 +59,6 @@ * timeexpire. */ - typedef struct dns_difftuple dns_difftuple_t; typedef ISC_LIST(dns_difftuple_t) dns_difftuplelist_t; @@ -253,13 +252,14 @@ dns_diff_applysilently(const dns_diff_t *diff, dns_db_t *db, */ typedef struct { - dns_db_t *db; + dns_db_t *db; dns_dbversion_t *ver; - bool warn; + bool warn; } dns_updatectx_t; isc_result_t -dns_diff_apply_with_callbacks(const dns_diff_t *diff, dns_rdatacallbacks_t *callbacks); +dns_diff_apply_with_callbacks(const dns_diff_t *diff, + dns_rdatacallbacks_t *callbacks); /*%< * Apply 'diff' to the database using the provided callbacks and context. * The context contains the database, version, and warning flag. diff --git a/lib/dns/master.c b/lib/dns/master.c index 191b91fc28..ce2dca13d4 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -2858,7 +2858,8 @@ commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx, dataset.resign = resign_fromlist(this, lctx); } result = callbacks->update(callbacks->add_private, owner, - &dataset, DNS_DIFFOP_ADD DNS__DB_FILELINE); + &dataset, + DNS_DIFFOP_ADD DNS__DB_FILELINE); if (result != ISC_R_SUCCESS) { dns_name_format(owner, namebuf, sizeof(namebuf)); if (source != NULL) { diff --git a/lib/dns/qpzone.c b/lib/dns/qpzone.c index ae3f4a43ce..1244426124 100644 --- a/lib/dns/qpzone.c +++ b/lib/dns/qpzone.c @@ -2073,8 +2073,8 @@ addwildcards(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name, } static isc_result_t -loading_addrdataset(void *arg, const dns_name_t *name, - dns_rdataset_t *rdataset, dns_diffop_t op ISC_ATTR_UNUSED DNS__DB_FLARG) { +loading_addrdataset(void *arg, const dns_name_t *name, dns_rdataset_t *rdataset, + dns_diffop_t op ISC_ATTR_UNUSED DNS__DB_FLARG) { qpz_load_t *loadctx = arg; qpzonedb_t *qpdb = (qpzonedb_t *)loadctx->db; qpznode_t *node = NULL; @@ -2440,7 +2440,7 @@ setgluecachestats(dns_db_t *db, isc_stats_t *stats) { return ISC_R_SUCCESS; } -static dns_qp_t* +static dns_qp_t * begin_transaction(qpzonedb_t *qpdb, dns_qpread_t *qprp, bool create) { dns_qp_t *qp = NULL; @@ -2460,14 +2460,14 @@ end_transaction(qpzonedb_t *qpdb, dns_qp_t *qp, bool create) { dns_qp_compact(qp, DNS_QPGC_MAYBE); dns_qpmulti_commit(qpdb->tree, &qp); } else { - dns_qpread_t *qprp = (dns_qpread_t*) qp; + dns_qpread_t *qprp = (dns_qpread_t *)qp; dns_qpread_destroy(qpdb->tree, qprp); } } static isc_result_t -findnodeintree(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name, bool create, - bool nsec3, dns_dbnode_t **nodep DNS__DB_FLARG) { +findnodeintree(qpzonedb_t *qpdb, dns_qp_t *qp, const dns_name_t *name, + bool create, bool nsec3, dns_dbnode_t **nodep DNS__DB_FLARG) { isc_result_t result; qpznode_t *node = NULL; dns_namespace_t nspace = nsec3 ? DNS_DBNAMESPACE_NSEC3 @@ -2547,7 +2547,8 @@ qpzone_findnode(dns_db_t *db, const dns_name_t *name, bool create, dns_qpread_t qpr = { 0 }; dns_qp_t *qp = begin_transaction(qpdb, &qpr, create); - isc_result_t result = findnodeintree(qpdb, qp, name, create, false, nodep DNS__DB_FLARG_PASS); + isc_result_t result = findnodeintree(qpdb, qp, name, create, false, + nodep DNS__DB_FLARG_PASS); end_transaction(qpdb, qp, create); @@ -2564,7 +2565,8 @@ qpzone_findnsec3node(dns_db_t *db, const dns_name_t *name, bool create, dns_qpread_t qpr = { 0 }; dns_qp_t *qp = begin_transaction(qpdb, &qpr, create); - isc_result_t result = findnodeintree(qpdb, qp, name, create, true, nodep DNS__DB_FLARG_PASS); + isc_result_t result = findnodeintree(qpdb, qp, name, create, true, + nodep DNS__DB_FLARG_PASS); end_transaction(qpdb, qp, create); @@ -4667,11 +4669,10 @@ qpzone_createiterator(dns_db_t *db, unsigned int options, */ static isc_result_t qpzone_addrdataset_inner(dns_db_t *db, dns_dbnode_t *dbnode, - dns_dbversion_t *dbversion, - isc_stdtime_t now ISC_ATTR_UNUSED, dns_rdataset_t *rdataset, - unsigned int options, - dns_rdataset_t *addedrdataset, - dns_qp_t *nsec) { + dns_dbversion_t *dbversion, + isc_stdtime_t now ISC_ATTR_UNUSED, + dns_rdataset_t *rdataset, unsigned int options, + dns_rdataset_t *addedrdataset, dns_qp_t *nsec) { isc_result_t result; qpzonedb_t *qpdb = (qpzonedb_t *)db; qpznode_t *node = (qpznode_t *)dbnode; @@ -4732,7 +4733,6 @@ qpzone_addrdataset_inner(dns_db_t *db, dns_dbnode_t *dbnode, newheader->resign_lsb = rdataset->resign & 0x1; } - /* * Add to the auxiliary NSEC tree if we're adding an NSEC record. */ @@ -5388,9 +5388,11 @@ qpzone_update_rdataset(qpzonedb_t *qpdb, qpz_version_t *version, dns_qp_t *qp, dns_rdataset_init(&ardataset); - is_nsec3 = (rds->type == dns_rdatatype_nsec3 || rds->covers == dns_rdatatype_nsec3); + is_nsec3 = (rds->type == dns_rdatatype_nsec3 || + rds->covers == dns_rdatatype_nsec3); - result = findnodeintree(qpdb, qp, name, true, is_nsec3, &node DNS__DB_FLARG_PASS); + result = findnodeintree(qpdb, qp, name, true, is_nsec3, + &node DNS__DB_FLARG_PASS); if (result != ISC_R_SUCCESS) { goto failure; @@ -5405,25 +5407,24 @@ qpzone_update_rdataset(qpzonedb_t *qpdb, qpz_version_t *version, dns_qp_t *qp, */ options = DNS_DBADD_MERGE | DNS_DBADD_EXACT | DNS_DBADD_EXACTTTL; - result = qpzone_addrdataset_inner((dns_db_t *)qpdb, node, - (dns_dbversion_t *)version, 0, - rds, options, - &ardataset, qp DNS__DB_FLARG_PASS); + result = qpzone_addrdataset_inner( + (dns_db_t *)qpdb, node, (dns_dbversion_t *)version, 0, + rds, options, &ardataset, qp DNS__DB_FLARG_PASS); break; case DNS_DIFFOP_DEL: case DNS_DIFFOP_DELRESIGN: options = DNS_DBSUB_EXACT | DNS_DBSUB_WANTOLD; - result = qpzone_subtractrdataset((dns_db_t *)qpdb, node, - (dns_dbversion_t *)version, - rds, options, - &ardataset DNS__DB_FLARG_PASS); + result = qpzone_subtractrdataset( + (dns_db_t *)qpdb, node, (dns_dbversion_t *)version, rds, + options, &ardataset DNS__DB_FLARG_PASS); break; default: UNREACHABLE(); } bool is_resign = rds->type == dns_rdatatype_rrsig && - (op == DNS_DIFFOP_DELRESIGN || op == DNS_DIFFOP_ADDRESIGN); + (op == DNS_DIFFOP_DELRESIGN || + op == DNS_DIFFOP_ADDRESIGN); if (result == ISC_R_SUCCESS && is_resign) { isc_stdtime_t resign; @@ -5448,19 +5449,21 @@ qpzone_update_callback(void *arg, const dns_name_t *name, dns_rdataset_t *rds, qpzonedb_t *qpdb = (qpzonedb_t *)ctx->base.db; qpz_version_t *version = (qpz_version_t *)ctx->base.ver; - return qpzone_update_rdataset(qpdb, version, ctx->qp, (dns_name_t *)name, rds, op); + return qpzone_update_rdataset(qpdb, version, ctx->qp, + (dns_name_t *)name, rds, op); } static isc_result_t -qpzone_beginupdate(dns_db_t *db, dns_dbversion_t *ver, dns_rdatacallbacks_t *callbacks) { +qpzone_beginupdate(dns_db_t *db, dns_dbversion_t *ver, + dns_rdatacallbacks_t *callbacks) { qpzonedb_t *qpdb = (qpzonedb_t *)db; REQUIRE(VALID_QPZONE(qpdb)); REQUIRE(ver != NULL); REQUIRE(DNS_CALLBACK_VALID(callbacks)); - qpzone_updatectx_t* ctx = isc_mem_get(qpdb->common.mctx, sizeof(*ctx)); - *ctx = (qpzone_updatectx_t) { + qpzone_updatectx_t *ctx = isc_mem_get(qpdb->common.mctx, sizeof(*ctx)); + *ctx = (qpzone_updatectx_t){ .base.db = db, .base.ver = ver, .base.warn = true, diff --git a/tests/dns/master_test.c b/tests/dns/master_test.c index 931f7017ca..9a36781486 100644 --- a/tests/dns/master_test.c +++ b/tests/dns/master_test.c @@ -65,8 +65,8 @@ static void rawdata_callback(dns_zone_t *zone, dns_masterrawheader_t *header); static isc_result_t -add_callback(void *arg, const dns_name_t *owner, - dns_rdataset_t *dataset, dns_diffop_t op DNS__DB_FLARG) { +add_callback(void *arg, const dns_name_t *owner, dns_rdataset_t *dataset, + dns_diffop_t op DNS__DB_FLARG) { char buf[BIGBUFLEN]; isc_buffer_t target; isc_result_t result; diff --git a/tests/dns/qpzone_test.c b/tests/dns/qpzone_test.c index 3d6016c779..5a369ec29e 100644 --- a/tests/dns/qpzone_test.c +++ b/tests/dns/qpzone_test.c @@ -51,19 +51,18 @@ /* * Macro that uses a for loop to execute a cleanup at the end of scope. */ -#define WITH_NEWVERSION(db, version_var, should_commit) \ - for (dns_dbversion_t *version_var = NULL, \ - *_tmp = ({ \ - isc_result_t _result = dns_db_newversion(db, &version_var); \ - assert_int_equal(_result, ISC_R_SUCCESS); \ - (dns_dbversion_t*)1; \ - }); \ - _tmp != NULL; \ - _tmp = ({ \ - dns_db_closeversion(db, &version_var, should_commit); \ - (dns_dbversion_t*)NULL; \ - })) - +#define WITH_NEWVERSION(db, version_var, should_commit) \ + for (dns_dbversion_t *version_var = NULL, *_tmp = ({ \ + isc_result_t _result = dns_db_newversion(db, \ + &version_var); \ + assert_int_equal(_result, ISC_R_SUCCESS); \ + (dns_dbversion_t *)1; \ + }); \ + _tmp != NULL; \ + _tmp = ({ \ + dns_db_closeversion(db, &version_var, should_commit); \ + (dns_dbversion_t *)NULL; \ + })) const char *ownercase_vectors[12][2] = { { @@ -116,41 +115,41 @@ const char *ownercase_vectors[12][2] = { } }; -static unsigned char example_org_data[] = { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'o', 'r', 'g', 0 }; +static unsigned char example_org_data[] = { 7, 'e', 'x', 'a', 'm', 'p', 'l', + 'e', 3, 'o', 'r', 'g', 0 }; static dns_name_t example_org_name = DNS_NAME_INITABSOLUTE(example_org_data); /* IPv6 test addresses */ static unsigned char aaaa_test_data[][16] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, /* ::1 */ - { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 } /* 2001:db8::2 */ + { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2 } /* 2001:db8::2 + */ }; /* RRSIG test signatures */ static unsigned char rrsig_signature1[64] = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40 + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, + 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, + 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40 }; static unsigned char rrsig_signature2[64] = { - 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, - 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, - 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80 + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, + 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80 }; /* RRSIG test structures */ static dns_rdata_rrsig_t rrsig_test_data1 = { - .common = { .rdtype = dns_rdatatype_rrsig, .rdclass = dns_rdataclass_in }, + .common = { .rdtype = dns_rdatatype_rrsig, + .rdclass = dns_rdataclass_in }, .covered = dns_rdatatype_a, .algorithm = DST_ALG_RSASHA256, .labels = 2, @@ -164,7 +163,8 @@ static dns_rdata_rrsig_t rrsig_test_data1 = { }; static dns_rdata_rrsig_t rrsig_test_data2 = { - .common = { .rdtype = dns_rdatatype_rrsig, .rdclass = dns_rdataclass_in }, + .common = { .rdtype = dns_rdatatype_rrsig, + .rdclass = dns_rdataclass_in }, .covered = dns_rdatatype_a, .algorithm = DST_ALG_RSASHA256, .labels = 2, @@ -281,7 +281,8 @@ apply_dns_update(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, dns_rdataset_init(&rdataset); dns_rdatalist_tordataset(&rdatalist, &rdataset); - isc_result_t callback_result = callbacks.update(callbacks.add_private, name, &rdataset, op); + isc_result_t callback_result = callbacks.update(callbacks.add_private, + name, &rdataset, op); assert_int_equal(result, ISC_R_SUCCESS); dns_rdataset_disassociate(&rdataset); @@ -404,35 +405,45 @@ ISC_RUN_TEST_IMPL(diffop_add_sub) { isc_result_t result; dns_db_t *db = NULL; - result = dns__qpzone_create(isc_g_mctx, &example_org_name, dns_dbtype_zone, - dns_rdataclass_in, 0, NULL, NULL, &db); + result = dns__qpzone_create(isc_g_mctx, &example_org_name, + dns_dbtype_zone, dns_rdataclass_in, 0, NULL, + NULL, &db); assert_int_equal(result, ISC_R_SUCCESS); assert_non_null(db); WITH_NEWVERSION(db, version, true) { - apply_dns_update(db, version, &example_org_name, dns_rdatatype_aaaa, - dns_rdataclass_in, 300, aaaa_test_data[0], 16, DNS_DIFFOP_ADD); + apply_dns_update(db, version, &example_org_name, + dns_rdatatype_aaaa, dns_rdataclass_in, 300, + aaaa_test_data[0], 16, DNS_DIFFOP_ADD); } WITH_NEWVERSION(db, version, true) { - result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_aaaa, - dns_rdataclass_in, 300, aaaa_test_data[1], 16, DNS_DIFFOP_ADD); + result = apply_dns_update(db, version, &example_org_name, + dns_rdatatype_aaaa, dns_rdataclass_in, + 300, aaaa_test_data[1], 16, + DNS_DIFFOP_ADD); assert_int_equal(result, ISC_R_SUCCESS); - verify_aaaa_records(db, version, &example_org_name, aaaa_test_data, 2, 300); + verify_aaaa_records(db, version, &example_org_name, + aaaa_test_data, 2, 300); } WITH_NEWVERSION(db, version, true) { - result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_aaaa, - dns_rdataclass_in, 300, aaaa_test_data[0], 16, DNS_DIFFOP_DEL); + result = apply_dns_update(db, version, &example_org_name, + dns_rdatatype_aaaa, dns_rdataclass_in, + 300, aaaa_test_data[0], 16, + DNS_DIFFOP_DEL); assert_int_equal(result, ISC_R_SUCCESS); - verify_aaaa_records(db, version, &example_org_name, &aaaa_test_data[1], 1, 300); + verify_aaaa_records(db, version, &example_org_name, + &aaaa_test_data[1], 1, 300); } WITH_NEWVERSION(db, version, false) { - result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_aaaa, - dns_rdataclass_in, 600, aaaa_test_data[0], 16, DNS_DIFFOP_ADD); + result = apply_dns_update(db, version, &example_org_name, + dns_rdatatype_aaaa, dns_rdataclass_in, + 600, aaaa_test_data[0], 16, + DNS_DIFFOP_ADD); assert_int_equal(result, DNS_R_NOTEXACT); } @@ -450,39 +461,52 @@ ISC_RUN_TEST_IMPL(diffop_addresign) { unsigned char rrsig_data1[512], rrsig_data2[512]; isc_buffer_init(&buffer1, rrsig_data1, sizeof(rrsig_data1)); - result = dns_rdata_fromstruct(&rdata1, dns_rdataclass_in, dns_rdatatype_rrsig, &rrsig_test_data1, &buffer1); + result = dns_rdata_fromstruct(&rdata1, dns_rdataclass_in, + dns_rdatatype_rrsig, &rrsig_test_data1, + &buffer1); assert_int_equal(result, ISC_R_SUCCESS); isc_buffer_init(&buffer2, rrsig_data2, sizeof(rrsig_data2)); - result = dns_rdata_fromstruct(&rdata2, dns_rdataclass_in, dns_rdatatype_rrsig, &rrsig_test_data2, &buffer2); + result = dns_rdata_fromstruct(&rdata2, dns_rdataclass_in, + dns_rdatatype_rrsig, &rrsig_test_data2, + &buffer2); assert_int_equal(result, ISC_R_SUCCESS); - result = dns__qpzone_create(isc_g_mctx, &example_org_name, dns_dbtype_zone, - dns_rdataclass_in, 0, NULL, NULL, &db); + result = dns__qpzone_create(isc_g_mctx, &example_org_name, + dns_dbtype_zone, dns_rdataclass_in, 0, NULL, + NULL, &db); assert_int_equal(result, ISC_R_SUCCESS); assert_non_null(db); WITH_NEWVERSION(db, version, true) { - result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_rrsig, - dns_rdataclass_in, 300, rdata1.data, rdata1.length, DNS_DIFFOP_ADDRESIGN); + result = apply_dns_update(db, version, &example_org_name, + dns_rdatatype_rrsig, + dns_rdataclass_in, 300, rdata1.data, + rdata1.length, DNS_DIFFOP_ADDRESIGN); assert_int_equal(result, ISC_R_SUCCESS); } WITH_NEWVERSION(db, version, true) { - result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_rrsig, - dns_rdataclass_in, 300, rdata2.data, rdata2.length, DNS_DIFFOP_ADDRESIGN); + result = apply_dns_update(db, version, &example_org_name, + dns_rdatatype_rrsig, + dns_rdataclass_in, 300, rdata2.data, + rdata2.length, DNS_DIFFOP_ADDRESIGN); assert_int_equal(result, ISC_R_SUCCESS); } WITH_NEWVERSION(db, version, true) { - result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_rrsig, - dns_rdataclass_in, 300, rdata1.data, rdata1.length, DNS_DIFFOP_DELRESIGN); + result = apply_dns_update(db, version, &example_org_name, + dns_rdatatype_rrsig, + dns_rdataclass_in, 300, rdata1.data, + rdata1.length, DNS_DIFFOP_DELRESIGN); assert_int_equal(result, ISC_R_SUCCESS); } WITH_NEWVERSION(db, version, true) { - result = apply_dns_update(db, version, &example_org_name, dns_rdatatype_rrsig, - dns_rdataclass_in, 300, rdata2.data, rdata2.length, DNS_DIFFOP_DELRESIGN); + result = apply_dns_update(db, version, &example_org_name, + dns_rdatatype_rrsig, + dns_rdataclass_in, 300, rdata2.data, + rdata2.length, DNS_DIFFOP_DELRESIGN); assert_int_equal(result, DNS_R_NXRRSET); }