00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <config.h>
00018
00019 #include <time.h>
00020
00021 #include <isc/log.h>
00022 #include <isc/magic.h>
00023 #include <isc/mem.h>
00024 #include <isc/netaddr.h>
00025 #include <isc/print.h>
00026 #include <isc/serial.h>
00027 #include <isc/stats.h>
00028 #include <isc/stdtime.h>
00029 #include <isc/string.h>
00030 #include <isc/taskpool.h>
00031 #include <isc/time.h>
00032 #include <isc/util.h>
00033
00034 #include <dns/db.h>
00035 #include <dns/dbiterator.h>
00036 #include <dns/diff.h>
00037 #include <dns/dnssec.h>
00038 #include <dns/events.h>
00039 #include <dns/fixedname.h>
00040 #include <dns/journal.h>
00041 #include <dns/keyvalues.h>
00042 #include <dns/log.h>
00043 #include <dns/message.h>
00044 #include <dns/nsec.h>
00045 #include <dns/nsec3.h>
00046 #include <dns/private.h>
00047 #include <dns/rdataclass.h>
00048 #include <dns/rdataset.h>
00049 #include <dns/rdatasetiter.h>
00050 #include <dns/rdatastruct.h>
00051 #include <dns/rdatatype.h>
00052 #include <dns/result.h>
00053 #include <dns/soa.h>
00054 #include <dns/ssu.h>
00055 #include <dns/tsig.h>
00056 #include <dns/update.h>
00057 #include <dns/view.h>
00058 #include <dns/zone.h>
00059 #include <dns/zt.h>
00060
00061
00062
00063
00064 #define STATE_MAGIC ISC_MAGIC('S', 'T', 'T', 'E')
00065 #define DNS_STATE_VALID(state) ISC_MAGIC_VALID(state, STATE_MAGIC)
00066
00067
00068
00069
00070 #define LOGLEVEL_PROTOCOL ISC_LOG_INFO
00071
00072
00073
00074
00075 #define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8)
00076
00077
00078
00079
00080
00081
00082 #define CHECK(op) \
00083 do { result = (op); \
00084 if (result != ISC_R_SUCCESS) goto failure; \
00085 } while (0)
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 #define FAIL(code) \
00097 do { \
00098 result = (code); \
00099 if (result != ISC_R_SUCCESS) goto failure; \
00100 } while (0)
00101
00102
00103
00104
00105
00106
00107 #define FAILC(code, msg) \
00108 do { \
00109 const char *_what = "failed"; \
00110 result = (code); \
00111 switch (result) { \
00112 case DNS_R_NXDOMAIN: \
00113 case DNS_R_YXDOMAIN: \
00114 case DNS_R_YXRRSET: \
00115 case DNS_R_NXRRSET: \
00116 _what = "unsuccessful"; \
00117 } \
00118 update_log(log, zone, LOGLEVEL_PROTOCOL, \
00119 "update %s: %s (%s)", _what, \
00120 msg, isc_result_totext(result)); \
00121 if (result != ISC_R_SUCCESS) goto failure; \
00122 } while (0)
00123
00124 #define FAILN(code, name, msg) \
00125 do { \
00126 const char *_what = "failed"; \
00127 result = (code); \
00128 switch (result) { \
00129 case DNS_R_NXDOMAIN: \
00130 case DNS_R_YXDOMAIN: \
00131 case DNS_R_YXRRSET: \
00132 case DNS_R_NXRRSET: \
00133 _what = "unsuccessful"; \
00134 } \
00135 if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) { \
00136 char _nbuf[DNS_NAME_FORMATSIZE]; \
00137 dns_name_format(name, _nbuf, sizeof(_nbuf)); \
00138 update_log(log, zone, LOGLEVEL_PROTOCOL, \
00139 "update %s: %s: %s (%s)", _what, _nbuf, \
00140 msg, isc_result_totext(result)); \
00141 } \
00142 if (result != ISC_R_SUCCESS) goto failure; \
00143 } while (0)
00144
00145 #define FAILNT(code, name, type, msg) \
00146 do { \
00147 const char *_what = "failed"; \
00148 result = (code); \
00149 switch (result) { \
00150 case DNS_R_NXDOMAIN: \
00151 case DNS_R_YXDOMAIN: \
00152 case DNS_R_YXRRSET: \
00153 case DNS_R_NXRRSET: \
00154 _what = "unsuccessful"; \
00155 } \
00156 if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) { \
00157 char _nbuf[DNS_NAME_FORMATSIZE]; \
00158 char _tbuf[DNS_RDATATYPE_FORMATSIZE]; \
00159 dns_name_format(name, _nbuf, sizeof(_nbuf)); \
00160 dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \
00161 update_log(log, zone, LOGLEVEL_PROTOCOL, \
00162 "update %s: %s/%s: %s (%s)", \
00163 _what, _nbuf, _tbuf, msg, \
00164 isc_result_totext(result)); \
00165 } \
00166 if (result != ISC_R_SUCCESS) goto failure; \
00167 } while (0)
00168
00169
00170
00171
00172
00173
00174 #define FAILS(code, msg) \
00175 do { \
00176 result = (code); \
00177 update_log(log, zone, LOGLEVEL_PROTOCOL, \
00178 "error: %s: %s", \
00179 msg, isc_result_totext(result)); \
00180 if (result != ISC_R_SUCCESS) goto failure; \
00181 } while (0)
00182
00183
00184
00185 typedef struct rr rr_t;
00186
00187 struct rr {
00188
00189 isc_uint32_t ttl;
00190 dns_rdata_t rdata;
00191 };
00192
00193 typedef struct update_event update_event_t;
00194
00195
00196
00197 static void
00198 update_log(dns_update_log_t *callback, dns_zone_t *zone,
00199 int level, const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
00200
00201 static void
00202 update_log(dns_update_log_t *callback, dns_zone_t *zone,
00203 int level, const char *fmt, ...)
00204 {
00205 va_list ap;
00206 char message[4096];
00207
00208 if (callback == NULL)
00209 return;
00210
00211 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
00212 return;
00213
00214
00215 va_start(ap, fmt);
00216 vsnprintf(message, sizeof(message), fmt, ap);
00217 va_end(ap);
00218
00219 (callback->func)(callback->arg, zone, level, message);
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 static isc_result_t
00231 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
00232 dns_diff_t *diff)
00233 {
00234 dns_diff_t temp_diff;
00235 isc_result_t result;
00236
00237
00238
00239
00240 dns_diff_init(diff->mctx, &temp_diff);
00241 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
00242
00243
00244
00245
00246 result = dns_diff_apply(&temp_diff, db, ver);
00247 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
00248 if (result != ISC_R_SUCCESS) {
00249 dns_difftuple_free(tuple);
00250 return (result);
00251 }
00252
00253
00254
00255
00256 dns_diff_appendminimal(diff, tuple);
00257
00258
00259
00260
00261 return (ISC_R_SUCCESS);
00262 }
00263
00264 static isc_result_t
00265 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
00266 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
00267 dns_rdata_t *rdata)
00268 {
00269 dns_difftuple_t *tuple = NULL;
00270 isc_result_t result;
00271 result = dns_difftuple_create(diff->mctx, op,
00272 name, ttl, rdata, &tuple);
00273 if (result != ISC_R_SUCCESS)
00274 return (result);
00275 return (do_one_tuple(&tuple, db, ver, diff));
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 typedef isc_result_t rrset_func(void *data, dns_rdataset_t *rrset);
00302
00303
00304
00305
00306 typedef isc_result_t rr_func(void *data, rr_t *rr);
00307
00308
00309
00310
00311 typedef struct {
00312 rr_func * rr_action;
00313 void * rr_action_data;
00314 } foreach_node_rr_ctx_t;
00315
00316
00317
00318
00319 static isc_result_t
00320 foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) {
00321 isc_result_t result;
00322 foreach_node_rr_ctx_t *ctx = data;
00323 for (result = dns_rdataset_first(rdataset);
00324 result == ISC_R_SUCCESS;
00325 result = dns_rdataset_next(rdataset))
00326 {
00327 rr_t rr = { 0, DNS_RDATA_INIT };
00328
00329 dns_rdataset_current(rdataset, &rr.rdata);
00330 rr.ttl = rdataset->ttl;
00331 result = (*ctx->rr_action)(ctx->rr_action_data, &rr);
00332 if (result != ISC_R_SUCCESS)
00333 return (result);
00334 }
00335 if (result != ISC_R_NOMORE)
00336 return (result);
00337 return (ISC_R_SUCCESS);
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347 static isc_result_t
00348 foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00349 rrset_func *action, void *action_data)
00350 {
00351 isc_result_t result;
00352 dns_dbnode_t *node;
00353 dns_rdatasetiter_t *iter;
00354
00355 node = NULL;
00356 result = dns_db_findnode(db, name, ISC_FALSE, &node);
00357 if (result == ISC_R_NOTFOUND)
00358 return (ISC_R_SUCCESS);
00359 if (result != ISC_R_SUCCESS)
00360 return (result);
00361
00362 iter = NULL;
00363 result = dns_db_allrdatasets(db, node, ver,
00364 (isc_stdtime_t) 0, &iter);
00365 if (result != ISC_R_SUCCESS)
00366 goto cleanup_node;
00367
00368 for (result = dns_rdatasetiter_first(iter);
00369 result == ISC_R_SUCCESS;
00370 result = dns_rdatasetiter_next(iter))
00371 {
00372 dns_rdataset_t rdataset;
00373
00374 dns_rdataset_init(&rdataset);
00375 dns_rdatasetiter_current(iter, &rdataset);
00376
00377 result = (*action)(action_data, &rdataset);
00378
00379 dns_rdataset_disassociate(&rdataset);
00380 if (result != ISC_R_SUCCESS)
00381 goto cleanup_iterator;
00382 }
00383 if (result == ISC_R_NOMORE)
00384 result = ISC_R_SUCCESS;
00385
00386 cleanup_iterator:
00387 dns_rdatasetiter_destroy(&iter);
00388
00389 cleanup_node:
00390 dns_db_detachnode(db, &node);
00391
00392 return (result);
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 static isc_result_t
00404 foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00405 rr_func *rr_action, void *rr_action_data)
00406 {
00407 foreach_node_rr_ctx_t ctx;
00408 ctx.rr_action = rr_action;
00409 ctx.rr_action_data = rr_action_data;
00410 return (foreach_rrset(db, ver, name,
00411 foreach_node_rr_action, &ctx));
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 static isc_result_t
00425 foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00426 dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action,
00427 void *rr_action_data)
00428 {
00429
00430 isc_result_t result;
00431 dns_dbnode_t *node;
00432 dns_rdataset_t rdataset;
00433
00434 if (type == dns_rdatatype_any)
00435 return (foreach_node_rr(db, ver, name,
00436 rr_action, rr_action_data));
00437
00438 node = NULL;
00439 if (type == dns_rdatatype_nsec3 ||
00440 (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3))
00441 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
00442 else
00443 result = dns_db_findnode(db, name, ISC_FALSE, &node);
00444 if (result == ISC_R_NOTFOUND)
00445 return (ISC_R_SUCCESS);
00446 if (result != ISC_R_SUCCESS)
00447 return (result);
00448
00449 dns_rdataset_init(&rdataset);
00450 result = dns_db_findrdataset(db, node, ver, type, covers,
00451 (isc_stdtime_t) 0, &rdataset, NULL);
00452 if (result == ISC_R_NOTFOUND) {
00453 result = ISC_R_SUCCESS;
00454 goto cleanup_node;
00455 }
00456 if (result != ISC_R_SUCCESS)
00457 goto cleanup_node;
00458
00459 for (result = dns_rdataset_first(&rdataset);
00460 result == ISC_R_SUCCESS;
00461 result = dns_rdataset_next(&rdataset))
00462 {
00463 rr_t rr = { 0, DNS_RDATA_INIT };
00464 dns_rdataset_current(&rdataset, &rr.rdata);
00465 rr.ttl = rdataset.ttl;
00466 result = (*rr_action)(rr_action_data, &rr);
00467 if (result != ISC_R_SUCCESS)
00468 goto cleanup_rdataset;
00469 }
00470 if (result != ISC_R_NOMORE)
00471 goto cleanup_rdataset;
00472 result = ISC_R_SUCCESS;
00473
00474 cleanup_rdataset:
00475 dns_rdataset_disassociate(&rdataset);
00476 cleanup_node:
00477 dns_db_detachnode(db, &node);
00478
00479 return (result);
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 typedef isc_boolean_t rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr);
00492
00493
00494
00495
00496 static isc_result_t
00497 rrset_exists_action(void *data, rr_t *rr) {
00498 UNUSED(data);
00499 UNUSED(rr);
00500 return (ISC_R_EXISTS);
00501 }
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 #define RETURN_EXISTENCE_FLAG \
00517 return ((result == ISC_R_EXISTS) ? \
00518 (*exists = ISC_TRUE, ISC_R_SUCCESS) : \
00519 ((result == ISC_R_SUCCESS) ? \
00520 (*exists = ISC_FALSE, ISC_R_SUCCESS) : \
00521 result))
00522
00523
00524
00525
00526
00527 static isc_result_t
00528 rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00529 dns_rdatatype_t type, dns_rdatatype_t covers,
00530 isc_boolean_t *exists)
00531 {
00532 isc_result_t result;
00533 result = foreach_rr(db, ver, name, type, covers,
00534 rrset_exists_action, NULL);
00535 RETURN_EXISTENCE_FLAG;
00536 }
00537
00538
00539
00540
00541
00542
00543 static isc_result_t
00544 rrset_visible(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00545 dns_rdatatype_t type, isc_boolean_t *visible)
00546 {
00547 isc_result_t result;
00548 dns_fixedname_t fixed;
00549
00550 dns_fixedname_init(&fixed);
00551 result = dns_db_find(db, name, ver, type, DNS_DBFIND_NOWILD,
00552 (isc_stdtime_t) 0, NULL,
00553 dns_fixedname_name(&fixed), NULL, NULL);
00554 switch (result) {
00555 case ISC_R_SUCCESS:
00556 *visible = ISC_TRUE;
00557 break;
00558
00559
00560
00561 case DNS_R_DELEGATION:
00562 case DNS_R_DNAME:
00563 case DNS_R_CNAME:
00564 case DNS_R_NXDOMAIN:
00565 case DNS_R_NXRRSET:
00566 case DNS_R_EMPTYNAME:
00567 case DNS_R_COVERINGNSEC:
00568 *visible = ISC_FALSE;
00569 result = ISC_R_SUCCESS;
00570 break;
00571 default:
00572 break;
00573 }
00574 return (result);
00575 }
00576
00577
00578
00579
00580
00581 static isc_result_t
00582 name_exists_action(void *data, dns_rdataset_t *rrset) {
00583 UNUSED(data);
00584 UNUSED(rrset);
00585 return (ISC_R_EXISTS);
00586 }
00587
00588
00589
00590
00591 static isc_result_t
00592 name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00593 isc_boolean_t *exists)
00594 {
00595 isc_result_t result;
00596 result = foreach_rrset(db, ver, name,
00597 name_exists_action, NULL);
00598 RETURN_EXISTENCE_FLAG;
00599 }
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 static int
00618 temp_order(const void *av, const void *bv) {
00619 dns_difftuple_t const * const *ap = av;
00620 dns_difftuple_t const * const *bp = bv;
00621 dns_difftuple_t const *a = *ap;
00622 dns_difftuple_t const *b = *bp;
00623 int r;
00624 r = dns_name_compare(&a->name, &b->name);
00625 if (r != 0)
00626 return (r);
00627 r = (b->rdata.type - a->rdata.type);
00628 if (r != 0)
00629 return (r);
00630 r = dns_rdata_casecompare(&a->rdata, &b->rdata);
00631 return (r);
00632 }
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 typedef struct {
00644 rr_predicate *predicate;
00645 dns_db_t *db;
00646 dns_dbversion_t *ver;
00647 dns_diff_t *diff;
00648 dns_name_t *name;
00649 dns_rdata_t *update_rr;
00650 } conditional_delete_ctx_t;
00651
00652
00653
00654
00655
00656
00657
00658
00659 static isc_boolean_t
00660 true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
00661 UNUSED(update_rr);
00662 UNUSED(db_rr);
00663 return (ISC_TRUE);
00664 }
00665
00666
00667
00668
00669 static isc_boolean_t
00670 rrsig_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
00671 UNUSED(update_rr);
00672 return ((db_rr->type == dns_rdatatype_rrsig) ?
00673 ISC_TRUE : ISC_FALSE);
00674 }
00675
00676
00677
00678
00679 static isc_result_t
00680 delete_if_action(void *data, rr_t *rr) {
00681 conditional_delete_ctx_t *ctx = data;
00682 if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) {
00683 isc_result_t result;
00684 result = update_one_rr(ctx->db, ctx->ver, ctx->diff,
00685 DNS_DIFFOP_DEL, ctx->name,
00686 rr->ttl, &rr->rdata);
00687 return (result);
00688 } else {
00689 return (ISC_R_SUCCESS);
00690 }
00691 }
00692
00693
00694
00695
00696
00697
00698
00699
00700 static isc_result_t
00701 delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver,
00702 dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers,
00703 dns_rdata_t *update_rr, dns_diff_t *diff)
00704 {
00705 conditional_delete_ctx_t ctx;
00706 ctx.predicate = predicate;
00707 ctx.db = db;
00708 ctx.ver = ver;
00709 ctx.diff = diff;
00710 ctx.name = name;
00711 ctx.update_rr = update_rr;
00712 return (foreach_rr(db, ver, name, type, covers,
00713 delete_if_action, &ctx));
00714 }
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725 static isc_result_t
00726 namelist_append_name(dns_diff_t *list, dns_name_t *name) {
00727 isc_result_t result;
00728 dns_difftuple_t *tuple = NULL;
00729 static dns_rdata_t dummy_rdata = DNS_RDATA_INIT;
00730
00731 CHECK(dns_difftuple_create(list->mctx, DNS_DIFFOP_EXISTS, name, 0,
00732 &dummy_rdata, &tuple));
00733 dns_diff_append(list, &tuple);
00734 failure:
00735 return (result);
00736 }
00737
00738 static isc_result_t
00739 namelist_append_subdomain(dns_db_t *db, dns_name_t *name, dns_diff_t *affected)
00740 {
00741 isc_result_t result;
00742 dns_fixedname_t fixedname;
00743 dns_name_t *child;
00744 dns_dbiterator_t *dbit = NULL;
00745
00746 dns_fixedname_init(&fixedname);
00747 child = dns_fixedname_name(&fixedname);
00748
00749 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
00750
00751 for (result = dns_dbiterator_seek(dbit, name);
00752 result == ISC_R_SUCCESS;
00753 result = dns_dbiterator_next(dbit))
00754 {
00755 dns_dbnode_t *node = NULL;
00756 CHECK(dns_dbiterator_current(dbit, &node, child));
00757 dns_db_detachnode(db, &node);
00758 if (! dns_name_issubdomain(child, name))
00759 break;
00760 CHECK(namelist_append_name(affected, child));
00761 }
00762 if (result == ISC_R_NOMORE)
00763 result = ISC_R_SUCCESS;
00764 failure:
00765 if (dbit != NULL)
00766 dns_dbiterator_destroy(&dbit);
00767 return (result);
00768 }
00769
00770
00771
00772
00773
00774
00775 static isc_result_t
00776 is_non_nsec_action(void *data, dns_rdataset_t *rrset) {
00777 UNUSED(data);
00778 if (!(rrset->type == dns_rdatatype_nsec ||
00779 rrset->type == dns_rdatatype_nsec3 ||
00780 (rrset->type == dns_rdatatype_rrsig &&
00781 (rrset->covers == dns_rdatatype_nsec ||
00782 rrset->covers == dns_rdatatype_nsec3))))
00783 return (ISC_R_EXISTS);
00784 return (ISC_R_SUCCESS);
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 static isc_result_t
00796 non_nsec_rrset_exists(dns_db_t *db, dns_dbversion_t *ver,
00797 dns_name_t *name, isc_boolean_t *exists)
00798 {
00799 isc_result_t result;
00800 result = foreach_rrset(db, ver, name, is_non_nsec_action, NULL);
00801 RETURN_EXISTENCE_FLAG;
00802 }
00803
00804
00805
00806
00807 static int
00808 name_order(const void *av, const void *bv) {
00809 dns_difftuple_t const * const *ap = av;
00810 dns_difftuple_t const * const *bp = bv;
00811 dns_difftuple_t const *a = *ap;
00812 dns_difftuple_t const *b = *bp;
00813 return (dns_name_compare(&a->name, &b->name));
00814 }
00815
00816 static isc_result_t
00817 uniqify_name_list(dns_diff_t *list) {
00818 isc_result_t result;
00819 dns_difftuple_t *p, *q;
00820
00821 CHECK(dns_diff_sort(list, name_order));
00822
00823 p = ISC_LIST_HEAD(list->tuples);
00824 while (p != NULL) {
00825 do {
00826 q = ISC_LIST_NEXT(p, link);
00827 if (q == NULL || ! dns_name_equal(&p->name, &q->name))
00828 break;
00829 ISC_LIST_UNLINK(list->tuples, q, link);
00830 dns_difftuple_free(&q);
00831 } while (1);
00832 p = ISC_LIST_NEXT(p, link);
00833 }
00834 failure:
00835 return (result);
00836 }
00837
00838 static isc_result_t
00839 is_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00840 isc_boolean_t *flag, isc_boolean_t *cut, isc_boolean_t *unsecure)
00841 {
00842 isc_result_t result;
00843 dns_fixedname_t foundname;
00844 dns_fixedname_init(&foundname);
00845 result = dns_db_find(db, name, ver, dns_rdatatype_any,
00846 DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
00847 (isc_stdtime_t) 0, NULL,
00848 dns_fixedname_name(&foundname),
00849 NULL, NULL);
00850 if (result == ISC_R_SUCCESS || result == DNS_R_EMPTYNAME) {
00851 *flag = ISC_TRUE;
00852 *cut = ISC_FALSE;
00853 if (unsecure != NULL)
00854 *unsecure = ISC_FALSE;
00855 return (ISC_R_SUCCESS);
00856 } else if (result == DNS_R_ZONECUT) {
00857 *flag = ISC_TRUE;
00858 *cut = ISC_TRUE;
00859 if (unsecure != NULL) {
00860
00861
00862
00863
00864 if (dns_db_find(db, name, ver, dns_rdatatype_ds, 0,
00865 (isc_stdtime_t) 0, NULL,
00866 dns_fixedname_name(&foundname),
00867 NULL, NULL) == DNS_R_NXRRSET)
00868 *unsecure = ISC_TRUE;
00869 else
00870 *unsecure = ISC_FALSE;
00871 }
00872 return (ISC_R_SUCCESS);
00873 } else if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
00874 result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) {
00875 *flag = ISC_FALSE;
00876 *cut = ISC_FALSE;
00877 if (unsecure != NULL)
00878 *unsecure = ISC_FALSE;
00879 return (ISC_R_SUCCESS);
00880 } else {
00881
00882
00883
00884 *flag = ISC_FALSE;
00885 *cut = ISC_FALSE;
00886 if (unsecure != NULL)
00887 *unsecure = ISC_FALSE;
00888 return (result);
00889 }
00890 }
00891
00892
00893
00894
00895
00896
00897
00898 static isc_result_t
00899 next_active(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
00900 dns_dbversion_t *ver, dns_name_t *oldname, dns_name_t *newname,
00901 isc_boolean_t forward)
00902 {
00903 isc_result_t result;
00904 dns_dbiterator_t *dbit = NULL;
00905 isc_boolean_t has_nsec = ISC_FALSE;
00906 unsigned int wraps = 0;
00907 isc_boolean_t secure = dns_db_issecure(db);
00908
00909 CHECK(dns_db_createiterator(db, 0, &dbit));
00910
00911 CHECK(dns_dbiterator_seek(dbit, oldname));
00912 do {
00913 dns_dbnode_t *node = NULL;
00914
00915 if (forward)
00916 result = dns_dbiterator_next(dbit);
00917 else
00918 result = dns_dbiterator_prev(dbit);
00919 if (result == ISC_R_NOMORE) {
00920
00921
00922
00923 if (forward)
00924 CHECK(dns_dbiterator_first(dbit));
00925 else
00926 CHECK(dns_dbiterator_last(dbit));
00927 wraps++;
00928 if (wraps == 2) {
00929 update_log(log, zone, ISC_LOG_ERROR,
00930 "secure zone with no NSECs");
00931 result = DNS_R_BADZONE;
00932 goto failure;
00933 }
00934 }
00935 CHECK(dns_dbiterator_current(dbit, &node, newname));
00936 dns_db_detachnode(db, &node);
00937
00938
00939
00940
00941
00942
00943
00944 CHECK(dns_dbiterator_pause(dbit));
00945 if (secure) {
00946 CHECK(rrset_exists(db, ver, newname,
00947 dns_rdatatype_nsec, 0, &has_nsec));
00948 } else {
00949 dns_fixedname_t ffound;
00950 dns_name_t *found;
00951 dns_fixedname_init(&ffound);
00952 found = dns_fixedname_name(&ffound);
00953 result = dns_db_find(db, newname, ver,
00954 dns_rdatatype_soa,
00955 DNS_DBFIND_NOWILD, 0, NULL, found,
00956 NULL, NULL);
00957 if (result == ISC_R_SUCCESS ||
00958 result == DNS_R_EMPTYNAME ||
00959 result == DNS_R_NXRRSET ||
00960 result == DNS_R_CNAME ||
00961 (result == DNS_R_DELEGATION &&
00962 dns_name_equal(newname, found))) {
00963 has_nsec = ISC_TRUE;
00964 result = ISC_R_SUCCESS;
00965 } else if (result != DNS_R_NXDOMAIN)
00966 break;
00967 }
00968 } while (! has_nsec);
00969 failure:
00970 if (dbit != NULL)
00971 dns_dbiterator_destroy(&dbit);
00972
00973 return (result);
00974 }
00975
00976
00977
00978
00979
00980 static isc_result_t
00981 add_nsec(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
00982 dns_dbversion_t *ver, dns_name_t *name, dns_ttl_t nsecttl,
00983 dns_diff_t *diff)
00984 {
00985 isc_result_t result;
00986 dns_dbnode_t *node = NULL;
00987 unsigned char buffer[DNS_NSEC_BUFFERSIZE];
00988 dns_rdata_t rdata = DNS_RDATA_INIT;
00989 dns_difftuple_t *tuple = NULL;
00990 dns_fixedname_t fixedname;
00991 dns_name_t *target;
00992
00993 dns_fixedname_init(&fixedname);
00994 target = dns_fixedname_name(&fixedname);
00995
00996
00997
00998
00999 CHECK(next_active(log, zone, db, ver, name, target, ISC_TRUE));
01000
01001
01002
01003
01004 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
01005 dns_rdata_init(&rdata);
01006 CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata));
01007 dns_db_detachnode(db, &node);
01008
01009
01010
01011
01012 CHECK(delete_if(true_p, db, ver, name, dns_rdatatype_nsec, 0,
01013 NULL, diff));
01014
01015
01016
01017 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
01018 nsecttl, &rdata, &tuple));
01019 CHECK(do_one_tuple(&tuple, db, ver, diff));
01020 INSIST(tuple == NULL);
01021
01022 failure:
01023 if (node != NULL)
01024 dns_db_detachnode(db, &node);
01025 return (result);
01026 }
01027
01028
01029
01030
01031 static isc_result_t
01032 add_placeholder_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
01033 dns_diff_t *diff)
01034 {
01035 isc_result_t result;
01036 dns_difftuple_t *tuple = NULL;
01037 isc_region_t r;
01038 unsigned char data[1] = { 0 };
01039 dns_rdata_t rdata = DNS_RDATA_INIT;
01040
01041 r.base = data;
01042 r.length = sizeof(data);
01043 dns_rdata_fromregion(&rdata, dns_db_class(db), dns_rdatatype_nsec, &r);
01044 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0,
01045 &rdata, &tuple));
01046 CHECK(do_one_tuple(&tuple, db, ver, diff));
01047 failure:
01048 return (result);
01049 }
01050
01051 static isc_result_t
01052 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
01053 isc_mem_t *mctx, unsigned int maxkeys,
01054 dst_key_t **keys, unsigned int *nkeys)
01055 {
01056 isc_result_t result;
01057 dns_dbnode_t *node = NULL;
01058 const char *directory = dns_zone_getkeydirectory(zone);
01059 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
01060 CHECK(dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
01061 directory, mctx, maxkeys, keys, nkeys));
01062 failure:
01063 if (node != NULL)
01064 dns_db_detachnode(db, &node);
01065 return (result);
01066 }
01067
01068
01069
01070
01071 static isc_result_t
01072 add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
01073 dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type,
01074 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
01075 isc_stdtime_t inception, isc_stdtime_t expire,
01076 isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly)
01077 {
01078 isc_result_t result;
01079 dns_dbnode_t *node = NULL;
01080 dns_rdataset_t rdataset;
01081 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
01082 isc_buffer_t buffer;
01083 unsigned char data[1024];
01084 unsigned int i, j;
01085 isc_boolean_t added_sig = ISC_FALSE;
01086 isc_mem_t *mctx = diff->mctx;
01087
01088 dns_rdataset_init(&rdataset);
01089 isc_buffer_init(&buffer, data, sizeof(data));
01090
01091
01092 if (type == dns_rdatatype_nsec3)
01093 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
01094 else
01095 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
01096 CHECK(dns_db_findrdataset(db, node, ver, type, 0,
01097 (isc_stdtime_t) 0, &rdataset, NULL));
01098 dns_db_detachnode(db, &node);
01099
01100 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
01101 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
01102 #define ALG(x) dst_key_alg(x)
01103
01104
01105
01106
01107
01108
01109 for (i = 0; i < nkeys; i++) {
01110 isc_boolean_t both = ISC_FALSE;
01111
01112 if (!dst_key_isprivate(keys[i]))
01113 continue;
01114
01115 if (check_ksk && !REVOKE(keys[i])) {
01116 isc_boolean_t have_ksk, have_nonksk;
01117 if (KSK(keys[i])) {
01118 have_ksk = ISC_TRUE;
01119 have_nonksk = ISC_FALSE;
01120 } else {
01121 have_ksk = ISC_FALSE;
01122 have_nonksk = ISC_TRUE;
01123 }
01124 for (j = 0; j < nkeys; j++) {
01125 if (j == i || ALG(keys[i]) != ALG(keys[j]))
01126 continue;
01127 if (REVOKE(keys[j]))
01128 continue;
01129 if (KSK(keys[j]))
01130 have_ksk = ISC_TRUE;
01131 else
01132 have_nonksk = ISC_TRUE;
01133 both = have_ksk && have_nonksk;
01134 if (both)
01135 break;
01136 }
01137 }
01138
01139 if (both) {
01140 if (type == dns_rdatatype_dnskey) {
01141 if (!KSK(keys[i]) && keyset_kskonly)
01142 continue;
01143 } else if (KSK(keys[i]))
01144 continue;
01145 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
01146 continue;
01147
01148
01149 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
01150 &inception, &expire,
01151 mctx, &buffer, &sig_rdata));
01152
01153
01154
01155 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
01156 rdataset.ttl, &sig_rdata));
01157 dns_rdata_reset(&sig_rdata);
01158 isc_buffer_init(&buffer, data, sizeof(data));
01159 added_sig = ISC_TRUE;
01160 }
01161 if (!added_sig) {
01162 update_log(log, zone, ISC_LOG_ERROR,
01163 "found no active private keys, "
01164 "unable to generate any signatures");
01165 result = ISC_R_NOTFOUND;
01166 }
01167
01168 failure:
01169 if (dns_rdataset_isassociated(&rdataset))
01170 dns_rdataset_disassociate(&rdataset);
01171 if (node != NULL)
01172 dns_db_detachnode(db, &node);
01173 return (result);
01174 }
01175
01176
01177
01178
01179
01180 static isc_result_t
01181 del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
01182 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys)
01183 {
01184 isc_result_t result;
01185 dns_dbnode_t *node = NULL;
01186 dns_rdataset_t rdataset;
01187 dns_rdata_t rdata = DNS_RDATA_INIT;
01188 unsigned int i;
01189 dns_rdata_rrsig_t rrsig;
01190 isc_boolean_t found;
01191
01192 dns_rdataset_init(&rdataset);
01193
01194 result = dns_db_findnode(db, name, ISC_FALSE, &node);
01195 if (result == ISC_R_NOTFOUND)
01196 return (ISC_R_SUCCESS);
01197 if (result != ISC_R_SUCCESS)
01198 goto failure;
01199 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig,
01200 dns_rdatatype_dnskey, (isc_stdtime_t) 0,
01201 &rdataset, NULL);
01202 dns_db_detachnode(db, &node);
01203
01204 if (result == ISC_R_NOTFOUND)
01205 return (ISC_R_SUCCESS);
01206 if (result != ISC_R_SUCCESS)
01207 goto failure;
01208
01209 for (result = dns_rdataset_first(&rdataset);
01210 result == ISC_R_SUCCESS;
01211 result = dns_rdataset_next(&rdataset)) {
01212 dns_rdataset_current(&rdataset, &rdata);
01213 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
01214 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01215 found = ISC_FALSE;
01216 for (i = 0; i < nkeys; i++) {
01217 if (rrsig.keyid == dst_key_id(keys[i])) {
01218 found = ISC_TRUE;
01219 if (!dst_key_isprivate(keys[i]) &&
01220 !dst_key_inactive(keys[i]))
01221 {
01222
01223
01224
01225
01226
01227 break;
01228 }
01229 result = update_one_rr(db, ver, diff,
01230 DNS_DIFFOP_DEL, name,
01231 rdataset.ttl, &rdata);
01232 break;
01233 }
01234 }
01235
01236
01237
01238 if (!found)
01239 result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
01240 name, rdataset.ttl, &rdata);
01241 dns_rdata_reset(&rdata);
01242 if (result != ISC_R_SUCCESS)
01243 break;
01244 }
01245 dns_rdataset_disassociate(&rdataset);
01246 if (result == ISC_R_NOMORE)
01247 result = ISC_R_SUCCESS;
01248 failure:
01249 if (node != NULL)
01250 dns_db_detachnode(db, &node);
01251 return (result);
01252 }
01253
01254 static isc_result_t
01255 add_exposed_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
01256 dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t cut,
01257 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
01258 isc_stdtime_t inception, isc_stdtime_t expire,
01259 isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
01260 unsigned int *sigs)
01261 {
01262 isc_result_t result;
01263 dns_dbnode_t *node;
01264 dns_rdatasetiter_t *iter;
01265
01266 node = NULL;
01267 result = dns_db_findnode(db, name, ISC_FALSE, &node);
01268 if (result == ISC_R_NOTFOUND)
01269 return (ISC_R_SUCCESS);
01270 if (result != ISC_R_SUCCESS)
01271 return (result);
01272
01273 iter = NULL;
01274 result = dns_db_allrdatasets(db, node, ver,
01275 (isc_stdtime_t) 0, &iter);
01276 if (result != ISC_R_SUCCESS)
01277 goto cleanup_node;
01278
01279 for (result = dns_rdatasetiter_first(iter);
01280 result == ISC_R_SUCCESS;
01281 result = dns_rdatasetiter_next(iter))
01282 {
01283 dns_rdataset_t rdataset;
01284 dns_rdatatype_t type;
01285 isc_boolean_t flag;
01286
01287 dns_rdataset_init(&rdataset);
01288 dns_rdatasetiter_current(iter, &rdataset);
01289 type = rdataset.type;
01290 dns_rdataset_disassociate(&rdataset);
01291
01292
01293
01294
01295
01296 if ((type == dns_rdatatype_rrsig) ||
01297 (cut && type != dns_rdatatype_ds))
01298 continue;
01299 result = rrset_exists(db, ver, name, dns_rdatatype_rrsig,
01300 type, &flag);
01301 if (result != ISC_R_SUCCESS)
01302 goto cleanup_iterator;
01303 if (flag)
01304 continue;;
01305 result = add_sigs(log, zone, db, ver, name, type, diff,
01306 keys, nkeys, inception, expire,
01307 check_ksk, keyset_kskonly);
01308 if (result != ISC_R_SUCCESS)
01309 goto cleanup_iterator;
01310 (*sigs)++;
01311 }
01312 if (result == ISC_R_NOMORE)
01313 result = ISC_R_SUCCESS;
01314
01315 cleanup_iterator:
01316 dns_rdatasetiter_destroy(&iter);
01317
01318 cleanup_node:
01319 dns_db_detachnode(db, &node);
01320
01321 return (result);
01322 }
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335 isc_result_t
01336 dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
01337 dns_dbversion_t *oldver, dns_dbversion_t *newver,
01338 dns_diff_t *diff, isc_uint32_t sigvalidityinterval)
01339 {
01340 return (dns_update_signaturesinc(log, zone, db, oldver, newver, diff,
01341 sigvalidityinterval, NULL));
01342 }
01343
01344 struct dns_update_state {
01345 unsigned int magic;
01346 dns_diff_t diffnames;
01347 dns_diff_t affected;
01348 dns_diff_t sig_diff;
01349 dns_diff_t nsec_diff;
01350 dns_diff_t nsec_mindiff;
01351 dns_diff_t work;
01352 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
01353 unsigned int nkeys;
01354 isc_stdtime_t inception, expire;
01355 dns_ttl_t nsecttl;
01356 isc_boolean_t check_ksk, keyset_kskonly;
01357 enum { sign_updates, remove_orphaned, build_chain, process_nsec,
01358 sign_nsec, update_nsec3, process_nsec3, sign_nsec3 } state;
01359 };
01360
01361 isc_result_t
01362 dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
01363 dns_dbversion_t *oldver, dns_dbversion_t *newver,
01364 dns_diff_t *diff, isc_uint32_t sigvalidityinterval,
01365 dns_update_state_t **statep)
01366 {
01367 isc_result_t result = ISC_R_SUCCESS;
01368 dns_update_state_t mystate, *state;
01369
01370 dns_difftuple_t *t, *next;
01371 isc_boolean_t flag, build_nsec, build_nsec3;
01372 unsigned int i;
01373 isc_stdtime_t now;
01374 dns_rdata_soa_t soa;
01375 dns_rdata_t rdata = DNS_RDATA_INIT;
01376 dns_rdataset_t rdataset;
01377 dns_dbnode_t *node = NULL;
01378 isc_boolean_t unsecure;
01379 isc_boolean_t cut;
01380 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
01381 unsigned int sigs = 0;
01382 unsigned int maxsigs = dns_zone_getsignatures(zone);
01383
01384 if (statep == NULL || (statep != NULL && *statep == NULL)) {
01385 if (statep == NULL) {
01386 state = &mystate;
01387 } else {
01388 state = isc_mem_get(diff->mctx, sizeof(*state));
01389 if (state == NULL)
01390 return (ISC_R_NOMEMORY);
01391 }
01392
01393 dns_diff_init(diff->mctx, &state->diffnames);
01394 dns_diff_init(diff->mctx, &state->affected);
01395 dns_diff_init(diff->mctx, &state->sig_diff);
01396 dns_diff_init(diff->mctx, &state->nsec_diff);
01397 dns_diff_init(diff->mctx, &state->nsec_mindiff);
01398 dns_diff_init(diff->mctx, &state->work);
01399 state->nkeys = 0;
01400
01401 result = find_zone_keys(zone, db, newver, diff->mctx,
01402 DNS_MAXZONEKEYS, state->zone_keys,
01403 &state->nkeys);
01404 if (result != ISC_R_SUCCESS) {
01405 update_log(log, zone, ISC_LOG_ERROR,
01406 "could not get zone keys for secure "
01407 "dynamic update");
01408 goto failure;
01409 }
01410
01411 isc_stdtime_get(&now);
01412 state->inception = now - 3600;
01413 state->expire = now + sigvalidityinterval;
01414
01415
01416
01417
01418
01419
01420
01421 state->check_ksk = ISC_TF((dns_zone_getoptions(zone) &
01422 DNS_ZONEOPT_UPDATECHECKKSK) != 0);
01423 state->keyset_kskonly = ISC_TF((dns_zone_getoptions(zone) &
01424 DNS_ZONEOPT_DNSKEYKSKONLY) != 0);
01425
01426
01427
01428
01429 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
01430 dns_rdataset_init(&rdataset);
01431 CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa,
01432 0, (isc_stdtime_t) 0, &rdataset,
01433 NULL));
01434 CHECK(dns_rdataset_first(&rdataset));
01435 dns_rdataset_current(&rdataset, &rdata);
01436 CHECK(dns_rdata_tostruct(&rdata, &soa, NULL));
01437 state->nsecttl = soa.minimum;
01438 dns_rdataset_disassociate(&rdataset);
01439 dns_db_detachnode(db, &node);
01440
01441
01442
01443
01444
01445
01446 CHECK(dns_diff_sort(diff, temp_order));
01447 state->state = sign_updates;
01448 state->magic = STATE_MAGIC;
01449 if (statep != NULL)
01450 *statep = state;
01451 } else {
01452 REQUIRE(DNS_STATE_VALID(*statep));
01453 state = *statep;
01454 }
01455
01456 next_state:
01457 switch (state->state) {
01458 case sign_updates:
01459 t = ISC_LIST_HEAD(diff->tuples);
01460 while (t != NULL) {
01461 dns_name_t *name = &t->name;
01462
01463
01464
01465
01466
01467 CHECK(namelist_append_name(&state->diffnames, name));
01468
01469 while (t != NULL && dns_name_equal(&t->name, name)) {
01470 dns_rdatatype_t type;
01471 type = t->rdata.type;
01472
01473
01474
01475
01476
01477
01478
01479 if (type == dns_rdatatype_rrsig)
01480 goto skip;
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490 if (type == dns_rdatatype_dnskey)
01491 del_keysigs(db, newver, name,
01492 &state->sig_diff,
01493 state->zone_keys,
01494 state->nkeys);
01495 else
01496 CHECK(delete_if(true_p, db, newver,
01497 name,
01498 dns_rdatatype_rrsig,
01499 type, NULL,
01500 &state->sig_diff));
01501
01502
01503
01504
01505
01506 CHECK(rrset_visible(db, newver, name, type,
01507 &flag));
01508 if (flag) {
01509 CHECK(add_sigs(log, zone, db, newver,
01510 name, type,
01511 &state->sig_diff,
01512 state->zone_keys,
01513 state->nkeys,
01514 state->inception,
01515 state->expire,
01516 state->check_ksk,
01517 state->keyset_kskonly));
01518 sigs++;
01519 }
01520 skip:
01521
01522 while (t != NULL &&
01523 dns_name_equal(&t->name, name) &&
01524 t->rdata.type == type)
01525 {
01526 next = ISC_LIST_NEXT(t, link);
01527 ISC_LIST_UNLINK(diff->tuples, t, link);
01528 ISC_LIST_APPEND(state->work.tuples, t,
01529 link);
01530 t = next;
01531 }
01532 }
01533 if (state != &mystate && sigs > maxsigs)
01534 return (DNS_R_CONTINUE);
01535 }
01536 ISC_LIST_APPENDLIST(diff->tuples, state->work.tuples, link);
01537
01538 update_log(log, zone, ISC_LOG_DEBUG(3),
01539 "updated data signatures");
01540
01541 case remove_orphaned:
01542 state->state = remove_orphaned;
01543
01544
01545 for (t = ISC_LIST_HEAD(state->diffnames.tuples);
01546 t != NULL;
01547 t = ISC_LIST_NEXT(t, link))
01548 {
01549 CHECK(non_nsec_rrset_exists(db, newver,
01550 &t->name, &flag));
01551 if (!flag) {
01552 CHECK(delete_if(true_p, db, newver, &t->name,
01553 dns_rdatatype_any, 0,
01554 NULL, &state->sig_diff));
01555 }
01556 }
01557 update_log(log, zone, ISC_LOG_DEBUG(3),
01558 "removed any orphaned NSEC records");
01559
01560
01561
01562
01563 CHECK(dns_private_chains(db, newver, privatetype, &build_nsec,
01564 &build_nsec3));
01565 if (!build_nsec) {
01566 state->state = update_nsec3;
01567 goto next_state;
01568 }
01569
01570 update_log(log, zone, ISC_LOG_DEBUG(3),
01571 "rebuilding NSEC chain");
01572
01573
01574 case build_chain:
01575 state->state = build_chain;
01576
01577
01578
01579
01580 for (t = ISC_LIST_HEAD(state->diffnames.tuples);
01581 t != NULL;
01582 t = ISC_LIST_NEXT(t, link))
01583 {
01584 isc_boolean_t existed, exists;
01585 dns_fixedname_t fixedname;
01586 dns_name_t *prevname;
01587
01588 dns_fixedname_init(&fixedname);
01589 prevname = dns_fixedname_name(&fixedname);
01590
01591 if (oldver != NULL)
01592 CHECK(name_exists(db, oldver, &t->name,
01593 &existed));
01594 else
01595 existed = ISC_FALSE;
01596 CHECK(name_exists(db, newver, &t->name, &exists));
01597 if (exists == existed)
01598 continue;
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611 CHECK(next_active(log, zone, db, newver,
01612 &t->name, prevname, ISC_FALSE));
01613 CHECK(namelist_append_name(&state->affected, prevname));
01614 }
01615
01616
01617
01618
01619
01620
01621 for (t = ISC_LIST_HEAD(state->diffnames.tuples);
01622 t != NULL;
01623 t = ISC_LIST_NEXT(t, link))
01624 {
01625 isc_boolean_t ns_existed, dname_existed;
01626 isc_boolean_t ns_exists, dname_exists;
01627
01628 if (oldver != NULL)
01629 CHECK(rrset_exists(db, oldver, &t->name,
01630 dns_rdatatype_ns, 0,
01631 &ns_existed));
01632 else
01633 ns_existed = ISC_FALSE;
01634 if (oldver != NULL)
01635 CHECK(rrset_exists(db, oldver, &t->name,
01636 dns_rdatatype_dname, 0,
01637 &dname_existed));
01638 else
01639 dname_existed = ISC_FALSE;
01640 CHECK(rrset_exists(db, newver, &t->name,
01641 dns_rdatatype_ns, 0, &ns_exists));
01642 CHECK(rrset_exists(db, newver, &t->name,
01643 dns_rdatatype_dname, 0,
01644 &dname_exists));
01645 if ((ns_exists || dname_exists) ==
01646 (ns_existed || dname_existed))
01647 continue;
01648
01649
01650
01651
01652 CHECK(namelist_append_subdomain(db, &t->name,
01653 &state->affected));
01654 }
01655 ISC_LIST_APPENDLIST(state->affected.tuples,
01656 state->diffnames.tuples, link);
01657 INSIST(ISC_LIST_EMPTY(state->diffnames.tuples));
01658
01659 CHECK(uniqify_name_list(&state->affected));
01660
01661
01662 case process_nsec:
01663 state->state = process_nsec;
01664
01665
01666
01667
01668
01669
01670
01671
01672 while ((t = ISC_LIST_HEAD(state->affected.tuples)) != NULL) {
01673 isc_boolean_t exists;
01674 dns_name_t *name = &t->name;
01675
01676 CHECK(name_exists(db, newver, name, &exists));
01677 if (! exists)
01678 goto unlink;
01679 CHECK(is_active(db, newver, name, &flag, &cut, NULL));
01680 if (!flag) {
01681
01682
01683
01684
01685 CHECK(delete_if(true_p, db, newver, name,
01686 dns_rdatatype_nsec, 0,
01687 NULL, &state->nsec_diff));
01688 CHECK(delete_if(rrsig_p, db, newver, name,
01689 dns_rdatatype_any, 0, NULL,
01690 diff));
01691 } else {
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701 if (!dns_name_equal(name, dns_db_origin(db))) {
01702 CHECK(rrset_exists(db, newver, name,
01703 dns_rdatatype_nsec,
01704 0, &flag));
01705 if (!flag)
01706 CHECK(add_placeholder_nsec(db,
01707 newver, name, diff));
01708 }
01709 CHECK(add_exposed_sigs(log, zone, db, newver,
01710 name, cut,
01711 &state->sig_diff,
01712 state->zone_keys,
01713 state->nkeys,
01714 state->inception,
01715 state->expire,
01716 state->check_ksk,
01717 state->keyset_kskonly,
01718 &sigs));
01719 }
01720 unlink:
01721 ISC_LIST_UNLINK(state->affected.tuples, t, link);
01722 ISC_LIST_APPEND(state->work.tuples, t, link);
01723 if (state != &mystate && sigs > maxsigs)
01724 return (DNS_R_CONTINUE);
01725 }
01726 ISC_LIST_APPENDLIST(state->affected.tuples,
01727 state->work.tuples, link);
01728
01729
01730
01731
01732
01733 for (t = ISC_LIST_HEAD(state->affected.tuples);
01734 t != NULL;
01735 t = ISC_LIST_NEXT(t, link))
01736 {
01737 CHECK(rrset_exists(db, newver, &t->name,
01738 dns_rdatatype_nsec, 0, &flag));
01739 if (flag) {
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759 CHECK(add_nsec(log, zone, db, newver, &t->name,
01760 state->nsecttl,
01761 &state->nsec_diff));
01762 }
01763 }
01764
01765
01766
01767
01768
01769
01770 while ((t = ISC_LIST_HEAD(state->nsec_diff.tuples)) != NULL) {
01771 ISC_LIST_UNLINK(state->nsec_diff.tuples, t, link);
01772 dns_diff_appendminimal(&state->nsec_mindiff, &t);
01773 }
01774
01775 update_log(log, zone, ISC_LOG_DEBUG(3),
01776 "signing rebuilt NSEC chain");
01777
01778
01779 case sign_nsec:
01780 state->state = sign_nsec;
01781
01782 while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
01783 {
01784 if (t->op == DNS_DIFFOP_DEL) {
01785 CHECK(delete_if(true_p, db, newver, &t->name,
01786 dns_rdatatype_rrsig,
01787 dns_rdatatype_nsec,
01788 NULL, &state->sig_diff));
01789 } else if (t->op == DNS_DIFFOP_ADD) {
01790 CHECK(add_sigs(log, zone, db, newver, &t->name,
01791 dns_rdatatype_nsec,
01792 &state->sig_diff,
01793 state->zone_keys, state->nkeys,
01794 state->inception, state->expire,
01795 state->check_ksk,
01796 state->keyset_kskonly));
01797 sigs++;
01798 } else {
01799 INSIST(0);
01800 }
01801 ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
01802 ISC_LIST_APPEND(state->work.tuples, t, link);
01803 if (state != &mystate && sigs > maxsigs)
01804 return (DNS_R_CONTINUE);
01805 }
01806 ISC_LIST_APPENDLIST(state->nsec_mindiff.tuples,
01807 state->work.tuples, link);
01808
01809 case update_nsec3:
01810 state->state = update_nsec3;
01811
01812
01813 while ((t = ISC_LIST_HEAD(state->sig_diff.tuples)) != NULL) {
01814 ISC_LIST_UNLINK(state->sig_diff.tuples, t, link);
01815 dns_diff_appendminimal(diff, &t);
01816 }
01817 while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
01818 {
01819 ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
01820 dns_diff_appendminimal(diff, &t);
01821 }
01822
01823 INSIST(ISC_LIST_EMPTY(state->sig_diff.tuples));
01824 INSIST(ISC_LIST_EMPTY(state->nsec_diff.tuples));
01825 INSIST(ISC_LIST_EMPTY(state->nsec_mindiff.tuples));
01826
01827 if (!build_nsec3) {
01828 update_log(log, zone, ISC_LOG_DEBUG(3),
01829 "no NSEC3 chains to rebuild");
01830 goto failure;
01831 }
01832
01833 update_log(log, zone, ISC_LOG_DEBUG(3),
01834 "rebuilding NSEC3 chains");
01835
01836 dns_diff_clear(&state->diffnames);
01837 dns_diff_clear(&state->affected);
01838
01839 CHECK(dns_diff_sort(diff, temp_order));
01840
01841
01842
01843
01844
01845
01846 t = ISC_LIST_HEAD(diff->tuples);
01847 while (t != NULL) {
01848 dns_name_t *name = &t->name;
01849
01850 isc_boolean_t ns_existed, dname_existed;
01851 isc_boolean_t ns_exists, dname_exists;
01852 isc_boolean_t exists, existed;
01853
01854 if (t->rdata.type == dns_rdatatype_nsec ||
01855 t->rdata.type == dns_rdatatype_rrsig) {
01856 t = ISC_LIST_NEXT(t, link);
01857 continue;
01858 }
01859
01860 CHECK(namelist_append_name(&state->affected, name));
01861
01862 if (oldver != NULL)
01863 CHECK(rrset_exists(db, oldver, name,
01864 dns_rdatatype_ns,
01865 0, &ns_existed));
01866 else
01867 ns_existed = ISC_FALSE;
01868 if (oldver != NULL)
01869 CHECK(rrset_exists(db, oldver, name,
01870 dns_rdatatype_dname, 0,
01871 &dname_existed));
01872 else
01873 dname_existed = ISC_FALSE;
01874 CHECK(rrset_exists(db, newver, name, dns_rdatatype_ns,
01875 0, &ns_exists));
01876 CHECK(rrset_exists(db, newver, name,
01877 dns_rdatatype_dname, 0,
01878 &dname_exists));
01879
01880 exists = ns_exists || dname_exists;
01881 existed = ns_existed || dname_existed;
01882 if (exists == existed)
01883 goto nextname;
01884
01885
01886
01887
01888 CHECK(namelist_append_subdomain(db, name,
01889 &state->affected));
01890
01891 nextname:
01892 while (t != NULL && dns_name_equal(&t->name, name))
01893 t = ISC_LIST_NEXT(t, link);
01894 }
01895
01896
01897 case process_nsec3:
01898 state->state = process_nsec3;
01899 while ((t = ISC_LIST_HEAD(state->affected.tuples)) != NULL) {
01900 dns_name_t *name = &t->name;
01901
01902 unsecure = ISC_FALSE;
01903 CHECK(is_active(db, newver, name, &flag, &cut,
01904 &unsecure));
01905
01906 if (!flag) {
01907 CHECK(delete_if(rrsig_p, db, newver, name,
01908 dns_rdatatype_any, 0, NULL,
01909 diff));
01910 CHECK(dns_nsec3_delnsec3sx(db, newver, name,
01911 privatetype,
01912 &state->nsec_diff));
01913 } else {
01914 CHECK(add_exposed_sigs(log, zone, db, newver,
01915 name, cut,
01916 &state->sig_diff,
01917 state->zone_keys,
01918 state->nkeys,
01919 state->inception,
01920 state->expire,
01921 state->check_ksk,
01922 state->keyset_kskonly,
01923 &sigs));
01924 CHECK(dns_nsec3_addnsec3sx(db, newver, name,
01925 state->nsecttl,
01926 unsecure,
01927 privatetype,
01928 &state->nsec_diff));
01929 }
01930 ISC_LIST_UNLINK(state->affected.tuples, t, link);
01931 ISC_LIST_APPEND(state->work.tuples, t, link);
01932 if (state != &mystate && sigs > maxsigs)
01933 return (DNS_R_CONTINUE);
01934 }
01935 ISC_LIST_APPENDLIST(state->affected.tuples,
01936 state->work.tuples, link);
01937
01938
01939
01940
01941
01942
01943 while ((t = ISC_LIST_HEAD(state->nsec_diff.tuples)) != NULL) {
01944 ISC_LIST_UNLINK(state->nsec_diff.tuples, t, link);
01945 dns_diff_appendminimal(&state->nsec_mindiff, &t);
01946 }
01947
01948 update_log(log, zone, ISC_LOG_DEBUG(3),
01949 "signing rebuilt NSEC3 chain");
01950
01951
01952 case sign_nsec3:
01953 state->state = sign_nsec3;
01954
01955 while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
01956 {
01957 if (t->op == DNS_DIFFOP_DEL) {
01958 CHECK(delete_if(true_p, db, newver, &t->name,
01959 dns_rdatatype_rrsig,
01960 dns_rdatatype_nsec3,
01961 NULL, &state->sig_diff));
01962 } else if (t->op == DNS_DIFFOP_ADD) {
01963 CHECK(add_sigs(log, zone, db, newver, &t->name,
01964 dns_rdatatype_nsec3,
01965 &state->sig_diff,
01966 state->zone_keys,
01967 state->nkeys, state->inception,
01968 state->expire, state->check_ksk,
01969 state->keyset_kskonly));
01970 sigs++;
01971 } else {
01972 INSIST(0);
01973 }
01974 ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
01975 ISC_LIST_APPEND(state->work.tuples, t, link);
01976 if (state != &mystate && sigs > maxsigs)
01977 return (DNS_R_CONTINUE);
01978 }
01979 ISC_LIST_APPENDLIST(state->nsec_mindiff.tuples,
01980 state->work.tuples, link);
01981
01982
01983 while ((t = ISC_LIST_HEAD(state->sig_diff.tuples)) != NULL) {
01984 ISC_LIST_UNLINK(state->sig_diff.tuples, t, link);
01985 dns_diff_appendminimal(diff, &t);
01986 }
01987 while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
01988 {
01989 ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
01990 dns_diff_appendminimal(diff, &t);
01991 }
01992
01993 INSIST(ISC_LIST_EMPTY(state->sig_diff.tuples));
01994 INSIST(ISC_LIST_EMPTY(state->nsec_diff.tuples));
01995 INSIST(ISC_LIST_EMPTY(state->nsec_mindiff.tuples));
01996 break;
01997 default:
01998 INSIST(0);
01999 }
02000
02001 failure:
02002 dns_diff_clear(&state->sig_diff);
02003 dns_diff_clear(&state->nsec_diff);
02004 dns_diff_clear(&state->nsec_mindiff);
02005
02006 dns_diff_clear(&state->affected);
02007 dns_diff_clear(&state->diffnames);
02008 dns_diff_clear(&state->work);
02009
02010 for (i = 0; i < state->nkeys; i++)
02011 dst_key_free(&state->zone_keys[i]);
02012
02013 if (state != &mystate && state != NULL) {
02014 *statep = NULL;
02015 state->magic = 0;
02016 isc_mem_put(diff->mctx, state, sizeof(*state));
02017 }
02018
02019 return (result);
02020 }
02021
02022 static isc_stdtime_t
02023 epoch_to_yyyymmdd(time_t when) {
02024 struct tm *tm;
02025 tm = localtime(&when);
02026 return (((tm->tm_year + 1900) * 10000) +
02027 ((tm->tm_mon + 1) * 100) + tm->tm_mday);
02028 }
02029
02030 isc_uint32_t
02031 dns_update_soaserial(isc_uint32_t serial, dns_updatemethod_t method) {
02032 isc_stdtime_t now;
02033 isc_uint32_t new_serial;
02034
02035 switch (method) {
02036 case dns_updatemethod_none:
02037 return (serial);
02038 case dns_updatemethod_unixtime:
02039 isc_stdtime_get(&now);
02040 if (now != 0 && isc_serial_gt(now, serial))
02041 return (now);
02042 break;
02043 case dns_updatemethod_date:
02044 isc_stdtime_get(&now);
02045 new_serial = epoch_to_yyyymmdd((time_t) now) * 100;
02046 if (new_serial != 0 && isc_serial_gt(new_serial, serial))
02047 return (new_serial);
02048 case dns_updatemethod_increment:
02049 break;
02050 }
02051
02052
02053 serial = (serial + 1) & 0xFFFFFFFF;
02054 if (serial == 0)
02055 serial = 1;
02056
02057 return (serial);
02058 }