xref: /netbsd-src/external/mpl/bind/dist/lib/dns/update.c (revision e7ac2a8b5bd66fa2e050809de09a075c36a7014d)
1 /*	$NetBSD: update.c,v 1.7 2020/08/03 17:23:41 christos Exp $	*/
2 
3 /*
4  * 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 
14 #include <inttypes.h>
15 #include <stdbool.h>
16 #include <time.h>
17 
18 #include <isc/log.h>
19 #include <isc/magic.h>
20 #include <isc/mem.h>
21 #include <isc/netaddr.h>
22 #include <isc/platform.h>
23 #include <isc/print.h>
24 #include <isc/random.h>
25 #include <isc/serial.h>
26 #include <isc/stats.h>
27 #include <isc/stdtime.h>
28 #include <isc/string.h>
29 #include <isc/taskpool.h>
30 #include <isc/time.h>
31 #include <isc/util.h>
32 
33 #include <dns/db.h>
34 #include <dns/dbiterator.h>
35 #include <dns/diff.h>
36 #include <dns/dnssec.h>
37 #include <dns/events.h>
38 #include <dns/fixedname.h>
39 #include <dns/journal.h>
40 #include <dns/kasp.h>
41 #include <dns/keyvalues.h>
42 #include <dns/log.h>
43 #include <dns/message.h>
44 #include <dns/nsec.h>
45 #include <dns/nsec3.h>
46 #include <dns/private.h>
47 #include <dns/rdataclass.h>
48 #include <dns/rdataset.h>
49 #include <dns/rdatasetiter.h>
50 #include <dns/rdatastruct.h>
51 #include <dns/rdatatype.h>
52 #include <dns/result.h>
53 #include <dns/soa.h>
54 #include <dns/ssu.h>
55 #include <dns/stats.h>
56 #include <dns/tsig.h>
57 #include <dns/update.h>
58 #include <dns/view.h>
59 #include <dns/zone.h>
60 #include <dns/zt.h>
61 
62 /**************************************************************************/
63 
64 #define STATE_MAGIC	       ISC_MAGIC('S', 'T', 'T', 'E')
65 #define DNS_STATE_VALID(state) ISC_MAGIC_VALID(state, STATE_MAGIC)
66 
67 /*%
68  * Log level for tracing dynamic update protocol requests.
69  */
70 #define LOGLEVEL_PROTOCOL ISC_LOG_INFO
71 
72 /*%
73  * Log level for low-level debug tracing.
74  */
75 #define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8)
76 
77 /*%
78  * Check an operation for failure.  These macros all assume that
79  * the function using them has a 'result' variable and a 'failure'
80  * label.
81  */
82 #define CHECK(op)                            \
83 	do {                                 \
84 		result = (op);               \
85 		if (result != ISC_R_SUCCESS) \
86 			goto failure;        \
87 	} while (/*CONSTCOND*/0)
88 
89 /*%
90  * Fail unconditionally with result 'code', which must not
91  * be ISC_R_SUCCESS.  The reason for failure presumably has
92  * been logged already.
93  *
94  * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
95  * from complaining about "end-of-loop code not reached".
96  */
97 
98 #define FAIL(code)                           \
99 	do {                                 \
100 		result = (code);             \
101 		if (result != ISC_R_SUCCESS) \
102 			goto failure;        \
103 	} while (/*CONSTCOND*/0)
104 
105 /*%
106  * Fail unconditionally and log as a client error.
107  * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
108  * from complaining about "end-of-loop code not reached".
109  */
110 #define FAILC(code, msg)                                                       \
111 	do {                                                                   \
112 		const char *_what = "failed";                                  \
113 		result = (code);                                               \
114 		switch (result) {                                              \
115 		case DNS_R_NXDOMAIN:                                           \
116 		case DNS_R_YXDOMAIN:                                           \
117 		case DNS_R_YXRRSET:                                            \
118 		case DNS_R_NXRRSET:                                            \
119 			_what = "unsuccessful";                                \
120 		}                                                              \
121 		update_log(log, zone, LOGLEVEL_PROTOCOL, "update %s: %s (%s)", \
122 			   _what, msg, isc_result_totext(result));             \
123 		if (result != ISC_R_SUCCESS)                                   \
124 			goto failure;                                          \
125 	} while (/*CONSTCOND*/0)
126 
127 #define FAILN(code, name, msg)                                             \
128 	do {                                                               \
129 		const char *_what = "failed";                              \
130 		result = (code);                                           \
131 		switch (result) {                                          \
132 		case DNS_R_NXDOMAIN:                                       \
133 		case DNS_R_YXDOMAIN:                                       \
134 		case DNS_R_YXRRSET:                                        \
135 		case DNS_R_NXRRSET:                                        \
136 			_what = "unsuccessful";                            \
137 		}                                                          \
138 		if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) {       \
139 			char _nbuf[DNS_NAME_FORMATSIZE];                   \
140 			dns_name_format(name, _nbuf, sizeof(_nbuf));       \
141 			update_log(log, zone, LOGLEVEL_PROTOCOL,           \
142 				   "update %s: %s: %s (%s)", _what, _nbuf, \
143 				   msg, isc_result_totext(result));        \
144 		}                                                          \
145 		if (result != ISC_R_SUCCESS)                               \
146 			goto failure;                                      \
147 	} while (/*CONSTCOND*/0)
148 
149 #define FAILNT(code, name, type, msg)                                         \
150 	do {                                                                  \
151 		const char *_what = "failed";                                 \
152 		result = (code);                                              \
153 		switch (result) {                                             \
154 		case DNS_R_NXDOMAIN:                                          \
155 		case DNS_R_YXDOMAIN:                                          \
156 		case DNS_R_YXRRSET:                                           \
157 		case DNS_R_NXRRSET:                                           \
158 			_what = "unsuccessful";                               \
159 		}                                                             \
160 		if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) {          \
161 			char _nbuf[DNS_NAME_FORMATSIZE];                      \
162 			char _tbuf[DNS_RDATATYPE_FORMATSIZE];                 \
163 			dns_name_format(name, _nbuf, sizeof(_nbuf));          \
164 			dns_rdatatype_format(type, _tbuf, sizeof(_tbuf));     \
165 			update_log(log, zone, LOGLEVEL_PROTOCOL,              \
166 				   "update %s: %s/%s: %s (%s)", _what, _nbuf, \
167 				   _tbuf, msg, isc_result_totext(result));    \
168 		}                                                             \
169 		if (result != ISC_R_SUCCESS)                                  \
170 			goto failure;                                         \
171 	} while (/*CONSTCOND*/0)
172 
173 /*%
174  * Fail unconditionally and log as a server error.
175  * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
176  * from complaining about "end-of-loop code not reached".
177  */
178 #define FAILS(code, msg)                                                       \
179 	do {                                                                   \
180 		result = (code);                                               \
181 		update_log(log, zone, LOGLEVEL_PROTOCOL, "error: %s: %s", msg, \
182 			   isc_result_totext(result));                         \
183 		if (result != ISC_R_SUCCESS)                                   \
184 			goto failure;                                          \
185 	} while (/*CONSTCOND*/0)
186 
187 /**************************************************************************/
188 
189 typedef struct rr rr_t;
190 
191 struct rr {
192 	/* dns_name_t name; */
193 	uint32_t ttl;
194 	dns_rdata_t rdata;
195 };
196 
197 typedef struct update_event update_event_t;
198 
199 /**************************************************************************/
200 
201 static void
202 update_log(dns_update_log_t *callback, dns_zone_t *zone, int level,
203 	   const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
204 
205 static void
206 update_log(dns_update_log_t *callback, dns_zone_t *zone, int level,
207 	   const char *fmt, ...) {
208 	va_list ap;
209 	char message[4096];
210 
211 	if (callback == NULL) {
212 		return;
213 	}
214 
215 	if (!isc_log_wouldlog(dns_lctx, level)) {
216 		return;
217 	}
218 
219 	va_start(ap, fmt);
220 	vsnprintf(message, sizeof(message), fmt, ap);
221 	va_end(ap);
222 
223 	(callback->func)(callback->arg, zone, level, message);
224 }
225 
226 /*%
227  * Update a single RR in version 'ver' of 'db' and log the
228  * update in 'diff'.
229  *
230  * Ensures:
231  * \li	'*tuple' == NULL.  Either the tuple is freed, or its
232  *	ownership has been transferred to the diff.
233  */
234 static isc_result_t
235 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
236 	     dns_diff_t *diff) {
237 	dns_diff_t temp_diff;
238 	isc_result_t result;
239 
240 	/*
241 	 * Create a singleton diff.
242 	 */
243 	dns_diff_init(diff->mctx, &temp_diff);
244 	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
245 
246 	/*
247 	 * Apply it to the database.
248 	 */
249 	result = dns_diff_apply(&temp_diff, db, ver);
250 	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
251 	if (result != ISC_R_SUCCESS) {
252 		dns_difftuple_free(tuple);
253 		return (result);
254 	}
255 
256 	/*
257 	 * Merge it into the current pending journal entry.
258 	 */
259 	dns_diff_appendminimal(diff, tuple);
260 
261 	/*
262 	 * Do not clear temp_diff.
263 	 */
264 	return (ISC_R_SUCCESS);
265 }
266 
267 static isc_result_t
268 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
269 	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
270 	      dns_rdata_t *rdata) {
271 	dns_difftuple_t *tuple = NULL;
272 	isc_result_t result;
273 	result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
274 	if (result != ISC_R_SUCCESS) {
275 		return (result);
276 	}
277 	return (do_one_tuple(&tuple, db, ver, diff));
278 }
279 
280 /**************************************************************************/
281 /*
282  * Callback-style iteration over rdatasets and rdatas.
283  *
284  * foreach_rrset() can be used to iterate over the RRsets
285  * of a name and call a callback function with each
286  * one.  Similarly, foreach_rr() can be used to iterate
287  * over the individual RRs at name, optionally restricted
288  * to RRs of a given type.
289  *
290  * The callback functions are called "actions" and take
291  * two arguments: a void pointer for passing arbitrary
292  * context information, and a pointer to the current RRset
293  * or RR.  By convention, their names end in "_action".
294  */
295 
296 /*
297  * XXXRTH  We might want to make this public somewhere in libdns.
298  */
299 
300 /*%
301  * Function type for foreach_rrset() iterator actions.
302  */
303 typedef isc_result_t
304 rrset_func(void *data, dns_rdataset_t *rrset);
305 
306 /*%
307  * Function type for foreach_rr() iterator actions.
308  */
309 typedef isc_result_t
310 rr_func(void *data, rr_t *rr);
311 
312 /*%
313  * Internal context struct for foreach_node_rr().
314  */
315 typedef struct {
316 	rr_func *rr_action;
317 	void *rr_action_data;
318 } foreach_node_rr_ctx_t;
319 
320 /*%
321  * Internal helper function for foreach_node_rr().
322  */
323 static isc_result_t
324 foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) {
325 	isc_result_t result;
326 	foreach_node_rr_ctx_t *ctx = data;
327 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
328 	     result = dns_rdataset_next(rdataset))
329 	{
330 		rr_t rr = { 0, DNS_RDATA_INIT };
331 
332 		dns_rdataset_current(rdataset, &rr.rdata);
333 		rr.ttl = rdataset->ttl;
334 		result = (*ctx->rr_action)(ctx->rr_action_data, &rr);
335 		if (result != ISC_R_SUCCESS) {
336 			return (result);
337 		}
338 	}
339 	if (result != ISC_R_NOMORE) {
340 		return (result);
341 	}
342 	return (ISC_R_SUCCESS);
343 }
344 
345 /*%
346  * For each rdataset of 'name' in 'ver' of 'db', call 'action'
347  * with the rdataset and 'action_data' as arguments.  If the name
348  * does not exist, do nothing.
349  *
350  * If 'action' returns an error, abort iteration and return the error.
351  */
352 static isc_result_t
353 foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
354 	      rrset_func *action, void *action_data) {
355 	isc_result_t result;
356 	dns_dbnode_t *node;
357 	dns_rdatasetiter_t *iter;
358 
359 	node = NULL;
360 	result = dns_db_findnode(db, name, false, &node);
361 	if (result == ISC_R_NOTFOUND) {
362 		return (ISC_R_SUCCESS);
363 	}
364 	if (result != ISC_R_SUCCESS) {
365 		return (result);
366 	}
367 
368 	iter = NULL;
369 	result = dns_db_allrdatasets(db, node, ver, (isc_stdtime_t)0, &iter);
370 	if (result != ISC_R_SUCCESS) {
371 		goto cleanup_node;
372 	}
373 
374 	for (result = dns_rdatasetiter_first(iter); result == ISC_R_SUCCESS;
375 	     result = dns_rdatasetiter_next(iter))
376 	{
377 		dns_rdataset_t rdataset;
378 
379 		dns_rdataset_init(&rdataset);
380 		dns_rdatasetiter_current(iter, &rdataset);
381 
382 		result = (*action)(action_data, &rdataset);
383 
384 		dns_rdataset_disassociate(&rdataset);
385 		if (result != ISC_R_SUCCESS) {
386 			goto cleanup_iterator;
387 		}
388 	}
389 	if (result == ISC_R_NOMORE) {
390 		result = ISC_R_SUCCESS;
391 	}
392 
393 cleanup_iterator:
394 	dns_rdatasetiter_destroy(&iter);
395 
396 cleanup_node:
397 	dns_db_detachnode(db, &node);
398 
399 	return (result);
400 }
401 
402 /*%
403  * For each RR of 'name' in 'ver' of 'db', call 'action'
404  * with the RR and 'action_data' as arguments.  If the name
405  * does not exist, do nothing.
406  *
407  * If 'action' returns an error, abort iteration
408  * and return the error.
409  */
410 static isc_result_t
411 foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
412 		rr_func *rr_action, void *rr_action_data) {
413 	foreach_node_rr_ctx_t ctx;
414 	ctx.rr_action = rr_action;
415 	ctx.rr_action_data = rr_action_data;
416 	return (foreach_rrset(db, ver, name, foreach_node_rr_action, &ctx));
417 }
418 
419 /*%
420  * For each of the RRs specified by 'db', 'ver', 'name', 'type',
421  * (which can be dns_rdatatype_any to match any type), and 'covers', call
422  * 'action' with the RR and 'action_data' as arguments. If the name
423  * does not exist, or if no RRset of the given type exists at the name,
424  * do nothing.
425  *
426  * If 'action' returns an error, abort iteration and return the error.
427  */
428 static isc_result_t
429 foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
430 	   dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action,
431 	   void *rr_action_data) {
432 	isc_result_t result;
433 	dns_dbnode_t *node;
434 	dns_rdataset_t rdataset;
435 
436 	if (type == dns_rdatatype_any) {
437 		return (foreach_node_rr(db, ver, name, rr_action,
438 					rr_action_data));
439 	}
440 
441 	node = NULL;
442 	if (type == dns_rdatatype_nsec3 ||
443 	    (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3))
444 	{
445 		result = dns_db_findnsec3node(db, name, false, &node);
446 	} else {
447 		result = dns_db_findnode(db, name, false, &node);
448 	}
449 	if (result == ISC_R_NOTFOUND) {
450 		return (ISC_R_SUCCESS);
451 	}
452 	if (result != ISC_R_SUCCESS) {
453 		return (result);
454 	}
455 
456 	dns_rdataset_init(&rdataset);
457 	result = dns_db_findrdataset(db, node, ver, type, covers,
458 				     (isc_stdtime_t)0, &rdataset, NULL);
459 	if (result == ISC_R_NOTFOUND) {
460 		result = ISC_R_SUCCESS;
461 		goto cleanup_node;
462 	}
463 	if (result != ISC_R_SUCCESS) {
464 		goto cleanup_node;
465 	}
466 
467 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
468 	     result = dns_rdataset_next(&rdataset))
469 	{
470 		rr_t rr = { 0, DNS_RDATA_INIT };
471 		dns_rdataset_current(&rdataset, &rr.rdata);
472 		rr.ttl = rdataset.ttl;
473 		result = (*rr_action)(rr_action_data, &rr);
474 		if (result != ISC_R_SUCCESS) {
475 			goto cleanup_rdataset;
476 		}
477 	}
478 	if (result != ISC_R_NOMORE) {
479 		goto cleanup_rdataset;
480 	}
481 	result = ISC_R_SUCCESS;
482 
483 cleanup_rdataset:
484 	dns_rdataset_disassociate(&rdataset);
485 cleanup_node:
486 	dns_db_detachnode(db, &node);
487 
488 	return (result);
489 }
490 
491 /**************************************************************************/
492 /*
493  * Various tests on the database contents (for prerequisites, etc).
494  */
495 
496 /*%
497  * Function type for predicate functions that compare a database RR 'db_rr'
498  * against an update RR 'update_rr'.
499  */
500 typedef bool
501 rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr);
502 
503 /*%
504  * Helper function for rrset_exists().
505  */
506 static isc_result_t
507 rrset_exists_action(void *data, rr_t *rr) {
508 	UNUSED(data);
509 	UNUSED(rr);
510 	return (ISC_R_EXISTS);
511 }
512 
513 /*%
514  * Utility macro for RR existence checking functions.
515  *
516  * If the variable 'result' has the value ISC_R_EXISTS or
517  * ISC_R_SUCCESS, set *exists to true or false,
518  * respectively, and return success.
519  *
520  * If 'result' has any other value, there was a failure.
521  * Return the failure result code and do not set *exists.
522  *
523  * This would be more readable as "do { if ... } while(0)",
524  * but that form generates tons of warnings on Solaris 2.6.
525  */
526 #define RETURN_EXISTENCE_FLAG                                         \
527 	return ((result == ISC_R_EXISTS)                              \
528 			? (*exists = true, ISC_R_SUCCESS)             \
529 			: ((result == ISC_R_SUCCESS)                  \
530 				   ? (*exists = false, ISC_R_SUCCESS) \
531 				   : result))
532 
533 /*%
534  * Set '*exists' to true iff an rrset of the given type exists,
535  * to false otherwise.
536  */
537 static isc_result_t
538 rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
539 	     dns_rdatatype_t type, dns_rdatatype_t covers, bool *exists) {
540 	isc_result_t result;
541 	result = foreach_rr(db, ver, name, type, covers, rrset_exists_action,
542 			    NULL);
543 	RETURN_EXISTENCE_FLAG;
544 }
545 
546 /*%
547  * Set '*visible' to true if the RRset exists and is part of the
548  * visible zone.  Otherwise '*visible' is set to false unless a
549  * error occurs.
550  */
551 static isc_result_t
552 rrset_visible(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
553 	      dns_rdatatype_t type, bool *visible) {
554 	isc_result_t result;
555 	dns_fixedname_t fixed;
556 
557 	dns_fixedname_init(&fixed);
558 	result = dns_db_find(db, name, ver, type, DNS_DBFIND_NOWILD,
559 			     (isc_stdtime_t)0, NULL, dns_fixedname_name(&fixed),
560 			     NULL, NULL);
561 	switch (result) {
562 	case ISC_R_SUCCESS:
563 		*visible = true;
564 		break;
565 	/*
566 	 * Glue, obscured, deleted or replaced records.
567 	 */
568 	case DNS_R_DELEGATION:
569 	case DNS_R_DNAME:
570 	case DNS_R_CNAME:
571 	case DNS_R_NXDOMAIN:
572 	case DNS_R_NXRRSET:
573 	case DNS_R_EMPTYNAME:
574 	case DNS_R_COVERINGNSEC:
575 		*visible = false;
576 		result = ISC_R_SUCCESS;
577 		break;
578 	default:
579 		*visible = false; /* silence false compiler warning */
580 		break;
581 	}
582 	return (result);
583 }
584 
585 /*%
586  * Context struct and helper function for name_exists().
587  */
588 
589 static isc_result_t
590 name_exists_action(void *data, dns_rdataset_t *rrset) {
591 	UNUSED(data);
592 	UNUSED(rrset);
593 	return (ISC_R_EXISTS);
594 }
595 
596 /*%
597  * Set '*exists' to true iff the given name exists, to false otherwise.
598  */
599 static isc_result_t
600 name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
601 	    bool *exists) {
602 	isc_result_t result;
603 	result = foreach_rrset(db, ver, name, name_exists_action, NULL);
604 	RETURN_EXISTENCE_FLAG;
605 }
606 
607 /**************************************************************************/
608 /*
609  * Checking of "RRset exists (value dependent)" prerequisites.
610  *
611  * In the RFC2136 section 3.2.5, this is the pseudocode involving
612  * a variable called "temp", a mapping of <name, type> tuples to rrsets.
613  *
614  * Here, we represent the "temp" data structure as (non-minimal) "dns_diff_t"
615  * where each tuple has op==DNS_DIFFOP_EXISTS.
616  */
617 
618 /*%
619  * A comparison function defining the sorting order for the entries
620  * in the "temp" data structure.  The major sort key is the owner name,
621  * followed by the type and rdata.
622  */
623 static int
624 temp_order(const void *av, const void *bv) {
625 	dns_difftuple_t const *const *ap = av;
626 	dns_difftuple_t const *const *bp = bv;
627 	dns_difftuple_t const *a = *ap;
628 	dns_difftuple_t const *b = *bp;
629 	int r;
630 	r = dns_name_compare(&a->name, &b->name);
631 	if (r != 0) {
632 		return (r);
633 	}
634 	r = (b->rdata.type - a->rdata.type);
635 	if (r != 0) {
636 		return (r);
637 	}
638 	r = dns_rdata_casecompare(&a->rdata, &b->rdata);
639 	return (r);
640 }
641 
642 /**************************************************************************/
643 /*
644  * Conditional deletion of RRs.
645  */
646 
647 /*%
648  * Context structure for delete_if().
649  */
650 
651 typedef struct {
652 	rr_predicate *predicate;
653 	dns_db_t *db;
654 	dns_dbversion_t *ver;
655 	dns_diff_t *diff;
656 	dns_name_t *name;
657 	dns_rdata_t *update_rr;
658 } conditional_delete_ctx_t;
659 
660 /*%
661  * Predicate functions for delete_if().
662  */
663 
664 /*%
665  * Return true always.
666  */
667 static bool
668 true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
669 	UNUSED(update_rr);
670 	UNUSED(db_rr);
671 	return (true);
672 }
673 
674 /*%
675  * Return true if the record is a RRSIG.
676  */
677 static bool
678 rrsig_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
679 	UNUSED(update_rr);
680 	return ((db_rr->type == dns_rdatatype_rrsig) ? true : false);
681 }
682 
683 /*%
684  * Internal helper function for delete_if().
685  */
686 static isc_result_t
687 delete_if_action(void *data, rr_t *rr) {
688 	conditional_delete_ctx_t *ctx = data;
689 	if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) {
690 		isc_result_t result;
691 		result = update_one_rr(ctx->db, ctx->ver, ctx->diff,
692 				       DNS_DIFFOP_DEL, ctx->name, rr->ttl,
693 				       &rr->rdata);
694 		return (result);
695 	} else {
696 		return (ISC_R_SUCCESS);
697 	}
698 }
699 
700 /*%
701  * Conditionally delete RRs.  Apply 'predicate' to the RRs
702  * specified by 'db', 'ver', 'name', and 'type' (which can
703  * be dns_rdatatype_any to match any type).  Delete those
704  * RRs for which the predicate returns true, and log the
705  * deletions in 'diff'.
706  */
707 static isc_result_t
708 delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver,
709 	  dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers,
710 	  dns_rdata_t *update_rr, dns_diff_t *diff) {
711 	conditional_delete_ctx_t ctx;
712 	ctx.predicate = predicate;
713 	ctx.db = db;
714 	ctx.ver = ver;
715 	ctx.diff = diff;
716 	ctx.name = name;
717 	ctx.update_rr = update_rr;
718 	return (foreach_rr(db, ver, name, type, covers, delete_if_action,
719 			   &ctx));
720 }
721 
722 /**************************************************************************/
723 /*
724  * Incremental updating of NSECs and RRSIGs.
725  */
726 
727 /*%
728  * We abuse the dns_diff_t type to represent a set of domain names
729  * affected by the update.
730  */
731 static isc_result_t
732 namelist_append_name(dns_diff_t *list, dns_name_t *name) {
733 	isc_result_t result;
734 	dns_difftuple_t *tuple = NULL;
735 	static dns_rdata_t dummy_rdata = DNS_RDATA_INIT;
736 
737 	CHECK(dns_difftuple_create(list->mctx, DNS_DIFFOP_EXISTS, name, 0,
738 				   &dummy_rdata, &tuple));
739 	dns_diff_append(list, &tuple);
740 failure:
741 	return (result);
742 }
743 
744 static isc_result_t
745 namelist_append_subdomain(dns_db_t *db, dns_name_t *name,
746 			  dns_diff_t *affected) {
747 	isc_result_t result;
748 	dns_fixedname_t fixedname;
749 	dns_name_t *child;
750 	dns_dbiterator_t *dbit = NULL;
751 
752 	child = dns_fixedname_initname(&fixedname);
753 
754 	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
755 
756 	for (result = dns_dbiterator_seek(dbit, name); result == ISC_R_SUCCESS;
757 	     result = dns_dbiterator_next(dbit))
758 	{
759 		dns_dbnode_t *node = NULL;
760 		CHECK(dns_dbiterator_current(dbit, &node, child));
761 		dns_db_detachnode(db, &node);
762 		if (!dns_name_issubdomain(child, name)) {
763 			break;
764 		}
765 		CHECK(namelist_append_name(affected, child));
766 	}
767 	if (result == ISC_R_NOMORE) {
768 		result = ISC_R_SUCCESS;
769 	}
770 failure:
771 	if (dbit != NULL) {
772 		dns_dbiterator_destroy(&dbit);
773 	}
774 	return (result);
775 }
776 
777 /*%
778  * Helper function for non_nsec_rrset_exists().
779  */
780 static isc_result_t
781 is_non_nsec_action(void *data, dns_rdataset_t *rrset) {
782 	UNUSED(data);
783 	if (!(rrset->type == dns_rdatatype_nsec ||
784 	      rrset->type == dns_rdatatype_nsec3 ||
785 	      (rrset->type == dns_rdatatype_rrsig &&
786 	       (rrset->covers == dns_rdatatype_nsec ||
787 		rrset->covers == dns_rdatatype_nsec3))))
788 	{
789 		return (ISC_R_EXISTS);
790 	}
791 	return (ISC_R_SUCCESS);
792 }
793 
794 /*%
795  * Check whether there is an rrset other than a NSEC or RRSIG NSEC,
796  * i.e., anything that justifies the continued existence of a name
797  * after a secure update.
798  *
799  * If such an rrset exists, set '*exists' to true.
800  * Otherwise, set it to false.
801  */
802 static isc_result_t
803 non_nsec_rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
804 		      bool *exists) {
805 	isc_result_t result;
806 	result = foreach_rrset(db, ver, name, is_non_nsec_action, NULL);
807 	RETURN_EXISTENCE_FLAG;
808 }
809 
810 /*%
811  * A comparison function for sorting dns_diff_t:s by name.
812  */
813 static int
814 name_order(const void *av, const void *bv) {
815 	dns_difftuple_t const *const *ap = av;
816 	dns_difftuple_t const *const *bp = bv;
817 	dns_difftuple_t const *a = *ap;
818 	dns_difftuple_t const *b = *bp;
819 	return (dns_name_compare(&a->name, &b->name));
820 }
821 
822 static isc_result_t
823 uniqify_name_list(dns_diff_t *list) {
824 	isc_result_t result;
825 	dns_difftuple_t *p, *q;
826 
827 	CHECK(dns_diff_sort(list, name_order));
828 
829 	p = ISC_LIST_HEAD(list->tuples);
830 	while (p != NULL) {
831 		do {
832 			q = ISC_LIST_NEXT(p, link);
833 			if (q == NULL || !dns_name_equal(&p->name, &q->name)) {
834 				break;
835 			}
836 			ISC_LIST_UNLINK(list->tuples, q, link);
837 			dns_difftuple_free(&q);
838 		} while (1);
839 		p = ISC_LIST_NEXT(p, link);
840 	}
841 failure:
842 	return (result);
843 }
844 
845 static isc_result_t
846 is_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, bool *flag,
847 	  bool *cut, bool *unsecure) {
848 	isc_result_t result;
849 	dns_fixedname_t foundname;
850 	dns_fixedname_init(&foundname);
851 	result = dns_db_find(db, name, ver, dns_rdatatype_any,
852 			     DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
853 			     (isc_stdtime_t)0, NULL,
854 			     dns_fixedname_name(&foundname), NULL, NULL);
855 	if (result == ISC_R_SUCCESS || result == DNS_R_EMPTYNAME) {
856 		*flag = true;
857 		*cut = false;
858 		if (unsecure != NULL) {
859 			*unsecure = false;
860 		}
861 		return (ISC_R_SUCCESS);
862 	} else if (result == DNS_R_ZONECUT) {
863 		*flag = true;
864 		*cut = true;
865 		if (unsecure != NULL) {
866 			/*
867 			 * We are at the zonecut.  Check to see if there
868 			 * is a DS RRset.
869 			 */
870 			if (dns_db_find(db, name, ver, dns_rdatatype_ds, 0,
871 					(isc_stdtime_t)0, NULL,
872 					dns_fixedname_name(&foundname), NULL,
873 					NULL) == DNS_R_NXRRSET)
874 			{
875 				*unsecure = true;
876 			} else {
877 				*unsecure = false;
878 			}
879 		}
880 		return (ISC_R_SUCCESS);
881 	} else if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
882 		   result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN)
883 	{
884 		*flag = false;
885 		*cut = false;
886 		if (unsecure != NULL) {
887 			*unsecure = false;
888 		}
889 		return (ISC_R_SUCCESS);
890 	} else {
891 		/*
892 		 * Silence compiler.
893 		 */
894 		*flag = false;
895 		*cut = false;
896 		if (unsecure != NULL) {
897 			*unsecure = false;
898 		}
899 		return (result);
900 	}
901 }
902 
903 /*%
904  * Find the next/previous name that has a NSEC record.
905  * In other words, skip empty database nodes and names that
906  * have had their NSECs removed because they are obscured by
907  * a zone cut.
908  */
909 static isc_result_t
910 next_active(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
911 	    dns_dbversion_t *ver, dns_name_t *oldname, dns_name_t *newname,
912 	    bool forward) {
913 	isc_result_t result;
914 	dns_dbiterator_t *dbit = NULL;
915 	bool has_nsec = false;
916 	unsigned int wraps = 0;
917 	bool secure = dns_db_issecure(db);
918 
919 	CHECK(dns_db_createiterator(db, 0, &dbit));
920 
921 	CHECK(dns_dbiterator_seek(dbit, oldname));
922 	do {
923 		dns_dbnode_t *node = NULL;
924 
925 		if (forward) {
926 			result = dns_dbiterator_next(dbit);
927 		} else {
928 			result = dns_dbiterator_prev(dbit);
929 		}
930 		if (result == ISC_R_NOMORE) {
931 			/*
932 			 * Wrap around.
933 			 */
934 			if (forward) {
935 				CHECK(dns_dbiterator_first(dbit));
936 			} else {
937 				CHECK(dns_dbiterator_last(dbit));
938 			}
939 			wraps++;
940 			if (wraps == 2) {
941 				update_log(log, zone, ISC_LOG_ERROR,
942 					   "secure zone with no NSECs");
943 				result = DNS_R_BADZONE;
944 				goto failure;
945 			}
946 		}
947 		CHECK(dns_dbiterator_current(dbit, &node, newname));
948 		dns_db_detachnode(db, &node);
949 
950 		/*
951 		 * The iterator may hold the tree lock, and
952 		 * rrset_exists() calls dns_db_findnode() which
953 		 * may try to reacquire it.  To avoid deadlock
954 		 * we must pause the iterator first.
955 		 */
956 		CHECK(dns_dbiterator_pause(dbit));
957 		if (secure) {
958 			CHECK(rrset_exists(db, ver, newname, dns_rdatatype_nsec,
959 					   0, &has_nsec));
960 		} else {
961 			dns_fixedname_t ffound;
962 			dns_name_t *found;
963 			found = dns_fixedname_initname(&ffound);
964 			result = dns_db_find(
965 				db, newname, ver, dns_rdatatype_soa,
966 				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
967 			if (result == ISC_R_SUCCESS ||
968 			    result == DNS_R_EMPTYNAME ||
969 			    result == DNS_R_NXRRSET || result == DNS_R_CNAME ||
970 			    (result == DNS_R_DELEGATION &&
971 			     dns_name_equal(newname, found)))
972 			{
973 				has_nsec = true;
974 				result = ISC_R_SUCCESS;
975 			} else if (result != DNS_R_NXDOMAIN) {
976 				break;
977 			}
978 		}
979 	} while (!has_nsec);
980 failure:
981 	if (dbit != NULL) {
982 		dns_dbiterator_destroy(&dbit);
983 	}
984 
985 	return (result);
986 }
987 
988 /*%
989  * Add a NSEC record for "name", recording the change in "diff".
990  * The existing NSEC is removed.
991  */
992 static isc_result_t
993 add_nsec(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
994 	 dns_dbversion_t *ver, dns_name_t *name, dns_ttl_t nsecttl,
995 	 dns_diff_t *diff) {
996 	isc_result_t result;
997 	dns_dbnode_t *node = NULL;
998 	unsigned char buffer[DNS_NSEC_BUFFERSIZE];
999 	dns_rdata_t rdata = DNS_RDATA_INIT;
1000 	dns_difftuple_t *tuple = NULL;
1001 	dns_fixedname_t fixedname;
1002 	dns_name_t *target;
1003 
1004 	target = dns_fixedname_initname(&fixedname);
1005 
1006 	/*
1007 	 * Find the successor name, aka NSEC target.
1008 	 */
1009 	CHECK(next_active(log, zone, db, ver, name, target, true));
1010 
1011 	/*
1012 	 * Create the NSEC RDATA.
1013 	 */
1014 	CHECK(dns_db_findnode(db, name, false, &node));
1015 	dns_rdata_init(&rdata);
1016 	CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata));
1017 	dns_db_detachnode(db, &node);
1018 
1019 	/*
1020 	 * Delete the old NSEC and record the change.
1021 	 */
1022 	CHECK(delete_if(true_p, db, ver, name, dns_rdatatype_nsec, 0, NULL,
1023 			diff));
1024 	/*
1025 	 * Add the new NSEC and record the change.
1026 	 */
1027 	CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, nsecttl,
1028 				   &rdata, &tuple));
1029 	CHECK(do_one_tuple(&tuple, db, ver, diff));
1030 	INSIST(tuple == NULL);
1031 
1032 failure:
1033 	if (node != NULL) {
1034 		dns_db_detachnode(db, &node);
1035 	}
1036 	return (result);
1037 }
1038 
1039 /*%
1040  * Add a placeholder NSEC record for "name", recording the change in "diff".
1041  */
1042 static isc_result_t
1043 add_placeholder_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
1044 		     dns_diff_t *diff) {
1045 	isc_result_t result;
1046 	dns_difftuple_t *tuple = NULL;
1047 	isc_region_t r;
1048 	unsigned char data[1] = { 0 }; /* The root domain, no bits. */
1049 	dns_rdata_t rdata = DNS_RDATA_INIT;
1050 
1051 	r.base = data;
1052 	r.length = sizeof(data);
1053 	dns_rdata_fromregion(&rdata, dns_db_class(db), dns_rdatatype_nsec, &r);
1054 	CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0, &rdata,
1055 				   &tuple));
1056 	CHECK(do_one_tuple(&tuple, db, ver, diff));
1057 failure:
1058 	return (result);
1059 }
1060 
1061 static isc_result_t
1062 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
1063 	       isc_mem_t *mctx, unsigned int maxkeys, dst_key_t **keys,
1064 	       unsigned int *nkeys) {
1065 	isc_result_t result;
1066 	isc_stdtime_t now;
1067 	dns_dbnode_t *node = NULL;
1068 	const char *directory = dns_zone_getkeydirectory(zone);
1069 	CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
1070 	isc_stdtime_get(&now);
1071 	CHECK(dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
1072 				      directory, now, mctx, maxkeys, keys,
1073 				      nkeys));
1074 failure:
1075 	if (node != NULL) {
1076 		dns_db_detachnode(db, &node);
1077 	}
1078 	return (result);
1079 }
1080 
1081 /*%
1082  * Add RRSIG records for an RRset, recording the change in "diff".
1083  */
1084 static isc_result_t
1085 add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1086 	 dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type,
1087 	 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
1088 	 isc_stdtime_t inception, isc_stdtime_t expire, bool check_ksk,
1089 	 bool keyset_kskonly) {
1090 	isc_result_t result;
1091 	dns_dbnode_t *node = NULL;
1092 	dns_kasp_t *kasp = dns_zone_getkasp(zone);
1093 	dns_rdataset_t rdataset;
1094 	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
1095 	dns_stats_t *dnssecsignstats = dns_zone_getdnssecsignstats(zone);
1096 	isc_buffer_t buffer;
1097 	unsigned char data[1024]; /* XXX */
1098 	unsigned int i, j;
1099 	bool added_sig = false;
1100 	isc_mem_t *mctx = diff->mctx;
1101 
1102 	if (kasp != NULL) {
1103 		check_ksk = false;
1104 		keyset_kskonly = true;
1105 	}
1106 
1107 	dns_rdataset_init(&rdataset);
1108 	isc_buffer_init(&buffer, data, sizeof(data));
1109 
1110 	/* Get the rdataset to sign. */
1111 	if (type == dns_rdatatype_nsec3) {
1112 		CHECK(dns_db_findnsec3node(db, name, false, &node));
1113 	} else {
1114 		CHECK(dns_db_findnode(db, name, false, &node));
1115 	}
1116 	CHECK(dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t)0,
1117 				  &rdataset, NULL));
1118 	dns_db_detachnode(db, &node);
1119 
1120 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
1121 #define KSK(x)	  ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
1122 #define ID(x)	  dst_key_id(x)
1123 #define ALG(x)	  dst_key_alg(x)
1124 
1125 	/*
1126 	 * If we are honoring KSK flags then we need to check that we
1127 	 * have both KSK and non-KSK keys that are not revoked per
1128 	 * algorithm.
1129 	 */
1130 	for (i = 0; i < nkeys; i++) {
1131 		bool both = false;
1132 
1133 		/* Don't add signatures for offline or inactive keys */
1134 		if (!dst_key_isprivate(keys[i])) {
1135 			continue;
1136 		}
1137 		if (dst_key_inactive(keys[i])) {
1138 			continue;
1139 		}
1140 
1141 		if (check_ksk && !REVOKE(keys[i])) {
1142 			bool have_ksk, have_nonksk;
1143 			if (KSK(keys[i])) {
1144 				have_ksk = true;
1145 				have_nonksk = false;
1146 			} else {
1147 				have_ksk = false;
1148 				have_nonksk = true;
1149 			}
1150 			for (j = 0; j < nkeys; j++) {
1151 				if (j == i || ALG(keys[i]) != ALG(keys[j])) {
1152 					continue;
1153 				}
1154 
1155 				/* Don't consider inactive keys, however
1156 				 * the key may be temporary offline, so do
1157 				 * consider keys which private key files are
1158 				 * unavailable.
1159 				 */
1160 				if (dst_key_inactive(keys[j])) {
1161 					continue;
1162 				}
1163 
1164 				if (REVOKE(keys[j])) {
1165 					continue;
1166 				}
1167 				if (KSK(keys[j])) {
1168 					have_ksk = true;
1169 				} else {
1170 					have_nonksk = true;
1171 				}
1172 				both = have_ksk && have_nonksk;
1173 				if (both) {
1174 					break;
1175 				}
1176 			}
1177 		}
1178 
1179 		if (kasp != NULL) {
1180 			/*
1181 			 * A dnssec-policy is found. Check what RRsets this
1182 			 * key should sign.
1183 			 */
1184 			isc_stdtime_t when;
1185 			isc_result_t kresult;
1186 			bool ksk = false;
1187 			bool zsk = false;
1188 
1189 			kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
1190 			if (kresult != ISC_R_SUCCESS) {
1191 				if (KSK(keys[i])) {
1192 					ksk = true;
1193 				}
1194 			}
1195 			kresult = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
1196 			if (kresult != ISC_R_SUCCESS) {
1197 				if (!KSK(keys[i])) {
1198 					zsk = true;
1199 				}
1200 			}
1201 
1202 			if (type == dns_rdatatype_dnskey ||
1203 			    type == dns_rdatatype_cdnskey ||
1204 			    type == dns_rdatatype_cds)
1205 			{
1206 				/*
1207 				 * DNSKEY RRset is signed with KSK.
1208 				 * CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
1209 				 */
1210 				if (!ksk) {
1211 					continue;
1212 				}
1213 			} else if (!zsk) {
1214 				/*
1215 				 * Other RRsets are signed with ZSK.
1216 				 */
1217 				continue;
1218 			} else if (zsk &&
1219 				   !dst_key_is_signing(keys[i], DST_BOOL_ZSK,
1220 						       inception, &when)) {
1221 				/*
1222 				 * This key is not active for zone-signing.
1223 				 */
1224 				continue;
1225 			}
1226 
1227 			/*
1228 			 * If this key is revoked, it may only sign the
1229 			 * DNSKEY RRset.
1230 			 */
1231 			if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
1232 				continue;
1233 			}
1234 		} else if (both) {
1235 			/*
1236 			 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
1237 			 */
1238 			if (type == dns_rdatatype_dnskey ||
1239 			    type == dns_rdatatype_cdnskey ||
1240 			    type == dns_rdatatype_cds)
1241 			{
1242 				if (!KSK(keys[i]) && keyset_kskonly) {
1243 					continue;
1244 				}
1245 			} else if (KSK(keys[i])) {
1246 				continue;
1247 			}
1248 		} else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
1249 			continue;
1250 		}
1251 
1252 		/* Calculate the signature, creating a RRSIG RDATA. */
1253 		CHECK(dns_dnssec_sign(name, &rdataset, keys[i], &inception,
1254 				      &expire, mctx, &buffer, &sig_rdata));
1255 
1256 		/* Update the database and journal with the RRSIG. */
1257 		/* XXX inefficient - will cause dataset merging */
1258 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
1259 				    rdataset.ttl, &sig_rdata));
1260 		dns_rdata_reset(&sig_rdata);
1261 		isc_buffer_init(&buffer, data, sizeof(data));
1262 		added_sig = true;
1263 		/* Update DNSSEC sign statistics. */
1264 		if (dnssecsignstats != NULL) {
1265 			dns_dnssecsignstats_increment(dnssecsignstats,
1266 						      ID(keys[i]),
1267 						      (uint8_t)ALG(keys[i]),
1268 						      dns_dnssecsignstats_sign);
1269 		}
1270 	}
1271 	if (!added_sig) {
1272 		update_log(log, zone, ISC_LOG_ERROR,
1273 			   "found no active private keys, "
1274 			   "unable to generate any signatures");
1275 		result = ISC_R_NOTFOUND;
1276 	}
1277 
1278 failure:
1279 	if (dns_rdataset_isassociated(&rdataset)) {
1280 		dns_rdataset_disassociate(&rdataset);
1281 	}
1282 	if (node != NULL) {
1283 		dns_db_detachnode(db, &node);
1284 	}
1285 	return (result);
1286 }
1287 
1288 /*
1289  * Delete expired RRsigs and any RRsigs we are about to re-sign.
1290  * See also zone.c:del_sigs().
1291  */
1292 static isc_result_t
1293 del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
1294 	    dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys) {
1295 	isc_result_t result;
1296 	dns_dbnode_t *node = NULL;
1297 	dns_rdataset_t rdataset;
1298 	dns_rdata_t rdata = DNS_RDATA_INIT;
1299 	unsigned int i;
1300 	dns_rdata_rrsig_t rrsig;
1301 	bool found;
1302 
1303 	dns_rdataset_init(&rdataset);
1304 
1305 	result = dns_db_findnode(db, name, false, &node);
1306 	if (result == ISC_R_NOTFOUND) {
1307 		return (ISC_R_SUCCESS);
1308 	}
1309 	if (result != ISC_R_SUCCESS) {
1310 		goto failure;
1311 	}
1312 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig,
1313 				     dns_rdatatype_dnskey, (isc_stdtime_t)0,
1314 				     &rdataset, NULL);
1315 	dns_db_detachnode(db, &node);
1316 
1317 	if (result == ISC_R_NOTFOUND) {
1318 		return (ISC_R_SUCCESS);
1319 	}
1320 	if (result != ISC_R_SUCCESS) {
1321 		goto failure;
1322 	}
1323 
1324 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
1325 	     result = dns_rdataset_next(&rdataset))
1326 	{
1327 		dns_rdataset_current(&rdataset, &rdata);
1328 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
1329 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
1330 		found = false;
1331 		for (i = 0; i < nkeys; i++) {
1332 			if (rrsig.keyid == dst_key_id(keys[i])) {
1333 				found = true;
1334 				if (!dst_key_isprivate(keys[i]) &&
1335 				    !dst_key_inactive(keys[i])) {
1336 					/*
1337 					 * The re-signing code in zone.c
1338 					 * will mark this as offline.
1339 					 * Just skip the record for now.
1340 					 */
1341 					break;
1342 				}
1343 				result = update_one_rr(db, ver, diff,
1344 						       DNS_DIFFOP_DEL, name,
1345 						       rdataset.ttl, &rdata);
1346 				break;
1347 			}
1348 		}
1349 		/*
1350 		 * If there is not a matching DNSKEY then delete the RRSIG.
1351 		 */
1352 		if (!found) {
1353 			result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
1354 					       name, rdataset.ttl, &rdata);
1355 		}
1356 		dns_rdata_reset(&rdata);
1357 		if (result != ISC_R_SUCCESS) {
1358 			break;
1359 		}
1360 	}
1361 	dns_rdataset_disassociate(&rdataset);
1362 	if (result == ISC_R_NOMORE) {
1363 		result = ISC_R_SUCCESS;
1364 	}
1365 failure:
1366 	if (node != NULL) {
1367 		dns_db_detachnode(db, &node);
1368 	}
1369 	return (result);
1370 }
1371 
1372 static isc_result_t
1373 add_exposed_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1374 		 dns_dbversion_t *ver, dns_name_t *name, bool cut,
1375 		 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
1376 		 isc_stdtime_t inception, isc_stdtime_t expire, bool check_ksk,
1377 		 bool keyset_kskonly, unsigned int *sigs) {
1378 	isc_result_t result;
1379 	dns_dbnode_t *node;
1380 	dns_rdatasetiter_t *iter;
1381 
1382 	node = NULL;
1383 	result = dns_db_findnode(db, name, false, &node);
1384 	if (result == ISC_R_NOTFOUND) {
1385 		return (ISC_R_SUCCESS);
1386 	}
1387 	if (result != ISC_R_SUCCESS) {
1388 		return (result);
1389 	}
1390 
1391 	iter = NULL;
1392 	result = dns_db_allrdatasets(db, node, ver, (isc_stdtime_t)0, &iter);
1393 	if (result != ISC_R_SUCCESS) {
1394 		goto cleanup_node;
1395 	}
1396 
1397 	for (result = dns_rdatasetiter_first(iter); result == ISC_R_SUCCESS;
1398 	     result = dns_rdatasetiter_next(iter))
1399 	{
1400 		dns_rdataset_t rdataset;
1401 		dns_rdatatype_t type;
1402 		bool flag;
1403 
1404 		dns_rdataset_init(&rdataset);
1405 		dns_rdatasetiter_current(iter, &rdataset);
1406 		type = rdataset.type;
1407 		dns_rdataset_disassociate(&rdataset);
1408 
1409 		/*
1410 		 * We don't need to sign unsigned NSEC records at the cut
1411 		 * as they are handled elsewhere.
1412 		 */
1413 		if ((type == dns_rdatatype_rrsig) ||
1414 		    (cut && type != dns_rdatatype_ds)) {
1415 			continue;
1416 		}
1417 		result = rrset_exists(db, ver, name, dns_rdatatype_rrsig, type,
1418 				      &flag);
1419 		if (result != ISC_R_SUCCESS) {
1420 			goto cleanup_iterator;
1421 		}
1422 		if (flag) {
1423 			continue;
1424 		}
1425 		result = add_sigs(log, zone, db, ver, name, type, diff, keys,
1426 				  nkeys, inception, expire, check_ksk,
1427 				  keyset_kskonly);
1428 		if (result != ISC_R_SUCCESS) {
1429 			goto cleanup_iterator;
1430 		}
1431 		(*sigs)++;
1432 	}
1433 	if (result == ISC_R_NOMORE) {
1434 		result = ISC_R_SUCCESS;
1435 	}
1436 
1437 cleanup_iterator:
1438 	dns_rdatasetiter_destroy(&iter);
1439 
1440 cleanup_node:
1441 	dns_db_detachnode(db, &node);
1442 
1443 	return (result);
1444 }
1445 
1446 /*%
1447  * Update RRSIG, NSEC and NSEC3 records affected by an update.  The original
1448  * update, including the SOA serial update but excluding the RRSIG & NSEC
1449  * changes, is in "diff" and has already been applied to "newver" of "db".
1450  * The database version prior to the update is "oldver".
1451  *
1452  * The necessary RRSIG, NSEC and NSEC3 changes will be applied to "newver"
1453  * and added (as a minimal diff) to "diff".
1454  *
1455  * The RRSIGs generated will be valid for 'sigvalidityinterval' seconds.
1456  */
1457 isc_result_t
1458 dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1459 		      dns_dbversion_t *oldver, dns_dbversion_t *newver,
1460 		      dns_diff_t *diff, uint32_t sigvalidityinterval) {
1461 	return (dns_update_signaturesinc(log, zone, db, oldver, newver, diff,
1462 					 sigvalidityinterval, NULL));
1463 }
1464 
1465 struct dns_update_state {
1466 	unsigned int magic;
1467 	dns_diff_t diffnames;
1468 	dns_diff_t affected;
1469 	dns_diff_t sig_diff;
1470 	dns_diff_t nsec_diff;
1471 	dns_diff_t nsec_mindiff;
1472 	dns_diff_t work;
1473 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
1474 	unsigned int nkeys;
1475 	isc_stdtime_t inception, expire, soaexpire, keyexpire;
1476 	dns_ttl_t nsecttl;
1477 	bool check_ksk, keyset_kskonly, build_nsec3;
1478 	enum { sign_updates,
1479 	       remove_orphaned,
1480 	       build_chain,
1481 	       process_nsec,
1482 	       sign_nsec,
1483 	       update_nsec3,
1484 	       process_nsec3,
1485 	       sign_nsec3 } state;
1486 };
1487 
1488 static uint32_t
1489 dns__jitter_expire(dns_zone_t *zone, uint32_t sigvalidityinterval) {
1490 	/* Spread out signatures over time */
1491 	if (sigvalidityinterval >= 3600U) {
1492 		uint32_t expiryinterval =
1493 			dns_zone_getsigresigninginterval(zone);
1494 
1495 		if (sigvalidityinterval < 7200U) {
1496 			expiryinterval = 1200;
1497 		} else if (expiryinterval > sigvalidityinterval) {
1498 			expiryinterval = sigvalidityinterval;
1499 		} else {
1500 			expiryinterval = sigvalidityinterval - expiryinterval;
1501 		}
1502 		uint32_t jitter = isc_random_uniform(expiryinterval);
1503 		sigvalidityinterval -= jitter;
1504 	}
1505 	return (sigvalidityinterval);
1506 }
1507 
1508 isc_result_t
1509 dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1510 			 dns_dbversion_t *oldver, dns_dbversion_t *newver,
1511 			 dns_diff_t *diff, uint32_t sigvalidityinterval,
1512 			 dns_update_state_t **statep) {
1513 	isc_result_t result = ISC_R_SUCCESS;
1514 	dns_update_state_t mystate, *state;
1515 
1516 	dns_difftuple_t *t, *next;
1517 	bool flag, build_nsec;
1518 	unsigned int i;
1519 	isc_stdtime_t now;
1520 	dns_rdata_soa_t soa;
1521 	dns_rdata_t rdata = DNS_RDATA_INIT;
1522 	dns_rdataset_t rdataset;
1523 	dns_dbnode_t *node = NULL;
1524 	bool unsecure;
1525 	bool cut;
1526 	dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
1527 	unsigned int sigs = 0;
1528 	unsigned int maxsigs = dns_zone_getsignatures(zone);
1529 
1530 	if (statep == NULL || *statep == NULL) {
1531 		if (statep == NULL) {
1532 			state = &mystate;
1533 		} else {
1534 			state = isc_mem_get(diff->mctx, sizeof(*state));
1535 		}
1536 
1537 		dns_diff_init(diff->mctx, &state->diffnames);
1538 		dns_diff_init(diff->mctx, &state->affected);
1539 		dns_diff_init(diff->mctx, &state->sig_diff);
1540 		dns_diff_init(diff->mctx, &state->nsec_diff);
1541 		dns_diff_init(diff->mctx, &state->nsec_mindiff);
1542 		dns_diff_init(diff->mctx, &state->work);
1543 		state->nkeys = 0;
1544 		state->build_nsec3 = false;
1545 
1546 		result = find_zone_keys(zone, db, newver, diff->mctx,
1547 					DNS_MAXZONEKEYS, state->zone_keys,
1548 					&state->nkeys);
1549 		if (result != ISC_R_SUCCESS) {
1550 			update_log(log, zone, ISC_LOG_ERROR,
1551 				   "could not get zone keys for secure "
1552 				   "dynamic update");
1553 			goto failure;
1554 		}
1555 
1556 		isc_stdtime_get(&now);
1557 		state->inception = now - 3600; /* Allow for some clock skew. */
1558 		state->expire = now +
1559 				dns__jitter_expire(zone, sigvalidityinterval);
1560 		state->soaexpire = now + sigvalidityinterval;
1561 		state->keyexpire = dns_zone_getkeyvalidityinterval(zone);
1562 		if (state->keyexpire == 0) {
1563 			state->keyexpire = state->expire;
1564 		} else {
1565 			state->keyexpire += now;
1566 		}
1567 
1568 		/*
1569 		 * Do we look at the KSK flag on the DNSKEY to determining which
1570 		 * keys sign which RRsets?  First check the zone option then
1571 		 * check the keys flags to make sure at least one has a ksk set
1572 		 * and one doesn't.
1573 		 */
1574 		state->check_ksk = ((dns_zone_getoptions(zone) &
1575 				     DNS_ZONEOPT_UPDATECHECKKSK) != 0);
1576 		state->keyset_kskonly = ((dns_zone_getoptions(zone) &
1577 					  DNS_ZONEOPT_DNSKEYKSKONLY) != 0);
1578 
1579 		/*
1580 		 * Get the NSEC/NSEC3 TTL from the SOA MINIMUM field.
1581 		 */
1582 		CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
1583 		dns_rdataset_init(&rdataset);
1584 		CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa,
1585 					  0, (isc_stdtime_t)0, &rdataset,
1586 					  NULL));
1587 		CHECK(dns_rdataset_first(&rdataset));
1588 		dns_rdataset_current(&rdataset, &rdata);
1589 		CHECK(dns_rdata_tostruct(&rdata, &soa, NULL));
1590 		state->nsecttl = soa.minimum;
1591 		dns_rdataset_disassociate(&rdataset);
1592 		dns_db_detachnode(db, &node);
1593 
1594 		/*
1595 		 * Find all RRsets directly affected by the update, and
1596 		 * update their RRSIGs.  Also build a list of names affected
1597 		 * by the update in "diffnames".
1598 		 */
1599 		CHECK(dns_diff_sort(diff, temp_order));
1600 		state->state = sign_updates;
1601 		state->magic = STATE_MAGIC;
1602 		if (statep != NULL) {
1603 			*statep = state;
1604 		}
1605 	} else {
1606 		REQUIRE(DNS_STATE_VALID(*statep));
1607 		state = *statep;
1608 	}
1609 
1610 next_state:
1611 	switch (state->state) {
1612 	case sign_updates:
1613 		t = ISC_LIST_HEAD(diff->tuples);
1614 		while (t != NULL) {
1615 			dns_name_t *name = &t->name;
1616 			/*
1617 			 * Now "name" is a new, unique name affected by the
1618 			 * update.
1619 			 */
1620 
1621 			CHECK(namelist_append_name(&state->diffnames, name));
1622 
1623 			while (t != NULL && dns_name_equal(&t->name, name)) {
1624 				dns_rdatatype_t type;
1625 				type = t->rdata.type;
1626 
1627 				/*
1628 				 * Now "name" and "type" denote a new unique
1629 				 * RRset affected by the update.
1630 				 */
1631 
1632 				/* Don't sign RRSIGs. */
1633 				if (type == dns_rdatatype_rrsig) {
1634 					goto skip;
1635 				}
1636 
1637 				/*
1638 				 * Delete all old RRSIGs covering this type,
1639 				 * since they are all invalid when the signed
1640 				 * RRset has changed.  We may not be able to
1641 				 * recreate all of them - tough.
1642 				 * Special case changes to the zone's DNSKEY
1643 				 * records to support offline KSKs.
1644 				 */
1645 				if (type == dns_rdatatype_dnskey) {
1646 					del_keysigs(db, newver, name,
1647 						    &state->sig_diff,
1648 						    state->zone_keys,
1649 						    state->nkeys);
1650 				} else {
1651 					CHECK(delete_if(
1652 						true_p, db, newver, name,
1653 						dns_rdatatype_rrsig, type, NULL,
1654 						&state->sig_diff));
1655 				}
1656 
1657 				/*
1658 				 * If this RRset is still visible after the
1659 				 * update, add a new signature for it.
1660 				 */
1661 				CHECK(rrset_visible(db, newver, name, type,
1662 						    &flag));
1663 				if (flag) {
1664 					isc_stdtime_t exp;
1665 					if (type == dns_rdatatype_dnskey ||
1666 					    type == dns_rdatatype_cdnskey ||
1667 					    type == dns_rdatatype_cds)
1668 					{
1669 						exp = state->keyexpire;
1670 					} else if (type == dns_rdatatype_soa) {
1671 						exp = state->soaexpire;
1672 					} else {
1673 						exp = state->expire;
1674 					}
1675 
1676 					CHECK(add_sigs(
1677 						log, zone, db, newver, name,
1678 						type, &state->sig_diff,
1679 						state->zone_keys, state->nkeys,
1680 						state->inception, exp,
1681 						state->check_ksk,
1682 						state->keyset_kskonly));
1683 					sigs++;
1684 				}
1685 			skip:
1686 				/* Skip any other updates to the same RRset. */
1687 				while (t != NULL &&
1688 				       dns_name_equal(&t->name, name) &&
1689 				       t->rdata.type == type) {
1690 					next = ISC_LIST_NEXT(t, link);
1691 					ISC_LIST_UNLINK(diff->tuples, t, link);
1692 					ISC_LIST_APPEND(state->work.tuples, t,
1693 							link);
1694 					t = next;
1695 				}
1696 			}
1697 			if (state != &mystate && sigs > maxsigs) {
1698 				return (DNS_R_CONTINUE);
1699 			}
1700 		}
1701 		ISC_LIST_APPENDLIST(diff->tuples, state->work.tuples, link);
1702 
1703 		update_log(log, zone, ISC_LOG_DEBUG(3),
1704 			   "updated data signatures");
1705 	/* FALLTHROUGH */
1706 	case remove_orphaned:
1707 		state->state = remove_orphaned;
1708 
1709 		/* Remove orphaned NSECs and RRSIG NSECs. */
1710 		for (t = ISC_LIST_HEAD(state->diffnames.tuples); t != NULL;
1711 		     t = ISC_LIST_NEXT(t, link))
1712 		{
1713 			CHECK(non_nsec_rrset_exists(db, newver, &t->name,
1714 						    &flag));
1715 			if (!flag) {
1716 				CHECK(delete_if(true_p, db, newver, &t->name,
1717 						dns_rdatatype_any, 0, NULL,
1718 						&state->sig_diff));
1719 			}
1720 		}
1721 		update_log(log, zone, ISC_LOG_DEBUG(3),
1722 			   "removed any orphaned NSEC records");
1723 
1724 		/*
1725 		 * See if we need to build NSEC or NSEC3 chains.
1726 		 */
1727 		CHECK(dns_private_chains(db, newver, privatetype, &build_nsec,
1728 					 &state->build_nsec3));
1729 		if (!build_nsec) {
1730 			state->state = update_nsec3;
1731 			goto next_state;
1732 		}
1733 
1734 		update_log(log, zone, ISC_LOG_DEBUG(3),
1735 			   "rebuilding NSEC chain");
1736 
1737 	/* FALLTHROUGH */
1738 	case build_chain:
1739 		state->state = build_chain;
1740 		/*
1741 		 * When a name is created or deleted, its predecessor needs to
1742 		 * have its NSEC updated.
1743 		 */
1744 		for (t = ISC_LIST_HEAD(state->diffnames.tuples); t != NULL;
1745 		     t = ISC_LIST_NEXT(t, link))
1746 		{
1747 			bool existed, exists;
1748 			dns_fixedname_t fixedname;
1749 			dns_name_t *prevname;
1750 
1751 			prevname = dns_fixedname_initname(&fixedname);
1752 
1753 			if (oldver != NULL) {
1754 				CHECK(name_exists(db, oldver, &t->name,
1755 						  &existed));
1756 			} else {
1757 				existed = false;
1758 			}
1759 			CHECK(name_exists(db, newver, &t->name, &exists));
1760 			if (exists == existed) {
1761 				continue;
1762 			}
1763 
1764 			/*
1765 			 * Find the predecessor.
1766 			 * When names become obscured or unobscured in this
1767 			 * update transaction, we may find the wrong
1768 			 * predecessor because the NSECs have not yet been
1769 			 * updated to reflect the delegation change.  This
1770 			 * should not matter because in this case, the correct
1771 			 * predecessor is either the delegation node or a
1772 			 * newly unobscured node, and those nodes are on the
1773 			 * "affected" list in any case.
1774 			 */
1775 			CHECK(next_active(log, zone, db, newver, &t->name,
1776 					  prevname, false));
1777 			CHECK(namelist_append_name(&state->affected, prevname));
1778 		}
1779 
1780 		/*
1781 		 * Find names potentially affected by delegation changes
1782 		 * (obscured by adding an NS or DNAME, or unobscured by
1783 		 * removing one).
1784 		 */
1785 		for (t = ISC_LIST_HEAD(state->diffnames.tuples); t != NULL;
1786 		     t = ISC_LIST_NEXT(t, link))
1787 		{
1788 			bool ns_existed, dname_existed;
1789 			bool ns_exists, dname_exists;
1790 
1791 			if (oldver != NULL) {
1792 				CHECK(rrset_exists(db, oldver, &t->name,
1793 						   dns_rdatatype_ns, 0,
1794 						   &ns_existed));
1795 			} else {
1796 				ns_existed = false;
1797 			}
1798 			if (oldver != NULL) {
1799 				CHECK(rrset_exists(db, oldver, &t->name,
1800 						   dns_rdatatype_dname, 0,
1801 						   &dname_existed));
1802 			} else {
1803 				dname_existed = false;
1804 			}
1805 			CHECK(rrset_exists(db, newver, &t->name,
1806 					   dns_rdatatype_ns, 0, &ns_exists));
1807 			CHECK(rrset_exists(db, newver, &t->name,
1808 					   dns_rdatatype_dname, 0,
1809 					   &dname_exists));
1810 			if ((ns_exists || dname_exists) ==
1811 			    (ns_existed || dname_existed)) {
1812 				continue;
1813 			}
1814 			/*
1815 			 * There was a delegation change.  Mark all subdomains
1816 			 * of t->name as potentially needing a NSEC update.
1817 			 */
1818 			CHECK(namelist_append_subdomain(db, &t->name,
1819 							&state->affected));
1820 		}
1821 		ISC_LIST_APPENDLIST(state->affected.tuples,
1822 				    state->diffnames.tuples, link);
1823 		INSIST(ISC_LIST_EMPTY(state->diffnames.tuples));
1824 
1825 		CHECK(uniqify_name_list(&state->affected));
1826 
1827 	/* FALLTHROUGH */
1828 	case process_nsec:
1829 		state->state = process_nsec;
1830 
1831 		/*
1832 		 * Determine which names should have NSECs, and delete/create
1833 		 * NSECs to make it so.  We don't know the final NSEC targets
1834 		 * yet, so we just create placeholder NSECs with arbitrary
1835 		 * contents to indicate that their respective owner names
1836 		 * should be part of the NSEC chain.
1837 		 */
1838 		while ((t = ISC_LIST_HEAD(state->affected.tuples)) != NULL) {
1839 			bool exists;
1840 			dns_name_t *name = &t->name;
1841 
1842 			CHECK(name_exists(db, newver, name, &exists));
1843 			if (!exists) {
1844 				goto unlink;
1845 			}
1846 			CHECK(is_active(db, newver, name, &flag, &cut, NULL));
1847 			if (!flag) {
1848 				/*
1849 				 * This name is obscured.  Delete any
1850 				 * existing NSEC record.
1851 				 */
1852 				CHECK(delete_if(true_p, db, newver, name,
1853 						dns_rdatatype_nsec, 0, NULL,
1854 						&state->nsec_diff));
1855 				CHECK(delete_if(rrsig_p, db, newver, name,
1856 						dns_rdatatype_any, 0, NULL,
1857 						diff));
1858 			} else {
1859 				/*
1860 				 * This name is not obscured.  It needs to have
1861 				 * a NSEC unless it is the at the origin, in
1862 				 * which case it should already exist if there
1863 				 * is a complete NSEC chain and if there isn't
1864 				 * a complete NSEC chain we don't want to add
1865 				 * one as that would signal that there is a
1866 				 * complete NSEC chain.
1867 				 */
1868 				if (!dns_name_equal(name, dns_db_origin(db))) {
1869 					CHECK(rrset_exists(db, newver, name,
1870 							   dns_rdatatype_nsec,
1871 							   0, &flag));
1872 					if (!flag) {
1873 						CHECK(add_placeholder_nsec(
1874 							db, newver, name,
1875 							diff));
1876 					}
1877 				}
1878 				CHECK(add_exposed_sigs(
1879 					log, zone, db, newver, name, cut,
1880 					&state->sig_diff, state->zone_keys,
1881 					state->nkeys, state->inception,
1882 					state->expire, state->check_ksk,
1883 					state->keyset_kskonly, &sigs));
1884 			}
1885 		unlink:
1886 			ISC_LIST_UNLINK(state->affected.tuples, t, link);
1887 			ISC_LIST_APPEND(state->work.tuples, t, link);
1888 			if (state != &mystate && sigs > maxsigs) {
1889 				return (DNS_R_CONTINUE);
1890 			}
1891 		}
1892 		ISC_LIST_APPENDLIST(state->affected.tuples, state->work.tuples,
1893 				    link);
1894 
1895 		/*
1896 		 * Now we know which names are part of the NSEC chain.
1897 		 * Make them all point at their correct targets.
1898 		 */
1899 		for (t = ISC_LIST_HEAD(state->affected.tuples); t != NULL;
1900 		     t = ISC_LIST_NEXT(t, link))
1901 		{
1902 			CHECK(rrset_exists(db, newver, &t->name,
1903 					   dns_rdatatype_nsec, 0, &flag));
1904 			if (flag) {
1905 				/*
1906 				 * There is a NSEC, but we don't know if it
1907 				 * is correct. Delete it and create a correct
1908 				 * one to be sure. If the update was
1909 				 * unnecessary, the diff minimization
1910 				 * will take care of eliminating it from the
1911 				 * journal, IXFRs, etc.
1912 				 *
1913 				 * The RRSIG bit should always be set in the
1914 				 * NSECs we generate, because they will all
1915 				 * get RRSIG NSECs.
1916 				 * (XXX what if the zone keys are missing?).
1917 				 * Because the RRSIG NSECs have not necessarily
1918 				 * been created yet, the correctness of the
1919 				 * bit mask relies on the assumption that NSECs
1920 				 * are only created if there is other data, and
1921 				 * if there is other data, there are other
1922 				 * RRSIGs.
1923 				 */
1924 				CHECK(add_nsec(log, zone, db, newver, &t->name,
1925 					       state->nsecttl,
1926 					       &state->nsec_diff));
1927 			}
1928 		}
1929 
1930 		/*
1931 		 * Minimize the set of NSEC updates so that we don't
1932 		 * have to regenerate the RRSIG NSECs for NSECs that were
1933 		 * replaced with identical ones.
1934 		 */
1935 		while ((t = ISC_LIST_HEAD(state->nsec_diff.tuples)) != NULL) {
1936 			ISC_LIST_UNLINK(state->nsec_diff.tuples, t, link);
1937 			dns_diff_appendminimal(&state->nsec_mindiff, &t);
1938 		}
1939 
1940 		update_log(log, zone, ISC_LOG_DEBUG(3),
1941 			   "signing rebuilt NSEC chain");
1942 
1943 	/* FALLTHROUGH */
1944 	case sign_nsec:
1945 		state->state = sign_nsec;
1946 		/* Update RRSIG NSECs. */
1947 		while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
1948 		{
1949 			if (t->op == DNS_DIFFOP_DEL) {
1950 				CHECK(delete_if(true_p, db, newver, &t->name,
1951 						dns_rdatatype_rrsig,
1952 						dns_rdatatype_nsec, NULL,
1953 						&state->sig_diff));
1954 			} else if (t->op == DNS_DIFFOP_ADD) {
1955 				CHECK(add_sigs(log, zone, db, newver, &t->name,
1956 					       dns_rdatatype_nsec,
1957 					       &state->sig_diff,
1958 					       state->zone_keys, state->nkeys,
1959 					       state->inception, state->expire,
1960 					       state->check_ksk,
1961 					       state->keyset_kskonly));
1962 				sigs++;
1963 			} else {
1964 				INSIST(0);
1965 				ISC_UNREACHABLE();
1966 			}
1967 			ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
1968 			ISC_LIST_APPEND(state->work.tuples, t, link);
1969 			if (state != &mystate && sigs > maxsigs) {
1970 				return (DNS_R_CONTINUE);
1971 			}
1972 		}
1973 		ISC_LIST_APPENDLIST(state->nsec_mindiff.tuples,
1974 				    state->work.tuples, link);
1975 	/* FALLTHROUGH */
1976 	case update_nsec3:
1977 		state->state = update_nsec3;
1978 
1979 		/* Record our changes for the journal. */
1980 		while ((t = ISC_LIST_HEAD(state->sig_diff.tuples)) != NULL) {
1981 			ISC_LIST_UNLINK(state->sig_diff.tuples, t, link);
1982 			dns_diff_appendminimal(diff, &t);
1983 		}
1984 		while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
1985 		{
1986 			ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
1987 			dns_diff_appendminimal(diff, &t);
1988 		}
1989 
1990 		INSIST(ISC_LIST_EMPTY(state->sig_diff.tuples));
1991 		INSIST(ISC_LIST_EMPTY(state->nsec_diff.tuples));
1992 		INSIST(ISC_LIST_EMPTY(state->nsec_mindiff.tuples));
1993 
1994 		if (!state->build_nsec3) {
1995 			update_log(log, zone, ISC_LOG_DEBUG(3),
1996 				   "no NSEC3 chains to rebuild");
1997 			goto failure;
1998 		}
1999 
2000 		update_log(log, zone, ISC_LOG_DEBUG(3),
2001 			   "rebuilding NSEC3 chains");
2002 
2003 		dns_diff_clear(&state->diffnames);
2004 		dns_diff_clear(&state->affected);
2005 
2006 		CHECK(dns_diff_sort(diff, temp_order));
2007 
2008 		/*
2009 		 * Find names potentially affected by delegation changes
2010 		 * (obscured by adding an NS or DNAME, or unobscured by
2011 		 * removing one).
2012 		 */
2013 		t = ISC_LIST_HEAD(diff->tuples);
2014 		while (t != NULL) {
2015 			dns_name_t *name = &t->name;
2016 
2017 			bool ns_existed, dname_existed;
2018 			bool ns_exists, dname_exists;
2019 			bool exists, existed;
2020 
2021 			if (t->rdata.type == dns_rdatatype_nsec ||
2022 			    t->rdata.type == dns_rdatatype_rrsig) {
2023 				t = ISC_LIST_NEXT(t, link);
2024 				continue;
2025 			}
2026 
2027 			CHECK(namelist_append_name(&state->affected, name));
2028 
2029 			if (oldver != NULL) {
2030 				CHECK(rrset_exists(db, oldver, name,
2031 						   dns_rdatatype_ns, 0,
2032 						   &ns_existed));
2033 			} else {
2034 				ns_existed = false;
2035 			}
2036 			if (oldver != NULL) {
2037 				CHECK(rrset_exists(db, oldver, name,
2038 						   dns_rdatatype_dname, 0,
2039 						   &dname_existed));
2040 			} else {
2041 				dname_existed = false;
2042 			}
2043 			CHECK(rrset_exists(db, newver, name, dns_rdatatype_ns,
2044 					   0, &ns_exists));
2045 			CHECK(rrset_exists(db, newver, name,
2046 					   dns_rdatatype_dname, 0,
2047 					   &dname_exists));
2048 
2049 			exists = ns_exists || dname_exists;
2050 			existed = ns_existed || dname_existed;
2051 			if (exists == existed) {
2052 				goto nextname;
2053 			}
2054 			/*
2055 			 * There was a delegation change.  Mark all subdomains
2056 			 * of t->name as potentially needing a NSEC3 update.
2057 			 */
2058 			CHECK(namelist_append_subdomain(db, name,
2059 							&state->affected));
2060 
2061 		nextname:
2062 			while (t != NULL && dns_name_equal(&t->name, name)) {
2063 				t = ISC_LIST_NEXT(t, link);
2064 			}
2065 		}
2066 
2067 	/* FALLTHROUGH */
2068 	case process_nsec3:
2069 		state->state = process_nsec3;
2070 		while ((t = ISC_LIST_HEAD(state->affected.tuples)) != NULL) {
2071 			dns_name_t *name = &t->name;
2072 
2073 			unsecure = false; /* Silence compiler warning. */
2074 			CHECK(is_active(db, newver, name, &flag, &cut,
2075 					&unsecure));
2076 
2077 			if (!flag) {
2078 				CHECK(delete_if(rrsig_p, db, newver, name,
2079 						dns_rdatatype_any, 0, NULL,
2080 						diff));
2081 				CHECK(dns_nsec3_delnsec3sx(db, newver, name,
2082 							   privatetype,
2083 							   &state->nsec_diff));
2084 			} else {
2085 				CHECK(add_exposed_sigs(
2086 					log, zone, db, newver, name, cut,
2087 					&state->sig_diff, state->zone_keys,
2088 					state->nkeys, state->inception,
2089 					state->expire, state->check_ksk,
2090 					state->keyset_kskonly, &sigs));
2091 				CHECK(dns_nsec3_addnsec3sx(
2092 					db, newver, name, state->nsecttl,
2093 					unsecure, privatetype,
2094 					&state->nsec_diff));
2095 			}
2096 			ISC_LIST_UNLINK(state->affected.tuples, t, link);
2097 			ISC_LIST_APPEND(state->work.tuples, t, link);
2098 			if (state != &mystate && sigs > maxsigs) {
2099 				return (DNS_R_CONTINUE);
2100 			}
2101 		}
2102 		ISC_LIST_APPENDLIST(state->affected.tuples, state->work.tuples,
2103 				    link);
2104 
2105 		/*
2106 		 * Minimize the set of NSEC3 updates so that we don't
2107 		 * have to regenerate the RRSIG NSEC3s for NSEC3s that were
2108 		 * replaced with identical ones.
2109 		 */
2110 		while ((t = ISC_LIST_HEAD(state->nsec_diff.tuples)) != NULL) {
2111 			ISC_LIST_UNLINK(state->nsec_diff.tuples, t, link);
2112 			dns_diff_appendminimal(&state->nsec_mindiff, &t);
2113 		}
2114 
2115 		update_log(log, zone, ISC_LOG_DEBUG(3),
2116 			   "signing rebuilt NSEC3 chain");
2117 
2118 	/* FALLTHROUGH */
2119 	case sign_nsec3:
2120 		state->state = sign_nsec3;
2121 		/* Update RRSIG NSEC3s. */
2122 		while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
2123 		{
2124 			if (t->op == DNS_DIFFOP_DEL) {
2125 				CHECK(delete_if(true_p, db, newver, &t->name,
2126 						dns_rdatatype_rrsig,
2127 						dns_rdatatype_nsec3, NULL,
2128 						&state->sig_diff));
2129 			} else if (t->op == DNS_DIFFOP_ADD) {
2130 				CHECK(add_sigs(log, zone, db, newver, &t->name,
2131 					       dns_rdatatype_nsec3,
2132 					       &state->sig_diff,
2133 					       state->zone_keys, state->nkeys,
2134 					       state->inception, state->expire,
2135 					       state->check_ksk,
2136 					       state->keyset_kskonly));
2137 				sigs++;
2138 			} else {
2139 				INSIST(0);
2140 				ISC_UNREACHABLE();
2141 			}
2142 			ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
2143 			ISC_LIST_APPEND(state->work.tuples, t, link);
2144 			if (state != &mystate && sigs > maxsigs) {
2145 				return (DNS_R_CONTINUE);
2146 			}
2147 		}
2148 		ISC_LIST_APPENDLIST(state->nsec_mindiff.tuples,
2149 				    state->work.tuples, link);
2150 
2151 		/* Record our changes for the journal. */
2152 		while ((t = ISC_LIST_HEAD(state->sig_diff.tuples)) != NULL) {
2153 			ISC_LIST_UNLINK(state->sig_diff.tuples, t, link);
2154 			dns_diff_appendminimal(diff, &t);
2155 		}
2156 		while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
2157 		{
2158 			ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
2159 			dns_diff_appendminimal(diff, &t);
2160 		}
2161 
2162 		INSIST(ISC_LIST_EMPTY(state->sig_diff.tuples));
2163 		INSIST(ISC_LIST_EMPTY(state->nsec_diff.tuples));
2164 		INSIST(ISC_LIST_EMPTY(state->nsec_mindiff.tuples));
2165 		break;
2166 	default:
2167 		INSIST(0);
2168 		ISC_UNREACHABLE();
2169 	}
2170 
2171 failure:
2172 	if (node != NULL) {
2173 		dns_db_detachnode(db, &node);
2174 	}
2175 
2176 	dns_diff_clear(&state->sig_diff);
2177 	dns_diff_clear(&state->nsec_diff);
2178 	dns_diff_clear(&state->nsec_mindiff);
2179 
2180 	dns_diff_clear(&state->affected);
2181 	dns_diff_clear(&state->diffnames);
2182 	dns_diff_clear(&state->work);
2183 
2184 	for (i = 0; i < state->nkeys; i++) {
2185 		dst_key_free(&state->zone_keys[i]);
2186 	}
2187 
2188 	if (state != &mystate && state != NULL) {
2189 		*statep = NULL;
2190 		state->magic = 0;
2191 		isc_mem_put(diff->mctx, state, sizeof(*state));
2192 	}
2193 
2194 	return (result);
2195 }
2196 
2197 static isc_stdtime_t
2198 epoch_to_yyyymmdd(time_t when) {
2199 	struct tm t, *tm = localtime_r(&when, &t);
2200 	if (tm == NULL) {
2201 		return (0);
2202 	}
2203 	return (((tm->tm_year + 1900) * 10000) + ((tm->tm_mon + 1) * 100) +
2204 		tm->tm_mday);
2205 }
2206 
2207 uint32_t
2208 dns_update_soaserial(uint32_t serial, dns_updatemethod_t method) {
2209 	isc_stdtime_t now;
2210 	uint32_t new_serial;
2211 
2212 	switch (method) {
2213 	case dns_updatemethod_none:
2214 		return (serial);
2215 	case dns_updatemethod_unixtime:
2216 		isc_stdtime_get(&now);
2217 		if (now != 0 && isc_serial_gt(now, serial)) {
2218 			return (now);
2219 		}
2220 		break;
2221 	case dns_updatemethod_date:
2222 		isc_stdtime_get(&now);
2223 		new_serial = epoch_to_yyyymmdd((time_t)now) * 100;
2224 		if (new_serial != 0 && isc_serial_gt(new_serial, serial)) {
2225 			return (new_serial);
2226 		}
2227 	case dns_updatemethod_increment:
2228 		break;
2229 	}
2230 
2231 	/* RFC1982 */
2232 	serial = (serial + 1) & 0xFFFFFFFF;
2233 	if (serial == 0) {
2234 		serial = 1;
2235 	}
2236 
2237 	return (serial);
2238 }
2239