2 * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
10 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
12 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
19 * Permission to use, copy, modify, and/or distribute this software for any
20 * purpose with or without fee is hereby granted, provided that the above
21 * copyright notice and this permission notice appear in all copies.
23 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
24 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
26 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
28 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
29 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 /* $Id: dnssec-signzone.c,v 1.204.94.5 2009/07/21 06:45:06 tbox Exp $ */
42 #include <isc/commandline.h>
43 #include <isc/entropy.h>
44 #include <isc/event.h>
48 #include <isc/mutex.h>
50 #include <isc/print.h>
51 #include <isc/random.h>
52 #include <isc/serial.h>
53 #include <isc/stdio.h>
54 #include <isc/string.h>
60 #include <dns/dbiterator.h>
62 #include <dns/dnssec.h>
64 #include <dns/fixedname.h>
65 #include <dns/keyvalues.h>
67 #include <dns/master.h>
68 #include <dns/masterdump.h>
70 #include <dns/rdata.h>
71 #include <dns/rdataset.h>
72 #include <dns/rdataclass.h>
73 #include <dns/rdatasetiter.h>
74 #include <dns/rdatastruct.h>
75 #include <dns/rdatatype.h>
76 #include <dns/result.h>
82 #include "dnssectool.h"
84 const char *program = "dnssec-signzone";
90 typedef struct signer_key_struct signer_key_t;
92 struct signer_key_struct {
94 isc_boolean_t issigningkey;
97 unsigned int position;
98 ISC_LINK(signer_key_t) link;
101 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
102 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
103 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
105 #define SOA_SERIAL_KEEP 0
106 #define SOA_SERIAL_INCREMENT 1
107 #define SOA_SERIAL_UNIXTIME 2
109 typedef struct signer_event sevent_t;
110 struct signer_event {
111 ISC_EVENT_COMMON(sevent_t);
112 dns_fixedname_t *fname;
116 static ISC_LIST(signer_key_t) keylist;
117 static unsigned int keycount = 0;
118 static isc_stdtime_t starttime = 0, endtime = 0, now;
119 static int cycle = -1;
120 static int jitter = 0;
121 static isc_boolean_t tryverify = ISC_FALSE;
122 static isc_boolean_t printstats = ISC_FALSE;
123 static isc_mem_t *mctx = NULL;
124 static isc_entropy_t *ectx = NULL;
125 static dns_ttl_t zonettl;
127 static char *tempfile = NULL;
128 static const dns_master_style_t *masterstyle;
129 static dns_masterformat_t inputformat = dns_masterformat_text;
130 static dns_masterformat_t outputformat = dns_masterformat_text;
131 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
132 static unsigned int nverified = 0, nverifyfailed = 0;
133 static const char *directory;
134 static isc_mutex_t namelock, statslock;
135 static isc_taskmgr_t *taskmgr = NULL;
136 static dns_db_t *gdb; /* The database */
137 static dns_dbversion_t *gversion; /* The database version */
138 static dns_dbiterator_t *gdbiter; /* The database iterator */
139 static dns_rdataclass_t gclass; /* The class */
140 static dns_name_t *gorigin; /* The database origin */
141 static isc_task_t *master = NULL;
142 static unsigned int ntasks = 0;
143 static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
144 static isc_boolean_t nokeys = ISC_FALSE;
145 static isc_boolean_t removefile = ISC_FALSE;
146 static isc_boolean_t generateds = ISC_FALSE;
147 static isc_boolean_t ignoreksk = ISC_FALSE;
148 static dns_name_t *dlv = NULL;
149 static dns_fixedname_t dlv_fixed;
150 static dns_master_style_t *dsstyle = NULL;
151 static unsigned int serialformat = SOA_SERIAL_KEEP;
153 #define INCSTAT(counter) \
157 UNLOCK(&statslock); \
161 sign(isc_task_t *task, isc_event_t *event);
165 set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
166 unsigned int shift, mask;
168 shift = 7 - (index % 8);
172 array[index / 8] |= mask;
174 array[index / 8] &= (~mask & 0xFF);
178 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
181 if (outputformat != dns_masterformat_text)
183 result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name,
185 check_result(result, "dns_master_dumpnodetostream");
188 static signer_key_t *
189 newkeystruct(dst_key_t *dstkey, isc_boolean_t signwithkey) {
192 key = isc_mem_get(mctx, sizeof(signer_key_t));
194 fatal("out of memory");
196 if ((dst_key_flags(dstkey) & DNS_KEYFLAG_KSK) != 0) {
197 key->issigningkey = signwithkey;
198 key->isksk = ISC_TRUE;
199 key->isdsk = ISC_FALSE;
201 key->issigningkey = signwithkey;
202 key->isksk = ISC_FALSE;
203 key->isdsk = ISC_TRUE;
205 key->position = keycount++;
206 ISC_LINK_INIT(key, link);
211 * Sign the given RRset with given key, and add the signature record to the
216 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
217 dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
220 isc_stdtime_t jendtime;
221 char keystr[KEY_FORMATSIZE];
222 dns_rdata_t trdata = DNS_RDATA_INIT;
223 unsigned char array[BUFSIZE];
225 dns_difftuple_t *tuple;
227 key_format(key, keystr, sizeof(keystr));
228 vbprintf(1, "\t%s %s\n", logmsg, keystr);
230 jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime;
231 isc_buffer_init(&b, array, sizeof(array));
232 result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
234 isc_entropy_stopcallbacksources(ectx);
235 if (result != ISC_R_SUCCESS) {
236 char keystr[KEY_FORMATSIZE];
237 key_format(key, keystr, sizeof(keystr));
238 fatal("dnskey '%s' failed to sign data: %s",
239 keystr, isc_result_totext(result));
244 result = dns_dnssec_verify(name, rdataset, key,
245 ISC_TRUE, mctx, &trdata);
246 if (result == ISC_R_SUCCESS) {
247 vbprintf(3, "\tsignature verified\n");
250 vbprintf(3, "\tsignature failed to verify\n");
251 INCSTAT(nverifyfailed);
256 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name, ttl, &trdata,
258 check_result(result, "dns_difftuple_create");
259 dns_diff_append(add, &tuple);
262 static inline isc_boolean_t
263 issigningkey(signer_key_t *key) {
264 return (key->issigningkey);
267 static inline isc_boolean_t
268 iszonekey(signer_key_t *key) {
269 return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
270 dst_key_iszonekey(key->key)));
274 * Finds the key that generated a RRSIG, if possible. First look at the keys
275 * that we've loaded already, and then see if there's a key on disk.
277 static signer_key_t *
278 keythatsigned(dns_rdata_rrsig_t *rrsig) {
280 dst_key_t *pubkey = NULL, *privkey = NULL;
283 key = ISC_LIST_HEAD(keylist);
284 while (key != NULL) {
285 if (rrsig->keyid == dst_key_id(key->key) &&
286 rrsig->algorithm == dst_key_alg(key->key) &&
287 dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
289 key = ISC_LIST_NEXT(key, link);
292 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
293 rrsig->algorithm, DST_TYPE_PUBLIC,
294 NULL, mctx, &pubkey);
295 if (result != ISC_R_SUCCESS)
298 result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
300 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
301 NULL, mctx, &privkey);
302 if (result == ISC_R_SUCCESS) {
303 dst_key_free(&pubkey);
304 key = newkeystruct(privkey, ISC_FALSE);
306 key = newkeystruct(pubkey, ISC_FALSE);
307 ISC_LIST_APPEND(keylist, key, link);
312 * Check to see if we expect to find a key at this name. If we see a RRSIG
313 * and can't find the signing key that we expect to find, we drop the rrsig.
314 * I'm not sure if this is completely correct, but it seems to work.
317 expecttofindkey(dns_name_t *name) {
318 unsigned int options = DNS_DBFIND_NOWILD;
319 dns_fixedname_t fname;
321 char namestr[DNS_NAME_FORMATSIZE];
323 dns_fixedname_init(&fname);
324 result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
325 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
331 case DNS_R_DELEGATION:
336 dns_name_format(name, namestr, sizeof(namestr));
337 fatal("failure looking for '%s DNSKEY' in database: %s",
338 namestr, isc_result_totext(result));
339 return (ISC_FALSE); /* removes a warning */
342 static inline isc_boolean_t
343 setverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key,
347 result = dns_dnssec_verify(name, set, key->key, ISC_FALSE, mctx, rrsig);
348 if (result == ISC_R_SUCCESS) {
352 INCSTAT(nverifyfailed);
358 * Signs a set. Goes through contortions to decide if each RRSIG should
359 * be dropped or retained, and then determines if any new SIGs need to
363 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
366 dns_rdataset_t sigset;
367 dns_rdata_t sigrdata = DNS_RDATA_INIT;
368 dns_rdata_rrsig_t rrsig;
371 isc_boolean_t nosigs = ISC_FALSE;
372 isc_boolean_t *wassignedby, *nowsignedby;
374 dns_difftuple_t *tuple;
377 char namestr[DNS_NAME_FORMATSIZE];
378 char typestr[TYPE_FORMATSIZE];
379 char sigstr[SIG_FORMATSIZE];
381 dns_name_format(name, namestr, sizeof(namestr));
382 type_format(set->type, typestr, sizeof(typestr));
384 ttl = ISC_MIN(set->ttl, endtime - starttime);
386 dns_rdataset_init(&sigset);
387 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
388 set->type, 0, &sigset, NULL);
389 if (result == ISC_R_NOTFOUND) {
390 result = ISC_R_SUCCESS;
393 if (result != ISC_R_SUCCESS)
394 fatal("failed while looking for '%s RRSIG %s': %s",
395 namestr, typestr, isc_result_totext(result));
397 vbprintf(1, "%s/%s:\n", namestr, typestr);
399 arraysize = keycount;
401 arraysize += dns_rdataset_count(&sigset);
402 wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
403 nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
404 if (wassignedby == NULL || nowsignedby == NULL)
405 fatal("out of memory");
407 for (i = 0; i < arraysize; i++)
408 wassignedby[i] = nowsignedby[i] = ISC_FALSE;
411 result = ISC_R_NOMORE;
413 result = dns_rdataset_first(&sigset);
415 while (result == ISC_R_SUCCESS) {
416 isc_boolean_t expired, future;
417 isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
419 dns_rdataset_current(&sigset, &sigrdata);
421 result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
422 check_result(result, "dns_rdata_tostruct");
424 future = isc_serial_lt(now, rrsig.timesigned);
426 key = keythatsigned(&rrsig);
427 sig_format(&rrsig, sigstr, sizeof(sigstr));
428 if (key != NULL && issigningkey(key))
429 expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
431 expired = isc_serial_gt(now, rrsig.timeexpire);
433 if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
434 /* rrsig is dropped and not replaced */
435 vbprintf(2, "\trrsig by %s dropped - "
436 "invalid validity period\n",
438 } else if (key == NULL && !future &&
439 expecttofindkey(&rrsig.signer))
441 /* rrsig is dropped and not replaced */
442 vbprintf(2, "\trrsig by %s dropped - "
443 "private dnskey not found\n",
445 } else if (key == NULL || future) {
446 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
447 expired ? "retained" : "dropped", sigstr);
450 } else if (issigningkey(key)) {
451 if (!expired && setverifies(name, set, key, &sigrdata))
453 vbprintf(2, "\trrsig by %s retained\n", sigstr);
455 wassignedby[key->position] = ISC_TRUE;
456 nowsignedby[key->position] = ISC_TRUE;
458 vbprintf(2, "\trrsig by %s dropped - %s\n",
460 expired ? "expired" :
462 wassignedby[key->position] = ISC_TRUE;
465 } else if (iszonekey(key)) {
466 if (!expired && setverifies(name, set, key, &sigrdata))
468 vbprintf(2, "\trrsig by %s retained\n", sigstr);
470 wassignedby[key->position] = ISC_TRUE;
471 nowsignedby[key->position] = ISC_TRUE;
473 vbprintf(2, "\trrsig by %s dropped - %s\n",
475 expired ? "expired" :
477 wassignedby[key->position] = ISC_TRUE;
479 } else if (!expired) {
480 vbprintf(2, "\trrsig by %s retained\n", sigstr);
483 vbprintf(2, "\trrsig by %s expired\n", sigstr);
487 nowsignedby[key->position] = ISC_TRUE;
489 if (sigset.ttl != ttl) {
490 vbprintf(2, "\tfixing ttl %s\n", sigstr);
492 result = dns_difftuple_create(mctx,
497 check_result(result, "dns_difftuple_create");
498 dns_diff_append(del, &tuple);
499 result = dns_difftuple_create(mctx,
504 check_result(result, "dns_difftuple_create");
505 dns_diff_append(add, &tuple);
509 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
512 check_result(result, "dns_difftuple_create");
513 dns_diff_append(del, &tuple);
520 signwithkey(name, set, key->key, ttl, add,
521 "resigning with dnskey");
522 nowsignedby[key->position] = ISC_TRUE;
525 dns_rdata_reset(&sigrdata);
526 dns_rdata_freestruct(&rrsig);
527 result = dns_rdataset_next(&sigset);
529 if (result == ISC_R_NOMORE)
530 result = ISC_R_SUCCESS;
532 check_result(result, "dns_rdataset_first/next");
533 if (dns_rdataset_isassociated(&sigset))
534 dns_rdataset_disassociate(&sigset);
536 for (key = ISC_LIST_HEAD(keylist);
538 key = ISC_LIST_NEXT(key, link))
540 if (nowsignedby[key->position])
543 if (!key->issigningkey)
545 if (!(ignoreksk || key->isdsk ||
547 set->type == dns_rdatatype_dnskey &&
548 dns_name_equal(name, gorigin))))
551 signwithkey(name, set, key->key, ttl, add,
552 "signing with dnskey");
555 isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
556 isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
560 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
567 isc_buffer_init(&b, filename, sizeof(filename));
568 if (directory != NULL) {
569 isc_buffer_putstr(&b, directory);
570 if (directory[strlen(directory) - 1] != '/')
571 isc_buffer_putstr(&b, "/");
573 isc_buffer_putstr(&b, prefix);
574 result = dns_name_tofilenametext(name, ISC_FALSE, &b);
575 check_result(result, "dns_name_tofilenametext()");
576 if (isc_buffer_availablelength(&b) == 0) {
577 char namestr[DNS_NAME_FORMATSIZE];
578 dns_name_format(name, namestr, sizeof(namestr));
579 fatal("name '%s' is too long", namestr);
581 isc_buffer_putuint8(&b, 0);
583 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
584 rdclass, 0, NULL, dbp);
585 check_result(result, "dns_db_create()");
587 result = dns_db_load(*dbp, filename);
588 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
593 * Loads the key set for a child zone, if there is one, and builds DS records.
596 loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
598 dns_dbversion_t *ver = NULL;
599 dns_dbnode_t *node = NULL;
601 dns_rdataset_t keyset;
603 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
605 dns_difftuple_t *tuple = NULL;
607 opendb("keyset-", name, gclass, &db);
609 return (ISC_R_NOTFOUND);
611 result = dns_db_findnode(db, name, ISC_FALSE, &node);
612 if (result != ISC_R_SUCCESS) {
614 return (DNS_R_BADDB);
616 dns_rdataset_init(&keyset);
617 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
619 if (result != ISC_R_SUCCESS) {
620 dns_db_detachnode(db, &node);
625 vbprintf(2, "found DNSKEY records\n");
627 result = dns_db_newversion(db, &ver);
628 check_result(result, "dns_db_newversion");
630 dns_diff_init(mctx, &diff);
632 for (result = dns_rdataset_first(&keyset);
633 result == ISC_R_SUCCESS;
634 result = dns_rdataset_next(&keyset))
636 dns_rdata_init(&key);
638 dns_rdataset_current(&keyset, &key);
639 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
641 check_result(result, "dns_ds_buildrdata");
643 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
645 check_result(result, "dns_difftuple_create");
646 dns_diff_append(&diff, &tuple);
648 dns_rdata_reset(&ds);
649 result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
651 check_result(result, "dns_ds_buildrdata");
653 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
655 check_result(result, "dns_difftuple_create");
656 dns_diff_append(&diff, &tuple);
658 result = dns_diff_apply(&diff, db, ver);
659 check_result(result, "dns_diff_apply");
660 dns_diff_clear(&diff);
662 dns_db_closeversion(db, &ver, ISC_TRUE);
664 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
666 check_result(result, "dns_db_findrdataset");
668 dns_rdataset_disassociate(&keyset);
669 dns_db_detachnode(db, &node);
675 nsec_setbit(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdatatype_t type,
679 dns_rdata_t rdata = DNS_RDATA_INIT;
680 dns_rdata_nsec_t nsec;
682 unsigned char bitmap[8192 + 512];
683 unsigned char nsecdata[8192 + 512 + DNS_NAME_MAXWIRE];
684 isc_boolean_t answer = ISC_FALSE;
685 unsigned int i, len, window;
688 result = dns_rdataset_first(rdataset);
689 check_result(result, "dns_rdataset_first()");
690 dns_rdataset_current(rdataset, &rdata);
691 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
692 check_result(result, "dns_rdata_tostruct");
694 INSIST(nsec.len <= sizeof(bitmap));
698 memset(bitmap, 0, sizeof(bitmap));
699 for (i = 0; i < nsec.len; i += len) {
700 INSIST(i + 2 <= nsec.len);
701 window = nsec.typebits[i];
702 len = nsec.typebits[i+1];
704 INSIST(len > 0 && len <= 32);
705 INSIST(i + len <= nsec.len);
706 memmove(&bitmap[window * 32 + 512], &nsec.typebits[i], len);
708 set_bit(bitmap + 512, type, val);
709 for (window = 0; window < 256; window++) {
710 for (octet = 31; octet >= 0; octet--)
711 if (bitmap[window * 32 + 512 + octet] != 0)
715 bitmap[newlen] = window;
716 bitmap[newlen + 1] = octet + 1;
721 memmove(&bitmap[newlen], &bitmap[window * 32 + 512], octet + 1);
724 if (newlen != nsec.len ||
725 memcmp(nsec.typebits, bitmap, newlen) != 0) {
726 dns_rdata_t newrdata = DNS_RDATA_INIT;
729 dns_difftuple_t *tuple = NULL;
731 dns_diff_init(mctx, &diff);
732 result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL, name,
733 rdataset->ttl, &rdata, &tuple);
734 check_result(result, "dns_difftuple_create");
735 dns_diff_append(&diff, &tuple);
737 nsec.typebits = bitmap;
739 isc_buffer_init(&b, nsecdata, sizeof(nsecdata));
740 result = dns_rdata_fromstruct(&newrdata, rdata.rdclass,
741 dns_rdatatype_nsec, &nsec,
743 check_result(result, "dns_rdata_fromstruct");
745 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
748 check_result(result, "dns_difftuple_create");
749 dns_diff_append(&diff, &tuple);
750 result = dns_diff_apply(&diff, gdb, gversion);
751 check_result(result, "dns_difftuple_apply");
752 dns_diff_clear(&diff);
755 dns_rdata_freestruct(&nsec);
760 delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
761 dns_rdataset_t nsset;
764 if (dns_name_equal(name, gorigin))
767 dns_rdataset_init(&nsset);
768 result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns,
770 if (dns_rdataset_isassociated(&nsset)) {
773 dns_rdataset_disassociate(&nsset);
776 return (ISC_TF(result == ISC_R_SUCCESS));
780 * Signs all records at a name. This mostly just signs each set individually,
781 * but also adds the RRSIG bit to any NSECs generated earlier, deals with
782 * parent/child KEY signatures, and handles other exceptional cases.
785 signname(dns_dbnode_t *node, dns_name_t *name) {
787 dns_rdataset_t rdataset;
788 dns_rdatasetiter_t *rdsiter;
789 isc_boolean_t isdelegation = ISC_FALSE;
790 isc_boolean_t hasds = ISC_FALSE;
791 isc_boolean_t changed = ISC_FALSE;
793 char namestr[DNS_NAME_FORMATSIZE];
794 isc_uint32_t nsttl = 0;
796 dns_name_format(name, namestr, sizeof(namestr));
799 * Determine if this is a delegation point.
801 if (delegation(name, node, &nsttl))
802 isdelegation = ISC_TRUE;
805 * If this is a delegation point, look for a DS set.
808 dns_rdataset_t dsset;
809 dns_rdataset_t sigdsset;
811 dns_rdataset_init(&dsset);
812 dns_rdataset_init(&sigdsset);
813 result = dns_db_findrdataset(gdb, node, gversion,
815 0, 0, &dsset, &sigdsset);
816 if (result == ISC_R_SUCCESS) {
817 dns_rdataset_disassociate(&dsset);
819 result = dns_db_deleterdataset(gdb, node,
823 check_result(result, "dns_db_deleterdataset");
828 result = loadds(name, nsttl, &dsset);
829 if (result == ISC_R_SUCCESS) {
830 result = dns_db_addrdataset(gdb, node,
833 check_result(result, "dns_db_addrdataset");
835 dns_rdataset_disassociate(&dsset);
836 if (dns_rdataset_isassociated(&sigdsset))
837 dns_rdataset_disassociate(&sigdsset);
838 } else if (dns_rdataset_isassociated(&sigdsset)) {
839 result = dns_db_deleterdataset(gdb, node,
843 check_result(result, "dns_db_deleterdataset");
844 dns_rdataset_disassociate(&sigdsset);
846 } else if (dns_rdataset_isassociated(&sigdsset))
847 dns_rdataset_disassociate(&sigdsset);
851 * Make sure that NSEC bits are appropriately set.
853 dns_rdataset_init(&rdataset);
854 RUNTIME_CHECK(dns_db_findrdataset(gdb, node, gversion,
855 dns_rdatatype_nsec, 0, 0, &rdataset,
856 NULL) == ISC_R_SUCCESS);
858 changed = nsec_setbit(name, &rdataset, dns_rdatatype_rrsig, 1);
860 dns_rdataset_disassociate(&rdataset);
861 RUNTIME_CHECK(dns_db_findrdataset(gdb, node, gversion,
862 dns_rdatatype_nsec, 0, 0,
864 NULL) == ISC_R_SUCCESS);
867 (void)nsec_setbit(name, &rdataset, dns_rdatatype_ds, 1);
869 (void)nsec_setbit(name, &rdataset, dns_rdatatype_ds, 0);
870 dns_rdataset_disassociate(&rdataset);
873 * Now iterate through the rdatasets.
875 dns_diff_init(mctx, &del);
876 dns_diff_init(mctx, &add);
878 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
879 check_result(result, "dns_db_allrdatasets()");
880 result = dns_rdatasetiter_first(rdsiter);
881 while (result == ISC_R_SUCCESS) {
882 dns_rdatasetiter_current(rdsiter, &rdataset);
884 /* If this is a RRSIG set, skip it. */
885 if (rdataset.type == dns_rdatatype_rrsig)
889 * If this name is a delegation point, skip all records
890 * except NSEC and DS sets. Otherwise check that there
894 if (rdataset.type != dns_rdatatype_nsec &&
895 rdataset.type != dns_rdatatype_ds)
897 } else if (rdataset.type == dns_rdatatype_ds) {
898 char namebuf[DNS_NAME_FORMATSIZE];
899 dns_name_format(name, namebuf, sizeof(namebuf));
900 fatal("'%s': found DS RRset without NS RRset\n",
904 signset(&del, &add, node, name, &rdataset);
907 dns_rdataset_disassociate(&rdataset);
908 result = dns_rdatasetiter_next(rdsiter);
910 if (result != ISC_R_NOMORE)
911 fatal("rdataset iteration for name '%s' failed: %s",
912 namestr, isc_result_totext(result));
914 dns_rdatasetiter_destroy(&rdsiter);
916 result = dns_diff_applysilently(&del, gdb, gversion);
917 if (result != ISC_R_SUCCESS)
918 fatal("failed to delete SIGs at node '%s': %s",
919 namestr, isc_result_totext(result));
921 result = dns_diff_applysilently(&add, gdb, gversion);
922 if (result != ISC_R_SUCCESS)
923 fatal("failed to add SIGs at node '%s': %s",
924 namestr, isc_result_totext(result));
926 dns_diff_clear(&del);
927 dns_diff_clear(&add);
930 static inline isc_boolean_t
931 active_node(dns_dbnode_t *node) {
932 dns_rdatasetiter_t *rdsiter = NULL;
933 dns_rdatasetiter_t *rdsiter2 = NULL;
934 isc_boolean_t active = ISC_FALSE;
936 dns_rdataset_t rdataset;
937 dns_rdatatype_t type;
938 dns_rdatatype_t covers;
941 dns_rdataset_init(&rdataset);
942 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
943 check_result(result, "dns_db_allrdatasets()");
944 result = dns_rdatasetiter_first(rdsiter);
945 while (result == ISC_R_SUCCESS) {
946 dns_rdatasetiter_current(rdsiter, &rdataset);
947 if (rdataset.type != dns_rdatatype_nsec &&
948 rdataset.type != dns_rdatatype_rrsig)
950 dns_rdataset_disassociate(&rdataset);
952 result = dns_rdatasetiter_next(rdsiter);
954 result = ISC_R_NOMORE;
956 if (result != ISC_R_NOMORE)
957 fatal("rdataset iteration failed: %s",
958 isc_result_totext(result));
962 * The node is empty of everything but NSEC / RRSIG records.
964 for (result = dns_rdatasetiter_first(rdsiter);
965 result == ISC_R_SUCCESS;
966 result = dns_rdatasetiter_next(rdsiter)) {
967 dns_rdatasetiter_current(rdsiter, &rdataset);
968 result = dns_db_deleterdataset(gdb, node, gversion,
971 check_result(result, "dns_db_deleterdataset()");
972 dns_rdataset_disassociate(&rdataset);
974 if (result != ISC_R_NOMORE)
975 fatal("rdataset iteration failed: %s",
976 isc_result_totext(result));
979 * Delete RRSIGs for types that no longer exist.
981 result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
982 check_result(result, "dns_db_allrdatasets()");
983 for (result = dns_rdatasetiter_first(rdsiter);
984 result == ISC_R_SUCCESS;
985 result = dns_rdatasetiter_next(rdsiter)) {
986 dns_rdatasetiter_current(rdsiter, &rdataset);
987 type = rdataset.type;
988 covers = rdataset.covers;
989 dns_rdataset_disassociate(&rdataset);
990 if (type != dns_rdatatype_rrsig)
993 for (result = dns_rdatasetiter_first(rdsiter2);
994 !found && result == ISC_R_SUCCESS;
995 result = dns_rdatasetiter_next(rdsiter2)) {
996 dns_rdatasetiter_current(rdsiter2, &rdataset);
997 if (rdataset.type == covers)
999 dns_rdataset_disassociate(&rdataset);
1002 if (result != ISC_R_NOMORE)
1003 fatal("rdataset iteration failed: %s",
1004 isc_result_totext(result));
1005 result = dns_db_deleterdataset(gdb, node,
1008 check_result(result,
1009 "dns_db_deleterdataset(rrsig)");
1010 } else if (result != ISC_R_NOMORE &&
1011 result != ISC_R_SUCCESS)
1012 fatal("rdataset iteration failed: %s",
1013 isc_result_totext(result));
1015 if (result != ISC_R_NOMORE)
1016 fatal("rdataset iteration failed: %s",
1017 isc_result_totext(result));
1018 dns_rdatasetiter_destroy(&rdsiter2);
1020 dns_rdatasetiter_destroy(&rdsiter);
1026 * Extracts the TTL from the SOA.
1030 dns_rdataset_t soaset;
1031 dns_fixedname_t fname;
1033 isc_result_t result;
1035 dns_rdata_t rdata = DNS_RDATA_INIT;
1036 dns_rdata_soa_t soa;
1038 dns_fixedname_init(&fname);
1039 name = dns_fixedname_name(&fname);
1040 dns_rdataset_init(&soaset);
1041 result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1042 0, 0, NULL, name, &soaset, NULL);
1043 if (result != ISC_R_SUCCESS)
1044 fatal("failed to find an SOA at the zone apex: %s",
1045 isc_result_totext(result));
1047 result = dns_rdataset_first(&soaset);
1048 check_result(result, "dns_rdataset_first");
1049 dns_rdataset_current(&soaset, &rdata);
1050 result = dns_rdata_tostruct(&rdata, &soa, NULL);
1051 check_result(result, "dns_rdata_tostruct");
1053 dns_rdataset_disassociate(&soaset);
1058 * Increment (or set if nonzero) the SOA serial
1061 setsoaserial(isc_uint32_t serial) {
1062 isc_result_t result;
1063 dns_dbnode_t *node = NULL;
1064 dns_rdataset_t rdataset;
1065 dns_rdata_t rdata = DNS_RDATA_INIT;
1066 isc_uint32_t old_serial, new_serial;
1068 result = dns_db_getoriginnode(gdb, &node);
1069 if (result != ISC_R_SUCCESS)
1072 dns_rdataset_init(&rdataset);
1074 result = dns_db_findrdataset(gdb, node, gversion,
1075 dns_rdatatype_soa, 0,
1076 0, &rdataset, NULL);
1077 if (result != ISC_R_SUCCESS)
1080 result = dns_rdataset_first(&rdataset);
1081 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1083 dns_rdataset_current(&rdataset, &rdata);
1085 old_serial = dns_soa_getserial(&rdata);
1088 /* Set SOA serial to the value provided. */
1089 new_serial = serial;
1091 /* Increment SOA serial using RFC 1982 arithmetics */
1092 new_serial = (old_serial + 1) & 0xFFFFFFFF;
1093 if (new_serial == 0)
1097 /* If the new serial is not likely to cause a zone transfer
1098 * (a/ixfr) from servers having the old serial, warn the user.
1100 * RFC1982 section 7 defines the maximum increment to be
1101 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1102 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1104 if (new_serial == old_serial ||
1105 (new_serial - old_serial) > 0x7fffffffU)
1106 fprintf(stderr, "%s: warning: Serial number not advanced, "
1107 "zone may not transfer\n", program);
1109 dns_soa_setserial(new_serial, &rdata);
1111 result = dns_db_deleterdataset(gdb, node, gversion,
1112 dns_rdatatype_soa, 0);
1113 check_result(result, "dns_db_deleterdataset");
1114 if (result != ISC_R_SUCCESS)
1117 result = dns_db_addrdataset(gdb, node, gversion,
1118 0, &rdataset, 0, NULL);
1119 check_result(result, "dns_db_addrdataset");
1120 if (result != ISC_R_SUCCESS)
1124 dns_rdataset_disassociate(&rdataset);
1126 dns_db_detachnode(gdb, &node);
1127 dns_rdata_reset(&rdata);
1133 * Delete any RRSIG records at a node.
1136 cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
1137 dns_rdatasetiter_t *rdsiter = NULL;
1139 isc_result_t result, dresult;
1141 if (outputformat != dns_masterformat_text)
1144 dns_rdataset_init(&set);
1145 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
1146 check_result(result, "dns_db_allrdatasets");
1147 result = dns_rdatasetiter_first(rdsiter);
1148 while (result == ISC_R_SUCCESS) {
1149 isc_boolean_t destroy = ISC_FALSE;
1150 dns_rdatatype_t covers = 0;
1151 dns_rdatasetiter_current(rdsiter, &set);
1152 if (set.type == dns_rdatatype_rrsig) {
1153 covers = set.covers;
1156 dns_rdataset_disassociate(&set);
1157 result = dns_rdatasetiter_next(rdsiter);
1159 dresult = dns_db_deleterdataset(db, node, version,
1160 dns_rdatatype_rrsig,
1162 check_result(dresult, "dns_db_deleterdataset");
1165 if (result != ISC_R_NOMORE)
1166 fatal("rdataset iteration failed: %s",
1167 isc_result_totext(result));
1168 dns_rdatasetiter_destroy(&rdsiter);
1172 * Set up the iterator and global state before starting the tasks.
1176 isc_result_t result;
1179 result = dns_db_createiterator(gdb, ISC_FALSE, &gdbiter);
1180 check_result(result, "dns_db_createiterator()");
1182 result = dns_dbiterator_first(gdbiter);
1183 check_result(result, "dns_dbiterator_first()");
1187 * Clean up the iterator and global state after the tasks complete.
1191 dns_dbiterator_destroy(&gdbiter);
1195 * Sign the apex of the zone.
1199 dns_dbnode_t *node = NULL;
1200 dns_fixedname_t fixed;
1202 isc_result_t result;
1204 dns_fixedname_init(&fixed);
1205 name = dns_fixedname_name(&fixed);
1206 result = dns_dbiterator_current(gdbiter, &node, name);
1207 check_result(result, "dns_dbiterator_current()");
1208 signname(node, name);
1209 dumpnode(name, node);
1210 cleannode(gdb, gversion, node);
1211 dns_db_detachnode(gdb, &node);
1212 result = dns_dbiterator_next(gdbiter);
1213 if (result == ISC_R_NOMORE)
1214 finished = ISC_TRUE;
1215 else if (result != ISC_R_SUCCESS)
1216 fatal("failure iterating database: %s",
1217 isc_result_totext(result));
1221 * Assigns a node to a worker thread. This is protected by the master task's
1225 assignwork(isc_task_t *task, isc_task_t *worker) {
1226 dns_fixedname_t *fname;
1230 dns_rdataset_t nsec;
1231 isc_boolean_t found;
1232 isc_result_t result;
1233 static unsigned int ended = 0; /* Protected by namelock. */
1241 if (ended == ntasks) {
1242 isc_task_detach(&task);
1248 fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1250 fatal("out of memory");
1251 dns_fixedname_init(fname);
1252 name = dns_fixedname_name(fname);
1256 result = dns_dbiterator_current(gdbiter, &node, name);
1257 if (result != ISC_R_SUCCESS)
1258 fatal("failure iterating database: %s",
1259 isc_result_totext(result));
1260 dns_rdataset_init(&nsec);
1261 result = dns_db_findrdataset(gdb, node, gversion,
1262 dns_rdatatype_nsec, 0, 0,
1264 if (result == ISC_R_SUCCESS)
1267 dumpnode(name, node);
1268 if (dns_rdataset_isassociated(&nsec))
1269 dns_rdataset_disassociate(&nsec);
1271 dns_db_detachnode(gdb, &node);
1273 result = dns_dbiterator_next(gdbiter);
1274 if (result == ISC_R_NOMORE) {
1275 finished = ISC_TRUE;
1277 } else if (result != ISC_R_SUCCESS)
1278 fatal("failure iterating database: %s",
1279 isc_result_totext(result));
1283 if (ended == ntasks) {
1284 isc_task_detach(&task);
1287 isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1290 sevent = (sevent_t *)
1291 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1292 sign, NULL, sizeof(sevent_t));
1294 fatal("failed to allocate event\n");
1296 sevent->node = node;
1297 sevent->fname = fname;
1298 isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1304 * Start a worker task
1307 startworker(isc_task_t *task, isc_event_t *event) {
1310 worker = (isc_task_t *)event->ev_arg;
1311 assignwork(task, worker);
1312 isc_event_free(&event);
1316 * Write a node to the output file, and restart the worker task.
1319 writenode(isc_task_t *task, isc_event_t *event) {
1321 sevent_t *sevent = (sevent_t *)event;
1323 worker = (isc_task_t *)event->ev_sender;
1324 dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1325 cleannode(gdb, gversion, sevent->node);
1326 dns_db_detachnode(gdb, &sevent->node);
1327 isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1328 assignwork(task, worker);
1329 isc_event_free(&event);
1333 * Sign a database node.
1336 sign(isc_task_t *task, isc_event_t *event) {
1337 dns_fixedname_t *fname;
1339 sevent_t *sevent, *wevent;
1341 sevent = (sevent_t *)event;
1342 node = sevent->node;
1343 fname = sevent->fname;
1344 isc_event_free(&event);
1346 signname(node, dns_fixedname_name(fname));
1347 wevent = (sevent_t *)
1348 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1349 writenode, NULL, sizeof(sevent_t));
1351 fatal("failed to allocate event\n");
1352 wevent->node = node;
1353 wevent->fname = fname;
1354 isc_task_send(master, ISC_EVENT_PTR(&wevent));
1358 * Generate NSEC records for the zone.
1362 dns_dbiterator_t *dbiter = NULL;
1363 dns_dbnode_t *node = NULL, *nextnode = NULL;
1364 dns_fixedname_t fname, fnextname, fzonecut;
1365 dns_name_t *name, *nextname, *zonecut;
1366 isc_boolean_t done = ISC_FALSE;
1367 isc_result_t result;
1369 dns_fixedname_init(&fname);
1370 name = dns_fixedname_name(&fname);
1371 dns_fixedname_init(&fnextname);
1372 nextname = dns_fixedname_name(&fnextname);
1373 dns_fixedname_init(&fzonecut);
1376 result = dns_db_createiterator(gdb, ISC_FALSE, &dbiter);
1377 check_result(result, "dns_db_createiterator()");
1379 result = dns_dbiterator_first(dbiter);
1380 check_result(result, "dns_dbiterator_first()");
1383 dns_dbiterator_current(dbiter, &node, name);
1384 if (delegation(name, node, NULL)) {
1385 zonecut = dns_fixedname_name(&fzonecut);
1386 dns_name_copy(name, zonecut, NULL);
1388 result = dns_dbiterator_next(dbiter);
1390 while (result == ISC_R_SUCCESS) {
1391 isc_boolean_t active = ISC_FALSE;
1392 result = dns_dbiterator_current(dbiter, &nextnode,
1394 if (result != ISC_R_SUCCESS)
1396 active = active_node(nextnode);
1398 dns_db_detachnode(gdb, &nextnode);
1399 result = dns_dbiterator_next(dbiter);
1402 if (!dns_name_issubdomain(nextname, gorigin) ||
1404 dns_name_issubdomain(nextname, zonecut)))
1406 dns_db_detachnode(gdb, &nextnode);
1407 result = dns_dbiterator_next(dbiter);
1410 dns_db_detachnode(gdb, &nextnode);
1413 if (result == ISC_R_NOMORE) {
1414 dns_name_clone(gorigin, nextname);
1416 } else if (result != ISC_R_SUCCESS)
1417 fatal("iterating through the database failed: %s",
1418 isc_result_totext(result));
1419 result = dns_nsec_build(gdb, gversion, node, nextname,
1421 check_result(result, "dns_nsec_build()");
1422 dns_db_detachnode(gdb, &node);
1425 dns_dbiterator_destroy(&dbiter);
1429 * Load the zone file from disk
1432 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
1435 dns_fixedname_t fname;
1437 isc_result_t result;
1439 len = strlen(origin);
1440 isc_buffer_init(&b, origin, len);
1441 isc_buffer_add(&b, len);
1443 dns_fixedname_init(&fname);
1444 name = dns_fixedname_name(&fname);
1445 result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
1446 if (result != ISC_R_SUCCESS)
1447 fatal("failed converting name '%s' to dns format: %s",
1448 origin, isc_result_totext(result));
1450 result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
1451 rdclass, 0, NULL, db);
1452 check_result(result, "dns_db_create()");
1454 result = dns_db_load2(*db, file, inputformat);
1455 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
1456 fatal("failed loading zone from '%s': %s",
1457 file, isc_result_totext(result));
1461 * Finds all public zone keys in the zone, and attempts to load the
1462 * private keys from disk.
1465 loadzonekeys(dns_db_t *db) {
1467 dns_dbversion_t *currentversion;
1468 isc_result_t result;
1469 dst_key_t *keys[20];
1470 unsigned int nkeys, i;
1472 currentversion = NULL;
1473 dns_db_currentversion(db, ¤tversion);
1476 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
1477 if (result != ISC_R_SUCCESS)
1478 fatal("failed to find the zone's origin: %s",
1479 isc_result_totext(result));
1481 result = dns_dnssec_findzonekeys(db, currentversion, node, gorigin,
1482 mctx, 20, keys, &nkeys);
1483 if (result == ISC_R_NOTFOUND)
1484 result = ISC_R_SUCCESS;
1485 if (result != ISC_R_SUCCESS)
1486 fatal("failed to find the zone keys: %s",
1487 isc_result_totext(result));
1489 for (i = 0; i < nkeys; i++) {
1492 key = newkeystruct(keys[i], dst_key_isprivate(keys[i]));
1493 ISC_LIST_APPEND(keylist, key, link);
1495 dns_db_detachnode(db, &node);
1496 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
1500 * Finds all public zone keys in the zone.
1503 loadzonepubkeys(dns_db_t *db) {
1504 dns_dbversion_t *currentversion = NULL;
1505 dns_dbnode_t *node = NULL;
1506 dns_rdataset_t rdataset;
1507 dns_rdata_t rdata = DNS_RDATA_INIT;
1510 isc_result_t result;
1512 dns_db_currentversion(db, ¤tversion);
1514 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
1515 if (result != ISC_R_SUCCESS)
1516 fatal("failed to find the zone's origin: %s",
1517 isc_result_totext(result));
1519 dns_rdataset_init(&rdataset);
1520 result = dns_db_findrdataset(db, node, currentversion,
1521 dns_rdatatype_dnskey, 0, 0, &rdataset, NULL);
1522 if (result != ISC_R_SUCCESS)
1523 fatal("failed to find keys at the zone apex: %s",
1524 isc_result_totext(result));
1525 result = dns_rdataset_first(&rdataset);
1526 check_result(result, "dns_rdataset_first");
1527 while (result == ISC_R_SUCCESS) {
1529 dns_rdata_reset(&rdata);
1530 dns_rdataset_current(&rdataset, &rdata);
1531 result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
1533 if (result != ISC_R_SUCCESS)
1535 if (!dst_key_iszonekey(pubkey)) {
1536 dst_key_free(&pubkey);
1540 key = newkeystruct(pubkey, ISC_FALSE);
1541 ISC_LIST_APPEND(keylist, key, link);
1543 result = dns_rdataset_next(&rdataset);
1545 dns_rdataset_disassociate(&rdataset);
1546 dns_db_detachnode(db, &node);
1547 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
1551 warnifallksk(dns_db_t *db) {
1552 dns_dbversion_t *currentversion = NULL;
1553 dns_dbnode_t *node = NULL;
1554 dns_rdataset_t rdataset;
1555 dns_rdata_t rdata = DNS_RDATA_INIT;
1556 isc_result_t result;
1557 dns_rdata_key_t key;
1558 isc_boolean_t have_non_ksk = ISC_FALSE;
1560 dns_db_currentversion(db, ¤tversion);
1562 result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
1563 if (result != ISC_R_SUCCESS)
1564 fatal("failed to find the zone's origin: %s",
1565 isc_result_totext(result));
1567 dns_rdataset_init(&rdataset);
1568 result = dns_db_findrdataset(db, node, currentversion,
1569 dns_rdatatype_dnskey, 0, 0, &rdataset, NULL);
1570 if (result != ISC_R_SUCCESS)
1571 fatal("failed to find keys at the zone apex: %s",
1572 isc_result_totext(result));
1573 result = dns_rdataset_first(&rdataset);
1574 check_result(result, "dns_rdataset_first");
1575 while (result == ISC_R_SUCCESS) {
1576 dns_rdata_reset(&rdata);
1577 dns_rdataset_current(&rdataset, &rdata);
1578 result = dns_rdata_tostruct(&rdata, &key, NULL);
1579 check_result(result, "dns_rdata_tostruct");
1580 if ((key.flags & DNS_KEYFLAG_KSK) == 0) {
1581 have_non_ksk = ISC_TRUE;
1582 result = ISC_R_NOMORE;
1584 result = dns_rdataset_next(&rdataset);
1586 dns_rdataset_disassociate(&rdataset);
1587 dns_db_detachnode(db, &node);
1588 dns_db_closeversion(db, ¤tversion, ISC_FALSE);
1589 if (!have_non_ksk && !ignoreksk)
1590 fprintf(stderr, "%s: warning: No non-KSK dnskey found. "
1591 "Supply non-KSK dnskey or use '-z'.\n",
1596 writeset(const char *prefix, dns_rdatatype_t type) {
1598 char namestr[DNS_NAME_FORMATSIZE];
1599 dns_db_t *db = NULL;
1600 dns_dbversion_t *version = NULL;
1602 dns_difftuple_t *tuple = NULL;
1603 dns_fixedname_t fixed;
1605 dns_rdata_t rdata, ds;
1606 isc_boolean_t have_ksk = ISC_FALSE;
1607 isc_boolean_t have_non_ksk = ISC_FALSE;
1609 isc_buffer_t namebuf;
1611 isc_result_t result;
1613 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
1614 unsigned char keybuf[DST_KEY_MAXSIZE];
1615 unsigned int filenamelen;
1616 const dns_master_style_t *style =
1617 (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
1619 isc_buffer_init(&namebuf, namestr, sizeof(namestr));
1620 result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
1621 check_result(result, "dns_name_tofilenametext");
1622 isc_buffer_putuint8(&namebuf, 0);
1623 filenamelen = strlen(prefix) + strlen(namestr);
1624 if (directory != NULL)
1625 filenamelen += strlen(directory) + 1;
1626 filename = isc_mem_get(mctx, filenamelen + 1);
1627 if (filename == NULL)
1628 fatal("out of memory");
1629 if (directory != NULL)
1630 sprintf(filename, "%s/", directory);
1633 strcat(filename, prefix);
1634 strcat(filename, namestr);
1636 dns_diff_init(mctx, &diff);
1638 for (key = ISC_LIST_HEAD(keylist);
1640 key = ISC_LIST_NEXT(key, link))
1642 have_non_ksk = ISC_TRUE;
1646 for (key = ISC_LIST_HEAD(keylist);
1648 key = ISC_LIST_NEXT(key, link))
1650 have_ksk = ISC_TRUE;
1654 if (type == dns_rdatatype_dlv) {
1656 unsigned int labels;
1658 dns_name_init(&tname, NULL);
1659 dns_fixedname_init(&fixed);
1660 name = dns_fixedname_name(&fixed);
1661 labels = dns_name_countlabels(gorigin);
1662 dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
1663 result = dns_name_concatenate(&tname, dlv, name, NULL);
1664 check_result(result, "dns_name_concatenate");
1668 for (key = ISC_LIST_HEAD(keylist);
1670 key = ISC_LIST_NEXT(key, link))
1672 if (have_ksk && have_non_ksk && !key->isksk)
1674 dns_rdata_init(&rdata);
1675 dns_rdata_init(&ds);
1676 isc_buffer_init(&b, keybuf, sizeof(keybuf));
1677 result = dst_key_todns(key->key, &b);
1678 check_result(result, "dst_key_todns");
1679 isc_buffer_usedregion(&b, &r);
1680 dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
1681 if (type != dns_rdatatype_dnskey) {
1682 result = dns_ds_buildrdata(gorigin, &rdata,
1685 check_result(result, "dns_ds_buildrdata");
1686 if (type == dns_rdatatype_dlv)
1687 ds.type = dns_rdatatype_dlv;
1688 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
1689 name, 0, &ds, &tuple);
1690 check_result(result, "dns_difftuple_create");
1691 dns_diff_append(&diff, &tuple);
1693 dns_rdata_reset(&ds);
1694 result = dns_ds_buildrdata(gorigin, &rdata,
1695 DNS_DSDIGEST_SHA256,
1697 check_result(result, "dns_ds_buildrdata");
1698 if (type == dns_rdatatype_dlv)
1699 ds.type = dns_rdatatype_dlv;
1700 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
1701 name, 0, &ds, &tuple);
1704 result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
1707 check_result(result, "dns_difftuple_create");
1708 dns_diff_append(&diff, &tuple);
1711 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
1712 gclass, 0, NULL, &db);
1713 check_result(result, "dns_db_create");
1715 result = dns_db_newversion(db, &version);
1716 check_result(result, "dns_db_newversion");
1718 result = dns_diff_apply(&diff, db, version);
1719 check_result(result, "dns_diff_apply");
1720 dns_diff_clear(&diff);
1722 result = dns_master_dump(mctx, db, version, style, filename);
1723 check_result(result, "dns_master_dump");
1725 isc_mem_put(mctx, filename, filenamelen + 1);
1727 dns_db_closeversion(db, &version, ISC_FALSE);
1732 print_time(FILE *fp) {
1735 if (outputformat != dns_masterformat_text)
1738 currenttime = time(NULL);
1739 fprintf(fp, "; File written on %s", ctime(¤ttime));
1743 print_version(FILE *fp) {
1744 if (outputformat != dns_masterformat_text)
1747 fprintf(fp, "; dnssec_signzone version " VERSION "\n");
1752 fprintf(stderr, "Usage:\n");
1753 fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
1755 fprintf(stderr, "\n");
1757 fprintf(stderr, "Version: %s\n", VERSION);
1759 fprintf(stderr, "Options: (default value in parenthesis) \n");
1760 fprintf(stderr, "\t-c class (IN)\n");
1761 fprintf(stderr, "\t-d directory\n");
1762 fprintf(stderr, "\t\tdirectory to find keyset files (.)\n");
1763 fprintf(stderr, "\t-g:\t");
1764 fprintf(stderr, "generate DS records from keyset files\n");
1765 fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
1766 fprintf(stderr, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n");
1767 fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
1768 fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now "
1769 "(now + 30 days)\n");
1770 fprintf(stderr, "\t-i interval:\n");
1771 fprintf(stderr, "\t\tcycle interval - resign "
1772 "if < interval from end ( (end-start)/4 )\n");
1773 fprintf(stderr, "\t-j jitter:\n");
1774 fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
1775 fprintf(stderr, "\t-v debuglevel (0)\n");
1776 fprintf(stderr, "\t-o origin:\n");
1777 fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
1778 fprintf(stderr, "\t-f outfile:\n");
1779 fprintf(stderr, "\t\tfile the signed zone is written in "
1780 "(zonefile + .signed)\n");
1781 fprintf(stderr, "\t-I format:\n");
1782 fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
1783 fprintf(stderr, "\t-O format:\n");
1784 fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
1785 fprintf(stderr, "\t-N format:\n");
1786 fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
1787 fprintf(stderr, "\t-r randomdev:\n");
1788 fprintf(stderr, "\t\ta file containing random data\n");
1789 fprintf(stderr, "\t-a:\t");
1790 fprintf(stderr, "verify generated signatures\n");
1791 fprintf(stderr, "\t-p:\t");
1792 fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
1793 fprintf(stderr, "\t-t:\t");
1794 fprintf(stderr, "print statistics\n");
1795 fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
1796 fprintf(stderr, "\t-k key_signing_key\n");
1797 fprintf(stderr, "\t-l lookasidezone\n");
1798 fprintf(stderr, "\t-z:\t");
1799 fprintf(stderr, "ignore KSK flag in DNSKEYs");
1801 fprintf(stderr, "\n");
1803 fprintf(stderr, "Signing Keys: ");
1804 fprintf(stderr, "(default: all zone keys that have private keys)\n");
1805 fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
1810 removetempfile(void) {
1812 isc_file_remove(tempfile);
1816 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish) {
1817 isc_uint64_t runtime_us; /* Runtime in microseconds */
1818 isc_uint64_t runtime_ms; /* Runtime in milliseconds */
1819 isc_uint64_t sig_ms; /* Signatures per millisecond */
1821 runtime_us = isc_time_microdiff(timer_finish, timer_start);
1823 printf("Signatures generated: %10d\n", nsigned);
1824 printf("Signatures retained: %10d\n", nretained);
1825 printf("Signatures dropped: %10d\n", ndropped);
1826 printf("Signatures successfully verified: %10d\n", nverified);
1827 printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed);
1828 runtime_ms = runtime_us / 1000;
1829 printf("Runtime in seconds: %7u.%03u\n",
1830 (unsigned int) (runtime_ms / 1000),
1831 (unsigned int) (runtime_ms % 1000));
1832 if (runtime_us > 0) {
1833 sig_ms = ((isc_uint64_t)nsigned * 1000000000) / runtime_us;
1834 printf("Signatures per second: %7u.%03u\n",
1835 (unsigned int) sig_ms / 1000,
1836 (unsigned int) sig_ms % 1000);
1841 main(int argc, char *argv[]) {
1843 char *startstr = NULL, *endstr = NULL, *classname = NULL;
1844 char *origin = NULL, *file = NULL, *output = NULL;
1845 char *inputformatstr = NULL, *outputformatstr = NULL;
1846 char *serialformatstr = NULL;
1847 char *dskeyfile[MAXDSKEYS];
1850 isc_time_t timer_start, timer_finish;
1852 isc_result_t result;
1853 isc_log_t *log = NULL;
1854 isc_boolean_t pseudorandom = ISC_FALSE;
1855 unsigned int eflags;
1856 isc_boolean_t free_output = ISC_FALSE;
1858 dns_rdataclass_t rdclass;
1859 isc_task_t **tasks = NULL;
1863 masterstyle = &dns_master_style_explicitttl;
1865 check_result(isc_app_start(), "isc_app_start");
1867 result = isc_mem_create(0, 0, &mctx);
1868 if (result != ISC_R_SUCCESS)
1869 fatal("out of memory");
1871 dns_result_register();
1873 isc_commandline_errprint = ISC_FALSE;
1875 while ((ch = isc_commandline_parse(argc, argv,
1876 "ac:d:e:f:ghi:I:j:k:l:n:N:o:O:pr:s:Stv:z"))
1880 tryverify = ISC_TRUE;
1884 classname = isc_commandline_argument;
1888 directory = isc_commandline_argument;
1892 endstr = isc_commandline_argument;
1896 output = isc_commandline_argument;
1900 generateds = ISC_TRUE;
1904 if (isc_commandline_option != '?')
1905 fprintf(stderr, "%s: invalid argument -%c\n",
1906 program, isc_commandline_option);
1912 fprintf(stderr, "%s: unhandled option -%c\n",
1913 program, isc_commandline_option);
1918 cycle = strtol(isc_commandline_argument, &endp, 0);
1919 if (*endp != '\0' || cycle < 0)
1920 fatal("cycle period must be numeric and "
1925 inputformatstr = isc_commandline_argument;
1930 jitter = strtol(isc_commandline_argument, &endp, 0);
1931 if (*endp != '\0' || jitter < 0)
1932 fatal("jitter must be numeric and positive");
1936 dns_fixedname_init(&dlv_fixed);
1937 len = strlen(isc_commandline_argument);
1938 isc_buffer_init(&b, isc_commandline_argument, len);
1939 isc_buffer_add(&b, len);
1941 dns_fixedname_init(&dlv_fixed);
1942 dlv = dns_fixedname_name(&dlv_fixed);
1943 result = dns_name_fromtext(dlv, &b, dns_rootname,
1945 check_result(result, "dns_name_fromtext(dlv)");
1949 if (ndskeys == MAXDSKEYS)
1950 fatal("too many key-signing keys specified");
1951 dskeyfile[ndskeys++] = isc_commandline_argument;
1956 ntasks = strtol(isc_commandline_argument, &endp, 0);
1957 if (*endp != '\0' || ntasks > ISC_INT32_MAX)
1958 fatal("number of cpus must be numeric");
1962 serialformatstr = isc_commandline_argument;
1966 origin = isc_commandline_argument;
1970 outputformatstr = isc_commandline_argument;
1974 pseudorandom = ISC_TRUE;
1978 setup_entropy(mctx, isc_commandline_argument, &ectx);
1982 startstr = isc_commandline_argument;
1986 /* This is intentionally undocumented */
1987 /* -S: simple output style */
1988 masterstyle = &dns_master_style_simple;
1992 printstats = ISC_TRUE;
1997 verbose = strtol(isc_commandline_argument, &endp, 0);
1999 fatal("verbose level must be numeric");
2003 ignoreksk = ISC_TRUE;
2009 setup_entropy(mctx, NULL, &ectx);
2010 eflags = ISC_ENTROPY_BLOCKING;
2012 eflags |= ISC_ENTROPY_GOODONLY;
2014 result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
2015 if (result != ISC_R_SUCCESS)
2016 fatal("could not create hash context");
2018 result = dst_lib_init(mctx, ectx, eflags);
2019 if (result != ISC_R_SUCCESS)
2020 fatal("could not initialize dst");
2022 isc_stdtime_get(&now);
2024 if (startstr != NULL)
2025 starttime = strtotime(startstr, now, now);
2027 starttime = now - 3600; /* Allow for some clock skew. */
2030 endtime = strtotime(endstr, now, starttime);
2032 endtime = starttime + (30 * 24 * 60 * 60);
2035 cycle = (endtime - starttime) / 4;
2038 ntasks = isc_os_ncpus();
2039 vbprintf(4, "using %d cpus\n", ntasks);
2041 rdclass = strtoclass(classname);
2043 setup_logging(verbose, mctx, &log);
2045 argc -= isc_commandline_index;
2046 argv += isc_commandline_index;
2059 if (output == NULL) {
2060 free_output = ISC_TRUE;
2061 output = isc_mem_allocate(mctx,
2062 strlen(file) + strlen(".signed") + 1);
2064 fatal("out of memory");
2065 sprintf(output, "%s.signed", file);
2068 if (inputformatstr != NULL) {
2069 if (strcasecmp(inputformatstr, "text") == 0)
2070 inputformat = dns_masterformat_text;
2071 else if (strcasecmp(inputformatstr, "raw") == 0)
2072 inputformat = dns_masterformat_raw;
2074 fatal("unknown file format: %s\n", inputformatstr);
2077 if (outputformatstr != NULL) {
2078 if (strcasecmp(outputformatstr, "text") == 0)
2079 outputformat = dns_masterformat_text;
2080 else if (strcasecmp(outputformatstr, "raw") == 0)
2081 outputformat = dns_masterformat_raw;
2083 fatal("unknown file format: %s\n", outputformatstr);
2086 if (serialformatstr != NULL) {
2087 if (strcasecmp(serialformatstr, "keep") == 0)
2088 serialformat = SOA_SERIAL_KEEP;
2089 else if (strcasecmp(serialformatstr, "increment") == 0 ||
2090 strcasecmp(serialformatstr, "incr") == 0)
2091 serialformat = SOA_SERIAL_INCREMENT;
2092 else if (strcasecmp(serialformatstr, "unixtime") == 0)
2093 serialformat = SOA_SERIAL_UNIXTIME;
2095 fatal("unknown soa serial format: %s\n", serialformatstr);
2098 result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
2099 0, 24, 0, 0, 0, 8, mctx);
2100 check_result(result, "dns_master_stylecreate");
2104 TIME_NOW(&timer_start);
2105 loadzone(file, origin, rdclass, &gdb);
2106 gorigin = dns_db_origin(gdb);
2107 gclass = dns_db_class(gdb);
2110 ISC_LIST_INIT(keylist);
2115 for (i = 0; i < argc; i++) {
2116 dst_key_t *newkey = NULL;
2118 result = dst_key_fromnamedfile(argv[i],
2122 if (result != ISC_R_SUCCESS)
2123 fatal("cannot load dnskey %s: %s", argv[i],
2124 isc_result_totext(result));
2126 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
2127 fatal("key %s not at origin\n", argv[i]);
2129 key = ISC_LIST_HEAD(keylist);
2130 while (key != NULL) {
2131 dst_key_t *dkey = key->key;
2132 if (dst_key_id(dkey) == dst_key_id(newkey) &&
2133 dst_key_alg(dkey) == dst_key_alg(newkey) &&
2134 dns_name_equal(dst_key_name(dkey),
2135 dst_key_name(newkey)))
2137 if (!dst_key_isprivate(dkey))
2138 fatal("cannot sign zone with "
2139 "non-private dnskey %s",
2143 key = ISC_LIST_NEXT(key, link);
2146 key = newkeystruct(newkey, ISC_TRUE);
2147 ISC_LIST_APPEND(keylist, key, link);
2149 dst_key_free(&newkey);
2152 loadzonepubkeys(gdb);
2155 for (i = 0; i < ndskeys; i++) {
2156 dst_key_t *newkey = NULL;
2158 result = dst_key_fromnamedfile(dskeyfile[i],
2162 if (result != ISC_R_SUCCESS)
2163 fatal("cannot load dnskey %s: %s", dskeyfile[i],
2164 isc_result_totext(result));
2166 if (!dns_name_equal(gorigin, dst_key_name(newkey)))
2167 fatal("key %s not at origin\n", dskeyfile[i]);
2169 key = ISC_LIST_HEAD(keylist);
2170 while (key != NULL) {
2171 dst_key_t *dkey = key->key;
2172 if (dst_key_id(dkey) == dst_key_id(newkey) &&
2173 dst_key_alg(dkey) == dst_key_alg(newkey) &&
2174 dns_name_equal(dst_key_name(dkey),
2175 dst_key_name(newkey)))
2177 /* Override key flags. */
2178 key->issigningkey = ISC_TRUE;
2179 key->isksk = ISC_TRUE;
2180 key->isdsk = ISC_FALSE;
2181 dst_key_free(&dkey);
2185 key = ISC_LIST_NEXT(key, link);
2188 /* Override dnskey flags. */
2189 key = newkeystruct(newkey, ISC_TRUE);
2190 key->isksk = ISC_TRUE;
2191 key->isdsk = ISC_FALSE;
2192 ISC_LIST_APPEND(keylist, key, link);
2196 if (ISC_LIST_EMPTY(keylist)) {
2197 fprintf(stderr, "%s: warning: No keys specified or found\n",
2205 result = dns_db_newversion(gdb, &gversion);
2206 check_result(result, "dns_db_newversion()");
2208 switch (serialformat) {
2209 case SOA_SERIAL_INCREMENT:
2212 case SOA_SERIAL_UNIXTIME:
2215 case SOA_SERIAL_KEEP:
2224 writeset("keyset-", dns_rdatatype_dnskey);
2225 writeset("dsset-", dns_rdatatype_ds);
2227 writeset("dlvset-", dns_rdatatype_dlv);
2231 tempfilelen = strlen(output) + 20;
2232 tempfile = isc_mem_get(mctx, tempfilelen);
2233 if (tempfile == NULL)
2234 fatal("out of memory");
2236 result = isc_file_mktemplate(output, tempfile, tempfilelen);
2237 check_result(result, "isc_file_mktemplate");
2240 result = isc_file_openunique(tempfile, &fp);
2241 if (result != ISC_R_SUCCESS)
2242 fatal("failed to open temporary output file: %s",
2243 isc_result_totext(result));
2244 removefile = ISC_TRUE;
2245 setfatalcallback(&removetempfile);
2250 result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
2251 if (result != ISC_R_SUCCESS)
2252 fatal("failed to create task manager: %s",
2253 isc_result_totext(result));
2256 result = isc_task_create(taskmgr, 0, &master);
2257 if (result != ISC_R_SUCCESS)
2258 fatal("failed to create task: %s", isc_result_totext(result));
2260 tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
2262 fatal("out of memory");
2263 for (i = 0; i < (int)ntasks; i++) {
2265 result = isc_task_create(taskmgr, 0, &tasks[i]);
2266 if (result != ISC_R_SUCCESS)
2267 fatal("failed to create task: %s",
2268 isc_result_totext(result));
2271 RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
2273 RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
2279 * There is more work to do. Spread it out over multiple
2280 * processors if possible.
2282 for (i = 0; i < (int)ntasks; i++) {
2283 result = isc_app_onrun(mctx, master, startworker,
2285 if (result != ISC_R_SUCCESS)
2286 fatal("failed to start task: %s",
2287 isc_result_totext(result));
2289 (void)isc_app_run();
2291 fatal("process aborted by user");
2293 isc_task_detach(&master);
2294 shuttingdown = ISC_TRUE;
2295 for (i = 0; i < (int)ntasks; i++)
2296 isc_task_detach(&tasks[i]);
2297 isc_taskmgr_destroy(&taskmgr);
2298 isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
2301 if (outputformat != dns_masterformat_text) {
2302 result = dns_master_dumptostream2(mctx, gdb, gversion,
2303 masterstyle, outputformat,
2305 check_result(result, "dns_master_dumptostream2");
2308 result = isc_stdio_close(fp);
2309 check_result(result, "isc_stdio_close");
2310 removefile = ISC_FALSE;
2312 result = isc_file_rename(tempfile, output);
2313 if (result != ISC_R_SUCCESS)
2314 fatal("failed to rename temp file to %s: %s\n",
2315 output, isc_result_totext(result));
2317 DESTROYLOCK(&namelock);
2319 DESTROYLOCK(&statslock);
2321 printf("%s\n", output);
2323 dns_db_closeversion(gdb, &gversion, ISC_FALSE);
2324 dns_db_detach(&gdb);
2326 while (!ISC_LIST_EMPTY(keylist)) {
2327 key = ISC_LIST_HEAD(keylist);
2328 ISC_LIST_UNLINK(keylist, key, link);
2329 dst_key_free(&key->key);
2330 isc_mem_put(mctx, key, sizeof(signer_key_t));
2333 isc_mem_put(mctx, tempfile, tempfilelen);
2336 isc_mem_free(mctx, output);
2338 dns_master_styledestroy(&dsstyle, mctx);
2340 cleanup_logging(&log);
2343 cleanup_entropy(&ectx);
2346 isc_mem_stats(mctx, stdout);
2347 isc_mem_destroy(&mctx);
2349 (void) isc_app_finish();
2352 TIME_NOW(&timer_finish);
2353 print_stats(&timer_start, &timer_finish);