a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews/*
3c5862dfc7718dc1c7ee402138de2227105f547cTinderbox User * Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC")
122230159d02eb8d947c3bb3f279469919c164c8Automatic Updater *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews */
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <config.h>
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt#include <time.h>
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <isc/log.h>
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews#include <isc/magic.h>
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews#include <isc/mem.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <isc/netaddr.h>
4162d3b36d1a3c25724c7e37ce839f67b2352bbbMark Andrews#include <isc/platform.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <isc/print.h>
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews#include <isc/serial.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <isc/stats.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <isc/stdtime.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <isc/string.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <isc/taskpool.h>
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt#include <isc/time.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <isc/util.h>
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/db.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/dbiterator.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/diff.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/dnssec.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/events.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/fixedname.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/journal.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/keyvalues.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/log.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/message.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/nsec.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/nsec3.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/private.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/rdataclass.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/rdataset.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/rdatasetiter.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/rdatastruct.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/rdatatype.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/result.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/soa.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/ssu.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/tsig.h>
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews#include <dns/update.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/view.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/zone.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#include <dns/zt.h>
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/**************************************************************************/
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews#define STATE_MAGIC ISC_MAGIC('S', 'T', 'T', 'E')
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews#define DNS_STATE_VALID(state) ISC_MAGIC_VALID(state, STATE_MAGIC)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Log level for tracing dynamic update protocol requests.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#define LOGLEVEL_PROTOCOL ISC_LOG_INFO
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Log level for low-level debug tracing.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Check an operation for failure. These macros all assume that
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * the function using them has a 'result' variable and a 'failure'
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * label.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#define CHECK(op) \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews do { result = (op); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS) goto failure; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } while (0)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Fail unconditionally with result 'code', which must not
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * be ISC_R_SUCCESS. The reason for failure presumably has
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * been logged already.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * from complaining about "end-of-loop code not reached".
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#define FAIL(code) \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews do { \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = (code); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS) goto failure; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } while (0)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Fail unconditionally and log as a client error.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * from complaining about "end-of-loop code not reached".
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#define FAILC(code, msg) \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews do { \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews const char *_what = "failed"; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = (code); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews switch (result) { \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_NXDOMAIN: \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_YXDOMAIN: \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_YXRRSET: \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_NXRRSET: \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews _what = "unsuccessful"; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews update_log(log, zone, LOGLEVEL_PROTOCOL, \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews "update %s: %s (%s)", _what, \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews msg, isc_result_totext(result)); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS) goto failure; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } while (0)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#define FAILN(code, name, msg) \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews do { \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews const char *_what = "failed"; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = (code); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews switch (result) { \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_NXDOMAIN: \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_YXDOMAIN: \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_YXRRSET: \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_NXRRSET: \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews _what = "unsuccessful"; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) { \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews char _nbuf[DNS_NAME_FORMATSIZE]; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_name_format(name, _nbuf, sizeof(_nbuf)); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews update_log(log, zone, LOGLEVEL_PROTOCOL, \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews "update %s: %s: %s (%s)", _what, _nbuf, \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews msg, isc_result_totext(result)); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS) goto failure; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } while (0)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#define FAILNT(code, name, type, msg) \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews do { \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews const char *_what = "failed"; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = (code); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews switch (result) { \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_NXDOMAIN: \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_YXDOMAIN: \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_YXRRSET: \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_NXRRSET: \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews _what = "unsuccessful"; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) { \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews char _nbuf[DNS_NAME_FORMATSIZE]; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews char _tbuf[DNS_RDATATYPE_FORMATSIZE]; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_name_format(name, _nbuf, sizeof(_nbuf)); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews update_log(log, zone, LOGLEVEL_PROTOCOL, \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews "update %s: %s/%s: %s (%s)", \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews _what, _nbuf, _tbuf, msg, \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_totext(result)); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS) goto failure; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } while (0)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Fail unconditionally and log as a server error.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * from complaining about "end-of-loop code not reached".
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#define FAILS(code, msg) \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews do { \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = (code); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews update_log(log, zone, LOGLEVEL_PROTOCOL, \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews "error: %s: %s", \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews msg, isc_result_totext(result)); \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS) goto failure; \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } while (0)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/**************************************************************************/
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewstypedef struct rr rr_t;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstruct rr {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /* dns_name_t name; */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_uint32_t ttl;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_t rdata;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews};
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewstypedef struct update_event update_event_t;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/**************************************************************************/
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic void
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsupdate_log(dns_update_log_t *callback, dns_zone_t *zone,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews int level, const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic void
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsupdate_log(dns_update_log_t *callback, dns_zone_t *zone,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews int level, const char *fmt, ...)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews va_list ap;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews char message[4096];
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (callback == NULL)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews va_start(ap, fmt);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews vsnprintf(message, sizeof(message), fmt, ap);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews va_end(ap);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (callback->func)(callback->arg, zone, level, message);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Update a single RR in version 'ver' of 'db' and log the
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * update in 'diff'.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Ensures:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * \li '*tuple' == NULL. Either the tuple is freed, or its
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * ownership has been transferred to the diff.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsdo_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t *diff)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t temp_diff;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Create a singleton diff.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_init(diff->mctx, &temp_diff);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Apply it to the database.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_diff_apply(&temp_diff, db, ver);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_free(tuple);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Merge it into the current pending journal entry.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_appendminimal(diff, tuple);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Do not clear temp_diff.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsupdate_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_t *rdata)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t *tuple = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_difftuple_create(diff->mctx, op,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews name, ttl, rdata, &tuple);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (do_one_tuple(&tuple, db, ver, diff));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/**************************************************************************/
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Callback-style iteration over rdatasets and rdatas.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * foreach_rrset() can be used to iterate over the RRsets
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * of a name and call a callback function with each
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * one. Similarly, foreach_rr() can be used to iterate
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * over the individual RRs at name, optionally restricted
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * to RRs of a given type.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * The callback functions are called "actions" and take
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * two arguments: a void pointer for passing arbitrary
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * context information, and a pointer to the current RRset
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * or RR. By convention, their names end in "_action".
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * XXXRTH We might want to make this public somewhere in libdns.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Function type for foreach_rrset() iterator actions.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewstypedef isc_result_t rrset_func(void *data, dns_rdataset_t *rrset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Function type for foreach_rr() iterator actions.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewstypedef isc_result_t rr_func(void *data, rr_t *rr);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Internal context struct for foreach_node_rr().
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewstypedef struct {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rr_func * rr_action;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews void * rr_action_data;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews} foreach_node_rr_ctx_t;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Internal helper function for foreach_node_rr().
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsforeach_node_rr_action(void *data, dns_rdataset_t *rdataset) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews foreach_node_rr_ctx_t *ctx = data;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews for (result = dns_rdataset_first(rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result == ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_rdataset_next(rdataset))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rr_t rr = { 0, DNS_RDATA_INIT };
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_current(rdataset, &rr.rdata);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rr.ttl = rdataset->ttl;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = (*ctx->rr_action)(ctx->rr_action_data, &rr);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_NOMORE)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * For each rdataset of 'name' in 'ver' of 'db', call 'action'
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * with the rdataset and 'action_data' as arguments. If the name
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * does not exist, do nothing.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * If 'action' returns an error, abort iteration and return the error.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsforeach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rrset_func *action, void *action_data)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbnode_t *node;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatasetiter_t *iter;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews node = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_db_findnode(db, name, ISC_FALSE, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_NOTFOUND)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews iter = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_db_allrdatasets(db, node, ver,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (isc_stdtime_t) 0, &iter);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews goto cleanup_node;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews for (result = dns_rdatasetiter_first(iter);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result == ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_rdatasetiter_next(iter))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_t rdataset;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_init(&rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatasetiter_current(iter, &rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = (*action)(action_data, &rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_disassociate(&rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews goto cleanup_iterator;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_NOMORE)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews cleanup_iterator:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatasetiter_destroy(&iter);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews cleanup_node:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * For each RR of 'name' in 'ver' of 'db', call 'action'
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * with the RR and 'action_data' as arguments. If the name
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * does not exist, do nothing.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * If 'action' returns an error, abort iteration
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * and return the error.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsforeach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rr_func *rr_action, void *rr_action_data)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews foreach_node_rr_ctx_t ctx;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ctx.rr_action = rr_action;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ctx.rr_action_data = rr_action_data;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (foreach_rrset(db, ver, name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews foreach_node_rr_action, &ctx));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * For each of the RRs specified by 'db', 'ver', 'name', 'type',
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * (which can be dns_rdatatype_any to match any type), and 'covers', call
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * 'action' with the RR and 'action_data' as arguments. If the name
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * does not exist, or if no RRset of the given type exists at the name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * do nothing.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * If 'action' returns an error, abort iteration and return the error.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsforeach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews void *rr_action_data)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbnode_t *node;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_t rdataset;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (type == dns_rdatatype_any)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (foreach_node_rr(db, ver, name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rr_action, rr_action_data));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews node = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (type == dns_rdatatype_nsec3 ||
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews else
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_db_findnode(db, name, ISC_FALSE, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_NOTFOUND)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_init(&rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_db_findrdataset(db, node, ver, type, covers,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (isc_stdtime_t) 0, &rdataset, NULL);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_NOTFOUND) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews goto cleanup_node;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews goto cleanup_node;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews for (result = dns_rdataset_first(&rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result == ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_rdataset_next(&rdataset))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rr_t rr = { 0, DNS_RDATA_INIT };
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_current(&rdataset, &rr.rdata);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rr.ttl = rdataset.ttl;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = (*rr_action)(rr_action_data, &rr);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews goto cleanup_rdataset;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_NOMORE)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews goto cleanup_rdataset;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews cleanup_rdataset:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_disassociate(&rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews cleanup_node:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/**************************************************************************/
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Various tests on the database contents (for prerequisites, etc).
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Function type for predicate functions that compare a database RR 'db_rr'
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * against an update RR 'update_rr'.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewstypedef isc_boolean_t rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Helper function for rrset_exists().
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsrrset_exists_action(void *data, rr_t *rr) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews UNUSED(data);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews UNUSED(rr);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_EXISTS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Utility macro for RR existence checking functions.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * If the variable 'result' has the value ISC_R_EXISTS or
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * ISC_R_SUCCESS, set *exists to ISC_TRUE or ISC_FALSE,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * respectively, and return success.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * If 'result' has any other value, there was a failure.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Return the failure result code and do not set *exists.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * This would be more readable as "do { if ... } while(0)",
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * but that form generates tons of warnings on Solaris 2.6.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#define RETURN_EXISTENCE_FLAG \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return ((result == ISC_R_EXISTS) ? \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (*exists = ISC_TRUE, ISC_R_SUCCESS) : \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ((result == ISC_R_SUCCESS) ? \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (*exists = ISC_FALSE, ISC_R_SUCCESS) : \
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Set '*exists' to true iff an rrset of the given type exists,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * to false otherwise.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsrrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatatype_t type, dns_rdatatype_t covers,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t *exists)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = foreach_rr(db, ver, name, type, covers,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rrset_exists_action, NULL);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews RETURN_EXISTENCE_FLAG;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Set '*visible' to true if the RRset exists and is part of the
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * visible zone. Otherwise '*visible' is set to false unless a
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * error occurs.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsrrset_visible(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatatype_t type, isc_boolean_t *visible)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_t fixed;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_init(&fixed);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_db_find(db, name, ver, type, DNS_DBFIND_NOWILD,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (isc_stdtime_t) 0, NULL,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_name(&fixed), NULL, NULL);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews switch (result) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case ISC_R_SUCCESS:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *visible = ISC_TRUE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews break;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Glue, obscured, deleted or replaced records.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_DELEGATION:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_DNAME:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_CNAME:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_NXDOMAIN:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_NXRRSET:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_EMPTYNAME:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews case DNS_R_COVERINGNSEC:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *visible = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews break;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews default:
3a49d0ff1000bb74a5f5abaef04f3e41e957c875Mark Andrews *visible = ISC_FALSE; /* silence false compiler warning */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews break;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Context struct and helper function for name_exists().
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsname_exists_action(void *data, dns_rdataset_t *rrset) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews UNUSED(data);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews UNUSED(rrset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_EXISTS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Set '*exists' to true iff the given name exists, to false otherwise.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsname_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t *exists)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = foreach_rrset(db, ver, name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews name_exists_action, NULL);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews RETURN_EXISTENCE_FLAG;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/**************************************************************************/
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Checking of "RRset exists (value dependent)" prerequisites.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * In the RFC2136 section 3.2.5, this is the pseudocode involving
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * a variable called "temp", a mapping of <name, type> tuples to rrsets.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Here, we represent the "temp" data structure as (non-minimal) "dns_diff_t"
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * where each tuple has op==DNS_DIFFOP_EXISTS.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * A comparison function defining the sorting order for the entries
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * in the "temp" data structure. The major sort key is the owner name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * followed by the type and rdata.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic int
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewstemp_order(const void *av, const void *bv) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t const * const *ap = av;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t const * const *bp = bv;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t const *a = *ap;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t const *b = *bp;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews int r;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews r = dns_name_compare(&a->name, &b->name);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (r != 0)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (r);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews r = (b->rdata.type - a->rdata.type);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (r != 0)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (r);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews r = dns_rdata_casecompare(&a->rdata, &b->rdata);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (r);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/**************************************************************************/
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Conditional deletion of RRs.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Context structure for delete_if().
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewstypedef struct {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rr_predicate *predicate;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_t *db;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbversion_t *ver;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t *diff;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_name_t *name;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_t *update_rr;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews} conditional_delete_ctx_t;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Predicate functions for delete_if().
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Return true always.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_boolean_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewstrue_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews UNUSED(update_rr);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews UNUSED(db_rr);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_TRUE);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Return true if the record is a RRSIG.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_boolean_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsrrsig_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews UNUSED(update_rr);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return ((db_rr->type == dns_rdatatype_rrsig) ?
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ISC_TRUE : ISC_FALSE);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Internal helper function for delete_if().
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsdelete_if_action(void *data, rr_t *rr) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews conditional_delete_ctx_t *ctx = data;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = update_one_rr(ctx->db, ctx->ver, ctx->diff,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews DNS_DIFFOP_DEL, ctx->name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rr->ttl, &rr->rdata);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } else {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Conditionally delete RRs. Apply 'predicate' to the RRs
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * specified by 'db', 'ver', 'name', and 'type' (which can
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * be dns_rdatatype_any to match any type). Delete those
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * RRs for which the predicate returns true, and log the
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * deletions in 'diff'.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsdelete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_t *update_rr, dns_diff_t *diff)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews conditional_delete_ctx_t ctx;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ctx.predicate = predicate;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ctx.db = db;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ctx.ver = ver;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ctx.diff = diff;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ctx.name = name;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ctx.update_rr = update_rr;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (foreach_rr(db, ver, name, type, covers,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews delete_if_action, &ctx));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/**************************************************************************/
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Incremental updating of NSECs and RRSIGs.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * We abuse the dns_diff_t type to represent a set of domain names
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * affected by the update.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsnamelist_append_name(dns_diff_t *list, dns_name_t *name) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t *tuple = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews static dns_rdata_t dummy_rdata = DNS_RDATA_INIT;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_difftuple_create(list->mctx, DNS_DIFFOP_EXISTS, name, 0,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews &dummy_rdata, &tuple));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_append(list, &tuple);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews failure:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsnamelist_append_subdomain(dns_db_t *db, dns_name_t *name, dns_diff_t *affected)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_t fixedname;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_name_t *child;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbiterator_t *dbit = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_init(&fixedname);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews child = dns_fixedname_name(&fixedname);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews for (result = dns_dbiterator_seek(dbit, name);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result == ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_dbiterator_next(dbit))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbnode_t *node = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_dbiterator_current(dbit, &node, child));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (! dns_name_issubdomain(child, name))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews break;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(namelist_append_name(affected, child));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_NOMORE)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews failure:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (dbit != NULL)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbiterator_destroy(&dbit);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Helper function for non_nsec_rrset_exists().
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsis_non_nsec_action(void *data, dns_rdataset_t *rrset) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews UNUSED(data);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (!(rrset->type == dns_rdatatype_nsec ||
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rrset->type == dns_rdatatype_nsec3 ||
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (rrset->type == dns_rdatatype_rrsig &&
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (rrset->covers == dns_rdatatype_nsec ||
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rrset->covers == dns_rdatatype_nsec3))))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_EXISTS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Check whether there is an rrset other than a NSEC or RRSIG NSEC,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * i.e., anything that justifies the continued existence of a name
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * after a secure update.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * If such an rrset exists, set '*exists' to ISC_TRUE.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Otherwise, set it to ISC_FALSE.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsnon_nsec_rrset_exists(dns_db_t *db, dns_dbversion_t *ver,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_name_t *name, isc_boolean_t *exists)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = foreach_rrset(db, ver, name, is_non_nsec_action, NULL);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews RETURN_EXISTENCE_FLAG;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * A comparison function for sorting dns_diff_t:s by name.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic int
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsname_order(const void *av, const void *bv) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t const * const *ap = av;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t const * const *bp = bv;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t const *a = *ap;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t const *b = *bp;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (dns_name_compare(&a->name, &b->name));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsuniqify_name_list(dns_diff_t *list) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t *p, *q;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_diff_sort(list, name_order));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews p = ISC_LIST_HEAD(list->tuples);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews while (p != NULL) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews do {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews q = ISC_LIST_NEXT(p, link);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (q == NULL || ! dns_name_equal(&p->name, &q->name))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews break;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews ISC_LIST_UNLINK(list->tuples, q, link);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_free(&q);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } while (1);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews p = ISC_LIST_NEXT(p, link);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews failure:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsis_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t *flag, isc_boolean_t *cut, isc_boolean_t *unsecure)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_t foundname;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_init(&foundname);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_db_find(db, name, ver, dns_rdatatype_any,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (isc_stdtime_t) 0, NULL,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_name(&foundname),
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews NULL, NULL);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_SUCCESS || result == DNS_R_EMPTYNAME) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *flag = ISC_TRUE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *cut = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (unsecure != NULL)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *unsecure = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } else if (result == DNS_R_ZONECUT) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *flag = ISC_TRUE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *cut = ISC_TRUE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (unsecure != NULL) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * We are at the zonecut. Check to see if there
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * is a DS RRset.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (dns_db_find(db, name, ver, dns_rdatatype_ds, 0,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (isc_stdtime_t) 0, NULL,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_name(&foundname),
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews NULL, NULL) == DNS_R_NXRRSET)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *unsecure = ISC_TRUE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews else
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *unsecure = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } else if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *flag = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *cut = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (unsecure != NULL)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *unsecure = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } else {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Silence compiler.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *flag = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *cut = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (unsecure != NULL)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *unsecure = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Find the next/previous name that has a NSEC record.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * In other words, skip empty database nodes and names that
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * have had their NSECs removed because they are obscured by
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * a zone cut.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsnext_active(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbversion_t *ver, dns_name_t *oldname, dns_name_t *newname,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t forward)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbiterator_t *dbit = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t has_nsec = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews unsigned int wraps = 0;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t secure = dns_db_issecure(db);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_db_createiterator(db, 0, &dbit));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_dbiterator_seek(dbit, oldname));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews do {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbnode_t *node = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (forward)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_dbiterator_next(dbit);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews else
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_dbiterator_prev(dbit);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_NOMORE) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Wrap around.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (forward)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_dbiterator_first(dbit));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews else
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_dbiterator_last(dbit));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews wraps++;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (wraps == 2) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews update_log(log, zone, ISC_LOG_ERROR,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews "secure zone with no NSECs");
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = DNS_R_BADZONE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews goto failure;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_dbiterator_current(dbit, &node, newname));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * The iterator may hold the tree lock, and
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * rrset_exists() calls dns_db_findnode() which
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * may try to reacquire it. To avoid deadlock
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * we must pause the iterator first.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_dbiterator_pause(dbit));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (secure) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(rrset_exists(db, ver, newname,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatatype_nsec, 0, &has_nsec));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } else {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_t ffound;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_name_t *found;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_init(&ffound);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews found = dns_fixedname_name(&ffound);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_db_find(db, newname, ver,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatatype_soa,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews DNS_DBFIND_NOWILD, 0, NULL, found,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews NULL, NULL);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_SUCCESS ||
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result == DNS_R_EMPTYNAME ||
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result == DNS_R_NXRRSET ||
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result == DNS_R_CNAME ||
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (result == DNS_R_DELEGATION &&
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_name_equal(newname, found))) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews has_nsec = ISC_TRUE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } else if (result != DNS_R_NXDOMAIN)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews break;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } while (! has_nsec);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews failure:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (dbit != NULL)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbiterator_destroy(&dbit);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Add a NSEC record for "name", recording the change in "diff".
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * The existing NSEC is removed.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsadd_nsec(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbversion_t *ver, dns_name_t *name, dns_ttl_t nsecttl,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t *diff)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbnode_t *node = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews unsigned char buffer[DNS_NSEC_BUFFERSIZE];
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t *tuple = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_t fixedname;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_name_t *target;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_fixedname_init(&fixedname);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews target = dns_fixedname_name(&fixedname);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Find the successor name, aka NSEC target.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(next_active(log, zone, db, ver, name, target, ISC_TRUE));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Create the NSEC RDATA.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_init(&rdata);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Delete the old NSEC and record the change.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(delete_if(true_p, db, ver, name, dns_rdatatype_nsec, 0,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews NULL, diff));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Add the new NSEC and record the change.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews nsecttl, &rdata, &tuple));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(do_one_tuple(&tuple, db, ver, diff));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews INSIST(tuple == NULL);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews failure:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (node != NULL)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Add a placeholder NSEC record for "name", recording the change in "diff".
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsadd_placeholder_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t *diff)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_difftuple_t *tuple = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_region_t r;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews unsigned char data[1] = { 0 }; /* The root domain, no bits. */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews r.base = data;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews r.length = sizeof(data);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_fromregion(&rdata, dns_db_class(db), dns_rdatatype_nsec, &r);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews &rdata, &tuple));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(do_one_tuple(&tuple, db, ver, diff));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews failure:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsfind_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_mem_t *mctx, unsigned int maxkeys,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dst_key_t **keys, unsigned int *nkeys)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbnode_t *node = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews const char *directory = dns_zone_getkeydirectory(zone);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews directory, mctx, maxkeys, keys, nkeys));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews failure:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (node != NULL)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Add RRSIG records for an RRset, recording the change in "diff".
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsadd_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_stdtime_t inception, isc_stdtime_t expire,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbnode_t *node = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_t rdataset;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_t sig_rdata = DNS_RDATA_INIT;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_buffer_t buffer;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews unsigned char data[1024]; /* XXX */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews unsigned int i, j;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t added_sig = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_mem_t *mctx = diff->mctx;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_init(&rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_buffer_init(&buffer, data, sizeof(data));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /* Get the rdataset to sign. */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (type == dns_rdatatype_nsec3)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews else
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_db_findrdataset(db, node, ver, type, 0,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (isc_stdtime_t) 0, &rdataset, NULL));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews#define ALG(x) dst_key_alg(x)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * If we are honoring KSK flags then we need to check that we
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * have both KSK and non-KSK keys that are not revoked per
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * algorithm.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews for (i = 0; i < nkeys; i++) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t both = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (!dst_key_isprivate(keys[i]))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews continue;
bf459d24a117ae2c54c37016430b41cd6d73491cMark Andrews if (dst_key_inactive(keys[i])) /* Should be redundant. */
bf459d24a117ae2c54c37016430b41cd6d73491cMark Andrews continue;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (check_ksk && !REVOKE(keys[i])) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t have_ksk, have_nonksk;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (KSK(keys[i])) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews have_ksk = ISC_TRUE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews have_nonksk = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } else {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews have_ksk = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews have_nonksk = ISC_TRUE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews for (j = 0; j < nkeys; j++) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (j == i || ALG(keys[i]) != ALG(keys[j]))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews continue;
bf459d24a117ae2c54c37016430b41cd6d73491cMark Andrews if (!dst_key_isprivate(keys[j]))
bf459d24a117ae2c54c37016430b41cd6d73491cMark Andrews continue;
bf459d24a117ae2c54c37016430b41cd6d73491cMark Andrews if (dst_key_inactive(keys[j])) /* SBR */
bf459d24a117ae2c54c37016430b41cd6d73491cMark Andrews continue;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (REVOKE(keys[j]))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews continue;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (KSK(keys[j]))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews have_ksk = ISC_TRUE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews else
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews have_nonksk = ISC_TRUE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews both = have_ksk && have_nonksk;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (both)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews break;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (both) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (type == dns_rdatatype_dnskey) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (!KSK(keys[i]) && keyset_kskonly)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews continue;
598b502695802c3d4e23316b85368e54f39f5cabMark Andrews } else if (KSK(keys[i])) {
598b502695802c3d4e23316b85368e54f39f5cabMark Andrews /*
598b502695802c3d4e23316b85368e54f39f5cabMark Andrews * CDS and CDNSKEY are signed with KSK
598b502695802c3d4e23316b85368e54f39f5cabMark Andrews * (RFC 7344, 4.1).
598b502695802c3d4e23316b85368e54f39f5cabMark Andrews */
598b502695802c3d4e23316b85368e54f39f5cabMark Andrews if (type != dns_rdatatype_cds &&
598b502695802c3d4e23316b85368e54f39f5cabMark Andrews type != dns_rdatatype_cdnskey)
598b502695802c3d4e23316b85368e54f39f5cabMark Andrews continue;
598b502695802c3d4e23316b85368e54f39f5cabMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews continue;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /* Calculate the signature, creating a RRSIG RDATA. */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews &inception, &expire,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews mctx, &buffer, &sig_rdata));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /* Update the database and journal with the RRSIG. */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /* XXX inefficient - will cause dataset merging */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rdataset.ttl, &sig_rdata));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_reset(&sig_rdata);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_buffer_init(&buffer, data, sizeof(data));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews added_sig = ISC_TRUE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (!added_sig) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews update_log(log, zone, ISC_LOG_ERROR,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews "found no active private keys, "
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews "unable to generate any signatures");
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = ISC_R_NOTFOUND;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews failure:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (dns_rdataset_isassociated(&rdataset))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_disassociate(&rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (node != NULL)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Delete expired RRsigs and any RRsigs we are about to re-sign.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * See also zone.c:del_sigs().
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsdel_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbnode_t *node = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_t rdataset;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews unsigned int i;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_rrsig_t rrsig;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t found;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_init(&rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_db_findnode(db, name, ISC_FALSE, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_NOTFOUND)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews goto failure;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatatype_dnskey, (isc_stdtime_t) 0,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews &rdataset, NULL);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_NOTFOUND)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews goto failure;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews for (result = dns_rdataset_first(&rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result == ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_rdataset_next(&rdataset)) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_current(&rdataset, &rdata);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews RUNTIME_CHECK(result == ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews found = ISC_FALSE;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews for (i = 0; i < nkeys; i++) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (rrsig.keyid == dst_key_id(keys[i])) {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews found = ISC_TRUE;
7ace3277956c49f7554b7130ef761bde3b35db30Mark Andrews if (!dst_key_isprivate(keys[i]) &&
7ace3277956c49f7554b7130ef761bde3b35db30Mark Andrews !dst_key_inactive(keys[i]))
7ace3277956c49f7554b7130ef761bde3b35db30Mark Andrews {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * The re-signing code in zone.c
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * will mark this as offline.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Just skip the record for now.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews break;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = update_one_rr(db, ver, diff,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews DNS_DIFFOP_DEL, name,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews rdataset.ttl, &rdata);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews break;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * If there is not a matching DNSKEY then delete the RRSIG.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (!found)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews name, rdataset.ttl, &rdata);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_reset(&rdata);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews break;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_disassociate(&rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_NOMORE)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsfailure:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (node != NULL)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsstatic isc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsadd_exposed_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t cut,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_stdtime_t inception, isc_stdtime_t expire,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews unsigned int *sigs)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_result_t result;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbnode_t *node;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatasetiter_t *iter;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews node = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_db_findnode(db, name, ISC_FALSE, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_NOTFOUND)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (ISC_R_SUCCESS);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews iter = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_db_allrdatasets(db, node, ver,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (isc_stdtime_t) 0, &iter);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews goto cleanup_node;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews for (result = dns_rdatasetiter_first(iter);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result == ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = dns_rdatasetiter_next(iter))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews {
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_t rdataset;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatatype_t type;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t flag;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_init(&rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatasetiter_current(iter, &rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews type = rdataset.type;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_disassociate(&rdataset);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * We don't need to sign unsigned NSEC records at the cut
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * as they are handled elsewhere.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if ((type == dns_rdatatype_rrsig) ||
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews (cut && type != dns_rdatatype_ds))
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews continue;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = rrset_exists(db, ver, name, dns_rdatatype_rrsig,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews type, &flag);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews goto cleanup_iterator;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (flag)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews continue;;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = add_sigs(log, zone, db, ver, name, type, diff,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews keys, nkeys, inception, expire,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews check_ksk, keyset_kskonly);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result != ISC_R_SUCCESS)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews goto cleanup_iterator;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews (*sigs)++;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews if (result == ISC_R_NOMORE)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews result = ISC_R_SUCCESS;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews cleanup_iterator:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatasetiter_destroy(&iter);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews cleanup_node:
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews/*%
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * Update RRSIG, NSEC and NSEC3 records affected by an update. The original
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * update, including the SOA serial update but excluding the RRSIG & NSEC
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * changes, is in "diff" and has already been applied to "newver" of "db".
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * The database version prior to the update is "oldver".
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * The necessary RRSIG, NSEC and NSEC3 changes will be applied to "newver"
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * and added (as a minimal diff) to "diff".
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews *
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews * The RRSIGs generated will be valid for 'sigvalidityinterval' seconds.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsisc_result_t
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrewsdns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbversion_t *oldver, dns_dbversion_t *newver,
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t *diff, isc_uint32_t sigvalidityinterval)
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews{
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews return (dns_update_signaturesinc(log, zone, db, oldver, newver, diff,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews sigvalidityinterval, NULL));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews}
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrewsstruct dns_update_state {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews unsigned int magic;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t diffnames;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t affected;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t sig_diff;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t nsec_diff;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_diff_t nsec_mindiff;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_t work;
8281fd83da005cdb114a4c784c847a7eec4bdc38Evan Hunt dst_key_t *zone_keys[DNS_MAXZONEKEYS];
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews unsigned int nkeys;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_stdtime_t inception, expire;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_ttl_t nsecttl;
24231afa05b4ceefe8f0aebcdabe9ccf002346f9Mark Andrews isc_boolean_t check_ksk, keyset_kskonly, build_nsec3;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews enum { sign_updates, remove_orphaned, build_chain, process_nsec,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews sign_nsec, update_nsec3, process_nsec3, sign_nsec3 } state;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews};
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrewsisc_result_t
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrewsdns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_dbversion_t *oldver, dns_dbversion_t *newver,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_t *diff, isc_uint32_t sigvalidityinterval,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_update_state_t **statep)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews{
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_result_t result = ISC_R_SUCCESS;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_update_state_t mystate, *state;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_difftuple_t *t, *next;
24231afa05b4ceefe8f0aebcdabe9ccf002346f9Mark Andrews isc_boolean_t flag, build_nsec;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews unsigned int i;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_stdtime_t now;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_soa_t soa;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdataset_t rdataset;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_dbnode_t *node = NULL;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t unsecure;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews isc_boolean_t cut;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews unsigned int sigs = 0;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews unsigned int maxsigs = dns_zone_getsignatures(zone);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (statep == NULL || (statep != NULL && *statep == NULL)) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (statep == NULL) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state = &mystate;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews } else {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state = isc_mem_get(diff->mctx, sizeof(*state));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (state == NULL)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews return (ISC_R_NOMEMORY);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_init(diff->mctx, &state->diffnames);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_init(diff->mctx, &state->affected);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_init(diff->mctx, &state->sig_diff);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_init(diff->mctx, &state->nsec_diff);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_init(diff->mctx, &state->nsec_mindiff);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_init(diff->mctx, &state->work);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->nkeys = 0;
24231afa05b4ceefe8f0aebcdabe9ccf002346f9Mark Andrews state->build_nsec3 = ISC_FALSE;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews result = find_zone_keys(zone, db, newver, diff->mctx,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews DNS_MAXZONEKEYS, state->zone_keys,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->nkeys);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (result != ISC_R_SUCCESS) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews update_log(log, zone, ISC_LOG_ERROR,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews "could not get zone keys for secure "
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews "dynamic update");
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews goto failure;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_stdtime_get(&now);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->inception = now - 3600; /* Allow for some clock skew. */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->expire = now + sigvalidityinterval;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Do we look at the KSK flag on the DNSKEY to determining which
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * keys sign which RRsets? First check the zone option then
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * check the keys flags to make sure at least one has a ksk set
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * and one doesn't.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->check_ksk = ISC_TF((dns_zone_getoptions(zone) &
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews DNS_ZONEOPT_UPDATECHECKKSK) != 0);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->keyset_kskonly = ISC_TF((dns_zone_getoptions(zone) &
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews DNS_ZONEOPT_DNSKEYKSKONLY) != 0);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Get the NSEC/NSEC3 TTL from the SOA MINIMUM field.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdataset_init(&rdataset);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews 0, (isc_stdtime_t) 0, &rdataset,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews NULL));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(dns_rdataset_first(&rdataset));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdataset_current(&rdataset, &rdata);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(dns_rdata_tostruct(&rdata, &soa, NULL));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->nsecttl = soa.minimum;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdataset_disassociate(&rdataset);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_db_detachnode(db, &node);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Find all RRsets directly affected by the update, and
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * update their RRSIGs. Also build a list of names affected
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * by the update in "diffnames".
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(dns_diff_sort(diff, temp_order));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->state = sign_updates;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->magic = STATE_MAGIC;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (statep != NULL)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews *statep = state;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews } else {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews REQUIRE(DNS_STATE_VALID(*statep));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state = *statep;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews next_state:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews switch (state->state) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews case sign_updates:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t = ISC_LIST_HEAD(diff->tuples);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while (t != NULL) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_name_t *name = &t->name;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Now "name" is a new, unique name affected by the
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * update.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(namelist_append_name(&state->diffnames, name));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while (t != NULL && dns_name_equal(&t->name, name)) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_t type;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews type = t->rdata.type;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Now "name" and "type" denote a new unique
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * RRset affected by the update.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /* Don't sign RRSIGs. */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (type == dns_rdatatype_rrsig)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews goto skip;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Delete all old RRSIGs covering this type,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * since they are all invalid when the signed
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * RRset has changed. We may not be able to
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * recreate all of them - tough.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Special case changes to the zone's DNSKEY
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * records to support offline KSKs.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (type == dns_rdatatype_dnskey)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews del_keysigs(db, newver, name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->sig_diff,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->zone_keys,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->nkeys);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews else
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(delete_if(true_p, db, newver,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_rrsig,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews type, NULL,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->sig_diff));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * If this RRset is still visible after the
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * update, add a new signature for it.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(rrset_visible(db, newver, name, type,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &flag));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (flag) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(add_sigs(log, zone, db, newver,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews name, type,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->sig_diff,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->zone_keys,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->nkeys,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->inception,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->expire,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->check_ksk,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->keyset_kskonly));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews sigs++;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews skip:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /* Skip any other updates to the same RRset. */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while (t != NULL &&
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_name_equal(&t->name, name) &&
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t->rdata.type == type)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews next = ISC_LIST_NEXT(t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_UNLINK(diff->tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_APPEND(state->work.tuples, t,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t = next;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (state != &mystate && sigs > maxsigs)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews return (DNS_R_CONTINUE);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_APPENDLIST(diff->tuples, state->work.tuples, link);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews update_log(log, zone, ISC_LOG_DEBUG(3),
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews "updated data signatures");
7dbeb5e7f067585abfb12fac314a0d2a8f0dd040Evan Hunt /* FALLTHROUGH */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews case remove_orphaned:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->state = remove_orphaned;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /* Remove orphaned NSECs and RRSIG NSECs. */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews for (t = ISC_LIST_HEAD(state->diffnames.tuples);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t != NULL;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t = ISC_LIST_NEXT(t, link))
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(non_nsec_rrset_exists(db, newver,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &t->name, &flag));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (!flag) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(delete_if(true_p, db, newver, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_any, 0,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews NULL, &state->sig_diff));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews update_log(log, zone, ISC_LOG_DEBUG(3),
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews "removed any orphaned NSEC records");
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * See if we need to build NSEC or NSEC3 chains.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(dns_private_chains(db, newver, privatetype, &build_nsec,
24231afa05b4ceefe8f0aebcdabe9ccf002346f9Mark Andrews &state->build_nsec3));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (!build_nsec) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->state = update_nsec3;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews goto next_state;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews update_log(log, zone, ISC_LOG_DEBUG(3),
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews "rebuilding NSEC chain");
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
7dbeb5e7f067585abfb12fac314a0d2a8f0dd040Evan Hunt /* FALLTHROUGH */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews case build_chain:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->state = build_chain;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * When a name is created or deleted, its predecessor needs to
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * have its NSEC updated.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews for (t = ISC_LIST_HEAD(state->diffnames.tuples);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t != NULL;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t = ISC_LIST_NEXT(t, link))
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_boolean_t existed, exists;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_fixedname_t fixedname;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_name_t *prevname;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_fixedname_init(&fixedname);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews prevname = dns_fixedname_name(&fixedname);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (oldver != NULL)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(name_exists(db, oldver, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &existed));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews else
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews existed = ISC_FALSE;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(name_exists(db, newver, &t->name, &exists));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (exists == existed)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews continue;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Find the predecessor.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * When names become obscured or unobscured in this
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * update transaction, we may find the wrong
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * predecessor because the NSECs have not yet been
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * updated to reflect the delegation change. This
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * should not matter because in this case, the correct
811acf52b825f9fb4889cad7b84b581a2d4776f9Tinderbox User * predecessor is either the delegation node or a
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * newly unobscured node, and those nodes are on the
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * "affected" list in any case.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(next_active(log, zone, db, newver,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &t->name, prevname, ISC_FALSE));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(namelist_append_name(&state->affected, prevname));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Find names potentially affected by delegation changes
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * (obscured by adding an NS or DNAME, or unobscured by
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * removing one).
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews for (t = ISC_LIST_HEAD(state->diffnames.tuples);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t != NULL;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t = ISC_LIST_NEXT(t, link))
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_boolean_t ns_existed, dname_existed;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_boolean_t ns_exists, dname_exists;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (oldver != NULL)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(rrset_exists(db, oldver, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_ns, 0,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &ns_existed));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews else
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ns_existed = ISC_FALSE;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (oldver != NULL)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(rrset_exists(db, oldver, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_dname, 0,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &dname_existed));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews else
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dname_existed = ISC_FALSE;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(rrset_exists(db, newver, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_ns, 0, &ns_exists));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(rrset_exists(db, newver, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_dname, 0,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &dname_exists));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if ((ns_exists || dname_exists) ==
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews (ns_existed || dname_existed))
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews continue;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * There was a delegation change. Mark all subdomains
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * of t->name as potentially needing a NSEC update.
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(namelist_append_subdomain(db, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->affected));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_APPENDLIST(state->affected.tuples,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->diffnames.tuples, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews INSIST(ISC_LIST_EMPTY(state->diffnames.tuples));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(uniqify_name_list(&state->affected));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
7dbeb5e7f067585abfb12fac314a0d2a8f0dd040Evan Hunt /* FALLTHROUGH */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews case process_nsec:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->state = process_nsec;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Determine which names should have NSECs, and delete/create
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * NSECs to make it so. We don't know the final NSEC targets
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * yet, so we just create placeholder NSECs with arbitrary
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * contents to indicate that their respective owner names
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * should be part of the NSEC chain.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while ((t = ISC_LIST_HEAD(state->affected.tuples)) != NULL) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_boolean_t exists;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_name_t *name = &t->name;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(name_exists(db, newver, name, &exists));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (! exists)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews goto unlink;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(is_active(db, newver, name, &flag, &cut, NULL));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (!flag) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * This name is obscured. Delete any
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * existing NSEC record.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(delete_if(true_p, db, newver, name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_nsec, 0,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews NULL, &state->nsec_diff));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(delete_if(rrsig_p, db, newver, name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_any, 0, NULL,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews diff));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews } else {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * This name is not obscured. It needs to have
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * a NSEC unless it is the at the origin, in
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * which case it should already exist if there
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * is a complete NSEC chain and if there isn't
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * a complete NSEC chain we don't want to add
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * one as that would signal that there is a
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * complete NSEC chain.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (!dns_name_equal(name, dns_db_origin(db))) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(rrset_exists(db, newver, name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_nsec,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews 0, &flag));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (!flag)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(add_placeholder_nsec(db,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews newver, name, diff));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(add_exposed_sigs(log, zone, db, newver,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews name, cut,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->sig_diff,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->zone_keys,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->nkeys,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->inception,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->expire,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->check_ksk,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->keyset_kskonly,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &sigs));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews unlink:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_UNLINK(state->affected.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_APPEND(state->work.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (state != &mystate && sigs > maxsigs)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews return (DNS_R_CONTINUE);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_APPENDLIST(state->affected.tuples,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->work.tuples, link);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Now we know which names are part of the NSEC chain.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Make them all point at their correct targets.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews for (t = ISC_LIST_HEAD(state->affected.tuples);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t != NULL;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t = ISC_LIST_NEXT(t, link))
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(rrset_exists(db, newver, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_nsec, 0, &flag));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (flag) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * There is a NSEC, but we don't know if it
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * is correct. Delete it and create a correct
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * one to be sure. If the update was
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * unnecessary, the diff minimization
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * will take care of eliminating it from the
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * journal, IXFRs, etc.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews *
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * The RRSIG bit should always be set in the
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * NSECs we generate, because they will all
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * get RRSIG NSECs.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * (XXX what if the zone keys are missing?).
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Because the RRSIG NSECs have not necessarily
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * been created yet, the correctness of the
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * bit mask relies on the assumption that NSECs
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * are only created if there is other data, and
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * if there is other data, there are other
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * RRSIGs.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(add_nsec(log, zone, db, newver, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->nsecttl,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->nsec_diff));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Minimize the set of NSEC updates so that we don't
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * have to regenerate the RRSIG NSECs for NSECs that were
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * replaced with identical ones.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while ((t = ISC_LIST_HEAD(state->nsec_diff.tuples)) != NULL) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_UNLINK(state->nsec_diff.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_appendminimal(&state->nsec_mindiff, &t);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews update_log(log, zone, ISC_LOG_DEBUG(3),
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews "signing rebuilt NSEC chain");
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
7dbeb5e7f067585abfb12fac314a0d2a8f0dd040Evan Hunt /* FALLTHROUGH */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews case sign_nsec:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->state = sign_nsec;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /* Update RRSIG NSECs. */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (t->op == DNS_DIFFOP_DEL) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(delete_if(true_p, db, newver, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_rrsig,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_nsec,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews NULL, &state->sig_diff));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews } else if (t->op == DNS_DIFFOP_ADD) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(add_sigs(log, zone, db, newver, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_nsec,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->sig_diff,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->zone_keys, state->nkeys,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->inception, state->expire,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->check_ksk,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->keyset_kskonly));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews sigs++;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews } else {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews INSIST(0);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_APPEND(state->work.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (state != &mystate && sigs > maxsigs)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews return (DNS_R_CONTINUE);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_APPENDLIST(state->nsec_mindiff.tuples,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->work.tuples, link);
7dbeb5e7f067585abfb12fac314a0d2a8f0dd040Evan Hunt /* FALLTHROUGH */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews case update_nsec3:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->state = update_nsec3;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /* Record our changes for the journal. */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while ((t = ISC_LIST_HEAD(state->sig_diff.tuples)) != NULL) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_UNLINK(state->sig_diff.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_appendminimal(diff, &t);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_appendminimal(diff, &t);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews INSIST(ISC_LIST_EMPTY(state->sig_diff.tuples));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews INSIST(ISC_LIST_EMPTY(state->nsec_diff.tuples));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews INSIST(ISC_LIST_EMPTY(state->nsec_mindiff.tuples));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
24231afa05b4ceefe8f0aebcdabe9ccf002346f9Mark Andrews if (!state->build_nsec3) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews update_log(log, zone, ISC_LOG_DEBUG(3),
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews "no NSEC3 chains to rebuild");
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews goto failure;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews update_log(log, zone, ISC_LOG_DEBUG(3),
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews "rebuilding NSEC3 chains");
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_clear(&state->diffnames);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_clear(&state->affected);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(dns_diff_sort(diff, temp_order));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Find names potentially affected by delegation changes
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * (obscured by adding an NS or DNAME, or unobscured by
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * removing one).
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t = ISC_LIST_HEAD(diff->tuples);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while (t != NULL) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_name_t *name = &t->name;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_boolean_t ns_existed, dname_existed;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_boolean_t ns_exists, dname_exists;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_boolean_t exists, existed;
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (t->rdata.type == dns_rdatatype_nsec ||
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t->rdata.type == dns_rdatatype_rrsig) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t = ISC_LIST_NEXT(t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews continue;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(namelist_append_name(&state->affected, name));
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (oldver != NULL)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(rrset_exists(db, oldver, name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_ns,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews 0, &ns_existed));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews else
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ns_existed = ISC_FALSE;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (oldver != NULL)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(rrset_exists(db, oldver, name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_dname, 0,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &dname_existed));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews else
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dname_existed = ISC_FALSE;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(rrset_exists(db, newver, name, dns_rdatatype_ns,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews 0, &ns_exists));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(rrset_exists(db, newver, name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_dname, 0,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &dname_exists));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews exists = ns_exists || dname_exists;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews existed = ns_existed || dname_existed;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (exists == existed)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews goto nextname;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * There was a delegation change. Mark all subdomains
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * of t->name as potentially needing a NSEC3 update.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(namelist_append_subdomain(db, name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->affected));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews nextname:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while (t != NULL && dns_name_equal(&t->name, name))
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews t = ISC_LIST_NEXT(t, link);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
7dbeb5e7f067585abfb12fac314a0d2a8f0dd040Evan Hunt /* FALLTHROUGH */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews case process_nsec3:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->state = process_nsec3;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while ((t = ISC_LIST_HEAD(state->affected.tuples)) != NULL) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_name_t *name = &t->name;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews unsecure = ISC_FALSE; /* Silence compiler warning. */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(is_active(db, newver, name, &flag, &cut,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &unsecure));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (!flag) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(delete_if(rrsig_p, db, newver, name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_any, 0, NULL,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews diff));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(dns_nsec3_delnsec3sx(db, newver, name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews privatetype,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->nsec_diff));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews } else {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(add_exposed_sigs(log, zone, db, newver,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews name, cut,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->sig_diff,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->zone_keys,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->nkeys,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->inception,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->expire,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->check_ksk,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->keyset_kskonly,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &sigs));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(dns_nsec3_addnsec3sx(db, newver, name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->nsecttl,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews unsecure,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews privatetype,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->nsec_diff));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_UNLINK(state->affected.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_APPEND(state->work.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (state != &mystate && sigs > maxsigs)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews return (DNS_R_CONTINUE);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_APPENDLIST(state->affected.tuples,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->work.tuples, link);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /*
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * Minimize the set of NSEC3 updates so that we don't
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * have to regenerate the RRSIG NSEC3s for NSEC3s that were
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews * replaced with identical ones.
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while ((t = ISC_LIST_HEAD(state->nsec_diff.tuples)) != NULL) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_UNLINK(state->nsec_diff.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_appendminimal(&state->nsec_mindiff, &t);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews update_log(log, zone, ISC_LOG_DEBUG(3),
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews "signing rebuilt NSEC3 chain");
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
7dbeb5e7f067585abfb12fac314a0d2a8f0dd040Evan Hunt /* FALLTHROUGH */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews case sign_nsec3:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->state = sign_nsec3;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /* Update RRSIG NSEC3s. */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (t->op == DNS_DIFFOP_DEL) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(delete_if(true_p, db, newver, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_rrsig,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_nsec3,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews NULL, &state->sig_diff));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews } else if (t->op == DNS_DIFFOP_ADD) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews CHECK(add_sigs(log, zone, db, newver, &t->name,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_rdatatype_nsec3,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews &state->sig_diff,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->zone_keys,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->nkeys, state->inception,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->expire, state->check_ksk,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->keyset_kskonly));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews sigs++;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews } else {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews INSIST(0);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_APPEND(state->work.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (state != &mystate && sigs > maxsigs)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews return (DNS_R_CONTINUE);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_APPENDLIST(state->nsec_mindiff.tuples,
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->work.tuples, link);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews /* Record our changes for the journal. */
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while ((t = ISC_LIST_HEAD(state->sig_diff.tuples)) != NULL) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_UNLINK(state->sig_diff.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_appendminimal(diff, &t);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
811acf52b825f9fb4889cad7b84b581a2d4776f9Tinderbox User {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_appendminimal(diff, &t);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews INSIST(ISC_LIST_EMPTY(state->sig_diff.tuples));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews INSIST(ISC_LIST_EMPTY(state->nsec_diff.tuples));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews INSIST(ISC_LIST_EMPTY(state->nsec_mindiff.tuples));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews break;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews default:
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews INSIST(0);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews failure:
73cf0ba4e82c6baef638ecc4e31321223f841d28Mark Andrews if (node != NULL) {
73cf0ba4e82c6baef638ecc4e31321223f841d28Mark Andrews dns_db_detachnode(db, &node);
73cf0ba4e82c6baef638ecc4e31321223f841d28Mark Andrews }
73cf0ba4e82c6baef638ecc4e31321223f841d28Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_clear(&state->sig_diff);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_clear(&state->nsec_diff);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_clear(&state->nsec_mindiff);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_clear(&state->affected);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_clear(&state->diffnames);
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dns_diff_clear(&state->work);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews for (i = 0; i < state->nkeys; i++)
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews dst_key_free(&state->zone_keys[i]);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews if (state != &mystate && state != NULL) {
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews *statep = NULL;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews state->magic = 0;
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews isc_mem_put(diff->mctx, state, sizeof(*state));
1b05d22789fd9a17aca4f459639bc2b6848c3160Mark Andrews }
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews return (result);
9198ab377b1cbf07d6d0c6eec25296c135bd66bdMark Andrews}
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews
7318bbc26262a66a0d740ceefed769961ef7e476Evan Huntstatic isc_stdtime_t
7318bbc26262a66a0d740ceefed769961ef7e476Evan Huntepoch_to_yyyymmdd(time_t when) {
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt struct tm *tm;
4162d3b36d1a3c25724c7e37ce839f67b2352bbbMark Andrews
4162d3b36d1a3c25724c7e37ce839f67b2352bbbMark Andrews#if defined(ISC_PLATFORM_USETHREADS) && !defined(WIN32)
4162d3b36d1a3c25724c7e37ce839f67b2352bbbMark Andrews struct tm tm0;
4162d3b36d1a3c25724c7e37ce839f67b2352bbbMark Andrews tm = localtime_r(&when, &tm0);
4162d3b36d1a3c25724c7e37ce839f67b2352bbbMark Andrews#else
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt tm = localtime(&when);
4162d3b36d1a3c25724c7e37ce839f67b2352bbbMark Andrews#endif
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt return (((tm->tm_year + 1900) * 10000) +
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt ((tm->tm_mon + 1) * 100) + tm->tm_mday);
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt}
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrewsisc_uint32_t
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrewsdns_update_soaserial(isc_uint32_t serial, dns_updatemethod_t method) {
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews isc_stdtime_t now;
b4ba66ba1e36a6d8236d20be55273ce663819d69Evan Hunt isc_uint32_t new_serial;
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews
b4ba66ba1e36a6d8236d20be55273ce663819d69Evan Hunt switch (method) {
b4ba66ba1e36a6d8236d20be55273ce663819d69Evan Hunt case dns_updatemethod_none:
b4ba66ba1e36a6d8236d20be55273ce663819d69Evan Hunt return (serial);
b4ba66ba1e36a6d8236d20be55273ce663819d69Evan Hunt case dns_updatemethod_unixtime:
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews isc_stdtime_get(&now);
122230159d02eb8d947c3bb3f279469919c164c8Automatic Updater if (now != 0 && isc_serial_gt(now, serial))
122230159d02eb8d947c3bb3f279469919c164c8Automatic Updater return (now);
b4ba66ba1e36a6d8236d20be55273ce663819d69Evan Hunt break;
b4ba66ba1e36a6d8236d20be55273ce663819d69Evan Hunt case dns_updatemethod_date:
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt isc_stdtime_get(&now);
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt new_serial = epoch_to_yyyymmdd((time_t) now) * 100;
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt if (new_serial != 0 && isc_serial_gt(new_serial, serial))
7318bbc26262a66a0d740ceefed769961ef7e476Evan Hunt return (new_serial);
b4ba66ba1e36a6d8236d20be55273ce663819d69Evan Hunt case dns_updatemethod_increment:
b4ba66ba1e36a6d8236d20be55273ce663819d69Evan Hunt break;
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews }
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews /* RFC1982 */
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews serial = (serial + 1) & 0xFFFFFFFF;
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews if (serial == 0)
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews serial = 1;
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews return (serial);
a69070d8fab55dbc63ba9f96c9d3e34f0ea9119aMark Andrews}