2 * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2003 Internet Software Consortium.
4 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
13 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
16 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 /* $Id: dnssec-signzone.c,v 1.177.18.24 2007/08/28 07:20:00 tbox Exp $ */
29 #include <isc/commandline.h>
30 #include <isc/entropy.h>
31 #include <isc/event.h>
35 #include <isc/mutex.h>
37 #include <isc/print.h>
38 #include <isc/random.h>
39 #include <isc/serial.h>
40 #include <isc/stdio.h>
41 #include <isc/string.h>
47 #include <dns/dbiterator.h>
49 #include <dns/dnssec.h>
51 #include <dns/fixedname.h>
52 #include <dns/keyvalues.h>
54 #include <dns/master.h>
55 #include <dns/masterdump.h>
57 #include <dns/rdata.h>
58 #include <dns/rdataset.h>
59 #include <dns/rdataclass.h>
60 #include <dns/rdatasetiter.h>
61 #include <dns/rdatastruct.h>
62 #include <dns/rdatatype.h>
63 #include <dns/result.h>
69 #include "dnssectool.h"
71 const char *program
= "dnssec-signzone";
77 typedef struct signer_key_struct signer_key_t
;
79 struct signer_key_struct
{
81 isc_boolean_t issigningkey
;
84 unsigned int position
;
85 ISC_LINK(signer_key_t
) link
;
88 #define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
89 #define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
90 #define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
92 #define SOA_SERIAL_KEEP 0
93 #define SOA_SERIAL_INCREMENT 1
94 #define SOA_SERIAL_UNIXTIME 2
96 typedef struct signer_event sevent_t
;
98 ISC_EVENT_COMMON(sevent_t
);
99 dns_fixedname_t
*fname
;
103 static ISC_LIST(signer_key_t
) keylist
;
104 static unsigned int keycount
= 0;
105 static isc_stdtime_t starttime
= 0, endtime
= 0, now
;
106 static int cycle
= -1;
107 static int jitter
= 0;
108 static isc_boolean_t tryverify
= ISC_FALSE
;
109 static isc_boolean_t printstats
= ISC_FALSE
;
110 static isc_mem_t
*mctx
= NULL
;
111 static isc_entropy_t
*ectx
= NULL
;
112 static dns_ttl_t zonettl
;
114 static char *tempfile
= NULL
;
115 static const dns_master_style_t
*masterstyle
;
116 static dns_masterformat_t inputformat
= dns_masterformat_text
;
117 static dns_masterformat_t outputformat
= dns_masterformat_text
;
118 static unsigned int nsigned
= 0, nretained
= 0, ndropped
= 0;
119 static unsigned int nverified
= 0, nverifyfailed
= 0;
120 static const char *directory
;
121 static isc_mutex_t namelock
, statslock
;
122 static isc_taskmgr_t
*taskmgr
= NULL
;
123 static dns_db_t
*gdb
; /* The database */
124 static dns_dbversion_t
*gversion
; /* The database version */
125 static dns_dbiterator_t
*gdbiter
; /* The database iterator */
126 static dns_rdataclass_t gclass
; /* The class */
127 static dns_name_t
*gorigin
; /* The database origin */
128 static isc_task_t
*master
= NULL
;
129 static unsigned int ntasks
= 0;
130 static isc_boolean_t shuttingdown
= ISC_FALSE
, finished
= ISC_FALSE
;
131 static unsigned int assigned
= 0, completed
= 0;
132 static isc_boolean_t nokeys
= ISC_FALSE
;
133 static isc_boolean_t removefile
= ISC_FALSE
;
134 static isc_boolean_t generateds
= ISC_FALSE
;
135 static isc_boolean_t ignoreksk
= ISC_FALSE
;
136 static dns_name_t
*dlv
= NULL
;
137 static dns_fixedname_t dlv_fixed
;
138 static dns_master_style_t
*dsstyle
= NULL
;
139 static unsigned int serialformat
= SOA_SERIAL_KEEP
;
141 #define INCSTAT(counter) \
145 UNLOCK(&statslock); \
149 sign(isc_task_t
*task
, isc_event_t
*event
);
153 set_bit(unsigned char *array
, unsigned int index
, unsigned int bit
) {
154 unsigned int shift
, mask
;
156 shift
= 7 - (index
% 8);
160 array
[index
/ 8] |= mask
;
162 array
[index
/ 8] &= (~mask
& 0xFF);
166 dumpnode(dns_name_t
*name
, dns_dbnode_t
*node
) {
169 if (outputformat
!= dns_masterformat_text
)
171 result
= dns_master_dumpnodetostream(mctx
, gdb
, gversion
, node
, name
,
173 check_result(result
, "dns_master_dumpnodetostream");
176 static signer_key_t
*
177 newkeystruct(dst_key_t
*dstkey
, isc_boolean_t signwithkey
) {
180 key
= isc_mem_get(mctx
, sizeof(signer_key_t
));
182 fatal("out of memory");
184 if ((dst_key_flags(dstkey
) & DNS_KEYFLAG_KSK
) != 0) {
185 key
->issigningkey
= signwithkey
;
186 key
->isksk
= ISC_TRUE
;
187 key
->isdsk
= ISC_FALSE
;
189 key
->issigningkey
= signwithkey
;
190 key
->isksk
= ISC_FALSE
;
191 key
->isdsk
= ISC_TRUE
;
193 key
->position
= keycount
++;
194 ISC_LINK_INIT(key
, link
);
199 signwithkey(dns_name_t
*name
, dns_rdataset_t
*rdataset
, dns_rdata_t
*rdata
,
200 dst_key_t
*key
, isc_buffer_t
*b
)
203 isc_stdtime_t jendtime
;
205 jendtime
= (jitter
!= 0) ? isc_random_jitter(endtime
, jitter
) : endtime
;
206 result
= dns_dnssec_sign(name
, rdataset
, key
, &starttime
, &jendtime
,
208 isc_entropy_stopcallbacksources(ectx
);
209 if (result
!= ISC_R_SUCCESS
) {
210 char keystr
[KEY_FORMATSIZE
];
211 key_format(key
, keystr
, sizeof(keystr
));
212 fatal("dnskey '%s' failed to sign data: %s",
213 keystr
, isc_result_totext(result
));
218 result
= dns_dnssec_verify(name
, rdataset
, key
,
219 ISC_TRUE
, mctx
, rdata
);
220 if (result
== ISC_R_SUCCESS
) {
221 vbprintf(3, "\tsignature verified\n");
224 vbprintf(3, "\tsignature failed to verify\n");
225 INCSTAT(nverifyfailed
);
230 static inline isc_boolean_t
231 issigningkey(signer_key_t
*key
) {
232 return (key
->issigningkey
);
235 static inline isc_boolean_t
236 iszonekey(signer_key_t
*key
) {
237 return (ISC_TF(dns_name_equal(dst_key_name(key
->key
), gorigin
) &&
238 dst_key_iszonekey(key
->key
)));
242 * Finds the key that generated a RRSIG, if possible. First look at the keys
243 * that we've loaded already, and then see if there's a key on disk.
245 static signer_key_t
*
246 keythatsigned(dns_rdata_rrsig_t
*rrsig
) {
248 dst_key_t
*pubkey
= NULL
, *privkey
= NULL
;
251 key
= ISC_LIST_HEAD(keylist
);
252 while (key
!= NULL
) {
253 if (rrsig
->keyid
== dst_key_id(key
->key
) &&
254 rrsig
->algorithm
== dst_key_alg(key
->key
) &&
255 dns_name_equal(&rrsig
->signer
, dst_key_name(key
->key
)))
257 key
= ISC_LIST_NEXT(key
, link
);
260 result
= dst_key_fromfile(&rrsig
->signer
, rrsig
->keyid
,
261 rrsig
->algorithm
, DST_TYPE_PUBLIC
,
262 NULL
, mctx
, &pubkey
);
263 if (result
!= ISC_R_SUCCESS
)
266 result
= dst_key_fromfile(&rrsig
->signer
, rrsig
->keyid
,
268 DST_TYPE_PUBLIC
| DST_TYPE_PRIVATE
,
269 NULL
, mctx
, &privkey
);
270 if (result
== ISC_R_SUCCESS
) {
271 dst_key_free(&pubkey
);
272 key
= newkeystruct(privkey
, ISC_FALSE
);
274 key
= newkeystruct(pubkey
, ISC_FALSE
);
275 ISC_LIST_APPEND(keylist
, key
, link
);
280 * Check to see if we expect to find a key at this name. If we see a RRSIG
281 * and can't find the signing key that we expect to find, we drop the rrsig.
282 * I'm not sure if this is completely correct, but it seems to work.
285 expecttofindkey(dns_name_t
*name
) {
286 unsigned int options
= DNS_DBFIND_NOWILD
;
287 dns_fixedname_t fname
;
289 char namestr
[DNS_NAME_FORMATSIZE
];
291 dns_fixedname_init(&fname
);
292 result
= dns_db_find(gdb
, name
, gversion
, dns_rdatatype_dnskey
, options
,
293 0, NULL
, dns_fixedname_name(&fname
), NULL
, NULL
);
299 case DNS_R_DELEGATION
:
304 dns_name_format(name
, namestr
, sizeof(namestr
));
305 fatal("failure looking for '%s DNSKEY' in database: %s",
306 namestr
, isc_result_totext(result
));
307 return (ISC_FALSE
); /* removes a warning */
310 static inline isc_boolean_t
311 setverifies(dns_name_t
*name
, dns_rdataset_t
*set
, signer_key_t
*key
,
315 result
= dns_dnssec_verify(name
, set
, key
->key
, ISC_FALSE
, mctx
, rrsig
);
316 if (result
== ISC_R_SUCCESS
) {
320 INCSTAT(nverifyfailed
);
326 * Signs a set. Goes through contortions to decide if each RRSIG should
327 * be dropped or retained, and then determines if any new SIGs need to
331 signset(dns_diff_t
*del
, dns_diff_t
*add
, dns_dbnode_t
*node
, dns_name_t
*name
,
334 dns_rdataset_t sigset
;
335 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
336 dns_rdata_rrsig_t rrsig
;
339 isc_boolean_t nosigs
= ISC_FALSE
;
340 isc_boolean_t
*wassignedby
, *nowsignedby
;
342 dns_difftuple_t
*tuple
;
345 char namestr
[DNS_NAME_FORMATSIZE
];
346 char typestr
[TYPE_FORMATSIZE
];
347 char sigstr
[SIG_FORMATSIZE
];
349 dns_name_format(name
, namestr
, sizeof(namestr
));
350 type_format(set
->type
, typestr
, sizeof(typestr
));
352 ttl
= ISC_MIN(set
->ttl
, endtime
- starttime
);
354 dns_rdataset_init(&sigset
);
355 result
= dns_db_findrdataset(gdb
, node
, gversion
, dns_rdatatype_rrsig
,
356 set
->type
, 0, &sigset
, NULL
);
357 if (result
== ISC_R_NOTFOUND
) {
358 result
= ISC_R_SUCCESS
;
361 if (result
!= ISC_R_SUCCESS
)
362 fatal("failed while looking for '%s RRSIG %s': %s",
363 namestr
, typestr
, isc_result_totext(result
));
365 vbprintf(1, "%s/%s:\n", namestr
, typestr
);
367 arraysize
= keycount
;
369 arraysize
+= dns_rdataset_count(&sigset
);
370 wassignedby
= isc_mem_get(mctx
, arraysize
* sizeof(isc_boolean_t
));
371 nowsignedby
= isc_mem_get(mctx
, arraysize
* sizeof(isc_boolean_t
));
372 if (wassignedby
== NULL
|| nowsignedby
== NULL
)
373 fatal("out of memory");
375 for (i
= 0; i
< arraysize
; i
++)
376 wassignedby
[i
] = nowsignedby
[i
] = ISC_FALSE
;
379 result
= ISC_R_NOMORE
;
381 result
= dns_rdataset_first(&sigset
);
383 while (result
== ISC_R_SUCCESS
) {
384 isc_boolean_t expired
, future
;
385 isc_boolean_t keep
= ISC_FALSE
, resign
= ISC_FALSE
;
387 dns_rdataset_current(&sigset
, &sigrdata
);
389 result
= dns_rdata_tostruct(&sigrdata
, &rrsig
, NULL
);
390 check_result(result
, "dns_rdata_tostruct");
392 future
= isc_serial_lt(now
, rrsig
.timesigned
);
394 key
= keythatsigned(&rrsig
);
395 sig_format(&rrsig
, sigstr
, sizeof(sigstr
));
396 if (key
!= NULL
&& issigningkey(key
))
397 expired
= isc_serial_gt(now
+ cycle
, rrsig
.timeexpire
);
399 expired
= isc_serial_gt(now
, rrsig
.timeexpire
);
401 if (isc_serial_gt(rrsig
.timesigned
, rrsig
.timeexpire
)) {
402 /* rrsig is dropped and not replaced */
403 vbprintf(2, "\trrsig by %s dropped - "
404 "invalid validity period\n",
406 } else if (key
== NULL
&& !future
&&
407 expecttofindkey(&rrsig
.signer
))
409 /* rrsig is dropped and not replaced */
410 vbprintf(2, "\trrsig by %s dropped - "
411 "private dnskey not found\n",
413 } else if (key
== NULL
|| future
) {
414 vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
415 expired
? "retained" : "dropped", sigstr
);
418 } else if (issigningkey(key
)) {
419 if (!expired
&& setverifies(name
, set
, key
, &sigrdata
))
421 vbprintf(2, "\trrsig by %s retained\n", sigstr
);
423 wassignedby
[key
->position
] = ISC_TRUE
;
424 nowsignedby
[key
->position
] = ISC_TRUE
;
426 vbprintf(2, "\trrsig by %s dropped - %s\n",
428 expired
? "expired" :
430 wassignedby
[key
->position
] = ISC_TRUE
;
433 } else if (iszonekey(key
)) {
434 if (!expired
&& setverifies(name
, set
, key
, &sigrdata
))
436 vbprintf(2, "\trrsig by %s retained\n", sigstr
);
438 wassignedby
[key
->position
] = ISC_TRUE
;
439 nowsignedby
[key
->position
] = ISC_TRUE
;
441 vbprintf(2, "\trrsig by %s dropped - %s\n",
443 expired
? "expired" :
445 wassignedby
[key
->position
] = ISC_TRUE
;
447 } else if (!expired
) {
448 vbprintf(2, "\trrsig by %s retained\n", sigstr
);
451 vbprintf(2, "\trrsig by %s expired\n", sigstr
);
455 nowsignedby
[key
->position
] = ISC_TRUE
;
457 if (sigset
.ttl
!= ttl
) {
458 vbprintf(2, "\tfixing ttl %s\n", sigstr
);
460 result
= dns_difftuple_create(mctx
,
465 check_result(result
, "dns_difftuple_create");
466 dns_diff_append(del
, &tuple
);
467 result
= dns_difftuple_create(mctx
,
472 check_result(result
, "dns_difftuple_create");
473 dns_diff_append(add
, &tuple
);
477 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_DEL
,
480 check_result(result
, "dns_difftuple_create");
481 dns_diff_append(del
, &tuple
);
487 dns_rdata_t trdata
= DNS_RDATA_INIT
;
488 unsigned char array
[BUFSIZE
];
489 char keystr
[KEY_FORMATSIZE
];
493 key_format(key
->key
, keystr
, sizeof(keystr
));
494 vbprintf(1, "\tresigning with dnskey %s\n", keystr
);
495 isc_buffer_init(&b
, array
, sizeof(array
));
496 signwithkey(name
, set
, &trdata
, key
->key
, &b
);
497 nowsignedby
[key
->position
] = ISC_TRUE
;
499 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
,
502 check_result(result
, "dns_difftuple_create");
503 dns_diff_append(add
, &tuple
);
506 dns_rdata_reset(&sigrdata
);
507 dns_rdata_freestruct(&rrsig
);
508 result
= dns_rdataset_next(&sigset
);
510 if (result
== ISC_R_NOMORE
)
511 result
= ISC_R_SUCCESS
;
513 check_result(result
, "dns_rdataset_first/next");
514 if (dns_rdataset_isassociated(&sigset
))
515 dns_rdataset_disassociate(&sigset
);
517 for (key
= ISC_LIST_HEAD(keylist
);
519 key
= ISC_LIST_NEXT(key
, link
))
523 unsigned char array
[BUFSIZE
];
524 char keystr
[KEY_FORMATSIZE
];
526 if (nowsignedby
[key
->position
])
529 if (!key
->issigningkey
)
531 if (!(ignoreksk
|| key
->isdsk
||
533 set
->type
== dns_rdatatype_dnskey
&&
534 dns_name_equal(name
, gorigin
))))
537 key_format(key
->key
, keystr
, sizeof(keystr
));
538 vbprintf(1, "\tsigning with dnskey %s\n", keystr
);
539 dns_rdata_init(&trdata
);
540 isc_buffer_init(&b
, array
, sizeof(array
));
541 signwithkey(name
, set
, &trdata
, key
->key
, &b
);
543 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
, name
,
544 ttl
, &trdata
, &tuple
);
545 check_result(result
, "dns_difftuple_create");
546 dns_diff_append(add
, &tuple
);
549 isc_mem_put(mctx
, wassignedby
, arraysize
* sizeof(isc_boolean_t
));
550 isc_mem_put(mctx
, nowsignedby
, arraysize
* sizeof(isc_boolean_t
));
554 opendb(const char *prefix
, dns_name_t
*name
, dns_rdataclass_t rdclass
,
561 isc_buffer_init(&b
, filename
, sizeof(filename
));
562 if (directory
!= NULL
) {
563 isc_buffer_putstr(&b
, directory
);
564 if (directory
[strlen(directory
) - 1] != '/')
565 isc_buffer_putstr(&b
, "/");
567 isc_buffer_putstr(&b
, prefix
);
568 result
= dns_name_tofilenametext(name
, ISC_FALSE
, &b
);
569 check_result(result
, "dns_name_tofilenametext()");
570 if (isc_buffer_availablelength(&b
) == 0) {
571 char namestr
[DNS_NAME_FORMATSIZE
];
572 dns_name_format(name
, namestr
, sizeof(namestr
));
573 fatal("name '%s' is too long", namestr
);
575 isc_buffer_putuint8(&b
, 0);
577 result
= dns_db_create(mctx
, "rbt", dns_rootname
, dns_dbtype_zone
,
578 rdclass
, 0, NULL
, dbp
);
579 check_result(result
, "dns_db_create()");
581 result
= dns_db_load(*dbp
, filename
);
582 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_SEENINCLUDE
)
587 * Loads the key set for a child zone, if there is one, and builds DS records.
590 loadds(dns_name_t
*name
, isc_uint32_t ttl
, dns_rdataset_t
*dsset
) {
592 dns_dbversion_t
*ver
= NULL
;
593 dns_dbnode_t
*node
= NULL
;
595 dns_rdataset_t keyset
;
597 unsigned char dsbuf
[DNS_DS_BUFFERSIZE
];
599 dns_difftuple_t
*tuple
= NULL
;
601 opendb("keyset-", name
, gclass
, &db
);
603 return (ISC_R_NOTFOUND
);
605 result
= dns_db_findnode(db
, name
, ISC_FALSE
, &node
);
606 if (result
!= ISC_R_SUCCESS
) {
608 return (DNS_R_BADDB
);
610 dns_rdataset_init(&keyset
);
611 result
= dns_db_findrdataset(db
, node
, NULL
, dns_rdatatype_dnskey
, 0, 0,
613 if (result
!= ISC_R_SUCCESS
) {
614 dns_db_detachnode(db
, &node
);
619 vbprintf(2, "found DNSKEY records\n");
621 result
= dns_db_newversion(db
, &ver
);
622 check_result(result
, "dns_db_newversion");
624 dns_diff_init(mctx
, &diff
);
626 for (result
= dns_rdataset_first(&keyset
);
627 result
== ISC_R_SUCCESS
;
628 result
= dns_rdataset_next(&keyset
))
630 dns_rdata_init(&key
);
632 dns_rdataset_current(&keyset
, &key
);
633 result
= dns_ds_buildrdata(name
, &key
, DNS_DSDIGEST_SHA1
,
635 check_result(result
, "dns_ds_buildrdata");
637 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
, name
,
639 check_result(result
, "dns_difftuple_create");
640 dns_diff_append(&diff
, &tuple
);
642 dns_rdata_reset(&ds
);
643 result
= dns_ds_buildrdata(name
, &key
, DNS_DSDIGEST_SHA256
,
645 check_result(result
, "dns_ds_buildrdata");
647 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
, name
,
649 check_result(result
, "dns_difftuple_create");
650 dns_diff_append(&diff
, &tuple
);
652 result
= dns_diff_apply(&diff
, db
, ver
);
653 check_result(result
, "dns_diff_apply");
654 dns_diff_clear(&diff
);
656 dns_db_closeversion(db
, &ver
, ISC_TRUE
);
658 result
= dns_db_findrdataset(db
, node
, NULL
, dns_rdatatype_ds
, 0, 0,
660 check_result(result
, "dns_db_findrdataset");
662 dns_rdataset_disassociate(&keyset
);
663 dns_db_detachnode(db
, &node
);
669 nsec_setbit(dns_name_t
*name
, dns_rdataset_t
*rdataset
, dns_rdatatype_t type
,
673 dns_rdata_t rdata
= DNS_RDATA_INIT
;
674 dns_rdata_nsec_t nsec
;
676 unsigned char bitmap
[8192 + 512];
677 unsigned char nsecdata
[8192 + 512 + DNS_NAME_MAXWIRE
];
678 isc_boolean_t answer
= ISC_FALSE
;
679 unsigned int i
, len
, window
;
682 result
= dns_rdataset_first(rdataset
);
683 check_result(result
, "dns_rdataset_first()");
684 dns_rdataset_current(rdataset
, &rdata
);
685 result
= dns_rdata_tostruct(&rdata
, &nsec
, NULL
);
686 check_result(result
, "dns_rdata_tostruct");
688 INSIST(nsec
.len
<= sizeof(bitmap
));
692 memset(bitmap
, 0, sizeof(bitmap
));
693 for (i
= 0; i
< nsec
.len
; i
+= len
) {
694 INSIST(i
+ 2 <= nsec
.len
);
695 window
= nsec
.typebits
[i
];
696 len
= nsec
.typebits
[i
+1];
698 INSIST(len
> 0 && len
<= 32);
699 INSIST(i
+ len
<= nsec
.len
);
700 memmove(&bitmap
[window
* 32 + 512], &nsec
.typebits
[i
], len
);
702 set_bit(bitmap
+ 512, type
, val
);
703 for (window
= 0; window
< 256; window
++) {
704 for (octet
= 31; octet
>= 0; octet
--)
705 if (bitmap
[window
* 32 + 512 + octet
] != 0)
709 bitmap
[newlen
] = window
;
710 bitmap
[newlen
+ 1] = octet
+ 1;
715 memmove(&bitmap
[newlen
], &bitmap
[window
* 32 + 512], octet
+ 1);
718 if (newlen
!= nsec
.len
||
719 memcmp(nsec
.typebits
, bitmap
, newlen
) != 0) {
720 dns_rdata_t newrdata
= DNS_RDATA_INIT
;
723 dns_difftuple_t
*tuple
= NULL
;
725 dns_diff_init(mctx
, &diff
);
726 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_DEL
, name
,
727 rdataset
->ttl
, &rdata
, &tuple
);
728 check_result(result
, "dns_difftuple_create");
729 dns_diff_append(&diff
, &tuple
);
731 nsec
.typebits
= bitmap
;
733 isc_buffer_init(&b
, nsecdata
, sizeof(nsecdata
));
734 result
= dns_rdata_fromstruct(&newrdata
, rdata
.rdclass
,
735 dns_rdatatype_nsec
, &nsec
,
737 check_result(result
, "dns_rdata_fromstruct");
739 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
,
742 check_result(result
, "dns_difftuple_create");
743 dns_diff_append(&diff
, &tuple
);
744 result
= dns_diff_apply(&diff
, gdb
, gversion
);
745 check_result(result
, "dns_difftuple_apply");
746 dns_diff_clear(&diff
);
749 dns_rdata_freestruct(&nsec
);
754 delegation(dns_name_t
*name
, dns_dbnode_t
*node
, isc_uint32_t
*ttlp
) {
755 dns_rdataset_t nsset
;
758 if (dns_name_equal(name
, gorigin
))
761 dns_rdataset_init(&nsset
);
762 result
= dns_db_findrdataset(gdb
, node
, gversion
, dns_rdatatype_ns
,
764 if (dns_rdataset_isassociated(&nsset
)) {
767 dns_rdataset_disassociate(&nsset
);
770 return (ISC_TF(result
== ISC_R_SUCCESS
));
774 * Signs all records at a name. This mostly just signs each set individually,
775 * but also adds the RRSIG bit to any NSECs generated earlier, deals with
776 * parent/child KEY signatures, and handles other exceptional cases.
779 signname(dns_dbnode_t
*node
, dns_name_t
*name
) {
781 dns_rdataset_t rdataset
;
782 dns_rdatasetiter_t
*rdsiter
;
783 isc_boolean_t isdelegation
= ISC_FALSE
;
784 isc_boolean_t hasds
= ISC_FALSE
;
785 isc_boolean_t changed
= ISC_FALSE
;
787 char namestr
[DNS_NAME_FORMATSIZE
];
788 isc_uint32_t nsttl
= 0;
790 dns_name_format(name
, namestr
, sizeof(namestr
));
793 * Determine if this is a delegation point.
795 if (delegation(name
, node
, &nsttl
))
796 isdelegation
= ISC_TRUE
;
799 * If this is a delegation point, look for a DS set.
802 dns_rdataset_t dsset
;
803 dns_rdataset_t sigdsset
;
805 dns_rdataset_init(&dsset
);
806 dns_rdataset_init(&sigdsset
);
807 result
= dns_db_findrdataset(gdb
, node
, gversion
,
809 0, 0, &dsset
, &sigdsset
);
810 if (result
== ISC_R_SUCCESS
) {
811 dns_rdataset_disassociate(&dsset
);
813 result
= dns_db_deleterdataset(gdb
, node
,
817 check_result(result
, "dns_db_deleterdataset");
822 result
= loadds(name
, nsttl
, &dsset
);
823 if (result
== ISC_R_SUCCESS
) {
824 result
= dns_db_addrdataset(gdb
, node
,
827 check_result(result
, "dns_db_addrdataset");
829 dns_rdataset_disassociate(&dsset
);
830 if (dns_rdataset_isassociated(&sigdsset
))
831 dns_rdataset_disassociate(&sigdsset
);
832 } else if (dns_rdataset_isassociated(&sigdsset
)) {
833 result
= dns_db_deleterdataset(gdb
, node
,
837 check_result(result
, "dns_db_deleterdataset");
838 dns_rdataset_disassociate(&sigdsset
);
840 } else if (dns_rdataset_isassociated(&sigdsset
))
841 dns_rdataset_disassociate(&sigdsset
);
845 * Make sure that NSEC bits are appropriately set.
847 dns_rdataset_init(&rdataset
);
848 RUNTIME_CHECK(dns_db_findrdataset(gdb
, node
, gversion
,
849 dns_rdatatype_nsec
, 0, 0, &rdataset
,
850 NULL
) == ISC_R_SUCCESS
);
852 changed
= nsec_setbit(name
, &rdataset
, dns_rdatatype_rrsig
, 1);
854 dns_rdataset_disassociate(&rdataset
);
855 RUNTIME_CHECK(dns_db_findrdataset(gdb
, node
, gversion
,
856 dns_rdatatype_nsec
, 0, 0,
858 NULL
) == ISC_R_SUCCESS
);
861 (void)nsec_setbit(name
, &rdataset
, dns_rdatatype_ds
, 1);
863 (void)nsec_setbit(name
, &rdataset
, dns_rdatatype_ds
, 0);
864 dns_rdataset_disassociate(&rdataset
);
867 * Now iterate through the rdatasets.
869 dns_diff_init(mctx
, &del
);
870 dns_diff_init(mctx
, &add
);
872 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
873 check_result(result
, "dns_db_allrdatasets()");
874 result
= dns_rdatasetiter_first(rdsiter
);
875 while (result
== ISC_R_SUCCESS
) {
876 dns_rdatasetiter_current(rdsiter
, &rdataset
);
878 /* If this is a RRSIG set, skip it. */
879 if (rdataset
.type
== dns_rdatatype_rrsig
)
883 * If this name is a delegation point, skip all records
884 * except NSEC and DS sets. Otherwise check that there
888 if (rdataset
.type
!= dns_rdatatype_nsec
&&
889 rdataset
.type
!= dns_rdatatype_ds
)
891 } else if (rdataset
.type
== dns_rdatatype_ds
) {
892 char namebuf
[DNS_NAME_FORMATSIZE
];
893 dns_name_format(name
, namebuf
, sizeof(namebuf
));
894 fatal("'%s': found DS RRset without NS RRset\n",
898 signset(&del
, &add
, node
, name
, &rdataset
);
901 dns_rdataset_disassociate(&rdataset
);
902 result
= dns_rdatasetiter_next(rdsiter
);
904 if (result
!= ISC_R_NOMORE
)
905 fatal("rdataset iteration for name '%s' failed: %s",
906 namestr
, isc_result_totext(result
));
908 dns_rdatasetiter_destroy(&rdsiter
);
910 result
= dns_diff_applysilently(&del
, gdb
, gversion
);
911 if (result
!= ISC_R_SUCCESS
)
912 fatal("failed to delete SIGs at node '%s': %s",
913 namestr
, isc_result_totext(result
));
915 result
= dns_diff_applysilently(&add
, gdb
, gversion
);
916 if (result
!= ISC_R_SUCCESS
)
917 fatal("failed to add SIGs at node '%s': %s",
918 namestr
, isc_result_totext(result
));
920 dns_diff_clear(&del
);
921 dns_diff_clear(&add
);
924 static inline isc_boolean_t
925 active_node(dns_dbnode_t
*node
) {
926 dns_rdatasetiter_t
*rdsiter
= NULL
;
927 dns_rdatasetiter_t
*rdsiter2
= NULL
;
928 isc_boolean_t active
= ISC_FALSE
;
930 dns_rdataset_t rdataset
;
931 dns_rdatatype_t type
;
932 dns_rdatatype_t covers
;
935 dns_rdataset_init(&rdataset
);
936 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter
);
937 check_result(result
, "dns_db_allrdatasets()");
938 result
= dns_rdatasetiter_first(rdsiter
);
939 while (result
== ISC_R_SUCCESS
) {
940 dns_rdatasetiter_current(rdsiter
, &rdataset
);
941 if (rdataset
.type
!= dns_rdatatype_nsec
&&
942 rdataset
.type
!= dns_rdatatype_rrsig
)
944 dns_rdataset_disassociate(&rdataset
);
946 result
= dns_rdatasetiter_next(rdsiter
);
948 result
= ISC_R_NOMORE
;
950 if (result
!= ISC_R_NOMORE
)
951 fatal("rdataset iteration failed: %s",
952 isc_result_totext(result
));
956 * The node is empty of everything but NSEC / RRSIG records.
958 for (result
= dns_rdatasetiter_first(rdsiter
);
959 result
== ISC_R_SUCCESS
;
960 result
= dns_rdatasetiter_next(rdsiter
)) {
961 dns_rdatasetiter_current(rdsiter
, &rdataset
);
962 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
965 check_result(result
, "dns_db_deleterdataset()");
966 dns_rdataset_disassociate(&rdataset
);
968 if (result
!= ISC_R_NOMORE
)
969 fatal("rdataset iteration failed: %s",
970 isc_result_totext(result
));
973 * Delete RRSIGs for types that no longer exist.
975 result
= dns_db_allrdatasets(gdb
, node
, gversion
, 0, &rdsiter2
);
976 check_result(result
, "dns_db_allrdatasets()");
977 for (result
= dns_rdatasetiter_first(rdsiter
);
978 result
== ISC_R_SUCCESS
;
979 result
= dns_rdatasetiter_next(rdsiter
)) {
980 dns_rdatasetiter_current(rdsiter
, &rdataset
);
981 type
= rdataset
.type
;
982 covers
= rdataset
.covers
;
983 dns_rdataset_disassociate(&rdataset
);
984 if (type
!= dns_rdatatype_rrsig
)
987 for (result
= dns_rdatasetiter_first(rdsiter2
);
988 !found
&& result
== ISC_R_SUCCESS
;
989 result
= dns_rdatasetiter_next(rdsiter2
)) {
990 dns_rdatasetiter_current(rdsiter2
, &rdataset
);
991 if (rdataset
.type
== covers
)
993 dns_rdataset_disassociate(&rdataset
);
996 if (result
!= ISC_R_NOMORE
)
997 fatal("rdataset iteration failed: %s",
998 isc_result_totext(result
));
999 result
= dns_db_deleterdataset(gdb
, node
,
1002 check_result(result
,
1003 "dns_db_deleterdataset(rrsig)");
1004 } else if (result
!= ISC_R_NOMORE
&&
1005 result
!= ISC_R_SUCCESS
)
1006 fatal("rdataset iteration failed: %s",
1007 isc_result_totext(result
));
1009 if (result
!= ISC_R_NOMORE
)
1010 fatal("rdataset iteration failed: %s",
1011 isc_result_totext(result
));
1012 dns_rdatasetiter_destroy(&rdsiter2
);
1014 dns_rdatasetiter_destroy(&rdsiter
);
1020 * Extracts the TTL from the SOA.
1024 dns_rdataset_t soaset
;
1025 dns_fixedname_t fname
;
1027 isc_result_t result
;
1029 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1030 dns_rdata_soa_t soa
;
1032 dns_fixedname_init(&fname
);
1033 name
= dns_fixedname_name(&fname
);
1034 dns_rdataset_init(&soaset
);
1035 result
= dns_db_find(gdb
, gorigin
, gversion
, dns_rdatatype_soa
,
1036 0, 0, NULL
, name
, &soaset
, NULL
);
1037 if (result
!= ISC_R_SUCCESS
)
1038 fatal("failed to find an SOA at the zone apex: %s",
1039 isc_result_totext(result
));
1041 result
= dns_rdataset_first(&soaset
);
1042 check_result(result
, "dns_rdataset_first");
1043 dns_rdataset_current(&soaset
, &rdata
);
1044 result
= dns_rdata_tostruct(&rdata
, &soa
, NULL
);
1045 check_result(result
, "dns_rdata_tostruct");
1047 dns_rdataset_disassociate(&soaset
);
1052 * Increment (or set if nonzero) the SOA serial
1055 setsoaserial(isc_uint32_t serial
) {
1056 isc_result_t result
;
1057 dns_dbnode_t
*node
= NULL
;
1058 dns_rdataset_t rdataset
;
1059 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1060 isc_uint32_t old_serial
, new_serial
;
1062 result
= dns_db_getoriginnode(gdb
, &node
);
1063 if (result
!= ISC_R_SUCCESS
)
1066 dns_rdataset_init(&rdataset
);
1068 result
= dns_db_findrdataset(gdb
, node
, gversion
,
1069 dns_rdatatype_soa
, 0,
1070 0, &rdataset
, NULL
);
1071 if (result
!= ISC_R_SUCCESS
)
1074 result
= dns_rdataset_first(&rdataset
);
1075 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1077 dns_rdataset_current(&rdataset
, &rdata
);
1079 old_serial
= dns_soa_getserial(&rdata
);
1082 /* Set SOA serial to the value provided. */
1083 new_serial
= serial
;
1085 /* Increment SOA serial using RFC 1982 arithmetics */
1086 new_serial
= (old_serial
+ 1) & 0xFFFFFFFF;
1087 if (new_serial
== 0)
1091 /* If the new serial is not likely to cause a zone transfer
1092 * (a/ixfr) from servers having the old serial, warn the user.
1094 * RFC1982 section 7 defines the maximum increment to be
1095 * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
1096 * comparison. (5 - 6 == (2^32)-1, not negative-one)
1098 if (new_serial
== old_serial
||
1099 (new_serial
- old_serial
) > 0x7fffffffU
)
1100 fprintf(stderr
, "%s: warning: Serial number not advanced, "
1101 "zone may not transfer\n", program
);
1103 dns_soa_setserial(new_serial
, &rdata
);
1105 result
= dns_db_deleterdataset(gdb
, node
, gversion
,
1106 dns_rdatatype_soa
, 0);
1107 check_result(result
, "dns_db_deleterdataset");
1108 if (result
!= ISC_R_SUCCESS
)
1111 result
= dns_db_addrdataset(gdb
, node
, gversion
,
1112 0, &rdataset
, 0, NULL
);
1113 check_result(result
, "dns_db_addrdataset");
1114 if (result
!= ISC_R_SUCCESS
)
1118 dns_rdataset_disassociate(&rdataset
);
1120 dns_db_detachnode(gdb
, &node
);
1121 dns_rdata_reset(&rdata
);
1127 * Delete any RRSIG records at a node.
1130 cleannode(dns_db_t
*db
, dns_dbversion_t
*version
, dns_dbnode_t
*node
) {
1131 dns_rdatasetiter_t
*rdsiter
= NULL
;
1133 isc_result_t result
, dresult
;
1135 if (outputformat
!= dns_masterformat_text
)
1138 dns_rdataset_init(&set
);
1139 result
= dns_db_allrdatasets(db
, node
, version
, 0, &rdsiter
);
1140 check_result(result
, "dns_db_allrdatasets");
1141 result
= dns_rdatasetiter_first(rdsiter
);
1142 while (result
== ISC_R_SUCCESS
) {
1143 isc_boolean_t destroy
= ISC_FALSE
;
1144 dns_rdatatype_t covers
= 0;
1145 dns_rdatasetiter_current(rdsiter
, &set
);
1146 if (set
.type
== dns_rdatatype_rrsig
) {
1147 covers
= set
.covers
;
1150 dns_rdataset_disassociate(&set
);
1151 result
= dns_rdatasetiter_next(rdsiter
);
1153 dresult
= dns_db_deleterdataset(db
, node
, version
,
1154 dns_rdatatype_rrsig
,
1156 check_result(dresult
, "dns_db_deleterdataset");
1159 if (result
!= ISC_R_NOMORE
)
1160 fatal("rdataset iteration failed: %s",
1161 isc_result_totext(result
));
1162 dns_rdatasetiter_destroy(&rdsiter
);
1166 * Set up the iterator and global state before starting the tasks.
1170 isc_result_t result
;
1173 result
= dns_db_createiterator(gdb
, ISC_FALSE
, &gdbiter
);
1174 check_result(result
, "dns_db_createiterator()");
1176 result
= dns_dbiterator_first(gdbiter
);
1177 check_result(result
, "dns_dbiterator_first()");
1181 * Clean up the iterator and global state after the tasks complete.
1185 dns_dbiterator_destroy(&gdbiter
);
1189 * Sign the apex of the zone.
1193 dns_dbnode_t
*node
= NULL
;
1194 dns_fixedname_t fixed
;
1196 isc_result_t result
;
1198 dns_fixedname_init(&fixed
);
1199 name
= dns_fixedname_name(&fixed
);
1200 result
= dns_dbiterator_current(gdbiter
, &node
, name
);
1201 check_result(result
, "dns_dbiterator_current()");
1202 signname(node
, name
);
1203 dumpnode(name
, node
);
1204 cleannode(gdb
, gversion
, node
);
1205 dns_db_detachnode(gdb
, &node
);
1206 result
= dns_dbiterator_next(gdbiter
);
1207 if (result
== ISC_R_NOMORE
)
1208 finished
= ISC_TRUE
;
1209 else if (result
!= ISC_R_SUCCESS
)
1210 fatal("failure iterating database: %s",
1211 isc_result_totext(result
));
1215 * Assigns a node to a worker thread. This is protected by the master task's
1219 assignwork(isc_task_t
*task
, isc_task_t
*worker
) {
1220 dns_fixedname_t
*fname
;
1224 dns_rdataset_t nsec
;
1225 isc_boolean_t found
;
1226 isc_result_t result
;
1232 if (assigned
== completed
) {
1233 isc_task_detach(&task
);
1239 fname
= isc_mem_get(mctx
, sizeof(dns_fixedname_t
));
1241 fatal("out of memory");
1242 dns_fixedname_init(fname
);
1243 name
= dns_fixedname_name(fname
);
1248 result
= dns_dbiterator_current(gdbiter
, &node
, name
);
1249 if (result
!= ISC_R_SUCCESS
)
1250 fatal("failure iterating database: %s",
1251 isc_result_totext(result
));
1252 dns_rdataset_init(&nsec
);
1253 result
= dns_db_findrdataset(gdb
, node
, gversion
,
1254 dns_rdatatype_nsec
, 0, 0,
1256 if (result
== ISC_R_SUCCESS
)
1259 dumpnode(name
, node
);
1260 if (dns_rdataset_isassociated(&nsec
))
1261 dns_rdataset_disassociate(&nsec
);
1263 dns_db_detachnode(gdb
, &node
);
1265 result
= dns_dbiterator_next(gdbiter
);
1266 if (result
== ISC_R_NOMORE
) {
1267 finished
= ISC_TRUE
;
1269 } else if (result
!= ISC_R_SUCCESS
)
1270 fatal("failure iterating database: %s",
1271 isc_result_totext(result
));
1275 if (assigned
== completed
) {
1276 isc_task_detach(&task
);
1279 isc_mem_put(mctx
, fname
, sizeof(dns_fixedname_t
));
1282 sevent
= (sevent_t
*)
1283 isc_event_allocate(mctx
, task
, SIGNER_EVENT_WORK
,
1284 sign
, NULL
, sizeof(sevent_t
));
1286 fatal("failed to allocate event\n");
1288 sevent
->node
= node
;
1289 sevent
->fname
= fname
;
1290 isc_task_send(worker
, ISC_EVENT_PTR(&sevent
));
1295 * Start a worker task
1298 startworker(isc_task_t
*task
, isc_event_t
*event
) {
1301 worker
= (isc_task_t
*)event
->ev_arg
;
1302 assignwork(task
, worker
);
1303 isc_event_free(&event
);
1307 * Write a node to the output file, and restart the worker task.
1310 writenode(isc_task_t
*task
, isc_event_t
*event
) {
1312 sevent_t
*sevent
= (sevent_t
*)event
;
1315 worker
= (isc_task_t
*)event
->ev_sender
;
1316 dumpnode(dns_fixedname_name(sevent
->fname
), sevent
->node
);
1317 cleannode(gdb
, gversion
, sevent
->node
);
1318 dns_db_detachnode(gdb
, &sevent
->node
);
1319 isc_mem_put(mctx
, sevent
->fname
, sizeof(dns_fixedname_t
));
1320 assignwork(task
, worker
);
1321 isc_event_free(&event
);
1325 * Sign a database node.
1328 sign(isc_task_t
*task
, isc_event_t
*event
) {
1329 dns_fixedname_t
*fname
;
1331 sevent_t
*sevent
, *wevent
;
1333 sevent
= (sevent_t
*)event
;
1334 node
= sevent
->node
;
1335 fname
= sevent
->fname
;
1336 isc_event_free(&event
);
1338 signname(node
, dns_fixedname_name(fname
));
1339 wevent
= (sevent_t
*)
1340 isc_event_allocate(mctx
, task
, SIGNER_EVENT_WRITE
,
1341 writenode
, NULL
, sizeof(sevent_t
));
1343 fatal("failed to allocate event\n");
1344 wevent
->node
= node
;
1345 wevent
->fname
= fname
;
1346 isc_task_send(master
, ISC_EVENT_PTR(&wevent
));
1350 * Generate NSEC records for the zone.
1354 dns_dbiterator_t
*dbiter
= NULL
;
1355 dns_dbnode_t
*node
= NULL
, *nextnode
= NULL
;
1356 dns_fixedname_t fname
, fnextname
, fzonecut
;
1357 dns_name_t
*name
, *nextname
, *zonecut
;
1358 isc_boolean_t done
= ISC_FALSE
;
1359 isc_result_t result
;
1361 dns_fixedname_init(&fname
);
1362 name
= dns_fixedname_name(&fname
);
1363 dns_fixedname_init(&fnextname
);
1364 nextname
= dns_fixedname_name(&fnextname
);
1365 dns_fixedname_init(&fzonecut
);
1368 result
= dns_db_createiterator(gdb
, ISC_FALSE
, &dbiter
);
1369 check_result(result
, "dns_db_createiterator()");
1371 result
= dns_dbiterator_first(dbiter
);
1372 check_result(result
, "dns_dbiterator_first()");
1375 dns_dbiterator_current(dbiter
, &node
, name
);
1376 if (delegation(name
, node
, NULL
)) {
1377 zonecut
= dns_fixedname_name(&fzonecut
);
1378 dns_name_copy(name
, zonecut
, NULL
);
1380 result
= dns_dbiterator_next(dbiter
);
1382 while (result
== ISC_R_SUCCESS
) {
1383 isc_boolean_t active
= ISC_FALSE
;
1384 result
= dns_dbiterator_current(dbiter
, &nextnode
,
1386 if (result
!= ISC_R_SUCCESS
)
1388 active
= active_node(nextnode
);
1390 dns_db_detachnode(gdb
, &nextnode
);
1391 result
= dns_dbiterator_next(dbiter
);
1394 if (!dns_name_issubdomain(nextname
, gorigin
) ||
1396 dns_name_issubdomain(nextname
, zonecut
)))
1398 dns_db_detachnode(gdb
, &nextnode
);
1399 result
= dns_dbiterator_next(dbiter
);
1402 dns_db_detachnode(gdb
, &nextnode
);
1405 if (result
== ISC_R_NOMORE
) {
1406 dns_name_clone(gorigin
, nextname
);
1408 } else if (result
!= ISC_R_SUCCESS
)
1409 fatal("iterating through the database failed: %s",
1410 isc_result_totext(result
));
1411 result
= dns_nsec_build(gdb
, gversion
, node
, nextname
,
1413 check_result(result
, "dns_nsec_build()");
1414 dns_db_detachnode(gdb
, &node
);
1417 dns_dbiterator_destroy(&dbiter
);
1421 * Load the zone file from disk
1424 loadzone(char *file
, char *origin
, dns_rdataclass_t rdclass
, dns_db_t
**db
) {
1427 dns_fixedname_t fname
;
1429 isc_result_t result
;
1431 len
= strlen(origin
);
1432 isc_buffer_init(&b
, origin
, len
);
1433 isc_buffer_add(&b
, len
);
1435 dns_fixedname_init(&fname
);
1436 name
= dns_fixedname_name(&fname
);
1437 result
= dns_name_fromtext(name
, &b
, dns_rootname
, ISC_FALSE
, NULL
);
1438 if (result
!= ISC_R_SUCCESS
)
1439 fatal("failed converting name '%s' to dns format: %s",
1440 origin
, isc_result_totext(result
));
1442 result
= dns_db_create(mctx
, "rbt", name
, dns_dbtype_zone
,
1443 rdclass
, 0, NULL
, db
);
1444 check_result(result
, "dns_db_create()");
1446 result
= dns_db_load2(*db
, file
, inputformat
);
1447 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_SEENINCLUDE
)
1448 fatal("failed loading zone from '%s': %s",
1449 file
, isc_result_totext(result
));
1453 * Finds all public zone keys in the zone, and attempts to load the
1454 * private keys from disk.
1457 loadzonekeys(dns_db_t
*db
) {
1459 dns_dbversion_t
*currentversion
;
1460 isc_result_t result
;
1461 dst_key_t
*keys
[20];
1462 unsigned int nkeys
, i
;
1464 currentversion
= NULL
;
1465 dns_db_currentversion(db
, ¤tversion
);
1468 result
= dns_db_findnode(db
, gorigin
, ISC_FALSE
, &node
);
1469 if (result
!= ISC_R_SUCCESS
)
1470 fatal("failed to find the zone's origin: %s",
1471 isc_result_totext(result
));
1473 result
= dns_dnssec_findzonekeys(db
, currentversion
, node
, gorigin
,
1474 mctx
, 20, keys
, &nkeys
);
1475 if (result
== ISC_R_NOTFOUND
)
1476 result
= ISC_R_SUCCESS
;
1477 if (result
!= ISC_R_SUCCESS
)
1478 fatal("failed to find the zone keys: %s",
1479 isc_result_totext(result
));
1481 for (i
= 0; i
< nkeys
; i
++) {
1484 key
= newkeystruct(keys
[i
], dst_key_isprivate(keys
[i
]));
1485 ISC_LIST_APPEND(keylist
, key
, link
);
1487 dns_db_detachnode(db
, &node
);
1488 dns_db_closeversion(db
, ¤tversion
, ISC_FALSE
);
1492 * Finds all public zone keys in the zone.
1495 loadzonepubkeys(dns_db_t
*db
) {
1496 dns_dbversion_t
*currentversion
= NULL
;
1497 dns_dbnode_t
*node
= NULL
;
1498 dns_rdataset_t rdataset
;
1499 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1502 isc_result_t result
;
1504 dns_db_currentversion(db
, ¤tversion
);
1506 result
= dns_db_findnode(db
, gorigin
, ISC_FALSE
, &node
);
1507 if (result
!= ISC_R_SUCCESS
)
1508 fatal("failed to find the zone's origin: %s",
1509 isc_result_totext(result
));
1511 dns_rdataset_init(&rdataset
);
1512 result
= dns_db_findrdataset(db
, node
, currentversion
,
1513 dns_rdatatype_dnskey
, 0, 0, &rdataset
, NULL
);
1514 if (result
!= ISC_R_SUCCESS
)
1515 fatal("failed to find keys at the zone apex: %s",
1516 isc_result_totext(result
));
1517 result
= dns_rdataset_first(&rdataset
);
1518 check_result(result
, "dns_rdataset_first");
1519 while (result
== ISC_R_SUCCESS
) {
1521 dns_rdata_reset(&rdata
);
1522 dns_rdataset_current(&rdataset
, &rdata
);
1523 result
= dns_dnssec_keyfromrdata(gorigin
, &rdata
, mctx
,
1525 if (result
!= ISC_R_SUCCESS
)
1527 if (!dst_key_iszonekey(pubkey
)) {
1528 dst_key_free(&pubkey
);
1532 key
= newkeystruct(pubkey
, ISC_FALSE
);
1533 ISC_LIST_APPEND(keylist
, key
, link
);
1535 result
= dns_rdataset_next(&rdataset
);
1537 dns_rdataset_disassociate(&rdataset
);
1538 dns_db_detachnode(db
, &node
);
1539 dns_db_closeversion(db
, ¤tversion
, ISC_FALSE
);
1543 warnifallksk(dns_db_t
*db
) {
1544 dns_dbversion_t
*currentversion
= NULL
;
1545 dns_dbnode_t
*node
= NULL
;
1546 dns_rdataset_t rdataset
;
1547 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1548 isc_result_t result
;
1549 dns_rdata_key_t key
;
1550 isc_boolean_t have_non_ksk
= ISC_FALSE
;
1552 dns_db_currentversion(db
, ¤tversion
);
1554 result
= dns_db_findnode(db
, gorigin
, ISC_FALSE
, &node
);
1555 if (result
!= ISC_R_SUCCESS
)
1556 fatal("failed to find the zone's origin: %s",
1557 isc_result_totext(result
));
1559 dns_rdataset_init(&rdataset
);
1560 result
= dns_db_findrdataset(db
, node
, currentversion
,
1561 dns_rdatatype_dnskey
, 0, 0, &rdataset
, NULL
);
1562 if (result
!= ISC_R_SUCCESS
)
1563 fatal("failed to find keys at the zone apex: %s",
1564 isc_result_totext(result
));
1565 result
= dns_rdataset_first(&rdataset
);
1566 check_result(result
, "dns_rdataset_first");
1567 while (result
== ISC_R_SUCCESS
) {
1568 dns_rdata_reset(&rdata
);
1569 dns_rdataset_current(&rdataset
, &rdata
);
1570 result
= dns_rdata_tostruct(&rdata
, &key
, NULL
);
1571 check_result(result
, "dns_rdata_tostruct");
1572 if ((key
.flags
& DNS_KEYFLAG_KSK
) == 0) {
1573 have_non_ksk
= ISC_TRUE
;
1574 result
= ISC_R_NOMORE
;
1576 result
= dns_rdataset_next(&rdataset
);
1578 dns_rdataset_disassociate(&rdataset
);
1579 dns_db_detachnode(db
, &node
);
1580 dns_db_closeversion(db
, ¤tversion
, ISC_FALSE
);
1581 if (!have_non_ksk
&& !ignoreksk
)
1582 fprintf(stderr
, "%s: warning: No non-KSK dnskey found. "
1583 "Supply non-KSK dnskey or use '-z'.\n",
1588 writeset(const char *prefix
, dns_rdatatype_t type
) {
1590 char namestr
[DNS_NAME_FORMATSIZE
];
1591 dns_db_t
*db
= NULL
;
1592 dns_dbversion_t
*version
= NULL
;
1594 dns_difftuple_t
*tuple
= NULL
;
1595 dns_fixedname_t fixed
;
1597 dns_rdata_t rdata
, ds
;
1598 isc_boolean_t have_ksk
= ISC_FALSE
;
1599 isc_boolean_t have_non_ksk
= ISC_FALSE
;
1601 isc_buffer_t namebuf
;
1603 isc_result_t result
;
1605 unsigned char dsbuf
[DNS_DS_BUFFERSIZE
];
1606 unsigned char keybuf
[DST_KEY_MAXSIZE
];
1607 unsigned int filenamelen
;
1608 const dns_master_style_t
*style
=
1609 (type
== dns_rdatatype_dnskey
) ? masterstyle
: dsstyle
;
1611 isc_buffer_init(&namebuf
, namestr
, sizeof(namestr
));
1612 result
= dns_name_tofilenametext(gorigin
, ISC_FALSE
, &namebuf
);
1613 check_result(result
, "dns_name_tofilenametext");
1614 isc_buffer_putuint8(&namebuf
, 0);
1615 filenamelen
= strlen(prefix
) + strlen(namestr
);
1616 if (directory
!= NULL
)
1617 filenamelen
+= strlen(directory
) + 1;
1618 filename
= isc_mem_get(mctx
, filenamelen
+ 1);
1619 if (filename
== NULL
)
1620 fatal("out of memory");
1621 if (directory
!= NULL
)
1622 sprintf(filename
, "%s/", directory
);
1625 strcat(filename
, prefix
);
1626 strcat(filename
, namestr
);
1628 dns_diff_init(mctx
, &diff
);
1630 for (key
= ISC_LIST_HEAD(keylist
);
1632 key
= ISC_LIST_NEXT(key
, link
))
1634 have_non_ksk
= ISC_TRUE
;
1638 for (key
= ISC_LIST_HEAD(keylist
);
1640 key
= ISC_LIST_NEXT(key
, link
))
1642 have_ksk
= ISC_TRUE
;
1646 if (type
== dns_rdatatype_dlv
) {
1648 unsigned int labels
;
1650 dns_name_init(&tname
, NULL
);
1651 dns_fixedname_init(&fixed
);
1652 name
= dns_fixedname_name(&fixed
);
1653 labels
= dns_name_countlabels(gorigin
);
1654 dns_name_getlabelsequence(gorigin
, 0, labels
- 1, &tname
);
1655 result
= dns_name_concatenate(&tname
, dlv
, name
, NULL
);
1656 check_result(result
, "dns_name_concatenate");
1660 for (key
= ISC_LIST_HEAD(keylist
);
1662 key
= ISC_LIST_NEXT(key
, link
))
1664 if (have_ksk
&& have_non_ksk
&& !key
->isksk
)
1666 dns_rdata_init(&rdata
);
1667 dns_rdata_init(&ds
);
1668 isc_buffer_init(&b
, keybuf
, sizeof(keybuf
));
1669 result
= dst_key_todns(key
->key
, &b
);
1670 check_result(result
, "dst_key_todns");
1671 isc_buffer_usedregion(&b
, &r
);
1672 dns_rdata_fromregion(&rdata
, gclass
, dns_rdatatype_dnskey
, &r
);
1673 if (type
!= dns_rdatatype_dnskey
) {
1674 result
= dns_ds_buildrdata(gorigin
, &rdata
,
1677 check_result(result
, "dns_ds_buildrdata");
1678 if (type
== dns_rdatatype_dlv
)
1679 ds
.type
= dns_rdatatype_dlv
;
1680 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
,
1681 name
, 0, &ds
, &tuple
);
1682 check_result(result
, "dns_difftuple_create");
1683 dns_diff_append(&diff
, &tuple
);
1685 dns_rdata_reset(&ds
);
1686 result
= dns_ds_buildrdata(gorigin
, &rdata
,
1687 DNS_DSDIGEST_SHA256
,
1689 check_result(result
, "dns_ds_buildrdata");
1690 if (type
== dns_rdatatype_dlv
)
1691 ds
.type
= dns_rdatatype_dlv
;
1692 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
,
1693 name
, 0, &ds
, &tuple
);
1696 result
= dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
,
1699 check_result(result
, "dns_difftuple_create");
1700 dns_diff_append(&diff
, &tuple
);
1703 result
= dns_db_create(mctx
, "rbt", dns_rootname
, dns_dbtype_zone
,
1704 gclass
, 0, NULL
, &db
);
1705 check_result(result
, "dns_db_create");
1707 result
= dns_db_newversion(db
, &version
);
1708 check_result(result
, "dns_db_newversion");
1710 result
= dns_diff_apply(&diff
, db
, version
);
1711 check_result(result
, "dns_diff_apply");
1712 dns_diff_clear(&diff
);
1714 result
= dns_master_dump(mctx
, db
, version
, style
, filename
);
1715 check_result(result
, "dns_master_dump");
1717 isc_mem_put(mctx
, filename
, filenamelen
+ 1);
1719 dns_db_closeversion(db
, &version
, ISC_FALSE
);
1724 print_time(FILE *fp
) {
1727 if (outputformat
!= dns_masterformat_text
)
1730 currenttime
= time(NULL
);
1731 fprintf(fp
, "; File written on %s", ctime(¤ttime
));
1735 print_version(FILE *fp
) {
1736 if (outputformat
!= dns_masterformat_text
)
1739 fprintf(fp
, "; dnssec_signzone version " VERSION
"\n");
1744 fprintf(stderr
, "Usage:\n");
1745 fprintf(stderr
, "\t%s [options] zonefile [keys]\n", program
);
1747 fprintf(stderr
, "\n");
1749 fprintf(stderr
, "Version: %s\n", VERSION
);
1751 fprintf(stderr
, "Options: (default value in parenthesis) \n");
1752 fprintf(stderr
, "\t-c class (IN)\n");
1753 fprintf(stderr
, "\t-d directory\n");
1754 fprintf(stderr
, "\t\tdirectory to find keyset files (.)\n");
1755 fprintf(stderr
, "\t-g:\t");
1756 fprintf(stderr
, "generate DS records from keyset files\n");
1757 fprintf(stderr
, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
1758 fprintf(stderr
, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n");
1759 fprintf(stderr
, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
1760 fprintf(stderr
, "\t\tRRSIG end time - absolute|from start|from now "
1761 "(now + 30 days)\n");
1762 fprintf(stderr
, "\t-i interval:\n");
1763 fprintf(stderr
, "\t\tcycle interval - resign "
1764 "if < interval from end ( (end-start)/4 )\n");
1765 fprintf(stderr
, "\t-j jitter:\n");
1766 fprintf(stderr
, "\t\trandomize signature end time up to jitter seconds\n");
1767 fprintf(stderr
, "\t-v debuglevel (0)\n");
1768 fprintf(stderr
, "\t-o origin:\n");
1769 fprintf(stderr
, "\t\tzone origin (name of zonefile)\n");
1770 fprintf(stderr
, "\t-f outfile:\n");
1771 fprintf(stderr
, "\t\tfile the signed zone is written in "
1772 "(zonefile + .signed)\n");
1773 fprintf(stderr
, "\t-I format:\n");
1774 fprintf(stderr
, "\t\tfile format of input zonefile (text)\n");
1775 fprintf(stderr
, "\t-O format:\n");
1776 fprintf(stderr
, "\t\tfile format of signed zone file (text)\n");
1777 fprintf(stderr
, "\t-N format:\n");
1778 fprintf(stderr
, "\t\tsoa serial format of signed zone file (keep)\n");
1779 fprintf(stderr
, "\t-r randomdev:\n");
1780 fprintf(stderr
, "\t\ta file containing random data\n");
1781 fprintf(stderr
, "\t-a:\t");
1782 fprintf(stderr
, "verify generated signatures\n");
1783 fprintf(stderr
, "\t-p:\t");
1784 fprintf(stderr
, "use pseudorandom data (faster but less secure)\n");
1785 fprintf(stderr
, "\t-t:\t");
1786 fprintf(stderr
, "print statistics\n");
1787 fprintf(stderr
, "\t-n ncpus (number of cpus present)\n");
1788 fprintf(stderr
, "\t-k key_signing_key\n");
1789 fprintf(stderr
, "\t-l lookasidezone\n");
1790 fprintf(stderr
, "\t-z:\t");
1791 fprintf(stderr
, "ignore KSK flag in DNSKEYs");
1793 fprintf(stderr
, "\n");
1795 fprintf(stderr
, "Signing Keys: ");
1796 fprintf(stderr
, "(default: all zone keys that have private keys)\n");
1797 fprintf(stderr
, "\tkeyfile (Kname+alg+tag)\n");
1802 removetempfile(void) {
1804 isc_file_remove(tempfile
);
1808 print_stats(isc_time_t
*timer_start
, isc_time_t
*timer_finish
) {
1809 isc_uint64_t runtime_us
; /* Runtime in microseconds */
1810 isc_uint64_t runtime_ms
; /* Runtime in milliseconds */
1811 isc_uint64_t sig_ms
; /* Signatures per millisecond */
1813 runtime_us
= isc_time_microdiff(timer_finish
, timer_start
);
1815 printf("Signatures generated: %10d\n", nsigned
);
1816 printf("Signatures retained: %10d\n", nretained
);
1817 printf("Signatures dropped: %10d\n", ndropped
);
1818 printf("Signatures successfully verified: %10d\n", nverified
);
1819 printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed
);
1820 runtime_ms
= runtime_us
/ 1000;
1821 printf("Runtime in seconds: %7u.%03u\n",
1822 (unsigned int) (runtime_ms
/ 1000),
1823 (unsigned int) (runtime_ms
% 1000));
1824 if (runtime_us
> 0) {
1825 sig_ms
= ((isc_uint64_t
)nsigned
* 1000000000) / runtime_us
;
1826 printf("Signatures per second: %7u.%03u\n",
1827 (unsigned int) sig_ms
/ 1000,
1828 (unsigned int) sig_ms
% 1000);
1833 main(int argc
, char *argv
[]) {
1835 char *startstr
= NULL
, *endstr
= NULL
, *classname
= NULL
;
1836 char *origin
= NULL
, *file
= NULL
, *output
= NULL
;
1837 char *inputformatstr
= NULL
, *outputformatstr
= NULL
;
1838 char *serialformatstr
= NULL
;
1839 char *dskeyfile
[MAXDSKEYS
];
1842 isc_time_t timer_start
, timer_finish
;
1844 isc_result_t result
;
1845 isc_log_t
*log
= NULL
;
1846 isc_boolean_t pseudorandom
= ISC_FALSE
;
1847 unsigned int eflags
;
1848 isc_boolean_t free_output
= ISC_FALSE
;
1850 dns_rdataclass_t rdclass
;
1851 isc_task_t
**tasks
= NULL
;
1855 masterstyle
= &dns_master_style_explicitttl
;
1857 check_result(isc_app_start(), "isc_app_start");
1859 result
= isc_mem_create(0, 0, &mctx
);
1860 if (result
!= ISC_R_SUCCESS
)
1861 fatal("out of memory");
1863 dns_result_register();
1865 while ((ch
= isc_commandline_parse(argc
, argv
,
1866 "ac:d:e:f:ghi:I:j:k:l:n:N:o:O:pr:s:Stv:z"))
1870 tryverify
= ISC_TRUE
;
1874 classname
= isc_commandline_argument
;
1878 directory
= isc_commandline_argument
;
1882 endstr
= isc_commandline_argument
;
1886 output
= isc_commandline_argument
;
1890 generateds
= ISC_TRUE
;
1900 cycle
= strtol(isc_commandline_argument
, &endp
, 0);
1901 if (*endp
!= '\0' || cycle
< 0)
1902 fatal("cycle period must be numeric and "
1907 inputformatstr
= isc_commandline_argument
;
1912 jitter
= strtol(isc_commandline_argument
, &endp
, 0);
1913 if (*endp
!= '\0' || jitter
< 0)
1914 fatal("jitter must be numeric and positive");
1918 dns_fixedname_init(&dlv_fixed
);
1919 len
= strlen(isc_commandline_argument
);
1920 isc_buffer_init(&b
, isc_commandline_argument
, len
);
1921 isc_buffer_add(&b
, len
);
1923 dns_fixedname_init(&dlv_fixed
);
1924 dlv
= dns_fixedname_name(&dlv_fixed
);
1925 result
= dns_name_fromtext(dlv
, &b
, dns_rootname
,
1927 check_result(result
, "dns_name_fromtext(dlv)");
1931 if (ndskeys
== MAXDSKEYS
)
1932 fatal("too many key-signing keys specified");
1933 dskeyfile
[ndskeys
++] = isc_commandline_argument
;
1938 ntasks
= strtol(isc_commandline_argument
, &endp
, 0);
1939 if (*endp
!= '\0' || ntasks
> ISC_INT32_MAX
)
1940 fatal("number of cpus must be numeric");
1944 serialformatstr
= isc_commandline_argument
;
1948 origin
= isc_commandline_argument
;
1952 outputformatstr
= isc_commandline_argument
;
1956 pseudorandom
= ISC_TRUE
;
1960 setup_entropy(mctx
, isc_commandline_argument
, &ectx
);
1964 startstr
= isc_commandline_argument
;
1968 /* This is intentionally undocumented */
1969 /* -S: simple output style */
1970 masterstyle
= &dns_master_style_simple
;
1974 printstats
= ISC_TRUE
;
1979 verbose
= strtol(isc_commandline_argument
, &endp
, 0);
1981 fatal("verbose level must be numeric");
1985 ignoreksk
= ISC_TRUE
;
1991 setup_entropy(mctx
, NULL
, &ectx
);
1992 eflags
= ISC_ENTROPY_BLOCKING
;
1994 eflags
|= ISC_ENTROPY_GOODONLY
;
1996 result
= isc_hash_create(mctx
, ectx
, DNS_NAME_MAXWIRE
);
1997 if (result
!= ISC_R_SUCCESS
)
1998 fatal("could not create hash context");
2000 result
= dst_lib_init(mctx
, ectx
, eflags
);
2001 if (result
!= ISC_R_SUCCESS
)
2002 fatal("could not initialize dst");
2004 isc_stdtime_get(&now
);
2006 if (startstr
!= NULL
)
2007 starttime
= strtotime(startstr
, now
, now
);
2009 starttime
= now
- 3600; /* Allow for some clock skew. */
2012 endtime
= strtotime(endstr
, now
, starttime
);
2014 endtime
= starttime
+ (30 * 24 * 60 * 60);
2017 cycle
= (endtime
- starttime
) / 4;
2020 ntasks
= isc_os_ncpus();
2021 vbprintf(4, "using %d cpus\n", ntasks
);
2023 rdclass
= strtoclass(classname
);
2025 setup_logging(verbose
, mctx
, &log
);
2027 argc
-= isc_commandline_index
;
2028 argv
+= isc_commandline_index
;
2041 if (output
== NULL
) {
2042 free_output
= ISC_TRUE
;
2043 output
= isc_mem_allocate(mctx
,
2044 strlen(file
) + strlen(".signed") + 1);
2046 fatal("out of memory");
2047 sprintf(output
, "%s.signed", file
);
2050 if (inputformatstr
!= NULL
) {
2051 if (strcasecmp(inputformatstr
, "text") == 0)
2052 inputformat
= dns_masterformat_text
;
2053 else if (strcasecmp(inputformatstr
, "raw") == 0)
2054 inputformat
= dns_masterformat_raw
;
2056 fatal("unknown file format: %s\n", inputformatstr
);
2059 if (outputformatstr
!= NULL
) {
2060 if (strcasecmp(outputformatstr
, "text") == 0)
2061 outputformat
= dns_masterformat_text
;
2062 else if (strcasecmp(outputformatstr
, "raw") == 0)
2063 outputformat
= dns_masterformat_raw
;
2065 fatal("unknown file format: %s\n", outputformatstr
);
2068 if (serialformatstr
!= NULL
) {
2069 if (strcasecmp(serialformatstr
, "keep") == 0)
2070 serialformat
= SOA_SERIAL_KEEP
;
2071 else if (strcasecmp(serialformatstr
, "increment") == 0 ||
2072 strcasecmp(serialformatstr
, "incr") == 0)
2073 serialformat
= SOA_SERIAL_INCREMENT
;
2074 else if (strcasecmp(serialformatstr
, "unixtime") == 0)
2075 serialformat
= SOA_SERIAL_UNIXTIME
;
2077 fatal("unknown soa serial format: %s\n", serialformatstr
);
2080 result
= dns_master_stylecreate(&dsstyle
, DNS_STYLEFLAG_NO_TTL
,
2081 0, 24, 0, 0, 0, 8, mctx
);
2082 check_result(result
, "dns_master_stylecreate");
2086 TIME_NOW(&timer_start
);
2087 loadzone(file
, origin
, rdclass
, &gdb
);
2088 gorigin
= dns_db_origin(gdb
);
2089 gclass
= dns_db_class(gdb
);
2092 ISC_LIST_INIT(keylist
);
2097 for (i
= 0; i
< argc
; i
++) {
2098 dst_key_t
*newkey
= NULL
;
2100 result
= dst_key_fromnamedfile(argv
[i
],
2104 if (result
!= ISC_R_SUCCESS
)
2105 fatal("cannot load dnskey %s: %s", argv
[i
],
2106 isc_result_totext(result
));
2108 key
= ISC_LIST_HEAD(keylist
);
2109 while (key
!= NULL
) {
2110 dst_key_t
*dkey
= key
->key
;
2111 if (dst_key_id(dkey
) == dst_key_id(newkey
) &&
2112 dst_key_alg(dkey
) == dst_key_alg(newkey
) &&
2113 dns_name_equal(dst_key_name(dkey
),
2114 dst_key_name(newkey
)))
2116 if (!dst_key_isprivate(dkey
))
2117 fatal("cannot sign zone with "
2118 "non-private dnskey %s",
2122 key
= ISC_LIST_NEXT(key
, link
);
2125 key
= newkeystruct(newkey
, ISC_TRUE
);
2126 ISC_LIST_APPEND(keylist
, key
, link
);
2128 dst_key_free(&newkey
);
2131 loadzonepubkeys(gdb
);
2134 for (i
= 0; i
< ndskeys
; i
++) {
2135 dst_key_t
*newkey
= NULL
;
2137 result
= dst_key_fromnamedfile(dskeyfile
[i
],
2141 if (result
!= ISC_R_SUCCESS
)
2142 fatal("cannot load dnskey %s: %s", dskeyfile
[i
],
2143 isc_result_totext(result
));
2145 key
= ISC_LIST_HEAD(keylist
);
2146 while (key
!= NULL
) {
2147 dst_key_t
*dkey
= key
->key
;
2148 if (dst_key_id(dkey
) == dst_key_id(newkey
) &&
2149 dst_key_alg(dkey
) == dst_key_alg(newkey
) &&
2150 dns_name_equal(dst_key_name(dkey
),
2151 dst_key_name(newkey
)))
2153 /* Override key flags. */
2154 key
->issigningkey
= ISC_TRUE
;
2155 key
->isksk
= ISC_TRUE
;
2156 key
->isdsk
= ISC_FALSE
;
2157 dst_key_free(&dkey
);
2161 key
= ISC_LIST_NEXT(key
, link
);
2164 /* Override dnskey flags. */
2165 key
= newkeystruct(newkey
, ISC_TRUE
);
2166 key
->isksk
= ISC_TRUE
;
2167 key
->isdsk
= ISC_FALSE
;
2168 ISC_LIST_APPEND(keylist
, key
, link
);
2172 if (ISC_LIST_EMPTY(keylist
)) {
2173 fprintf(stderr
, "%s: warning: No keys specified or found\n",
2181 result
= dns_db_newversion(gdb
, &gversion
);
2182 check_result(result
, "dns_db_newversion()");
2184 switch (serialformat
) {
2185 case SOA_SERIAL_INCREMENT
:
2188 case SOA_SERIAL_UNIXTIME
:
2191 case SOA_SERIAL_KEEP
:
2200 writeset("keyset-", dns_rdatatype_dnskey
);
2201 writeset("dsset-", dns_rdatatype_ds
);
2203 writeset("dlvset-", dns_rdatatype_dlv
);
2207 tempfilelen
= strlen(output
) + 20;
2208 tempfile
= isc_mem_get(mctx
, tempfilelen
);
2209 if (tempfile
== NULL
)
2210 fatal("out of memory");
2212 result
= isc_file_mktemplate(output
, tempfile
, tempfilelen
);
2213 check_result(result
, "isc_file_mktemplate");
2216 result
= isc_file_openunique(tempfile
, &fp
);
2217 if (result
!= ISC_R_SUCCESS
)
2218 fatal("failed to open temporary output file: %s",
2219 isc_result_totext(result
));
2220 removefile
= ISC_TRUE
;
2221 setfatalcallback(&removetempfile
);
2226 result
= isc_taskmgr_create(mctx
, ntasks
, 0, &taskmgr
);
2227 if (result
!= ISC_R_SUCCESS
)
2228 fatal("failed to create task manager: %s",
2229 isc_result_totext(result
));
2232 result
= isc_task_create(taskmgr
, 0, &master
);
2233 if (result
!= ISC_R_SUCCESS
)
2234 fatal("failed to create task: %s", isc_result_totext(result
));
2236 tasks
= isc_mem_get(mctx
, ntasks
* sizeof(isc_task_t
*));
2238 fatal("out of memory");
2239 for (i
= 0; i
< (int)ntasks
; i
++) {
2241 result
= isc_task_create(taskmgr
, 0, &tasks
[i
]);
2242 if (result
!= ISC_R_SUCCESS
)
2243 fatal("failed to create task: %s",
2244 isc_result_totext(result
));
2247 RUNTIME_CHECK(isc_mutex_init(&namelock
) == ISC_R_SUCCESS
);
2249 RUNTIME_CHECK(isc_mutex_init(&statslock
) == ISC_R_SUCCESS
);
2255 * There is more work to do. Spread it out over multiple
2256 * processors if possible.
2258 for (i
= 0; i
< (int)ntasks
; i
++) {
2259 result
= isc_app_onrun(mctx
, master
, startworker
,
2261 if (result
!= ISC_R_SUCCESS
)
2262 fatal("failed to start task: %s",
2263 isc_result_totext(result
));
2265 (void)isc_app_run();
2267 fatal("process aborted by user");
2269 isc_task_detach(&master
);
2270 shuttingdown
= ISC_TRUE
;
2271 for (i
= 0; i
< (int)ntasks
; i
++)
2272 isc_task_detach(&tasks
[i
]);
2273 isc_taskmgr_destroy(&taskmgr
);
2274 isc_mem_put(mctx
, tasks
, ntasks
* sizeof(isc_task_t
*));
2277 if (outputformat
!= dns_masterformat_text
) {
2278 result
= dns_master_dumptostream2(mctx
, gdb
, gversion
,
2279 masterstyle
, outputformat
,
2281 check_result(result
, "dns_master_dumptostream2");
2284 result
= isc_stdio_close(fp
);
2285 check_result(result
, "isc_stdio_close");
2286 removefile
= ISC_FALSE
;
2288 result
= isc_file_rename(tempfile
, output
);
2289 if (result
!= ISC_R_SUCCESS
)
2290 fatal("failed to rename temp file to %s: %s\n",
2291 output
, isc_result_totext(result
));
2293 DESTROYLOCK(&namelock
);
2295 DESTROYLOCK(&statslock
);
2297 printf("%s\n", output
);
2299 dns_db_closeversion(gdb
, &gversion
, ISC_FALSE
);
2300 dns_db_detach(&gdb
);
2302 while (!ISC_LIST_EMPTY(keylist
)) {
2303 key
= ISC_LIST_HEAD(keylist
);
2304 ISC_LIST_UNLINK(keylist
, key
, link
);
2305 dst_key_free(&key
->key
);
2306 isc_mem_put(mctx
, key
, sizeof(signer_key_t
));
2309 isc_mem_put(mctx
, tempfile
, tempfilelen
);
2312 isc_mem_free(mctx
, output
);
2314 dns_master_styledestroy(&dsstyle
, mctx
);
2316 cleanup_logging(&log
);
2319 cleanup_entropy(&ectx
);
2322 isc_mem_stats(mctx
, stdout
);
2323 isc_mem_destroy(&mctx
);
2325 (void) isc_app_finish();
2328 TIME_NOW(&timer_finish
);
2329 print_stats(&timer_start
, &timer_finish
);