00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <isc/netaddr.h>
00023 #include <isc/print.h>
00024 #include <isc/serial.h>
00025 #include <isc/stats.h>
00026 #include <isc/string.h>
00027 #include <isc/taskpool.h>
00028 #include <isc/util.h>
00029
00030 #include <dns/db.h>
00031 #include <dns/dbiterator.h>
00032 #include <dns/diff.h>
00033 #include <dns/dnssec.h>
00034 #include <dns/events.h>
00035 #include <dns/fixedname.h>
00036 #include <dns/journal.h>
00037 #include <dns/keyvalues.h>
00038 #include <dns/message.h>
00039 #include <dns/nsec.h>
00040 #include <dns/nsec3.h>
00041 #include <dns/private.h>
00042 #include <dns/rdataclass.h>
00043 #include <dns/rdataset.h>
00044 #include <dns/rdatasetiter.h>
00045 #include <dns/rdatastruct.h>
00046 #include <dns/rdatatype.h>
00047 #include <dns/soa.h>
00048 #include <dns/ssu.h>
00049 #include <dns/tsig.h>
00050 #include <dns/update.h>
00051 #include <dns/view.h>
00052 #include <dns/zone.h>
00053 #include <dns/zt.h>
00054
00055 #include <named/client.h>
00056 #include <named/log.h>
00057 #include <named/server.h>
00058 #include <named/update.h>
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 #define LOGLEVEL_PROTOCOL ISC_LOG_INFO
00076
00077
00078
00079
00080 #define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8)
00081
00082
00083
00084
00085
00086
00087 #define CHECK(op) \
00088 do { result = (op); \
00089 if (result != ISC_R_SUCCESS) goto failure; \
00090 } while (0)
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 #define FAIL(code) \
00102 do { \
00103 result = (code); \
00104 if (result != ISC_R_SUCCESS) goto failure; \
00105 } while (0)
00106
00107
00108
00109
00110
00111
00112 #define FAILC(code, msg) \
00113 do { \
00114 const char *_what = "failed"; \
00115 result = (code); \
00116 switch (result) { \
00117 case DNS_R_NXDOMAIN: \
00118 case DNS_R_YXDOMAIN: \
00119 case DNS_R_YXRRSET: \
00120 case DNS_R_NXRRSET: \
00121 _what = "unsuccessful"; \
00122 } \
00123 update_log(client, zone, LOGLEVEL_PROTOCOL, \
00124 "update %s: %s (%s)", _what, \
00125 msg, isc_result_totext(result)); \
00126 if (result != ISC_R_SUCCESS) goto failure; \
00127 } while (0)
00128 #define PREREQFAILC(code, msg) \
00129 do { \
00130 inc_stats(zone, dns_nsstatscounter_updatebadprereq); \
00131 FAILC(code, msg); \
00132 } while (0)
00133
00134 #define FAILN(code, name, msg) \
00135 do { \
00136 const char *_what = "failed"; \
00137 result = (code); \
00138 switch (result) { \
00139 case DNS_R_NXDOMAIN: \
00140 case DNS_R_YXDOMAIN: \
00141 case DNS_R_YXRRSET: \
00142 case DNS_R_NXRRSET: \
00143 _what = "unsuccessful"; \
00144 } \
00145 if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \
00146 char _nbuf[DNS_NAME_FORMATSIZE]; \
00147 dns_name_format(name, _nbuf, sizeof(_nbuf)); \
00148 update_log(client, zone, LOGLEVEL_PROTOCOL, \
00149 "update %s: %s: %s (%s)", _what, _nbuf, \
00150 msg, isc_result_totext(result)); \
00151 } \
00152 if (result != ISC_R_SUCCESS) goto failure; \
00153 } while (0)
00154 #define PREREQFAILN(code, name, msg) \
00155 do { \
00156 inc_stats(zone, dns_nsstatscounter_updatebadprereq); \
00157 FAILN(code, name, msg); \
00158 } while (0)
00159
00160 #define FAILNT(code, name, type, msg) \
00161 do { \
00162 const char *_what = "failed"; \
00163 result = (code); \
00164 switch (result) { \
00165 case DNS_R_NXDOMAIN: \
00166 case DNS_R_YXDOMAIN: \
00167 case DNS_R_YXRRSET: \
00168 case DNS_R_NXRRSET: \
00169 _what = "unsuccessful"; \
00170 } \
00171 if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \
00172 char _nbuf[DNS_NAME_FORMATSIZE]; \
00173 char _tbuf[DNS_RDATATYPE_FORMATSIZE]; \
00174 dns_name_format(name, _nbuf, sizeof(_nbuf)); \
00175 dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \
00176 update_log(client, zone, LOGLEVEL_PROTOCOL, \
00177 "update %s: %s/%s: %s (%s)", \
00178 _what, _nbuf, _tbuf, msg, \
00179 isc_result_totext(result)); \
00180 } \
00181 if (result != ISC_R_SUCCESS) goto failure; \
00182 } while (0)
00183 #define PREREQFAILNT(code, name, type, msg) \
00184 do { \
00185 inc_stats(zone, dns_nsstatscounter_updatebadprereq); \
00186 FAILNT(code, name, type, msg); \
00187 } while (0)
00188
00189
00190
00191
00192
00193
00194 #define FAILS(code, msg) \
00195 do { \
00196 result = (code); \
00197 update_log(client, zone, LOGLEVEL_PROTOCOL, \
00198 "error: %s: %s", \
00199 msg, isc_result_totext(result)); \
00200 if (result != ISC_R_SUCCESS) goto failure; \
00201 } while (0)
00202
00203
00204
00205
00206 #define TCPCLIENT(client) (((client)->attributes & NS_CLIENTATTR_TCP) != 0)
00207
00208
00209
00210 typedef struct rr rr_t;
00211
00212 struct rr {
00213
00214 isc_uint32_t ttl;
00215 dns_rdata_t rdata;
00216 };
00217
00218 typedef struct update_event update_event_t;
00219
00220 struct update_event {
00221 ISC_EVENT_COMMON(update_event_t);
00222 dns_zone_t *zone;
00223 isc_result_t result;
00224 dns_message_t *answer;
00225 };
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 typedef struct {
00237 dns_db_t *db;
00238 dns_dbversion_t *ver;
00239 dns_diff_t *diff;
00240 dns_name_t *name;
00241 dns_name_t *oldname;
00242 dns_rdata_t *update_rr;
00243 dns_ttl_t update_rr_ttl;
00244 isc_boolean_t ignore_add;
00245 dns_diff_t del_diff;
00246 dns_diff_t add_diff;
00247 } add_rr_prepare_ctx_t;
00248
00249
00250
00251
00252
00253
00254 static void update_action(isc_task_t *task, isc_event_t *event);
00255 static void updatedone_action(isc_task_t *task, isc_event_t *event);
00256 static isc_result_t send_forward_event(ns_client_t *client, dns_zone_t *zone);
00257 static void forward_done(isc_task_t *task, isc_event_t *event);
00258 static isc_result_t add_rr_prepare_action(void *data, rr_t *rr);
00259
00260
00261
00262 static void
00263 update_log(ns_client_t *client, dns_zone_t *zone,
00264 int level, const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
00265
00266 static void
00267 update_log(ns_client_t *client, dns_zone_t *zone,
00268 int level, const char *fmt, ...)
00269 {
00270 va_list ap;
00271 char message[4096];
00272 char namebuf[DNS_NAME_FORMATSIZE];
00273 char classbuf[DNS_RDATACLASS_FORMATSIZE];
00274
00275 if (client == NULL || zone == NULL)
00276 return;
00277
00278 if (isc_log_wouldlog(ns_g_lctx, level) == ISC_FALSE)
00279 return;
00280
00281 dns_name_format(dns_zone_getorigin(zone), namebuf,
00282 sizeof(namebuf));
00283 dns_rdataclass_format(dns_zone_getclass(zone), classbuf,
00284 sizeof(classbuf));
00285
00286 va_start(ap, fmt);
00287 vsnprintf(message, sizeof(message), fmt, ap);
00288 va_end(ap);
00289
00290 ns_client_log(client, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE,
00291 level, "updating zone '%s/%s': %s",
00292 namebuf, classbuf, message);
00293 }
00294
00295 static void
00296 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
00297 update_log(arg, zone, level, "%s", message);
00298 }
00299
00300
00301
00302
00303 static inline void
00304 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
00305 isc_stats_increment(ns_g_server->nsstats, counter);
00306
00307 if (zone != NULL) {
00308 isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
00309 if (zonestats != NULL)
00310 isc_stats_increment(zonestats, counter);
00311 }
00312 }
00313
00314
00315
00316
00317
00318
00319
00320 static isc_result_t
00321 checkqueryacl(ns_client_t *client, dns_acl_t *queryacl, dns_name_t *zonename,
00322 dns_acl_t *updateacl, dns_ssutable_t *ssutable)
00323 {
00324 char namebuf[DNS_NAME_FORMATSIZE];
00325 char classbuf[DNS_RDATACLASS_FORMATSIZE];
00326 int level;
00327 isc_result_t result;
00328
00329 result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE);
00330 if (result != ISC_R_SUCCESS) {
00331 dns_name_format(zonename, namebuf, sizeof(namebuf));
00332 dns_rdataclass_format(client->view->rdclass, classbuf,
00333 sizeof(classbuf));
00334
00335 level = (updateacl == NULL && ssutable == NULL) ?
00336 ISC_LOG_INFO : ISC_LOG_ERROR;
00337
00338 ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
00339 NS_LOGMODULE_UPDATE, level,
00340 "update '%s/%s' denied due to allow-query",
00341 namebuf, classbuf);
00342 } else if (updateacl == NULL && ssutable == NULL) {
00343 dns_name_format(zonename, namebuf, sizeof(namebuf));
00344 dns_rdataclass_format(client->view->rdclass, classbuf,
00345 sizeof(classbuf));
00346
00347 result = DNS_R_REFUSED;
00348 ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
00349 NS_LOGMODULE_UPDATE, ISC_LOG_INFO,
00350 "update '%s/%s' denied", namebuf, classbuf);
00351 }
00352 return (result);
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 static isc_result_t
00370 checkupdateacl(ns_client_t *client, dns_acl_t *acl, const char *message,
00371 dns_name_t *zonename, isc_boolean_t slave,
00372 isc_boolean_t has_ssutable)
00373 {
00374 char namebuf[DNS_NAME_FORMATSIZE];
00375 char classbuf[DNS_RDATACLASS_FORMATSIZE];
00376 int level = ISC_LOG_ERROR;
00377 const char *msg = "denied";
00378 isc_result_t result;
00379
00380 if (slave && acl == NULL) {
00381 result = DNS_R_NOTIMP;
00382 level = ISC_LOG_DEBUG(3);
00383 msg = "disabled";
00384 } else {
00385 result = ns_client_checkaclsilent(client, NULL, acl, ISC_FALSE);
00386 if (result == ISC_R_SUCCESS) {
00387 level = ISC_LOG_DEBUG(3);
00388 msg = "approved";
00389 } else if (acl == NULL && !has_ssutable) {
00390 level = ISC_LOG_INFO;
00391 }
00392 }
00393
00394 if (client->signer != NULL) {
00395 dns_name_format(client->signer, namebuf, sizeof(namebuf));
00396 ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
00397 NS_LOGMODULE_UPDATE, ISC_LOG_INFO,
00398 "signer \"%s\" %s", namebuf, msg);
00399 }
00400
00401 dns_name_format(zonename, namebuf, sizeof(namebuf));
00402 dns_rdataclass_format(client->view->rdclass, classbuf,
00403 sizeof(classbuf));
00404
00405 ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
00406 NS_LOGMODULE_UPDATE, level, "%s '%s/%s' %s",
00407 message, namebuf, classbuf, msg);
00408 return (result);
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 static isc_result_t
00420 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
00421 dns_diff_t *diff)
00422 {
00423 dns_diff_t temp_diff;
00424 isc_result_t result;
00425
00426
00427
00428
00429 dns_diff_init(diff->mctx, &temp_diff);
00430 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
00431
00432
00433
00434
00435 result = dns_diff_apply(&temp_diff, db, ver);
00436 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
00437 if (result != ISC_R_SUCCESS) {
00438 dns_difftuple_free(tuple);
00439 return (result);
00440 }
00441
00442
00443
00444
00445 dns_diff_appendminimal(diff, tuple);
00446
00447
00448
00449
00450 return (ISC_R_SUCCESS);
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460 static isc_result_t
00461 do_diff(dns_diff_t *updates, dns_db_t *db, dns_dbversion_t *ver,
00462 dns_diff_t *diff)
00463 {
00464 isc_result_t result;
00465 while (! ISC_LIST_EMPTY(updates->tuples)) {
00466 dns_difftuple_t *t = ISC_LIST_HEAD(updates->tuples);
00467 ISC_LIST_UNLINK(updates->tuples, t, link);
00468 CHECK(do_one_tuple(&t, db, ver, diff));
00469 }
00470 return (ISC_R_SUCCESS);
00471
00472 failure:
00473 dns_diff_clear(diff);
00474 return (result);
00475 }
00476
00477 static isc_result_t
00478 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
00479 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
00480 dns_rdata_t *rdata)
00481 {
00482 dns_difftuple_t *tuple = NULL;
00483 isc_result_t result;
00484 result = dns_difftuple_create(diff->mctx, op,
00485 name, ttl, rdata, &tuple);
00486 if (result != ISC_R_SUCCESS)
00487 return (result);
00488 return (do_one_tuple(&tuple, db, ver, diff));
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 typedef isc_result_t rrset_func(void *data, dns_rdataset_t *rrset);
00515
00516
00517
00518
00519 typedef isc_result_t rr_func(void *data, rr_t *rr);
00520
00521
00522
00523
00524 typedef struct {
00525 rr_func * rr_action;
00526 void * rr_action_data;
00527 } foreach_node_rr_ctx_t;
00528
00529
00530
00531
00532 static isc_result_t
00533 foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) {
00534 isc_result_t result;
00535 foreach_node_rr_ctx_t *ctx = data;
00536 for (result = dns_rdataset_first(rdataset);
00537 result == ISC_R_SUCCESS;
00538 result = dns_rdataset_next(rdataset))
00539 {
00540 rr_t rr = { 0, DNS_RDATA_INIT };
00541
00542 dns_rdataset_current(rdataset, &rr.rdata);
00543 rr.ttl = rdataset->ttl;
00544 result = (*ctx->rr_action)(ctx->rr_action_data, &rr);
00545 if (result != ISC_R_SUCCESS)
00546 return (result);
00547 }
00548 if (result != ISC_R_NOMORE)
00549 return (result);
00550 return (ISC_R_SUCCESS);
00551 }
00552
00553
00554
00555
00556
00557
00558
00559
00560 static isc_result_t
00561 foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00562 rrset_func *action, void *action_data)
00563 {
00564 isc_result_t result;
00565 dns_dbnode_t *node;
00566 dns_rdatasetiter_t *iter;
00567 dns_clientinfomethods_t cm;
00568 dns_clientinfo_t ci;
00569 dns_dbversion_t *oldver = NULL;
00570
00571 dns_clientinfomethods_init(&cm, ns_client_sourceip);
00572
00573
00574
00575
00576
00577 dns_db_currentversion(db, &oldver);
00578 dns_clientinfo_init(&ci, NULL, (ver != oldver) ? ver : NULL);
00579 dns_db_closeversion(db, &oldver, ISC_FALSE);
00580
00581 node = NULL;
00582 result = dns_db_findnodeext(db, name, ISC_FALSE, &cm, &ci, &node);
00583 if (result == ISC_R_NOTFOUND)
00584 return (ISC_R_SUCCESS);
00585 if (result != ISC_R_SUCCESS)
00586 return (result);
00587
00588 iter = NULL;
00589 result = dns_db_allrdatasets(db, node, ver,
00590 (isc_stdtime_t) 0, &iter);
00591 if (result != ISC_R_SUCCESS)
00592 goto cleanup_node;
00593
00594 for (result = dns_rdatasetiter_first(iter);
00595 result == ISC_R_SUCCESS;
00596 result = dns_rdatasetiter_next(iter))
00597 {
00598 dns_rdataset_t rdataset;
00599
00600 dns_rdataset_init(&rdataset);
00601 dns_rdatasetiter_current(iter, &rdataset);
00602
00603 result = (*action)(action_data, &rdataset);
00604
00605 dns_rdataset_disassociate(&rdataset);
00606 if (result != ISC_R_SUCCESS)
00607 goto cleanup_iterator;
00608 }
00609 if (result == ISC_R_NOMORE)
00610 result = ISC_R_SUCCESS;
00611
00612 cleanup_iterator:
00613 dns_rdatasetiter_destroy(&iter);
00614
00615 cleanup_node:
00616 dns_db_detachnode(db, &node);
00617
00618 return (result);
00619 }
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629 static isc_result_t
00630 foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00631 rr_func *rr_action, void *rr_action_data)
00632 {
00633 foreach_node_rr_ctx_t ctx;
00634 ctx.rr_action = rr_action;
00635 ctx.rr_action_data = rr_action_data;
00636 return (foreach_rrset(db, ver, name,
00637 foreach_node_rr_action, &ctx));
00638 }
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650 static isc_result_t
00651 foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00652 dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action,
00653 void *rr_action_data)
00654 {
00655
00656 isc_result_t result;
00657 dns_dbnode_t *node;
00658 dns_rdataset_t rdataset;
00659 dns_clientinfomethods_t cm;
00660 dns_clientinfo_t ci;
00661 dns_dbversion_t *oldver = NULL;
00662 dns_fixedname_t fixed;
00663
00664 dns_clientinfomethods_init(&cm, ns_client_sourceip);
00665
00666
00667
00668
00669
00670 dns_db_currentversion(db, &oldver);
00671 dns_clientinfo_init(&ci, NULL, (ver != oldver) ? ver : NULL);
00672 dns_db_closeversion(db, &oldver, ISC_FALSE);
00673
00674 if (type == dns_rdatatype_any)
00675 return (foreach_node_rr(db, ver, name,
00676 rr_action, rr_action_data));
00677
00678 node = NULL;
00679 if (type == dns_rdatatype_nsec3 ||
00680 (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3))
00681 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
00682 else
00683 result = dns_db_findnodeext(db, name, ISC_FALSE,
00684 &cm, &ci, &node);
00685 if (result == ISC_R_NOTFOUND)
00686 return (ISC_R_SUCCESS);
00687 if (result != ISC_R_SUCCESS)
00688 return (result);
00689
00690 dns_rdataset_init(&rdataset);
00691 result = dns_db_findrdataset(db, node, ver, type, covers,
00692 (isc_stdtime_t) 0, &rdataset, NULL);
00693 if (result == ISC_R_NOTFOUND) {
00694 result = ISC_R_SUCCESS;
00695 goto cleanup_node;
00696 }
00697 if (result != ISC_R_SUCCESS)
00698 goto cleanup_node;
00699
00700 if (rr_action == add_rr_prepare_action) {
00701 add_rr_prepare_ctx_t *ctx = rr_action_data;
00702
00703 dns_fixedname_init(&fixed);
00704 ctx->oldname = dns_fixedname_name(&fixed);
00705 dns_name_copy(name, ctx->oldname, NULL);
00706 dns_rdataset_getownercase(&rdataset, ctx->oldname);
00707 }
00708
00709 for (result = dns_rdataset_first(&rdataset);
00710 result == ISC_R_SUCCESS;
00711 result = dns_rdataset_next(&rdataset))
00712 {
00713 rr_t rr = { 0, DNS_RDATA_INIT };
00714 dns_rdataset_current(&rdataset, &rr.rdata);
00715 rr.ttl = rdataset.ttl;
00716 result = (*rr_action)(rr_action_data, &rr);
00717 if (result != ISC_R_SUCCESS)
00718 goto cleanup_rdataset;
00719 }
00720 if (result != ISC_R_NOMORE)
00721 goto cleanup_rdataset;
00722 result = ISC_R_SUCCESS;
00723
00724 cleanup_rdataset:
00725 dns_rdataset_disassociate(&rdataset);
00726 cleanup_node:
00727 dns_db_detachnode(db, &node);
00728
00729 return (result);
00730 }
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741 typedef isc_boolean_t rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr);
00742
00743
00744
00745
00746 static isc_result_t
00747 rrset_exists_action(void *data, rr_t *rr) {
00748 UNUSED(data);
00749 UNUSED(rr);
00750 return (ISC_R_EXISTS);
00751 }
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 #define RETURN_EXISTENCE_FLAG \
00767 return ((result == ISC_R_EXISTS) ? \
00768 (*exists = ISC_TRUE, ISC_R_SUCCESS) : \
00769 ((result == ISC_R_SUCCESS) ? \
00770 (*exists = ISC_FALSE, ISC_R_SUCCESS) : \
00771 result))
00772
00773
00774
00775
00776
00777 static isc_result_t
00778 rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00779 dns_rdatatype_t type, dns_rdatatype_t covers,
00780 isc_boolean_t *exists)
00781 {
00782 isc_result_t result;
00783 result = foreach_rr(db, ver, name, type, covers,
00784 rrset_exists_action, NULL);
00785 RETURN_EXISTENCE_FLAG;
00786 }
00787
00788
00789
00790
00791 static isc_result_t
00792 cname_compatibility_action(void *data, dns_rdataset_t *rrset) {
00793 UNUSED(data);
00794 if (rrset->type != dns_rdatatype_cname &&
00795 ! dns_rdatatype_isdnssec(rrset->type))
00796 return (ISC_R_EXISTS);
00797 return (ISC_R_SUCCESS);
00798 }
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 static isc_result_t
00809 cname_incompatible_rrset_exists(dns_db_t *db, dns_dbversion_t *ver,
00810 dns_name_t *name, isc_boolean_t *exists) {
00811 isc_result_t result;
00812 result = foreach_rrset(db, ver, name,
00813 cname_compatibility_action, NULL);
00814 RETURN_EXISTENCE_FLAG;
00815 }
00816
00817
00818
00819
00820 static isc_result_t
00821 count_rr_action(void *data, rr_t *rr) {
00822 int *countp = data;
00823 UNUSED(rr);
00824 (*countp)++;
00825 return (ISC_R_SUCCESS);
00826 }
00827
00828
00829
00830
00831 static isc_result_t
00832 rr_count(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00833 dns_rdatatype_t type, dns_rdatatype_t covers, int *countp)
00834 {
00835 *countp = 0;
00836 return (foreach_rr(db, ver, name, type, covers,
00837 count_rr_action, countp));
00838 }
00839
00840
00841
00842
00843
00844 static isc_result_t
00845 name_exists_action(void *data, dns_rdataset_t *rrset) {
00846 UNUSED(data);
00847 UNUSED(rrset);
00848 return (ISC_R_EXISTS);
00849 }
00850
00851
00852
00853
00854 static isc_result_t
00855 name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00856 isc_boolean_t *exists)
00857 {
00858 isc_result_t result;
00859 result = foreach_rrset(db, ver, name,
00860 name_exists_action, NULL);
00861 RETURN_EXISTENCE_FLAG;
00862 }
00863
00864
00865
00866
00867
00868
00869 typedef struct {
00870
00871 dns_name_t *name;
00872
00873
00874 dns_name_t *signer;
00875
00876
00877 isc_netaddr_t *tcpaddr;
00878
00879
00880 dns_ssutable_t *table;
00881
00882
00883 dst_key_t *key;
00884 } ssu_check_t;
00885
00886 static isc_result_t
00887 ssu_checkrule(void *data, dns_rdataset_t *rrset) {
00888 ssu_check_t *ssuinfo = data;
00889 isc_boolean_t result;
00890
00891
00892
00893
00894
00895 if (rrset->type == dns_rdatatype_rrsig ||
00896 rrset->type == dns_rdatatype_nsec)
00897 return (ISC_R_SUCCESS);
00898 result = dns_ssutable_checkrules(ssuinfo->table, ssuinfo->signer,
00899 ssuinfo->name, ssuinfo->tcpaddr,
00900 rrset->type, ssuinfo->key);
00901 return (result == ISC_TRUE ? ISC_R_SUCCESS : ISC_R_FAILURE);
00902 }
00903
00904 static isc_boolean_t
00905 ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
00906 dns_ssutable_t *ssutable, dns_name_t *signer,
00907 isc_netaddr_t *tcpaddr, dst_key_t *key)
00908 {
00909 isc_result_t result;
00910 ssu_check_t ssuinfo;
00911
00912 ssuinfo.name = name;
00913 ssuinfo.table = ssutable;
00914 ssuinfo.signer = signer;
00915 ssuinfo.tcpaddr = tcpaddr;
00916 ssuinfo.key = key;
00917 result = foreach_rrset(db, ver, name, ssu_checkrule, &ssuinfo);
00918 return (ISC_TF(result == ISC_R_SUCCESS));
00919 }
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 static isc_result_t
00938 temp_append(dns_diff_t *diff, dns_name_t *name, dns_rdata_t *rdata) {
00939 isc_result_t result;
00940 dns_difftuple_t *tuple = NULL;
00941
00942 REQUIRE(DNS_DIFF_VALID(diff));
00943 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_EXISTS,
00944 name, 0, rdata, &tuple));
00945 ISC_LIST_APPEND(diff->tuples, tuple, link);
00946 failure:
00947 return (result);
00948 }
00949
00950
00951
00952
00953
00954
00955
00956 static isc_result_t
00957 temp_check_rrset(dns_difftuple_t *a, dns_difftuple_t *b) {
00958 for (;;) {
00959 if (a == NULL || b == NULL)
00960 break;
00961 INSIST(a->op == DNS_DIFFOP_EXISTS &&
00962 b->op == DNS_DIFFOP_EXISTS);
00963 INSIST(a->rdata.type == b->rdata.type);
00964 INSIST(dns_name_equal(&a->name, &b->name));
00965 if (dns_rdata_casecompare(&a->rdata, &b->rdata) != 0)
00966 return (DNS_R_NXRRSET);
00967 a = ISC_LIST_NEXT(a, link);
00968 b = ISC_LIST_NEXT(b, link);
00969 }
00970 if (a != NULL || b != NULL)
00971 return (DNS_R_NXRRSET);
00972 return (ISC_R_SUCCESS);
00973 }
00974
00975
00976
00977
00978
00979
00980 static int
00981 temp_order(const void *av, const void *bv) {
00982 dns_difftuple_t const * const *ap = av;
00983 dns_difftuple_t const * const *bp = bv;
00984 dns_difftuple_t const *a = *ap;
00985 dns_difftuple_t const *b = *bp;
00986 int r;
00987 r = dns_name_compare(&a->name, &b->name);
00988 if (r != 0)
00989 return (r);
00990 r = (b->rdata.type - a->rdata.type);
00991 if (r != 0)
00992 return (r);
00993 r = dns_rdata_casecompare(&a->rdata, &b->rdata);
00994 return (r);
00995 }
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007 static isc_result_t
01008 temp_check(isc_mem_t *mctx, dns_diff_t *temp, dns_db_t *db,
01009 dns_dbversion_t *ver, dns_name_t *tmpname, dns_rdatatype_t *typep)
01010 {
01011 isc_result_t result;
01012 dns_name_t *name;
01013 dns_dbnode_t *node;
01014 dns_difftuple_t *t;
01015 dns_diff_t trash;
01016
01017 dns_diff_init(mctx, &trash);
01018
01019
01020
01021
01022
01023
01024 t = ISC_LIST_HEAD(temp->tuples);
01025 while (t != NULL) {
01026 name = &t->name;
01027 (void)dns_name_copy(name, tmpname, NULL);
01028 *typep = t->rdata.type;
01029
01030
01031 node = NULL;
01032 result = dns_db_findnode(db, name, ISC_FALSE, &node);
01033 if (result == ISC_R_NOTFOUND) {
01034 dns_diff_clear(&trash);
01035 return (DNS_R_NXRRSET);
01036 }
01037 if (result != ISC_R_SUCCESS) {
01038 dns_diff_clear(&trash);
01039 return (result);
01040 }
01041
01042
01043 while (t != NULL && dns_name_equal(&t->name, name)) {
01044 dns_rdatatype_t type, covers;
01045 dns_rdataset_t rdataset;
01046 dns_diff_t d_rrs;
01047
01048 dns_diff_t u_rrs;
01049
01050
01051 *typep = type = t->rdata.type;
01052 if (type == dns_rdatatype_rrsig ||
01053 type == dns_rdatatype_sig)
01054 covers = dns_rdata_covers(&t->rdata);
01055 else if (type == dns_rdatatype_any) {
01056 dns_db_detachnode(db, &node);
01057 dns_diff_clear(&trash);
01058 return (DNS_R_NXRRSET);
01059 } else
01060 covers = 0;
01061
01062
01063
01064
01065
01066 dns_rdataset_init(&rdataset);
01067 result = dns_db_findrdataset(db, node, ver, type,
01068 covers, (isc_stdtime_t) 0,
01069 &rdataset, NULL);
01070 if (result != ISC_R_SUCCESS) {
01071 dns_db_detachnode(db, &node);
01072 dns_diff_clear(&trash);
01073 return (DNS_R_NXRRSET);
01074 }
01075
01076 dns_diff_init(mctx, &d_rrs);
01077 dns_diff_init(mctx, &u_rrs);
01078
01079 for (result = dns_rdataset_first(&rdataset);
01080 result == ISC_R_SUCCESS;
01081 result = dns_rdataset_next(&rdataset))
01082 {
01083 dns_rdata_t rdata = DNS_RDATA_INIT;
01084 dns_rdataset_current(&rdataset, &rdata);
01085 result = temp_append(&d_rrs, name, &rdata);
01086 if (result != ISC_R_SUCCESS)
01087 goto failure;
01088 }
01089 if (result != ISC_R_NOMORE)
01090 goto failure;
01091 result = dns_diff_sort(&d_rrs, temp_order);
01092 if (result != ISC_R_SUCCESS)
01093 goto failure;
01094
01095
01096
01097
01098
01099
01100 while (t != NULL &&
01101 dns_name_equal(&t->name, name) &&
01102 t->rdata.type == type)
01103 {
01104 dns_difftuple_t *next =
01105 ISC_LIST_NEXT(t, link);
01106 ISC_LIST_UNLINK(temp->tuples, t, link);
01107 ISC_LIST_APPEND(u_rrs.tuples, t, link);
01108 t = next;
01109 }
01110
01111
01112 result = temp_check_rrset(ISC_LIST_HEAD(u_rrs.tuples),
01113 ISC_LIST_HEAD(d_rrs.tuples));
01114 if (result != ISC_R_SUCCESS)
01115 goto failure;
01116
01117
01118
01119
01120
01121
01122 ISC_LIST_APPENDLIST(trash.tuples, u_rrs.tuples, link);
01123 ISC_LIST_APPENDLIST(trash.tuples, d_rrs.tuples, link);
01124 dns_rdataset_disassociate(&rdataset);
01125
01126 continue;
01127
01128 failure:
01129 dns_diff_clear(&d_rrs);
01130 dns_diff_clear(&u_rrs);
01131 dns_diff_clear(&trash);
01132 dns_rdataset_disassociate(&rdataset);
01133 dns_db_detachnode(db, &node);
01134 return (result);
01135 }
01136
01137 dns_db_detachnode(db, &node);
01138 }
01139
01140 dns_diff_clear(&trash);
01141 return (ISC_R_SUCCESS);
01142 }
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153 typedef struct {
01154 rr_predicate *predicate;
01155 dns_db_t *db;
01156 dns_dbversion_t *ver;
01157 dns_diff_t *diff;
01158 dns_name_t *name;
01159 dns_rdata_t *update_rr;
01160 } conditional_delete_ctx_t;
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170 static isc_boolean_t
01171 type_not_soa_nor_ns_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
01172 UNUSED(update_rr);
01173 return ((db_rr->type != dns_rdatatype_soa &&
01174 db_rr->type != dns_rdatatype_ns &&
01175 db_rr->type != dns_rdatatype_nsec3param &&
01176 db_rr->type != dns_rdatatype_rrsig &&
01177 db_rr->type != dns_rdatatype_nsec) ?
01178 ISC_TRUE : ISC_FALSE);
01179 }
01180
01181
01182
01183
01184 static isc_boolean_t
01185 type_not_dnssec(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
01186 UNUSED(update_rr);
01187 return ((db_rr->type != dns_rdatatype_rrsig &&
01188 db_rr->type != dns_rdatatype_nsec) ?
01189 ISC_TRUE : ISC_FALSE);
01190 }
01191
01192
01193
01194
01195 static isc_boolean_t
01196 true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
01197 UNUSED(update_rr);
01198 UNUSED(db_rr);
01199 return (ISC_TRUE);
01200 }
01201
01202
01203
01204
01205 static isc_boolean_t
01206 rr_equal_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
01207
01208
01209
01210
01211
01212 return (dns_rdata_casecompare(update_rr, db_rr) == 0 ?
01213 ISC_TRUE : ISC_FALSE);
01214 }
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228 static isc_boolean_t
01229 replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
01230 dns_rdata_rrsig_t updatesig, dbsig;
01231 isc_result_t result;
01232
01233 if (db_rr->type != update_rr->type)
01234 return (ISC_FALSE);
01235 if (db_rr->type == dns_rdatatype_cname)
01236 return (ISC_TRUE);
01237 if (db_rr->type == dns_rdatatype_dname)
01238 return (ISC_TRUE);
01239 if (db_rr->type == dns_rdatatype_soa)
01240 return (ISC_TRUE);
01241 if (db_rr->type == dns_rdatatype_nsec)
01242 return (ISC_TRUE);
01243 if (db_rr->type == dns_rdatatype_rrsig) {
01244
01245
01246
01247
01248 result = dns_rdata_tostruct(db_rr, &dbsig, NULL);
01249 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01250 result = dns_rdata_tostruct(update_rr, &updatesig, NULL);
01251 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01252 if (dbsig.keyid == updatesig.keyid &&
01253 dbsig.covered == updatesig.covered &&
01254 dbsig.algorithm == updatesig.algorithm)
01255 return (ISC_TRUE);
01256 }
01257 if (db_rr->type == dns_rdatatype_wks) {
01258
01259
01260
01261
01262
01263
01264 INSIST(db_rr->length >= 5 && update_rr->length >= 5);
01265 return (memcmp(db_rr->data, update_rr->data, 5) == 0 ?
01266 ISC_TRUE : ISC_FALSE);
01267 }
01268
01269 if (db_rr->type == dns_rdatatype_nsec3param) {
01270 if (db_rr->length != update_rr->length)
01271 return (ISC_FALSE);
01272 INSIST(db_rr->length >= 4 && update_rr->length >= 4);
01273
01274
01275
01276
01277 if (db_rr->data[0] == update_rr->data[0] &&
01278 memcmp(db_rr->data+2, update_rr->data+2,
01279 update_rr->length - 2) == 0)
01280 return (ISC_TRUE);
01281 }
01282 return (ISC_FALSE);
01283 }
01284
01285
01286
01287
01288 static isc_result_t
01289 delete_if_action(void *data, rr_t *rr) {
01290 conditional_delete_ctx_t *ctx = data;
01291 if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) {
01292 isc_result_t result;
01293 result = update_one_rr(ctx->db, ctx->ver, ctx->diff,
01294 DNS_DIFFOP_DEL, ctx->name,
01295 rr->ttl, &rr->rdata);
01296 return (result);
01297 } else {
01298 return (ISC_R_SUCCESS);
01299 }
01300 }
01301
01302
01303
01304
01305
01306
01307
01308
01309 static isc_result_t
01310 delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver,
01311 dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers,
01312 dns_rdata_t *update_rr, dns_diff_t *diff)
01313 {
01314 conditional_delete_ctx_t ctx;
01315 ctx.predicate = predicate;
01316 ctx.db = db;
01317 ctx.ver = ver;
01318 ctx.diff = diff;
01319 ctx.name = name;
01320 ctx.update_rr = update_rr;
01321 return (foreach_rr(db, ver, name, type, covers,
01322 delete_if_action, &ctx));
01323 }
01324
01325
01326
01327 static isc_result_t
01328 add_rr_prepare_action(void *data, rr_t *rr) {
01329 isc_result_t result = ISC_R_SUCCESS;
01330 add_rr_prepare_ctx_t *ctx = data;
01331 dns_difftuple_t *tuple = NULL;
01332 isc_boolean_t equal, case_equal, ttl_equal;
01333
01334
01335
01336
01337 case_equal = dns_name_caseequal(ctx->name, ctx->oldname);
01338
01339
01340
01341
01342 ttl_equal = rr->ttl == ctx->update_rr_ttl;
01343
01344
01345
01346
01347
01348 equal = ISC_TF(dns_rdata_casecompare(&rr->rdata, ctx->update_rr) == 0);
01349 if (equal && case_equal && ttl_equal) {
01350 ctx->ignore_add = ISC_TRUE;
01351 return (ISC_R_SUCCESS);
01352 }
01353
01354
01355
01356
01357
01358 if (replaces_p(ctx->update_rr, &rr->rdata)) {
01359 CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL,
01360 ctx->oldname, rr->ttl, &rr->rdata,
01361 &tuple));
01362 dns_diff_append(&ctx->del_diff, &tuple);
01363 return (ISC_R_SUCCESS);
01364 }
01365
01366
01367
01368
01369
01370 if (!ttl_equal || !case_equal) {
01371 CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL,
01372 ctx->oldname, rr->ttl, &rr->rdata,
01373 &tuple));
01374 dns_diff_append(&ctx->del_diff, &tuple);
01375 if (!equal) {
01376 CHECK(dns_difftuple_create(ctx->add_diff.mctx,
01377 DNS_DIFFOP_ADD, ctx->name,
01378 ctx->update_rr_ttl,
01379 &rr->rdata, &tuple));
01380 dns_diff_append(&ctx->add_diff, &tuple);
01381 }
01382 }
01383 failure:
01384 return (result);
01385 }
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399 static void
01400 get_current_rr(dns_message_t *msg, dns_section_t section,
01401 dns_rdataclass_t zoneclass, dns_name_t **name,
01402 dns_rdata_t *rdata, dns_rdatatype_t *covers,
01403 dns_ttl_t *ttl, dns_rdataclass_t *update_class)
01404 {
01405 dns_rdataset_t *rdataset;
01406 isc_result_t result;
01407 dns_message_currentname(msg, section, name);
01408 rdataset = ISC_LIST_HEAD((*name)->list);
01409 INSIST(rdataset != NULL);
01410 INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
01411 *covers = rdataset->covers;
01412 *ttl = rdataset->ttl;
01413 result = dns_rdataset_first(rdataset);
01414 INSIST(result == ISC_R_SUCCESS);
01415 dns_rdataset_current(rdataset, rdata);
01416 INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE);
01417 *update_class = rdata->rdclass;
01418 rdata->rdclass = zoneclass;
01419 }
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433 static isc_result_t
01434 update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
01435 isc_mem_t *mctx, dns_updatemethod_t method)
01436 {
01437 dns_difftuple_t *deltuple = NULL;
01438 dns_difftuple_t *addtuple = NULL;
01439 isc_uint32_t serial;
01440 isc_result_t result;
01441
01442 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
01443 CHECK(dns_difftuple_copy(deltuple, &addtuple));
01444 addtuple->op = DNS_DIFFOP_ADD;
01445
01446 serial = dns_soa_getserial(&addtuple->rdata);
01447 serial = dns_update_soaserial(serial, method);
01448 dns_soa_setserial(serial, &addtuple->rdata);
01449 CHECK(do_one_tuple(&deltuple, db, ver, diff));
01450 CHECK(do_one_tuple(&addtuple, db, ver, diff));
01451 result = ISC_R_SUCCESS;
01452
01453 failure:
01454 if (addtuple != NULL)
01455 dns_difftuple_free(&addtuple);
01456 if (deltuple != NULL)
01457 dns_difftuple_free(&deltuple);
01458 return (result);
01459 }
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481 static isc_result_t
01482 check_soa_increment(dns_db_t *db, dns_dbversion_t *ver,
01483 dns_rdata_t *update_rdata, isc_boolean_t *ok)
01484 {
01485 isc_uint32_t db_serial;
01486 isc_uint32_t update_serial;
01487 isc_result_t result;
01488
01489 update_serial = dns_soa_getserial(update_rdata);
01490
01491 result = dns_db_getsoaserial(db, ver, &db_serial);
01492 if (result != ISC_R_SUCCESS)
01493 return (result);
01494
01495 if (DNS_SERIAL_GE(db_serial, update_serial)) {
01496 *ok = ISC_FALSE;
01497 } else {
01498 *ok = ISC_TRUE;
01499 }
01500
01501 return (ISC_R_SUCCESS);
01502
01503 }
01504
01505
01506
01507
01508
01509
01510
01511 static isc_result_t
01512 send_update_event(ns_client_t *client, dns_zone_t *zone) {
01513 isc_result_t result = ISC_R_SUCCESS;
01514 update_event_t *event = NULL;
01515 isc_task_t *zonetask = NULL;
01516 ns_client_t *evclient;
01517
01518 event = (update_event_t *)
01519 isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE,
01520 update_action, NULL, sizeof(*event));
01521 if (event == NULL)
01522 FAIL(ISC_R_NOMEMORY);
01523 event->zone = zone;
01524 event->result = ISC_R_SUCCESS;
01525
01526 evclient = NULL;
01527 ns_client_attach(client, &evclient);
01528 INSIST(client->nupdates == 0);
01529 client->nupdates++;
01530 event->ev_arg = evclient;
01531
01532 dns_zone_gettask(zone, &zonetask);
01533 isc_task_send(zonetask, ISC_EVENT_PTR(&event));
01534
01535 failure:
01536 if (event != NULL)
01537 isc_event_free(ISC_EVENT_PTR(&event));
01538 return (result);
01539 }
01540
01541 static void
01542 respond(ns_client_t *client, isc_result_t result) {
01543 isc_result_t msg_result;
01544
01545 msg_result = dns_message_reply(client->message, ISC_TRUE);
01546 if (msg_result != ISC_R_SUCCESS)
01547 goto msg_failure;
01548 client->message->rcode = dns_result_torcode(result);
01549
01550 ns_client_send(client);
01551 return;
01552
01553 msg_failure:
01554 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE,
01555 ISC_LOG_ERROR,
01556 "could not create update response message: %s",
01557 isc_result_totext(msg_result));
01558 ns_client_next(client, msg_result);
01559 }
01560
01561 void
01562 ns_update_start(ns_client_t *client, isc_result_t sigresult) {
01563 dns_message_t *request = client->message;
01564 isc_result_t result;
01565 dns_name_t *zonename;
01566 dns_rdataset_t *zone_rdataset;
01567 dns_zone_t *zone = NULL, *raw = NULL;
01568
01569
01570
01571
01572 result = dns_message_firstname(request, DNS_SECTION_ZONE);
01573 if (result != ISC_R_SUCCESS)
01574 FAILC(DNS_R_FORMERR, "update zone section empty");
01575
01576
01577
01578
01579
01580 zonename = NULL;
01581 dns_message_currentname(request, DNS_SECTION_ZONE, &zonename);
01582 zone_rdataset = ISC_LIST_HEAD(zonename->list);
01583 if (zone_rdataset->type != dns_rdatatype_soa)
01584 FAILC(DNS_R_FORMERR,
01585 "update zone section contains non-SOA");
01586 if (ISC_LIST_NEXT(zone_rdataset, link) != NULL)
01587 FAILC(DNS_R_FORMERR,
01588 "update zone section contains multiple RRs");
01589
01590
01591 result = dns_message_nextname(request, DNS_SECTION_ZONE);
01592 if (result != ISC_R_NOMORE)
01593 FAILC(DNS_R_FORMERR,
01594 "update zone section contains multiple RRs");
01595
01596 result = dns_zt_find(client->view->zonetable, zonename, 0, NULL,
01597 &zone);
01598 if (result != ISC_R_SUCCESS)
01599 FAILC(DNS_R_NOTAUTH, "not authoritative for update zone");
01600
01601
01602
01603
01604
01605 dns_zone_getraw(zone, &raw);
01606 if (raw != NULL) {
01607 dns_zone_detach(&zone);
01608 dns_zone_attach(raw, &zone);
01609 dns_zone_detach(&raw);
01610 }
01611
01612 switch(dns_zone_gettype(zone)) {
01613 case dns_zone_master:
01614 case dns_zone_dlz:
01615
01616
01617
01618
01619 if (sigresult != ISC_R_SUCCESS)
01620 FAIL(sigresult);
01621 CHECK(send_update_event(client, zone));
01622 break;
01623 case dns_zone_slave:
01624 CHECK(checkupdateacl(client, dns_zone_getforwardacl(zone),
01625 "update forwarding", zonename, ISC_TRUE,
01626 ISC_FALSE));
01627 CHECK(send_forward_event(client, zone));
01628 break;
01629 default:
01630 FAILC(DNS_R_NOTAUTH, "not authoritative for update zone");
01631 }
01632 return;
01633
01634 failure:
01635 if (result == DNS_R_REFUSED) {
01636 INSIST(dns_zone_gettype(zone) == dns_zone_slave);
01637 inc_stats(zone, dns_nsstatscounter_updaterej);
01638 }
01639
01640
01641
01642
01643
01644 respond(client, result);
01645 if (zone != NULL)
01646 dns_zone_detach(&zone);
01647 }
01648
01649
01650
01651
01652
01653
01654
01655 static isc_result_t
01656 remove_orphaned_ds(dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff) {
01657 isc_result_t result;
01658 isc_boolean_t ns_exists;
01659 dns_difftuple_t *tupple;
01660 dns_diff_t temp_diff;
01661
01662 dns_diff_init(diff->mctx, &temp_diff);
01663
01664 for (tupple = ISC_LIST_HEAD(diff->tuples);
01665 tupple != NULL;
01666 tupple = ISC_LIST_NEXT(tupple, link)) {
01667 if (!((tupple->op == DNS_DIFFOP_DEL &&
01668 tupple->rdata.type == dns_rdatatype_ns) ||
01669 (tupple->op == DNS_DIFFOP_ADD &&
01670 tupple->rdata.type == dns_rdatatype_ds)))
01671 continue;
01672 CHECK(rrset_exists(db, newver, &tupple->name,
01673 dns_rdatatype_ns, 0, &ns_exists));
01674 if (ns_exists &&
01675 !dns_name_equal(&tupple->name, dns_db_origin(db)))
01676 continue;
01677 CHECK(delete_if(true_p, db, newver, &tupple->name,
01678 dns_rdatatype_ds, 0, NULL, &temp_diff));
01679 }
01680 result = ISC_R_SUCCESS;
01681
01682 failure:
01683 for (tupple = ISC_LIST_HEAD(temp_diff.tuples);
01684 tupple != NULL;
01685 tupple = ISC_LIST_HEAD(temp_diff.tuples)) {
01686 ISC_LIST_UNLINK(temp_diff.tuples, tupple, link);
01687 dns_diff_appendminimal(diff, &tupple);
01688 }
01689 return (result);
01690 }
01691
01692
01693
01694
01695 static isc_result_t
01696 check_mx(ns_client_t *client, dns_zone_t *zone,
01697 dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff)
01698 {
01699 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123.")];
01700 char ownerbuf[DNS_NAME_FORMATSIZE];
01701 char namebuf[DNS_NAME_FORMATSIZE];
01702 char altbuf[DNS_NAME_FORMATSIZE];
01703 dns_difftuple_t *t;
01704 dns_fixedname_t fixed;
01705 dns_name_t *foundname;
01706 dns_rdata_mx_t mx;
01707 dns_rdata_t rdata;
01708 isc_boolean_t ok = ISC_TRUE;
01709 isc_boolean_t isaddress;
01710 isc_result_t result;
01711 struct in6_addr addr6;
01712 struct in_addr addr;
01713 unsigned int options;
01714
01715 dns_fixedname_init(&fixed);
01716 foundname = dns_fixedname_name(&fixed);
01717 dns_rdata_init(&rdata);
01718 options = dns_zone_getoptions(zone);
01719
01720 for (t = ISC_LIST_HEAD(diff->tuples);
01721 t != NULL;
01722 t = ISC_LIST_NEXT(t, link)) {
01723 if (t->op != DNS_DIFFOP_ADD ||
01724 t->rdata.type != dns_rdatatype_mx)
01725 continue;
01726
01727 result = dns_rdata_tostruct(&t->rdata, &mx, NULL);
01728 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01729
01730
01731
01732
01733 dns_name_format(&mx.mx, namebuf, sizeof(namebuf));
01734 dns_name_format(&t->name, ownerbuf, sizeof(ownerbuf));
01735 isaddress = ISC_FALSE;
01736 if ((options & DNS_RDATA_CHECKMX) != 0 &&
01737 strlcpy(tmp, namebuf, sizeof(tmp)) < sizeof(tmp)) {
01738 if (tmp[strlen(tmp) - 1] == '.')
01739 tmp[strlen(tmp) - 1] = '\0';
01740 if (inet_aton(tmp, &addr) == 1 ||
01741 inet_pton(AF_INET6, tmp, &addr6) == 1)
01742 isaddress = ISC_TRUE;
01743 }
01744
01745 if (isaddress && (options & DNS_RDATA_CHECKMXFAIL) != 0) {
01746 update_log(client, zone, ISC_LOG_ERROR,
01747 "%s/MX: '%s': %s",
01748 ownerbuf, namebuf,
01749 dns_result_totext(DNS_R_MXISADDRESS));
01750 ok = ISC_FALSE;
01751 } else if (isaddress) {
01752 update_log(client, zone, ISC_LOG_WARNING,
01753 "%s/MX: warning: '%s': %s",
01754 ownerbuf, namebuf,
01755 dns_result_totext(DNS_R_MXISADDRESS));
01756 }
01757
01758
01759
01760
01761 if ((options & DNS_ZONEOPT_CHECKINTEGRITY) == 0)
01762 continue;
01763 result = dns_db_find(db, &mx.mx, newver, dns_rdatatype_a,
01764 0, 0, NULL, foundname, NULL, NULL);
01765 if (result == ISC_R_SUCCESS)
01766 continue;
01767
01768 if (result == DNS_R_NXRRSET) {
01769 result = dns_db_find(db, &mx.mx, newver,
01770 dns_rdatatype_aaaa,
01771 0, 0, NULL, foundname,
01772 NULL, NULL);
01773 if (result == ISC_R_SUCCESS)
01774 continue;
01775 }
01776
01777 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN) {
01778 update_log(client, zone, ISC_LOG_ERROR,
01779 "%s/MX '%s' has no address records "
01780 "(A or AAAA)", ownerbuf, namebuf);
01781 ok = ISC_FALSE;
01782 } else if (result == DNS_R_CNAME) {
01783 update_log(client, zone, ISC_LOG_ERROR,
01784 "%s/MX '%s' is a CNAME (illegal)",
01785 ownerbuf, namebuf);
01786 ok = ISC_FALSE;
01787 } else if (result == DNS_R_DNAME) {
01788 dns_name_format(foundname, altbuf, sizeof altbuf);
01789 update_log(client, zone, ISC_LOG_ERROR,
01790 "%s/MX '%s' is below a DNAME '%s' (illegal)",
01791 ownerbuf, namebuf, altbuf);
01792 ok = ISC_FALSE;
01793 }
01794 }
01795 return (ok ? ISC_R_SUCCESS : DNS_R_REFUSED);
01796 }
01797
01798 static isc_result_t
01799 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
01800 const dns_rdata_t *rdata, isc_boolean_t *flag)
01801 {
01802 dns_rdataset_t rdataset;
01803 dns_dbnode_t *node = NULL;
01804 isc_result_t result;
01805
01806 dns_rdataset_init(&rdataset);
01807 if (rdata->type == dns_rdatatype_nsec3)
01808 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
01809 else
01810 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
01811 result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
01812 (isc_stdtime_t) 0, &rdataset, NULL);
01813 if (result == ISC_R_NOTFOUND) {
01814 *flag = ISC_FALSE;
01815 result = ISC_R_SUCCESS;
01816 goto failure;
01817 }
01818
01819 for (result = dns_rdataset_first(&rdataset);
01820 result == ISC_R_SUCCESS;
01821 result = dns_rdataset_next(&rdataset)) {
01822 dns_rdata_t myrdata = DNS_RDATA_INIT;
01823 dns_rdataset_current(&rdataset, &myrdata);
01824 if (!dns_rdata_casecompare(&myrdata, rdata))
01825 break;
01826 }
01827 dns_rdataset_disassociate(&rdataset);
01828 if (result == ISC_R_SUCCESS) {
01829 *flag = ISC_TRUE;
01830 } else if (result == ISC_R_NOMORE) {
01831 *flag = ISC_FALSE;
01832 result = ISC_R_SUCCESS;
01833 }
01834
01835 failure:
01836 if (node != NULL)
01837 dns_db_detachnode(db, &node);
01838 return (result);
01839 }
01840
01841 static isc_result_t
01842 get_iterations(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype,
01843 unsigned int *iterationsp)
01844 {
01845 dns_dbnode_t *node = NULL;
01846 dns_rdata_nsec3param_t nsec3param;
01847 dns_rdataset_t rdataset;
01848 isc_result_t result;
01849 unsigned int iterations = 0;
01850
01851 dns_rdataset_init(&rdataset);
01852
01853 result = dns_db_getoriginnode(db, &node);
01854 if (result != ISC_R_SUCCESS)
01855 return (result);
01856 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
01857 0, (isc_stdtime_t) 0, &rdataset, NULL);
01858 if (result == ISC_R_NOTFOUND)
01859 goto try_private;
01860 if (result != ISC_R_SUCCESS)
01861 goto failure;
01862
01863 for (result = dns_rdataset_first(&rdataset);
01864 result == ISC_R_SUCCESS;
01865 result = dns_rdataset_next(&rdataset)) {
01866 dns_rdata_t rdata = DNS_RDATA_INIT;
01867 dns_rdataset_current(&rdataset, &rdata);
01868 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
01869 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
01870 continue;
01871 if (nsec3param.iterations > iterations)
01872 iterations = nsec3param.iterations;
01873 }
01874 if (result != ISC_R_NOMORE)
01875 goto failure;
01876
01877 dns_rdataset_disassociate(&rdataset);
01878
01879 try_private:
01880 if (privatetype == 0)
01881 goto success;
01882
01883 result = dns_db_findrdataset(db, node, ver, privatetype,
01884 0, (isc_stdtime_t) 0, &rdataset, NULL);
01885 if (result == ISC_R_NOTFOUND)
01886 goto success;
01887 if (result != ISC_R_SUCCESS)
01888 goto failure;
01889
01890 for (result = dns_rdataset_first(&rdataset);
01891 result == ISC_R_SUCCESS;
01892 result = dns_rdataset_next(&rdataset)) {
01893 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
01894 dns_rdata_t private = DNS_RDATA_INIT;
01895 dns_rdata_t rdata = DNS_RDATA_INIT;
01896
01897 dns_rdataset_current(&rdataset, &rdata);
01898 if (!dns_nsec3param_fromprivate(&private, &rdata,
01899 buf, sizeof(buf)))
01900 continue;
01901 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
01902 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
01903 continue;
01904 if (nsec3param.iterations > iterations)
01905 iterations = nsec3param.iterations;
01906 }
01907 if (result != ISC_R_NOMORE)
01908 goto failure;
01909
01910 success:
01911 *iterationsp = iterations;
01912 result = ISC_R_SUCCESS;
01913
01914 failure:
01915 if (node != NULL)
01916 dns_db_detachnode(db, &node);
01917 if (dns_rdataset_isassociated(&rdataset))
01918 dns_rdataset_disassociate(&rdataset);
01919 return (result);
01920 }
01921
01922
01923
01924
01925
01926 static isc_result_t
01927 check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
01928 dns_dbversion_t *ver, dns_diff_t *diff)
01929 {
01930 dns_difftuple_t *tuple;
01931 isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
01932 isc_result_t result;
01933 unsigned int iterations = 0, max;
01934 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
01935
01936
01937 for (tuple = ISC_LIST_HEAD(diff->tuples);
01938 tuple != NULL;
01939 tuple = ISC_LIST_NEXT(tuple, link)) {
01940 if (tuple->op != DNS_DIFFOP_ADD)
01941 continue;
01942
01943 if (tuple->rdata.type == dns_rdatatype_dnskey) {
01944 isc_uint8_t alg;
01945 alg = tuple->rdata.data[3];
01946 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
01947 alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
01948 nseconly = ISC_TRUE;
01949 break;
01950 }
01951 } else if (tuple->rdata.type == dns_rdatatype_nsec3param) {
01952 nsec3 = ISC_TRUE;
01953 break;
01954 }
01955 }
01956
01957
01958 if (!nseconly) {
01959 result = dns_nsec_nseconly(db, ver, &nseconly);
01960
01961
01962
01963
01964
01965
01966 if (result == ISC_R_NOTFOUND)
01967 result = ISC_R_SUCCESS;
01968
01969 CHECK(result);
01970 }
01971
01972
01973 if (!nsec3)
01974 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
01975 privatetype, &nsec3));
01976
01977
01978 if (nseconly && nsec3) {
01979 update_log(client, zone, ISC_LOG_ERROR,
01980 "NSEC only DNSKEYs and NSEC3 chains not allowed");
01981 result = DNS_R_REFUSED;
01982 goto failure;
01983 }
01984
01985
01986 CHECK(get_iterations(db, ver, privatetype, &iterations));
01987 CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max));
01988 if (max != 0 && iterations > max) {
01989 update_log(client, zone, ISC_LOG_ERROR,
01990 "too many NSEC3 iterations (%u) for "
01991 "weakest DNSKEY (%u)", iterations, max);
01992 result = DNS_R_REFUSED;
01993 goto failure;
01994 }
01995
01996 failure:
01997 return (result);
01998 }
01999
02000
02001
02002
02003 static isc_result_t
02004 add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
02005 dns_dbversion_t *ver, dns_diff_t *diff)
02006 {
02007 isc_result_t result = ISC_R_SUCCESS;
02008 dns_difftuple_t *tuple, *newtuple = NULL, *next;
02009 dns_rdata_t rdata = DNS_RDATA_INIT;
02010 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE + 1];
02011 dns_diff_t temp_diff;
02012 dns_diffop_t op;
02013 isc_boolean_t flag;
02014 dns_name_t *name = dns_zone_getorigin(zone);
02015 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
02016 isc_uint32_t ttl = 0;
02017 isc_boolean_t ttl_good = ISC_FALSE;
02018
02019 update_log(client, zone, ISC_LOG_DEBUG(3),
02020 "checking for NSEC3PARAM changes");
02021
02022 dns_diff_init(diff->mctx, &temp_diff);
02023
02024
02025
02026
02027 for (tuple = ISC_LIST_HEAD(diff->tuples);
02028 tuple != NULL;
02029 tuple = next) {
02030
02031 next = ISC_LIST_NEXT(tuple, link);
02032
02033 if (tuple->rdata.type != dns_rdatatype_nsec3param ||
02034 !dns_name_equal(name, &tuple->name))
02035 continue;
02036 ISC_LIST_UNLINK(diff->tuples, tuple, link);
02037 ISC_LIST_APPEND(temp_diff.tuples, tuple, link);
02038 }
02039
02040
02041
02042
02043
02044 for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
02045 tuple != NULL; tuple = next) {
02046 if (tuple->op == DNS_DIFFOP_ADD) {
02047 if (!ttl_good) {
02048
02049
02050
02051
02052 ttl = tuple->ttl;
02053 ttl_good = ISC_TRUE;
02054 }
02055
02056
02057
02058
02059 next = ISC_LIST_HEAD(temp_diff.tuples);
02060 while (next != NULL) {
02061 unsigned char *next_data = next->rdata.data;
02062 unsigned char *tuple_data = tuple->rdata.data;
02063 if (next->op == DNS_DIFFOP_DEL &&
02064 next->rdata.length == tuple->rdata.length &&
02065 !memcmp(next_data, tuple_data,
02066 next->rdata.length)) {
02067 ISC_LIST_UNLINK(temp_diff.tuples, next,
02068 link);
02069 ISC_LIST_APPEND(diff->tuples, next,
02070 link);
02071 break;
02072 }
02073 next = ISC_LIST_NEXT(next, link);
02074 }
02075
02076
02077
02078
02079 if (next == NULL) {
02080 next = ISC_LIST_NEXT(tuple, link);
02081 continue;
02082 }
02083
02084
02085
02086
02087 next = ISC_LIST_NEXT(tuple, link);
02088 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
02089 ISC_LIST_APPEND(diff->tuples, tuple, link);
02090 } else
02091 next = ISC_LIST_NEXT(tuple, link);
02092 }
02093
02094
02095
02096
02097
02098
02099
02100
02101 for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
02102 tuple != NULL; tuple = next) {
02103 next = ISC_LIST_NEXT(tuple, link);
02104 if ((tuple->rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) {
02105
02106
02107
02108
02109
02110 if (!ttl_good) {
02111 ttl = tuple->ttl;
02112 ttl_good = ISC_TRUE;
02113 }
02114 op = (tuple->op == DNS_DIFFOP_DEL) ?
02115 DNS_DIFFOP_ADD : DNS_DIFFOP_DEL;
02116 CHECK(dns_difftuple_create(diff->mctx, op, name,
02117 ttl, &tuple->rdata,
02118 &newtuple));
02119 CHECK(do_one_tuple(&newtuple, db, ver, diff));
02120 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
02121 dns_diff_appendminimal(diff, &tuple);
02122 }
02123 }
02124
02125
02126
02127
02128
02129
02130 for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
02131 tuple != NULL; tuple = next) {
02132
02133
02134
02135
02136 if (!ttl_good) {
02137 ttl = tuple->ttl;
02138 ttl_good = ISC_TRUE;
02139 }
02140 if (tuple->op == DNS_DIFFOP_ADD) {
02141 isc_boolean_t nseconly = ISC_FALSE;
02142
02143
02144
02145
02146
02147
02148
02149 next = ISC_LIST_HEAD(temp_diff.tuples);
02150 while (next != NULL) {
02151 unsigned char *next_data = next->rdata.data;
02152 unsigned char *tuple_data = tuple->rdata.data;
02153 if (next->op != DNS_DIFFOP_DEL ||
02154 next->rdata.length != tuple->rdata.length ||
02155 next_data[0] != tuple_data[0] ||
02156 next_data[2] != tuple_data[2] ||
02157 next_data[3] != tuple_data[3] ||
02158 memcmp(next_data + 4, tuple_data + 4,
02159 tuple->rdata.length - 4)) {
02160 next = ISC_LIST_NEXT(next, link);
02161 continue;
02162 }
02163 ISC_LIST_UNLINK(temp_diff.tuples, next, link);
02164 ISC_LIST_APPEND(diff->tuples, next, link);
02165 next = ISC_LIST_HEAD(temp_diff.tuples);
02166 }
02167
02168
02169
02170
02171
02172 dns_nsec3param_toprivate(&tuple->rdata, &rdata,
02173 privatetype, buf, sizeof(buf));
02174 buf[2] |= DNS_NSEC3FLAG_CREATE;
02175
02176
02177
02178
02179
02180
02181
02182 result = dns_nsec_nseconly(db, ver, &nseconly);
02183 if (result == ISC_R_NOTFOUND || nseconly)
02184 buf[2] |= DNS_NSEC3FLAG_INITIAL;
02185
02186
02187
02188
02189 CHECK(rr_exists(db, ver, name, &rdata, &flag));
02190
02191 if (!flag) {
02192 CHECK(dns_difftuple_create(diff->mctx,
02193 DNS_DIFFOP_ADD,
02194 name, 0, &rdata,
02195 &newtuple));
02196 CHECK(do_one_tuple(&newtuple, db, ver, diff));
02197 }
02198
02199
02200
02201
02202
02203
02204 buf[2] ^= DNS_NSEC3FLAG_OPTOUT;
02205 CHECK(rr_exists(db, ver, name, &rdata, &flag));
02206
02207 if (flag) {
02208 CHECK(dns_difftuple_create(diff->mctx,
02209 DNS_DIFFOP_DEL,
02210 name, 0, &rdata,
02211 &newtuple));
02212 CHECK(do_one_tuple(&newtuple, db, ver, diff));
02213 }
02214
02215
02216
02217
02218
02219 next = ISC_LIST_NEXT(tuple, link);
02220 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
02221 name, ttl, &tuple->rdata,
02222 &newtuple));
02223 CHECK(do_one_tuple(&newtuple, db, ver, diff));
02224 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
02225 dns_diff_appendminimal(diff, &tuple);
02226 dns_rdata_reset(&rdata);
02227 } else
02228 next = ISC_LIST_NEXT(tuple, link);
02229 }
02230
02231 for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
02232 tuple != NULL; tuple = next) {
02233
02234 INSIST(ttl_good);
02235
02236 next = ISC_LIST_NEXT(tuple, link);
02237
02238
02239
02240 dns_nsec3param_toprivate(&tuple->rdata, &rdata, privatetype,
02241 buf, sizeof(buf));
02242
02243 buf[2] |= DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC;
02244
02245 CHECK(rr_exists(db, ver, name, &rdata, &flag));
02246 if (!flag) {
02247 buf[2] &= ~DNS_NSEC3FLAG_NONSEC;
02248 CHECK(rr_exists(db, ver, name, &rdata, &flag));
02249 }
02250
02251 if (!flag) {
02252 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
02253 name, 0, &rdata, &newtuple));
02254 CHECK(do_one_tuple(&newtuple, db, ver, diff));
02255 }
02256 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
02257 ttl, &tuple->rdata, &newtuple));
02258 CHECK(do_one_tuple(&newtuple, db, ver, diff));
02259 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
02260 dns_diff_appendminimal(diff, &tuple);
02261 dns_rdata_reset(&rdata);
02262 }
02263
02264 result = ISC_R_SUCCESS;
02265 failure:
02266 dns_diff_clear(&temp_diff);
02267 return (result);
02268 }
02269
02270 static isc_result_t
02271 rollback_private(dns_db_t *db, dns_rdatatype_t privatetype,
02272 dns_dbversion_t *ver, dns_diff_t *diff)
02273 {
02274 dns_diff_t temp_diff;
02275 dns_diffop_t op;
02276 dns_difftuple_t *tuple, *newtuple = NULL, *next;
02277 dns_name_t *name = dns_db_origin(db);
02278 isc_mem_t *mctx = diff->mctx;
02279 isc_result_t result;
02280
02281 if (privatetype == 0)
02282 return (ISC_R_SUCCESS);
02283
02284 dns_diff_init(mctx, &temp_diff);
02285
02286
02287
02288
02289 for (tuple = ISC_LIST_HEAD(diff->tuples);
02290 tuple != NULL; tuple = next) {
02291
02292 next = ISC_LIST_NEXT(tuple, link);
02293
02294 if (tuple->rdata.type != privatetype ||
02295 !dns_name_equal(name, &tuple->name))
02296 continue;
02297
02298
02299
02300
02301
02302 if (tuple->op == DNS_DIFFOP_DEL &&
02303 tuple->rdata.length == 5 &&
02304 tuple->rdata.data[0] != 0 &&
02305 tuple->rdata.data[4] != 0)
02306 continue;
02307
02308 ISC_LIST_UNLINK(diff->tuples, tuple, link);
02309 ISC_LIST_PREPEND(temp_diff.tuples, tuple, link);
02310 }
02311
02312
02313
02314
02315 while ((tuple = ISC_LIST_HEAD(temp_diff.tuples)) != NULL) {
02316 op = (tuple->op == DNS_DIFFOP_DEL) ?
02317 DNS_DIFFOP_ADD : DNS_DIFFOP_DEL;
02318 CHECK(dns_difftuple_create(mctx, op, name, tuple->ttl,
02319 &tuple->rdata, &newtuple));
02320 CHECK(do_one_tuple(&newtuple, db, ver, &temp_diff));
02321 }
02322 result = ISC_R_SUCCESS;
02323
02324 failure:
02325 dns_diff_clear(&temp_diff);
02326 return (result);
02327 }
02328
02329
02330
02331
02332
02333 static isc_result_t
02334 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
02335 dns_dbversion_t *ver, dns_diff_t *diff)
02336 {
02337 dns_difftuple_t *tuple, *newtuple = NULL, *next;
02338 dns_rdata_dnskey_t dnskey;
02339 dns_rdata_t rdata = DNS_RDATA_INIT;
02340 isc_boolean_t flag;
02341 isc_region_t r;
02342 isc_result_t result = ISC_R_SUCCESS;
02343 isc_uint16_t keyid;
02344 unsigned char buf[5];
02345 dns_name_t *name = dns_db_origin(db);
02346 dns_diff_t temp_diff;
02347
02348 dns_diff_init(diff->mctx, &temp_diff);
02349
02350
02351
02352
02353 for (tuple = ISC_LIST_HEAD(diff->tuples);
02354 tuple != NULL; tuple = next) {
02355
02356 next = ISC_LIST_NEXT(tuple, link);
02357
02358 if (tuple->rdata.type != dns_rdatatype_dnskey)
02359 continue;
02360
02361 ISC_LIST_UNLINK(diff->tuples, tuple, link);
02362 ISC_LIST_APPEND(temp_diff.tuples, tuple, link);
02363 }
02364
02365
02366
02367
02368 for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
02369 tuple != NULL; tuple = next) {
02370 if (tuple->op == DNS_DIFFOP_ADD) {
02371
02372
02373
02374
02375 next = ISC_LIST_HEAD(temp_diff.tuples);
02376 while (next != NULL) {
02377 unsigned char *next_data = next->rdata.data;
02378 unsigned char *tuple_data = tuple->rdata.data;
02379 if (next->op == DNS_DIFFOP_DEL &&
02380 dns_name_equal(&tuple->name, &next->name) &&
02381 next->rdata.length == tuple->rdata.length &&
02382 !memcmp(next_data, tuple_data,
02383 next->rdata.length)) {
02384 ISC_LIST_UNLINK(temp_diff.tuples, next,
02385 link);
02386 ISC_LIST_APPEND(diff->tuples, next,
02387 link);
02388 break;
02389 }
02390 next = ISC_LIST_NEXT(next, link);
02391 }
02392
02393
02394
02395
02396 if (next == NULL) {
02397 next = ISC_LIST_NEXT(tuple, link);
02398 continue;
02399 }
02400
02401
02402
02403
02404 next = ISC_LIST_NEXT(tuple, link);
02405 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
02406 ISC_LIST_APPEND(diff->tuples, tuple, link);
02407 } else
02408 next = ISC_LIST_NEXT(tuple, link);
02409 }
02410
02411
02412
02413
02414 for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
02415 tuple != NULL;
02416 tuple = ISC_LIST_HEAD(temp_diff.tuples)) {
02417
02418 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
02419 ISC_LIST_APPEND(diff->tuples, tuple, link);
02420
02421 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
02422 RUNTIME_CHECK(result == ISC_R_SUCCESS);
02423 if ((dnskey.flags &
02424 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
02425 != DNS_KEYOWNER_ZONE)
02426 continue;
02427
02428 dns_rdata_toregion(&tuple->rdata, &r);
02429
02430 keyid = dst_region_computeid(&r, dnskey.algorithm);
02431
02432 buf[0] = dnskey.algorithm;
02433 buf[1] = (keyid & 0xff00) >> 8;
02434 buf[2] = (keyid & 0xff);
02435 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
02436 buf[4] = 0;
02437 rdata.data = buf;
02438 rdata.length = sizeof(buf);
02439 rdata.type = privatetype;
02440 rdata.rdclass = tuple->rdata.rdclass;
02441
02442 CHECK(rr_exists(db, ver, name, &rdata, &flag));
02443 if (flag)
02444 continue;
02445 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
02446 name, 0, &rdata, &newtuple));
02447 CHECK(do_one_tuple(&newtuple, db, ver, diff));
02448 INSIST(newtuple == NULL);
02449
02450
02451
02452
02453 buf[4] = 1;
02454 CHECK(rr_exists(db, ver, name, &rdata, &flag));
02455 if (flag) {
02456 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
02457 name, 0, &rdata, &newtuple));
02458 CHECK(do_one_tuple(&newtuple, db, ver, diff));
02459 INSIST(newtuple == NULL);
02460 }
02461 }
02462
02463 failure:
02464 dns_diff_clear(&temp_diff);
02465 return (result);
02466 }
02467
02468 static isc_boolean_t
02469 isdnssec(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype) {
02470 isc_result_t result;
02471 isc_boolean_t build_nsec, build_nsec3;
02472
02473 if (dns_db_issecure(db))
02474 return (ISC_TRUE);
02475
02476 result = dns_private_chains(db, ver, privatetype,
02477 &build_nsec, &build_nsec3);
02478 RUNTIME_CHECK(result == ISC_R_SUCCESS);
02479 return (build_nsec || build_nsec3);
02480 }
02481
02482 static void
02483 update_action(isc_task_t *task, isc_event_t *event) {
02484 update_event_t *uev = (update_event_t *) event;
02485 dns_zone_t *zone = uev->zone;
02486 ns_client_t *client = (ns_client_t *)event->ev_arg;
02487 isc_result_t result;
02488 dns_db_t *db = NULL;
02489 dns_dbversion_t *oldver = NULL;
02490 dns_dbversion_t *ver = NULL;
02491 dns_diff_t diff;
02492 dns_diff_t temp;
02493 isc_boolean_t soa_serial_changed = ISC_FALSE;
02494 isc_mem_t *mctx = client->mctx;
02495 dns_rdatatype_t covers;
02496 dns_message_t *request = client->message;
02497 dns_rdataclass_t zoneclass;
02498 dns_name_t *zonename;
02499 dns_ssutable_t *ssutable = NULL;
02500 dns_fixedname_t tmpnamefixed;
02501 dns_name_t *tmpname = NULL;
02502 unsigned int options, options2;
02503 dns_difftuple_t *tuple;
02504 dns_rdata_dnskey_t dnskey;
02505 isc_boolean_t had_dnskey;
02506 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
02507 dns_ttl_t maxttl = 0;
02508
02509 INSIST(event->ev_type == DNS_EVENT_UPDATE);
02510
02511 dns_diff_init(mctx, &diff);
02512 dns_diff_init(mctx, &temp);
02513
02514 CHECK(dns_zone_getdb(zone, &db));
02515 zonename = dns_db_origin(db);
02516 zoneclass = dns_db_class(db);
02517 dns_zone_getssutable(zone, &ssutable);
02518
02519
02520
02521
02522
02523
02524 CHECK(checkqueryacl(client, dns_zone_getqueryacl(zone), zonename,
02525 dns_zone_getupdateacl(zone), ssutable));
02526
02527
02528
02529
02530 dns_db_currentversion(db, &oldver);
02531 CHECK(dns_db_newversion(db, &ver));
02532
02533
02534
02535
02536
02537 for (result = dns_message_firstname(request, DNS_SECTION_PREREQUISITE);
02538 result == ISC_R_SUCCESS;
02539 result = dns_message_nextname(request, DNS_SECTION_PREREQUISITE))
02540 {
02541 dns_name_t *name = NULL;
02542 dns_rdata_t rdata = DNS_RDATA_INIT;
02543 dns_ttl_t ttl;
02544 dns_rdataclass_t update_class;
02545 isc_boolean_t flag;
02546
02547 get_current_rr(request, DNS_SECTION_PREREQUISITE, zoneclass,
02548 &name, &rdata, &covers, &ttl, &update_class);
02549
02550 if (ttl != 0)
02551 PREREQFAILC(DNS_R_FORMERR,
02552 "prerequisite TTL is not zero");
02553
02554 if (! dns_name_issubdomain(name, zonename))
02555 PREREQFAILN(DNS_R_NOTZONE, name,
02556 "prerequisite name is out of zone");
02557
02558 if (update_class == dns_rdataclass_any) {
02559 if (rdata.length != 0)
02560 PREREQFAILC(DNS_R_FORMERR,
02561 "class ANY prerequisite "
02562 "RDATA is not empty");
02563 if (rdata.type == dns_rdatatype_any) {
02564 CHECK(name_exists(db, ver, name, &flag));
02565 if (! flag) {
02566 PREREQFAILN(DNS_R_NXDOMAIN, name,
02567 "'name in use' "
02568 "prerequisite not "
02569 "satisfied");
02570 }
02571 } else {
02572 CHECK(rrset_exists(db, ver, name,
02573 rdata.type, covers, &flag));
02574 if (! flag) {
02575
02576 PREREQFAILNT(DNS_R_NXRRSET, name, rdata.type,
02577 "'rrset exists (value independent)' "
02578 "prerequisite not satisfied");
02579 }
02580 }
02581 } else if (update_class == dns_rdataclass_none) {
02582 if (rdata.length != 0)
02583 PREREQFAILC(DNS_R_FORMERR,
02584 "class NONE prerequisite "
02585 "RDATA is not empty");
02586 if (rdata.type == dns_rdatatype_any) {
02587 CHECK(name_exists(db, ver, name, &flag));
02588 if (flag) {
02589 PREREQFAILN(DNS_R_YXDOMAIN, name,
02590 "'name not in use' "
02591 "prerequisite not "
02592 "satisfied");
02593 }
02594 } else {
02595 CHECK(rrset_exists(db, ver, name,
02596 rdata.type, covers, &flag));
02597 if (flag) {
02598
02599 PREREQFAILNT(DNS_R_YXRRSET, name,
02600 rdata.type,
02601 "'rrset does not exist' "
02602 "prerequisite not "
02603 "satisfied");
02604 }
02605 }
02606 } else if (update_class == zoneclass) {
02607
02608 result = temp_append(&temp, name, &rdata);
02609 if (result != ISC_R_SUCCESS) {
02610 UNEXPECTED_ERROR(__FILE__, __LINE__,
02611 "temp entry creation failed: %s",
02612 dns_result_totext(result));
02613 FAIL(ISC_R_UNEXPECTED);
02614 }
02615 } else {
02616 PREREQFAILC(DNS_R_FORMERR, "malformed prerequisite");
02617 }
02618 }
02619 if (result != ISC_R_NOMORE)
02620 FAIL(result);
02621
02622
02623
02624
02625
02626 if (ISC_LIST_HEAD(temp.tuples) != NULL) {
02627 dns_rdatatype_t type;
02628
02629
02630
02631
02632
02633 result = dns_diff_sort(&temp, temp_order);
02634 if (result != ISC_R_SUCCESS)
02635 FAILC(result, "'RRset exists (value dependent)' "
02636 "prerequisite not satisfied");
02637
02638 dns_fixedname_init(&tmpnamefixed);
02639 tmpname = dns_fixedname_name(&tmpnamefixed);
02640 result = temp_check(mctx, &temp, db, ver, tmpname, &type);
02641 if (result != ISC_R_SUCCESS)
02642 FAILNT(result, tmpname, type,
02643 "'RRset exists (value dependent)' "
02644 "prerequisite not satisfied");
02645 }
02646
02647 update_log(client, zone, LOGLEVEL_DEBUG,
02648 "prerequisites are OK");
02649
02650
02651
02652
02653
02654 if (ssutable == NULL)
02655 CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone),
02656 "update", zonename, ISC_FALSE, ISC_FALSE));
02657 else if (client->signer == NULL && !TCPCLIENT(client))
02658 CHECK(checkupdateacl(client, NULL, "update", zonename,
02659 ISC_FALSE, ISC_TRUE));
02660
02661 if (dns_zone_getupdatedisabled(zone))
02662 FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled "
02663 "because the zone is frozen. Use "
02664 "'rndc thaw' to re-enable updates.");
02665
02666
02667
02668
02669
02670 for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
02671 result == ISC_R_SUCCESS;
02672 result = dns_message_nextname(request, DNS_SECTION_UPDATE))
02673 {
02674 dns_name_t *name = NULL;
02675 dns_rdata_t rdata = DNS_RDATA_INIT;
02676 dns_ttl_t ttl;
02677 dns_rdataclass_t update_class;
02678 get_current_rr(request, DNS_SECTION_UPDATE, zoneclass,
02679 &name, &rdata, &covers, &ttl, &update_class);
02680
02681 if (! dns_name_issubdomain(name, zonename))
02682 FAILC(DNS_R_NOTZONE,
02683 "update RR is outside zone");
02684 if (update_class == zoneclass) {
02685
02686
02687
02688
02689
02690 if (dns_rdatatype_ismeta(rdata.type)) {
02691 FAILC(DNS_R_FORMERR,
02692 "meta-RR in update");
02693 }
02694 result = dns_zone_checknames(zone, name, &rdata);
02695 if (result != ISC_R_SUCCESS)
02696 FAIL(DNS_R_REFUSED);
02697 } else if (update_class == dns_rdataclass_any) {
02698 if (ttl != 0 || rdata.length != 0 ||
02699 (dns_rdatatype_ismeta(rdata.type) &&
02700 rdata.type != dns_rdatatype_any))
02701 FAILC(DNS_R_FORMERR,
02702 "meta-RR in update");
02703 } else if (update_class == dns_rdataclass_none) {
02704 if (ttl != 0 ||
02705 dns_rdatatype_ismeta(rdata.type))
02706 FAILC(DNS_R_FORMERR,
02707 "meta-RR in update");
02708 } else {
02709 update_log(client, zone, ISC_LOG_WARNING,
02710 "update RR has incorrect class %d",
02711 update_class);
02712 FAIL(DNS_R_FORMERR);
02713 }
02714
02715
02716
02717
02718
02719
02720 if (rdata.type == dns_rdatatype_nsec3) {
02721 FAILC(DNS_R_REFUSED,
02722 "explicit NSEC3 updates are not allowed "
02723 "in secure zones");
02724 } else if (rdata.type == dns_rdatatype_nsec) {
02725 FAILC(DNS_R_REFUSED,
02726 "explicit NSEC updates are not allowed "
02727 "in secure zones");
02728 } else if (rdata.type == dns_rdatatype_rrsig &&
02729 !dns_name_equal(name, zonename)) {
02730 FAILC(DNS_R_REFUSED,
02731 "explicit RRSIG updates are currently "
02732 "not supported in secure zones except "
02733 "at the apex");
02734 }
02735
02736 if (ssutable != NULL) {
02737 isc_netaddr_t *tcpaddr, netaddr;
02738 dst_key_t *tsigkey = NULL;
02739
02740
02741
02742
02743
02744
02745 if (TCPCLIENT(client)) {
02746 isc_netaddr_fromsockaddr(&netaddr,
02747 &client->peeraddr);
02748 tcpaddr = &netaddr;
02749 } else
02750 tcpaddr = NULL;
02751
02752 if (client->message->tsigkey != NULL)
02753 tsigkey = client->message->tsigkey->key;
02754
02755 if (rdata.type != dns_rdatatype_any) {
02756 if (!dns_ssutable_checkrules(ssutable,
02757 client->signer,
02758 name, tcpaddr,
02759 rdata.type,
02760 tsigkey))
02761 FAILC(DNS_R_REFUSED,
02762 "rejected by secure update");
02763 } else {
02764 if (!ssu_checkall(db, ver, name, ssutable,
02765 client->signer, tcpaddr,
02766 tsigkey))
02767 FAILC(DNS_R_REFUSED,
02768 "rejected by secure update");
02769 }
02770 }
02771 }
02772 if (result != ISC_R_NOMORE)
02773 FAIL(result);
02774
02775 update_log(client, zone, LOGLEVEL_DEBUG,
02776 "update section prescan OK");
02777
02778
02779
02780
02781
02782 options = dns_zone_getoptions(zone);
02783 options2 = dns_zone_getoptions2(zone);
02784 for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
02785 result == ISC_R_SUCCESS;
02786 result = dns_message_nextname(request, DNS_SECTION_UPDATE))
02787 {
02788 dns_name_t *name = NULL;
02789 dns_rdata_t rdata = DNS_RDATA_INIT;
02790 dns_ttl_t ttl;
02791 dns_rdataclass_t update_class;
02792 isc_boolean_t flag;
02793
02794 get_current_rr(request, DNS_SECTION_UPDATE, zoneclass,
02795 &name, &rdata, &covers, &ttl, &update_class);
02796
02797 if (update_class == zoneclass) {
02798
02799
02800
02801 if (rdata.type == dns_rdatatype_md ||
02802 rdata.type == dns_rdatatype_mf) {
02803 char typebuf[DNS_RDATATYPE_FORMATSIZE];
02804
02805 dns_rdatatype_format(rdata.type, typebuf,
02806 sizeof(typebuf));
02807 update_log(client, zone, LOGLEVEL_PROTOCOL,
02808 "attempt to add %s ignored",
02809 typebuf);
02810 continue;
02811 }
02812 if ((rdata.type == dns_rdatatype_ns ||
02813 rdata.type == dns_rdatatype_dname) &&
02814 dns_name_iswildcard(name)) {
02815 char typebuf[DNS_RDATATYPE_FORMATSIZE];
02816
02817 dns_rdatatype_format(rdata.type, typebuf,
02818 sizeof(typebuf));
02819 update_log(client, zone,
02820 LOGLEVEL_PROTOCOL,
02821 "attempt to add wildcard %s record "
02822 "ignored", typebuf);
02823 continue;
02824 }
02825 if (rdata.type == dns_rdatatype_cname) {
02826 CHECK(cname_incompatible_rrset_exists(db, ver,
02827 name,
02828 &flag));
02829 if (flag) {
02830 update_log(client, zone,
02831 LOGLEVEL_PROTOCOL,
02832 "attempt to add CNAME "
02833 "alongside non-CNAME "
02834 "ignored");
02835 continue;
02836 }
02837 } else {
02838 CHECK(rrset_exists(db, ver, name,
02839 dns_rdatatype_cname, 0,
02840 &flag));
02841 if (flag &&
02842 ! dns_rdatatype_isdnssec(rdata.type))
02843 {
02844 update_log(client, zone,
02845 LOGLEVEL_PROTOCOL,
02846 "attempt to add non-CNAME "
02847 "alongside CNAME ignored");
02848 continue;
02849 }
02850 }
02851 if (rdata.type == dns_rdatatype_soa) {
02852 isc_boolean_t ok;
02853 CHECK(rrset_exists(db, ver, name,
02854 dns_rdatatype_soa, 0,
02855 &flag));
02856 if (! flag) {
02857 update_log(client, zone,
02858 LOGLEVEL_PROTOCOL,
02859 "attempt to create 2nd "
02860 "SOA ignored");
02861 continue;
02862 }
02863 CHECK(check_soa_increment(db, ver, &rdata,
02864 &ok));
02865 if (! ok) {
02866 update_log(client, zone,
02867 LOGLEVEL_PROTOCOL,
02868 "SOA update failed to "
02869 "increment serial, "
02870 "ignoring it");
02871 continue;
02872 }
02873 soa_serial_changed = ISC_TRUE;
02874 }
02875
02876 if (rdata.type == privatetype) {
02877 update_log(client, zone, LOGLEVEL_PROTOCOL,
02878 "attempt to add a private type "
02879 "(%u) record rejected internal "
02880 "use only", privatetype);
02881 continue;
02882 }
02883
02884 if (rdata.type == dns_rdatatype_nsec3param) {
02885
02886
02887
02888
02889 if ((rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) {
02890 update_log(client, zone,
02891 LOGLEVEL_PROTOCOL,
02892 "attempt to add NSEC3PARAM "
02893 "record with non OPTOUT "
02894 "flag");
02895 continue;
02896 }
02897 }
02898
02899 if ((options & DNS_ZONEOPT_CHECKWILDCARD) != 0 &&
02900 dns_name_internalwildcard(name)) {
02901 char namestr[DNS_NAME_FORMATSIZE];
02902 dns_name_format(name, namestr,
02903 sizeof(namestr));
02904 update_log(client, zone, LOGLEVEL_PROTOCOL,
02905 "warning: ownername '%s' contains "
02906 "a non-terminal wildcard", namestr);
02907 }
02908
02909 if ((options2 & DNS_ZONEOPT2_CHECKTTL) != 0) {
02910 maxttl = dns_zone_getmaxttl(zone);
02911 if (ttl > maxttl) {
02912 ttl = maxttl;
02913 update_log(client, zone,
02914 LOGLEVEL_PROTOCOL,
02915 "reducing TTL to the "
02916 "configured max-zone-ttl %d",
02917 maxttl);
02918 }
02919 }
02920
02921 if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) {
02922 char namestr[DNS_NAME_FORMATSIZE];
02923 char typestr[DNS_RDATATYPE_FORMATSIZE];
02924 char rdstr[2048];
02925 isc_buffer_t buf;
02926 int len = 0;
02927 const char *truncated = "";
02928
02929 dns_name_format(name, namestr, sizeof(namestr));
02930 dns_rdatatype_format(rdata.type, typestr,
02931 sizeof(typestr));
02932 isc_buffer_init(&buf, rdstr, sizeof(rdstr));
02933 result = dns_rdata_totext(&rdata, NULL, &buf);
02934 if (result == ISC_R_NOSPACE) {
02935 len = (int)isc_buffer_usedlength(&buf);
02936 truncated = " [TRUNCATED]";
02937 } else if (result != ISC_R_SUCCESS) {
02938 snprintf(rdstr, sizeof(rdstr), "[dns_"
02939 "rdata_totext failed: %s]",
02940 dns_result_totext(result));
02941 len = strlen(rdstr);
02942 } else
02943 len = (int)isc_buffer_usedlength(&buf);
02944 update_log(client, zone, LOGLEVEL_PROTOCOL,
02945 "adding an RR at '%s' %s %.*s%s",
02946 namestr, typestr, len, rdstr,
02947 truncated);
02948 }
02949
02950
02951 {
02952 add_rr_prepare_ctx_t ctx;
02953 ctx.db = db;
02954 ctx.ver = ver;
02955 ctx.diff = &diff;
02956 ctx.name = name;
02957 ctx.oldname = name;
02958 ctx.update_rr = &rdata;
02959 ctx.update_rr_ttl = ttl;
02960 ctx.ignore_add = ISC_FALSE;
02961 dns_diff_init(mctx, &ctx.del_diff);
02962 dns_diff_init(mctx, &ctx.add_diff);
02963 CHECK(foreach_rr(db, ver, name, rdata.type,
02964 covers, add_rr_prepare_action,
02965 &ctx));
02966
02967 if (ctx.ignore_add) {
02968 dns_diff_clear(&ctx.del_diff);
02969 dns_diff_clear(&ctx.add_diff);
02970 } else {
02971 result = do_diff(&ctx.del_diff, db, ver,
02972 &diff);
02973 if (result == ISC_R_SUCCESS) {
02974 result = do_diff(&ctx.add_diff,
02975 db, ver,
02976 &diff);
02977 }
02978 if (result != ISC_R_SUCCESS) {
02979 dns_diff_clear(&ctx.del_diff);
02980 dns_diff_clear(&ctx.add_diff);
02981 goto failure;
02982 }
02983 CHECK(update_one_rr(db, ver, &diff,
02984 DNS_DIFFOP_ADD,
02985 name, ttl, &rdata));
02986 }
02987 }
02988 } else if (update_class == dns_rdataclass_any) {
02989 if (rdata.type == dns_rdatatype_any) {
02990 if (isc_log_wouldlog(ns_g_lctx,
02991 LOGLEVEL_PROTOCOL))
02992 {
02993 char namestr[DNS_NAME_FORMATSIZE];
02994 dns_name_format(name, namestr,
02995 sizeof(namestr));
02996 update_log(client, zone,
02997 LOGLEVEL_PROTOCOL,
02998 "delete all rrsets from "
02999 "name '%s'", namestr);
03000 }
03001 if (dns_name_equal(name, zonename)) {
03002 CHECK(delete_if(type_not_soa_nor_ns_p,
03003 db, ver, name,
03004 dns_rdatatype_any, 0,
03005 &rdata, &diff));
03006 } else {
03007 CHECK(delete_if(type_not_dnssec,
03008 db, ver, name,
03009 dns_rdatatype_any, 0,
03010 &rdata, &diff));
03011 }
03012 } else if (dns_name_equal(name, zonename) &&
03013 (rdata.type == dns_rdatatype_soa ||
03014 rdata.type == dns_rdatatype_ns)) {
03015 update_log(client, zone, LOGLEVEL_PROTOCOL,
03016 "attempt to delete all SOA "
03017 "or NS records ignored");
03018 continue;
03019 } else {
03020 if (isc_log_wouldlog(ns_g_lctx,
03021 LOGLEVEL_PROTOCOL))
03022 {
03023 char namestr[DNS_NAME_FORMATSIZE];
03024 char typestr[DNS_RDATATYPE_FORMATSIZE];
03025 dns_name_format(name, namestr,
03026 sizeof(namestr));
03027 dns_rdatatype_format(rdata.type,
03028 typestr,
03029 sizeof(typestr));
03030 update_log(client, zone,
03031 LOGLEVEL_PROTOCOL,
03032 "deleting rrset at '%s' %s",
03033 namestr, typestr);
03034 }
03035 CHECK(delete_if(true_p, db, ver, name,
03036 rdata.type, covers, &rdata,
03037 &diff));
03038 }
03039 } else if (update_class == dns_rdataclass_none) {
03040 char namestr[DNS_NAME_FORMATSIZE];
03041 char typestr[DNS_RDATATYPE_FORMATSIZE];
03042
03043
03044
03045
03046
03047 if (dns_name_equal(name, zonename)) {
03048 if (rdata.type == dns_rdatatype_soa) {
03049 update_log(client, zone,
03050 LOGLEVEL_PROTOCOL,
03051 "attempt to delete SOA "
03052 "ignored");
03053 continue;
03054 }
03055 if (rdata.type == dns_rdatatype_ns) {
03056 int count;
03057 CHECK(rr_count(db, ver, name,
03058 dns_rdatatype_ns,
03059 0, &count));
03060 if (count == 1) {
03061 update_log(client, zone,
03062 LOGLEVEL_PROTOCOL,
03063 "attempt to "
03064 "delete last "
03065 "NS ignored");
03066 continue;
03067 }
03068 }
03069 }
03070 dns_name_format(name, namestr, sizeof(namestr));
03071 dns_rdatatype_format(rdata.type, typestr,
03072 sizeof(typestr));
03073 update_log(client, zone, LOGLEVEL_PROTOCOL,
03074 "deleting an RR at %s %s", namestr, typestr);
03075 CHECK(delete_if(rr_equal_p, db, ver, name, rdata.type,
03076 covers, &rdata, &diff));
03077 }
03078 }
03079 if (result != ISC_R_NOMORE)
03080 FAIL(result);
03081
03082
03083
03084
03085
03086
03087 if (! ISC_LIST_EMPTY(diff.tuples))
03088 CHECK(check_dnssec(client, zone, db, ver, &diff));
03089
03090 if (! ISC_LIST_EMPTY(diff.tuples)) {
03091 unsigned int errors = 0;
03092 CHECK(dns_zone_nscheck(zone, db, ver, &errors));
03093 if (errors != 0) {
03094 update_log(client, zone, LOGLEVEL_PROTOCOL,
03095 "update rejected: post update name server "
03096 "sanity check failed");
03097 result = DNS_R_REFUSED;
03098 goto failure;
03099 }
03100 }
03101
03102
03103
03104
03105
03106
03107 if (! ISC_LIST_EMPTY(diff.tuples)) {
03108 char *journalfile;
03109 dns_journal_t *journal;
03110 isc_boolean_t has_dnskey;
03111
03112
03113
03114
03115
03116 if (! soa_serial_changed) {
03117 CHECK(update_soa_serial(db, ver, &diff, mctx,
03118 dns_zone_getserialupdatemethod(zone)));
03119 }
03120
03121 CHECK(check_mx(client, zone, db, ver, &diff));
03122
03123 CHECK(remove_orphaned_ds(db, ver, &diff));
03124
03125 CHECK(rrset_exists(db, ver, zonename, dns_rdatatype_dnskey,
03126 0, &has_dnskey));
03127
03128 #define ALLOW_SECURE_TO_INSECURE(zone) \
03129 ((dns_zone_getoptions(zone) & DNS_ZONEOPT_SECURETOINSECURE) != 0)
03130
03131 CHECK(rrset_exists(db, oldver, zonename, dns_rdatatype_dnskey,
03132 0, &had_dnskey));
03133 if (!ALLOW_SECURE_TO_INSECURE(zone)) {
03134 if (had_dnskey && !has_dnskey) {
03135 update_log(client, zone, LOGLEVEL_PROTOCOL,
03136 "update rejected: all DNSKEY "
03137 "records removed and "
03138 "'dnssec-secure-to-insecure' "
03139 "not set");
03140 result = DNS_R_REFUSED;
03141 goto failure;
03142 }
03143 }
03144
03145 CHECK(rollback_private(db, privatetype, ver, &diff));
03146
03147 CHECK(add_signing_records(db, privatetype, ver, &diff));
03148
03149 CHECK(add_nsec3param_records(client, zone, db, ver, &diff));
03150
03151 if (had_dnskey && !has_dnskey) {
03152
03153
03154
03155
03156
03157
03158 CHECK(dns_nsec3param_deletechains(db, ver, zone,
03159 ISC_TRUE, &diff));
03160 } else if (has_dnskey && isdnssec(db, ver, privatetype)) {
03161 isc_uint32_t interval;
03162 dns_update_log_t log;
03163
03164 interval = dns_zone_getsigvalidityinterval(zone);
03165 log.func = update_log_cb;
03166 log.arg = client;
03167 result = dns_update_signatures(&log, zone, db, oldver,
03168 ver, &diff, interval);
03169
03170 if (result != ISC_R_SUCCESS) {
03171 update_log(client, zone,
03172 ISC_LOG_ERROR,
03173 "RRSIG/NSEC/NSEC3 update failed: %s",
03174 isc_result_totext(result));
03175 goto failure;
03176 }
03177 }
03178
03179 journalfile = dns_zone_getjournal(zone);
03180 if (journalfile != NULL) {
03181 update_log(client, zone, LOGLEVEL_DEBUG,
03182 "writing journal %s", journalfile);
03183
03184 journal = NULL;
03185 result = dns_journal_open(mctx, journalfile,
03186 DNS_JOURNAL_CREATE, &journal);
03187 if (result != ISC_R_SUCCESS)
03188 FAILS(result, "journal open failed");
03189
03190 result = dns_journal_write_transaction(journal, &diff);
03191 if (result != ISC_R_SUCCESS) {
03192 dns_journal_destroy(&journal);
03193 FAILS(result, "journal write failed");
03194 }
03195
03196 dns_journal_destroy(&journal);
03197 }
03198
03199
03200
03201
03202
03203
03204 update_log(client, zone, LOGLEVEL_DEBUG,
03205 "committing update transaction");
03206
03207 dns_db_closeversion(db, &ver, ISC_TRUE);
03208
03209
03210
03211
03212 dns_zone_markdirty(zone);
03213
03214
03215
03216
03217 dns_zone_notify(zone);
03218
03219
03220
03221
03222
03223
03224
03225
03226 for (tuple = ISC_LIST_HEAD(diff.tuples);
03227 tuple != NULL;
03228 tuple = ISC_LIST_NEXT(tuple, link)) {
03229 isc_region_t r;
03230 dns_secalg_t algorithm;
03231 isc_uint16_t keyid;
03232
03233 if (tuple->rdata.type != dns_rdatatype_dnskey)
03234 continue;
03235
03236 dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
03237 if ((dnskey.flags &
03238 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
03239 != DNS_KEYOWNER_ZONE)
03240 continue;
03241
03242 dns_rdata_toregion(&tuple->rdata, &r);
03243 algorithm = dnskey.algorithm;
03244 keyid = dst_region_computeid(&r, algorithm);
03245
03246 result = dns_zone_signwithkey(zone, algorithm, keyid,
03247 ISC_TF(tuple->op == DNS_DIFFOP_DEL));
03248 if (result != ISC_R_SUCCESS) {
03249 update_log(client, zone, ISC_LOG_ERROR,
03250 "dns_zone_signwithkey failed: %s",
03251 dns_result_totext(result));
03252 }
03253 }
03254
03255
03256
03257
03258
03259
03260
03261 for (tuple = ISC_LIST_HEAD(diff.tuples);
03262 tuple != NULL;
03263 tuple = ISC_LIST_NEXT(tuple, link)) {
03264 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
03265 dns_rdata_t rdata = DNS_RDATA_INIT;
03266 dns_rdata_nsec3param_t nsec3param;
03267
03268 if (tuple->rdata.type != privatetype ||
03269 tuple->op != DNS_DIFFOP_ADD)
03270 continue;
03271
03272 if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
03273 buf, sizeof(buf)))
03274 continue;
03275 dns_rdata_tostruct(&rdata, &nsec3param, NULL);
03276 if (nsec3param.flags == 0)
03277 continue;
03278
03279 result = dns_zone_addnsec3chain(zone, &nsec3param);
03280 if (result != ISC_R_SUCCESS) {
03281 update_log(client, zone, ISC_LOG_ERROR,
03282 "dns_zone_addnsec3chain failed: %s",
03283 dns_result_totext(result));
03284 }
03285 }
03286 } else {
03287 update_log(client, zone, LOGLEVEL_DEBUG, "redundant request");
03288 dns_db_closeversion(db, &ver, ISC_TRUE);
03289 }
03290 result = ISC_R_SUCCESS;
03291 goto common;
03292
03293 failure:
03294
03295
03296
03297 if (ver != NULL) {
03298 update_log(client, zone, LOGLEVEL_DEBUG,
03299 "rolling back");
03300 dns_db_closeversion(db, &ver, ISC_FALSE);
03301 }
03302
03303 common:
03304 dns_diff_clear(&temp);
03305 dns_diff_clear(&diff);
03306
03307 if (oldver != NULL)
03308 dns_db_closeversion(db, &oldver, ISC_FALSE);
03309
03310 if (db != NULL)
03311 dns_db_detach(&db);
03312
03313 if (ssutable != NULL)
03314 dns_ssutable_detach(&ssutable);
03315
03316 isc_task_detach(&task);
03317 uev->result = result;
03318 if (zone != NULL)
03319 INSIST(uev->zone == zone);
03320 uev->ev_type = DNS_EVENT_UPDATEDONE;
03321 uev->ev_action = updatedone_action;
03322 isc_task_send(client->task, &event);
03323
03324 INSIST(ver == NULL);
03325 INSIST(event == NULL);
03326 }
03327
03328 static void
03329 updatedone_action(isc_task_t *task, isc_event_t *event) {
03330 update_event_t *uev = (update_event_t *) event;
03331 ns_client_t *client = (ns_client_t *) event->ev_arg;
03332
03333 UNUSED(task);
03334
03335 INSIST(event->ev_type == DNS_EVENT_UPDATEDONE);
03336 INSIST(task == client->task);
03337
03338 INSIST(client->nupdates > 0);
03339 switch (uev->result) {
03340 case ISC_R_SUCCESS:
03341 inc_stats(uev->zone, dns_nsstatscounter_updatedone);
03342 break;
03343 case DNS_R_REFUSED:
03344 inc_stats(uev->zone, dns_nsstatscounter_updaterej);
03345 break;
03346 default:
03347 inc_stats(uev->zone, dns_nsstatscounter_updatefail);
03348 break;
03349 }
03350 if (uev->zone != NULL)
03351 dns_zone_detach(&uev->zone);
03352 client->nupdates--;
03353 respond(client, uev->result);
03354 isc_event_free(&event);
03355 ns_client_detach(&client);
03356 }
03357
03358
03359
03360
03361
03362 static void
03363 forward_fail(isc_task_t *task, isc_event_t *event) {
03364 ns_client_t *client = (ns_client_t *)event->ev_arg;
03365
03366 UNUSED(task);
03367
03368 INSIST(client->nupdates > 0);
03369 client->nupdates--;
03370 respond(client, DNS_R_SERVFAIL);
03371 isc_event_free(&event);
03372 ns_client_detach(&client);
03373 }
03374
03375
03376 static void
03377 forward_callback(void *arg, isc_result_t result, dns_message_t *answer) {
03378 update_event_t *uev = arg;
03379 ns_client_t *client = uev->ev_arg;
03380 dns_zone_t *zone = uev->zone;
03381
03382 if (result != ISC_R_SUCCESS) {
03383 INSIST(answer == NULL);
03384 uev->ev_type = DNS_EVENT_UPDATEDONE;
03385 uev->ev_action = forward_fail;
03386 inc_stats(zone, dns_nsstatscounter_updatefwdfail);
03387 } else {
03388 uev->ev_type = DNS_EVENT_UPDATEDONE;
03389 uev->ev_action = forward_done;
03390 uev->answer = answer;
03391 inc_stats(zone, dns_nsstatscounter_updaterespfwd);
03392 }
03393 isc_task_send(client->task, ISC_EVENT_PTR(&uev));
03394 dns_zone_detach(&zone);
03395 }
03396
03397 static void
03398 forward_done(isc_task_t *task, isc_event_t *event) {
03399 update_event_t *uev = (update_event_t *) event;
03400 ns_client_t *client = (ns_client_t *)event->ev_arg;
03401
03402 UNUSED(task);
03403
03404 INSIST(client->nupdates > 0);
03405 client->nupdates--;
03406 ns_client_sendraw(client, uev->answer);
03407 dns_message_destroy(&uev->answer);
03408 isc_event_free(&event);
03409 ns_client_detach(&client);
03410 }
03411
03412 static void
03413 forward_action(isc_task_t *task, isc_event_t *event) {
03414 update_event_t *uev = (update_event_t *) event;
03415 dns_zone_t *zone = uev->zone;
03416 ns_client_t *client = (ns_client_t *)event->ev_arg;
03417 isc_result_t result;
03418
03419 result = dns_zone_forwardupdate(zone, client->message,
03420 forward_callback, event);
03421 if (result != ISC_R_SUCCESS) {
03422 uev->ev_type = DNS_EVENT_UPDATEDONE;
03423 uev->ev_action = forward_fail;
03424 isc_task_send(client->task, &event);
03425 inc_stats(zone, dns_nsstatscounter_updatefwdfail);
03426 dns_zone_detach(&zone);
03427 } else
03428 inc_stats(zone, dns_nsstatscounter_updatereqfwd);
03429 isc_task_detach(&task);
03430 }
03431
03432 static isc_result_t
03433 send_forward_event(ns_client_t *client, dns_zone_t *zone) {
03434 char namebuf[DNS_NAME_FORMATSIZE];
03435 char classbuf[DNS_RDATACLASS_FORMATSIZE];
03436 isc_result_t result = ISC_R_SUCCESS;
03437 update_event_t *event = NULL;
03438 isc_task_t *zonetask = NULL;
03439 ns_client_t *evclient;
03440
03441
03442
03443
03444 if (!client->mortal && (client->attributes & NS_CLIENTATTR_TCP) == 0)
03445 CHECK(ns_client_replace(client));
03446
03447 event = (update_event_t *)
03448 isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE,
03449 forward_action, NULL, sizeof(*event));
03450 if (event == NULL)
03451 FAIL(ISC_R_NOMEMORY);
03452 event->zone = zone;
03453 event->result = ISC_R_SUCCESS;
03454
03455 evclient = NULL;
03456 ns_client_attach(client, &evclient);
03457 INSIST(client->nupdates == 0);
03458 client->nupdates++;
03459 event->ev_arg = evclient;
03460
03461 dns_name_format(dns_zone_getorigin(zone), namebuf,
03462 sizeof(namebuf));
03463 dns_rdataclass_format(dns_zone_getclass(zone), classbuf,
03464 sizeof(classbuf));
03465
03466 ns_client_log(client, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE,
03467 LOGLEVEL_PROTOCOL, "forwarding update for zone '%s/%s'",
03468 namebuf, classbuf);
03469
03470 dns_zone_gettask(zone, &zonetask);
03471 isc_task_send(zonetask, ISC_EVENT_PTR(&event));
03472
03473 failure:
03474 if (event != NULL)
03475 isc_event_free(ISC_EVENT_PTR(&event));
03476 return (result);
03477 }