2 * Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
22 #include <isc/netaddr.h>
23 #include <isc/print.h>
24 #include <isc/serial.h>
25 #include <isc/stats.h>
26 #include <isc/stdtime.h>
27 #include <isc/string.h>
28 #include <isc/taskpool.h>
32 #include <dns/dbiterator.h>
34 #include <dns/dnssec.h>
35 #include <dns/events.h>
36 #include <dns/fixedname.h>
37 #include <dns/journal.h>
38 #include <dns/keyvalues.h>
40 #include <dns/message.h>
42 #include <dns/nsec3.h>
43 #include <dns/private.h>
44 #include <dns/rdataclass.h>
45 #include <dns/rdataset.h>
46 #include <dns/rdatasetiter.h>
47 #include <dns/rdatastruct.h>
48 #include <dns/rdatatype.h>
49 #include <dns/result.h>
53 #include <dns/update.h>
59 /**************************************************************************/
62 * Log level for tracing dynamic update protocol requests.
64 #define LOGLEVEL_PROTOCOL ISC_LOG_INFO
67 * Log level for low-level debug tracing.
69 #define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8)
72 * Check an operation for failure. These macros all assume that
73 * the function using them has a 'result' variable and a 'failure'
78 if (result != ISC_R_SUCCESS) goto failure; \
82 * Fail unconditionally with result 'code', which must not
83 * be ISC_R_SUCCESS. The reason for failure presumably has
84 * been logged already.
86 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
87 * from complaining about "end-of-loop code not reached".
93 if (result != ISC_R_SUCCESS) goto failure; \
97 * Fail unconditionally and log as a client error.
98 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
99 * from complaining about "end-of-loop code not reached".
101 #define FAILC(code, msg) \
103 const char *_what = "failed"; \
106 case DNS_R_NXDOMAIN: \
107 case DNS_R_YXDOMAIN: \
108 case DNS_R_YXRRSET: \
109 case DNS_R_NXRRSET: \
110 _what = "unsuccessful"; \
112 update_log(log, zone, LOGLEVEL_PROTOCOL, \
113 "update %s: %s (%s)", _what, \
114 msg, isc_result_totext(result)); \
115 if (result != ISC_R_SUCCESS) goto failure; \
118 #define FAILN(code, name, msg) \
120 const char *_what = "failed"; \
123 case DNS_R_NXDOMAIN: \
124 case DNS_R_YXDOMAIN: \
125 case DNS_R_YXRRSET: \
126 case DNS_R_NXRRSET: \
127 _what = "unsuccessful"; \
129 if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) { \
130 char _nbuf[DNS_NAME_FORMATSIZE]; \
131 dns_name_format(name, _nbuf, sizeof(_nbuf)); \
132 update_log(log, zone, LOGLEVEL_PROTOCOL, \
133 "update %s: %s: %s (%s)", _what, _nbuf, \
134 msg, isc_result_totext(result)); \
136 if (result != ISC_R_SUCCESS) goto failure; \
139 #define FAILNT(code, name, type, msg) \
141 const char *_what = "failed"; \
144 case DNS_R_NXDOMAIN: \
145 case DNS_R_YXDOMAIN: \
146 case DNS_R_YXRRSET: \
147 case DNS_R_NXRRSET: \
148 _what = "unsuccessful"; \
150 if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) { \
151 char _nbuf[DNS_NAME_FORMATSIZE]; \
152 char _tbuf[DNS_RDATATYPE_FORMATSIZE]; \
153 dns_name_format(name, _nbuf, sizeof(_nbuf)); \
154 dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \
155 update_log(log, zone, LOGLEVEL_PROTOCOL, \
156 "update %s: %s/%s: %s (%s)", \
157 _what, _nbuf, _tbuf, msg, \
158 isc_result_totext(result)); \
160 if (result != ISC_R_SUCCESS) goto failure; \
164 * Fail unconditionally and log as a server error.
165 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
166 * from complaining about "end-of-loop code not reached".
168 #define FAILS(code, msg) \
171 update_log(log, zone, LOGLEVEL_PROTOCOL, \
173 msg, isc_result_totext(result)); \
174 if (result != ISC_R_SUCCESS) goto failure; \
177 /**************************************************************************/
179 typedef struct rr rr_t;
182 /* dns_name_t name; */
187 typedef struct update_event update_event_t;
189 /**************************************************************************/
192 update_log(dns_update_log_t *callback, dns_zone_t *zone,
193 int level, const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
196 update_log(dns_update_log_t *callback, dns_zone_t *zone,
197 int level, const char *fmt, ...)
202 if (callback == NULL)
205 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
210 vsnprintf(message, sizeof(message), fmt, ap);
213 (callback->func)(callback->arg, zone, level, message);
217 * Update a single RR in version 'ver' of 'db' and log the
221 * \li '*tuple' == NULL. Either the tuple is freed, or its
222 * ownership has been transferred to the diff.
225 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
228 dns_diff_t temp_diff;
232 * Create a singleton diff.
234 dns_diff_init(diff->mctx, &temp_diff);
235 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
238 * Apply it to the database.
240 result = dns_diff_apply(&temp_diff, db, ver);
241 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
242 if (result != ISC_R_SUCCESS) {
243 dns_difftuple_free(tuple);
248 * Merge it into the current pending journal entry.
250 dns_diff_appendminimal(diff, tuple);
253 * Do not clear temp_diff.
255 return (ISC_R_SUCCESS);
259 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
260 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
263 dns_difftuple_t *tuple = NULL;
265 result = dns_difftuple_create(diff->mctx, op,
266 name, ttl, rdata, &tuple);
267 if (result != ISC_R_SUCCESS)
269 return (do_one_tuple(&tuple, db, ver, diff));
272 /**************************************************************************/
274 * Callback-style iteration over rdatasets and rdatas.
276 * foreach_rrset() can be used to iterate over the RRsets
277 * of a name and call a callback function with each
278 * one. Similarly, foreach_rr() can be used to iterate
279 * over the individual RRs at name, optionally restricted
280 * to RRs of a given type.
282 * The callback functions are called "actions" and take
283 * two arguments: a void pointer for passing arbitrary
284 * context information, and a pointer to the current RRset
285 * or RR. By convention, their names end in "_action".
289 * XXXRTH We might want to make this public somewhere in libdns.
293 * Function type for foreach_rrset() iterator actions.
295 typedef isc_result_t rrset_func(void *data, dns_rdataset_t *rrset);
298 * Function type for foreach_rr() iterator actions.
300 typedef isc_result_t rr_func(void *data, rr_t *rr);
303 * Internal context struct for foreach_node_rr().
307 void * rr_action_data;
308 } foreach_node_rr_ctx_t;
311 * Internal helper function for foreach_node_rr().
314 foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) {
316 foreach_node_rr_ctx_t *ctx = data;
317 for (result = dns_rdataset_first(rdataset);
318 result == ISC_R_SUCCESS;
319 result = dns_rdataset_next(rdataset))
321 rr_t rr = { 0, DNS_RDATA_INIT };
323 dns_rdataset_current(rdataset, &rr.rdata);
324 rr.ttl = rdataset->ttl;
325 result = (*ctx->rr_action)(ctx->rr_action_data, &rr);
326 if (result != ISC_R_SUCCESS)
329 if (result != ISC_R_NOMORE)
331 return (ISC_R_SUCCESS);
335 * For each rdataset of 'name' in 'ver' of 'db', call 'action'
336 * with the rdataset and 'action_data' as arguments. If the name
337 * does not exist, do nothing.
339 * If 'action' returns an error, abort iteration and return the error.
342 foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
343 rrset_func *action, void *action_data)
347 dns_rdatasetiter_t *iter;
350 result = dns_db_findnode(db, name, ISC_FALSE, &node);
351 if (result == ISC_R_NOTFOUND)
352 return (ISC_R_SUCCESS);
353 if (result != ISC_R_SUCCESS)
357 result = dns_db_allrdatasets(db, node, ver,
358 (isc_stdtime_t) 0, &iter);
359 if (result != ISC_R_SUCCESS)
362 for (result = dns_rdatasetiter_first(iter);
363 result == ISC_R_SUCCESS;
364 result = dns_rdatasetiter_next(iter))
366 dns_rdataset_t rdataset;
368 dns_rdataset_init(&rdataset);
369 dns_rdatasetiter_current(iter, &rdataset);
371 result = (*action)(action_data, &rdataset);
373 dns_rdataset_disassociate(&rdataset);
374 if (result != ISC_R_SUCCESS)
375 goto cleanup_iterator;
377 if (result == ISC_R_NOMORE)
378 result = ISC_R_SUCCESS;
381 dns_rdatasetiter_destroy(&iter);
384 dns_db_detachnode(db, &node);
390 * For each RR of 'name' in 'ver' of 'db', call 'action'
391 * with the RR and 'action_data' as arguments. If the name
392 * does not exist, do nothing.
394 * If 'action' returns an error, abort iteration
395 * and return the error.
398 foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
399 rr_func *rr_action, void *rr_action_data)
401 foreach_node_rr_ctx_t ctx;
402 ctx.rr_action = rr_action;
403 ctx.rr_action_data = rr_action_data;
404 return (foreach_rrset(db, ver, name,
405 foreach_node_rr_action, &ctx));
410 * For each of the RRs specified by 'db', 'ver', 'name', 'type',
411 * (which can be dns_rdatatype_any to match any type), and 'covers', call
412 * 'action' with the RR and 'action_data' as arguments. If the name
413 * does not exist, or if no RRset of the given type exists at the name,
416 * If 'action' returns an error, abort iteration and return the error.
419 foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
420 dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action,
421 void *rr_action_data)
426 dns_rdataset_t rdataset;
428 if (type == dns_rdatatype_any)
429 return (foreach_node_rr(db, ver, name,
430 rr_action, rr_action_data));
433 if (type == dns_rdatatype_nsec3 ||
434 (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3))
435 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
437 result = dns_db_findnode(db, name, ISC_FALSE, &node);
438 if (result == ISC_R_NOTFOUND)
439 return (ISC_R_SUCCESS);
440 if (result != ISC_R_SUCCESS)
443 dns_rdataset_init(&rdataset);
444 result = dns_db_findrdataset(db, node, ver, type, covers,
445 (isc_stdtime_t) 0, &rdataset, NULL);
446 if (result == ISC_R_NOTFOUND) {
447 result = ISC_R_SUCCESS;
450 if (result != ISC_R_SUCCESS)
453 for (result = dns_rdataset_first(&rdataset);
454 result == ISC_R_SUCCESS;
455 result = dns_rdataset_next(&rdataset))
457 rr_t rr = { 0, DNS_RDATA_INIT };
458 dns_rdataset_current(&rdataset, &rr.rdata);
459 rr.ttl = rdataset.ttl;
460 result = (*rr_action)(rr_action_data, &rr);
461 if (result != ISC_R_SUCCESS)
462 goto cleanup_rdataset;
464 if (result != ISC_R_NOMORE)
465 goto cleanup_rdataset;
466 result = ISC_R_SUCCESS;
469 dns_rdataset_disassociate(&rdataset);
471 dns_db_detachnode(db, &node);
476 /**************************************************************************/
478 * Various tests on the database contents (for prerequisites, etc).
482 * Function type for predicate functions that compare a database RR 'db_rr'
483 * against an update RR 'update_rr'.
485 typedef isc_boolean_t rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr);
488 * Helper function for rrset_exists().
491 rrset_exists_action(void *data, rr_t *rr) {
494 return (ISC_R_EXISTS);
498 * Utility macro for RR existence checking functions.
500 * If the variable 'result' has the value ISC_R_EXISTS or
501 * ISC_R_SUCCESS, set *exists to ISC_TRUE or ISC_FALSE,
502 * respectively, and return success.
504 * If 'result' has any other value, there was a failure.
505 * Return the failure result code and do not set *exists.
507 * This would be more readable as "do { if ... } while(0)",
508 * but that form generates tons of warnings on Solaris 2.6.
510 #define RETURN_EXISTENCE_FLAG \
511 return ((result == ISC_R_EXISTS) ? \
512 (*exists = ISC_TRUE, ISC_R_SUCCESS) : \
513 ((result == ISC_R_SUCCESS) ? \
514 (*exists = ISC_FALSE, ISC_R_SUCCESS) : \
518 * Set '*exists' to true iff an rrset of the given type exists,
519 * to false otherwise.
522 rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
523 dns_rdatatype_t type, dns_rdatatype_t covers,
524 isc_boolean_t *exists)
527 result = foreach_rr(db, ver, name, type, covers,
528 rrset_exists_action, NULL);
529 RETURN_EXISTENCE_FLAG;
533 * Set '*visible' to true if the RRset exists and is part of the
534 * visible zone. Otherwise '*visible' is set to false unless a
538 rrset_visible(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
539 dns_rdatatype_t type, isc_boolean_t *visible)
542 dns_fixedname_t fixed;
544 dns_fixedname_init(&fixed);
545 result = dns_db_find(db, name, ver, type, DNS_DBFIND_NOWILD,
546 (isc_stdtime_t) 0, NULL,
547 dns_fixedname_name(&fixed), NULL, NULL);
553 * Glue, obscured, deleted or replaced records.
555 case DNS_R_DELEGATION:
560 case DNS_R_EMPTYNAME:
561 case DNS_R_COVERINGNSEC:
562 *visible = ISC_FALSE;
563 result = ISC_R_SUCCESS;
572 * Context struct and helper function for name_exists().
576 name_exists_action(void *data, dns_rdataset_t *rrset) {
579 return (ISC_R_EXISTS);
583 * Set '*exists' to true iff the given name exists, to false otherwise.
586 name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
587 isc_boolean_t *exists)
590 result = foreach_rrset(db, ver, name,
591 name_exists_action, NULL);
592 RETURN_EXISTENCE_FLAG;
595 /**************************************************************************/
597 * Checking of "RRset exists (value dependent)" prerequisites.
599 * In the RFC2136 section 3.2.5, this is the pseudocode involving
600 * a variable called "temp", a mapping of <name, type> tuples to rrsets.
602 * Here, we represent the "temp" data structure as (non-minimal) "dns_diff_t"
603 * where each tuple has op==DNS_DIFFOP_EXISTS.
607 * A comparison function defining the sorting order for the entries
608 * in the "temp" data structure. The major sort key is the owner name,
609 * followed by the type and rdata.
612 temp_order(const void *av, const void *bv) {
613 dns_difftuple_t const * const *ap = av;
614 dns_difftuple_t const * const *bp = bv;
615 dns_difftuple_t const *a = *ap;
616 dns_difftuple_t const *b = *bp;
618 r = dns_name_compare(&a->name, &b->name);
621 r = (b->rdata.type - a->rdata.type);
624 r = dns_rdata_casecompare(&a->rdata, &b->rdata);
628 /**************************************************************************/
630 * Conditional deletion of RRs.
634 * Context structure for delete_if().
638 rr_predicate *predicate;
640 dns_dbversion_t *ver;
643 dns_rdata_t *update_rr;
644 } conditional_delete_ctx_t;
647 * Predicate functions for delete_if().
651 * Return true always.
654 true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
661 * Return true if the record is a RRSIG.
664 rrsig_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
666 return ((db_rr->type == dns_rdatatype_rrsig) ?
667 ISC_TRUE : ISC_FALSE);
671 * Internal helper function for delete_if().
674 delete_if_action(void *data, rr_t *rr) {
675 conditional_delete_ctx_t *ctx = data;
676 if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) {
678 result = update_one_rr(ctx->db, ctx->ver, ctx->diff,
679 DNS_DIFFOP_DEL, ctx->name,
680 rr->ttl, &rr->rdata);
683 return (ISC_R_SUCCESS);
688 * Conditionally delete RRs. Apply 'predicate' to the RRs
689 * specified by 'db', 'ver', 'name', and 'type' (which can
690 * be dns_rdatatype_any to match any type). Delete those
691 * RRs for which the predicate returns true, and log the
692 * deletions in 'diff'.
695 delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver,
696 dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers,
697 dns_rdata_t *update_rr, dns_diff_t *diff)
699 conditional_delete_ctx_t ctx;
700 ctx.predicate = predicate;
705 ctx.update_rr = update_rr;
706 return (foreach_rr(db, ver, name, type, covers,
707 delete_if_action, &ctx));
710 /**************************************************************************/
712 * Incremental updating of NSECs and RRSIGs.
716 * We abuse the dns_diff_t type to represent a set of domain names
717 * affected by the update.
720 namelist_append_name(dns_diff_t *list, dns_name_t *name) {
722 dns_difftuple_t *tuple = NULL;
723 static dns_rdata_t dummy_rdata = DNS_RDATA_INIT;
725 CHECK(dns_difftuple_create(list->mctx, DNS_DIFFOP_EXISTS, name, 0,
726 &dummy_rdata, &tuple));
727 dns_diff_append(list, &tuple);
733 namelist_append_subdomain(dns_db_t *db, dns_name_t *name, dns_diff_t *affected)
736 dns_fixedname_t fixedname;
738 dns_dbiterator_t *dbit = NULL;
740 dns_fixedname_init(&fixedname);
741 child = dns_fixedname_name(&fixedname);
743 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
745 for (result = dns_dbiterator_seek(dbit, name);
746 result == ISC_R_SUCCESS;
747 result = dns_dbiterator_next(dbit))
749 dns_dbnode_t *node = NULL;
750 CHECK(dns_dbiterator_current(dbit, &node, child));
751 dns_db_detachnode(db, &node);
752 if (! dns_name_issubdomain(child, name))
754 CHECK(namelist_append_name(affected, child));
756 if (result == ISC_R_NOMORE)
757 result = ISC_R_SUCCESS;
760 dns_dbiterator_destroy(&dbit);
767 * Helper function for non_nsec_rrset_exists().
770 is_non_nsec_action(void *data, dns_rdataset_t *rrset) {
772 if (!(rrset->type == dns_rdatatype_nsec ||
773 rrset->type == dns_rdatatype_nsec3 ||
774 (rrset->type == dns_rdatatype_rrsig &&
775 (rrset->covers == dns_rdatatype_nsec ||
776 rrset->covers == dns_rdatatype_nsec3))))
777 return (ISC_R_EXISTS);
778 return (ISC_R_SUCCESS);
782 * Check whether there is an rrset other than a NSEC or RRSIG NSEC,
783 * i.e., anything that justifies the continued existence of a name
784 * after a secure update.
786 * If such an rrset exists, set '*exists' to ISC_TRUE.
787 * Otherwise, set it to ISC_FALSE.
790 non_nsec_rrset_exists(dns_db_t *db, dns_dbversion_t *ver,
791 dns_name_t *name, isc_boolean_t *exists)
794 result = foreach_rrset(db, ver, name, is_non_nsec_action, NULL);
795 RETURN_EXISTENCE_FLAG;
799 * A comparison function for sorting dns_diff_t:s by name.
802 name_order(const void *av, const void *bv) {
803 dns_difftuple_t const * const *ap = av;
804 dns_difftuple_t const * const *bp = bv;
805 dns_difftuple_t const *a = *ap;
806 dns_difftuple_t const *b = *bp;
807 return (dns_name_compare(&a->name, &b->name));
811 uniqify_name_list(dns_diff_t *list) {
813 dns_difftuple_t *p, *q;
815 CHECK(dns_diff_sort(list, name_order));
817 p = ISC_LIST_HEAD(list->tuples);
820 q = ISC_LIST_NEXT(p, link);
821 if (q == NULL || ! dns_name_equal(&p->name, &q->name))
823 ISC_LIST_UNLINK(list->tuples, q, link);
824 dns_difftuple_free(&q);
826 p = ISC_LIST_NEXT(p, link);
833 is_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
834 isc_boolean_t *flag, isc_boolean_t *cut, isc_boolean_t *unsecure)
837 dns_fixedname_t foundname;
838 dns_fixedname_init(&foundname);
839 result = dns_db_find(db, name, ver, dns_rdatatype_any,
840 DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
841 (isc_stdtime_t) 0, NULL,
842 dns_fixedname_name(&foundname),
844 if (result == ISC_R_SUCCESS || result == DNS_R_EMPTYNAME) {
847 if (unsecure != NULL)
848 *unsecure = ISC_FALSE;
849 return (ISC_R_SUCCESS);
850 } else if (result == DNS_R_ZONECUT) {
853 if (unsecure != NULL) {
855 * We are at the zonecut. Check to see if there
858 if (dns_db_find(db, name, ver, dns_rdatatype_ds, 0,
859 (isc_stdtime_t) 0, NULL,
860 dns_fixedname_name(&foundname),
861 NULL, NULL) == DNS_R_NXRRSET)
862 *unsecure = ISC_TRUE;
864 *unsecure = ISC_FALSE;
866 return (ISC_R_SUCCESS);
867 } else if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
868 result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) {
871 if (unsecure != NULL)
872 *unsecure = ISC_FALSE;
873 return (ISC_R_SUCCESS);
880 if (unsecure != NULL)
881 *unsecure = ISC_FALSE;
887 * Find the next/previous name that has a NSEC record.
888 * In other words, skip empty database nodes and names that
889 * have had their NSECs removed because they are obscured by
893 next_active(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
894 dns_dbversion_t *ver, dns_name_t *oldname, dns_name_t *newname,
895 isc_boolean_t forward)
898 dns_dbiterator_t *dbit = NULL;
899 isc_boolean_t has_nsec = ISC_FALSE;
900 unsigned int wraps = 0;
901 isc_boolean_t secure = dns_db_issecure(db);
903 CHECK(dns_db_createiterator(db, 0, &dbit));
905 CHECK(dns_dbiterator_seek(dbit, oldname));
907 dns_dbnode_t *node = NULL;
910 result = dns_dbiterator_next(dbit);
912 result = dns_dbiterator_prev(dbit);
913 if (result == ISC_R_NOMORE) {
918 CHECK(dns_dbiterator_first(dbit));
920 CHECK(dns_dbiterator_last(dbit));
923 update_log(log, zone, ISC_LOG_ERROR,
924 "secure zone with no NSECs");
925 result = DNS_R_BADZONE;
929 CHECK(dns_dbiterator_current(dbit, &node, newname));
930 dns_db_detachnode(db, &node);
933 * The iterator may hold the tree lock, and
934 * rrset_exists() calls dns_db_findnode() which
935 * may try to reacquire it. To avoid deadlock
936 * we must pause the iterator first.
938 CHECK(dns_dbiterator_pause(dbit));
940 CHECK(rrset_exists(db, ver, newname,
941 dns_rdatatype_nsec, 0, &has_nsec));
943 dns_fixedname_t ffound;
945 dns_fixedname_init(&ffound);
946 found = dns_fixedname_name(&ffound);
947 result = dns_db_find(db, newname, ver,
949 DNS_DBFIND_NOWILD, 0, NULL, found,
951 if (result == ISC_R_SUCCESS ||
952 result == DNS_R_EMPTYNAME ||
953 result == DNS_R_NXRRSET ||
954 result == DNS_R_CNAME ||
955 (result == DNS_R_DELEGATION &&
956 dns_name_equal(newname, found))) {
958 result = ISC_R_SUCCESS;
959 } else if (result != DNS_R_NXDOMAIN)
962 } while (! has_nsec);
965 dns_dbiterator_destroy(&dbit);
971 * Add a NSEC record for "name", recording the change in "diff".
972 * The existing NSEC is removed.
975 add_nsec(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
976 dns_dbversion_t *ver, dns_name_t *name, dns_ttl_t nsecttl,
980 dns_dbnode_t *node = NULL;
981 unsigned char buffer[DNS_NSEC_BUFFERSIZE];
982 dns_rdata_t rdata = DNS_RDATA_INIT;
983 dns_difftuple_t *tuple = NULL;
984 dns_fixedname_t fixedname;
987 dns_fixedname_init(&fixedname);
988 target = dns_fixedname_name(&fixedname);
991 * Find the successor name, aka NSEC target.
993 CHECK(next_active(log, zone, db, ver, name, target, ISC_TRUE));
996 * Create the NSEC RDATA.
998 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
999 dns_rdata_init(&rdata);
1000 CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata));
1001 dns_db_detachnode(db, &node);
1004 * Delete the old NSEC and record the change.
1006 CHECK(delete_if(true_p, db, ver, name, dns_rdatatype_nsec, 0,
1009 * Add the new NSEC and record the change.
1011 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
1012 nsecttl, &rdata, &tuple));
1013 CHECK(do_one_tuple(&tuple, db, ver, diff));
1014 INSIST(tuple == NULL);
1018 dns_db_detachnode(db, &node);
1023 * Add a placeholder NSEC record for "name", recording the change in "diff".
1026 add_placeholder_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
1029 isc_result_t result;
1030 dns_difftuple_t *tuple = NULL;
1032 unsigned char data[1] = { 0 }; /* The root domain, no bits. */
1033 dns_rdata_t rdata = DNS_RDATA_INIT;
1036 r.length = sizeof(data);
1037 dns_rdata_fromregion(&rdata, dns_db_class(db), dns_rdatatype_nsec, &r);
1038 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0,
1040 CHECK(do_one_tuple(&tuple, db, ver, diff));
1046 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
1047 isc_mem_t *mctx, unsigned int maxkeys,
1048 dst_key_t **keys, unsigned int *nkeys)
1050 isc_result_t result;
1051 dns_dbnode_t *node = NULL;
1052 const char *directory = dns_zone_getkeydirectory(zone);
1053 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
1054 CHECK(dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
1055 directory, mctx, maxkeys, keys, nkeys));
1058 dns_db_detachnode(db, &node);
1063 * Add RRSIG records for an RRset, recording the change in "diff".
1066 add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1067 dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type,
1068 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
1069 isc_stdtime_t inception, isc_stdtime_t expire,
1070 isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly)
1072 isc_result_t result;
1073 dns_dbnode_t *node = NULL;
1074 dns_rdataset_t rdataset;
1075 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
1076 isc_buffer_t buffer;
1077 unsigned char data[1024]; /* XXX */
1079 isc_boolean_t added_sig = ISC_FALSE;
1080 isc_mem_t *mctx = diff->mctx;
1082 dns_rdataset_init(&rdataset);
1083 isc_buffer_init(&buffer, data, sizeof(data));
1085 /* Get the rdataset to sign. */
1086 if (type == dns_rdatatype_nsec3)
1087 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
1089 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
1090 CHECK(dns_db_findrdataset(db, node, ver, type, 0,
1091 (isc_stdtime_t) 0, &rdataset, NULL));
1092 dns_db_detachnode(db, &node);
1094 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
1095 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
1096 #define ALG(x) dst_key_alg(x)
1099 * If we are honoring KSK flags then we need to check that we
1100 * have both KSK and non-KSK keys that are not revoked per
1103 for (i = 0; i < nkeys; i++) {
1104 isc_boolean_t both = ISC_FALSE;
1106 if (!dst_key_isprivate(keys[i]))
1109 if (check_ksk && !REVOKE(keys[i])) {
1110 isc_boolean_t have_ksk, have_nonksk;
1112 have_ksk = ISC_TRUE;
1113 have_nonksk = ISC_FALSE;
1115 have_ksk = ISC_FALSE;
1116 have_nonksk = ISC_TRUE;
1118 for (j = 0; j < nkeys; j++) {
1119 if (j == i || ALG(keys[i]) != ALG(keys[j]))
1121 if (REVOKE(keys[j]))
1124 have_ksk = ISC_TRUE;
1126 have_nonksk = ISC_TRUE;
1127 both = have_ksk && have_nonksk;
1134 if (type == dns_rdatatype_dnskey) {
1135 if (!KSK(keys[i]) && keyset_kskonly)
1137 } else if (KSK(keys[i]))
1139 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
1142 /* Calculate the signature, creating a RRSIG RDATA. */
1143 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
1144 &inception, &expire,
1145 mctx, &buffer, &sig_rdata));
1147 /* Update the database and journal with the RRSIG. */
1148 /* XXX inefficient - will cause dataset merging */
1149 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
1150 rdataset.ttl, &sig_rdata));
1151 dns_rdata_reset(&sig_rdata);
1152 isc_buffer_init(&buffer, data, sizeof(data));
1153 added_sig = ISC_TRUE;
1156 update_log(log, zone, ISC_LOG_ERROR,
1157 "found no active private keys, "
1158 "unable to generate any signatures");
1159 result = ISC_R_NOTFOUND;
1163 if (dns_rdataset_isassociated(&rdataset))
1164 dns_rdataset_disassociate(&rdataset);
1166 dns_db_detachnode(db, &node);
1171 * Delete expired RRsigs and any RRsigs we are about to re-sign.
1172 * See also zone.c:del_sigs().
1175 del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
1176 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys)
1178 isc_result_t result;
1179 dns_dbnode_t *node = NULL;
1180 dns_rdataset_t rdataset;
1181 dns_rdata_t rdata = DNS_RDATA_INIT;
1183 dns_rdata_rrsig_t rrsig;
1184 isc_boolean_t found;
1186 dns_rdataset_init(&rdataset);
1188 result = dns_db_findnode(db, name, ISC_FALSE, &node);
1189 if (result == ISC_R_NOTFOUND)
1190 return (ISC_R_SUCCESS);
1191 if (result != ISC_R_SUCCESS)
1193 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig,
1194 dns_rdatatype_dnskey, (isc_stdtime_t) 0,
1196 dns_db_detachnode(db, &node);
1198 if (result == ISC_R_NOTFOUND)
1199 return (ISC_R_SUCCESS);
1200 if (result != ISC_R_SUCCESS)
1203 for (result = dns_rdataset_first(&rdataset);
1204 result == ISC_R_SUCCESS;
1205 result = dns_rdataset_next(&rdataset)) {
1206 dns_rdataset_current(&rdataset, &rdata);
1207 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
1208 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1210 for (i = 0; i < nkeys; i++) {
1211 if (rrsig.keyid == dst_key_id(keys[i])) {
1213 if (!dst_key_isprivate(keys[i]) &&
1214 !dst_key_inactive(keys[i]))
1217 * The re-signing code in zone.c
1218 * will mark this as offline.
1219 * Just skip the record for now.
1223 result = update_one_rr(db, ver, diff,
1224 DNS_DIFFOP_DEL, name,
1225 rdataset.ttl, &rdata);
1230 * If there is not a matching DNSKEY then delete the RRSIG.
1233 result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
1234 name, rdataset.ttl, &rdata);
1235 dns_rdata_reset(&rdata);
1236 if (result != ISC_R_SUCCESS)
1239 dns_rdataset_disassociate(&rdataset);
1240 if (result == ISC_R_NOMORE)
1241 result = ISC_R_SUCCESS;
1244 dns_db_detachnode(db, &node);
1249 add_exposed_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1250 dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t cut,
1251 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
1252 isc_stdtime_t inception, isc_stdtime_t expire,
1253 isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly)
1255 isc_result_t result;
1257 dns_rdatasetiter_t *iter;
1260 result = dns_db_findnode(db, name, ISC_FALSE, &node);
1261 if (result == ISC_R_NOTFOUND)
1262 return (ISC_R_SUCCESS);
1263 if (result != ISC_R_SUCCESS)
1267 result = dns_db_allrdatasets(db, node, ver,
1268 (isc_stdtime_t) 0, &iter);
1269 if (result != ISC_R_SUCCESS)
1272 for (result = dns_rdatasetiter_first(iter);
1273 result == ISC_R_SUCCESS;
1274 result = dns_rdatasetiter_next(iter))
1276 dns_rdataset_t rdataset;
1277 dns_rdatatype_t type;
1280 dns_rdataset_init(&rdataset);
1281 dns_rdatasetiter_current(iter, &rdataset);
1282 type = rdataset.type;
1283 dns_rdataset_disassociate(&rdataset);
1286 * We don't need to sign unsigned NSEC records at the cut
1287 * as they are handled elsewhere.
1289 if ((type == dns_rdatatype_rrsig) ||
1290 (cut && type != dns_rdatatype_ds))
1292 result = rrset_exists(db, ver, name, dns_rdatatype_rrsig,
1294 if (result != ISC_R_SUCCESS)
1295 goto cleanup_iterator;
1298 result = add_sigs(log, zone, db, ver, name, type, diff,
1299 keys, nkeys, inception, expire,
1300 check_ksk, keyset_kskonly);
1301 if (result != ISC_R_SUCCESS)
1302 goto cleanup_iterator;
1304 if (result == ISC_R_NOMORE)
1305 result = ISC_R_SUCCESS;
1308 dns_rdatasetiter_destroy(&iter);
1311 dns_db_detachnode(db, &node);
1317 * Update RRSIG, NSEC and NSEC3 records affected by an update. The original
1318 * update, including the SOA serial update but excluding the RRSIG & NSEC
1319 * changes, is in "diff" and has already been applied to "newver" of "db".
1320 * The database version prior to the update is "oldver".
1322 * The necessary RRSIG, NSEC and NSEC3 changes will be applied to "newver"
1323 * and added (as a minimal diff) to "diff".
1325 * The RRSIGs generated will be valid for 'sigvalidityinterval' seconds.
1328 dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1329 dns_dbversion_t *oldver, dns_dbversion_t *newver,
1330 dns_diff_t *diff, isc_uint32_t sigvalidityinterval)
1332 isc_result_t result;
1334 dns_diff_t diffnames;
1335 dns_diff_t affected;
1336 dns_diff_t sig_diff;
1337 dns_diff_t nsec_diff;
1338 dns_diff_t nsec_mindiff;
1339 isc_boolean_t flag, build_nsec, build_nsec3;
1340 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
1341 unsigned int nkeys = 0;
1343 isc_stdtime_t now, inception, expire;
1345 dns_rdata_soa_t soa;
1346 dns_rdata_t rdata = DNS_RDATA_INIT;
1347 dns_rdataset_t rdataset;
1348 dns_dbnode_t *node = NULL;
1349 isc_boolean_t check_ksk, keyset_kskonly;
1350 isc_boolean_t unsecure;
1352 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
1354 dns_diff_init(diff->mctx, &diffnames);
1355 dns_diff_init(diff->mctx, &affected);
1357 dns_diff_init(diff->mctx, &sig_diff);
1358 dns_diff_init(diff->mctx, &nsec_diff);
1359 dns_diff_init(diff->mctx, &nsec_mindiff);
1361 result = find_zone_keys(zone, db, newver, diff->mctx,
1362 DNS_MAXZONEKEYS, zone_keys, &nkeys);
1363 if (result != ISC_R_SUCCESS) {
1364 update_log(log, zone, ISC_LOG_ERROR,
1365 "could not get zone keys for secure dynamic update");
1369 isc_stdtime_get(&now);
1370 inception = now - 3600; /* Allow for some clock skew. */
1371 expire = now + sigvalidityinterval;
1374 * Do we look at the KSK flag on the DNSKEY to determining which
1375 * keys sign which RRsets? First check the zone option then
1376 * check the keys flags to make sure at least one has a ksk set
1379 check_ksk = ISC_TF((dns_zone_getoptions(zone) &
1380 DNS_ZONEOPT_UPDATECHECKKSK) != 0);
1381 keyset_kskonly = ISC_TF((dns_zone_getoptions(zone) &
1382 DNS_ZONEOPT_DNSKEYKSKONLY) != 0);
1385 * Get the NSEC/NSEC3 TTL from the SOA MINIMUM field.
1387 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
1388 dns_rdataset_init(&rdataset);
1389 CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa, 0,
1390 (isc_stdtime_t) 0, &rdataset, NULL));
1391 CHECK(dns_rdataset_first(&rdataset));
1392 dns_rdataset_current(&rdataset, &rdata);
1393 CHECK(dns_rdata_tostruct(&rdata, &soa, NULL));
1394 nsecttl = soa.minimum;
1395 dns_rdataset_disassociate(&rdataset);
1396 dns_db_detachnode(db, &node);
1399 * Find all RRsets directly affected by the update, and
1400 * update their RRSIGs. Also build a list of names affected
1401 * by the update in "diffnames".
1403 CHECK(dns_diff_sort(diff, temp_order));
1405 t = ISC_LIST_HEAD(diff->tuples);
1407 dns_name_t *name = &t->name;
1408 /* Now "name" is a new, unique name affected by the update. */
1410 CHECK(namelist_append_name(&diffnames, name));
1412 while (t != NULL && dns_name_equal(&t->name, name)) {
1413 dns_rdatatype_t type;
1414 type = t->rdata.type;
1417 * Now "name" and "type" denote a new unique RRset
1418 * affected by the update.
1421 /* Don't sign RRSIGs. */
1422 if (type == dns_rdatatype_rrsig)
1426 * Delete all old RRSIGs covering this type, since they
1427 * are all invalid when the signed RRset has changed.
1428 * We may not be able to recreate all of them - tough.
1429 * Special case changes to the zone's DNSKEY records
1430 * to support offline KSKs.
1432 if (type == dns_rdatatype_dnskey)
1433 del_keysigs(db, newver, name, &sig_diff,
1436 CHECK(delete_if(true_p, db, newver, name,
1437 dns_rdatatype_rrsig, type,
1441 * If this RRset is still visible after the update,
1442 * add a new signature for it.
1444 CHECK(rrset_visible(db, newver, name, type, &flag));
1446 CHECK(add_sigs(log, zone, db, newver, name,
1447 type, &sig_diff, zone_keys,
1448 nkeys, inception, expire,
1449 check_ksk, keyset_kskonly));
1452 /* Skip any other updates to the same RRset. */
1454 dns_name_equal(&t->name, name) &&
1455 t->rdata.type == type)
1457 t = ISC_LIST_NEXT(t, link);
1461 update_log(log, zone, ISC_LOG_DEBUG(3), "updated data signatures");
1463 /* Remove orphaned NSECs and RRSIG NSECs. */
1464 for (t = ISC_LIST_HEAD(diffnames.tuples);
1466 t = ISC_LIST_NEXT(t, link))
1468 CHECK(non_nsec_rrset_exists(db, newver, &t->name, &flag));
1470 CHECK(delete_if(true_p, db, newver, &t->name,
1471 dns_rdatatype_any, 0,
1475 update_log(log, zone, ISC_LOG_DEBUG(3),
1476 "removed any orphaned NSEC records");
1479 * See if we need to build NSEC or NSEC3 chains.
1481 CHECK(dns_private_chains(db, newver, privatetype, &build_nsec,
1486 update_log(log, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC chain");
1489 * When a name is created or deleted, its predecessor needs to
1490 * have its NSEC updated.
1492 for (t = ISC_LIST_HEAD(diffnames.tuples);
1494 t = ISC_LIST_NEXT(t, link))
1496 isc_boolean_t existed, exists;
1497 dns_fixedname_t fixedname;
1498 dns_name_t *prevname;
1500 dns_fixedname_init(&fixedname);
1501 prevname = dns_fixedname_name(&fixedname);
1504 CHECK(name_exists(db, oldver, &t->name, &existed));
1506 existed = ISC_FALSE;
1507 CHECK(name_exists(db, newver, &t->name, &exists));
1508 if (exists == existed)
1512 * Find the predecessor.
1513 * When names become obscured or unobscured in this update
1514 * transaction, we may find the wrong predecessor because
1515 * the NSECs have not yet been updated to reflect the delegation
1516 * change. This should not matter because in this case,
1517 * the correct predecessor is either the delegation node or
1518 * a newly unobscured node, and those nodes are on the
1519 * "affected" list in any case.
1521 CHECK(next_active(log, zone, db, newver,
1522 &t->name, prevname, ISC_FALSE));
1523 CHECK(namelist_append_name(&affected, prevname));
1527 * Find names potentially affected by delegation changes
1528 * (obscured by adding an NS or DNAME, or unobscured by
1531 for (t = ISC_LIST_HEAD(diffnames.tuples);
1533 t = ISC_LIST_NEXT(t, link))
1535 isc_boolean_t ns_existed, dname_existed;
1536 isc_boolean_t ns_exists, dname_exists;
1539 CHECK(rrset_exists(db, oldver, &t->name,
1540 dns_rdatatype_ns, 0, &ns_existed));
1542 ns_existed = ISC_FALSE;
1544 CHECK(rrset_exists(db, oldver, &t->name,
1545 dns_rdatatype_dname, 0,
1548 dname_existed = ISC_FALSE;
1549 CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_ns, 0,
1551 CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_dname, 0,
1553 if ((ns_exists || dname_exists) == (ns_existed || dname_existed))
1556 * There was a delegation change. Mark all subdomains
1557 * of t->name as potentially needing a NSEC update.
1559 CHECK(namelist_append_subdomain(db, &t->name, &affected));
1562 ISC_LIST_APPENDLIST(affected.tuples, diffnames.tuples, link);
1563 INSIST(ISC_LIST_EMPTY(diffnames.tuples));
1565 CHECK(uniqify_name_list(&affected));
1568 * Determine which names should have NSECs, and delete/create
1569 * NSECs to make it so. We don't know the final NSEC targets yet,
1570 * so we just create placeholder NSECs with arbitrary contents
1571 * to indicate that their respective owner names should be part of
1574 for (t = ISC_LIST_HEAD(affected.tuples);
1576 t = ISC_LIST_NEXT(t, link))
1578 isc_boolean_t exists;
1579 dns_name_t *name = &t->name;
1581 CHECK(name_exists(db, newver, name, &exists));
1584 CHECK(is_active(db, newver, name, &flag, &cut, NULL));
1587 * This name is obscured. Delete any
1588 * existing NSEC record.
1590 CHECK(delete_if(true_p, db, newver, name,
1591 dns_rdatatype_nsec, 0,
1593 CHECK(delete_if(rrsig_p, db, newver, name,
1594 dns_rdatatype_any, 0, NULL, diff));
1597 * This name is not obscured. It needs to have a
1598 * NSEC unless it is the at the origin, in which
1599 * case it should already exist if there is a complete
1600 * NSEC chain and if there isn't a complete NSEC chain
1601 * we don't want to add one as that would signal that
1602 * there is a complete NSEC chain.
1604 if (!dns_name_equal(name, dns_db_origin(db))) {
1605 CHECK(rrset_exists(db, newver, name,
1606 dns_rdatatype_nsec, 0,
1609 CHECK(add_placeholder_nsec(db, newver,
1612 CHECK(add_exposed_sigs(log, zone, db, newver, name,
1613 cut, &sig_diff, zone_keys, nkeys,
1614 inception, expire, check_ksk,
1620 * Now we know which names are part of the NSEC chain.
1621 * Make them all point at their correct targets.
1623 for (t = ISC_LIST_HEAD(affected.tuples);
1625 t = ISC_LIST_NEXT(t, link))
1627 CHECK(rrset_exists(db, newver, &t->name,
1628 dns_rdatatype_nsec, 0, &flag));
1631 * There is a NSEC, but we don't know if it is correct.
1632 * Delete it and create a correct one to be sure.
1633 * If the update was unnecessary, the diff minimization
1634 * will take care of eliminating it from the journal,
1637 * The RRSIG bit should always be set in the NSECs
1638 * we generate, because they will all get RRSIG NSECs.
1639 * (XXX what if the zone keys are missing?).
1640 * Because the RRSIG NSECs have not necessarily been
1641 * created yet, the correctness of the bit mask relies
1642 * on the assumption that NSECs are only created if
1643 * there is other data, and if there is other data,
1644 * there are other RRSIGs.
1646 CHECK(add_nsec(log, zone, db, newver, &t->name,
1647 nsecttl, &nsec_diff));
1652 * Minimize the set of NSEC updates so that we don't
1653 * have to regenerate the RRSIG NSECs for NSECs that were
1654 * replaced with identical ones.
1656 while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) {
1657 ISC_LIST_UNLINK(nsec_diff.tuples, t, link);
1658 dns_diff_appendminimal(&nsec_mindiff, &t);
1661 update_log(log, zone, ISC_LOG_DEBUG(3), "signing rebuilt NSEC chain");
1663 /* Update RRSIG NSECs. */
1664 for (t = ISC_LIST_HEAD(nsec_mindiff.tuples);
1666 t = ISC_LIST_NEXT(t, link))
1668 if (t->op == DNS_DIFFOP_DEL) {
1669 CHECK(delete_if(true_p, db, newver, &t->name,
1670 dns_rdatatype_rrsig, dns_rdatatype_nsec,
1672 } else if (t->op == DNS_DIFFOP_ADD) {
1673 CHECK(add_sigs(log, zone, db, newver, &t->name,
1674 dns_rdatatype_nsec, &sig_diff,
1675 zone_keys, nkeys, inception, expire,
1676 check_ksk, keyset_kskonly));
1684 /* Record our changes for the journal. */
1685 while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) {
1686 ISC_LIST_UNLINK(sig_diff.tuples, t, link);
1687 dns_diff_appendminimal(diff, &t);
1689 while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) {
1690 ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link);
1691 dns_diff_appendminimal(diff, &t);
1694 INSIST(ISC_LIST_EMPTY(sig_diff.tuples));
1695 INSIST(ISC_LIST_EMPTY(nsec_diff.tuples));
1696 INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples));
1699 update_log(log, zone, ISC_LOG_DEBUG(3),
1700 "no NSEC3 chains to rebuild");
1704 update_log(log, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC3 chains");
1706 dns_diff_clear(&diffnames);
1707 dns_diff_clear(&affected);
1709 CHECK(dns_diff_sort(diff, temp_order));
1712 * Find names potentially affected by delegation changes
1713 * (obscured by adding an NS or DNAME, or unobscured by
1716 t = ISC_LIST_HEAD(diff->tuples);
1718 dns_name_t *name = &t->name;
1720 isc_boolean_t ns_existed, dname_existed;
1721 isc_boolean_t ns_exists, dname_exists;
1722 isc_boolean_t exists, existed;
1724 if (t->rdata.type == dns_rdatatype_nsec ||
1725 t->rdata.type == dns_rdatatype_rrsig) {
1726 t = ISC_LIST_NEXT(t, link);
1730 CHECK(namelist_append_name(&affected, name));
1733 CHECK(rrset_exists(db, oldver, name, dns_rdatatype_ns,
1736 ns_existed = ISC_FALSE;
1738 CHECK(rrset_exists(db, oldver, name,
1739 dns_rdatatype_dname, 0,
1742 dname_existed = ISC_FALSE;
1743 CHECK(rrset_exists(db, newver, name, dns_rdatatype_ns, 0,
1745 CHECK(rrset_exists(db, newver, name, dns_rdatatype_dname, 0,
1748 exists = ns_exists || dname_exists;
1749 existed = ns_existed || dname_existed;
1750 if (exists == existed)
1753 * There was a delegation change. Mark all subdomains
1754 * of t->name as potentially needing a NSEC3 update.
1756 CHECK(namelist_append_subdomain(db, name, &affected));
1759 while (t != NULL && dns_name_equal(&t->name, name))
1760 t = ISC_LIST_NEXT(t, link);
1763 for (t = ISC_LIST_HEAD(affected.tuples);
1765 t = ISC_LIST_NEXT(t, link)) {
1766 dns_name_t *name = &t->name;
1768 unsecure = ISC_FALSE; /* Silence compiler warning. */
1769 CHECK(is_active(db, newver, name, &flag, &cut, &unsecure));
1772 CHECK(delete_if(rrsig_p, db, newver, name,
1773 dns_rdatatype_any, 0, NULL, diff));
1774 CHECK(dns_nsec3_delnsec3sx(db, newver, name,
1775 privatetype, &nsec_diff));
1777 CHECK(add_exposed_sigs(log, zone, db, newver, name,
1778 cut, &sig_diff, zone_keys, nkeys,
1779 inception, expire, check_ksk,
1781 CHECK(dns_nsec3_addnsec3sx(db, newver, name, nsecttl,
1782 unsecure, privatetype,
1788 * Minimize the set of NSEC3 updates so that we don't
1789 * have to regenerate the RRSIG NSEC3s for NSEC3s that were
1790 * replaced with identical ones.
1792 while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) {
1793 ISC_LIST_UNLINK(nsec_diff.tuples, t, link);
1794 dns_diff_appendminimal(&nsec_mindiff, &t);
1797 update_log(log, zone, ISC_LOG_DEBUG(3),
1798 "signing rebuilt NSEC3 chain");
1800 /* Update RRSIG NSEC3s. */
1801 for (t = ISC_LIST_HEAD(nsec_mindiff.tuples);
1803 t = ISC_LIST_NEXT(t, link))
1805 if (t->op == DNS_DIFFOP_DEL) {
1806 CHECK(delete_if(true_p, db, newver, &t->name,
1807 dns_rdatatype_rrsig,
1808 dns_rdatatype_nsec3,
1810 } else if (t->op == DNS_DIFFOP_ADD) {
1811 CHECK(add_sigs(log, zone, db, newver, &t->name,
1812 dns_rdatatype_nsec3,
1813 &sig_diff, zone_keys, nkeys,
1814 inception, expire, check_ksk,
1821 /* Record our changes for the journal. */
1822 while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) {
1823 ISC_LIST_UNLINK(sig_diff.tuples, t, link);
1824 dns_diff_appendminimal(diff, &t);
1826 while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) {
1827 ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link);
1828 dns_diff_appendminimal(diff, &t);
1831 INSIST(ISC_LIST_EMPTY(sig_diff.tuples));
1832 INSIST(ISC_LIST_EMPTY(nsec_diff.tuples));
1833 INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples));
1836 dns_diff_clear(&sig_diff);
1837 dns_diff_clear(&nsec_diff);
1838 dns_diff_clear(&nsec_mindiff);
1840 dns_diff_clear(&affected);
1841 dns_diff_clear(&diffnames);
1843 for (i = 0; i < nkeys; i++)
1844 dst_key_free(&zone_keys[i]);
1850 dns_update_soaserial(isc_uint32_t serial, dns_updatemethod_t method) {
1853 if (method == dns_updatemethod_unixtime) {
1854 isc_stdtime_get(&now);
1855 if (now != 0 && isc_serial_gt(now, serial))
1860 serial = (serial + 1) & 0xFFFFFFFF;