Dump the signed zone in the text format at the end of dnssec-signzone

Instead of dumping the signed zone contents node by node during the
signing, dump the entire zone at the end.  This was already done for the
raw zone format, but it shows that the IO is better utilized when the
zone dump is done in one single write rather than in small chunks.

A side effect of dumping node by node was that all names were printed
relative to the zone origin rather than being grouped under different
$ORIGINs as would normally be the case when dumping a zone. Also, state
was not maintained from one node to the next regarding whether the CLASS
has already been printed, so it was always included with the first
record of each node.

Since dnssec-signzone uses the dns_master_style_explicittl text format
style, and is the only application that does so, we can revise that
style and add a new DNS_STYLEFLAG_CLASS_PERNAME flag to get the output
back to what it was before this change.
This commit is contained in:
Ondřej Surý
2023-01-12 16:36:43 +01:00
parent a2d773fb98
commit f5095e6c34
3 changed files with 39 additions and 109 deletions

View File

@@ -117,12 +117,6 @@ static int nsec_datatype = dns_rdatatype_nsec;
#define SOA_SERIAL_UNIXTIME 2
#define SOA_SERIAL_DATE 3
typedef struct signer_work swork_t;
struct signer_work {
dns_fixedname_t *fname;
dns_dbnode_t *node;
};
static dns_dnsseckeylist_t keylist;
static unsigned int keycount = 0;
static isc_rwlock_t keylist_lock;
@@ -190,9 +184,6 @@ static bool no_max_check = false;
UNLOCK(&statslock); \
}
static void
sign(void *arg);
/*%
* Store a copy of 'name' in 'fzonecut' and return a pointer to that copy.
*/
@@ -215,14 +206,7 @@ dumpnode(dns_name_t *name, dns_dbnode_t *node) {
isc_result_t result;
unsigned int bufsize = 4096;
if (outputformat != dns_masterformat_text) {
return;
}
if (!output_dnssec_only) {
result = dns_master_dumpnodetostream(mctx, gdb, gversion, node,
name, masterstyle, outfp);
check_result(result, "dns_master_dumpnodetostream");
return;
}
@@ -273,6 +257,17 @@ dumpnode(dns_name_t *name, dns_dbnode_t *node) {
dns_rdatasetiter_destroy(&iter);
}
static void
lock_and_dumpnode(dns_name_t *name, dns_dbnode_t *node) {
if (!output_dnssec_only) {
return;
}
LOCK(&namelock);
dumpnode(name, node);
UNLOCK(&namelock);
}
/*%
* Sign the given RRset with given key, and add the signature record to the
* given tuple.
@@ -1500,47 +1495,6 @@ cleanup:
return (result);
}
/*%
* Delete any RRSIG records at a node.
*/
static void
cleannode(dns_db_t *db, dns_dbversion_t *dbversion, dns_dbnode_t *node) {
dns_rdatasetiter_t *rdsiter = NULL;
dns_rdataset_t set;
isc_result_t result, dresult;
if (outputformat != dns_masterformat_text || !disable_zone_check) {
return;
}
dns_rdataset_init(&set);
result = dns_db_allrdatasets(db, node, dbversion, 0, 0, &rdsiter);
check_result(result, "dns_db_allrdatasets");
result = dns_rdatasetiter_first(rdsiter);
while (result == ISC_R_SUCCESS) {
bool destroy = false;
dns_rdatatype_t covers = 0;
dns_rdatasetiter_current(rdsiter, &set);
if (set.type == dns_rdatatype_rrsig) {
covers = set.covers;
destroy = true;
}
dns_rdataset_disassociate(&set);
result = dns_rdatasetiter_next(rdsiter);
if (destroy) {
dresult = dns_db_deleterdataset(db, node, dbversion,
dns_rdatatype_rrsig,
covers);
check_result(dresult, "dns_db_deleterdataset");
}
}
if (result != ISC_R_NOMORE) {
fatal("rdataset iteration failed: %s",
isc_result_totext(result));
}
dns_rdatasetiter_destroy(&rdsiter);
}
/*%
* Set up the iterator and global state before starting the tasks.
*/
@@ -1579,10 +1533,7 @@ signapex(void) {
result = dns_dbiterator_current(gdbiter, &node, name);
check_dns_dbiterator_current(result);
signname(node, name);
LOCK(&namelock);
dumpnode(name, node);
UNLOCK(&namelock);
cleannode(gdb, gversion, node);
dns_db_detachnode(gdb, &node);
result = dns_dbiterator_first(gdbiter);
if (result == ISC_R_NOMORE) {
@@ -1599,7 +1550,7 @@ signapex(void) {
*/
static void
assignwork(void *arg) {
dns_fixedname_t *fname = NULL;
dns_fixedname_t fname;
dns_name_t *name = NULL;
dns_dbnode_t *node = NULL;
dns_rdataset_t nsec;
@@ -1608,7 +1559,6 @@ assignwork(void *arg) {
static dns_name_t *zonecut = NULL; /* Protected by namelock. */
static dns_fixedname_t fzonecut; /* Protected by namelock. */
static unsigned int ended = 0; /* Protected by namelock. */
swork_t *swork = NULL;
UNUSED(arg);
@@ -1622,11 +1572,11 @@ assignwork(void *arg) {
if (ended == nloops) {
isc_loopmgr_shutdown(loopmgr);
}
goto unlock;
UNLOCK(&namelock);
return;
}
fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
name = dns_fixedname_initname(fname);
name = dns_fixedname_initname(&fname);
node = NULL;
found = false;
while (!found) {
@@ -1698,52 +1648,23 @@ assignwork(void *arg) {
if (ended == nloops) {
isc_loopmgr_shutdown(loopmgr);
}
isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
goto unlock;
UNLOCK(&namelock);
return;
}
swork = isc_mem_get(mctx, sizeof(*swork));
*swork = (swork_t){
.node = node,
.fname = fname,
};
unlock:
UNLOCK(&namelock);
if (swork != NULL) {
sign(swork);
}
}
/*%
* Write a node to the output file, and restart the worker task.
*/
static void
writenode(swork_t *swork) {
LOCK(&namelock);
dumpnode(dns_fixedname_name(swork->fname), swork->node);
UNLOCK(&namelock);
cleannode(gdb, gversion, swork->node);
dns_db_detachnode(gdb, &swork->node);
isc_mem_put(mctx, swork->fname, sizeof(dns_fixedname_t));
isc_mem_put(mctx, swork, sizeof(*swork));
signname(node, dns_fixedname_name(&fname));
/*%
* Write a node to the output file, and restart the worker task.
*/
lock_and_dumpnode(dns_fixedname_name(&fname), node);
dns_db_detachnode(gdb, &node);
isc_job_run(loopmgr, assignwork, NULL);
}
/*%
* Sign a database node.
*/
static void
sign(void *arg) {
swork_t *swork = (swork_t *)arg;
dns_fixedname_t *fname = swork->fname;
dns_dbnode_t *node = swork->node;
signname(node, dns_fixedname_name(fname));
swork->node = node;
swork->fname = fname;
writenode(swork);
}
/*%
* Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
*/
@@ -4039,7 +3960,7 @@ main(int argc, char *argv[]) {
}
}
if (outputformat != dns_masterformat_text) {
if (!output_dnssec_only) {
dns_masterrawheader_t header;
dns_master_initrawheader(&header);
if (rawversion == 0U) {
@@ -4051,7 +3972,7 @@ main(int argc, char *argv[]) {
result = dns_master_dumptostream(mctx, gdb, gversion,
masterstyle, outputformat,
&header, outfp);
check_result(result, "dns_master_dumptostream3");
check_result(result, "dns_master_dumptostream");
}
if (!output_stdout) {

View File

@@ -114,6 +114,12 @@ typedef struct dns_master_style dns_master_style_t;
/*% Print expired cache entries. */
#define DNS_STYLEFLAG_EXPIRED 0x200000000ULL
/*%
* If set concurrently with DNS_STYLEFLAG_OMIT_CLASS, the class will
* be included when printing a new name.
*/
#define DNS_STYLEFLAG_CLASS_PERNAME 0x400000000ULL
ISC_LANG_BEGINDECLS
/***

View File

@@ -151,9 +151,8 @@ const dns_master_style_t dns_master_style_full = {
const dns_master_style_t dns_master_style_explicitttl = {
DNS_STYLEFLAG_OMIT_OWNER | DNS_STYLEFLAG_OMIT_CLASS |
DNS_STYLEFLAG_REL_OWNER | DNS_STYLEFLAG_REL_DATA |
DNS_STYLEFLAG_COMMENT | DNS_STYLEFLAG_RRCOMMENT |
DNS_STYLEFLAG_MULTILINE,
DNS_STYLEFLAG_CLASS_PERNAME | DNS_STYLEFLAG_COMMENT |
DNS_STYLEFLAG_RRCOMMENT | DNS_STYLEFLAG_MULTILINE,
24,
32,
32,
@@ -1066,6 +1065,10 @@ dump_rdatasets_text(isc_mem_t *mctx, const dns_name_t *name,
ctx->neworigin = NULL;
}
if ((ctx->style.flags & DNS_STYLEFLAG_CLASS_PERNAME) != 0) {
ctx->class_printed = false;
}
again:
for (i = 0; itresult == ISC_R_SUCCESS && i < MAXSORT;
itresult = dns_rdatasetiter_next(rdsiter), i++)