xref: /netbsd-src/external/mpl/bind/dist/bin/dnssec/dnssec-signzone.c (revision f3cfa6f6ce31685c6c4a758bc430e69eb99f50a4)
1 /*	$NetBSD: dnssec-signzone.c,v 1.3 2019/01/09 16:54:59 christos Exp $	*/
2 
3 /*
4  * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  *
13  * Portions Copyright (C) Network Associates, Inc.
14  *
15  * Permission to use, copy, modify, and/or distribute this software for any
16  * purpose with or without fee is hereby granted, provided that the above
17  * copyright notice and this permission notice appear in all copies.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
20  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
22  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
24  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
25  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26  */
27 
28 /*! \file */
29 
30 #include <config.h>
31 
32 #include <inttypes.h>
33 #include <stdbool.h>
34 #include <stdlib.h>
35 #include <time.h>
36 #include <unistd.h>
37 
38 #include <isc/app.h>
39 #include <isc/base32.h>
40 #include <isc/commandline.h>
41 #include <isc/event.h>
42 #include <isc/file.h>
43 #include <isc/hash.h>
44 #include <isc/hex.h>
45 #include <isc/md.h>
46 #include <isc/mem.h>
47 #include <isc/mutex.h>
48 #include <isc/os.h>
49 #include <isc/print.h>
50 #include <isc/random.h>
51 #include <isc/rwlock.h>
52 #include <isc/serial.h>
53 #include <isc/safe.h>
54 #include <isc/stdio.h>
55 #include <isc/string.h>
56 #include <isc/task.h>
57 #include <isc/time.h>
58 #include <isc/util.h>
59 
60 #include <dns/db.h>
61 #include <dns/dbiterator.h>
62 #include <dns/diff.h>
63 #include <dns/dnssec.h>
64 #include <dns/ds.h>
65 #include <dns/fixedname.h>
66 #include <dns/keyvalues.h>
67 #include <dns/log.h>
68 #include <dns/master.h>
69 #include <dns/masterdump.h>
70 #include <dns/nsec.h>
71 #include <dns/nsec3.h>
72 #include <dns/rdata.h>
73 #include <dns/rdatalist.h>
74 #include <dns/rdataset.h>
75 #include <dns/rdataclass.h>
76 #include <dns/rdatasetiter.h>
77 #include <dns/rdatastruct.h>
78 #include <dns/rdatatype.h>
79 #include <dns/result.h>
80 #include <dns/soa.h>
81 #include <dns/time.h>
82 #include <dns/update.h>
83 #include <dns/zoneverify.h>
84 
85 #include <dst/dst.h>
86 
87 #if USE_PKCS11
88 #include <pk11/result.h>
89 #endif
90 
91 #include "dnssectool.h"
92 
93 #ifndef PATH_MAX
94 #define PATH_MAX 1024   /* WIN32, and others don't define this. */
95 #endif
96 
97 const char *program = "dnssec-signzone";
98 int verbose;
99 
100 typedef struct hashlist hashlist_t;
101 
102 static int nsec_datatype = dns_rdatatype_nsec;
103 
104 #define check_dns_dbiterator_current(result) \
105 	check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \
106 		     "dns_dbiterator_current()")
107 
108 #define IS_NSEC3	(nsec_datatype == dns_rdatatype_nsec3)
109 #define OPTOUT(x)	(((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
110 
111 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
112 
113 #define BUFSIZE 2048
114 #define MAXDSKEYS 8
115 
116 #define SIGNER_EVENTCLASS	ISC_EVENTCLASS(0x4453)
117 #define SIGNER_EVENT_WRITE	(SIGNER_EVENTCLASS + 0)
118 #define SIGNER_EVENT_WORK	(SIGNER_EVENTCLASS + 1)
119 
120 #define SOA_SERIAL_KEEP		0
121 #define SOA_SERIAL_INCREMENT	1
122 #define SOA_SERIAL_UNIXTIME	2
123 #define SOA_SERIAL_DATE		3
124 
125 typedef struct signer_event sevent_t;
126 struct signer_event {
127 	ISC_EVENT_COMMON(sevent_t);
128 	dns_fixedname_t *fname;
129 	dns_dbnode_t *node;
130 };
131 
132 static dns_dnsseckeylist_t keylist;
133 static unsigned int keycount = 0;
134 isc_rwlock_t keylist_lock;
135 static isc_stdtime_t starttime = 0, endtime = 0, dnskey_endtime = 0, now;
136 static int cycle = -1;
137 static int jitter = 0;
138 static bool tryverify = false;
139 static bool printstats = false;
140 static isc_mem_t *mctx = NULL;
141 static dns_ttl_t zone_soa_min_ttl;
142 static dns_ttl_t soa_ttl;
143 static FILE *outfp = NULL;
144 static char *tempfile = NULL;
145 static const dns_master_style_t *masterstyle;
146 static dns_masterformat_t inputformat = dns_masterformat_text;
147 static dns_masterformat_t outputformat = dns_masterformat_text;
148 static uint32_t rawversion = 1, serialnum = 0;
149 static bool snset = false;
150 static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
151 static unsigned int nverified = 0, nverifyfailed = 0;
152 static const char *directory = NULL, *dsdir = NULL;
153 static isc_mutex_t namelock, statslock;
154 static isc_taskmgr_t *taskmgr = NULL;
155 static dns_db_t *gdb;			/* The database */
156 static dns_dbversion_t *gversion;	/* The database version */
157 static dns_dbiterator_t *gdbiter;	/* The database iterator */
158 static dns_rdataclass_t gclass;		/* The class */
159 static dns_name_t *gorigin;		/* The database origin */
160 static int nsec3flags = 0;
161 static dns_iterations_t nsec3iter = 10U;
162 static unsigned char saltbuf[255];
163 static unsigned char *gsalt = saltbuf;
164 static size_t salt_length = 0;
165 static isc_task_t *master = NULL;
166 static unsigned int ntasks = 0;
167 static bool shuttingdown = false, finished = false;
168 static bool nokeys = false;
169 static bool removefile = false;
170 static bool generateds = false;
171 static bool ignore_kskflag = false;
172 static bool keyset_kskonly = false;
173 static dns_name_t *dlv = NULL;
174 static dns_fixedname_t dlv_fixed;
175 static dns_master_style_t *dsstyle = NULL;
176 static unsigned int serialformat = SOA_SERIAL_KEEP;
177 static unsigned int hash_length = 0;
178 static bool unknownalg = false;
179 static bool disable_zone_check = false;
180 static bool update_chain = false;
181 static bool set_keyttl = false;
182 static dns_ttl_t keyttl;
183 static bool smartsign = false;
184 static bool remove_orphansigs = false;
185 static bool remove_inactkeysigs = false;
186 static bool output_dnssec_only = false;
187 static bool output_stdout = false;
188 bool set_maxttl = false;
189 static dns_ttl_t maxttl = 0;
190 
191 #define INCSTAT(counter)		\
192 	if (printstats) {		\
193 		LOCK(&statslock);	\
194 		counter++;		\
195 		UNLOCK(&statslock);	\
196 	}
197 
198 static void
199 sign(isc_task_t *task, isc_event_t *event);
200 
201 /*%
202  * Store a copy of 'name' in 'fzonecut' and return a pointer to that copy.
203  */
204 static dns_name_t *
205 savezonecut(dns_fixedname_t *fzonecut, dns_name_t *name) {
206 	dns_name_t *result;
207 
208 	result = dns_fixedname_initname(fzonecut);
209 	dns_name_copy(name, result, NULL);
210 
211 	return (result);
212 }
213 
214 static void
215 dumpnode(dns_name_t *name, dns_dbnode_t *node) {
216 	dns_rdataset_t rds;
217 	dns_rdatasetiter_t *iter = NULL;
218 	isc_buffer_t *buffer = NULL;
219 	isc_region_t r;
220 	isc_result_t result;
221 	unsigned bufsize = 4096;
222 
223 	if (outputformat != dns_masterformat_text)
224 		return;
225 
226 	if (!output_dnssec_only) {
227 		result = dns_master_dumpnodetostream(mctx, gdb, gversion, node,
228 						     name, masterstyle, outfp);
229 		check_result(result, "dns_master_dumpnodetostream");
230 		return;
231 	}
232 
233 	result = dns_db_allrdatasets(gdb, node, gversion, 0, &iter);
234 	check_result(result, "dns_db_allrdatasets");
235 
236 	dns_rdataset_init(&rds);
237 
238 	result = isc_buffer_allocate(mctx, &buffer, bufsize);
239 	check_result(result, "isc_buffer_allocate");
240 
241 	for (result = dns_rdatasetiter_first(iter);
242 	     result == ISC_R_SUCCESS;
243 	     result = dns_rdatasetiter_next(iter)) {
244 
245 		dns_rdatasetiter_current(iter, &rds);
246 
247 		if (rds.type != dns_rdatatype_rrsig &&
248 		    rds.type != dns_rdatatype_nsec &&
249 		    rds.type != dns_rdatatype_nsec3 &&
250 		    rds.type != dns_rdatatype_nsec3param &&
251 		    (!smartsign || rds.type != dns_rdatatype_dnskey)) {
252 			dns_rdataset_disassociate(&rds);
253 			continue;
254 		}
255 
256 		for (;;) {
257 			result = dns_master_rdatasettotext(name, &rds,
258 							   masterstyle, buffer);
259 			if (result != ISC_R_NOSPACE)
260 				break;
261 
262 			bufsize <<= 1;
263 			isc_buffer_free(&buffer);
264 			result = isc_buffer_allocate(mctx, &buffer, bufsize);
265 			check_result(result, "isc_buffer_allocate");
266 		}
267 		check_result(result, "dns_master_rdatasettotext");
268 
269 		isc_buffer_usedregion(buffer, &r);
270 		result = isc_stdio_write(r.base, 1, r.length, outfp, NULL);
271 		check_result(result, "isc_stdio_write");
272 		isc_buffer_clear(buffer);
273 
274 		dns_rdataset_disassociate(&rds);
275 	}
276 
277 	isc_buffer_free(&buffer);
278 	dns_rdatasetiter_destroy(&iter);
279 }
280 
281 /*%
282  * Sign the given RRset with given key, and add the signature record to the
283  * given tuple.
284  */
285 static void
286 signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
287 	    dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
288 {
289 	isc_result_t result;
290 	isc_stdtime_t jendtime, expiry;
291 	char keystr[DST_KEY_FORMATSIZE];
292 	dns_rdata_t trdata = DNS_RDATA_INIT;
293 	unsigned char array[BUFSIZE];
294 	isc_buffer_t b;
295 	dns_difftuple_t *tuple;
296 
297 	dst_key_format(key, keystr, sizeof(keystr));
298 	vbprintf(1, "\t%s %s\n", logmsg, keystr);
299 
300 	if (rdataset->type == dns_rdatatype_dnskey)
301 		expiry = dnskey_endtime;
302 	else
303 		expiry = endtime;
304 
305 	jendtime = (jitter != 0) ? expiry - isc_random_uniform(jitter) : expiry;
306 	isc_buffer_init(&b, array, sizeof(array));
307 	result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
308 				 mctx, &b, &trdata);
309 	if (result != ISC_R_SUCCESS) {
310 		fatal("dnskey '%s' failed to sign data: %s",
311 		      keystr, isc_result_totext(result));
312 	}
313 	INCSTAT(nsigned);
314 
315 	if (tryverify) {
316 		result = dns_dnssec_verify(name, rdataset, key,
317 					   true, 0, mctx, &trdata, NULL);
318 		if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) {
319 			vbprintf(3, "\tsignature verified\n");
320 			INCSTAT(nverified);
321 		} else {
322 			vbprintf(3, "\tsignature failed to verify\n");
323 			INCSTAT(nverifyfailed);
324 		}
325 	}
326 
327 	tuple = NULL;
328 	result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN,
329 				      name, ttl, &trdata, &tuple);
330 	check_result(result, "dns_difftuple_create");
331 	dns_diff_append(add, &tuple);
332 }
333 
334 static inline bool
335 issigningkey(dns_dnsseckey_t *key) {
336 	return (key->force_sign || key->hint_sign);
337 }
338 
339 static inline bool
340 ispublishedkey(dns_dnsseckey_t *key) {
341 	return ((key->force_publish || key->hint_publish) &&
342 		!key->hint_remove);
343 }
344 
345 static inline bool
346 iszonekey(dns_dnsseckey_t *key) {
347 	return (dns_name_equal(dst_key_name(key->key), gorigin) &&
348 		dst_key_iszonekey(key->key));
349 }
350 
351 static inline bool
352 isksk(dns_dnsseckey_t *key) {
353 	return (key->ksk);
354 }
355 
356 static inline bool
357 iszsk(dns_dnsseckey_t *key) {
358 	return (ignore_kskflag || !key->ksk);
359 }
360 
361 /*%
362  * Find the key that generated an RRSIG, if it is in the key list.  If
363  * so, return a pointer to it, otherwise return NULL.
364  *
365  * No locking is performed here, this must be done by the caller.
366  */
367 static dns_dnsseckey_t *
368 keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
369 	dns_dnsseckey_t *key;
370 
371 	for (key = ISC_LIST_HEAD(keylist);
372 	     key != NULL;
373 	     key = ISC_LIST_NEXT(key, link)) {
374 		if (rrsig->keyid == dst_key_id(key->key) &&
375 		    rrsig->algorithm == dst_key_alg(key->key) &&
376 		    dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
377 			return (key);
378 	}
379 	return (NULL);
380 }
381 
382 /*%
383  * Finds the key that generated a RRSIG, if possible.  First look at the keys
384  * that we've loaded already, and then see if there's a key on disk.
385  */
386 static dns_dnsseckey_t *
387 keythatsigned(dns_rdata_rrsig_t *rrsig) {
388 	isc_result_t result;
389 	dst_key_t *pubkey = NULL, *privkey = NULL;
390 	dns_dnsseckey_t *key = NULL;
391 
392 	isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
393 	key = keythatsigned_unlocked(rrsig);
394 	isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
395 	if (key != NULL)
396 		return (key);
397 
398 	/*
399 	 * We did not find the key in our list.  Get a write lock now, since
400 	 * we may be modifying the bits.  We could do the tryupgrade() dance,
401 	 * but instead just get a write lock and check once again to see if
402 	 * it is on our list.  It's possible someone else may have added it
403 	 * after all.
404 	 */
405 	isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
406 	key = keythatsigned_unlocked(rrsig);
407 	if (key != NULL) {
408 		isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
409 		return (key);
410 	}
411 
412 	result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
413 				  rrsig->algorithm, DST_TYPE_PUBLIC,
414 				  directory, mctx, &pubkey);
415 	if (result != ISC_R_SUCCESS) {
416 		isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
417 		return (NULL);
418 	}
419 
420 	result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
421 				  rrsig->algorithm,
422 				  DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
423 				  directory, mctx, &privkey);
424 	if (result == ISC_R_SUCCESS) {
425 		dst_key_free(&pubkey);
426 		result = dns_dnsseckey_create(mctx, &privkey, &key);
427 	} else
428 		result = dns_dnsseckey_create(mctx, &pubkey, &key);
429 
430 	if (result == ISC_R_SUCCESS) {
431 		key->force_publish = false;
432 		key->force_sign = false;
433 		key->index = keycount++;
434 		ISC_LIST_APPEND(keylist, key, link);
435 	}
436 
437 	isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
438 	return (key);
439 }
440 
441 /*%
442  * Check to see if we expect to find a key at this name.  If we see a RRSIG
443  * and can't find the signing key that we expect to find, we drop the rrsig.
444  * I'm not sure if this is completely correct, but it seems to work.
445  */
446 static bool
447 expecttofindkey(dns_name_t *name) {
448 	unsigned int options = DNS_DBFIND_NOWILD;
449 	dns_fixedname_t fname;
450 	isc_result_t result;
451 	char namestr[DNS_NAME_FORMATSIZE];
452 
453 	dns_fixedname_init(&fname);
454 	result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
455 			     0, NULL, dns_fixedname_name(&fname), NULL, NULL);
456 	switch (result) {
457 	case ISC_R_SUCCESS:
458 	case DNS_R_NXDOMAIN:
459 	case DNS_R_NXRRSET:
460 		return (true);
461 	case DNS_R_DELEGATION:
462 	case DNS_R_CNAME:
463 	case DNS_R_DNAME:
464 		return (false);
465 	}
466 	dns_name_format(name, namestr, sizeof(namestr));
467 	fatal("failure looking for '%s DNSKEY' in database: %s",
468 	      namestr, isc_result_totext(result));
469 	/* NOTREACHED */
470 	return (false); /* removes a warning */
471 }
472 
473 static inline bool
474 setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
475 	    dns_rdata_t *rrsig)
476 {
477 	isc_result_t result;
478 	result = dns_dnssec_verify(name, set, key, false, 0, mctx, rrsig,
479 				   NULL);
480 	if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) {
481 		INCSTAT(nverified);
482 		return (true);
483 	} else {
484 		INCSTAT(nverifyfailed);
485 		return (false);
486 	}
487 }
488 
489 /*%
490  * Signs a set.  Goes through contortions to decide if each RRSIG should
491  * be dropped or retained, and then determines if any new SIGs need to
492  * be generated.
493  */
494 static void
495 signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
496 	dns_rdataset_t *set)
497 {
498 	dns_rdataset_t sigset;
499 	dns_rdata_t sigrdata = DNS_RDATA_INIT;
500 	dns_rdata_rrsig_t rrsig;
501 	dns_dnsseckey_t *key;
502 	isc_result_t result;
503 	bool nosigs = false;
504 	bool *wassignedby, *nowsignedby;
505 	int arraysize;
506 	dns_difftuple_t *tuple;
507 	dns_ttl_t ttl;
508 	int i;
509 	char namestr[DNS_NAME_FORMATSIZE];
510 	char typestr[DNS_RDATATYPE_FORMATSIZE];
511 	char sigstr[SIG_FORMATSIZE];
512 
513 	dns_name_format(name, namestr, sizeof(namestr));
514 	dns_rdatatype_format(set->type, typestr, sizeof(typestr));
515 
516 	ttl = ISC_MIN(set->ttl, endtime - starttime);
517 
518 	dns_rdataset_init(&sigset);
519 	result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
520 				     set->type, 0, &sigset, NULL);
521 	if (result == ISC_R_NOTFOUND) {
522 		vbprintf(2, "no existing signatures for %s/%s\n",
523 			 namestr, typestr);
524 		result = ISC_R_SUCCESS;
525 		nosigs = true;
526 	}
527 	if (result != ISC_R_SUCCESS)
528 		fatal("failed while looking for '%s RRSIG %s': %s",
529 		      namestr, typestr, isc_result_totext(result));
530 
531 	vbprintf(1, "%s/%s:\n", namestr, typestr);
532 
533 	arraysize = keycount;
534 	if (!nosigs)
535 		arraysize += dns_rdataset_count(&sigset);
536 	wassignedby = isc_mem_get(mctx, arraysize * sizeof(bool));
537 	nowsignedby = isc_mem_get(mctx, arraysize * sizeof(bool));
538 
539 	for (i = 0; i < arraysize; i++)
540 		wassignedby[i] = nowsignedby[i] = false;
541 
542 	if (nosigs)
543 		result = ISC_R_NOMORE;
544 	else
545 		result = dns_rdataset_first(&sigset);
546 
547 	while (result == ISC_R_SUCCESS) {
548 		bool expired, future;
549 		bool keep = false, resign = false;
550 
551 		dns_rdataset_current(&sigset, &sigrdata);
552 
553 		result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
554 		check_result(result, "dns_rdata_tostruct");
555 
556 		future = isc_serial_lt(now, rrsig.timesigned);
557 
558 		key = keythatsigned(&rrsig);
559 		sig_format(&rrsig, sigstr, sizeof(sigstr));
560 		if (key != NULL && issigningkey(key))
561 			expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
562 		else
563 			expired = isc_serial_gt(now, rrsig.timeexpire);
564 
565 		if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
566 			/* rrsig is dropped and not replaced */
567 			vbprintf(2, "\trrsig by %s dropped - "
568 				 "invalid validity period\n",
569 				 sigstr);
570 		} else if (key == NULL && !future &&
571 			   expecttofindkey(&rrsig.signer)) {
572 			/* rrsig is dropped and not replaced */
573 			vbprintf(2, "\trrsig by %s dropped - "
574 				 "private dnskey not found\n",
575 				 sigstr);
576 		} else if (key == NULL || future) {
577 			keep = (!expired && !remove_orphansigs);
578 			vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
579 				 keep ? "retained" : "dropped", sigstr);
580 		} else if (!dns_dnssec_keyactive(key->key, now) &&
581 			   remove_inactkeysigs) {
582 			keep = false;
583 			vbprintf(2, "\trrsig by %s dropped - key inactive\n",
584 				 sigstr);
585 		} else if (issigningkey(key)) {
586 			wassignedby[key->index] = true;
587 
588 			if (!expired && rrsig.originalttl == set->ttl &&
589 			    setverifies(name, set, key->key, &sigrdata)) {
590 				vbprintf(2, "\trrsig by %s retained\n", sigstr);
591 				keep = true;
592 			} else {
593 				vbprintf(2, "\trrsig by %s dropped - %s\n",
594 					 sigstr, expired ? "expired" :
595 					 rrsig.originalttl != set->ttl ?
596 					 "ttl change" : "failed to verify");
597 				resign = true;
598 			}
599 		} else if (!ispublishedkey(key) && remove_orphansigs) {
600 			vbprintf(2, "\trrsig by %s dropped - dnskey removed\n",
601 				 sigstr);
602 		} else if (iszonekey(key)) {
603 			wassignedby[key->index] = true;
604 
605 			if (!expired && rrsig.originalttl == set->ttl &&
606 			    setverifies(name, set, key->key, &sigrdata)) {
607 				vbprintf(2, "\trrsig by %s retained\n", sigstr);
608 				keep = true;
609 			} else {
610 				vbprintf(2, "\trrsig by %s dropped - %s\n",
611 					 sigstr, expired ? "expired" :
612 					 rrsig.originalttl != set->ttl ?
613 					 "ttl change" : "failed to verify");
614 			}
615 		} else if (!expired) {
616 			vbprintf(2, "\trrsig by %s retained\n", sigstr);
617 			keep = true;
618 		} else {
619 			vbprintf(2, "\trrsig by %s expired\n", sigstr);
620 		}
621 
622 		if (keep) {
623 			if (key != NULL)
624 				nowsignedby[key->index] = true;
625 			INCSTAT(nretained);
626 			if (sigset.ttl != ttl) {
627 				vbprintf(2, "\tfixing ttl %s\n", sigstr);
628 				tuple = NULL;
629 				result = dns_difftuple_create(mctx,
630 						      DNS_DIFFOP_DELRESIGN,
631 						      name, sigset.ttl,
632 						      &sigrdata, &tuple);
633 				check_result(result, "dns_difftuple_create");
634 				dns_diff_append(del, &tuple);
635 				result = dns_difftuple_create(mctx,
636 						      DNS_DIFFOP_ADDRESIGN,
637 						      name, ttl,
638 						      &sigrdata, &tuple);
639 				check_result(result, "dns_difftuple_create");
640 				dns_diff_append(add, &tuple);
641 			}
642 		} else {
643 			tuple = NULL;
644 			vbprintf(2, "removing signature by %s\n", sigstr);
645 			result = dns_difftuple_create(mctx,
646 						      DNS_DIFFOP_DELRESIGN,
647 						      name, sigset.ttl,
648 						      &sigrdata, &tuple);
649 			check_result(result, "dns_difftuple_create");
650 			dns_diff_append(del, &tuple);
651 			INCSTAT(ndropped);
652 		}
653 
654 		if (resign) {
655 			INSIST(!keep);
656 
657 			signwithkey(name, set, key->key, ttl, add,
658 				    "resigning with dnskey");
659 			nowsignedby[key->index] = true;
660 		}
661 
662 		dns_rdata_reset(&sigrdata);
663 		dns_rdata_freestruct(&rrsig);
664 		result = dns_rdataset_next(&sigset);
665 	}
666 	if (result == ISC_R_NOMORE)
667 		result = ISC_R_SUCCESS;
668 
669 	check_result(result, "dns_rdataset_first/next");
670 	if (dns_rdataset_isassociated(&sigset))
671 		dns_rdataset_disassociate(&sigset);
672 
673 	for (key = ISC_LIST_HEAD(keylist);
674 	     key != NULL;
675 	     key = ISC_LIST_NEXT(key, link))
676 	{
677 		if (nowsignedby[key->index])
678 			continue;
679 
680 		if (!issigningkey(key))
681 			continue;
682 
683 		if ((set->type == dns_rdatatype_cds ||
684 		     set->type == dns_rdatatype_cdnskey ||
685 		     set->type == dns_rdatatype_dnskey) &&
686 		     dns_name_equal(name, gorigin)) {
687 			bool have_ksk;
688 			dns_dnsseckey_t *tmpkey;
689 
690 			have_ksk = isksk(key);
691 			for (tmpkey = ISC_LIST_HEAD(keylist);
692 			     tmpkey != NULL;
693 			     tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
694 				if (dst_key_alg(key->key) !=
695 				    dst_key_alg(tmpkey->key))
696 					continue;
697 				if (REVOKE(tmpkey->key))
698 					continue;
699 				if (isksk(tmpkey))
700 					have_ksk = true;
701 			}
702 			if (isksk(key) || !have_ksk ||
703 			    (iszsk(key) && !keyset_kskonly))
704 				signwithkey(name, set, key->key, ttl, add,
705 					    "signing with dnskey");
706 		} else if (iszsk(key)) {
707 			signwithkey(name, set, key->key, ttl, add,
708 				    "signing with dnskey");
709 		}
710 	}
711 
712 	isc_mem_put(mctx, wassignedby, arraysize * sizeof(bool));
713 	isc_mem_put(mctx, nowsignedby, arraysize * sizeof(bool));
714 }
715 
716 struct hashlist {
717 	unsigned char *hashbuf;
718 	size_t entries;
719 	size_t size;
720 	size_t length;
721 };
722 
723 static void
724 hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
725 
726 	l->entries = 0;
727 	l->length = length + 1;
728 
729 	if (nodes != 0) {
730 		l->size = nodes;
731 		l->hashbuf = malloc(l->size * l->length);
732 		if (l->hashbuf == NULL)
733 			l->size = 0;
734 	} else {
735 		l->size = 0;
736 		l->hashbuf = NULL;
737 	}
738 }
739 
740 static void
741 hashlist_free(hashlist_t *l) {
742 	if (l->hashbuf) {
743 		free(l->hashbuf);
744 		l->hashbuf = NULL;
745 		l->entries = 0;
746 		l->length = 0;
747 		l->size = 0;
748 	}
749 }
750 
751 static void
752 hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
753 {
754 
755 	REQUIRE(len <= l->length);
756 
757 	if (l->entries == l->size) {
758 		l->size = l->size * 2 + 100;
759 		l->hashbuf = realloc(l->hashbuf, l->size * l->length);
760 		if (l->hashbuf == NULL)
761 			fatal("unable to grow hashlist: out of memory");
762 	}
763 	memset(l->hashbuf + l->entries * l->length, 0, l->length);
764 	memmove(l->hashbuf + l->entries * l->length, hash, len);
765 	l->entries++;
766 }
767 
768 static void
769 hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
770 		      unsigned int hashalg, unsigned int iterations,
771 		      const unsigned char *salt, size_t salt_len,
772 		      bool speculative)
773 {
774 	char nametext[DNS_NAME_FORMATSIZE];
775 	unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
776 	unsigned int len;
777 	size_t i;
778 
779 	len = isc_iterated_hash(hash, hashalg, iterations,
780 				salt, (int)salt_len,
781 				name->ndata, name->length);
782 	if (verbose) {
783 		dns_name_format(name, nametext, sizeof nametext);
784 		for (i = 0 ; i < len; i++)
785 			fprintf(stderr, "%02x", hash[i]);
786 		fprintf(stderr, " %s\n", nametext);
787 	}
788 	hash[len++] = speculative ? 1 : 0;
789 	hashlist_add(l, hash, len);
790 }
791 
792 static int
793 hashlist_comp(const void *a, const void *b) {
794 	return (memcmp(a, b, hash_length + 1));
795 }
796 
797 static void
798 hashlist_sort(hashlist_t *l) {
799 	qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
800 }
801 
802 static bool
803 hashlist_hasdup(hashlist_t *l) {
804 	unsigned char *current;
805 	unsigned char *next = l->hashbuf;
806 	size_t entries = l->entries;
807 
808 	/*
809 	 * Skip initial speculative wild card hashs.
810 	 */
811 	while (entries > 0U && next[l->length-1] != 0U) {
812 		next += l->length;
813 		entries--;
814 	}
815 
816 	current = next;
817 	while (entries-- > 1U) {
818 		next += l->length;
819 		if (next[l->length-1] != 0)
820 			continue;
821 		if (isc_safe_memequal(current, next, l->length - 1))
822 			return (true);
823 		current = next;
824 	}
825 	return (false);
826 }
827 
828 static const unsigned char *
829 hashlist_findnext(const hashlist_t *l,
830 		  const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
831 {
832 	size_t entries = l->entries;
833 	const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
834 					    l->length, hashlist_comp);
835 	INSIST(next != NULL);
836 
837 	do {
838 		if (next < l->hashbuf + (l->entries - 1) * l->length)
839 			next += l->length;
840 		else
841 			next = l->hashbuf;
842 		if (next[l->length - 1] == 0)
843 			break;
844 	} while (entries-- > 1U);
845 	INSIST(entries != 0U);
846 	return (next);
847 }
848 
849 static bool
850 hashlist_exists(const hashlist_t *l,
851 		const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
852 {
853 	if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
854 		return (true);
855 	else
856 		return (false);
857 }
858 
859 static void
860 addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
861 		  unsigned int hashalg, unsigned int iterations,
862 		  const unsigned char *salt, size_t salt_len)
863 {
864 	dns_fixedname_t fixed;
865 	dns_name_t *wild;
866 	dns_dbnode_t *node = NULL;
867 	isc_result_t result;
868 	char namestr[DNS_NAME_FORMATSIZE];
869 
870 	wild = dns_fixedname_initname(&fixed);
871 
872 	result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
873 	if (result == ISC_R_NOSPACE)
874 		return;
875 	check_result(result,"addnowildcardhash: dns_name_concatenate()");
876 
877 	result = dns_db_findnode(gdb, wild, false, &node);
878 	if (result == ISC_R_SUCCESS) {
879 		dns_db_detachnode(gdb, &node);
880 		return;
881 	}
882 
883 	if (verbose) {
884 		dns_name_format(wild, namestr, sizeof(namestr));
885 		fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
886 	}
887 
888 	hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_len,
889 			      true);
890 }
891 
892 static void
893 opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
894        dns_db_t **dbp)
895 {
896 	char filename[PATH_MAX];
897 	isc_buffer_t b;
898 	isc_result_t result;
899 
900 	isc_buffer_init(&b, filename, sizeof(filename));
901 	if (dsdir != NULL) {
902 		/* allow room for a trailing slash */
903 		if (strlen(dsdir) >= isc_buffer_availablelength(&b))
904 			fatal("path '%s' is too long", dsdir);
905 		isc_buffer_putstr(&b, dsdir);
906 		if (dsdir[strlen(dsdir) - 1] != '/')
907 			isc_buffer_putstr(&b, "/");
908 	}
909 	if (strlen(prefix) > isc_buffer_availablelength(&b))
910 		fatal("path '%s' is too long", dsdir);
911 	isc_buffer_putstr(&b, prefix);
912 	result = dns_name_tofilenametext(name, false, &b);
913 	check_result(result, "dns_name_tofilenametext()");
914 	if (isc_buffer_availablelength(&b) == 0) {
915 		char namestr[DNS_NAME_FORMATSIZE];
916 		dns_name_format(name, namestr, sizeof(namestr));
917 		fatal("name '%s' is too long", namestr);
918 	}
919 	isc_buffer_putuint8(&b, 0);
920 
921 	result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
922 			       rdclass, 0, NULL, dbp);
923 	check_result(result, "dns_db_create()");
924 
925 	result = dns_db_load(*dbp, filename, inputformat, DNS_MASTER_HINT);
926 	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
927 		dns_db_detach(dbp);
928 }
929 
930 /*%
931  * Load the DS set for a child zone, if a dsset-* file can be found.
932  * If not, try to find a keyset-* file from an earlier version of
933  * dnssec-signzone, and build DS records from that.
934  */
935 static isc_result_t
936 loadds(dns_name_t *name, uint32_t ttl, dns_rdataset_t *dsset) {
937 	dns_db_t *db = NULL;
938 	dns_dbversion_t *ver = NULL;
939 	dns_dbnode_t *node = NULL;
940 	isc_result_t result;
941 	dns_rdataset_t keyset;
942 	dns_rdata_t key, ds;
943 	unsigned char dsbuf[DNS_DS_BUFFERSIZE];
944 	dns_diff_t diff;
945 	dns_difftuple_t *tuple = NULL;
946 
947 	opendb("dsset-", name, gclass, &db);
948 	if (db != NULL) {
949 		result = dns_db_findnode(db, name, false, &node);
950 		if (result == ISC_R_SUCCESS) {
951 			dns_rdataset_init(dsset);
952 			result = dns_db_findrdataset(db, node, NULL,
953 						     dns_rdatatype_ds, 0, 0,
954 						     dsset, NULL);
955 			dns_db_detachnode(db, &node);
956 			if (result == ISC_R_SUCCESS) {
957 				vbprintf(2, "found DS records\n");
958 				dsset->ttl = ttl;
959 				dns_db_detach(&db);
960 				return (result);
961 			}
962 		}
963 		dns_db_detach(&db);
964 	}
965 
966 	/* No DS records found; try again, looking for DNSKEY records */
967 	opendb("keyset-", name, gclass, &db);
968 	if (db == NULL) {
969 		return (ISC_R_NOTFOUND);
970 	}
971 
972 	result = dns_db_findnode(db, name, false, &node);
973 	if (result != ISC_R_SUCCESS) {
974 		dns_db_detach(&db);
975 		return (result);
976 	}
977 
978 	dns_rdataset_init(&keyset);
979 	result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
980 				     &keyset, NULL);
981 	if (result != ISC_R_SUCCESS) {
982 		dns_db_detachnode(db, &node);
983 		dns_db_detach(&db);
984 		return (result);
985 	}
986 	vbprintf(2, "found DNSKEY records\n");
987 
988 	result = dns_db_newversion(db, &ver);
989 	check_result(result, "dns_db_newversion");
990 	dns_diff_init(mctx, &diff);
991 
992 	for (result = dns_rdataset_first(&keyset);
993 	     result == ISC_R_SUCCESS;
994 	     result = dns_rdataset_next(&keyset))
995 	{
996 		dns_rdata_init(&key);
997 		dns_rdata_init(&ds);
998 		dns_rdataset_current(&keyset, &key);
999 		result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
1000 					   dsbuf, &ds);
1001 		check_result(result, "dns_ds_buildrdata");
1002 
1003 		result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
1004 					      ttl, &ds, &tuple);
1005 		check_result(result, "dns_difftuple_create");
1006 		dns_diff_append(&diff, &tuple);
1007 
1008 		dns_rdata_reset(&ds);
1009 		result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
1010 					   dsbuf, &ds);
1011 		check_result(result, "dns_ds_buildrdata");
1012 
1013 		result = dns_difftuple_create(mctx, DNS_DIFFOP_ADDRESIGN, name,
1014 					      ttl, &ds, &tuple);
1015 		check_result(result, "dns_difftuple_create");
1016 		dns_diff_append(&diff, &tuple);
1017 	}
1018 
1019 	result = dns_diff_apply(&diff, db, ver);
1020 	check_result(result, "dns_diff_apply");
1021 	dns_diff_clear(&diff);
1022 
1023 	dns_db_closeversion(db, &ver, true);
1024 
1025 	result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
1026 				     dsset, NULL);
1027 	check_result(result, "dns_db_findrdataset");
1028 
1029 	dns_rdataset_disassociate(&keyset);
1030 	dns_db_detachnode(db, &node);
1031 	dns_db_detach(&db);
1032 	return (result);
1033 }
1034 
1035 static bool
1036 secure(dns_name_t *name, dns_dbnode_t *node) {
1037 	dns_rdataset_t dsset;
1038 	isc_result_t result;
1039 
1040 	if (dns_name_equal(name, gorigin))
1041 		return (false);
1042 
1043 	dns_rdataset_init(&dsset);
1044 	result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
1045 				     0, 0, &dsset, NULL);
1046 	if (dns_rdataset_isassociated(&dsset))
1047 		dns_rdataset_disassociate(&dsset);
1048 
1049 	return (result == ISC_R_SUCCESS);
1050 }
1051 
1052 static bool
1053 is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
1054 	      dns_name_t *name, dns_dbnode_t *node, uint32_t *ttlp)
1055 {
1056 	dns_rdataset_t nsset;
1057 	isc_result_t result;
1058 
1059 	if (dns_name_equal(name, origin))
1060 		return (false);
1061 
1062 	dns_rdataset_init(&nsset);
1063 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns,
1064 				     0, 0, &nsset, NULL);
1065 	if (dns_rdataset_isassociated(&nsset)) {
1066 		if (ttlp != NULL)
1067 			*ttlp = nsset.ttl;
1068 		dns_rdataset_disassociate(&nsset);
1069 	}
1070 
1071 	return ((result == ISC_R_SUCCESS));
1072 }
1073 
1074 /*%
1075  * Return true if version 'ver' of database 'db' contains a DNAME RRset at
1076  * 'node'; return false otherwise.
1077  */
1078 static bool
1079 has_dname(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) {
1080 	dns_rdataset_t dnameset;
1081 	isc_result_t result;
1082 
1083 	dns_rdataset_init(&dnameset);
1084 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dname, 0, 0,
1085 				     &dnameset, NULL);
1086 	if (dns_rdataset_isassociated(&dnameset)) {
1087 		dns_rdataset_disassociate(&dnameset);
1088 	}
1089 
1090 	return ((result == ISC_R_SUCCESS));
1091 }
1092 
1093 /*%
1094  * Signs all records at a name.
1095  */
1096 static void
1097 signname(dns_dbnode_t *node, dns_name_t *name) {
1098 	isc_result_t result;
1099 	dns_rdataset_t rdataset;
1100 	dns_rdatasetiter_t *rdsiter;
1101 	bool isdelegation = false;
1102 	dns_diff_t del, add;
1103 	char namestr[DNS_NAME_FORMATSIZE];
1104 
1105 	dns_rdataset_init(&rdataset);
1106 	dns_name_format(name, namestr, sizeof(namestr));
1107 
1108 	/*
1109 	 * Determine if this is a delegation point.
1110 	 */
1111 	if (is_delegation(gdb, gversion, gorigin, name, node, NULL))
1112 		isdelegation = true;
1113 
1114 	/*
1115 	 * Now iterate through the rdatasets.
1116 	 */
1117 	dns_diff_init(mctx, &del);
1118 	dns_diff_init(mctx, &add);
1119 	rdsiter = NULL;
1120 	result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1121 	check_result(result, "dns_db_allrdatasets()");
1122 	result = dns_rdatasetiter_first(rdsiter);
1123 	while (result == ISC_R_SUCCESS) {
1124 		dns_rdatasetiter_current(rdsiter, &rdataset);
1125 
1126 		/* If this is a RRSIG set, skip it. */
1127 		if (rdataset.type == dns_rdatatype_rrsig)
1128 			goto skip;
1129 
1130 		/*
1131 		 * If this name is a delegation point, skip all records
1132 		 * except NSEC and DS sets.  Otherwise check that there
1133 		 * isn't a DS record.
1134 		 */
1135 		if (isdelegation) {
1136 			if (rdataset.type != nsec_datatype &&
1137 			    rdataset.type != dns_rdatatype_ds)
1138 				goto skip;
1139 		} else if (rdataset.type == dns_rdatatype_ds) {
1140 			char namebuf[DNS_NAME_FORMATSIZE];
1141 			dns_name_format(name, namebuf, sizeof(namebuf));
1142 			fatal("'%s': found DS RRset without NS RRset\n",
1143 			      namebuf);
1144 		}
1145 
1146 		signset(&del, &add, node, name, &rdataset);
1147 
1148  skip:
1149 		dns_rdataset_disassociate(&rdataset);
1150 		result = dns_rdatasetiter_next(rdsiter);
1151 	}
1152 	if (result != ISC_R_NOMORE)
1153 		fatal("rdataset iteration for name '%s' failed: %s",
1154 		      namestr, isc_result_totext(result));
1155 
1156 	dns_rdatasetiter_destroy(&rdsiter);
1157 
1158 	result = dns_diff_applysilently(&del, gdb, gversion);
1159 	if (result != ISC_R_SUCCESS)
1160 		fatal("failed to delete SIGs at node '%s': %s",
1161 		      namestr, isc_result_totext(result));
1162 
1163 	result = dns_diff_applysilently(&add, gdb, gversion);
1164 	if (result != ISC_R_SUCCESS)
1165 		fatal("failed to add SIGs at node '%s': %s",
1166 		      namestr, isc_result_totext(result));
1167 
1168 	dns_diff_clear(&del);
1169 	dns_diff_clear(&add);
1170 }
1171 
1172 /*
1173  * See if the node contains any non RRSIG/NSEC records and report to
1174  * caller.  Clean out extranous RRSIG records for node.
1175  */
1176 static inline bool
1177 active_node(dns_dbnode_t *node) {
1178 	dns_rdatasetiter_t *rdsiter = NULL;
1179 	dns_rdatasetiter_t *rdsiter2 = NULL;
1180 	bool active = false;
1181 	isc_result_t result;
1182 	dns_rdataset_t rdataset;
1183 	dns_rdatatype_t type;
1184 	dns_rdatatype_t covers;
1185 	bool found;
1186 
1187 	dns_rdataset_init(&rdataset);
1188 	result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1189 	check_result(result, "dns_db_allrdatasets()");
1190 	result = dns_rdatasetiter_first(rdsiter);
1191 	while (result == ISC_R_SUCCESS) {
1192 		dns_rdatasetiter_current(rdsiter, &rdataset);
1193 		if (rdataset.type != dns_rdatatype_nsec &&
1194 		    rdataset.type != dns_rdatatype_nsec3 &&
1195 		    rdataset.type != dns_rdatatype_rrsig)
1196 			active = true;
1197 		dns_rdataset_disassociate(&rdataset);
1198 		if (!active)
1199 			result = dns_rdatasetiter_next(rdsiter);
1200 		else
1201 			result = ISC_R_NOMORE;
1202 	}
1203 	if (result != ISC_R_NOMORE)
1204 		fatal("rdataset iteration failed: %s",
1205 		      isc_result_totext(result));
1206 
1207 	if (!active && nsec_datatype == dns_rdatatype_nsec) {
1208 		/*%
1209 		 * The node is empty of everything but NSEC / RRSIG records.
1210 		 */
1211 		for (result = dns_rdatasetiter_first(rdsiter);
1212 		     result == ISC_R_SUCCESS;
1213 		     result = dns_rdatasetiter_next(rdsiter)) {
1214 			dns_rdatasetiter_current(rdsiter, &rdataset);
1215 			result = dns_db_deleterdataset(gdb, node, gversion,
1216 						       rdataset.type,
1217 						       rdataset.covers);
1218 			check_result(result, "dns_db_deleterdataset()");
1219 			dns_rdataset_disassociate(&rdataset);
1220 		}
1221 		if (result != ISC_R_NOMORE)
1222 			fatal("rdataset iteration failed: %s",
1223 			      isc_result_totext(result));
1224 	} else {
1225 		/*
1226 		 * Delete RRSIGs for types that no longer exist.
1227 		 */
1228 		result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
1229 		check_result(result, "dns_db_allrdatasets()");
1230 		for (result = dns_rdatasetiter_first(rdsiter);
1231 		     result == ISC_R_SUCCESS;
1232 		     result = dns_rdatasetiter_next(rdsiter)) {
1233 			dns_rdatasetiter_current(rdsiter, &rdataset);
1234 			type = rdataset.type;
1235 			covers = rdataset.covers;
1236 			dns_rdataset_disassociate(&rdataset);
1237 			/*
1238 			 * Delete the NSEC chain if we are signing with
1239 			 * NSEC3.
1240 			 */
1241 			if (nsec_datatype == dns_rdatatype_nsec3 &&
1242 			    (type == dns_rdatatype_nsec ||
1243 			     covers == dns_rdatatype_nsec)) {
1244 				result = dns_db_deleterdataset(gdb, node,
1245 							       gversion, type,
1246 							       covers);
1247 				check_result(result,
1248 					   "dns_db_deleterdataset(nsec/rrsig)");
1249 				continue;
1250 			}
1251 			if (type != dns_rdatatype_rrsig)
1252 				continue;
1253 			found = false;
1254 			for (result = dns_rdatasetiter_first(rdsiter2);
1255 			     !found && result == ISC_R_SUCCESS;
1256 			     result = dns_rdatasetiter_next(rdsiter2)) {
1257 				dns_rdatasetiter_current(rdsiter2, &rdataset);
1258 				if (rdataset.type == covers)
1259 					found = true;
1260 				dns_rdataset_disassociate(&rdataset);
1261 			}
1262 			if (!found) {
1263 				if (result != ISC_R_NOMORE)
1264 					fatal("rdataset iteration failed: %s",
1265 					      isc_result_totext(result));
1266 				result = dns_db_deleterdataset(gdb, node,
1267 							       gversion, type,
1268 							       covers);
1269 				check_result(result,
1270 					     "dns_db_deleterdataset(rrsig)");
1271 			} else if (result != ISC_R_NOMORE &&
1272 				   result != ISC_R_SUCCESS)
1273 				fatal("rdataset iteration failed: %s",
1274 				      isc_result_totext(result));
1275 		}
1276 		if (result != ISC_R_NOMORE)
1277 			fatal("rdataset iteration failed: %s",
1278 			      isc_result_totext(result));
1279 		dns_rdatasetiter_destroy(&rdsiter2);
1280 	}
1281 	dns_rdatasetiter_destroy(&rdsiter);
1282 
1283 	return (active);
1284 }
1285 
1286 /*%
1287  * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
1288  */
1289 static void
1290 get_soa_ttls(void) {
1291 	dns_rdataset_t soaset;
1292 	dns_fixedname_t fname;
1293 	dns_name_t *name;
1294 	isc_result_t result;
1295 	dns_rdata_t rdata = DNS_RDATA_INIT;
1296 
1297 	name = dns_fixedname_initname(&fname);
1298 	dns_rdataset_init(&soaset);
1299 	result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1300 			     0, 0, NULL, name, &soaset, NULL);
1301 	if (result != ISC_R_SUCCESS)
1302 		fatal("failed to find an SOA at the zone apex: %s",
1303 		      isc_result_totext(result));
1304 
1305 	result = dns_rdataset_first(&soaset);
1306 	check_result(result, "dns_rdataset_first");
1307 	dns_rdataset_current(&soaset, &rdata);
1308 	zone_soa_min_ttl = dns_soa_getminimum(&rdata);
1309 	soa_ttl = soaset.ttl;
1310 	if (set_maxttl) {
1311 		zone_soa_min_ttl = ISC_MIN(zone_soa_min_ttl, maxttl);
1312 		soa_ttl = ISC_MIN(soa_ttl, maxttl);
1313 	}
1314 	dns_rdataset_disassociate(&soaset);
1315 }
1316 
1317 /*%
1318  * Increment (or set if nonzero) the SOA serial
1319  */
1320 static isc_result_t
1321 setsoaserial(uint32_t serial, dns_updatemethod_t method) {
1322 	isc_result_t result;
1323 	dns_dbnode_t *node = NULL;
1324 	dns_rdataset_t rdataset;
1325 	dns_rdata_t rdata = DNS_RDATA_INIT;
1326 	uint32_t old_serial, new_serial;
1327 
1328 	result = dns_db_getoriginnode(gdb, &node);
1329 	if (result != ISC_R_SUCCESS)
1330 		return result;
1331 
1332 	dns_rdataset_init(&rdataset);
1333 
1334 	result = dns_db_findrdataset(gdb, node, gversion,
1335 				     dns_rdatatype_soa, 0,
1336 				     0, &rdataset, NULL);
1337 	if (result != ISC_R_SUCCESS)
1338 		goto cleanup;
1339 
1340 	result = dns_rdataset_first(&rdataset);
1341 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
1342 
1343 	dns_rdataset_current(&rdataset, &rdata);
1344 
1345 	old_serial = dns_soa_getserial(&rdata);
1346 
1347 	if (method == dns_updatemethod_date ||
1348 	    method == dns_updatemethod_unixtime) {
1349 		new_serial = dns_update_soaserial(old_serial, method);
1350 	} else if (serial != 0 || method == dns_updatemethod_none) {
1351 		/* Set SOA serial to the value provided. */
1352 		new_serial = serial;
1353 	} else {
1354 		/* Increment SOA serial using RFC 1982 arithmetics */
1355 		new_serial = (old_serial + 1) & 0xFFFFFFFF;
1356 		if (new_serial == 0)
1357 			new_serial = 1;
1358 	}
1359 
1360 	/* If the new serial is not likely to cause a zone transfer
1361 	 * (a/ixfr) from servers having the old serial, warn the user.
1362 	 *
1363 	 * RFC1982 section 7 defines the maximum increment to be
1364 	 * (2^(32-1))-1.  Using u_int32_t arithmetic, we can do a single
1365 	 * comparison.  (5 - 6 == (2^32)-1, not negative-one)
1366 	 */
1367 	if (new_serial == old_serial ||
1368 	    (new_serial - old_serial) > 0x7fffffffU)
1369 		fprintf(stderr, "%s: warning: Serial number not advanced, "
1370 			"zone may not transfer\n", program);
1371 
1372 	dns_soa_setserial(new_serial, &rdata);
1373 
1374 	result = dns_db_deleterdataset(gdb, node, gversion,
1375 				       dns_rdatatype_soa, 0);
1376 	check_result(result, "dns_db_deleterdataset");
1377 	if (result != ISC_R_SUCCESS)
1378 		goto cleanup;
1379 
1380 	result = dns_db_addrdataset(gdb, node, gversion,
1381 				    0, &rdataset, 0, NULL);
1382 	check_result(result, "dns_db_addrdataset");
1383 	if (result != ISC_R_SUCCESS)
1384 		goto cleanup;
1385 
1386 cleanup:
1387 	dns_rdataset_disassociate(&rdataset);
1388 	if (node != NULL)
1389 		dns_db_detachnode(gdb, &node);
1390 	dns_rdata_reset(&rdata);
1391 
1392 	return (result);
1393 }
1394 
1395 /*%
1396  * Delete any RRSIG records at a node.
1397  */
1398 static void
1399 cleannode(dns_db_t *db, dns_dbversion_t *dbversion, dns_dbnode_t *node) {
1400 	dns_rdatasetiter_t *rdsiter = NULL;
1401 	dns_rdataset_t set;
1402 	isc_result_t result, dresult;
1403 
1404 	if (outputformat != dns_masterformat_text || !disable_zone_check)
1405 		return;
1406 
1407 	dns_rdataset_init(&set);
1408 	result = dns_db_allrdatasets(db, node, dbversion, 0, &rdsiter);
1409 	check_result(result, "dns_db_allrdatasets");
1410 	result = dns_rdatasetiter_first(rdsiter);
1411 	while (result == ISC_R_SUCCESS) {
1412 		bool destroy = false;
1413 		dns_rdatatype_t covers = 0;
1414 		dns_rdatasetiter_current(rdsiter, &set);
1415 		if (set.type == dns_rdatatype_rrsig) {
1416 			covers = set.covers;
1417 			destroy = true;
1418 		}
1419 		dns_rdataset_disassociate(&set);
1420 		result = dns_rdatasetiter_next(rdsiter);
1421 		if (destroy) {
1422 			dresult = dns_db_deleterdataset(db, node, dbversion,
1423 							dns_rdatatype_rrsig,
1424 							covers);
1425 			check_result(dresult, "dns_db_deleterdataset");
1426 		}
1427 	}
1428 	if (result != ISC_R_NOMORE)
1429 		fatal("rdataset iteration failed: %s",
1430 		      isc_result_totext(result));
1431 	dns_rdatasetiter_destroy(&rdsiter);
1432 }
1433 
1434 /*%
1435  * Set up the iterator and global state before starting the tasks.
1436  */
1437 static void
1438 presign(void) {
1439 	isc_result_t result;
1440 
1441 	gdbiter = NULL;
1442 	result = dns_db_createiterator(gdb, 0, &gdbiter);
1443 	check_result(result, "dns_db_createiterator()");
1444 }
1445 
1446 /*%
1447  * Clean up the iterator and global state after the tasks complete.
1448  */
1449 static void
1450 postsign(void) {
1451 	dns_dbiterator_destroy(&gdbiter);
1452 }
1453 
1454 /*%
1455  * Sign the apex of the zone.
1456  * Note the origin may not be the first node if there are out of zone
1457  * records.
1458  */
1459 static void
1460 signapex(void) {
1461 	dns_dbnode_t *node = NULL;
1462 	dns_fixedname_t fixed;
1463 	dns_name_t *name;
1464 	isc_result_t result;
1465 
1466 	name = dns_fixedname_initname(&fixed);
1467 	result = dns_dbiterator_seek(gdbiter, gorigin);
1468 	check_result(result, "dns_dbiterator_seek()");
1469 	result = dns_dbiterator_current(gdbiter, &node, name);
1470 	check_dns_dbiterator_current(result);
1471 	signname(node, name);
1472 	dumpnode(name, node);
1473 	cleannode(gdb, gversion, node);
1474 	dns_db_detachnode(gdb, &node);
1475 	result = dns_dbiterator_first(gdbiter);
1476 	if (result == ISC_R_NOMORE)
1477 		finished = true;
1478 	else if (result != ISC_R_SUCCESS)
1479 		fatal("failure iterating database: %s",
1480 		      isc_result_totext(result));
1481 }
1482 
1483 /*%
1484  * Assigns a node to a worker thread.  This is protected by the master task's
1485  * lock.
1486  */
1487 static void
1488 assignwork(isc_task_t *task, isc_task_t *worker) {
1489 	dns_fixedname_t *fname;
1490 	dns_name_t *name;
1491 	dns_dbnode_t *node;
1492 	sevent_t *sevent;
1493 	dns_rdataset_t nsec;
1494 	bool found;
1495 	isc_result_t result;
1496 	static dns_name_t *zonecut = NULL;	/* Protected by namelock. */
1497 	static dns_fixedname_t fzonecut;	/* Protected by namelock. */
1498 	static unsigned int ended = 0;		/* Protected by namelock. */
1499 
1500 	if (shuttingdown)
1501 		return;
1502 
1503 	LOCK(&namelock);
1504 	if (finished) {
1505 		ended++;
1506 		if (ended == ntasks) {
1507 			isc_task_detach(&task);
1508 			isc_app_shutdown();
1509 		}
1510 		goto unlock;
1511 	}
1512 
1513 	fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
1514 	if (fname == NULL)
1515 		fatal("out of memory");
1516 	name = dns_fixedname_initname(fname);
1517 	node = NULL;
1518 	found = false;
1519 	while (!found) {
1520 		result = dns_dbiterator_current(gdbiter, &node, name);
1521 		check_dns_dbiterator_current(result);
1522 		/*
1523 		 * The origin was handled by signapex().
1524 		 */
1525 		if (dns_name_equal(name, gorigin)) {
1526 			dns_db_detachnode(gdb, &node);
1527 			goto next;
1528 		}
1529 		/*
1530 		 * Sort the zone data from the glue and out-of-zone data.
1531 		 * For NSEC zones nodes with zone data have NSEC records.
1532 		 * For NSEC3 zones the NSEC3 nodes are zone data but
1533 		 * outside of the zone name space.  For the rest we need
1534 		 * to track the bottom of zone cuts.
1535 		 * Nodes which don't need to be signed are dumped here.
1536 		 */
1537 		dns_rdataset_init(&nsec);
1538 		result = dns_db_findrdataset(gdb, node, gversion,
1539 					     nsec_datatype, 0, 0,
1540 					     &nsec, NULL);
1541 		if (dns_rdataset_isassociated(&nsec))
1542 			dns_rdataset_disassociate(&nsec);
1543 		if (result == ISC_R_SUCCESS) {
1544 			found = true;
1545 		} else if (nsec_datatype == dns_rdatatype_nsec3) {
1546 			if (dns_name_issubdomain(name, gorigin) &&
1547 			    (zonecut == NULL ||
1548 			     !dns_name_issubdomain(name, zonecut))) {
1549 				if (is_delegation(gdb, gversion, gorigin,
1550 						  name, node, NULL))
1551 				{
1552 					zonecut = savezonecut(&fzonecut, name);
1553 					if (!OPTOUT(nsec3flags) ||
1554 					    secure(name, node)) {
1555 						found = true;
1556 					}
1557 				} else if (has_dname(gdb, gversion, node)) {
1558 					zonecut = savezonecut(&fzonecut, name);
1559 					found = true;
1560 				} else {
1561 					found = true;
1562 				}
1563 			}
1564 		}
1565 
1566 		if (!found) {
1567 			dumpnode(name, node);
1568 			dns_db_detachnode(gdb, &node);
1569 		}
1570 
1571  next:
1572 		result = dns_dbiterator_next(gdbiter);
1573 		if (result == ISC_R_NOMORE) {
1574 			finished = true;
1575 			break;
1576 		} else if (result != ISC_R_SUCCESS)
1577 			fatal("failure iterating database: %s",
1578 			      isc_result_totext(result));
1579 	}
1580 	if (!found) {
1581 		ended++;
1582 		if (ended == ntasks) {
1583 			isc_task_detach(&task);
1584 			isc_app_shutdown();
1585 		}
1586 		isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
1587 		goto unlock;
1588 	}
1589 	sevent = (sevent_t *)
1590 		 isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
1591 				    sign, NULL, sizeof(sevent_t));
1592 	if (sevent == NULL)
1593 		fatal("failed to allocate event\n");
1594 
1595 	sevent->node = node;
1596 	sevent->fname = fname;
1597 	isc_task_send(worker, ISC_EVENT_PTR(&sevent));
1598  unlock:
1599 	UNLOCK(&namelock);
1600 }
1601 
1602 /*%
1603  * Start a worker task
1604  */
1605 static void
1606 startworker(isc_task_t *task, isc_event_t *event) {
1607 	isc_task_t *worker;
1608 
1609 	worker = (isc_task_t *)event->ev_arg;
1610 	assignwork(task, worker);
1611 	isc_event_free(&event);
1612 }
1613 
1614 /*%
1615  * Write a node to the output file, and restart the worker task.
1616  */
1617 static void
1618 writenode(isc_task_t *task, isc_event_t *event) {
1619 	isc_task_t *worker;
1620 	sevent_t *sevent = (sevent_t *)event;
1621 
1622 	worker = (isc_task_t *)event->ev_sender;
1623 	dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
1624 	cleannode(gdb, gversion, sevent->node);
1625 	dns_db_detachnode(gdb, &sevent->node);
1626 	isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
1627 	assignwork(task, worker);
1628 	isc_event_free(&event);
1629 }
1630 
1631 /*%
1632  *  Sign a database node.
1633  */
1634 static void
1635 sign(isc_task_t *task, isc_event_t *event) {
1636 	dns_fixedname_t *fname;
1637 	dns_dbnode_t *node;
1638 	sevent_t *sevent, *wevent;
1639 
1640 	sevent = (sevent_t *)event;
1641 	node = sevent->node;
1642 	fname = sevent->fname;
1643 	isc_event_free(&event);
1644 
1645 	signname(node, dns_fixedname_name(fname));
1646 	wevent = (sevent_t *)
1647 		 isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
1648 				    writenode, NULL, sizeof(sevent_t));
1649 	if (wevent == NULL)
1650 		fatal("failed to allocate event\n");
1651 	wevent->node = node;
1652 	wevent->fname = fname;
1653 	isc_task_send(master, ISC_EVENT_PTR(&wevent));
1654 }
1655 
1656 /*%
1657  * Update / remove the DS RRset.  Preserve RRSIG(DS) if possible.
1658  */
1659 static void
1660 add_ds(dns_name_t *name, dns_dbnode_t *node, uint32_t nsttl) {
1661 	dns_rdataset_t dsset;
1662 	dns_rdataset_t sigdsset;
1663 	isc_result_t result;
1664 
1665 	dns_rdataset_init(&dsset);
1666 	dns_rdataset_init(&sigdsset);
1667 	result = dns_db_findrdataset(gdb, node, gversion,
1668 				     dns_rdatatype_ds,
1669 				     0, 0, &dsset, &sigdsset);
1670 	if (result == ISC_R_SUCCESS) {
1671 		dns_rdataset_disassociate(&dsset);
1672 		result = dns_db_deleterdataset(gdb, node, gversion,
1673 					       dns_rdatatype_ds, 0);
1674 		check_result(result, "dns_db_deleterdataset");
1675 	}
1676 
1677 	result = loadds(name, nsttl, &dsset);
1678 	if (result == ISC_R_SUCCESS) {
1679 		result = dns_db_addrdataset(gdb, node, gversion, 0,
1680 					    &dsset, 0, NULL);
1681 		check_result(result, "dns_db_addrdataset");
1682 		dns_rdataset_disassociate(&dsset);
1683 		if (dns_rdataset_isassociated(&sigdsset))
1684 			dns_rdataset_disassociate(&sigdsset);
1685 	} else if (dns_rdataset_isassociated(&sigdsset)) {
1686 		result = dns_db_deleterdataset(gdb, node, gversion,
1687 					       dns_rdatatype_rrsig,
1688 					       dns_rdatatype_ds);
1689 		check_result(result, "dns_db_deleterdataset");
1690 		dns_rdataset_disassociate(&sigdsset);
1691 	}
1692 }
1693 
1694 /*
1695  * Remove records of the given type and their signatures.
1696  */
1697 static void
1698 remove_records(dns_dbnode_t *node, dns_rdatatype_t which,
1699 	       bool checknsec)
1700 {
1701 	isc_result_t result;
1702 	dns_rdatatype_t type, covers;
1703 	dns_rdatasetiter_t *rdsiter = NULL;
1704 	dns_rdataset_t rdataset;
1705 
1706 	dns_rdataset_init(&rdataset);
1707 
1708 	/*
1709 	 * Delete any records of the given type at the apex.
1710 	 */
1711 	result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1712 	check_result(result, "dns_db_allrdatasets()");
1713 	for (result = dns_rdatasetiter_first(rdsiter);
1714 	     result == ISC_R_SUCCESS;
1715 	     result = dns_rdatasetiter_next(rdsiter)) {
1716 		dns_rdatasetiter_current(rdsiter, &rdataset);
1717 		type = rdataset.type;
1718 		covers = rdataset.covers;
1719 		dns_rdataset_disassociate(&rdataset);
1720 		if (type == which || covers == which) {
1721 			if (which == dns_rdatatype_nsec &&
1722 			    checknsec && !update_chain)
1723 				fatal("Zone contains NSEC records.  Use -u "
1724 				      "to update to NSEC3.");
1725 			if (which == dns_rdatatype_nsec3param &&
1726 			    checknsec && !update_chain)
1727 				fatal("Zone contains NSEC3 chains.  Use -u "
1728 				      "to update to NSEC.");
1729 			result = dns_db_deleterdataset(gdb, node, gversion,
1730 						       type, covers);
1731 			check_result(result, "dns_db_deleterdataset()");
1732 			continue;
1733 		}
1734 	}
1735 	dns_rdatasetiter_destroy(&rdsiter);
1736 }
1737 
1738 /*
1739  * Remove signatures covering the given type.  If type == 0,
1740  * then remove all signatures, unless this is a delegation, in
1741  * which case remove all signatures except for DS or nsec_datatype
1742  */
1743 static void
1744 remove_sigs(dns_dbnode_t *node, bool delegation,
1745 	    dns_rdatatype_t which)
1746 {
1747 	isc_result_t result;
1748 	dns_rdatatype_t type, covers;
1749 	dns_rdatasetiter_t *rdsiter = NULL;
1750 	dns_rdataset_t rdataset;
1751 
1752 	dns_rdataset_init(&rdataset);
1753 	result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1754 	check_result(result, "dns_db_allrdatasets()");
1755 	for (result = dns_rdatasetiter_first(rdsiter);
1756 	     result == ISC_R_SUCCESS;
1757 	     result = dns_rdatasetiter_next(rdsiter)) {
1758 		dns_rdatasetiter_current(rdsiter, &rdataset);
1759 		type = rdataset.type;
1760 		covers = rdataset.covers;
1761 		dns_rdataset_disassociate(&rdataset);
1762 
1763 		if (type != dns_rdatatype_rrsig)
1764 			continue;
1765 
1766 		if (which == 0 && delegation &&
1767 		    (dns_rdatatype_atparent(covers) ||
1768 		     (nsec_datatype == dns_rdatatype_nsec &&
1769 		      covers == nsec_datatype)))
1770 			continue;
1771 
1772 		if (which != 0 && covers != which)
1773 			continue;
1774 
1775 		result = dns_db_deleterdataset(gdb, node, gversion,
1776 					       type, covers);
1777 		check_result(result, "dns_db_deleterdataset()");
1778 	}
1779 	dns_rdatasetiter_destroy(&rdsiter);
1780 }
1781 
1782 /*%
1783  * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records.
1784  */
1785 static void
1786 nsecify(void) {
1787 	dns_dbiterator_t *dbiter = NULL;
1788 	dns_dbnode_t *node = NULL, *nextnode = NULL;
1789 	dns_fixedname_t fname, fnextname, fzonecut;
1790 	dns_name_t *name, *nextname, *zonecut;
1791 	dns_rdataset_t rdataset;
1792 	dns_rdatasetiter_t *rdsiter = NULL;
1793 	dns_rdatatype_t type, covers;
1794 	bool done = false;
1795 	isc_result_t result;
1796 	uint32_t nsttl = 0;
1797 
1798 	dns_rdataset_init(&rdataset);
1799 	name = dns_fixedname_initname(&fname);
1800 	nextname = dns_fixedname_initname(&fnextname);
1801 	zonecut = NULL;
1802 
1803 	/*
1804 	 * Remove any NSEC3 chains.
1805 	 */
1806 	result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
1807 	check_result(result, "dns_db_createiterator()");
1808 	for (result = dns_dbiterator_first(dbiter);
1809 	     result == ISC_R_SUCCESS;
1810 	     result = dns_dbiterator_next(dbiter)) {
1811 		result = dns_dbiterator_current(dbiter, &node, name);
1812 		check_dns_dbiterator_current(result);
1813 		result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1814 		check_result(result, "dns_db_allrdatasets()");
1815 		for (result = dns_rdatasetiter_first(rdsiter);
1816 		     result == ISC_R_SUCCESS;
1817 		     result = dns_rdatasetiter_next(rdsiter)) {
1818 			dns_rdatasetiter_current(rdsiter, &rdataset);
1819 			type = rdataset.type;
1820 			covers = rdataset.covers;
1821 			dns_rdataset_disassociate(&rdataset);
1822 			result = dns_db_deleterdataset(gdb, node, gversion,
1823 						       type, covers);
1824 			check_result(result,
1825 				     "dns_db_deleterdataset(nsec3param/rrsig)");
1826 		}
1827 		dns_rdatasetiter_destroy(&rdsiter);
1828 		dns_db_detachnode(gdb, &node);
1829 	}
1830 	dns_dbiterator_destroy(&dbiter);
1831 
1832 	result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1833 	check_result(result, "dns_db_createiterator()");
1834 
1835 	result = dns_dbiterator_first(dbiter);
1836 	check_result(result, "dns_dbiterator_first()");
1837 
1838 	while (!done) {
1839 		result = dns_dbiterator_current(dbiter, &node, name);
1840 		check_dns_dbiterator_current(result);
1841 		/*
1842 		 * Skip out-of-zone records.
1843 		 */
1844 		if (!dns_name_issubdomain(name, gorigin)) {
1845 			result = dns_dbiterator_next(dbiter);
1846 			if (result == ISC_R_NOMORE)
1847 				done = true;
1848 			else
1849 				check_result(result, "dns_dbiterator_next()");
1850 			dns_db_detachnode(gdb, &node);
1851 			continue;
1852 		}
1853 
1854 		if (dns_name_equal(name, gorigin)) {
1855 			remove_records(node, dns_rdatatype_nsec3param,
1856 				       true);
1857 			/* Clean old rrsigs at apex. */
1858 			(void)active_node(node);
1859 		}
1860 
1861 		if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) {
1862 			zonecut = savezonecut(&fzonecut, name);
1863 			remove_sigs(node, true, 0);
1864 			if (generateds)
1865 				add_ds(name, node, nsttl);
1866 		} else if (has_dname(gdb, gversion, node)) {
1867 			zonecut = savezonecut(&fzonecut, name);
1868 		}
1869 
1870 		result = dns_dbiterator_next(dbiter);
1871 		nextnode = NULL;
1872 		while (result == ISC_R_SUCCESS) {
1873 			bool active = false;
1874 			result = dns_dbiterator_current(dbiter, &nextnode,
1875 							nextname);
1876 			check_dns_dbiterator_current(result);
1877 			active = active_node(nextnode);
1878 			if (!active) {
1879 				dns_db_detachnode(gdb, &nextnode);
1880 				result = dns_dbiterator_next(dbiter);
1881 				continue;
1882 			}
1883 			if (!dns_name_issubdomain(nextname, gorigin) ||
1884 			    (zonecut != NULL &&
1885 			     dns_name_issubdomain(nextname, zonecut)))
1886 			{
1887 				remove_sigs(nextnode, false, 0);
1888 				remove_records(nextnode, dns_rdatatype_nsec,
1889 					       false);
1890 				dns_db_detachnode(gdb, &nextnode);
1891 				result = dns_dbiterator_next(dbiter);
1892 				continue;
1893 			}
1894 			dns_db_detachnode(gdb, &nextnode);
1895 			break;
1896 		}
1897 		if (result == ISC_R_NOMORE) {
1898 			dns_name_clone(gorigin, nextname);
1899 			done = true;
1900 		} else if (result != ISC_R_SUCCESS)
1901 			fatal("iterating through the database failed: %s",
1902 			      isc_result_totext(result));
1903 		dns_dbiterator_pause(dbiter);
1904 		result = dns_nsec_build(gdb, gversion, node, nextname,
1905 					zone_soa_min_ttl);
1906 		check_result(result, "dns_nsec_build()");
1907 		dns_db_detachnode(gdb, &node);
1908 	}
1909 
1910 	dns_dbiterator_destroy(&dbiter);
1911 }
1912 
1913 static void
1914 addnsec3param(const unsigned char *salt, size_t salt_len,
1915 	      dns_iterations_t iterations)
1916 {
1917 	dns_dbnode_t *node = NULL;
1918 	dns_rdata_nsec3param_t nsec3param;
1919 	unsigned char nsec3parambuf[5 + 255];
1920 	dns_rdatalist_t rdatalist;
1921 	dns_rdataset_t rdataset;
1922 	dns_rdata_t rdata = DNS_RDATA_INIT;
1923 	isc_buffer_t b;
1924 	isc_result_t result;
1925 
1926 	dns_rdataset_init(&rdataset);
1927 
1928 	nsec3param.common.rdclass = gclass;
1929 	nsec3param.common.rdtype = dns_rdatatype_nsec3param;
1930 	ISC_LINK_INIT(&nsec3param.common, link);
1931 	nsec3param.mctx = NULL;
1932 	nsec3param.flags = 0;
1933 	nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
1934 	nsec3param.iterations = iterations;
1935 	nsec3param.salt_length = (unsigned char)salt_len;
1936 	DE_CONST(salt, nsec3param.salt);
1937 
1938 	isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
1939 	result = dns_rdata_fromstruct(&rdata, gclass,
1940 				      dns_rdatatype_nsec3param,
1941 				      &nsec3param, &b);
1942 	check_result(result, "dns_rdata_fromstruct()");
1943 	dns_rdatalist_init(&rdatalist);
1944 	rdatalist.rdclass = rdata.rdclass;
1945 	rdatalist.type = rdata.type;
1946 	ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
1947 	result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
1948 	check_result(result, "dns_rdatalist_tordataset()");
1949 
1950 	result = dns_db_findnode(gdb, gorigin, true, &node);
1951 	check_result(result, "dns_db_find(gorigin)");
1952 
1953 	/*
1954 	 * Delete any current NSEC3PARAM records.
1955 	 */
1956 	result = dns_db_deleterdataset(gdb, node, gversion,
1957 				       dns_rdatatype_nsec3param, 0);
1958 	if (result == DNS_R_UNCHANGED)
1959 		result = ISC_R_SUCCESS;
1960 	check_result(result, "dddnsec3param: dns_db_deleterdataset()");
1961 
1962 	result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
1963 				    DNS_DBADD_MERGE, NULL);
1964 	if (result == DNS_R_UNCHANGED)
1965 		result = ISC_R_SUCCESS;
1966 	check_result(result, "addnsec3param: dns_db_addrdataset()");
1967 	dns_db_detachnode(gdb, &node);
1968 }
1969 
1970 static void
1971 addnsec3(dns_name_t *name, dns_dbnode_t *node,
1972 	 const unsigned char *salt, size_t salt_len,
1973 	 unsigned int iterations, hashlist_t *hashlist,
1974 	 dns_ttl_t ttl)
1975 {
1976 	unsigned char hash[NSEC3_MAX_HASH_LENGTH];
1977 	const unsigned char *nexthash;
1978 	unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
1979 	dns_fixedname_t hashname;
1980 	dns_rdatalist_t rdatalist;
1981 	dns_rdataset_t rdataset;
1982 	dns_rdata_t rdata = DNS_RDATA_INIT;
1983 	isc_result_t result;
1984 	dns_dbnode_t *nsec3node = NULL;
1985 	char namebuf[DNS_NAME_FORMATSIZE];
1986 	size_t hash_len;
1987 
1988 	dns_name_format(name, namebuf, sizeof(namebuf));
1989 
1990 	dns_fixedname_init(&hashname);
1991 	dns_rdataset_init(&rdataset);
1992 
1993 	dns_name_downcase(name, name, NULL);
1994 	result = dns_nsec3_hashname(&hashname, hash, &hash_len,
1995 				    name, gorigin, dns_hash_sha1, iterations,
1996 				    salt, salt_len);
1997 	check_result(result, "addnsec3: dns_nsec3_hashname()");
1998 	nexthash = hashlist_findnext(hashlist, hash);
1999 	result = dns_nsec3_buildrdata(gdb, gversion, node,
2000 				      unknownalg ?
2001 					  DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
2002 				      nsec3flags, iterations,
2003 				      salt, salt_len,
2004 				      nexthash, ISC_SHA1_DIGESTLENGTH,
2005 				      nsec3buffer, &rdata);
2006 	check_result(result, "addnsec3: dns_nsec3_buildrdata()");
2007 	dns_rdatalist_init(&rdatalist);
2008 	rdatalist.rdclass = rdata.rdclass;
2009 	rdatalist.type = rdata.type;
2010 	rdatalist.ttl = ttl;
2011 	ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
2012 	result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
2013 	check_result(result, "dns_rdatalist_tordataset()");
2014 	result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
2015 				      true, &nsec3node);
2016 	check_result(result, "addnsec3: dns_db_findnode()");
2017 	result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
2018 				    0, NULL);
2019 	if (result == DNS_R_UNCHANGED)
2020 		result = ISC_R_SUCCESS;
2021 	check_result(result, "addnsec3: dns_db_addrdataset()");
2022 	dns_db_detachnode(gdb, &nsec3node);
2023 }
2024 
2025 /*%
2026  * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
2027  *
2028  * Extract the hash from the first label of 'name' then see if it
2029  * is in hashlist.  If 'name' is not in the hashlist then delete the
2030  * any NSEC3 records which have the same parameters as the chain we
2031  * are building.
2032  *
2033  * XXXMPA Should we also check that it of the form &lt;hash&gt;.&lt;origin&gt;?
2034  */
2035 static void
2036 nsec3clean(dns_name_t *name, dns_dbnode_t *node,
2037 	   unsigned int hashalg, unsigned int iterations,
2038 	   const unsigned char *salt, size_t salt_len, hashlist_t *hashlist)
2039 {
2040 	dns_label_t label;
2041 	dns_rdata_nsec3_t nsec3;
2042 	dns_rdata_t rdata, delrdata;
2043 	dns_rdatalist_t rdatalist;
2044 	dns_rdataset_t rdataset, delrdataset;
2045 	bool delete_rrsigs = false;
2046 	isc_buffer_t target;
2047 	isc_result_t result;
2048 	unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
2049 	bool exists;
2050 
2051 	/*
2052 	 * Get the first label.
2053 	 */
2054 	dns_name_getlabel(name, 0, &label);
2055 
2056 	/*
2057 	 * We want just the label contents.
2058 	 */
2059 	isc_region_consume(&label, 1);
2060 
2061 	/*
2062 	 * Decode base32hex string.
2063 	 */
2064 	isc_buffer_init(&target, hash, sizeof(hash) - 1);
2065 	result = isc_base32hex_decoderegion(&label, &target);
2066 	if (result != ISC_R_SUCCESS)
2067 		return;
2068 
2069 	hash[isc_buffer_usedlength(&target)] = 0;
2070 
2071 	exists = hashlist_exists(hashlist, hash);
2072 
2073 	/*
2074 	 * Verify that the NSEC3 parameters match the current ones
2075 	 * otherwise we are dealing with a different NSEC3 chain.
2076 	 */
2077 	dns_rdataset_init(&rdataset);
2078 	dns_rdataset_init(&delrdataset);
2079 
2080 	result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
2081 				     0, 0, &rdataset, NULL);
2082 	if (result != ISC_R_SUCCESS)
2083 		return;
2084 
2085 	/*
2086 	 * Delete any NSEC3 records which are not part of the current
2087 	 * NSEC3 chain.
2088 	 */
2089 	for (result = dns_rdataset_first(&rdataset);
2090 	     result == ISC_R_SUCCESS;
2091 	     result = dns_rdataset_next(&rdataset)) {
2092 		dns_rdata_init(&rdata);
2093 		dns_rdataset_current(&rdataset, &rdata);
2094 		result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2095 		check_result(result, "dns_rdata_tostruct");
2096 		if (exists && nsec3.hash == hashalg &&
2097 		    nsec3.iterations == iterations &&
2098 		    nsec3.salt_length == salt_len &&
2099 		    isc_safe_memequal(nsec3.salt, salt, salt_len))
2100 			continue;
2101 		dns_rdatalist_init(&rdatalist);
2102 		rdatalist.rdclass = rdata.rdclass;
2103 		rdatalist.type = rdata.type;
2104 		if (set_maxttl)
2105 			rdatalist.ttl = ISC_MIN(rdataset.ttl, maxttl);
2106 		dns_rdata_init(&delrdata);
2107 		dns_rdata_clone(&rdata, &delrdata);
2108 		ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
2109 		result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
2110 		check_result(result, "dns_rdatalist_tordataset()");
2111 		result = dns_db_subtractrdataset(gdb, node, gversion,
2112 						 &delrdataset, 0, NULL);
2113 		dns_rdataset_disassociate(&delrdataset);
2114 		if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET)
2115 			check_result(result, "dns_db_subtractrdataset(NSEC3)");
2116 		delete_rrsigs = true;
2117 	}
2118 	dns_rdataset_disassociate(&rdataset);
2119 	if (result != ISC_R_NOMORE)
2120 		check_result(result, "dns_rdataset_first/next");
2121 
2122 	if (!delete_rrsigs)
2123 		return;
2124 	/*
2125 	 * Delete the NSEC3 RRSIGs
2126 	 */
2127 	result = dns_db_deleterdataset(gdb, node, gversion,
2128 				       dns_rdatatype_rrsig,
2129 				       dns_rdatatype_nsec3);
2130 	if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
2131 		check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
2132 }
2133 
2134 static void
2135 rrset_cleanup(dns_name_t *name, dns_rdataset_t *rdataset,
2136 	      dns_diff_t *add, dns_diff_t *del)
2137 {
2138 	isc_result_t result;
2139 	unsigned int count1 = 0;
2140 	dns_rdataset_t tmprdataset;
2141 	char namestr[DNS_NAME_FORMATSIZE];
2142 	char typestr[DNS_RDATATYPE_FORMATSIZE];
2143 
2144 	dns_name_format(name, namestr, sizeof(namestr));
2145 	dns_rdatatype_format(rdataset->type, typestr, sizeof(typestr));
2146 
2147 	dns_rdataset_init(&tmprdataset);
2148 	for (result = dns_rdataset_first(rdataset);
2149 	     result == ISC_R_SUCCESS;
2150 	     result = dns_rdataset_next(rdataset)) {
2151 		dns_rdata_t rdata1 = DNS_RDATA_INIT;
2152 		unsigned int count2 = 0;
2153 
2154 		count1++;
2155 		dns_rdataset_current(rdataset, &rdata1);
2156 		dns_rdataset_clone(rdataset, &tmprdataset);
2157 		for (result = dns_rdataset_first(&tmprdataset);
2158 		     result == ISC_R_SUCCESS;
2159 		     result = dns_rdataset_next(&tmprdataset)) {
2160 			dns_rdata_t rdata2 = DNS_RDATA_INIT;
2161 			dns_difftuple_t *tuple = NULL;
2162 			count2++;
2163 			dns_rdataset_current(&tmprdataset, &rdata2);
2164 			if (count1 < count2 &&
2165 			    dns_rdata_casecompare(&rdata1, &rdata2) == 0)
2166 			{
2167 				vbprintf(2, "removing duplicate at %s/%s\n",
2168 					    namestr, typestr);
2169 				result = dns_difftuple_create(mctx,
2170 						      DNS_DIFFOP_DELRESIGN,
2171 						      name, rdataset->ttl,
2172 						      &rdata2, &tuple);
2173 				check_result(result, "dns_difftuple_create");
2174 				dns_diff_append(del, &tuple);
2175 			} else if (set_maxttl && rdataset->ttl > maxttl) {
2176 				vbprintf(2, "reducing ttl of %s/%s "
2177 					    "from %d to %d\n",
2178 					    namestr, typestr,
2179 					    rdataset->ttl, maxttl);
2180 				result = dns_difftuple_create(mctx,
2181 						      DNS_DIFFOP_DELRESIGN,
2182 						      name, rdataset->ttl,
2183 						      &rdata2, &tuple);
2184 				check_result(result, "dns_difftuple_create");
2185 				dns_diff_append(del, &tuple);
2186 				tuple = NULL;
2187 				result = dns_difftuple_create(mctx,
2188 						      DNS_DIFFOP_ADDRESIGN,
2189 						      name, maxttl,
2190 						      &rdata2, &tuple);
2191 				check_result(result, "dns_difftuple_create");
2192 				dns_diff_append(add, &tuple);
2193 			}
2194 		}
2195 		dns_rdataset_disassociate(&tmprdataset);
2196 	}
2197 }
2198 
2199 static void
2200 cleanup_zone(void) {
2201 	isc_result_t result;
2202 	dns_dbiterator_t *dbiter = NULL;
2203 	dns_rdatasetiter_t *rdsiter = NULL;
2204 	dns_diff_t add, del;
2205 	dns_dbnode_t *node = NULL;
2206 	dns_rdataset_t rdataset;
2207 	dns_fixedname_t fname;
2208 	dns_name_t *name;
2209 
2210 	dns_diff_init(mctx, &add);
2211 	dns_diff_init(mctx, &del);
2212 	name = dns_fixedname_initname(&fname);
2213 	dns_rdataset_init(&rdataset);
2214 
2215 	result = dns_db_createiterator(gdb, 0, &dbiter);
2216 	check_result(result, "dns_db_createiterator()");
2217 
2218 	for (result = dns_dbiterator_first(dbiter);
2219 	     result == ISC_R_SUCCESS;
2220 	     result = dns_dbiterator_next(dbiter)) {
2221 
2222 		result = dns_dbiterator_current(dbiter, &node, name);
2223 		check_dns_dbiterator_current(result);
2224 		result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
2225 		check_result(result, "dns_db_allrdatasets()");
2226 		for (result = dns_rdatasetiter_first(rdsiter);
2227 		     result == ISC_R_SUCCESS;
2228 		     result = dns_rdatasetiter_next(rdsiter)) {
2229 			dns_rdatasetiter_current(rdsiter, &rdataset);
2230 			rrset_cleanup(name, &rdataset, &add, &del);
2231 			dns_rdataset_disassociate(&rdataset);
2232 		}
2233 		if (result != ISC_R_NOMORE)
2234 			fatal("rdatasets iteration failed.");
2235 		dns_rdatasetiter_destroy(&rdsiter);
2236 		dns_db_detachnode(gdb, &node);
2237 	}
2238 	if (result != ISC_R_NOMORE)
2239 		fatal("zone iteration failed.");
2240 
2241 	result = dns_diff_applysilently(&del, gdb, gversion);
2242 	check_result(result, "dns_diff_applysilently");
2243 
2244 	result = dns_diff_applysilently(&add, gdb, gversion);
2245 	check_result(result, "dns_diff_applysilently");
2246 
2247 	dns_diff_clear(&del);
2248 	dns_diff_clear(&add);
2249 	dns_dbiterator_destroy(&dbiter);
2250 }
2251 
2252 /*
2253  * Generate NSEC3 records for the zone.
2254  */
2255 static void
2256 nsec3ify(unsigned int hashalg, dns_iterations_t iterations,
2257 	 const unsigned char *salt, size_t salt_len, hashlist_t *hashlist)
2258 {
2259 	dns_dbiterator_t *dbiter = NULL;
2260 	dns_dbnode_t *node = NULL, *nextnode = NULL;
2261 	dns_fixedname_t fname, fnextname, fzonecut;
2262 	dns_name_t *name, *nextname, *zonecut;
2263 	dns_rdataset_t rdataset;
2264 	int order;
2265 	bool active;
2266 	bool done = false;
2267 	isc_result_t result;
2268 	uint32_t nsttl = 0;
2269 	unsigned int count, nlabels;
2270 
2271 	dns_rdataset_init(&rdataset);
2272 	name = dns_fixedname_initname(&fname);
2273 	nextname = dns_fixedname_initname(&fnextname);
2274 	zonecut = NULL;
2275 
2276 	/*
2277 	 * Walk the zone generating the hash names.
2278 	 */
2279 	result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2280 	check_result(result, "dns_db_createiterator()");
2281 
2282 	result = dns_dbiterator_first(dbiter);
2283 	check_result(result, "dns_dbiterator_first()");
2284 
2285 	while (!done) {
2286 		result = dns_dbiterator_current(dbiter, &node, name);
2287 		check_dns_dbiterator_current(result);
2288 		/*
2289 		 * Skip out-of-zone records.
2290 		 */
2291 		if (!dns_name_issubdomain(name, gorigin)) {
2292 			result = dns_dbiterator_next(dbiter);
2293 			if (result == ISC_R_NOMORE)
2294 				done = true;
2295 			else
2296 				check_result(result, "dns_dbiterator_next()");
2297 			dns_db_detachnode(gdb, &node);
2298 			continue;
2299 		}
2300 
2301 		if (dns_name_equal(name, gorigin)) {
2302 			remove_records(node, dns_rdatatype_nsec, true);
2303 			/* Clean old rrsigs at apex. */
2304 			(void)active_node(node);
2305 		}
2306 
2307 		if (has_dname(gdb, gversion, node)) {
2308 			zonecut = savezonecut(&fzonecut, name);
2309 		}
2310 
2311 		result = dns_dbiterator_next(dbiter);
2312 		nextnode = NULL;
2313 		while (result == ISC_R_SUCCESS) {
2314 			result = dns_dbiterator_current(dbiter, &nextnode,
2315 							nextname);
2316 			check_dns_dbiterator_current(result);
2317 			active = active_node(nextnode);
2318 			if (!active) {
2319 				dns_db_detachnode(gdb, &nextnode);
2320 				result = dns_dbiterator_next(dbiter);
2321 				continue;
2322 			}
2323 			if (!dns_name_issubdomain(nextname, gorigin) ||
2324 			    (zonecut != NULL &&
2325 			     dns_name_issubdomain(nextname, zonecut))) {
2326 				remove_sigs(nextnode, false, 0);
2327 				dns_db_detachnode(gdb, &nextnode);
2328 				result = dns_dbiterator_next(dbiter);
2329 				continue;
2330 			}
2331 			if (is_delegation(gdb, gversion, gorigin,
2332 					  nextname, nextnode, &nsttl))
2333 			{
2334 				zonecut = savezonecut(&fzonecut, nextname);
2335 				remove_sigs(nextnode, true, 0);
2336 				if (generateds)
2337 					add_ds(nextname, nextnode, nsttl);
2338 				if (OPTOUT(nsec3flags) &&
2339 				    !secure(nextname, nextnode)) {
2340 					dns_db_detachnode(gdb, &nextnode);
2341 					result = dns_dbiterator_next(dbiter);
2342 					continue;
2343 				}
2344 			} else if (has_dname(gdb, gversion, nextnode)) {
2345 				zonecut = savezonecut(&fzonecut, nextname);
2346 			}
2347 			dns_db_detachnode(gdb, &nextnode);
2348 			break;
2349 		}
2350 		if (result == ISC_R_NOMORE) {
2351 			dns_name_copy(gorigin, nextname, NULL);
2352 			done = true;
2353 		} else if (result != ISC_R_SUCCESS)
2354 			fatal("iterating through the database failed: %s",
2355 			      isc_result_totext(result));
2356 		dns_name_downcase(name, name, NULL);
2357 		hashlist_add_dns_name(hashlist, name, hashalg, iterations,
2358 				      salt, salt_len, false);
2359 		dns_db_detachnode(gdb, &node);
2360 		/*
2361 		 * Add hashs for empty nodes.  Use closest encloser logic.
2362 		 * The closest encloser either has data or is a empty
2363 		 * node for another <name,nextname> span so we don't add
2364 		 * it here.  Empty labels on nextname are within the span.
2365 		 */
2366 		dns_name_downcase(nextname, nextname, NULL);
2367 		dns_name_fullcompare(name, nextname, &order, &nlabels);
2368 		addnowildcardhash(hashlist, name, hashalg, iterations,
2369 				  salt, salt_len);
2370 		count = dns_name_countlabels(nextname);
2371 		while (count > nlabels + 1) {
2372 			count--;
2373 			dns_name_split(nextname, count, NULL, nextname);
2374 			hashlist_add_dns_name(hashlist, nextname, hashalg,
2375 					      iterations, salt, salt_len,
2376 					      false);
2377 			addnowildcardhash(hashlist, nextname, hashalg,
2378 					  iterations, salt, salt_len);
2379 		}
2380 	}
2381 	dns_dbiterator_destroy(&dbiter);
2382 
2383 	/*
2384 	 * We have all the hashes now so we can sort them.
2385 	 */
2386 	hashlist_sort(hashlist);
2387 
2388 	/*
2389 	 * Check for duplicate hashes.  If found the salt needs to
2390 	 * be changed.
2391 	 */
2392 	if (hashlist_hasdup(hashlist))
2393 		fatal("Duplicate hash detected. Pick a different salt.");
2394 
2395 	/*
2396 	 * Generate the nsec3 records.
2397 	 */
2398 	zonecut = NULL;
2399 	done = false;
2400 
2401 	addnsec3param(salt, salt_len, iterations);
2402 
2403 	/*
2404 	 * Clean out NSEC3 records which don't match this chain.
2405 	 */
2406 	result = dns_db_createiterator(gdb, DNS_DB_NSEC3ONLY, &dbiter);
2407 	check_result(result, "dns_db_createiterator()");
2408 
2409 	for (result = dns_dbiterator_first(dbiter);
2410 	     result == ISC_R_SUCCESS;
2411 	     result = dns_dbiterator_next(dbiter)) {
2412 		result = dns_dbiterator_current(dbiter, &node, name);
2413 		check_dns_dbiterator_current(result);
2414 		nsec3clean(name, node, hashalg, iterations, salt, salt_len,
2415 			   hashlist);
2416 		dns_db_detachnode(gdb, &node);
2417 	}
2418 	dns_dbiterator_destroy(&dbiter);
2419 
2420 	/*
2421 	 * Generate / complete the new chain.
2422 	 */
2423 	result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
2424 	check_result(result, "dns_db_createiterator()");
2425 
2426 	result = dns_dbiterator_first(dbiter);
2427 	check_result(result, "dns_dbiterator_first()");
2428 
2429 	while (!done) {
2430 		result = dns_dbiterator_current(dbiter, &node, name);
2431 		check_dns_dbiterator_current(result);
2432 		/*
2433 		 * Skip out-of-zone records.
2434 		 */
2435 		if (!dns_name_issubdomain(name, gorigin)) {
2436 			result = dns_dbiterator_next(dbiter);
2437 			if (result == ISC_R_NOMORE)
2438 				done = true;
2439 			else
2440 				check_result(result, "dns_dbiterator_next()");
2441 			dns_db_detachnode(gdb, &node);
2442 			continue;
2443 		}
2444 
2445 		if (has_dname(gdb, gversion, node)) {
2446 			zonecut = savezonecut(&fzonecut, name);
2447 		}
2448 
2449 		result = dns_dbiterator_next(dbiter);
2450 		nextnode = NULL;
2451 		while (result == ISC_R_SUCCESS) {
2452 			result = dns_dbiterator_current(dbiter, &nextnode,
2453 							nextname);
2454 			check_dns_dbiterator_current(result);
2455 			active = active_node(nextnode);
2456 			if (!active) {
2457 				dns_db_detachnode(gdb, &nextnode);
2458 				result = dns_dbiterator_next(dbiter);
2459 				continue;
2460 			}
2461 			if (!dns_name_issubdomain(nextname, gorigin) ||
2462 			    (zonecut != NULL &&
2463 			     dns_name_issubdomain(nextname, zonecut))) {
2464 				dns_db_detachnode(gdb, &nextnode);
2465 				result = dns_dbiterator_next(dbiter);
2466 				continue;
2467 			}
2468 			if (is_delegation(gdb, gversion, gorigin,
2469 					  nextname, nextnode, NULL))
2470 			{
2471 				zonecut = savezonecut(&fzonecut, nextname);
2472 				if (OPTOUT(nsec3flags) &&
2473 				    !secure(nextname, nextnode)) {
2474 					dns_db_detachnode(gdb, &nextnode);
2475 					result = dns_dbiterator_next(dbiter);
2476 					continue;
2477 				}
2478 			} else if (has_dname(gdb, gversion, nextnode)) {
2479 				zonecut = savezonecut(&fzonecut, nextname);
2480 			}
2481 			dns_db_detachnode(gdb, &nextnode);
2482 			break;
2483 		}
2484 		if (result == ISC_R_NOMORE) {
2485 			dns_name_copy(gorigin, nextname, NULL);
2486 			done = true;
2487 		} else if (result != ISC_R_SUCCESS)
2488 			fatal("iterating through the database failed: %s",
2489 			      isc_result_totext(result));
2490 		/*
2491 		 * We need to pause here to release the lock on the database.
2492 		 */
2493 		dns_dbiterator_pause(dbiter);
2494 		addnsec3(name, node, salt, salt_len, iterations,
2495 			 hashlist, zone_soa_min_ttl);
2496 		dns_db_detachnode(gdb, &node);
2497 		/*
2498 		 * Add NSEC3's for empty nodes.  Use closest encloser logic.
2499 		 */
2500 		dns_name_fullcompare(name, nextname, &order, &nlabels);
2501 		count = dns_name_countlabels(nextname);
2502 		while (count > nlabels + 1) {
2503 			count--;
2504 			dns_name_split(nextname, count, NULL, nextname);
2505 			addnsec3(nextname, NULL, salt, salt_len,
2506 				 iterations, hashlist, zone_soa_min_ttl);
2507 		}
2508 	}
2509 	dns_dbiterator_destroy(&dbiter);
2510 }
2511 
2512 /*%
2513  * Load the zone file from disk
2514  */
2515 static void
2516 loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
2517 	isc_buffer_t b;
2518 	int len;
2519 	dns_fixedname_t fname;
2520 	dns_name_t *name;
2521 	isc_result_t result;
2522 
2523 	len = strlen(origin);
2524 	isc_buffer_init(&b, origin, len);
2525 	isc_buffer_add(&b, len);
2526 
2527 	name = dns_fixedname_initname(&fname);
2528 	result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
2529 	if (result != ISC_R_SUCCESS)
2530 		fatal("failed converting name '%s' to dns format: %s",
2531 		      origin, isc_result_totext(result));
2532 
2533 	result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
2534 			       rdclass, 0, NULL, db);
2535 	check_result(result, "dns_db_create()");
2536 
2537 	result = dns_db_load(*db, file, inputformat, 0);
2538 	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
2539 		fatal("failed loading zone from '%s': %s",
2540 		      file, isc_result_totext(result));
2541 }
2542 
2543 /*%
2544  * Finds all public zone keys in the zone, and attempts to load the
2545  * private keys from disk.
2546  */
2547 static void
2548 loadzonekeys(bool preserve_keys, bool load_public) {
2549 	dns_dbnode_t *node;
2550 	dns_dbversion_t *currentversion = NULL;
2551 	isc_result_t result;
2552 	dns_rdataset_t rdataset, keysigs, soasigs;
2553 
2554 	node = NULL;
2555 	result = dns_db_findnode(gdb, gorigin, false, &node);
2556 	if (result != ISC_R_SUCCESS)
2557 		fatal("failed to find the zone's origin: %s",
2558 		      isc_result_totext(result));
2559 
2560 	dns_db_currentversion(gdb, &currentversion);
2561 
2562 	dns_rdataset_init(&rdataset);
2563 	dns_rdataset_init(&soasigs);
2564 	dns_rdataset_init(&keysigs);
2565 
2566 	/* Make note of the keys which signed the SOA, if any */
2567 	result = dns_db_findrdataset(gdb, node, currentversion,
2568 				     dns_rdatatype_soa, 0, 0,
2569 				     &rdataset, &soasigs);
2570 	if (result != ISC_R_SUCCESS)
2571 		goto cleanup;
2572 
2573 	/* Preserve the TTL of the DNSKEY RRset, if any */
2574 	dns_rdataset_disassociate(&rdataset);
2575 	result = dns_db_findrdataset(gdb, node, currentversion,
2576 				     dns_rdatatype_dnskey, 0, 0,
2577 				     &rdataset, &keysigs);
2578 
2579 	if (result != ISC_R_SUCCESS)
2580 		goto cleanup;
2581 
2582 	if (set_keyttl && keyttl != rdataset.ttl) {
2583 		fprintf(stderr, "User-specified TTL %u conflicts "
2584 				"with existing DNSKEY RRset TTL.\n",
2585 				keyttl);
2586 		fprintf(stderr, "Imported keys will use the RRSet "
2587 				"TTL %u instead.\n",
2588 				rdataset.ttl);
2589 	}
2590 	keyttl = rdataset.ttl;
2591 
2592 	/* Load keys corresponding to the existing DNSKEY RRset. */
2593 	result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx,
2594 						&rdataset, &keysigs, &soasigs,
2595 						preserve_keys, load_public,
2596 						&keylist);
2597 	if (result != ISC_R_SUCCESS)
2598 		fatal("failed to load the zone keys: %s",
2599 		      isc_result_totext(result));
2600 
2601  cleanup:
2602 	if (dns_rdataset_isassociated(&rdataset))
2603 		dns_rdataset_disassociate(&rdataset);
2604 	if (dns_rdataset_isassociated(&keysigs))
2605 		dns_rdataset_disassociate(&keysigs);
2606 	if (dns_rdataset_isassociated(&soasigs))
2607 		dns_rdataset_disassociate(&soasigs);
2608 	dns_db_detachnode(gdb, &node);
2609 	dns_db_closeversion(gdb, &currentversion, false);
2610 }
2611 
2612 static void
2613 loadexplicitkeys(char *keyfiles[], int n, bool setksk) {
2614 	isc_result_t result;
2615 	int i;
2616 
2617 	for (i = 0; i < n; i++) {
2618 		dns_dnsseckey_t *key = NULL;
2619 		dst_key_t *newkey = NULL;
2620 
2621 		result = dst_key_fromnamedfile(keyfiles[i], directory,
2622 					       DST_TYPE_PUBLIC |
2623 					       DST_TYPE_PRIVATE,
2624 					       mctx, &newkey);
2625 		if (result != ISC_R_SUCCESS)
2626 			fatal("cannot load dnskey %s: %s", keyfiles[i],
2627 			      isc_result_totext(result));
2628 
2629 		if (!dns_name_equal(gorigin, dst_key_name(newkey)))
2630 			fatal("key %s not at origin\n", keyfiles[i]);
2631 
2632 		if (!dst_key_isprivate(newkey))
2633 			fatal("cannot sign zone with non-private dnskey %s",
2634 			      keyfiles[i]);
2635 
2636 		/* Skip any duplicates */
2637 		for (key = ISC_LIST_HEAD(keylist);
2638 		     key != NULL;
2639 		     key = ISC_LIST_NEXT(key, link)) {
2640 			if (dst_key_id(key->key) == dst_key_id(newkey) &&
2641 			    dst_key_alg(key->key) == dst_key_alg(newkey))
2642 				break;
2643 		}
2644 
2645 		if (key == NULL) {
2646 			/* We haven't seen this key before */
2647 			dns_dnsseckey_create(mctx, &newkey, &key);
2648 			ISC_LIST_APPEND(keylist, key, link);
2649 			key->source = dns_keysource_user;
2650 		} else {
2651 			dst_key_free(&key->key);
2652 			key->key = newkey;
2653 		}
2654 
2655 		key->force_publish = true;
2656 		key->force_sign = true;
2657 
2658 		if (setksk)
2659 			key->ksk = true;
2660 	}
2661 }
2662 
2663 static void
2664 report(const char *format, ...) {
2665 	va_list args;
2666 	va_start(args, format);
2667 	vfprintf(stderr, format, args);
2668 	va_end(args);
2669 	putc('\n', stderr);
2670 }
2671 
2672 static void
2673 clear_keylist(dns_dnsseckeylist_t *list) {
2674 	dns_dnsseckey_t *key;
2675 	while (!ISC_LIST_EMPTY(*list)) {
2676 		key = ISC_LIST_HEAD(*list);
2677 		ISC_LIST_UNLINK(*list, key, link);
2678 		dns_dnsseckey_destroy(mctx, &key);
2679 	}
2680 }
2681 
2682 static void
2683 build_final_keylist(void) {
2684 	isc_result_t result;
2685 	dns_dbnode_t *node = NULL;
2686 	dns_dbversion_t *ver = NULL;
2687 	dns_diff_t diff;
2688 	dns_dnsseckeylist_t rmkeys, matchkeys;
2689 	char name[DNS_NAME_FORMATSIZE];
2690 	dns_rdataset_t cdsset, cdnskeyset, soaset;
2691 
2692 	ISC_LIST_INIT(rmkeys);
2693 	ISC_LIST_INIT(matchkeys);
2694 
2695 	dns_rdataset_init(&soaset);
2696 	dns_rdataset_init(&cdsset);
2697 	dns_rdataset_init(&cdnskeyset);
2698 
2699 	/*
2700 	 * Find keys that match this zone in the key repository.
2701 	 */
2702 	result = dns_dnssec_findmatchingkeys(gorigin, directory,
2703 					     now, mctx, &matchkeys);
2704 	if (result == ISC_R_NOTFOUND) {
2705 		result = ISC_R_SUCCESS;
2706 	}
2707 	check_result(result, "dns_dnssec_findmatchingkeys");
2708 
2709 	result = dns_db_newversion(gdb, &ver);
2710 	check_result(result, "dns_db_newversion");
2711 
2712 	result = dns_db_getoriginnode(gdb, &node);
2713 	check_result(result, "dns_db_getoriginnode");
2714 
2715 	/* Get the CDS rdataset */
2716 	result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_cds,
2717 				     dns_rdatatype_none, 0, &cdsset, NULL);
2718 	if (result != ISC_R_SUCCESS &&
2719 	    dns_rdataset_isassociated(&cdsset))
2720 	{
2721 		dns_rdataset_disassociate(&cdsset);
2722 	}
2723 
2724 	/* Get the CDNSKEY rdataset */
2725 	result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_cdnskey,
2726 				     dns_rdatatype_none, 0, &cdnskeyset, NULL);
2727 	if (result != ISC_R_SUCCESS &&
2728 	    dns_rdataset_isassociated(&cdnskeyset))
2729 	{
2730 		dns_rdataset_disassociate(&cdnskeyset);
2731 	}
2732 
2733 	dns_diff_init(mctx, &diff);
2734 
2735 	/*
2736 	 * Update keylist with information from from the key repository.
2737 	 */
2738 	dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
2739 			      &diff, ignore_kskflag, mctx, report);
2740 
2741 	/*
2742 	 * Update keylist with sync records.
2743 	 */
2744 	dns_dnssec_syncupdate(&keylist, &rmkeys, &cdsset, &cdnskeyset,
2745 			      now, keyttl, &diff, mctx);
2746 
2747 	dns_name_format(gorigin, name, sizeof(name));
2748 
2749 	result = dns_diff_applysilently(&diff, gdb, ver);
2750 	if (result != ISC_R_SUCCESS) {
2751 		fatal("failed to update DNSKEY RRset at node '%s': %s",
2752 		      name, isc_result_totext(result));
2753 	}
2754 
2755 	dns_db_detachnode(gdb, &node);
2756 	dns_db_closeversion(gdb, &ver, true);
2757 
2758 	dns_diff_clear(&diff);
2759 
2760 	if (dns_rdataset_isassociated(&cdsset)) {
2761 		dns_rdataset_disassociate(&cdsset);
2762 	}
2763 	if (dns_rdataset_isassociated(&cdnskeyset)) {
2764 		dns_rdataset_disassociate(&cdnskeyset);
2765 	}
2766 
2767 	clear_keylist(&rmkeys);
2768 	clear_keylist(&matchkeys);
2769 }
2770 
2771 static void
2772 warnifallksk(dns_db_t *db) {
2773 	dns_dbversion_t *currentversion = NULL;
2774 	dns_dbnode_t *node = NULL;
2775 	dns_rdataset_t rdataset;
2776 	dns_rdata_t rdata = DNS_RDATA_INIT;
2777 	isc_result_t result;
2778 	dns_rdata_dnskey_t dnskey;
2779 	bool have_non_ksk = false;
2780 
2781 	dns_db_currentversion(db, &currentversion);
2782 
2783 	result = dns_db_findnode(db, gorigin, false, &node);
2784 	if (result != ISC_R_SUCCESS)
2785 		fatal("failed to find the zone's origin: %s",
2786 		      isc_result_totext(result));
2787 
2788 	dns_rdataset_init(&rdataset);
2789 	result = dns_db_findrdataset(db, node, currentversion,
2790 				     dns_rdatatype_dnskey, 0, 0, &rdataset,
2791 				     NULL);
2792 	if (result != ISC_R_SUCCESS)
2793 		fatal("failed to find keys at the zone apex: %s",
2794 		      isc_result_totext(result));
2795 	result = dns_rdataset_first(&rdataset);
2796 	check_result(result, "dns_rdataset_first");
2797 	while (result == ISC_R_SUCCESS) {
2798 		dns_rdata_reset(&rdata);
2799 		dns_rdataset_current(&rdataset, &rdata);
2800 		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2801 		check_result(result, "dns_rdata_tostruct");
2802 		if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
2803 			have_non_ksk = true;
2804 			result = ISC_R_NOMORE;
2805 		} else
2806 			result = dns_rdataset_next(&rdataset);
2807 		dns_rdata_freestruct(&dnskey);
2808 	}
2809 	dns_rdataset_disassociate(&rdataset);
2810 	dns_db_detachnode(db, &node);
2811 	dns_db_closeversion(db, &currentversion, false);
2812 	if (!have_non_ksk && !ignore_kskflag) {
2813 		if (disable_zone_check)
2814 			fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
2815 				"supply a ZSK or use '-z'.\n",
2816 				program);
2817 		else
2818 			fatal("No non-KSK DNSKEY found; "
2819 			      "supply a ZSK or use '-z'.");
2820 	}
2821 }
2822 
2823 static void
2824 set_nsec3params(bool update, bool set_salt,
2825 		bool set_optout, bool set_iter)
2826 {
2827 	isc_result_t result;
2828 	dns_dbversion_t *ver = NULL;
2829 	dns_dbnode_t *node = NULL;
2830 	dns_rdataset_t rdataset;
2831 	dns_rdata_t rdata = DNS_RDATA_INIT;
2832 	dns_rdata_nsec3_t nsec3;
2833 	dns_fixedname_t fname;
2834 	dns_name_t *hashname;
2835 	unsigned char orig_salt[255];
2836 	size_t orig_saltlen;
2837 	dns_hash_t orig_hash;
2838 	uint16_t orig_iter;
2839 
2840 	dns_db_currentversion(gdb, &ver);
2841 	dns_rdataset_init(&rdataset);
2842 
2843 	orig_saltlen = sizeof(orig_salt);
2844 	result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
2845 					   &orig_iter, orig_salt,
2846 					   &orig_saltlen);
2847 	if (result != ISC_R_SUCCESS)
2848 		goto cleanup;
2849 
2850 	nsec_datatype = dns_rdatatype_nsec3;
2851 
2852 	if (!update && set_salt) {
2853 		if (salt_length != orig_saltlen ||
2854 		    !isc_safe_memequal(saltbuf, orig_salt, salt_length))
2855 			fatal("An NSEC3 chain exists with a different salt. "
2856 			      "Use -u to update it.");
2857 	} else if (!set_salt) {
2858 		salt_length = orig_saltlen;
2859 		memmove(saltbuf, orig_salt, orig_saltlen);
2860 		gsalt = saltbuf;
2861 	}
2862 
2863 	if (!update && set_iter) {
2864 		if (nsec3iter != orig_iter)
2865 			fatal("An NSEC3 chain exists with different "
2866 			      "iterations. Use -u to update it.");
2867 	} else if (!set_iter)
2868 		nsec3iter = orig_iter;
2869 
2870 	/*
2871 	 * Find an NSEC3 record to get the current OPTOUT value.
2872 	 * (This assumes all NSEC3 records agree.)
2873 	 */
2874 
2875 	hashname = dns_fixedname_initname(&fname);
2876 	result = dns_nsec3_hashname(&fname, NULL, NULL,
2877 				    gorigin, gorigin, dns_hash_sha1,
2878 				    orig_iter, orig_salt, orig_saltlen);
2879 	check_result(result, "dns_nsec3_hashname");
2880 
2881 	result = dns_db_findnsec3node(gdb, hashname, false, &node);
2882 	if (result != ISC_R_SUCCESS)
2883 		goto cleanup;
2884 
2885 	result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3,
2886 				     0, 0, &rdataset, NULL);
2887 	if (result != ISC_R_SUCCESS)
2888 		goto cleanup;
2889 
2890 	result = dns_rdataset_first(&rdataset);
2891 	check_result(result, "dns_rdataset_first");
2892 	dns_rdataset_current(&rdataset, &rdata);
2893 	result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
2894 	check_result(result, "dns_rdata_tostruct");
2895 
2896 	if (!update && set_optout) {
2897 		if (nsec3flags != nsec3.flags)
2898 			fatal("An NSEC3 chain exists with%s OPTOUT. "
2899 			      "Use -u -%s to %s it.",
2900 			      OPTOUT(nsec3.flags) ? "" : "out",
2901 			      OPTOUT(nsec3.flags) ? "AA" : "A",
2902 			      OPTOUT(nsec3.flags) ? "clear" : "set");
2903 	} else if (!set_optout)
2904 		nsec3flags = nsec3.flags;
2905 
2906 	dns_rdata_freestruct(&nsec3);
2907 
2908  cleanup:
2909 	if (dns_rdataset_isassociated(&rdataset))
2910 		dns_rdataset_disassociate(&rdataset);
2911 	if (node != NULL)
2912 		dns_db_detachnode(gdb, &node);
2913 	dns_db_closeversion(gdb, &ver, false);
2914 }
2915 
2916 static void
2917 writeset(const char *prefix, dns_rdatatype_t type) {
2918 	char *filename;
2919 	char namestr[DNS_NAME_FORMATSIZE];
2920 	dns_db_t *db = NULL;
2921 	dns_dbversion_t *dbversion = NULL;
2922 	dns_diff_t diff;
2923 	dns_difftuple_t *tuple = NULL;
2924 	dns_fixedname_t fixed;
2925 	dns_name_t *name;
2926 	dns_rdata_t rdata, ds;
2927 	bool have_ksk = false;
2928 	bool have_non_ksk = false;
2929 	isc_buffer_t b;
2930 	isc_buffer_t namebuf;
2931 	isc_region_t r;
2932 	isc_result_t result;
2933 	dns_dnsseckey_t *key, *tmpkey;
2934 	unsigned char dsbuf[DNS_DS_BUFFERSIZE];
2935 	unsigned char keybuf[DST_KEY_MAXSIZE];
2936 	unsigned int filenamelen;
2937 	const dns_master_style_t *style =
2938 		(type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
2939 
2940 	isc_buffer_init(&namebuf, namestr, sizeof(namestr));
2941 	result = dns_name_tofilenametext(gorigin, false, &namebuf);
2942 	check_result(result, "dns_name_tofilenametext");
2943 	isc_buffer_putuint8(&namebuf, 0);
2944 	filenamelen = strlen(prefix) + strlen(namestr) + 1;
2945 	if (dsdir != NULL)
2946 		filenamelen += strlen(dsdir) + 1;
2947 	filename = isc_mem_get(mctx, filenamelen);
2948 	if (filename == NULL)
2949 		fatal("out of memory");
2950 	if (dsdir != NULL)
2951 		snprintf(filename, filenamelen, "%s/", dsdir);
2952 	else
2953 		filename[0] = 0;
2954 	strlcat(filename, prefix, filenamelen);
2955 	strlcat(filename, namestr, filenamelen);
2956 
2957 	dns_diff_init(mctx, &diff);
2958 
2959 	if (type == dns_rdatatype_dlv) {
2960 		dns_name_t tname;
2961 		unsigned int labels;
2962 
2963 		dns_name_init(&tname, NULL);
2964 		name = dns_fixedname_initname(&fixed);
2965 		labels = dns_name_countlabels(gorigin);
2966 		dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
2967 		result = dns_name_concatenate(&tname, dlv, name, NULL);
2968 		check_result(result, "dns_name_concatenate");
2969 	} else
2970 		name = gorigin;
2971 
2972 	for (key = ISC_LIST_HEAD(keylist);
2973 	     key != NULL;
2974 	     key = ISC_LIST_NEXT(key, link))
2975 	{
2976 		if (REVOKE(key->key))
2977 			continue;
2978 		if (isksk(key)) {
2979 			have_ksk = true;
2980 			have_non_ksk = false;
2981 		} else {
2982 			have_ksk = false;
2983 			have_non_ksk = true;
2984 		}
2985 		for (tmpkey = ISC_LIST_HEAD(keylist);
2986 		     tmpkey != NULL;
2987 		     tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
2988 			if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
2989 				continue;
2990 			if (REVOKE(tmpkey->key))
2991 				continue;
2992 			if (isksk(tmpkey))
2993 				have_ksk = true;
2994 			else
2995 				have_non_ksk = true;
2996 		}
2997 		if (have_ksk && have_non_ksk && !isksk(key))
2998 			continue;
2999 		dns_rdata_init(&rdata);
3000 		dns_rdata_init(&ds);
3001 		isc_buffer_init(&b, keybuf, sizeof(keybuf));
3002 		result = dst_key_todns(key->key, &b);
3003 		check_result(result, "dst_key_todns");
3004 		isc_buffer_usedregion(&b, &r);
3005 		dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
3006 		if (type != dns_rdatatype_dnskey) {
3007 			result = dns_ds_buildrdata(gorigin, &rdata,
3008 						   DNS_DSDIGEST_SHA1,
3009 						   dsbuf, &ds);
3010 			check_result(result, "dns_ds_buildrdata");
3011 			if (type == dns_rdatatype_dlv)
3012 				ds.type = dns_rdatatype_dlv;
3013 			result = dns_difftuple_create(mctx,
3014 						      DNS_DIFFOP_ADDRESIGN,
3015 						      name, 0, &ds, &tuple);
3016 			check_result(result, "dns_difftuple_create");
3017 			dns_diff_append(&diff, &tuple);
3018 
3019 			dns_rdata_reset(&ds);
3020 			result = dns_ds_buildrdata(gorigin, &rdata,
3021 						   DNS_DSDIGEST_SHA256,
3022 						   dsbuf, &ds);
3023 			check_result(result, "dns_ds_buildrdata");
3024 			if (type == dns_rdatatype_dlv)
3025 				ds.type = dns_rdatatype_dlv;
3026 			result = dns_difftuple_create(mctx,
3027 						      DNS_DIFFOP_ADDRESIGN,
3028 						      name, 0, &ds, &tuple);
3029 
3030 		} else
3031 			result = dns_difftuple_create(mctx,
3032 						      DNS_DIFFOP_ADDRESIGN,
3033 						      gorigin, zone_soa_min_ttl,
3034 						      &rdata, &tuple);
3035 		check_result(result, "dns_difftuple_create");
3036 		dns_diff_append(&diff, &tuple);
3037 	}
3038 
3039 	result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
3040 			       gclass, 0, NULL, &db);
3041 	check_result(result, "dns_db_create");
3042 
3043 	result = dns_db_newversion(db, &dbversion);
3044 	check_result(result, "dns_db_newversion");
3045 
3046 	result = dns_diff_apply(&diff, db, dbversion);
3047 	check_result(result, "dns_diff_apply");
3048 	dns_diff_clear(&diff);
3049 
3050 	result = dns_master_dump(mctx, db, dbversion, style, filename,
3051 				 dns_masterformat_text, NULL);
3052 	check_result(result, "dns_master_dump");
3053 
3054 	isc_mem_put(mctx, filename, filenamelen);
3055 
3056 	dns_db_closeversion(db, &dbversion, false);
3057 	dns_db_detach(&db);
3058 }
3059 
3060 static void
3061 print_time(FILE *fp) {
3062 	time_t currenttime;
3063 
3064 	if (outputformat != dns_masterformat_text)
3065 		return;
3066 
3067 	currenttime = time(NULL);
3068 	fprintf(fp, "; File written on %s", ctime(&currenttime));
3069 }
3070 
3071 static void
3072 print_version(FILE *fp) {
3073 	if (outputformat != dns_masterformat_text)
3074 		return;
3075 
3076 	fprintf(fp, "; dnssec_signzone version " VERSION "\n");
3077 }
3078 
3079 ISC_PLATFORM_NORETURN_PRE static void
3080 usage(void) ISC_PLATFORM_NORETURN_POST;
3081 
3082 static void
3083 usage(void) {
3084 	fprintf(stderr, "Usage:\n");
3085 	fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
3086 
3087 	fprintf(stderr, "\n");
3088 
3089 	fprintf(stderr, "Version: %s\n", VERSION);
3090 
3091 	fprintf(stderr, "Options: (default value in parenthesis) \n");
3092 	fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
3093 			"\t\tfor the zone and determines how they are to "
3094 			"be used\n");
3095 	fprintf(stderr, "\t-K directory:\n");
3096 	fprintf(stderr, "\t\tdirectory to find key files (.)\n");
3097 	fprintf(stderr, "\t-d directory:\n");
3098 	fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
3099 	fprintf(stderr, "\t-g:\t");
3100 	fprintf(stderr, "update DS records based on child zones' "
3101 			"dsset-* files\n");
3102 	fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
3103 	fprintf(stderr, "\t\tRRSIG start time "
3104 				"- absolute|offset (now - 1 hour)\n");
3105 	fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
3106 	fprintf(stderr, "\t\tRRSIG end time "
3107 				"- absolute|from start|from now "
3108 				"(now + 30 days)\n");
3109 	fprintf(stderr, "\t-X [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
3110 	fprintf(stderr, "\t\tDNSKEY RRSIG end "
3111 				"- absolute|from start|from now "
3112 				"(matches -e)\n");
3113 	fprintf(stderr, "\t-i interval:\n");
3114 	fprintf(stderr, "\t\tcycle interval - resign "
3115 				"if < interval from end ( (end-start)/4 )\n");
3116 	fprintf(stderr, "\t-j jitter:\n");
3117 	fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
3118 	fprintf(stderr, "\t-v debuglevel (0)\n");
3119 	fprintf(stderr, "\t-V:\tprint version information\n");
3120 	fprintf(stderr, "\t-o origin:\n");
3121 	fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
3122 	fprintf(stderr, "\t-f outfile:\n");
3123 	fprintf(stderr, "\t\tfile the signed zone is written in "
3124 				"(zonefile + .signed)\n");
3125 	fprintf(stderr, "\t-I format:\n");
3126 	fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
3127 	fprintf(stderr, "\t-O format:\n");
3128 	fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
3129 	fprintf(stderr, "\t-N format:\n");
3130 	fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
3131 	fprintf(stderr, "\t-D:\n");
3132 	fprintf(stderr, "\t\toutput only DNSSEC-related records\n");
3133 	fprintf(stderr, "\t-a:\t");
3134 	fprintf(stderr, "verify generated signatures\n");
3135 	fprintf(stderr, "\t-c class (IN)\n");
3136 	fprintf(stderr, "\t-E engine:\n");
3137 #if USE_PKCS11
3138 	fprintf(stderr, "\t\tpath to PKCS#11 provider library "
3139 		"(default is %s)\n", PK11_LIB_LOCATION);
3140 #else
3141 	fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
3142 #endif
3143 	fprintf(stderr, "\t-P:\t");
3144 	fprintf(stderr, "disable post-sign verification\n");
3145 	fprintf(stderr, "\t-Q:\t");
3146 	fprintf(stderr, "remove signatures from keys that are no "
3147 				"longer active\n");
3148 	fprintf(stderr, "\t-R:\t");
3149 	fprintf(stderr, "remove signatures from keys that no longer exist\n");
3150 	fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
3151 	fprintf(stderr, "\t-t:\t");
3152 	fprintf(stderr, "print statistics\n");
3153 	fprintf(stderr, "\t-u:\t");
3154 	fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
3155 	fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
3156 	fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
3157 	fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
3158 			"\t\twith older versions of dnssec-signzone -g\n");
3159 	fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
3160 	fprintf(stderr, "\t-k key_signing_key\n");
3161 	fprintf(stderr, "\t-l lookasidezone\n");
3162 	fprintf(stderr, "\t-3 NSEC3 salt\n");
3163 	fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
3164 	fprintf(stderr, "\t-A NSEC3 optout\n");
3165 
3166 	fprintf(stderr, "\n");
3167 
3168 	fprintf(stderr, "Signing Keys: ");
3169 	fprintf(stderr, "(default: all zone keys that have private keys)\n");
3170 	fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
3171 
3172 	exit(0);
3173 }
3174 
3175 static void
3176 removetempfile(void) {
3177 	if (removefile)
3178 		isc_file_remove(tempfile);
3179 }
3180 
3181 static void
3182 print_stats(isc_time_t *timer_start, isc_time_t *timer_finish,
3183 	    isc_time_t *sign_start, isc_time_t *sign_finish)
3184 {
3185 	uint64_t time_us;      /* Time in microseconds */
3186 	uint64_t time_ms;      /* Time in milliseconds */
3187 	uint64_t sig_ms;	   /* Signatures per millisecond */
3188 	FILE *out = output_stdout ? stderr : stdout;
3189 
3190 	fprintf(out, "Signatures generated:               %10u\n", nsigned);
3191 	fprintf(out, "Signatures retained:                %10u\n", nretained);
3192 	fprintf(out, "Signatures dropped:                 %10u\n", ndropped);
3193 	fprintf(out, "Signatures successfully verified:   %10u\n", nverified);
3194 	fprintf(out, "Signatures unsuccessfully "
3195 		     "verified: %10u\n", nverifyfailed);
3196 
3197 	time_us = isc_time_microdiff(sign_finish, sign_start);
3198 	time_ms = time_us / 1000;
3199 	fprintf(out, "Signing time in seconds:           %7u.%03u\n",
3200 		(unsigned int) (time_ms / 1000),
3201 		(unsigned int) (time_ms % 1000));
3202 	if (time_us > 0) {
3203 		sig_ms = ((uint64_t)nsigned * 1000000000) / time_us;
3204 		fprintf(out, "Signatures per second:             %7u.%03u\n",
3205 			(unsigned int) sig_ms / 1000,
3206 			(unsigned int) sig_ms % 1000);
3207 	}
3208 
3209 	time_us = isc_time_microdiff(timer_finish, timer_start);
3210 	time_ms = time_us / 1000;
3211 	fprintf(out, "Runtime in seconds:                %7u.%03u\n",
3212 		(unsigned int) (time_ms / 1000),
3213 		(unsigned int) (time_ms % 1000));
3214 }
3215 
3216 int
3217 main(int argc, char *argv[]) {
3218 	int i, ch;
3219 	char *startstr = NULL, *endstr = NULL, *classname = NULL;
3220 	char *dnskey_endstr = NULL;
3221 	char *origin = NULL, *file = NULL, *output = NULL;
3222 	char *inputformatstr = NULL, *outputformatstr = NULL;
3223 	char *serialformatstr = NULL;
3224 	char *dskeyfile[MAXDSKEYS];
3225 	int ndskeys = 0;
3226 	char *endp;
3227 	isc_time_t timer_start, timer_finish;
3228 	isc_time_t sign_start, sign_finish;
3229 	dns_dnsseckey_t *key;
3230 	isc_result_t result, vresult;
3231 	isc_log_t *log = NULL;
3232 	const char *engine = NULL;
3233 	bool free_output = false;
3234 	int tempfilelen = 0;
3235 	dns_rdataclass_t rdclass;
3236 	isc_task_t **tasks = NULL;
3237 	isc_buffer_t b;
3238 	int len;
3239 	hashlist_t hashlist;
3240 	bool make_keyset = false;
3241 	bool set_salt = false;
3242 	bool set_optout = false;
3243 	bool set_iter = false;
3244 	bool nonsecify = false;
3245 
3246 	/* Unused letters: Bb G J q Yy (and F is reserved). */
3247 #define CMDLINE_FLAGS \
3248 	"3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:M:n:N:o:O:PpQRr:s:ST:tuUv:VX:xzZ:"
3249 
3250 	/*
3251 	 * Process memory debugging argument first.
3252 	 */
3253 	while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3254 		switch (ch) {
3255 		case 'm':
3256 			if (strcasecmp(isc_commandline_argument, "record") == 0)
3257 				isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
3258 			if (strcasecmp(isc_commandline_argument, "trace") == 0)
3259 				isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
3260 			if (strcasecmp(isc_commandline_argument, "usage") == 0)
3261 				isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
3262 			if (strcasecmp(isc_commandline_argument, "size") == 0)
3263 				isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
3264 			if (strcasecmp(isc_commandline_argument, "mctx") == 0)
3265 				isc_mem_debugging |= ISC_MEM_DEBUGCTX;
3266 			break;
3267 		default:
3268 			break;
3269 		}
3270 	}
3271 	isc_commandline_reset = true;
3272 
3273 #ifdef _WIN32
3274 	InitSockets();
3275 #endif
3276 
3277 	masterstyle = &dns_master_style_explicitttl;
3278 
3279 	check_result(isc_app_start(), "isc_app_start");
3280 
3281 	result = isc_mem_create(0, 0, &mctx);
3282 	if (result != ISC_R_SUCCESS)
3283 		fatal("out of memory");
3284 
3285 #if USE_PKCS11
3286 	pk11_result_register();
3287 #endif
3288 	dns_result_register();
3289 
3290 	isc_commandline_errprint = false;
3291 
3292 	while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
3293 		switch (ch) {
3294 		case '3':
3295 			set_salt = true;
3296 			nsec_datatype = dns_rdatatype_nsec3;
3297 			if (strcmp(isc_commandline_argument, "-") != 0) {
3298 				isc_buffer_t target;
3299 				char *sarg;
3300 
3301 				sarg = isc_commandline_argument;
3302 				isc_buffer_init(&target, saltbuf,
3303 						sizeof(saltbuf));
3304 				result = isc_hex_decodestring(sarg, &target);
3305 				check_result(result,
3306 					     "isc_hex_decodestring(salt)");
3307 				salt_length = isc_buffer_usedlength(&target);
3308 			}
3309 			break;
3310 
3311 		case 'A':
3312 			set_optout = true;
3313 			if (OPTOUT(nsec3flags))
3314 				nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
3315 			else
3316 				nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
3317 			break;
3318 
3319 		case 'a':
3320 			tryverify = true;
3321 			break;
3322 
3323 		case 'C':
3324 			make_keyset = true;
3325 			break;
3326 
3327 		case 'c':
3328 			classname = isc_commandline_argument;
3329 			break;
3330 
3331 		case 'd':
3332 			dsdir = isc_commandline_argument;
3333 			if (strlen(dsdir) == 0U)
3334 				fatal("DS directory must be non-empty string");
3335 			result = try_dir(dsdir);
3336 			if (result != ISC_R_SUCCESS)
3337 				fatal("cannot open directory %s: %s",
3338 				      dsdir, isc_result_totext(result));
3339 			break;
3340 
3341 		case 'D':
3342 			output_dnssec_only = true;
3343 			break;
3344 
3345 		case 'E':
3346 			engine = isc_commandline_argument;
3347 			break;
3348 
3349 		case 'e':
3350 			endstr = isc_commandline_argument;
3351 			break;
3352 
3353 		case 'f':
3354 			output = isc_commandline_argument;
3355 			if (strcmp(output, "-") == 0)
3356 				output_stdout = true;
3357 			break;
3358 
3359 		case 'g':
3360 			generateds = true;
3361 			break;
3362 
3363 		case 'H':
3364 			set_iter = true;
3365 			nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
3366 			if (*endp != '\0')
3367 				fatal("iterations must be numeric");
3368 			if (nsec3iter  > 0xffffU)
3369 				fatal("iterations too big");
3370 			break;
3371 
3372 		case 'I':
3373 			inputformatstr = isc_commandline_argument;
3374 			break;
3375 
3376 		case 'i':
3377 			endp = NULL;
3378 			cycle = strtol(isc_commandline_argument, &endp, 0);
3379 			if (*endp != '\0' || cycle < 0)
3380 				fatal("cycle period must be numeric and "
3381 				      "positive");
3382 			break;
3383 
3384 		case 'j':
3385 			endp = NULL;
3386 			jitter = strtol(isc_commandline_argument, &endp, 0);
3387 			if (*endp != '\0' || jitter < 0)
3388 				fatal("jitter must be numeric and positive");
3389 			break;
3390 
3391 		case 'K':
3392 			directory = isc_commandline_argument;
3393 			break;
3394 
3395 		case 'k':
3396 			if (ndskeys == MAXDSKEYS)
3397 				fatal("too many key-signing keys specified");
3398 			dskeyfile[ndskeys++] = isc_commandline_argument;
3399 			break;
3400 
3401 		case 'L':
3402 			snset = true;
3403 			endp = NULL;
3404 			serialnum = strtol(isc_commandline_argument, &endp, 0);
3405 			if (*endp != '\0') {
3406 				fprintf(stderr, "source serial number "
3407 						"must be numeric");
3408 				exit(1);
3409 			}
3410 			break;
3411 
3412 		case 'l':
3413 			len = strlen(isc_commandline_argument);
3414 			isc_buffer_init(&b, isc_commandline_argument, len);
3415 			isc_buffer_add(&b, len);
3416 
3417 			dlv = dns_fixedname_initname(&dlv_fixed);
3418 			result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
3419 						   NULL);
3420 			check_result(result, "dns_name_fromtext(dlv)");
3421 			break;
3422 
3423 		case 'M':
3424 			endp = NULL;
3425 			set_maxttl = true;
3426 			maxttl = strtol(isc_commandline_argument, &endp, 0);
3427 			if (*endp != '\0') {
3428 				fprintf(stderr, "maximum TTL "
3429 						"must be numeric");
3430 				exit(1);
3431 			}
3432 			break;
3433 
3434 		case 'm':
3435 			break;
3436 
3437 		case 'N':
3438 			serialformatstr = isc_commandline_argument;
3439 			break;
3440 
3441 		case 'n':
3442 			endp = NULL;
3443 			ntasks = strtol(isc_commandline_argument, &endp, 0);
3444 			if (*endp != '\0' || ntasks > INT32_MAX)
3445 				fatal("number of cpus must be numeric");
3446 			break;
3447 
3448 		case 'O':
3449 			outputformatstr = isc_commandline_argument;
3450 			break;
3451 
3452 		case 'o':
3453 			origin = isc_commandline_argument;
3454 			break;
3455 
3456 		case 'P':
3457 			disable_zone_check = true;
3458 			break;
3459 
3460 		case 'p':
3461 			fatal("The -p option has been deprecated.\n");
3462 			break;
3463 
3464 		case 'Q':
3465 			remove_inactkeysigs = true;
3466 			break;
3467 
3468 		case 'R':
3469 			remove_orphansigs = true;
3470 			break;
3471 
3472 		case 'r':
3473 			fatal("The -r options has been deprecated.\n");
3474 			break;
3475 
3476 		case 'S':
3477 			smartsign = true;
3478 			break;
3479 
3480 		case 's':
3481 			startstr = isc_commandline_argument;
3482 			break;
3483 
3484 		case 'T':
3485 			endp = NULL;
3486 			set_keyttl = true;
3487 			keyttl = strtottl(isc_commandline_argument);
3488 			break;
3489 
3490 		case 't':
3491 			printstats = true;
3492 			break;
3493 
3494 		case 'U':	/* Undocumented for testing only. */
3495 			unknownalg = true;
3496 			break;
3497 
3498 		case 'u':
3499 			update_chain = true;
3500 			break;
3501 
3502 		case 'v':
3503 			endp = NULL;
3504 			verbose = strtol(isc_commandline_argument, &endp, 0);
3505 			if (*endp != '\0')
3506 				fatal("verbose level must be numeric");
3507 			break;
3508 
3509 		case 'X':
3510 			dnskey_endstr = isc_commandline_argument;
3511 			break;
3512 
3513 		case 'x':
3514 			keyset_kskonly = true;
3515 			break;
3516 
3517 		case 'z':
3518 			ignore_kskflag = true;
3519 			break;
3520 
3521 		case 'F':
3522 			/* Reserved for FIPS mode */
3523 			/* FALLTHROUGH */
3524 		case '?':
3525 			if (isc_commandline_option != '?')
3526 				fprintf(stderr, "%s: invalid argument -%c\n",
3527 					program, isc_commandline_option);
3528 			/* FALLTHROUGH */
3529 		case 'h':
3530 			/* Does not return. */
3531 			usage();
3532 
3533 		case 'V':
3534 			/* Does not return. */
3535 			version(program);
3536 
3537 		case 'Z':	/* Undocumented test options */
3538 			if (!strcmp(isc_commandline_argument, "nonsecify"))
3539 				nonsecify = true;
3540 			break;
3541 
3542 		default:
3543 			fprintf(stderr, "%s: unhandled option -%c\n",
3544 				program, isc_commandline_option);
3545 			exit(1);
3546 		}
3547 	}
3548 
3549 	result = dst_lib_init(mctx, engine);
3550 	if (result != ISC_R_SUCCESS)
3551 		fatal("could not initialize dst: %s",
3552 		      isc_result_totext(result));
3553 
3554 	isc_stdtime_get(&now);
3555 
3556 	if (startstr != NULL) {
3557 		starttime = strtotime(startstr, now, now, NULL);
3558 	} else
3559 		starttime = now - 3600;  /* Allow for some clock skew. */
3560 
3561 	if (endstr != NULL)
3562 		endtime = strtotime(endstr, now, starttime, NULL);
3563 	else
3564 		endtime = starttime + (30 * 24 * 60 * 60);
3565 
3566 	if (dnskey_endstr != NULL) {
3567 		dnskey_endtime = strtotime(dnskey_endstr, now, starttime,
3568 					   NULL);
3569 		if (endstr != NULL && dnskey_endtime == endtime)
3570 			fprintf(stderr, "WARNING: -e and -X were both set, "
3571 					"but have identical values.\n");
3572 	} else
3573 		dnskey_endtime = endtime;
3574 
3575 	if (cycle == -1)
3576 		cycle = (endtime - starttime) / 4;
3577 
3578 	if (ntasks == 0)
3579 		ntasks = isc_os_ncpus() * 2;
3580 	vbprintf(4, "using %d cpus\n", ntasks);
3581 
3582 	rdclass = strtoclass(classname);
3583 
3584 	if (directory == NULL)
3585 		directory = ".";
3586 
3587 	setup_logging(mctx, &log);
3588 
3589 	argc -= isc_commandline_index;
3590 	argv += isc_commandline_index;
3591 
3592 	if (argc < 1)
3593 		usage();
3594 
3595 	file = argv[0];
3596 
3597 	argc -= 1;
3598 	argv += 1;
3599 
3600 	if (origin == NULL)
3601 		origin = file;
3602 
3603 	if (output == NULL) {
3604 		size_t size;
3605 		free_output = true;
3606 		size = strlen(file) + strlen(".signed") + 1;
3607 		output = isc_mem_allocate(mctx, size);
3608 		if (output == NULL)
3609 			fatal("out of memory");
3610 		snprintf(output, size, "%s.signed", file);
3611 	}
3612 
3613 	if (inputformatstr != NULL) {
3614 		if (strcasecmp(inputformatstr, "text") == 0)
3615 			inputformat = dns_masterformat_text;
3616 		else if (strcasecmp(inputformatstr, "map") == 0)
3617 			inputformat = dns_masterformat_map;
3618 		else if (strcasecmp(inputformatstr, "raw") == 0)
3619 			inputformat = dns_masterformat_raw;
3620 		else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
3621 			inputformat = dns_masterformat_raw;
3622 			fprintf(stderr,
3623 				"WARNING: input format version ignored\n");
3624 		} else
3625 			fatal("unknown file format: %s", inputformatstr);
3626 
3627 	}
3628 
3629 	if (outputformatstr != NULL) {
3630 		if (strcasecmp(outputformatstr, "text") == 0) {
3631 			outputformat = dns_masterformat_text;
3632 		} else if (strcasecmp(outputformatstr, "full") == 0) {
3633 			outputformat = dns_masterformat_text;
3634 			masterstyle = &dns_master_style_full;
3635 		} else if (strcasecmp(outputformatstr, "map") == 0) {
3636 			outputformat = dns_masterformat_map;
3637 		} else if (strcasecmp(outputformatstr, "raw") == 0) {
3638 			outputformat = dns_masterformat_raw;
3639 		} else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
3640 			char *end;
3641 			outputformat = dns_masterformat_raw;
3642 
3643 			outputformat = dns_masterformat_raw;
3644 			rawversion = strtol(outputformatstr + 4, &end, 10);
3645 			if (end == outputformatstr + 4 || *end != '\0' ||
3646 			    rawversion > 1U) {
3647 				fprintf(stderr,
3648 					"unknown raw format version\n");
3649 				exit(1);
3650 			}
3651 		} else
3652 			fatal("unknown file format: %s", outputformatstr);
3653 	}
3654 
3655 	if (serialformatstr != NULL) {
3656 		if (strcasecmp(serialformatstr, "keep") == 0)
3657 			serialformat = SOA_SERIAL_KEEP;
3658 		else if (strcasecmp(serialformatstr, "increment") == 0 ||
3659 			 strcasecmp(serialformatstr, "incr") == 0)
3660 			serialformat = SOA_SERIAL_INCREMENT;
3661 		else if (strcasecmp(serialformatstr, "unixtime") == 0)
3662 			serialformat = SOA_SERIAL_UNIXTIME;
3663 		else if (strcasecmp(serialformatstr, "date") == 0)
3664 			serialformat = SOA_SERIAL_DATE;
3665 		else
3666 			fatal("unknown soa serial format: %s",
3667 			      serialformatstr);
3668 	}
3669 
3670 	if (output_dnssec_only && outputformat != dns_masterformat_text)
3671 		fatal("option -D can only be used with \"-O text\"");
3672 
3673 	if (output_dnssec_only && serialformat != SOA_SERIAL_KEEP)
3674 		fatal("option -D can only be used with \"-N keep\"");
3675 
3676 	if (output_dnssec_only && set_maxttl)
3677 		fatal("option -D cannot be used with -M");
3678 
3679 	result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
3680 					0, 24, 0, 0, 0, 8, 0xffffffff, mctx);
3681 	check_result(result, "dns_master_stylecreate");
3682 
3683 	gdb = NULL;
3684 	TIME_NOW(&timer_start);
3685 	loadzone(file, origin, rdclass, &gdb);
3686 	gorigin = dns_db_origin(gdb);
3687 	gclass = dns_db_class(gdb);
3688 	get_soa_ttls();
3689 
3690 	if (set_maxttl && set_keyttl && keyttl > maxttl) {
3691 		fprintf(stderr, "%s: warning: Specified key TTL %u "
3692 			"exceeds maximum zone TTL; reducing to %u\n",
3693 			program, keyttl, maxttl);
3694 		keyttl = maxttl;
3695 	}
3696 
3697 	if (!set_keyttl)
3698 		keyttl = soa_ttl;
3699 
3700 	/*
3701 	 * Check for any existing NSEC3 parameters in the zone,
3702 	 * and use them as defaults if -u was not specified.
3703 	 */
3704 	if (update_chain && !set_optout && !set_iter && !set_salt)
3705 		nsec_datatype = dns_rdatatype_nsec;
3706 	else
3707 		set_nsec3params(update_chain, set_salt, set_optout, set_iter);
3708 
3709 	/*
3710 	 * We need to do this early on, as we start messing with the list
3711 	 * of keys rather early.
3712 	 */
3713 	ISC_LIST_INIT(keylist);
3714 	result = isc_rwlock_init(&keylist_lock, 0, 0);
3715 	if (result != ISC_R_SUCCESS)
3716 		fatal("could not initialize keylist_lock: %s",
3717 		      isc_result_totext(result));
3718 
3719 	/*
3720 	 * Fill keylist with:
3721 	 * 1) Keys listed in the DNSKEY set that have
3722 	 *    private keys associated, *if* no keys were
3723 	 *    set on the command line.
3724 	 * 2) ZSKs set on the command line
3725 	 * 3) KSKs set on the command line
3726 	 * 4) Any keys remaining in the DNSKEY set which
3727 	 *    do not have private keys associated and were
3728 	 *    not specified on the command line.
3729 	 */
3730 	if (argc == 0 || smartsign) {
3731 		loadzonekeys(!smartsign, false);
3732 	}
3733 	loadexplicitkeys(argv, argc, false);
3734 	loadexplicitkeys(dskeyfile, ndskeys, true);
3735 	loadzonekeys(!smartsign, true);
3736 
3737 	/*
3738 	 * If we're doing smart signing, look in the key repository for
3739 	 * key files with metadata, and merge them with the keylist
3740 	 * we have now.
3741 	 */
3742 	if (smartsign) {
3743 		build_final_keylist();
3744 	}
3745 
3746 	/* Now enumerate the key list */
3747 	for (key = ISC_LIST_HEAD(keylist);
3748 	     key != NULL;
3749 	     key = ISC_LIST_NEXT(key, link)) {
3750 		key->index = keycount++;
3751 	}
3752 
3753 	if (keycount == 0) {
3754 		if (disable_zone_check)
3755 			fprintf(stderr, "%s: warning: No keys specified "
3756 					"or found\n", program);
3757 		else
3758 			fatal("No signing keys specified or found.");
3759 		nokeys = true;
3760 	}
3761 
3762 	warnifallksk(gdb);
3763 
3764 	if (IS_NSEC3) {
3765 		unsigned int max;
3766 		bool answer;
3767 
3768 		hash_length = dns_nsec3_hashlength(dns_hash_sha1);
3769 		hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
3770 			      hash_length);
3771 		result = dns_nsec_nseconly(gdb, gversion, &answer);
3772 		if (result == ISC_R_NOTFOUND)
3773 			fprintf(stderr, "%s: warning: NSEC3 generation "
3774 				"requested with no DNSKEY; ignoring\n",
3775 				program);
3776 		else if (result != ISC_R_SUCCESS)
3777 			check_result(result, "dns_nsec_nseconly");
3778 		else if (answer)
3779 			fatal("NSEC3 generation requested with "
3780 			      "NSEC-only DNSKEY");
3781 
3782 		result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
3783 		check_result(result, "dns_nsec3_maxiterations()");
3784 		if (nsec3iter > max)
3785 			fatal("NSEC3 iterations too big for weakest DNSKEY "
3786 			      "strength. Maximum iterations allowed %u.", max);
3787 	} else {
3788 		hashlist_init(&hashlist, 0, 0);	/* silence clang */
3789 	}
3790 
3791 	gversion = NULL;
3792 	result = dns_db_newversion(gdb, &gversion);
3793 	check_result(result, "dns_db_newversion()");
3794 
3795 	switch (serialformat) {
3796 		case SOA_SERIAL_INCREMENT:
3797 			setsoaserial(0, dns_updatemethod_increment);
3798 			break;
3799 		case SOA_SERIAL_UNIXTIME:
3800 			setsoaserial(now, dns_updatemethod_unixtime);
3801 			break;
3802 		case SOA_SERIAL_DATE:
3803 			setsoaserial(now, dns_updatemethod_date);
3804 			break;
3805 		case SOA_SERIAL_KEEP:
3806 		default:
3807 			/* do nothing */
3808 			break;
3809 	}
3810 
3811 	/* Remove duplicates and cap TTLs at maxttl */
3812 	cleanup_zone();
3813 
3814 	if (!nonsecify) {
3815 		if (IS_NSEC3)
3816 			nsec3ify(dns_hash_sha1, nsec3iter, gsalt, salt_length,
3817 				 &hashlist);
3818 		else
3819 			nsecify();
3820 	}
3821 
3822 	if (!nokeys) {
3823 		writeset("dsset-", dns_rdatatype_ds);
3824 		if (make_keyset)
3825 			writeset("keyset-", dns_rdatatype_dnskey);
3826 		if (dlv != NULL) {
3827 			writeset("dlvset-", dns_rdatatype_dlv);
3828 		}
3829 	}
3830 
3831 	if (output_stdout) {
3832 		outfp = stdout;
3833 		if (outputformatstr == NULL)
3834 			masterstyle = &dns_master_style_full;
3835 	} else {
3836 		tempfilelen = strlen(output) + 20;
3837 		tempfile = isc_mem_get(mctx, tempfilelen);
3838 		if (tempfile == NULL)
3839 			fatal("out of memory");
3840 
3841 		result = isc_file_mktemplate(output, tempfile, tempfilelen);
3842 		check_result(result, "isc_file_mktemplate");
3843 
3844 		if (outputformat == dns_masterformat_text)
3845 			result = isc_file_openunique(tempfile, &outfp);
3846 		else
3847 			result = isc_file_bopenunique(tempfile, &outfp);
3848 		if (result != ISC_R_SUCCESS)
3849 			fatal("failed to open temporary output file: %s",
3850 			      isc_result_totext(result));
3851 		removefile = true;
3852 		setfatalcallback(&removetempfile);
3853 	}
3854 
3855 	print_time(outfp);
3856 	print_version(outfp);
3857 
3858 	result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
3859 	if (result != ISC_R_SUCCESS)
3860 		fatal("failed to create task manager: %s",
3861 		      isc_result_totext(result));
3862 
3863 	master = NULL;
3864 	result = isc_task_create(taskmgr, 0, &master);
3865 	if (result != ISC_R_SUCCESS)
3866 		fatal("failed to create task: %s", isc_result_totext(result));
3867 
3868 	tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
3869 	if (tasks == NULL)
3870 		fatal("out of memory");
3871 	for (i = 0; i < (int)ntasks; i++) {
3872 		tasks[i] = NULL;
3873 		result = isc_task_create(taskmgr, 0, &tasks[i]);
3874 		if (result != ISC_R_SUCCESS)
3875 			fatal("failed to create task: %s",
3876 			      isc_result_totext(result));
3877 	}
3878 
3879 	isc_mutex_init(&namelock);
3880 
3881 	if (printstats) {
3882 		isc_mutex_init(&statslock);
3883 	}
3884 
3885 	presign();
3886 	TIME_NOW(&sign_start);
3887 	signapex();
3888 	if (!finished) {
3889 		/*
3890 		 * There is more work to do.  Spread it out over multiple
3891 		 * processors if possible.
3892 		 */
3893 		for (i = 0; i < (int)ntasks; i++) {
3894 			result = isc_app_onrun(mctx, master, startworker,
3895 					       tasks[i]);
3896 			if (result != ISC_R_SUCCESS)
3897 				fatal("failed to start task: %s",
3898 				      isc_result_totext(result));
3899 		}
3900 		(void)isc_app_run();
3901 		if (!finished)
3902 			fatal("process aborted by user");
3903 	} else
3904 		isc_task_detach(&master);
3905 	shuttingdown = true;
3906 	for (i = 0; i < (int)ntasks; i++)
3907 		isc_task_detach(&tasks[i]);
3908 	isc_taskmgr_destroy(&taskmgr);
3909 	isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
3910 	postsign();
3911 	TIME_NOW(&sign_finish);
3912 
3913 	if (disable_zone_check) {
3914 		vresult = ISC_R_SUCCESS;
3915 	} else {
3916 		vresult = dns_zoneverify_dnssec(NULL, gdb, gversion, gorigin,
3917 						NULL, mctx, ignore_kskflag,
3918 						keyset_kskonly);
3919 		if (vresult != ISC_R_SUCCESS) {
3920 			fprintf(output_stdout ? stderr : stdout,
3921 				"Zone verification failed (%s)\n",
3922 				isc_result_totext(vresult));
3923 		}
3924 	}
3925 
3926 	if (outputformat != dns_masterformat_text) {
3927 		dns_masterrawheader_t header;
3928 		dns_master_initrawheader(&header);
3929 		if (rawversion == 0U)
3930 			header.flags = DNS_MASTERRAW_COMPAT;
3931 		else if (snset) {
3932 			header.flags = DNS_MASTERRAW_SOURCESERIALSET;
3933 			header.sourceserial = serialnum;
3934 		}
3935 		result = dns_master_dumptostream(mctx, gdb, gversion,
3936 						 masterstyle, outputformat,
3937 						 &header, outfp);
3938 		check_result(result, "dns_master_dumptostream3");
3939 	}
3940 
3941 	isc_mutex_destroy(&namelock);
3942 	if (printstats)
3943 		isc_mutex_destroy(&statslock);
3944 
3945 	if (!output_stdout) {
3946 		result = isc_stdio_close(outfp);
3947 		check_result(result, "isc_stdio_close");
3948 		removefile = false;
3949 
3950 		if (vresult == ISC_R_SUCCESS) {
3951 			result = isc_file_rename(tempfile, output);
3952 			if (result != ISC_R_SUCCESS) {
3953 				fatal("failed to rename temp file to %s: %s",
3954 				      output, isc_result_totext(result));
3955 			}
3956 			printf("%s\n", output);
3957 		} else {
3958 			isc_file_remove(tempfile);
3959 		}
3960 	}
3961 
3962 	dns_db_closeversion(gdb, &gversion, false);
3963 	dns_db_detach(&gdb);
3964 
3965 	hashlist_free(&hashlist);
3966 
3967 	while (!ISC_LIST_EMPTY(keylist)) {
3968 		key = ISC_LIST_HEAD(keylist);
3969 		ISC_LIST_UNLINK(keylist, key, link);
3970 		dns_dnsseckey_destroy(mctx, &key);
3971 	}
3972 
3973 	if (tempfilelen != 0)
3974 		isc_mem_put(mctx, tempfile, tempfilelen);
3975 
3976 	if (free_output)
3977 		isc_mem_free(mctx, output);
3978 
3979 	dns_master_styledestroy(&dsstyle, mctx);
3980 
3981 	cleanup_logging(&log);
3982 	dst_lib_destroy();
3983 	dns_name_destroy();
3984 	if (verbose > 10)
3985 		isc_mem_stats(mctx, stdout);
3986 	isc_mem_destroy(&mctx);
3987 
3988 	(void) isc_app_finish();
3989 
3990 	if (printstats) {
3991 		TIME_NOW(&timer_finish);
3992 		print_stats(&timer_start, &timer_finish,
3993 			    &sign_start, &sign_finish);
3994 	}
3995 
3996 #ifdef _WIN32
3997 	DestroySockets();
3998 #endif
3999 	return (vresult == ISC_R_SUCCESS ? 0 : 1);
4000 }
4001