1 /* $NetBSD: update.c,v 1.4 2014/12/10 04:37:58 christos Exp $ */
4 * Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
24 #include <isc/netaddr.h>
25 #include <isc/print.h>
26 #include <isc/serial.h>
27 #include <isc/stats.h>
28 #include <isc/stdtime.h>
29 #include <isc/string.h>
30 #include <isc/taskpool.h>
34 #include <dns/dbiterator.h>
36 #include <dns/dnssec.h>
37 #include <dns/events.h>
38 #include <dns/fixedname.h>
39 #include <dns/journal.h>
40 #include <dns/keyvalues.h>
42 #include <dns/message.h>
44 #include <dns/nsec3.h>
45 #include <dns/private.h>
46 #include <dns/rdataclass.h>
47 #include <dns/rdataset.h>
48 #include <dns/rdatasetiter.h>
49 #include <dns/rdatastruct.h>
50 #include <dns/rdatatype.h>
51 #include <dns/result.h>
55 #include <dns/update.h>
61 /**************************************************************************/
64 * Log level for tracing dynamic update protocol requests.
66 #define LOGLEVEL_PROTOCOL ISC_LOG_INFO
69 * Log level for low-level debug tracing.
71 #define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8)
74 * Check an operation for failure. These macros all assume that
75 * the function using them has a 'result' variable and a 'failure'
80 if (result != ISC_R_SUCCESS) goto failure; \
81 } while (/*CONSTCOND*/0)
84 * Fail unconditionally with result 'code', which must not
85 * be ISC_R_SUCCESS. The reason for failure presumably has
86 * been logged already.
88 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
89 * from complaining about "end-of-loop code not reached".
95 if (result != ISC_R_SUCCESS) goto failure; \
96 } while (/*CONSTCOND*/0)
99 * Fail unconditionally and log as a client error.
100 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
101 * from complaining about "end-of-loop code not reached".
103 #define FAILC(code, msg) \
105 const char *_what = "failed"; \
108 case DNS_R_NXDOMAIN: \
109 case DNS_R_YXDOMAIN: \
110 case DNS_R_YXRRSET: \
111 case DNS_R_NXRRSET: \
112 _what = "unsuccessful"; \
114 update_log(log, zone, LOGLEVEL_PROTOCOL, \
115 "update %s: %s (%s)", _what, \
116 msg, isc_result_totext(result)); \
117 if (result != ISC_R_SUCCESS) goto failure; \
118 } while (/*CONSTCOND*/0)
120 #define FAILN(code, name, msg) \
122 const char *_what = "failed"; \
125 case DNS_R_NXDOMAIN: \
126 case DNS_R_YXDOMAIN: \
127 case DNS_R_YXRRSET: \
128 case DNS_R_NXRRSET: \
129 _what = "unsuccessful"; \
131 if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) { \
132 char _nbuf[DNS_NAME_FORMATSIZE]; \
133 dns_name_format(name, _nbuf, sizeof(_nbuf)); \
134 update_log(log, zone, LOGLEVEL_PROTOCOL, \
135 "update %s: %s: %s (%s)", _what, _nbuf, \
136 msg, isc_result_totext(result)); \
138 if (result != ISC_R_SUCCESS) goto failure; \
139 } while (/*CONSTCOND*/0)
141 #define FAILNT(code, name, type, msg) \
143 const char *_what = "failed"; \
146 case DNS_R_NXDOMAIN: \
147 case DNS_R_YXDOMAIN: \
148 case DNS_R_YXRRSET: \
149 case DNS_R_NXRRSET: \
150 _what = "unsuccessful"; \
152 if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) { \
153 char _nbuf[DNS_NAME_FORMATSIZE]; \
154 char _tbuf[DNS_RDATATYPE_FORMATSIZE]; \
155 dns_name_format(name, _nbuf, sizeof(_nbuf)); \
156 dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \
157 update_log(log, zone, LOGLEVEL_PROTOCOL, \
158 "update %s: %s/%s: %s (%s)", \
159 _what, _nbuf, _tbuf, msg, \
160 isc_result_totext(result)); \
162 if (result != ISC_R_SUCCESS) goto failure; \
163 } while (/*CONSTCOND*/0)
166 * Fail unconditionally and log as a server error.
167 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
168 * from complaining about "end-of-loop code not reached".
170 #define FAILS(code, msg) \
173 update_log(log, zone, LOGLEVEL_PROTOCOL, \
175 msg, isc_result_totext(result)); \
176 if (result != ISC_R_SUCCESS) goto failure; \
177 } while (/*CONSTCOND*/0)
179 /**************************************************************************/
181 typedef struct rr rr_t
;
184 /* dns_name_t name; */
189 typedef struct update_event update_event_t
;
191 /**************************************************************************/
194 update_log(dns_update_log_t
*callback
, dns_zone_t
*zone
,
195 int level
, const char *fmt
, ...) ISC_FORMAT_PRINTF(4, 5);
198 update_log(dns_update_log_t
*callback
, dns_zone_t
*zone
,
199 int level
, const char *fmt
, ...)
204 if (callback
== NULL
)
207 if (isc_log_wouldlog(dns_lctx
, level
) == ISC_FALSE
)
212 vsnprintf(message
, sizeof(message
), fmt
, ap
);
215 (callback
->func
)(callback
->arg
, zone
, level
, message
);
219 * Update a single RR in version 'ver' of 'db' and log the
223 * \li '*tuple' == NULL. Either the tuple is freed, or its
224 * ownership has been transferred to the diff.
227 do_one_tuple(dns_difftuple_t
**tuple
, dns_db_t
*db
, dns_dbversion_t
*ver
,
230 dns_diff_t temp_diff
;
234 * Create a singleton diff.
236 dns_diff_init(diff
->mctx
, &temp_diff
);
237 ISC_LIST_APPEND(temp_diff
.tuples
, *tuple
, link
);
240 * Apply it to the database.
242 result
= dns_diff_apply(&temp_diff
, db
, ver
);
243 ISC_LIST_UNLINK(temp_diff
.tuples
, *tuple
, link
);
244 if (result
!= ISC_R_SUCCESS
) {
245 dns_difftuple_free(tuple
);
250 * Merge it into the current pending journal entry.
252 dns_diff_appendminimal(diff
, tuple
);
255 * Do not clear temp_diff.
257 return (ISC_R_SUCCESS
);
261 update_one_rr(dns_db_t
*db
, dns_dbversion_t
*ver
, dns_diff_t
*diff
,
262 dns_diffop_t op
, dns_name_t
*name
, dns_ttl_t ttl
,
265 dns_difftuple_t
*tuple
= NULL
;
267 result
= dns_difftuple_create(diff
->mctx
, op
,
268 name
, ttl
, rdata
, &tuple
);
269 if (result
!= ISC_R_SUCCESS
)
271 return (do_one_tuple(&tuple
, db
, ver
, diff
));
274 /**************************************************************************/
276 * Callback-style iteration over rdatasets and rdatas.
278 * foreach_rrset() can be used to iterate over the RRsets
279 * of a name and call a callback function with each
280 * one. Similarly, foreach_rr() can be used to iterate
281 * over the individual RRs at name, optionally restricted
282 * to RRs of a given type.
284 * The callback functions are called "actions" and take
285 * two arguments: a void pointer for passing arbitrary
286 * context information, and a pointer to the current RRset
287 * or RR. By convention, their names end in "_action".
291 * XXXRTH We might want to make this public somewhere in libdns.
295 * Function type for foreach_rrset() iterator actions.
297 typedef isc_result_t
rrset_func(void *data
, dns_rdataset_t
*rrset
);
300 * Function type for foreach_rr() iterator actions.
302 typedef isc_result_t
rr_func(void *data
, rr_t
*rr
);
305 * Internal context struct for foreach_node_rr().
309 void * rr_action_data
;
310 } foreach_node_rr_ctx_t
;
313 * Internal helper function for foreach_node_rr().
316 foreach_node_rr_action(void *data
, dns_rdataset_t
*rdataset
) {
318 foreach_node_rr_ctx_t
*ctx
= data
;
319 for (result
= dns_rdataset_first(rdataset
);
320 result
== ISC_R_SUCCESS
;
321 result
= dns_rdataset_next(rdataset
))
323 rr_t rr
= { 0, DNS_RDATA_INIT
};
325 dns_rdataset_current(rdataset
, &rr
.rdata
);
326 rr
.ttl
= rdataset
->ttl
;
327 result
= (*ctx
->rr_action
)(ctx
->rr_action_data
, &rr
);
328 if (result
!= ISC_R_SUCCESS
)
331 if (result
!= ISC_R_NOMORE
)
333 return (ISC_R_SUCCESS
);
337 * For each rdataset of 'name' in 'ver' of 'db', call 'action'
338 * with the rdataset and 'action_data' as arguments. If the name
339 * does not exist, do nothing.
341 * If 'action' returns an error, abort iteration and return the error.
344 foreach_rrset(dns_db_t
*db
, dns_dbversion_t
*ver
, dns_name_t
*name
,
345 rrset_func
*action
, void *action_data
)
349 dns_rdatasetiter_t
*iter
;
352 result
= dns_db_findnode(db
, name
, ISC_FALSE
, &node
);
353 if (result
== ISC_R_NOTFOUND
)
354 return (ISC_R_SUCCESS
);
355 if (result
!= ISC_R_SUCCESS
)
359 result
= dns_db_allrdatasets(db
, node
, ver
,
360 (isc_stdtime_t
) 0, &iter
);
361 if (result
!= ISC_R_SUCCESS
)
364 for (result
= dns_rdatasetiter_first(iter
);
365 result
== ISC_R_SUCCESS
;
366 result
= dns_rdatasetiter_next(iter
))
368 dns_rdataset_t rdataset
;
370 dns_rdataset_init(&rdataset
);
371 dns_rdatasetiter_current(iter
, &rdataset
);
373 result
= (*action
)(action_data
, &rdataset
);
375 dns_rdataset_disassociate(&rdataset
);
376 if (result
!= ISC_R_SUCCESS
)
377 goto cleanup_iterator
;
379 if (result
== ISC_R_NOMORE
)
380 result
= ISC_R_SUCCESS
;
383 dns_rdatasetiter_destroy(&iter
);
386 dns_db_detachnode(db
, &node
);
392 * For each RR of 'name' in 'ver' of 'db', call 'action'
393 * with the RR and 'action_data' as arguments. If the name
394 * does not exist, do nothing.
396 * If 'action' returns an error, abort iteration
397 * and return the error.
400 foreach_node_rr(dns_db_t
*db
, dns_dbversion_t
*ver
, dns_name_t
*name
,
401 rr_func
*rr_action
, void *rr_action_data
)
403 foreach_node_rr_ctx_t ctx
;
404 ctx
.rr_action
= rr_action
;
405 ctx
.rr_action_data
= rr_action_data
;
406 return (foreach_rrset(db
, ver
, name
,
407 foreach_node_rr_action
, &ctx
));
412 * For each of the RRs specified by 'db', 'ver', 'name', 'type',
413 * (which can be dns_rdatatype_any to match any type), and 'covers', call
414 * 'action' with the RR and 'action_data' as arguments. If the name
415 * does not exist, or if no RRset of the given type exists at the name,
418 * If 'action' returns an error, abort iteration and return the error.
421 foreach_rr(dns_db_t
*db
, dns_dbversion_t
*ver
, dns_name_t
*name
,
422 dns_rdatatype_t type
, dns_rdatatype_t covers
, rr_func
*rr_action
,
423 void *rr_action_data
)
428 dns_rdataset_t rdataset
;
430 if (type
== dns_rdatatype_any
)
431 return (foreach_node_rr(db
, ver
, name
,
432 rr_action
, rr_action_data
));
435 if (type
== dns_rdatatype_nsec3
||
436 (type
== dns_rdatatype_rrsig
&& covers
== dns_rdatatype_nsec3
))
437 result
= dns_db_findnsec3node(db
, name
, ISC_FALSE
, &node
);
439 result
= dns_db_findnode(db
, name
, ISC_FALSE
, &node
);
440 if (result
== ISC_R_NOTFOUND
)
441 return (ISC_R_SUCCESS
);
442 if (result
!= ISC_R_SUCCESS
)
445 dns_rdataset_init(&rdataset
);
446 result
= dns_db_findrdataset(db
, node
, ver
, type
, covers
,
447 (isc_stdtime_t
) 0, &rdataset
, NULL
);
448 if (result
== ISC_R_NOTFOUND
) {
449 result
= ISC_R_SUCCESS
;
452 if (result
!= ISC_R_SUCCESS
)
455 for (result
= dns_rdataset_first(&rdataset
);
456 result
== ISC_R_SUCCESS
;
457 result
= dns_rdataset_next(&rdataset
))
459 rr_t rr
= { 0, DNS_RDATA_INIT
};
460 dns_rdataset_current(&rdataset
, &rr
.rdata
);
461 rr
.ttl
= rdataset
.ttl
;
462 result
= (*rr_action
)(rr_action_data
, &rr
);
463 if (result
!= ISC_R_SUCCESS
)
464 goto cleanup_rdataset
;
466 if (result
!= ISC_R_NOMORE
)
467 goto cleanup_rdataset
;
468 result
= ISC_R_SUCCESS
;
471 dns_rdataset_disassociate(&rdataset
);
473 dns_db_detachnode(db
, &node
);
478 /**************************************************************************/
480 * Various tests on the database contents (for prerequisites, etc).
484 * Function type for predicate functions that compare a database RR 'db_rr'
485 * against an update RR 'update_rr'.
487 typedef isc_boolean_t
rr_predicate(dns_rdata_t
*update_rr
, dns_rdata_t
*db_rr
);
490 * Helper function for rrset_exists().
493 rrset_exists_action(void *data
, rr_t
*rr
) {
496 return (ISC_R_EXISTS
);
500 * Utility macro for RR existence checking functions.
502 * If the variable 'result' has the value ISC_R_EXISTS or
503 * ISC_R_SUCCESS, set *exists to ISC_TRUE or ISC_FALSE,
504 * respectively, and return success.
506 * If 'result' has any other value, there was a failure.
507 * Return the failure result code and do not set *exists.
509 * This would be more readable as "do { if ... } while(0)",
510 * but that form generates tons of warnings on Solaris 2.6.
512 #define RETURN_EXISTENCE_FLAG \
513 return ((result == ISC_R_EXISTS) ? \
514 (*exists = ISC_TRUE, ISC_R_SUCCESS) : \
515 ((result == ISC_R_SUCCESS) ? \
516 (*exists = ISC_FALSE, ISC_R_SUCCESS) : \
520 * Set '*exists' to true iff an rrset of the given type exists,
521 * to false otherwise.
524 rrset_exists(dns_db_t
*db
, dns_dbversion_t
*ver
, dns_name_t
*name
,
525 dns_rdatatype_t type
, dns_rdatatype_t covers
,
526 isc_boolean_t
*exists
)
529 result
= foreach_rr(db
, ver
, name
, type
, covers
,
530 rrset_exists_action
, NULL
);
531 RETURN_EXISTENCE_FLAG
;
535 * Set '*visible' to true if the RRset exists and is part of the
536 * visible zone. Otherwise '*visible' is set to false unless a
540 rrset_visible(dns_db_t
*db
, dns_dbversion_t
*ver
, dns_name_t
*name
,
541 dns_rdatatype_t type
, isc_boolean_t
*visible
)
544 dns_fixedname_t fixed
;
546 dns_fixedname_init(&fixed
);
547 result
= dns_db_find(db
, name
, ver
, type
, DNS_DBFIND_NOWILD
,
548 (isc_stdtime_t
) 0, NULL
,
549 dns_fixedname_name(&fixed
), NULL
, NULL
);
555 * Glue, obscured, deleted or replaced records.
557 case DNS_R_DELEGATION
:
562 case DNS_R_EMPTYNAME
:
563 case DNS_R_COVERINGNSEC
:
564 *visible
= ISC_FALSE
;
565 result
= ISC_R_SUCCESS
;
574 * Context struct and helper function for name_exists().
578 name_exists_action(void *data
, dns_rdataset_t
*rrset
) {
581 return (ISC_R_EXISTS
);
585 * Set '*exists' to true iff the given name exists, to false otherwise.
588 name_exists(dns_db_t
*db
, dns_dbversion_t
*ver
, dns_name_t
*name
,
589 isc_boolean_t
*exists
)
592 result
= foreach_rrset(db
, ver
, name
,
593 name_exists_action
, NULL
);
594 RETURN_EXISTENCE_FLAG
;
597 /**************************************************************************/
599 * Checking of "RRset exists (value dependent)" prerequisites.
601 * In the RFC2136 section 3.2.5, this is the pseudocode involving
602 * a variable called "temp", a mapping of <name, type> tuples to rrsets.
604 * Here, we represent the "temp" data structure as (non-minimal) "dns_diff_t"
605 * where each tuple has op==DNS_DIFFOP_EXISTS.
609 * A comparison function defining the sorting order for the entries
610 * in the "temp" data structure. The major sort key is the owner name,
611 * followed by the type and rdata.
614 temp_order(const void *av
, const void *bv
) {
615 dns_difftuple_t
const * const *ap
= av
;
616 dns_difftuple_t
const * const *bp
= bv
;
617 dns_difftuple_t
const *a
= *ap
;
618 dns_difftuple_t
const *b
= *bp
;
620 r
= dns_name_compare(&a
->name
, &b
->name
);
623 r
= (b
->rdata
.type
- a
->rdata
.type
);
626 r
= dns_rdata_casecompare(&a
->rdata
, &b
->rdata
);
630 /**************************************************************************/
632 * Conditional deletion of RRs.
636 * Context structure for delete_if().
640 rr_predicate
*predicate
;
642 dns_dbversion_t
*ver
;
645 dns_rdata_t
*update_rr
;
646 } conditional_delete_ctx_t
;
649 * Predicate functions for delete_if().
653 * Return true always.
656 true_p(dns_rdata_t
*update_rr
, dns_rdata_t
*db_rr
) {
663 * Return true if the record is a RRSIG.
666 rrsig_p(dns_rdata_t
*update_rr
, dns_rdata_t
*db_rr
) {
668 return ((db_rr
->type
== dns_rdatatype_rrsig
) ?
669 ISC_TRUE
: ISC_FALSE
);
673 * Internal helper function for delete_if().
676 delete_if_action(void *data
, rr_t
*rr
) {
677 conditional_delete_ctx_t
*ctx
= data
;
678 if ((*ctx
->predicate
)(ctx
->update_rr
, &rr
->rdata
)) {
680 result
= update_one_rr(ctx
->db
, ctx
->ver
, ctx
->diff
,
681 DNS_DIFFOP_DEL
, ctx
->name
,
682 rr
->ttl
, &rr
->rdata
);
685 return (ISC_R_SUCCESS
);
690 * Conditionally delete RRs. Apply 'predicate' to the RRs
691 * specified by 'db', 'ver', 'name', and 'type' (which can
692 * be dns_rdatatype_any to match any type). Delete those
693 * RRs for which the predicate returns true, and log the
694 * deletions in 'diff'.
697 delete_if(rr_predicate
*predicate
, dns_db_t
*db
, dns_dbversion_t
*ver
,
698 dns_name_t
*name
, dns_rdatatype_t type
, dns_rdatatype_t covers
,
699 dns_rdata_t
*update_rr
, dns_diff_t
*diff
)
701 conditional_delete_ctx_t ctx
;
702 ctx
.predicate
= predicate
;
707 ctx
.update_rr
= update_rr
;
708 return (foreach_rr(db
, ver
, name
, type
, covers
,
709 delete_if_action
, &ctx
));
712 /**************************************************************************/
714 * Incremental updating of NSECs and RRSIGs.
718 * We abuse the dns_diff_t type to represent a set of domain names
719 * affected by the update.
722 namelist_append_name(dns_diff_t
*list
, dns_name_t
*name
) {
724 dns_difftuple_t
*tuple
= NULL
;
725 static dns_rdata_t dummy_rdata
= DNS_RDATA_INIT
;
727 CHECK(dns_difftuple_create(list
->mctx
, DNS_DIFFOP_EXISTS
, name
, 0,
728 &dummy_rdata
, &tuple
));
729 dns_diff_append(list
, &tuple
);
735 namelist_append_subdomain(dns_db_t
*db
, dns_name_t
*name
, dns_diff_t
*affected
)
738 dns_fixedname_t fixedname
;
740 dns_dbiterator_t
*dbit
= NULL
;
742 dns_fixedname_init(&fixedname
);
743 child
= dns_fixedname_name(&fixedname
);
745 CHECK(dns_db_createiterator(db
, DNS_DB_NONSEC3
, &dbit
));
747 for (result
= dns_dbiterator_seek(dbit
, name
);
748 result
== ISC_R_SUCCESS
;
749 result
= dns_dbiterator_next(dbit
))
751 dns_dbnode_t
*node
= NULL
;
752 CHECK(dns_dbiterator_current(dbit
, &node
, child
));
753 dns_db_detachnode(db
, &node
);
754 if (! dns_name_issubdomain(child
, name
))
756 CHECK(namelist_append_name(affected
, child
));
758 if (result
== ISC_R_NOMORE
)
759 result
= ISC_R_SUCCESS
;
762 dns_dbiterator_destroy(&dbit
);
769 * Helper function for non_nsec_rrset_exists().
772 is_non_nsec_action(void *data
, dns_rdataset_t
*rrset
) {
774 if (!(rrset
->type
== dns_rdatatype_nsec
||
775 rrset
->type
== dns_rdatatype_nsec3
||
776 (rrset
->type
== dns_rdatatype_rrsig
&&
777 (rrset
->covers
== dns_rdatatype_nsec
||
778 rrset
->covers
== dns_rdatatype_nsec3
))))
779 return (ISC_R_EXISTS
);
780 return (ISC_R_SUCCESS
);
784 * Check whether there is an rrset other than a NSEC or RRSIG NSEC,
785 * i.e., anything that justifies the continued existence of a name
786 * after a secure update.
788 * If such an rrset exists, set '*exists' to ISC_TRUE.
789 * Otherwise, set it to ISC_FALSE.
792 non_nsec_rrset_exists(dns_db_t
*db
, dns_dbversion_t
*ver
,
793 dns_name_t
*name
, isc_boolean_t
*exists
)
796 result
= foreach_rrset(db
, ver
, name
, is_non_nsec_action
, NULL
);
797 RETURN_EXISTENCE_FLAG
;
801 * A comparison function for sorting dns_diff_t:s by name.
804 name_order(const void *av
, const void *bv
) {
805 dns_difftuple_t
const * const *ap
= av
;
806 dns_difftuple_t
const * const *bp
= bv
;
807 dns_difftuple_t
const *a
= *ap
;
808 dns_difftuple_t
const *b
= *bp
;
809 return (dns_name_compare(&a
->name
, &b
->name
));
813 uniqify_name_list(dns_diff_t
*list
) {
815 dns_difftuple_t
*p
, *q
;
817 CHECK(dns_diff_sort(list
, name_order
));
819 p
= ISC_LIST_HEAD(list
->tuples
);
822 q
= ISC_LIST_NEXT(p
, link
);
823 if (q
== NULL
|| ! dns_name_equal(&p
->name
, &q
->name
))
825 ISC_LIST_UNLINK(list
->tuples
, q
, link
);
826 dns_difftuple_free(&q
);
828 p
= ISC_LIST_NEXT(p
, link
);
835 is_active(dns_db_t
*db
, dns_dbversion_t
*ver
, dns_name_t
*name
,
836 isc_boolean_t
*flag
, isc_boolean_t
*cut
, isc_boolean_t
*unsecure
)
839 dns_fixedname_t foundname
;
840 dns_fixedname_init(&foundname
);
841 result
= dns_db_find(db
, name
, ver
, dns_rdatatype_any
,
842 DNS_DBFIND_GLUEOK
| DNS_DBFIND_NOWILD
,
843 (isc_stdtime_t
) 0, NULL
,
844 dns_fixedname_name(&foundname
),
846 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_EMPTYNAME
) {
849 if (unsecure
!= NULL
)
850 *unsecure
= ISC_FALSE
;
851 return (ISC_R_SUCCESS
);
852 } else if (result
== DNS_R_ZONECUT
) {
855 if (unsecure
!= NULL
) {
857 * We are at the zonecut. Check to see if there
860 if (dns_db_find(db
, name
, ver
, dns_rdatatype_ds
, 0,
861 (isc_stdtime_t
) 0, NULL
,
862 dns_fixedname_name(&foundname
),
863 NULL
, NULL
) == DNS_R_NXRRSET
)
864 *unsecure
= ISC_TRUE
;
866 *unsecure
= ISC_FALSE
;
868 return (ISC_R_SUCCESS
);
869 } else if (result
== DNS_R_GLUE
|| result
== DNS_R_DNAME
||
870 result
== DNS_R_DELEGATION
|| result
== DNS_R_NXDOMAIN
) {
873 if (unsecure
!= NULL
)
874 *unsecure
= ISC_FALSE
;
875 return (ISC_R_SUCCESS
);
882 if (unsecure
!= NULL
)
883 *unsecure
= ISC_FALSE
;
889 * Find the next/previous name that has a NSEC record.
890 * In other words, skip empty database nodes and names that
891 * have had their NSECs removed because they are obscured by
895 next_active(dns_update_log_t
*log
, dns_zone_t
*zone
, dns_db_t
*db
,
896 dns_dbversion_t
*ver
, dns_name_t
*oldname
, dns_name_t
*newname
,
897 isc_boolean_t forward
)
900 dns_dbiterator_t
*dbit
= NULL
;
901 isc_boolean_t has_nsec
= ISC_FALSE
;
902 unsigned int wraps
= 0;
903 isc_boolean_t secure
= dns_db_issecure(db
);
905 CHECK(dns_db_createiterator(db
, 0, &dbit
));
907 CHECK(dns_dbiterator_seek(dbit
, oldname
));
909 dns_dbnode_t
*node
= NULL
;
912 result
= dns_dbiterator_next(dbit
);
914 result
= dns_dbiterator_prev(dbit
);
915 if (result
== ISC_R_NOMORE
) {
920 CHECK(dns_dbiterator_first(dbit
));
922 CHECK(dns_dbiterator_last(dbit
));
925 update_log(log
, zone
, ISC_LOG_ERROR
,
926 "secure zone with no NSECs");
927 result
= DNS_R_BADZONE
;
931 CHECK(dns_dbiterator_current(dbit
, &node
, newname
));
932 dns_db_detachnode(db
, &node
);
935 * The iterator may hold the tree lock, and
936 * rrset_exists() calls dns_db_findnode() which
937 * may try to reacquire it. To avoid deadlock
938 * we must pause the iterator first.
940 CHECK(dns_dbiterator_pause(dbit
));
942 CHECK(rrset_exists(db
, ver
, newname
,
943 dns_rdatatype_nsec
, 0, &has_nsec
));
945 dns_fixedname_t ffound
;
947 dns_fixedname_init(&ffound
);
948 found
= dns_fixedname_name(&ffound
);
949 result
= dns_db_find(db
, newname
, ver
,
951 DNS_DBFIND_NOWILD
, 0, NULL
, found
,
953 if (result
== ISC_R_SUCCESS
||
954 result
== DNS_R_EMPTYNAME
||
955 result
== DNS_R_NXRRSET
||
956 result
== DNS_R_CNAME
||
957 (result
== DNS_R_DELEGATION
&&
958 dns_name_equal(newname
, found
))) {
960 result
= ISC_R_SUCCESS
;
961 } else if (result
!= DNS_R_NXDOMAIN
)
964 } while (! has_nsec
);
967 dns_dbiterator_destroy(&dbit
);
973 * Add a NSEC record for "name", recording the change in "diff".
974 * The existing NSEC is removed.
977 add_nsec(dns_update_log_t
*log
, dns_zone_t
*zone
, dns_db_t
*db
,
978 dns_dbversion_t
*ver
, dns_name_t
*name
, dns_ttl_t nsecttl
,
982 dns_dbnode_t
*node
= NULL
;
983 unsigned char buffer
[DNS_NSEC_BUFFERSIZE
];
984 dns_rdata_t rdata
= DNS_RDATA_INIT
;
985 dns_difftuple_t
*tuple
= NULL
;
986 dns_fixedname_t fixedname
;
989 dns_fixedname_init(&fixedname
);
990 target
= dns_fixedname_name(&fixedname
);
993 * Find the successor name, aka NSEC target.
995 CHECK(next_active(log
, zone
, db
, ver
, name
, target
, ISC_TRUE
));
998 * Create the NSEC RDATA.
1000 CHECK(dns_db_findnode(db
, name
, ISC_FALSE
, &node
));
1001 dns_rdata_init(&rdata
);
1002 CHECK(dns_nsec_buildrdata(db
, ver
, node
, target
, buffer
, &rdata
));
1003 dns_db_detachnode(db
, &node
);
1006 * Delete the old NSEC and record the change.
1008 CHECK(delete_if(true_p
, db
, ver
, name
, dns_rdatatype_nsec
, 0,
1011 * Add the new NSEC and record the change.
1013 CHECK(dns_difftuple_create(diff
->mctx
, DNS_DIFFOP_ADD
, name
,
1014 nsecttl
, &rdata
, &tuple
));
1015 CHECK(do_one_tuple(&tuple
, db
, ver
, diff
));
1016 INSIST(tuple
== NULL
);
1020 dns_db_detachnode(db
, &node
);
1025 * Add a placeholder NSEC record for "name", recording the change in "diff".
1028 add_placeholder_nsec(dns_db_t
*db
, dns_dbversion_t
*ver
, dns_name_t
*name
,
1031 isc_result_t result
;
1032 dns_difftuple_t
*tuple
= NULL
;
1034 unsigned char data
[1] = { 0 }; /* The root domain, no bits. */
1035 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1038 r
.length
= sizeof(data
);
1039 dns_rdata_fromregion(&rdata
, dns_db_class(db
), dns_rdatatype_nsec
, &r
);
1040 CHECK(dns_difftuple_create(diff
->mctx
, DNS_DIFFOP_ADD
, name
, 0,
1042 CHECK(do_one_tuple(&tuple
, db
, ver
, diff
));
1048 find_zone_keys(dns_zone_t
*zone
, dns_db_t
*db
, dns_dbversion_t
*ver
,
1049 isc_mem_t
*mctx
, unsigned int maxkeys
,
1050 dst_key_t
**keys
, unsigned int *nkeys
)
1052 isc_result_t result
;
1053 dns_dbnode_t
*node
= NULL
;
1054 const char *directory
= dns_zone_getkeydirectory(zone
);
1055 CHECK(dns_db_findnode(db
, dns_db_origin(db
), ISC_FALSE
, &node
));
1056 CHECK(dns_dnssec_findzonekeys2(db
, ver
, node
, dns_db_origin(db
),
1057 directory
, mctx
, maxkeys
, keys
, nkeys
));
1060 dns_db_detachnode(db
, &node
);
1065 * Add RRSIG records for an RRset, recording the change in "diff".
1068 add_sigs(dns_update_log_t
*log
, dns_zone_t
*zone
, dns_db_t
*db
,
1069 dns_dbversion_t
*ver
, dns_name_t
*name
, dns_rdatatype_t type
,
1070 dns_diff_t
*diff
, dst_key_t
**keys
, unsigned int nkeys
,
1071 isc_stdtime_t inception
, isc_stdtime_t expire
,
1072 isc_boolean_t check_ksk
, isc_boolean_t keyset_kskonly
)
1074 isc_result_t result
;
1075 dns_dbnode_t
*node
= NULL
;
1076 dns_rdataset_t rdataset
;
1077 dns_rdata_t sig_rdata
= DNS_RDATA_INIT
;
1078 isc_buffer_t buffer
;
1079 unsigned char data
[1024]; /* XXX */
1081 isc_boolean_t added_sig
= ISC_FALSE
;
1082 isc_mem_t
*mctx
= diff
->mctx
;
1084 dns_rdataset_init(&rdataset
);
1085 isc_buffer_init(&buffer
, data
, sizeof(data
));
1087 /* Get the rdataset to sign. */
1088 if (type
== dns_rdatatype_nsec3
)
1089 CHECK(dns_db_findnsec3node(db
, name
, ISC_FALSE
, &node
));
1091 CHECK(dns_db_findnode(db
, name
, ISC_FALSE
, &node
));
1092 CHECK(dns_db_findrdataset(db
, node
, ver
, type
, 0,
1093 (isc_stdtime_t
) 0, &rdataset
, NULL
));
1094 dns_db_detachnode(db
, &node
);
1096 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
1097 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
1098 #define ALG(x) dst_key_alg(x)
1101 * If we are honoring KSK flags then we need to check that we
1102 * have both KSK and non-KSK keys that are not revoked per
1105 for (i
= 0; i
< nkeys
; i
++) {
1106 isc_boolean_t both
= ISC_FALSE
;
1108 if (!dst_key_isprivate(keys
[i
]))
1111 if (check_ksk
&& !REVOKE(keys
[i
])) {
1112 isc_boolean_t have_ksk
, have_nonksk
;
1114 have_ksk
= ISC_TRUE
;
1115 have_nonksk
= ISC_FALSE
;
1117 have_ksk
= ISC_FALSE
;
1118 have_nonksk
= ISC_TRUE
;
1120 for (j
= 0; j
< nkeys
; j
++) {
1121 if (j
== i
|| ALG(keys
[i
]) != ALG(keys
[j
]))
1123 if (REVOKE(keys
[j
]))
1126 have_ksk
= ISC_TRUE
;
1128 have_nonksk
= ISC_TRUE
;
1129 both
= have_ksk
&& have_nonksk
;
1136 if (type
== dns_rdatatype_dnskey
) {
1137 if (!KSK(keys
[i
]) && keyset_kskonly
)
1139 } else if (KSK(keys
[i
]))
1141 } else if (REVOKE(keys
[i
]) && type
!= dns_rdatatype_dnskey
)
1144 /* Calculate the signature, creating a RRSIG RDATA. */
1145 CHECK(dns_dnssec_sign(name
, &rdataset
, keys
[i
],
1146 &inception
, &expire
,
1147 mctx
, &buffer
, &sig_rdata
));
1149 /* Update the database and journal with the RRSIG. */
1150 /* XXX inefficient - will cause dataset merging */
1151 CHECK(update_one_rr(db
, ver
, diff
, DNS_DIFFOP_ADDRESIGN
, name
,
1152 rdataset
.ttl
, &sig_rdata
));
1153 dns_rdata_reset(&sig_rdata
);
1154 isc_buffer_init(&buffer
, data
, sizeof(data
));
1155 added_sig
= ISC_TRUE
;
1158 update_log(log
, zone
, ISC_LOG_ERROR
,
1159 "found no active private keys, "
1160 "unable to generate any signatures");
1161 result
= ISC_R_NOTFOUND
;
1165 if (dns_rdataset_isassociated(&rdataset
))
1166 dns_rdataset_disassociate(&rdataset
);
1168 dns_db_detachnode(db
, &node
);
1173 * Delete expired RRsigs and any RRsigs we are about to re-sign.
1174 * See also zone.c:del_sigs().
1177 del_keysigs(dns_db_t
*db
, dns_dbversion_t
*ver
, dns_name_t
*name
,
1178 dns_diff_t
*diff
, dst_key_t
**keys
, unsigned int nkeys
)
1180 isc_result_t result
;
1181 dns_dbnode_t
*node
= NULL
;
1182 dns_rdataset_t rdataset
;
1183 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1185 dns_rdata_rrsig_t rrsig
;
1186 isc_boolean_t found
;
1188 dns_rdataset_init(&rdataset
);
1190 result
= dns_db_findnode(db
, name
, ISC_FALSE
, &node
);
1191 if (result
== ISC_R_NOTFOUND
)
1192 return (ISC_R_SUCCESS
);
1193 if (result
!= ISC_R_SUCCESS
)
1195 result
= dns_db_findrdataset(db
, node
, ver
, dns_rdatatype_rrsig
,
1196 dns_rdatatype_dnskey
, (isc_stdtime_t
) 0,
1198 dns_db_detachnode(db
, &node
);
1200 if (result
== ISC_R_NOTFOUND
)
1201 return (ISC_R_SUCCESS
);
1202 if (result
!= ISC_R_SUCCESS
)
1205 for (result
= dns_rdataset_first(&rdataset
);
1206 result
== ISC_R_SUCCESS
;
1207 result
= dns_rdataset_next(&rdataset
)) {
1208 dns_rdataset_current(&rdataset
, &rdata
);
1209 result
= dns_rdata_tostruct(&rdata
, &rrsig
, NULL
);
1210 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1212 for (i
= 0; i
< nkeys
; i
++) {
1213 if (rrsig
.keyid
== dst_key_id(keys
[i
])) {
1215 if (!dst_key_isprivate(keys
[i
]) &&
1216 !dst_key_inactive(keys
[i
]))
1219 * The re-signing code in zone.c
1220 * will mark this as offline.
1221 * Just skip the record for now.
1225 result
= update_one_rr(db
, ver
, diff
,
1226 DNS_DIFFOP_DEL
, name
,
1227 rdataset
.ttl
, &rdata
);
1232 * If there is not a matching DNSKEY then delete the RRSIG.
1235 result
= update_one_rr(db
, ver
, diff
, DNS_DIFFOP_DEL
,
1236 name
, rdataset
.ttl
, &rdata
);
1237 dns_rdata_reset(&rdata
);
1238 if (result
!= ISC_R_SUCCESS
)
1241 dns_rdataset_disassociate(&rdataset
);
1242 if (result
== ISC_R_NOMORE
)
1243 result
= ISC_R_SUCCESS
;
1246 dns_db_detachnode(db
, &node
);
1251 add_exposed_sigs(dns_update_log_t
*log
, dns_zone_t
*zone
, dns_db_t
*db
,
1252 dns_dbversion_t
*ver
, dns_name_t
*name
, isc_boolean_t cut
,
1253 dns_diff_t
*diff
, dst_key_t
**keys
, unsigned int nkeys
,
1254 isc_stdtime_t inception
, isc_stdtime_t expire
,
1255 isc_boolean_t check_ksk
, isc_boolean_t keyset_kskonly
)
1257 isc_result_t result
;
1259 dns_rdatasetiter_t
*iter
;
1262 result
= dns_db_findnode(db
, name
, ISC_FALSE
, &node
);
1263 if (result
== ISC_R_NOTFOUND
)
1264 return (ISC_R_SUCCESS
);
1265 if (result
!= ISC_R_SUCCESS
)
1269 result
= dns_db_allrdatasets(db
, node
, ver
,
1270 (isc_stdtime_t
) 0, &iter
);
1271 if (result
!= ISC_R_SUCCESS
)
1274 for (result
= dns_rdatasetiter_first(iter
);
1275 result
== ISC_R_SUCCESS
;
1276 result
= dns_rdatasetiter_next(iter
))
1278 dns_rdataset_t rdataset
;
1279 dns_rdatatype_t type
;
1282 dns_rdataset_init(&rdataset
);
1283 dns_rdatasetiter_current(iter
, &rdataset
);
1284 type
= rdataset
.type
;
1285 dns_rdataset_disassociate(&rdataset
);
1288 * We don't need to sign unsigned NSEC records at the cut
1289 * as they are handled elsewhere.
1291 if ((type
== dns_rdatatype_rrsig
) ||
1292 (cut
&& type
!= dns_rdatatype_ds
))
1294 result
= rrset_exists(db
, ver
, name
, dns_rdatatype_rrsig
,
1296 if (result
!= ISC_R_SUCCESS
)
1297 goto cleanup_iterator
;
1300 result
= add_sigs(log
, zone
, db
, ver
, name
, type
, diff
,
1301 keys
, nkeys
, inception
, expire
,
1302 check_ksk
, keyset_kskonly
);
1303 if (result
!= ISC_R_SUCCESS
)
1304 goto cleanup_iterator
;
1306 if (result
== ISC_R_NOMORE
)
1307 result
= ISC_R_SUCCESS
;
1310 dns_rdatasetiter_destroy(&iter
);
1313 dns_db_detachnode(db
, &node
);
1319 * Update RRSIG, NSEC and NSEC3 records affected by an update. The original
1320 * update, including the SOA serial update but excluding the RRSIG & NSEC
1321 * changes, is in "diff" and has already been applied to "newver" of "db".
1322 * The database version prior to the update is "oldver".
1324 * The necessary RRSIG, NSEC and NSEC3 changes will be applied to "newver"
1325 * and added (as a minimal diff) to "diff".
1327 * The RRSIGs generated will be valid for 'sigvalidityinterval' seconds.
1330 dns_update_signatures(dns_update_log_t
*log
, dns_zone_t
*zone
, dns_db_t
*db
,
1331 dns_dbversion_t
*oldver
, dns_dbversion_t
*newver
,
1332 dns_diff_t
*diff
, isc_uint32_t sigvalidityinterval
)
1334 isc_result_t result
;
1336 dns_diff_t diffnames
;
1337 dns_diff_t affected
;
1338 dns_diff_t sig_diff
;
1339 dns_diff_t nsec_diff
;
1340 dns_diff_t nsec_mindiff
;
1341 isc_boolean_t flag
, build_nsec
, build_nsec3
;
1342 dst_key_t
*zone_keys
[DNS_MAXZONEKEYS
];
1343 unsigned int nkeys
= 0;
1345 isc_stdtime_t now
, inception
, expire
;
1347 dns_rdata_soa_t soa
;
1348 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1349 dns_rdataset_t rdataset
;
1350 dns_dbnode_t
*node
= NULL
;
1351 isc_boolean_t check_ksk
, keyset_kskonly
;
1352 isc_boolean_t unsecure
;
1354 dns_rdatatype_t privatetype
= dns_zone_getprivatetype(zone
);
1356 dns_diff_init(diff
->mctx
, &diffnames
);
1357 dns_diff_init(diff
->mctx
, &affected
);
1359 dns_diff_init(diff
->mctx
, &sig_diff
);
1360 dns_diff_init(diff
->mctx
, &nsec_diff
);
1361 dns_diff_init(diff
->mctx
, &nsec_mindiff
);
1363 result
= find_zone_keys(zone
, db
, newver
, diff
->mctx
,
1364 DNS_MAXZONEKEYS
, zone_keys
, &nkeys
);
1365 if (result
!= ISC_R_SUCCESS
) {
1366 update_log(log
, zone
, ISC_LOG_ERROR
,
1367 "could not get zone keys for secure dynamic update");
1371 isc_stdtime_get(&now
);
1372 inception
= now
- 3600; /* Allow for some clock skew. */
1373 expire
= now
+ sigvalidityinterval
;
1376 * Do we look at the KSK flag on the DNSKEY to determining which
1377 * keys sign which RRsets? First check the zone option then
1378 * check the keys flags to make sure at least one has a ksk set
1381 check_ksk
= ISC_TF((dns_zone_getoptions(zone
) &
1382 DNS_ZONEOPT_UPDATECHECKKSK
) != 0);
1383 keyset_kskonly
= ISC_TF((dns_zone_getoptions(zone
) &
1384 DNS_ZONEOPT_DNSKEYKSKONLY
) != 0);
1387 * Get the NSEC/NSEC3 TTL from the SOA MINIMUM field.
1389 CHECK(dns_db_findnode(db
, dns_db_origin(db
), ISC_FALSE
, &node
));
1390 dns_rdataset_init(&rdataset
);
1391 CHECK(dns_db_findrdataset(db
, node
, newver
, dns_rdatatype_soa
, 0,
1392 (isc_stdtime_t
) 0, &rdataset
, NULL
));
1393 CHECK(dns_rdataset_first(&rdataset
));
1394 dns_rdataset_current(&rdataset
, &rdata
);
1395 CHECK(dns_rdata_tostruct(&rdata
, &soa
, NULL
));
1396 nsecttl
= soa
.minimum
;
1397 dns_rdataset_disassociate(&rdataset
);
1398 dns_db_detachnode(db
, &node
);
1401 * Find all RRsets directly affected by the update, and
1402 * update their RRSIGs. Also build a list of names affected
1403 * by the update in "diffnames".
1405 CHECK(dns_diff_sort(diff
, temp_order
));
1407 t
= ISC_LIST_HEAD(diff
->tuples
);
1409 dns_name_t
*name
= &t
->name
;
1410 /* Now "name" is a new, unique name affected by the update. */
1412 CHECK(namelist_append_name(&diffnames
, name
));
1414 while (t
!= NULL
&& dns_name_equal(&t
->name
, name
)) {
1415 dns_rdatatype_t type
;
1416 type
= t
->rdata
.type
;
1419 * Now "name" and "type" denote a new unique RRset
1420 * affected by the update.
1423 /* Don't sign RRSIGs. */
1424 if (type
== dns_rdatatype_rrsig
)
1428 * Delete all old RRSIGs covering this type, since they
1429 * are all invalid when the signed RRset has changed.
1430 * We may not be able to recreate all of them - tough.
1431 * Special case changes to the zone's DNSKEY records
1432 * to support offline KSKs.
1434 if (type
== dns_rdatatype_dnskey
)
1435 del_keysigs(db
, newver
, name
, &sig_diff
,
1438 CHECK(delete_if(true_p
, db
, newver
, name
,
1439 dns_rdatatype_rrsig
, type
,
1443 * If this RRset is still visible after the update,
1444 * add a new signature for it.
1446 CHECK(rrset_visible(db
, newver
, name
, type
, &flag
));
1448 CHECK(add_sigs(log
, zone
, db
, newver
, name
,
1449 type
, &sig_diff
, zone_keys
,
1450 nkeys
, inception
, expire
,
1451 check_ksk
, keyset_kskonly
));
1454 /* Skip any other updates to the same RRset. */
1456 dns_name_equal(&t
->name
, name
) &&
1457 t
->rdata
.type
== type
)
1459 t
= ISC_LIST_NEXT(t
, link
);
1463 update_log(log
, zone
, ISC_LOG_DEBUG(3), "updated data signatures");
1465 /* Remove orphaned NSECs and RRSIG NSECs. */
1466 for (t
= ISC_LIST_HEAD(diffnames
.tuples
);
1468 t
= ISC_LIST_NEXT(t
, link
))
1470 CHECK(non_nsec_rrset_exists(db
, newver
, &t
->name
, &flag
));
1472 CHECK(delete_if(true_p
, db
, newver
, &t
->name
,
1473 dns_rdatatype_any
, 0,
1477 update_log(log
, zone
, ISC_LOG_DEBUG(3),
1478 "removed any orphaned NSEC records");
1481 * See if we need to build NSEC or NSEC3 chains.
1483 CHECK(dns_private_chains(db
, newver
, privatetype
, &build_nsec
,
1488 update_log(log
, zone
, ISC_LOG_DEBUG(3), "rebuilding NSEC chain");
1491 * When a name is created or deleted, its predecessor needs to
1492 * have its NSEC updated.
1494 for (t
= ISC_LIST_HEAD(diffnames
.tuples
);
1496 t
= ISC_LIST_NEXT(t
, link
))
1498 isc_boolean_t existed
, exists
;
1499 dns_fixedname_t fixedname
;
1500 dns_name_t
*prevname
;
1502 dns_fixedname_init(&fixedname
);
1503 prevname
= dns_fixedname_name(&fixedname
);
1506 CHECK(name_exists(db
, oldver
, &t
->name
, &existed
));
1508 existed
= ISC_FALSE
;
1509 CHECK(name_exists(db
, newver
, &t
->name
, &exists
));
1510 if (exists
== existed
)
1514 * Find the predecessor.
1515 * When names become obscured or unobscured in this update
1516 * transaction, we may find the wrong predecessor because
1517 * the NSECs have not yet been updated to reflect the delegation
1518 * change. This should not matter because in this case,
1519 * the correct predecessor is either the delegation node or
1520 * a newly unobscured node, and those nodes are on the
1521 * "affected" list in any case.
1523 CHECK(next_active(log
, zone
, db
, newver
,
1524 &t
->name
, prevname
, ISC_FALSE
));
1525 CHECK(namelist_append_name(&affected
, prevname
));
1529 * Find names potentially affected by delegation changes
1530 * (obscured by adding an NS or DNAME, or unobscured by
1533 for (t
= ISC_LIST_HEAD(diffnames
.tuples
);
1535 t
= ISC_LIST_NEXT(t
, link
))
1537 isc_boolean_t ns_existed
, dname_existed
;
1538 isc_boolean_t ns_exists
, dname_exists
;
1541 CHECK(rrset_exists(db
, oldver
, &t
->name
,
1542 dns_rdatatype_ns
, 0, &ns_existed
));
1544 ns_existed
= ISC_FALSE
;
1546 CHECK(rrset_exists(db
, oldver
, &t
->name
,
1547 dns_rdatatype_dname
, 0,
1550 dname_existed
= ISC_FALSE
;
1551 CHECK(rrset_exists(db
, newver
, &t
->name
, dns_rdatatype_ns
, 0,
1553 CHECK(rrset_exists(db
, newver
, &t
->name
, dns_rdatatype_dname
, 0,
1555 if ((ns_exists
|| dname_exists
) == (ns_existed
|| dname_existed
))
1558 * There was a delegation change. Mark all subdomains
1559 * of t->name as potentially needing a NSEC update.
1561 CHECK(namelist_append_subdomain(db
, &t
->name
, &affected
));
1564 ISC_LIST_APPENDLIST(affected
.tuples
, diffnames
.tuples
, link
);
1565 INSIST(ISC_LIST_EMPTY(diffnames
.tuples
));
1567 CHECK(uniqify_name_list(&affected
));
1570 * Determine which names should have NSECs, and delete/create
1571 * NSECs to make it so. We don't know the final NSEC targets yet,
1572 * so we just create placeholder NSECs with arbitrary contents
1573 * to indicate that their respective owner names should be part of
1576 for (t
= ISC_LIST_HEAD(affected
.tuples
);
1578 t
= ISC_LIST_NEXT(t
, link
))
1580 isc_boolean_t exists
;
1581 dns_name_t
*name
= &t
->name
;
1583 CHECK(name_exists(db
, newver
, name
, &exists
));
1586 CHECK(is_active(db
, newver
, name
, &flag
, &cut
, NULL
));
1589 * This name is obscured. Delete any
1590 * existing NSEC record.
1592 CHECK(delete_if(true_p
, db
, newver
, name
,
1593 dns_rdatatype_nsec
, 0,
1595 CHECK(delete_if(rrsig_p
, db
, newver
, name
,
1596 dns_rdatatype_any
, 0, NULL
, diff
));
1599 * This name is not obscured. It needs to have a
1600 * NSEC unless it is the at the origin, in which
1601 * case it should already exist if there is a complete
1602 * NSEC chain and if there isn't a complete NSEC chain
1603 * we don't want to add one as that would signal that
1604 * there is a complete NSEC chain.
1606 if (!dns_name_equal(name
, dns_db_origin(db
))) {
1607 CHECK(rrset_exists(db
, newver
, name
,
1608 dns_rdatatype_nsec
, 0,
1611 CHECK(add_placeholder_nsec(db
, newver
,
1614 CHECK(add_exposed_sigs(log
, zone
, db
, newver
, name
,
1615 cut
, &sig_diff
, zone_keys
, nkeys
,
1616 inception
, expire
, check_ksk
,
1622 * Now we know which names are part of the NSEC chain.
1623 * Make them all point at their correct targets.
1625 for (t
= ISC_LIST_HEAD(affected
.tuples
);
1627 t
= ISC_LIST_NEXT(t
, link
))
1629 CHECK(rrset_exists(db
, newver
, &t
->name
,
1630 dns_rdatatype_nsec
, 0, &flag
));
1633 * There is a NSEC, but we don't know if it is correct.
1634 * Delete it and create a correct one to be sure.
1635 * If the update was unnecessary, the diff minimization
1636 * will take care of eliminating it from the journal,
1639 * The RRSIG bit should always be set in the NSECs
1640 * we generate, because they will all get RRSIG NSECs.
1641 * (XXX what if the zone keys are missing?).
1642 * Because the RRSIG NSECs have not necessarily been
1643 * created yet, the correctness of the bit mask relies
1644 * on the assumption that NSECs are only created if
1645 * there is other data, and if there is other data,
1646 * there are other RRSIGs.
1648 CHECK(add_nsec(log
, zone
, db
, newver
, &t
->name
,
1649 nsecttl
, &nsec_diff
));
1654 * Minimize the set of NSEC updates so that we don't
1655 * have to regenerate the RRSIG NSECs for NSECs that were
1656 * replaced with identical ones.
1658 while ((t
= ISC_LIST_HEAD(nsec_diff
.tuples
)) != NULL
) {
1659 ISC_LIST_UNLINK(nsec_diff
.tuples
, t
, link
);
1660 dns_diff_appendminimal(&nsec_mindiff
, &t
);
1663 update_log(log
, zone
, ISC_LOG_DEBUG(3), "signing rebuilt NSEC chain");
1665 /* Update RRSIG NSECs. */
1666 for (t
= ISC_LIST_HEAD(nsec_mindiff
.tuples
);
1668 t
= ISC_LIST_NEXT(t
, link
))
1670 if (t
->op
== DNS_DIFFOP_DEL
) {
1671 CHECK(delete_if(true_p
, db
, newver
, &t
->name
,
1672 dns_rdatatype_rrsig
, dns_rdatatype_nsec
,
1674 } else if (t
->op
== DNS_DIFFOP_ADD
) {
1675 CHECK(add_sigs(log
, zone
, db
, newver
, &t
->name
,
1676 dns_rdatatype_nsec
, &sig_diff
,
1677 zone_keys
, nkeys
, inception
, expire
,
1678 check_ksk
, keyset_kskonly
));
1686 /* Record our changes for the journal. */
1687 while ((t
= ISC_LIST_HEAD(sig_diff
.tuples
)) != NULL
) {
1688 ISC_LIST_UNLINK(sig_diff
.tuples
, t
, link
);
1689 dns_diff_appendminimal(diff
, &t
);
1691 while ((t
= ISC_LIST_HEAD(nsec_mindiff
.tuples
)) != NULL
) {
1692 ISC_LIST_UNLINK(nsec_mindiff
.tuples
, t
, link
);
1693 dns_diff_appendminimal(diff
, &t
);
1696 INSIST(ISC_LIST_EMPTY(sig_diff
.tuples
));
1697 INSIST(ISC_LIST_EMPTY(nsec_diff
.tuples
));
1698 INSIST(ISC_LIST_EMPTY(nsec_mindiff
.tuples
));
1701 update_log(log
, zone
, ISC_LOG_DEBUG(3),
1702 "no NSEC3 chains to rebuild");
1706 update_log(log
, zone
, ISC_LOG_DEBUG(3), "rebuilding NSEC3 chains");
1708 dns_diff_clear(&diffnames
);
1709 dns_diff_clear(&affected
);
1711 CHECK(dns_diff_sort(diff
, temp_order
));
1714 * Find names potentially affected by delegation changes
1715 * (obscured by adding an NS or DNAME, or unobscured by
1718 t
= ISC_LIST_HEAD(diff
->tuples
);
1720 dns_name_t
*name
= &t
->name
;
1722 isc_boolean_t ns_existed
, dname_existed
;
1723 isc_boolean_t ns_exists
, dname_exists
;
1724 isc_boolean_t exists
, existed
;
1726 if (t
->rdata
.type
== dns_rdatatype_nsec
||
1727 t
->rdata
.type
== dns_rdatatype_rrsig
) {
1728 t
= ISC_LIST_NEXT(t
, link
);
1732 CHECK(namelist_append_name(&affected
, name
));
1735 CHECK(rrset_exists(db
, oldver
, name
, dns_rdatatype_ns
,
1738 ns_existed
= ISC_FALSE
;
1740 CHECK(rrset_exists(db
, oldver
, name
,
1741 dns_rdatatype_dname
, 0,
1744 dname_existed
= ISC_FALSE
;
1745 CHECK(rrset_exists(db
, newver
, name
, dns_rdatatype_ns
, 0,
1747 CHECK(rrset_exists(db
, newver
, name
, dns_rdatatype_dname
, 0,
1750 exists
= ns_exists
|| dname_exists
;
1751 existed
= ns_existed
|| dname_existed
;
1752 if (exists
== existed
)
1755 * There was a delegation change. Mark all subdomains
1756 * of t->name as potentially needing a NSEC3 update.
1758 CHECK(namelist_append_subdomain(db
, name
, &affected
));
1761 while (t
!= NULL
&& dns_name_equal(&t
->name
, name
))
1762 t
= ISC_LIST_NEXT(t
, link
);
1765 for (t
= ISC_LIST_HEAD(affected
.tuples
);
1767 t
= ISC_LIST_NEXT(t
, link
)) {
1768 dns_name_t
*name
= &t
->name
;
1770 unsecure
= ISC_FALSE
; /* Silence compiler warning. */
1771 CHECK(is_active(db
, newver
, name
, &flag
, &cut
, &unsecure
));
1774 CHECK(delete_if(rrsig_p
, db
, newver
, name
,
1775 dns_rdatatype_any
, 0, NULL
, diff
));
1776 CHECK(dns_nsec3_delnsec3sx(db
, newver
, name
,
1777 privatetype
, &nsec_diff
));
1779 CHECK(add_exposed_sigs(log
, zone
, db
, newver
, name
,
1780 cut
, &sig_diff
, zone_keys
, nkeys
,
1781 inception
, expire
, check_ksk
,
1783 CHECK(dns_nsec3_addnsec3sx(db
, newver
, name
, nsecttl
,
1784 unsecure
, privatetype
,
1790 * Minimize the set of NSEC3 updates so that we don't
1791 * have to regenerate the RRSIG NSEC3s for NSEC3s that were
1792 * replaced with identical ones.
1794 while ((t
= ISC_LIST_HEAD(nsec_diff
.tuples
)) != NULL
) {
1795 ISC_LIST_UNLINK(nsec_diff
.tuples
, t
, link
);
1796 dns_diff_appendminimal(&nsec_mindiff
, &t
);
1799 update_log(log
, zone
, ISC_LOG_DEBUG(3),
1800 "signing rebuilt NSEC3 chain");
1802 /* Update RRSIG NSEC3s. */
1803 for (t
= ISC_LIST_HEAD(nsec_mindiff
.tuples
);
1805 t
= ISC_LIST_NEXT(t
, link
))
1807 if (t
->op
== DNS_DIFFOP_DEL
) {
1808 CHECK(delete_if(true_p
, db
, newver
, &t
->name
,
1809 dns_rdatatype_rrsig
,
1810 dns_rdatatype_nsec3
,
1812 } else if (t
->op
== DNS_DIFFOP_ADD
) {
1813 CHECK(add_sigs(log
, zone
, db
, newver
, &t
->name
,
1814 dns_rdatatype_nsec3
,
1815 &sig_diff
, zone_keys
, nkeys
,
1816 inception
, expire
, check_ksk
,
1823 /* Record our changes for the journal. */
1824 while ((t
= ISC_LIST_HEAD(sig_diff
.tuples
)) != NULL
) {
1825 ISC_LIST_UNLINK(sig_diff
.tuples
, t
, link
);
1826 dns_diff_appendminimal(diff
, &t
);
1828 while ((t
= ISC_LIST_HEAD(nsec_mindiff
.tuples
)) != NULL
) {
1829 ISC_LIST_UNLINK(nsec_mindiff
.tuples
, t
, link
);
1830 dns_diff_appendminimal(diff
, &t
);
1833 INSIST(ISC_LIST_EMPTY(sig_diff
.tuples
));
1834 INSIST(ISC_LIST_EMPTY(nsec_diff
.tuples
));
1835 INSIST(ISC_LIST_EMPTY(nsec_mindiff
.tuples
));
1838 dns_diff_clear(&sig_diff
);
1839 dns_diff_clear(&nsec_diff
);
1840 dns_diff_clear(&nsec_mindiff
);
1842 dns_diff_clear(&affected
);
1843 dns_diff_clear(&diffnames
);
1845 for (i
= 0; i
< nkeys
; i
++)
1846 dst_key_free(&zone_keys
[i
]);
1852 dns_update_soaserial(isc_uint32_t serial
, dns_updatemethod_t method
) {
1855 if (method
== dns_updatemethod_unixtime
) {
1856 isc_stdtime_get(&now
);
1857 if (now
!= 0 && isc_serial_gt(now
, serial
))
1862 serial
= (serial
+ 1) & 0xFFFFFFFF;