Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: zone.c,v 1.27 2026/04/08 00:16:14 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 /*! \file */
     17 
     18 #include <errno.h>
     19 #include <inttypes.h>
     20 #include <stdbool.h>
     21 
     22 #include <isc/async.h>
     23 #include <isc/atomic.h>
     24 #include <isc/file.h>
     25 #include <isc/hash.h>
     26 #include <isc/hashmap.h>
     27 #include <isc/hex.h>
     28 #include <isc/list.h>
     29 #include <isc/loop.h>
     30 #include <isc/md.h>
     31 #include <isc/mutex.h>
     32 #include <isc/overflow.h>
     33 #include <isc/random.h>
     34 #include <isc/ratelimiter.h>
     35 #include <isc/refcount.h>
     36 #include <isc/result.h>
     37 #include <isc/rwlock.h>
     38 #include <isc/serial.h>
     39 #include <isc/stats.h>
     40 #include <isc/stdtime.h>
     41 #include <isc/strerr.h>
     42 #include <isc/string.h>
     43 #include <isc/thread.h>
     44 #include <isc/tid.h>
     45 #include <isc/timer.h>
     46 #include <isc/tls.h>
     47 #include <isc/util.h>
     48 
     49 #include <dns/acl.h>
     50 #include <dns/adb.h>
     51 #include <dns/callbacks.h>
     52 #include <dns/catz.h>
     53 #include <dns/db.h>
     54 #include <dns/dbiterator.h>
     55 #include <dns/dlz.h>
     56 #include <dns/dnssec.h>
     57 #include <dns/journal.h>
     58 #include <dns/kasp.h>
     59 #include <dns/keydata.h>
     60 #include <dns/keymgr.h>
     61 #include <dns/keytable.h>
     62 #include <dns/keyvalues.h>
     63 #include <dns/log.h>
     64 #include <dns/master.h>
     65 #include <dns/masterdump.h>
     66 #include <dns/message.h>
     67 #include <dns/name.h>
     68 #include <dns/nsec.h>
     69 #include <dns/nsec3.h>
     70 #include <dns/opcode.h>
     71 #include <dns/peer.h>
     72 #include <dns/private.h>
     73 #include <dns/rcode.h>
     74 #include <dns/rdata.h>
     75 #include <dns/rdataclass.h>
     76 #include <dns/rdatalist.h>
     77 #include <dns/rdataset.h>
     78 #include <dns/rdatasetiter.h>
     79 #include <dns/rdatastruct.h>
     80 #include <dns/rdatatype.h>
     81 #include <dns/remote.h>
     82 #include <dns/request.h>
     83 #include <dns/resolver.h>
     84 #include <dns/rriterator.h>
     85 #include <dns/skr.h>
     86 #include <dns/soa.h>
     87 #include <dns/ssu.h>
     88 #include <dns/stats.h>
     89 #include <dns/time.h>
     90 #include <dns/tsig.h>
     91 #include <dns/ttl.h>
     92 #include <dns/update.h>
     93 #include <dns/xfrin.h>
     94 #include <dns/zone.h>
     95 #include <dns/zoneverify.h>
     96 #include <dns/zt.h>
     97 
     98 #include <dst/dst.h>
     99 
    100 #include "zone_p.h"
    101 
    102 #define ZONE_MAGIC	     ISC_MAGIC('Z', 'O', 'N', 'E')
    103 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
    104 
    105 #define NOTIFY_MAGIC		 ISC_MAGIC('N', 't', 'f', 'y')
    106 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
    107 
    108 #define CHECKDS_MAGIC		   ISC_MAGIC('C', 'h', 'D', 'S')
    109 #define DNS_CHECKDS_VALID(checkds) ISC_MAGIC_VALID(checkds, CHECKDS_MAGIC)
    110 
    111 #define STUB_MAGIC	     ISC_MAGIC('S', 't', 'u', 'b')
    112 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
    113 
    114 #define ZONEMGR_MAGIC		ISC_MAGIC('Z', 'm', 'g', 'r')
    115 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
    116 
    117 #define FORWARD_MAGIC		ISC_MAGIC('F', 'o', 'r', 'w')
    118 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
    119 
    120 #define IO_MAGIC	   ISC_MAGIC('Z', 'm', 'I', 'O')
    121 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
    122 
    123 #define KEYMGMT_MAGIC		ISC_MAGIC('M', 'g', 'm', 't')
    124 #define DNS_KEYMGMT_VALID(load) ISC_MAGIC_VALID(load, KEYMGMT_MAGIC)
    125 
    126 #define KEYFILEIO_MAGIC		  ISC_MAGIC('K', 'y', 'I', 'O')
    127 #define DNS_KEYFILEIO_VALID(kfio) ISC_MAGIC_VALID(kfio, KEYFILEIO_MAGIC)
    128 
    129 /*%
    130  * Ensure 'a' is at least 'min' but not more than 'max'.
    131  */
    132 #define RANGE(a, min, max) (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
    133 
    134 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
    135 
    136 /*%
    137  * Key flags
    138  */
    139 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
    140 #define KSK(x)	  ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
    141 #define ID(x)	  dst_key_id(x)
    142 #define ALG(x)	  dst_key_alg(x)
    143 
    144 /*%
    145  * KASP flags
    146  */
    147 #define KASP_LOCK(k)                \
    148 	if ((k) != NULL) {          \
    149 		LOCK(&((k)->lock)); \
    150 	}
    151 
    152 #define KASP_UNLOCK(k)                \
    153 	if ((k) != NULL) {            \
    154 		UNLOCK(&((k)->lock)); \
    155 	}
    156 
    157 /*
    158  * Default values.
    159  */
    160 #define DNS_DEFAULT_IDLEIN  3600       /*%< 1 hour */
    161 #define DNS_DEFAULT_IDLEOUT 3600       /*%< 1 hour */
    162 #define MAX_XFER_TIME	    (2 * 3600) /*%< Documented default is 2 hours */
    163 #define RESIGN_DELAY	    3600       /*%< 1 hour */
    164 
    165 #ifndef DNS_MAX_EXPIRE
    166 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
    167 #endif				/* ifndef DNS_MAX_EXPIRE */
    168 
    169 #ifndef DNS_DUMP_DELAY
    170 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
    171 #endif			   /* ifndef DNS_DUMP_DELAY */
    172 
    173 typedef struct dns_notify dns_notify_t;
    174 typedef struct dns_checkds dns_checkds_t;
    175 typedef struct dns_stub dns_stub_t;
    176 typedef struct dns_load dns_load_t;
    177 typedef struct dns_forward dns_forward_t;
    178 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
    179 typedef struct dns_keymgmt dns_keymgmt_t;
    180 typedef struct dns_signing dns_signing_t;
    181 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
    182 typedef struct dns_nsec3chain dns_nsec3chain_t;
    183 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
    184 typedef struct dns_nsfetch dns_nsfetch_t;
    185 typedef struct dns_keyfetch dns_keyfetch_t;
    186 typedef struct dns_asyncload dns_asyncload_t;
    187 typedef struct dns_include dns_include_t;
    188 
    189 #define DNS_ZONE_CHECKLOCK
    190 #ifdef DNS_ZONE_CHECKLOCK
    191 #define LOCK_ZONE(z)                  \
    192 	do {                          \
    193 		LOCK(&(z)->lock);     \
    194 		INSIST(!(z)->locked); \
    195 		(z)->locked = true;   \
    196 	} while (0)
    197 #define UNLOCK_ZONE(z)               \
    198 	do {                         \
    199 		INSIST((z)->locked); \
    200 		(z)->locked = false; \
    201 		UNLOCK(&(z)->lock);  \
    202 	} while (0)
    203 #define LOCKED_ZONE(z) ((z)->locked)
    204 #define TRYLOCK_ZONE(result, z)                         \
    205 	do {                                            \
    206 		result = isc_mutex_trylock(&(z)->lock); \
    207 		if (result == ISC_R_SUCCESS) {          \
    208 			INSIST(!(z)->locked);           \
    209 			(z)->locked = true;             \
    210 		}                                       \
    211 	} while (0)
    212 #else /* ifdef DNS_ZONE_CHECKLOCK */
    213 #define LOCK_ZONE(z)   LOCK(&(z)->lock)
    214 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
    215 #define LOCKED_ZONE(z) true
    216 #define TRYLOCK_ZONE(result, z)                         \
    217 	do {                                            \
    218 		result = isc_mutex_trylock(&(z)->lock); \
    219 	} while (0)
    220 #endif /* ifdef DNS_ZONE_CHECKLOCK */
    221 
    222 #define ZONEDB_INITLOCK(l)    isc_rwlock_init(l)
    223 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
    224 #define ZONEDB_LOCK(l, t)     RWLOCK((l), (t))
    225 #define ZONEDB_UNLOCK(l, t)   RWUNLOCK((l), (t))
    226 
    227 #ifdef ENABLE_AFL
    228 extern bool dns_fuzzing_resolver;
    229 #endif /* ifdef ENABLE_AFL */
    230 
    231 /*%
    232  *	Hold key file IO locks.
    233  */
    234 typedef struct dns_keyfileio {
    235 	unsigned int magic;
    236 	isc_mutex_t lock;
    237 	isc_refcount_t references;
    238 	dns_name_t *name;
    239 	dns_fixedname_t fname;
    240 } dns_keyfileio_t;
    241 
    242 struct dns_keymgmt {
    243 	unsigned int magic;
    244 	isc_rwlock_t lock;
    245 	isc_mem_t *mctx;
    246 	isc_hashmap_t *table;
    247 };
    248 
    249 /*
    250  * Initial size of the keymgmt hash table.
    251  */
    252 #define DNS_KEYMGMT_HASH_BITS 12
    253 
    254 struct dns_zone {
    255 	/* Unlocked */
    256 	unsigned int magic;
    257 	isc_mutex_t lock;
    258 #ifndef _LP64
    259 	isc_mutex_t atomic_lock;
    260 #endif
    261 #ifdef DNS_ZONE_CHECKLOCK
    262 	bool locked;
    263 #endif /* ifdef DNS_ZONE_CHECKLOCK */
    264 	isc_mem_t *mctx;
    265 	isc_refcount_t references;
    266 
    267 	isc_rwlock_t dblock;
    268 	dns_db_t *db; /* Locked by dblock */
    269 
    270 	unsigned int tid;
    271 
    272 	/* Locked */
    273 	dns_zonemgr_t *zmgr;
    274 	ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
    275 	isc_loop_t *loop;
    276 	isc_timer_t *timer;
    277 	isc_refcount_t irefs;
    278 	dns_name_t origin;
    279 	char *masterfile;
    280 	const FILE *stream;		     /* loading from a stream? */
    281 	ISC_LIST(dns_include_t) includes;    /* Include files */
    282 	ISC_LIST(dns_include_t) newincludes; /* Loading */
    283 	unsigned int nincludes;
    284 	dns_masterformat_t masterformat;
    285 	const dns_master_style_t *masterstyle;
    286 	char *journal;
    287 	int32_t journalsize;
    288 	dns_rdataclass_t rdclass;
    289 	dns_zonetype_t type;
    290 #ifdef _LP64
    291 	atomic_uint_fast64_t flags;
    292 	atomic_uint_fast64_t options;
    293 #else
    294 	uint64_t flags;
    295 	uint64_t options;
    296 #endif
    297 	unsigned int db_argc;
    298 	char **db_argv;
    299 	isc_time_t expiretime;
    300 	isc_time_t refreshtime;
    301 	isc_time_t dumptime;
    302 	isc_time_t loadtime;
    303 	isc_time_t notifytime;
    304 	isc_time_t resigntime;
    305 	isc_time_t keywarntime;
    306 	isc_time_t signingtime;
    307 	isc_time_t nsec3chaintime;
    308 	isc_time_t refreshkeytime;
    309 	isc_time_t xfrintime;
    310 	uint32_t refreshkeyinterval;
    311 	uint32_t refreshkeycount;
    312 	uint32_t refresh;
    313 	uint32_t retry;
    314 	uint32_t expire;
    315 	uint32_t minimum;
    316 	isc_stdtime_t key_expiry;
    317 	isc_stdtime_t log_key_expired_timer;
    318 	char *keydirectory;
    319 	dns_keyfileio_t *kfio;
    320 	dns_keystorelist_t *keystores;
    321 	dns_xfrin_t *xfr;
    322 
    323 	uint32_t maxrefresh;
    324 	uint32_t minrefresh;
    325 	uint32_t maxretry;
    326 	uint32_t minretry;
    327 
    328 	uint32_t maxrecords;
    329 	uint32_t maxrrperset;
    330 	uint32_t maxtypepername;
    331 
    332 	dns_remote_t primaries;
    333 
    334 	dns_remote_t parentals;
    335 	dns_dnsseckeylist_t checkds_ok;
    336 	dns_checkdstype_t checkdstype;
    337 	uint32_t nsfetchcount;
    338 	uint32_t parent_nscount;
    339 
    340 	dns_remote_t notify;
    341 	dns_notifytype_t notifytype;
    342 	isc_sockaddr_t notifyfrom;
    343 	isc_sockaddr_t notifysrc4;
    344 	isc_sockaddr_t notifysrc6;
    345 	isc_sockaddr_t parentalsrc4;
    346 	isc_sockaddr_t parentalsrc6;
    347 	isc_sockaddr_t xfrsource4;
    348 	isc_sockaddr_t xfrsource6;
    349 	isc_sockaddr_t sourceaddr;
    350 	dns_tsigkey_t *tsigkey;	    /* key used for xfr */
    351 	dns_transport_t *transport; /* transport used for xfr */
    352 	/* Access Control Lists */
    353 	dns_acl_t *update_acl;
    354 	dns_acl_t *forward_acl;
    355 	dns_acl_t *notify_acl;
    356 	dns_acl_t *query_acl;
    357 	dns_acl_t *queryon_acl;
    358 	dns_acl_t *xfr_acl;
    359 	bool update_disabled;
    360 	bool zero_no_soa_ttl;
    361 	dns_severity_t check_names;
    362 	ISC_LIST(dns_notify_t) notifies;
    363 	ISC_LIST(dns_checkds_t) checkds_requests;
    364 	dns_request_t *request;
    365 	dns_loadctx_t *loadctx;
    366 	dns_dumpctx_t *dumpctx;
    367 	uint32_t minxfrratebytesin;
    368 	uint32_t minxfrratesecondsin;
    369 	uint32_t maxxfrin;
    370 	uint32_t maxxfrout;
    371 	uint32_t idlein;
    372 	uint32_t idleout;
    373 	dns_ssutable_t *ssutable;
    374 	uint32_t sigvalidityinterval;
    375 	uint32_t keyvalidityinterval;
    376 	uint32_t sigresigninginterval;
    377 	dns_view_t *view;
    378 	dns_view_t *prev_view;
    379 	dns_kasp_t *kasp;
    380 	dns_kasp_t *defaultkasp;
    381 	dns_dnsseckeylist_t keyring;
    382 	dns_checkmxfunc_t checkmx;
    383 	dns_checksrvfunc_t checksrv;
    384 	dns_checknsfunc_t checkns;
    385 	/*%
    386 	 * Zones in certain states such as "waiting for zone transfer"
    387 	 * or "zone transfer in progress" are kept on per-state linked lists
    388 	 * in the zone manager using the 'statelink' field.  The 'statelist'
    389 	 * field points at the list the zone is currently on.  It the zone
    390 	 * is not on any such list, statelist is NULL.
    391 	 */
    392 	ISC_LINK(dns_zone_t) statelink;
    393 	dns_zonelist_t *statelist;
    394 	/*%
    395 	 * Statistics counters about zone management.
    396 	 */
    397 	isc_stats_t *stats;
    398 	/*%
    399 	 * Optional per-zone statistics counters.  Counted outside of this
    400 	 * module.
    401 	 */
    402 	dns_zonestat_level_t statlevel;
    403 	bool requeststats_on;
    404 	isc_stats_t *requeststats;
    405 	dns_stats_t *rcvquerystats;
    406 	dns_stats_t *dnssecsignstats;
    407 	uint32_t notifydelay;
    408 	uint32_t notifydefer;
    409 	dns_isselffunc_t isself;
    410 	void *isselfarg;
    411 
    412 	char *strnamerd;
    413 	char *strname;
    414 	char *strrdclass;
    415 	char *strviewname;
    416 
    417 	/*%
    418 	 * Serial number for deferred journal compaction.
    419 	 */
    420 	uint32_t compact_serial;
    421 	/*%
    422 	 * Keys that are signing the zone for the first time.
    423 	 */
    424 	dns_signinglist_t signing;
    425 	dns_nsec3chainlist_t nsec3chain;
    426 	/*%
    427 	 * List of outstanding NSEC3PARAM change requests.
    428 	 */
    429 	ISC_LIST(struct np3) setnsec3param_queue;
    430 	/*%
    431 	 * Signing / re-signing quantum stopping parameters.
    432 	 */
    433 	uint32_t signatures;
    434 	uint32_t nodes;
    435 	dns_rdatatype_t privatetype;
    436 
    437 	/*%
    438 	 * Autosigning/key-maintenance options
    439 	 */
    440 #ifdef _LP64
    441 	atomic_uint_fast64_t keyopts;
    442 #else
    443 	uint64_t keyopts;
    444 #endif
    445 
    446 	/*%
    447 	 * True if added by "rndc addzone"
    448 	 */
    449 	bool added;
    450 
    451 	/*%
    452 	 * True if added by automatically by named.
    453 	 */
    454 	bool automatic;
    455 
    456 	/*%
    457 	 * response policy data to be relayed to the database
    458 	 */
    459 	dns_rpz_zones_t *rpzs;
    460 	dns_rpz_num_t rpz_num;
    461 
    462 	/*%
    463 	 * catalog zone data
    464 	 */
    465 	dns_catz_zones_t *catzs;
    466 
    467 	/*%
    468 	 * parent catalog zone
    469 	 */
    470 	dns_catz_zone_t *parentcatz;
    471 
    472 	/*%
    473 	 * Serial number update method.
    474 	 */
    475 	dns_updatemethod_t updatemethod;
    476 
    477 	/*%
    478 	 * whether ixfr is requested
    479 	 */
    480 	bool requestixfr;
    481 	uint32_t ixfr_ratio;
    482 
    483 	/*%
    484 	 * whether EDNS EXPIRE is requested
    485 	 */
    486 	bool requestexpire;
    487 
    488 	/*%
    489 	 * Outstanding forwarded UPDATE requests.
    490 	 */
    491 	dns_forwardlist_t forwards;
    492 
    493 	dns_zone_t *raw;
    494 	dns_zone_t *secure;
    495 
    496 	bool sourceserialset;
    497 	uint32_t sourceserial;
    498 
    499 	/*%
    500 	 * soa and maximum zone ttl
    501 	 */
    502 	dns_ttl_t soattl;
    503 	dns_ttl_t maxttl;
    504 
    505 	/*
    506 	 * Inline zone signing state.
    507 	 */
    508 	dns_diff_t rss_diff;
    509 	dns_dbversion_t *rss_newver;
    510 	dns_dbversion_t *rss_oldver;
    511 	dns_db_t *rss_db;
    512 	dns_zone_t *rss_raw;
    513 	struct rss *rss;
    514 	dns_update_state_t *rss_state;
    515 
    516 	isc_stats_t *gluecachestats;
    517 
    518 	/*%
    519 	 * Offline KSK signed key responses.
    520 	 */
    521 	dns_skr_t *skr;
    522 	dns_skrbundle_t *skrbundle;
    523 };
    524 
    525 #define zonediff_init(z, d)                \
    526 	do {                               \
    527 		dns__zonediff_t *_z = (z); \
    528 		(_z)->diff = (d);          \
    529 		(_z)->offline = false;     \
    530 	} while (0)
    531 #ifdef _LP64
    532 #define ISC_ZONE_GET(z, f) atomic_load_relaxed(&(z)->f)
    533 #define ISC_ZONE_SET(z, f, o) atomic_fetch_or(&(z)->f, (o))
    534 #define ISC_ZONE_CLR(z, f, o) atomic_fetch_and(&(z)->f, ~(o))
    535 #else
    536 #define ISC_ZONE_GET(z, f) \
    537 	({ \
    538 		isc_mutex_lock(&(z)->atomic_lock); \
    539 		uint64_t x = (z)->f; \
    540 		isc_mutex_unlock(&(z)->atomic_lock); \
    541 		x; \
    542 	})
    543 #define ISC_ZONE_SET(z, f, o) \
    544 	({ \
    545 		isc_mutex_lock(&(z)->atomic_lock); \
    546 		uint64_t x = ((z)->f | (o)); \
    547 		isc_mutex_unlock(&(z)->atomic_lock); \
    548 		x; \
    549 	})
    550 #define ISC_ZONE_CLR(z, f, o) \
    551 	({ \
    552 		isc_mutex_lock(&(z)->atomic_lock); \
    553 		uint64_t x = ((z)->f & ~(o)); \
    554 		isc_mutex_unlock(&(z)->atomic_lock); \
    555 		x; \
    556 	})
    557 #endif
    558 #define ISC_ZONE_TEST(z, f, o) ((ISC_ZONE_GET(z, f) & (o)) != 0)
    559 
    560 #define DNS_ZONE_FLAG(z, f)    ISC_ZONE_TEST(z, flags, f)
    561 #define DNS_ZONE_SETFLAG(z, f) ISC_ZONE_SET(z, flags, f)
    562 #define DNS_ZONE_CLRFLAG(z, f) ISC_ZONE_CLR(z, flags, f)
    563 typedef enum {
    564 	DNS_ZONEFLG_REFRESH = 0x00000001U,     /*%< refresh check in progress */
    565 	DNS_ZONEFLG_NEEDDUMP = 0x00000002U,    /*%< zone need consolidation */
    566 	DNS_ZONEFLG_USEVC = 0x00000004U,       /*%< use tcp for refresh query */
    567 	DNS_ZONEFLG_DUMPING = 0x00000008U,     /*%< a dump is in progress */
    568 	DNS_ZONEFLG_HASINCLUDE = 0x00000010U,  /*%< $INCLUDE in zone file */
    569 	DNS_ZONEFLG_LOADED = 0x00000020U,      /*%< database has loaded */
    570 	DNS_ZONEFLG_EXITING = 0x00000040U,     /*%< zone is being destroyed */
    571 	DNS_ZONEFLG_EXPIRED = 0x00000080U,     /*%< zone has expired */
    572 	DNS_ZONEFLG_NEEDREFRESH = 0x00000100U, /*%< refresh check needed */
    573 	DNS_ZONEFLG_UPTODATE = 0x00000200U,    /*%< zone contents are
    574 						* up-to-date */
    575 	DNS_ZONEFLG_NEEDNOTIFY = 0x00000400U,  /*%< need to send out notify
    576 						* messages */
    577 	DNS_ZONEFLG_FIXJOURNAL = 0x00000800U,  /*%< journal file had
    578 						* recoverable error,
    579 						* needs rewriting */
    580 	DNS_ZONEFLG_NOPRIMARIES = 0x00001000U, /*%< an attempt to refresh a
    581 						* zone with no primaries
    582 						* occurred */
    583 	DNS_ZONEFLG_LOADING = 0x00002000U,     /*%< load from disk in progress*/
    584 	DNS_ZONEFLG_HAVETIMERS = 0x00004000U,  /*%< timer values have been set
    585 						* from SOA (if not set, we
    586 						* are still using
    587 						* default timer values) */
    588 	DNS_ZONEFLG_FORCEXFER = 0x00008000U,   /*%< Force a zone xfer */
    589 	DNS_ZONEFLG_NOREFRESH = 0x00010000U,
    590 	DNS_ZONEFLG_DIALNOTIFY = 0x00020000U,
    591 	DNS_ZONEFLG_DIALREFRESH = 0x00040000U,
    592 	DNS_ZONEFLG_SHUTDOWN = 0x00080000U,
    593 	DNS_ZONEFLG_NOIXFR = 0x00100000U, /*%< IXFR failed, force AXFR */
    594 	DNS_ZONEFLG_FLUSH = 0x00200000U,
    595 	DNS_ZONEFLG_NOEDNS = 0x00400000U,
    596 	DNS_ZONEFLG_USEALTXFRSRC = 0x00800000U, /*%< Obsoleted. */
    597 	DNS_ZONEFLG_SOABEFOREAXFR = 0x01000000U,
    598 	DNS_ZONEFLG_NEEDCOMPACT = 0x02000000U,
    599 	DNS_ZONEFLG_REFRESHING = 0x04000000U, /*%< Refreshing keydata */
    600 	DNS_ZONEFLG_THAW = 0x08000000U,
    601 	DNS_ZONEFLG_LOADPENDING = 0x10000000U, /*%< Loading scheduled */
    602 	DNS_ZONEFLG_NODELAY = 0x20000000U,
    603 	DNS_ZONEFLG_SENDSECURE = 0x40000000U,
    604 	DNS_ZONEFLG_NEEDSTARTUPNOTIFY = 0x80000000U, /*%< need to send out
    605 						      * notify due to the zone
    606 						      * just being loaded for
    607 						      * the first time. */
    608 	DNS_ZONEFLG_NOTIFYNODEFER = 0x100000000U,    /*%< ignore the
    609 						      * notify-defer option. */
    610 	DNS_ZONEFLG_NOTIFYDEFERRED = 0x200000000U,   /*%< notify was deferred
    611 						      * according to the
    612 						      * notify-defer option. */
    613 	DNS_ZONEFLG_FIRSTREFRESH = 0x400000000U, /*%< First refresh pending */
    614 	DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
    615 } dns_zoneflg_t;
    616 
    617 #define DNS_ZONE_OPTION(z, o)		ISC_ZONE_TEST(z, options, o)
    618 #define DNS_ZONE_SETOPTION(z, o)	ISC_ZONE_SET(z, options, o)
    619 #define DNS_ZONE_CLROPTION(z, o)	ISC_ZONE_CLR(z, options, o)
    620 #define DNS_ZONEKEY_OPTION(z, o)	ISC_ZONE_TEST(z, keyopts, o)
    621 #define DNS_ZONEKEY_SETOPTION(z, o)	ISC_ZONE_SET(z, keyopts, o)
    622 #define DNS_ZONEKEY_CLROPTION(z, o)	ISC_ZONE_CLR(z, keyopts, o)
    623 
    624 /* Flags for zone_load() */
    625 typedef enum {
    626 	DNS_ZONELOADFLAG_NOSTAT = 0x00000001U, /* Do not stat() master files */
    627 	DNS_ZONELOADFLAG_THAW = 0x00000002U,   /* Thaw the zone on successful
    628 						* load. */
    629 } dns_zoneloadflag_t;
    630 
    631 #define UNREACH_CACHE_SIZE 10U
    632 #define UNREACH_HOLD_TIME  600 /* 10 minutes */
    633 
    634 struct dns_unreachable {
    635 	isc_sockaddr_t remote;
    636 	isc_sockaddr_t local;
    637 	atomic_uint_fast32_t expire;
    638 	atomic_uint_fast32_t last;
    639 	uint32_t count;
    640 };
    641 
    642 struct dns_zonemgr {
    643 	unsigned int magic;
    644 	isc_mem_t *mctx;
    645 	isc_refcount_t refs;
    646 	isc_loopmgr_t *loopmgr;
    647 	isc_nm_t *netmgr;
    648 	uint32_t workers;
    649 	isc_mem_t **mctxpool;
    650 	isc_ratelimiter_t *checkdsrl;
    651 	isc_ratelimiter_t *notifyrl;
    652 	isc_ratelimiter_t *refreshrl;
    653 	isc_ratelimiter_t *startupnotifyrl;
    654 	isc_ratelimiter_t *startuprefreshrl;
    655 	isc_rwlock_t rwlock;
    656 	isc_rwlock_t urlock;
    657 
    658 	/* Locked by rwlock. */
    659 	dns_zonelist_t zones;
    660 	dns_zonelist_t waiting_for_xfrin;
    661 	dns_zonelist_t xfrin_in_progress;
    662 
    663 	/* Configuration data. */
    664 	uint32_t transfersin;
    665 	uint32_t transfersperns;
    666 	unsigned int checkdsrate;
    667 	unsigned int notifyrate;
    668 	unsigned int startupnotifyrate;
    669 	unsigned int serialqueryrate;
    670 	unsigned int startupserialqueryrate;
    671 
    672 	/* Locked by urlock. */
    673 	/* LRU cache */
    674 	struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
    675 
    676 	dns_keymgmt_t *keymgmt;
    677 
    678 	isc_tlsctx_cache_t *tlsctx_cache;
    679 	isc_rwlock_t tlsctx_cache_rwlock;
    680 };
    681 
    682 /*%
    683  * Hold notify state.
    684  */
    685 struct dns_notify {
    686 	unsigned int magic;
    687 	unsigned int flags;
    688 	isc_mem_t *mctx;
    689 	dns_zone_t *zone;
    690 	dns_adbfind_t *find;
    691 	dns_request_t *request;
    692 	dns_name_t ns;
    693 	isc_sockaddr_t src;
    694 	isc_sockaddr_t dst;
    695 	dns_tsigkey_t *key;
    696 	dns_transport_t *transport;
    697 	ISC_LINK(dns_notify_t) link;
    698 	isc_rlevent_t *rlevent;
    699 };
    700 
    701 typedef enum dns_notify_flags {
    702 	DNS_NOTIFY_NOSOA = 1 << 0,
    703 	DNS_NOTIFY_STARTUP = 1 << 1,
    704 	DNS_NOTIFY_TCP = 1 << 2,
    705 } dns_notify_flags_t;
    706 
    707 /*%
    708  * Hold checkds state.
    709  */
    710 struct dns_checkds {
    711 	unsigned int magic;
    712 	dns_notify_flags_t flags;
    713 	isc_mem_t *mctx;
    714 	dns_zone_t *zone;
    715 	dns_adbfind_t *find;
    716 	dns_request_t *request;
    717 	dns_name_t ns;
    718 	isc_sockaddr_t src;
    719 	isc_sockaddr_t dst;
    720 	dns_tsigkey_t *key;
    721 	dns_transport_t *transport;
    722 	ISC_LINK(dns_checkds_t) link;
    723 	isc_rlevent_t *rlevent;
    724 };
    725 
    726 /*%
    727  *	dns_stub holds state while performing a 'stub' transfer.
    728  *	'db' is the zone's 'db' or a new one if this is the initial
    729  *	transfer.
    730  */
    731 
    732 struct dns_stub {
    733 	unsigned int magic;
    734 	isc_mem_t *mctx;
    735 	dns_zone_t *zone;
    736 	dns_db_t *db;
    737 	dns_dbversion_t *version;
    738 	atomic_uint_fast32_t pending_requests;
    739 };
    740 
    741 /*%
    742  *	Hold load state.
    743  */
    744 struct dns_load {
    745 	dns_zone_t *zone;
    746 	dns_db_t *db;
    747 	isc_time_t loadtime;
    748 	dns_rdatacallbacks_t callbacks;
    749 };
    750 
    751 /*%
    752  *	Hold forward state.
    753  */
    754 struct dns_forward {
    755 	unsigned int magic;
    756 	isc_mem_t *mctx;
    757 	dns_zone_t *zone;
    758 	isc_buffer_t *msgbuf;
    759 	dns_request_t *request;
    760 	uint32_t which;
    761 	isc_sockaddr_t addr;
    762 	dns_transport_t *transport;
    763 	dns_updatecallback_t callback;
    764 	void *callback_arg;
    765 	unsigned int options;
    766 	ISC_LINK(dns_forward_t) link;
    767 };
    768 
    769 /*%
    770  *	Hold state for when we are signing a zone with a new
    771  *	DNSKEY as result of an update.
    772  */
    773 struct dns_signing {
    774 	unsigned int magic;
    775 	dns_db_t *db;
    776 	dns_dbiterator_t *dbiterator;
    777 	dns_secalg_t algorithm;
    778 	uint16_t keyid;
    779 	bool deleteit;
    780 	bool fullsign;
    781 	bool done;
    782 	ISC_LINK(dns_signing_t) link;
    783 };
    784 
    785 struct dns_nsec3chain {
    786 	unsigned int magic;
    787 	dns_db_t *db;
    788 	dns_dbiterator_t *dbiterator;
    789 	dns_rdata_nsec3param_t nsec3param;
    790 	unsigned char salt[255];
    791 	bool done;
    792 	bool seen_nsec;
    793 	bool delete_nsec;
    794 	bool save_delete_nsec;
    795 	ISC_LINK(dns_nsec3chain_t) link;
    796 };
    797 
    798 /*%<
    799  * 'dbiterator' contains a iterator for the database.  If we are creating
    800  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
    801  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
    802  * iterated.
    803  *
    804  * 'nsec3param' contains the parameters of the NSEC3 chain being created
    805  * or removed.
    806  *
    807  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
    808  *
    809  * 'seen_nsec' will be set to true if, while iterating the zone to create a
    810  * NSEC3 chain, a NSEC record is seen.
    811  *
    812  * 'delete_nsec' will be set to true if, at the completion of the creation
    813  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
    814  * are in the process of deleting the NSEC chain.
    815  *
    816  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
    817  * so it can be recovered in the event of a error.
    818  */
    819 
    820 struct dns_keyfetch {
    821 	isc_mem_t *mctx;
    822 	dns_fixedname_t name;
    823 	dns_rdataset_t keydataset;
    824 	dns_rdataset_t dnskeyset;
    825 	dns_rdataset_t dnskeysigset;
    826 	dns_zone_t *zone;
    827 	dns_db_t *db;
    828 	dns_fetch_t *fetch;
    829 };
    830 
    831 struct dns_nsfetch {
    832 	isc_mem_t *mctx;
    833 	dns_fixedname_t name;
    834 	dns_name_t pname;
    835 	dns_rdataset_t nsrrset;
    836 	dns_rdataset_t nssigset;
    837 	dns_zone_t *zone;
    838 	dns_fetch_t *fetch;
    839 };
    840 
    841 /*%
    842  * Hold state for an asynchronous load
    843  */
    844 struct dns_asyncload {
    845 	dns_zone_t *zone;
    846 	unsigned int flags;
    847 	dns_zt_callback_t *loaded;
    848 	void *loaded_arg;
    849 };
    850 
    851 /*%
    852  * Reference to an include file encountered during loading
    853  */
    854 struct dns_include {
    855 	char *name;
    856 	isc_time_t filetime;
    857 	ISC_LINK(dns_include_t) link;
    858 };
    859 
    860 /*
    861  * These can be overridden by the -T mkeytimers option on the command
    862  * line, so that we can test with shorter periods than specified in
    863  * RFC 5011.
    864  */
    865 #define HOUR  3600
    866 #define DAY   (24 * HOUR)
    867 #define MONTH (30 * DAY)
    868 unsigned int dns_zone_mkey_hour = HOUR;
    869 unsigned int dns_zone_mkey_day = DAY;
    870 unsigned int dns_zone_mkey_month = MONTH;
    871 
    872 #define SEND_BUFFER_SIZE 2048
    873 
    874 static void
    875 zone_timer_set(dns_zone_t *zone, isc_time_t *next, isc_time_t *now);
    876 
    877 typedef struct zone_settimer {
    878 	dns_zone_t *zone;
    879 	isc_time_t now;
    880 } zone_settimer_t;
    881 
    882 static void
    883 zone_settimer(dns_zone_t *, isc_time_t *);
    884 static void
    885 cancel_refresh(dns_zone_t *);
    886 static void
    887 zone_debuglogc(dns_zone_t *zone, isc_logcategory_t *category, const char *me,
    888 	       int debuglevel, const char *fmt, ...);
    889 static void
    890 zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg,
    891 	      ...) ISC_FORMAT_PRINTF(4, 5);
    892 static void
    893 notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
    894 	ISC_FORMAT_PRINTF(3, 4);
    895 static void
    896 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
    897 	ISC_FORMAT_PRINTF(3, 4);
    898 static void
    899 queue_xfrin(dns_zone_t *zone);
    900 static isc_result_t
    901 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
    902 	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
    903 	      dns_rdata_t *rdata);
    904 static void
    905 zone_unload(dns_zone_t *zone);
    906 static void
    907 zone_expire(dns_zone_t *zone);
    908 static void
    909 zone_refresh(dns_zone_t *zone);
    910 static void
    911 zone_iattach(dns_zone_t *source, dns_zone_t **target);
    912 static void
    913 zone_idetach(dns_zone_t **zonep);
    914 static isc_result_t
    915 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump);
    916 static void
    917 zone_attachdb(dns_zone_t *zone, dns_db_t *db);
    918 static void
    919 zone_detachdb(dns_zone_t *zone);
    920 static void
    921 zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs);
    922 static void
    923 zone_catz_disable(dns_zone_t *zone);
    924 static isc_result_t
    925 default_journal(dns_zone_t *zone);
    926 static void
    927 zone_xfrdone(dns_zone_t *zone, uint32_t *expireopt, isc_result_t result);
    928 static isc_result_t
    929 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
    930 	      isc_result_t result);
    931 static void
    932 zone_needdump(dns_zone_t *zone, unsigned int delay);
    933 static void
    934 zone_shutdown(void *arg);
    935 static void
    936 zone_loaddone(void *arg, isc_result_t result);
    937 static isc_result_t
    938 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime);
    939 static void
    940 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
    941 static void
    942 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
    943 static void
    944 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
    945 static void
    946 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
    947 static isc_result_t
    948 zone_send_secureserial(dns_zone_t *zone, uint32_t serial);
    949 static void
    950 refresh_callback(void *arg);
    951 static void
    952 stub_callback(void *arg);
    953 static void
    954 queue_soa_query(dns_zone_t *zone);
    955 static void
    956 soa_query(void *arg);
    957 static void
    958 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub);
    959 static int
    960 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type);
    961 static void
    962 checkds_cancel(dns_zone_t *zone);
    963 static void
    964 checkds_find_address(dns_checkds_t *checkds);
    965 static void
    966 checkds_send(dns_zone_t *zone);
    967 static void
    968 checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep);
    969 static void
    970 checkds_done(void *arg);
    971 static void
    972 checkds_send_tons(dns_checkds_t *checkds);
    973 static void
    974 checkds_send_toaddr(void *arg);
    975 static void
    976 nsfetch_levelup(dns_nsfetch_t *nsfetch);
    977 static void
    978 notify_cancel(dns_zone_t *zone);
    979 static void
    980 notify_find_address(dns_notify_t *notify);
    981 static void
    982 notify_send(dns_notify_t *notify);
    983 static isc_result_t
    984 notify_createmessage(dns_zone_t *zone, unsigned int flags,
    985 		     dns_message_t **messagep);
    986 static void
    987 notify_done(void *arg);
    988 static void
    989 notify_send_toaddr(void *arg);
    990 static isc_result_t
    991 zone_dump(dns_zone_t *, bool);
    992 static void
    993 got_transfer_quota(void *arg);
    994 static isc_result_t
    995 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone);
    996 static void
    997 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
    998 static void
    999 zonemgr_free(dns_zonemgr_t *zmgr);
   1000 static void
   1001 rss_post(void *arg);
   1002 
   1003 static isc_result_t
   1004 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
   1005 		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
   1006 		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
   1007 		 uint32_t *minimum, unsigned int *errors);
   1008 
   1009 static void
   1010 zone_freedbargs(dns_zone_t *zone);
   1011 static void
   1012 forward_callback(void *arg);
   1013 static void
   1014 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat);
   1015 static void
   1016 zone_maintenance(dns_zone_t *zone);
   1017 static void
   1018 zone_notify(dns_zone_t *zone, isc_time_t *now);
   1019 static void
   1020 dump_done(void *arg, isc_result_t result);
   1021 static isc_result_t
   1022 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
   1023 		 bool deleteit, bool fullsign);
   1024 static isc_result_t
   1025 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
   1026 	    dns_name_t *name, dns_diff_t *diff);
   1027 static void
   1028 zone_rekey(dns_zone_t *zone);
   1029 static isc_result_t
   1030 zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
   1031 static dns_ttl_t
   1032 zone_nsecttl(dns_zone_t *zone);
   1033 static void
   1034 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value);
   1035 static void
   1036 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial);
   1037 static isc_result_t
   1038 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
   1039 			 bool *fixjournal);
   1040 static void
   1041 setnsec3param(void *arg);
   1042 
   1043 static void
   1044 zmgr_tlsctx_attach(dns_zonemgr_t *zmgr, isc_tlsctx_cache_t **ptlsctx_cache);
   1045 /*%<
   1046  *	Attach to TLS client context cache used for zone transfers via
   1047  *	encrypted transports (e.g. XoT).
   1048  *
   1049  * The obtained reference needs to be detached by a call to
   1050  * 'isc_tlsctx_cache_detach()' when not needed anymore.
   1051  *
   1052  * Requires:
   1053  *\li	'zmgr' is a valid zone manager.
   1054  *\li	'ptlsctx_cache' is not 'NULL' and points to 'NULL'.
   1055  */
   1056 
   1057 #define ENTER zone_debuglog(zone, __func__, 1, "enter")
   1058 
   1059 static const unsigned int dbargc_default = 1;
   1060 static const char *dbargv_default[] = { ZONEDB_DEFAULT };
   1061 
   1062 #define DNS_ZONE_JITTER_ADD(a, b, c)                                         \
   1063 	do {                                                                 \
   1064 		isc_interval_t _i;                                           \
   1065 		uint32_t _j;                                                 \
   1066 		_j = (b) - isc_random_uniform((b) / 4);                      \
   1067 		isc_interval_set(&_i, _j, 0);                                \
   1068 		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) {          \
   1069 			dns_zone_log(zone, ISC_LOG_WARNING,                  \
   1070 				     "epoch approaching: upgrade required: " \
   1071 				     "now + %s failed",                      \
   1072 				     #b);                                    \
   1073 			isc_interval_set(&_i, _j / 2, 0);                    \
   1074 			(void)isc_time_add((a), &_i, (c));                   \
   1075 		}                                                            \
   1076 	} while (0)
   1077 
   1078 #define DNS_ZONE_TIME_ADD(a, b, c)                                           \
   1079 	do {                                                                 \
   1080 		isc_interval_t _i;                                           \
   1081 		isc_interval_set(&_i, (b), 0);                               \
   1082 		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) {          \
   1083 			dns_zone_log(zone, ISC_LOG_WARNING,                  \
   1084 				     "epoch approaching: upgrade required: " \
   1085 				     "now + %s failed",                      \
   1086 				     #b);                                    \
   1087 			isc_interval_set(&_i, (b) / 2, 0);                   \
   1088 			(void)isc_time_add((a), &_i, (c));                   \
   1089 		}                                                            \
   1090 	} while (0)
   1091 
   1092 #define DNS_ZONE_TIME_SUBTRACT(a, b, c)                                      \
   1093 	do {                                                                 \
   1094 		isc_interval_t _i;                                           \
   1095 		isc_interval_set(&_i, (b), 0);                               \
   1096 		if (isc_time_subtract((a), &_i, (c)) != ISC_R_SUCCESS) {     \
   1097 			dns_zone_log(zone, ISC_LOG_WARNING,                  \
   1098 				     "epoch approaching: upgrade required: " \
   1099 				     "isc_time_subtract() failed");          \
   1100 			isc_interval_set(&_i, (b) / 2, 0);                   \
   1101 			(void)isc_time_subtract((a), &_i, (c));              \
   1102 		}                                                            \
   1103 	} while (0)
   1104 
   1105 typedef struct nsec3param nsec3param_t;
   1106 struct nsec3param {
   1107 	dns_rdata_nsec3param_t rdata;
   1108 	unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
   1109 	unsigned int length;
   1110 	bool nsec;
   1111 	bool replace;
   1112 	bool resalt;
   1113 	bool lookup;
   1114 	ISC_LINK(nsec3param_t) link;
   1115 };
   1116 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
   1117 
   1118 struct np3 {
   1119 	dns_zone_t *zone;
   1120 	nsec3param_t params;
   1121 	ISC_LINK(struct np3) link;
   1122 };
   1123 
   1124 struct setserial {
   1125 	dns_zone_t *zone;
   1126 	uint32_t serial;
   1127 };
   1128 
   1129 struct stub_cb_args {
   1130 	dns_stub_t *stub;
   1131 	dns_tsigkey_t *tsig_key;
   1132 	uint16_t udpsize;
   1133 	int timeout;
   1134 	bool reqnsid;
   1135 };
   1136 
   1137 struct stub_glue_request {
   1138 	dns_request_t *request;
   1139 	dns_name_t name;
   1140 	struct stub_cb_args *args;
   1141 	bool ipv4;
   1142 };
   1143 
   1144 /*%
   1145  * Increment resolver-related statistics counters.  Zone must be locked.
   1146  */
   1147 static void
   1148 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
   1149 	if (zone->stats != NULL) {
   1150 		isc_stats_increment(zone->stats, counter);
   1151 	}
   1152 }
   1153 
   1154 /***
   1155  ***	Public functions.
   1156  ***/
   1157 
   1158 void
   1159 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx, unsigned int tid) {
   1160 	isc_time_t now;
   1161 	dns_zone_t *zone = NULL;
   1162 
   1163 	REQUIRE(zonep != NULL && *zonep == NULL);
   1164 	REQUIRE(mctx != NULL);
   1165 
   1166 	now = isc_time_now();
   1167 	zone = isc_mem_get(mctx, sizeof(*zone));
   1168 	*zone = (dns_zone_t){
   1169 		.masterformat = dns_masterformat_none,
   1170 		.journalsize = -1,
   1171 		.rdclass = dns_rdataclass_none,
   1172 		.type = dns_zone_none,
   1173 		.refresh = DNS_ZONE_DEFAULTREFRESH,
   1174 		.retry = DNS_ZONE_DEFAULTRETRY,
   1175 		.maxrefresh = DNS_ZONE_MAXREFRESH,
   1176 		.minrefresh = DNS_ZONE_MINREFRESH,
   1177 		.maxretry = DNS_ZONE_MAXRETRY,
   1178 		.minretry = DNS_ZONE_MINRETRY,
   1179 		.checkdstype = dns_checkdstype_yes,
   1180 		.notifytype = dns_notifytype_yes,
   1181 		.zero_no_soa_ttl = true,
   1182 		.check_names = dns_severity_ignore,
   1183 		.idlein = DNS_DEFAULT_IDLEIN,
   1184 		.idleout = DNS_DEFAULT_IDLEOUT,
   1185 		.maxxfrin = MAX_XFER_TIME,
   1186 		.maxxfrout = MAX_XFER_TIME,
   1187 		.sigvalidityinterval = 30 * 24 * 3600,
   1188 		.sigresigninginterval = 7 * 24 * 3600,
   1189 		.statlevel = dns_zonestat_none,
   1190 		.notifydelay = 5,
   1191 		.signatures = 10,
   1192 		.nodes = 100,
   1193 		.privatetype = (dns_rdatatype_t)0xffffU,
   1194 		.rpz_num = DNS_RPZ_INVALID_NUM,
   1195 		.requestixfr = true,
   1196 		.ixfr_ratio = 100,
   1197 		.requestexpire = true,
   1198 		.updatemethod = dns_updatemethod_increment,
   1199 		.tid = tid,
   1200 		.notifytime = now,
   1201 		.newincludes = ISC_LIST_INITIALIZER,
   1202 		.notifies = ISC_LIST_INITIALIZER,
   1203 		.checkds_requests = ISC_LIST_INITIALIZER,
   1204 		.signing = ISC_LIST_INITIALIZER,
   1205 		.nsec3chain = ISC_LIST_INITIALIZER,
   1206 		.setnsec3param_queue = ISC_LIST_INITIALIZER,
   1207 		.forwards = ISC_LIST_INITIALIZER,
   1208 		.link = ISC_LINK_INITIALIZER,
   1209 		.statelink = ISC_LINK_INITIALIZER,
   1210 	};
   1211 	dns_remote_t r = {
   1212 		.magic = DNS_REMOTE_MAGIC,
   1213 	};
   1214 
   1215 	isc_mem_attach(mctx, &zone->mctx);
   1216 	isc_mutex_init(&zone->lock);
   1217 #ifndef _LP64
   1218 	isc_mutex_init(&zone->atomic_lock);
   1219 #endif
   1220 	ZONEDB_INITLOCK(&zone->dblock);
   1221 
   1222 	isc_refcount_init(&zone->references, 1);
   1223 	isc_refcount_init(&zone->irefs, 0);
   1224 	dns_name_init(&zone->origin, NULL);
   1225 	isc_sockaddr_any(&zone->notifysrc4);
   1226 	isc_sockaddr_any6(&zone->notifysrc6);
   1227 	isc_sockaddr_any(&zone->parentalsrc4);
   1228 	isc_sockaddr_any6(&zone->parentalsrc6);
   1229 	isc_sockaddr_any(&zone->xfrsource4);
   1230 	isc_sockaddr_any6(&zone->xfrsource6);
   1231 
   1232 	zone->primaries = r;
   1233 	zone->parentals = r;
   1234 	zone->notify = r;
   1235 	zone->defaultkasp = NULL;
   1236 	ISC_LIST_INIT(zone->keyring);
   1237 
   1238 	isc_stats_create(mctx, &zone->gluecachestats,
   1239 			 dns_gluecachestatscounter_max);
   1240 
   1241 	zone->magic = ZONE_MAGIC;
   1242 
   1243 	/* Must be after magic is set. */
   1244 	dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
   1245 
   1246 	*zonep = zone;
   1247 }
   1248 
   1249 static void
   1250 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
   1251 	dns_dnsseckey_t *key;
   1252 	while (!ISC_LIST_EMPTY(*list)) {
   1253 		key = ISC_LIST_HEAD(*list);
   1254 		ISC_LIST_UNLINK(*list, key, link);
   1255 		dns_dnsseckey_destroy(mctx, &key);
   1256 	}
   1257 }
   1258 
   1259 /*
   1260  * Free a zone.  Because we require that there be no more
   1261  * outstanding events or references, no locking is necessary.
   1262  */
   1263 static void
   1264 zone_free(dns_zone_t *zone) {
   1265 	dns_signing_t *signing = NULL;
   1266 	dns_nsec3chain_t *nsec3chain = NULL;
   1267 	dns_include_t *include = NULL;
   1268 
   1269 	REQUIRE(DNS_ZONE_VALID(zone));
   1270 	REQUIRE(!LOCKED_ZONE(zone));
   1271 	REQUIRE(zone->timer == NULL);
   1272 	REQUIRE(zone->zmgr == NULL);
   1273 
   1274 	isc_refcount_destroy(&zone->references);
   1275 	isc_refcount_destroy(&zone->irefs);
   1276 
   1277 	/*
   1278 	 * Managed objects.  Order is important.
   1279 	 */
   1280 	if (zone->request != NULL) {
   1281 		dns_request_destroy(&zone->request); /* XXXMPA */
   1282 	}
   1283 	INSIST(zone->statelist == NULL);
   1284 	INSIST(zone->view == NULL);
   1285 	INSIST(zone->prev_view == NULL);
   1286 
   1287 	/* Unmanaged objects */
   1288 	for (struct np3 *npe = ISC_LIST_HEAD(zone->setnsec3param_queue);
   1289 	     npe != NULL; npe = ISC_LIST_HEAD(zone->setnsec3param_queue))
   1290 	{
   1291 		ISC_LIST_UNLINK(zone->setnsec3param_queue, npe, link);
   1292 		isc_mem_put(zone->mctx, npe, sizeof(*npe));
   1293 	}
   1294 
   1295 	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
   1296 	     signing = ISC_LIST_HEAD(zone->signing))
   1297 	{
   1298 		ISC_LIST_UNLINK(zone->signing, signing, link);
   1299 		dns_db_detach(&signing->db);
   1300 		dns_dbiterator_destroy(&signing->dbiterator);
   1301 		isc_mem_put(zone->mctx, signing, sizeof *signing);
   1302 	}
   1303 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
   1304 	     nsec3chain = ISC_LIST_HEAD(zone->nsec3chain))
   1305 	{
   1306 		ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
   1307 		dns_db_detach(&nsec3chain->db);
   1308 		dns_dbiterator_destroy(&nsec3chain->dbiterator);
   1309 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   1310 	}
   1311 	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
   1312 	     include = ISC_LIST_HEAD(zone->includes))
   1313 	{
   1314 		ISC_LIST_UNLINK(zone->includes, include, link);
   1315 		isc_mem_free(zone->mctx, include->name);
   1316 		isc_mem_put(zone->mctx, include, sizeof *include);
   1317 	}
   1318 	for (include = ISC_LIST_HEAD(zone->newincludes); include != NULL;
   1319 	     include = ISC_LIST_HEAD(zone->newincludes))
   1320 	{
   1321 		ISC_LIST_UNLINK(zone->newincludes, include, link);
   1322 		isc_mem_free(zone->mctx, include->name);
   1323 		isc_mem_put(zone->mctx, include, sizeof *include);
   1324 	}
   1325 	if (zone->masterfile != NULL) {
   1326 		isc_mem_free(zone->mctx, zone->masterfile);
   1327 	}
   1328 	zone->masterfile = NULL;
   1329 	if (zone->keydirectory != NULL) {
   1330 		isc_mem_free(zone->mctx, zone->keydirectory);
   1331 	}
   1332 	zone->keydirectory = NULL;
   1333 	if (zone->kasp != NULL) {
   1334 		dns_kasp_detach(&zone->kasp);
   1335 	}
   1336 	if (zone->defaultkasp != NULL) {
   1337 		dns_kasp_detach(&zone->defaultkasp);
   1338 	}
   1339 	if (!ISC_LIST_EMPTY(zone->keyring)) {
   1340 		clear_keylist(&zone->keyring, zone->mctx);
   1341 	}
   1342 	if (!ISC_LIST_EMPTY(zone->checkds_ok)) {
   1343 		clear_keylist(&zone->checkds_ok, zone->mctx);
   1344 	}
   1345 	if (zone->skr != NULL) {
   1346 		zone->skrbundle = NULL;
   1347 		dns_skr_detach(&zone->skr);
   1348 	}
   1349 
   1350 	zone->journalsize = -1;
   1351 	if (zone->journal != NULL) {
   1352 		isc_mem_free(zone->mctx, zone->journal);
   1353 	}
   1354 	zone->journal = NULL;
   1355 	if (zone->stats != NULL) {
   1356 		isc_stats_detach(&zone->stats);
   1357 	}
   1358 	if (zone->requeststats != NULL) {
   1359 		isc_stats_detach(&zone->requeststats);
   1360 	}
   1361 	if (zone->rcvquerystats != NULL) {
   1362 		dns_stats_detach(&zone->rcvquerystats);
   1363 	}
   1364 	if (zone->dnssecsignstats != NULL) {
   1365 		dns_stats_detach(&zone->dnssecsignstats);
   1366 	}
   1367 	if (zone->db != NULL) {
   1368 		zone_detachdb(zone);
   1369 	}
   1370 	if (zone->rpzs != NULL) {
   1371 		REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
   1372 		dns_rpz_zones_detach(&zone->rpzs);
   1373 		zone->rpz_num = DNS_RPZ_INVALID_NUM;
   1374 	}
   1375 	if (zone->catzs != NULL) {
   1376 		dns_catz_zones_detach(&zone->catzs);
   1377 	}
   1378 	zone_freedbargs(zone);
   1379 
   1380 	dns_zone_setparentals(zone, NULL, NULL, NULL, NULL, 0);
   1381 	dns_zone_setprimaries(zone, NULL, NULL, NULL, NULL, 0);
   1382 	dns_zone_setalsonotify(zone, NULL, NULL, NULL, NULL, 0);
   1383 
   1384 	zone->check_names = dns_severity_ignore;
   1385 	if (zone->update_acl != NULL) {
   1386 		dns_acl_detach(&zone->update_acl);
   1387 	}
   1388 	if (zone->forward_acl != NULL) {
   1389 		dns_acl_detach(&zone->forward_acl);
   1390 	}
   1391 	if (zone->notify_acl != NULL) {
   1392 		dns_acl_detach(&zone->notify_acl);
   1393 	}
   1394 	if (zone->query_acl != NULL) {
   1395 		dns_acl_detach(&zone->query_acl);
   1396 	}
   1397 	if (zone->queryon_acl != NULL) {
   1398 		dns_acl_detach(&zone->queryon_acl);
   1399 	}
   1400 	if (zone->xfr_acl != NULL) {
   1401 		dns_acl_detach(&zone->xfr_acl);
   1402 	}
   1403 	if (dns_name_dynamic(&zone->origin)) {
   1404 		dns_name_free(&zone->origin, zone->mctx);
   1405 	}
   1406 	if (zone->strnamerd != NULL) {
   1407 		isc_mem_free(zone->mctx, zone->strnamerd);
   1408 	}
   1409 	if (zone->strname != NULL) {
   1410 		isc_mem_free(zone->mctx, zone->strname);
   1411 	}
   1412 	if (zone->strrdclass != NULL) {
   1413 		isc_mem_free(zone->mctx, zone->strrdclass);
   1414 	}
   1415 	if (zone->strviewname != NULL) {
   1416 		isc_mem_free(zone->mctx, zone->strviewname);
   1417 	}
   1418 	if (zone->ssutable != NULL) {
   1419 		dns_ssutable_detach(&zone->ssutable);
   1420 	}
   1421 	if (zone->gluecachestats != NULL) {
   1422 		isc_stats_detach(&zone->gluecachestats);
   1423 	}
   1424 
   1425 	/* last stuff */
   1426 	ZONEDB_DESTROYLOCK(&zone->dblock);
   1427 	isc_mutex_destroy(&zone->lock);
   1428 #ifndef _LP64
   1429 	isc_mutex_destroy(&zone->atomic_lock);
   1430 #endif
   1431 	zone->magic = 0;
   1432 	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
   1433 }
   1434 
   1435 /*
   1436  * Returns true iff this the signed side of an inline-signing zone.
   1437  * Caller should hold zone lock.
   1438  */
   1439 static bool
   1440 inline_secure(dns_zone_t *zone) {
   1441 	REQUIRE(DNS_ZONE_VALID(zone));
   1442 	if (zone->raw != NULL) {
   1443 		return true;
   1444 	}
   1445 	return false;
   1446 }
   1447 
   1448 /*
   1449  * Returns true iff this the unsigned side of an inline-signing zone
   1450  * Caller should hold zone lock.
   1451  */
   1452 static bool
   1453 inline_raw(dns_zone_t *zone) {
   1454 	REQUIRE(DNS_ZONE_VALID(zone));
   1455 	if (zone->secure != NULL) {
   1456 		return true;
   1457 	}
   1458 	return false;
   1459 }
   1460 
   1461 /*
   1462  *	Single shot.
   1463  */
   1464 void
   1465 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
   1466 	char namebuf[1024];
   1467 
   1468 	REQUIRE(DNS_ZONE_VALID(zone));
   1469 	REQUIRE(rdclass != dns_rdataclass_none);
   1470 
   1471 	/*
   1472 	 * Test and set.
   1473 	 */
   1474 	LOCK_ZONE(zone);
   1475 	INSIST(zone != zone->raw);
   1476 	REQUIRE(zone->rdclass == dns_rdataclass_none ||
   1477 		zone->rdclass == rdclass);
   1478 	zone->rdclass = rdclass;
   1479 
   1480 	if (zone->strnamerd != NULL) {
   1481 		isc_mem_free(zone->mctx, zone->strnamerd);
   1482 	}
   1483 	if (zone->strrdclass != NULL) {
   1484 		isc_mem_free(zone->mctx, zone->strrdclass);
   1485 	}
   1486 
   1487 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1488 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1489 	zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
   1490 	zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
   1491 
   1492 	if (inline_secure(zone)) {
   1493 		dns_zone_setclass(zone->raw, rdclass);
   1494 	}
   1495 	UNLOCK_ZONE(zone);
   1496 }
   1497 
   1498 dns_rdataclass_t
   1499 dns_zone_getclass(dns_zone_t *zone) {
   1500 	REQUIRE(DNS_ZONE_VALID(zone));
   1501 
   1502 	return zone->rdclass;
   1503 }
   1504 
   1505 void
   1506 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
   1507 	REQUIRE(DNS_ZONE_VALID(zone));
   1508 
   1509 	LOCK_ZONE(zone);
   1510 	zone->notifytype = notifytype;
   1511 	UNLOCK_ZONE(zone);
   1512 }
   1513 
   1514 void
   1515 dns_zone_setcheckdstype(dns_zone_t *zone, dns_checkdstype_t checkdstype) {
   1516 	REQUIRE(DNS_ZONE_VALID(zone));
   1517 
   1518 	LOCK_ZONE(zone);
   1519 	zone->checkdstype = checkdstype;
   1520 	UNLOCK_ZONE(zone);
   1521 }
   1522 
   1523 isc_result_t
   1524 dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
   1525 	isc_result_t result;
   1526 	unsigned int soacount;
   1527 
   1528 	REQUIRE(DNS_ZONE_VALID(zone));
   1529 	REQUIRE(serialp != NULL);
   1530 
   1531 	LOCK_ZONE(zone);
   1532 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   1533 	if (zone->db != NULL) {
   1534 		result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
   1535 					  serialp, NULL, NULL, NULL, NULL,
   1536 					  NULL);
   1537 		if (result == ISC_R_SUCCESS && soacount == 0) {
   1538 			result = ISC_R_FAILURE;
   1539 		}
   1540 	} else {
   1541 		result = DNS_R_NOTLOADED;
   1542 	}
   1543 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   1544 	UNLOCK_ZONE(zone);
   1545 
   1546 	return result;
   1547 }
   1548 
   1549 /*
   1550  *	Single shot.
   1551  */
   1552 void
   1553 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
   1554 	char namebuf[1024];
   1555 
   1556 	REQUIRE(DNS_ZONE_VALID(zone));
   1557 	REQUIRE(type != dns_zone_none);
   1558 
   1559 	/*
   1560 	 * Test and set.
   1561 	 */
   1562 	LOCK_ZONE(zone);
   1563 	REQUIRE(zone->type == dns_zone_none || zone->type == type);
   1564 	zone->type = type;
   1565 
   1566 	if (zone->strnamerd != NULL) {
   1567 		isc_mem_free(zone->mctx, zone->strnamerd);
   1568 	}
   1569 
   1570 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1571 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1572 	UNLOCK_ZONE(zone);
   1573 }
   1574 
   1575 static void
   1576 zone_freedbargs(dns_zone_t *zone) {
   1577 	unsigned int i;
   1578 
   1579 	/* Free the old database argument list. */
   1580 	if (zone->db_argv != NULL) {
   1581 		for (i = 0; i < zone->db_argc; i++) {
   1582 			isc_mem_free(zone->mctx, zone->db_argv[i]);
   1583 		}
   1584 		isc_mem_cput(zone->mctx, zone->db_argv, zone->db_argc,
   1585 			     sizeof(*zone->db_argv));
   1586 	}
   1587 	zone->db_argc = 0;
   1588 	zone->db_argv = NULL;
   1589 }
   1590 
   1591 isc_result_t
   1592 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
   1593 	size_t size = 0;
   1594 	unsigned int i;
   1595 	isc_result_t result = ISC_R_SUCCESS;
   1596 	void *mem;
   1597 	char **tmp, *tmp2, *base;
   1598 
   1599 	REQUIRE(DNS_ZONE_VALID(zone));
   1600 	REQUIRE(argv != NULL && *argv == NULL);
   1601 
   1602 	LOCK_ZONE(zone);
   1603 	size = ISC_CHECKED_MUL(zone->db_argc + 1, sizeof(char *));
   1604 	for (i = 0; i < zone->db_argc; i++) {
   1605 		size += strlen(zone->db_argv[i]) + 1;
   1606 	}
   1607 	mem = isc_mem_allocate(mctx, size);
   1608 	{
   1609 		tmp = mem;
   1610 		tmp2 = mem;
   1611 		base = mem;
   1612 		tmp2 += ISC_CHECKED_MUL(zone->db_argc + 1, sizeof(char *));
   1613 		for (i = 0; i < zone->db_argc; i++) {
   1614 			*tmp++ = tmp2;
   1615 			strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
   1616 			tmp2 += strlen(tmp2) + 1;
   1617 		}
   1618 		*tmp = NULL;
   1619 	}
   1620 	UNLOCK_ZONE(zone);
   1621 	*argv = mem;
   1622 	return result;
   1623 }
   1624 
   1625 void
   1626 dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc,
   1627 		   const char *const *dbargv) {
   1628 	char **argv = NULL;
   1629 	unsigned int i;
   1630 
   1631 	REQUIRE(DNS_ZONE_VALID(zone));
   1632 	REQUIRE(dbargc >= 1);
   1633 	REQUIRE(dbargv != NULL);
   1634 
   1635 	LOCK_ZONE(zone);
   1636 
   1637 	/* Set up a new database argument list. */
   1638 	argv = isc_mem_cget(zone->mctx, dbargc, sizeof(*argv));
   1639 	for (i = 0; i < dbargc; i++) {
   1640 		argv[i] = NULL;
   1641 	}
   1642 	for (i = 0; i < dbargc; i++) {
   1643 		argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
   1644 	}
   1645 
   1646 	/* Free the old list. */
   1647 	zone_freedbargs(zone);
   1648 
   1649 	zone->db_argc = dbargc;
   1650 	zone->db_argv = argv;
   1651 
   1652 	UNLOCK_ZONE(zone);
   1653 }
   1654 
   1655 static void
   1656 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
   1657 	char namebuf[1024];
   1658 
   1659 	if (zone->prev_view == NULL && zone->view != NULL) {
   1660 		dns_view_weakattach(zone->view, &zone->prev_view);
   1661 	}
   1662 
   1663 	INSIST(zone != zone->raw);
   1664 	if (zone->view != NULL) {
   1665 		dns_view_sfd_del(zone->view, &zone->origin);
   1666 		dns_view_weakdetach(&zone->view);
   1667 	}
   1668 	dns_view_weakattach(view, &zone->view);
   1669 	dns_view_sfd_add(view, &zone->origin);
   1670 
   1671 	if (zone->strviewname != NULL) {
   1672 		isc_mem_free(zone->mctx, zone->strviewname);
   1673 	}
   1674 	if (zone->strnamerd != NULL) {
   1675 		isc_mem_free(zone->mctx, zone->strnamerd);
   1676 	}
   1677 
   1678 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1679 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1680 	zone_viewname_tostr(zone, namebuf, sizeof namebuf);
   1681 	zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
   1682 
   1683 	if (inline_secure(zone)) {
   1684 		dns_zone_setview(zone->raw, view);
   1685 	}
   1686 }
   1687 
   1688 void
   1689 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
   1690 	REQUIRE(DNS_ZONE_VALID(zone));
   1691 
   1692 	LOCK_ZONE(zone);
   1693 	dns_zone_setview_helper(zone, view);
   1694 	UNLOCK_ZONE(zone);
   1695 }
   1696 
   1697 dns_view_t *
   1698 dns_zone_getview(dns_zone_t *zone) {
   1699 	REQUIRE(DNS_ZONE_VALID(zone));
   1700 
   1701 	return zone->view;
   1702 }
   1703 
   1704 void
   1705 dns_zone_setviewcommit(dns_zone_t *zone) {
   1706 	REQUIRE(DNS_ZONE_VALID(zone));
   1707 
   1708 	LOCK_ZONE(zone);
   1709 	if (zone->prev_view != NULL) {
   1710 		dns_view_weakdetach(&zone->prev_view);
   1711 	}
   1712 	if (inline_secure(zone)) {
   1713 		dns_zone_setviewcommit(zone->raw);
   1714 	}
   1715 	UNLOCK_ZONE(zone);
   1716 }
   1717 
   1718 void
   1719 dns_zone_setviewrevert(dns_zone_t *zone) {
   1720 	REQUIRE(DNS_ZONE_VALID(zone));
   1721 
   1722 	LOCK_ZONE(zone);
   1723 	if (zone->prev_view != NULL) {
   1724 		dns_zone_setview_helper(zone, zone->prev_view);
   1725 		dns_view_weakdetach(&zone->prev_view);
   1726 	}
   1727 	if (zone->catzs != NULL) {
   1728 		zone_catz_enable(zone, zone->catzs);
   1729 	}
   1730 	if (inline_secure(zone)) {
   1731 		dns_zone_setviewrevert(zone->raw);
   1732 	}
   1733 	UNLOCK_ZONE(zone);
   1734 }
   1735 
   1736 isc_result_t
   1737 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
   1738 	isc_result_t result = ISC_R_SUCCESS;
   1739 	char namebuf[1024];
   1740 
   1741 	REQUIRE(DNS_ZONE_VALID(zone));
   1742 	REQUIRE(origin != NULL);
   1743 
   1744 	LOCK_ZONE(zone);
   1745 	INSIST(zone != zone->raw);
   1746 	if (dns_name_dynamic(&zone->origin)) {
   1747 		dns_name_free(&zone->origin, zone->mctx);
   1748 		dns_name_init(&zone->origin, NULL);
   1749 	}
   1750 	dns_name_dup(origin, zone->mctx, &zone->origin);
   1751 
   1752 	if (zone->strnamerd != NULL) {
   1753 		isc_mem_free(zone->mctx, zone->strnamerd);
   1754 	}
   1755 	if (zone->strname != NULL) {
   1756 		isc_mem_free(zone->mctx, zone->strname);
   1757 	}
   1758 
   1759 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1760 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1761 	zone_name_tostr(zone, namebuf, sizeof namebuf);
   1762 	zone->strname = isc_mem_strdup(zone->mctx, namebuf);
   1763 
   1764 	if (inline_secure(zone)) {
   1765 		result = dns_zone_setorigin(zone->raw, origin);
   1766 	}
   1767 	UNLOCK_ZONE(zone);
   1768 	return result;
   1769 }
   1770 
   1771 static isc_result_t
   1772 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
   1773 	char *copy;
   1774 
   1775 	if (value != NULL) {
   1776 		copy = isc_mem_strdup(zone->mctx, value);
   1777 	} else {
   1778 		copy = NULL;
   1779 	}
   1780 
   1781 	if (*field != NULL) {
   1782 		isc_mem_free(zone->mctx, *field);
   1783 	}
   1784 
   1785 	*field = copy;
   1786 	return ISC_R_SUCCESS;
   1787 }
   1788 
   1789 isc_result_t
   1790 dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
   1791 		 const dns_master_style_t *style) {
   1792 	isc_result_t result = ISC_R_SUCCESS;
   1793 
   1794 	REQUIRE(DNS_ZONE_VALID(zone));
   1795 	REQUIRE(zone->stream == NULL);
   1796 
   1797 	LOCK_ZONE(zone);
   1798 	result = dns_zone_setstring(zone, &zone->masterfile, file);
   1799 	if (result == ISC_R_SUCCESS) {
   1800 		zone->masterformat = format;
   1801 		if (format == dns_masterformat_text) {
   1802 			zone->masterstyle = style;
   1803 		}
   1804 		result = default_journal(zone);
   1805 	}
   1806 	UNLOCK_ZONE(zone);
   1807 
   1808 	return result;
   1809 }
   1810 
   1811 const char *
   1812 dns_zone_getfile(dns_zone_t *zone) {
   1813 	REQUIRE(DNS_ZONE_VALID(zone));
   1814 
   1815 	return zone->masterfile;
   1816 }
   1817 
   1818 isc_result_t
   1819 dns_zone_setstream(dns_zone_t *zone, const FILE *stream,
   1820 		   dns_masterformat_t format, const dns_master_style_t *style) {
   1821 	isc_result_t result = ISC_R_SUCCESS;
   1822 
   1823 	REQUIRE(DNS_ZONE_VALID(zone));
   1824 	REQUIRE(stream != NULL);
   1825 	REQUIRE(zone->masterfile == NULL);
   1826 
   1827 	LOCK_ZONE(zone);
   1828 	zone->stream = stream;
   1829 	zone->masterformat = format;
   1830 	if (format == dns_masterformat_text) {
   1831 		zone->masterstyle = style;
   1832 	}
   1833 	result = default_journal(zone);
   1834 	UNLOCK_ZONE(zone);
   1835 
   1836 	return result;
   1837 }
   1838 
   1839 dns_ttl_t
   1840 dns_zone_getmaxttl(dns_zone_t *zone) {
   1841 	REQUIRE(DNS_ZONE_VALID(zone));
   1842 
   1843 	return zone->maxttl;
   1844 }
   1845 
   1846 void
   1847 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
   1848 	REQUIRE(DNS_ZONE_VALID(zone));
   1849 
   1850 	LOCK_ZONE(zone);
   1851 	if (maxttl != 0) {
   1852 		DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_CHECKTTL);
   1853 	} else {
   1854 		DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_CHECKTTL);
   1855 	}
   1856 	zone->maxttl = maxttl;
   1857 	UNLOCK_ZONE(zone);
   1858 
   1859 	return;
   1860 }
   1861 
   1862 static isc_result_t
   1863 default_journal(dns_zone_t *zone) {
   1864 	isc_result_t result;
   1865 	char *journal;
   1866 
   1867 	REQUIRE(DNS_ZONE_VALID(zone));
   1868 	REQUIRE(LOCKED_ZONE(zone));
   1869 
   1870 	if (zone->masterfile != NULL) {
   1871 		/* Calculate string length including '\0'. */
   1872 		int len = strlen(zone->masterfile) + sizeof(".jnl");
   1873 		journal = isc_mem_allocate(zone->mctx, len);
   1874 		strlcpy(journal, zone->masterfile, len);
   1875 		strlcat(journal, ".jnl", len);
   1876 	} else {
   1877 		journal = NULL;
   1878 	}
   1879 	result = dns_zone_setstring(zone, &zone->journal, journal);
   1880 	if (journal != NULL) {
   1881 		isc_mem_free(zone->mctx, journal);
   1882 	}
   1883 	return result;
   1884 }
   1885 
   1886 isc_result_t
   1887 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
   1888 	isc_result_t result = ISC_R_SUCCESS;
   1889 
   1890 	REQUIRE(DNS_ZONE_VALID(zone));
   1891 
   1892 	LOCK_ZONE(zone);
   1893 	result = dns_zone_setstring(zone, &zone->journal, myjournal);
   1894 	UNLOCK_ZONE(zone);
   1895 
   1896 	return result;
   1897 }
   1898 
   1899 char *
   1900 dns_zone_getjournal(dns_zone_t *zone) {
   1901 	REQUIRE(DNS_ZONE_VALID(zone));
   1902 
   1903 	return zone->journal;
   1904 }
   1905 
   1906 /*
   1907  * Return true iff the zone is "dynamic", in the sense that the zone's
   1908  * master file (if any) is written by the server, rather than being
   1909  * updated manually and read by the server.
   1910  *
   1911  * This is true for secondary zones, mirror zones, stub zones, key zones,
   1912  * and zones that allow dynamic updates either by having an update
   1913  * policy ("ssutable") or an "allow-update" ACL with a value other than
   1914  * exactly "{ none; }".
   1915  */
   1916 bool
   1917 dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
   1918 	REQUIRE(DNS_ZONE_VALID(zone));
   1919 
   1920 	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
   1921 	    zone->type == dns_zone_stub || zone->type == dns_zone_key ||
   1922 	    (zone->type == dns_zone_redirect &&
   1923 	     dns_remote_addresses(&zone->primaries) != NULL))
   1924 	{
   1925 		return true;
   1926 	}
   1927 
   1928 	/* Inline zones are always dynamic. */
   1929 	if (zone->type == dns_zone_primary && zone->raw != NULL) {
   1930 		return true;
   1931 	}
   1932 
   1933 	/* If !ignore_freeze, we need check whether updates are disabled.  */
   1934 	if (zone->type == dns_zone_primary &&
   1935 	    (!zone->update_disabled || ignore_freeze) &&
   1936 	    ((zone->ssutable != NULL) ||
   1937 	     (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
   1938 	{
   1939 		return true;
   1940 	}
   1941 
   1942 	return false;
   1943 }
   1944 
   1945 /*
   1946  * Set the response policy index and information for a zone.
   1947  */
   1948 isc_result_t
   1949 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
   1950 		    dns_rpz_num_t rpz_num) {
   1951 	/*
   1952 	 * This must happen only once or be redundant.
   1953 	 */
   1954 	LOCK_ZONE(zone);
   1955 	if (zone->rpzs != NULL) {
   1956 		REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
   1957 	} else {
   1958 		REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
   1959 		dns_rpz_zones_attach(rpzs, &zone->rpzs);
   1960 		zone->rpz_num = rpz_num;
   1961 	}
   1962 	rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
   1963 	UNLOCK_ZONE(zone);
   1964 
   1965 	return ISC_R_SUCCESS;
   1966 }
   1967 
   1968 dns_rpz_num_t
   1969 dns_zone_get_rpz_num(dns_zone_t *zone) {
   1970 	return zone->rpz_num;
   1971 }
   1972 
   1973 /*
   1974  * If a zone is a response policy zone, mark its new database.
   1975  */
   1976 void
   1977 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
   1978 	if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
   1979 		return;
   1980 	}
   1981 	REQUIRE(zone->rpzs != NULL);
   1982 	dns_rpz_dbupdate_register(db, zone->rpzs->zones[zone->rpz_num]);
   1983 }
   1984 
   1985 static void
   1986 dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
   1987 	if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
   1988 		return;
   1989 	}
   1990 	REQUIRE(zone->rpzs != NULL);
   1991 	dns_rpz_dbupdate_unregister(db, zone->rpzs->zones[zone->rpz_num]);
   1992 }
   1993 
   1994 /*
   1995  * If a zone is a catalog zone, attach it to update notification in database.
   1996  */
   1997 void
   1998 dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
   1999 	REQUIRE(DNS_ZONE_VALID(zone));
   2000 	REQUIRE(db != NULL);
   2001 
   2002 	if (zone->catzs != NULL) {
   2003 		dns_catz_dbupdate_register(db, zone->catzs);
   2004 	}
   2005 }
   2006 
   2007 static void
   2008 dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
   2009 	REQUIRE(DNS_ZONE_VALID(zone));
   2010 	REQUIRE(db != NULL);
   2011 
   2012 	if (zone->catzs != NULL) {
   2013 		dns_catz_dbupdate_unregister(db, zone->catzs);
   2014 	}
   2015 }
   2016 
   2017 static void
   2018 zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
   2019 	REQUIRE(DNS_ZONE_VALID(zone));
   2020 	REQUIRE(catzs != NULL);
   2021 
   2022 	INSIST(zone->catzs == NULL || zone->catzs == catzs);
   2023 	dns_catz_catzs_set_view(catzs, zone->view);
   2024 	if (zone->catzs == NULL) {
   2025 		dns_catz_zones_attach(catzs, &zone->catzs);
   2026 	}
   2027 }
   2028 
   2029 void
   2030 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
   2031 	REQUIRE(DNS_ZONE_VALID(zone));
   2032 
   2033 	LOCK_ZONE(zone);
   2034 	zone_catz_enable(zone, catzs);
   2035 	UNLOCK_ZONE(zone);
   2036 }
   2037 
   2038 static void
   2039 zone_catz_disable(dns_zone_t *zone) {
   2040 	REQUIRE(DNS_ZONE_VALID(zone));
   2041 
   2042 	if (zone->catzs != NULL) {
   2043 		if (zone->db != NULL) {
   2044 			dns_zone_catz_disable_db(zone, zone->db);
   2045 		}
   2046 		dns_catz_zones_detach(&zone->catzs);
   2047 	}
   2048 }
   2049 
   2050 void
   2051 dns_zone_catz_disable(dns_zone_t *zone) {
   2052 	REQUIRE(DNS_ZONE_VALID(zone));
   2053 
   2054 	LOCK_ZONE(zone);
   2055 	zone_catz_disable(zone);
   2056 	UNLOCK_ZONE(zone);
   2057 }
   2058 
   2059 bool
   2060 dns_zone_catz_is_enabled(dns_zone_t *zone) {
   2061 	REQUIRE(DNS_ZONE_VALID(zone));
   2062 
   2063 	return zone->catzs != NULL;
   2064 }
   2065 
   2066 /*
   2067  * Set catalog zone ownership of the zone
   2068  */
   2069 void
   2070 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
   2071 	REQUIRE(DNS_ZONE_VALID(zone));
   2072 	REQUIRE(catz != NULL);
   2073 	LOCK_ZONE(zone);
   2074 	INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
   2075 	zone->parentcatz = catz;
   2076 	UNLOCK_ZONE(zone);
   2077 }
   2078 
   2079 dns_catz_zone_t *
   2080 dns_zone_get_parentcatz(dns_zone_t *zone) {
   2081 	REQUIRE(DNS_ZONE_VALID(zone));
   2082 
   2083 	dns_catz_zone_t *parentcatz = NULL;
   2084 
   2085 	LOCK_ZONE(zone);
   2086 	parentcatz = zone->parentcatz;
   2087 	UNLOCK_ZONE(zone);
   2088 
   2089 	return parentcatz;
   2090 }
   2091 
   2092 static bool
   2093 zone_touched(dns_zone_t *zone) {
   2094 	isc_result_t result;
   2095 	isc_time_t modtime;
   2096 	dns_include_t *include;
   2097 
   2098 	REQUIRE(DNS_ZONE_VALID(zone));
   2099 
   2100 	result = isc_file_getmodtime(zone->masterfile, &modtime);
   2101 	if (result != ISC_R_SUCCESS ||
   2102 	    isc_time_compare(&modtime, &zone->loadtime) > 0)
   2103 	{
   2104 		return true;
   2105 	}
   2106 
   2107 	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
   2108 	     include = ISC_LIST_NEXT(include, link))
   2109 	{
   2110 		result = isc_file_getmodtime(include->name, &modtime);
   2111 		if (result != ISC_R_SUCCESS ||
   2112 		    isc_time_compare(&modtime, &include->filetime) > 0)
   2113 		{
   2114 			return true;
   2115 		}
   2116 	}
   2117 
   2118 	return false;
   2119 }
   2120 
   2121 /*
   2122  * Note: when dealing with inline-signed zones, external callers will always
   2123  * call zone_load() for the secure zone; zone_load() calls itself recursively
   2124  * in order to load the raw zone.
   2125  */
   2126 static isc_result_t
   2127 zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
   2128 	isc_result_t result;
   2129 	isc_time_t now;
   2130 	isc_time_t loadtime;
   2131 	dns_db_t *db = NULL;
   2132 	bool rbt, hasraw, is_dynamic;
   2133 
   2134 	REQUIRE(DNS_ZONE_VALID(zone));
   2135 
   2136 	if (!locked) {
   2137 		LOCK_ZONE(zone);
   2138 	}
   2139 
   2140 	INSIST(zone != zone->raw);
   2141 	hasraw = inline_secure(zone);
   2142 	if (hasraw) {
   2143 		/*
   2144 		 * We are trying to load an inline-signed zone.  First call
   2145 		 * self recursively to try loading the raw version of the zone.
   2146 		 * Assuming the raw zone file is readable, there are two
   2147 		 * possibilities:
   2148 		 *
   2149 		 *  a) the raw zone was not yet loaded and thus it will be
   2150 		 *     loaded now, synchronously; if this succeeds, a
   2151 		 *     subsequent attempt to load the signed zone file will
   2152 		 *     take place and thus zone_postload() will be called
   2153 		 *     twice: first for the raw zone and then for the secure
   2154 		 *     zone; the latter call will take care of syncing the raw
   2155 		 *     version with the secure version,
   2156 		 *
   2157 		 *  b) the raw zone was already loaded and we are trying to
   2158 		 *     reload it, which will happen asynchronously; this means
   2159 		 *     zone_postload() will only be called for the raw zone
   2160 		 *     because "result" returned by the zone_load() call below
   2161 		 *     will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
   2162 		 *     zone_postload() called for the raw zone will take care
   2163 		 *     of syncing the raw version with the secure version.
   2164 		 */
   2165 		result = zone_load(zone->raw, flags, false);
   2166 		if (result != ISC_R_SUCCESS) {
   2167 			if (!locked) {
   2168 				UNLOCK_ZONE(zone);
   2169 			}
   2170 			return result;
   2171 		}
   2172 		LOCK_ZONE(zone->raw);
   2173 	}
   2174 
   2175 	now = isc_time_now();
   2176 
   2177 	INSIST(zone->type != dns_zone_none);
   2178 
   2179 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
   2180 		if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
   2181 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
   2182 		}
   2183 		result = DNS_R_CONTINUE;
   2184 		goto cleanup;
   2185 	}
   2186 
   2187 	INSIST(zone->db_argc >= 1);
   2188 
   2189 	rbt = strcmp(zone->db_argv[0], ZONEDB_DEFAULT) == 0;
   2190 
   2191 	if (zone->db != NULL && zone->masterfile == NULL && rbt) {
   2192 		/*
   2193 		 * The zone has no master file configured.
   2194 		 */
   2195 		result = ISC_R_SUCCESS;
   2196 		goto cleanup;
   2197 	}
   2198 
   2199 	is_dynamic = dns_zone_isdynamic(zone, false);
   2200 	if (zone->db != NULL && is_dynamic) {
   2201 		/*
   2202 		 * This is a secondary, stub, or dynamically updated zone
   2203 		 * being reloaded.  Do nothing - the database we already
   2204 		 * have is guaranteed to be up-to-date.
   2205 		 */
   2206 		if (zone->type == dns_zone_primary && !hasraw) {
   2207 			result = DNS_R_DYNAMIC;
   2208 		} else {
   2209 			result = ISC_R_SUCCESS;
   2210 		}
   2211 		goto cleanup;
   2212 	}
   2213 
   2214 	/*
   2215 	 * Store the current time before the zone is loaded, so that if the
   2216 	 * file changes between the time of the load and the time that
   2217 	 * zone->loadtime is set, then the file will still be reloaded
   2218 	 * the next time dns_zone_load is called.
   2219 	 */
   2220 	loadtime = isc_time_now();
   2221 
   2222 	/*
   2223 	 * Don't do the load if the file that stores the zone is older
   2224 	 * than the last time the zone was loaded.  If the zone has not
   2225 	 * been loaded yet, zone->loadtime will be the epoch.
   2226 	 */
   2227 	if (zone->masterfile != NULL) {
   2228 		isc_time_t filetime;
   2229 
   2230 		/*
   2231 		 * The file is already loaded.	If we are just doing a
   2232 		 * "rndc reconfig", we are done.
   2233 		 */
   2234 		if (!isc_time_isepoch(&zone->loadtime) &&
   2235 		    (flags & DNS_ZONELOADFLAG_NOSTAT) != 0)
   2236 		{
   2237 			result = ISC_R_SUCCESS;
   2238 			goto cleanup;
   2239 		}
   2240 
   2241 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   2242 		    !zone_touched(zone))
   2243 		{
   2244 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2245 				      ISC_LOG_DEBUG(1),
   2246 				      "skipping load: master file "
   2247 				      "older than last load");
   2248 			result = DNS_R_UPTODATE;
   2249 			goto cleanup;
   2250 		}
   2251 
   2252 		/*
   2253 		 * If the file modification time is in the past
   2254 		 * set loadtime to that value.
   2255 		 */
   2256 		result = isc_file_getmodtime(zone->masterfile, &filetime);
   2257 		if (result == ISC_R_SUCCESS &&
   2258 		    isc_time_compare(&loadtime, &filetime) > 0)
   2259 		{
   2260 			loadtime = filetime;
   2261 		}
   2262 	}
   2263 
   2264 	/*
   2265 	 * Built in zones (with the exception of empty zones) don't need
   2266 	 * to be reloaded.
   2267 	 */
   2268 	if (zone->type == dns_zone_primary &&
   2269 	    strcmp(zone->db_argv[0], "_builtin") == 0 &&
   2270 	    (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
   2271 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   2272 	{
   2273 		result = ISC_R_SUCCESS;
   2274 		goto cleanup;
   2275 	}
   2276 
   2277 	/*
   2278 	 * Zones associated with a DLZ don't need to be loaded either,
   2279 	 * but we need to associate the database with the zone object.
   2280 	 */
   2281 	if (strcmp(zone->db_argv[0], "dlz") == 0) {
   2282 		dns_dlzdb_t *dlzdb;
   2283 		dns_dlzfindzone_t findzone;
   2284 
   2285 		for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
   2286 		     dlzdb != NULL; dlzdb = ISC_LIST_NEXT(dlzdb, link))
   2287 		{
   2288 			INSIST(DNS_DLZ_VALID(dlzdb));
   2289 			if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0) {
   2290 				break;
   2291 			}
   2292 		}
   2293 
   2294 		if (dlzdb == NULL) {
   2295 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2296 				      ISC_LOG_ERROR,
   2297 				      "DLZ %s does not exist or is set "
   2298 				      "to 'search yes;'",
   2299 				      zone->db_argv[1]);
   2300 			result = ISC_R_NOTFOUND;
   2301 			goto cleanup;
   2302 		}
   2303 
   2304 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   2305 		/* ask SDLZ driver if the zone is supported */
   2306 		findzone = dlzdb->implementation->methods->findzone;
   2307 		result = (*findzone)(dlzdb->implementation->driverarg,
   2308 				     dlzdb->dbdata, dlzdb->mctx,
   2309 				     zone->view->rdclass, &zone->origin, NULL,
   2310 				     NULL, &db);
   2311 		if (result != ISC_R_NOTFOUND) {
   2312 			if (zone->db != NULL) {
   2313 				zone_detachdb(zone);
   2314 			}
   2315 			zone_attachdb(zone, db);
   2316 			dns_db_detach(&db);
   2317 			result = ISC_R_SUCCESS;
   2318 		}
   2319 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   2320 
   2321 		if (result == ISC_R_SUCCESS) {
   2322 			if (dlzdb->configure_callback == NULL) {
   2323 				goto cleanup;
   2324 			}
   2325 
   2326 			result = (*dlzdb->configure_callback)(zone->view, dlzdb,
   2327 							      zone);
   2328 			if (result != ISC_R_SUCCESS) {
   2329 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2330 					      ISC_LOG_ERROR,
   2331 					      "DLZ configuration callback: %s",
   2332 					      isc_result_totext(result));
   2333 			}
   2334 		}
   2335 		goto cleanup;
   2336 	}
   2337 
   2338 	if ((zone->type == dns_zone_secondary ||
   2339 	     zone->type == dns_zone_mirror || zone->type == dns_zone_stub ||
   2340 	     (zone->type == dns_zone_redirect &&
   2341 	      dns_remote_addresses(&zone->primaries) != NULL)) &&
   2342 	    rbt)
   2343 	{
   2344 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIRSTREFRESH);
   2345 
   2346 		if (zone->stream == NULL &&
   2347 		    (zone->masterfile == NULL ||
   2348 		     !isc_file_exists(zone->masterfile)))
   2349 		{
   2350 			if (zone->masterfile != NULL) {
   2351 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2352 					      ISC_LOG_DEBUG(1),
   2353 					      "no master file");
   2354 			}
   2355 			zone->refreshtime = now;
   2356 			if (zone->loop != NULL) {
   2357 				zone_settimer(zone, &now);
   2358 			}
   2359 			result = ISC_R_SUCCESS;
   2360 			goto cleanup;
   2361 		}
   2362 	}
   2363 
   2364 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
   2365 		      "starting load");
   2366 
   2367 	result = dns_zone_makedb(zone, &db);
   2368 	if (result != ISC_R_SUCCESS) {
   2369 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   2370 			      "loading zone: creating database: %s",
   2371 			      isc_result_totext(result));
   2372 		goto cleanup;
   2373 	}
   2374 
   2375 	if (!dns_db_ispersistent(db)) {
   2376 		if (zone->masterfile != NULL || zone->stream != NULL) {
   2377 			result = zone_startload(db, zone, loadtime);
   2378 		} else {
   2379 			result = DNS_R_NOMASTERFILE;
   2380 			if (zone->type == dns_zone_primary ||
   2381 			    (zone->type == dns_zone_redirect &&
   2382 			     dns_remote_addresses(&zone->primaries) == NULL))
   2383 			{
   2384 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2385 					      ISC_LOG_ERROR,
   2386 					      "loading zone: "
   2387 					      "no master file configured");
   2388 				goto cleanup;
   2389 			}
   2390 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2391 				      ISC_LOG_INFO,
   2392 				      "loading zone: "
   2393 				      "no master file configured: continuing");
   2394 		}
   2395 	}
   2396 
   2397 	if (result == DNS_R_CONTINUE) {
   2398 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
   2399 		if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
   2400 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
   2401 		}
   2402 		goto cleanup;
   2403 	}
   2404 
   2405 	result = zone_postload(zone, db, loadtime, result);
   2406 
   2407 cleanup:
   2408 	if (hasraw) {
   2409 		UNLOCK_ZONE(zone->raw);
   2410 	}
   2411 	if (!locked) {
   2412 		UNLOCK_ZONE(zone);
   2413 	}
   2414 	if (db != NULL) {
   2415 		dns_db_detach(&db);
   2416 	}
   2417 	return result;
   2418 }
   2419 
   2420 isc_result_t
   2421 dns_zone_load(dns_zone_t *zone, bool newonly) {
   2422 	return zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false);
   2423 }
   2424 
   2425 static void
   2426 zone_asyncload(void *arg) {
   2427 	dns_asyncload_t *asl = arg;
   2428 	dns_zone_t *zone = asl->zone;
   2429 	isc_result_t result;
   2430 
   2431 	REQUIRE(DNS_ZONE_VALID(zone));
   2432 
   2433 	LOCK_ZONE(zone);
   2434 	result = zone_load(zone, asl->flags, true);
   2435 	if (result != DNS_R_CONTINUE) {
   2436 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
   2437 	}
   2438 	UNLOCK_ZONE(zone);
   2439 
   2440 	/* Inform the zone table we've finished loading */
   2441 	if (asl->loaded != NULL) {
   2442 		asl->loaded(asl->loaded_arg);
   2443 	}
   2444 
   2445 	isc_mem_put(zone->mctx, asl, sizeof(*asl));
   2446 	dns_zone_idetach(&zone);
   2447 }
   2448 
   2449 isc_result_t
   2450 dns_zone_asyncload(dns_zone_t *zone, bool newonly, dns_zt_callback_t *done,
   2451 		   void *arg) {
   2452 	dns_asyncload_t *asl = NULL;
   2453 
   2454 	REQUIRE(DNS_ZONE_VALID(zone));
   2455 
   2456 	if (zone->zmgr == NULL) {
   2457 		return ISC_R_FAILURE;
   2458 	}
   2459 
   2460 	/* If we already have a load pending, stop now */
   2461 	LOCK_ZONE(zone);
   2462 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
   2463 		UNLOCK_ZONE(zone);
   2464 		return ISC_R_ALREADYRUNNING;
   2465 	}
   2466 
   2467 	asl = isc_mem_get(zone->mctx, sizeof(*asl));
   2468 
   2469 	asl->zone = NULL;
   2470 	asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
   2471 	asl->loaded = done;
   2472 	asl->loaded_arg = arg;
   2473 
   2474 	zone_iattach(zone, &asl->zone);
   2475 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
   2476 	isc_async_run(zone->loop, zone_asyncload, asl);
   2477 	UNLOCK_ZONE(zone);
   2478 
   2479 	return ISC_R_SUCCESS;
   2480 }
   2481 
   2482 bool
   2483 dns__zone_loadpending(dns_zone_t *zone) {
   2484 	REQUIRE(DNS_ZONE_VALID(zone));
   2485 
   2486 	return DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
   2487 }
   2488 
   2489 isc_result_t
   2490 dns_zone_loadandthaw(dns_zone_t *zone) {
   2491 	isc_result_t result;
   2492 
   2493 	if (inline_raw(zone)) {
   2494 		result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW, false);
   2495 	} else {
   2496 		/*
   2497 		 * When thawing a zone, we don't know what changes
   2498 		 * have been made. If we do DNSSEC maintenance on this
   2499 		 * zone, schedule a full sign for this zone.
   2500 		 */
   2501 		if (zone->type == dns_zone_primary &&
   2502 		    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
   2503 		{
   2504 			DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
   2505 		}
   2506 		result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
   2507 	}
   2508 
   2509 	switch (result) {
   2510 	case DNS_R_CONTINUE:
   2511 		/* Deferred thaw. */
   2512 		break;
   2513 	case DNS_R_UPTODATE:
   2514 	case ISC_R_SUCCESS:
   2515 	case DNS_R_SEENINCLUDE:
   2516 		zone->update_disabled = false;
   2517 		break;
   2518 	case DNS_R_NOMASTERFILE:
   2519 		zone->update_disabled = false;
   2520 		break;
   2521 	default:
   2522 		/* Error, remain in disabled state. */
   2523 		break;
   2524 	}
   2525 	return result;
   2526 }
   2527 
   2528 static unsigned int
   2529 get_primary_options(dns_zone_t *zone) {
   2530 	unsigned int options;
   2531 
   2532 	options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
   2533 	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
   2534 	    (zone->type == dns_zone_redirect &&
   2535 	     dns_remote_addresses(&zone->primaries) == NULL))
   2536 	{
   2537 		options |= DNS_MASTER_SECONDARY;
   2538 	}
   2539 	if (zone->type == dns_zone_key) {
   2540 		options |= DNS_MASTER_KEY;
   2541 	}
   2542 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
   2543 		options |= DNS_MASTER_CHECKNS;
   2544 	}
   2545 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
   2546 		options |= DNS_MASTER_FATALNS;
   2547 	}
   2548 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
   2549 		options |= DNS_MASTER_CHECKNAMES;
   2550 	}
   2551 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
   2552 		options |= DNS_MASTER_CHECKNAMESFAIL;
   2553 	}
   2554 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
   2555 		options |= DNS_MASTER_CHECKMX;
   2556 	}
   2557 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
   2558 		options |= DNS_MASTER_CHECKMXFAIL;
   2559 	}
   2560 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
   2561 		options |= DNS_MASTER_CHECKWILDCARD;
   2562 	}
   2563 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
   2564 		options |= DNS_MASTER_CHECKTTL;
   2565 	}
   2566 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSVCB)) {
   2567 		options |= DNS_MASTER_CHECKSVCB;
   2568 	}
   2569 
   2570 	return options;
   2571 }
   2572 
   2573 static void
   2574 zone_registerinclude(const char *filename, void *arg) {
   2575 	isc_result_t result;
   2576 	dns_zone_t *zone = (dns_zone_t *)arg;
   2577 	dns_include_t *inc = NULL;
   2578 
   2579 	REQUIRE(DNS_ZONE_VALID(zone));
   2580 
   2581 	if (filename == NULL) {
   2582 		return;
   2583 	}
   2584 
   2585 	/*
   2586 	 * Suppress duplicates.
   2587 	 */
   2588 	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
   2589 	     inc = ISC_LIST_NEXT(inc, link))
   2590 	{
   2591 		if (strcmp(filename, inc->name) == 0) {
   2592 			return;
   2593 		}
   2594 	}
   2595 
   2596 	inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
   2597 	inc->name = isc_mem_strdup(zone->mctx, filename);
   2598 	ISC_LINK_INIT(inc, link);
   2599 
   2600 	result = isc_file_getmodtime(filename, &inc->filetime);
   2601 	if (result != ISC_R_SUCCESS) {
   2602 		isc_time_settoepoch(&inc->filetime);
   2603 	}
   2604 
   2605 	ISC_LIST_APPEND(zone->newincludes, inc, link);
   2606 }
   2607 
   2608 static void
   2609 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
   2610 	isc_result_t result;
   2611 	unsigned int soacount;
   2612 
   2613 	LOCK(&raw->lock);
   2614 	if (raw->db != NULL) {
   2615 		result = zone_get_from_db(raw, raw->db, NULL, &soacount, NULL,
   2616 					  &rawdata->sourceserial, NULL, NULL,
   2617 					  NULL, NULL, NULL);
   2618 		if (result == ISC_R_SUCCESS && soacount > 0U) {
   2619 			rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
   2620 		}
   2621 	}
   2622 	UNLOCK(&raw->lock);
   2623 }
   2624 
   2625 /*
   2626  * Save the raw serial number for inline-signing zones.
   2627  * (XXX: Other information from the header will be used
   2628  * for other purposes in the future, but for now this is
   2629  * all we're interested in.)
   2630  */
   2631 static void
   2632 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
   2633 	if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) {
   2634 		return;
   2635 	}
   2636 
   2637 	zone->sourceserial = header->sourceserial;
   2638 	zone->sourceserialset = true;
   2639 }
   2640 
   2641 void
   2642 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
   2643 	if (zone == NULL) {
   2644 		return;
   2645 	}
   2646 
   2647 	LOCK_ZONE(zone);
   2648 	zone_setrawdata(zone, header);
   2649 	UNLOCK_ZONE(zone);
   2650 }
   2651 
   2652 static isc_result_t
   2653 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
   2654 	isc_result_t result;
   2655 	isc_result_t tresult;
   2656 	unsigned int options;
   2657 	dns_load_t *load = isc_mem_get(zone->mctx, sizeof(*load));
   2658 
   2659 	ENTER;
   2660 
   2661 	*load = (dns_load_t){
   2662 		.loadtime = loadtime,
   2663 	};
   2664 
   2665 	dns_zone_rpz_enable_db(zone, db);
   2666 	dns_zone_catz_enable_db(zone, db);
   2667 
   2668 	options = get_primary_options(zone);
   2669 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
   2670 		options |= DNS_MASTER_MANYERRORS;
   2671 	}
   2672 
   2673 	zone_iattach(zone, &load->zone);
   2674 	dns_db_attach(db, &load->db);
   2675 
   2676 	dns_rdatacallbacks_init(&load->callbacks);
   2677 	load->callbacks.rawdata = zone_setrawdata;
   2678 	zone_iattach(zone, &load->callbacks.zone);
   2679 
   2680 	result = dns_db_beginload(db, &load->callbacks);
   2681 	if (result != ISC_R_SUCCESS) {
   2682 		goto cleanup;
   2683 	}
   2684 
   2685 	if (zone->zmgr != NULL && zone->db != NULL) {
   2686 		result = dns_master_loadfileasync(
   2687 			zone->masterfile, dns_db_origin(db), dns_db_origin(db),
   2688 			zone->rdclass, options, 0, &load->callbacks, zone->loop,
   2689 			zone_loaddone, load, &zone->loadctx,
   2690 			zone_registerinclude, zone, zone->mctx,
   2691 			zone->masterformat, zone->maxttl);
   2692 		if (result != ISC_R_SUCCESS) {
   2693 			goto cleanup;
   2694 		}
   2695 
   2696 		return DNS_R_CONTINUE;
   2697 	} else if (zone->stream != NULL) {
   2698 		FILE *stream = UNCONST(zone->stream);
   2699 		result = dns_master_loadstream(
   2700 			stream, &zone->origin, &zone->origin, zone->rdclass,
   2701 			options, &load->callbacks, zone->mctx);
   2702 	} else {
   2703 		result = dns_master_loadfile(
   2704 			zone->masterfile, &zone->origin, &zone->origin,
   2705 			zone->rdclass, options, 0, &load->callbacks,
   2706 			zone_registerinclude, zone, zone->mctx,
   2707 			zone->masterformat, zone->maxttl);
   2708 	}
   2709 
   2710 cleanup:
   2711 	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
   2712 		dns_zone_rpz_disable_db(zone, load->db);
   2713 		dns_zone_catz_disable_db(zone, load->db);
   2714 	}
   2715 
   2716 	tresult = dns_db_endload(db, &load->callbacks);
   2717 	if (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) {
   2718 		result = tresult;
   2719 	}
   2720 
   2721 	zone_idetach(&load->callbacks.zone);
   2722 	dns_db_detach(&load->db);
   2723 	zone_idetach(&load->zone);
   2724 
   2725 	isc_mem_put(zone->mctx, load, sizeof(*load));
   2726 	return result;
   2727 }
   2728 
   2729 static bool
   2730 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
   2731 	      dns_name_t *owner) {
   2732 	isc_result_t result;
   2733 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2734 	char namebuf[DNS_NAME_FORMATSIZE];
   2735 	char altbuf[DNS_NAME_FORMATSIZE];
   2736 	dns_fixedname_t fixed;
   2737 	dns_name_t *foundname;
   2738 	int level;
   2739 
   2740 	/*
   2741 	 * "." means the services does not exist.
   2742 	 */
   2743 	if (dns_name_equal(name, dns_rootname)) {
   2744 		return true;
   2745 	}
   2746 
   2747 	/*
   2748 	 * Outside of zone.
   2749 	 */
   2750 	if (!dns_name_issubdomain(name, &zone->origin)) {
   2751 		if (zone->checkmx != NULL) {
   2752 			return (zone->checkmx)(zone, name, owner);
   2753 		}
   2754 		return true;
   2755 	}
   2756 
   2757 	if (zone->type == dns_zone_primary) {
   2758 		level = ISC_LOG_ERROR;
   2759 	} else {
   2760 		level = ISC_LOG_WARNING;
   2761 	}
   2762 
   2763 	foundname = dns_fixedname_initname(&fixed);
   2764 
   2765 	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
   2766 			     foundname, NULL, NULL);
   2767 	if (result == ISC_R_SUCCESS) {
   2768 		return true;
   2769 	}
   2770 
   2771 	if (result == DNS_R_NXRRSET) {
   2772 		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
   2773 				     NULL, foundname, NULL, NULL);
   2774 		if (result == ISC_R_SUCCESS) {
   2775 			return true;
   2776 		}
   2777 	}
   2778 
   2779 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
   2780 	dns_name_format(name, namebuf, sizeof namebuf);
   2781 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   2782 	    result == DNS_R_EMPTYNAME)
   2783 	{
   2784 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
   2785 			level = ISC_LOG_WARNING;
   2786 		}
   2787 		dns_zone_log(zone, level,
   2788 			     "%s/MX '%s' has no address records (A or AAAA)",
   2789 			     ownerbuf, namebuf);
   2790 		return (level == ISC_LOG_WARNING) ? true : false;
   2791 	}
   2792 
   2793 	if (result == DNS_R_CNAME) {
   2794 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
   2795 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
   2796 		{
   2797 			level = ISC_LOG_WARNING;
   2798 		}
   2799 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
   2800 			dns_zone_log(zone, level,
   2801 				     "%s/MX '%s' is a CNAME (illegal)",
   2802 				     ownerbuf, namebuf);
   2803 		}
   2804 		return (level == ISC_LOG_WARNING) ? true : false;
   2805 	}
   2806 
   2807 	if (result == DNS_R_DNAME) {
   2808 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
   2809 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
   2810 		{
   2811 			level = ISC_LOG_WARNING;
   2812 		}
   2813 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
   2814 			dns_name_format(foundname, altbuf, sizeof altbuf);
   2815 			dns_zone_log(zone, level,
   2816 				     "%s/MX '%s' is below a DNAME"
   2817 				     " '%s' (illegal)",
   2818 				     ownerbuf, namebuf, altbuf);
   2819 		}
   2820 		return (level == ISC_LOG_WARNING) ? true : false;
   2821 	}
   2822 
   2823 	if (zone->checkmx != NULL && result == DNS_R_DELEGATION) {
   2824 		return (zone->checkmx)(zone, name, owner);
   2825 	}
   2826 
   2827 	return true;
   2828 }
   2829 
   2830 static bool
   2831 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
   2832 	       dns_name_t *owner) {
   2833 	isc_result_t result;
   2834 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2835 	char namebuf[DNS_NAME_FORMATSIZE];
   2836 	char altbuf[DNS_NAME_FORMATSIZE];
   2837 	dns_fixedname_t fixed;
   2838 	dns_name_t *foundname;
   2839 	int level;
   2840 
   2841 	/*
   2842 	 * "." means the services does not exist.
   2843 	 */
   2844 	if (dns_name_equal(name, dns_rootname)) {
   2845 		return true;
   2846 	}
   2847 
   2848 	/*
   2849 	 * Outside of zone.
   2850 	 */
   2851 	if (!dns_name_issubdomain(name, &zone->origin)) {
   2852 		if (zone->checksrv != NULL) {
   2853 			return (zone->checksrv)(zone, name, owner);
   2854 		}
   2855 		return true;
   2856 	}
   2857 
   2858 	if (zone->type == dns_zone_primary) {
   2859 		level = ISC_LOG_ERROR;
   2860 	} else {
   2861 		level = ISC_LOG_WARNING;
   2862 	}
   2863 
   2864 	foundname = dns_fixedname_initname(&fixed);
   2865 
   2866 	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
   2867 			     foundname, NULL, NULL);
   2868 	if (result == ISC_R_SUCCESS) {
   2869 		return true;
   2870 	}
   2871 
   2872 	if (result == DNS_R_NXRRSET) {
   2873 		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
   2874 				     NULL, foundname, NULL, NULL);
   2875 		if (result == ISC_R_SUCCESS) {
   2876 			return true;
   2877 		}
   2878 	}
   2879 
   2880 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
   2881 	dns_name_format(name, namebuf, sizeof namebuf);
   2882 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   2883 	    result == DNS_R_EMPTYNAME)
   2884 	{
   2885 		dns_zone_log(zone, level,
   2886 			     "%s/SRV '%s' has no address records (A or AAAA)",
   2887 			     ownerbuf, namebuf);
   2888 		/* XXX950 make fatal for 9.5.0. */
   2889 		return true;
   2890 	}
   2891 
   2892 	if (result == DNS_R_CNAME) {
   2893 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
   2894 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
   2895 		{
   2896 			level = ISC_LOG_WARNING;
   2897 		}
   2898 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
   2899 			dns_zone_log(zone, level,
   2900 				     "%s/SRV '%s' is a CNAME (illegal)",
   2901 				     ownerbuf, namebuf);
   2902 		}
   2903 		return (level == ISC_LOG_WARNING) ? true : false;
   2904 	}
   2905 
   2906 	if (result == DNS_R_DNAME) {
   2907 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
   2908 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
   2909 		{
   2910 			level = ISC_LOG_WARNING;
   2911 		}
   2912 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
   2913 			dns_name_format(foundname, altbuf, sizeof altbuf);
   2914 			dns_zone_log(zone, level,
   2915 				     "%s/SRV '%s' is below a "
   2916 				     "DNAME '%s' (illegal)",
   2917 				     ownerbuf, namebuf, altbuf);
   2918 		}
   2919 		return (level == ISC_LOG_WARNING) ? true : false;
   2920 	}
   2921 
   2922 	if (zone->checksrv != NULL && result == DNS_R_DELEGATION) {
   2923 		return (zone->checksrv)(zone, name, owner);
   2924 	}
   2925 
   2926 	return true;
   2927 }
   2928 
   2929 static bool
   2930 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
   2931 		dns_name_t *owner) {
   2932 	bool answer = true;
   2933 	isc_result_t result, tresult;
   2934 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2935 	char namebuf[DNS_NAME_FORMATSIZE];
   2936 	char altbuf[DNS_NAME_FORMATSIZE];
   2937 	dns_fixedname_t fixed;
   2938 	dns_name_t *foundname;
   2939 	dns_rdataset_t a;
   2940 	dns_rdataset_t aaaa;
   2941 	int level;
   2942 
   2943 	/*
   2944 	 * Outside of zone.
   2945 	 */
   2946 	if (!dns_name_issubdomain(name, &zone->origin)) {
   2947 		if (zone->checkns != NULL) {
   2948 			return (zone->checkns)(zone, name, owner, NULL, NULL);
   2949 		}
   2950 		return true;
   2951 	}
   2952 
   2953 	if (zone->type == dns_zone_primary) {
   2954 		level = ISC_LOG_ERROR;
   2955 	} else {
   2956 		level = ISC_LOG_WARNING;
   2957 	}
   2958 
   2959 	foundname = dns_fixedname_initname(&fixed);
   2960 	dns_rdataset_init(&a);
   2961 	dns_rdataset_init(&aaaa);
   2962 
   2963 	/*
   2964 	 * Perform a regular lookup to catch DNAME records then look
   2965 	 * for glue.
   2966 	 */
   2967 	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
   2968 			     foundname, &a, NULL);
   2969 	switch (result) {
   2970 	case ISC_R_SUCCESS:
   2971 	case DNS_R_DNAME:
   2972 	case DNS_R_CNAME:
   2973 		break;
   2974 	default:
   2975 		if (dns_rdataset_isassociated(&a)) {
   2976 			dns_rdataset_disassociate(&a);
   2977 		}
   2978 		result = dns_db_find(db, name, NULL, dns_rdatatype_a,
   2979 				     DNS_DBFIND_GLUEOK, 0, NULL, foundname, &a,
   2980 				     NULL);
   2981 	}
   2982 	if (result == ISC_R_SUCCESS) {
   2983 		dns_rdataset_disassociate(&a);
   2984 		return true;
   2985 	} else if (result == DNS_R_DELEGATION) {
   2986 		dns_rdataset_disassociate(&a);
   2987 	}
   2988 
   2989 	if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
   2990 	    result == DNS_R_GLUE)
   2991 	{
   2992 		tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
   2993 				      DNS_DBFIND_GLUEOK, 0, NULL, foundname,
   2994 				      &aaaa, NULL);
   2995 		if (tresult == ISC_R_SUCCESS) {
   2996 			if (dns_rdataset_isassociated(&a)) {
   2997 				dns_rdataset_disassociate(&a);
   2998 			}
   2999 			dns_rdataset_disassociate(&aaaa);
   3000 			return true;
   3001 		}
   3002 		if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME) {
   3003 			dns_rdataset_disassociate(&aaaa);
   3004 		}
   3005 		if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
   3006 			/*
   3007 			 * Check glue against child zone.
   3008 			 */
   3009 			if (zone->checkns != NULL) {
   3010 				answer = (zone->checkns)(zone, name, owner, &a,
   3011 							 &aaaa);
   3012 			}
   3013 			if (dns_rdataset_isassociated(&a)) {
   3014 				dns_rdataset_disassociate(&a);
   3015 			}
   3016 			if (dns_rdataset_isassociated(&aaaa)) {
   3017 				dns_rdataset_disassociate(&aaaa);
   3018 			}
   3019 			return answer;
   3020 		}
   3021 	}
   3022 
   3023 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
   3024 	dns_name_format(name, namebuf, sizeof namebuf);
   3025 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   3026 	    result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION)
   3027 	{
   3028 		const char *what;
   3029 		bool required = false;
   3030 		if (dns_name_issubdomain(name, owner)) {
   3031 			what = "REQUIRED GLUE ";
   3032 			required = true;
   3033 		} else if (result == DNS_R_DELEGATION) {
   3034 			what = "SIBLING GLUE ";
   3035 		} else {
   3036 			what = "";
   3037 		}
   3038 
   3039 		if (result != DNS_R_DELEGATION || required ||
   3040 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING))
   3041 		{
   3042 			dns_zone_log(zone, level,
   3043 				     "%s/NS '%s' has no %s"
   3044 				     "address records (A or AAAA)",
   3045 				     ownerbuf, namebuf, what);
   3046 			/*
   3047 			 * Log missing address record.
   3048 			 */
   3049 			if (result == DNS_R_DELEGATION && zone->checkns != NULL)
   3050 			{
   3051 				(void)(zone->checkns)(zone, name, owner, &a,
   3052 						      &aaaa);
   3053 			}
   3054 			/* XXX950 make fatal for 9.5.0. */
   3055 			/* answer = false; */
   3056 		}
   3057 	} else if (result == DNS_R_CNAME) {
   3058 		dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
   3059 			     ownerbuf, namebuf);
   3060 		/* XXX950 make fatal for 9.5.0. */
   3061 		/* answer = false; */
   3062 	} else if (result == DNS_R_DNAME) {
   3063 		dns_name_format(foundname, altbuf, sizeof altbuf);
   3064 		dns_zone_log(zone, level,
   3065 			     "%s/NS '%s' is below a DNAME '%s' (illegal)",
   3066 			     ownerbuf, namebuf, altbuf);
   3067 		/* XXX950 make fatal for 9.5.0. */
   3068 		/* answer = false; */
   3069 	}
   3070 
   3071 	if (dns_rdataset_isassociated(&a)) {
   3072 		dns_rdataset_disassociate(&a);
   3073 	}
   3074 	if (dns_rdataset_isassociated(&aaaa)) {
   3075 		dns_rdataset_disassociate(&aaaa);
   3076 	}
   3077 	return answer;
   3078 }
   3079 
   3080 static bool
   3081 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
   3082 		     dns_rdataset_t *rdataset) {
   3083 	dns_rdataset_t tmprdataset;
   3084 	isc_result_t result;
   3085 	bool answer = true;
   3086 	bool format = true;
   3087 	int level = ISC_LOG_WARNING;
   3088 	char ownerbuf[DNS_NAME_FORMATSIZE];
   3089 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
   3090 	unsigned int count1 = 0;
   3091 
   3092 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL)) {
   3093 		level = ISC_LOG_ERROR;
   3094 	}
   3095 
   3096 	dns_rdataset_init(&tmprdataset);
   3097 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   3098 	     result = dns_rdataset_next(rdataset))
   3099 	{
   3100 		dns_rdata_t rdata1 = DNS_RDATA_INIT;
   3101 		unsigned int count2 = 0;
   3102 
   3103 		count1++;
   3104 		dns_rdataset_current(rdataset, &rdata1);
   3105 		dns_rdataset_clone(rdataset, &tmprdataset);
   3106 		for (result = dns_rdataset_first(&tmprdataset);
   3107 		     result == ISC_R_SUCCESS;
   3108 		     result = dns_rdataset_next(&tmprdataset))
   3109 		{
   3110 			dns_rdata_t rdata2 = DNS_RDATA_INIT;
   3111 			count2++;
   3112 			if (count1 >= count2) {
   3113 				continue;
   3114 			}
   3115 			dns_rdataset_current(&tmprdataset, &rdata2);
   3116 			if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
   3117 				if (format) {
   3118 					dns_name_format(owner, ownerbuf,
   3119 							sizeof ownerbuf);
   3120 					dns_rdatatype_format(rdata1.type,
   3121 							     typebuf,
   3122 							     sizeof(typebuf));
   3123 					format = false;
   3124 				}
   3125 				dns_zone_log(zone, level,
   3126 					     "%s/%s has "
   3127 					     "semantically identical records",
   3128 					     ownerbuf, typebuf);
   3129 				if (level == ISC_LOG_ERROR) {
   3130 					answer = false;
   3131 				}
   3132 				break;
   3133 			}
   3134 		}
   3135 		dns_rdataset_disassociate(&tmprdataset);
   3136 		if (!format) {
   3137 			break;
   3138 		}
   3139 	}
   3140 	return answer;
   3141 }
   3142 
   3143 static bool
   3144 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
   3145 	dns_dbiterator_t *dbiterator = NULL;
   3146 	dns_dbnode_t *node = NULL;
   3147 	dns_fixedname_t fixed;
   3148 	dns_name_t *name;
   3149 	dns_rdataset_t rdataset;
   3150 	dns_rdatasetiter_t *rdsit = NULL;
   3151 	bool ok = true;
   3152 	isc_result_t result;
   3153 
   3154 	name = dns_fixedname_initname(&fixed);
   3155 	dns_rdataset_init(&rdataset);
   3156 
   3157 	result = dns_db_createiterator(db, 0, &dbiterator);
   3158 	if (result != ISC_R_SUCCESS) {
   3159 		return true;
   3160 	}
   3161 
   3162 	for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
   3163 	     result = dns_dbiterator_next(dbiterator))
   3164 	{
   3165 		result = dns_dbiterator_current(dbiterator, &node, name);
   3166 		if (result != ISC_R_SUCCESS) {
   3167 			continue;
   3168 		}
   3169 
   3170 		result = dns_db_allrdatasets(db, node, NULL, 0, 0, &rdsit);
   3171 		if (result != ISC_R_SUCCESS) {
   3172 			continue;
   3173 		}
   3174 
   3175 		for (result = dns_rdatasetiter_first(rdsit);
   3176 		     result == ISC_R_SUCCESS;
   3177 		     result = dns_rdatasetiter_next(rdsit))
   3178 		{
   3179 			dns_rdatasetiter_current(rdsit, &rdataset);
   3180 			if (!zone_rrset_check_dup(zone, name, &rdataset)) {
   3181 				ok = false;
   3182 			}
   3183 			dns_rdataset_disassociate(&rdataset);
   3184 		}
   3185 		dns_rdatasetiter_destroy(&rdsit);
   3186 		dns_db_detachnode(db, &node);
   3187 	}
   3188 
   3189 	if (node != NULL) {
   3190 		dns_db_detachnode(db, &node);
   3191 	}
   3192 	dns_dbiterator_destroy(&dbiterator);
   3193 
   3194 	return ok;
   3195 }
   3196 
   3197 static bool
   3198 isspf(const dns_rdata_t *rdata) {
   3199 	char buf[1024];
   3200 	const unsigned char *data = rdata->data;
   3201 	unsigned int rdl = rdata->length, i = 0, tl, len;
   3202 
   3203 	while (rdl > 0U) {
   3204 		len = tl = *data;
   3205 		++data;
   3206 		--rdl;
   3207 		INSIST(tl <= rdl);
   3208 		if (len > sizeof(buf) - i - 1) {
   3209 			len = sizeof(buf) - i - 1;
   3210 		}
   3211 		memmove(buf + i, data, len);
   3212 		i += len;
   3213 		data += tl;
   3214 		rdl -= tl;
   3215 	}
   3216 
   3217 	if (i < 6U) {
   3218 		return false;
   3219 	}
   3220 
   3221 	buf[i] = 0;
   3222 	if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' ')) {
   3223 		return true;
   3224 	}
   3225 	return false;
   3226 }
   3227 
   3228 static bool
   3229 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
   3230 	dns_dbiterator_t *dbiterator = NULL;
   3231 	dns_dbnode_t *node = NULL;
   3232 	dns_rdataset_t rdataset;
   3233 	dns_fixedname_t fixed;
   3234 	dns_fixedname_t fixedbottom;
   3235 	dns_rdata_mx_t mx;
   3236 	dns_rdata_ns_t ns;
   3237 	dns_rdata_in_srv_t srv;
   3238 	dns_name_t *name;
   3239 	dns_name_t *bottom;
   3240 	isc_result_t result;
   3241 	bool ok = true, have_spf, have_txt;
   3242 	int level;
   3243 	char namebuf[DNS_NAME_FORMATSIZE];
   3244 	bool logged_algorithm[DST_MAX_ALGS];
   3245 	bool logged_digest_type[DNS_DSDIGEST_MAX + 1];
   3246 
   3247 	name = dns_fixedname_initname(&fixed);
   3248 	bottom = dns_fixedname_initname(&fixedbottom);
   3249 	dns_rdataset_init(&rdataset);
   3250 
   3251 	result = dns_db_createiterator(db, 0, &dbiterator);
   3252 	if (result != ISC_R_SUCCESS) {
   3253 		return true;
   3254 	}
   3255 
   3256 	result = dns_dbiterator_first(dbiterator);
   3257 	while (result == ISC_R_SUCCESS) {
   3258 		result = dns_dbiterator_current(dbiterator, &node, name);
   3259 		if (result != ISC_R_SUCCESS) {
   3260 			goto cleanup;
   3261 		}
   3262 
   3263 		/*
   3264 		 * Is this name visible in the zone?
   3265 		 */
   3266 		if (!dns_name_issubdomain(name, &zone->origin) ||
   3267 		    (dns_name_countlabels(bottom) > 0 &&
   3268 		     dns_name_issubdomain(name, bottom)))
   3269 		{
   3270 			goto next;
   3271 		}
   3272 
   3273 		dns_dbiterator_pause(dbiterator);
   3274 
   3275 		/*
   3276 		 * Check for deprecated KEY algorithms
   3277 		 */
   3278 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_key,
   3279 					     0, 0, &rdataset, NULL);
   3280 		if (result != ISC_R_SUCCESS) {
   3281 			goto checkforns;
   3282 		}
   3283 
   3284 		memset(logged_algorithm, 0, sizeof(logged_algorithm));
   3285 		for (result = dns_rdataset_first(&rdataset);
   3286 		     result == ISC_R_SUCCESS;
   3287 		     result = dns_rdataset_next(&rdataset))
   3288 		{
   3289 			dns_rdata_t rdata = DNS_RDATA_INIT;
   3290 			dns_rdata_key_t key;
   3291 			dns_rdataset_current(&rdataset, &rdata);
   3292 
   3293 			result = dns_rdata_tostruct(&rdata, &key, NULL);
   3294 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3295 
   3296 			/*
   3297 			 * If we ever deprecate a private algorithm use
   3298 			 * dst_algorithm_fromdata() here.
   3299 			 */
   3300 			switch (key.algorithm) {
   3301 			case DNS_KEYALG_RSASHA1:
   3302 			case DNS_KEYALG_NSEC3RSASHA1:
   3303 				if (!logged_algorithm[key.algorithm]) {
   3304 					char algbuf[DNS_SECALG_FORMATSIZE];
   3305 					dns_name_format(name, namebuf,
   3306 							sizeof(namebuf));
   3307 					dns_secalg_format(key.algorithm, algbuf,
   3308 							  sizeof(algbuf));
   3309 					dnssec_log(zone, ISC_LOG_WARNING,
   3310 						   "%s/KEY deprecated "
   3311 						   "algorithm %u (%s)",
   3312 						   namebuf, key.algorithm,
   3313 						   algbuf);
   3314 					logged_algorithm[key.algorithm] = true;
   3315 				}
   3316 				break;
   3317 			default:
   3318 				break;
   3319 			}
   3320 		}
   3321 		dns_rdataset_disassociate(&rdataset);
   3322 
   3323 	checkforns:
   3324 		/*
   3325 		 * Don't check the NS records at the origin.
   3326 		 */
   3327 		if (dns_name_equal(name, &zone->origin)) {
   3328 			goto checkfords;
   3329 		}
   3330 
   3331 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
   3332 					     0, 0, &rdataset, NULL);
   3333 		if (result != ISC_R_SUCCESS) {
   3334 			goto checkfords;
   3335 		}
   3336 
   3337 		/*
   3338 		 * Remember bottom of zone due to NS.
   3339 		 */
   3340 		dns_name_copy(name, bottom);
   3341 
   3342 		result = dns_rdataset_first(&rdataset);
   3343 		while (result == ISC_R_SUCCESS) {
   3344 			dns_rdata_t rdata = DNS_RDATA_INIT;
   3345 			dns_rdataset_current(&rdataset, &rdata);
   3346 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
   3347 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3348 			if (!zone_check_glue(zone, db, &ns.name, name)) {
   3349 				ok = false;
   3350 			}
   3351 			dns_rdata_reset(&rdata);
   3352 			result = dns_rdataset_next(&rdataset);
   3353 		}
   3354 		dns_rdataset_disassociate(&rdataset);
   3355 
   3356 		/*
   3357 		 * Check for deprecated DS digest types.
   3358 		 */
   3359 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds,
   3360 					     0, 0, &rdataset, NULL);
   3361 		if (result != ISC_R_SUCCESS) {
   3362 			goto next;
   3363 		}
   3364 
   3365 		memset(logged_algorithm, 0, sizeof(logged_algorithm));
   3366 		memset(logged_digest_type, 0, sizeof(logged_digest_type));
   3367 		for (result = dns_rdataset_first(&rdataset);
   3368 		     result == ISC_R_SUCCESS;
   3369 		     result = dns_rdataset_next(&rdataset))
   3370 		{
   3371 			dns_rdata_t rdata = DNS_RDATA_INIT;
   3372 			dns_rdataset_current(&rdataset, &rdata);
   3373 			dns_rdata_ds_t ds;
   3374 
   3375 			result = dns_rdata_tostruct(&rdata, &ds, NULL);
   3376 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3377 			switch (ds.digest_type) {
   3378 			case DNS_DSDIGEST_SHA1:
   3379 			case DNS_DSDIGEST_GOST:
   3380 				if (!logged_digest_type[ds.digest_type]) {
   3381 					char algbuf[DNS_DSDIGEST_FORMATSIZE];
   3382 					dns_name_format(name, namebuf,
   3383 							sizeof(namebuf));
   3384 					dns_dsdigest_format(ds.digest_type,
   3385 							    algbuf,
   3386 							    sizeof(algbuf));
   3387 					dnssec_log(zone, ISC_LOG_WARNING,
   3388 						   "%s/DS deprecated digest "
   3389 						   "type %u (%s)",
   3390 						   namebuf, ds.digest_type,
   3391 						   algbuf);
   3392 					logged_digest_type[ds.digest_type] =
   3393 						true;
   3394 				}
   3395 				break;
   3396 			}
   3397 
   3398 			/*
   3399 			 * If we ever deprecate a private algorithm use
   3400 			 * dst_algorithm_fromdata() here.
   3401 			 */
   3402 			switch (ds.algorithm) {
   3403 			case DNS_KEYALG_RSASHA1:
   3404 			case DNS_KEYALG_NSEC3RSASHA1:
   3405 				if (!logged_algorithm[ds.algorithm]) {
   3406 					char algbuf[DNS_SECALG_FORMATSIZE];
   3407 					dns_name_format(name, namebuf,
   3408 							sizeof(namebuf));
   3409 					dns_secalg_format(ds.algorithm, algbuf,
   3410 							  sizeof(algbuf));
   3411 					dnssec_log(zone, ISC_LOG_WARNING,
   3412 						   "%s/DS deprecated algorithm "
   3413 						   "%u (%s)",
   3414 						   namebuf, ds.algorithm,
   3415 						   algbuf);
   3416 					logged_algorithm[ds.algorithm] = true;
   3417 				}
   3418 				break;
   3419 			}
   3420 		}
   3421 		dns_rdataset_disassociate(&rdataset);
   3422 
   3423 		goto next;
   3424 
   3425 	checkfords:
   3426 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds,
   3427 					     0, 0, &rdataset, NULL);
   3428 		if (result != ISC_R_SUCCESS) {
   3429 			goto checkfordname;
   3430 		}
   3431 		dns_rdataset_disassociate(&rdataset);
   3432 
   3433 		if (zone->type == dns_zone_primary) {
   3434 			level = ISC_LOG_ERROR;
   3435 			ok = false;
   3436 		} else {
   3437 			level = ISC_LOG_WARNING;
   3438 		}
   3439 		dns_name_format(name, namebuf, sizeof(namebuf));
   3440 		dns_zone_log(zone, level, "DS not at delegation point (%s)",
   3441 			     namebuf);
   3442 
   3443 	checkfordname:
   3444 		result = dns_db_findrdataset(db, node, NULL,
   3445 					     dns_rdatatype_dname, 0, 0,
   3446 					     &rdataset, NULL);
   3447 		if (result == ISC_R_SUCCESS) {
   3448 			/*
   3449 			 * Remember bottom of zone due to DNAME.
   3450 			 */
   3451 			dns_name_copy(name, bottom);
   3452 			dns_rdataset_disassociate(&rdataset);
   3453 		}
   3454 
   3455 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
   3456 					     0, 0, &rdataset, NULL);
   3457 		if (result != ISC_R_SUCCESS) {
   3458 			goto checksrv;
   3459 		}
   3460 		result = dns_rdataset_first(&rdataset);
   3461 		while (result == ISC_R_SUCCESS) {
   3462 			dns_rdata_t rdata = DNS_RDATA_INIT;
   3463 			dns_rdataset_current(&rdataset, &rdata);
   3464 			result = dns_rdata_tostruct(&rdata, &mx, NULL);
   3465 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3466 			if (!zone_check_mx(zone, db, &mx.mx, name)) {
   3467 				ok = false;
   3468 			}
   3469 			dns_rdata_reset(&rdata);
   3470 			result = dns_rdataset_next(&rdataset);
   3471 		}
   3472 		dns_rdataset_disassociate(&rdataset);
   3473 
   3474 	checksrv:
   3475 		if (zone->rdclass != dns_rdataclass_in) {
   3476 			goto next;
   3477 		}
   3478 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
   3479 					     0, 0, &rdataset, NULL);
   3480 		if (result != ISC_R_SUCCESS) {
   3481 			goto checkspf;
   3482 		}
   3483 		result = dns_rdataset_first(&rdataset);
   3484 		while (result == ISC_R_SUCCESS) {
   3485 			dns_rdata_t rdata = DNS_RDATA_INIT;
   3486 			dns_rdataset_current(&rdataset, &rdata);
   3487 			result = dns_rdata_tostruct(&rdata, &srv, NULL);
   3488 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3489 			if (!zone_check_srv(zone, db, &srv.target, name)) {
   3490 				ok = false;
   3491 			}
   3492 			dns_rdata_reset(&rdata);
   3493 			result = dns_rdataset_next(&rdataset);
   3494 		}
   3495 		dns_rdataset_disassociate(&rdataset);
   3496 
   3497 	checkspf:
   3498 		/*
   3499 		 * Check if there is a type SPF record without an
   3500 		 * SPF-formatted type TXT record also being present.
   3501 		 */
   3502 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) {
   3503 			goto next;
   3504 		}
   3505 		if (zone->rdclass != dns_rdataclass_in) {
   3506 			goto next;
   3507 		}
   3508 		have_spf = have_txt = false;
   3509 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
   3510 					     0, 0, &rdataset, NULL);
   3511 		if (result == ISC_R_SUCCESS) {
   3512 			dns_rdataset_disassociate(&rdataset);
   3513 			have_spf = true;
   3514 		}
   3515 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
   3516 					     0, 0, &rdataset, NULL);
   3517 		if (result != ISC_R_SUCCESS) {
   3518 			goto notxt;
   3519 		}
   3520 		result = dns_rdataset_first(&rdataset);
   3521 		while (result == ISC_R_SUCCESS) {
   3522 			dns_rdata_t rdata = DNS_RDATA_INIT;
   3523 			dns_rdataset_current(&rdataset, &rdata);
   3524 			have_txt = isspf(&rdata);
   3525 			dns_rdata_reset(&rdata);
   3526 			if (have_txt) {
   3527 				break;
   3528 			}
   3529 			result = dns_rdataset_next(&rdataset);
   3530 		}
   3531 		dns_rdataset_disassociate(&rdataset);
   3532 
   3533 	notxt:
   3534 		if (have_spf && !have_txt) {
   3535 			dns_name_format(name, namebuf, sizeof(namebuf));
   3536 			dns_zone_log(zone, ISC_LOG_WARNING,
   3537 				     "'%s' found type "
   3538 				     "SPF record but no SPF TXT record found, "
   3539 				     "add matching type TXT record",
   3540 				     namebuf);
   3541 		}
   3542 
   3543 	next:
   3544 		dns_db_detachnode(db, &node);
   3545 		result = dns_dbiterator_next(dbiterator);
   3546 	}
   3547 
   3548 cleanup:
   3549 	if (node != NULL) {
   3550 		dns_db_detachnode(db, &node);
   3551 	}
   3552 	dns_dbiterator_destroy(&dbiterator);
   3553 
   3554 	return ok;
   3555 }
   3556 
   3557 /*
   3558  * OpenSSL verification of RSA keys with exponent 3 is known to be
   3559  * broken prior OpenSSL 0.9.8c/0.9.7k.	Look for such keys and warn
   3560  * if they are in use.
   3561  */
   3562 static void
   3563 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
   3564 	dns_dbnode_t *node = NULL;
   3565 	dns_dbversion_t *version = NULL;
   3566 	dns_rdata_dnskey_t dnskey;
   3567 	dns_rdataset_t rdataset;
   3568 	isc_result_t result;
   3569 	bool logged_algorithm[DST_MAX_ALGS] = { 0 };
   3570 	bool alldeprecated = true;
   3571 
   3572 	result = dns_db_findnode(db, &zone->origin, false, &node);
   3573 	if (result != ISC_R_SUCCESS) {
   3574 		goto cleanup;
   3575 	}
   3576 
   3577 	dns_db_currentversion(db, &version);
   3578 	dns_rdataset_init(&rdataset);
   3579 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
   3580 				     dns_rdatatype_none, 0, &rdataset, NULL);
   3581 	if (result != ISC_R_SUCCESS) {
   3582 		goto cleanup;
   3583 	}
   3584 
   3585 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   3586 	     result = dns_rdataset_next(&rdataset))
   3587 	{
   3588 		char algbuf[DNS_SECALG_FORMATSIZE];
   3589 		dns_rdata_t rdata = DNS_RDATA_INIT;
   3590 		dns_rdataset_current(&rdataset, &rdata);
   3591 		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
   3592 		INSIST(result == ISC_R_SUCCESS);
   3593 
   3594 		/*
   3595 		 * RFC 3110, section 4: Performance Considerations:
   3596 		 *
   3597 		 * A public exponent of 3 minimizes the effort needed to verify
   3598 		 * a signature.  Use of 3 as the public exponent is weak for
   3599 		 * confidentiality uses since, if the same data can be collected
   3600 		 * encrypted under three different keys with an exponent of 3
   3601 		 * then, using the Chinese Remainder Theorem [NETSEC], the
   3602 		 * original plain text can be easily recovered.  If a key is
   3603 		 * known to be used only for authentication, as is the case with
   3604 		 * DNSSEC, then an exponent of 3 is acceptable.  However other
   3605 		 * applications in the future may wish to leverage DNS
   3606 		 * distributed keys for applications that do require
   3607 		 * confidentiality.  For keys which might have such other uses,
   3608 		 * a more conservative choice would be 65537 (F4, the fourth
   3609 		 * fermat number).
   3610 		 */
   3611 		if (dnskey.datalen > 1 && dnskey.data[0] == 1 &&
   3612 		    dnskey.data[1] == 3 &&
   3613 		    (dnskey.algorithm == DNS_KEYALG_RSAMD5 ||
   3614 		     dnskey.algorithm == DNS_KEYALG_RSASHA1 ||
   3615 		     dnskey.algorithm == DNS_KEYALG_NSEC3RSASHA1 ||
   3616 		     dnskey.algorithm == DNS_KEYALG_RSASHA256 ||
   3617 		     dnskey.algorithm == DNS_KEYALG_RSASHA512))
   3618 		{
   3619 			char algorithm[DNS_SECALG_FORMATSIZE];
   3620 			isc_region_t r;
   3621 
   3622 			dns_rdata_toregion(&rdata, &r);
   3623 			dns_secalg_format(dnskey.algorithm, algorithm,
   3624 					  sizeof(algorithm));
   3625 
   3626 			dnssec_log(zone, ISC_LOG_WARNING,
   3627 				   "weak %s (%u) key found (exponent=3, id=%u)",
   3628 				   algorithm, dnskey.algorithm,
   3629 				   dst_region_computeid(&r));
   3630 		}
   3631 
   3632 		switch (dnskey.algorithm) {
   3633 		case DNS_KEYALG_RSAMD5:
   3634 		case DNS_KEYALG_DSA:
   3635 		case DNS_KEYALG_RSASHA1:
   3636 		case DNS_KEYALG_NSEC3DSA:
   3637 		case DNS_KEYALG_NSEC3RSASHA1:
   3638 		case DNS_KEYALG_ECCGOST:
   3639 			if (!logged_algorithm[dnskey.algorithm]) {
   3640 				dns_secalg_format(dnskey.algorithm, algbuf,
   3641 						  sizeof(algbuf));
   3642 				dnssec_log(zone, ISC_LOG_WARNING,
   3643 					   "deprecated DNSKEY algorithm found: "
   3644 					   "%u (%s)\n",
   3645 					   dnskey.algorithm, algbuf);
   3646 				logged_algorithm[dnskey.algorithm] = true;
   3647 			}
   3648 			break;
   3649 		default:
   3650 			alldeprecated = false;
   3651 			break;
   3652 		}
   3653 	}
   3654 	dns_rdataset_disassociate(&rdataset);
   3655 
   3656 	if (alldeprecated) {
   3657 		dnssec_log(zone, ISC_LOG_WARNING,
   3658 			   "all DNSKEY algorithms found are deprecated");
   3659 	}
   3660 
   3661 cleanup:
   3662 	if (node != NULL) {
   3663 		dns_db_detachnode(db, &node);
   3664 	}
   3665 	if (version != NULL) {
   3666 		dns_db_closeversion(db, &version, false);
   3667 	}
   3668 }
   3669 
   3670 static void
   3671 resume_signingwithkey(dns_zone_t *zone) {
   3672 	dns_dbnode_t *node = NULL;
   3673 	dns_dbversion_t *version = NULL;
   3674 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3675 	dns_rdataset_t rdataset;
   3676 	isc_result_t result;
   3677 	dns_db_t *db = NULL;
   3678 
   3679 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3680 	if (zone->db != NULL) {
   3681 		dns_db_attach(zone->db, &db);
   3682 	}
   3683 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3684 	if (db == NULL) {
   3685 		goto cleanup;
   3686 	}
   3687 
   3688 	result = dns_db_findnode(db, &zone->origin, false, &node);
   3689 	if (result != ISC_R_SUCCESS) {
   3690 		goto cleanup;
   3691 	}
   3692 
   3693 	dns_db_currentversion(db, &version);
   3694 	dns_rdataset_init(&rdataset);
   3695 	result = dns_db_findrdataset(db, node, version, zone->privatetype,
   3696 				     dns_rdatatype_none, 0, &rdataset, NULL);
   3697 	if (result != ISC_R_SUCCESS) {
   3698 		INSIST(!dns_rdataset_isassociated(&rdataset));
   3699 		goto cleanup;
   3700 	}
   3701 
   3702 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   3703 	     result = dns_rdataset_next(&rdataset))
   3704 	{
   3705 		dns_rdataset_current(&rdataset, &rdata);
   3706 		if (rdata.length != 5 || rdata.data[0] == 0 ||
   3707 		    rdata.data[4] != 0)
   3708 		{
   3709 			dns_rdata_reset(&rdata);
   3710 			continue;
   3711 		}
   3712 
   3713 		result = zone_signwithkey(zone, rdata.data[0],
   3714 					  (rdata.data[1] << 8) | rdata.data[2],
   3715 					  rdata.data[3], false);
   3716 		if (result != ISC_R_SUCCESS) {
   3717 			dnssec_log(zone, ISC_LOG_ERROR,
   3718 				   "zone_signwithkey failed: %s",
   3719 				   isc_result_totext(result));
   3720 		}
   3721 		dns_rdata_reset(&rdata);
   3722 	}
   3723 	dns_rdataset_disassociate(&rdataset);
   3724 
   3725 cleanup:
   3726 	if (db != NULL) {
   3727 		if (node != NULL) {
   3728 			dns_db_detachnode(db, &node);
   3729 		}
   3730 		if (version != NULL) {
   3731 			dns_db_closeversion(db, &version, false);
   3732 		}
   3733 		dns_db_detach(&db);
   3734 	}
   3735 }
   3736 
   3737 /*
   3738  * Initiate adding/removing NSEC3 records belonging to the chain defined by the
   3739  * supplied NSEC3PARAM RDATA.
   3740  *
   3741  * Zone must be locked by caller.
   3742  */
   3743 static isc_result_t
   3744 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
   3745 	dns_nsec3chain_t *nsec3chain, *current;
   3746 	dns_dbversion_t *version = NULL;
   3747 	bool nseconly = false, nsec3ok = false;
   3748 	isc_result_t result;
   3749 	isc_time_t now;
   3750 	unsigned int options = 0;
   3751 	char saltbuf[255 * 2 + 1];
   3752 	char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
   3753 	dns_db_t *db = NULL;
   3754 
   3755 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3756 	if (zone->db != NULL) {
   3757 		dns_db_attach(zone->db, &db);
   3758 	}
   3759 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3760 
   3761 	if (db == NULL) {
   3762 		result = ISC_R_SUCCESS;
   3763 		goto cleanup;
   3764 	}
   3765 
   3766 	/*
   3767 	 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
   3768 	 * chain from it is pointless as it would not be possible for the
   3769 	 * latter to exist in the first place.
   3770 	 */
   3771 	dns_db_currentversion(db, &version);
   3772 	result = dns_nsec_nseconly(db, version, NULL, &nseconly);
   3773 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
   3774 	dns_db_closeversion(db, &version, false);
   3775 	if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
   3776 		result = ISC_R_SUCCESS;
   3777 		goto cleanup;
   3778 	}
   3779 
   3780 	/*
   3781 	 * Allocate and initialize structure preserving state of
   3782 	 * adding/removing records belonging to this NSEC3 chain between
   3783 	 * separate zone_nsec3chain() calls.
   3784 	 */
   3785 	nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
   3786 
   3787 	nsec3chain->magic = 0;
   3788 	nsec3chain->done = false;
   3789 	nsec3chain->db = NULL;
   3790 	nsec3chain->dbiterator = NULL;
   3791 	nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
   3792 	nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
   3793 	nsec3chain->nsec3param.hash = nsec3param->hash;
   3794 	nsec3chain->nsec3param.iterations = nsec3param->iterations;
   3795 	nsec3chain->nsec3param.flags = nsec3param->flags;
   3796 	nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
   3797 	memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
   3798 	nsec3chain->nsec3param.salt = nsec3chain->salt;
   3799 	nsec3chain->seen_nsec = false;
   3800 	nsec3chain->delete_nsec = false;
   3801 	nsec3chain->save_delete_nsec = false;
   3802 
   3803 	/*
   3804 	 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
   3805 	 */
   3806 	if (nsec3param->flags == 0) {
   3807 		strlcpy(flags, "NONE", sizeof(flags));
   3808 	} else {
   3809 		flags[0] = '\0';
   3810 		if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
   3811 			strlcat(flags, "REMOVE", sizeof(flags));
   3812 		}
   3813 		if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
   3814 			if (flags[0] == '\0') {
   3815 				strlcpy(flags, "INITIAL", sizeof(flags));
   3816 			} else {
   3817 				strlcat(flags, "|INITIAL", sizeof(flags));
   3818 			}
   3819 		}
   3820 		if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
   3821 			if (flags[0] == '\0') {
   3822 				strlcpy(flags, "CREATE", sizeof(flags));
   3823 			} else {
   3824 				strlcat(flags, "|CREATE", sizeof(flags));
   3825 			}
   3826 		}
   3827 		if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
   3828 			if (flags[0] == '\0') {
   3829 				strlcpy(flags, "NONSEC", sizeof(flags));
   3830 			} else {
   3831 				strlcat(flags, "|NONSEC", sizeof(flags));
   3832 			}
   3833 		}
   3834 		if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
   3835 			if (flags[0] == '\0') {
   3836 				strlcpy(flags, "OPTOUT", sizeof(flags));
   3837 			} else {
   3838 				strlcat(flags, "|OPTOUT", sizeof(flags));
   3839 			}
   3840 		}
   3841 	}
   3842 	result = dns_nsec3param_salttotext(nsec3param, saltbuf,
   3843 					   sizeof(saltbuf));
   3844 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3845 	dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
   3846 		   nsec3param->hash, flags, nsec3param->iterations, saltbuf);
   3847 
   3848 	/*
   3849 	 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
   3850 	 * currently being processed, interrupt its processing to avoid
   3851 	 * simultaneously adding and removing records for the same NSEC3 chain.
   3852 	 */
   3853 	for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL;
   3854 	     current = ISC_LIST_NEXT(current, link))
   3855 	{
   3856 		if ((current->db == db) &&
   3857 		    (current->nsec3param.hash == nsec3param->hash) &&
   3858 		    (current->nsec3param.iterations ==
   3859 		     nsec3param->iterations) &&
   3860 		    (current->nsec3param.salt_length ==
   3861 		     nsec3param->salt_length) &&
   3862 		    memcmp(current->nsec3param.salt, nsec3param->salt,
   3863 			   nsec3param->salt_length) == 0)
   3864 		{
   3865 			current->done = true;
   3866 		}
   3867 	}
   3868 
   3869 	/*
   3870 	 * Attach zone database to the structure initialized above and create
   3871 	 * an iterator for it with appropriate options in order to avoid
   3872 	 * creating NSEC3 records for NSEC3 records.
   3873 	 */
   3874 	dns_db_attach(db, &nsec3chain->db);
   3875 	if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
   3876 		options = DNS_DB_NONSEC3;
   3877 	}
   3878 	result = dns_db_createiterator(nsec3chain->db, options,
   3879 				       &nsec3chain->dbiterator);
   3880 	if (result == ISC_R_SUCCESS) {
   3881 		result = dns_dbiterator_first(nsec3chain->dbiterator);
   3882 	}
   3883 	if (result == ISC_R_SUCCESS) {
   3884 		/*
   3885 		 * Database iterator initialization succeeded.  We are now
   3886 		 * ready to kick off adding/removing records belonging to this
   3887 		 * NSEC3 chain.  Append the structure initialized above to the
   3888 		 * "nsec3chain" list for the zone and set the appropriate zone
   3889 		 * timer so that zone_nsec3chain() is called as soon as
   3890 		 * possible.
   3891 		 */
   3892 		dns_dbiterator_pause(nsec3chain->dbiterator);
   3893 		ISC_LIST_INITANDAPPEND(zone->nsec3chain, nsec3chain, link);
   3894 		nsec3chain = NULL;
   3895 		if (isc_time_isepoch(&zone->nsec3chaintime)) {
   3896 			now = isc_time_now();
   3897 			zone->nsec3chaintime = now;
   3898 			if (zone->loop != NULL) {
   3899 				zone_settimer(zone, &now);
   3900 			}
   3901 		}
   3902 	}
   3903 
   3904 	if (nsec3chain != NULL) {
   3905 		if (nsec3chain->db != NULL) {
   3906 			dns_db_detach(&nsec3chain->db);
   3907 		}
   3908 		if (nsec3chain->dbiterator != NULL) {
   3909 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
   3910 		}
   3911 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   3912 	}
   3913 
   3914 cleanup:
   3915 	if (db != NULL) {
   3916 		dns_db_detach(&db);
   3917 	}
   3918 	return result;
   3919 }
   3920 
   3921 /*
   3922  * Find private-type records at the zone apex which signal that an NSEC3 chain
   3923  * should be added or removed.  For each such record, extract NSEC3PARAM RDATA
   3924  * and pass it to zone_addnsec3chain().
   3925  *
   3926  * Zone must be locked by caller.
   3927  */
   3928 static void
   3929 resume_addnsec3chain(dns_zone_t *zone) {
   3930 	dns_dbnode_t *node = NULL;
   3931 	dns_dbversion_t *version = NULL;
   3932 	dns_rdataset_t rdataset;
   3933 	isc_result_t result;
   3934 	dns_rdata_nsec3param_t nsec3param;
   3935 	bool nseconly = false, nsec3ok = false;
   3936 	dns_db_t *db = NULL;
   3937 
   3938 	INSIST(LOCKED_ZONE(zone));
   3939 
   3940 	if (zone->privatetype == 0) {
   3941 		return;
   3942 	}
   3943 
   3944 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3945 	if (zone->db != NULL) {
   3946 		dns_db_attach(zone->db, &db);
   3947 	}
   3948 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3949 	if (db == NULL) {
   3950 		goto cleanup;
   3951 	}
   3952 
   3953 	result = dns_db_findnode(db, &zone->origin, false, &node);
   3954 	if (result != ISC_R_SUCCESS) {
   3955 		goto cleanup;
   3956 	}
   3957 
   3958 	dns_db_currentversion(db, &version);
   3959 
   3960 	/*
   3961 	 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
   3962 	 * apex to exist and contain no keys using NSEC-only algorithms.
   3963 	 */
   3964 	result = dns_nsec_nseconly(db, version, NULL, &nseconly);
   3965 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
   3966 
   3967 	/*
   3968 	 * Get the RRset containing all private-type records at the zone apex.
   3969 	 */
   3970 	dns_rdataset_init(&rdataset);
   3971 	result = dns_db_findrdataset(db, node, version, zone->privatetype,
   3972 				     dns_rdatatype_none, 0, &rdataset, NULL);
   3973 	if (result != ISC_R_SUCCESS) {
   3974 		INSIST(!dns_rdataset_isassociated(&rdataset));
   3975 		goto cleanup;
   3976 	}
   3977 
   3978 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   3979 	     result = dns_rdataset_next(&rdataset))
   3980 	{
   3981 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   3982 		dns_rdata_t rdata = DNS_RDATA_INIT;
   3983 		dns_rdata_t private = DNS_RDATA_INIT;
   3984 
   3985 		dns_rdataset_current(&rdataset, &private);
   3986 		/*
   3987 		 * Try extracting NSEC3PARAM RDATA from this private-type
   3988 		 * record.  Failure means this private-type record does not
   3989 		 * represent an NSEC3PARAM record, so skip it.
   3990 		 */
   3991 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
   3992 						sizeof(buf)))
   3993 		{
   3994 			continue;
   3995 		}
   3996 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   3997 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3998 		if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
   3999 		    ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
   4000 		{
   4001 			/*
   4002 			 * Pass the NSEC3PARAM RDATA contained in this
   4003 			 * private-type record to zone_addnsec3chain() so that
   4004 			 * it can kick off adding or removing NSEC3 records.
   4005 			 */
   4006 			result = zone_addnsec3chain(zone, &nsec3param);
   4007 			if (result != ISC_R_SUCCESS) {
   4008 				dnssec_log(zone, ISC_LOG_ERROR,
   4009 					   "zone_addnsec3chain failed: %s",
   4010 					   isc_result_totext(result));
   4011 			}
   4012 		}
   4013 	}
   4014 	dns_rdataset_disassociate(&rdataset);
   4015 
   4016 cleanup:
   4017 	if (db != NULL) {
   4018 		if (node != NULL) {
   4019 			dns_db_detachnode(db, &node);
   4020 		}
   4021 		if (version != NULL) {
   4022 			dns_db_closeversion(db, &version, false);
   4023 		}
   4024 		dns_db_detach(&db);
   4025 	}
   4026 }
   4027 
   4028 static void
   4029 set_resigntime(dns_zone_t *zone) {
   4030 	dns_fixedname_t fixed;
   4031 	isc_stdtime_t resign;
   4032 	isc_result_t result;
   4033 	uint32_t nanosecs;
   4034 	dns_db_t *db = NULL;
   4035 	dns_typepair_t typepair;
   4036 
   4037 	INSIST(LOCKED_ZONE(zone));
   4038 
   4039 	/* We only re-sign zones that can be dynamically updated */
   4040 	if (!dns_zone_isdynamic(zone, false)) {
   4041 		return;
   4042 	}
   4043 
   4044 	if (inline_raw(zone)) {
   4045 		return;
   4046 	}
   4047 
   4048 	dns_fixedname_init(&fixed);
   4049 
   4050 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   4051 	if (zone->db != NULL) {
   4052 		dns_db_attach(zone->db, &db);
   4053 	}
   4054 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   4055 	if (db == NULL) {
   4056 		isc_time_settoepoch(&zone->resigntime);
   4057 		return;
   4058 	}
   4059 
   4060 	result = dns_db_getsigningtime(db, &resign, dns_fixedname_name(&fixed),
   4061 				       &typepair);
   4062 	if (result != ISC_R_SUCCESS) {
   4063 		isc_time_settoepoch(&zone->resigntime);
   4064 		goto cleanup;
   4065 	}
   4066 
   4067 	resign -= dns_zone_getsigresigninginterval(zone);
   4068 	nanosecs = isc_random_uniform(1000000000);
   4069 	isc_time_set(&zone->resigntime, resign, nanosecs);
   4070 
   4071 cleanup:
   4072 	dns_db_detach(&db);
   4073 	return;
   4074 }
   4075 
   4076 static isc_result_t
   4077 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
   4078 	bool ok = false;
   4079 	dns_dbnode_t *node = NULL;
   4080 	dns_dbversion_t *version = NULL;
   4081 	dns_rdata_nsec3param_t nsec3param;
   4082 	dns_rdataset_t rdataset;
   4083 	isc_result_t result;
   4084 	bool dynamic = (zone->type == dns_zone_primary)
   4085 			       ? dns_zone_isdynamic(zone, false)
   4086 			       : false;
   4087 
   4088 	dns_rdataset_init(&rdataset);
   4089 	result = dns_db_findnode(db, &zone->origin, false, &node);
   4090 	if (result != ISC_R_SUCCESS) {
   4091 		dns_zone_log(zone, ISC_LOG_ERROR,
   4092 			     "nsec3param lookup failure: %s",
   4093 			     isc_result_totext(result));
   4094 		return result;
   4095 	}
   4096 	dns_db_currentversion(db, &version);
   4097 
   4098 	result = dns_db_findrdataset(db, node, version,
   4099 				     dns_rdatatype_nsec3param,
   4100 				     dns_rdatatype_none, 0, &rdataset, NULL);
   4101 	if (result == ISC_R_NOTFOUND) {
   4102 		INSIST(!dns_rdataset_isassociated(&rdataset));
   4103 		result = ISC_R_SUCCESS;
   4104 		goto cleanup;
   4105 	}
   4106 	if (result != ISC_R_SUCCESS) {
   4107 		INSIST(!dns_rdataset_isassociated(&rdataset));
   4108 		dns_zone_log(zone, ISC_LOG_ERROR,
   4109 			     "nsec3param lookup failure: %s",
   4110 			     isc_result_totext(result));
   4111 		goto cleanup;
   4112 	}
   4113 
   4114 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   4115 	     result = dns_rdataset_next(&rdataset))
   4116 	{
   4117 		dns_rdata_t rdata = DNS_RDATA_INIT;
   4118 
   4119 		dns_rdataset_current(&rdataset, &rdata);
   4120 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   4121 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4122 
   4123 		/*
   4124 		 * For dynamic zones we must support every algorithm so we
   4125 		 * can regenerate all the NSEC3 chains.
   4126 		 * For non-dynamic zones we only need to find a supported
   4127 		 * algorithm.
   4128 		 */
   4129 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
   4130 		    nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
   4131 		{
   4132 			dns_zone_log(zone, ISC_LOG_WARNING,
   4133 				     "nsec3 test \"unknown\" hash algorithm "
   4134 				     "found: %u",
   4135 				     nsec3param.hash);
   4136 			ok = true;
   4137 		} else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
   4138 			if (dynamic) {
   4139 				dns_zone_log(zone, ISC_LOG_ERROR,
   4140 					     "unsupported nsec3 hash algorithm"
   4141 					     " in dynamic zone: %u",
   4142 					     nsec3param.hash);
   4143 				result = DNS_R_BADZONE;
   4144 				/* Stop second error message. */
   4145 				ok = true;
   4146 				break;
   4147 			} else {
   4148 				dns_zone_log(zone, ISC_LOG_WARNING,
   4149 					     "unsupported nsec3 hash "
   4150 					     "algorithm: %u",
   4151 					     nsec3param.hash);
   4152 			}
   4153 		} else {
   4154 			ok = true;
   4155 		}
   4156 
   4157 		/*
   4158 		 * Warn if the zone has excessive NSEC3 iterations.
   4159 		 */
   4160 		if (nsec3param.iterations > dns_nsec3_maxiterations()) {
   4161 			dnssec_log(zone, ISC_LOG_WARNING,
   4162 				   "excessive NSEC3PARAM iterations %u > %u",
   4163 				   nsec3param.iterations,
   4164 				   dns_nsec3_maxiterations());
   4165 		}
   4166 	}
   4167 	if (result == ISC_R_NOMORE) {
   4168 		result = ISC_R_SUCCESS;
   4169 	}
   4170 
   4171 	if (!ok) {
   4172 		result = DNS_R_BADZONE;
   4173 		dns_zone_log(zone, ISC_LOG_ERROR,
   4174 			     "no supported nsec3 hash algorithm");
   4175 	}
   4176 
   4177 cleanup:
   4178 	if (dns_rdataset_isassociated(&rdataset)) {
   4179 		dns_rdataset_disassociate(&rdataset);
   4180 	}
   4181 	dns_db_closeversion(db, &version, false);
   4182 	dns_db_detachnode(db, &node);
   4183 	return result;
   4184 }
   4185 
   4186 /*
   4187  * Set the timer for refreshing the key zone to the soonest future time
   4188  * of the set (current timer, keydata->refresh, keydata->addhd,
   4189  * keydata->removehd).
   4190  */
   4191 static void
   4192 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
   4193 		    isc_stdtime_t now, bool force) {
   4194 	isc_stdtime_t then;
   4195 	isc_time_t timenow, timethen;
   4196 	char timebuf[80];
   4197 
   4198 	ENTER;
   4199 	then = key->refresh;
   4200 	if (force) {
   4201 		then = now;
   4202 	}
   4203 	if (key->addhd > now && key->addhd < then) {
   4204 		then = key->addhd;
   4205 	}
   4206 	if (key->removehd > now && key->removehd < then) {
   4207 		then = key->removehd;
   4208 	}
   4209 
   4210 	timenow = isc_time_now();
   4211 	if (then > now) {
   4212 		DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
   4213 	} else {
   4214 		timethen = timenow;
   4215 	}
   4216 	if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
   4217 	    isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
   4218 	{
   4219 		zone->refreshkeytime = timethen;
   4220 	}
   4221 
   4222 	isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   4223 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
   4224 	zone_settimer(zone, &timenow);
   4225 }
   4226 
   4227 /*
   4228  * If keynode references a key or a DS rdataset, and if the key
   4229  * zone does not contain a KEYDATA record for the corresponding name,
   4230  * then create an empty KEYDATA and push it into the zone as a placeholder,
   4231  * then schedule a key refresh immediately. This new KEYDATA record will be
   4232  * updated during the refresh.
   4233  *
   4234  * If the key zone is changed, set '*changed' to true.
   4235  */
   4236 static isc_result_t
   4237 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   4238 	       dns_diff_t *diff, dns_keynode_t *keynode, dns_name_t *keyname,
   4239 	       bool *changed) {
   4240 	isc_result_t result = ISC_R_SUCCESS;
   4241 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4242 	dns_rdata_keydata_t kd;
   4243 	unsigned char rrdata[4096];
   4244 	isc_buffer_t rrdatabuf;
   4245 	isc_stdtime_t now = isc_stdtime_now();
   4246 
   4247 	REQUIRE(keynode != NULL);
   4248 
   4249 	ENTER;
   4250 
   4251 	/*
   4252 	 * If the keynode has no trust anchor set, we shouldn't be here.
   4253 	 */
   4254 	if (!dns_keynode_dsset(keynode, NULL)) {
   4255 		return ISC_R_FAILURE;
   4256 	}
   4257 
   4258 	memset(&kd, 0, sizeof(kd));
   4259 	kd.common.rdclass = zone->rdclass;
   4260 	kd.common.rdtype = dns_rdatatype_keydata;
   4261 	ISC_LINK_INIT(&kd.common, link);
   4262 
   4263 	isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
   4264 
   4265 	CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass, dns_rdatatype_keydata,
   4266 				   &kd, &rrdatabuf));
   4267 	/* Add rdata to zone. */
   4268 	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, keyname, 0, &rdata));
   4269 	*changed = true;
   4270 
   4271 	/* Refresh new keys from the zone apex as soon as possible. */
   4272 	set_refreshkeytimer(zone, &kd, now, true);
   4273 	return ISC_R_SUCCESS;
   4274 
   4275 cleanup:
   4276 	return result;
   4277 }
   4278 
   4279 /*
   4280  * Remove from the key zone all the KEYDATA records found in rdataset.
   4281  */
   4282 static isc_result_t
   4283 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
   4284 	       dns_name_t *name, dns_rdataset_t *rdataset) {
   4285 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4286 	isc_result_t result, uresult;
   4287 
   4288 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   4289 	     result = dns_rdataset_next(rdataset))
   4290 	{
   4291 		dns_rdata_reset(&rdata);
   4292 		dns_rdataset_current(rdataset, &rdata);
   4293 		uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name, 0,
   4294 					&rdata);
   4295 		if (uresult != ISC_R_SUCCESS) {
   4296 			return uresult;
   4297 		}
   4298 	}
   4299 	if (result == ISC_R_NOMORE) {
   4300 		result = ISC_R_SUCCESS;
   4301 	}
   4302 	return result;
   4303 }
   4304 
   4305 /*
   4306  * Compute the DNSSEC key ID for a DNSKEY record.
   4307  */
   4308 static isc_result_t
   4309 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
   4310 	    dns_keytag_t *tag) {
   4311 	isc_result_t result;
   4312 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4313 	unsigned char data[4096];
   4314 	isc_buffer_t buffer;
   4315 	dst_key_t *dstkey = NULL;
   4316 
   4317 	isc_buffer_init(&buffer, data, sizeof(data));
   4318 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
   4319 			     dns_rdatatype_dnskey, dnskey, &buffer);
   4320 
   4321 	result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
   4322 	if (result == ISC_R_SUCCESS) {
   4323 		*tag = dst_key_id(dstkey);
   4324 		dst_key_free(&dstkey);
   4325 	}
   4326 
   4327 	return result;
   4328 }
   4329 
   4330 /*
   4331  * Synth-from-dnssec callbacks to add/delete names from namespace tree.
   4332  */
   4333 static void
   4334 sfd_add(const dns_name_t *name, void *arg) {
   4335 	if (arg != NULL) {
   4336 		dns_view_sfd_add(arg, name);
   4337 	}
   4338 }
   4339 
   4340 static void
   4341 sfd_del(const dns_name_t *name, void *arg) {
   4342 	if (arg != NULL) {
   4343 		dns_view_sfd_del(arg, name);
   4344 	}
   4345 }
   4346 
   4347 /*
   4348  * Add key to the security roots.
   4349  */
   4350 static void
   4351 trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
   4352 	  bool initial) {
   4353 	isc_result_t result;
   4354 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4355 	unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
   4356 	isc_buffer_t buffer;
   4357 	dns_keytable_t *sr = NULL;
   4358 	dns_rdata_ds_t ds;
   4359 
   4360 	result = dns_view_getsecroots(zone->view, &sr);
   4361 	if (result != ISC_R_SUCCESS) {
   4362 		return;
   4363 	}
   4364 
   4365 	/* Build DS record for key. */
   4366 	isc_buffer_init(&buffer, data, sizeof(data));
   4367 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
   4368 			     dns_rdatatype_dnskey, dnskey, &buffer);
   4369 	CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
   4370 				  &ds));
   4371 	CHECK(dns_keytable_add(sr, true, initial, keyname, &ds, sfd_add,
   4372 			       zone->view));
   4373 
   4374 	dns_keytable_detach(&sr);
   4375 
   4376 cleanup:
   4377 	if (sr != NULL) {
   4378 		dns_keytable_detach(&sr);
   4379 	}
   4380 	return;
   4381 }
   4382 
   4383 /*
   4384  * Add a null key to the security roots for so that all queries
   4385  * to the zone will fail.
   4386  */
   4387 static void
   4388 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
   4389 	isc_result_t result;
   4390 	dns_keytable_t *sr = NULL;
   4391 
   4392 	result = dns_view_getsecroots(zone->view, &sr);
   4393 	if (result == ISC_R_SUCCESS) {
   4394 		dns_keytable_marksecure(sr, keyname);
   4395 		dns_keytable_detach(&sr);
   4396 	}
   4397 }
   4398 
   4399 /*
   4400  * Scan a set of KEYDATA records from the key zone.  The ones that are
   4401  * valid (i.e., the add holddown timer has expired) become trusted keys.
   4402  */
   4403 static void
   4404 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
   4405 	isc_result_t result;
   4406 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4407 	dns_rdata_keydata_t keydata;
   4408 	dns_rdata_dnskey_t dnskey;
   4409 	int trusted = 0, revoked = 0, pending = 0;
   4410 	isc_stdtime_t now = isc_stdtime_now();
   4411 	dns_keytable_t *sr = NULL;
   4412 
   4413 	result = dns_view_getsecroots(zone->view, &sr);
   4414 	if (result == ISC_R_SUCCESS) {
   4415 		dns_keytable_delete(sr, name, sfd_del, zone->view);
   4416 		dns_keytable_detach(&sr);
   4417 	}
   4418 
   4419 	/* Now insert all the accepted trust anchors from this keydata set. */
   4420 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   4421 	     result = dns_rdataset_next(rdataset))
   4422 	{
   4423 		dns_rdata_reset(&rdata);
   4424 		dns_rdataset_current(rdataset, &rdata);
   4425 
   4426 		/* Convert rdata to keydata. */
   4427 		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
   4428 		if (result == ISC_R_NOTIMPLEMENTED) {
   4429 			continue;
   4430 		}
   4431 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4432 
   4433 		/* Set the key refresh timer to force a fast refresh. */
   4434 		set_refreshkeytimer(zone, &keydata, now, true);
   4435 
   4436 		/* If the removal timer is nonzero, this key was revoked. */
   4437 		if (keydata.removehd != 0) {
   4438 			revoked++;
   4439 			continue;
   4440 		}
   4441 
   4442 		/*
   4443 		 * If the add timer is still pending, this key is not
   4444 		 * trusted yet.
   4445 		 */
   4446 		if (now < keydata.addhd) {
   4447 			pending++;
   4448 			continue;
   4449 		}
   4450 
   4451 		/* Convert keydata to dnskey. */
   4452 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
   4453 
   4454 		/* Add to keytables. */
   4455 		trusted++;
   4456 		trust_key(zone, name, &dnskey, keydata.addhd == 0);
   4457 	}
   4458 
   4459 	if (trusted == 0 && pending != 0) {
   4460 		char namebuf[DNS_NAME_FORMATSIZE];
   4461 		dns_name_format(name, namebuf, sizeof namebuf);
   4462 		dnssec_log(zone, ISC_LOG_ERROR,
   4463 			   "No valid trust anchors for '%s'!", namebuf);
   4464 		dnssec_log(zone, ISC_LOG_ERROR,
   4465 			   "%d key(s) revoked, %d still pending", revoked,
   4466 			   pending);
   4467 		dnssec_log(zone, ISC_LOG_ERROR, "All queries to '%s' will fail",
   4468 			   namebuf);
   4469 		fail_secure(zone, name);
   4470 	}
   4471 }
   4472 
   4473 static isc_result_t
   4474 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
   4475 	     dns_diff_t *diff) {
   4476 	dns_diff_t temp_diff;
   4477 	isc_result_t result;
   4478 
   4479 	/*
   4480 	 * Create a singleton diff.
   4481 	 */
   4482 	dns_diff_init(diff->mctx, &temp_diff);
   4483 	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
   4484 
   4485 	/*
   4486 	 * Apply it to the database.
   4487 	 */
   4488 	result = dns_diff_apply(&temp_diff, db, ver);
   4489 	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
   4490 	if (result != ISC_R_SUCCESS) {
   4491 		dns_difftuple_free(tuple);
   4492 		return result;
   4493 	}
   4494 
   4495 	/*
   4496 	 * Merge it into the current pending journal entry.
   4497 	 */
   4498 	dns_diff_appendminimal(diff, tuple);
   4499 
   4500 	/*
   4501 	 * Do not clear temp_diff.
   4502 	 */
   4503 	return ISC_R_SUCCESS;
   4504 }
   4505 
   4506 static isc_result_t
   4507 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
   4508 	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
   4509 	      dns_rdata_t *rdata) {
   4510 	dns_difftuple_t *tuple = NULL;
   4511 	isc_result_t result;
   4512 	result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
   4513 	if (result != ISC_R_SUCCESS) {
   4514 		return result;
   4515 	}
   4516 	return do_one_tuple(&tuple, db, ver, diff);
   4517 }
   4518 
   4519 static isc_result_t
   4520 update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   4521 		  dns_diff_t *diff, isc_mem_t *mctx,
   4522 		  dns_updatemethod_t method) {
   4523 	dns_difftuple_t *deltuple = NULL;
   4524 	dns_difftuple_t *addtuple = NULL;
   4525 	uint32_t serial;
   4526 	isc_result_t result;
   4527 	dns_updatemethod_t used = dns_updatemethod_none;
   4528 
   4529 	INSIST(method != dns_updatemethod_none);
   4530 
   4531 	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
   4532 	CHECK(dns_difftuple_copy(deltuple, &addtuple));
   4533 	addtuple->op = DNS_DIFFOP_ADD;
   4534 
   4535 	serial = dns_soa_getserial(&addtuple->rdata);
   4536 	serial = dns_update_soaserial(serial, method, &used);
   4537 	if (method != used) {
   4538 		dns_zone_log(zone, ISC_LOG_WARNING,
   4539 			     "update_soa_serial:new serial would be lower than "
   4540 			     "old serial, using increment method instead");
   4541 	}
   4542 	dns_soa_setserial(serial, &addtuple->rdata);
   4543 	CHECK(do_one_tuple(&deltuple, db, ver, diff));
   4544 	CHECK(do_one_tuple(&addtuple, db, ver, diff));
   4545 	result = ISC_R_SUCCESS;
   4546 
   4547 cleanup:
   4548 	if (addtuple != NULL) {
   4549 		dns_difftuple_free(&addtuple);
   4550 	}
   4551 	if (deltuple != NULL) {
   4552 		dns_difftuple_free(&deltuple);
   4553 	}
   4554 	return result;
   4555 }
   4556 
   4557 /*
   4558  * Write all transactions in 'diff' to the zone journal file.
   4559  */
   4560 static isc_result_t
   4561 zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
   4562 	     const char *caller) {
   4563 	const char *journalfile;
   4564 	isc_result_t result = ISC_R_SUCCESS;
   4565 	dns_journal_t *journal = NULL;
   4566 	unsigned int mode = DNS_JOURNAL_CREATE | DNS_JOURNAL_WRITE;
   4567 
   4568 	ENTER;
   4569 	journalfile = dns_zone_getjournal(zone);
   4570 	if (journalfile != NULL) {
   4571 		result = dns_journal_open(zone->mctx, journalfile, mode,
   4572 					  &journal);
   4573 		if (result != ISC_R_SUCCESS) {
   4574 			dns_zone_log(zone, ISC_LOG_ERROR,
   4575 				     "%s:dns_journal_open -> %s", caller,
   4576 				     isc_result_totext(result));
   4577 			return result;
   4578 		}
   4579 
   4580 		if (sourceserial != NULL) {
   4581 			dns_journal_set_sourceserial(journal, *sourceserial);
   4582 		}
   4583 
   4584 		result = dns_journal_write_transaction(journal, diff);
   4585 		if (result != ISC_R_SUCCESS) {
   4586 			dns_zone_log(zone, ISC_LOG_ERROR,
   4587 				     "%s:dns_journal_write_transaction -> %s",
   4588 				     caller, isc_result_totext(result));
   4589 		}
   4590 		dns_journal_destroy(&journal);
   4591 	}
   4592 
   4593 	return result;
   4594 }
   4595 
   4596 /*
   4597  * Create an SOA record for a newly-created zone
   4598  */
   4599 static isc_result_t
   4600 add_soa(dns_zone_t *zone, dns_db_t *db) {
   4601 	isc_result_t result;
   4602 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4603 	unsigned char buf[DNS_SOA_BUFFERSIZE];
   4604 	dns_dbversion_t *ver = NULL;
   4605 	dns_diff_t diff;
   4606 
   4607 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
   4608 
   4609 	dns_diff_init(zone->mctx, &diff);
   4610 	result = dns_db_newversion(db, &ver);
   4611 	if (result != ISC_R_SUCCESS) {
   4612 		dns_zone_log(zone, ISC_LOG_ERROR,
   4613 			     "add_soa:dns_db_newversion -> %s",
   4614 			     isc_result_totext(result));
   4615 		goto cleanup;
   4616 	}
   4617 
   4618 	/* Build SOA record */
   4619 	result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
   4620 				    0, 0, 0, 0, 0, buf, &rdata);
   4621 	if (result != ISC_R_SUCCESS) {
   4622 		dns_zone_log(zone, ISC_LOG_ERROR,
   4623 			     "add_soa:dns_soa_buildrdata -> %s",
   4624 			     isc_result_totext(result));
   4625 		goto cleanup;
   4626 	}
   4627 
   4628 	result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, &zone->origin, 0,
   4629 			       &rdata);
   4630 
   4631 cleanup:
   4632 	dns_diff_clear(&diff);
   4633 	if (ver != NULL) {
   4634 		dns_db_closeversion(db, &ver, result == ISC_R_SUCCESS);
   4635 	}
   4636 
   4637 	INSIST(ver == NULL);
   4638 
   4639 	return result;
   4640 }
   4641 
   4642 struct addifmissing_arg {
   4643 	dns_db_t *db;
   4644 	dns_dbversion_t *ver;
   4645 	dns_diff_t *diff;
   4646 	dns_zone_t *zone;
   4647 	bool *changed;
   4648 	isc_result_t result;
   4649 };
   4650 
   4651 static void
   4652 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
   4653 	     dns_name_t *keyname, void *arg) {
   4654 	dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
   4655 	dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
   4656 	dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
   4657 	dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
   4658 	bool *changed = ((struct addifmissing_arg *)arg)->changed;
   4659 	isc_result_t result;
   4660 	dns_fixedname_t fname;
   4661 
   4662 	UNUSED(keytable);
   4663 
   4664 	if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS) {
   4665 		return;
   4666 	}
   4667 
   4668 	if (!dns_keynode_managed(keynode)) {
   4669 		return;
   4670 	}
   4671 
   4672 	/*
   4673 	 * If the keynode has no trust anchor set, return.
   4674 	 */
   4675 	if (!dns_keynode_dsset(keynode, NULL)) {
   4676 		return;
   4677 	}
   4678 
   4679 	/*
   4680 	 * Check whether there's already a KEYDATA entry for this name;
   4681 	 * if so, we don't need to add another.
   4682 	 */
   4683 	dns_fixedname_init(&fname);
   4684 	result = dns_db_find(db, keyname, ver, dns_rdatatype_keydata,
   4685 			     DNS_DBFIND_NOWILD, 0, NULL,
   4686 			     dns_fixedname_name(&fname), NULL, NULL);
   4687 	if (result == ISC_R_SUCCESS) {
   4688 		return;
   4689 	}
   4690 
   4691 	/*
   4692 	 * Create the keydata.
   4693 	 */
   4694 	result = create_keydata(zone, db, ver, diff, keynode, keyname, changed);
   4695 	if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
   4696 		((struct addifmissing_arg *)arg)->result = result;
   4697 	}
   4698 }
   4699 
   4700 /*
   4701  * Synchronize the set of initializing keys found in managed-keys {}
   4702  * statements with the set of trust anchors found in the managed-keys.bind
   4703  * zone.  If a domain is no longer named in managed-keys, delete all keys
   4704  * from that domain from the key zone.	If a domain is configured as an
   4705  * initial-key in trust-anchors, but there are no references to it in the
   4706  * key zone, load the key zone with the initializing key(s) for that
   4707  * domain and schedule a key refresh. If a domain is configured as
   4708  * an initial-ds in trust-anchors, fetch the DNSKEY RRset, load the key
   4709  * zone with the matching key, and schedule a key refresh.
   4710  */
   4711 static isc_result_t
   4712 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
   4713 	isc_result_t result = ISC_R_SUCCESS;
   4714 	bool changed = false;
   4715 	bool commit = false;
   4716 	dns_keynode_t *keynode = NULL;
   4717 	dns_view_t *view = zone->view;
   4718 	dns_keytable_t *sr = NULL;
   4719 	dns_dbversion_t *ver = NULL;
   4720 	dns_diff_t diff;
   4721 	dns_rriterator_t rrit;
   4722 	struct addifmissing_arg arg;
   4723 
   4724 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
   4725 
   4726 	dns_diff_init(zone->mctx, &diff);
   4727 
   4728 	CHECK(dns_view_getsecroots(view, &sr));
   4729 
   4730 	result = dns_db_newversion(db, &ver);
   4731 	if (result != ISC_R_SUCCESS) {
   4732 		dnssec_log(zone, ISC_LOG_ERROR,
   4733 			   "sync_keyzone:dns_db_newversion -> %s",
   4734 			   isc_result_totext(result));
   4735 		goto cleanup;
   4736 	}
   4737 
   4738 	/*
   4739 	 * Walk the zone DB.  If we find any keys whose names are no longer
   4740 	 * in trust-anchors, or which have been changed from initial to static,
   4741 	 * (meaning they are permanent and not RFC5011-maintained), delete
   4742 	 * them from the zone.  Otherwise call load_secroots(), which
   4743 	 * loads keys into secroots as appropriate.
   4744 	 */
   4745 	dns_rriterator_init(&rrit, db, ver, 0);
   4746 	for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
   4747 	     result = dns_rriterator_nextrrset(&rrit))
   4748 	{
   4749 		dns_rdataset_t *rdataset = NULL;
   4750 		dns_rdata_t rdata = DNS_RDATA_INIT;
   4751 		dns_rdata_keydata_t keydata;
   4752 		isc_stdtime_t now = isc_stdtime_now();
   4753 		bool load = true;
   4754 		dns_name_t *rrname = NULL;
   4755 		uint32_t ttl;
   4756 
   4757 		dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
   4758 		if (!dns_rdataset_isassociated(rdataset)) {
   4759 			dns_rriterator_destroy(&rrit);
   4760 			goto cleanup;
   4761 		}
   4762 
   4763 		if (rdataset->type != dns_rdatatype_keydata) {
   4764 			continue;
   4765 		}
   4766 
   4767 		/*
   4768 		 * The managed-keys zone can contain a placeholder instead of
   4769 		 * legitimate data, in which case we will not use it, and we
   4770 		 * will try to refresh it.
   4771 		 */
   4772 		for (result = dns_rdataset_first(rdataset);
   4773 		     result == ISC_R_SUCCESS;
   4774 		     result = dns_rdataset_next(rdataset))
   4775 		{
   4776 			isc_result_t iresult;
   4777 
   4778 			dns_rdata_reset(&rdata);
   4779 			dns_rdataset_current(rdataset, &rdata);
   4780 
   4781 			iresult = dns_rdata_tostruct(&rdata, &keydata, NULL);
   4782 			/* Do we have a valid placeholder KEYDATA record? */
   4783 			if (iresult == ISC_R_SUCCESS && keydata.flags == 0 &&
   4784 			    keydata.protocol == 0 && keydata.algorithm == 0)
   4785 			{
   4786 				set_refreshkeytimer(zone, &keydata, now, true);
   4787 				load = false;
   4788 			}
   4789 		}
   4790 
   4791 		/*
   4792 		 * Release db wrlock to prevent LOR reports against
   4793 		 * dns_keytable_forall() call below.
   4794 		 */
   4795 		dns_rriterator_pause(&rrit);
   4796 		result = dns_keytable_find(sr, rrname, &keynode);
   4797 		if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
   4798 			CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
   4799 			changed = true;
   4800 		} else if (load) {
   4801 			load_secroots(zone, rrname, rdataset);
   4802 		}
   4803 
   4804 		if (keynode != NULL) {
   4805 			dns_keynode_detach(&keynode);
   4806 		}
   4807 	}
   4808 	dns_rriterator_destroy(&rrit);
   4809 
   4810 	/*
   4811 	 * Walk secroots to find any initial keys that aren't in
   4812 	 * the zone.  If we find any, add them to the zone directly.
   4813 	 * If any DS-style initial keys are found, refresh the key
   4814 	 * zone so that they'll be looked up.
   4815 	 */
   4816 	arg.db = db;
   4817 	arg.ver = ver;
   4818 	arg.result = ISC_R_SUCCESS;
   4819 	arg.diff = &diff;
   4820 	arg.zone = zone;
   4821 	arg.changed = &changed;
   4822 	dns_keytable_forall(sr, addifmissing, &arg);
   4823 	result = arg.result;
   4824 	if (changed) {
   4825 		/* Write changes to journal file. */
   4826 		CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
   4827 					zone->updatemethod));
   4828 		CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
   4829 
   4830 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   4831 		zone_needdump(zone, 30);
   4832 		commit = true;
   4833 	}
   4834 
   4835 cleanup:
   4836 	if (result != ISC_R_SUCCESS) {
   4837 		dnssec_log(zone, ISC_LOG_ERROR,
   4838 			   "unable to synchronize managed keys: %s",
   4839 			   isc_result_totext(result));
   4840 		isc_time_settoepoch(&zone->refreshkeytime);
   4841 	}
   4842 	if (keynode != NULL) {
   4843 		dns_keynode_detach(&keynode);
   4844 	}
   4845 	if (sr != NULL) {
   4846 		dns_keytable_detach(&sr);
   4847 	}
   4848 	if (ver != NULL) {
   4849 		dns_db_closeversion(db, &ver, commit);
   4850 	}
   4851 	dns_diff_clear(&diff);
   4852 
   4853 	INSIST(ver == NULL);
   4854 
   4855 	return result;
   4856 }
   4857 
   4858 isc_result_t
   4859 dns_zone_synckeyzone(dns_zone_t *zone) {
   4860 	isc_result_t result;
   4861 	dns_db_t *db = NULL;
   4862 
   4863 	if (zone->type != dns_zone_key) {
   4864 		return DNS_R_BADZONE;
   4865 	}
   4866 
   4867 	CHECK(dns_zone_getdb(zone, &db));
   4868 
   4869 	LOCK_ZONE(zone);
   4870 	result = sync_keyzone(zone, db);
   4871 	UNLOCK_ZONE(zone);
   4872 
   4873 cleanup:
   4874 	if (db != NULL) {
   4875 		dns_db_detach(&db);
   4876 	}
   4877 	return result;
   4878 }
   4879 
   4880 static void
   4881 maybe_send_secure(dns_zone_t *zone) {
   4882 	isc_result_t result;
   4883 
   4884 	/*
   4885 	 * We've finished loading, or else failed to load, an inline-signing
   4886 	 * 'secure' zone.  We now need information about the status of the
   4887 	 * 'raw' zone.  If we failed to load, then we need it to send a
   4888 	 * copy of its database; if we succeeded, we need it to send its
   4889 	 * serial number so that we can sync with it.  If it has not yet
   4890 	 * loaded, we set a flag so that it will send the necessary
   4891 	 * information when it has finished loading.
   4892 	 */
   4893 	if (zone->raw->db != NULL) {
   4894 		if (zone->db != NULL) {
   4895 			uint32_t serial;
   4896 			unsigned int soacount;
   4897 
   4898 			result = zone_get_from_db(
   4899 				zone->raw, zone->raw->db, NULL, &soacount, NULL,
   4900 				&serial, NULL, NULL, NULL, NULL, NULL);
   4901 			if (result == ISC_R_SUCCESS && soacount > 0U) {
   4902 				zone_send_secureserial(zone->raw, serial);
   4903 			}
   4904 		} else {
   4905 			zone_send_securedb(zone->raw, zone->raw->db);
   4906 		}
   4907 	} else {
   4908 		DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
   4909 	}
   4910 }
   4911 
   4912 static bool
   4913 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
   4914 	isc_result_t result;
   4915 	bool answer = false;
   4916 	dns_diff_t diff;
   4917 
   4918 	dns_diff_init(mctx, &diff);
   4919 	result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
   4920 	if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) {
   4921 		answer = true;
   4922 	}
   4923 	dns_diff_clear(&diff);
   4924 	return answer;
   4925 }
   4926 
   4927 static void
   4928 process_zone_setnsec3param(dns_zone_t *zone) {
   4929 	struct np3 *npe = NULL;
   4930 	while ((npe = ISC_LIST_HEAD(zone->setnsec3param_queue)) != NULL) {
   4931 		ISC_LIST_UNLINK(zone->setnsec3param_queue, npe, link);
   4932 		zone_iattach(zone, &npe->zone);
   4933 		isc_async_run(zone->loop, setnsec3param, npe);
   4934 	}
   4935 }
   4936 
   4937 /*
   4938  * The zone is presumed to be locked.
   4939  * If this is a inline_raw zone the secure version is also locked.
   4940  */
   4941 static isc_result_t
   4942 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
   4943 	      isc_result_t result) {
   4944 	unsigned int soacount = 0;
   4945 	unsigned int nscount = 0;
   4946 	unsigned int errors = 0;
   4947 	uint32_t serial, oldserial, refresh, retry, expire, minimum, soattl;
   4948 	isc_time_t now;
   4949 	bool needdump = false;
   4950 	bool fixjournal = false;
   4951 	bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
   4952 	bool noprimary = false;
   4953 	bool had_db = false;
   4954 	dns_include_t *inc;
   4955 	bool is_dynamic = false;
   4956 
   4957 	INSIST(LOCKED_ZONE(zone));
   4958 	if (inline_raw(zone)) {
   4959 		INSIST(LOCKED_ZONE(zone->secure));
   4960 	}
   4961 
   4962 	now = isc_time_now();
   4963 
   4964 	/*
   4965 	 * Initiate zone transfer?  We may need a error code that
   4966 	 * indicates that the "permanent" form does not exist.
   4967 	 * XXX better error feedback to log.
   4968 	 */
   4969 	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
   4970 		if (zone->type == dns_zone_secondary ||
   4971 		    zone->type == dns_zone_mirror ||
   4972 		    zone->type == dns_zone_stub ||
   4973 		    (zone->type == dns_zone_redirect &&
   4974 		     dns_remote_addresses(&zone->primaries) == NULL))
   4975 		{
   4976 			if (result == ISC_R_FILENOTFOUND) {
   4977 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4978 					      ISC_LOG_DEBUG(1),
   4979 					      "no master file");
   4980 			} else if (result != DNS_R_NOMASTERFILE) {
   4981 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4982 					      ISC_LOG_ERROR,
   4983 					      "loading from master file %s "
   4984 					      "failed: %s",
   4985 					      zone->masterfile,
   4986 					      isc_result_totext(result));
   4987 			}
   4988 		} else if (zone->type == dns_zone_primary &&
   4989 			   inline_secure(zone) && result == ISC_R_FILENOTFOUND)
   4990 		{
   4991 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4992 				      ISC_LOG_DEBUG(1),
   4993 				      "no master file, requesting db");
   4994 			maybe_send_secure(zone);
   4995 		} else {
   4996 			int level = ISC_LOG_ERROR;
   4997 			if (zone->type == dns_zone_key &&
   4998 			    result == ISC_R_FILENOTFOUND)
   4999 			{
   5000 				level = ISC_LOG_DEBUG(1);
   5001 			}
   5002 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
   5003 				      "loading from master file %s failed: %s",
   5004 				      zone->masterfile,
   5005 				      isc_result_totext(result));
   5006 			noprimary = true;
   5007 		}
   5008 
   5009 		if (zone->type != dns_zone_key) {
   5010 			goto cleanup;
   5011 		}
   5012 	}
   5013 
   5014 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
   5015 		      "number of nodes in database: %u",
   5016 		      dns_db_nodecount(db, dns_dbtree_main));
   5017 
   5018 	if (result == DNS_R_SEENINCLUDE) {
   5019 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
   5020 	} else {
   5021 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
   5022 	}
   5023 
   5024 	/*
   5025 	 * If there's no master file for a key zone, then the zone is new:
   5026 	 * create an SOA record.  (We do this now, instead of later, so that
   5027 	 * if there happens to be a journal file, we can roll forward from
   5028 	 * a sane starting point.)
   5029 	 */
   5030 	if (noprimary && zone->type == dns_zone_key) {
   5031 		result = add_soa(zone, db);
   5032 		if (result != ISC_R_SUCCESS) {
   5033 			goto cleanup;
   5034 		}
   5035 	}
   5036 
   5037 	/*
   5038 	 * Apply update log, if any, on initial load.
   5039 	 */
   5040 	if (zone->journal != NULL &&
   5041 	    !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
   5042 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   5043 	{
   5044 		result = zone_journal_rollforward(zone, db, &needdump,
   5045 						  &fixjournal);
   5046 		if (result != ISC_R_SUCCESS) {
   5047 			goto cleanup;
   5048 		}
   5049 	}
   5050 
   5051 	/*
   5052 	 * Obtain ns, soa and cname counts for top of zone.
   5053 	 */
   5054 	INSIST(db != NULL);
   5055 	result = zone_get_from_db(zone, db, &nscount, &soacount, &soattl,
   5056 				  &serial, &refresh, &retry, &expire, &minimum,
   5057 				  &errors);
   5058 	if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
   5059 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   5060 			      "could not find NS and/or SOA records");
   5061 	}
   5062 
   5063 	/*
   5064 	 * Process any queued NSEC3PARAM change requests. Only for dynamic
   5065 	 * zones, an inline-signing zone will perform this action when
   5066 	 * receiving the secure db (receive_secure_db).
   5067 	 */
   5068 	is_dynamic = dns_zone_isdynamic(zone, true);
   5069 	if (is_dynamic) {
   5070 		process_zone_setnsec3param(zone);
   5071 	}
   5072 
   5073 	/*
   5074 	 * Check to make sure the journal is up to date, and remove the
   5075 	 * journal file if it isn't, as we wouldn't be able to apply
   5076 	 * updates otherwise.
   5077 	 */
   5078 	if (zone->journal != NULL && is_dynamic &&
   5079 	    !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
   5080 	{
   5081 		uint32_t jserial;
   5082 		dns_journal_t *journal = NULL;
   5083 		bool empty = false;
   5084 
   5085 		result = dns_journal_open(zone->mctx, zone->journal,
   5086 					  DNS_JOURNAL_READ, &journal);
   5087 		if (result == ISC_R_SUCCESS) {
   5088 			jserial = dns_journal_last_serial(journal);
   5089 			empty = dns_journal_empty(journal);
   5090 			dns_journal_destroy(&journal);
   5091 		} else {
   5092 			jserial = serial;
   5093 			result = ISC_R_SUCCESS;
   5094 		}
   5095 
   5096 		if (jserial != serial) {
   5097 			if (!empty) {
   5098 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5099 					      ISC_LOG_INFO,
   5100 					      "journal file is out of date: "
   5101 					      "removing journal file");
   5102 			}
   5103 			if (remove(zone->journal) < 0 && errno != ENOENT) {
   5104 				char strbuf[ISC_STRERRORSIZE];
   5105 				strerror_r(errno, strbuf, sizeof(strbuf));
   5106 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   5107 					      DNS_LOGMODULE_ZONE,
   5108 					      ISC_LOG_WARNING,
   5109 					      "unable to remove journal "
   5110 					      "'%s': '%s'",
   5111 					      zone->journal, strbuf);
   5112 			}
   5113 		}
   5114 	}
   5115 
   5116 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
   5117 		      "loaded; checking validity");
   5118 
   5119 	/*
   5120 	 * Primary / Secondary / Mirror / Stub zones require both NS and SOA
   5121 	 * records at the top of the zone.
   5122 	 */
   5123 
   5124 	switch (zone->type) {
   5125 	case dns_zone_dlz:
   5126 	case dns_zone_primary:
   5127 	case dns_zone_secondary:
   5128 	case dns_zone_mirror:
   5129 	case dns_zone_stub:
   5130 	case dns_zone_redirect:
   5131 		if (soacount != 1) {
   5132 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5133 				      ISC_LOG_ERROR, "has %d SOA records",
   5134 				      soacount);
   5135 			result = DNS_R_BADZONE;
   5136 		}
   5137 		if (nscount == 0) {
   5138 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5139 				      ISC_LOG_ERROR, "has no NS records");
   5140 			result = DNS_R_BADZONE;
   5141 		}
   5142 		if (result != ISC_R_SUCCESS) {
   5143 			goto cleanup;
   5144 		}
   5145 		if (zone->type == dns_zone_primary && errors != 0) {
   5146 			result = DNS_R_BADZONE;
   5147 			goto cleanup;
   5148 		}
   5149 		if (zone->type != dns_zone_stub &&
   5150 		    zone->type != dns_zone_redirect)
   5151 		{
   5152 			result = check_nsec3param(zone, db);
   5153 			if (result != ISC_R_SUCCESS) {
   5154 				goto cleanup;
   5155 			}
   5156 		}
   5157 		if (zone->type == dns_zone_primary &&
   5158 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
   5159 		    !integrity_checks(zone, db))
   5160 		{
   5161 			result = DNS_R_BADZONE;
   5162 			goto cleanup;
   5163 		}
   5164 		if (zone->type == dns_zone_primary &&
   5165 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
   5166 		    !zone_check_dup(zone, db))
   5167 		{
   5168 			result = DNS_R_BADZONE;
   5169 			goto cleanup;
   5170 		}
   5171 
   5172 		if (zone->type == dns_zone_primary) {
   5173 			result = dns_zone_cdscheck(zone, db, NULL);
   5174 			if (result != ISC_R_SUCCESS) {
   5175 				dns_zone_log(zone, ISC_LOG_ERROR,
   5176 					     "CDS/CDNSKEY consistency checks "
   5177 					     "failed");
   5178 				goto cleanup;
   5179 			}
   5180 		}
   5181 
   5182 		result = dns_zone_verifydb(zone, db, NULL);
   5183 		if (result != ISC_R_SUCCESS) {
   5184 			goto cleanup;
   5185 		}
   5186 
   5187 		if (zone->db != NULL) {
   5188 			unsigned int oldsoacount;
   5189 
   5190 			/*
   5191 			 * This is checked in zone_replacedb() for
   5192 			 * secondary zones as they don't reload from disk.
   5193 			 */
   5194 			result = zone_get_from_db(
   5195 				zone, zone->db, NULL, &oldsoacount, NULL,
   5196 				&oldserial, NULL, NULL, NULL, NULL, NULL);
   5197 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   5198 			RUNTIME_CHECK(oldsoacount > 0U);
   5199 			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
   5200 			    !isc_serial_gt(serial, oldserial))
   5201 			{
   5202 				uint32_t serialmin, serialmax;
   5203 
   5204 				INSIST(zone->type == dns_zone_primary);
   5205 				INSIST(zone->raw == NULL);
   5206 
   5207 				if (serial == oldserial &&
   5208 				    zone_unchanged(zone->db, db, zone->mctx))
   5209 				{
   5210 					dns_zone_logc(zone,
   5211 						      DNS_LOGCATEGORY_ZONELOAD,
   5212 						      ISC_LOG_INFO,
   5213 						      "ixfr-from-differences: "
   5214 						      "unchanged");
   5215 					zone->loadtime = loadtime;
   5216 					goto done;
   5217 				}
   5218 
   5219 				serialmin = (oldserial + 1) & 0xffffffffU;
   5220 				serialmax = (oldserial + 0x7fffffffU) &
   5221 					    0xffffffffU;
   5222 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5223 					      ISC_LOG_ERROR,
   5224 					      "ixfr-from-differences: "
   5225 					      "new serial (%u) out of range "
   5226 					      "[%u - %u]",
   5227 					      serial, serialmin, serialmax);
   5228 				result = DNS_R_BADZONE;
   5229 				goto cleanup;
   5230 			} else if (!isc_serial_ge(serial, oldserial)) {
   5231 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5232 					      ISC_LOG_ERROR,
   5233 					      "zone serial (%u/%u) has gone "
   5234 					      "backwards",
   5235 					      serial, oldserial);
   5236 			} else if (serial == oldserial && !hasinclude &&
   5237 				   strcmp(zone->db_argv[0], "_builtin") != 0)
   5238 			{
   5239 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5240 					      ISC_LOG_ERROR,
   5241 					      "zone serial (%u) unchanged. "
   5242 					      "zone may fail to transfer "
   5243 					      "to secondaries.",
   5244 					      serial);
   5245 			}
   5246 		}
   5247 
   5248 		if (zone->type == dns_zone_primary &&
   5249 		    (zone->update_acl != NULL || zone->ssutable != NULL) &&
   5250 		    dns_zone_getsigresigninginterval(zone) < (3 * refresh) &&
   5251 		    dns_db_issecure(db))
   5252 		{
   5253 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5254 				      ISC_LOG_WARNING,
   5255 				      "sig-re-signing-interval less than "
   5256 				      "3 * refresh.");
   5257 		}
   5258 
   5259 		zone->refresh = RANGE(refresh, zone->minrefresh,
   5260 				      zone->maxrefresh);
   5261 		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
   5262 		zone->expire = RANGE(expire, zone->refresh + zone->retry,
   5263 				     DNS_MAX_EXPIRE);
   5264 		zone->soattl = soattl;
   5265 		zone->minimum = minimum;
   5266 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   5267 
   5268 		if (zone->type == dns_zone_secondary ||
   5269 		    zone->type == dns_zone_mirror ||
   5270 		    zone->type == dns_zone_stub ||
   5271 		    (zone->type == dns_zone_redirect &&
   5272 		     dns_remote_addresses(&zone->primaries) != NULL))
   5273 		{
   5274 			isc_time_t t;
   5275 			uint32_t delay;
   5276 
   5277 			result = isc_file_getmodtime(zone->journal, &t);
   5278 			if (result != ISC_R_SUCCESS) {
   5279 				result = isc_file_getmodtime(zone->masterfile,
   5280 							     &t);
   5281 			}
   5282 			if (result == ISC_R_SUCCESS) {
   5283 				DNS_ZONE_TIME_ADD(&t, zone->expire,
   5284 						  &zone->expiretime);
   5285 			} else {
   5286 				DNS_ZONE_TIME_ADD(&now, zone->retry,
   5287 						  &zone->expiretime);
   5288 			}
   5289 
   5290 			delay = (zone->retry -
   5291 				 isc_random_uniform((zone->retry * 3) / 4));
   5292 			DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
   5293 			if (isc_time_compare(&zone->refreshtime,
   5294 					     &zone->expiretime) >= 0)
   5295 			{
   5296 				DNS_ZONE_SETFLAG(zone,
   5297 						 DNS_ZONEFLG_FIRSTREFRESH);
   5298 				zone->refreshtime = now;
   5299 			} else {
   5300 				/* The zone is up to date. */
   5301 				DNS_ZONE_CLRFLAG(zone,
   5302 						 DNS_ZONEFLG_FIRSTREFRESH);
   5303 			}
   5304 		}
   5305 
   5306 		break;
   5307 
   5308 	case dns_zone_key:
   5309 		/* Nothing needs to be done now */
   5310 		break;
   5311 
   5312 	default:
   5313 		UNEXPECTED_ERROR("unexpected zone type %d", zone->type);
   5314 		result = ISC_R_UNEXPECTED;
   5315 		goto cleanup;
   5316 	}
   5317 
   5318 	/*
   5319 	 * Check for weak DNSKEY's.
   5320 	 */
   5321 	if (zone->type == dns_zone_primary) {
   5322 		zone_check_dnskeys(zone, db);
   5323 	}
   5324 
   5325 	/*
   5326 	 * Schedule DNSSEC key refresh.
   5327 	 */
   5328 	if (zone->type == dns_zone_primary &&
   5329 	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
   5330 	{
   5331 		zone->refreshkeytime = now;
   5332 	}
   5333 
   5334 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   5335 	if (zone->db != NULL) {
   5336 		had_db = true;
   5337 		result = zone_replacedb(zone, db, false);
   5338 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   5339 		if (result != ISC_R_SUCCESS) {
   5340 			goto cleanup;
   5341 		}
   5342 	} else {
   5343 		zone_attachdb(zone, db);
   5344 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   5345 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED |
   5346 					       DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
   5347 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
   5348 		    inline_raw(zone))
   5349 		{
   5350 			if (zone->secure->db == NULL) {
   5351 				zone_send_securedb(zone, db);
   5352 			} else {
   5353 				zone_send_secureserial(zone, serial);
   5354 			}
   5355 		}
   5356 	}
   5357 
   5358 	/*
   5359 	 * Finished loading inline-signing zone; need to get status
   5360 	 * from the raw side now.
   5361 	 */
   5362 	if (zone->type == dns_zone_primary && inline_secure(zone)) {
   5363 		maybe_send_secure(zone);
   5364 	}
   5365 
   5366 	result = ISC_R_SUCCESS;
   5367 
   5368 	if (fixjournal) {
   5369 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
   5370 		zone_journal_compact(zone, zone->db, 0);
   5371 	}
   5372 	if (needdump) {
   5373 		if (zone->type == dns_zone_key) {
   5374 			zone_needdump(zone, 30);
   5375 		} else {
   5376 			zone_needdump(zone, DNS_DUMP_DELAY);
   5377 		}
   5378 	}
   5379 
   5380 	if (zone->loop != NULL) {
   5381 		if (zone->type == dns_zone_primary) {
   5382 			set_resigntime(zone);
   5383 			resume_signingwithkey(zone);
   5384 			resume_addnsec3chain(zone);
   5385 		}
   5386 
   5387 		is_dynamic = dns_zone_isdynamic(zone, false);
   5388 		if (zone->type == dns_zone_primary && is_dynamic &&
   5389 		    dns_db_issecure(db) && !inline_raw(zone))
   5390 		{
   5391 			isc_stdtime_t resign;
   5392 			dns_name_t *name;
   5393 			dns_fixedname_t fixed;
   5394 			dns_typepair_t typepair;
   5395 
   5396 			name = dns_fixedname_initname(&fixed);
   5397 
   5398 			result = dns_db_getsigningtime(db, &resign, name,
   5399 						       &typepair);
   5400 			if (result == ISC_R_SUCCESS) {
   5401 				isc_stdtime_t timenow = isc_stdtime_now();
   5402 				char namebuf[DNS_NAME_FORMATSIZE];
   5403 				char typebuf[DNS_RDATATYPE_FORMATSIZE];
   5404 
   5405 				dns_name_format(name, namebuf, sizeof(namebuf));
   5406 				dns_rdatatype_format(
   5407 					DNS_TYPEPAIR_COVERS(typepair), typebuf,
   5408 					sizeof(typebuf));
   5409 				dnssec_log(
   5410 					zone, ISC_LOG_DEBUG(3),
   5411 					"next resign: %s/%s "
   5412 					"in %d seconds",
   5413 					namebuf, typebuf,
   5414 					resign - timenow -
   5415 						dns_zone_getsigresigninginterval(
   5416 							zone));
   5417 			} else {
   5418 				dnssec_log(zone, ISC_LOG_WARNING,
   5419 					   "signed dynamic zone has no "
   5420 					   "resign event scheduled");
   5421 			}
   5422 		}
   5423 
   5424 		zone_settimer(zone, &now);
   5425 	}
   5426 
   5427 	/*
   5428 	 * Clear old include list.
   5429 	 */
   5430 	for (inc = ISC_LIST_HEAD(zone->includes); inc != NULL;
   5431 	     inc = ISC_LIST_HEAD(zone->includes))
   5432 	{
   5433 		ISC_LIST_UNLINK(zone->includes, inc, link);
   5434 		isc_mem_free(zone->mctx, inc->name);
   5435 		isc_mem_put(zone->mctx, inc, sizeof(*inc));
   5436 	}
   5437 	zone->nincludes = 0;
   5438 
   5439 	/*
   5440 	 * Transfer new include list.
   5441 	 */
   5442 	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
   5443 	     inc = ISC_LIST_HEAD(zone->newincludes))
   5444 	{
   5445 		ISC_LIST_UNLINK(zone->newincludes, inc, link);
   5446 		ISC_LIST_APPEND(zone->includes, inc, link);
   5447 		zone->nincludes++;
   5448 	}
   5449 
   5450 	if (!dns_db_ispersistent(db)) {
   5451 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
   5452 			      "loaded serial %u%s", serial,
   5453 			      dns_db_issecure(db) ? " (DNSSEC signed)" : "");
   5454 	}
   5455 
   5456 	if (!had_db && zone->type == dns_zone_mirror) {
   5457 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
   5458 			      "mirror zone is now in use");
   5459 	}
   5460 
   5461 	zone->loadtime = loadtime;
   5462 	goto done;
   5463 
   5464 cleanup:
   5465 	if (result != ISC_R_SUCCESS) {
   5466 		dns_zone_rpz_disable_db(zone, db);
   5467 		dns_zone_catz_disable_db(zone, db);
   5468 	}
   5469 
   5470 	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
   5471 	     inc = ISC_LIST_HEAD(zone->newincludes))
   5472 	{
   5473 		ISC_LIST_UNLINK(zone->newincludes, inc, link);
   5474 		isc_mem_free(zone->mctx, inc->name);
   5475 		isc_mem_put(zone->mctx, inc, sizeof(*inc));
   5476 	}
   5477 	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
   5478 	    zone->type == dns_zone_stub || zone->type == dns_zone_key ||
   5479 	    (zone->type == dns_zone_redirect &&
   5480 	     dns_remote_addresses(&zone->primaries) != NULL))
   5481 	{
   5482 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIRSTREFRESH);
   5483 
   5484 		if (result != ISC_R_NOMEMORY) {
   5485 			if (zone->journal != NULL) {
   5486 				zone_saveunique(zone, zone->journal,
   5487 						"jn-XXXXXXXX");
   5488 			}
   5489 			if (zone->masterfile != NULL) {
   5490 				zone_saveunique(zone, zone->masterfile,
   5491 						"db-XXXXXXXX");
   5492 			}
   5493 		}
   5494 
   5495 		/* Mark the zone for immediate refresh. */
   5496 		zone->refreshtime = now;
   5497 		if (zone->loop != NULL) {
   5498 			zone_settimer(zone, &now);
   5499 		}
   5500 		result = ISC_R_SUCCESS;
   5501 	} else if (zone->type == dns_zone_primary ||
   5502 		   zone->type == dns_zone_redirect)
   5503 	{
   5504 		if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
   5505 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5506 				      ISC_LOG_ERROR,
   5507 				      "not loaded due to errors.");
   5508 		} else if (zone->type == dns_zone_primary) {
   5509 			result = ISC_R_SUCCESS;
   5510 		}
   5511 	}
   5512 
   5513 done:
   5514 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
   5515 	/*
   5516 	 * If this is an inline-signed zone and we were called for the raw
   5517 	 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
   5518 	 * as well, but only if this is a reload, not an initial zone load: in
   5519 	 * the former case, zone_postload() will not be run for the secure
   5520 	 * zone; in the latter case, it will be.  Check which case we are
   5521 	 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
   5522 	 * secure zone: if it is set, this must be a reload.
   5523 	 */
   5524 	if (inline_raw(zone) && DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
   5525 	{
   5526 		DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
   5527 		/*
   5528 		 * Re-start zone maintenance if it had been stalled
   5529 		 * due to DNS_ZONEFLG_LOADPENDING being set when
   5530 		 * zone_maintenance was called.
   5531 		 */
   5532 		if (zone->secure->loop != NULL) {
   5533 			zone_settimer(zone->secure, &now);
   5534 		}
   5535 	}
   5536 
   5537 	zone_debuglog(zone, __func__, 99, "done");
   5538 
   5539 	return result;
   5540 }
   5541 
   5542 static bool
   5543 exit_check(dns_zone_t *zone) {
   5544 	REQUIRE(LOCKED_ZONE(zone));
   5545 
   5546 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
   5547 	    isc_refcount_current(&zone->irefs) == 0)
   5548 	{
   5549 		/*
   5550 		 * DNS_ZONEFLG_SHUTDOWN can only be set if references == 0.
   5551 		 */
   5552 		INSIST(isc_refcount_current(&zone->references) == 0);
   5553 		return true;
   5554 	}
   5555 	return false;
   5556 }
   5557 
   5558 static bool
   5559 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
   5560 	      dns_name_t *name, bool logit) {
   5561 	isc_result_t result;
   5562 	char namebuf[DNS_NAME_FORMATSIZE];
   5563 	char altbuf[DNS_NAME_FORMATSIZE];
   5564 	dns_fixedname_t fixed;
   5565 	dns_name_t *foundname;
   5566 	int level;
   5567 
   5568 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS)) {
   5569 		return true;
   5570 	}
   5571 
   5572 	if (zone->type == dns_zone_primary) {
   5573 		level = ISC_LOG_ERROR;
   5574 	} else {
   5575 		level = ISC_LOG_WARNING;
   5576 	}
   5577 
   5578 	foundname = dns_fixedname_initname(&fixed);
   5579 
   5580 	result = dns_db_find(db, name, version, dns_rdatatype_a, 0, 0, NULL,
   5581 			     foundname, NULL, NULL);
   5582 	if (result == ISC_R_SUCCESS) {
   5583 		return true;
   5584 	}
   5585 
   5586 	if (result == DNS_R_NXRRSET) {
   5587 		result = dns_db_find(db, name, version, dns_rdatatype_aaaa, 0,
   5588 				     0, NULL, foundname, NULL, NULL);
   5589 		if (result == ISC_R_SUCCESS) {
   5590 			return true;
   5591 		}
   5592 	}
   5593 
   5594 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   5595 	    result == DNS_R_EMPTYNAME)
   5596 	{
   5597 		if (logit) {
   5598 			dns_name_format(name, namebuf, sizeof namebuf);
   5599 			dns_zone_log(zone, level,
   5600 				     "NS '%s' has no address "
   5601 				     "records (A or AAAA)",
   5602 				     namebuf);
   5603 		}
   5604 		return false;
   5605 	}
   5606 
   5607 	if (result == DNS_R_CNAME) {
   5608 		if (logit) {
   5609 			dns_name_format(name, namebuf, sizeof namebuf);
   5610 			dns_zone_log(zone, level,
   5611 				     "NS '%s' is a CNAME "
   5612 				     "(illegal)",
   5613 				     namebuf);
   5614 		}
   5615 		return false;
   5616 	}
   5617 
   5618 	if (result == DNS_R_DNAME) {
   5619 		if (logit) {
   5620 			dns_name_format(name, namebuf, sizeof namebuf);
   5621 			dns_name_format(foundname, altbuf, sizeof altbuf);
   5622 			dns_zone_log(zone, level,
   5623 				     "NS '%s' is below a DNAME "
   5624 				     "'%s' (illegal)",
   5625 				     namebuf, altbuf);
   5626 		}
   5627 		return false;
   5628 	}
   5629 
   5630 	return true;
   5631 }
   5632 
   5633 static isc_result_t
   5634 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
   5635 		 dns_dbversion_t *version, unsigned int *nscount,
   5636 		 unsigned int *errors, bool logit) {
   5637 	isc_result_t result;
   5638 	unsigned int count = 0;
   5639 	unsigned int ecount = 0;
   5640 	dns_rdataset_t rdataset;
   5641 	dns_rdata_t rdata;
   5642 	dns_rdata_ns_t ns;
   5643 
   5644 	dns_rdataset_init(&rdataset);
   5645 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
   5646 				     dns_rdatatype_none, 0, &rdataset, NULL);
   5647 	if (result == ISC_R_NOTFOUND) {
   5648 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5649 		goto success;
   5650 	}
   5651 	if (result != ISC_R_SUCCESS) {
   5652 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5653 		goto invalidate_rdataset;
   5654 	}
   5655 
   5656 	result = dns_rdataset_first(&rdataset);
   5657 	while (result == ISC_R_SUCCESS) {
   5658 		if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
   5659 		    (zone->type == dns_zone_primary ||
   5660 		     zone->type == dns_zone_secondary ||
   5661 		     zone->type == dns_zone_mirror))
   5662 		{
   5663 			dns_rdata_init(&rdata);
   5664 			dns_rdataset_current(&rdataset, &rdata);
   5665 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
   5666 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   5667 			if (dns_name_issubdomain(&ns.name, &zone->origin) &&
   5668 			    !zone_check_ns(zone, db, version, &ns.name, logit))
   5669 			{
   5670 				ecount++;
   5671 			}
   5672 		}
   5673 		count++;
   5674 		result = dns_rdataset_next(&rdataset);
   5675 	}
   5676 	dns_rdataset_disassociate(&rdataset);
   5677 
   5678 success:
   5679 	SET_IF_NOT_NULL(nscount, count);
   5680 	SET_IF_NOT_NULL(errors, ecount);
   5681 
   5682 	result = ISC_R_SUCCESS;
   5683 
   5684 invalidate_rdataset:
   5685 	dns_rdataset_invalidate(&rdataset);
   5686 
   5687 	return result;
   5688 }
   5689 
   5690 #define SET_SOA_VALUES(soattl_v, serial_v, refresh_v, retry_v, expire_v, \
   5691 		       minimum_v)                                        \
   5692 	{                                                                \
   5693 		SET_IF_NOT_NULL(soattl, soattl_v);                       \
   5694 		SET_IF_NOT_NULL(serial, serial_v);                       \
   5695 		SET_IF_NOT_NULL(refresh, refresh_v);                     \
   5696 		SET_IF_NOT_NULL(retry, retry_v);                         \
   5697 		SET_IF_NOT_NULL(expire, expire_v);                       \
   5698 		SET_IF_NOT_NULL(minimum, minimum_v);                     \
   5699 	}
   5700 
   5701 #define CLR_SOA_VALUES()                          \
   5702 	{                                         \
   5703 		SET_SOA_VALUES(0, 0, 0, 0, 0, 0); \
   5704 	}
   5705 
   5706 static isc_result_t
   5707 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   5708 		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
   5709 		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
   5710 		 uint32_t *minimum) {
   5711 	isc_result_t result;
   5712 	unsigned int count = 0;
   5713 	dns_rdataset_t rdataset;
   5714 	dns_rdata_t rdata = DNS_RDATA_INIT;
   5715 
   5716 	dns_rdataset_init(&rdataset);
   5717 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
   5718 				     dns_rdatatype_none, 0, &rdataset, NULL);
   5719 	if (result == ISC_R_NOTFOUND) {
   5720 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5721 		result = ISC_R_SUCCESS;
   5722 		goto invalidate_rdataset;
   5723 	}
   5724 	if (result != ISC_R_SUCCESS) {
   5725 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5726 		goto invalidate_rdataset;
   5727 	}
   5728 
   5729 	result = dns_rdataset_first(&rdataset);
   5730 	while (result == ISC_R_SUCCESS) {
   5731 		dns_rdata_init(&rdata);
   5732 		dns_rdataset_current(&rdataset, &rdata);
   5733 		count++;
   5734 		if (count == 1) {
   5735 			dns_rdata_soa_t soa;
   5736 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
   5737 			SET_SOA_VALUES(rdataset.ttl, soa.serial, soa.refresh,
   5738 				       soa.retry, soa.expire, soa.minimum);
   5739 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   5740 		}
   5741 
   5742 		result = dns_rdataset_next(&rdataset);
   5743 		dns_rdata_reset(&rdata);
   5744 	}
   5745 	dns_rdataset_disassociate(&rdataset);
   5746 
   5747 	result = ISC_R_SUCCESS;
   5748 
   5749 invalidate_rdataset:
   5750 	SET_IF_NOT_NULL(soacount, count);
   5751 	if (count == 0) {
   5752 		CLR_SOA_VALUES();
   5753 	}
   5754 
   5755 	dns_rdataset_invalidate(&rdataset);
   5756 
   5757 	return result;
   5758 }
   5759 
   5760 /*
   5761  * zone must be locked.
   5762  */
   5763 static isc_result_t
   5764 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
   5765 		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
   5766 		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
   5767 		 uint32_t *minimum, unsigned int *errors) {
   5768 	isc_result_t result;
   5769 	isc_result_t answer = ISC_R_SUCCESS;
   5770 	dns_dbversion_t *version = NULL;
   5771 	dns_dbnode_t *node;
   5772 
   5773 	REQUIRE(db != NULL);
   5774 	REQUIRE(zone != NULL);
   5775 
   5776 	dns_db_currentversion(db, &version);
   5777 
   5778 	SET_IF_NOT_NULL(nscount, 0);
   5779 	SET_IF_NOT_NULL(soacount, 0);
   5780 	SET_IF_NOT_NULL(errors, 0);
   5781 	CLR_SOA_VALUES();
   5782 
   5783 	node = NULL;
   5784 	result = dns_db_findnode(db, &zone->origin, false, &node);
   5785 	if (result != ISC_R_SUCCESS) {
   5786 		answer = result;
   5787 		goto closeversion;
   5788 	}
   5789 
   5790 	if (nscount != NULL || errors != NULL) {
   5791 		result = zone_count_ns_rr(zone, db, node, version, nscount,
   5792 					  errors, true);
   5793 		if (result != ISC_R_SUCCESS) {
   5794 			answer = result;
   5795 		}
   5796 	}
   5797 
   5798 	if (soacount != NULL || soattl != NULL || serial != NULL ||
   5799 	    refresh != NULL || retry != NULL || expire != NULL ||
   5800 	    minimum != NULL)
   5801 	{
   5802 		result = zone_load_soa_rr(db, node, version, soacount, soattl,
   5803 					  serial, refresh, retry, expire,
   5804 					  minimum);
   5805 		if (result != ISC_R_SUCCESS) {
   5806 			answer = result;
   5807 		}
   5808 	}
   5809 
   5810 	dns_db_detachnode(db, &node);
   5811 closeversion:
   5812 	dns_db_closeversion(db, &version, false);
   5813 
   5814 	return answer;
   5815 }
   5816 
   5817 static void
   5818 zone_destroy(dns_zone_t *zone) {
   5819 	/*
   5820 	 * Stop things being restarted after we cancel them below.
   5821 	 */
   5822 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
   5823 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "final reference detached");
   5824 
   5825 	if (zone->loop == NULL) {
   5826 		/*
   5827 		 * This zone is unmanaged; we're probably running in
   5828 		 * named-checkzone or a unit test. There's no loop, so we
   5829 		 * need to free it immediately.
   5830 		 */
   5831 		zone_shutdown(zone);
   5832 	} else {
   5833 		/*
   5834 		 * This zone has a loop; it can clean
   5835 		 * itself up asynchronously.
   5836 		 */
   5837 		isc_async_run(zone->loop, zone_shutdown, zone);
   5838 	}
   5839 }
   5840 
   5841 #if DNS_ZONE_TRACE
   5842 ISC_REFCOUNT_TRACE_IMPL(dns_zone, zone_destroy);
   5843 #else
   5844 ISC_REFCOUNT_IMPL(dns_zone, zone_destroy);
   5845 #endif
   5846 
   5847 void
   5848 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
   5849 	REQUIRE(DNS_ZONE_VALID(source));
   5850 
   5851 	LOCK_ZONE(source);
   5852 	zone_iattach(source, target);
   5853 	UNLOCK_ZONE(source);
   5854 }
   5855 
   5856 static void
   5857 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
   5858 	REQUIRE(DNS_ZONE_VALID(source));
   5859 	REQUIRE(LOCKED_ZONE(source));
   5860 	REQUIRE(target != NULL && *target == NULL);
   5861 	INSIST(isc_refcount_increment0(&source->irefs) +
   5862 		       isc_refcount_current(&source->references) >
   5863 	       0);
   5864 	*target = source;
   5865 }
   5866 
   5867 static void
   5868 zone_idetach(dns_zone_t **zonep) {
   5869 	dns_zone_t *zone;
   5870 
   5871 	/*
   5872 	 * 'zone' locked by caller.
   5873 	 */
   5874 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
   5875 	REQUIRE(LOCKED_ZONE(*zonep));
   5876 
   5877 	zone = *zonep;
   5878 	*zonep = NULL;
   5879 
   5880 	INSIST(isc_refcount_decrement(&zone->irefs) - 1 +
   5881 		       isc_refcount_current(&zone->references) >
   5882 	       0);
   5883 }
   5884 
   5885 void
   5886 dns_zone_idetach(dns_zone_t **zonep) {
   5887 	dns_zone_t *zone;
   5888 
   5889 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
   5890 
   5891 	zone = *zonep;
   5892 	*zonep = NULL;
   5893 
   5894 	if (isc_refcount_decrement(&zone->irefs) == 1) {
   5895 		bool free_needed;
   5896 		LOCK_ZONE(zone);
   5897 		free_needed = exit_check(zone);
   5898 		UNLOCK_ZONE(zone);
   5899 		if (free_needed) {
   5900 			zone_free(zone);
   5901 		}
   5902 	}
   5903 }
   5904 
   5905 isc_mem_t *
   5906 dns_zone_getmctx(dns_zone_t *zone) {
   5907 	REQUIRE(DNS_ZONE_VALID(zone));
   5908 
   5909 	return zone->mctx;
   5910 }
   5911 
   5912 dns_zonemgr_t *
   5913 dns_zone_getmgr(dns_zone_t *zone) {
   5914 	REQUIRE(DNS_ZONE_VALID(zone));
   5915 
   5916 	return zone->zmgr;
   5917 }
   5918 
   5919 void
   5920 dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
   5921 	REQUIRE(DNS_ZONE_VALID(zone));
   5922 
   5923 	LOCK_ZONE(zone);
   5924 	if (zone->kasp != NULL) {
   5925 		dns_kasp_detach(&zone->kasp);
   5926 	}
   5927 	if (kasp != NULL) {
   5928 		dns_kasp_attach(kasp, &zone->kasp);
   5929 	}
   5930 	UNLOCK_ZONE(zone);
   5931 }
   5932 
   5933 void
   5934 dns_zone_setdefaultkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
   5935 	REQUIRE(DNS_ZONE_VALID(zone));
   5936 
   5937 	LOCK_ZONE(zone);
   5938 	if (zone->defaultkasp != NULL) {
   5939 		dns_kasp_detach(&zone->defaultkasp);
   5940 	}
   5941 	if (kasp != NULL) {
   5942 		dns_kasp_attach(kasp, &zone->defaultkasp);
   5943 	}
   5944 	UNLOCK_ZONE(zone);
   5945 }
   5946 
   5947 dns_kasp_t *
   5948 dns_zone_getkasp(dns_zone_t *zone) {
   5949 	dns_kasp_t *kasp;
   5950 
   5951 	REQUIRE(DNS_ZONE_VALID(zone));
   5952 
   5953 	LOCK_ZONE(zone);
   5954 	if (inline_raw(zone) && zone->secure != NULL) {
   5955 		kasp = zone->secure->kasp;
   5956 	} else {
   5957 		kasp = zone->kasp;
   5958 	}
   5959 	UNLOCK_ZONE(zone);
   5960 
   5961 	return kasp;
   5962 }
   5963 
   5964 static void
   5965 dns_zone_setskr(dns_zone_t *zone, dns_skr_t *skr) {
   5966 	REQUIRE(DNS_ZONE_VALID(zone));
   5967 
   5968 	LOCK_ZONE(zone);
   5969 	zone->skrbundle = NULL;
   5970 	if (zone->skr != NULL) {
   5971 		dns_skr_detach(&zone->skr);
   5972 	}
   5973 	if (skr != NULL) {
   5974 		dns_skr_attach(skr, &zone->skr);
   5975 	}
   5976 	UNLOCK_ZONE(zone);
   5977 }
   5978 
   5979 dns_skrbundle_t *
   5980 dns_zone_getskrbundle(dns_zone_t *zone) {
   5981 	dns_skrbundle_t *bundle;
   5982 
   5983 	REQUIRE(DNS_ZONE_VALID(zone));
   5984 
   5985 	LOCK_ZONE(zone);
   5986 	if (inline_raw(zone) && zone->secure != NULL) {
   5987 		bundle = zone->secure->skrbundle;
   5988 	} else {
   5989 		bundle = zone->skrbundle;
   5990 	}
   5991 	UNLOCK_ZONE(zone);
   5992 
   5993 	return bundle;
   5994 }
   5995 
   5996 void
   5997 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
   5998 	REQUIRE(DNS_ZONE_VALID(zone));
   5999 
   6000 	if (value) {
   6001 		DNS_ZONE_SETOPTION(zone, option);
   6002 	} else {
   6003 		DNS_ZONE_CLROPTION(zone, option);
   6004 	}
   6005 }
   6006 
   6007 dns_zoneopt_t
   6008 dns_zone_getoptions(dns_zone_t *zone) {
   6009 	REQUIRE(DNS_ZONE_VALID(zone));
   6010 
   6011 	return ISC_ZONE_GET(zone, options);
   6012 }
   6013 
   6014 void
   6015 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value) {
   6016 	REQUIRE(DNS_ZONE_VALID(zone));
   6017 
   6018 	if (value) {
   6019 		DNS_ZONEKEY_SETOPTION(zone, keyopt);
   6020 	} else {
   6021 		DNS_ZONEKEY_CLROPTION(zone, keyopt);
   6022 	}
   6023 }
   6024 
   6025 unsigned int
   6026 dns_zone_getkeyopts(dns_zone_t *zone) {
   6027 	REQUIRE(DNS_ZONE_VALID(zone));
   6028 
   6029 	return ISC_ZONE_GET(zone, keyopts);
   6030 }
   6031 
   6032 void
   6033 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
   6034 	REQUIRE(DNS_ZONE_VALID(zone));
   6035 	REQUIRE(xfrsource != NULL);
   6036 
   6037 	LOCK_ZONE(zone);
   6038 	zone->xfrsource4 = *xfrsource;
   6039 	UNLOCK_ZONE(zone);
   6040 }
   6041 
   6042 void
   6043 dns_zone_getxfrsource4(dns_zone_t *zone, isc_sockaddr_t *xfrsource) {
   6044 	REQUIRE(DNS_ZONE_VALID(zone));
   6045 	REQUIRE(xfrsource != NULL);
   6046 
   6047 	LOCK_ZONE(zone);
   6048 	*xfrsource = zone->xfrsource4;
   6049 	UNLOCK_ZONE(zone);
   6050 }
   6051 
   6052 void
   6053 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
   6054 	REQUIRE(DNS_ZONE_VALID(zone));
   6055 	REQUIRE(xfrsource != NULL);
   6056 
   6057 	LOCK_ZONE(zone);
   6058 	zone->xfrsource6 = *xfrsource;
   6059 	UNLOCK_ZONE(zone);
   6060 }
   6061 
   6062 void
   6063 dns_zone_getxfrsource6(dns_zone_t *zone, isc_sockaddr_t *xfrsource) {
   6064 	REQUIRE(DNS_ZONE_VALID(zone));
   6065 	REQUIRE(xfrsource != NULL);
   6066 
   6067 	LOCK_ZONE(zone);
   6068 	*xfrsource = zone->xfrsource6;
   6069 	UNLOCK_ZONE(zone);
   6070 }
   6071 
   6072 void
   6073 dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
   6074 	REQUIRE(DNS_ZONE_VALID(zone));
   6075 	REQUIRE(parentalsrc != NULL);
   6076 
   6077 	LOCK_ZONE(zone);
   6078 	zone->parentalsrc4 = *parentalsrc;
   6079 	UNLOCK_ZONE(zone);
   6080 }
   6081 
   6082 void
   6083 dns_zone_getparentalsrc4(dns_zone_t *zone, isc_sockaddr_t *parentalsrc) {
   6084 	REQUIRE(DNS_ZONE_VALID(zone));
   6085 	REQUIRE(parentalsrc != NULL);
   6086 
   6087 	LOCK_ZONE(zone);
   6088 	*parentalsrc = zone->parentalsrc4;
   6089 	UNLOCK_ZONE(zone);
   6090 }
   6091 
   6092 void
   6093 dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
   6094 	REQUIRE(DNS_ZONE_VALID(zone));
   6095 
   6096 	LOCK_ZONE(zone);
   6097 	zone->parentalsrc6 = *parentalsrc;
   6098 	UNLOCK_ZONE(zone);
   6099 }
   6100 
   6101 void
   6102 dns_zone_getparentalsrc6(dns_zone_t *zone, isc_sockaddr_t *parentalsrc) {
   6103 	REQUIRE(DNS_ZONE_VALID(zone));
   6104 	REQUIRE(parentalsrc != NULL);
   6105 
   6106 	LOCK_ZONE(zone);
   6107 	*parentalsrc = zone->parentalsrc6;
   6108 	UNLOCK_ZONE(zone);
   6109 }
   6110 
   6111 void
   6112 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
   6113 	REQUIRE(DNS_ZONE_VALID(zone));
   6114 	REQUIRE(notifysrc != NULL);
   6115 
   6116 	LOCK_ZONE(zone);
   6117 	zone->notifysrc4 = *notifysrc;
   6118 	UNLOCK_ZONE(zone);
   6119 }
   6120 
   6121 void
   6122 dns_zone_getnotifysrc4(dns_zone_t *zone, isc_sockaddr_t *notifysrc) {
   6123 	REQUIRE(DNS_ZONE_VALID(zone));
   6124 	REQUIRE(notifysrc != NULL);
   6125 
   6126 	LOCK_ZONE(zone);
   6127 	*notifysrc = zone->notifysrc4;
   6128 	UNLOCK_ZONE(zone);
   6129 }
   6130 
   6131 void
   6132 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
   6133 	REQUIRE(DNS_ZONE_VALID(zone));
   6134 	REQUIRE(notifysrc != NULL);
   6135 
   6136 	LOCK_ZONE(zone);
   6137 	zone->notifysrc6 = *notifysrc;
   6138 	UNLOCK_ZONE(zone);
   6139 }
   6140 
   6141 void
   6142 dns_zone_getnotifysrc6(dns_zone_t *zone, isc_sockaddr_t *notifysrc) {
   6143 	REQUIRE(DNS_ZONE_VALID(zone));
   6144 	REQUIRE(notifysrc != NULL);
   6145 
   6146 	LOCK_ZONE(zone);
   6147 	*notifysrc = zone->notifysrc6;
   6148 	UNLOCK_ZONE(zone);
   6149 }
   6150 
   6151 void
   6152 dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *addresses,
   6153 		       isc_sockaddr_t *sources, dns_name_t **keynames,
   6154 		       dns_name_t **tlsnames, uint32_t count) {
   6155 	dns_remote_t remote;
   6156 
   6157 	REQUIRE(DNS_ZONE_VALID(zone));
   6158 
   6159 	LOCK_ZONE(zone);
   6160 
   6161 	remote.magic = DNS_REMOTE_MAGIC;
   6162 	remote.addresses = addresses;
   6163 	remote.sources = sources;
   6164 	remote.keynames = keynames;
   6165 	remote.tlsnames = tlsnames;
   6166 	remote.addrcnt = count;
   6167 
   6168 	if (dns_remote_equal(&zone->notify, &remote)) {
   6169 		goto unlock;
   6170 	}
   6171 
   6172 	dns_remote_clear(&zone->notify);
   6173 
   6174 	/*
   6175 	 * If count == 0, don't allocate any space for servers to notify.
   6176 	 */
   6177 	if (count == 0) {
   6178 		goto unlock;
   6179 	}
   6180 
   6181 	/*
   6182 	 * Now set up the notify address and key lists.
   6183 	 */
   6184 	dns_remote_init(&zone->notify, count, addresses, sources, keynames,
   6185 			tlsnames, true, zone->mctx);
   6186 
   6187 unlock:
   6188 	UNLOCK_ZONE(zone);
   6189 }
   6190 
   6191 static bool
   6192 has_pf(isc_sockaddr_t *addresses, size_t count, int pf) {
   6193 	for (size_t i = 0; i < count; i++) {
   6194 		if (isc_sockaddr_pf(&addresses[i]) == pf) {
   6195 			return true;
   6196 		}
   6197 	}
   6198 	return false;
   6199 }
   6200 
   6201 static void
   6202 report_no_active_addresses(dns_zone_t *zone, isc_sockaddr_t *addresses,
   6203 			   size_t count, const char *what) {
   6204 	if (isc_net_probeipv4() == ISC_R_DISABLED) {
   6205 		if (!has_pf(addresses, count, AF_INET6)) {
   6206 			dns_zone_log(zone, ISC_LOG_NOTICE,
   6207 				     "IPv4 disabled and no IPv6 %s", what);
   6208 		}
   6209 	} else if (isc_net_probeipv6() == ISC_R_DISABLED) {
   6210 		if (!has_pf(addresses, count, AF_INET)) {
   6211 			dns_zone_log(zone, ISC_LOG_NOTICE,
   6212 				     "IPv6 disabled and no IPv4 %s", what);
   6213 		}
   6214 	}
   6215 }
   6216 
   6217 void
   6218 dns_zone_setprimaries(dns_zone_t *zone, isc_sockaddr_t *addresses,
   6219 		      isc_sockaddr_t *sources, dns_name_t **keynames,
   6220 		      dns_name_t **tlsnames, uint32_t count) {
   6221 	dns_remote_t remote;
   6222 
   6223 	REQUIRE(DNS_ZONE_VALID(zone));
   6224 
   6225 	LOCK_ZONE(zone);
   6226 
   6227 	remote.magic = DNS_REMOTE_MAGIC;
   6228 	remote.addresses = addresses;
   6229 	remote.sources = sources;
   6230 	remote.keynames = keynames;
   6231 	remote.tlsnames = tlsnames;
   6232 	remote.addrcnt = count;
   6233 
   6234 	/*
   6235 	 * The refresh code assumes that 'primaries' wouldn't change under it.
   6236 	 * If it will change then kill off any current refresh in progress
   6237 	 * and update the primaries info.  If it won't change then we can just
   6238 	 * unlock and exit.
   6239 	 */
   6240 	if (!dns_remote_equal(&zone->primaries, &remote)) {
   6241 		if (zone->request != NULL) {
   6242 			dns_request_cancel(zone->request);
   6243 		}
   6244 	} else {
   6245 		goto unlock;
   6246 	}
   6247 
   6248 	dns_remote_clear(&zone->primaries);
   6249 
   6250 	/*
   6251 	 * If count == 0, don't allocate any space for primaries.
   6252 	 */
   6253 	if (count == 0) {
   6254 		goto unlock;
   6255 	}
   6256 
   6257 	report_no_active_addresses(zone, addresses, count, "primaries");
   6258 
   6259 	/*
   6260 	 * Now set up the primaries and primary key lists.
   6261 	 */
   6262 	dns_remote_init(&zone->primaries, count, addresses, sources, keynames,
   6263 			tlsnames, true, zone->mctx);
   6264 
   6265 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
   6266 
   6267 unlock:
   6268 	UNLOCK_ZONE(zone);
   6269 }
   6270 
   6271 void
   6272 dns_zone_setparentals(dns_zone_t *zone, isc_sockaddr_t *addresses,
   6273 		      isc_sockaddr_t *sources, dns_name_t **keynames,
   6274 		      dns_name_t **tlsnames, uint32_t count) {
   6275 	dns_remote_t remote;
   6276 
   6277 	REQUIRE(DNS_ZONE_VALID(zone));
   6278 
   6279 	LOCK_ZONE(zone);
   6280 
   6281 	remote.magic = DNS_REMOTE_MAGIC;
   6282 	remote.addresses = addresses;
   6283 	remote.sources = sources;
   6284 	remote.keynames = keynames;
   6285 	remote.tlsnames = tlsnames;
   6286 	remote.addrcnt = count;
   6287 
   6288 	if (dns_remote_equal(&zone->parentals, &remote)) {
   6289 		goto unlock;
   6290 	}
   6291 
   6292 	dns_remote_clear(&zone->parentals);
   6293 
   6294 	/*
   6295 	 * If count == 0, don't allocate any space for parentals.
   6296 	 */
   6297 	if (count == 0) {
   6298 		goto unlock;
   6299 	}
   6300 
   6301 	report_no_active_addresses(zone, addresses, count, "parental-agents");
   6302 
   6303 	/*
   6304 	 * Now set up the parentals and parental key lists.
   6305 	 */
   6306 	dns_remote_init(&zone->parentals, count, addresses, sources, keynames,
   6307 			tlsnames, true, zone->mctx);
   6308 
   6309 	dns_zone_log(zone, ISC_LOG_NOTICE, "checkds: set %u parentals", count);
   6310 
   6311 unlock:
   6312 	UNLOCK_ZONE(zone);
   6313 }
   6314 
   6315 isc_result_t
   6316 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
   6317 	isc_result_t result = ISC_R_SUCCESS;
   6318 
   6319 	REQUIRE(DNS_ZONE_VALID(zone));
   6320 
   6321 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   6322 	if (zone->db == NULL) {
   6323 		result = DNS_R_NOTLOADED;
   6324 	} else {
   6325 		dns_db_attach(zone->db, dpb);
   6326 	}
   6327 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   6328 
   6329 	return result;
   6330 }
   6331 
   6332 void
   6333 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
   6334 	REQUIRE(DNS_ZONE_VALID(zone));
   6335 	REQUIRE(zone->type == dns_zone_staticstub);
   6336 
   6337 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   6338 	REQUIRE(zone->db == NULL);
   6339 	dns_db_attach(db, &zone->db);
   6340 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   6341 }
   6342 
   6343 static bool
   6344 was_dumping(dns_zone_t *zone) {
   6345 	REQUIRE(LOCKED_ZONE(zone));
   6346 
   6347 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   6348 		return true;
   6349 	}
   6350 
   6351 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
   6352 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   6353 	isc_time_settoepoch(&zone->dumptime);
   6354 	return false;
   6355 }
   6356 
   6357 static isc_result_t
   6358 keyfromfile(dns_zone_t *zone, dst_key_t *pubkey, isc_mem_t *mctx,
   6359 	    dst_key_t **key) {
   6360 	const char *directory = zone->keydirectory;
   6361 	dns_kasp_t *kasp = zone->kasp;
   6362 	dst_key_t *foundkey = NULL;
   6363 	isc_result_t result = ISC_R_NOTFOUND;
   6364 
   6365 	if (kasp == NULL || (strcmp(dns_kasp_getname(kasp), "none") == 0) ||
   6366 	    (strcmp(dns_kasp_getname(kasp), "insecure") == 0))
   6367 	{
   6368 		result = dst_key_fromfile(
   6369 			dst_key_name(pubkey), dst_key_id(pubkey),
   6370 			dst_key_alg(pubkey),
   6371 			DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE,
   6372 			directory, mctx, &foundkey);
   6373 	} else {
   6374 		for (dns_kasp_key_t *kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp));
   6375 		     kkey != NULL; kkey = ISC_LIST_NEXT(kkey, link))
   6376 		{
   6377 			dns_keystore_t *ks = dns_kasp_key_keystore(kkey);
   6378 			directory = dns_keystore_directory(ks,
   6379 							   zone->keydirectory);
   6380 
   6381 			result = dst_key_fromfile(
   6382 				dst_key_name(pubkey), dst_key_id(pubkey),
   6383 				dst_key_alg(pubkey),
   6384 				DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
   6385 					DST_TYPE_STATE,
   6386 				directory, mctx, &foundkey);
   6387 			if (result == ISC_R_SUCCESS) {
   6388 				break;
   6389 			}
   6390 		}
   6391 	}
   6392 
   6393 	*key = foundkey;
   6394 	return result;
   6395 }
   6396 
   6397 #define is_zone_key(key) \
   6398 	((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE)
   6399 
   6400 static isc_result_t
   6401 findzonekeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   6402 	     dns_dbnode_t *node, const dns_name_t *name, isc_stdtime_t now,
   6403 	     isc_mem_t *mctx, unsigned int maxkeys, dst_key_t **keys,
   6404 	     unsigned int *nkeys) {
   6405 	dns_rdataset_t rdataset;
   6406 	dns_rdata_t rdata = DNS_RDATA_INIT;
   6407 	isc_result_t result;
   6408 	dst_key_t *pubkey = NULL;
   6409 	unsigned int count = 0;
   6410 
   6411 	*nkeys = 0;
   6412 	memset(keys, 0, sizeof(*keys) * maxkeys);
   6413 	dns_rdataset_init(&rdataset);
   6414 	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
   6415 				  &rdataset, NULL));
   6416 	CHECK(dns_rdataset_first(&rdataset));
   6417 	while (result == ISC_R_SUCCESS && count < maxkeys) {
   6418 		pubkey = NULL;
   6419 		dns_rdataset_current(&rdataset, &rdata);
   6420 		CHECK(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey));
   6421 		dst_key_setttl(pubkey, rdataset.ttl);
   6422 
   6423 		if (!is_zone_key(pubkey)) {
   6424 			goto next;
   6425 		}
   6426 		/* Corrupted .key file? */
   6427 		if (!dns_name_equal(name, dst_key_name(pubkey))) {
   6428 			goto next;
   6429 		}
   6430 		keys[count] = NULL;
   6431 		result = keyfromfile(zone, pubkey, mctx, &keys[count]);
   6432 
   6433 		/*
   6434 		 * If the key was revoked and the private file
   6435 		 * doesn't exist, maybe it was revoked internally
   6436 		 * by named.  Try loading the unrevoked version.
   6437 		 */
   6438 		if (result == ISC_R_FILENOTFOUND) {
   6439 			uint32_t flags;
   6440 			flags = dst_key_flags(pubkey);
   6441 			if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
   6442 				dst_key_setflags(pubkey,
   6443 						 flags & ~DNS_KEYFLAG_REVOKE);
   6444 				result = keyfromfile(zone, pubkey, mctx,
   6445 						     &keys[count]);
   6446 				if (result == ISC_R_SUCCESS &&
   6447 				    dst_key_pubcompare(pubkey, keys[count],
   6448 						       false))
   6449 				{
   6450 					dst_key_setflags(keys[count], flags);
   6451 				}
   6452 				dst_key_setflags(pubkey, flags);
   6453 			}
   6454 		}
   6455 
   6456 		if (result != ISC_R_SUCCESS) {
   6457 			char filename[DNS_NAME_FORMATSIZE +
   6458 				      DNS_SECALG_FORMATSIZE +
   6459 				      sizeof("key file for //65535")];
   6460 			isc_result_t result2;
   6461 			isc_buffer_t buf;
   6462 
   6463 			isc_buffer_init(&buf, filename, sizeof(filename));
   6464 			result2 = dst_key_getfilename(
   6465 				dst_key_name(pubkey), dst_key_id(pubkey),
   6466 				dst_key_alg(pubkey),
   6467 				DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
   6468 					DST_TYPE_STATE,
   6469 				NULL, mctx, &buf);
   6470 			if (result2 != ISC_R_SUCCESS) {
   6471 				char namebuf[DNS_NAME_FORMATSIZE];
   6472 				char algbuf[DNS_SECALG_FORMATSIZE];
   6473 
   6474 				dns_name_format(dst_key_name(pubkey), namebuf,
   6475 						sizeof(namebuf));
   6476 				dns_secalg_format(dst_key_alg(pubkey), algbuf,
   6477 						  sizeof(algbuf));
   6478 				snprintf(filename, sizeof(filename) - 1,
   6479 					 "key file for %s/%s/%d", namebuf,
   6480 					 algbuf, dst_key_id(pubkey));
   6481 			}
   6482 
   6483 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   6484 				      DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
   6485 				      "dns_zone_findkeys: error reading %s: %s",
   6486 				      filename, isc_result_totext(result));
   6487 		}
   6488 
   6489 		if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
   6490 			keys[count] = pubkey;
   6491 			pubkey = NULL;
   6492 			count++;
   6493 			goto next;
   6494 		}
   6495 
   6496 		CHECK(result);
   6497 
   6498 		/*
   6499 		 * If a key is marked inactive, skip it
   6500 		 */
   6501 		if (!dns_dnssec_keyactive(keys[count], now)) {
   6502 			dst_key_setinactive(pubkey, true);
   6503 			dst_key_free(&keys[count]);
   6504 			keys[count] = pubkey;
   6505 			pubkey = NULL;
   6506 			count++;
   6507 			goto next;
   6508 		}
   6509 
   6510 		/*
   6511 		 * Whatever the key's default TTL may have
   6512 		 * been, the rdataset TTL takes priority.
   6513 		 */
   6514 		dst_key_setttl(keys[count], rdataset.ttl);
   6515 		count++;
   6516 	next:
   6517 		if (pubkey != NULL) {
   6518 			dst_key_free(&pubkey);
   6519 		}
   6520 		dns_rdata_reset(&rdata);
   6521 		result = dns_rdataset_next(&rdataset);
   6522 	}
   6523 	if (result != ISC_R_NOMORE) {
   6524 		CHECK(result);
   6525 	}
   6526 	if (count == 0) {
   6527 		result = ISC_R_NOTFOUND;
   6528 	} else {
   6529 		result = ISC_R_SUCCESS;
   6530 	}
   6531 
   6532 cleanup:
   6533 	if (dns_rdataset_isassociated(&rdataset)) {
   6534 		dns_rdataset_disassociate(&rdataset);
   6535 	}
   6536 	if (pubkey != NULL) {
   6537 		dst_key_free(&pubkey);
   6538 	}
   6539 	if (result != ISC_R_SUCCESS) {
   6540 		while (count > 0) {
   6541 			dst_key_free(&keys[--count]);
   6542 		}
   6543 	}
   6544 	*nkeys = count;
   6545 	return result;
   6546 }
   6547 
   6548 /*%
   6549  * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
   6550  * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
   6551  * Only load the public part of a given key if it is not active at timestamp
   6552  * 'now'.  Store the number of keys found in 'nkeys'.
   6553  */
   6554 isc_result_t
   6555 dns_zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   6556 		  isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
   6557 		  dst_key_t **keys, unsigned int *nkeys) {
   6558 	isc_result_t result;
   6559 	dns_dbnode_t *node = NULL;
   6560 
   6561 	REQUIRE(DNS_ZONE_VALID(zone));
   6562 	REQUIRE(mctx != NULL);
   6563 	REQUIRE(nkeys != NULL);
   6564 	REQUIRE(keys != NULL);
   6565 
   6566 	CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
   6567 
   6568 	dns_zone_lock_keyfiles(zone);
   6569 
   6570 	result = findzonekeys(zone, db, ver, node, dns_db_origin(db), now, mctx,
   6571 			      maxkeys, keys, nkeys);
   6572 
   6573 	dns_zone_unlock_keyfiles(zone);
   6574 
   6575 	if (result == ISC_R_NOTFOUND) {
   6576 		result = ISC_R_SUCCESS;
   6577 	}
   6578 
   6579 cleanup:
   6580 
   6581 	if (node != NULL) {
   6582 		dns_db_detachnode(db, &node);
   6583 	}
   6584 	return result;
   6585 }
   6586 
   6587 void
   6588 dns_zone_prepare_shutdown(dns_zone_t *zone) {
   6589 	REQUIRE(DNS_ZONE_VALID(zone));
   6590 
   6591 	LOCK_ZONE(zone);
   6592 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
   6593 	UNLOCK_ZONE(zone);
   6594 }
   6595 
   6596 /*%
   6597  * Find DNSSEC keys used for signing zone with dnssec-policy. Load these keys
   6598  * into 'keys'. Requires KASP to be locked.
   6599  */
   6600 isc_result_t
   6601 dns_zone_getdnsseckeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   6602 		       isc_stdtime_t now, dns_dnsseckeylist_t *keys) {
   6603 	isc_result_t result;
   6604 	const char *dir = dns_zone_getkeydirectory(zone);
   6605 	dns_dbnode_t *node = NULL;
   6606 	dns_dnsseckey_t *key, *key_next;
   6607 	dns_dnsseckeylist_t dnskeys;
   6608 	dns_name_t *origin = dns_zone_getorigin(zone);
   6609 	dns_kasp_t *kasp = zone->kasp;
   6610 	dns_rdataset_t keyset;
   6611 
   6612 	REQUIRE(DNS_ZONE_VALID(zone));
   6613 	REQUIRE(kasp != NULL);
   6614 
   6615 	ISC_LIST_INIT(dnskeys);
   6616 
   6617 	dns_rdataset_init(&keyset);
   6618 
   6619 	CHECK(dns_db_findnode(db, origin, false, &node));
   6620 
   6621 	/* Get keys from private key files. */
   6622 	dns_zone_lock_keyfiles(zone);
   6623 	result = dns_dnssec_findmatchingkeys(origin, kasp, dir, zone->keystores,
   6624 					     now, false, dns_zone_getmctx(zone),
   6625 					     keys);
   6626 	dns_zone_unlock_keyfiles(zone);
   6627 
   6628 	if (result != ISC_R_NOTFOUND) {
   6629 		CHECK(result);
   6630 	}
   6631 
   6632 	/* Get public keys (dnskeys). */
   6633 	dns_rdataset_init(&keyset);
   6634 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
   6635 				     dns_rdatatype_none, 0, &keyset, NULL);
   6636 	if (result == ISC_R_SUCCESS) {
   6637 		CHECK(dns_dnssec_keylistfromrdataset(
   6638 			origin, kasp, dir, dns_zone_getmctx(zone), &keyset,
   6639 			NULL, NULL, false, false, &dnskeys));
   6640 	} else if (result != ISC_R_NOTFOUND) {
   6641 		CHECK(result);
   6642 	}
   6643 
   6644 	/* Add new 'dnskeys' to 'keys'. */
   6645 	for (dns_dnsseckey_t *k1 = ISC_LIST_HEAD(dnskeys); k1 != NULL;
   6646 	     k1 = key_next)
   6647 	{
   6648 		dns_dnsseckey_t *k2 = NULL;
   6649 		key_next = ISC_LIST_NEXT(k1, link);
   6650 
   6651 		for (k2 = ISC_LIST_HEAD(*keys); k2 != NULL;
   6652 		     k2 = ISC_LIST_NEXT(k2, link))
   6653 		{
   6654 			if (dst_key_compare(k1->key, k2->key)) {
   6655 				break;
   6656 			}
   6657 		}
   6658 		/* No match found, add the new key. */
   6659 		if (k2 == NULL) {
   6660 			ISC_LIST_UNLINK(dnskeys, k1, link);
   6661 			ISC_LIST_APPEND(*keys, k1, link);
   6662 		}
   6663 	}
   6664 
   6665 cleanup:
   6666 	if (dns_rdataset_isassociated(&keyset)) {
   6667 		dns_rdataset_disassociate(&keyset);
   6668 	}
   6669 	if (node != NULL) {
   6670 		dns_db_detachnode(db, &node);
   6671 	}
   6672 	while (!ISC_LIST_EMPTY(dnskeys)) {
   6673 		key = ISC_LIST_HEAD(dnskeys);
   6674 		ISC_LIST_UNLINK(dnskeys, key, link);
   6675 		dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
   6676 	}
   6677 	return result;
   6678 }
   6679 
   6680 static isc_result_t
   6681 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
   6682 	dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) {
   6683 	isc_result_t result;
   6684 
   6685 	if ((rdata->flags & DNS_RDATA_OFFLINE) != 0) {
   6686 		return ISC_R_SUCCESS;
   6687 	}
   6688 	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
   6689 			       name, ttl, rdata);
   6690 	if (result != ISC_R_SUCCESS) {
   6691 		return result;
   6692 	}
   6693 	rdata->flags |= DNS_RDATA_OFFLINE;
   6694 	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
   6695 			       name, ttl, rdata);
   6696 	zonediff->offline = true;
   6697 	return result;
   6698 }
   6699 
   6700 static void
   6701 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when,
   6702 		       isc_stdtime_t now) {
   6703 	unsigned int delta;
   6704 	char timebuf[80];
   6705 
   6706 	LOCK_ZONE(zone);
   6707 	zone->key_expiry = when;
   6708 	if (when <= now) {
   6709 		dns_zone_log(zone, ISC_LOG_ERROR,
   6710 			     "DNSKEY RRSIG(s) have expired");
   6711 		isc_time_settoepoch(&zone->keywarntime);
   6712 	} else if (when < now + 7 * 24 * 3600) {
   6713 		isc_time_t t;
   6714 		isc_time_set(&t, when, 0);
   6715 		isc_time_formattimestamp(&t, timebuf, 80);
   6716 		dns_zone_log(zone, ISC_LOG_WARNING,
   6717 			     "DNSKEY RRSIG(s) will expire within 7 days: %s",
   6718 			     timebuf);
   6719 		delta = when - now;
   6720 		delta--;	    /* loop prevention */
   6721 		delta /= 24 * 3600; /* to whole days */
   6722 		delta *= 24 * 3600; /* to seconds */
   6723 		isc_time_set(&zone->keywarntime, when - delta, 0);
   6724 	} else {
   6725 		isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
   6726 		isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
   6727 		dns_zone_log(zone, ISC_LOG_NOTICE, "setting keywarntime to %s",
   6728 			     timebuf);
   6729 	}
   6730 	UNLOCK_ZONE(zone);
   6731 }
   6732 
   6733 /*
   6734  * Helper function to del_sigs(). We don't want to delete RRSIGs that
   6735  * have no new key.
   6736  */
   6737 static bool
   6738 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
   6739 	  bool kasp, bool *warn) {
   6740 	unsigned int i = 0;
   6741 	isc_result_t ret;
   6742 	bool have_ksk = false, have_zsk = false;
   6743 	bool have_pksk = false, have_pzsk = false;
   6744 
   6745 	for (i = 0; i < nkeys; i++) {
   6746 		bool ksk, zsk;
   6747 
   6748 		if (have_pksk && have_ksk && have_pzsk && have_zsk) {
   6749 			break;
   6750 		}
   6751 
   6752 		if (rrsig_ptr->algorithm != dst_key_alg(keys[i])) {
   6753 			continue;
   6754 		}
   6755 
   6756 		ret = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
   6757 		if (ret != ISC_R_SUCCESS) {
   6758 			ksk = KSK(keys[i]);
   6759 		}
   6760 		ret = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
   6761 		if (ret != ISC_R_SUCCESS) {
   6762 			zsk = !KSK(keys[i]);
   6763 		}
   6764 
   6765 		if (ksk) {
   6766 			have_ksk = true;
   6767 			if (dst_key_isprivate(keys[i])) {
   6768 				have_pksk = true;
   6769 			}
   6770 		}
   6771 		if (zsk) {
   6772 			have_zsk = true;
   6773 			if (dst_key_isprivate(keys[i])) {
   6774 				have_pzsk = true;
   6775 			}
   6776 		}
   6777 	}
   6778 
   6779 	if (have_zsk && have_ksk && !have_pzsk) {
   6780 		*warn = true;
   6781 	}
   6782 
   6783 	if (have_pksk && have_pzsk) {
   6784 		return true;
   6785 	}
   6786 
   6787 	/*
   6788 	 * Deleting the SOA RRSIG is always okay.
   6789 	 */
   6790 	if (rrsig_ptr->covered == dns_rdatatype_soa) {
   6791 		return true;
   6792 	}
   6793 
   6794 	/*
   6795 	 * It's okay to delete a signature if there is an active key with the
   6796 	 * same algorithm to replace it, unless that violates the DNSSEC
   6797 	 * policy.
   6798 	 */
   6799 	if (have_pksk || have_pzsk) {
   6800 		if (kasp && have_pzsk) {
   6801 			return true;
   6802 		}
   6803 		return !kasp;
   6804 	}
   6805 
   6806 	/*
   6807 	 * Failing that, it is *not* okay to delete a signature
   6808 	 * if the associated public key is still in the DNSKEY RRset
   6809 	 */
   6810 	for (i = 0; i < nkeys; i++) {
   6811 		if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
   6812 		    (rrsig_ptr->keyid == dst_key_id(keys[i])))
   6813 		{
   6814 			return false;
   6815 		}
   6816 	}
   6817 
   6818 	/*
   6819 	 * But if the key is gone, then go ahead.
   6820 	 */
   6821 	return true;
   6822 }
   6823 
   6824 /*
   6825  * Delete expired RRsigs and any RRsigs we are about to re-sign.
   6826  * See also update.c:del_keysigs().
   6827  */
   6828 static isc_result_t
   6829 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
   6830 	 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
   6831 	 unsigned int nkeys, isc_stdtime_t now, bool incremental) {
   6832 	isc_result_t result;
   6833 	dns_dbnode_t *node = NULL;
   6834 	dns_rdataset_t rdataset;
   6835 	unsigned int i;
   6836 	dns_rdata_rrsig_t rrsig;
   6837 	dns_kasp_t *kasp = zone->kasp;
   6838 	bool found;
   6839 	bool offlineksk = false;
   6840 	int64_t timewarn = 0, timemaybe = 0;
   6841 
   6842 	dns_rdataset_init(&rdataset);
   6843 
   6844 	if (kasp != NULL) {
   6845 		offlineksk = dns_kasp_offlineksk(kasp);
   6846 	}
   6847 
   6848 	if (type == dns_rdatatype_nsec3) {
   6849 		result = dns_db_findnsec3node(db, name, false, &node);
   6850 	} else {
   6851 		result = dns_db_findnode(db, name, false, &node);
   6852 	}
   6853 	if (result == ISC_R_NOTFOUND) {
   6854 		return ISC_R_SUCCESS;
   6855 	}
   6856 	CHECK(result);
   6857 
   6858 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
   6859 				     (isc_stdtime_t)0, &rdataset, NULL);
   6860 	dns_db_detachnode(db, &node);
   6861 
   6862 	if (result == ISC_R_NOTFOUND) {
   6863 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6864 		return ISC_R_SUCCESS;
   6865 	}
   6866 	if (result != ISC_R_SUCCESS) {
   6867 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6868 		goto cleanup;
   6869 	}
   6870 
   6871 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   6872 	     result = dns_rdataset_next(&rdataset))
   6873 	{
   6874 		dns_rdata_t rdata = DNS_RDATA_INIT;
   6875 
   6876 		dns_rdataset_current(&rdataset, &rdata);
   6877 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   6878 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   6879 
   6880 		if (!dns_rdatatype_iskeymaterial(type)) {
   6881 			bool warn = false, deleted = false;
   6882 			if (delsig_ok(&rrsig, keys, nkeys, kasp != NULL, &warn))
   6883 			{
   6884 				result = update_one_rr(db, ver, zonediff->diff,
   6885 						       DNS_DIFFOP_DELRESIGN,
   6886 						       name, rdataset.ttl,
   6887 						       &rdata);
   6888 				if (result != ISC_R_SUCCESS) {
   6889 					break;
   6890 				}
   6891 				deleted = true;
   6892 			}
   6893 			if (warn && !deleted) {
   6894 				/*
   6895 				 * At this point, we've got an RRSIG,
   6896 				 * which is signed by an inactive key.
   6897 				 * An administrator needs to provide a new
   6898 				 * key/alg, but until that time, we want to
   6899 				 * keep the old RRSIG.  Marking the key as
   6900 				 * offline will prevent us spinning waiting
   6901 				 * for the private part.
   6902 				 */
   6903 				if (incremental) {
   6904 					result = offline(db, ver, zonediff,
   6905 							 name, rdataset.ttl,
   6906 							 &rdata);
   6907 					if (result != ISC_R_SUCCESS) {
   6908 						break;
   6909 					}
   6910 				}
   6911 
   6912 				/*
   6913 				 * Log the key id and algorithm of
   6914 				 * the inactive key with no replacement
   6915 				 */
   6916 				if (zone->log_key_expired_timer <= now) {
   6917 					char origin[DNS_NAME_FORMATSIZE];
   6918 					char algbuf[DNS_NAME_FORMATSIZE];
   6919 					dns_name_format(&zone->origin, origin,
   6920 							sizeof(origin));
   6921 					dns_secalg_format(rrsig.algorithm,
   6922 							  algbuf,
   6923 							  sizeof(algbuf));
   6924 					dns_zone_log(zone, ISC_LOG_WARNING,
   6925 						     "Key %s/%s/%d "
   6926 						     "missing or inactive "
   6927 						     "and has no replacement: "
   6928 						     "retaining signatures.",
   6929 						     origin, algbuf,
   6930 						     rrsig.keyid);
   6931 					zone->log_key_expired_timer = now +
   6932 								      3600;
   6933 				}
   6934 			}
   6935 			continue;
   6936 		}
   6937 
   6938 		/*
   6939 		 * KSK RRSIGs requires special processing.
   6940 		 */
   6941 		found = false;
   6942 		for (i = 0; i < nkeys; i++) {
   6943 			if (rrsig.algorithm == dst_key_alg(keys[i]) &&
   6944 			    rrsig.keyid == dst_key_id(keys[i]))
   6945 			{
   6946 				found = true;
   6947 				/*
   6948 				 * Mark offline DNSKEY.
   6949 				 * We want the earliest offline expire time
   6950 				 * iff there is a new offline signature.
   6951 				 */
   6952 				if (!dst_key_inactive(keys[i]) &&
   6953 				    !dst_key_isprivate(keys[i]) && !offlineksk)
   6954 				{
   6955 					int64_t timeexpire = dns_time64_from32(
   6956 						rrsig.timeexpire);
   6957 					if (timewarn != 0 &&
   6958 					    timewarn > timeexpire)
   6959 					{
   6960 						timewarn = timeexpire;
   6961 					}
   6962 					if (rdata.flags & DNS_RDATA_OFFLINE) {
   6963 						if (timemaybe == 0 ||
   6964 						    timemaybe > timeexpire)
   6965 						{
   6966 							timemaybe = timeexpire;
   6967 						}
   6968 						break;
   6969 					}
   6970 					if (timewarn == 0) {
   6971 						timewarn = timemaybe;
   6972 					}
   6973 					if (timewarn == 0 ||
   6974 					    timewarn > timeexpire)
   6975 					{
   6976 						timewarn = timeexpire;
   6977 					}
   6978 					result = offline(db, ver, zonediff,
   6979 							 name, rdataset.ttl,
   6980 							 &rdata);
   6981 					break;
   6982 				}
   6983 				result = update_one_rr(db, ver, zonediff->diff,
   6984 						       DNS_DIFFOP_DELRESIGN,
   6985 						       name, rdataset.ttl,
   6986 						       &rdata);
   6987 				break;
   6988 			}
   6989 		}
   6990 
   6991 		/*
   6992 		 * If there is not a matching DNSKEY then
   6993 		 * delete the RRSIG.
   6994 		 */
   6995 		if (!found) {
   6996 			result = update_one_rr(db, ver, zonediff->diff,
   6997 					       DNS_DIFFOP_DELRESIGN, name,
   6998 					       rdataset.ttl, &rdata);
   6999 		}
   7000 		if (result != ISC_R_SUCCESS) {
   7001 			break;
   7002 		}
   7003 	}
   7004 
   7005 	dns_rdataset_disassociate(&rdataset);
   7006 	if (result == ISC_R_NOMORE) {
   7007 		result = ISC_R_SUCCESS;
   7008 	}
   7009 	if (timewarn > 0) {
   7010 		isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
   7011 		if (timewarn == stdwarn) {
   7012 			set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
   7013 					       now);
   7014 		} else {
   7015 			dns_zone_log(zone, ISC_LOG_ERROR,
   7016 				     "key expiry warning time out of range");
   7017 		}
   7018 	}
   7019 cleanup:
   7020 	if (node != NULL) {
   7021 		dns_db_detachnode(db, &node);
   7022 	}
   7023 	return result;
   7024 }
   7025 
   7026 static isc_result_t
   7027 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
   7028 	 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
   7029 	 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t now,
   7030 	 isc_stdtime_t inception, isc_stdtime_t expire) {
   7031 	isc_result_t result;
   7032 	dns_dbnode_t *node = NULL;
   7033 	dns_stats_t *dnssecsignstats;
   7034 	dns_rdataset_t rdataset;
   7035 	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
   7036 	unsigned char data[1024]; /* XXX */
   7037 	isc_buffer_t buffer;
   7038 	unsigned int i;
   7039 	bool use_kasp = false;
   7040 	bool offlineksk = false;
   7041 
   7042 	if (zone->kasp != NULL) {
   7043 		use_kasp = true;
   7044 		offlineksk = dns_kasp_offlineksk(zone->kasp);
   7045 	}
   7046 
   7047 	dns_rdataset_init(&rdataset);
   7048 	isc_buffer_init(&buffer, data, sizeof(data));
   7049 
   7050 	if (type == dns_rdatatype_nsec3) {
   7051 		result = dns_db_findnsec3node(db, name, false, &node);
   7052 	} else {
   7053 		result = dns_db_findnode(db, name, false, &node);
   7054 	}
   7055 	if (result == ISC_R_NOTFOUND) {
   7056 		return ISC_R_SUCCESS;
   7057 	}
   7058 	CHECK(result);
   7059 
   7060 	result = dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t)0,
   7061 				     &rdataset, NULL);
   7062 	dns_db_detachnode(db, &node);
   7063 	if (result == ISC_R_NOTFOUND) {
   7064 		INSIST(!dns_rdataset_isassociated(&rdataset));
   7065 		return ISC_R_SUCCESS;
   7066 	}
   7067 	if (result != ISC_R_SUCCESS) {
   7068 		INSIST(!dns_rdataset_isassociated(&rdataset));
   7069 		goto cleanup;
   7070 	}
   7071 
   7072 	for (i = 0; i < nkeys; i++) {
   7073 		/* Don't add signatures for offline or inactive keys */
   7074 		if (!dst_key_isprivate(keys[i]) && !offlineksk) {
   7075 			continue;
   7076 		}
   7077 		if (dst_key_inactive(keys[i]) && !offlineksk) {
   7078 			continue;
   7079 		}
   7080 
   7081 		if (use_kasp) {
   7082 			/*
   7083 			 * A dnssec-policy is found. Check what RRsets this
   7084 			 * key should sign.
   7085 			 */
   7086 			isc_result_t kresult;
   7087 			isc_stdtime_t when;
   7088 			bool ksk = false;
   7089 			bool zsk = false;
   7090 			bool have_zsk = false;
   7091 
   7092 			kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
   7093 			if (kresult != ISC_R_SUCCESS) {
   7094 				if (KSK(keys[i])) {
   7095 					ksk = true;
   7096 				}
   7097 			}
   7098 			kresult = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
   7099 			if (kresult != ISC_R_SUCCESS) {
   7100 				if (!KSK(keys[i])) {
   7101 					zsk = true;
   7102 				}
   7103 			}
   7104 
   7105 			/*
   7106 			 * Don't consider inactive keys or offline keys.
   7107 			 */
   7108 			if (!dst_key_isprivate(keys[i]) && offlineksk && zsk) {
   7109 				continue;
   7110 			}
   7111 			if (dst_key_inactive(keys[i]) && offlineksk && zsk) {
   7112 				continue;
   7113 			}
   7114 
   7115 			if (offlineksk) {
   7116 				have_zsk = true;
   7117 			} else {
   7118 				(void)dst_key_have_ksk_and_zsk(keys, nkeys, i,
   7119 							       true, ksk, zsk,
   7120 							       NULL, &have_zsk);
   7121 			}
   7122 
   7123 			if (dns_rdatatype_iskeymaterial(type)) {
   7124 				/*
   7125 				 * DNSKEY RRset is signed with KSK.
   7126 				 * CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
   7127 				 */
   7128 				if (!ksk) {
   7129 					continue;
   7130 				}
   7131 			} else if (!zsk) {
   7132 				/*
   7133 				 * Other RRsets are signed with ZSK.
   7134 				 */
   7135 				if (type != dns_rdatatype_soa &&
   7136 				    type != zone->privatetype)
   7137 				{
   7138 					continue;
   7139 				}
   7140 				if (have_zsk) {
   7141 					continue;
   7142 				}
   7143 			} else if (!dst_key_is_signing(keys[i], DST_BOOL_ZSK,
   7144 						       now, &when))
   7145 			{
   7146 				/*
   7147 				 * This key is not active for zone-signing.
   7148 				 */
   7149 				continue;
   7150 			}
   7151 		} else if (!REVOKE(keys[i])) {
   7152 			/*
   7153 			 * Don't consider inactive keys, however the KSK may be
   7154 			 * temporary offline, so do consider keys which private
   7155 			 * key files are unavailable.
   7156 			 */
   7157 			bool both = dst_key_have_ksk_and_zsk(
   7158 				keys, nkeys, i, false, KSK(keys[i]),
   7159 				!KSK(keys[i]), NULL, NULL);
   7160 			if (both) {
   7161 				/*
   7162 				 * CDS and CDNSKEY are signed with KSK (RFC
   7163 				 * 7344, 4.1).
   7164 				 */
   7165 				if (dns_rdatatype_iskeymaterial(type)) {
   7166 					if (!KSK(keys[i])) {
   7167 						continue;
   7168 					}
   7169 				} else if (KSK(keys[i])) {
   7170 					continue;
   7171 				}
   7172 			}
   7173 		}
   7174 
   7175 		/*
   7176 		 * If this key is revoked, it may only sign the DNSKEY RRset.
   7177 		 */
   7178 		if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
   7179 			continue;
   7180 		}
   7181 
   7182 		/* Calculate the signature, creating a RRSIG RDATA. */
   7183 		isc_buffer_clear(&buffer);
   7184 
   7185 		if (offlineksk && dns_rdatatype_iskeymaterial(type)) {
   7186 			/* Look up the signature in the SKR bundle */
   7187 			dns_skrbundle_t *bundle = dns_zone_getskrbundle(zone);
   7188 			if (bundle == NULL) {
   7189 				CHECK(DNS_R_NOSKRBUNDLE);
   7190 			}
   7191 			CHECK(dns_skrbundle_getsig(bundle, keys[i], type,
   7192 						   &sig_rdata));
   7193 		} else {
   7194 			CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
   7195 					      &inception, &expire, mctx,
   7196 					      &buffer, &sig_rdata));
   7197 		}
   7198 
   7199 		/* Update the database and journal with the RRSIG. */
   7200 		/* XXX inefficient - will cause dataset merging */
   7201 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
   7202 				    rdataset.ttl, &sig_rdata));
   7203 		dns_rdata_reset(&sig_rdata);
   7204 		isc_buffer_init(&buffer, data, sizeof(data));
   7205 
   7206 		/* Update DNSSEC sign statistics. */
   7207 		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
   7208 		if (dnssecsignstats != NULL) {
   7209 			/* Generated a new signature. */
   7210 			dns_dnssecsignstats_increment(dnssecsignstats,
   7211 						      ID(keys[i]),
   7212 						      (uint8_t)ALG(keys[i]),
   7213 						      dns_dnssecsignstats_sign);
   7214 			/* This is a refresh. */
   7215 			dns_dnssecsignstats_increment(
   7216 				dnssecsignstats, ID(keys[i]),
   7217 				(uint8_t)ALG(keys[i]),
   7218 				dns_dnssecsignstats_refresh);
   7219 		}
   7220 	}
   7221 
   7222 cleanup:
   7223 	if (dns_rdataset_isassociated(&rdataset)) {
   7224 		dns_rdataset_disassociate(&rdataset);
   7225 	}
   7226 	if (node != NULL) {
   7227 		dns_db_detachnode(db, &node);
   7228 	}
   7229 	return result;
   7230 }
   7231 
   7232 static void
   7233 calculate_rrsig_validity(dns_zone_t *zone, isc_stdtime_t now,
   7234 			 isc_stdtime_t *inception, isc_stdtime_t *soaexpire,
   7235 			 isc_stdtime_t *expire, isc_stdtime_t *fullexpire) {
   7236 	REQUIRE(inception != NULL);
   7237 	REQUIRE(soaexpire != NULL);
   7238 	/* expire and fullexpire are optional */
   7239 
   7240 	isc_stdtime_t jitter = DEFAULT_JITTER;
   7241 	isc_stdtime_t sigvalidity = dns_zone_getsigvalidityinterval(zone);
   7242 	isc_stdtime_t shortjitter = 0, fulljitter = 0;
   7243 
   7244 	if (zone->kasp != NULL) {
   7245 		jitter = dns_kasp_sigjitter(zone->kasp);
   7246 		sigvalidity = dns_kasp_sigvalidity(zone->kasp);
   7247 		INSIST(jitter <= sigvalidity);
   7248 	}
   7249 
   7250 	if (jitter > sigvalidity) {
   7251 		jitter = sigvalidity;
   7252 	}
   7253 
   7254 	*inception = now - 3600; /* Allow for clock skew. */
   7255 	*soaexpire = now + sigvalidity;
   7256 
   7257 	/*
   7258 	 * Spread out signatures over time if they happen to be
   7259 	 * clumped.  We don't do this for each add_sigs() call as
   7260 	 * we still want some clustering to occur.  In normal operations
   7261 	 * the records should be re-signed as they fall due and they should
   7262 	 * already be spread out.  However if the server is off for a
   7263 	 * period we need to ensure that the clusters don't become
   7264 	 * synchronised by using the full jitter range.
   7265 	 */
   7266 	if (sigvalidity >= 3600U) {
   7267 		if (sigvalidity > 7200U) {
   7268 			shortjitter = isc_random_uniform(3600);
   7269 			fulljitter = isc_random_uniform(jitter);
   7270 		} else {
   7271 			shortjitter = fulljitter = isc_random_uniform(1200);
   7272 		}
   7273 	}
   7274 
   7275 	SET_IF_NOT_NULL(expire, *soaexpire - shortjitter - 1);
   7276 	SET_IF_NOT_NULL(fullexpire, *soaexpire - fulljitter - 1);
   7277 }
   7278 
   7279 static void
   7280 zone_resigninc(dns_zone_t *zone) {
   7281 	dns_db_t *db = NULL;
   7282 	dns_dbversion_t *version = NULL;
   7283 	dns_diff_t _sig_diff;
   7284 	dns__zonediff_t zonediff;
   7285 	dns_fixedname_t fixed;
   7286 	dns_name_t *name;
   7287 	dns_typepair_t typepair;
   7288 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   7289 	isc_result_t result;
   7290 	isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
   7291 	unsigned int i;
   7292 	unsigned int nkeys = 0;
   7293 	isc_stdtime_t resign;
   7294 
   7295 	ENTER;
   7296 
   7297 	dns_diff_init(zone->mctx, &_sig_diff);
   7298 	zonediff_init(&zonediff, &_sig_diff);
   7299 
   7300 	/*
   7301 	 * Zone is frozen. Pause for 5 minutes.
   7302 	 */
   7303 	if (zone->update_disabled) {
   7304 		CHECK(ISC_R_FAILURE);
   7305 	}
   7306 
   7307 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   7308 	if (zone->db != NULL) {
   7309 		dns_db_attach(zone->db, &db);
   7310 	}
   7311 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   7312 	if (db == NULL) {
   7313 		CHECK(ISC_R_FAILURE);
   7314 	}
   7315 
   7316 	result = dns_db_newversion(db, &version);
   7317 	if (result != ISC_R_SUCCESS) {
   7318 		dns_zone_log(zone, ISC_LOG_ERROR,
   7319 			     "zone_resigninc:dns_db_newversion -> %s",
   7320 			     isc_result_totext(result));
   7321 		goto cleanup;
   7322 	}
   7323 
   7324 	now = isc_stdtime_now();
   7325 
   7326 	result = dns_zone_findkeys(zone, db, version, now, zone->mctx,
   7327 				   DNS_MAXZONEKEYS, zone_keys, &nkeys);
   7328 	if (result != ISC_R_SUCCESS) {
   7329 		dns_zone_log(zone, ISC_LOG_ERROR,
   7330 			     "zone_resigninc:dns_zone_findkeys -> %s",
   7331 			     isc_result_totext(result));
   7332 		goto cleanup;
   7333 	}
   7334 
   7335 	calculate_rrsig_validity(zone, now, &inception, &soaexpire, &expire,
   7336 				 &fullexpire);
   7337 
   7338 	stop = now + 5;
   7339 
   7340 	name = dns_fixedname_initname(&fixed);
   7341 	result = dns_db_getsigningtime(db, &resign, name, &typepair);
   7342 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   7343 		dns_zone_log(zone, ISC_LOG_ERROR,
   7344 			     "zone_resigninc:dns_db_getsigningtime -> %s",
   7345 			     isc_result_totext(result));
   7346 	}
   7347 
   7348 	i = 0;
   7349 	while (result == ISC_R_SUCCESS) {
   7350 		dns_rdatatype_t covers = DNS_TYPEPAIR_COVERS(typepair);
   7351 
   7352 		resign -= dns_zone_getsigresigninginterval(zone);
   7353 
   7354 		/*
   7355 		 * Stop if we hit the SOA as that means we have walked the
   7356 		 * entire zone.  The SOA record should always be the most
   7357 		 * recent signature.
   7358 		 */
   7359 		/* XXXMPA increase number of RRsets signed pre call */
   7360 		if ((covers == dns_rdatatype_soa &&
   7361 		     dns_name_equal(name, &zone->origin)) ||
   7362 		    i++ > zone->signatures || resign > stop)
   7363 		{
   7364 			break;
   7365 		}
   7366 
   7367 		result = del_sigs(zone, db, version, name, covers, &zonediff,
   7368 				  zone_keys, nkeys, now, true);
   7369 		if (result != ISC_R_SUCCESS) {
   7370 			dns_zone_log(zone, ISC_LOG_ERROR,
   7371 				     "zone_resigninc:del_sigs -> %s",
   7372 				     isc_result_totext(result));
   7373 			break;
   7374 		}
   7375 
   7376 		/*
   7377 		 * If re-signing is over 5 minutes late use 'fullexpire'
   7378 		 * to redistribute the signature over the complete
   7379 		 * re-signing window, otherwise only add a small amount
   7380 		 * of jitter.
   7381 		 */
   7382 		result = add_sigs(db, version, name, zone, covers,
   7383 				  zonediff.diff, zone_keys, nkeys, zone->mctx,
   7384 				  now, inception,
   7385 				  resign > (now - 300) ? expire : fullexpire);
   7386 		if (result != ISC_R_SUCCESS) {
   7387 			dns_zone_log(zone, ISC_LOG_ERROR,
   7388 				     "zone_resigninc:add_sigs -> %s",
   7389 				     isc_result_totext(result));
   7390 			break;
   7391 		}
   7392 		result = dns_db_getsigningtime(db, &resign, name, &typepair);
   7393 		if (nkeys == 0 && result == ISC_R_NOTFOUND) {
   7394 			result = ISC_R_SUCCESS;
   7395 			break;
   7396 		}
   7397 		if (result != ISC_R_SUCCESS) {
   7398 			dns_zone_log(zone, ISC_LOG_ERROR,
   7399 				     "zone_resigninc:dns_db_getsigningtime -> "
   7400 				     "%s",
   7401 				     isc_result_totext(result));
   7402 		}
   7403 	}
   7404 
   7405 	if (result != ISC_R_NOMORE) {
   7406 		CHECK(result);
   7407 	}
   7408 
   7409 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
   7410 			  &zonediff, zone_keys, nkeys, now, true);
   7411 	if (result != ISC_R_SUCCESS) {
   7412 		dns_zone_log(zone, ISC_LOG_ERROR,
   7413 			     "zone_resigninc:del_sigs -> %s",
   7414 			     isc_result_totext(result));
   7415 		goto cleanup;
   7416 	}
   7417 
   7418 	/*
   7419 	 * Did we change anything in the zone?
   7420 	 */
   7421 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
   7422 		/*
   7423 		 * Commit the changes if any key has been marked as offline.
   7424 		 */
   7425 		if (zonediff.offline) {
   7426 			dns_db_closeversion(db, &version, true);
   7427 		}
   7428 		goto cleanup;
   7429 	}
   7430 
   7431 	/* Increment SOA serial if we have made changes */
   7432 	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
   7433 				   zone->updatemethod);
   7434 	if (result != ISC_R_SUCCESS) {
   7435 		dns_zone_log(zone, ISC_LOG_ERROR,
   7436 			     "zone_resigninc:update_soa_serial -> %s",
   7437 			     isc_result_totext(result));
   7438 		goto cleanup;
   7439 	}
   7440 
   7441 	/*
   7442 	 * Generate maximum life time signatures so that the above loop
   7443 	 * termination is sensible.
   7444 	 */
   7445 	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
   7446 			  zonediff.diff, zone_keys, nkeys, zone->mctx, now,
   7447 			  inception, soaexpire);
   7448 	if (result != ISC_R_SUCCESS) {
   7449 		dns_zone_log(zone, ISC_LOG_ERROR,
   7450 			     "zone_resigninc:add_sigs -> %s",
   7451 			     isc_result_totext(result));
   7452 		goto cleanup;
   7453 	}
   7454 
   7455 	/* Write changes to journal file. */
   7456 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
   7457 
   7458 	/* Everything has succeeded. Commit the changes. */
   7459 	dns_db_closeversion(db, &version, true);
   7460 
   7461 cleanup:
   7462 	dns_diff_clear(&_sig_diff);
   7463 	for (i = 0; i < nkeys; i++) {
   7464 		dst_key_free(&zone_keys[i]);
   7465 	}
   7466 	if (version != NULL) {
   7467 		dns_db_closeversion(db, &version, false);
   7468 		dns_db_detach(&db);
   7469 	} else if (db != NULL) {
   7470 		dns_db_detach(&db);
   7471 	}
   7472 
   7473 	LOCK_ZONE(zone);
   7474 	if (result == ISC_R_SUCCESS) {
   7475 		set_resigntime(zone);
   7476 		zone_needdump(zone, DNS_DUMP_DELAY);
   7477 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   7478 	} else {
   7479 		/*
   7480 		 * Something failed.  Retry in 5 minutes.
   7481 		 */
   7482 		isc_interval_t ival;
   7483 		isc_interval_set(&ival, 300, 0);
   7484 		isc_time_nowplusinterval(&zone->resigntime, &ival);
   7485 	}
   7486 	UNLOCK_ZONE(zone);
   7487 
   7488 	INSIST(version == NULL);
   7489 }
   7490 
   7491 static isc_result_t
   7492 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
   7493 	    dns_name_t *newname, bool bottom) {
   7494 	isc_result_t result;
   7495 	dns_dbiterator_t *dbit = NULL;
   7496 	dns_rdatasetiter_t *rdsit = NULL;
   7497 	dns_dbnode_t *node = NULL;
   7498 
   7499 	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
   7500 	CHECK(dns_dbiterator_seek(dbit, oldname));
   7501 	do {
   7502 		result = dns_dbiterator_next(dbit);
   7503 		if (result == ISC_R_NOMORE) {
   7504 			CHECK(dns_dbiterator_first(dbit));
   7505 		}
   7506 		CHECK(dns_dbiterator_current(dbit, &node, newname));
   7507 		if (bottom && dns_name_issubdomain(newname, oldname) &&
   7508 		    !dns_name_equal(newname, oldname))
   7509 		{
   7510 			dns_db_detachnode(db, &node);
   7511 			continue;
   7512 		}
   7513 		/*
   7514 		 * Is this node empty?
   7515 		 */
   7516 		CHECK(dns_db_allrdatasets(db, node, version, 0, 0, &rdsit));
   7517 		result = dns_rdatasetiter_first(rdsit);
   7518 		dns_db_detachnode(db, &node);
   7519 		dns_rdatasetiter_destroy(&rdsit);
   7520 		if (result != ISC_R_NOMORE) {
   7521 			break;
   7522 		}
   7523 	} while (1);
   7524 cleanup:
   7525 	if (node != NULL) {
   7526 		dns_db_detachnode(db, &node);
   7527 	}
   7528 	if (dbit != NULL) {
   7529 		dns_dbiterator_destroy(&dbit);
   7530 	}
   7531 	return result;
   7532 }
   7533 
   7534 static bool
   7535 signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
   7536 		     dns_dbversion_t *version, dns_rdatatype_t type,
   7537 		     dst_key_t *key, bool fullsign) {
   7538 	isc_result_t result;
   7539 	dns_rdataset_t rdataset;
   7540 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7541 	dns_rdata_rrsig_t rrsig;
   7542 	int count = 0;
   7543 	dns_kasp_t *kasp = zone->kasp;
   7544 
   7545 	dns_rdataset_init(&rdataset);
   7546 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
   7547 				     type, 0, &rdataset, NULL);
   7548 	if (result != ISC_R_SUCCESS) {
   7549 		INSIST(!dns_rdataset_isassociated(&rdataset));
   7550 		return false;
   7551 	}
   7552 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   7553 	     result = dns_rdataset_next(&rdataset))
   7554 	{
   7555 		dns_rdataset_current(&rdataset, &rdata);
   7556 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   7557 		INSIST(result == ISC_R_SUCCESS);
   7558 		if (rrsig.algorithm == dst_key_alg(key) &&
   7559 		    rrsig.keyid == dst_key_id(key))
   7560 		{
   7561 			dns_rdataset_disassociate(&rdataset);
   7562 			return true;
   7563 		}
   7564 		if (rrsig.algorithm == dst_key_alg(key)) {
   7565 			count++;
   7566 		}
   7567 		dns_rdata_reset(&rdata);
   7568 	}
   7569 
   7570 	if (zone->kasp != NULL && !fullsign) {
   7571 		dns_kasp_key_t *kkey;
   7572 		int zsk_count = 0;
   7573 		bool approved;
   7574 
   7575 		KASP_LOCK(kasp);
   7576 		for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
   7577 		     kkey = ISC_LIST_NEXT(kkey, link))
   7578 		{
   7579 			if (dns_kasp_key_algorithm(kkey) != dst_key_alg(key)) {
   7580 				continue;
   7581 			}
   7582 			if (dns_kasp_key_zsk(kkey)) {
   7583 				zsk_count++;
   7584 			}
   7585 		}
   7586 		KASP_UNLOCK(kasp);
   7587 
   7588 		if (dns_rdatatype_iskeymaterial(type)) {
   7589 			/*
   7590 			 * CDS and CDNSKEY are signed with KSK like DNSKEY.
   7591 			 * (RFC 7344, section 4.1 specifies that they must
   7592 			 * be signed with a key in the current DS RRset,
   7593 			 * which would only include KSK's.)
   7594 			 */
   7595 			approved = false;
   7596 		} else {
   7597 			approved = (zsk_count == count);
   7598 		}
   7599 
   7600 		dns_rdataset_disassociate(&rdataset);
   7601 		return approved;
   7602 	}
   7603 
   7604 	dns_rdataset_disassociate(&rdataset);
   7605 	return false;
   7606 }
   7607 
   7608 static isc_result_t
   7609 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
   7610 	 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom, dns_diff_t *diff) {
   7611 	dns_fixedname_t fixed;
   7612 	dns_name_t *next;
   7613 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7614 	isc_result_t result;
   7615 	unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
   7616 
   7617 	next = dns_fixedname_initname(&fixed);
   7618 
   7619 	CHECK(next_active(db, version, name, next, bottom));
   7620 	CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer, &rdata));
   7621 	CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
   7622 			    &rdata));
   7623 cleanup:
   7624 	return result;
   7625 }
   7626 
   7627 static isc_result_t
   7628 check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
   7629 			dns_dbversion_t *version, bool *is_bottom_of_zone) {
   7630 	isc_result_t result;
   7631 	dns_rdatasetiter_t *iterator = NULL;
   7632 	dns_rdataset_t rdataset;
   7633 	bool seen_soa = false, seen_ns = false, seen_dname = false;
   7634 
   7635 	REQUIRE(is_bottom_of_zone != NULL);
   7636 
   7637 	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
   7638 	if (result != ISC_R_SUCCESS) {
   7639 		if (result == ISC_R_NOTFOUND) {
   7640 			result = ISC_R_SUCCESS;
   7641 		}
   7642 		return result;
   7643 	}
   7644 
   7645 	dns_rdataset_init(&rdataset);
   7646 	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
   7647 	     result = dns_rdatasetiter_next(iterator))
   7648 	{
   7649 		dns_rdatasetiter_current(iterator, &rdataset);
   7650 		switch (rdataset.type) {
   7651 		case dns_rdatatype_soa:
   7652 			seen_soa = true;
   7653 			break;
   7654 		case dns_rdatatype_ns:
   7655 			seen_ns = true;
   7656 			break;
   7657 		case dns_rdatatype_dname:
   7658 			seen_dname = true;
   7659 			break;
   7660 		}
   7661 		dns_rdataset_disassociate(&rdataset);
   7662 	}
   7663 	if (result != ISC_R_NOMORE) {
   7664 		goto cleanup;
   7665 	}
   7666 	if ((seen_ns && !seen_soa) || seen_dname) {
   7667 		*is_bottom_of_zone = true;
   7668 	}
   7669 	result = ISC_R_SUCCESS;
   7670 
   7671 cleanup:
   7672 	dns_rdatasetiter_destroy(&iterator);
   7673 
   7674 	return result;
   7675 }
   7676 
   7677 typedef struct seen {
   7678 	bool rr;
   7679 	bool soa;
   7680 	bool ns;
   7681 	bool nsec;
   7682 	bool nsec3;
   7683 	bool ds;
   7684 	bool dname;
   7685 } seen_t;
   7686 
   7687 static isc_result_t
   7688 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   7689 	     dns_rdatasetiter_t **iterp, seen_t *seen) {
   7690 	isc_result_t result;
   7691 	dns_rdataset_t rdataset = DNS_RDATASET_INIT;
   7692 
   7693 	*seen = (seen_t){};
   7694 
   7695 	RETERR(dns_db_allrdatasets(db, node, version, 0, 0, iterp));
   7696 
   7697 	for (result = dns_rdatasetiter_first(*iterp); result == ISC_R_SUCCESS;
   7698 	     result = dns_rdatasetiter_next(*iterp))
   7699 	{
   7700 		dns_rdatasetiter_current(*iterp, &rdataset);
   7701 
   7702 		if (rdataset.type == dns_rdatatype_rrsig) {
   7703 			dns_rdataset_disassociate(&rdataset);
   7704 			continue;
   7705 		}
   7706 
   7707 		(*seen).rr = true;
   7708 
   7709 		if (rdataset.type == dns_rdatatype_soa) {
   7710 			(*seen).soa = true;
   7711 		} else if (rdataset.type == dns_rdatatype_ns) {
   7712 			(*seen).ns = true;
   7713 		} else if (rdataset.type == dns_rdatatype_ds) {
   7714 			(*seen).ds = true;
   7715 		} else if (rdataset.type == dns_rdatatype_dname) {
   7716 			(*seen).dname = true;
   7717 		} else if (rdataset.type == dns_rdatatype_nsec) {
   7718 			(*seen).nsec = true;
   7719 		} else if (rdataset.type == dns_rdatatype_nsec3) {
   7720 			(*seen).nsec3 = true;
   7721 		}
   7722 
   7723 		dns_rdataset_disassociate(&rdataset);
   7724 	}
   7725 
   7726 	return ISC_R_SUCCESS;
   7727 }
   7728 
   7729 static isc_result_t
   7730 sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
   7731 	    dns_dbnode_t *node, dns_dbversion_t *version, bool build_nsec3,
   7732 	    bool build_nsec, dst_key_t *key, isc_stdtime_t now,
   7733 	    isc_stdtime_t inception, isc_stdtime_t expire, dns_ttl_t nsecttl,
   7734 	    bool both, bool is_ksk, bool is_zsk, bool fullsign,
   7735 	    bool is_bottom_of_zone, dns_diff_t *diff, int32_t *signatures,
   7736 	    isc_mem_t *mctx) {
   7737 	isc_result_t result;
   7738 	dns_rdatasetiter_t *iterator = NULL;
   7739 	dns_rdataset_t rdataset;
   7740 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7741 	dns_stats_t *dnssecsignstats;
   7742 	bool offlineksk = false;
   7743 	isc_buffer_t buffer;
   7744 	unsigned char data[1024];
   7745 	seen_t seen;
   7746 
   7747 	if (zone->kasp != NULL) {
   7748 		offlineksk = dns_kasp_offlineksk(zone->kasp);
   7749 	}
   7750 
   7751 	result = allrdatasets(db, node, version, &iterator, &seen);
   7752 	if (result != ISC_R_SUCCESS) {
   7753 		if (result == ISC_R_NOTFOUND) {
   7754 			result = ISC_R_SUCCESS;
   7755 		}
   7756 		return result;
   7757 	}
   7758 
   7759 	dns_rdataset_init(&rdataset);
   7760 	isc_buffer_init(&buffer, data, sizeof(data));
   7761 
   7762 	/*
   7763 	 * Going from insecure to NSEC3.
   7764 	 * Don't generate NSEC3 records for NSEC3 records.
   7765 	 */
   7766 	if (build_nsec3 && !seen.nsec3 && seen.rr) {
   7767 		bool unsecure = !seen.ds && seen.ns && !seen.soa;
   7768 		CHECK(dns_nsec3_addnsec3s(db, version, name, nsecttl, unsecure,
   7769 					  diff));
   7770 		(*signatures)--;
   7771 	}
   7772 	/*
   7773 	 * Going from insecure to NSEC.
   7774 	 * Don't generate NSEC records for NSEC3 records.
   7775 	 */
   7776 	if (build_nsec && !seen.nsec3 && !seen.nsec && seen.rr) {
   7777 		/*
   7778 		 * Build a NSEC record except at the origin.
   7779 		 */
   7780 		if (!dns_name_equal(name, dns_db_origin(db))) {
   7781 			CHECK(add_nsec(db, version, name, node, nsecttl,
   7782 				       is_bottom_of_zone, diff));
   7783 			/* Count a NSEC generation as a signature generation. */
   7784 			(*signatures)--;
   7785 		}
   7786 	}
   7787 	result = dns_rdatasetiter_first(iterator);
   7788 	while (result == ISC_R_SUCCESS) {
   7789 		isc_stdtime_t when;
   7790 
   7791 		dns_rdatasetiter_current(iterator, &rdataset);
   7792 		if (rdataset.type == dns_rdatatype_soa ||
   7793 		    rdataset.type == dns_rdatatype_rrsig)
   7794 		{
   7795 			goto next_rdataset;
   7796 		}
   7797 		if (dns_rdatatype_iskeymaterial(rdataset.type)) {
   7798 			/*
   7799 			 * CDS and CDNSKEY are signed with KSK like DNSKEY.
   7800 			 * (RFC 7344, section 4.1 specifies that they must
   7801 			 * be signed with a key in the current DS RRset,
   7802 			 * which would only include KSK's.)
   7803 			 */
   7804 			if (!is_ksk && both) {
   7805 				goto next_rdataset;
   7806 			}
   7807 		} else if (!is_zsk && both) {
   7808 			goto next_rdataset;
   7809 		} else if (is_zsk &&
   7810 			   !dst_key_is_signing(key, DST_BOOL_ZSK, now, &when))
   7811 		{
   7812 			/* Only applies to dnssec-policy. */
   7813 			if (zone->kasp != NULL) {
   7814 				goto next_rdataset;
   7815 			}
   7816 		}
   7817 
   7818 		if (seen.ns && !seen.soa && rdataset.type != dns_rdatatype_ds &&
   7819 		    rdataset.type != dns_rdatatype_nsec)
   7820 		{
   7821 			goto next_rdataset;
   7822 		}
   7823 		if (signed_with_good_key(zone, db, node, version, rdataset.type,
   7824 					 key, fullsign))
   7825 		{
   7826 			goto next_rdataset;
   7827 		}
   7828 
   7829 		/* Calculate the signature, creating a RRSIG RDATA. */
   7830 		isc_buffer_clear(&buffer);
   7831 		if (offlineksk && dns_rdatatype_iskeymaterial(rdataset.type)) {
   7832 			/* Look up the signature in the SKR bundle */
   7833 			dns_skrbundle_t *bundle = dns_zone_getskrbundle(zone);
   7834 			if (bundle == NULL) {
   7835 				CHECK(DNS_R_NOSKRBUNDLE);
   7836 			}
   7837 			CHECK(dns_skrbundle_getsig(bundle, key, rdataset.type,
   7838 						   &rdata));
   7839 		} else {
   7840 			CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
   7841 					      &expire, mctx, &buffer, &rdata));
   7842 		}
   7843 
   7844 		/* Update the database and journal with the RRSIG. */
   7845 		/* XXX inefficient - will cause dataset merging */
   7846 		CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
   7847 				    name, rdataset.ttl, &rdata));
   7848 		dns_rdata_reset(&rdata);
   7849 
   7850 		/* Update DNSSEC sign statistics. */
   7851 		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
   7852 		if (dnssecsignstats != NULL) {
   7853 			/* Generated a new signature. */
   7854 			dns_dnssecsignstats_increment(dnssecsignstats, ID(key),
   7855 						      ALG(key),
   7856 						      dns_dnssecsignstats_sign);
   7857 			/* This is a refresh. */
   7858 			dns_dnssecsignstats_increment(
   7859 				dnssecsignstats, ID(key), ALG(key),
   7860 				dns_dnssecsignstats_refresh);
   7861 		}
   7862 
   7863 		(*signatures)--;
   7864 	next_rdataset:
   7865 		dns_rdataset_disassociate(&rdataset);
   7866 		result = dns_rdatasetiter_next(iterator);
   7867 	}
   7868 	if (result == ISC_R_NOMORE) {
   7869 		result = ISC_R_SUCCESS;
   7870 	}
   7871 
   7872 cleanup:
   7873 	if (dns_rdataset_isassociated(&rdataset)) {
   7874 		dns_rdataset_disassociate(&rdataset);
   7875 	}
   7876 	if (iterator != NULL) {
   7877 		dns_rdatasetiter_destroy(&iterator);
   7878 	}
   7879 	return result;
   7880 }
   7881 
   7882 /*
   7883  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
   7884  */
   7885 static isc_result_t
   7886 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
   7887 	     dns_ttl_t nsecttl, bool update_only, dns_diff_t *diff) {
   7888 	isc_result_t result;
   7889 	dns_rdataset_t rdataset;
   7890 	dns_dbnode_t *node = NULL;
   7891 
   7892 	CHECK(dns_db_getoriginnode(db, &node));
   7893 	if (update_only) {
   7894 		dns_rdataset_init(&rdataset);
   7895 		result = dns_db_findrdataset(
   7896 			db, node, version, dns_rdatatype_nsec,
   7897 			dns_rdatatype_none, 0, &rdataset, NULL);
   7898 		if (dns_rdataset_isassociated(&rdataset)) {
   7899 			dns_rdataset_disassociate(&rdataset);
   7900 		}
   7901 		if (result == ISC_R_NOTFOUND) {
   7902 			goto success;
   7903 		}
   7904 		CHECK(result);
   7905 	}
   7906 	CHECK(delete_nsec(db, version, node, name, diff));
   7907 	CHECK(add_nsec(db, version, name, node, nsecttl, false, diff));
   7908 success:
   7909 	result = ISC_R_SUCCESS;
   7910 cleanup:
   7911 	if (node != NULL) {
   7912 		dns_db_detachnode(db, &node);
   7913 	}
   7914 	return result;
   7915 }
   7916 
   7917 static isc_result_t
   7918 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
   7919 		  dns_dbversion_t *version, bool build_nsec3, dns_ttl_t nsecttl,
   7920 		  dns_diff_t *diff) {
   7921 	isc_result_t result;
   7922 	dns_dbnode_t *node = NULL;
   7923 	dns_rdataset_t rdataset;
   7924 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7925 	unsigned char data[5];
   7926 	bool seen_done = false;
   7927 	bool have_rr = false;
   7928 
   7929 	dns_rdataset_init(&rdataset);
   7930 	CHECK(dns_db_getoriginnode(signing->db, &node));
   7931 
   7932 	result = dns_db_findrdataset(signing->db, node, version,
   7933 				     zone->privatetype, dns_rdatatype_none, 0,
   7934 				     &rdataset, NULL);
   7935 	if (result == ISC_R_NOTFOUND) {
   7936 		INSIST(!dns_rdataset_isassociated(&rdataset));
   7937 		result = ISC_R_SUCCESS;
   7938 		goto cleanup;
   7939 	}
   7940 	if (result != ISC_R_SUCCESS) {
   7941 		INSIST(!dns_rdataset_isassociated(&rdataset));
   7942 		goto cleanup;
   7943 	}
   7944 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   7945 	     result = dns_rdataset_next(&rdataset))
   7946 	{
   7947 		dns_rdataset_current(&rdataset, &rdata);
   7948 		/*
   7949 		 * If we don't match the algorithm or keyid skip the record.
   7950 		 */
   7951 		if (rdata.length != 5 || rdata.data[0] != signing->algorithm ||
   7952 		    rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
   7953 		    rdata.data[2] != (signing->keyid & 0xff))
   7954 		{
   7955 			have_rr = true;
   7956 			dns_rdata_reset(&rdata);
   7957 			continue;
   7958 		}
   7959 		/*
   7960 		 * We have a match.  If we were signing (!signing->deleteit)
   7961 		 * and we already have a record indicating that we have
   7962 		 * finished signing (rdata.data[4] != 0) then keep it.
   7963 		 * Otherwise it needs to be deleted as we have removed all
   7964 		 * the signatures (signing->deleteit), so any record indicating
   7965 		 * completion is now out of date, or we have finished signing
   7966 		 * with the new record so we no longer need to remember that
   7967 		 * we need to sign the zone with the matching key across a
   7968 		 * nameserver re-start.
   7969 		 */
   7970 		if (!signing->deleteit && rdata.data[4] != 0) {
   7971 			seen_done = true;
   7972 			have_rr = true;
   7973 		} else {
   7974 			CHECK(update_one_rr(signing->db, version, diff,
   7975 					    DNS_DIFFOP_DEL, &zone->origin,
   7976 					    rdataset.ttl, &rdata));
   7977 		}
   7978 		dns_rdata_reset(&rdata);
   7979 	}
   7980 	if (result == ISC_R_NOMORE) {
   7981 		result = ISC_R_SUCCESS;
   7982 	}
   7983 	if (!signing->deleteit && !seen_done) {
   7984 		/*
   7985 		 * If we were signing then we need to indicate that we have
   7986 		 * finished signing the zone with this key.  If it is already
   7987 		 * there we don't need to add it a second time.
   7988 		 */
   7989 		data[0] = signing->algorithm;
   7990 		data[1] = (signing->keyid >> 8) & 0xff;
   7991 		data[2] = signing->keyid & 0xff;
   7992 		data[3] = 0;
   7993 		data[4] = 1;
   7994 		rdata.length = sizeof(data);
   7995 		rdata.data = data;
   7996 		rdata.type = zone->privatetype;
   7997 		rdata.rdclass = dns_db_class(signing->db);
   7998 		CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
   7999 				    &zone->origin, rdataset.ttl, &rdata));
   8000 	} else if (!have_rr) {
   8001 		dns_name_t *origin = dns_db_origin(signing->db);
   8002 		/*
   8003 		 * Rebuild the NSEC/NSEC3 record for the origin as we no
   8004 		 * longer have any private records.
   8005 		 */
   8006 		if (build_nsec3) {
   8007 			CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
   8008 						  nsecttl, false, diff));
   8009 		}
   8010 		CHECK(updatesecure(signing->db, version, origin, nsecttl, true,
   8011 				   diff));
   8012 	}
   8013 
   8014 cleanup:
   8015 	if (dns_rdataset_isassociated(&rdataset)) {
   8016 		dns_rdataset_disassociate(&rdataset);
   8017 	}
   8018 	if (node != NULL) {
   8019 		dns_db_detachnode(signing->db, &node);
   8020 	}
   8021 	return result;
   8022 }
   8023 
   8024 /*
   8025  * Called from zone_nsec3chain() in order to update zone records indicating
   8026  * processing status of given NSEC3 chain:
   8027  *
   8028  *   - If the supplied dns_nsec3chain_t structure has been fully processed
   8029  *     (which is indicated by "active" being set to false):
   8030  *
   8031  *       - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
   8032  *
   8033  *       - remove all private-type records containing NSEC3PARAM RDATA matching
   8034  *         the relevant NSEC3 chain.
   8035  *
   8036  *   - If the supplied dns_nsec3chain_t structure has not been fully processed
   8037  *     (which is indicated by "active" being set to true), only remove the
   8038  *     NSEC3PARAM record which matches the relevant NSEC3 chain and has the
   8039  *     "flags" field set to 0.
   8040  *
   8041  *   - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
   8042  *     in the relevant private-type record, but with the "flags" field set to
   8043  *     0, indicating that this NSEC3 chain is now complete for this zone.
   8044  *
   8045  * Note that this function is called at different processing stages for NSEC3
   8046  * chain additions vs. removals and needs to handle all cases properly.
   8047  */
   8048 static isc_result_t
   8049 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
   8050 		 bool active, dns_rdatatype_t privatetype, dns_diff_t *diff) {
   8051 	dns_dbnode_t *node = NULL;
   8052 	dns_name_t *name = dns_db_origin(db);
   8053 	dns_rdata_t rdata = DNS_RDATA_INIT;
   8054 	dns_rdataset_t rdataset;
   8055 	dns_rdata_nsec3param_t nsec3param;
   8056 	dns_rdata_soa_t soa;
   8057 	isc_result_t result;
   8058 	isc_buffer_t buffer;
   8059 	unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
   8060 	dns_ttl_t ttl = 0;
   8061 	bool nseconly = false, nsec3ok = false;
   8062 
   8063 	dns_rdataset_init(&rdataset);
   8064 
   8065 	result = dns_db_getoriginnode(db, &node);
   8066 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8067 
   8068 	/* Default TTL is SOA MINIMUM */
   8069 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0, 0,
   8070 				     &rdataset, NULL);
   8071 	if (result == ISC_R_SUCCESS) {
   8072 		CHECK(dns_rdataset_first(&rdataset));
   8073 		dns_rdataset_current(&rdataset, &rdata);
   8074 		CHECK(dns_rdata_tostruct(&rdata, &soa, NULL));
   8075 		ttl = soa.minimum;
   8076 		dns_rdata_reset(&rdata);
   8077 	}
   8078 	if (dns_rdataset_isassociated(&rdataset)) {
   8079 		dns_rdataset_disassociate(&rdataset);
   8080 	}
   8081 
   8082 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
   8083 				     0, &rdataset, NULL);
   8084 	if (result == ISC_R_NOTFOUND) {
   8085 		goto try_private;
   8086 	}
   8087 	if (result != ISC_R_SUCCESS) {
   8088 		goto cleanup;
   8089 	}
   8090 
   8091 	/*
   8092 	 * Delete all NSEC3PARAM records which match that in nsec3chain.
   8093 	 */
   8094 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   8095 	     result = dns_rdataset_next(&rdataset))
   8096 	{
   8097 		dns_rdataset_current(&rdataset, &rdata);
   8098 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
   8099 
   8100 		if (nsec3param.hash != chain->nsec3param.hash ||
   8101 		    (active && nsec3param.flags != 0) ||
   8102 		    nsec3param.iterations != chain->nsec3param.iterations ||
   8103 		    nsec3param.salt_length != chain->nsec3param.salt_length ||
   8104 		    memcmp(nsec3param.salt, chain->nsec3param.salt,
   8105 			   nsec3param.salt_length))
   8106 		{
   8107 			/*
   8108 			 * If the SOA minimum is different to the current TTL,
   8109 			 * delete the record.  We will re-add it with the new
   8110 			 * TTL below.
   8111 			 */
   8112 			if (rdataset.ttl != ttl) {
   8113 				CHECK(update_one_rr(db, ver, diff,
   8114 						    DNS_DIFFOP_DEL, name,
   8115 						    rdataset.ttl, &rdata));
   8116 			}
   8117 			dns_rdata_reset(&rdata);
   8118 			continue;
   8119 		}
   8120 
   8121 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
   8122 				    rdataset.ttl, &rdata));
   8123 		dns_rdata_reset(&rdata);
   8124 	}
   8125 	if (result != ISC_R_NOMORE) {
   8126 		goto cleanup;
   8127 	}
   8128 
   8129 	/*
   8130 	 * Restore any NSEC3PARAM records that we deleted to change the TTL.
   8131 	 */
   8132 	if (rdataset.ttl != ttl) {
   8133 		for (result = dns_rdataset_first(&rdataset);
   8134 		     result == ISC_R_SUCCESS;
   8135 		     result = dns_rdataset_next(&rdataset))
   8136 		{
   8137 			dns_rdataset_current(&rdataset, &rdata);
   8138 			CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
   8139 
   8140 			if (nsec3param.hash != chain->nsec3param.hash ||
   8141 			    (active && nsec3param.flags != 0) ||
   8142 			    nsec3param.iterations !=
   8143 				    chain->nsec3param.iterations ||
   8144 			    nsec3param.salt_length !=
   8145 				    chain->nsec3param.salt_length ||
   8146 			    memcmp(nsec3param.salt, chain->nsec3param.salt,
   8147 				   nsec3param.salt_length))
   8148 			{
   8149 				CHECK(update_one_rr(db, ver, diff,
   8150 						    DNS_DIFFOP_ADD, name, ttl,
   8151 						    &rdata));
   8152 			}
   8153 			dns_rdata_reset(&rdata);
   8154 		}
   8155 	}
   8156 
   8157 	dns_rdataset_disassociate(&rdataset);
   8158 
   8159 try_private:
   8160 
   8161 	if (active) {
   8162 		goto add;
   8163 	}
   8164 
   8165 	result = dns_nsec_nseconly(db, ver, diff, &nseconly);
   8166 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
   8167 
   8168 	/*
   8169 	 * Delete all private records which match that in nsec3chain.
   8170 	 */
   8171 	result = dns_db_findrdataset(db, node, ver, privatetype, 0, 0,
   8172 				     &rdataset, NULL);
   8173 	if (result == ISC_R_NOTFOUND) {
   8174 		goto add;
   8175 	}
   8176 	CHECK(result);
   8177 
   8178 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   8179 	     result = dns_rdataset_next(&rdataset))
   8180 	{
   8181 		dns_rdata_t private = DNS_RDATA_INIT;
   8182 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   8183 
   8184 		dns_rdataset_current(&rdataset, &private);
   8185 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
   8186 						sizeof(buf)))
   8187 		{
   8188 			continue;
   8189 		}
   8190 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
   8191 
   8192 		if ((!nsec3ok &&
   8193 		     (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
   8194 		    nsec3param.hash != chain->nsec3param.hash ||
   8195 		    nsec3param.iterations != chain->nsec3param.iterations ||
   8196 		    nsec3param.salt_length != chain->nsec3param.salt_length ||
   8197 		    memcmp(nsec3param.salt, chain->nsec3param.salt,
   8198 			   nsec3param.salt_length))
   8199 		{
   8200 			dns_rdata_reset(&rdata);
   8201 			continue;
   8202 		}
   8203 
   8204 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
   8205 				    rdataset.ttl, &private));
   8206 		dns_rdata_reset(&rdata);
   8207 	}
   8208 	if (result != ISC_R_NOMORE) {
   8209 		goto cleanup;
   8210 	}
   8211 
   8212 add:
   8213 	if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
   8214 		result = ISC_R_SUCCESS;
   8215 		goto cleanup;
   8216 	}
   8217 
   8218 	/*
   8219 	 * Add a NSEC3PARAM record which matches that in nsec3chain but
   8220 	 * with all flags bits cleared.
   8221 	 *
   8222 	 * Note: we do not clear chain->nsec3param.flags as this change
   8223 	 * may be reversed.
   8224 	 */
   8225 	isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
   8226 	CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
   8227 				   dns_rdatatype_nsec3param, &chain->nsec3param,
   8228 				   &buffer));
   8229 	rdata.data[1] = 0; /* Clear flag bits. */
   8230 	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
   8231 
   8232 cleanup:
   8233 	dns_db_detachnode(db, &node);
   8234 	if (dns_rdataset_isassociated(&rdataset)) {
   8235 		dns_rdataset_disassociate(&rdataset);
   8236 	}
   8237 	return result;
   8238 }
   8239 
   8240 static isc_result_t
   8241 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
   8242 	    dns_name_t *name, dns_diff_t *diff) {
   8243 	dns_rdataset_t rdataset;
   8244 	isc_result_t result;
   8245 
   8246 	dns_rdataset_init(&rdataset);
   8247 
   8248 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
   8249 				     &rdataset, NULL);
   8250 	if (result == ISC_R_NOTFOUND) {
   8251 		return ISC_R_SUCCESS;
   8252 	}
   8253 	if (result != ISC_R_SUCCESS) {
   8254 		return result;
   8255 	}
   8256 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   8257 	     result = dns_rdataset_next(&rdataset))
   8258 	{
   8259 		dns_rdata_t rdata = DNS_RDATA_INIT;
   8260 
   8261 		dns_rdataset_current(&rdataset, &rdata);
   8262 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
   8263 				    rdataset.ttl, &rdata));
   8264 	}
   8265 	if (result == ISC_R_NOMORE) {
   8266 		result = ISC_R_SUCCESS;
   8267 	}
   8268 
   8269 cleanup:
   8270 	dns_rdataset_disassociate(&rdataset);
   8271 	return result;
   8272 }
   8273 
   8274 static isc_result_t
   8275 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
   8276 		    dns_name_t *name, const dns_rdata_nsec3param_t *param,
   8277 		    dns_diff_t *diff) {
   8278 	dns_rdataset_t rdataset;
   8279 	dns_rdata_nsec3_t nsec3;
   8280 	isc_result_t result;
   8281 
   8282 	dns_rdataset_init(&rdataset);
   8283 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0,
   8284 				     &rdataset, NULL);
   8285 	if (result == ISC_R_NOTFOUND) {
   8286 		return ISC_R_SUCCESS;
   8287 	}
   8288 	if (result != ISC_R_SUCCESS) {
   8289 		return result;
   8290 	}
   8291 
   8292 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   8293 	     result = dns_rdataset_next(&rdataset))
   8294 	{
   8295 		dns_rdata_t rdata = DNS_RDATA_INIT;
   8296 
   8297 		dns_rdataset_current(&rdataset, &rdata);
   8298 		CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
   8299 		if (nsec3.hash != param->hash ||
   8300 		    nsec3.iterations != param->iterations ||
   8301 		    nsec3.salt_length != param->salt_length ||
   8302 		    memcmp(nsec3.salt, param->salt, nsec3.salt_length))
   8303 		{
   8304 			continue;
   8305 		}
   8306 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
   8307 				    rdataset.ttl, &rdata));
   8308 	}
   8309 	if (result == ISC_R_NOMORE) {
   8310 		result = ISC_R_SUCCESS;
   8311 	}
   8312 
   8313 cleanup:
   8314 	dns_rdataset_disassociate(&rdataset);
   8315 	return result;
   8316 }
   8317 
   8318 static isc_result_t
   8319 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
   8320 		const dns_rdata_nsec3param_t *param, bool *answer) {
   8321 	dns_dbnode_t *node = NULL;
   8322 	dns_rdata_t rdata = DNS_RDATA_INIT;
   8323 	dns_rdata_nsec3param_t myparam;
   8324 	dns_rdataset_t rdataset;
   8325 	isc_result_t result;
   8326 
   8327 	*answer = false;
   8328 
   8329 	result = dns_db_getoriginnode(db, &node);
   8330 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8331 
   8332 	dns_rdataset_init(&rdataset);
   8333 
   8334 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
   8335 				     &rdataset, NULL);
   8336 	if (result == ISC_R_SUCCESS) {
   8337 		dns_rdataset_disassociate(&rdataset);
   8338 		dns_db_detachnode(db, &node);
   8339 		return result;
   8340 	}
   8341 	if (result != ISC_R_NOTFOUND) {
   8342 		dns_db_detachnode(db, &node);
   8343 		return result;
   8344 	}
   8345 
   8346 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
   8347 				     0, &rdataset, NULL);
   8348 	if (result == ISC_R_NOTFOUND) {
   8349 		*answer = true;
   8350 		dns_db_detachnode(db, &node);
   8351 		return ISC_R_SUCCESS;
   8352 	}
   8353 	if (result != ISC_R_SUCCESS) {
   8354 		dns_db_detachnode(db, &node);
   8355 		return result;
   8356 	}
   8357 
   8358 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   8359 	     result = dns_rdataset_next(&rdataset))
   8360 	{
   8361 		dns_rdataset_current(&rdataset, &rdata);
   8362 		CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
   8363 		dns_rdata_reset(&rdata);
   8364 		/*
   8365 		 * Ignore any NSEC3PARAM removals.
   8366 		 */
   8367 		if (NSEC3REMOVE(myparam.flags)) {
   8368 			continue;
   8369 		}
   8370 		/*
   8371 		 * Ignore the chain that we are in the process of deleting.
   8372 		 */
   8373 		if (myparam.hash == param->hash &&
   8374 		    myparam.iterations == param->iterations &&
   8375 		    myparam.salt_length == param->salt_length &&
   8376 		    !memcmp(myparam.salt, param->salt, myparam.salt_length))
   8377 		{
   8378 			continue;
   8379 		}
   8380 		/*
   8381 		 * Found an active NSEC3 chain.
   8382 		 */
   8383 		break;
   8384 	}
   8385 	if (result == ISC_R_NOMORE) {
   8386 		*answer = true;
   8387 		result = ISC_R_SUCCESS;
   8388 	}
   8389 
   8390 cleanup:
   8391 	if (dns_rdataset_isassociated(&rdataset)) {
   8392 		dns_rdataset_disassociate(&rdataset);
   8393 	}
   8394 	dns_db_detachnode(db, &node);
   8395 	return result;
   8396 }
   8397 
   8398 /*%
   8399  * Given a tuple which is part of a diff, return a pointer to the next tuple in
   8400  * that diff which has the same name and type (or NULL if no such tuple is
   8401  * found).
   8402  */
   8403 static dns_difftuple_t *
   8404 find_next_matching_tuple(dns_difftuple_t *cur) {
   8405 	dns_difftuple_t *next = cur;
   8406 
   8407 	while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
   8408 		if (cur->rdata.type == next->rdata.type &&
   8409 		    dns_name_equal(&cur->name, &next->name))
   8410 		{
   8411 			return next;
   8412 		}
   8413 	}
   8414 
   8415 	return NULL;
   8416 }
   8417 
   8418 /*%
   8419  * Remove all tuples with the same name and type as 'cur' from 'src' and append
   8420  * them to 'dst'.
   8421  */
   8422 static void
   8423 move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
   8424 	do {
   8425 		dns_difftuple_t *next = find_next_matching_tuple(cur);
   8426 		ISC_LIST_UNLINK(src->tuples, cur, link);
   8427 		dns_diff_appendminimal(dst, &cur);
   8428 		cur = next;
   8429 	} while (cur != NULL);
   8430 }
   8431 
   8432 /*%
   8433  * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
   8434  * 'diff'.  Gradually remove tuples from 'diff' and append them to 'zonediff'
   8435  * along with tuples representing relevant signature changes.
   8436  */
   8437 isc_result_t
   8438 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
   8439 		     dst_key_t *zone_keys[], unsigned int nkeys,
   8440 		     dns_zone_t *zone, isc_stdtime_t inception,
   8441 		     isc_stdtime_t expire, isc_stdtime_t keyexpire,
   8442 		     isc_stdtime_t now, dns__zonediff_t *zonediff) {
   8443 	dns_difftuple_t *tuple;
   8444 	isc_result_t result;
   8445 
   8446 	while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
   8447 		isc_stdtime_t exp = expire;
   8448 
   8449 		if (keyexpire != 0 &&
   8450 		    dns_rdatatype_iskeymaterial(tuple->rdata.type))
   8451 		{
   8452 			exp = keyexpire;
   8453 		}
   8454 
   8455 		result = del_sigs(zone, db, version, &tuple->name,
   8456 				  tuple->rdata.type, zonediff, zone_keys, nkeys,
   8457 				  now, false);
   8458 		if (result != ISC_R_SUCCESS) {
   8459 			dns_zone_log(zone, ISC_LOG_ERROR,
   8460 				     "dns__zone_updatesigs:del_sigs -> %s",
   8461 				     isc_result_totext(result));
   8462 			return result;
   8463 		}
   8464 		result = add_sigs(db, version, &tuple->name, zone,
   8465 				  tuple->rdata.type, zonediff->diff, zone_keys,
   8466 				  nkeys, zone->mctx, now, inception, exp);
   8467 		if (result != ISC_R_SUCCESS) {
   8468 			dns_zone_log(zone, ISC_LOG_ERROR,
   8469 				     "dns__zone_updatesigs:add_sigs -> %s",
   8470 				     isc_result_totext(result));
   8471 			return result;
   8472 		}
   8473 
   8474 		/*
   8475 		 * Signature changes for all RRs with name tuple->name and type
   8476 		 * tuple->rdata.type were appended to zonediff->diff.  Now we
   8477 		 * remove all the "raw" changes with the same name and type
   8478 		 * from diff (so that they are not processed by this loop
   8479 		 * again) and append them to zonediff so that they get applied.
   8480 		 */
   8481 		move_matching_tuples(tuple, diff, zonediff->diff);
   8482 	}
   8483 	return ISC_R_SUCCESS;
   8484 }
   8485 
   8486 /*
   8487  * Incrementally build and sign a new NSEC3 chain using the parameters
   8488  * requested.
   8489  */
   8490 static void
   8491 zone_nsec3chain(dns_zone_t *zone) {
   8492 	dns_db_t *db = NULL;
   8493 	dns_dbnode_t *node = NULL;
   8494 	dns_dbversion_t *version = NULL;
   8495 	dns_diff_t _sig_diff;
   8496 	dns_diff_t nsec_diff;
   8497 	dns_diff_t nsec3_diff;
   8498 	dns_diff_t param_diff;
   8499 	dns__zonediff_t zonediff;
   8500 	dns_fixedname_t fixed;
   8501 	dns_fixedname_t nextfixed;
   8502 	dns_name_t *name, *nextname;
   8503 	dns_rdataset_t rdataset;
   8504 	dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
   8505 	dns_nsec3chainlist_t cleanup;
   8506 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   8507 	int32_t signatures;
   8508 	bool delegation;
   8509 	bool first;
   8510 	isc_result_t result;
   8511 	isc_stdtime_t now, inception, soaexpire, expire;
   8512 	unsigned int i;
   8513 	unsigned int nkeys = 0;
   8514 	uint32_t nodes;
   8515 	bool unsecure = false;
   8516 	seen_t seen;
   8517 	dns_rdatasetiter_t *iterator = NULL;
   8518 	bool buildnsecchain;
   8519 	bool updatensec = false;
   8520 	dns_rdatatype_t privatetype = zone->privatetype;
   8521 
   8522 	ENTER;
   8523 
   8524 	dns_rdataset_init(&rdataset);
   8525 	name = dns_fixedname_initname(&fixed);
   8526 	nextname = dns_fixedname_initname(&nextfixed);
   8527 	dns_diff_init(zone->mctx, &param_diff);
   8528 	dns_diff_init(zone->mctx, &nsec3_diff);
   8529 	dns_diff_init(zone->mctx, &nsec_diff);
   8530 	dns_diff_init(zone->mctx, &_sig_diff);
   8531 	zonediff_init(&zonediff, &_sig_diff);
   8532 	ISC_LIST_INIT(cleanup);
   8533 
   8534 	/*
   8535 	 * Updates are disabled.  Pause for 5 minutes.
   8536 	 */
   8537 	if (zone->update_disabled) {
   8538 		CHECK(ISC_R_FAILURE);
   8539 	}
   8540 
   8541 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   8542 	/*
   8543 	 * This function is called when zone timer fires, after the latter gets
   8544 	 * set by zone_addnsec3chain().  If the action triggering the call to
   8545 	 * zone_addnsec3chain() is closely followed by a zone deletion request,
   8546 	 * it might turn out that the timer thread will not be woken up until
   8547 	 * after the zone is deleted by rmzone(), which calls dns_db_detach()
   8548 	 * for zone->db, causing the latter to become NULL.  Return immediately
   8549 	 * if that happens.
   8550 	 */
   8551 	if (zone->db != NULL) {
   8552 		dns_db_attach(zone->db, &db);
   8553 	}
   8554 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   8555 	if (db == NULL) {
   8556 		return;
   8557 	}
   8558 
   8559 	result = dns_db_newversion(db, &version);
   8560 	if (result != ISC_R_SUCCESS) {
   8561 		dnssec_log(zone, ISC_LOG_ERROR,
   8562 			   "zone_nsec3chain:dns_db_newversion -> %s",
   8563 			   isc_result_totext(result));
   8564 		goto cleanup;
   8565 	}
   8566 
   8567 	now = isc_stdtime_now();
   8568 
   8569 	result = dns_zone_findkeys(zone, db, version, now, zone->mctx,
   8570 				   DNS_MAXZONEKEYS, zone_keys, &nkeys);
   8571 	if (result != ISC_R_SUCCESS) {
   8572 		dnssec_log(zone, ISC_LOG_ERROR,
   8573 			   "zone_nsec3chain:dns_zone_findkeys -> %s",
   8574 			   isc_result_totext(result));
   8575 		goto cleanup;
   8576 	}
   8577 
   8578 	calculate_rrsig_validity(zone, now, &inception, &soaexpire, NULL,
   8579 				 &expire);
   8580 
   8581 	/*
   8582 	 * We keep pulling nodes off each iterator in turn until
   8583 	 * we have no more nodes to pull off or we reach the limits
   8584 	 * for this quantum.
   8585 	 */
   8586 	nodes = zone->nodes;
   8587 	signatures = zone->signatures;
   8588 	LOCK_ZONE(zone);
   8589 	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   8590 	UNLOCK_ZONE(zone);
   8591 	first = true;
   8592 
   8593 	if (nsec3chain != NULL) {
   8594 		nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
   8595 	}
   8596 	/*
   8597 	 * Generate new NSEC3 chains first.
   8598 	 *
   8599 	 * The following while loop iterates over nodes in the zone database,
   8600 	 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
   8601 	 * them.  Once all nodes are processed, the "delete_nsec" field is
   8602 	 * consulted to check whether we are supposed to remove NSEC records
   8603 	 * from the zone database; if so, the database iterator is reset to
   8604 	 * point to the first node and the loop traverses all of them again,
   8605 	 * this time removing NSEC records.  If we hit a node which is obscured
   8606 	 * by a delegation or a DNAME, nodes are skipped over until we find one
   8607 	 * that is not obscured by the same obscuring name and then normal
   8608 	 * processing is resumed.
   8609 	 *
   8610 	 * The above is repeated until all requested NSEC3 chain changes are
   8611 	 * applied or when we reach the limits for this quantum, whichever
   8612 	 * happens first.
   8613 	 *
   8614 	 * Note that the "signatures" variable is only used here to limit the
   8615 	 * amount of work performed.  Actual DNSSEC signatures are only
   8616 	 * generated by dns__zone_updatesigs() calls later in this function.
   8617 	 */
   8618 	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
   8619 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8620 
   8621 		LOCK_ZONE(zone);
   8622 		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
   8623 
   8624 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   8625 		if (nsec3chain->done || nsec3chain->db != zone->db) {
   8626 			ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
   8627 			ISC_LIST_APPEND(cleanup, nsec3chain, link);
   8628 		}
   8629 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   8630 		UNLOCK_ZONE(zone);
   8631 		if (ISC_LIST_TAIL(cleanup) == nsec3chain) {
   8632 			goto next_addchain;
   8633 		}
   8634 
   8635 		/*
   8636 		 * Possible future db.
   8637 		 */
   8638 		if (nsec3chain->db != db) {
   8639 			goto next_addchain;
   8640 		}
   8641 
   8642 		if (NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
   8643 			goto next_addchain;
   8644 		}
   8645 
   8646 		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
   8647 
   8648 		if (nsec3chain->delete_nsec) {
   8649 			delegation = false;
   8650 			dns_dbiterator_pause(nsec3chain->dbiterator);
   8651 			CHECK(delete_nsec(db, version, node, name, &nsec_diff));
   8652 			goto next_addnode;
   8653 		}
   8654 		/*
   8655 		 * On the first pass we need to check if the current node
   8656 		 * has not been obscured.
   8657 		 */
   8658 		delegation = false;
   8659 		unsecure = false;
   8660 		if (first) {
   8661 			dns_fixedname_t ffound;
   8662 			dns_name_t *found;
   8663 			found = dns_fixedname_initname(&ffound);
   8664 			result = dns_db_find(
   8665 				db, name, version, dns_rdatatype_soa,
   8666 				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
   8667 			if ((result == DNS_R_DELEGATION ||
   8668 			     result == DNS_R_DNAME) &&
   8669 			    !dns_name_equal(name, found))
   8670 			{
   8671 				/*
   8672 				 * Remember the obscuring name so that
   8673 				 * we skip all obscured names.
   8674 				 */
   8675 				dns_name_copy(found, name);
   8676 				delegation = true;
   8677 				goto next_addnode;
   8678 			}
   8679 		}
   8680 
   8681 		/*
   8682 		 * Check to see if this is a bottom of zone node.
   8683 		 */
   8684 		result = allrdatasets(db, node, version, &iterator, &seen);
   8685 		if (result == ISC_R_NOTFOUND) {
   8686 			/* Empty node? */
   8687 			goto next_addnode;
   8688 		}
   8689 		CHECK(result);
   8690 
   8691 		INSIST(!seen.nsec3);
   8692 
   8693 		dns_rdatasetiter_destroy(&iterator);
   8694 		/*
   8695 		 * Is there a NSEC chain than needs to be cleaned up?
   8696 		 */
   8697 		if (seen.nsec) {
   8698 			nsec3chain->seen_nsec = true;
   8699 		}
   8700 
   8701 		if (seen.ns && !seen.soa && !seen.ds) {
   8702 			unsecure = true;
   8703 		}
   8704 		if ((seen.ns && !seen.soa) || seen.dname) {
   8705 			delegation = true;
   8706 		}
   8707 
   8708 		/*
   8709 		 * Process one node.
   8710 		 */
   8711 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8712 		result = dns_nsec3_addnsec3(
   8713 			db, version, name, &nsec3chain->nsec3param,
   8714 			zone_nsecttl(zone), unsecure, &nsec3_diff);
   8715 		if (result != ISC_R_SUCCESS) {
   8716 			dnssec_log(zone, ISC_LOG_ERROR,
   8717 				   "zone_nsec3chain:"
   8718 				   "dns_nsec3_addnsec3 -> %s",
   8719 				   isc_result_totext(result));
   8720 			goto cleanup;
   8721 		}
   8722 
   8723 		/*
   8724 		 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
   8725 		 * two signatures.  Additionally there will, in general, be
   8726 		 * two signature generated below.
   8727 		 *
   8728 		 * If we are only changing the optout flag the cost is half
   8729 		 * that of the cost of generating a completely new chain.
   8730 		 */
   8731 		signatures -= 4;
   8732 
   8733 		/*
   8734 		 * Go onto next node.
   8735 		 */
   8736 	next_addnode:
   8737 		first = false;
   8738 		dns_db_detachnode(db, &node);
   8739 		do {
   8740 			result = dns_dbiterator_next(nsec3chain->dbiterator);
   8741 
   8742 			if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
   8743 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8744 				CHECK(fixup_nsec3param(db, version, nsec3chain,
   8745 						       false, privatetype,
   8746 						       &param_diff));
   8747 				LOCK_ZONE(zone);
   8748 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
   8749 						link);
   8750 				UNLOCK_ZONE(zone);
   8751 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
   8752 				goto next_addchain;
   8753 			}
   8754 			if (result == ISC_R_NOMORE) {
   8755 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8756 				if (nsec3chain->seen_nsec) {
   8757 					CHECK(fixup_nsec3param(
   8758 						db, version, nsec3chain, true,
   8759 						privatetype, &param_diff));
   8760 					nsec3chain->delete_nsec = true;
   8761 					goto same_addchain;
   8762 				}
   8763 				CHECK(fixup_nsec3param(db, version, nsec3chain,
   8764 						       false, privatetype,
   8765 						       &param_diff));
   8766 				LOCK_ZONE(zone);
   8767 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
   8768 						link);
   8769 				UNLOCK_ZONE(zone);
   8770 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
   8771 				goto next_addchain;
   8772 			} else if (result != ISC_R_SUCCESS) {
   8773 				dnssec_log(zone, ISC_LOG_ERROR,
   8774 					   "zone_nsec3chain:"
   8775 					   "dns_dbiterator_next -> %s",
   8776 					   isc_result_totext(result));
   8777 				goto cleanup;
   8778 			} else if (delegation) {
   8779 				dns_dbiterator_current(nsec3chain->dbiterator,
   8780 						       &node, nextname);
   8781 				dns_db_detachnode(db, &node);
   8782 				if (!dns_name_issubdomain(nextname, name)) {
   8783 					break;
   8784 				}
   8785 			} else {
   8786 				break;
   8787 			}
   8788 		} while (1);
   8789 		continue;
   8790 
   8791 	same_addchain:
   8792 		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
   8793 		first = true;
   8794 		continue;
   8795 
   8796 	next_addchain:
   8797 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8798 		nsec3chain = nextnsec3chain;
   8799 		first = true;
   8800 		if (nsec3chain != NULL) {
   8801 			nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
   8802 		}
   8803 	}
   8804 
   8805 	if (nsec3chain != NULL) {
   8806 		goto skip_removals;
   8807 	}
   8808 
   8809 	/*
   8810 	 * Process removals.
   8811 	 *
   8812 	 * This is a counterpart of the above while loop which takes care of
   8813 	 * removing an NSEC3 chain.  It starts with determining whether the
   8814 	 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
   8815 	 * NSEC chain by iterating over all nodes in the zone database and only
   8816 	 * then goes on to remove NSEC3 records be iterating over all nodes
   8817 	 * again and calling deletematchingnsec3() for each of them; otherwise,
   8818 	 * it starts removing NSEC3 records immediately.  Rules for processing
   8819 	 * obscured nodes and interrupting work are the same as for the while
   8820 	 * loop above.
   8821 	 */
   8822 	LOCK_ZONE(zone);
   8823 	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   8824 	UNLOCK_ZONE(zone);
   8825 	first = true;
   8826 	buildnsecchain = false;
   8827 	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
   8828 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8829 
   8830 		LOCK_ZONE(zone);
   8831 		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
   8832 		UNLOCK_ZONE(zone);
   8833 
   8834 		if (nsec3chain->db != db) {
   8835 			goto next_removechain;
   8836 		}
   8837 
   8838 		if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
   8839 			goto next_removechain;
   8840 		}
   8841 
   8842 		/*
   8843 		 * Work out if we need to build a NSEC chain as a consequence
   8844 		 * of removing this NSEC3 chain.
   8845 		 */
   8846 		if (first && !updatensec &&
   8847 		    (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
   8848 		{
   8849 			result = need_nsec_chain(db, version,
   8850 						 &nsec3chain->nsec3param,
   8851 						 &buildnsecchain);
   8852 			if (result != ISC_R_SUCCESS) {
   8853 				dnssec_log(zone, ISC_LOG_ERROR,
   8854 					   "zone_nsec3chain:"
   8855 					   "need_nsec_chain -> %s",
   8856 					   isc_result_totext(result));
   8857 				goto cleanup;
   8858 			}
   8859 		}
   8860 
   8861 		if (first) {
   8862 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   8863 				   "zone_nsec3chain:buildnsecchain = %u",
   8864 				   buildnsecchain);
   8865 		}
   8866 
   8867 		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
   8868 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8869 		delegation = false;
   8870 
   8871 		if (!buildnsecchain) {
   8872 			/*
   8873 			 * Delete the NSEC3PARAM record matching this chain.
   8874 			 */
   8875 			if (first) {
   8876 				result = fixup_nsec3param(
   8877 					db, version, nsec3chain, true,
   8878 					privatetype, &param_diff);
   8879 				if (result != ISC_R_SUCCESS) {
   8880 					dnssec_log(zone, ISC_LOG_ERROR,
   8881 						   "zone_nsec3chain:"
   8882 						   "fixup_nsec3param -> %s",
   8883 						   isc_result_totext(result));
   8884 					goto cleanup;
   8885 				}
   8886 			}
   8887 
   8888 			/*
   8889 			 * Delete the NSEC3 records.
   8890 			 */
   8891 			result = deletematchingnsec3(db, version, node, name,
   8892 						     &nsec3chain->nsec3param,
   8893 						     &nsec3_diff);
   8894 			if (result != ISC_R_SUCCESS) {
   8895 				dnssec_log(zone, ISC_LOG_ERROR,
   8896 					   "zone_nsec3chain:"
   8897 					   "deletematchingnsec3 -> %s",
   8898 					   isc_result_totext(result));
   8899 				goto cleanup;
   8900 			}
   8901 			goto next_removenode;
   8902 		}
   8903 
   8904 		if (first) {
   8905 			dns_fixedname_t ffound;
   8906 			dns_name_t *found;
   8907 			found = dns_fixedname_initname(&ffound);
   8908 			result = dns_db_find(
   8909 				db, name, version, dns_rdatatype_soa,
   8910 				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
   8911 			if ((result == DNS_R_DELEGATION ||
   8912 			     result == DNS_R_DNAME) &&
   8913 			    !dns_name_equal(name, found))
   8914 			{
   8915 				/*
   8916 				 * Remember the obscuring name so that
   8917 				 * we skip all obscured names.
   8918 				 */
   8919 				dns_name_copy(found, name);
   8920 				delegation = true;
   8921 				goto next_removenode;
   8922 			}
   8923 		}
   8924 
   8925 		/*
   8926 		 * Check to see if this is a bottom of zone node.
   8927 		 */
   8928 		result = allrdatasets(db, node, version, &iterator, &seen);
   8929 		if (result == ISC_R_NOTFOUND) {
   8930 			/* Empty node? */
   8931 			goto next_removenode;
   8932 		}
   8933 		CHECK(result);
   8934 
   8935 		dns_rdatasetiter_destroy(&iterator);
   8936 
   8937 		if (!seen.rr || seen.nsec3 || seen.nsec) {
   8938 			goto next_removenode;
   8939 		}
   8940 		if ((seen.ns && !seen.soa) || seen.dname) {
   8941 			delegation = true;
   8942 		}
   8943 
   8944 		/*
   8945 		 * Add a NSEC record except at the origin.
   8946 		 */
   8947 		if (!dns_name_equal(name, dns_db_origin(db))) {
   8948 			dns_dbiterator_pause(nsec3chain->dbiterator);
   8949 			CHECK(add_nsec(db, version, name, node,
   8950 				       zone_nsecttl(zone), delegation,
   8951 				       &nsec_diff));
   8952 			signatures--;
   8953 		}
   8954 
   8955 	next_removenode:
   8956 		first = false;
   8957 		dns_db_detachnode(db, &node);
   8958 		do {
   8959 			result = dns_dbiterator_next(nsec3chain->dbiterator);
   8960 			if (result == ISC_R_NOMORE && buildnsecchain) {
   8961 				/*
   8962 				 * The NSEC chain should now be built.
   8963 				 * We can now remove the NSEC3 chain.
   8964 				 */
   8965 				updatensec = true;
   8966 				goto same_removechain;
   8967 			}
   8968 			if (result == ISC_R_NOMORE) {
   8969 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8970 				LOCK_ZONE(zone);
   8971 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
   8972 						link);
   8973 				UNLOCK_ZONE(zone);
   8974 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
   8975 				result = fixup_nsec3param(
   8976 					db, version, nsec3chain, false,
   8977 					privatetype, &param_diff);
   8978 				if (result != ISC_R_SUCCESS) {
   8979 					dnssec_log(zone, ISC_LOG_ERROR,
   8980 						   "zone_nsec3chain:"
   8981 						   "fixup_nsec3param -> %s",
   8982 						   isc_result_totext(result));
   8983 					goto cleanup;
   8984 				}
   8985 				goto next_removechain;
   8986 			} else if (result != ISC_R_SUCCESS) {
   8987 				dnssec_log(zone, ISC_LOG_ERROR,
   8988 					   "zone_nsec3chain:"
   8989 					   "dns_dbiterator_next -> %s",
   8990 					   isc_result_totext(result));
   8991 				goto cleanup;
   8992 			} else if (delegation) {
   8993 				dns_dbiterator_current(nsec3chain->dbiterator,
   8994 						       &node, nextname);
   8995 				dns_db_detachnode(db, &node);
   8996 				if (!dns_name_issubdomain(nextname, name)) {
   8997 					break;
   8998 				}
   8999 			} else {
   9000 				break;
   9001 			}
   9002 		} while (1);
   9003 		continue;
   9004 
   9005 	same_removechain:
   9006 		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
   9007 		buildnsecchain = false;
   9008 		first = true;
   9009 		continue;
   9010 
   9011 	next_removechain:
   9012 		dns_dbiterator_pause(nsec3chain->dbiterator);
   9013 		nsec3chain = nextnsec3chain;
   9014 		first = true;
   9015 	}
   9016 
   9017 skip_removals:
   9018 	/*
   9019 	 * We may need to update the NSEC/NSEC3 records for the zone apex.
   9020 	 */
   9021 	if (!ISC_LIST_EMPTY(param_diff.tuples)) {
   9022 		bool rebuild_nsec = false, rebuild_nsec3 = false;
   9023 		result = dns_db_getoriginnode(db, &node);
   9024 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9025 		result = dns_db_allrdatasets(db, node, version, 0, 0,
   9026 					     &iterator);
   9027 		if (result != ISC_R_SUCCESS) {
   9028 			dnssec_log(zone, ISC_LOG_ERROR,
   9029 				   "zone_nsec3chain:dns_db_allrdatasets -> %s",
   9030 				   isc_result_totext(result));
   9031 			goto cleanup;
   9032 		}
   9033 		for (result = dns_rdatasetiter_first(iterator);
   9034 		     result == ISC_R_SUCCESS;
   9035 		     result = dns_rdatasetiter_next(iterator))
   9036 		{
   9037 			dns_rdatasetiter_current(iterator, &rdataset);
   9038 			if (rdataset.type == dns_rdatatype_nsec) {
   9039 				rebuild_nsec = true;
   9040 			} else if (rdataset.type == dns_rdatatype_nsec3param) {
   9041 				rebuild_nsec3 = true;
   9042 			}
   9043 			dns_rdataset_disassociate(&rdataset);
   9044 		}
   9045 		dns_rdatasetiter_destroy(&iterator);
   9046 		dns_db_detachnode(db, &node);
   9047 
   9048 		if (rebuild_nsec) {
   9049 			if (nsec3chain != NULL) {
   9050 				dns_dbiterator_pause(nsec3chain->dbiterator);
   9051 			}
   9052 
   9053 			result = updatesecure(db, version, &zone->origin,
   9054 					      zone_nsecttl(zone), true,
   9055 					      &nsec_diff);
   9056 			if (result != ISC_R_SUCCESS) {
   9057 				dnssec_log(zone, ISC_LOG_ERROR,
   9058 					   "zone_nsec3chain:updatesecure -> %s",
   9059 					   isc_result_totext(result));
   9060 				goto cleanup;
   9061 			}
   9062 		}
   9063 
   9064 		if (rebuild_nsec3) {
   9065 			if (nsec3chain != NULL) {
   9066 				dns_dbiterator_pause(nsec3chain->dbiterator);
   9067 			}
   9068 
   9069 			result = dns_nsec3_addnsec3s(
   9070 				db, version, dns_db_origin(db),
   9071 				zone_nsecttl(zone), false, &nsec3_diff);
   9072 			if (result != ISC_R_SUCCESS) {
   9073 				dnssec_log(zone, ISC_LOG_ERROR,
   9074 					   "zone_nsec3chain:"
   9075 					   "dns_nsec3_addnsec3s -> %s",
   9076 					   isc_result_totext(result));
   9077 				goto cleanup;
   9078 			}
   9079 		}
   9080 	}
   9081 
   9082 	/*
   9083 	 * Add / update signatures for the NSEC3 records.
   9084 	 */
   9085 	if (nsec3chain != NULL) {
   9086 		dns_dbiterator_pause(nsec3chain->dbiterator);
   9087 	}
   9088 	result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
   9089 				      nkeys, zone, inception, expire, 0, now,
   9090 				      &zonediff);
   9091 	if (result != ISC_R_SUCCESS) {
   9092 		dnssec_log(zone, ISC_LOG_ERROR,
   9093 			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
   9094 			   isc_result_totext(result));
   9095 		goto cleanup;
   9096 	}
   9097 
   9098 	/*
   9099 	 * We have changed the NSEC3PARAM or private RRsets
   9100 	 * above so we need to update the signatures.
   9101 	 */
   9102 	result = dns__zone_updatesigs(&param_diff, db, version, zone_keys,
   9103 				      nkeys, zone, inception, expire, 0, now,
   9104 				      &zonediff);
   9105 	if (result != ISC_R_SUCCESS) {
   9106 		dnssec_log(zone, ISC_LOG_ERROR,
   9107 			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
   9108 			   isc_result_totext(result));
   9109 		goto cleanup;
   9110 	}
   9111 
   9112 	if (updatensec) {
   9113 		result = updatesecure(db, version, &zone->origin,
   9114 				      zone_nsecttl(zone), false, &nsec_diff);
   9115 		if (result != ISC_R_SUCCESS) {
   9116 			dnssec_log(zone, ISC_LOG_ERROR,
   9117 				   "zone_nsec3chain:updatesecure -> %s",
   9118 				   isc_result_totext(result));
   9119 			goto cleanup;
   9120 		}
   9121 	}
   9122 
   9123 	result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys, nkeys,
   9124 				      zone, inception, expire, 0, now,
   9125 				      &zonediff);
   9126 	if (result != ISC_R_SUCCESS) {
   9127 		dnssec_log(zone, ISC_LOG_ERROR,
   9128 			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
   9129 			   isc_result_totext(result));
   9130 		goto cleanup;
   9131 	}
   9132 
   9133 	/*
   9134 	 * If we made no effective changes to the zone then we can just
   9135 	 * cleanup otherwise we need to increment the serial.
   9136 	 */
   9137 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
   9138 		/*
   9139 		 * No need to call dns_db_closeversion() here as it is
   9140 		 * called with commit = true below.
   9141 		 */
   9142 		goto closeversion;
   9143 	}
   9144 
   9145 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
   9146 			  &zonediff, zone_keys, nkeys, now, false);
   9147 	if (result != ISC_R_SUCCESS) {
   9148 		dnssec_log(zone, ISC_LOG_ERROR,
   9149 			   "zone_nsec3chain:del_sigs -> %s",
   9150 			   isc_result_totext(result));
   9151 		goto cleanup;
   9152 	}
   9153 
   9154 	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
   9155 				   zone->updatemethod);
   9156 	if (result != ISC_R_SUCCESS) {
   9157 		dnssec_log(zone, ISC_LOG_ERROR,
   9158 			   "zone_nsec3chain:update_soa_serial -> %s",
   9159 			   isc_result_totext(result));
   9160 		goto cleanup;
   9161 	}
   9162 
   9163 	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
   9164 			  zonediff.diff, zone_keys, nkeys, zone->mctx, now,
   9165 			  inception, soaexpire);
   9166 	if (result != ISC_R_SUCCESS) {
   9167 		dnssec_log(zone, ISC_LOG_ERROR,
   9168 			   "zone_nsec3chain:add_sigs -> %s",
   9169 			   isc_result_totext(result));
   9170 		goto cleanup;
   9171 	}
   9172 
   9173 	/* Write changes to journal file. */
   9174 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
   9175 
   9176 	LOCK_ZONE(zone);
   9177 	zone_needdump(zone, DNS_DUMP_DELAY);
   9178 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   9179 	UNLOCK_ZONE(zone);
   9180 
   9181 closeversion:
   9182 	/*
   9183 	 * Pause all iterators so that dns_db_closeversion() can succeed.
   9184 	 */
   9185 	LOCK_ZONE(zone);
   9186 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
   9187 	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
   9188 	{
   9189 		dns_dbiterator_pause(nsec3chain->dbiterator);
   9190 	}
   9191 	UNLOCK_ZONE(zone);
   9192 
   9193 	/*
   9194 	 * Everything has succeeded. Commit the changes.
   9195 	 * Unconditionally commit as zonediff.offline not checked above.
   9196 	 */
   9197 	dns_db_closeversion(db, &version, true);
   9198 
   9199 	/*
   9200 	 * Everything succeeded so we can clean these up now.
   9201 	 */
   9202 	nsec3chain = ISC_LIST_HEAD(cleanup);
   9203 	while (nsec3chain != NULL) {
   9204 		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
   9205 		dns_db_detach(&nsec3chain->db);
   9206 		dns_dbiterator_destroy(&nsec3chain->dbiterator);
   9207 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   9208 		nsec3chain = ISC_LIST_HEAD(cleanup);
   9209 	}
   9210 
   9211 	LOCK_ZONE(zone);
   9212 	set_resigntime(zone);
   9213 	UNLOCK_ZONE(zone);
   9214 
   9215 cleanup:
   9216 	if (result != ISC_R_SUCCESS) {
   9217 		dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
   9218 			   isc_result_totext(result));
   9219 	}
   9220 
   9221 	/*
   9222 	 * On error roll back the current nsec3chain.
   9223 	 */
   9224 	if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
   9225 		if (nsec3chain->done) {
   9226 			dns_db_detach(&nsec3chain->db);
   9227 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
   9228 			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   9229 		} else {
   9230 			result = dns_dbiterator_first(nsec3chain->dbiterator);
   9231 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9232 			dns_dbiterator_pause(nsec3chain->dbiterator);
   9233 			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
   9234 		}
   9235 	}
   9236 
   9237 	/*
   9238 	 * Rollback the cleanup list.
   9239 	 */
   9240 	nsec3chain = ISC_LIST_TAIL(cleanup);
   9241 	while (nsec3chain != NULL) {
   9242 		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
   9243 		if (nsec3chain->done) {
   9244 			dns_db_detach(&nsec3chain->db);
   9245 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
   9246 			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   9247 		} else {
   9248 			LOCK_ZONE(zone);
   9249 			ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
   9250 			UNLOCK_ZONE(zone);
   9251 			result = dns_dbiterator_first(nsec3chain->dbiterator);
   9252 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9253 			dns_dbiterator_pause(nsec3chain->dbiterator);
   9254 			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
   9255 		}
   9256 		nsec3chain = ISC_LIST_TAIL(cleanup);
   9257 	}
   9258 
   9259 	LOCK_ZONE(zone);
   9260 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
   9261 	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
   9262 	{
   9263 		dns_dbiterator_pause(nsec3chain->dbiterator);
   9264 	}
   9265 	UNLOCK_ZONE(zone);
   9266 
   9267 	dns_diff_clear(&param_diff);
   9268 	dns_diff_clear(&nsec3_diff);
   9269 	dns_diff_clear(&nsec_diff);
   9270 	dns_diff_clear(&_sig_diff);
   9271 
   9272 	if (iterator != NULL) {
   9273 		dns_rdatasetiter_destroy(&iterator);
   9274 	}
   9275 
   9276 	for (i = 0; i < nkeys; i++) {
   9277 		dst_key_free(&zone_keys[i]);
   9278 	}
   9279 
   9280 	if (node != NULL) {
   9281 		dns_db_detachnode(db, &node);
   9282 	}
   9283 	if (version != NULL) {
   9284 		dns_db_closeversion(db, &version, false);
   9285 		dns_db_detach(&db);
   9286 	} else if (db != NULL) {
   9287 		dns_db_detach(&db);
   9288 	}
   9289 
   9290 	LOCK_ZONE(zone);
   9291 	if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
   9292 		isc_interval_t interval;
   9293 		if (zone->update_disabled || result != ISC_R_SUCCESS) {
   9294 			isc_interval_set(&interval, 60, 0); /* 1 minute */
   9295 		} else {
   9296 			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
   9297 		}
   9298 		isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
   9299 	} else {
   9300 		isc_time_settoepoch(&zone->nsec3chaintime);
   9301 	}
   9302 	UNLOCK_ZONE(zone);
   9303 
   9304 	INSIST(version == NULL);
   9305 }
   9306 
   9307 /*%
   9308  * Delete all RRSIG records with the given algorithm and keyid.
   9309  * Remove the NSEC record and RRSIGs if nkeys is zero.
   9310  * If all remaining RRsets are signed with the given algorithm
   9311  * set *has_algp to true.
   9312  */
   9313 static isc_result_t
   9314 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
   9315 	dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
   9316 	uint16_t keyid, bool *has_algp, dns_diff_t *diff) {
   9317 	dns_rdata_rrsig_t rrsig;
   9318 	dns_rdataset_t rdataset;
   9319 	dns_rdatasetiter_t *iterator = NULL;
   9320 	isc_result_t result;
   9321 	bool alg_missed = false;
   9322 	bool alg_found = false;
   9323 
   9324 	char namebuf[DNS_NAME_FORMATSIZE];
   9325 	dns_name_format(name, namebuf, sizeof(namebuf));
   9326 
   9327 	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
   9328 	if (result != ISC_R_SUCCESS) {
   9329 		if (result == ISC_R_NOTFOUND) {
   9330 			result = ISC_R_SUCCESS;
   9331 		}
   9332 		return result;
   9333 	}
   9334 
   9335 	dns_rdataset_init(&rdataset);
   9336 	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
   9337 	     result = dns_rdatasetiter_next(iterator))
   9338 	{
   9339 		bool has_alg = false;
   9340 		dns_rdatasetiter_current(iterator, &rdataset);
   9341 		if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
   9342 			for (result = dns_rdataset_first(&rdataset);
   9343 			     result == ISC_R_SUCCESS;
   9344 			     result = dns_rdataset_next(&rdataset))
   9345 			{
   9346 				dns_rdata_t rdata = DNS_RDATA_INIT;
   9347 				dns_rdataset_current(&rdataset, &rdata);
   9348 				CHECK(update_one_rr(db, version, diff,
   9349 						    DNS_DIFFOP_DEL, name,
   9350 						    rdataset.ttl, &rdata));
   9351 			}
   9352 			if (result != ISC_R_NOMORE) {
   9353 				goto cleanup;
   9354 			}
   9355 			dns_rdataset_disassociate(&rdataset);
   9356 			continue;
   9357 		}
   9358 		if (rdataset.type != dns_rdatatype_rrsig) {
   9359 			dns_rdataset_disassociate(&rdataset);
   9360 			continue;
   9361 		}
   9362 		for (result = dns_rdataset_first(&rdataset);
   9363 		     result == ISC_R_SUCCESS;
   9364 		     result = dns_rdataset_next(&rdataset))
   9365 		{
   9366 			dns_rdata_t rdata = DNS_RDATA_INIT;
   9367 			dns_rdataset_current(&rdataset, &rdata);
   9368 			CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
   9369 			if (nkeys != 0 && (rrsig.algorithm != algorithm ||
   9370 					   rrsig.keyid != keyid))
   9371 			{
   9372 				if (rrsig.algorithm == algorithm) {
   9373 					has_alg = true;
   9374 				}
   9375 				continue;
   9376 			}
   9377 			CHECK(update_one_rr(db, version, diff,
   9378 					    DNS_DIFFOP_DELRESIGN, name,
   9379 					    rdataset.ttl, &rdata));
   9380 		}
   9381 		dns_rdataset_disassociate(&rdataset);
   9382 		if (result != ISC_R_NOMORE) {
   9383 			break;
   9384 		}
   9385 
   9386 		/*
   9387 		 * After deleting, if there's still a signature for
   9388 		 * 'algorithm', set alg_found; if not, set alg_missed.
   9389 		 */
   9390 		if (has_alg) {
   9391 			alg_found = true;
   9392 		} else {
   9393 			alg_missed = true;
   9394 		}
   9395 	}
   9396 	if (result == ISC_R_NOMORE) {
   9397 		result = ISC_R_SUCCESS;
   9398 	}
   9399 
   9400 	/*
   9401 	 * Set `has_algp` if the algorithm was found in every RRset:
   9402 	 * i.e., found in at least one, and not missing from any.
   9403 	 */
   9404 	*has_algp = (alg_found && !alg_missed);
   9405 cleanup:
   9406 	if (dns_rdataset_isassociated(&rdataset)) {
   9407 		dns_rdataset_disassociate(&rdataset);
   9408 	}
   9409 	dns_rdatasetiter_destroy(&iterator);
   9410 	return result;
   9411 }
   9412 
   9413 /*
   9414  * Prevent the zone entering a inconsistent state where
   9415  * NSEC only DNSKEYs are present with NSEC3 chains.
   9416  */
   9417 bool
   9418 dns_zone_check_dnskey_nsec3(dns_zone_t *zone, dns_db_t *db,
   9419 			    dns_dbversion_t *ver, dns_diff_t *diff,
   9420 			    dst_key_t **keys, unsigned int numkeys) {
   9421 	uint8_t alg;
   9422 	dns_rdatatype_t privatetype;
   9423 	;
   9424 	bool nseconly = false, nsec3 = false;
   9425 	isc_result_t result;
   9426 
   9427 	REQUIRE(DNS_ZONE_VALID(zone));
   9428 	REQUIRE(db != NULL);
   9429 
   9430 	privatetype = dns_zone_getprivatetype(zone);
   9431 
   9432 	/* Scan the tuples for an NSEC-only DNSKEY */
   9433 	if (diff != NULL) {
   9434 		for (dns_difftuple_t *tuple = ISC_LIST_HEAD(diff->tuples);
   9435 		     tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
   9436 		{
   9437 			if (nseconly && nsec3) {
   9438 				break;
   9439 			}
   9440 
   9441 			if (tuple->op != DNS_DIFFOP_ADD) {
   9442 				continue;
   9443 			}
   9444 
   9445 			if (tuple->rdata.type == dns_rdatatype_nsec3param) {
   9446 				nsec3 = true;
   9447 			}
   9448 
   9449 			if (tuple->rdata.type != dns_rdatatype_dnskey) {
   9450 				continue;
   9451 			}
   9452 
   9453 			alg = tuple->rdata.data[3];
   9454 			if (alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_DSA ||
   9455 			    alg == DNS_KEYALG_RSASHA1)
   9456 			{
   9457 				nseconly = true;
   9458 			}
   9459 		}
   9460 	}
   9461 	/* Scan the zone keys for an NSEC-only DNSKEY */
   9462 	if (keys != NULL && !nseconly) {
   9463 		for (unsigned int i = 0; i < numkeys; i++) {
   9464 			alg = dst_key_alg(keys[i]);
   9465 			if (alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_DSA ||
   9466 			    alg == DNS_KEYALG_RSASHA1)
   9467 			{
   9468 				nseconly = true;
   9469 				break;
   9470 			}
   9471 		}
   9472 	}
   9473 
   9474 	/* Check DB for NSEC-only DNSKEY */
   9475 	if (!nseconly) {
   9476 		result = dns_nsec_nseconly(db, ver, diff, &nseconly);
   9477 		/*
   9478 		 * Adding an NSEC3PARAM record can proceed without a
   9479 		 * DNSKEY (it will trigger a delayed change), so we can
   9480 		 * ignore ISC_R_NOTFOUND here.
   9481 		 */
   9482 		if (result == ISC_R_NOTFOUND) {
   9483 			result = ISC_R_SUCCESS;
   9484 		}
   9485 		CHECK(result);
   9486 	}
   9487 
   9488 	/* Check existing DB for NSEC3 */
   9489 	if (!nsec3) {
   9490 		CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3));
   9491 	}
   9492 
   9493 	/* Check kasp for NSEC3PARAM settings */
   9494 	if (!nsec3) {
   9495 		dns_kasp_t *kasp = zone->kasp;
   9496 		if (kasp != NULL) {
   9497 			nsec3 = dns_kasp_nsec3(kasp);
   9498 		}
   9499 	}
   9500 
   9501 	/* Refuse to allow NSEC3 with NSEC-only keys */
   9502 	if (nseconly && nsec3) {
   9503 		goto cleanup;
   9504 	}
   9505 
   9506 	return true;
   9507 
   9508 cleanup:
   9509 	return false;
   9510 }
   9511 
   9512 /*
   9513  * Incrementally sign the zone using the keys requested.
   9514  * Builds the NSEC chain if required.
   9515  */
   9516 static void
   9517 zone_sign(dns_zone_t *zone) {
   9518 	dns_db_t *db = NULL;
   9519 	dns_dbnode_t *node = NULL;
   9520 	dns_dbversion_t *version = NULL;
   9521 	dns_diff_t _sig_diff;
   9522 	dns_diff_t post_diff;
   9523 	dns__zonediff_t zonediff;
   9524 	dns_fixedname_t fixed;
   9525 	dns_fixedname_t nextfixed;
   9526 	dns_kasp_t *kasp;
   9527 	dns_name_t *name, *nextname;
   9528 	dns_rdataset_t rdataset;
   9529 	dns_signing_t *signing, *nextsigning;
   9530 	dns_signinglist_t cleanup;
   9531 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   9532 	int32_t signatures;
   9533 	bool is_ksk, is_zsk;
   9534 	bool with_ksk, with_zsk;
   9535 	bool commit = false;
   9536 	bool is_bottom_of_zone;
   9537 	bool build_nsec = false;
   9538 	bool build_nsec3 = false;
   9539 	bool use_kasp = false;
   9540 	bool first;
   9541 	isc_result_t result;
   9542 	isc_stdtime_t now, inception, soaexpire, expire;
   9543 	unsigned int i, j;
   9544 	unsigned int nkeys = 0;
   9545 	uint32_t nodes;
   9546 
   9547 	ENTER;
   9548 
   9549 	dns_rdataset_init(&rdataset);
   9550 	name = dns_fixedname_initname(&fixed);
   9551 	nextname = dns_fixedname_initname(&nextfixed);
   9552 	dns_diff_init(zone->mctx, &_sig_diff);
   9553 	dns_diff_init(zone->mctx, &post_diff);
   9554 	zonediff_init(&zonediff, &_sig_diff);
   9555 	ISC_LIST_INIT(cleanup);
   9556 
   9557 	/*
   9558 	 * Updates are disabled.  Pause for 1 minute.
   9559 	 */
   9560 	if (zone->update_disabled) {
   9561 		result = ISC_R_FAILURE;
   9562 		goto done;
   9563 	}
   9564 
   9565 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   9566 	if (zone->db != NULL) {
   9567 		dns_db_attach(zone->db, &db);
   9568 	}
   9569 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   9570 	if (db == NULL) {
   9571 		result = ISC_R_FAILURE;
   9572 		goto done;
   9573 	}
   9574 
   9575 	result = dns_db_newversion(db, &version);
   9576 	if (result != ISC_R_SUCCESS) {
   9577 		dnssec_log(zone, ISC_LOG_ERROR,
   9578 			   "zone_sign:dns_db_newversion -> %s",
   9579 			   isc_result_totext(result));
   9580 		goto done;
   9581 	}
   9582 
   9583 	now = isc_stdtime_now();
   9584 
   9585 	result = dns_zone_findkeys(zone, db, version, now, zone->mctx,
   9586 				   DNS_MAXZONEKEYS, zone_keys, &nkeys);
   9587 	if (result != ISC_R_SUCCESS) {
   9588 		dnssec_log(zone, ISC_LOG_ERROR,
   9589 			   "zone_sign:dns_zone_findkeys -> %s",
   9590 			   isc_result_totext(result));
   9591 		goto done;
   9592 	}
   9593 
   9594 	kasp = zone->kasp;
   9595 
   9596 	calculate_rrsig_validity(zone, now, &inception, &soaexpire, NULL,
   9597 				 &expire);
   9598 
   9599 	/*
   9600 	 * We keep pulling nodes off each iterator in turn until
   9601 	 * we have no more nodes to pull off or we reach the limits
   9602 	 * for this quantum.
   9603 	 */
   9604 	nodes = zone->nodes;
   9605 	signatures = zone->signatures;
   9606 	signing = ISC_LIST_HEAD(zone->signing);
   9607 	first = true;
   9608 
   9609 	if (kasp != NULL) {
   9610 		use_kasp = true;
   9611 	}
   9612 	dnssec_log(zone, ISC_LOG_DEBUG(3), "zone_sign:use kasp -> %s",
   9613 		   use_kasp ? "yes" : "no");
   9614 
   9615 	/* Determine which type of chain to build */
   9616 	CHECK(dns_private_chains(db, version, zone->privatetype, &build_nsec,
   9617 				 &build_nsec3));
   9618 	if (!build_nsec && !build_nsec3) {
   9619 		if (use_kasp) {
   9620 			build_nsec3 = dns_kasp_nsec3(kasp);
   9621 			if (!dns_zone_check_dnskey_nsec3(
   9622 				    zone, db, version, NULL,
   9623 				    (dst_key_t **)&zone_keys, nkeys))
   9624 			{
   9625 				dnssec_log(zone, ISC_LOG_INFO,
   9626 					   "wait building NSEC3 chain until "
   9627 					   "NSEC only DNSKEYs are removed");
   9628 				build_nsec3 = false;
   9629 			}
   9630 			build_nsec = !build_nsec3;
   9631 		} else {
   9632 			/* If neither chain is found, default to NSEC */
   9633 			build_nsec = true;
   9634 		}
   9635 	}
   9636 
   9637 	while (signing != NULL && nodes-- > 0 && signatures > 0) {
   9638 		bool has_alg = false;
   9639 
   9640 		dns_dbiterator_pause(signing->dbiterator);
   9641 		nextsigning = ISC_LIST_NEXT(signing, link);
   9642 
   9643 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   9644 		if (signing->done || signing->db != zone->db) {
   9645 			/*
   9646 			 * The zone has been reloaded.	We will have to
   9647 			 * created new signings as part of the reload
   9648 			 * process so we can destroy this one.
   9649 			 */
   9650 			ISC_LIST_UNLINK(zone->signing, signing, link);
   9651 			ISC_LIST_APPEND(cleanup, signing, link);
   9652 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   9653 			goto next_signing;
   9654 		}
   9655 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   9656 
   9657 		if (signing->db != db) {
   9658 			goto next_signing;
   9659 		}
   9660 
   9661 		is_bottom_of_zone = false;
   9662 
   9663 		if (first && signing->deleteit) {
   9664 			/*
   9665 			 * Remove the key we are deleting from consideration.
   9666 			 */
   9667 			for (i = 0, j = 0; i < nkeys; i++) {
   9668 				/*
   9669 				 * Find the key we want to remove.
   9670 				 */
   9671 				if (ALG(zone_keys[i]) == signing->algorithm &&
   9672 				    dst_key_id(zone_keys[i]) == signing->keyid)
   9673 				{
   9674 					dst_key_free(&zone_keys[i]);
   9675 					continue;
   9676 				}
   9677 				zone_keys[j] = zone_keys[i];
   9678 				j++;
   9679 			}
   9680 			for (i = j; i < nkeys; i++) {
   9681 				zone_keys[i] = NULL;
   9682 			}
   9683 			nkeys = j;
   9684 		}
   9685 
   9686 		dns_dbiterator_current(signing->dbiterator, &node, name);
   9687 
   9688 		if (signing->deleteit) {
   9689 			dns_dbiterator_pause(signing->dbiterator);
   9690 			CHECK(del_sig(db, version, name, node, nkeys,
   9691 				      signing->algorithm, signing->keyid,
   9692 				      &has_alg, zonediff.diff));
   9693 		}
   9694 
   9695 		/*
   9696 		 * On the first pass we need to check if the current node
   9697 		 * has not been obscured.
   9698 		 */
   9699 		if (first) {
   9700 			dns_fixedname_t ffound;
   9701 			dns_name_t *found;
   9702 			found = dns_fixedname_initname(&ffound);
   9703 			result = dns_db_find(
   9704 				db, name, version, dns_rdatatype_soa,
   9705 				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
   9706 			if ((result == DNS_R_DELEGATION ||
   9707 			     result == DNS_R_DNAME) &&
   9708 			    !dns_name_equal(name, found))
   9709 			{
   9710 				/*
   9711 				 * Remember the obscuring name so that
   9712 				 * we skip all obscured names.
   9713 				 */
   9714 				dns_name_copy(found, name);
   9715 				is_bottom_of_zone = true;
   9716 				goto next_node;
   9717 			}
   9718 		}
   9719 
   9720 		/*
   9721 		 * Process one node.
   9722 		 */
   9723 		with_ksk = false;
   9724 		with_zsk = false;
   9725 		dns_dbiterator_pause(signing->dbiterator);
   9726 
   9727 		CHECK(check_if_bottom_of_zone(db, node, version,
   9728 					      &is_bottom_of_zone));
   9729 
   9730 		for (i = 0; !has_alg && i < nkeys; i++) {
   9731 			bool both = false;
   9732 			/*
   9733 			 * Find the keys we want to sign with.
   9734 			 */
   9735 			if (!dst_key_isprivate(zone_keys[i])) {
   9736 				continue;
   9737 			}
   9738 			if (dst_key_inactive(zone_keys[i])) {
   9739 				continue;
   9740 			}
   9741 
   9742 			/*
   9743 			 * When adding look for the specific key.
   9744 			 */
   9745 			if (!signing->deleteit &&
   9746 			    (dst_key_alg(zone_keys[i]) != signing->algorithm ||
   9747 			     dst_key_id(zone_keys[i]) != signing->keyid))
   9748 			{
   9749 				continue;
   9750 			}
   9751 
   9752 			/*
   9753 			 * When deleting make sure we are properly signed
   9754 			 * with the algorithm that was being removed.
   9755 			 */
   9756 			if (signing->deleteit &&
   9757 			    ALG(zone_keys[i]) != signing->algorithm)
   9758 			{
   9759 				continue;
   9760 			}
   9761 
   9762 			/*
   9763 			 * We do KSK processing.
   9764 			 */
   9765 			if (use_kasp) {
   9766 				/*
   9767 				 * A dnssec-policy is found. Check what
   9768 				 * RRsets this key can sign.
   9769 				 */
   9770 				isc_result_t kresult;
   9771 				is_ksk = false;
   9772 				kresult = dst_key_getbool(
   9773 					zone_keys[i], DST_BOOL_KSK, &is_ksk);
   9774 				if (kresult != ISC_R_SUCCESS) {
   9775 					if (KSK(zone_keys[i])) {
   9776 						is_ksk = true;
   9777 					}
   9778 				}
   9779 
   9780 				is_zsk = false;
   9781 				kresult = dst_key_getbool(
   9782 					zone_keys[i], DST_BOOL_ZSK, &is_zsk);
   9783 				if (kresult != ISC_R_SUCCESS) {
   9784 					if (!KSK(zone_keys[i])) {
   9785 						is_zsk = true;
   9786 					}
   9787 				}
   9788 				both = true;
   9789 			} else {
   9790 				is_ksk = KSK(zone_keys[i]);
   9791 				is_zsk = !is_ksk;
   9792 
   9793 				/*
   9794 				 * Don't consider inactive keys, however the key
   9795 				 * may be temporary offline, so do consider KSKs
   9796 				 * which private key files are unavailable.
   9797 				 */
   9798 				both = dst_key_have_ksk_and_zsk(
   9799 					zone_keys, nkeys, i, false, is_ksk,
   9800 					is_zsk, NULL, NULL);
   9801 				if (both || REVOKE(zone_keys[i])) {
   9802 					is_ksk = KSK(zone_keys[i]);
   9803 					is_zsk = !KSK(zone_keys[i]);
   9804 				} else {
   9805 					is_ksk = false;
   9806 					is_zsk = false;
   9807 				}
   9808 			}
   9809 
   9810 			/*
   9811 			 * If deleting signatures, we need to ensure that
   9812 			 * the RRset is still signed at least once by a
   9813 			 * KSK and a ZSK.
   9814 			 */
   9815 			if (signing->deleteit && is_zsk && with_zsk) {
   9816 				continue;
   9817 			}
   9818 
   9819 			if (signing->deleteit && is_ksk && with_ksk) {
   9820 				continue;
   9821 			}
   9822 
   9823 			CHECK(sign_a_node(
   9824 				db, zone, name, node, version, build_nsec3,
   9825 				build_nsec, zone_keys[i], now, inception,
   9826 				expire, zone_nsecttl(zone), both, is_ksk,
   9827 				is_zsk, signing->fullsign, is_bottom_of_zone,
   9828 				zonediff.diff, &signatures, zone->mctx));
   9829 			/*
   9830 			 * If we are adding we are done.  Look for other keys
   9831 			 * of the same algorithm if deleting.
   9832 			 */
   9833 			if (!signing->deleteit) {
   9834 				break;
   9835 			}
   9836 			if (is_zsk) {
   9837 				with_zsk = true;
   9838 			}
   9839 			if (is_ksk) {
   9840 				with_ksk = true;
   9841 			}
   9842 		}
   9843 
   9844 		/*
   9845 		 * Go onto next node.
   9846 		 */
   9847 	next_node:
   9848 		first = false;
   9849 		dns_db_detachnode(db, &node);
   9850 		do {
   9851 			result = dns_dbiterator_next(signing->dbiterator);
   9852 			if (result == ISC_R_NOMORE) {
   9853 				ISC_LIST_UNLINK(zone->signing, signing, link);
   9854 				ISC_LIST_APPEND(cleanup, signing, link);
   9855 				dns_dbiterator_pause(signing->dbiterator);
   9856 				if (nkeys != 0 && build_nsec) {
   9857 					/*
   9858 					 * We have finished regenerating the
   9859 					 * zone with a zone signing key.
   9860 					 * The NSEC chain is now complete and
   9861 					 * there is a full set of signatures
   9862 					 * for the zone.  We can now clear the
   9863 					 * OPT bit from the NSEC record.
   9864 					 */
   9865 					result = updatesecure(
   9866 						db, version, &zone->origin,
   9867 						zone_nsecttl(zone), false,
   9868 						&post_diff);
   9869 					if (result != ISC_R_SUCCESS) {
   9870 						dnssec_log(zone, ISC_LOG_ERROR,
   9871 							   "updatesecure -> %s",
   9872 							   isc_result_totext(
   9873 								   result));
   9874 						goto done;
   9875 					}
   9876 				}
   9877 				result = updatesignwithkey(
   9878 					zone, signing, version, build_nsec3,
   9879 					zone_nsecttl(zone), &post_diff);
   9880 				if (result != ISC_R_SUCCESS) {
   9881 					dnssec_log(zone, ISC_LOG_ERROR,
   9882 						   "updatesignwithkey -> %s",
   9883 						   isc_result_totext(result));
   9884 					goto done;
   9885 				}
   9886 				build_nsec = false;
   9887 				goto next_signing;
   9888 			} else if (result != ISC_R_SUCCESS) {
   9889 				dnssec_log(zone, ISC_LOG_ERROR,
   9890 					   "zone_sign:"
   9891 					   "dns_dbiterator_next -> %s",
   9892 					   isc_result_totext(result));
   9893 				goto done;
   9894 			} else if (is_bottom_of_zone) {
   9895 				dns_dbiterator_current(signing->dbiterator,
   9896 						       &node, nextname);
   9897 				dns_db_detachnode(db, &node);
   9898 				if (!dns_name_issubdomain(nextname, name)) {
   9899 					break;
   9900 				}
   9901 			} else {
   9902 				break;
   9903 			}
   9904 		} while (1);
   9905 		continue;
   9906 
   9907 	next_signing:
   9908 		dns_dbiterator_pause(signing->dbiterator);
   9909 		signing = nextsigning;
   9910 		first = true;
   9911 	}
   9912 
   9913 	if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
   9914 		result = dns__zone_updatesigs(&post_diff, db, version,
   9915 					      zone_keys, nkeys, zone, inception,
   9916 					      expire, 0, now, &zonediff);
   9917 		if (result != ISC_R_SUCCESS) {
   9918 			dnssec_log(zone, ISC_LOG_ERROR,
   9919 				   "zone_sign:dns__zone_updatesigs -> %s",
   9920 				   isc_result_totext(result));
   9921 			goto done;
   9922 		}
   9923 	}
   9924 
   9925 	/*
   9926 	 * Have we changed anything?
   9927 	 */
   9928 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
   9929 		if (zonediff.offline) {
   9930 			commit = true;
   9931 		}
   9932 		result = ISC_R_SUCCESS;
   9933 		goto pauseall;
   9934 	}
   9935 
   9936 	commit = true;
   9937 
   9938 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
   9939 			  &zonediff, zone_keys, nkeys, now, false);
   9940 	if (result != ISC_R_SUCCESS) {
   9941 		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
   9942 			   isc_result_totext(result));
   9943 		goto done;
   9944 	}
   9945 
   9946 	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
   9947 				   zone->updatemethod);
   9948 	if (result != ISC_R_SUCCESS) {
   9949 		dnssec_log(zone, ISC_LOG_ERROR,
   9950 			   "zone_sign:update_soa_serial -> %s",
   9951 			   isc_result_totext(result));
   9952 		goto done;
   9953 	}
   9954 
   9955 	/*
   9956 	 * Generate maximum life time signatures so that the above loop
   9957 	 * termination is sensible.
   9958 	 */
   9959 	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
   9960 			  zonediff.diff, zone_keys, nkeys, zone->mctx, now,
   9961 			  inception, soaexpire);
   9962 	if (result != ISC_R_SUCCESS) {
   9963 		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
   9964 			   isc_result_totext(result));
   9965 		goto done;
   9966 	}
   9967 
   9968 	/*
   9969 	 * Write changes to journal file.
   9970 	 */
   9971 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
   9972 
   9973 pauseall:
   9974 	/*
   9975 	 * Pause all iterators so that dns_db_closeversion() can succeed.
   9976 	 */
   9977 	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
   9978 	     signing = ISC_LIST_NEXT(signing, link))
   9979 	{
   9980 		dns_dbiterator_pause(signing->dbiterator);
   9981 	}
   9982 
   9983 	for (signing = ISC_LIST_HEAD(cleanup); signing != NULL;
   9984 	     signing = ISC_LIST_NEXT(signing, link))
   9985 	{
   9986 		dns_dbiterator_pause(signing->dbiterator);
   9987 	}
   9988 
   9989 	/*
   9990 	 * Everything has succeeded. Commit the changes.
   9991 	 */
   9992 	dns_db_closeversion(db, &version, commit);
   9993 
   9994 	/*
   9995 	 * Everything succeeded so we can clean these up now.
   9996 	 */
   9997 	signing = ISC_LIST_HEAD(cleanup);
   9998 	while (signing != NULL) {
   9999 		ISC_LIST_UNLINK(cleanup, signing, link);
   10000 		dns_db_detach(&signing->db);
   10001 		dns_dbiterator_destroy(&signing->dbiterator);
   10002 		isc_mem_put(zone->mctx, signing, sizeof *signing);
   10003 		signing = ISC_LIST_HEAD(cleanup);
   10004 	}
   10005 
   10006 	LOCK_ZONE(zone);
   10007 	set_resigntime(zone);
   10008 	if (commit) {
   10009 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   10010 		zone_needdump(zone, DNS_DUMP_DELAY);
   10011 	}
   10012 	UNLOCK_ZONE(zone);
   10013 
   10014 cleanup:
   10015 	if (result != ISC_R_SUCCESS) {
   10016 		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
   10017 			   isc_result_totext(result));
   10018 	}
   10019 
   10020 done:
   10021 	/*
   10022 	 * Pause all dbiterators.
   10023 	 */
   10024 	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
   10025 	     signing = ISC_LIST_NEXT(signing, link))
   10026 	{
   10027 		dns_dbiterator_pause(signing->dbiterator);
   10028 	}
   10029 
   10030 	/*
   10031 	 * Rollback the cleanup list.
   10032 	 */
   10033 	signing = ISC_LIST_HEAD(cleanup);
   10034 	while (signing != NULL) {
   10035 		ISC_LIST_UNLINK(cleanup, signing, link);
   10036 		ISC_LIST_PREPEND(zone->signing, signing, link);
   10037 		dns_dbiterator_first(signing->dbiterator);
   10038 		dns_dbiterator_pause(signing->dbiterator);
   10039 		signing = ISC_LIST_HEAD(cleanup);
   10040 	}
   10041 
   10042 	dns_diff_clear(&_sig_diff);
   10043 	dns_diff_clear(&post_diff);
   10044 
   10045 	for (i = 0; i < nkeys; i++) {
   10046 		dst_key_free(&zone_keys[i]);
   10047 	}
   10048 
   10049 	if (node != NULL) {
   10050 		dns_db_detachnode(db, &node);
   10051 	}
   10052 
   10053 	if (version != NULL) {
   10054 		dns_db_closeversion(db, &version, false);
   10055 		dns_db_detach(&db);
   10056 	} else if (db != NULL) {
   10057 		dns_db_detach(&db);
   10058 	}
   10059 
   10060 	LOCK_ZONE(zone);
   10061 	if (ISC_LIST_HEAD(zone->signing) != NULL) {
   10062 		isc_interval_t interval;
   10063 		if (zone->update_disabled || result != ISC_R_SUCCESS) {
   10064 			isc_interval_set(&interval, 60, 0); /* 1 minute */
   10065 		} else {
   10066 			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
   10067 		}
   10068 		isc_time_nowplusinterval(&zone->signingtime, &interval);
   10069 	} else {
   10070 		isc_time_settoepoch(&zone->signingtime);
   10071 	}
   10072 	UNLOCK_ZONE(zone);
   10073 
   10074 	INSIST(version == NULL);
   10075 }
   10076 
   10077 static isc_result_t
   10078 normalize_key(dns_rdata_t *rr, dns_rdata_t *target, unsigned char *data,
   10079 	      int size) {
   10080 	dns_rdata_dnskey_t dnskey;
   10081 	dns_rdata_keydata_t keydata;
   10082 	isc_buffer_t buf;
   10083 	isc_result_t result;
   10084 
   10085 	dns_rdata_reset(target);
   10086 	isc_buffer_init(&buf, data, size);
   10087 
   10088 	switch (rr->type) {
   10089 	case dns_rdatatype_dnskey:
   10090 		result = dns_rdata_tostruct(rr, &dnskey, NULL);
   10091 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10092 		dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
   10093 		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
   10094 				     &dnskey, &buf);
   10095 		break;
   10096 	case dns_rdatatype_keydata:
   10097 		result = dns_rdata_tostruct(rr, &keydata, NULL);
   10098 		if (result == ISC_R_UNEXPECTEDEND) {
   10099 			return result;
   10100 		}
   10101 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10102 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
   10103 		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
   10104 				     &dnskey, &buf);
   10105 		break;
   10106 	default:
   10107 		UNREACHABLE();
   10108 	}
   10109 	return ISC_R_SUCCESS;
   10110 }
   10111 
   10112 /*
   10113  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
   10114  * a KEYDATA rdataset from the key zone.
   10115  *
   10116  * 'rr' contains either a DNSKEY record, or a KEYDATA record
   10117  *
   10118  * After normalizing keys to the same format (DNSKEY, with revoke bit
   10119  * cleared), return true if a key that matches 'rr' is found in
   10120  * 'rdset', or false if not.
   10121  */
   10122 
   10123 static bool
   10124 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
   10125 	unsigned char data1[4096], data2[4096];
   10126 	dns_rdata_t rdata, rdata1, rdata2;
   10127 	isc_result_t result;
   10128 
   10129 	dns_rdata_init(&rdata);
   10130 	dns_rdata_init(&rdata1);
   10131 	dns_rdata_init(&rdata2);
   10132 
   10133 	result = normalize_key(rr, &rdata1, data1, sizeof(data1));
   10134 	if (result != ISC_R_SUCCESS) {
   10135 		return false;
   10136 	}
   10137 
   10138 	for (result = dns_rdataset_first(rdset); result == ISC_R_SUCCESS;
   10139 	     result = dns_rdataset_next(rdset))
   10140 	{
   10141 		dns_rdata_reset(&rdata);
   10142 		dns_rdataset_current(rdset, &rdata);
   10143 		result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
   10144 		if (result != ISC_R_SUCCESS) {
   10145 			continue;
   10146 		}
   10147 		if (dns_rdata_compare(&rdata1, &rdata2) == 0) {
   10148 			return true;
   10149 		}
   10150 	}
   10151 
   10152 	return false;
   10153 }
   10154 
   10155 /*
   10156  * Calculate the refresh interval for a keydata zone, per
   10157  * RFC5011: MAX(1 hr,
   10158  *		MIN(15 days,
   10159  *		    1/2 * OrigTTL,
   10160  *		    1/2 * RRSigExpirationInterval))
   10161  * or for retries: MAX(1 hr,
   10162  *		       MIN(1 day,
   10163  *			   1/10 * OrigTTL,
   10164  *			   1/10 * RRSigExpirationInterval))
   10165  */
   10166 static isc_stdtime_t
   10167 refresh_time(dns_keyfetch_t *kfetch, bool retry) {
   10168 	isc_result_t result;
   10169 	uint32_t t;
   10170 	dns_rdataset_t *rdset;
   10171 	dns_rdata_t sigrr = DNS_RDATA_INIT;
   10172 	dns_rdata_sig_t sig;
   10173 	isc_stdtime_t now = isc_stdtime_now();
   10174 
   10175 	if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
   10176 		rdset = &kfetch->dnskeysigset;
   10177 	} else {
   10178 		return now + dns_zone_mkey_hour;
   10179 	}
   10180 
   10181 	result = dns_rdataset_first(rdset);
   10182 	if (result != ISC_R_SUCCESS) {
   10183 		return now + dns_zone_mkey_hour;
   10184 	}
   10185 
   10186 	dns_rdataset_current(rdset, &sigrr);
   10187 	result = dns_rdata_tostruct(&sigrr, &sig, NULL);
   10188 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10189 
   10190 	if (!retry) {
   10191 		t = sig.originalttl / 2;
   10192 
   10193 		if (isc_serial_gt(sig.timeexpire, now)) {
   10194 			uint32_t exp = (sig.timeexpire - now) / 2;
   10195 			if (t > exp) {
   10196 				t = exp;
   10197 			}
   10198 		}
   10199 
   10200 		if (t > (15 * dns_zone_mkey_day)) {
   10201 			t = (15 * dns_zone_mkey_day);
   10202 		}
   10203 
   10204 		if (t < dns_zone_mkey_hour) {
   10205 			t = dns_zone_mkey_hour;
   10206 		}
   10207 	} else {
   10208 		t = sig.originalttl / 10;
   10209 
   10210 		if (isc_serial_gt(sig.timeexpire, now)) {
   10211 			uint32_t exp = (sig.timeexpire - now) / 10;
   10212 			if (t > exp) {
   10213 				t = exp;
   10214 			}
   10215 		}
   10216 
   10217 		if (t > dns_zone_mkey_day) {
   10218 			t = dns_zone_mkey_day;
   10219 		}
   10220 
   10221 		if (t < dns_zone_mkey_hour) {
   10222 			t = dns_zone_mkey_hour;
   10223 		}
   10224 	}
   10225 
   10226 	return now + t;
   10227 }
   10228 
   10229 /*
   10230  * This routine is called when no changes are needed in a KEYDATA
   10231  * record except to simply update the refresh timer.  Caller should
   10232  * hold zone lock.
   10233  */
   10234 static isc_result_t
   10235 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) {
   10236 	isc_result_t result;
   10237 	isc_buffer_t keyb;
   10238 	unsigned char key_buf[4096];
   10239 	dns_rdata_t rdata = DNS_RDATA_INIT;
   10240 	dns_rdata_keydata_t keydata;
   10241 	dns_name_t *name;
   10242 	dns_zone_t *zone = kfetch->zone;
   10243 	isc_stdtime_t now = isc_stdtime_now();
   10244 
   10245 	name = dns_fixedname_name(&kfetch->name);
   10246 
   10247 	for (result = dns_rdataset_first(&kfetch->keydataset);
   10248 	     result == ISC_R_SUCCESS;
   10249 	     result = dns_rdataset_next(&kfetch->keydataset))
   10250 	{
   10251 		dns_rdata_reset(&rdata);
   10252 		dns_rdataset_current(&kfetch->keydataset, &rdata);
   10253 
   10254 		/* Delete old version */
   10255 		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL, name,
   10256 				    0, &rdata));
   10257 
   10258 		/* Update refresh timer */
   10259 		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
   10260 		if (result == ISC_R_UNEXPECTEDEND) {
   10261 			continue;
   10262 		}
   10263 		CHECK(result);
   10264 
   10265 		keydata.refresh = refresh_time(kfetch, true);
   10266 		set_refreshkeytimer(zone, &keydata, now, false);
   10267 
   10268 		dns_rdata_reset(&rdata);
   10269 		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   10270 		CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass,
   10271 					   dns_rdatatype_keydata, &keydata,
   10272 					   &keyb));
   10273 
   10274 		/* Insert updated version */
   10275 		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD, name,
   10276 				    0, &rdata));
   10277 	}
   10278 	result = ISC_R_SUCCESS;
   10279 cleanup:
   10280 	return result;
   10281 }
   10282 
   10283 /*
   10284  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
   10285  */
   10286 static bool
   10287 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
   10288 	isc_result_t result;
   10289 	dns_name_t *keyname;
   10290 	isc_mem_t *mctx;
   10291 	dns_rdata_t sigrr = DNS_RDATA_INIT;
   10292 	dns_rdata_t rr = DNS_RDATA_INIT;
   10293 	dns_rdata_rrsig_t sig;
   10294 	dns_rdata_dnskey_t dnskey;
   10295 	dst_key_t *dstkey = NULL;
   10296 	unsigned char key_buf[4096];
   10297 	isc_buffer_t keyb;
   10298 	bool answer = false;
   10299 
   10300 	REQUIRE(kfetch != NULL && keydata != NULL);
   10301 	REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
   10302 
   10303 	keyname = dns_fixedname_name(&kfetch->name);
   10304 	mctx = kfetch->zone->view->mctx;
   10305 
   10306 	/* Generate a key from keydata */
   10307 	isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   10308 	dns_keydata_todnskey(keydata, &dnskey, NULL);
   10309 	dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
   10310 			     &dnskey, &keyb);
   10311 	result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
   10312 	if (result != ISC_R_SUCCESS) {
   10313 		return false;
   10314 	}
   10315 
   10316 	/* See if that key generated any of the signatures */
   10317 	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
   10318 	     result == ISC_R_SUCCESS;
   10319 	     result = dns_rdataset_next(&kfetch->dnskeysigset))
   10320 	{
   10321 		dns_fixedname_t fixed;
   10322 		dns_fixedname_init(&fixed);
   10323 
   10324 		dns_rdata_reset(&sigrr);
   10325 		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
   10326 		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
   10327 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10328 
   10329 		if (dst_key_alg(dstkey) == sig.algorithm &&
   10330 		    dst_key_rid(dstkey) == sig.keyid)
   10331 		{
   10332 			result = dns_dnssec_verify(
   10333 				keyname, &kfetch->dnskeyset, dstkey, false, 0,
   10334 				mctx, &sigrr, dns_fixedname_name(&fixed));
   10335 
   10336 			dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
   10337 				   "Confirm revoked DNSKEY is self-signed: %s",
   10338 				   isc_result_totext(result));
   10339 
   10340 			if (result == ISC_R_SUCCESS) {
   10341 				answer = true;
   10342 				break;
   10343 			}
   10344 		}
   10345 	}
   10346 
   10347 	dst_key_free(&dstkey);
   10348 	return answer;
   10349 }
   10350 
   10351 /*
   10352  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
   10353  * anchors are being managed; scan the keyset, and update the key zone and the
   10354  * local trust anchors according to RFC5011.
   10355  */
   10356 static void
   10357 keyfetch_done(void *arg) {
   10358 	dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
   10359 	isc_result_t result, eresult;
   10360 	dns_keyfetch_t *kfetch = NULL;
   10361 	dns_zone_t *zone = NULL;
   10362 	isc_mem_t *mctx = NULL;
   10363 	dns_keytable_t *secroots = NULL;
   10364 	dns_dbversion_t *ver = NULL;
   10365 	dns_diff_t diff;
   10366 	bool alldone = false;
   10367 	bool commit = false;
   10368 	dns_name_t *keyname = NULL;
   10369 	dns_rdata_t sigrr = DNS_RDATA_INIT;
   10370 	dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
   10371 	dns_rdata_t keydatarr = DNS_RDATA_INIT;
   10372 	dns_rdata_rrsig_t sig;
   10373 	dns_rdata_dnskey_t dnskey;
   10374 	dns_rdata_keydata_t keydata;
   10375 	bool initializing;
   10376 	char namebuf[DNS_NAME_FORMATSIZE];
   10377 	unsigned char key_buf[4096];
   10378 	isc_buffer_t keyb;
   10379 	dst_key_t *dstkey = NULL;
   10380 	isc_stdtime_t now;
   10381 	int pending = 0;
   10382 	bool secure = false, initial = false;
   10383 	bool free_needed;
   10384 	dns_keynode_t *keynode = NULL;
   10385 	dns_rdataset_t *dnskeys = NULL, *dnskeysigs = NULL;
   10386 	dns_rdataset_t *keydataset = NULL, dsset;
   10387 
   10388 	INSIST(resp != NULL);
   10389 
   10390 	kfetch = resp->arg;
   10391 
   10392 	INSIST(kfetch != NULL);
   10393 
   10394 	zone = kfetch->zone;
   10395 	mctx = kfetch->mctx;
   10396 	keyname = dns_fixedname_name(&kfetch->name);
   10397 	dnskeys = &kfetch->dnskeyset;
   10398 	dnskeysigs = &kfetch->dnskeysigset;
   10399 	keydataset = &kfetch->keydataset;
   10400 
   10401 	eresult = resp->result;
   10402 
   10403 	/* Free resources which are not of interest */
   10404 	if (resp->node != NULL) {
   10405 		dns_db_detachnode(resp->db, &resp->node);
   10406 	}
   10407 	if (resp->db != NULL) {
   10408 		dns_db_detach(&resp->db);
   10409 	}
   10410 
   10411 	dns_resolver_destroyfetch(&kfetch->fetch);
   10412 
   10413 	LOCK_ZONE(zone);
   10414 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
   10415 		goto out;
   10416 	}
   10417 
   10418 	now = isc_stdtime_now();
   10419 	dns_name_format(keyname, namebuf, sizeof(namebuf));
   10420 
   10421 	result = dns_view_getsecroots(zone->view, &secroots);
   10422 	INSIST(result == ISC_R_SUCCESS);
   10423 
   10424 	dns_diff_init(mctx, &diff);
   10425 
   10426 	CHECK(dns_db_newversion(kfetch->db, &ver));
   10427 
   10428 	zone->refreshkeycount--;
   10429 	alldone = (zone->refreshkeycount == 0);
   10430 
   10431 	if (alldone) {
   10432 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
   10433 	}
   10434 
   10435 	dnssec_log(zone, ISC_LOG_DEBUG(3),
   10436 		   "Returned from key fetch in keyfetch_done() for '%s': %s",
   10437 		   namebuf, isc_result_totext(eresult));
   10438 
   10439 	/* Fetch failed */
   10440 	if (eresult != ISC_R_SUCCESS || !dns_rdataset_isassociated(dnskeys)) {
   10441 		dnssec_log(zone, ISC_LOG_WARNING,
   10442 			   "Unable to fetch DNSKEY set '%s': %s", namebuf,
   10443 			   isc_result_totext(eresult));
   10444 		CHECK(minimal_update(kfetch, ver, &diff));
   10445 		goto done;
   10446 	}
   10447 
   10448 	/* No RRSIGs found */
   10449 	if (!dns_rdataset_isassociated(dnskeysigs)) {
   10450 		dnssec_log(zone, ISC_LOG_WARNING,
   10451 			   "No DNSKEY RRSIGs found for '%s': %s", namebuf,
   10452 			   isc_result_totext(eresult));
   10453 		CHECK(minimal_update(kfetch, ver, &diff));
   10454 		goto done;
   10455 	}
   10456 
   10457 	/*
   10458 	 * Clear any cached trust level, as we need to run validation
   10459 	 * over again; trusted keys might have changed.
   10460 	 */
   10461 	dnskeys->trust = dnskeysigs->trust = dns_trust_none;
   10462 
   10463 	/* Look up the trust anchor */
   10464 	result = dns_keytable_find(secroots, keyname, &keynode);
   10465 	if (result != ISC_R_SUCCESS) {
   10466 		goto anchors_done;
   10467 	}
   10468 
   10469 	/*
   10470 	 * If the keynode has a DS trust anchor, use it for verification.
   10471 	 */
   10472 	dns_rdataset_init(&dsset);
   10473 	if (dns_keynode_dsset(keynode, &dsset)) {
   10474 		for (result = dns_rdataset_first(dnskeysigs);
   10475 		     result == ISC_R_SUCCESS;
   10476 		     result = dns_rdataset_next(dnskeysigs))
   10477 		{
   10478 			isc_result_t tresult;
   10479 			dns_rdata_t keyrdata = DNS_RDATA_INIT;
   10480 
   10481 			dns_rdata_reset(&sigrr);
   10482 			dns_rdataset_current(dnskeysigs, &sigrr);
   10483 			result = dns_rdata_tostruct(&sigrr, &sig, NULL);
   10484 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10485 
   10486 			for (tresult = dns_rdataset_first(&dsset);
   10487 			     tresult == ISC_R_SUCCESS;
   10488 			     tresult = dns_rdataset_next(&dsset))
   10489 			{
   10490 				dns_rdata_t dsrdata = DNS_RDATA_INIT;
   10491 				dns_rdata_ds_t ds;
   10492 
   10493 				dns_rdata_reset(&dsrdata);
   10494 				dns_rdataset_current(&dsset, &dsrdata);
   10495 				tresult = dns_rdata_tostruct(&dsrdata, &ds,
   10496 							     NULL);
   10497 				RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
   10498 
   10499 				if (ds.key_tag != sig.keyid ||
   10500 				    ds.algorithm != sig.algorithm)
   10501 				{
   10502 					continue;
   10503 				}
   10504 
   10505 				result = dns_dnssec_matchdskey(
   10506 					keyname, &dsrdata, dnskeys, &keyrdata);
   10507 				if (result == ISC_R_SUCCESS) {
   10508 					break;
   10509 				}
   10510 			}
   10511 
   10512 			if (tresult == ISC_R_NOMORE) {
   10513 				continue;
   10514 			}
   10515 
   10516 			result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
   10517 							 mctx, &dstkey);
   10518 			if (result != ISC_R_SUCCESS) {
   10519 				continue;
   10520 			}
   10521 
   10522 			result = dns_dnssec_verify(keyname, dnskeys, dstkey,
   10523 						   false, 0, mctx, &sigrr,
   10524 						   NULL);
   10525 			dst_key_free(&dstkey);
   10526 
   10527 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   10528 				   "Verifying DNSKEY set for zone "
   10529 				   "'%s' using DS %d/%d: %s",
   10530 				   namebuf, sig.keyid, sig.algorithm,
   10531 				   isc_result_totext(result));
   10532 
   10533 			if (result == ISC_R_SUCCESS) {
   10534 				dnskeys->trust = dns_trust_secure;
   10535 				dnskeysigs->trust = dns_trust_secure;
   10536 				initial = dns_keynode_initial(keynode);
   10537 				dns_keynode_trust(keynode);
   10538 				secure = true;
   10539 				break;
   10540 			}
   10541 		}
   10542 		dns_rdataset_disassociate(&dsset);
   10543 	}
   10544 
   10545 anchors_done:
   10546 	if (keynode != NULL) {
   10547 		dns_keynode_detach(&keynode);
   10548 	}
   10549 
   10550 	/*
   10551 	 * If we were not able to verify the answer using the current
   10552 	 * trusted keys then all we can do is look at any revoked keys.
   10553 	 */
   10554 	if (!secure) {
   10555 		dnssec_log(zone, ISC_LOG_INFO,
   10556 			   "DNSKEY set for zone '%s' could not be verified "
   10557 			   "with current keys",
   10558 			   namebuf);
   10559 	}
   10560 
   10561 	/*
   10562 	 * First scan keydataset to find keys that are not in dnskeyset
   10563 	 *   - Missing keys which are not scheduled for removal,
   10564 	 *     log a warning
   10565 	 *   - Missing keys which are scheduled for removal and
   10566 	 *     the remove hold-down timer has completed should
   10567 	 *     be removed from the key zone
   10568 	 *   - Missing keys whose acceptance timers have not yet
   10569 	 *     completed, log a warning and reset the acceptance
   10570 	 *     timer to 30 days in the future
   10571 	 *   - All keys not being removed have their refresh timers
   10572 	 *     updated
   10573 	 */
   10574 	initializing = true;
   10575 	for (result = dns_rdataset_first(keydataset); result == ISC_R_SUCCESS;
   10576 	     result = dns_rdataset_next(keydataset))
   10577 	{
   10578 		dns_keytag_t keytag;
   10579 
   10580 		dns_rdata_reset(&keydatarr);
   10581 		dns_rdataset_current(keydataset, &keydatarr);
   10582 		result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
   10583 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10584 
   10585 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
   10586 		result = compute_tag(keyname, &dnskey, mctx, &keytag);
   10587 		if (result != ISC_R_SUCCESS) {
   10588 			/*
   10589 			 * Skip if we cannot compute the key tag.
   10590 			 * This may happen if the algorithm is unsupported
   10591 			 */
   10592 			dns_zone_log(zone, ISC_LOG_ERROR,
   10593 				     "Cannot compute tag for key in zone %s: "
   10594 				     "%s "
   10595 				     "(skipping)",
   10596 				     namebuf, isc_result_totext(result));
   10597 			continue;
   10598 		}
   10599 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10600 
   10601 		/*
   10602 		 * If any keydata record has a nonzero add holddown, then
   10603 		 * there was a pre-existing trust anchor for this domain;
   10604 		 * that means we are *not* initializing it and shouldn't
   10605 		 * automatically trust all the keys we find at the zone apex.
   10606 		 */
   10607 		initializing = initializing && (keydata.addhd == 0);
   10608 
   10609 		if (!matchkey(dnskeys, &keydatarr)) {
   10610 			bool deletekey = false;
   10611 
   10612 			if (!secure) {
   10613 				if (keydata.removehd != 0 &&
   10614 				    keydata.removehd <= now)
   10615 				{
   10616 					deletekey = true;
   10617 				}
   10618 			} else if (keydata.addhd == 0) {
   10619 				deletekey = true;
   10620 			} else if (keydata.addhd > now) {
   10621 				dnssec_log(zone, ISC_LOG_INFO,
   10622 					   "Pending key %d for zone %s "
   10623 					   "unexpectedly missing from DNSKEY "
   10624 					   "RRset: restarting 30-day "
   10625 					   "acceptance timer",
   10626 					   keytag, namebuf);
   10627 				if (keydata.addhd < now + dns_zone_mkey_month) {
   10628 					keydata.addhd = now +
   10629 							dns_zone_mkey_month;
   10630 				}
   10631 				keydata.refresh = refresh_time(kfetch, false);
   10632 			} else if (keydata.removehd == 0) {
   10633 				dnssec_log(zone, ISC_LOG_INFO,
   10634 					   "Active key %d for zone %s "
   10635 					   "unexpectedly missing from DNSKEY "
   10636 					   "RRset",
   10637 					   keytag, namebuf);
   10638 				keydata.refresh = now + dns_zone_mkey_hour;
   10639 			} else if (keydata.removehd <= now) {
   10640 				deletekey = true;
   10641 				dnssec_log(
   10642 					zone, ISC_LOG_INFO,
   10643 					"Revoked key %d for zone %s no longer "
   10644 					"present in DNSKEY RRset: deleting "
   10645 					"from managed keys database",
   10646 					keytag, namebuf);
   10647 			} else {
   10648 				keydata.refresh = refresh_time(kfetch, false);
   10649 			}
   10650 
   10651 			if (secure || deletekey) {
   10652 				/* Delete old version */
   10653 				CHECK(update_one_rr(kfetch->db, ver, &diff,
   10654 						    DNS_DIFFOP_DEL, keyname, 0,
   10655 						    &keydatarr));
   10656 			}
   10657 
   10658 			if (!secure || deletekey) {
   10659 				continue;
   10660 			}
   10661 
   10662 			dns_rdata_reset(&keydatarr);
   10663 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   10664 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
   10665 					     dns_rdatatype_keydata, &keydata,
   10666 					     &keyb);
   10667 
   10668 			/* Insert updated version */
   10669 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   10670 					    DNS_DIFFOP_ADD, keyname, 0,
   10671 					    &keydatarr));
   10672 
   10673 			set_refreshkeytimer(zone, &keydata, now, false);
   10674 		}
   10675 	}
   10676 
   10677 	/*
   10678 	 * Next scan dnskeyset:
   10679 	 *   - If new keys are found (i.e., lacking a match in keydataset)
   10680 	 *     add them to the key zone and set the acceptance timer
   10681 	 *     to 30 days in the future (or to immediately if we've
   10682 	 *     determined that we're initializing the zone for the
   10683 	 *     first time)
   10684 	 *   - Previously-known keys that have been revoked
   10685 	 *     must be scheduled for removal from the key zone (or,
   10686 	 *     if they hadn't been accepted as trust anchors yet
   10687 	 *     anyway, removed at once)
   10688 	 *   - Previously-known unrevoked keys whose acceptance timers
   10689 	 *     have completed are promoted to trust anchors
   10690 	 *   - All keys not being removed have their refresh
   10691 	 *     timers updated
   10692 	 */
   10693 	for (result = dns_rdataset_first(dnskeys); result == ISC_R_SUCCESS;
   10694 	     result = dns_rdataset_next(dnskeys))
   10695 	{
   10696 		bool revoked = false;
   10697 		bool newkey = false;
   10698 		bool updatekey = false;
   10699 		bool deletekey = false;
   10700 		bool trustkey = false;
   10701 		dns_keytag_t keytag;
   10702 
   10703 		dns_rdata_reset(&dnskeyrr);
   10704 		dns_rdataset_current(dnskeys, &dnskeyrr);
   10705 		result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
   10706 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10707 
   10708 		/* Skip ZSK's */
   10709 		if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
   10710 			continue;
   10711 		}
   10712 
   10713 		result = compute_tag(keyname, &dnskey, mctx, &keytag);
   10714 		if (result != ISC_R_SUCCESS) {
   10715 			/*
   10716 			 * Skip if we cannot compute the key tag.
   10717 			 * This may happen if the algorithm is unsupported
   10718 			 */
   10719 			dns_zone_log(zone, ISC_LOG_ERROR,
   10720 				     "Cannot compute tag for key in zone %s: "
   10721 				     "%s "
   10722 				     "(skipping)",
   10723 				     namebuf, isc_result_totext(result));
   10724 			continue;
   10725 		}
   10726 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10727 
   10728 		revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
   10729 
   10730 		if (matchkey(keydataset, &dnskeyrr)) {
   10731 			dns_rdata_reset(&keydatarr);
   10732 			dns_rdataset_current(keydataset, &keydatarr);
   10733 			result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
   10734 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10735 
   10736 			if (revoked && revocable(kfetch, &keydata)) {
   10737 				if (keydata.addhd > now) {
   10738 					/*
   10739 					 * Key wasn't trusted yet, and now
   10740 					 * it's been revoked?  Just remove it
   10741 					 */
   10742 					deletekey = true;
   10743 					dnssec_log(zone, ISC_LOG_INFO,
   10744 						   "Pending key %d for "
   10745 						   "zone %s is now revoked: "
   10746 						   "deleting from the "
   10747 						   "managed keys database",
   10748 						   keytag, namebuf);
   10749 				} else if (keydata.removehd == 0) {
   10750 					/*
   10751 					 * Remove key from secroots.
   10752 					 */
   10753 					dns_view_untrust(zone->view, keyname,
   10754 							 &dnskey);
   10755 
   10756 					/* If initializing, delete now */
   10757 					if (keydata.addhd == 0) {
   10758 						deletekey = true;
   10759 					} else {
   10760 						keydata.removehd =
   10761 							now +
   10762 							dns_zone_mkey_month;
   10763 						keydata.flags |=
   10764 							DNS_KEYFLAG_REVOKE;
   10765 					}
   10766 
   10767 					dnssec_log(zone, ISC_LOG_INFO,
   10768 						   "Trusted key %d for "
   10769 						   "zone %s is now revoked",
   10770 						   keytag, namebuf);
   10771 				} else if (keydata.removehd < now) {
   10772 					/* Scheduled for removal */
   10773 					deletekey = true;
   10774 
   10775 					dnssec_log(zone, ISC_LOG_INFO,
   10776 						   "Revoked key %d for "
   10777 						   "zone %s removal timer "
   10778 						   "complete: deleting from "
   10779 						   "the managed keys database",
   10780 						   keytag, namebuf);
   10781 				}
   10782 			} else if (revoked && keydata.removehd == 0) {
   10783 				dnssec_log(zone, ISC_LOG_WARNING,
   10784 					   "Active key %d for zone "
   10785 					   "%s is revoked but "
   10786 					   "did not self-sign; "
   10787 					   "ignoring",
   10788 					   keytag, namebuf);
   10789 				continue;
   10790 			} else if (secure) {
   10791 				if (keydata.removehd != 0) {
   10792 					/*
   10793 					 * Key isn't revoked--but it
   10794 					 * seems it used to be.
   10795 					 * Remove it now and add it
   10796 					 * back as if it were a fresh key,
   10797 					 * with a 30-day acceptance timer.
   10798 					 */
   10799 					deletekey = true;
   10800 					newkey = true;
   10801 					keydata.removehd = 0;
   10802 					keydata.addhd = now +
   10803 							dns_zone_mkey_month;
   10804 
   10805 					dnssec_log(zone, ISC_LOG_INFO,
   10806 						   "Revoked key %d for "
   10807 						   "zone %s has returned: "
   10808 						   "starting 30-day "
   10809 						   "acceptance timer",
   10810 						   keytag, namebuf);
   10811 				} else if (keydata.addhd > now) {
   10812 					pending++;
   10813 				} else if (keydata.addhd == 0) {
   10814 					keydata.addhd = now;
   10815 				}
   10816 
   10817 				if (keydata.addhd <= now) {
   10818 					trustkey = true;
   10819 					dnssec_log(zone, ISC_LOG_INFO,
   10820 						   "Key %d for zone %s "
   10821 						   "is now trusted (%s)",
   10822 						   keytag, namebuf,
   10823 						   initial ? "initializing key "
   10824 							     "verified"
   10825 							   : "acceptance timer "
   10826 							     "complete");
   10827 				}
   10828 			} else if (keydata.addhd > now) {
   10829 				/*
   10830 				 * Not secure, and key is pending:
   10831 				 * reset the acceptance timer
   10832 				 */
   10833 				pending++;
   10834 				keydata.addhd = now + dns_zone_mkey_month;
   10835 				dnssec_log(zone, ISC_LOG_INFO,
   10836 					   "Pending key %d "
   10837 					   "for zone %s was "
   10838 					   "not validated: restarting "
   10839 					   "30-day acceptance timer",
   10840 					   keytag, namebuf);
   10841 			}
   10842 
   10843 			if (!deletekey && !newkey) {
   10844 				updatekey = true;
   10845 			}
   10846 		} else if (secure) {
   10847 			/*
   10848 			 * Key wasn't in the key zone but it's
   10849 			 * revoked now anyway, so just skip it
   10850 			 */
   10851 			if (revoked) {
   10852 				continue;
   10853 			}
   10854 
   10855 			/* Key wasn't in the key zone: add it */
   10856 			newkey = true;
   10857 
   10858 			if (initializing) {
   10859 				dnssec_log(zone, ISC_LOG_WARNING,
   10860 					   "Initializing automatic trust "
   10861 					   "anchor management for zone '%s'; "
   10862 					   "DNSKEY ID %d is now trusted, "
   10863 					   "waiving the normal 30-day "
   10864 					   "waiting period.",
   10865 					   namebuf, keytag);
   10866 				trustkey = true;
   10867 			} else {
   10868 				dnssec_log(zone, ISC_LOG_INFO,
   10869 					   "New key %d observed "
   10870 					   "for zone '%s': "
   10871 					   "starting 30-day "
   10872 					   "acceptance timer",
   10873 					   keytag, namebuf);
   10874 			}
   10875 		} else {
   10876 			/*
   10877 			 * No previously known key, and the key is not
   10878 			 * secure, so skip it.
   10879 			 */
   10880 			continue;
   10881 		}
   10882 
   10883 		/* Delete old version */
   10884 		if (deletekey || !newkey) {
   10885 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   10886 					    DNS_DIFFOP_DEL, keyname, 0,
   10887 					    &keydatarr));
   10888 		}
   10889 
   10890 		if (updatekey) {
   10891 			/* Set refresh timer */
   10892 			keydata.refresh = refresh_time(kfetch, false);
   10893 			dns_rdata_reset(&keydatarr);
   10894 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   10895 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
   10896 					     dns_rdatatype_keydata, &keydata,
   10897 					     &keyb);
   10898 
   10899 			/* Insert updated version */
   10900 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   10901 					    DNS_DIFFOP_ADD, keyname, 0,
   10902 					    &keydatarr));
   10903 		} else if (newkey) {
   10904 			/* Convert DNSKEY to KEYDATA */
   10905 			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
   10906 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10907 			dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
   10908 					       NULL);
   10909 			keydata.addhd = initializing
   10910 						? now
   10911 						: now + dns_zone_mkey_month;
   10912 			keydata.refresh = refresh_time(kfetch, false);
   10913 			dns_rdata_reset(&keydatarr);
   10914 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   10915 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
   10916 					     dns_rdatatype_keydata, &keydata,
   10917 					     &keyb);
   10918 
   10919 			/* Insert into key zone */
   10920 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   10921 					    DNS_DIFFOP_ADD, keyname, 0,
   10922 					    &keydatarr));
   10923 		}
   10924 
   10925 		if (trustkey) {
   10926 			/* Trust this key. */
   10927 			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
   10928 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10929 			trust_key(zone, keyname, &dnskey, false);
   10930 		}
   10931 
   10932 		if (secure && !deletekey) {
   10933 			INSIST(newkey || updatekey);
   10934 			set_refreshkeytimer(zone, &keydata, now, false);
   10935 		}
   10936 	}
   10937 
   10938 	/*
   10939 	 * RFC5011 says, "A trust point that has all of its trust anchors
   10940 	 * revoked is considered deleted and is treated as if the trust
   10941 	 * point was never configured."  But if someone revoked their
   10942 	 * active key before the standby was trusted, that would mean the
   10943 	 * zone would suddenly be nonsecured.  We avoid this by checking to
   10944 	 * see if there's pending keydata.  If so, we put a null key in
   10945 	 * the security roots; then all queries to the zone will fail.
   10946 	 */
   10947 	if (pending != 0) {
   10948 		fail_secure(zone, keyname);
   10949 	}
   10950 
   10951 done:
   10952 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   10953 		/* Write changes to journal file. */
   10954 		CHECK(update_soa_serial(zone, kfetch->db, ver, &diff, mctx,
   10955 					zone->updatemethod));
   10956 		CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
   10957 		commit = true;
   10958 
   10959 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   10960 		zone_needdump(zone, 30);
   10961 	} else if (result == ISC_R_NOMORE) {
   10962 		/*
   10963 		 * If "updatekey" was true for all keys found in the DNSKEY
   10964 		 * response and the previous update of those keys happened
   10965 		 * during the same second (only possible if a key refresh was
   10966 		 * externally triggered), it may happen that all relevant
   10967 		 * update_one_rr() calls will return ISC_R_SUCCESS, but
   10968 		 * diff.tuples will remain empty.  Reset result to
   10969 		 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
   10970 		 */
   10971 		result = ISC_R_SUCCESS;
   10972 	}
   10973 
   10974 cleanup:
   10975 	if (result != ISC_R_SUCCESS) {
   10976 		dnssec_log(zone, ISC_LOG_ERROR,
   10977 			   "error during managed-keys processing (%s): "
   10978 			   "DNSSEC validation may be at risk",
   10979 			   isc_result_totext(result));
   10980 	}
   10981 	dns_diff_clear(&diff);
   10982 	if (ver != NULL) {
   10983 		dns_db_closeversion(kfetch->db, &ver, commit);
   10984 	}
   10985 
   10986 out:
   10987 	dns_db_detach(&kfetch->db);
   10988 
   10989 	isc_refcount_decrement(&zone->irefs);
   10990 
   10991 	if (dns_rdataset_isassociated(keydataset)) {
   10992 		dns_rdataset_disassociate(keydataset);
   10993 	}
   10994 	if (dns_rdataset_isassociated(dnskeys)) {
   10995 		dns_rdataset_disassociate(dnskeys);
   10996 	}
   10997 	if (dns_rdataset_isassociated(dnskeysigs)) {
   10998 		dns_rdataset_disassociate(dnskeysigs);
   10999 	}
   11000 
   11001 	dns_resolver_freefresp(&resp);
   11002 	dns_name_free(keyname, mctx);
   11003 	isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(dns_keyfetch_t));
   11004 
   11005 	if (secroots != NULL) {
   11006 		dns_keytable_detach(&secroots);
   11007 	}
   11008 
   11009 	free_needed = exit_check(zone);
   11010 	UNLOCK_ZONE(zone);
   11011 
   11012 	if (free_needed) {
   11013 		zone_free(zone);
   11014 	}
   11015 
   11016 	INSIST(ver == NULL);
   11017 }
   11018 
   11019 static void
   11020 retry_keyfetch(dns_keyfetch_t *kfetch, dns_name_t *kname) {
   11021 	isc_time_t timenow, timethen;
   11022 	dns_zone_t *zone = kfetch->zone;
   11023 	bool free_needed;
   11024 	char namebuf[DNS_NAME_FORMATSIZE];
   11025 
   11026 	dns_name_format(kname, namebuf, sizeof(namebuf));
   11027 	dnssec_log(zone, ISC_LOG_WARNING,
   11028 		   "Failed to create fetch for %s DNSKEY update", namebuf);
   11029 
   11030 	/*
   11031 	 * Error during a key fetch; cancel and retry in an hour.
   11032 	 */
   11033 	LOCK_ZONE(zone);
   11034 	zone->refreshkeycount--;
   11035 	isc_refcount_decrement(&zone->irefs);
   11036 	dns_db_detach(&kfetch->db);
   11037 	dns_rdataset_disassociate(&kfetch->keydataset);
   11038 	dns_name_free(kname, zone->mctx);
   11039 	isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(*kfetch));
   11040 
   11041 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   11042 		/* Don't really retry if we are exiting */
   11043 		char timebuf[80];
   11044 
   11045 		timenow = isc_time_now();
   11046 		DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
   11047 		zone->refreshkeytime = timethen;
   11048 		zone_settimer(zone, &timenow);
   11049 
   11050 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   11051 		dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
   11052 			   timebuf);
   11053 	}
   11054 
   11055 	free_needed = exit_check(zone);
   11056 	UNLOCK_ZONE(zone);
   11057 
   11058 	if (free_needed) {
   11059 		zone_free(zone);
   11060 	}
   11061 }
   11062 
   11063 static void
   11064 do_keyfetch(void *arg) {
   11065 	isc_result_t result;
   11066 	dns_keyfetch_t *kfetch = (dns_keyfetch_t *)arg;
   11067 	dns_name_t *kname = dns_fixedname_name(&kfetch->name);
   11068 	dns_resolver_t *resolver = NULL;
   11069 	dns_zone_t *zone = kfetch->zone;
   11070 	unsigned int options = DNS_FETCHOPT_NOVALIDATE | DNS_FETCHOPT_UNSHARED |
   11071 			       DNS_FETCHOPT_NOCACHED;
   11072 
   11073 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   11074 		goto retry;
   11075 	}
   11076 
   11077 	result = dns_view_getresolver(zone->view, &resolver);
   11078 	if (result != ISC_R_SUCCESS) {
   11079 		goto retry;
   11080 	}
   11081 
   11082 	/*
   11083 	 * Use of DNS_FETCHOPT_NOCACHED is essential here.  If it is not
   11084 	 * set and the cache still holds a non-expired, validated version
   11085 	 * of the RRset being queried for by the time the response is
   11086 	 * received, the cached RRset will be passed to keyfetch_done()
   11087 	 * instead of the one received in the response as the latter will
   11088 	 * have a lower trust level due to not being validated until
   11089 	 * keyfetch_done() is called.
   11090 	 */
   11091 	result = dns_resolver_createfetch(
   11092 		resolver, kname, dns_rdatatype_dnskey, NULL, NULL, NULL, NULL,
   11093 		0, options, 0, NULL, NULL, NULL, zone->loop, keyfetch_done,
   11094 		kfetch, NULL, &kfetch->dnskeyset, &kfetch->dnskeysigset,
   11095 		&kfetch->fetch);
   11096 
   11097 	dns_resolver_detach(&resolver);
   11098 	if (result == ISC_R_SUCCESS) {
   11099 		return;
   11100 	}
   11101 retry:
   11102 	retry_keyfetch(kfetch, kname);
   11103 }
   11104 
   11105 /*
   11106  * Refresh the data in the key zone.  Initiate a fetch to look up
   11107  * DNSKEY records at the trust anchor name.
   11108  */
   11109 static void
   11110 zone_refreshkeys(dns_zone_t *zone) {
   11111 	isc_result_t result;
   11112 	dns_rriterator_t rrit;
   11113 	dns_db_t *db = NULL;
   11114 	dns_dbversion_t *ver = NULL;
   11115 	dns_diff_t diff;
   11116 	dns_rdata_t rdata = DNS_RDATA_INIT;
   11117 	dns_rdata_keydata_t kd;
   11118 	isc_stdtime_t now = isc_stdtime_now();
   11119 	bool commit = false;
   11120 	bool fetching = false;
   11121 	bool timerset = false;
   11122 
   11123 	ENTER;
   11124 	REQUIRE(zone->db != NULL);
   11125 
   11126 	LOCK_ZONE(zone);
   11127 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   11128 		isc_time_settoepoch(&zone->refreshkeytime);
   11129 		UNLOCK_ZONE(zone);
   11130 		return;
   11131 	}
   11132 
   11133 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   11134 	dns_db_attach(zone->db, &db);
   11135 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   11136 
   11137 	dns_diff_init(zone->mctx, &diff);
   11138 
   11139 	CHECK(dns_db_newversion(db, &ver));
   11140 
   11141 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
   11142 
   11143 	dns_rriterator_init(&rrit, db, ver, 0);
   11144 	for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
   11145 	     result = dns_rriterator_nextrrset(&rrit))
   11146 	{
   11147 		isc_stdtime_t timer = 0xffffffff;
   11148 		dns_name_t *name = NULL, *kname = NULL;
   11149 		dns_rdataset_t *kdset = NULL;
   11150 		uint32_t ttl;
   11151 
   11152 		dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
   11153 		if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
   11154 		    !dns_rdataset_isassociated(kdset))
   11155 		{
   11156 			continue;
   11157 		}
   11158 
   11159 		/*
   11160 		 * Scan the stored keys looking for ones that need
   11161 		 * removal or refreshing
   11162 		 */
   11163 		for (result = dns_rdataset_first(kdset);
   11164 		     result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset))
   11165 		{
   11166 			dns_rdata_reset(&rdata);
   11167 			dns_rdataset_current(kdset, &rdata);
   11168 			result = dns_rdata_tostruct(&rdata, &kd, NULL);
   11169 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   11170 
   11171 			/* Removal timer expired? */
   11172 			if (kd.removehd != 0 && kd.removehd < now) {
   11173 				dns_rriterator_pause(&rrit);
   11174 				CHECK(update_one_rr(db, ver, &diff,
   11175 						    DNS_DIFFOP_DEL, name, ttl,
   11176 						    &rdata));
   11177 				continue;
   11178 			}
   11179 
   11180 			/* Acceptance timer expired? */
   11181 			if (kd.addhd <= now) {
   11182 				timer = kd.addhd;
   11183 			}
   11184 
   11185 			/* Or do we just need to refresh the keyset? */
   11186 			if (timer > kd.refresh) {
   11187 				timer = kd.refresh;
   11188 			}
   11189 
   11190 			dns_rriterator_pause(&rrit);
   11191 			set_refreshkeytimer(zone, &kd, now, false);
   11192 			timerset = true;
   11193 		}
   11194 
   11195 		if (timer > now) {
   11196 			continue;
   11197 		}
   11198 
   11199 		dns_rriterator_pause(&rrit);
   11200 
   11201 #ifdef ENABLE_AFL
   11202 		if (!dns_fuzzing_resolver) {
   11203 #endif /* ifdef ENABLE_AFL */
   11204 			dns_keyfetch_t *kfetch = NULL;
   11205 
   11206 			kfetch = isc_mem_get(zone->mctx,
   11207 					     sizeof(dns_keyfetch_t));
   11208 			*kfetch = (dns_keyfetch_t){ .zone = zone };
   11209 			isc_mem_attach(zone->mctx, &kfetch->mctx);
   11210 
   11211 			zone->refreshkeycount++;
   11212 			isc_refcount_increment0(&zone->irefs);
   11213 			kname = dns_fixedname_initname(&kfetch->name);
   11214 			dns_name_dup(name, zone->mctx, kname);
   11215 			dns_rdataset_init(&kfetch->dnskeyset);
   11216 			dns_rdataset_init(&kfetch->dnskeysigset);
   11217 			dns_rdataset_init(&kfetch->keydataset);
   11218 			dns_rdataset_clone(kdset, &kfetch->keydataset);
   11219 			dns_db_attach(db, &kfetch->db);
   11220 
   11221 			if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   11222 				char namebuf[DNS_NAME_FORMATSIZE];
   11223 				dns_name_format(kname, namebuf,
   11224 						sizeof(namebuf));
   11225 				dnssec_log(zone, ISC_LOG_DEBUG(3),
   11226 					   "Creating key fetch in "
   11227 					   "zone_refreshkeys() for '%s'",
   11228 					   namebuf);
   11229 			}
   11230 
   11231 			isc_async_run(zone->loop, do_keyfetch, kfetch);
   11232 			fetching = true;
   11233 #ifdef ENABLE_AFL
   11234 		}
   11235 #endif /* ifdef ENABLE_AFL */
   11236 	}
   11237 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   11238 		CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
   11239 					zone->updatemethod));
   11240 		CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
   11241 		commit = true;
   11242 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   11243 		zone_needdump(zone, 30);
   11244 	}
   11245 
   11246 cleanup:
   11247 	if (!timerset) {
   11248 		isc_time_settoepoch(&zone->refreshkeytime);
   11249 	}
   11250 
   11251 	if (!fetching) {
   11252 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
   11253 	}
   11254 
   11255 	dns_diff_clear(&diff);
   11256 	if (ver != NULL) {
   11257 		dns_rriterator_destroy(&rrit);
   11258 		dns_db_closeversion(db, &ver, commit);
   11259 	}
   11260 	dns_db_detach(&db);
   11261 
   11262 	UNLOCK_ZONE(zone);
   11263 
   11264 	INSIST(ver == NULL);
   11265 }
   11266 
   11267 static void
   11268 zone_maintenance(dns_zone_t *zone) {
   11269 	isc_time_t now;
   11270 	isc_result_t result;
   11271 	bool load_pending, exiting, dumping, viewok = false, notify;
   11272 	bool refreshkeys, sign, resign, rekey, chain, warn_expire;
   11273 
   11274 	REQUIRE(DNS_ZONE_VALID(zone));
   11275 	ENTER;
   11276 
   11277 	/*
   11278 	 * Are we pending load/reload, exiting, or unconfigured
   11279 	 * (e.g. because of a syntax failure in the config file)?
   11280 	 * If so, don't attempt maintenance.
   11281 	 */
   11282 	LOCK_ZONE(zone);
   11283 	load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
   11284 	exiting = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING);
   11285 	if (!load_pending && !exiting && zone->view != NULL) {
   11286 		dns_adb_t *adb = NULL;
   11287 		dns_view_getadb(zone->view, &adb);
   11288 		if (adb != NULL) {
   11289 			dns_adb_detach(&adb);
   11290 			viewok = true;
   11291 		}
   11292 	}
   11293 	UNLOCK_ZONE(zone);
   11294 
   11295 	if (load_pending || exiting || !viewok) {
   11296 		return;
   11297 	}
   11298 
   11299 	now = isc_time_now();
   11300 
   11301 	/*
   11302 	 * Expire check.
   11303 	 */
   11304 	switch (zone->type) {
   11305 	case dns_zone_redirect:
   11306 		if (dns_remote_addresses(&zone->primaries) == NULL) {
   11307 			break;
   11308 		}
   11309 		FALLTHROUGH;
   11310 	case dns_zone_secondary:
   11311 	case dns_zone_mirror:
   11312 	case dns_zone_stub:
   11313 		LOCK_ZONE(zone);
   11314 		if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
   11315 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   11316 		{
   11317 			zone_expire(zone);
   11318 			zone->refreshtime = now;
   11319 		}
   11320 		UNLOCK_ZONE(zone);
   11321 		break;
   11322 	default:
   11323 		break;
   11324 	}
   11325 
   11326 	/*
   11327 	 * Up to date check.
   11328 	 */
   11329 	switch (zone->type) {
   11330 	case dns_zone_redirect:
   11331 		if (dns_remote_addresses(&zone->primaries) == NULL) {
   11332 			break;
   11333 		}
   11334 		FALLTHROUGH;
   11335 	case dns_zone_secondary:
   11336 	case dns_zone_mirror:
   11337 	case dns_zone_stub:
   11338 		LOCK_ZONE(zone);
   11339 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
   11340 		    isc_time_compare(&now, &zone->refreshtime) >= 0)
   11341 		{
   11342 			zone_refresh(zone);
   11343 		}
   11344 		UNLOCK_ZONE(zone);
   11345 		break;
   11346 	default:
   11347 		break;
   11348 	}
   11349 
   11350 	/*
   11351 	 * Secondaries send notifies before backing up to disk,
   11352 	 * primaries after.
   11353 	 */
   11354 	LOCK_ZONE(zone);
   11355 	if (zone->notifydefer != 0 &&
   11356 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYNODEFER) &&
   11357 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED))
   11358 	{
   11359 		if (isc_time_compare(&now, &zone->notifytime) > 0) {
   11360 			zone->notifytime = now;
   11361 		}
   11362 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED);
   11363 		DNS_ZONE_TIME_ADD(&zone->notifytime, zone->notifydefer,
   11364 				  &zone->notifytime);
   11365 	}
   11366 	notify = (zone->type == dns_zone_secondary ||
   11367 		  zone->type == dns_zone_mirror) &&
   11368 		 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   11369 		  DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
   11370 		 isc_time_compare(&now, &zone->notifytime) >= 0;
   11371 	UNLOCK_ZONE(zone);
   11372 
   11373 	if (notify) {
   11374 		zone_notify(zone, &now);
   11375 	}
   11376 
   11377 	/*
   11378 	 * Do we need to consolidate the backing store?
   11379 	 */
   11380 	switch (zone->type) {
   11381 	case dns_zone_primary:
   11382 	case dns_zone_secondary:
   11383 	case dns_zone_mirror:
   11384 	case dns_zone_key:
   11385 	case dns_zone_redirect:
   11386 	case dns_zone_stub:
   11387 		LOCK_ZONE(zone);
   11388 		if (zone->masterfile != NULL &&
   11389 		    isc_time_compare(&now, &zone->dumptime) >= 0 &&
   11390 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   11391 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
   11392 		{
   11393 			dumping = was_dumping(zone);
   11394 		} else {
   11395 			dumping = true;
   11396 		}
   11397 		UNLOCK_ZONE(zone);
   11398 		if (!dumping) {
   11399 			result = zone_dump(zone, true); /* loop locked */
   11400 			if (result != ISC_R_SUCCESS) {
   11401 				dns_zone_log(zone, ISC_LOG_WARNING,
   11402 					     "dump failed: %s",
   11403 					     isc_result_totext(result));
   11404 			}
   11405 		}
   11406 		break;
   11407 	default:
   11408 		break;
   11409 	}
   11410 
   11411 	/*
   11412 	 * Primary/redirect zones send notifies now, if needed
   11413 	 */
   11414 	switch (zone->type) {
   11415 	case dns_zone_primary:
   11416 	case dns_zone_redirect:
   11417 		LOCK_ZONE(zone);
   11418 		notify = (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   11419 			  DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
   11420 			 isc_time_compare(&now, &zone->notifytime) >= 0;
   11421 		UNLOCK_ZONE(zone);
   11422 		if (notify) {
   11423 			zone_notify(zone, &now);
   11424 		}
   11425 	default:
   11426 		break;
   11427 	}
   11428 
   11429 	/*
   11430 	 * Do we need to refresh keys?
   11431 	 */
   11432 	switch (zone->type) {
   11433 	case dns_zone_key:
   11434 		LOCK_ZONE(zone);
   11435 		refreshkeys = isc_time_compare(&now, &zone->refreshkeytime) >=
   11436 				      0 &&
   11437 			      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   11438 			      !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING);
   11439 		UNLOCK_ZONE(zone);
   11440 		if (refreshkeys) {
   11441 			zone_refreshkeys(zone);
   11442 		}
   11443 		break;
   11444 	case dns_zone_primary:
   11445 		LOCK_ZONE(zone);
   11446 		if (zone->rss != NULL) {
   11447 			isc_time_settoepoch(&zone->refreshkeytime);
   11448 			UNLOCK_ZONE(zone);
   11449 			break;
   11450 		}
   11451 		rekey = (!isc_time_isepoch(&zone->refreshkeytime) &&
   11452 			 isc_time_compare(&now, &zone->refreshkeytime) >= 0);
   11453 		UNLOCK_ZONE(zone);
   11454 		if (rekey) {
   11455 			zone_rekey(zone);
   11456 		}
   11457 	default:
   11458 		break;
   11459 	}
   11460 
   11461 	switch (zone->type) {
   11462 	case dns_zone_primary:
   11463 	case dns_zone_redirect:
   11464 	case dns_zone_secondary:
   11465 		/*
   11466 		 * Do we need to sign/resign some RRsets?
   11467 		 */
   11468 		LOCK_ZONE(zone);
   11469 		if (zone->rss != NULL) {
   11470 			isc_time_settoepoch(&zone->signingtime);
   11471 			isc_time_settoepoch(&zone->resigntime);
   11472 			isc_time_settoepoch(&zone->nsec3chaintime);
   11473 			isc_time_settoepoch(&zone->keywarntime);
   11474 			UNLOCK_ZONE(zone);
   11475 			break;
   11476 		}
   11477 		sign = !isc_time_isepoch(&zone->signingtime) &&
   11478 		       isc_time_compare(&now, &zone->signingtime) >= 0;
   11479 		resign = !isc_time_isepoch(&zone->resigntime) &&
   11480 			 isc_time_compare(&now, &zone->resigntime) >= 0;
   11481 		chain = !isc_time_isepoch(&zone->nsec3chaintime) &&
   11482 			isc_time_compare(&now, &zone->nsec3chaintime) >= 0;
   11483 		warn_expire = !isc_time_isepoch(&zone->keywarntime) &&
   11484 			      isc_time_compare(&now, &zone->keywarntime) >= 0;
   11485 		UNLOCK_ZONE(zone);
   11486 
   11487 		if (sign) {
   11488 			zone_sign(zone);
   11489 		} else if (resign) {
   11490 			zone_resigninc(zone);
   11491 		} else if (chain) {
   11492 			zone_nsec3chain(zone);
   11493 		}
   11494 
   11495 		/*
   11496 		 * Do we need to issue a key expiry warning?
   11497 		 */
   11498 		if (warn_expire) {
   11499 			set_key_expiry_warning(zone, zone->key_expiry,
   11500 					       isc_time_seconds(&now));
   11501 		}
   11502 		break;
   11503 
   11504 	default:
   11505 		break;
   11506 	}
   11507 	LOCK_ZONE(zone);
   11508 	zone_settimer(zone, &now);
   11509 	UNLOCK_ZONE(zone);
   11510 }
   11511 
   11512 void
   11513 dns_zone_markdirty(dns_zone_t *zone) {
   11514 	uint32_t serial;
   11515 	isc_result_t result = ISC_R_SUCCESS;
   11516 	dns_zone_t *secure = NULL;
   11517 
   11518 	/*
   11519 	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
   11520 	 * could result in a deadlock due to a LOR so we will spin if we
   11521 	 * can't obtain the both locks.
   11522 	 */
   11523 again:
   11524 	LOCK_ZONE(zone);
   11525 	if (zone->type == dns_zone_primary) {
   11526 		if (inline_raw(zone)) {
   11527 			unsigned int soacount;
   11528 			secure = zone->secure;
   11529 			INSIST(secure != zone);
   11530 			TRYLOCK_ZONE(result, secure);
   11531 			if (result != ISC_R_SUCCESS) {
   11532 				UNLOCK_ZONE(zone);
   11533 				secure = NULL;
   11534 				isc_thread_yield();
   11535 				goto again;
   11536 			}
   11537 
   11538 			ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   11539 			if (zone->db != NULL) {
   11540 				result = zone_get_from_db(
   11541 					zone, zone->db, NULL, &soacount, NULL,
   11542 					&serial, NULL, NULL, NULL, NULL, NULL);
   11543 			} else {
   11544 				result = DNS_R_NOTLOADED;
   11545 			}
   11546 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   11547 			if (result == ISC_R_SUCCESS && soacount > 0U) {
   11548 				zone_send_secureserial(zone, serial);
   11549 			}
   11550 		}
   11551 
   11552 		/* XXXMPA make separate call back */
   11553 		if (result == ISC_R_SUCCESS) {
   11554 			set_resigntime(zone);
   11555 			if (zone->loop != NULL) {
   11556 				isc_time_t now;
   11557 				now = isc_time_now();
   11558 				zone_settimer(zone, &now);
   11559 			}
   11560 		}
   11561 	}
   11562 	if (secure != NULL) {
   11563 		UNLOCK_ZONE(secure);
   11564 	}
   11565 	zone_needdump(zone, DNS_DUMP_DELAY);
   11566 	UNLOCK_ZONE(zone);
   11567 }
   11568 
   11569 void
   11570 dns_zone_expire(dns_zone_t *zone) {
   11571 	REQUIRE(DNS_ZONE_VALID(zone));
   11572 
   11573 	LOCK_ZONE(zone);
   11574 	zone_expire(zone);
   11575 	UNLOCK_ZONE(zone);
   11576 }
   11577 
   11578 static void
   11579 zone_expire(dns_zone_t *zone) {
   11580 	dns_db_t *db = NULL;
   11581 
   11582 	/*
   11583 	 * 'zone' locked by caller.
   11584 	 */
   11585 
   11586 	REQUIRE(LOCKED_ZONE(zone));
   11587 
   11588 	dns_zone_log(zone, ISC_LOG_WARNING, "expired");
   11589 
   11590 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
   11591 	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
   11592 	zone->retry = DNS_ZONE_DEFAULTRETRY;
   11593 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   11594 
   11595 	/*
   11596 	 * An RPZ zone has expired; before unloading it, we must
   11597 	 * first remove it from the RPZ summary database. The
   11598 	 * easiest way to do this is "update" it with an empty
   11599 	 * database so that the update callback synchronizes
   11600 	 * the diff automatically.
   11601 	 */
   11602 	if (zone->rpzs != NULL && zone->rpz_num != DNS_RPZ_INVALID_NUM) {
   11603 		isc_result_t result;
   11604 		dns_rpz_zone_t *rpz = zone->rpzs->zones[zone->rpz_num];
   11605 
   11606 		CHECK(dns_db_create(zone->mctx, ZONEDB_DEFAULT, &zone->origin,
   11607 				    dns_dbtype_zone, zone->rdclass, 0, NULL,
   11608 				    &db));
   11609 		CHECK(dns_rpz_dbupdate_callback(db, rpz));
   11610 		dns_zone_log(zone, ISC_LOG_WARNING,
   11611 			     "response-policy zone expired; "
   11612 			     "policies unloaded");
   11613 	}
   11614 
   11615 cleanup:
   11616 	if (db != NULL) {
   11617 		dns_db_detach(&db);
   11618 	}
   11619 
   11620 	zone_unload(zone);
   11621 }
   11622 
   11623 static void
   11624 zone_refresh(dns_zone_t *zone) {
   11625 	isc_interval_t i;
   11626 	uint32_t oldflags;
   11627 	isc_result_t result;
   11628 
   11629 	REQUIRE(DNS_ZONE_VALID(zone));
   11630 	REQUIRE(LOCKED_ZONE(zone));
   11631 
   11632 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   11633 		return;
   11634 	}
   11635 
   11636 	/*
   11637 	 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
   11638 	 * in progress at a time.
   11639 	 */
   11640 
   11641 	oldflags = ISC_ZONE_GET(zone, flags);
   11642 	if (dns_remote_addresses(&zone->primaries) == NULL) {
   11643 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
   11644 		if ((oldflags & DNS_ZONEFLG_NOPRIMARIES) == 0) {
   11645 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   11646 				      ISC_LOG_ERROR,
   11647 				      "cannot refresh: no primaries");
   11648 		}
   11649 		return;
   11650 	}
   11651 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
   11652 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
   11653 	if ((oldflags & (DNS_ZONEFLG_REFRESH | DNS_ZONEFLG_LOADING)) != 0) {
   11654 		return;
   11655 	}
   11656 
   11657 	/*
   11658 	 * Set the next refresh time as if refresh check has failed.
   11659 	 * Setting this to the retry time will do that.  XXXMLG
   11660 	 * If we are successful it will be reset using zone->refresh.
   11661 	 */
   11662 	isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
   11663 			 0);
   11664 	result = isc_time_nowplusinterval(&zone->refreshtime, &i);
   11665 	if (result != ISC_R_SUCCESS) {
   11666 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_WARNING,
   11667 			      "isc_time_nowplusinterval() failed: %s",
   11668 			      isc_result_totext(result));
   11669 	}
   11670 
   11671 	/*
   11672 	 * When lacking user-specified timer values from the SOA,
   11673 	 * do exponential backoff of the retry time up to a
   11674 	 * maximum of six hours.
   11675 	 */
   11676 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS)) {
   11677 		zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
   11678 	}
   11679 
   11680 	dns_remote_reset(&zone->primaries, true);
   11681 
   11682 	/* initiate soa query */
   11683 	queue_soa_query(zone);
   11684 }
   11685 
   11686 static void
   11687 zone_refresh_async(void *arg) {
   11688 	dns_zone_t *zone = arg;
   11689 
   11690 	LOCK_ZONE(zone);
   11691 	zone_refresh(zone);
   11692 	UNLOCK_ZONE(zone);
   11693 
   11694 	dns_zone_detach(&zone);
   11695 }
   11696 
   11697 void
   11698 dns_zone_refresh(dns_zone_t *zone) {
   11699 	REQUIRE(DNS_ZONE_VALID(zone));
   11700 
   11701 	dns_zone_ref(zone);
   11702 	isc_async_run(zone->loop, zone_refresh_async, zone);
   11703 }
   11704 
   11705 static isc_result_t
   11706 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
   11707 			 bool *fixjournal) {
   11708 	dns_journal_t *journal = NULL;
   11709 	unsigned int options;
   11710 	isc_result_t result;
   11711 
   11712 	if (zone->type == dns_zone_primary &&
   11713 	    (inline_secure(zone) ||
   11714 	     (zone->update_acl != NULL || zone->ssutable != NULL)))
   11715 	{
   11716 		options = DNS_JOURNALOPT_RESIGN;
   11717 	} else {
   11718 		options = 0;
   11719 	}
   11720 
   11721 	result = dns_journal_open(zone->mctx, zone->journal, DNS_JOURNAL_READ,
   11722 				  &journal);
   11723 	if (result == ISC_R_NOTFOUND) {
   11724 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(3),
   11725 			      "no journal file, but that's OK ");
   11726 		return ISC_R_SUCCESS;
   11727 	} else if (result != ISC_R_SUCCESS) {
   11728 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   11729 			      "journal open failed: %s",
   11730 			      isc_result_totext(result));
   11731 		return result;
   11732 	}
   11733 
   11734 	if (dns_journal_empty(journal)) {
   11735 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
   11736 			      "journal empty");
   11737 		dns_journal_destroy(&journal);
   11738 		return ISC_R_SUCCESS;
   11739 	}
   11740 
   11741 	result = dns_journal_rollforward(journal, db, options);
   11742 	switch (result) {
   11743 	case ISC_R_SUCCESS:
   11744 		*needdump = true;
   11745 		FALLTHROUGH;
   11746 	case DNS_R_UPTODATE:
   11747 		if (dns_journal_recovered(journal)) {
   11748 			*fixjournal = true;
   11749 			dns_zone_logc(
   11750 				zone, DNS_LOGCATEGORY_ZONELOAD,
   11751 				ISC_LOG_DEBUG(1),
   11752 				"journal rollforward completed successfully "
   11753 				"using old journal format: %s",
   11754 				isc_result_totext(result));
   11755 		} else {
   11756 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   11757 				      ISC_LOG_DEBUG(1),
   11758 				      "journal rollforward completed "
   11759 				      "successfully: %s",
   11760 				      isc_result_totext(result));
   11761 		}
   11762 
   11763 		dns_journal_destroy(&journal);
   11764 		return ISC_R_SUCCESS;
   11765 	case ISC_R_NOTFOUND:
   11766 	case ISC_R_RANGE:
   11767 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   11768 			      "journal rollforward failed: journal out of sync "
   11769 			      "with zone");
   11770 		dns_journal_destroy(&journal);
   11771 		return result;
   11772 	default:
   11773 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   11774 			      "journal rollforward failed: %s",
   11775 			      isc_result_totext(result));
   11776 		dns_journal_destroy(&journal);
   11777 		return result;
   11778 	}
   11779 }
   11780 
   11781 static void
   11782 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
   11783 	isc_result_t result;
   11784 	int32_t journalsize;
   11785 	dns_dbversion_t *ver = NULL;
   11786 	uint64_t dbsize;
   11787 	uint32_t options = 0;
   11788 
   11789 	INSIST(LOCKED_ZONE(zone));
   11790 	if (inline_raw(zone)) {
   11791 		INSIST(LOCKED_ZONE(zone->secure));
   11792 	}
   11793 
   11794 	journalsize = zone->journalsize;
   11795 	if (journalsize == -1) {
   11796 		journalsize = DNS_JOURNAL_SIZE_MAX;
   11797 		dns_db_currentversion(db, &ver);
   11798 		result = dns_db_getsize(db, ver, NULL, &dbsize);
   11799 		dns_db_closeversion(db, &ver, false);
   11800 		if (result != ISC_R_SUCCESS) {
   11801 			dns_zone_log(zone, ISC_LOG_ERROR,
   11802 				     "zone_journal_compact: "
   11803 				     "could not get zone size: %s",
   11804 				     isc_result_totext(result));
   11805 		} else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
   11806 			journalsize = (int32_t)dbsize * 2;
   11807 		}
   11808 	}
   11809 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIXJOURNAL)) {
   11810 		options |= DNS_JOURNAL_COMPACTALL;
   11811 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
   11812 		zone_debuglog(zone, __func__, 1, "repair full journal");
   11813 	} else {
   11814 		zone_debuglog(zone, __func__, 1, "target journal size %d",
   11815 			      journalsize);
   11816 	}
   11817 	result = dns_journal_compact(zone->mctx, zone->journal, serial, options,
   11818 				     journalsize);
   11819 	switch (result) {
   11820 	case ISC_R_SUCCESS:
   11821 	case ISC_R_NOSPACE:
   11822 	case ISC_R_NOTFOUND:
   11823 		dns_zone_log(zone, ISC_LOG_DEBUG(3), "dns_journal_compact: %s",
   11824 			     isc_result_totext(result));
   11825 		break;
   11826 	default:
   11827 		dns_zone_log(zone, ISC_LOG_ERROR,
   11828 			     "dns_journal_compact failed: %s",
   11829 			     isc_result_totext(result));
   11830 		break;
   11831 	}
   11832 }
   11833 
   11834 isc_result_t
   11835 dns_zone_flush(dns_zone_t *zone) {
   11836 	isc_result_t result = ISC_R_SUCCESS;
   11837 	bool dumping;
   11838 
   11839 	REQUIRE(DNS_ZONE_VALID(zone));
   11840 
   11841 	LOCK_ZONE(zone);
   11842 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
   11843 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   11844 	    zone->masterfile != NULL)
   11845 	{
   11846 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
   11847 		result = ISC_R_ALREADYRUNNING;
   11848 		dumping = was_dumping(zone);
   11849 	} else {
   11850 		dumping = true;
   11851 	}
   11852 	UNLOCK_ZONE(zone);
   11853 	if (!dumping) {
   11854 		result = zone_dump(zone, true);
   11855 	}
   11856 	return result;
   11857 }
   11858 
   11859 isc_result_t
   11860 dns_zone_dump(dns_zone_t *zone) {
   11861 	isc_result_t result = ISC_R_ALREADYRUNNING;
   11862 	bool dumping;
   11863 
   11864 	REQUIRE(DNS_ZONE_VALID(zone));
   11865 
   11866 	LOCK_ZONE(zone);
   11867 	dumping = was_dumping(zone);
   11868 	UNLOCK_ZONE(zone);
   11869 	if (!dumping) {
   11870 		result = zone_dump(zone, false);
   11871 	}
   11872 	return result;
   11873 }
   11874 
   11875 static void
   11876 zone_needdump(dns_zone_t *zone, unsigned int delay) {
   11877 	isc_time_t dumptime;
   11878 	isc_time_t now;
   11879 
   11880 	/*
   11881 	 * 'zone' locked by caller
   11882 	 */
   11883 
   11884 	REQUIRE(DNS_ZONE_VALID(zone));
   11885 	REQUIRE(LOCKED_ZONE(zone));
   11886 	ENTER;
   11887 
   11888 	/*
   11889 	 * Do we have a place to dump to and are we loaded?
   11890 	 */
   11891 	if (zone->masterfile == NULL ||
   11892 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
   11893 	{
   11894 		return;
   11895 	}
   11896 
   11897 	now = isc_time_now();
   11898 	/* add some noise */
   11899 	DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
   11900 
   11901 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   11902 	if (isc_time_isepoch(&zone->dumptime) ||
   11903 	    isc_time_compare(&zone->dumptime, &dumptime) > 0)
   11904 	{
   11905 		zone->dumptime = dumptime;
   11906 	}
   11907 	if (zone->loop != NULL) {
   11908 		zone_settimer(zone, &now);
   11909 	}
   11910 }
   11911 
   11912 static void
   11913 dump_done(void *arg, isc_result_t result) {
   11914 	dns_zone_t *zone = arg;
   11915 	dns_zone_t *secure = NULL;
   11916 	dns_db_t *db;
   11917 	dns_dbversion_t *version;
   11918 	bool again = false;
   11919 	bool compact = false;
   11920 	uint32_t serial;
   11921 	isc_result_t tresult;
   11922 
   11923 	REQUIRE(DNS_ZONE_VALID(zone));
   11924 
   11925 	ENTER;
   11926 
   11927 	/*
   11928 	 * Adjust modification time of zone file to preserve expire timing.
   11929 	 */
   11930 	if ((zone->type == dns_zone_secondary ||
   11931 	     zone->type == dns_zone_mirror ||
   11932 	     zone->type == dns_zone_redirect) &&
   11933 	    result == ISC_R_SUCCESS)
   11934 	{
   11935 		LOCK_ZONE(zone);
   11936 		isc_time_t when;
   11937 		isc_interval_t i;
   11938 		isc_interval_set(&i, zone->expire, 0);
   11939 		result = isc_time_subtract(&zone->expiretime, &i, &when);
   11940 		if (result == ISC_R_SUCCESS) {
   11941 			(void)isc_file_settime(zone->masterfile, &when);
   11942 		} else {
   11943 			result = ISC_R_SUCCESS;
   11944 		}
   11945 		UNLOCK_ZONE(zone);
   11946 	}
   11947 
   11948 	if (result == ISC_R_SUCCESS && zone->journal != NULL) {
   11949 		/*
   11950 		 * We don't own these, zone->dctx must stay valid.
   11951 		 */
   11952 		db = dns_dumpctx_db(zone->dumpctx);
   11953 		version = dns_dumpctx_version(zone->dumpctx);
   11954 		tresult = dns_db_getsoaserial(db, version, &serial);
   11955 
   11956 		/*
   11957 		 * Handle lock order inversion.
   11958 		 */
   11959 	again:
   11960 		LOCK_ZONE(zone);
   11961 		if (inline_raw(zone)) {
   11962 			secure = zone->secure;
   11963 			INSIST(secure != zone);
   11964 			TRYLOCK_ZONE(result, secure);
   11965 			if (result != ISC_R_SUCCESS) {
   11966 				UNLOCK_ZONE(zone);
   11967 				secure = NULL;
   11968 				isc_thread_yield();
   11969 				goto again;
   11970 			}
   11971 		}
   11972 
   11973 		/*
   11974 		 * If there is a secure version of this zone
   11975 		 * use its serial if it is less than ours.
   11976 		 */
   11977 		if (tresult == ISC_R_SUCCESS && secure != NULL) {
   11978 			uint32_t sserial;
   11979 			isc_result_t mresult;
   11980 
   11981 			ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
   11982 			if (secure->db != NULL) {
   11983 				mresult = dns_db_getsoaserial(zone->secure->db,
   11984 							      NULL, &sserial);
   11985 				if (mresult == ISC_R_SUCCESS &&
   11986 				    isc_serial_lt(sserial, serial))
   11987 				{
   11988 					serial = sserial;
   11989 				}
   11990 			}
   11991 			ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
   11992 		}
   11993 		if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
   11994 			dns_db_t *zdb = NULL;
   11995 			if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
   11996 				zone_journal_compact(zone, zdb, serial);
   11997 				dns_db_detach(&zdb);
   11998 			}
   11999 		} else if (tresult == ISC_R_SUCCESS) {
   12000 			compact = true;
   12001 			zone->compact_serial = serial;
   12002 		}
   12003 		if (secure != NULL) {
   12004 			UNLOCK_ZONE(secure);
   12005 		}
   12006 		UNLOCK_ZONE(zone);
   12007 	}
   12008 
   12009 	LOCK_ZONE(zone);
   12010 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
   12011 	if (compact) {
   12012 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
   12013 	}
   12014 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN)) {
   12015 		/*
   12016 		 * If DNS_ZONEFLG_SHUTDOWN is set, all external references to
   12017 		 * the zone are gone, which means it is in the process of being
   12018 		 * cleaned up, so do not reschedule dumping.
   12019 		 *
   12020 		 * Detach from the raw version of the zone in case this
   12021 		 * operation has been deferred in zone_shutdown().
   12022 		 */
   12023 		if (zone->raw != NULL) {
   12024 			dns_zone_detach(&zone->raw);
   12025 		}
   12026 		if (result == ISC_R_SUCCESS) {
   12027 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
   12028 		}
   12029 	} else if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
   12030 		/*
   12031 		 * Try again in a short while.
   12032 		 */
   12033 		zone_needdump(zone, DNS_DUMP_DELAY);
   12034 	} else if (result == ISC_R_SUCCESS &&
   12035 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
   12036 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   12037 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   12038 	{
   12039 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   12040 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
   12041 		isc_time_settoepoch(&zone->dumptime);
   12042 		again = true;
   12043 	} else if (result == ISC_R_SUCCESS) {
   12044 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
   12045 	}
   12046 
   12047 	if (zone->dumpctx != NULL) {
   12048 		dns_dumpctx_detach(&zone->dumpctx);
   12049 	}
   12050 	UNLOCK_ZONE(zone);
   12051 	if (again) {
   12052 		(void)zone_dump(zone, false);
   12053 	}
   12054 	dns_zone_idetach(&zone);
   12055 }
   12056 
   12057 static isc_result_t
   12058 zone_dump(dns_zone_t *zone, bool compact) {
   12059 	isc_result_t result;
   12060 	dns_dbversion_t *version = NULL;
   12061 	bool again = false;
   12062 	dns_db_t *db = NULL;
   12063 	char *masterfile = NULL;
   12064 	dns_masterformat_t masterformat = dns_masterformat_none;
   12065 	const dns_master_style_t *masterstyle = NULL;
   12066 	dns_masterrawheader_t rawdata;
   12067 
   12068 	/*
   12069 	 * 'compact' MUST only be set if we are loop locked.
   12070 	 */
   12071 
   12072 	REQUIRE(DNS_ZONE_VALID(zone));
   12073 	ENTER;
   12074 
   12075 redo:
   12076 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   12077 	if (zone->db != NULL) {
   12078 		dns_db_attach(zone->db, &db);
   12079 	}
   12080 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   12081 	LOCK_ZONE(zone);
   12082 	if (zone->masterfile != NULL) {
   12083 		masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
   12084 		masterformat = zone->masterformat;
   12085 	}
   12086 	if (zone->type == dns_zone_key) {
   12087 		masterstyle = &dns_master_style_keyzone;
   12088 	} else if (zone->masterstyle != NULL) {
   12089 		masterstyle = zone->masterstyle;
   12090 	} else {
   12091 		masterstyle = &dns_master_style_default;
   12092 	}
   12093 	UNLOCK_ZONE(zone);
   12094 	if (db == NULL) {
   12095 		result = DNS_R_NOTLOADED;
   12096 		goto fail;
   12097 	}
   12098 	if (masterfile == NULL) {
   12099 		result = DNS_R_NOMASTERFILE;
   12100 		goto fail;
   12101 	}
   12102 
   12103 	dns_db_currentversion(db, &version);
   12104 
   12105 	dns_master_initrawheader(&rawdata);
   12106 
   12107 	if (inline_secure(zone)) {
   12108 		get_raw_serial(zone->raw, &rawdata);
   12109 	}
   12110 
   12111 	if (compact && zone->type != dns_zone_stub) {
   12112 		LOCK_ZONE(zone);
   12113 		zone_iattach(zone, &(dns_zone_t *){ NULL });
   12114 
   12115 		INSIST(zone != zone->raw);
   12116 
   12117 		result = dns_master_dumpasync(
   12118 			zone->mctx, db, version, masterstyle, masterfile,
   12119 			zone->loop, dump_done, zone, &zone->dumpctx,
   12120 			masterformat, &rawdata);
   12121 
   12122 		UNLOCK_ZONE(zone);
   12123 		if (result != ISC_R_SUCCESS) {
   12124 			dns_zone_idetach(&(dns_zone_t *){ zone });
   12125 			goto fail;
   12126 		}
   12127 		result = DNS_R_CONTINUE;
   12128 	} else {
   12129 		result = dns_master_dump(zone->mctx, db, version, masterstyle,
   12130 					 masterfile, masterformat, &rawdata);
   12131 		if ((zone->type == dns_zone_secondary ||
   12132 		     zone->type == dns_zone_mirror ||
   12133 		     zone->type == dns_zone_redirect) &&
   12134 		    result == ISC_R_SUCCESS)
   12135 		{
   12136 			isc_time_t when;
   12137 			isc_interval_t i;
   12138 			isc_interval_set(&i, zone->expire, 0);
   12139 			result = isc_time_subtract(&zone->expiretime, &i,
   12140 						   &when);
   12141 			if (result == ISC_R_SUCCESS) {
   12142 				(void)isc_file_settime(zone->masterfile, &when);
   12143 			} else {
   12144 				result = ISC_R_SUCCESS;
   12145 			}
   12146 		}
   12147 	}
   12148 fail:
   12149 	if (version != NULL) {
   12150 		dns_db_closeversion(db, &version, false);
   12151 	}
   12152 	if (db != NULL) {
   12153 		dns_db_detach(&db);
   12154 	}
   12155 	if (masterfile != NULL) {
   12156 		isc_mem_free(zone->mctx, masterfile);
   12157 		masterfile = NULL;
   12158 	}
   12159 
   12160 	if (result == DNS_R_CONTINUE) {
   12161 		/*
   12162 		 * Asyncronous write is in progress.  Zone flags will get
   12163 		 * updated on completion.  Cleanup is complete.  We are done.
   12164 		 */
   12165 		return ISC_R_SUCCESS;
   12166 	}
   12167 
   12168 	again = false;
   12169 	LOCK_ZONE(zone);
   12170 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
   12171 	if (result != ISC_R_SUCCESS) {
   12172 		/*
   12173 		 * Try again in a short while.
   12174 		 */
   12175 		zone_needdump(zone, DNS_DUMP_DELAY);
   12176 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
   12177 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   12178 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   12179 	{
   12180 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   12181 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
   12182 		isc_time_settoepoch(&zone->dumptime);
   12183 		again = true;
   12184 	} else {
   12185 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
   12186 	}
   12187 	UNLOCK_ZONE(zone);
   12188 	if (again) {
   12189 		goto redo;
   12190 	}
   12191 
   12192 	return result;
   12193 }
   12194 
   12195 static isc_result_t
   12196 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
   12197 	     dns_masterformat_t format, const uint32_t rawversion) {
   12198 	isc_result_t result;
   12199 	dns_dbversion_t *version = NULL;
   12200 	dns_db_t *db = NULL;
   12201 	dns_masterrawheader_t rawdata;
   12202 
   12203 	REQUIRE(DNS_ZONE_VALID(zone));
   12204 
   12205 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   12206 	if (zone->db != NULL) {
   12207 		dns_db_attach(zone->db, &db);
   12208 	}
   12209 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   12210 	if (db == NULL) {
   12211 		return DNS_R_NOTLOADED;
   12212 	}
   12213 
   12214 	dns_db_currentversion(db, &version);
   12215 	dns_master_initrawheader(&rawdata);
   12216 	if (rawversion == 0) {
   12217 		rawdata.flags |= DNS_MASTERRAW_COMPAT;
   12218 	} else if (inline_secure(zone)) {
   12219 		get_raw_serial(zone->raw, &rawdata);
   12220 	} else if (zone->sourceserialset) {
   12221 		rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
   12222 		rawdata.sourceserial = zone->sourceserial;
   12223 	}
   12224 	result = dns_master_dumptostream(zone->mctx, db, version, style, format,
   12225 					 &rawdata, fd);
   12226 	dns_db_closeversion(db, &version, false);
   12227 	dns_db_detach(&db);
   12228 	return result;
   12229 }
   12230 
   12231 isc_result_t
   12232 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
   12233 		      const dns_master_style_t *style,
   12234 		      const uint32_t rawversion) {
   12235 	return dumptostream(zone, fd, style, format, rawversion);
   12236 }
   12237 
   12238 void
   12239 dns_zone_unload(dns_zone_t *zone) {
   12240 	REQUIRE(DNS_ZONE_VALID(zone));
   12241 
   12242 	LOCK_ZONE(zone);
   12243 	zone_unload(zone);
   12244 	UNLOCK_ZONE(zone);
   12245 }
   12246 
   12247 static void
   12248 notify_cancel(dns_zone_t *zone) {
   12249 	dns_notify_t *notify;
   12250 
   12251 	/*
   12252 	 * 'zone' locked by caller.
   12253 	 */
   12254 
   12255 	REQUIRE(LOCKED_ZONE(zone));
   12256 
   12257 	for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
   12258 	     notify = ISC_LIST_NEXT(notify, link))
   12259 	{
   12260 		if (notify->find != NULL) {
   12261 			dns_adb_cancelfind(notify->find);
   12262 		}
   12263 		if (notify->request != NULL) {
   12264 			dns_request_cancel(notify->request);
   12265 		}
   12266 	}
   12267 }
   12268 
   12269 static void
   12270 checkds_cancel(dns_zone_t *zone) {
   12271 	dns_checkds_t *checkds;
   12272 
   12273 	/*
   12274 	 * 'zone' locked by caller.
   12275 	 */
   12276 
   12277 	REQUIRE(LOCKED_ZONE(zone));
   12278 
   12279 	for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
   12280 	     checkds = ISC_LIST_NEXT(checkds, link))
   12281 	{
   12282 		if (checkds->find != NULL) {
   12283 			dns_adb_cancelfind(checkds->find);
   12284 		}
   12285 		if (checkds->request != NULL) {
   12286 			dns_request_cancel(checkds->request);
   12287 		}
   12288 	}
   12289 }
   12290 
   12291 static void
   12292 forward_cancel(dns_zone_t *zone) {
   12293 	dns_forward_t *forward;
   12294 
   12295 	/*
   12296 	 * 'zone' locked by caller.
   12297 	 */
   12298 
   12299 	REQUIRE(LOCKED_ZONE(zone));
   12300 
   12301 	for (forward = ISC_LIST_HEAD(zone->forwards); forward != NULL;
   12302 	     forward = ISC_LIST_NEXT(forward, link))
   12303 	{
   12304 		if (forward->request != NULL) {
   12305 			dns_request_cancel(forward->request);
   12306 		}
   12307 	}
   12308 }
   12309 
   12310 static void
   12311 zone_unload(dns_zone_t *zone) {
   12312 	/*
   12313 	 * 'zone' locked by caller.
   12314 	 */
   12315 
   12316 	REQUIRE(LOCKED_ZONE(zone));
   12317 
   12318 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
   12319 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
   12320 	{
   12321 		if (zone->dumpctx != NULL) {
   12322 			dns_dumpctx_cancel(zone->dumpctx);
   12323 		}
   12324 	}
   12325 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   12326 	zone_detachdb(zone);
   12327 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   12328 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
   12329 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   12330 
   12331 	if (zone->type == dns_zone_mirror) {
   12332 		dns_zone_log(zone, ISC_LOG_INFO,
   12333 			     "mirror zone is no longer in use; "
   12334 			     "reverting to normal recursion");
   12335 	}
   12336 }
   12337 
   12338 void
   12339 dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
   12340 	REQUIRE(DNS_ZONE_VALID(zone));
   12341 	REQUIRE(val > 0);
   12342 
   12343 	zone->minrefresh = val;
   12344 }
   12345 
   12346 void
   12347 dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
   12348 	REQUIRE(DNS_ZONE_VALID(zone));
   12349 	REQUIRE(val > 0);
   12350 
   12351 	zone->maxrefresh = val;
   12352 }
   12353 
   12354 void
   12355 dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
   12356 	REQUIRE(DNS_ZONE_VALID(zone));
   12357 	REQUIRE(val > 0);
   12358 
   12359 	zone->minretry = val;
   12360 }
   12361 
   12362 void
   12363 dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
   12364 	REQUIRE(DNS_ZONE_VALID(zone));
   12365 	REQUIRE(val > 0);
   12366 
   12367 	zone->maxretry = val;
   12368 }
   12369 
   12370 uint32_t
   12371 dns_zone_getmaxrecords(dns_zone_t *zone) {
   12372 	REQUIRE(DNS_ZONE_VALID(zone));
   12373 
   12374 	return zone->maxrecords;
   12375 }
   12376 
   12377 void
   12378 dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
   12379 	REQUIRE(DNS_ZONE_VALID(zone));
   12380 
   12381 	zone->maxrecords = val;
   12382 }
   12383 
   12384 void
   12385 dns_zone_setmaxrrperset(dns_zone_t *zone, uint32_t val) {
   12386 	REQUIRE(DNS_ZONE_VALID(zone));
   12387 
   12388 	zone->maxrrperset = val;
   12389 	if (zone->db != NULL) {
   12390 		dns_db_setmaxrrperset(zone->db, val);
   12391 	}
   12392 }
   12393 
   12394 void
   12395 dns_zone_setmaxtypepername(dns_zone_t *zone, uint32_t val) {
   12396 	REQUIRE(DNS_ZONE_VALID(zone));
   12397 
   12398 	zone->maxtypepername = val;
   12399 	if (zone->db != NULL) {
   12400 		dns_db_setmaxtypepername(zone->db, val);
   12401 	}
   12402 }
   12403 
   12404 static bool
   12405 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
   12406 		isc_sockaddr_t *addr, dns_tsigkey_t *key,
   12407 		dns_transport_t *transport) {
   12408 	dns_notify_t *notify;
   12409 	dns_zonemgr_t *zmgr;
   12410 	isc_result_t result;
   12411 
   12412 	for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
   12413 	     notify = ISC_LIST_NEXT(notify, link))
   12414 	{
   12415 		if (notify->request != NULL) {
   12416 			continue;
   12417 		}
   12418 		if (name != NULL && dns_name_dynamic(&notify->ns) &&
   12419 		    dns_name_equal(name, &notify->ns))
   12420 		{
   12421 			goto requeue;
   12422 		}
   12423 		if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst) &&
   12424 		    notify->key == key && notify->transport == transport)
   12425 		{
   12426 			goto requeue;
   12427 		}
   12428 	}
   12429 	return false;
   12430 
   12431 requeue:
   12432 	/*
   12433 	 * If we are enqueued on the startup ratelimiter and this is
   12434 	 * not a startup notify, re-enqueue on the normal notify
   12435 	 * ratelimiter.
   12436 	 */
   12437 	if (notify->rlevent != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
   12438 	    (notify->flags & DNS_NOTIFY_STARTUP) != 0)
   12439 	{
   12440 		zmgr = notify->zone->zmgr;
   12441 		result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
   12442 						 &notify->rlevent);
   12443 		if (result != ISC_R_SUCCESS) {
   12444 			return true;
   12445 		}
   12446 
   12447 		notify->flags &= ~DNS_NOTIFY_STARTUP;
   12448 		result = isc_ratelimiter_enqueue(
   12449 			notify->zone->zmgr->notifyrl, notify->zone->loop,
   12450 			notify_send_toaddr, notify, &notify->rlevent);
   12451 		if (result != ISC_R_SUCCESS) {
   12452 			return false;
   12453 		}
   12454 	}
   12455 
   12456 	return true;
   12457 }
   12458 
   12459 static bool
   12460 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
   12461 	dns_tsigkey_t *key = NULL;
   12462 	isc_sockaddr_t src;
   12463 	isc_sockaddr_t any;
   12464 	bool isself;
   12465 	isc_netaddr_t dstaddr;
   12466 	isc_result_t result;
   12467 
   12468 	if (zone->view == NULL || zone->isself == NULL) {
   12469 		return false;
   12470 	}
   12471 
   12472 	switch (isc_sockaddr_pf(dst)) {
   12473 	case PF_INET:
   12474 		src = zone->notifysrc4;
   12475 		isc_sockaddr_any(&any);
   12476 		break;
   12477 	case PF_INET6:
   12478 		src = zone->notifysrc6;
   12479 		isc_sockaddr_any6(&any);
   12480 		break;
   12481 	default:
   12482 		return false;
   12483 	}
   12484 
   12485 	/*
   12486 	 * When sending from any the kernel will assign a source address
   12487 	 * that matches the destination address.
   12488 	 */
   12489 	if (isc_sockaddr_eqaddr(&any, &src)) {
   12490 		src = *dst;
   12491 	}
   12492 
   12493 	isc_netaddr_fromsockaddr(&dstaddr, dst);
   12494 	result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
   12495 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   12496 		return false;
   12497 	}
   12498 	isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
   12499 				zone->isselfarg);
   12500 	if (key != NULL) {
   12501 		dns_tsigkey_detach(&key);
   12502 	}
   12503 	return isself;
   12504 }
   12505 
   12506 static void
   12507 notify_destroy(dns_notify_t *notify, bool locked) {
   12508 	isc_mem_t *mctx;
   12509 
   12510 	REQUIRE(DNS_NOTIFY_VALID(notify));
   12511 
   12512 	if (notify->zone != NULL) {
   12513 		if (!locked) {
   12514 			LOCK_ZONE(notify->zone);
   12515 		}
   12516 		REQUIRE(LOCKED_ZONE(notify->zone));
   12517 		if (ISC_LINK_LINKED(notify, link)) {
   12518 			ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
   12519 		}
   12520 		if (!locked) {
   12521 			UNLOCK_ZONE(notify->zone);
   12522 		}
   12523 		if (locked) {
   12524 			zone_idetach(&notify->zone);
   12525 		} else {
   12526 			dns_zone_idetach(&notify->zone);
   12527 		}
   12528 	}
   12529 	if (notify->find != NULL) {
   12530 		dns_adb_destroyfind(&notify->find);
   12531 	}
   12532 	if (notify->request != NULL) {
   12533 		dns_request_destroy(&notify->request);
   12534 	}
   12535 	if (dns_name_dynamic(&notify->ns)) {
   12536 		dns_name_free(&notify->ns, notify->mctx);
   12537 	}
   12538 	if (notify->key != NULL) {
   12539 		dns_tsigkey_detach(&notify->key);
   12540 	}
   12541 	if (notify->transport != NULL) {
   12542 		dns_transport_detach(&notify->transport);
   12543 	}
   12544 	mctx = notify->mctx;
   12545 	isc_mem_put(notify->mctx, notify, sizeof(*notify));
   12546 	isc_mem_detach(&mctx);
   12547 }
   12548 
   12549 static isc_result_t
   12550 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
   12551 	dns_notify_t *notify;
   12552 
   12553 	REQUIRE(notifyp != NULL && *notifyp == NULL);
   12554 
   12555 	notify = isc_mem_get(mctx, sizeof(*notify));
   12556 	*notify = (dns_notify_t){
   12557 		.flags = flags,
   12558 	};
   12559 
   12560 	isc_mem_attach(mctx, &notify->mctx);
   12561 	isc_sockaddr_any(&notify->src);
   12562 	isc_sockaddr_any(&notify->dst);
   12563 	dns_name_init(&notify->ns, NULL);
   12564 	ISC_LINK_INIT(notify, link);
   12565 	notify->magic = NOTIFY_MAGIC;
   12566 	*notifyp = notify;
   12567 	return ISC_R_SUCCESS;
   12568 }
   12569 
   12570 /*
   12571  * XXXAG should check for DNS_ZONEFLG_EXITING
   12572  */
   12573 static void
   12574 process_notify_adb_event(void *arg) {
   12575 	dns_adbfind_t *find = (dns_adbfind_t *)arg;
   12576 	dns_notify_t *notify = (dns_notify_t *)find->cbarg;
   12577 	dns_adbstatus_t astat = find->status;
   12578 
   12579 	REQUIRE(DNS_NOTIFY_VALID(notify));
   12580 	REQUIRE(find == notify->find);
   12581 
   12582 	switch (astat) {
   12583 	case DNS_ADB_MOREADDRESSES:
   12584 		dns_adb_destroyfind(&notify->find);
   12585 		notify_find_address(notify);
   12586 		return;
   12587 
   12588 	case DNS_ADB_NOMOREADDRESSES:
   12589 		LOCK_ZONE(notify->zone);
   12590 		notify_send(notify);
   12591 		UNLOCK_ZONE(notify->zone);
   12592 		break;
   12593 
   12594 	default:
   12595 		break;
   12596 	}
   12597 
   12598 	notify_destroy(notify, false);
   12599 }
   12600 
   12601 static void
   12602 notify_find_address(dns_notify_t *notify) {
   12603 	isc_result_t result;
   12604 	unsigned int options;
   12605 	dns_adb_t *adb = NULL;
   12606 
   12607 	REQUIRE(DNS_NOTIFY_VALID(notify));
   12608 
   12609 	options = DNS_ADBFIND_WANTEVENT;
   12610 	if (isc_net_probeipv4() != ISC_R_DISABLED) {
   12611 		options |= DNS_ADBFIND_INET;
   12612 	}
   12613 	if (isc_net_probeipv6() != ISC_R_DISABLED) {
   12614 		options |= DNS_ADBFIND_INET6;
   12615 	}
   12616 
   12617 	dns_view_getadb(notify->zone->view, &adb);
   12618 	if (adb == NULL) {
   12619 		goto destroy;
   12620 	}
   12621 
   12622 	result = dns_adb_createfind(adb, notify->zone->loop,
   12623 				    process_notify_adb_event, notify,
   12624 				    &notify->ns, dns_rootname, 0, options, 0,
   12625 				    NULL, notify->zone->view->dstport, 0, NULL,
   12626 				    NULL, NULL, &notify->find);
   12627 	dns_adb_detach(&adb);
   12628 
   12629 	/* Something failed? */
   12630 	if (result != ISC_R_SUCCESS) {
   12631 		goto destroy;
   12632 	}
   12633 
   12634 	/* More addresses pending? */
   12635 	if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
   12636 		return;
   12637 	}
   12638 
   12639 	/* We have as many addresses as we can get. */
   12640 	LOCK_ZONE(notify->zone);
   12641 	notify_send(notify);
   12642 	UNLOCK_ZONE(notify->zone);
   12643 
   12644 destroy:
   12645 	notify_destroy(notify, false);
   12646 }
   12647 
   12648 static isc_result_t
   12649 notify_send_queue(dns_notify_t *notify, bool startup) {
   12650 	return isc_ratelimiter_enqueue(
   12651 		startup ? notify->zone->zmgr->startupnotifyrl
   12652 			: notify->zone->zmgr->notifyrl,
   12653 		notify->zone->loop, notify_send_toaddr, notify,
   12654 		&notify->rlevent);
   12655 }
   12656 
   12657 static void
   12658 notify_send_toaddr(void *arg) {
   12659 	dns_notify_t *notify = (dns_notify_t *)arg;
   12660 	isc_result_t result;
   12661 	dns_message_t *message = NULL;
   12662 	isc_netaddr_t dstip;
   12663 	dns_tsigkey_t *key = NULL;
   12664 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   12665 	isc_sockaddr_t src;
   12666 	unsigned int options, timeout, udptimeout;
   12667 	bool have_notifysource = false;
   12668 	isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
   12669 
   12670 	REQUIRE(DNS_NOTIFY_VALID(notify));
   12671 
   12672 	LOCK_ZONE(notify->zone);
   12673 
   12674 	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
   12675 
   12676 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0 ||
   12677 	    notify->rlevent->canceled ||
   12678 	    DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
   12679 	    notify->zone->view->requestmgr == NULL || notify->zone->db == NULL)
   12680 	{
   12681 		result = ISC_R_CANCELED;
   12682 		goto cleanup;
   12683 	}
   12684 
   12685 	/*
   12686 	 * The raw IPv4 address should also exist.  Don't send to the
   12687 	 * mapped form.
   12688 	 */
   12689 	if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
   12690 	    IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr))
   12691 	{
   12692 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
   12693 			   "notify: ignoring IPv6 mapped IPV4 address: %s",
   12694 			   addrbuf);
   12695 		result = ISC_R_CANCELED;
   12696 		goto cleanup;
   12697 	}
   12698 
   12699 	result = notify_createmessage(notify->zone, notify->flags, &message);
   12700 	if (result != ISC_R_SUCCESS) {
   12701 		goto cleanup;
   12702 	}
   12703 
   12704 	if (notify->key != NULL) {
   12705 		/* Transfer ownership of key */
   12706 		key = notify->key;
   12707 		notify->key = NULL;
   12708 	} else {
   12709 		isc_netaddr_fromsockaddr(&dstip, &notify->dst);
   12710 		result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
   12711 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   12712 			notify_log(notify->zone, ISC_LOG_ERROR,
   12713 				   "NOTIFY to %s not sent. "
   12714 				   "Peer TSIG key lookup failure.",
   12715 				   addrbuf);
   12716 			goto cleanup_message;
   12717 		}
   12718 	}
   12719 
   12720 	if (key != NULL) {
   12721 		char namebuf[DNS_NAME_FORMATSIZE];
   12722 
   12723 		dns_name_format(key->name, namebuf, sizeof(namebuf));
   12724 		notify_log(notify->zone, ISC_LOG_INFO,
   12725 			   "sending notify to %s : TSIG (%s)", addrbuf,
   12726 			   namebuf);
   12727 	} else {
   12728 		notify_log(notify->zone, ISC_LOG_INFO, "sending notify to %s",
   12729 			   addrbuf);
   12730 	}
   12731 	options = 0;
   12732 	if (notify->zone->view->peers != NULL) {
   12733 		dns_peer_t *peer = NULL;
   12734 		bool usetcp = false;
   12735 		result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
   12736 						 &dstip, &peer);
   12737 		if (result == ISC_R_SUCCESS) {
   12738 			result = dns_peer_getnotifysource(peer, &src);
   12739 			if (result == ISC_R_SUCCESS) {
   12740 				have_notifysource = true;
   12741 			}
   12742 			result = dns_peer_getforcetcp(peer, &usetcp);
   12743 			if (result == ISC_R_SUCCESS && usetcp) {
   12744 				options |= DNS_FETCHOPT_TCP;
   12745 			}
   12746 		}
   12747 	}
   12748 	switch (isc_sockaddr_pf(&notify->dst)) {
   12749 	case PF_INET:
   12750 		if (!have_notifysource) {
   12751 			isc_sockaddr_t any;
   12752 			isc_sockaddr_any(&any);
   12753 
   12754 			src = notify->src;
   12755 			if (isc_sockaddr_equal(&src, &any)) {
   12756 				src = notify->zone->notifysrc4;
   12757 			}
   12758 		}
   12759 		break;
   12760 	case PF_INET6:
   12761 		if (!have_notifysource) {
   12762 			isc_sockaddr_t any;
   12763 			isc_sockaddr_any6(&any);
   12764 
   12765 			src = notify->src;
   12766 			if (isc_sockaddr_equal(&src, &any)) {
   12767 				src = notify->zone->notifysrc6;
   12768 			}
   12769 		}
   12770 		break;
   12771 	default:
   12772 		result = ISC_R_NOTIMPLEMENTED;
   12773 		goto cleanup_key;
   12774 	}
   12775 	udptimeout = 5;
   12776 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY)) {
   12777 		udptimeout = 30;
   12778 	}
   12779 	timeout = 3 * udptimeout + 1;
   12780 again:
   12781 	if ((notify->flags & DNS_NOTIFY_TCP) != 0) {
   12782 		options |= DNS_REQUESTOPT_TCP;
   12783 		udptimeout = 0;
   12784 		timeout = 15;
   12785 	}
   12786 
   12787 	zmgr_tlsctx_attach(notify->zone->zmgr, &zmgr_tlsctx_cache);
   12788 
   12789 	result = dns_request_create(notify->zone->view->requestmgr, message,
   12790 				    &src, &notify->dst, notify->transport,
   12791 				    zmgr_tlsctx_cache, options, key, timeout,
   12792 				    udptimeout, 2, notify->zone->loop,
   12793 				    notify_done, notify, &notify->request);
   12794 
   12795 	isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
   12796 
   12797 	switch (result) {
   12798 	case ISC_R_SUCCESS:
   12799 		if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
   12800 			inc_stats(notify->zone,
   12801 				  dns_zonestatscounter_notifyoutv4);
   12802 		} else {
   12803 			inc_stats(notify->zone,
   12804 				  dns_zonestatscounter_notifyoutv6);
   12805 		}
   12806 		break;
   12807 	case ISC_R_SHUTTINGDOWN:
   12808 	case ISC_R_CANCELED:
   12809 	case ISC_R_ADDRNOTAVAIL:
   12810 	case DNS_R_BLACKHOLED:
   12811 	case ISC_R_FAMILYNOSUPPORT:
   12812 		notify_log(notify->zone, ISC_LOG_NOTICE,
   12813 			   "notify to %s failed: %s", addrbuf,
   12814 			   isc_result_totext(result));
   12815 		break;
   12816 	default:
   12817 		if ((notify->flags & DNS_NOTIFY_TCP) == 0) {
   12818 			notify_log(notify->zone, ISC_LOG_NOTICE,
   12819 				   "notify to %s failed: %s: retrying over TCP",
   12820 				   addrbuf, isc_result_totext(result));
   12821 			notify->flags |= DNS_NOTIFY_TCP;
   12822 			goto again;
   12823 		}
   12824 	}
   12825 
   12826 cleanup_key:
   12827 	if (key != NULL) {
   12828 		dns_tsigkey_detach(&key);
   12829 	}
   12830 cleanup_message:
   12831 	dns_message_detach(&message);
   12832 cleanup:
   12833 	UNLOCK_ZONE(notify->zone);
   12834 	if (notify->rlevent != NULL) {
   12835 		isc_rlevent_free(&notify->rlevent);
   12836 	}
   12837 
   12838 	if (result != ISC_R_SUCCESS) {
   12839 		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
   12840 		notify_log(notify->zone, ISC_LOG_WARNING,
   12841 			   "notify to %s failed: %s", addrbuf,
   12842 			   isc_result_totext(result));
   12843 		notify_destroy(notify, false);
   12844 	}
   12845 }
   12846 
   12847 static void
   12848 notify_send(dns_notify_t *notify) {
   12849 	dns_adbaddrinfo_t *ai;
   12850 	isc_sockaddr_t dst;
   12851 	isc_result_t result;
   12852 	dns_notify_t *newnotify = NULL;
   12853 	unsigned int flags;
   12854 	bool startup;
   12855 
   12856 	/*
   12857 	 * Zone lock held by caller.
   12858 	 */
   12859 	REQUIRE(DNS_NOTIFY_VALID(notify));
   12860 	REQUIRE(LOCKED_ZONE(notify->zone));
   12861 
   12862 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING)) {
   12863 		return;
   12864 	}
   12865 
   12866 	for (ai = ISC_LIST_HEAD(notify->find->list); ai != NULL;
   12867 	     ai = ISC_LIST_NEXT(ai, publink))
   12868 	{
   12869 		dst = ai->sockaddr;
   12870 		if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
   12871 				    NULL, NULL))
   12872 		{
   12873 			continue;
   12874 		}
   12875 		if (notify_isself(notify->zone, &dst)) {
   12876 			continue;
   12877 		}
   12878 		newnotify = NULL;
   12879 		flags = notify->flags & DNS_NOTIFY_NOSOA;
   12880 		result = notify_create(notify->mctx, flags, &newnotify);
   12881 		if (result != ISC_R_SUCCESS) {
   12882 			goto cleanup;
   12883 		}
   12884 		zone_iattach(notify->zone, &newnotify->zone);
   12885 		ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
   12886 		newnotify->dst = dst;
   12887 		if (isc_sockaddr_pf(&dst) == AF_INET6) {
   12888 			isc_sockaddr_any6(&newnotify->src);
   12889 		}
   12890 		startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
   12891 		result = notify_send_queue(newnotify, startup);
   12892 		if (result != ISC_R_SUCCESS) {
   12893 			goto cleanup;
   12894 		}
   12895 		newnotify = NULL;
   12896 	}
   12897 
   12898 cleanup:
   12899 	if (newnotify != NULL) {
   12900 		notify_destroy(newnotify, true);
   12901 	}
   12902 }
   12903 
   12904 void
   12905 dns_zone_notify(dns_zone_t *zone, bool nodefer) {
   12906 	isc_time_t now;
   12907 
   12908 	REQUIRE(DNS_ZONE_VALID(zone));
   12909 
   12910 	LOCK_ZONE(zone);
   12911 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   12912 	if (nodefer) {
   12913 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED)) {
   12914 			/*
   12915 			 * We have previously deferred the notify, but we have a
   12916 			 * new request not to defer it. Reverse the deferring
   12917 			 * operation.
   12918 			 */
   12919 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED);
   12920 			DNS_ZONE_TIME_SUBTRACT(&zone->notifytime,
   12921 					       zone->notifydefer,
   12922 					       &zone->notifytime);
   12923 		}
   12924 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOTIFYNODEFER);
   12925 	}
   12926 	now = isc_time_now();
   12927 	zone_settimer(zone, &now);
   12928 	UNLOCK_ZONE(zone);
   12929 }
   12930 
   12931 static void
   12932 zone_notify(dns_zone_t *zone, isc_time_t *now) {
   12933 	dns_dbnode_t *node = NULL;
   12934 	dns_db_t *zonedb = NULL;
   12935 	dns_dbversion_t *version = NULL;
   12936 	dns_name_t *origin = NULL;
   12937 	dns_name_t primary;
   12938 	dns_rdata_ns_t ns;
   12939 	dns_rdata_soa_t soa;
   12940 	uint32_t serial;
   12941 	dns_rdata_t rdata = DNS_RDATA_INIT;
   12942 	dns_rdataset_t nsrdset;
   12943 	dns_rdataset_t soardset;
   12944 	isc_result_t result;
   12945 	isc_sockaddr_t src;
   12946 	isc_sockaddr_t dst;
   12947 	bool isqueued;
   12948 	dns_notifytype_t notifytype;
   12949 	unsigned int flags = 0;
   12950 	bool loggednotify = false;
   12951 	bool startup;
   12952 
   12953 	REQUIRE(DNS_ZONE_VALID(zone));
   12954 
   12955 	LOCK_ZONE(zone);
   12956 	startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   12957 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY |
   12958 				       DNS_ZONEFLG_NEEDSTARTUPNOTIFY |
   12959 				       DNS_ZONEFLG_NOTIFYNODEFER |
   12960 				       DNS_ZONEFLG_NOTIFYDEFERRED);
   12961 	notifytype = zone->notifytype;
   12962 	DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
   12963 	UNLOCK_ZONE(zone);
   12964 
   12965 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
   12966 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   12967 	{
   12968 		return;
   12969 	}
   12970 
   12971 	if (notifytype == dns_notifytype_no) {
   12972 		return;
   12973 	}
   12974 
   12975 	if (notifytype == dns_notifytype_masteronly &&
   12976 	    zone->type != dns_zone_primary)
   12977 	{
   12978 		return;
   12979 	}
   12980 
   12981 	origin = &zone->origin;
   12982 
   12983 	/*
   12984 	 * If the zone is dialup we are done as we don't want to send
   12985 	 * the current soa so as to force a refresh query.
   12986 	 */
   12987 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
   12988 		flags |= DNS_NOTIFY_NOSOA;
   12989 	}
   12990 
   12991 	/*
   12992 	 * Record that this was a notify due to starting up.
   12993 	 */
   12994 	if (startup) {
   12995 		flags |= DNS_NOTIFY_STARTUP;
   12996 	}
   12997 
   12998 	/*
   12999 	 * Get SOA RRset.
   13000 	 */
   13001 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   13002 	if (zone->db != NULL) {
   13003 		dns_db_attach(zone->db, &zonedb);
   13004 	}
   13005 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   13006 	if (zonedb == NULL) {
   13007 		return;
   13008 	}
   13009 	dns_db_currentversion(zonedb, &version);
   13010 	result = dns_db_findnode(zonedb, origin, false, &node);
   13011 	if (result != ISC_R_SUCCESS) {
   13012 		goto cleanup1;
   13013 	}
   13014 
   13015 	dns_rdataset_init(&soardset);
   13016 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
   13017 				     dns_rdatatype_none, 0, &soardset, NULL);
   13018 	if (result != ISC_R_SUCCESS) {
   13019 		goto cleanup2;
   13020 	}
   13021 
   13022 	/*
   13023 	 * Find serial and primary server's name.
   13024 	 */
   13025 	dns_name_init(&primary, NULL);
   13026 	result = dns_rdataset_first(&soardset);
   13027 	if (result != ISC_R_SUCCESS) {
   13028 		goto cleanup3;
   13029 	}
   13030 	dns_rdataset_current(&soardset, &rdata);
   13031 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   13032 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   13033 	dns_rdata_reset(&rdata);
   13034 	dns_name_dup(&soa.origin, zone->mctx, &primary);
   13035 	serial = soa.serial;
   13036 	dns_rdataset_disassociate(&soardset);
   13037 
   13038 	/*
   13039 	 * Enqueue notify requests for 'also-notify' servers.
   13040 	 */
   13041 	LOCK_ZONE(zone);
   13042 
   13043 	dns_remote_reset(&zone->notify, false);
   13044 	while (!dns_remote_done(&zone->notify)) {
   13045 		dns_tsigkey_t *key = NULL;
   13046 		dns_transport_t *transport = NULL;
   13047 		dns_notify_t *notify = NULL;
   13048 		dns_view_t *view = dns_zone_getview(zone);
   13049 
   13050 		if (dns_remote_keyname(&zone->notify) != NULL) {
   13051 			dns_name_t *keyname = dns_remote_keyname(&zone->notify);
   13052 			(void)dns_view_gettsig(view, keyname, &key);
   13053 		}
   13054 
   13055 		if (dns_remote_tlsname(&zone->notify) != NULL) {
   13056 			dns_name_t *tlsname = dns_remote_tlsname(&zone->notify);
   13057 			result = dns_view_gettransport(view, DNS_TRANSPORT_TLS,
   13058 						       tlsname, &transport);
   13059 
   13060 			if (result == ISC_R_SUCCESS) {
   13061 				notify_log(
   13062 					zone, ISC_LOG_INFO,
   13063 					"got TLS configuration for a notify");
   13064 			} else {
   13065 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   13066 					      ISC_LOG_ERROR,
   13067 					      "could not get TLS configuration "
   13068 					      "for zone transfer: %s",
   13069 					      isc_result_totext(result));
   13070 				if (key != NULL) {
   13071 					dns_tsigkey_detach(&key);
   13072 				}
   13073 				goto next;
   13074 			}
   13075 
   13076 			flags |= DNS_NOTIFY_TCP;
   13077 		}
   13078 
   13079 		/* TODO: glue the transport to the notify */
   13080 
   13081 		dst = dns_remote_curraddr(&zone->notify);
   13082 		src = dns_remote_sourceaddr(&zone->notify);
   13083 		INSIST(isc_sockaddr_pf(&src) == isc_sockaddr_pf(&dst));
   13084 
   13085 		if (isc_sockaddr_disabled(&dst)) {
   13086 			if (key != NULL) {
   13087 				dns_tsigkey_detach(&key);
   13088 			}
   13089 			if (transport != NULL) {
   13090 				dns_transport_detach(&transport);
   13091 			}
   13092 			goto next;
   13093 		}
   13094 
   13095 		if (notify_isqueued(zone, flags, NULL, &dst, key, transport)) {
   13096 			if (key != NULL) {
   13097 				dns_tsigkey_detach(&key);
   13098 			}
   13099 			if (transport != NULL) {
   13100 				dns_transport_detach(&transport);
   13101 			}
   13102 			goto next;
   13103 		}
   13104 
   13105 		result = notify_create(zone->mctx, flags, &notify);
   13106 		if (result != ISC_R_SUCCESS) {
   13107 			if (key != NULL) {
   13108 				dns_tsigkey_detach(&key);
   13109 			}
   13110 			if (transport != NULL) {
   13111 				dns_transport_detach(&transport);
   13112 			}
   13113 			goto next;
   13114 		}
   13115 
   13116 		zone_iattach(zone, &notify->zone);
   13117 		notify->src = src;
   13118 		notify->dst = dst;
   13119 
   13120 		INSIST(notify->key == NULL);
   13121 
   13122 		if (key != NULL) {
   13123 			notify->key = key;
   13124 			key = NULL;
   13125 		}
   13126 
   13127 		INSIST(notify->transport == NULL);
   13128 		if (transport != NULL) {
   13129 			notify->transport = transport;
   13130 			transport = NULL;
   13131 		}
   13132 
   13133 		ISC_LIST_APPEND(zone->notifies, notify, link);
   13134 		result = notify_send_queue(notify, startup);
   13135 		if (result != ISC_R_SUCCESS) {
   13136 			notify_destroy(notify, true);
   13137 		}
   13138 		if (!loggednotify) {
   13139 			notify_log(zone, ISC_LOG_INFO,
   13140 				   "sending notifies (serial %u)", serial);
   13141 			loggednotify = true;
   13142 		}
   13143 	next:
   13144 		flags &= ~DNS_NOTIFY_TCP;
   13145 		dns_remote_next(&zone->notify, false);
   13146 	}
   13147 	UNLOCK_ZONE(zone);
   13148 
   13149 	if (notifytype == dns_notifytype_explicit) {
   13150 		goto cleanup3;
   13151 	}
   13152 
   13153 	/*
   13154 	 * Process NS RRset to generate notifies.
   13155 	 */
   13156 
   13157 	dns_rdataset_init(&nsrdset);
   13158 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
   13159 				     dns_rdatatype_none, 0, &nsrdset, NULL);
   13160 	if (result != ISC_R_SUCCESS) {
   13161 		goto cleanup3;
   13162 	}
   13163 
   13164 	result = dns_rdataset_first(&nsrdset);
   13165 	while (result == ISC_R_SUCCESS) {
   13166 		dns_notify_t *notify = NULL;
   13167 
   13168 		dns_rdataset_current(&nsrdset, &rdata);
   13169 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
   13170 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   13171 		dns_rdata_reset(&rdata);
   13172 		/*
   13173 		 * Don't notify the primary server unless explicitly
   13174 		 * configured to do so.
   13175 		 */
   13176 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
   13177 		    dns_name_compare(&primary, &ns.name) == 0)
   13178 		{
   13179 			result = dns_rdataset_next(&nsrdset);
   13180 			continue;
   13181 		}
   13182 
   13183 		if (!loggednotify) {
   13184 			notify_log(zone, ISC_LOG_INFO,
   13185 				   "sending notifies (serial %u)", serial);
   13186 			loggednotify = true;
   13187 		}
   13188 
   13189 		LOCK_ZONE(zone);
   13190 		isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL,
   13191 					   NULL);
   13192 		UNLOCK_ZONE(zone);
   13193 		if (isqueued) {
   13194 			result = dns_rdataset_next(&nsrdset);
   13195 			continue;
   13196 		}
   13197 		result = notify_create(zone->mctx, flags, &notify);
   13198 		if (result != ISC_R_SUCCESS) {
   13199 			continue;
   13200 		}
   13201 		dns_zone_iattach(zone, &notify->zone);
   13202 		dns_name_dup(&ns.name, zone->mctx, &notify->ns);
   13203 		LOCK_ZONE(zone);
   13204 		ISC_LIST_APPEND(zone->notifies, notify, link);
   13205 		UNLOCK_ZONE(zone);
   13206 		notify_find_address(notify);
   13207 		result = dns_rdataset_next(&nsrdset);
   13208 	}
   13209 	dns_rdataset_disassociate(&nsrdset);
   13210 
   13211 cleanup3:
   13212 	if (dns_name_dynamic(&primary)) {
   13213 		dns_name_free(&primary, zone->mctx);
   13214 	}
   13215 cleanup2:
   13216 	dns_db_detachnode(zonedb, &node);
   13217 cleanup1:
   13218 	dns_db_closeversion(zonedb, &version, false);
   13219 	dns_db_detach(&zonedb);
   13220 }
   13221 
   13222 /***
   13223  *** Private
   13224  ***/
   13225 static void
   13226 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, dns_name_t *name,
   13227 	     dns_message_t **messagep) {
   13228 	dns_message_t *message = NULL;
   13229 	dns_name_t *qname = NULL;
   13230 	dns_rdataset_t *qrdataset = NULL;
   13231 
   13232 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER,
   13233 			   &message);
   13234 
   13235 	message->opcode = dns_opcode_query;
   13236 	message->rdclass = zone->rdclass;
   13237 
   13238 	dns_message_gettempname(message, &qname);
   13239 
   13240 	dns_message_gettemprdataset(message, &qrdataset);
   13241 
   13242 	/*
   13243 	 * Make question.
   13244 	 */
   13245 	dns_name_clone(name, qname);
   13246 	dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
   13247 	ISC_LIST_APPEND(qname->list, qrdataset, link);
   13248 	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
   13249 
   13250 	*messagep = message;
   13251 }
   13252 
   13253 static isc_result_t
   13254 add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
   13255 	bool reqexpire) {
   13256 	isc_result_t result;
   13257 	dns_rdataset_t *rdataset = NULL;
   13258 	dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
   13259 	int count = 0;
   13260 
   13261 	/* Set EDNS options if applicable. */
   13262 	if (reqnsid) {
   13263 		INSIST(count < DNS_EDNSOPTIONS);
   13264 		ednsopts[count].code = DNS_OPT_NSID;
   13265 		ednsopts[count].length = 0;
   13266 		ednsopts[count].value = NULL;
   13267 		count++;
   13268 	}
   13269 	if (reqexpire) {
   13270 		INSIST(count < DNS_EDNSOPTIONS);
   13271 		ednsopts[count].code = DNS_OPT_EXPIRE;
   13272 		ednsopts[count].length = 0;
   13273 		ednsopts[count].value = NULL;
   13274 		count++;
   13275 	}
   13276 	result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
   13277 				      ednsopts, count);
   13278 	if (result != ISC_R_SUCCESS) {
   13279 		return result;
   13280 	}
   13281 
   13282 	return dns_message_setopt(message, rdataset);
   13283 }
   13284 
   13285 /*
   13286  * Called when stub zone update is finished.
   13287  * Update zone refresh, retry, expire values accordingly with
   13288  * SOA received from primary, sync database to file, restart
   13289  * zone management timer.
   13290  */
   13291 static void
   13292 stub_finish_zone_update(dns_stub_t *stub, isc_time_t now) {
   13293 	uint32_t refresh, retry, expire;
   13294 	isc_result_t result;
   13295 	isc_interval_t i;
   13296 	unsigned int soacount;
   13297 	dns_zone_t *zone = stub->zone;
   13298 
   13299 	/*
   13300 	 * Tidy up.
   13301 	 */
   13302 	dns_db_closeversion(stub->db, &stub->version, true);
   13303 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   13304 	if (zone->db == NULL) {
   13305 		zone_attachdb(zone, stub->db);
   13306 	}
   13307 	result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL, NULL,
   13308 				  &refresh, &retry, &expire, NULL, NULL);
   13309 	if (result == ISC_R_SUCCESS && soacount > 0U) {
   13310 		zone->refresh = RANGE(refresh, zone->minrefresh,
   13311 				      zone->maxrefresh);
   13312 		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
   13313 		zone->expire = RANGE(expire, zone->refresh + zone->retry,
   13314 				     DNS_MAX_EXPIRE);
   13315 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   13316 	}
   13317 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   13318 	dns_db_detach(&stub->db);
   13319 
   13320 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   13321 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   13322 	DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
   13323 	isc_interval_set(&i, zone->expire, 0);
   13324 	DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
   13325 
   13326 	if (zone->masterfile != NULL) {
   13327 		zone_needdump(zone, 0);
   13328 	}
   13329 
   13330 	zone_settimer(zone, &now);
   13331 }
   13332 
   13333 /*
   13334  * Process answers for A and AAAA queries when
   13335  * resolving nameserver addresses for which glue
   13336  * was missing in a previous answer for a NS query.
   13337  */
   13338 static void
   13339 stub_glue_response(void *arg) {
   13340 	dns_request_t *request = (dns_request_t *)arg;
   13341 	struct stub_glue_request *sgr = dns_request_getarg(request);
   13342 	struct stub_cb_args *cb_args = sgr->args;
   13343 	dns_stub_t *stub = cb_args->stub;
   13344 	dns_message_t *msg = NULL;
   13345 	dns_zone_t *zone = NULL;
   13346 	char primary[ISC_SOCKADDR_FORMATSIZE];
   13347 	char source[ISC_SOCKADDR_FORMATSIZE];
   13348 	uint32_t addr_count, cnamecnt;
   13349 	isc_result_t result;
   13350 	isc_sockaddr_t curraddr;
   13351 	isc_time_t now;
   13352 	dns_rdataset_t *addr_rdataset = NULL;
   13353 	dns_dbnode_t *node = NULL;
   13354 
   13355 	INSIST(DNS_STUB_VALID(stub));
   13356 
   13357 	zone = stub->zone;
   13358 
   13359 	ENTER;
   13360 
   13361 	now = isc_time_now();
   13362 
   13363 	LOCK_ZONE(zone);
   13364 
   13365 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   13366 		zone_debuglog(zone, __func__, 1, "exiting");
   13367 		goto cleanup;
   13368 	}
   13369 
   13370 	curraddr = dns_remote_curraddr(&zone->primaries);
   13371 	isc_sockaddr_format(&curraddr, primary, sizeof(primary));
   13372 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   13373 
   13374 	if (dns_request_getresult(request) != ISC_R_SUCCESS) {
   13375 		dns_zonemgr_unreachableadd(zone->zmgr, &curraddr,
   13376 					   &zone->sourceaddr, &now);
   13377 		dns_zone_log(zone, ISC_LOG_INFO,
   13378 			     "could not refresh stub from primary %s"
   13379 			     " (source %s): %s",
   13380 			     primary, source,
   13381 			     isc_result_totext(dns_request_getresult(request)));
   13382 		goto cleanup;
   13383 	}
   13384 
   13385 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
   13386 			   &msg);
   13387 	result = dns_request_getresponse(request, msg, 0);
   13388 	if (result != ISC_R_SUCCESS) {
   13389 		dns_zone_log(zone, ISC_LOG_INFO,
   13390 			     "refreshing stub: unable to parse response (%s)",
   13391 			     isc_result_totext(result));
   13392 		goto cleanup;
   13393 	}
   13394 
   13395 	/*
   13396 	 * Unexpected opcode.
   13397 	 */
   13398 	if (msg->opcode != dns_opcode_query) {
   13399 		char opcode[128];
   13400 		isc_buffer_t rb;
   13401 
   13402 		isc_buffer_init(&rb, opcode, sizeof(opcode));
   13403 		(void)dns_opcode_totext(msg->opcode, &rb);
   13404 
   13405 		dns_zone_log(zone, ISC_LOG_INFO,
   13406 			     "refreshing stub: "
   13407 			     "unexpected opcode (%.*s) from %s (source %s)",
   13408 			     (int)rb.used, opcode, primary, source);
   13409 		goto cleanup;
   13410 	}
   13411 
   13412 	/*
   13413 	 * Unexpected rcode.
   13414 	 */
   13415 	if (msg->rcode != dns_rcode_noerror) {
   13416 		char rcode[128];
   13417 		isc_buffer_t rb;
   13418 
   13419 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   13420 		(void)dns_rcode_totext(msg->rcode, &rb);
   13421 
   13422 		dns_zone_log(zone, ISC_LOG_INFO,
   13423 			     "refreshing stub: "
   13424 			     "unexpected rcode (%.*s) from %s (source %s)",
   13425 			     (int)rb.used, rcode, primary, source);
   13426 		goto cleanup;
   13427 	}
   13428 
   13429 	/*
   13430 	 * We need complete messages.
   13431 	 */
   13432 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
   13433 		if (dns_request_usedtcp(request)) {
   13434 			dns_zone_log(zone, ISC_LOG_INFO,
   13435 				     "refreshing stub: truncated TCP "
   13436 				     "response from primary %s (source %s)",
   13437 				     primary, source);
   13438 		}
   13439 		goto cleanup;
   13440 	}
   13441 
   13442 	/*
   13443 	 * If non-auth log.
   13444 	 */
   13445 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
   13446 		dns_zone_log(zone, ISC_LOG_INFO,
   13447 			     "refreshing stub: "
   13448 			     "non-authoritative answer from "
   13449 			     "primary %s (source %s)",
   13450 			     primary, source);
   13451 		goto cleanup;
   13452 	}
   13453 
   13454 	/*
   13455 	 * Sanity checks.
   13456 	 */
   13457 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
   13458 	addr_count = message_count(msg, DNS_SECTION_ANSWER,
   13459 				   sgr->ipv4 ? dns_rdatatype_a
   13460 					     : dns_rdatatype_aaaa);
   13461 
   13462 	if (cnamecnt != 0) {
   13463 		dns_zone_log(zone, ISC_LOG_INFO,
   13464 			     "refreshing stub: unexpected CNAME response "
   13465 			     "from primary %s (source %s)",
   13466 			     primary, source);
   13467 		goto cleanup;
   13468 	}
   13469 
   13470 	if (addr_count == 0) {
   13471 		dns_zone_log(zone, ISC_LOG_INFO,
   13472 			     "refreshing stub: no %s records in response "
   13473 			     "from primary %s (source %s)",
   13474 			     sgr->ipv4 ? "A" : "AAAA", primary, source);
   13475 		goto cleanup;
   13476 	}
   13477 	/*
   13478 	 * Extract A or AAAA RRset from message.
   13479 	 */
   13480 	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &sgr->name,
   13481 				      sgr->ipv4 ? dns_rdatatype_a
   13482 						: dns_rdatatype_aaaa,
   13483 				      dns_rdatatype_none, NULL, &addr_rdataset);
   13484 	if (result != ISC_R_SUCCESS) {
   13485 		if (result != DNS_R_NXDOMAIN && result != DNS_R_NXRRSET) {
   13486 			char namebuf[DNS_NAME_FORMATSIZE];
   13487 			dns_name_format(&sgr->name, namebuf, sizeof(namebuf));
   13488 			dns_zone_log(
   13489 				zone, ISC_LOG_INFO,
   13490 				"refreshing stub: dns_message_findname(%s/%s) "
   13491 				"failed (%s)",
   13492 				namebuf, sgr->ipv4 ? "A" : "AAAA",
   13493 				isc_result_totext(result));
   13494 		}
   13495 		goto cleanup;
   13496 	}
   13497 
   13498 	result = dns_db_findnode(stub->db, &sgr->name, true, &node);
   13499 	if (result != ISC_R_SUCCESS) {
   13500 		dns_zone_log(zone, ISC_LOG_INFO,
   13501 			     "refreshing stub: "
   13502 			     "dns_db_findnode() failed: %s",
   13503 			     isc_result_totext(result));
   13504 		goto cleanup;
   13505 	}
   13506 
   13507 	result = dns_db_addrdataset(stub->db, node, stub->version, 0,
   13508 				    addr_rdataset, 0, NULL);
   13509 	if (result != ISC_R_SUCCESS) {
   13510 		dns_zone_log(zone, ISC_LOG_INFO,
   13511 			     "refreshing stub: "
   13512 			     "dns_db_addrdataset() failed: %s",
   13513 			     isc_result_totext(result));
   13514 	}
   13515 	dns_db_detachnode(stub->db, &node);
   13516 
   13517 cleanup:
   13518 	if (msg != NULL) {
   13519 		dns_message_detach(&msg);
   13520 	}
   13521 
   13522 	dns_name_free(&sgr->name, zone->mctx);
   13523 	dns_request_destroy(&sgr->request);
   13524 	isc_mem_put(zone->mctx, sgr, sizeof(*sgr));
   13525 
   13526 	/* If last request, release all related resources */
   13527 	if (atomic_fetch_sub_release(&stub->pending_requests, 1) == 1) {
   13528 		isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
   13529 		stub_finish_zone_update(stub, now);
   13530 		UNLOCK_ZONE(zone);
   13531 		stub->magic = 0;
   13532 		dns_zone_idetach(&stub->zone);
   13533 		INSIST(stub->db == NULL);
   13534 		INSIST(stub->version == NULL);
   13535 		isc_mem_put(stub->mctx, stub, sizeof(*stub));
   13536 	} else {
   13537 		UNLOCK_ZONE(zone);
   13538 	}
   13539 }
   13540 
   13541 /*
   13542  * Create and send an A or AAAA query to the primary
   13543  * server of the stub zone given.
   13544  */
   13545 static isc_result_t
   13546 stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4,
   13547 				const dns_name_t *name) {
   13548 	dns_message_t *message = NULL;
   13549 	dns_zone_t *zone;
   13550 	isc_result_t result;
   13551 	struct stub_glue_request *sgr;
   13552 	isc_sockaddr_t curraddr;
   13553 
   13554 	zone = args->stub->zone;
   13555 	sgr = isc_mem_get(zone->mctx, sizeof(*sgr));
   13556 	*sgr = (struct stub_glue_request){
   13557 		.args = args,
   13558 		.name = (dns_name_t)DNS_NAME_INITEMPTY,
   13559 		.ipv4 = ipv4,
   13560 	};
   13561 
   13562 	dns_name_dup(name, zone->mctx, &sgr->name);
   13563 
   13564 	create_query(zone, ipv4 ? dns_rdatatype_a : dns_rdatatype_aaaa,
   13565 		     &sgr->name, &message);
   13566 
   13567 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   13568 		result = add_opt(message, args->udpsize, args->reqnsid, false);
   13569 		if (result != ISC_R_SUCCESS) {
   13570 			zone_debuglog(zone, __func__, 1,
   13571 				      "unable to add opt record: %s",
   13572 				      isc_result_totext(result));
   13573 			goto fail;
   13574 		}
   13575 	}
   13576 
   13577 	atomic_fetch_add_release(&args->stub->pending_requests, 1);
   13578 
   13579 	curraddr = dns_remote_curraddr(&zone->primaries);
   13580 	result = dns_request_create(
   13581 		zone->view->requestmgr, message, &zone->sourceaddr, &curraddr,
   13582 		NULL, NULL, DNS_REQUESTOPT_TCP, args->tsig_key,
   13583 		args->timeout * 3, args->timeout, 2, zone->loop,
   13584 		stub_glue_response, sgr, &sgr->request);
   13585 
   13586 	if (result != ISC_R_SUCCESS) {
   13587 		uint_fast32_t pr;
   13588 		pr = atomic_fetch_sub_release(&args->stub->pending_requests, 1);
   13589 		INSIST(pr > 1);
   13590 		zone_debuglog(zone, __func__, 1,
   13591 			      "dns_request_create() failed: %s",
   13592 			      isc_result_totext(result));
   13593 		goto fail;
   13594 	}
   13595 
   13596 	dns_message_detach(&message);
   13597 
   13598 	return ISC_R_SUCCESS;
   13599 
   13600 fail:
   13601 	dns_name_free(&sgr->name, zone->mctx);
   13602 	isc_mem_put(zone->mctx, sgr, sizeof(*sgr));
   13603 
   13604 	if (message != NULL) {
   13605 		dns_message_detach(&message);
   13606 	}
   13607 
   13608 	return result;
   13609 }
   13610 
   13611 static isc_result_t
   13612 save_nsrrset(dns_message_t *message, dns_name_t *name,
   13613 	     struct stub_cb_args *cb_args, dns_db_t *db,
   13614 	     dns_dbversion_t *version) {
   13615 	dns_rdataset_t *nsrdataset = NULL;
   13616 	dns_rdataset_t *rdataset = NULL;
   13617 	dns_dbnode_t *node = NULL;
   13618 	dns_rdata_ns_t ns;
   13619 	isc_result_t result;
   13620 	dns_rdata_t rdata = DNS_RDATA_INIT;
   13621 	bool has_glue = false;
   13622 	dns_name_t *ns_name;
   13623 	/*
   13624 	 * List of NS entries in answer, keep names that will be used
   13625 	 * to resolve missing A/AAAA glue for each entry.
   13626 	 */
   13627 	dns_namelist_t ns_list;
   13628 	ISC_LIST_INIT(ns_list);
   13629 
   13630 	/*
   13631 	 * Extract NS RRset from message.
   13632 	 */
   13633 	result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
   13634 				      dns_rdatatype_ns, dns_rdatatype_none,
   13635 				      NULL, &nsrdataset);
   13636 	if (result != ISC_R_SUCCESS) {
   13637 		goto done;
   13638 	}
   13639 
   13640 	/*
   13641 	 * Add NS rdataset.
   13642 	 */
   13643 	result = dns_db_findnode(db, name, true, &node);
   13644 	if (result != ISC_R_SUCCESS) {
   13645 		goto done;
   13646 	}
   13647 	result = dns_db_addrdataset(db, node, version, 0, nsrdataset, 0, NULL);
   13648 	dns_db_detachnode(db, &node);
   13649 	if (result != ISC_R_SUCCESS) {
   13650 		goto done;
   13651 	}
   13652 	/*
   13653 	 * Add glue rdatasets.
   13654 	 */
   13655 	for (result = dns_rdataset_first(nsrdataset); result == ISC_R_SUCCESS;
   13656 	     result = dns_rdataset_next(nsrdataset))
   13657 	{
   13658 		dns_rdataset_current(nsrdataset, &rdata);
   13659 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
   13660 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   13661 		dns_rdata_reset(&rdata);
   13662 
   13663 		if (!dns_name_issubdomain(&ns.name, name)) {
   13664 			continue;
   13665 		}
   13666 		rdataset = NULL;
   13667 		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
   13668 					      &ns.name, dns_rdatatype_aaaa,
   13669 					      dns_rdatatype_none, NULL,
   13670 					      &rdataset);
   13671 		if (result == ISC_R_SUCCESS) {
   13672 			has_glue = true;
   13673 			result = dns_db_findnode(db, &ns.name, true, &node);
   13674 			if (result != ISC_R_SUCCESS) {
   13675 				goto done;
   13676 			}
   13677 			result = dns_db_addrdataset(db, node, version, 0,
   13678 						    rdataset, 0, NULL);
   13679 			dns_db_detachnode(db, &node);
   13680 			if (result != ISC_R_SUCCESS) {
   13681 				goto done;
   13682 			}
   13683 		}
   13684 
   13685 		rdataset = NULL;
   13686 		result = dns_message_findname(
   13687 			message, DNS_SECTION_ADDITIONAL, &ns.name,
   13688 			dns_rdatatype_a, dns_rdatatype_none, NULL, &rdataset);
   13689 		if (result == ISC_R_SUCCESS) {
   13690 			has_glue = true;
   13691 			result = dns_db_findnode(db, &ns.name, true, &node);
   13692 			if (result != ISC_R_SUCCESS) {
   13693 				goto done;
   13694 			}
   13695 			result = dns_db_addrdataset(db, node, version, 0,
   13696 						    rdataset, 0, NULL);
   13697 			dns_db_detachnode(db, &node);
   13698 			if (result != ISC_R_SUCCESS) {
   13699 				goto done;
   13700 			}
   13701 		}
   13702 
   13703 		/*
   13704 		 * If no glue is found so far, we add the name to the list to
   13705 		 * resolve the A/AAAA glue later. If any glue is found in any
   13706 		 * iteration step, this list will be discarded and only the glue
   13707 		 * provided in this message will be used.
   13708 		 */
   13709 		if (!has_glue && dns_name_issubdomain(&ns.name, name)) {
   13710 			dns_name_t *tmp_name;
   13711 			tmp_name = isc_mem_get(cb_args->stub->mctx,
   13712 					       sizeof(*tmp_name));
   13713 			dns_name_init(tmp_name, NULL);
   13714 			dns_name_dup(&ns.name, cb_args->stub->mctx, tmp_name);
   13715 			ISC_LIST_APPEND(ns_list, tmp_name, link);
   13716 		}
   13717 	}
   13718 
   13719 	if (result != ISC_R_NOMORE) {
   13720 		goto done;
   13721 	}
   13722 
   13723 	/*
   13724 	 * If no glue records were found, we attempt to resolve A/AAAA
   13725 	 * for each NS entry found in the answer.
   13726 	 */
   13727 	if (!has_glue) {
   13728 		for (ns_name = ISC_LIST_HEAD(ns_list); ns_name != NULL;
   13729 		     ns_name = ISC_LIST_NEXT(ns_name, link))
   13730 		{
   13731 			/*
   13732 			 * Resolve NS IPv4 address/A.
   13733 			 */
   13734 			result = stub_request_nameserver_address(cb_args, true,
   13735 								 ns_name);
   13736 			if (result != ISC_R_SUCCESS) {
   13737 				goto done;
   13738 			}
   13739 			/*
   13740 			 * Resolve NS IPv6 address/AAAA.
   13741 			 */
   13742 			result = stub_request_nameserver_address(cb_args, false,
   13743 								 ns_name);
   13744 			if (result != ISC_R_SUCCESS) {
   13745 				goto done;
   13746 			}
   13747 		}
   13748 	}
   13749 
   13750 	result = ISC_R_SUCCESS;
   13751 
   13752 done:
   13753 	while ((ns_name = ISC_LIST_HEAD(ns_list)) != NULL) {
   13754 		ISC_LIST_UNLINK(ns_list, ns_name, link);
   13755 		dns_name_free(ns_name, cb_args->stub->mctx);
   13756 		isc_mem_put(cb_args->stub->mctx, ns_name, sizeof(*ns_name));
   13757 	}
   13758 	return result;
   13759 }
   13760 
   13761 static void
   13762 stub_callback(void *arg) {
   13763 	dns_request_t *request = (dns_request_t *)arg;
   13764 	struct stub_cb_args *cb_args = dns_request_getarg(request);
   13765 	dns_stub_t *stub = cb_args->stub;
   13766 	dns_message_t *msg = NULL;
   13767 	dns_zone_t *zone = NULL;
   13768 	char primary[ISC_SOCKADDR_FORMATSIZE];
   13769 	char source[ISC_SOCKADDR_FORMATSIZE];
   13770 	uint32_t nscnt, cnamecnt;
   13771 	isc_result_t result;
   13772 	isc_sockaddr_t curraddr;
   13773 	isc_time_t now;
   13774 	bool exiting = false;
   13775 
   13776 	INSIST(DNS_STUB_VALID(stub));
   13777 
   13778 	zone = stub->zone;
   13779 
   13780 	ENTER;
   13781 
   13782 	now = isc_time_now();
   13783 
   13784 	LOCK_ZONE(zone);
   13785 
   13786 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   13787 		goto exiting;
   13788 	}
   13789 
   13790 	curraddr = dns_remote_curraddr(&zone->primaries);
   13791 	isc_sockaddr_format(&curraddr, primary, sizeof(primary));
   13792 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   13793 
   13794 	result = dns_request_getresult(request);
   13795 	switch (result) {
   13796 	case ISC_R_SUCCESS:
   13797 		break;
   13798 	case ISC_R_SHUTTINGDOWN:
   13799 	case ISC_R_CANCELED:
   13800 		goto exiting;
   13801 	case ISC_R_TIMEDOUT:
   13802 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   13803 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   13804 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   13805 				     "refreshing stub: timeout retrying "
   13806 				     "without EDNS primary %s (source %s)",
   13807 				     primary, source);
   13808 			goto same_primary;
   13809 		}
   13810 		FALLTHROUGH;
   13811 	default:
   13812 		dns_zonemgr_unreachableadd(zone->zmgr, &curraddr,
   13813 					   &zone->sourceaddr, &now);
   13814 		dns_zone_log(zone, ISC_LOG_INFO,
   13815 			     "could not refresh stub from primary "
   13816 			     "%s (source %s): %s",
   13817 			     primary, source, isc_result_totext(result));
   13818 		goto next_primary;
   13819 	}
   13820 
   13821 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
   13822 			   &msg);
   13823 
   13824 	result = dns_request_getresponse(request, msg, 0);
   13825 	if (result != ISC_R_SUCCESS) {
   13826 		goto next_primary;
   13827 	}
   13828 
   13829 	/*
   13830 	 * Unexpected opcode.
   13831 	 */
   13832 	if (msg->opcode != dns_opcode_query) {
   13833 		char opcode[128];
   13834 		isc_buffer_t rb;
   13835 
   13836 		isc_buffer_init(&rb, opcode, sizeof(opcode));
   13837 		(void)dns_opcode_totext(msg->opcode, &rb);
   13838 
   13839 		dns_zone_log(zone, ISC_LOG_INFO,
   13840 			     "refreshing stub: "
   13841 			     "unexpected opcode (%.*s) from %s (source %s)",
   13842 			     (int)rb.used, opcode, primary, source);
   13843 		goto next_primary;
   13844 	}
   13845 
   13846 	/*
   13847 	 * Unexpected rcode.
   13848 	 */
   13849 	if (msg->rcode != dns_rcode_noerror) {
   13850 		char rcode[128];
   13851 		isc_buffer_t rb;
   13852 
   13853 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   13854 		(void)dns_rcode_totext(msg->rcode, &rb);
   13855 
   13856 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
   13857 		    (msg->rcode == dns_rcode_servfail ||
   13858 		     msg->rcode == dns_rcode_notimp ||
   13859 		     (msg->rcode == dns_rcode_formerr && msg->opt == NULL)))
   13860 		{
   13861 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   13862 				     "refreshing stub: rcode (%.*s) retrying "
   13863 				     "without EDNS primary %s (source %s)",
   13864 				     (int)rb.used, rcode, primary, source);
   13865 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   13866 			goto same_primary;
   13867 		}
   13868 
   13869 		dns_zone_log(zone, ISC_LOG_INFO,
   13870 			     "refreshing stub: "
   13871 			     "unexpected rcode (%.*s) from %s (source %s)",
   13872 			     (int)rb.used, rcode, primary, source);
   13873 		goto next_primary;
   13874 	}
   13875 
   13876 	/*
   13877 	 * We need complete messages.
   13878 	 */
   13879 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
   13880 		if (dns_request_usedtcp(request)) {
   13881 			dns_zone_log(zone, ISC_LOG_INFO,
   13882 				     "refreshing stub: truncated TCP "
   13883 				     "response from primary %s (source %s)",
   13884 				     primary, source);
   13885 			goto next_primary;
   13886 		}
   13887 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
   13888 		goto same_primary;
   13889 	}
   13890 
   13891 	/*
   13892 	 * If non-auth log and next primary.
   13893 	 */
   13894 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
   13895 		dns_zone_log(zone, ISC_LOG_INFO,
   13896 			     "refreshing stub: "
   13897 			     "non-authoritative answer from "
   13898 			     "primary %s (source %s)",
   13899 			     primary, source);
   13900 		goto next_primary;
   13901 	}
   13902 
   13903 	/*
   13904 	 * Sanity checks.
   13905 	 */
   13906 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
   13907 	nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
   13908 
   13909 	if (cnamecnt != 0) {
   13910 		dns_zone_log(zone, ISC_LOG_INFO,
   13911 			     "refreshing stub: unexpected CNAME response "
   13912 			     "from primary %s (source %s)",
   13913 			     primary, source);
   13914 		goto next_primary;
   13915 	}
   13916 
   13917 	if (nscnt == 0) {
   13918 		dns_zone_log(zone, ISC_LOG_INFO,
   13919 			     "refreshing stub: no NS records in response "
   13920 			     "from primary %s (source %s)",
   13921 			     primary, source);
   13922 		goto next_primary;
   13923 	}
   13924 
   13925 	atomic_fetch_add(&stub->pending_requests, 1);
   13926 
   13927 	/*
   13928 	 * Save answer.
   13929 	 */
   13930 	result = save_nsrrset(msg, &zone->origin, cb_args, stub->db,
   13931 			      stub->version);
   13932 	if (result != ISC_R_SUCCESS) {
   13933 		dns_zone_log(zone, ISC_LOG_INFO,
   13934 			     "refreshing stub: unable to save NS records "
   13935 			     "from primary %s (source %s)",
   13936 			     primary, source);
   13937 		goto next_primary;
   13938 	}
   13939 
   13940 	dns_message_detach(&msg);
   13941 	dns_request_destroy(&zone->request);
   13942 
   13943 	/*
   13944 	 * Check to see if there are no outstanding requests and
   13945 	 * finish off if that is so.
   13946 	 */
   13947 	if (atomic_fetch_sub(&stub->pending_requests, 1) == 1) {
   13948 		isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
   13949 		stub_finish_zone_update(stub, now);
   13950 		goto free_stub;
   13951 	}
   13952 
   13953 	UNLOCK_ZONE(zone);
   13954 	return;
   13955 
   13956 exiting:
   13957 	zone_debuglog(zone, __func__, 1, "exiting");
   13958 	exiting = true;
   13959 
   13960 next_primary:
   13961 	isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
   13962 	if (stub->version != NULL) {
   13963 		dns_db_closeversion(stub->db, &stub->version, false);
   13964 	}
   13965 	if (stub->db != NULL) {
   13966 		dns_db_detach(&stub->db);
   13967 	}
   13968 	if (msg != NULL) {
   13969 		dns_message_detach(&msg);
   13970 	}
   13971 	dns_request_destroy(&zone->request);
   13972 	/*
   13973 	 * Skip to next failed / untried primary.
   13974 	 */
   13975 	dns_remote_next(&zone->primaries, true);
   13976 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
   13977 	if (exiting || dns_remote_done(&zone->primaries)) {
   13978 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   13979 		zone_settimer(zone, &now);
   13980 		goto free_stub;
   13981 	}
   13982 	queue_soa_query(zone);
   13983 	goto free_stub;
   13984 
   13985 same_primary:
   13986 	isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
   13987 	if (msg != NULL) {
   13988 		dns_message_detach(&msg);
   13989 	}
   13990 	dns_request_destroy(&zone->request);
   13991 	ns_query(zone, NULL, stub);
   13992 	UNLOCK_ZONE(zone);
   13993 	return;
   13994 
   13995 free_stub:
   13996 	UNLOCK_ZONE(zone);
   13997 	stub->magic = 0;
   13998 	dns_zone_idetach(&stub->zone);
   13999 	INSIST(stub->db == NULL);
   14000 	INSIST(stub->version == NULL);
   14001 	isc_mem_put(stub->mctx, stub, sizeof(*stub));
   14002 }
   14003 
   14004 /*
   14005  * Get the EDNS EXPIRE option from the response and if it exists trim
   14006  * expire to be not more than it.
   14007  */
   14008 static void
   14009 get_edns_expire(dns_zone_t *zone, dns_message_t *message, uint32_t *expirep) {
   14010 	isc_result_t result;
   14011 	uint32_t expire;
   14012 	dns_rdata_t rdata = DNS_RDATA_INIT;
   14013 	isc_buffer_t optbuf;
   14014 	uint16_t optcode;
   14015 	uint16_t optlen;
   14016 
   14017 	REQUIRE(expirep != NULL);
   14018 	REQUIRE(message != NULL);
   14019 
   14020 	if (message->opt == NULL) {
   14021 		return;
   14022 	}
   14023 
   14024 	result = dns_rdataset_first(message->opt);
   14025 	if (result == ISC_R_SUCCESS) {
   14026 		dns_rdataset_current(message->opt, &rdata);
   14027 		isc_buffer_init(&optbuf, rdata.data, rdata.length);
   14028 		isc_buffer_add(&optbuf, rdata.length);
   14029 		while (isc_buffer_remaininglength(&optbuf) >= 4) {
   14030 			optcode = isc_buffer_getuint16(&optbuf);
   14031 			optlen = isc_buffer_getuint16(&optbuf);
   14032 			/*
   14033 			 * A EDNS EXPIRE response has a length of 4.
   14034 			 */
   14035 			if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
   14036 				isc_buffer_forward(&optbuf, optlen);
   14037 				continue;
   14038 			}
   14039 			expire = isc_buffer_getuint32(&optbuf);
   14040 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   14041 				     "got EDNS EXPIRE of %u", expire);
   14042 			/*
   14043 			 * Trim *expirep?
   14044 			 */
   14045 			if (expire < *expirep) {
   14046 				*expirep = expire;
   14047 			}
   14048 			break;
   14049 		}
   14050 	}
   14051 }
   14052 
   14053 /*
   14054  * Set the file modification time zone->expire seconds before expiretime.
   14055  */
   14056 static void
   14057 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
   14058 	isc_result_t result;
   14059 	isc_time_t when;
   14060 	isc_interval_t i;
   14061 
   14062 	isc_interval_set(&i, zone->expire, 0);
   14063 	result = isc_time_subtract(expiretime, &i, &when);
   14064 	if (result != ISC_R_SUCCESS) {
   14065 		return;
   14066 	}
   14067 
   14068 	result = ISC_R_FAILURE;
   14069 	if (zone->journal != NULL) {
   14070 		result = isc_file_settime(zone->journal, &when);
   14071 	}
   14072 	if (result == ISC_R_SUCCESS &&
   14073 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   14074 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
   14075 	{
   14076 		result = isc_file_settime(zone->masterfile, &when);
   14077 	} else if (result != ISC_R_SUCCESS) {
   14078 		result = isc_file_settime(zone->masterfile, &when);
   14079 	}
   14080 
   14081 	/*
   14082 	 * Someone removed the file from underneath us!
   14083 	 */
   14084 	if (result == ISC_R_FILENOTFOUND) {
   14085 		zone_needdump(zone, DNS_DUMP_DELAY);
   14086 	} else if (result != ISC_R_SUCCESS) {
   14087 		dns_zone_log(zone, ISC_LOG_ERROR,
   14088 			     "refresh: could not set "
   14089 			     "file modification time of '%s': %s",
   14090 			     zone->masterfile, isc_result_totext(result));
   14091 	}
   14092 }
   14093 
   14094 /*
   14095  * An SOA query has finished (successfully or not).
   14096  */
   14097 static void
   14098 refresh_callback(void *arg) {
   14099 	dns_request_t *request = (dns_request_t *)arg;
   14100 	dns_zone_t *zone = dns_request_getarg(request);
   14101 	dns_message_t *msg = NULL;
   14102 	uint32_t soacnt, cnamecnt, soacount, nscount;
   14103 	isc_time_t now;
   14104 	char primary[ISC_SOCKADDR_FORMATSIZE];
   14105 	char source[ISC_SOCKADDR_FORMATSIZE];
   14106 	dns_rdataset_t *rdataset = NULL;
   14107 	dns_rdata_t rdata = DNS_RDATA_INIT;
   14108 	dns_rdata_soa_t soa;
   14109 	isc_result_t result;
   14110 	const isc_result_t eresult = dns_request_getresult(request);
   14111 	isc_sockaddr_t curraddr;
   14112 	uint32_t serial, oldserial = 0;
   14113 	bool do_queue_xfrin = false;
   14114 
   14115 	INSIST(DNS_ZONE_VALID(zone));
   14116 
   14117 	ENTER;
   14118 
   14119 	if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   14120 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(3),
   14121 			      "refresh: request result: %s",
   14122 			      isc_result_totext(eresult));
   14123 	}
   14124 
   14125 	now = isc_time_now();
   14126 
   14127 	LOCK_ZONE(zone);
   14128 
   14129 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   14130 		goto exiting;
   14131 	}
   14132 
   14133 	/*
   14134 	 * If timeout, log and try the next primary
   14135 	 */
   14136 	curraddr = dns_remote_curraddr(&zone->primaries);
   14137 	isc_sockaddr_format(&curraddr, primary, sizeof(primary));
   14138 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   14139 
   14140 	switch (eresult) {
   14141 	case ISC_R_SUCCESS:
   14142 		break;
   14143 	case ISC_R_SHUTTINGDOWN:
   14144 	case ISC_R_CANCELED:
   14145 		goto exiting;
   14146 	case ISC_R_TIMEDOUT:
   14147 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   14148 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   14149 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14150 				      ISC_LOG_DEBUG(1),
   14151 				      "refresh: timeout retrying without EDNS "
   14152 				      "primary %s (source %s)",
   14153 				      primary, source);
   14154 			goto same_primary;
   14155 		} else if (!dns_request_usedtcp(request)) {
   14156 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14157 				      ISC_LOG_INFO,
   14158 				      "refresh: retry limit for "
   14159 				      "primary %s exceeded (source %s)",
   14160 				      primary, source);
   14161 			/* Try with secondary with TCP. */
   14162 			if ((zone->type == dns_zone_secondary ||
   14163 			     zone->type == dns_zone_mirror ||
   14164 			     zone->type == dns_zone_redirect) &&
   14165 			    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
   14166 			{
   14167 				if (!dns_zonemgr_unreachable(
   14168 					    zone->zmgr, &curraddr,
   14169 					    &zone->sourceaddr, &now))
   14170 				{
   14171 					DNS_ZONE_SETFLAG(
   14172 						zone,
   14173 						DNS_ZONEFLG_SOABEFOREAXFR);
   14174 					goto tcp_transfer;
   14175 				}
   14176 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14177 					      ISC_LOG_DEBUG(1),
   14178 					      "refresh: skipped tcp fallback "
   14179 					      "as primary %s (source %s) is "
   14180 					      "unreachable (cached)",
   14181 					      primary, source);
   14182 			}
   14183 			goto next_primary;
   14184 		}
   14185 		FALLTHROUGH;
   14186 	default:
   14187 		result = eresult;
   14188 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14189 			      "refresh: failure trying primary "
   14190 			      "%s (source %s): %s",
   14191 			      primary, source, isc_result_totext(result));
   14192 		goto next_primary;
   14193 	}
   14194 
   14195 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
   14196 			   &msg);
   14197 	result = dns_request_getresponse(request, msg, 0);
   14198 	if (result != ISC_R_SUCCESS) {
   14199 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14200 			      "refresh: failure trying primary "
   14201 			      "%s (source %s): %s",
   14202 			      primary, source, isc_result_totext(result));
   14203 		goto next_primary;
   14204 	}
   14205 
   14206 	/*
   14207 	 * Unexpected opcode.
   14208 	 */
   14209 	if (msg->opcode != dns_opcode_query) {
   14210 		char opcode[128];
   14211 		isc_buffer_t rb;
   14212 
   14213 		isc_buffer_init(&rb, opcode, sizeof(opcode));
   14214 		(void)dns_opcode_totext(msg->opcode, &rb);
   14215 
   14216 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14217 			      "refresh: "
   14218 			      "unexpected opcode (%.*s) from %s (source %s)",
   14219 			      (int)rb.used, opcode, primary, source);
   14220 		goto next_primary;
   14221 	}
   14222 
   14223 	/*
   14224 	 * Unexpected rcode.
   14225 	 */
   14226 	if (msg->rcode != dns_rcode_noerror) {
   14227 		char rcode[128];
   14228 		isc_buffer_t rb;
   14229 
   14230 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   14231 		(void)dns_rcode_totext(msg->rcode, &rb);
   14232 
   14233 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
   14234 		    (msg->rcode == dns_rcode_servfail ||
   14235 		     msg->rcode == dns_rcode_notimp ||
   14236 		     (msg->rcode == dns_rcode_formerr && msg->opt == NULL)))
   14237 		{
   14238 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14239 				      ISC_LOG_DEBUG(1),
   14240 				      "refresh: rcode (%.*s) retrying without "
   14241 				      "EDNS primary %s (source %s)",
   14242 				      (int)rb.used, rcode, primary, source);
   14243 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   14244 			goto same_primary;
   14245 		}
   14246 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
   14247 		    msg->rcode == dns_rcode_badvers)
   14248 		{
   14249 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14250 				      ISC_LOG_DEBUG(1),
   14251 				      "refresh: rcode (%.*s) retrying without "
   14252 				      "EDNS EXPIRE OPTION primary %s "
   14253 				      "(source %s)",
   14254 				      (int)rb.used, rcode, primary, source);
   14255 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   14256 			goto same_primary;
   14257 		}
   14258 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14259 			      "refresh: unexpected rcode (%.*s) from "
   14260 			      "primary %s (source %s)",
   14261 			      (int)rb.used, rcode, primary, source);
   14262 		/*
   14263 		 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
   14264 		 */
   14265 		if (msg->rcode == dns_rcode_refused &&
   14266 		    (zone->type == dns_zone_secondary ||
   14267 		     zone->type == dns_zone_mirror ||
   14268 		     zone->type == dns_zone_redirect))
   14269 		{
   14270 			goto tcp_transfer;
   14271 		}
   14272 		goto next_primary;
   14273 	}
   14274 
   14275 	/*
   14276 	 * If truncated punt to zone transfer which will query again.
   14277 	 */
   14278 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
   14279 		if (zone->type == dns_zone_secondary ||
   14280 		    zone->type == dns_zone_mirror ||
   14281 		    zone->type == dns_zone_redirect)
   14282 		{
   14283 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14284 				      ISC_LOG_INFO,
   14285 				      "refresh: truncated UDP answer, "
   14286 				      "initiating TCP zone xfer "
   14287 				      "for primary %s (source %s)",
   14288 				      primary, source);
   14289 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
   14290 			goto tcp_transfer;
   14291 		} else {
   14292 			INSIST(zone->type == dns_zone_stub);
   14293 			if (dns_request_usedtcp(request)) {
   14294 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14295 					      ISC_LOG_INFO,
   14296 					      "refresh: truncated TCP response "
   14297 					      "from primary %s (source %s)",
   14298 					      primary, source);
   14299 				goto next_primary;
   14300 			}
   14301 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
   14302 			goto same_primary;
   14303 		}
   14304 	}
   14305 
   14306 	/*
   14307 	 * If non-auth, log and try the next primary
   14308 	 */
   14309 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
   14310 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14311 			      "refresh: non-authoritative answer from "
   14312 			      "primary %s (source %s)",
   14313 			      primary, source);
   14314 		goto next_primary;
   14315 	}
   14316 
   14317 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
   14318 	soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
   14319 	nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
   14320 	soacount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_soa);
   14321 
   14322 	/*
   14323 	 * There should not be a CNAME record at top of zone.
   14324 	 */
   14325 	if (cnamecnt != 0) {
   14326 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14327 			      "refresh: CNAME at top of zone "
   14328 			      "in primary %s (source %s)",
   14329 			      primary, source);
   14330 		goto next_primary;
   14331 	}
   14332 
   14333 	/*
   14334 	 * If referral, log and try the next primary;
   14335 	 */
   14336 	if (soacnt == 0 && soacount == 0 && nscount != 0) {
   14337 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14338 			      "refresh: referral response "
   14339 			      "from primary %s (source %s)",
   14340 			      primary, source);
   14341 		goto next_primary;
   14342 	}
   14343 
   14344 	/*
   14345 	 * If nodata, log and try the next primary;
   14346 	 */
   14347 	if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
   14348 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14349 			      "refresh: NODATA response "
   14350 			      "from primary %s (source %s)",
   14351 			      primary, source);
   14352 		goto next_primary;
   14353 	}
   14354 
   14355 	/*
   14356 	 * Only one soa at top of zone.
   14357 	 */
   14358 	if (soacnt != 1) {
   14359 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14360 			      "refresh: answer SOA count (%d) != 1 "
   14361 			      "from primary %s (source %s)",
   14362 			      soacnt, primary, source);
   14363 		goto next_primary;
   14364 	}
   14365 
   14366 	/*
   14367 	 * Extract serial
   14368 	 */
   14369 	rdataset = NULL;
   14370 	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
   14371 				      dns_rdatatype_soa, dns_rdatatype_none,
   14372 				      NULL, &rdataset);
   14373 	if (result != ISC_R_SUCCESS) {
   14374 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14375 			      "refresh: unable to get SOA record "
   14376 			      "from primary %s (source %s)",
   14377 			      primary, source);
   14378 		goto next_primary;
   14379 	}
   14380 
   14381 	result = dns_rdataset_first(rdataset);
   14382 	if (result != ISC_R_SUCCESS) {
   14383 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14384 			      "refresh: dns_rdataset_first() failed");
   14385 		goto next_primary;
   14386 	}
   14387 
   14388 	dns_rdataset_current(rdataset, &rdata);
   14389 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   14390 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14391 
   14392 	serial = soa.serial;
   14393 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   14394 		unsigned int dbsoacount;
   14395 		result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
   14396 					  NULL, &oldserial, NULL, NULL, NULL,
   14397 					  NULL, NULL);
   14398 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14399 		RUNTIME_CHECK(dbsoacount > 0U);
   14400 		zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__, 1,
   14401 			       "serial: new %u, old %u", serial, oldserial);
   14402 	} else {
   14403 		zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__, 1,
   14404 			       "serial: new %u, old not loaded", serial);
   14405 	}
   14406 
   14407 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
   14408 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
   14409 	    isc_serial_gt(serial, oldserial))
   14410 	{
   14411 		if (dns_zonemgr_unreachable(zone->zmgr, &curraddr,
   14412 					    &zone->sourceaddr, &now))
   14413 		{
   14414 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14415 				      ISC_LOG_INFO,
   14416 				      "refresh: skipping %s as primary %s "
   14417 				      "(source %s) is unreachable (cached)",
   14418 				      (zone->type == dns_zone_secondary ||
   14419 				       zone->type == dns_zone_mirror ||
   14420 				       zone->type == dns_zone_redirect)
   14421 					      ? "zone transfer"
   14422 					      : "NS query",
   14423 				      primary, source);
   14424 			goto next_primary;
   14425 		}
   14426 	tcp_transfer:
   14427 		dns_request_destroy(&zone->request);
   14428 		if (zone->type == dns_zone_secondary ||
   14429 		    zone->type == dns_zone_mirror ||
   14430 		    zone->type == dns_zone_redirect)
   14431 		{
   14432 			do_queue_xfrin = true;
   14433 		} else {
   14434 			INSIST(zone->type == dns_zone_stub);
   14435 			ns_query(zone, rdataset, NULL);
   14436 		}
   14437 		if (msg != NULL) {
   14438 			dns_message_detach(&msg);
   14439 		}
   14440 	} else if (isc_serial_eq(soa.serial, oldserial)) {
   14441 		isc_time_t expiretime;
   14442 		uint32_t expire;
   14443 
   14444 		/*
   14445 		 * Compute the new expire time based on this response.
   14446 		 */
   14447 		expire = zone->expire;
   14448 		get_edns_expire(zone, msg, &expire);
   14449 		DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
   14450 
   14451 		/*
   14452 		 * Has the expire time improved?
   14453 		 */
   14454 		if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
   14455 			zone->expiretime = expiretime;
   14456 			if (zone->masterfile != NULL) {
   14457 				setmodtime(zone, &expiretime);
   14458 			}
   14459 		}
   14460 
   14461 		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
   14462 		dns_remote_mark(&zone->primaries, true);
   14463 		goto next_primary;
   14464 	} else {
   14465 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) {
   14466 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14467 				      ISC_LOG_INFO,
   14468 				      "serial number (%u) "
   14469 				      "received from primary %s < ours (%u)",
   14470 				      soa.serial, primary, oldserial);
   14471 		} else {
   14472 			zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__,
   14473 				       1, "ahead");
   14474 		}
   14475 		dns_remote_mark(&zone->primaries, true);
   14476 		goto next_primary;
   14477 	}
   14478 	if (msg != NULL) {
   14479 		dns_message_detach(&msg);
   14480 	}
   14481 	goto detach;
   14482 
   14483 next_primary:
   14484 	if (msg != NULL) {
   14485 		dns_message_detach(&msg);
   14486 	}
   14487 	dns_request_destroy(&zone->request);
   14488 	/*
   14489 	 * Skip to next failed / untried primary.
   14490 	 */
   14491 	dns_remote_next(&zone->primaries, true);
   14492 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
   14493 	if (dns_remote_done(&zone->primaries)) {
   14494 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   14495 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
   14496 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   14497 			zone->refreshtime = now;
   14498 		}
   14499 		zone_settimer(zone, &now);
   14500 		goto detach;
   14501 	}
   14502 
   14503 	queue_soa_query(zone);
   14504 	goto detach;
   14505 
   14506 exiting:
   14507 	/*
   14508 	 * We can get here not only during shutdown, but also when the refresh
   14509 	 * is canceled during reconfiguration. In that case, make sure to clear
   14510 	 * the DNS_ZONEFLG_REFRESH flag so that future zone refreshes don't get
   14511 	 * stuck, and make sure a new refresh attempt is made again soon after
   14512 	 * the reconfiguration is complete.
   14513 	 */
   14514 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   14515 	zone->refreshtime = now;
   14516 	zone_settimer(zone, &now);
   14517 
   14518 	dns_request_destroy(&zone->request);
   14519 	goto detach;
   14520 
   14521 same_primary:
   14522 	if (msg != NULL) {
   14523 		dns_message_detach(&msg);
   14524 	}
   14525 	dns_request_destroy(&zone->request);
   14526 	queue_soa_query(zone);
   14527 
   14528 detach:
   14529 	if (do_queue_xfrin) {
   14530 		/* Shows in the statistics channel the duration of the step. */
   14531 		zone->xfrintime = isc_time_now();
   14532 	}
   14533 	UNLOCK_ZONE(zone);
   14534 	if (do_queue_xfrin) {
   14535 		queue_xfrin(zone);
   14536 	}
   14537 	dns_zone_idetach(&zone);
   14538 	return;
   14539 }
   14540 
   14541 struct soaquery {
   14542 	dns_zone_t *zone;
   14543 	isc_rlevent_t *rlevent;
   14544 };
   14545 
   14546 static void
   14547 queue_soa_query(dns_zone_t *zone) {
   14548 	isc_result_t result;
   14549 	struct soaquery *sq = NULL;
   14550 
   14551 	ENTER;
   14552 	/*
   14553 	 * Locked by caller
   14554 	 */
   14555 	REQUIRE(LOCKED_ZONE(zone));
   14556 
   14557 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   14558 		cancel_refresh(zone);
   14559 		return;
   14560 	}
   14561 
   14562 	sq = isc_mem_get(zone->mctx, sizeof(*sq));
   14563 	*sq = (struct soaquery){ .zone = NULL };
   14564 
   14565 	/* Shows in the statistics channel the duration of the current step. */
   14566 	zone->xfrintime = isc_time_now();
   14567 
   14568 	/*
   14569 	 * Attach so that we won't clean up until the event is delivered.
   14570 	 */
   14571 	zone_iattach(zone, &sq->zone);
   14572 	result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->loop,
   14573 					 soa_query, sq, &sq->rlevent);
   14574 	if (result != ISC_R_SUCCESS) {
   14575 		zone_idetach(&sq->zone);
   14576 		isc_mem_put(zone->mctx, sq, sizeof(*sq));
   14577 		cancel_refresh(zone);
   14578 	}
   14579 }
   14580 
   14581 static void
   14582 soa_query(void *arg) {
   14583 	struct soaquery *sq = (struct soaquery *)arg;
   14584 	dns_zone_t *zone = sq->zone;
   14585 	isc_result_t result = ISC_R_FAILURE;
   14586 	dns_message_t *message = NULL;
   14587 	isc_netaddr_t primaryip;
   14588 	dns_tsigkey_t *key = NULL;
   14589 	dns_transport_t *transport = NULL;
   14590 	uint32_t options;
   14591 	bool cancel = true;
   14592 	int timeout;
   14593 	bool have_xfrsource = false, reqnsid, reqexpire;
   14594 	uint16_t udpsize = SEND_BUFFER_SIZE;
   14595 	isc_sockaddr_t curraddr, sourceaddr;
   14596 	bool do_queue_xfrin = false;
   14597 
   14598 	REQUIRE(DNS_ZONE_VALID(zone));
   14599 
   14600 	ENTER;
   14601 
   14602 	LOCK_ZONE(zone);
   14603 	if (sq->rlevent->canceled || DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
   14604 	    zone->view->requestmgr == NULL)
   14605 	{
   14606 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   14607 			cancel = false;
   14608 		}
   14609 		goto cleanup;
   14610 	}
   14611 
   14612 again:
   14613 	dns_zone_logc(
   14614 		zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(3),
   14615 		"soa_query: remote server current address index %d count %d",
   14616 		zone->primaries.curraddr, zone->primaries.addrcnt);
   14617 	INSIST(dns_remote_count(&zone->primaries) > 0);
   14618 	INSIST(!dns_remote_done(&zone->primaries));
   14619 
   14620 	sourceaddr = dns_remote_sourceaddr(&zone->primaries);
   14621 	curraddr = dns_remote_curraddr(&zone->primaries);
   14622 	isc_netaddr_fromsockaddr(&primaryip, &curraddr);
   14623 
   14624 	if (isc_sockaddr_disabled(&curraddr)) {
   14625 		goto skip_primary;
   14626 	}
   14627 
   14628 	/*
   14629 	 * First, look for a tsig key in the primaries statement, then
   14630 	 * try for a server key.
   14631 	 */
   14632 	if (dns_remote_keyname(&zone->primaries) != NULL) {
   14633 		dns_view_t *view = dns_zone_getview(zone);
   14634 		dns_name_t *keyname = dns_remote_keyname(&zone->primaries);
   14635 		result = dns_view_gettsig(view, keyname, &key);
   14636 		if (result != ISC_R_SUCCESS) {
   14637 			char namebuf[DNS_NAME_FORMATSIZE];
   14638 			dns_name_format(keyname, namebuf, sizeof(namebuf));
   14639 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14640 				      ISC_LOG_ERROR, "unable to find key: %s",
   14641 				      namebuf);
   14642 			goto skip_primary;
   14643 		}
   14644 	}
   14645 	if (key == NULL) {
   14646 		result = dns_view_getpeertsig(zone->view, &primaryip, &key);
   14647 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   14648 			char addrbuf[ISC_NETADDR_FORMATSIZE];
   14649 			isc_netaddr_format(&primaryip, addrbuf,
   14650 					   sizeof(addrbuf));
   14651 			dns_zone_logc(
   14652 				zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
   14653 				"unable to find TSIG key for %s", addrbuf);
   14654 			goto skip_primary;
   14655 		}
   14656 	}
   14657 
   14658 	if (dns_remote_tlsname(&zone->primaries) != NULL) {
   14659 		dns_view_t *view = dns_zone_getview(zone);
   14660 		dns_name_t *tlsname = dns_remote_tlsname(&zone->primaries);
   14661 		result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
   14662 					       &transport);
   14663 		if (result != ISC_R_SUCCESS) {
   14664 			char namebuf[DNS_NAME_FORMATSIZE];
   14665 			dns_name_format(tlsname, namebuf, sizeof(namebuf));
   14666 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14667 				      ISC_LOG_ERROR,
   14668 				      "unable to find TLS configuration: %s",
   14669 				      namebuf);
   14670 			goto skip_primary;
   14671 		}
   14672 	}
   14673 
   14674 	options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? DNS_REQUESTOPT_TCP
   14675 							 : 0;
   14676 	reqnsid = zone->view->requestnsid;
   14677 	reqexpire = zone->requestexpire;
   14678 	if (zone->view->peers != NULL) {
   14679 		dns_peer_t *peer = NULL;
   14680 		bool edns, usetcp;
   14681 		result = dns_peerlist_peerbyaddr(zone->view->peers, &primaryip,
   14682 						 &peer);
   14683 		if (result == ISC_R_SUCCESS) {
   14684 			result = dns_peer_getsupportedns(peer, &edns);
   14685 			if (result == ISC_R_SUCCESS && !edns) {
   14686 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   14687 			}
   14688 			result = dns_peer_gettransfersource(peer,
   14689 							    &zone->sourceaddr);
   14690 			if (result == ISC_R_SUCCESS) {
   14691 				have_xfrsource = true;
   14692 			}
   14693 			udpsize = dns_view_getudpsize(zone->view);
   14694 			(void)dns_peer_getudpsize(peer, &udpsize);
   14695 			(void)dns_peer_getrequestnsid(peer, &reqnsid);
   14696 			(void)dns_peer_getrequestexpire(peer, &reqexpire);
   14697 			result = dns_peer_getforcetcp(peer, &usetcp);
   14698 			if (result == ISC_R_SUCCESS && usetcp) {
   14699 				options |= DNS_REQUESTOPT_TCP;
   14700 			}
   14701 		}
   14702 	}
   14703 
   14704 	switch (isc_sockaddr_pf(&curraddr)) {
   14705 	case PF_INET:
   14706 		if (!have_xfrsource) {
   14707 			isc_sockaddr_t any;
   14708 			isc_sockaddr_any(&any);
   14709 
   14710 			zone->sourceaddr = sourceaddr;
   14711 			if (isc_sockaddr_equal(&sourceaddr, &any)) {
   14712 				zone->sourceaddr = zone->xfrsource4;
   14713 			}
   14714 		}
   14715 		break;
   14716 	case PF_INET6:
   14717 		if (!have_xfrsource) {
   14718 			isc_sockaddr_t any;
   14719 			isc_sockaddr_any6(&any);
   14720 
   14721 			zone->sourceaddr = sourceaddr;
   14722 			if (isc_sockaddr_equal(&zone->sourceaddr, &any)) {
   14723 				zone->sourceaddr = zone->xfrsource6;
   14724 			}
   14725 		}
   14726 		break;
   14727 	default:
   14728 		result = ISC_R_NOTIMPLEMENTED;
   14729 		goto cleanup;
   14730 	}
   14731 
   14732 	/*
   14733 	 * FIXME(OS): This is a bit hackish, but it enforces the SOA query to go
   14734 	 * through the XFR channel instead of doing dns_request that doesn't
   14735 	 * have DoT support yet.
   14736 	 */
   14737 	if (transport != NULL) {
   14738 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
   14739 		do_queue_xfrin = true;
   14740 		cancel = false;
   14741 		result = ISC_R_SUCCESS;
   14742 		goto cleanup;
   14743 	}
   14744 
   14745 	create_query(zone, dns_rdatatype_soa, &zone->origin, &message);
   14746 
   14747 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   14748 		result = add_opt(message, udpsize, reqnsid, reqexpire);
   14749 		if (result != ISC_R_SUCCESS) {
   14750 			zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__,
   14751 				       1, "unable to add opt record: %s",
   14752 				       isc_result_totext(result));
   14753 		}
   14754 	}
   14755 
   14756 	zone_iattach(zone, &(dns_zone_t *){ NULL });
   14757 	timeout = 5;
   14758 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
   14759 		timeout = 30;
   14760 	}
   14761 	result = dns_request_create(
   14762 		zone->view->requestmgr, message, &zone->sourceaddr, &curraddr,
   14763 		NULL, NULL, options, key, timeout * 3 + 1, timeout, 2,
   14764 		zone->loop, refresh_callback, zone, &zone->request);
   14765 	if (result != ISC_R_SUCCESS) {
   14766 		zone_idetach(&(dns_zone_t *){ zone });
   14767 		zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__, 1,
   14768 			       "dns_request_create() failed: %s",
   14769 			       isc_result_totext(result));
   14770 		goto skip_primary;
   14771 	} else {
   14772 		/* Shows in the statistics channel the duration of the query. */
   14773 		zone->xfrintime = isc_time_now();
   14774 
   14775 		if (isc_sockaddr_pf(&curraddr) == PF_INET) {
   14776 			inc_stats(zone, dns_zonestatscounter_soaoutv4);
   14777 		} else {
   14778 			inc_stats(zone, dns_zonestatscounter_soaoutv6);
   14779 		}
   14780 	}
   14781 	cancel = false;
   14782 cleanup:
   14783 	if (transport != NULL) {
   14784 		dns_transport_detach(&transport);
   14785 	}
   14786 	if (key != NULL) {
   14787 		dns_tsigkey_detach(&key);
   14788 	}
   14789 	if (result != ISC_R_SUCCESS) {
   14790 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   14791 	}
   14792 	if (message != NULL) {
   14793 		dns_message_detach(&message);
   14794 	}
   14795 	if (cancel) {
   14796 		cancel_refresh(zone);
   14797 	}
   14798 	if (do_queue_xfrin) {
   14799 		/* Shows in the statistics channel the duration of the step. */
   14800 		zone->xfrintime = isc_time_now();
   14801 	}
   14802 	UNLOCK_ZONE(zone);
   14803 	if (do_queue_xfrin) {
   14804 		queue_xfrin(zone);
   14805 	}
   14806 	isc_rlevent_free(&sq->rlevent);
   14807 	isc_mem_put(zone->mctx, sq, sizeof(*sq));
   14808 	dns_zone_idetach(&zone);
   14809 	return;
   14810 
   14811 skip_primary:
   14812 	if (transport != NULL) {
   14813 		dns_transport_detach(&transport);
   14814 	}
   14815 	if (key != NULL) {
   14816 		dns_tsigkey_detach(&key);
   14817 	}
   14818 	if (message != NULL) {
   14819 		dns_message_detach(&message);
   14820 	}
   14821 	/*
   14822 	 * Skip to next failed / untried primary.
   14823 	 */
   14824 	dns_remote_next(&zone->primaries, true);
   14825 	if (!dns_remote_done(&zone->primaries)) {
   14826 		goto again;
   14827 	}
   14828 	dns_remote_reset(&zone->primaries, false);
   14829 	goto cleanup;
   14830 }
   14831 
   14832 static void
   14833 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
   14834 	isc_result_t result;
   14835 	dns_message_t *message = NULL;
   14836 	isc_netaddr_t primaryip;
   14837 	dns_tsigkey_t *key = NULL;
   14838 	dns_dbnode_t *node = NULL;
   14839 	int timeout;
   14840 	bool have_xfrsource = false;
   14841 	bool reqnsid;
   14842 	uint16_t udpsize = SEND_BUFFER_SIZE;
   14843 	isc_sockaddr_t curraddr, sourceaddr;
   14844 	struct stub_cb_args *cb_args = NULL;
   14845 
   14846 	REQUIRE(DNS_ZONE_VALID(zone));
   14847 	REQUIRE(LOCKED_ZONE(zone));
   14848 	REQUIRE((soardataset != NULL && stub == NULL) ||
   14849 		(soardataset == NULL && stub != NULL));
   14850 	REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
   14851 
   14852 	ENTER;
   14853 
   14854 	if (stub == NULL) {
   14855 		stub = isc_mem_get(zone->mctx, sizeof(*stub));
   14856 		stub->magic = STUB_MAGIC;
   14857 		stub->mctx = zone->mctx;
   14858 		stub->zone = NULL;
   14859 		stub->db = NULL;
   14860 		stub->version = NULL;
   14861 		atomic_init(&stub->pending_requests, 0);
   14862 
   14863 		/*
   14864 		 * Attach so that the zone won't disappear from under us.
   14865 		 */
   14866 		zone_iattach(zone, &stub->zone);
   14867 
   14868 		/*
   14869 		 * If a db exists we will update it, otherwise we create a
   14870 		 * new one and attach it to the zone once we have the NS
   14871 		 * RRset and glue.
   14872 		 */
   14873 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   14874 		if (zone->db != NULL) {
   14875 			dns_db_attach(zone->db, &stub->db);
   14876 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   14877 		} else {
   14878 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   14879 
   14880 			INSIST(zone->db_argc >= 1);
   14881 			result = dns_db_create(zone->mctx, zone->db_argv[0],
   14882 					       &zone->origin, dns_dbtype_stub,
   14883 					       zone->rdclass, zone->db_argc - 1,
   14884 					       zone->db_argv + 1, &stub->db);
   14885 			if (result != ISC_R_SUCCESS) {
   14886 				dns_zone_log(zone, ISC_LOG_ERROR,
   14887 					     "refreshing stub: "
   14888 					     "could not create "
   14889 					     "database: %s",
   14890 					     isc_result_totext(result));
   14891 				goto cleanup;
   14892 			}
   14893 			dns_db_setloop(stub->db, zone->loop);
   14894 			dns_db_setmaxrrperset(stub->db, zone->maxrrperset);
   14895 			dns_db_setmaxtypepername(stub->db,
   14896 						 zone->maxtypepername);
   14897 		}
   14898 
   14899 		result = dns_db_newversion(stub->db, &stub->version);
   14900 		if (result != ISC_R_SUCCESS) {
   14901 			dns_zone_log(zone, ISC_LOG_INFO,
   14902 				     "refreshing stub: "
   14903 				     "dns_db_newversion() failed: %s",
   14904 				     isc_result_totext(result));
   14905 			goto cleanup;
   14906 		}
   14907 
   14908 		/*
   14909 		 * Update SOA record.
   14910 		 */
   14911 		result = dns_db_findnode(stub->db, &zone->origin, true, &node);
   14912 		if (result != ISC_R_SUCCESS) {
   14913 			dns_zone_log(zone, ISC_LOG_INFO,
   14914 				     "refreshing stub: "
   14915 				     "dns_db_findnode() failed: %s",
   14916 				     isc_result_totext(result));
   14917 			goto cleanup;
   14918 		}
   14919 
   14920 		result = dns_db_addrdataset(stub->db, node, stub->version, 0,
   14921 					    soardataset, 0, NULL);
   14922 		dns_db_detachnode(stub->db, &node);
   14923 		if (result != ISC_R_SUCCESS) {
   14924 			dns_zone_log(zone, ISC_LOG_INFO,
   14925 				     "refreshing stub: "
   14926 				     "dns_db_addrdataset() failed: %s",
   14927 				     isc_result_totext(result));
   14928 			goto cleanup;
   14929 		}
   14930 	}
   14931 
   14932 	/*
   14933 	 * XXX Optimisation: Create message when zone is setup and reuse.
   14934 	 */
   14935 	create_query(zone, dns_rdatatype_ns, &zone->origin, &message);
   14936 
   14937 	INSIST(dns_remote_count(&zone->primaries) > 0);
   14938 	INSIST(!dns_remote_done(&zone->primaries));
   14939 
   14940 	sourceaddr = dns_remote_sourceaddr(&zone->primaries);
   14941 	curraddr = dns_remote_curraddr(&zone->primaries);
   14942 	isc_netaddr_fromsockaddr(&primaryip, &curraddr);
   14943 	/*
   14944 	 * First, look for a tsig key in the primaries statement, then
   14945 	 * try for a server key.
   14946 	 */
   14947 	if (dns_remote_keyname(&zone->primaries) != NULL) {
   14948 		dns_view_t *view = dns_zone_getview(zone);
   14949 		dns_name_t *keyname = dns_remote_keyname(&zone->primaries);
   14950 		result = dns_view_gettsig(view, keyname, &key);
   14951 		if (result != ISC_R_SUCCESS) {
   14952 			char namebuf[DNS_NAME_FORMATSIZE];
   14953 			dns_name_format(keyname, namebuf, sizeof(namebuf));
   14954 			dns_zone_log(zone, ISC_LOG_ERROR,
   14955 				     "unable to find key: %s", namebuf);
   14956 		}
   14957 	}
   14958 	if (key == NULL) {
   14959 		(void)dns_view_getpeertsig(zone->view, &primaryip, &key);
   14960 	}
   14961 
   14962 	/* FIXME(OS): Do we need the transport here too? Most probably yes */
   14963 
   14964 	reqnsid = zone->view->requestnsid;
   14965 	if (zone->view->peers != NULL) {
   14966 		dns_peer_t *peer = NULL;
   14967 		bool edns;
   14968 		result = dns_peerlist_peerbyaddr(zone->view->peers, &primaryip,
   14969 						 &peer);
   14970 		if (result == ISC_R_SUCCESS) {
   14971 			result = dns_peer_getsupportedns(peer, &edns);
   14972 			if (result == ISC_R_SUCCESS && !edns) {
   14973 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   14974 			}
   14975 			result = dns_peer_gettransfersource(peer,
   14976 							    &zone->sourceaddr);
   14977 			if (result == ISC_R_SUCCESS) {
   14978 				have_xfrsource = true;
   14979 			}
   14980 			udpsize = dns_view_getudpsize(zone->view);
   14981 			(void)dns_peer_getudpsize(peer, &udpsize);
   14982 			(void)dns_peer_getrequestnsid(peer, &reqnsid);
   14983 		}
   14984 	}
   14985 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   14986 		result = add_opt(message, udpsize, reqnsid, false);
   14987 		if (result != ISC_R_SUCCESS) {
   14988 			zone_debuglog(zone, __func__, 1,
   14989 				      "unable to add opt record: %s",
   14990 				      isc_result_totext(result));
   14991 		}
   14992 	}
   14993 
   14994 	/*
   14995 	 * Always use TCP so that we shouldn't truncate in additional section.
   14996 	 */
   14997 	switch (isc_sockaddr_pf(&curraddr)) {
   14998 	case PF_INET:
   14999 		if (!have_xfrsource) {
   15000 			isc_sockaddr_t any;
   15001 			isc_sockaddr_any(&any);
   15002 
   15003 			zone->sourceaddr = sourceaddr;
   15004 			if (isc_sockaddr_equal(&zone->sourceaddr, &any)) {
   15005 				zone->sourceaddr = zone->xfrsource4;
   15006 			}
   15007 		}
   15008 		break;
   15009 	case PF_INET6:
   15010 		if (!have_xfrsource) {
   15011 			isc_sockaddr_t any;
   15012 			isc_sockaddr_any6(&any);
   15013 
   15014 			zone->sourceaddr = sourceaddr;
   15015 			if (isc_sockaddr_equal(&zone->sourceaddr, &any)) {
   15016 				zone->sourceaddr = zone->xfrsource6;
   15017 			}
   15018 		}
   15019 		break;
   15020 	default:
   15021 		result = ISC_R_NOTIMPLEMENTED;
   15022 		POST(result);
   15023 		goto cleanup;
   15024 	}
   15025 	timeout = 5;
   15026 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
   15027 		timeout = 30;
   15028 	}
   15029 
   15030 	/*
   15031 	 * Save request parameters so we can reuse them later on
   15032 	 * for resolving missing glue A/AAAA records.
   15033 	 */
   15034 	cb_args = isc_mem_get(zone->mctx, sizeof(*cb_args));
   15035 	cb_args->stub = stub;
   15036 	cb_args->tsig_key = key;
   15037 	cb_args->udpsize = udpsize;
   15038 	cb_args->timeout = timeout;
   15039 	cb_args->reqnsid = reqnsid;
   15040 
   15041 	result = dns_request_create(
   15042 		zone->view->requestmgr, message, &zone->sourceaddr, &curraddr,
   15043 		NULL, NULL, DNS_REQUESTOPT_TCP, key, timeout * 3 + 1, timeout,
   15044 		2, zone->loop, stub_callback, cb_args, &zone->request);
   15045 	if (result != ISC_R_SUCCESS) {
   15046 		zone_debuglog(zone, __func__, 1,
   15047 			      "dns_request_create() failed: %s",
   15048 			      isc_result_totext(result));
   15049 		goto cleanup;
   15050 	}
   15051 	dns_message_detach(&message);
   15052 	goto unlock;
   15053 
   15054 cleanup:
   15055 	cancel_refresh(zone);
   15056 	stub->magic = 0;
   15057 	if (stub->version != NULL) {
   15058 		dns_db_closeversion(stub->db, &stub->version, false);
   15059 	}
   15060 	if (stub->db != NULL) {
   15061 		dns_db_detach(&stub->db);
   15062 	}
   15063 	if (stub->zone != NULL) {
   15064 		zone_idetach(&stub->zone);
   15065 	}
   15066 	if (cb_args != NULL) {
   15067 		isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
   15068 	}
   15069 	isc_mem_put(stub->mctx, stub, sizeof(*stub));
   15070 	if (message != NULL) {
   15071 		dns_message_detach(&message);
   15072 	}
   15073 unlock:
   15074 	if (key != NULL) {
   15075 		dns_tsigkey_detach(&key);
   15076 	}
   15077 	return;
   15078 }
   15079 
   15080 /*
   15081  * Shut the zone down.
   15082  */
   15083 static void
   15084 zone_shutdown(void *arg) {
   15085 	dns_zone_t *zone = (dns_zone_t *)arg;
   15086 	bool free_needed, linked = false;
   15087 	dns_zone_t *raw = NULL, *secure = NULL;
   15088 	dns_view_t *view = NULL, *prev_view = NULL;
   15089 
   15090 	REQUIRE(DNS_ZONE_VALID(zone));
   15091 	INSIST(isc_refcount_current(&zone->references) == 0);
   15092 
   15093 	zone_debuglog(zone, __func__, 3, "shutting down");
   15094 
   15095 	/*
   15096 	 * If we were waiting for xfrin quota, step out of
   15097 	 * the queue.
   15098 	 * If there's no zone manager, we can't be waiting for the
   15099 	 * xfrin quota
   15100 	 */
   15101 	if (zone->zmgr != NULL) {
   15102 		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   15103 		if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
   15104 			ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
   15105 					statelink);
   15106 			linked = true;
   15107 			zone->statelist = NULL;
   15108 		}
   15109 		if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
   15110 			ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
   15111 					statelink);
   15112 			zone->statelist = NULL;
   15113 			zmgr_resume_xfrs(zone->zmgr, false);
   15114 		}
   15115 		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   15116 	}
   15117 
   15118 	/*
   15119 	 * In loop context, no locking required.  See zone_xfrdone().
   15120 	 */
   15121 	if (zone->xfr != NULL) {
   15122 		/* The final detach will happen in zone_xfrdone() */
   15123 		dns_xfrin_shutdown(zone->xfr);
   15124 	}
   15125 
   15126 	/* Safe to release the zone now */
   15127 	if (zone->zmgr != NULL) {
   15128 		dns_zonemgr_releasezone(zone->zmgr, zone);
   15129 	}
   15130 
   15131 	LOCK_ZONE(zone);
   15132 	INSIST(zone != zone->raw);
   15133 
   15134 	/*
   15135 	 * Detach the views early, we don't need them anymore.  However, we need
   15136 	 * to detach them outside of the zone lock to break the lock loop
   15137 	 * between view, adb and zone locks.
   15138 	 */
   15139 	view = zone->view;
   15140 	zone->view = NULL;
   15141 	prev_view = zone->prev_view;
   15142 	zone->prev_view = NULL;
   15143 
   15144 	if (linked) {
   15145 		isc_refcount_decrement(&zone->irefs);
   15146 	}
   15147 	if (zone->request != NULL) {
   15148 		dns_request_cancel(zone->request);
   15149 	}
   15150 
   15151 	if (zone->loadctx != NULL) {
   15152 		dns_loadctx_cancel(zone->loadctx);
   15153 	}
   15154 
   15155 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
   15156 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
   15157 	{
   15158 		if (zone->dumpctx != NULL) {
   15159 			dns_dumpctx_cancel(zone->dumpctx);
   15160 		}
   15161 	}
   15162 
   15163 	checkds_cancel(zone);
   15164 
   15165 	notify_cancel(zone);
   15166 
   15167 	forward_cancel(zone);
   15168 
   15169 	if (zone->timer != NULL) {
   15170 		isc_refcount_decrement(&zone->irefs);
   15171 		isc_timer_destroy(&zone->timer);
   15172 	}
   15173 
   15174 	/*
   15175 	 * We have now canceled everything set the flag to allow exit_check()
   15176 	 * to succeed.	We must not unlock between setting this flag and
   15177 	 * calling exit_check().
   15178 	 */
   15179 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
   15180 	free_needed = exit_check(zone);
   15181 	/*
   15182 	 * If a dump is in progress for the secure zone, defer detaching from
   15183 	 * the raw zone as it may prevent the unsigned serial number from being
   15184 	 * stored in the raw-format dump of the secure zone.  In this scenario,
   15185 	 * dump_done() takes care of cleaning up the zone->raw reference.
   15186 	 */
   15187 	if (inline_secure(zone) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   15188 		raw = zone->raw;
   15189 		zone->raw = NULL;
   15190 	}
   15191 	if (inline_raw(zone)) {
   15192 		secure = zone->secure;
   15193 		zone->secure = NULL;
   15194 	}
   15195 	UNLOCK_ZONE(zone);
   15196 
   15197 	if (view != NULL) {
   15198 		dns_view_weakdetach(&view);
   15199 	}
   15200 	if (prev_view != NULL) {
   15201 		dns_view_weakdetach(&prev_view);
   15202 	}
   15203 
   15204 	if (raw != NULL) {
   15205 		dns_zone_detach(&raw);
   15206 	}
   15207 	if (secure != NULL) {
   15208 		dns_zone_idetach(&secure);
   15209 	}
   15210 	if (free_needed) {
   15211 		zone_free(zone);
   15212 	}
   15213 }
   15214 
   15215 static void
   15216 zone_timer(void *arg) {
   15217 	dns_zone_t *zone = (dns_zone_t *)arg;
   15218 
   15219 	REQUIRE(DNS_ZONE_VALID(zone));
   15220 
   15221 	zone_maintenance(zone);
   15222 }
   15223 
   15224 static void
   15225 zone_timer_stop(dns_zone_t *zone) {
   15226 	zone_debuglog(zone, __func__, 10, "stop zone timer");
   15227 	if (zone->timer != NULL) {
   15228 		isc_timer_stop(zone->timer);
   15229 	}
   15230 }
   15231 
   15232 static void
   15233 zone_timer_set(dns_zone_t *zone, isc_time_t *next, isc_time_t *now) {
   15234 	isc_interval_t interval;
   15235 
   15236 	if (isc_time_compare(next, now) <= 0) {
   15237 		isc_interval_set(&interval, 0, 0);
   15238 	} else {
   15239 		isc_time_subtract(next, now, &interval);
   15240 	}
   15241 
   15242 	if (zone->loop == NULL) {
   15243 		zone_debuglog(zone, __func__, 10, "zone is not managed");
   15244 	} else if (zone->timer == NULL) {
   15245 		isc_refcount_increment0(&zone->irefs);
   15246 		isc_timer_create(zone->loop, zone_timer, zone, &zone->timer);
   15247 	}
   15248 	if (zone->timer != NULL) {
   15249 		isc_timer_start(zone->timer, isc_timertype_once, &interval);
   15250 	}
   15251 }
   15252 
   15253 static void
   15254 zone__settimer(void *arg) {
   15255 	zone_settimer_t *data = arg;
   15256 	dns_zone_t *zone = data->zone;
   15257 	isc_time_t *now = &data->now;
   15258 	isc_time_t next;
   15259 	bool free_needed = false;
   15260 
   15261 	REQUIRE(DNS_ZONE_VALID(zone));
   15262 	ENTER;
   15263 
   15264 	LOCK_ZONE(zone);
   15265 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   15266 		goto free;
   15267 	}
   15268 	isc_time_settoepoch(&next);
   15269 
   15270 	switch (zone->type) {
   15271 	case dns_zone_redirect:
   15272 		if (dns_remote_addresses(&zone->primaries) != NULL) {
   15273 			goto treat_as_secondary;
   15274 		}
   15275 		FALLTHROUGH;
   15276 	case dns_zone_primary:
   15277 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   15278 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
   15279 		{
   15280 			next = zone->notifytime;
   15281 		}
   15282 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   15283 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
   15284 		{
   15285 			INSIST(!isc_time_isepoch(&zone->dumptime));
   15286 			if (isc_time_isepoch(&next) ||
   15287 			    isc_time_compare(&zone->dumptime, &next) < 0)
   15288 			{
   15289 				next = zone->dumptime;
   15290 			}
   15291 		}
   15292 		if (zone->type == dns_zone_redirect) {
   15293 			break;
   15294 		}
   15295 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
   15296 		    !isc_time_isepoch(&zone->refreshkeytime))
   15297 		{
   15298 			if (isc_time_isepoch(&next) ||
   15299 			    isc_time_compare(&zone->refreshkeytime, &next) < 0)
   15300 			{
   15301 				next = zone->refreshkeytime;
   15302 			}
   15303 		}
   15304 		if (!isc_time_isepoch(&zone->resigntime)) {
   15305 			if (isc_time_isepoch(&next) ||
   15306 			    isc_time_compare(&zone->resigntime, &next) < 0)
   15307 			{
   15308 				next = zone->resigntime;
   15309 			}
   15310 		}
   15311 		if (!isc_time_isepoch(&zone->keywarntime)) {
   15312 			if (isc_time_isepoch(&next) ||
   15313 			    isc_time_compare(&zone->keywarntime, &next) < 0)
   15314 			{
   15315 				next = zone->keywarntime;
   15316 			}
   15317 		}
   15318 		if (!isc_time_isepoch(&zone->signingtime)) {
   15319 			if (isc_time_isepoch(&next) ||
   15320 			    isc_time_compare(&zone->signingtime, &next) < 0)
   15321 			{
   15322 				next = zone->signingtime;
   15323 			}
   15324 		}
   15325 		if (!isc_time_isepoch(&zone->nsec3chaintime)) {
   15326 			if (isc_time_isepoch(&next) ||
   15327 			    isc_time_compare(&zone->nsec3chaintime, &next) < 0)
   15328 			{
   15329 				next = zone->nsec3chaintime;
   15330 			}
   15331 		}
   15332 		break;
   15333 
   15334 	case dns_zone_secondary:
   15335 	case dns_zone_mirror:
   15336 	treat_as_secondary:
   15337 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   15338 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
   15339 		{
   15340 			next = zone->notifytime;
   15341 		}
   15342 		FALLTHROUGH;
   15343 	case dns_zone_stub:
   15344 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
   15345 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOPRIMARIES) &&
   15346 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
   15347 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
   15348 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
   15349 		    !isc_time_isepoch(&zone->refreshtime) &&
   15350 		    (isc_time_isepoch(&next) ||
   15351 		     isc_time_compare(&zone->refreshtime, &next) < 0))
   15352 		{
   15353 			next = zone->refreshtime;
   15354 		}
   15355 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   15356 		    !isc_time_isepoch(&zone->expiretime))
   15357 		{
   15358 			if (isc_time_isepoch(&next) ||
   15359 			    isc_time_compare(&zone->expiretime, &next) < 0)
   15360 			{
   15361 				next = zone->expiretime;
   15362 			}
   15363 		}
   15364 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   15365 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
   15366 		{
   15367 			INSIST(!isc_time_isepoch(&zone->dumptime));
   15368 			if (isc_time_isepoch(&next) ||
   15369 			    isc_time_compare(&zone->dumptime, &next) < 0)
   15370 			{
   15371 				next = zone->dumptime;
   15372 			}
   15373 		}
   15374 		break;
   15375 
   15376 	case dns_zone_key:
   15377 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   15378 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
   15379 		{
   15380 			INSIST(!isc_time_isepoch(&zone->dumptime));
   15381 			if (isc_time_isepoch(&next) ||
   15382 			    isc_time_compare(&zone->dumptime, &next) < 0)
   15383 			{
   15384 				next = zone->dumptime;
   15385 			}
   15386 		}
   15387 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
   15388 			if (isc_time_isepoch(&next) ||
   15389 			    (!isc_time_isepoch(&zone->refreshkeytime) &&
   15390 			     isc_time_compare(&zone->refreshkeytime, &next) <
   15391 				     0))
   15392 			{
   15393 				next = zone->refreshkeytime;
   15394 			}
   15395 		}
   15396 		break;
   15397 
   15398 	default:
   15399 		break;
   15400 	}
   15401 
   15402 	if (isc_time_isepoch(&next)) {
   15403 		zone_timer_stop(zone);
   15404 	} else {
   15405 		zone_timer_set(zone, &next, now);
   15406 	}
   15407 
   15408 free:
   15409 	isc_mem_put(zone->mctx, data, sizeof(*data));
   15410 	isc_refcount_decrement(&zone->irefs);
   15411 	free_needed = exit_check(zone);
   15412 	UNLOCK_ZONE(zone);
   15413 	if (free_needed) {
   15414 		zone_free(zone);
   15415 	}
   15416 }
   15417 
   15418 static void
   15419 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
   15420 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   15421 		return;
   15422 	}
   15423 
   15424 	zone_settimer_t *arg = isc_mem_get(zone->mctx, sizeof(*arg));
   15425 	*arg = (zone_settimer_t){
   15426 		.zone = zone,
   15427 		.now = *now,
   15428 	};
   15429 	isc_refcount_increment0(&zone->irefs);
   15430 	isc_async_run(zone->loop, zone__settimer, arg);
   15431 }
   15432 
   15433 static void
   15434 cancel_refresh(dns_zone_t *zone) {
   15435 	isc_time_t now;
   15436 
   15437 	/*
   15438 	 * 'zone' locked by caller.
   15439 	 */
   15440 
   15441 	REQUIRE(DNS_ZONE_VALID(zone));
   15442 	REQUIRE(LOCKED_ZONE(zone));
   15443 
   15444 	ENTER;
   15445 
   15446 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   15447 	now = isc_time_now();
   15448 	zone_settimer(zone, &now);
   15449 }
   15450 
   15451 static isc_result_t
   15452 notify_createmessage(dns_zone_t *zone, unsigned int flags,
   15453 		     dns_message_t **messagep) {
   15454 	dns_db_t *zonedb = NULL;
   15455 	dns_dbnode_t *node = NULL;
   15456 	dns_dbversion_t *version = NULL;
   15457 	dns_message_t *message = NULL;
   15458 	dns_rdataset_t rdataset;
   15459 	dns_rdata_t rdata = DNS_RDATA_INIT;
   15460 
   15461 	dns_name_t *tempname = NULL;
   15462 	dns_rdata_t *temprdata = NULL;
   15463 	dns_rdatalist_t *temprdatalist = NULL;
   15464 	dns_rdataset_t *temprdataset = NULL;
   15465 
   15466 	isc_result_t result;
   15467 	isc_region_t r;
   15468 	isc_buffer_t *b = NULL;
   15469 
   15470 	REQUIRE(DNS_ZONE_VALID(zone));
   15471 	REQUIRE(messagep != NULL && *messagep == NULL);
   15472 
   15473 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER,
   15474 			   &message);
   15475 
   15476 	message->opcode = dns_opcode_notify;
   15477 	message->flags |= DNS_MESSAGEFLAG_AA;
   15478 	message->rdclass = zone->rdclass;
   15479 
   15480 	dns_message_gettempname(message, &tempname);
   15481 
   15482 	dns_message_gettemprdataset(message, &temprdataset);
   15483 
   15484 	/*
   15485 	 * Make question.
   15486 	 */
   15487 	dns_name_clone(&zone->origin, tempname);
   15488 	dns_rdataset_makequestion(temprdataset, zone->rdclass,
   15489 				  dns_rdatatype_soa);
   15490 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
   15491 	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
   15492 	tempname = NULL;
   15493 	temprdataset = NULL;
   15494 
   15495 	if ((flags & DNS_NOTIFY_NOSOA) != 0) {
   15496 		goto done;
   15497 	}
   15498 
   15499 	dns_message_gettempname(message, &tempname);
   15500 	dns_message_gettemprdata(message, &temprdata);
   15501 	dns_message_gettemprdataset(message, &temprdataset);
   15502 	dns_message_gettemprdatalist(message, &temprdatalist);
   15503 
   15504 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   15505 	INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
   15506 	dns_db_attach(zone->db, &zonedb);
   15507 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   15508 
   15509 	dns_name_clone(&zone->origin, tempname);
   15510 	dns_db_currentversion(zonedb, &version);
   15511 	result = dns_db_findnode(zonedb, tempname, false, &node);
   15512 	if (result != ISC_R_SUCCESS) {
   15513 		goto soa_cleanup;
   15514 	}
   15515 
   15516 	dns_rdataset_init(&rdataset);
   15517 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
   15518 				     dns_rdatatype_none, 0, &rdataset, NULL);
   15519 	if (result != ISC_R_SUCCESS) {
   15520 		goto soa_cleanup;
   15521 	}
   15522 	result = dns_rdataset_first(&rdataset);
   15523 	if (result != ISC_R_SUCCESS) {
   15524 		goto soa_cleanup;
   15525 	}
   15526 	dns_rdataset_current(&rdataset, &rdata);
   15527 	dns_rdata_toregion(&rdata, &r);
   15528 	isc_buffer_allocate(zone->mctx, &b, r.length);
   15529 	isc_buffer_putmem(b, r.base, r.length);
   15530 	isc_buffer_usedregion(b, &r);
   15531 	dns_rdata_init(temprdata);
   15532 	dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
   15533 	dns_message_takebuffer(message, &b);
   15534 	result = dns_rdataset_next(&rdataset);
   15535 	dns_rdataset_disassociate(&rdataset);
   15536 	if (result != ISC_R_NOMORE) {
   15537 		goto soa_cleanup;
   15538 	}
   15539 	temprdatalist->rdclass = rdata.rdclass;
   15540 	temprdatalist->type = rdata.type;
   15541 	temprdatalist->ttl = rdataset.ttl;
   15542 	ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
   15543 
   15544 	dns_rdatalist_tordataset(temprdatalist, temprdataset);
   15545 
   15546 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
   15547 	dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
   15548 	temprdatalist = NULL;
   15549 	temprdataset = NULL;
   15550 	temprdata = NULL;
   15551 	tempname = NULL;
   15552 
   15553 soa_cleanup:
   15554 	if (node != NULL) {
   15555 		dns_db_detachnode(zonedb, &node);
   15556 	}
   15557 	if (version != NULL) {
   15558 		dns_db_closeversion(zonedb, &version, false);
   15559 	}
   15560 	if (zonedb != NULL) {
   15561 		dns_db_detach(&zonedb);
   15562 	}
   15563 	if (tempname != NULL) {
   15564 		dns_message_puttempname(message, &tempname);
   15565 	}
   15566 	if (temprdata != NULL) {
   15567 		dns_message_puttemprdata(message, &temprdata);
   15568 	}
   15569 	if (temprdataset != NULL) {
   15570 		dns_message_puttemprdataset(message, &temprdataset);
   15571 	}
   15572 	if (temprdatalist != NULL) {
   15573 		dns_message_puttemprdatalist(message, &temprdatalist);
   15574 	}
   15575 
   15576 done:
   15577 	*messagep = message;
   15578 	return ISC_R_SUCCESS;
   15579 }
   15580 
   15581 isc_result_t
   15582 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
   15583 		       isc_sockaddr_t *to, dns_message_t *msg) {
   15584 	unsigned int i;
   15585 	dns_rdata_soa_t soa;
   15586 	dns_rdataset_t *rdataset = NULL;
   15587 	dns_rdata_t rdata = DNS_RDATA_INIT;
   15588 	isc_result_t result;
   15589 	char fromtext[ISC_SOCKADDR_FORMATSIZE];
   15590 	int match = 0;
   15591 	isc_netaddr_t netaddr;
   15592 	uint32_t serial = 0;
   15593 	bool have_serial = false;
   15594 	dns_tsigkey_t *tsigkey;
   15595 	const dns_name_t *tsig;
   15596 
   15597 	REQUIRE(DNS_ZONE_VALID(zone));
   15598 
   15599 	/*
   15600 	 * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
   15601 	 * ROLLOVER.
   15602 	 *
   15603 	 * SOA:	RFC1996
   15604 	 * Check that 'from' is a valid notify source, (zone->primaries).
   15605 	 *	Return DNS_R_REFUSED if not.
   15606 	 *
   15607 	 * If the notify message contains a serial number check it
   15608 	 * against the zones serial and return if <= current serial
   15609 	 *
   15610 	 * If a refresh check is progress, if so just record the
   15611 	 * fact we received a NOTIFY and from where and return.
   15612 	 * We will perform a new refresh check when the current one
   15613 	 * completes. Return ISC_R_SUCCESS.
   15614 	 *
   15615 	 * Otherwise initiate a refresh check using 'from' as the
   15616 	 * first address to check.  Return ISC_R_SUCCESS.
   15617 	 */
   15618 
   15619 	isc_sockaddr_format(from, fromtext, sizeof(fromtext));
   15620 
   15621 	/*
   15622 	 * Notify messages are processed by the raw zone.
   15623 	 */
   15624 	LOCK_ZONE(zone);
   15625 	INSIST(zone != zone->raw);
   15626 	if (inline_secure(zone)) {
   15627 		result = dns_zone_notifyreceive(zone->raw, from, to, msg);
   15628 		UNLOCK_ZONE(zone);
   15629 		return result;
   15630 	}
   15631 	/*
   15632 	 *  We only handle NOTIFY (SOA) at the present.
   15633 	 */
   15634 	if (isc_sockaddr_pf(from) == PF_INET) {
   15635 		inc_stats(zone, dns_zonestatscounter_notifyinv4);
   15636 	} else {
   15637 		inc_stats(zone, dns_zonestatscounter_notifyinv6);
   15638 	}
   15639 	if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
   15640 	    dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
   15641 				 dns_rdatatype_soa, dns_rdatatype_none, NULL,
   15642 				 NULL) != ISC_R_SUCCESS)
   15643 	{
   15644 		UNLOCK_ZONE(zone);
   15645 		if (msg->counts[DNS_SECTION_QUESTION] == 0) {
   15646 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   15647 				      ISC_LOG_NOTICE,
   15648 				      "NOTIFY with no question "
   15649 				      "section from: %s",
   15650 				      fromtext);
   15651 			return DNS_R_FORMERR;
   15652 		}
   15653 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_NOTICE,
   15654 			      "NOTIFY zone does not match");
   15655 		return DNS_R_NOTIMP;
   15656 	}
   15657 
   15658 	/*
   15659 	 * If we are a primary zone just succeed.
   15660 	 */
   15661 	if (zone->type == dns_zone_primary) {
   15662 		UNLOCK_ZONE(zone);
   15663 		return ISC_R_SUCCESS;
   15664 	}
   15665 
   15666 	isc_netaddr_fromsockaddr(&netaddr, from);
   15667 	for (i = 0; i < dns_remote_count(&zone->primaries); i++) {
   15668 		isc_sockaddr_t sockaddr = dns_remote_addr(&zone->primaries, i);
   15669 		if (isc_sockaddr_eqaddr(from, &sockaddr)) {
   15670 			break;
   15671 		}
   15672 		if (zone->view->aclenv->match_mapped &&
   15673 		    IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
   15674 		    isc_sockaddr_pf(&sockaddr) == AF_INET)
   15675 		{
   15676 			isc_netaddr_t na1, na2;
   15677 			isc_netaddr_fromv4mapped(&na1, &netaddr);
   15678 			isc_netaddr_fromsockaddr(&na2, &sockaddr);
   15679 			if (isc_netaddr_equal(&na1, &na2)) {
   15680 				break;
   15681 			}
   15682 		}
   15683 	}
   15684 
   15685 	/*
   15686 	 * Accept notify requests from non primaries if they are on
   15687 	 * 'zone->notify_acl'.
   15688 	 */
   15689 	tsigkey = dns_message_gettsigkey(msg);
   15690 	tsig = dns_tsigkey_identity(tsigkey);
   15691 	if (i >= dns_remote_count(&zone->primaries) &&
   15692 	    zone->notify_acl != NULL &&
   15693 	    (dns_acl_match(&netaddr, tsig, zone->notify_acl, zone->view->aclenv,
   15694 			   &match, NULL) == ISC_R_SUCCESS) &&
   15695 	    match > 0)
   15696 	{
   15697 		/* Accept notify. */
   15698 	} else if (i >= dns_remote_count(&zone->primaries)) {
   15699 		UNLOCK_ZONE(zone);
   15700 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   15701 			      "refused notify from non-primary: %s", fromtext);
   15702 		inc_stats(zone, dns_zonestatscounter_notifyrej);
   15703 		return DNS_R_REFUSED;
   15704 	}
   15705 
   15706 	/*
   15707 	 * If the zone is loaded and there are answers check the serial
   15708 	 * to see if we need to do a refresh.  Do not worry about this
   15709 	 * check if we are a dialup zone as we use the notify request
   15710 	 * to trigger a refresh check.
   15711 	 */
   15712 	if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
   15713 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   15714 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH))
   15715 	{
   15716 		result = dns_message_findname(
   15717 			msg, DNS_SECTION_ANSWER, &zone->origin,
   15718 			dns_rdatatype_soa, dns_rdatatype_none, NULL, &rdataset);
   15719 		if (result == ISC_R_SUCCESS) {
   15720 			result = dns_rdataset_first(rdataset);
   15721 		}
   15722 		if (result == ISC_R_SUCCESS) {
   15723 			uint32_t oldserial;
   15724 			unsigned int soacount;
   15725 
   15726 			dns_rdataset_current(rdataset, &rdata);
   15727 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
   15728 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   15729 			serial = soa.serial;
   15730 			have_serial = true;
   15731 			/*
   15732 			 * The following should safely be performed without DB
   15733 			 * lock and succeed in this context.
   15734 			 */
   15735 			result = zone_get_from_db(zone, zone->db, NULL,
   15736 						  &soacount, NULL, &oldserial,
   15737 						  NULL, NULL, NULL, NULL, NULL);
   15738 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   15739 			RUNTIME_CHECK(soacount > 0U);
   15740 			if (isc_serial_le(serial, oldserial)) {
   15741 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   15742 					      ISC_LOG_INFO,
   15743 					      "notify from %s: "
   15744 					      "zone is up to date",
   15745 					      fromtext);
   15746 				UNLOCK_ZONE(zone);
   15747 				return ISC_R_SUCCESS;
   15748 			}
   15749 		}
   15750 	}
   15751 
   15752 	/*
   15753 	 * If we got this far and there was a refresh in progress just
   15754 	 * let it complete.  Record where we got the notify from so we
   15755 	 * can perform a refresh check when the current one completes
   15756 	 */
   15757 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
   15758 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   15759 		zone->notifyfrom = *from;
   15760 		UNLOCK_ZONE(zone);
   15761 		if (have_serial) {
   15762 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   15763 				      ISC_LOG_INFO,
   15764 				      "notify from %s: "
   15765 				      "serial %u: refresh in progress, "
   15766 				      "refresh check queued",
   15767 				      fromtext, serial);
   15768 		} else {
   15769 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   15770 				      ISC_LOG_INFO,
   15771 				      "notify from %s: "
   15772 				      "refresh in progress, "
   15773 				      "refresh check queued",
   15774 				      fromtext);
   15775 		}
   15776 		return ISC_R_SUCCESS;
   15777 	}
   15778 	if (have_serial) {
   15779 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   15780 			      "notify from %s: serial %u", fromtext, serial);
   15781 	} else {
   15782 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   15783 			      "notify from %s: no serial", fromtext);
   15784 	}
   15785 	zone->notifyfrom = *from;
   15786 	UNLOCK_ZONE(zone);
   15787 
   15788 	if (to != NULL) {
   15789 		dns_zonemgr_unreachabledel(zone->zmgr, from, to);
   15790 	}
   15791 	dns_zone_refresh(zone);
   15792 	return ISC_R_SUCCESS;
   15793 }
   15794 
   15795 void
   15796 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
   15797 	REQUIRE(DNS_ZONE_VALID(zone));
   15798 
   15799 	LOCK_ZONE(zone);
   15800 	if (zone->notify_acl != NULL) {
   15801 		dns_acl_detach(&zone->notify_acl);
   15802 	}
   15803 	dns_acl_attach(acl, &zone->notify_acl);
   15804 	UNLOCK_ZONE(zone);
   15805 }
   15806 
   15807 void
   15808 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
   15809 	REQUIRE(DNS_ZONE_VALID(zone));
   15810 
   15811 	LOCK_ZONE(zone);
   15812 	if (zone->query_acl != NULL) {
   15813 		dns_acl_detach(&zone->query_acl);
   15814 	}
   15815 	dns_acl_attach(acl, &zone->query_acl);
   15816 	UNLOCK_ZONE(zone);
   15817 }
   15818 
   15819 void
   15820 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
   15821 	REQUIRE(DNS_ZONE_VALID(zone));
   15822 
   15823 	LOCK_ZONE(zone);
   15824 	if (zone->queryon_acl != NULL) {
   15825 		dns_acl_detach(&zone->queryon_acl);
   15826 	}
   15827 	dns_acl_attach(acl, &zone->queryon_acl);
   15828 	UNLOCK_ZONE(zone);
   15829 }
   15830 
   15831 void
   15832 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
   15833 	REQUIRE(DNS_ZONE_VALID(zone));
   15834 
   15835 	LOCK_ZONE(zone);
   15836 	if (zone->update_acl != NULL) {
   15837 		dns_acl_detach(&zone->update_acl);
   15838 	}
   15839 	dns_acl_attach(acl, &zone->update_acl);
   15840 	UNLOCK_ZONE(zone);
   15841 }
   15842 
   15843 void
   15844 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
   15845 	REQUIRE(DNS_ZONE_VALID(zone));
   15846 
   15847 	LOCK_ZONE(zone);
   15848 	if (zone->forward_acl != NULL) {
   15849 		dns_acl_detach(&zone->forward_acl);
   15850 	}
   15851 	dns_acl_attach(acl, &zone->forward_acl);
   15852 	UNLOCK_ZONE(zone);
   15853 }
   15854 
   15855 void
   15856 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
   15857 	REQUIRE(DNS_ZONE_VALID(zone));
   15858 
   15859 	LOCK_ZONE(zone);
   15860 	if (zone->xfr_acl != NULL) {
   15861 		dns_acl_detach(&zone->xfr_acl);
   15862 	}
   15863 	dns_acl_attach(acl, &zone->xfr_acl);
   15864 	UNLOCK_ZONE(zone);
   15865 }
   15866 
   15867 dns_acl_t *
   15868 dns_zone_getnotifyacl(dns_zone_t *zone) {
   15869 	REQUIRE(DNS_ZONE_VALID(zone));
   15870 
   15871 	return zone->notify_acl;
   15872 }
   15873 
   15874 dns_acl_t *
   15875 dns_zone_getqueryacl(dns_zone_t *zone) {
   15876 	REQUIRE(DNS_ZONE_VALID(zone));
   15877 
   15878 	return zone->query_acl;
   15879 }
   15880 
   15881 dns_acl_t *
   15882 dns_zone_getqueryonacl(dns_zone_t *zone) {
   15883 	REQUIRE(DNS_ZONE_VALID(zone));
   15884 
   15885 	return zone->queryon_acl;
   15886 }
   15887 
   15888 dns_acl_t *
   15889 dns_zone_getupdateacl(dns_zone_t *zone) {
   15890 	REQUIRE(DNS_ZONE_VALID(zone));
   15891 
   15892 	return zone->update_acl;
   15893 }
   15894 
   15895 dns_acl_t *
   15896 dns_zone_getforwardacl(dns_zone_t *zone) {
   15897 	REQUIRE(DNS_ZONE_VALID(zone));
   15898 
   15899 	return zone->forward_acl;
   15900 }
   15901 
   15902 dns_acl_t *
   15903 dns_zone_getxfracl(dns_zone_t *zone) {
   15904 	REQUIRE(DNS_ZONE_VALID(zone));
   15905 
   15906 	return zone->xfr_acl;
   15907 }
   15908 
   15909 void
   15910 dns_zone_clearupdateacl(dns_zone_t *zone) {
   15911 	REQUIRE(DNS_ZONE_VALID(zone));
   15912 
   15913 	LOCK_ZONE(zone);
   15914 	if (zone->update_acl != NULL) {
   15915 		dns_acl_detach(&zone->update_acl);
   15916 	}
   15917 	UNLOCK_ZONE(zone);
   15918 }
   15919 
   15920 void
   15921 dns_zone_clearforwardacl(dns_zone_t *zone) {
   15922 	REQUIRE(DNS_ZONE_VALID(zone));
   15923 
   15924 	LOCK_ZONE(zone);
   15925 	if (zone->forward_acl != NULL) {
   15926 		dns_acl_detach(&zone->forward_acl);
   15927 	}
   15928 	UNLOCK_ZONE(zone);
   15929 }
   15930 
   15931 void
   15932 dns_zone_clearnotifyacl(dns_zone_t *zone) {
   15933 	REQUIRE(DNS_ZONE_VALID(zone));
   15934 
   15935 	LOCK_ZONE(zone);
   15936 	if (zone->notify_acl != NULL) {
   15937 		dns_acl_detach(&zone->notify_acl);
   15938 	}
   15939 	UNLOCK_ZONE(zone);
   15940 }
   15941 
   15942 void
   15943 dns_zone_clearqueryacl(dns_zone_t *zone) {
   15944 	REQUIRE(DNS_ZONE_VALID(zone));
   15945 
   15946 	LOCK_ZONE(zone);
   15947 	if (zone->query_acl != NULL) {
   15948 		dns_acl_detach(&zone->query_acl);
   15949 	}
   15950 	UNLOCK_ZONE(zone);
   15951 }
   15952 
   15953 void
   15954 dns_zone_clearqueryonacl(dns_zone_t *zone) {
   15955 	REQUIRE(DNS_ZONE_VALID(zone));
   15956 
   15957 	LOCK_ZONE(zone);
   15958 	if (zone->queryon_acl != NULL) {
   15959 		dns_acl_detach(&zone->queryon_acl);
   15960 	}
   15961 	UNLOCK_ZONE(zone);
   15962 }
   15963 
   15964 void
   15965 dns_zone_clearxfracl(dns_zone_t *zone) {
   15966 	REQUIRE(DNS_ZONE_VALID(zone));
   15967 
   15968 	LOCK_ZONE(zone);
   15969 	if (zone->xfr_acl != NULL) {
   15970 		dns_acl_detach(&zone->xfr_acl);
   15971 	}
   15972 	UNLOCK_ZONE(zone);
   15973 }
   15974 
   15975 bool
   15976 dns_zone_getupdatedisabled(dns_zone_t *zone) {
   15977 	REQUIRE(DNS_ZONE_VALID(zone));
   15978 	return zone->update_disabled;
   15979 }
   15980 
   15981 void
   15982 dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
   15983 	REQUIRE(DNS_ZONE_VALID(zone));
   15984 	zone->update_disabled = state;
   15985 }
   15986 
   15987 bool
   15988 dns_zone_getzeronosoattl(dns_zone_t *zone) {
   15989 	REQUIRE(DNS_ZONE_VALID(zone));
   15990 	return zone->zero_no_soa_ttl;
   15991 }
   15992 
   15993 void
   15994 dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
   15995 	REQUIRE(DNS_ZONE_VALID(zone));
   15996 	zone->zero_no_soa_ttl = state;
   15997 }
   15998 
   15999 void
   16000 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
   16001 	REQUIRE(DNS_ZONE_VALID(zone));
   16002 
   16003 	zone->check_names = severity;
   16004 }
   16005 
   16006 dns_severity_t
   16007 dns_zone_getchecknames(dns_zone_t *zone) {
   16008 	REQUIRE(DNS_ZONE_VALID(zone));
   16009 
   16010 	return zone->check_names;
   16011 }
   16012 
   16013 void
   16014 dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
   16015 	REQUIRE(DNS_ZONE_VALID(zone));
   16016 
   16017 	zone->journalsize = size;
   16018 }
   16019 
   16020 int32_t
   16021 dns_zone_getjournalsize(dns_zone_t *zone) {
   16022 	REQUIRE(DNS_ZONE_VALID(zone));
   16023 
   16024 	return zone->journalsize;
   16025 }
   16026 
   16027 static void
   16028 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
   16029 	isc_result_t result = ISC_R_FAILURE;
   16030 	isc_buffer_t buffer;
   16031 
   16032 	REQUIRE(buf != NULL);
   16033 	REQUIRE(length > 1U);
   16034 
   16035 	/*
   16036 	 * Leave space for terminating '\0'.
   16037 	 */
   16038 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   16039 	if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
   16040 		if (dns_name_dynamic(&zone->origin)) {
   16041 			result = dns_name_totext(
   16042 				&zone->origin, DNS_NAME_OMITFINALDOT, &buffer);
   16043 		}
   16044 		if (result != ISC_R_SUCCESS &&
   16045 		    isc_buffer_availablelength(&buffer) >=
   16046 			    (sizeof("<UNKNOWN>") - 1))
   16047 		{
   16048 			isc_buffer_putstr(&buffer, "<UNKNOWN>");
   16049 		}
   16050 
   16051 		if (isc_buffer_availablelength(&buffer) > 0) {
   16052 			isc_buffer_putstr(&buffer, "/");
   16053 		}
   16054 		(void)dns_rdataclass_totext(zone->rdclass, &buffer);
   16055 	}
   16056 
   16057 	if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
   16058 	    strcmp(zone->view->name, "_default") != 0 &&
   16059 	    strlen(zone->view->name) < isc_buffer_availablelength(&buffer))
   16060 	{
   16061 		isc_buffer_putstr(&buffer, "/");
   16062 		isc_buffer_putstr(&buffer, zone->view->name);
   16063 	}
   16064 	if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer)) {
   16065 		isc_buffer_putstr(&buffer, " (signed)");
   16066 	}
   16067 	if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer)) {
   16068 		isc_buffer_putstr(&buffer, " (unsigned)");
   16069 	}
   16070 
   16071 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   16072 }
   16073 
   16074 static void
   16075 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
   16076 	isc_result_t result = ISC_R_FAILURE;
   16077 	isc_buffer_t buffer;
   16078 
   16079 	REQUIRE(buf != NULL);
   16080 	REQUIRE(length > 1U);
   16081 
   16082 	/*
   16083 	 * Leave space for terminating '\0'.
   16084 	 */
   16085 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   16086 	if (dns_name_dynamic(&zone->origin)) {
   16087 		result = dns_name_totext(&zone->origin, DNS_NAME_OMITFINALDOT,
   16088 					 &buffer);
   16089 	}
   16090 	if (result != ISC_R_SUCCESS &&
   16091 	    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
   16092 	{
   16093 		isc_buffer_putstr(&buffer, "<UNKNOWN>");
   16094 	}
   16095 
   16096 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   16097 }
   16098 
   16099 static void
   16100 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
   16101 	isc_buffer_t buffer;
   16102 
   16103 	REQUIRE(buf != NULL);
   16104 	REQUIRE(length > 1U);
   16105 
   16106 	/*
   16107 	 * Leave space for terminating '\0'.
   16108 	 */
   16109 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   16110 	(void)dns_rdataclass_totext(zone->rdclass, &buffer);
   16111 
   16112 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   16113 }
   16114 
   16115 static void
   16116 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
   16117 	isc_buffer_t buffer;
   16118 
   16119 	REQUIRE(buf != NULL);
   16120 	REQUIRE(length > 1U);
   16121 
   16122 	/*
   16123 	 * Leave space for terminating '\0'.
   16124 	 */
   16125 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   16126 
   16127 	if (zone->view == NULL) {
   16128 		isc_buffer_putstr(&buffer, "_none");
   16129 	} else if (strlen(zone->view->name) <
   16130 		   isc_buffer_availablelength(&buffer))
   16131 	{
   16132 		isc_buffer_putstr(&buffer, zone->view->name);
   16133 	} else {
   16134 		isc_buffer_putstr(&buffer, "_toolong");
   16135 	}
   16136 
   16137 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   16138 }
   16139 
   16140 void
   16141 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
   16142 	REQUIRE(DNS_ZONE_VALID(zone));
   16143 	REQUIRE(buf != NULL);
   16144 
   16145 	LOCK_ZONE(zone);
   16146 	zone_namerd_tostr(zone, buf, length);
   16147 	UNLOCK_ZONE(zone);
   16148 }
   16149 
   16150 void
   16151 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
   16152 	REQUIRE(DNS_ZONE_VALID(zone));
   16153 	REQUIRE(buf != NULL);
   16154 	zone_name_tostr(zone, buf, length);
   16155 }
   16156 
   16157 void
   16158 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
   16159 	      const char *prefix, const char *fmt, va_list ap) {
   16160 	char message[4096];
   16161 	const char *zstr;
   16162 
   16163 	REQUIRE(DNS_ZONE_VALID(zone));
   16164 
   16165 	if (!isc_log_wouldlog(dns_lctx, level)) {
   16166 		return;
   16167 	}
   16168 
   16169 	vsnprintf(message, sizeof(message), fmt, ap);
   16170 
   16171 	switch (zone->type) {
   16172 	case dns_zone_key:
   16173 		zstr = "managed-keys-zone";
   16174 		break;
   16175 	case dns_zone_redirect:
   16176 		zstr = "redirect-zone";
   16177 		break;
   16178 	default:
   16179 		zstr = "zone ";
   16180 	}
   16181 
   16182 	isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
   16183 		      "%s%s%s%s: %s", prefix != NULL ? prefix : "",
   16184 		      prefix != NULL ? ": " : "", zstr, zone->strnamerd,
   16185 		      message);
   16186 }
   16187 
   16188 static void
   16189 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
   16190 	va_list ap;
   16191 
   16192 	va_start(ap, fmt);
   16193 	dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
   16194 	va_end(ap);
   16195 }
   16196 
   16197 void
   16198 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, int level,
   16199 	      const char *fmt, ...) {
   16200 	va_list ap;
   16201 
   16202 	va_start(ap, fmt);
   16203 	dns_zone_logv(zone, category, level, NULL, fmt, ap);
   16204 	va_end(ap);
   16205 }
   16206 
   16207 void
   16208 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
   16209 	va_list ap;
   16210 
   16211 	va_start(ap, fmt);
   16212 	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
   16213 	va_end(ap);
   16214 }
   16215 
   16216 static void
   16217 zone_debuglogc(dns_zone_t *zone, isc_logcategory_t *category, const char *me,
   16218 	       int debuglevel, const char *fmt, ...) {
   16219 	int level = ISC_LOG_DEBUG(debuglevel);
   16220 	va_list ap;
   16221 
   16222 	va_start(ap, fmt);
   16223 	dns_zone_logv(zone, category, level, me, fmt, ap);
   16224 	va_end(ap);
   16225 }
   16226 
   16227 static void
   16228 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, const char *fmt,
   16229 	      ...) {
   16230 	int level = ISC_LOG_DEBUG(debuglevel);
   16231 	va_list ap;
   16232 
   16233 	va_start(ap, fmt);
   16234 	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
   16235 	va_end(ap);
   16236 }
   16237 
   16238 static void
   16239 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
   16240 	va_list ap;
   16241 
   16242 	va_start(ap, fmt);
   16243 	dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
   16244 	va_end(ap);
   16245 }
   16246 
   16247 static int
   16248 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) {
   16249 	isc_result_t result;
   16250 	dns_name_t *name;
   16251 	dns_rdataset_t *curr;
   16252 	int count = 0;
   16253 
   16254 	result = dns_message_firstname(msg, section);
   16255 	while (result == ISC_R_SUCCESS) {
   16256 		name = NULL;
   16257 		dns_message_currentname(msg, section, &name);
   16258 
   16259 		for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
   16260 		     curr = ISC_LIST_PREV(curr, link))
   16261 		{
   16262 			if (curr->type == type) {
   16263 				count++;
   16264 			}
   16265 		}
   16266 		result = dns_message_nextname(msg, section);
   16267 	}
   16268 
   16269 	return count;
   16270 }
   16271 
   16272 void
   16273 dns_zone_setminxfrratein(dns_zone_t *zone, uint32_t bytes, uint32_t seconds) {
   16274 	REQUIRE(DNS_ZONE_VALID(zone));
   16275 
   16276 	zone->minxfrratebytesin = bytes;
   16277 	zone->minxfrratesecondsin = seconds;
   16278 }
   16279 
   16280 uint32_t
   16281 dns_zone_getminxfrratebytesin(dns_zone_t *zone) {
   16282 	REQUIRE(DNS_ZONE_VALID(zone));
   16283 
   16284 	return zone->minxfrratebytesin;
   16285 }
   16286 
   16287 uint32_t
   16288 dns_zone_getminxfrratesecondsin(dns_zone_t *zone) {
   16289 	REQUIRE(DNS_ZONE_VALID(zone));
   16290 
   16291 	return zone->minxfrratesecondsin;
   16292 }
   16293 
   16294 void
   16295 dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
   16296 	REQUIRE(DNS_ZONE_VALID(zone));
   16297 
   16298 	zone->maxxfrin = maxxfrin;
   16299 }
   16300 
   16301 uint32_t
   16302 dns_zone_getmaxxfrin(dns_zone_t *zone) {
   16303 	REQUIRE(DNS_ZONE_VALID(zone));
   16304 
   16305 	return zone->maxxfrin;
   16306 }
   16307 
   16308 void
   16309 dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
   16310 	REQUIRE(DNS_ZONE_VALID(zone));
   16311 	zone->maxxfrout = maxxfrout;
   16312 }
   16313 
   16314 uint32_t
   16315 dns_zone_getmaxxfrout(dns_zone_t *zone) {
   16316 	REQUIRE(DNS_ZONE_VALID(zone));
   16317 
   16318 	return zone->maxxfrout;
   16319 }
   16320 
   16321 dns_zonetype_t
   16322 dns_zone_gettype(dns_zone_t *zone) {
   16323 	REQUIRE(DNS_ZONE_VALID(zone));
   16324 
   16325 	return zone->type;
   16326 }
   16327 
   16328 const char *
   16329 dns_zonetype_name(dns_zonetype_t type) {
   16330 	switch (type) {
   16331 	case dns_zone_none:
   16332 		return "none";
   16333 	case dns_zone_primary:
   16334 		return "primary";
   16335 	case dns_zone_secondary:
   16336 		return "secondary";
   16337 	case dns_zone_mirror:
   16338 		return "mirror";
   16339 	case dns_zone_stub:
   16340 		return "stub";
   16341 	case dns_zone_staticstub:
   16342 		return "static-stub";
   16343 	case dns_zone_key:
   16344 		return "key";
   16345 	case dns_zone_dlz:
   16346 		return "dlz";
   16347 	case dns_zone_redirect:
   16348 		return "redirect";
   16349 	default:
   16350 		return "unknown";
   16351 	}
   16352 }
   16353 
   16354 dns_zonetype_t
   16355 dns_zone_getredirecttype(dns_zone_t *zone) {
   16356 	REQUIRE(DNS_ZONE_VALID(zone));
   16357 	REQUIRE(zone->type == dns_zone_redirect);
   16358 
   16359 	return dns_remote_addresses(&zone->primaries) == NULL
   16360 		       ? dns_zone_primary
   16361 		       : dns_zone_secondary;
   16362 }
   16363 
   16364 dns_name_t *
   16365 dns_zone_getorigin(dns_zone_t *zone) {
   16366 	REQUIRE(DNS_ZONE_VALID(zone));
   16367 
   16368 	return &zone->origin;
   16369 }
   16370 
   16371 void
   16372 dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
   16373 	REQUIRE(DNS_ZONE_VALID(zone));
   16374 
   16375 	if (idlein == 0) {
   16376 		idlein = DNS_DEFAULT_IDLEIN;
   16377 	}
   16378 	zone->idlein = idlein;
   16379 }
   16380 
   16381 uint32_t
   16382 dns_zone_getidlein(dns_zone_t *zone) {
   16383 	REQUIRE(DNS_ZONE_VALID(zone));
   16384 
   16385 	return zone->idlein;
   16386 }
   16387 
   16388 void
   16389 dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
   16390 	REQUIRE(DNS_ZONE_VALID(zone));
   16391 
   16392 	zone->idleout = idleout;
   16393 }
   16394 
   16395 uint32_t
   16396 dns_zone_getidleout(dns_zone_t *zone) {
   16397 	REQUIRE(DNS_ZONE_VALID(zone));
   16398 
   16399 	return zone->idleout;
   16400 }
   16401 
   16402 static void
   16403 notify_done(void *arg) {
   16404 	dns_request_t *request = (dns_request_t *)arg;
   16405 	dns_notify_t *notify = dns_request_getarg(request);
   16406 	isc_result_t result;
   16407 	dns_message_t *message = NULL;
   16408 	isc_buffer_t buf;
   16409 	char rcode[128];
   16410 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   16411 
   16412 	REQUIRE(DNS_NOTIFY_VALID(notify));
   16413 
   16414 	isc_buffer_init(&buf, rcode, sizeof(rcode));
   16415 	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
   16416 	dns_message_create(notify->zone->mctx, NULL, NULL,
   16417 			   DNS_MESSAGE_INTENTPARSE, &message);
   16418 
   16419 	result = dns_request_getresult(request);
   16420 	if (result != ISC_R_SUCCESS) {
   16421 		goto fail;
   16422 	}
   16423 
   16424 	result = dns_request_getresponse(request, message,
   16425 					 DNS_MESSAGEPARSE_PRESERVEORDER);
   16426 	if (result != ISC_R_SUCCESS) {
   16427 		goto fail;
   16428 	}
   16429 
   16430 	result = dns_rcode_totext(message->rcode, &buf);
   16431 	if (result == ISC_R_SUCCESS) {
   16432 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
   16433 			   "notify response from %s: %.*s", addrbuf,
   16434 			   (int)buf.used, rcode);
   16435 	}
   16436 
   16437 fail:
   16438 	dns_message_detach(&message);
   16439 
   16440 	if (result == ISC_R_SUCCESS) {
   16441 		notify_log(notify->zone, ISC_LOG_DEBUG(1),
   16442 			   "notify to %s successful", addrbuf);
   16443 	} else if (result == ISC_R_SHUTTINGDOWN || result == ISC_R_CANCELED) {
   16444 		/* just destroy the notify */
   16445 	} else if ((notify->flags & DNS_NOTIFY_TCP) == 0) {
   16446 		notify_log(notify->zone, ISC_LOG_NOTICE,
   16447 			   "notify to %s failed: %s: retrying over TCP",
   16448 			   addrbuf, isc_result_totext(result));
   16449 		notify->flags |= DNS_NOTIFY_TCP;
   16450 		dns_request_destroy(&notify->request);
   16451 		notify_send_queue(notify, notify->flags & DNS_NOTIFY_STARTUP);
   16452 		return;
   16453 	} else if (result == ISC_R_TIMEDOUT) {
   16454 		notify_log(notify->zone, ISC_LOG_WARNING,
   16455 			   "notify to %s failed: %s: retries exceeded", addrbuf,
   16456 			   isc_result_totext(result));
   16457 	} else {
   16458 		notify_log(notify->zone, ISC_LOG_WARNING,
   16459 			   "notify to %s failed: %s", addrbuf,
   16460 			   isc_result_totext(result));
   16461 	}
   16462 	notify_destroy(notify, false);
   16463 }
   16464 
   16465 struct rss {
   16466 	dns_zone_t *zone;
   16467 	dns_db_t *db;
   16468 	uint32_t serial;
   16469 	ISC_LINK(struct rss) link;
   16470 };
   16471 
   16472 static void
   16473 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
   16474 	UNUSED(arg);
   16475 	dns_zone_log(zone, level, "%s", message);
   16476 }
   16477 
   16478 static isc_result_t
   16479 dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, isc_mem_t *mctx,
   16480 	     dns_dnsseckeylist_t *keylist, bool *inuse) {
   16481 	isc_result_t result;
   16482 	dst_key_t *dstkey = NULL;
   16483 
   16484 	result = dns_dnssec_keyfromrdata(dns_zone_getorigin(zone), rdata, mctx,
   16485 					 &dstkey);
   16486 	if (result != ISC_R_SUCCESS) {
   16487 		dns_zone_log(zone, ISC_LOG_ERROR,
   16488 			     "dns_dnssec_keyfromrdata() failed: %s",
   16489 			     isc_result_totext(result));
   16490 		return result;
   16491 	}
   16492 
   16493 	for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL;
   16494 	     k = ISC_LIST_NEXT(k, link))
   16495 	{
   16496 		if (dst_key_pubcompare(k->key, dstkey, false)) {
   16497 			*inuse = true;
   16498 			break;
   16499 		}
   16500 	}
   16501 
   16502 	dst_key_free(&dstkey);
   16503 	return ISC_R_SUCCESS;
   16504 }
   16505 
   16506 static isc_result_t
   16507 cdnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata,
   16508 	      dns_dnsseckeylist_t *keylist, bool *inuse) {
   16509 	isc_result_t result;
   16510 	dns_rdata_cdnskey_t cdnskey;
   16511 
   16512 	result = dns_rdata_tostruct(rdata, &cdnskey, NULL);
   16513 	if (result != ISC_R_SUCCESS) {
   16514 		dns_zone_log(zone, ISC_LOG_ERROR,
   16515 			     "dns_rdata_tostruct(cdnskey) failed: %s",
   16516 			     isc_result_totext(result));
   16517 		return result;
   16518 	}
   16519 
   16520 	for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL;
   16521 	     k = ISC_LIST_NEXT(k, link))
   16522 	{
   16523 		dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT;
   16524 		unsigned char keybuf[DST_KEY_MAXSIZE];
   16525 
   16526 		result = dns_dnssec_make_dnskey(k->key, keybuf, sizeof(keybuf),
   16527 						&cdnskeyrdata);
   16528 		if (result != ISC_R_SUCCESS) {
   16529 			dns_zone_log(zone, ISC_LOG_ERROR,
   16530 				     "dns_dnssec_make_dnskey() failed: %s",
   16531 				     isc_result_totext(result));
   16532 			return result;
   16533 		}
   16534 
   16535 		cdnskeyrdata.type = dns_rdatatype_cdnskey;
   16536 		if (dns_rdata_compare(rdata, &cdnskeyrdata) == 0) {
   16537 			*inuse = true;
   16538 			break;
   16539 		}
   16540 	}
   16541 
   16542 	return ISC_R_SUCCESS;
   16543 }
   16544 
   16545 static isc_result_t
   16546 cds_inuse(dns_zone_t *zone, dns_rdata_t *rdata, dns_dnsseckeylist_t *keylist,
   16547 	  bool *inuse) {
   16548 	isc_result_t result;
   16549 	dns_rdata_ds_t cds;
   16550 
   16551 	result = dns_rdata_tostruct(rdata, &cds, NULL);
   16552 	if (result != ISC_R_SUCCESS) {
   16553 		dns_zone_log(zone, ISC_LOG_ERROR,
   16554 			     "dns_rdata_tostruct(cds) failed: %s",
   16555 			     isc_result_totext(result));
   16556 		return result;
   16557 	}
   16558 
   16559 	for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL;
   16560 	     k = ISC_LIST_NEXT(k, link))
   16561 	{
   16562 		dns_rdata_t dnskey = DNS_RDATA_INIT;
   16563 		dns_rdata_t cdsrdata = DNS_RDATA_INIT;
   16564 		unsigned char keybuf[DST_KEY_MAXSIZE];
   16565 		unsigned char cdsbuf[DNS_DS_BUFFERSIZE];
   16566 
   16567 		if (dst_key_id(k->key) != cds.key_tag ||
   16568 		    dst_key_alg(k->key) != cds.algorithm)
   16569 		{
   16570 			continue;
   16571 		}
   16572 		result = dns_dnssec_make_dnskey(k->key, keybuf, sizeof(keybuf),
   16573 						&dnskey);
   16574 		if (result != ISC_R_SUCCESS) {
   16575 			dns_zone_log(zone, ISC_LOG_ERROR,
   16576 				     "dns_dnssec_make_dnskey() failed: %s",
   16577 				     isc_result_totext(result));
   16578 			return result;
   16579 		}
   16580 		result = dns_ds_buildrdata(dns_zone_getorigin(zone), &dnskey,
   16581 					   cds.digest_type, cdsbuf, &cdsrdata);
   16582 		if (result != ISC_R_SUCCESS) {
   16583 			dns_zone_log(zone, ISC_LOG_ERROR,
   16584 				     "dns_ds_buildrdata(keytag=%d, algo=%d, "
   16585 				     "digest=%d) failed: %s",
   16586 				     cds.key_tag, cds.algorithm,
   16587 				     cds.digest_type,
   16588 				     isc_result_totext(result));
   16589 			return result;
   16590 		}
   16591 
   16592 		cdsrdata.type = dns_rdatatype_cds;
   16593 		if (dns_rdata_compare(rdata, &cdsrdata) == 0) {
   16594 			*inuse = true;
   16595 			break;
   16596 		}
   16597 	}
   16598 
   16599 	return ISC_R_SUCCESS;
   16600 }
   16601 
   16602 isc_result_t
   16603 dns_zone_dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, bool *inuse) {
   16604 	dns_dnsseckeylist_t keylist;
   16605 	dns_dnsseckey_t *key = NULL;
   16606 	isc_result_t result = ISC_R_SUCCESS;
   16607 	isc_stdtime_t now = isc_stdtime_now();
   16608 	isc_mem_t *mctx;
   16609 	dns_kasp_t *kasp;
   16610 	dns_keystorelist_t *keystores;
   16611 	const char *keydir;
   16612 
   16613 	REQUIRE(DNS_ZONE_VALID(zone));
   16614 	REQUIRE(dns_rdatatype_iskeymaterial(rdata->type));
   16615 
   16616 	mctx = zone->mctx;
   16617 
   16618 	ISC_LIST_INIT(keylist);
   16619 
   16620 	*inuse = false;
   16621 
   16622 	kasp = dns_zone_getkasp(zone);
   16623 	keydir = dns_zone_getkeydirectory(zone);
   16624 	keystores = dns_zone_getkeystores(zone);
   16625 
   16626 	dns_zone_lock_keyfiles(zone);
   16627 	result = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone), kasp,
   16628 					     keydir, keystores, now, false,
   16629 					     mctx, &keylist);
   16630 	dns_zone_unlock_keyfiles(zone);
   16631 	if (result == ISC_R_NOTFOUND) {
   16632 		return ISC_R_SUCCESS;
   16633 	} else if (result != ISC_R_SUCCESS) {
   16634 		dns_zone_log(zone, ISC_LOG_ERROR,
   16635 			     "dns_dnssec_findmatchingkeys() failed: %s",
   16636 			     isc_result_totext(result));
   16637 		return result;
   16638 	}
   16639 
   16640 	switch (rdata->type) {
   16641 	case dns_rdatatype_dnskey:
   16642 		result = dnskey_inuse(zone, rdata, mctx, &keylist, inuse);
   16643 		break;
   16644 	case dns_rdatatype_cdnskey:
   16645 		result = cdnskey_inuse(zone, rdata, &keylist, inuse);
   16646 		break;
   16647 	case dns_rdatatype_cds:
   16648 		result = cds_inuse(zone, rdata, &keylist, inuse);
   16649 		break;
   16650 	default:
   16651 		UNREACHABLE();
   16652 		break;
   16653 	}
   16654 
   16655 	while (!ISC_LIST_EMPTY(keylist)) {
   16656 		key = ISC_LIST_HEAD(keylist);
   16657 		ISC_LIST_UNLINK(keylist, key, link);
   16658 		dns_dnsseckey_destroy(mctx, &key);
   16659 	}
   16660 	return result;
   16661 }
   16662 
   16663 static isc_result_t
   16664 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
   16665 		    uint32_t start, uint32_t end, dns_difftuple_t **soatuplep,
   16666 		    dns_diff_t *diff) {
   16667 	isc_result_t result;
   16668 	dns_difftuple_t *tuple = NULL;
   16669 	dns_diffop_t op = DNS_DIFFOP_ADD;
   16670 	int n_soa = 0;
   16671 
   16672 	REQUIRE(soatuplep != NULL);
   16673 
   16674 	if (start == end) {
   16675 		return DNS_R_UNCHANGED;
   16676 	}
   16677 
   16678 	CHECK(dns_journal_iter_init(journal, start, end, NULL));
   16679 	for (result = dns_journal_first_rr(journal); result == ISC_R_SUCCESS;
   16680 	     result = dns_journal_next_rr(journal))
   16681 	{
   16682 		dns_name_t *name = NULL;
   16683 		uint32_t ttl;
   16684 		dns_rdata_t *rdata = NULL;
   16685 		dns_journal_current_rr(journal, &name, &ttl, &rdata);
   16686 
   16687 		if (rdata->type == dns_rdatatype_soa) {
   16688 			n_soa++;
   16689 			if (n_soa == 2) {
   16690 				/*
   16691 				 * Save the latest raw SOA record.
   16692 				 */
   16693 				if (*soatuplep != NULL) {
   16694 					dns_difftuple_free(soatuplep);
   16695 				}
   16696 				CHECK(dns_difftuple_create(
   16697 					diff->mctx, DNS_DIFFOP_ADD, name, ttl,
   16698 					rdata, soatuplep));
   16699 			}
   16700 			if (n_soa == 3) {
   16701 				n_soa = 1;
   16702 			}
   16703 			continue;
   16704 		}
   16705 
   16706 		/* Sanity. */
   16707 		if (n_soa == 0) {
   16708 			dns_zone_log(raw, ISC_LOG_ERROR,
   16709 				     "corrupt journal file: '%s'\n",
   16710 				     raw->journal);
   16711 			return ISC_R_FAILURE;
   16712 		}
   16713 
   16714 		if (zone->privatetype != 0 && rdata->type == zone->privatetype)
   16715 		{
   16716 			continue;
   16717 		}
   16718 
   16719 		/*
   16720 		 * Skip DNSSEC records that BIND maintains with inline-signing.
   16721 		 */
   16722 		if (rdata->type == dns_rdatatype_nsec ||
   16723 		    rdata->type == dns_rdatatype_rrsig ||
   16724 		    rdata->type == dns_rdatatype_nsec3 ||
   16725 		    rdata->type == dns_rdatatype_nsec3param)
   16726 		{
   16727 			continue;
   16728 		}
   16729 		/*
   16730 		 * Allow DNSKEY, CDNSKEY, CDS because users should be able to
   16731 		 * update the zone with these records from a different provider,
   16732 		 * but skip records that are under our control.
   16733 		 */
   16734 		if (dns_rdatatype_iskeymaterial(rdata->type)) {
   16735 			bool inuse = false;
   16736 			isc_result_t r = dns_zone_dnskey_inuse(zone, rdata,
   16737 							       &inuse);
   16738 			if (r == ISC_R_SUCCESS && inuse) {
   16739 				continue;
   16740 			}
   16741 		}
   16742 
   16743 		op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
   16744 
   16745 		CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
   16746 					   &tuple));
   16747 		dns_diff_appendminimal(diff, &tuple);
   16748 	}
   16749 	if (result == ISC_R_NOMORE) {
   16750 		result = ISC_R_SUCCESS;
   16751 	}
   16752 
   16753 cleanup:
   16754 	return result;
   16755 }
   16756 
   16757 /*
   16758  * Filter the key material preserving TTL changes.  If kasp in effect honour the
   16759  * existing ttl.  The lists returned by sync_secure_db/dns_db_diffx should be
   16760  * DNSSEC RRset order so we can process 'del' and 'add' in parallel rather than
   16761  * searching for TTL only changes first and processing them, then checking the
   16762  * 'in use' status on a subsequent pass.
   16763  */
   16764 
   16765 static void
   16766 filter_keymaterial(dns_zone_t *zone, dns_difftuplelist_t *del,
   16767 		   dns_difftuplelist_t *add, bool kasp, dns_ttl_t ttl) {
   16768 	dns_difftuple_t *deltuple = ISC_LIST_HEAD(*del);
   16769 	dns_difftuple_t *addtuple = ISC_LIST_HEAD(*add);
   16770 	isc_result_t result;
   16771 
   16772 	while (deltuple != NULL || addtuple != NULL) {
   16773 		dns_difftuple_t *delnext = NULL, *addnext = NULL;
   16774 		bool inuse = false;
   16775 		if (deltuple != NULL) {
   16776 			delnext = ISC_LIST_NEXT(deltuple, link);
   16777 		}
   16778 		if (addtuple != NULL) {
   16779 			addnext = ISC_LIST_NEXT(addtuple, link);
   16780 		}
   16781 		if (deltuple != NULL && addtuple != NULL) {
   16782 			int n = dns_rdata_compare(&deltuple->rdata,
   16783 						  &addtuple->rdata);
   16784 			if (n == 0) {
   16785 				/*
   16786 				 * If the rdata is equal then the only
   16787 				 * difference will be a TTL change.
   16788 				 */
   16789 				if (kasp) {
   16790 					/* TTL is managed by dnssec-policy */
   16791 					ISC_LIST_UNLINK(*del, deltuple, link);
   16792 					dns_difftuple_free(&deltuple);
   16793 					ISC_LIST_UNLINK(*add, addtuple, link);
   16794 					dns_difftuple_free(&addtuple);
   16795 				}
   16796 				deltuple = delnext;
   16797 				addtuple = addnext;
   16798 				continue;
   16799 			}
   16800 			if (n < 0) {
   16801 				goto checkdel;
   16802 			}
   16803 			goto checkadd;
   16804 		} else if (deltuple != NULL) {
   16805 		checkdel:
   16806 			result = dns_zone_dnskey_inuse(zone, &deltuple->rdata,
   16807 						       &inuse);
   16808 			if (result == ISC_R_SUCCESS && inuse) {
   16809 				ISC_LIST_UNLINK(*del, deltuple, link);
   16810 				dns_difftuple_free(&deltuple);
   16811 			}
   16812 			deltuple = delnext;
   16813 		} else {
   16814 		checkadd:
   16815 			result = dns_zone_dnskey_inuse(zone, &addtuple->rdata,
   16816 						       &inuse);
   16817 			if (result == ISC_R_SUCCESS && inuse) {
   16818 				ISC_LIST_UNLINK(*add, addtuple, link);
   16819 				dns_difftuple_free(&addtuple);
   16820 			} else if (kasp) {
   16821 				addtuple->ttl = ttl;
   16822 			}
   16823 			addtuple = addnext;
   16824 		}
   16825 	}
   16826 }
   16827 
   16828 static isc_result_t
   16829 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
   16830 	       dns_dbversion_t *secver, dns_difftuple_t **soatuple,
   16831 	       dns_diff_t *diff) {
   16832 	isc_result_t result;
   16833 	dns_db_t *rawdb = NULL;
   16834 	dns_dbversion_t *rawver = NULL;
   16835 	dns_difftuple_t *tuple = NULL, *next;
   16836 	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
   16837 	dns_rdata_soa_t oldsoa, newsoa;
   16838 	dns_difftuplelist_t add = ISC_LIST_INITIALIZER;
   16839 	dns_difftuplelist_t del = ISC_LIST_INITIALIZER;
   16840 	dns_difftuplelist_t keyadd = ISC_LIST_INITIALIZER;
   16841 	dns_difftuplelist_t keydel = ISC_LIST_INITIALIZER;
   16842 	dns_difftuplelist_t ckeyadd = ISC_LIST_INITIALIZER;
   16843 	dns_difftuplelist_t ckeydel = ISC_LIST_INITIALIZER;
   16844 	dns_difftuplelist_t cdsadd = ISC_LIST_INITIALIZER;
   16845 	dns_difftuplelist_t cdsdel = ISC_LIST_INITIALIZER;
   16846 	dns_kasp_t *kasp = NULL;
   16847 	dns_ttl_t keyttl = 0, ckeyttl = 0, cdsttl = 0;
   16848 
   16849 	REQUIRE(DNS_ZONE_VALID(seczone));
   16850 	REQUIRE(soatuple != NULL && *soatuple == NULL);
   16851 
   16852 	if (!seczone->sourceserialset) {
   16853 		return DNS_R_UNCHANGED;
   16854 	}
   16855 
   16856 	dns_db_attach(raw->db, &rawdb);
   16857 	dns_db_currentversion(rawdb, &rawver);
   16858 	result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
   16859 	dns_db_closeversion(rawdb, &rawver, false);
   16860 	dns_db_detach(&rawdb);
   16861 
   16862 	if (result != ISC_R_SUCCESS) {
   16863 		return result;
   16864 	}
   16865 
   16866 	/*
   16867 	 * If kasp is in effect honour the existing DNSKEY, CDNSKEY and CDS
   16868 	 * TTLs.
   16869 	 */
   16870 	kasp = seczone->kasp;
   16871 	if (kasp != NULL) {
   16872 		dns_rdataset_t rdataset;
   16873 		dns_dbnode_t *node = NULL;
   16874 		dns_ttl_t ttl = dns_kasp_dnskeyttl(kasp);
   16875 
   16876 		dns_rdataset_init(&rdataset);
   16877 
   16878 		result = dns_db_getoriginnode(secdb, &node);
   16879 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   16880 
   16881 		result = dns_db_findrdataset(
   16882 			secdb, node, secver, dns_rdatatype_dnskey,
   16883 			dns_rdatatype_none, 0, &rdataset, NULL);
   16884 		keyttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl;
   16885 		if (dns_rdataset_isassociated(&rdataset)) {
   16886 			dns_rdataset_disassociate(&rdataset);
   16887 		}
   16888 
   16889 		result = dns_db_findrdataset(
   16890 			secdb, node, secver, dns_rdatatype_cdnskey,
   16891 			dns_rdatatype_none, 0, &rdataset, NULL);
   16892 		ckeyttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl;
   16893 		if (dns_rdataset_isassociated(&rdataset)) {
   16894 			dns_rdataset_disassociate(&rdataset);
   16895 		}
   16896 
   16897 		result = dns_db_findrdataset(
   16898 			secdb, node, secver, dns_rdatatype_cds,
   16899 			dns_rdatatype_none, 0, &rdataset, NULL);
   16900 		cdsttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl;
   16901 		if (dns_rdataset_isassociated(&rdataset)) {
   16902 			dns_rdataset_disassociate(&rdataset);
   16903 		}
   16904 		dns_db_detachnode(secdb, &node);
   16905 	}
   16906 
   16907 	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) {
   16908 		dns_difftuplelist_t *al = &add, *dl = &del;
   16909 
   16910 		next = ISC_LIST_NEXT(tuple, link);
   16911 
   16912 		/*
   16913 		 * Skip private records that BIND maintains with inline-signing.
   16914 		 */
   16915 		if (seczone->privatetype != 0 &&
   16916 		    tuple->rdata.type == seczone->privatetype)
   16917 		{
   16918 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
   16919 			dns_difftuple_free(&tuple);
   16920 			continue;
   16921 		}
   16922 
   16923 		/*
   16924 		 * Skip DNSSEC records that BIND maintains with inline-signing.
   16925 		 */
   16926 		if (tuple->rdata.type == dns_rdatatype_nsec ||
   16927 		    tuple->rdata.type == dns_rdatatype_rrsig ||
   16928 		    tuple->rdata.type == dns_rdatatype_nsec3 ||
   16929 		    tuple->rdata.type == dns_rdatatype_nsec3param)
   16930 		{
   16931 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
   16932 			dns_difftuple_free(&tuple);
   16933 			continue;
   16934 		}
   16935 
   16936 		/*
   16937 		 * Apex DNSKEY, CDNSKEY and CDS need special processing so
   16938 		 * split them out.
   16939 		 */
   16940 		if (dns_rdatatype_iskeymaterial(tuple->rdata.type) &&
   16941 		    dns_name_equal(&tuple->name, &seczone->origin))
   16942 		{
   16943 			switch (tuple->rdata.type) {
   16944 			case dns_rdatatype_dnskey:
   16945 				al = &keyadd;
   16946 				dl = &keydel;
   16947 				break;
   16948 			case dns_rdatatype_cdnskey:
   16949 				al = &ckeyadd;
   16950 				dl = &ckeydel;
   16951 				break;
   16952 			case dns_rdatatype_cds:
   16953 				al = &cdsadd;
   16954 				dl = &cdsdel;
   16955 				break;
   16956 			default:
   16957 				UNREACHABLE();
   16958 			}
   16959 		}
   16960 
   16961 		if (tuple->rdata.type == dns_rdatatype_soa) {
   16962 			if (tuple->op == DNS_DIFFOP_DEL) {
   16963 				INSIST(oldtuple == NULL);
   16964 				oldtuple = tuple;
   16965 			}
   16966 			if (tuple->op == DNS_DIFFOP_ADD) {
   16967 				INSIST(newtuple == NULL);
   16968 				newtuple = tuple;
   16969 			}
   16970 		}
   16971 
   16972 		/*
   16973 		 * Split into deletions and additions.
   16974 		 */
   16975 		ISC_LIST_UNLINK(diff->tuples, tuple, link);
   16976 		switch (tuple->op) {
   16977 		case DNS_DIFFOP_DEL:
   16978 		case DNS_DIFFOP_DELRESIGN:
   16979 			ISC_LIST_APPEND(*dl, tuple, link);
   16980 			break;
   16981 		case DNS_DIFFOP_ADD:
   16982 		case DNS_DIFFOP_ADDRESIGN:
   16983 			ISC_LIST_APPEND(*al, tuple, link);
   16984 			break;
   16985 		default:
   16986 			UNREACHABLE();
   16987 		}
   16988 	}
   16989 
   16990 	if (oldtuple != NULL && newtuple != NULL) {
   16991 		result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
   16992 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   16993 
   16994 		result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
   16995 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   16996 
   16997 		/*
   16998 		 * If the SOA records are the same except for the serial
   16999 		 * remove them from the diff.
   17000 		 */
   17001 		if (oldtuple->ttl == newtuple->ttl &&
   17002 		    oldsoa.refresh == newsoa.refresh &&
   17003 		    oldsoa.retry == newsoa.retry &&
   17004 		    oldsoa.minimum == newsoa.minimum &&
   17005 		    oldsoa.expire == newsoa.expire &&
   17006 		    dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
   17007 		    dns_name_equal(&oldsoa.contact, &newsoa.contact))
   17008 		{
   17009 			ISC_LIST_UNLINK(del, oldtuple, link);
   17010 			dns_difftuple_free(&oldtuple);
   17011 			ISC_LIST_UNLINK(add, newtuple, link);
   17012 			dns_difftuple_free(&newtuple);
   17013 		}
   17014 	}
   17015 
   17016 	/*
   17017 	 * Filter out keys we manage but still allow TTL changes.
   17018 	 */
   17019 	filter_keymaterial(seczone, &keydel, &keyadd, kasp != NULL, keyttl);
   17020 	filter_keymaterial(seczone, &ckeydel, &ckeyadd, kasp != NULL, ckeyttl);
   17021 	filter_keymaterial(seczone, &cdsdel, &cdsadd, kasp != NULL, cdsttl);
   17022 
   17023 	/*
   17024 	 * Rebuild the diff now that we have filtered it
   17025 	 */
   17026 	ISC_LIST_APPENDLIST(diff->tuples, del, link);
   17027 	ISC_LIST_APPENDLIST(diff->tuples, keydel, link);
   17028 	ISC_LIST_APPENDLIST(diff->tuples, ckeydel, link);
   17029 	ISC_LIST_APPENDLIST(diff->tuples, cdsdel, link);
   17030 	ISC_LIST_APPENDLIST(diff->tuples, add, link);
   17031 	ISC_LIST_APPENDLIST(diff->tuples, keyadd, link);
   17032 	ISC_LIST_APPENDLIST(diff->tuples, ckeyadd, link);
   17033 	ISC_LIST_APPENDLIST(diff->tuples, cdsadd, link);
   17034 
   17035 	if (ISC_LIST_EMPTY(diff->tuples)) {
   17036 		return DNS_R_UNCHANGED;
   17037 	}
   17038 
   17039 	/*
   17040 	 * If there are still SOA records in the diff they can now be removed
   17041 	 * saving the new SOA record.
   17042 	 */
   17043 	if (oldtuple != NULL) {
   17044 		ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
   17045 		dns_difftuple_free(&oldtuple);
   17046 	}
   17047 
   17048 	if (newtuple != NULL) {
   17049 		ISC_LIST_UNLINK(diff->tuples, newtuple, link);
   17050 		*soatuple = newtuple;
   17051 	}
   17052 
   17053 	return ISC_R_SUCCESS;
   17054 }
   17055 
   17056 static void
   17057 receive_secure_serial(void *arg) {
   17058 	struct rss *rss = (struct rss *)arg;
   17059 	dns_zone_t *zone = rss->zone;
   17060 	isc_result_t result = ISC_R_SUCCESS;
   17061 	dns_journal_t *rjournal = NULL;
   17062 	dns_journal_t *sjournal = NULL;
   17063 	uint32_t start, end = rss->serial;
   17064 	dns_difftuple_t *tuple = NULL, *soatuple = NULL;
   17065 	dns_update_log_t log = { update_log_cb, NULL };
   17066 	uint32_t newserial = 0, desired = 0;
   17067 	isc_time_t timenow;
   17068 	int level = ISC_LOG_ERROR;
   17069 
   17070 	ENTER;
   17071 
   17072 	LOCK_ZONE(zone);
   17073 
   17074 	/*
   17075 	 * The receive_secure_serial() is loop-serialized for the zone.  Make
   17076 	 * sure there's no processing currently running.
   17077 	 */
   17078 
   17079 	INSIST(zone->rss == NULL || zone->rss == rss);
   17080 
   17081 	if (zone->rss != NULL) {
   17082 		INSIST(zone->rss == rss);
   17083 		UNLOCK_ZONE(zone);
   17084 	} else {
   17085 		zone->rss = rss;
   17086 		dns_diff_init(zone->mctx, &zone->rss_diff);
   17087 
   17088 		/*
   17089 		 * zone->db may be NULL, if the load from disk failed.
   17090 		 */
   17091 		result = ISC_R_SUCCESS;
   17092 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   17093 		if (zone->db != NULL) {
   17094 			dns_db_attach(zone->db, &zone->rss_db);
   17095 		} else {
   17096 			result = ISC_R_FAILURE;
   17097 		}
   17098 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   17099 
   17100 		if (result == ISC_R_SUCCESS && zone->raw != NULL) {
   17101 			dns_zone_attach(zone->raw, &zone->rss_raw);
   17102 		} else {
   17103 			result = ISC_R_FAILURE;
   17104 		}
   17105 
   17106 		UNLOCK_ZONE(zone);
   17107 
   17108 		CHECK(result);
   17109 
   17110 		/*
   17111 		 * We first attempt to sync the raw zone to the secure zone
   17112 		 * by using the raw zone's journal, applying all the deltas
   17113 		 * from the latest source-serial of the secure zone up to
   17114 		 * the current serial number of the raw zone.
   17115 		 *
   17116 		 * If that fails, then we'll fall back to a direct comparison
   17117 		 * between raw and secure zones.
   17118 		 */
   17119 		CHECK(dns_journal_open(zone->rss_raw->mctx,
   17120 				       zone->rss_raw->journal,
   17121 				       DNS_JOURNAL_WRITE, &rjournal));
   17122 
   17123 		result = dns_journal_open(zone->mctx, zone->journal,
   17124 					  DNS_JOURNAL_READ, &sjournal);
   17125 		if (result != ISC_R_NOTFOUND) {
   17126 			CHECK(result);
   17127 		}
   17128 
   17129 		if (!dns_journal_get_sourceserial(rjournal, &start)) {
   17130 			start = dns_journal_first_serial(rjournal);
   17131 			dns_journal_set_sourceserial(rjournal, start);
   17132 		}
   17133 		if (sjournal != NULL) {
   17134 			uint32_t serial;
   17135 			/*
   17136 			 * We read the secure journal first, if that
   17137 			 * exists use its value provided it is greater
   17138 			 * that from the raw journal.
   17139 			 */
   17140 			if (dns_journal_get_sourceserial(sjournal, &serial)) {
   17141 				if (isc_serial_gt(serial, start)) {
   17142 					start = serial;
   17143 				}
   17144 			}
   17145 			dns_journal_destroy(&sjournal);
   17146 		}
   17147 
   17148 		dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
   17149 		CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
   17150 
   17151 		/*
   17152 		 * Try to apply diffs from the raw zone's journal to the secure
   17153 		 * zone.  If that fails, we recover by syncing up the databases
   17154 		 * directly.
   17155 		 */
   17156 		result = sync_secure_journal(zone, zone->rss_raw, rjournal,
   17157 					     start, end, &soatuple,
   17158 					     &zone->rss_diff);
   17159 		if (result == DNS_R_UNCHANGED) {
   17160 			goto cleanup;
   17161 		} else if (result != ISC_R_SUCCESS) {
   17162 			CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
   17163 					     zone->rss_oldver, &soatuple,
   17164 					     &zone->rss_diff));
   17165 		}
   17166 
   17167 		CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
   17168 				     zone->rss_newver));
   17169 
   17170 		if (soatuple != NULL) {
   17171 			uint32_t oldserial;
   17172 
   17173 			CHECK(dns_db_createsoatuple(
   17174 				zone->rss_db, zone->rss_oldver,
   17175 				zone->rss_diff.mctx, DNS_DIFFOP_DEL, &tuple));
   17176 			oldserial = dns_soa_getserial(&tuple->rdata);
   17177 			newserial = desired =
   17178 				dns_soa_getserial(&soatuple->rdata);
   17179 			if (!isc_serial_gt(newserial, oldserial)) {
   17180 				newserial = oldserial + 1;
   17181 				if (newserial == 0) {
   17182 					newserial++;
   17183 				}
   17184 				dns_soa_setserial(newserial, &soatuple->rdata);
   17185 			}
   17186 			CHECK(do_one_tuple(&tuple, zone->rss_db,
   17187 					   zone->rss_newver, &zone->rss_diff));
   17188 			CHECK(do_one_tuple(&soatuple, zone->rss_db,
   17189 					   zone->rss_newver, &zone->rss_diff));
   17190 		} else {
   17191 			CHECK(update_soa_serial(zone, zone->rss_db,
   17192 						zone->rss_newver,
   17193 						&zone->rss_diff, zone->mctx,
   17194 						zone->updatemethod));
   17195 		}
   17196 	}
   17197 	result = dns_update_signaturesinc(
   17198 		&log, zone, zone->rss_db, zone->rss_oldver, zone->rss_newver,
   17199 		&zone->rss_diff, zone->sigvalidityinterval, &zone->rss_state);
   17200 	if (result == DNS_R_CONTINUE) {
   17201 		if (rjournal != NULL) {
   17202 			dns_journal_destroy(&rjournal);
   17203 		}
   17204 		isc_async_run(zone->loop, receive_secure_serial, rss);
   17205 		return;
   17206 	}
   17207 
   17208 	/*
   17209 	 * If something went wrong while trying to update the secure zone and
   17210 	 * the latter was already signed before, do not apply raw zone deltas
   17211 	 * to it as that would break existing DNSSEC signatures.  However, if
   17212 	 * the secure zone was not yet signed (e.g. because no signing keys
   17213 	 * were created for it), commence applying raw zone deltas to it so
   17214 	 * that contents of the raw zone and the secure zone are kept in sync.
   17215 	 */
   17216 	if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
   17217 		goto cleanup;
   17218 	}
   17219 
   17220 	if (rjournal == NULL) {
   17221 		CHECK(dns_journal_open(zone->rss_raw->mctx,
   17222 				       zone->rss_raw->journal,
   17223 				       DNS_JOURNAL_WRITE, &rjournal));
   17224 	}
   17225 	CHECK(zone_journal(zone, &zone->rss_diff, &end,
   17226 			   "receive_secure_serial"));
   17227 
   17228 	dns_journal_set_sourceserial(rjournal, end);
   17229 	dns_journal_commit(rjournal);
   17230 
   17231 	LOCK_ZONE(zone);
   17232 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   17233 
   17234 	zone->sourceserial = end;
   17235 	zone->sourceserialset = true;
   17236 	zone_needdump(zone, DNS_DUMP_DELAY);
   17237 
   17238 	/*
   17239 	 * Set resign time to make sure it is set to the earliest
   17240 	 * signature expiration.
   17241 	 */
   17242 	set_resigntime(zone);
   17243 	timenow = isc_time_now();
   17244 	zone_settimer(zone, &timenow);
   17245 	UNLOCK_ZONE(zone);
   17246 
   17247 	dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
   17248 	dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
   17249 
   17250 	if (newserial != 0) {
   17251 		dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
   17252 			     newserial, desired);
   17253 	}
   17254 
   17255 cleanup:
   17256 	isc_mem_put(zone->mctx, rss, sizeof(*rss));
   17257 	zone->rss = NULL;
   17258 
   17259 	if (zone->rss_raw != NULL) {
   17260 		dns_zone_detach(&zone->rss_raw);
   17261 	}
   17262 	if (result != ISC_R_SUCCESS) {
   17263 		LOCK_ZONE(zone);
   17264 		set_resigntime(zone);
   17265 		timenow = isc_time_now();
   17266 		zone_settimer(zone, &timenow);
   17267 		UNLOCK_ZONE(zone);
   17268 		if (result == DNS_R_UNCHANGED) {
   17269 			level = ISC_LOG_INFO;
   17270 		}
   17271 		dns_zone_log(zone, level, "receive_secure_serial: %s",
   17272 			     isc_result_totext(result));
   17273 	}
   17274 	if (tuple != NULL) {
   17275 		dns_difftuple_free(&tuple);
   17276 	}
   17277 	if (soatuple != NULL) {
   17278 		dns_difftuple_free(&soatuple);
   17279 	}
   17280 	if (zone->rss_db != NULL) {
   17281 		if (zone->rss_oldver != NULL) {
   17282 			dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
   17283 					    false);
   17284 		}
   17285 		if (zone->rss_newver != NULL) {
   17286 			dns_db_closeversion(zone->rss_db, &zone->rss_newver,
   17287 					    false);
   17288 		}
   17289 		dns_db_detach(&zone->rss_db);
   17290 	}
   17291 	INSIST(zone->rss_oldver == NULL);
   17292 	INSIST(zone->rss_newver == NULL);
   17293 	if (rjournal != NULL) {
   17294 		dns_journal_destroy(&rjournal);
   17295 	}
   17296 	dns_diff_clear(&zone->rss_diff);
   17297 
   17298 	dns_zone_idetach(&zone);
   17299 }
   17300 
   17301 static isc_result_t
   17302 zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
   17303 	struct rss *rss = NULL;
   17304 
   17305 	rss = isc_mem_get(zone->secure->mctx, sizeof(*rss));
   17306 	*rss = (struct rss){
   17307 		.serial = serial,
   17308 		.link = ISC_LINK_INITIALIZER,
   17309 	};
   17310 
   17311 	INSIST(LOCKED_ZONE(zone->secure));
   17312 	zone_iattach(zone->secure, &rss->zone);
   17313 	isc_async_run(zone->secure->loop, receive_secure_serial, rss);
   17314 
   17315 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
   17316 	return ISC_R_SUCCESS;
   17317 }
   17318 
   17319 static isc_result_t
   17320 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   17321 	       dns_name_t *name, dns_rdataset_t *rdataset, uint32_t oldserial) {
   17322 	dns_rdata_soa_t soa;
   17323 	dns_rdata_t rdata = DNS_RDATA_INIT;
   17324 	dns_rdatalist_t temprdatalist;
   17325 	dns_rdataset_t temprdataset;
   17326 	isc_buffer_t b;
   17327 	isc_result_t result;
   17328 	unsigned char buf[DNS_SOA_BUFFERSIZE];
   17329 
   17330 	result = dns_rdataset_first(rdataset);
   17331 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17332 	dns_rdataset_current(rdataset, &rdata);
   17333 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   17334 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17335 
   17336 	if (isc_serial_gt(soa.serial, oldserial)) {
   17337 		return dns_db_addrdataset(db, node, version, 0, rdataset, 0,
   17338 					  NULL);
   17339 	}
   17340 	/*
   17341 	 * Always bump the serial.
   17342 	 */
   17343 	oldserial++;
   17344 	if (oldserial == 0) {
   17345 		oldserial++;
   17346 	}
   17347 	soa.serial = oldserial;
   17348 
   17349 	/*
   17350 	 * Construct a replacement rdataset.
   17351 	 */
   17352 	dns_rdata_reset(&rdata);
   17353 	isc_buffer_init(&b, buf, sizeof(buf));
   17354 	result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
   17355 				      dns_rdatatype_soa, &soa, &b);
   17356 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17357 	dns_rdatalist_init(&temprdatalist);
   17358 	temprdatalist.rdclass = rdata.rdclass;
   17359 	temprdatalist.type = rdata.type;
   17360 	temprdatalist.ttl = rdataset->ttl;
   17361 	ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
   17362 
   17363 	dns_rdataset_init(&temprdataset);
   17364 	dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
   17365 
   17366 	dns_rdataset_getownercase(rdataset, name);
   17367 	dns_rdataset_setownercase(&temprdataset, name);
   17368 	return dns_db_addrdataset(db, node, version, 0, &temprdataset, 0, NULL);
   17369 }
   17370 
   17371 /*
   17372  * This function should populate an nsec3paramlist_t with the
   17373  * nsecparam_t data from a zone.
   17374  */
   17375 static isc_result_t
   17376 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
   17377 	isc_result_t result;
   17378 	dns_dbnode_t *node = NULL;
   17379 	dns_rdataset_t rdataset, prdataset;
   17380 	dns_dbversion_t *version = NULL;
   17381 	nsec3param_t *nsec3param = NULL;
   17382 	nsec3param_t *nsec3p = NULL;
   17383 	nsec3param_t *next;
   17384 	dns_db_t *db = NULL;
   17385 	unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   17386 
   17387 	REQUIRE(DNS_ZONE_VALID(zone));
   17388 	REQUIRE(nsec3list != NULL);
   17389 	REQUIRE(ISC_LIST_EMPTY(*nsec3list));
   17390 
   17391 	dns_rdataset_init(&rdataset);
   17392 	dns_rdataset_init(&prdataset);
   17393 
   17394 	dns_db_attach(zone->db, &db);
   17395 	CHECK(dns_db_getoriginnode(db, &node));
   17396 
   17397 	dns_db_currentversion(db, &version);
   17398 	result = dns_db_findrdataset(db, node, version,
   17399 				     dns_rdatatype_nsec3param,
   17400 				     dns_rdatatype_none, 0, &rdataset, NULL);
   17401 
   17402 	if (result != ISC_R_SUCCESS) {
   17403 		goto getprivate;
   17404 	}
   17405 
   17406 	/*
   17407 	 * Walk nsec3param rdataset making a list of parameters (note that
   17408 	 * multiple simultaneous nsec3 chains are annoyingly legal -- this
   17409 	 * is why we use an nsec3list, even though we will usually only
   17410 	 * have one).
   17411 	 */
   17412 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   17413 	     result = dns_rdataset_next(&rdataset))
   17414 	{
   17415 		dns_rdata_t rdata = DNS_RDATA_INIT;
   17416 		dns_rdata_t private = DNS_RDATA_INIT;
   17417 
   17418 		dns_rdataset_current(&rdataset, &rdata);
   17419 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   17420 			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   17421 			      "looping through nsec3param data");
   17422 		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
   17423 		ISC_LINK_INIT(nsec3param, link);
   17424 
   17425 		/*
   17426 		 * now transfer the data from the rdata to
   17427 		 * the nsec3param
   17428 		 */
   17429 		dns_nsec3param_toprivate(&rdata, &private, zone->privatetype,
   17430 					 nsec3param->data,
   17431 					 sizeof(nsec3param->data));
   17432 		nsec3param->length = private.length;
   17433 		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
   17434 	}
   17435 
   17436 getprivate:
   17437 	result = dns_db_findrdataset(db, node, version, zone->privatetype,
   17438 				     dns_rdatatype_none, 0, &prdataset, NULL);
   17439 	if (result != ISC_R_SUCCESS) {
   17440 		goto done;
   17441 	}
   17442 
   17443 	/*
   17444 	 * walk private type records, converting them to nsec3 parameters
   17445 	 * using dns_nsec3param_fromprivate(), do the right thing based on
   17446 	 * CREATE and REMOVE flags
   17447 	 */
   17448 	for (result = dns_rdataset_first(&prdataset); result == ISC_R_SUCCESS;
   17449 	     result = dns_rdataset_next(&prdataset))
   17450 	{
   17451 		dns_rdata_t rdata = DNS_RDATA_INIT;
   17452 		dns_rdata_t private = DNS_RDATA_INIT;
   17453 
   17454 		dns_rdataset_current(&prdataset, &private);
   17455 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   17456 			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   17457 			      "looping through nsec3param private data");
   17458 
   17459 		/*
   17460 		 * Do we have a valid private record?
   17461 		 */
   17462 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
   17463 						sizeof(buf)))
   17464 		{
   17465 			continue;
   17466 		}
   17467 
   17468 		/*
   17469 		 * Remove any NSEC3PARAM records scheduled to be removed.
   17470 		 */
   17471 		if (NSEC3REMOVE(rdata.data[1])) {
   17472 			/*
   17473 			 * Zero out the flags.
   17474 			 */
   17475 			rdata.data[1] = 0;
   17476 
   17477 			for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL;
   17478 			     nsec3p = next)
   17479 			{
   17480 				next = ISC_LIST_NEXT(nsec3p, link);
   17481 
   17482 				if (nsec3p->length ==
   17483 					    (unsigned int)rdata.length + 1 &&
   17484 				    memcmp(rdata.data, nsec3p->data + 1,
   17485 					   nsec3p->length - 1) == 0)
   17486 				{
   17487 					ISC_LIST_UNLINK(*nsec3list, nsec3p,
   17488 							link);
   17489 					isc_mem_put(zone->mctx, nsec3p,
   17490 						    sizeof(nsec3param_t));
   17491 				}
   17492 			}
   17493 			continue;
   17494 		}
   17495 
   17496 		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
   17497 		ISC_LINK_INIT(nsec3param, link);
   17498 
   17499 		/*
   17500 		 * Copy the remaining private records so the nsec/nsec3
   17501 		 * chain gets created.
   17502 		 */
   17503 		INSIST(private.length <= sizeof(nsec3param->data));
   17504 		memmove(nsec3param->data, private.data, private.length);
   17505 		nsec3param->length = private.length;
   17506 		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
   17507 	}
   17508 
   17509 done:
   17510 	if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND) {
   17511 		result = ISC_R_SUCCESS;
   17512 	}
   17513 
   17514 cleanup:
   17515 	if (node != NULL) {
   17516 		dns_db_detachnode(db, &node);
   17517 	}
   17518 	if (version != NULL) {
   17519 		dns_db_closeversion(db, &version, false);
   17520 	}
   17521 	if (db != NULL) {
   17522 		dns_db_detach(&db);
   17523 	}
   17524 	if (dns_rdataset_isassociated(&rdataset)) {
   17525 		dns_rdataset_disassociate(&rdataset);
   17526 	}
   17527 	if (dns_rdataset_isassociated(&prdataset)) {
   17528 		dns_rdataset_disassociate(&prdataset);
   17529 	}
   17530 	return result;
   17531 }
   17532 
   17533 /*
   17534  * Populate new zone db with private type records found by save_nsec3param().
   17535  */
   17536 static isc_result_t
   17537 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
   17538 		   nsec3paramlist_t *nsec3list) {
   17539 	isc_result_t result = ISC_R_SUCCESS;
   17540 	dns_diff_t diff;
   17541 	dns_rdata_t rdata;
   17542 	nsec3param_t *nsec3p = NULL;
   17543 	nsec3param_t *next;
   17544 
   17545 	REQUIRE(DNS_ZONE_VALID(zone));
   17546 	REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
   17547 
   17548 	dns_diff_init(zone->mctx, &diff);
   17549 
   17550 	/*
   17551 	 * Loop through the list of private-type records, set the INITIAL
   17552 	 * and CREATE flags, and the add the record to the apex of the tree
   17553 	 * in db.
   17554 	 */
   17555 	for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL; nsec3p = next)
   17556 	{
   17557 		next = ISC_LIST_NEXT(nsec3p, link);
   17558 		dns_rdata_init(&rdata);
   17559 		nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
   17560 		rdata.length = nsec3p->length;
   17561 		rdata.data = nsec3p->data;
   17562 		rdata.type = zone->privatetype;
   17563 		rdata.rdclass = zone->rdclass;
   17564 		result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
   17565 				       &zone->origin, 0, &rdata);
   17566 		if (result != ISC_R_SUCCESS) {
   17567 			break;
   17568 		}
   17569 	}
   17570 
   17571 	dns_diff_clear(&diff);
   17572 	return result;
   17573 }
   17574 
   17575 static isc_result_t
   17576 copy_non_dnssec_records(dns_db_t *db, dns_db_t *version, dns_db_t *rawdb,
   17577 			dns_dbiterator_t *dbiterator, unsigned int *oldserial) {
   17578 	dns_dbnode_t *rawnode = NULL, *node = NULL;
   17579 	dns_fixedname_t fixed;
   17580 	dns_name_t *name = dns_fixedname_initname(&fixed);
   17581 	dns_rdataset_t rdataset;
   17582 	dns_rdatasetiter_t *rdsit = NULL;
   17583 	isc_result_t result;
   17584 
   17585 	result = dns_dbiterator_current(dbiterator, &rawnode, name);
   17586 	if (result != ISC_R_SUCCESS) {
   17587 		return ISC_R_SUCCESS;
   17588 	}
   17589 
   17590 	dns_dbiterator_pause(dbiterator);
   17591 
   17592 	result = dns_db_findnode(db, name, true, &node);
   17593 	if (result != ISC_R_SUCCESS) {
   17594 		goto cleanup;
   17595 	}
   17596 
   17597 	result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, 0, &rdsit);
   17598 	if (result != ISC_R_SUCCESS) {
   17599 		goto cleanup;
   17600 	}
   17601 
   17602 	dns_rdataset_init(&rdataset);
   17603 
   17604 	for (result = dns_rdatasetiter_first(rdsit); result == ISC_R_SUCCESS;
   17605 	     result = dns_rdatasetiter_next(rdsit))
   17606 	{
   17607 		dns_rdatasetiter_current(rdsit, &rdataset);
   17608 		if (rdataset.type == dns_rdatatype_nsec ||
   17609 		    rdataset.type == dns_rdatatype_rrsig ||
   17610 		    rdataset.type == dns_rdatatype_nsec3 ||
   17611 		    rdataset.type == dns_rdatatype_nsec3param)
   17612 		{
   17613 			dns_rdataset_disassociate(&rdataset);
   17614 			continue;
   17615 		}
   17616 		/*
   17617 		 * Allow DNSKEY, CDNSKEY, CDS because users should be able to
   17618 		 * update the zone with these records from a different provider,
   17619 		 * and thus they may exist in the raw version of the zone.
   17620 		 */
   17621 
   17622 		if (rdataset.type == dns_rdatatype_soa && oldserial != NULL) {
   17623 			result = checkandaddsoa(db, node, version, name,
   17624 						&rdataset, *oldserial);
   17625 		} else {
   17626 			result = dns_db_addrdataset(db, node, version, 0,
   17627 						    &rdataset, 0, NULL);
   17628 		}
   17629 		dns_rdataset_disassociate(&rdataset);
   17630 		if (result != ISC_R_SUCCESS) {
   17631 			goto cleanup;
   17632 		}
   17633 	}
   17634 	if (result == ISC_R_NOMORE) {
   17635 		result = ISC_R_SUCCESS;
   17636 	}
   17637 
   17638 cleanup:
   17639 	if (rdsit != NULL) {
   17640 		dns_rdatasetiter_destroy(&rdsit);
   17641 	}
   17642 	if (rawnode) {
   17643 		dns_db_detachnode(rawdb, &rawnode);
   17644 	}
   17645 	if (node) {
   17646 		dns_db_detachnode(db, &node);
   17647 	}
   17648 	return result;
   17649 }
   17650 
   17651 static void
   17652 receive_secure_db(void *arg) {
   17653 	isc_result_t result;
   17654 	struct rss *rss = (struct rss *)arg;
   17655 	dns_zone_t *zone = rss->zone;
   17656 	dns_db_t *rawdb = rss->db, *db = NULL;
   17657 	dns_dbiterator_t *dbiterator = NULL;
   17658 	dns_dbversion_t *version = NULL;
   17659 	isc_time_t loadtime;
   17660 	unsigned int oldserial = 0, *oldserialp = NULL;
   17661 	nsec3paramlist_t nsec3list;
   17662 
   17663 	ISC_LIST_INIT(nsec3list);
   17664 
   17665 	LOCK_ZONE(zone);
   17666 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
   17667 		CHECK(ISC_R_SHUTTINGDOWN);
   17668 	}
   17669 
   17670 	loadtime = isc_time_now();
   17671 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   17672 	if (zone->db != NULL) {
   17673 		result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
   17674 		if (result == ISC_R_SUCCESS) {
   17675 			oldserialp = &oldserial;
   17676 		}
   17677 
   17678 		/*
   17679 		 * assemble nsec3parameters from the old zone, and set a flag
   17680 		 * if any are found
   17681 		 */
   17682 		result = save_nsec3param(zone, &nsec3list);
   17683 		if (result != ISC_R_SUCCESS) {
   17684 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   17685 			goto cleanup;
   17686 		}
   17687 	}
   17688 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   17689 
   17690 	CHECK(dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
   17691 			    dns_dbtype_zone, zone->rdclass, zone->db_argc - 1,
   17692 			    zone->db_argv + 1, &db));
   17693 
   17694 	result = dns_db_setgluecachestats(db, zone->gluecachestats);
   17695 	if (result != ISC_R_NOTIMPLEMENTED) {
   17696 		CHECK(result);
   17697 	}
   17698 
   17699 	CHECK(dns_db_newversion(db, &version));
   17700 	CHECK(dns_db_createiterator(rawdb, DNS_DB_NONSEC3, &dbiterator));
   17701 
   17702 	for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
   17703 	     result = dns_dbiterator_next(dbiterator))
   17704 	{
   17705 		CHECK(copy_non_dnssec_records(db, version, rawdb, dbiterator,
   17706 					      oldserialp));
   17707 	}
   17708 	dns_dbiterator_destroy(&dbiterator);
   17709 	if (result != ISC_R_NOMORE) {
   17710 		goto cleanup;
   17711 	}
   17712 
   17713 	/*
   17714 	 * Call restore_nsec3param() to create private-type records from
   17715 	 * the old nsec3 parameters and insert them into db
   17716 	 */
   17717 	if (!ISC_LIST_EMPTY(nsec3list)) {
   17718 		CHECK(restore_nsec3param(zone, db, version, &nsec3list));
   17719 	}
   17720 
   17721 	dns_db_closeversion(db, &version, true);
   17722 
   17723 	/*
   17724 	 * Lock hierarchy: zmgr, zone, raw.
   17725 	 */
   17726 	INSIST(zone != zone->raw);
   17727 	LOCK_ZONE(zone->raw);
   17728 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   17729 	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
   17730 	zone_needdump(zone, 0); /* XXXMPA */
   17731 	UNLOCK_ZONE(zone->raw);
   17732 
   17733 	/*
   17734 	 * Process any queued NSEC3PARAM change requests.
   17735 	 */
   17736 	process_zone_setnsec3param(zone);
   17737 
   17738 cleanup:
   17739 	UNLOCK_ZONE(zone);
   17740 	if (dbiterator != NULL) {
   17741 		dns_dbiterator_destroy(&dbiterator);
   17742 	}
   17743 	if (result != ISC_R_SUCCESS) {
   17744 		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
   17745 			     isc_result_totext(result));
   17746 	}
   17747 
   17748 	while (!ISC_LIST_EMPTY(nsec3list)) {
   17749 		nsec3param_t *nsec3p;
   17750 		nsec3p = ISC_LIST_HEAD(nsec3list);
   17751 		ISC_LIST_UNLINK(nsec3list, nsec3p, link);
   17752 		isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
   17753 	}
   17754 	if (db != NULL) {
   17755 		if (version != NULL) {
   17756 			dns_db_closeversion(db, &version, false);
   17757 		}
   17758 		dns_db_detach(&db);
   17759 	}
   17760 
   17761 	dns_db_detach(&rawdb);
   17762 	isc_mem_put(zone->mctx, rss, sizeof(*rss));
   17763 	dns_zone_idetach(&zone);
   17764 
   17765 	INSIST(version == NULL);
   17766 }
   17767 
   17768 static isc_result_t
   17769 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
   17770 	struct rss *rss = NULL;
   17771 
   17772 	rss = isc_mem_get(zone->secure->mctx, sizeof(*rss));
   17773 	*rss = (struct rss){ .link = ISC_LINK_INITIALIZER };
   17774 
   17775 	INSIST(LOCKED_ZONE(zone->secure));
   17776 	zone_iattach(zone->secure, &rss->zone);
   17777 	dns_db_attach(db, &rss->db);
   17778 	isc_async_run(zone->secure->loop, receive_secure_db, rss);
   17779 
   17780 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
   17781 	return ISC_R_SUCCESS;
   17782 }
   17783 
   17784 isc_result_t
   17785 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
   17786 	isc_result_t result;
   17787 	dns_zone_t *secure = NULL;
   17788 
   17789 	REQUIRE(DNS_ZONE_VALID(zone));
   17790 again:
   17791 	LOCK_ZONE(zone);
   17792 	if (inline_raw(zone)) {
   17793 		secure = zone->secure;
   17794 		INSIST(secure != zone);
   17795 		TRYLOCK_ZONE(result, secure);
   17796 		if (result != ISC_R_SUCCESS) {
   17797 			UNLOCK_ZONE(zone);
   17798 			secure = NULL;
   17799 			isc_thread_yield();
   17800 			goto again;
   17801 		}
   17802 	}
   17803 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   17804 	result = zone_replacedb(zone, db, dump);
   17805 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   17806 	if (secure != NULL) {
   17807 		UNLOCK_ZONE(secure);
   17808 	}
   17809 	UNLOCK_ZONE(zone);
   17810 	return result;
   17811 }
   17812 
   17813 static isc_result_t
   17814 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
   17815 	dns_dbversion_t *ver;
   17816 	isc_result_t result;
   17817 	unsigned int soacount = 0;
   17818 	unsigned int nscount = 0;
   17819 
   17820 	/*
   17821 	 * 'zone' and 'zone->db' locked by caller.
   17822 	 */
   17823 	REQUIRE(DNS_ZONE_VALID(zone));
   17824 	REQUIRE(LOCKED_ZONE(zone));
   17825 	if (inline_raw(zone)) {
   17826 		REQUIRE(LOCKED_ZONE(zone->secure));
   17827 	}
   17828 
   17829 	result = zone_get_from_db(zone, db, &nscount, &soacount, NULL, NULL,
   17830 				  NULL, NULL, NULL, NULL, NULL);
   17831 	if (result == ISC_R_SUCCESS) {
   17832 		if (soacount != 1) {
   17833 			dns_zone_log(zone, ISC_LOG_ERROR, "has %d SOA records",
   17834 				     soacount);
   17835 			result = DNS_R_BADZONE;
   17836 		}
   17837 		if (nscount == 0 && zone->type != dns_zone_key) {
   17838 			dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
   17839 			result = DNS_R_BADZONE;
   17840 		}
   17841 		if (result != ISC_R_SUCCESS) {
   17842 			return result;
   17843 		}
   17844 	} else {
   17845 		dns_zone_log(zone, ISC_LOG_ERROR,
   17846 			     "retrieving SOA and NS records failed: %s",
   17847 			     isc_result_totext(result));
   17848 		return result;
   17849 	}
   17850 
   17851 	result = check_nsec3param(zone, db);
   17852 	if (result != ISC_R_SUCCESS) {
   17853 		return result;
   17854 	}
   17855 
   17856 	ver = NULL;
   17857 	dns_db_currentversion(db, &ver);
   17858 
   17859 	/*
   17860 	 * The initial version of a secondary zone is always dumped;
   17861 	 * subsequent versions may be journaled instead if this
   17862 	 * is enabled in the configuration.
   17863 	 */
   17864 	if (zone->db != NULL && zone->journal != NULL &&
   17865 	    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
   17866 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
   17867 	{
   17868 		uint32_t serial, oldserial;
   17869 
   17870 		dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
   17871 
   17872 		result = dns_db_getsoaserial(db, ver, &serial);
   17873 		if (result != ISC_R_SUCCESS) {
   17874 			dns_zone_log(zone, ISC_LOG_ERROR,
   17875 				     "ixfr-from-differences: unable to get "
   17876 				     "new serial");
   17877 			goto fail;
   17878 		}
   17879 
   17880 		/*
   17881 		 * This is checked in zone_postload() for primary zones.
   17882 		 */
   17883 		result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
   17884 					  &oldserial, NULL, NULL, NULL, NULL,
   17885 					  NULL);
   17886 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17887 		RUNTIME_CHECK(soacount > 0U);
   17888 		if ((zone->type == dns_zone_secondary ||
   17889 		     (zone->type == dns_zone_redirect &&
   17890 		      dns_remote_addresses(&zone->primaries) != NULL)) &&
   17891 		    !isc_serial_gt(serial, oldserial))
   17892 		{
   17893 			uint32_t serialmin, serialmax;
   17894 			serialmin = (oldserial + 1) & 0xffffffffU;
   17895 			serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
   17896 			dns_zone_log(zone, ISC_LOG_ERROR,
   17897 				     "ixfr-from-differences: failed: "
   17898 				     "new serial (%u) out of range [%u - %u]",
   17899 				     serial, serialmin, serialmax);
   17900 			result = ISC_R_RANGE;
   17901 			goto fail;
   17902 		}
   17903 
   17904 		result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
   17905 				     zone->journal);
   17906 		if (result != ISC_R_SUCCESS) {
   17907 			char strbuf[ISC_STRERRORSIZE];
   17908 			strerror_r(errno, strbuf, sizeof(strbuf));
   17909 			dns_zone_log(zone, ISC_LOG_ERROR,
   17910 				     "ixfr-from-differences: failed: "
   17911 				     "%s",
   17912 				     strbuf);
   17913 			goto fallback;
   17914 		}
   17915 		if (dump) {
   17916 			zone_needdump(zone, DNS_DUMP_DELAY);
   17917 		} else {
   17918 			zone_journal_compact(zone, zone->db, serial);
   17919 		}
   17920 		if (zone->type == dns_zone_primary && inline_raw(zone)) {
   17921 			zone_send_secureserial(zone, serial);
   17922 		}
   17923 	} else {
   17924 	fallback:
   17925 		if (dump && zone->masterfile != NULL) {
   17926 			/*
   17927 			 * If DNS_ZONEFLG_FORCEXFER was set we don't want
   17928 			 * to keep the old masterfile.
   17929 			 */
   17930 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
   17931 			    remove(zone->masterfile) < 0 && errno != ENOENT)
   17932 			{
   17933 				char strbuf[ISC_STRERRORSIZE];
   17934 				strerror_r(errno, strbuf, sizeof(strbuf));
   17935 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   17936 					      DNS_LOGMODULE_ZONE,
   17937 					      ISC_LOG_WARNING,
   17938 					      "unable to remove masterfile "
   17939 					      "'%s': '%s'",
   17940 					      zone->masterfile, strbuf);
   17941 			}
   17942 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) {
   17943 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
   17944 			} else {
   17945 				zone_needdump(zone, 0);
   17946 			}
   17947 		}
   17948 		if (dump && zone->journal != NULL) {
   17949 			/*
   17950 			 * The in-memory database just changed, and
   17951 			 * because 'dump' is set, it didn't change by
   17952 			 * being loaded from disk.  Also, we have not
   17953 			 * journaled diffs for this change.
   17954 			 * Therefore, the on-disk journal is missing
   17955 			 * the deltas for this change.	Since it can
   17956 			 * no longer be used to bring the zone
   17957 			 * up-to-date, it is useless and should be
   17958 			 * removed.
   17959 			 */
   17960 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   17961 				      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   17962 				      "removing journal file");
   17963 			if (remove(zone->journal) < 0 && errno != ENOENT) {
   17964 				char strbuf[ISC_STRERRORSIZE];
   17965 				strerror_r(errno, strbuf, sizeof(strbuf));
   17966 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   17967 					      DNS_LOGMODULE_ZONE,
   17968 					      ISC_LOG_WARNING,
   17969 					      "unable to remove journal "
   17970 					      "'%s': '%s'",
   17971 					      zone->journal, strbuf);
   17972 			}
   17973 		}
   17974 
   17975 		if (inline_raw(zone)) {
   17976 			zone_send_securedb(zone, db);
   17977 		}
   17978 	}
   17979 
   17980 	dns_db_closeversion(db, &ver, false);
   17981 
   17982 	dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
   17983 
   17984 	if (zone->db != NULL) {
   17985 		zone_detachdb(zone);
   17986 	}
   17987 	zone_attachdb(zone, db);
   17988 	dns_db_setloop(zone->db, zone->loop);
   17989 	dns_db_setmaxrrperset(zone->db, zone->maxrrperset);
   17990 	dns_db_setmaxtypepername(zone->db, zone->maxtypepername);
   17991 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
   17992 	return ISC_R_SUCCESS;
   17993 
   17994 fail:
   17995 	dns_db_closeversion(db, &ver, false);
   17996 	return result;
   17997 }
   17998 
   17999 /* The caller must hold the dblock as a writer. */
   18000 static void
   18001 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
   18002 	REQUIRE(zone->db == NULL && db != NULL);
   18003 
   18004 	dns_db_attach(db, &zone->db);
   18005 }
   18006 
   18007 /* The caller must hold the dblock as a writer. */
   18008 static void
   18009 zone_detachdb(dns_zone_t *zone) {
   18010 	REQUIRE(zone->db != NULL);
   18011 
   18012 	dns_zone_rpz_disable_db(zone, zone->db);
   18013 	dns_zone_catz_disable_db(zone, zone->db);
   18014 	dns_db_detach(&zone->db);
   18015 }
   18016 
   18017 static void
   18018 zone_xfrdone(dns_zone_t *zone, uint32_t *expireopt, isc_result_t result) {
   18019 	isc_time_t now, expiretime;
   18020 	bool again = false;
   18021 	unsigned int soacount;
   18022 	unsigned int nscount;
   18023 	uint32_t serial, refresh, retry, expire, minimum, soattl, oldexpire;
   18024 	isc_result_t xfrresult = result;
   18025 	bool free_needed;
   18026 	dns_zone_t *secure = NULL;
   18027 
   18028 	REQUIRE(DNS_ZONE_VALID(zone));
   18029 
   18030 	dns_zone_logc(
   18031 		zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
   18032 		expireopt == NULL ? "zone transfer finished: %s"
   18033 				  : "zone transfer finished: %s, expire=%u",
   18034 		isc_result_totext(result), expireopt != NULL ? *expireopt : 0);
   18035 
   18036 	/*
   18037 	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
   18038 	 * could result in a deadlock due to a LOR so we will spin if we
   18039 	 * can't obtain both locks.
   18040 	 */
   18041 again:
   18042 	LOCK_ZONE(zone);
   18043 	if (inline_raw(zone)) {
   18044 		secure = zone->secure;
   18045 		INSIST(secure != zone);
   18046 		TRYLOCK_ZONE(result, secure);
   18047 		if (result != ISC_R_SUCCESS) {
   18048 			UNLOCK_ZONE(zone);
   18049 			secure = NULL;
   18050 			isc_thread_yield();
   18051 			goto again;
   18052 		}
   18053 	}
   18054 
   18055 	INSIST(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH));
   18056 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   18057 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
   18058 
   18059 	now = isc_time_now();
   18060 	switch (xfrresult) {
   18061 	case ISC_R_SUCCESS:
   18062 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   18063 		FALLTHROUGH;
   18064 	case DNS_R_UPTODATE:
   18065 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER |
   18066 					       DNS_ZONEFLG_FIRSTREFRESH);
   18067 		/*
   18068 		 * Has the zone expired underneath us?
   18069 		 */
   18070 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   18071 		if (zone->db == NULL) {
   18072 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   18073 			goto same_primary;
   18074 		}
   18075 
   18076 		oldexpire = zone->expire;
   18077 
   18078 		/*
   18079 		 * Update the zone structure's data from the actual
   18080 		 * SOA received.
   18081 		 */
   18082 		nscount = 0;
   18083 		soacount = 0;
   18084 		INSIST(zone->db != NULL);
   18085 		result = zone_get_from_db(zone, zone->db, &nscount, &soacount,
   18086 					  &soattl, &serial, &refresh, &retry,
   18087 					  &expire, &minimum, NULL);
   18088 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   18089 		if (result == ISC_R_SUCCESS) {
   18090 			if (soacount != 1) {
   18091 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18092 					      ISC_LOG_ERROR,
   18093 					      "transferred zone "
   18094 					      "has %d SOA records",
   18095 					      soacount);
   18096 				if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
   18097 				{
   18098 					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
   18099 					zone->retry = DNS_ZONE_DEFAULTRETRY;
   18100 				}
   18101 				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   18102 				zone_unload(zone);
   18103 				goto next_primary;
   18104 			}
   18105 			if (nscount == 0) {
   18106 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18107 					      ISC_LOG_ERROR,
   18108 					      "transferred zone "
   18109 					      "has no NS records");
   18110 				if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
   18111 				{
   18112 					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
   18113 					zone->retry = DNS_ZONE_DEFAULTRETRY;
   18114 				}
   18115 				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   18116 				zone_unload(zone);
   18117 				goto next_primary;
   18118 			}
   18119 			zone->refresh = RANGE(refresh, zone->minrefresh,
   18120 					      zone->maxrefresh);
   18121 			zone->retry = RANGE(retry, zone->minretry,
   18122 					    zone->maxretry);
   18123 			zone->expire = RANGE(expire,
   18124 					     zone->refresh + zone->retry,
   18125 					     DNS_MAX_EXPIRE);
   18126 			zone->soattl = soattl;
   18127 			zone->minimum = minimum;
   18128 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   18129 		}
   18130 
   18131 		/*
   18132 		 * Set our next refresh time.
   18133 		 */
   18134 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
   18135 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   18136 			zone->refreshtime = now;
   18137 		} else {
   18138 			DNS_ZONE_JITTER_ADD(&now, zone->refresh,
   18139 					    &zone->refreshtime);
   18140 		}
   18141 
   18142 		/*
   18143 		 * Set our next expire time. If the parent returned
   18144 		 * an EXPIRE option use that to update zone->expiretime.
   18145 		 */
   18146 		expire = zone->expire;
   18147 		if (expireopt != NULL && *expireopt < expire) {
   18148 			expire = *expireopt;
   18149 		}
   18150 		DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
   18151 		if (oldexpire != zone->expire ||
   18152 		    isc_time_compare(&expiretime, &zone->expiretime) > 0)
   18153 		{
   18154 			zone->expiretime = expiretime;
   18155 		}
   18156 
   18157 		/*
   18158 		 * Set loadtime.
   18159 		 */
   18160 		zone->loadtime = now;
   18161 
   18162 		if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
   18163 			char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
   18164 			if (zone->tsigkey != NULL) {
   18165 				char namebuf[DNS_NAME_FORMATSIZE];
   18166 				dns_name_format(zone->tsigkey->name, namebuf,
   18167 						sizeof(namebuf));
   18168 				snprintf(buf, sizeof(buf), ": TSIG '%s'",
   18169 					 namebuf);
   18170 			} else {
   18171 				buf[0] = '\0';
   18172 			}
   18173 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18174 				      ISC_LOG_INFO, "transferred serial %u%s",
   18175 				      serial, buf);
   18176 			if (inline_raw(zone)) {
   18177 				zone_send_secureserial(zone, serial);
   18178 			}
   18179 		}
   18180 
   18181 		/*
   18182 		 * This is not necessary if we just performed a AXFR
   18183 		 * however it is necessary for an IXFR / UPTODATE and
   18184 		 * won't hurt with an AXFR.
   18185 		 */
   18186 		if (zone->masterfile != NULL || zone->journal != NULL) {
   18187 			unsigned int delay = DNS_DUMP_DELAY;
   18188 			isc_interval_t i;
   18189 			isc_time_t when;
   18190 
   18191 			/*
   18192 			 * Compute effective modification time.
   18193 			 */
   18194 			isc_interval_set(&i, zone->expire, 0);
   18195 			result = isc_time_subtract(&zone->expiretime, &i,
   18196 						   &when);
   18197 			if (result != ISC_R_SUCCESS) {
   18198 				when = now;
   18199 			}
   18200 
   18201 			result = ISC_R_FAILURE;
   18202 			if (zone->journal != NULL) {
   18203 				result = isc_file_settime(zone->journal, &when);
   18204 			}
   18205 			if (result != ISC_R_SUCCESS && zone->masterfile != NULL)
   18206 			{
   18207 				result = isc_file_settime(zone->masterfile,
   18208 							  &when);
   18209 			}
   18210 
   18211 			if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
   18212 			    result == ISC_R_FILENOTFOUND)
   18213 			{
   18214 				delay = 0;
   18215 			}
   18216 
   18217 			if ((result == ISC_R_SUCCESS ||
   18218 			     result == ISC_R_FILENOTFOUND) &&
   18219 			    zone->masterfile != NULL)
   18220 			{
   18221 				zone_needdump(zone, delay);
   18222 			} else if (result != ISC_R_SUCCESS) {
   18223 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18224 					      ISC_LOG_ERROR,
   18225 					      "transfer: could not set file "
   18226 					      "modification time of '%s': %s",
   18227 					      zone->masterfile,
   18228 					      isc_result_totext(result));
   18229 			}
   18230 		}
   18231 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
   18232 		inc_stats(zone, dns_zonestatscounter_xfrsuccess);
   18233 		break;
   18234 
   18235 	case DNS_R_BADIXFR:
   18236 		/* Force retry with AXFR. */
   18237 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOIXFR);
   18238 		goto same_primary;
   18239 
   18240 	case DNS_R_TOOMANYRECORDS:
   18241 	case DNS_R_VERIFYFAILURE:
   18242 		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
   18243 		inc_stats(zone, dns_zonestatscounter_xfrfail);
   18244 		break;
   18245 
   18246 	case ISC_R_SHUTTINGDOWN:
   18247 		dns_remote_reset(&zone->primaries, true);
   18248 		break;
   18249 
   18250 	default:
   18251 	next_primary:
   18252 		/*
   18253 		 * Skip to next failed / untried primary.
   18254 		 */
   18255 		dns_remote_next(&zone->primaries, true);
   18256 	same_primary:
   18257 		if (dns_remote_done(&zone->primaries)) {
   18258 			dns_remote_reset(&zone->primaries, false);
   18259 		} else {
   18260 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
   18261 			again = true;
   18262 		}
   18263 		inc_stats(zone, dns_zonestatscounter_xfrfail);
   18264 		break;
   18265 	}
   18266 	zone_settimer(zone, &now);
   18267 
   18268 	/*
   18269 	 * We are called as the done callback of a zone
   18270 	 * transfer object that just entered its shutting-down state or
   18271 	 * failed to start.  Since we are no longer responsible for shutting
   18272 	 * it down, we can detach our reference.
   18273 	 */
   18274 	if (zone->xfr != NULL) {
   18275 		dns_xfrin_detach(&zone->xfr);
   18276 	}
   18277 
   18278 	if (zone->tsigkey != NULL) {
   18279 		dns_tsigkey_detach(&zone->tsigkey);
   18280 	}
   18281 
   18282 	if (zone->transport != NULL) {
   18283 		dns_transport_detach(&zone->transport);
   18284 	}
   18285 
   18286 	/*
   18287 	 * Handle any deferred journal compaction.
   18288 	 */
   18289 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
   18290 		dns_db_t *db = NULL;
   18291 		if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
   18292 			zone_journal_compact(zone, db, zone->compact_serial);
   18293 			dns_db_detach(&db);
   18294 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
   18295 		}
   18296 	}
   18297 
   18298 	if (secure != NULL) {
   18299 		UNLOCK_ZONE(secure);
   18300 	}
   18301 	/*
   18302 	 * This transfer finishing freed up a transfer quota slot.
   18303 	 * Let any other zones waiting for quota have it.
   18304 	 */
   18305 	if (zone->zmgr != NULL &&
   18306 	    zone->statelist == &zone->zmgr->xfrin_in_progress)
   18307 	{
   18308 		UNLOCK_ZONE(zone);
   18309 		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   18310 		ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
   18311 		zone->statelist = NULL;
   18312 		zmgr_resume_xfrs(zone->zmgr, false);
   18313 		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   18314 		LOCK_ZONE(zone);
   18315 	}
   18316 
   18317 	/*
   18318 	 * Retry with a different server if necessary.
   18319 	 */
   18320 	if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   18321 		queue_soa_query(zone);
   18322 	}
   18323 
   18324 	isc_refcount_decrement(&zone->irefs);
   18325 	free_needed = exit_check(zone);
   18326 	UNLOCK_ZONE(zone);
   18327 	if (free_needed) {
   18328 		zone_free(zone);
   18329 	}
   18330 }
   18331 
   18332 static void
   18333 zone_loaddone(void *arg, isc_result_t result) {
   18334 	dns_load_t *load = arg;
   18335 	dns_zone_t *zone;
   18336 	isc_result_t tresult;
   18337 	dns_zone_t *secure = NULL;
   18338 
   18339 	zone = load->zone;
   18340 
   18341 	ENTER;
   18342 
   18343 	/*
   18344 	 * If zone loading failed, remove the update db callbacks prior
   18345 	 * to calling the list of callbacks in the zone load structure.
   18346 	 */
   18347 	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
   18348 		dns_zone_rpz_disable_db(zone, load->db);
   18349 		dns_zone_catz_disable_db(zone, load->db);
   18350 	}
   18351 
   18352 	tresult = dns_db_endload(load->db, &load->callbacks);
   18353 	if (tresult != ISC_R_SUCCESS &&
   18354 	    (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
   18355 	{
   18356 		result = tresult;
   18357 	}
   18358 
   18359 	/*
   18360 	 * Lock hierarchy: zmgr, zone, raw.
   18361 	 */
   18362 again:
   18363 	LOCK_ZONE(zone);
   18364 	INSIST(zone != zone->raw);
   18365 	if (inline_secure(zone)) {
   18366 		LOCK_ZONE(zone->raw);
   18367 	} else if (inline_raw(zone)) {
   18368 		secure = zone->secure;
   18369 		TRYLOCK_ZONE(tresult, secure);
   18370 		if (tresult != ISC_R_SUCCESS) {
   18371 			UNLOCK_ZONE(zone);
   18372 			secure = NULL;
   18373 			isc_thread_yield();
   18374 			goto again;
   18375 		}
   18376 	}
   18377 	(void)zone_postload(zone, load->db, load->loadtime, result);
   18378 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
   18379 	zone_idetach(&load->callbacks.zone);
   18380 	/*
   18381 	 * Leave the zone frozen if the reload fails.
   18382 	 */
   18383 	if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
   18384 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
   18385 	{
   18386 		zone->update_disabled = false;
   18387 	}
   18388 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
   18389 	if (inline_secure(zone)) {
   18390 		UNLOCK_ZONE(zone->raw);
   18391 	} else if (secure != NULL) {
   18392 		UNLOCK_ZONE(secure);
   18393 	}
   18394 	UNLOCK_ZONE(zone);
   18395 
   18396 	dns_db_detach(&load->db);
   18397 	if (zone->loadctx != NULL) {
   18398 		dns_loadctx_detach(&zone->loadctx);
   18399 	}
   18400 	isc_mem_put(zone->mctx, load, sizeof(*load));
   18401 
   18402 	dns_zone_idetach(&zone);
   18403 }
   18404 
   18405 void
   18406 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
   18407 	REQUIRE(DNS_ZONE_VALID(zone));
   18408 	REQUIRE(table != NULL);
   18409 	REQUIRE(*table == NULL);
   18410 
   18411 	LOCK_ZONE(zone);
   18412 	if (zone->ssutable != NULL) {
   18413 		dns_ssutable_attach(zone->ssutable, table);
   18414 	}
   18415 	UNLOCK_ZONE(zone);
   18416 }
   18417 
   18418 void
   18419 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
   18420 	REQUIRE(DNS_ZONE_VALID(zone));
   18421 
   18422 	LOCK_ZONE(zone);
   18423 	if (zone->ssutable != NULL) {
   18424 		dns_ssutable_detach(&zone->ssutable);
   18425 	}
   18426 	if (table != NULL) {
   18427 		dns_ssutable_attach(table, &zone->ssutable);
   18428 	}
   18429 	UNLOCK_ZONE(zone);
   18430 }
   18431 
   18432 void
   18433 dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
   18434 	REQUIRE(DNS_ZONE_VALID(zone));
   18435 
   18436 	zone->sigvalidityinterval = interval;
   18437 }
   18438 
   18439 uint32_t
   18440 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
   18441 	REQUIRE(DNS_ZONE_VALID(zone));
   18442 
   18443 	return zone->sigvalidityinterval;
   18444 }
   18445 
   18446 void
   18447 dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
   18448 	REQUIRE(DNS_ZONE_VALID(zone));
   18449 
   18450 	zone->keyvalidityinterval = interval;
   18451 }
   18452 
   18453 uint32_t
   18454 dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
   18455 	REQUIRE(DNS_ZONE_VALID(zone));
   18456 
   18457 	return zone->keyvalidityinterval;
   18458 }
   18459 
   18460 void
   18461 dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
   18462 	isc_time_t now;
   18463 
   18464 	REQUIRE(DNS_ZONE_VALID(zone));
   18465 
   18466 	LOCK_ZONE(zone);
   18467 	zone->sigresigninginterval = interval;
   18468 	set_resigntime(zone);
   18469 	if (zone->loop != NULL) {
   18470 		now = isc_time_now();
   18471 		zone_settimer(zone, &now);
   18472 	}
   18473 	UNLOCK_ZONE(zone);
   18474 }
   18475 
   18476 uint32_t
   18477 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
   18478 	REQUIRE(DNS_ZONE_VALID(zone));
   18479 
   18480 	return zone->sigresigninginterval;
   18481 }
   18482 
   18483 void
   18484 dns_zone_getsourceaddr(dns_zone_t *zone, isc_sockaddr_t *sourceaddr) {
   18485 	REQUIRE(DNS_ZONE_VALID(zone));
   18486 	REQUIRE(sourceaddr != NULL);
   18487 
   18488 	LOCK_ZONE(zone);
   18489 	INSIST(dns_remote_count(&zone->primaries) > 0);
   18490 	*sourceaddr = zone->sourceaddr;
   18491 	UNLOCK_ZONE(zone);
   18492 }
   18493 
   18494 isc_result_t
   18495 dns_zone_getprimaryaddr(dns_zone_t *zone, isc_sockaddr_t *primaryaddr) {
   18496 	isc_result_t result = ISC_R_NOMORE;
   18497 
   18498 	REQUIRE(DNS_ZONE_VALID(zone));
   18499 	REQUIRE(primaryaddr != NULL);
   18500 
   18501 	LOCK_ZONE(zone);
   18502 	INSIST(dns_remote_count(&zone->primaries) > 0);
   18503 	if (!dns_remote_done(&zone->primaries)) {
   18504 		*primaryaddr = dns_remote_curraddr(&zone->primaries);
   18505 		result = ISC_R_SUCCESS;
   18506 	}
   18507 	UNLOCK_ZONE(zone);
   18508 
   18509 	return result;
   18510 }
   18511 
   18512 isc_time_t
   18513 dns_zone_getxfrintime(dns_zone_t *zone) {
   18514 	isc_time_t xfrintime;
   18515 
   18516 	REQUIRE(DNS_ZONE_VALID(zone));
   18517 
   18518 	LOCK_ZONE(zone);
   18519 	xfrintime = zone->xfrintime;
   18520 	UNLOCK_ZONE(zone);
   18521 
   18522 	return xfrintime;
   18523 }
   18524 
   18525 static void
   18526 queue_xfrin(dns_zone_t *zone) {
   18527 	isc_result_t result;
   18528 	dns_zonemgr_t *zmgr = zone->zmgr;
   18529 
   18530 	ENTER;
   18531 
   18532 	INSIST(zone->statelist == NULL);
   18533 
   18534 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   18535 	ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
   18536 	isc_refcount_increment0(&zone->irefs);
   18537 	zone->statelist = &zmgr->waiting_for_xfrin;
   18538 	result = zmgr_start_xfrin_ifquota(zmgr, zone);
   18539 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   18540 
   18541 	if (result == ISC_R_QUOTA) {
   18542 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   18543 			      "zone transfer deferred due to quota");
   18544 	} else if (result != ISC_R_SUCCESS) {
   18545 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
   18546 			      "starting zone transfer: %s",
   18547 			      isc_result_totext(result));
   18548 	}
   18549 }
   18550 
   18551 /*
   18552  * Get the transport type used for the SOA query to the current primary server
   18553  * before an ongoing incoming zone transfer.
   18554  *
   18555  * Requires:
   18556  *	The zone is locked by the caller.
   18557  */
   18558 static dns_transport_type_t
   18559 get_request_transport_type(dns_zone_t *zone) {
   18560 	dns_transport_type_t transport_type = DNS_TRANSPORT_NONE;
   18561 
   18562 	if (zone->transport != NULL) {
   18563 		transport_type = dns_transport_get_type(zone->transport);
   18564 	} else {
   18565 		transport_type = (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC))
   18566 					 ? DNS_TRANSPORT_TCP
   18567 					 : DNS_TRANSPORT_UDP;
   18568 
   18569 		/* Check if the peer is forced to always use TCP. */
   18570 		if (transport_type != DNS_TRANSPORT_TCP &&
   18571 		    !dns_remote_done(&zone->primaries))
   18572 		{
   18573 			isc_result_t result;
   18574 			isc_sockaddr_t primaryaddr;
   18575 			isc_netaddr_t primaryip;
   18576 			dns_peer_t *peer = NULL;
   18577 
   18578 			primaryaddr = dns_remote_curraddr(&zone->primaries);
   18579 			isc_netaddr_fromsockaddr(&primaryip, &primaryaddr);
   18580 			result = dns_peerlist_peerbyaddr(zone->view->peers,
   18581 							 &primaryip, &peer);
   18582 			if (result == ISC_R_SUCCESS && peer != NULL) {
   18583 				bool usetcp;
   18584 				result = dns_peer_getforcetcp(peer, &usetcp);
   18585 				if (result == ISC_R_SUCCESS && usetcp) {
   18586 					transport_type = DNS_TRANSPORT_TCP;
   18587 				}
   18588 			}
   18589 		}
   18590 	}
   18591 
   18592 	return transport_type;
   18593 }
   18594 
   18595 dns_transport_type_t
   18596 dns_zone_getrequesttransporttype(dns_zone_t *zone) {
   18597 	dns_transport_type_t transport_type;
   18598 
   18599 	REQUIRE(DNS_ZONE_VALID(zone));
   18600 
   18601 	LOCK_ZONE(zone);
   18602 	transport_type = get_request_transport_type(zone);
   18603 	UNLOCK_ZONE(zone);
   18604 
   18605 	return transport_type;
   18606 }
   18607 
   18608 /*
   18609  * This event callback is called when a zone has received
   18610  * any necessary zone transfer quota.  This is the time
   18611  * to go ahead and start the transfer.
   18612  */
   18613 static void
   18614 got_transfer_quota(void *arg) {
   18615 	dns_zone_t *zone = (dns_zone_t *)arg;
   18616 	isc_result_t result = ISC_R_SUCCESS;
   18617 	dns_peer_t *peer = NULL;
   18618 	char primary[ISC_SOCKADDR_FORMATSIZE];
   18619 	char source[ISC_SOCKADDR_FORMATSIZE];
   18620 	dns_rdatatype_t xfrtype;
   18621 	isc_netaddr_t primaryip;
   18622 	isc_sockaddr_t primaryaddr;
   18623 	isc_sockaddr_t sourceaddr;
   18624 	isc_time_t now;
   18625 	dns_transport_type_t soa_transport_type = DNS_TRANSPORT_NONE;
   18626 	const char *soa_before = "";
   18627 	bool loaded;
   18628 	isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
   18629 	dns_xfrin_t *xfr = NULL;
   18630 
   18631 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   18632 		zone_xfrdone(zone, NULL, ISC_R_CANCELED);
   18633 		return;
   18634 	}
   18635 
   18636 	now = isc_time_now();
   18637 
   18638 	primaryaddr = dns_remote_curraddr(&zone->primaries);
   18639 	isc_sockaddr_format(&primaryaddr, primary, sizeof(primary));
   18640 	if (dns_zonemgr_unreachable(zone->zmgr, &primaryaddr, &zone->sourceaddr,
   18641 				    &now))
   18642 	{
   18643 		isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   18644 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   18645 			      "got_transfer_quota: skipping zone transfer as "
   18646 			      "primary %s (source %s) is unreachable (cached)",
   18647 			      primary, source);
   18648 		zone_xfrdone(zone, NULL, ISC_R_CANCELED);
   18649 		return;
   18650 	}
   18651 
   18652 	isc_netaddr_fromsockaddr(&primaryip, &primaryaddr);
   18653 	(void)dns_peerlist_peerbyaddr(zone->view->peers, &primaryip, &peer);
   18654 
   18655 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
   18656 		soa_before = "SOA before ";
   18657 	}
   18658 	/*
   18659 	 * Decide whether we should request IXFR or AXFR.
   18660 	 */
   18661 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   18662 	loaded = (zone->db != NULL);
   18663 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   18664 
   18665 	if (!loaded) {
   18666 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
   18667 			      "no database exists yet, requesting AXFR of "
   18668 			      "initial version from %s",
   18669 			      primary);
   18670 		xfrtype = dns_rdatatype_axfr;
   18671 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
   18672 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
   18673 			      "forced reload, requesting AXFR of "
   18674 			      "initial version from %s",
   18675 			      primary);
   18676 		xfrtype = dns_rdatatype_axfr;
   18677 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOIXFR)) {
   18678 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
   18679 			      "retrying with AXFR from %s due to "
   18680 			      "previous IXFR failure",
   18681 			      primary);
   18682 		xfrtype = dns_rdatatype_axfr;
   18683 		LOCK_ZONE(zone);
   18684 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOIXFR);
   18685 		UNLOCK_ZONE(zone);
   18686 	} else {
   18687 		bool use_ixfr = true;
   18688 		if (peer != NULL) {
   18689 			result = dns_peer_getrequestixfr(peer, &use_ixfr);
   18690 		}
   18691 		if (peer == NULL || result != ISC_R_SUCCESS) {
   18692 			use_ixfr = zone->requestixfr;
   18693 		}
   18694 		if (!use_ixfr) {
   18695 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18696 				      ISC_LOG_DEBUG(1),
   18697 				      "IXFR disabled, "
   18698 				      "requesting %sAXFR from %s",
   18699 				      soa_before, primary);
   18700 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
   18701 				xfrtype = dns_rdatatype_soa;
   18702 			} else {
   18703 				xfrtype = dns_rdatatype_axfr;
   18704 			}
   18705 		} else {
   18706 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18707 				      ISC_LOG_DEBUG(1),
   18708 				      "requesting IXFR from %s", primary);
   18709 			xfrtype = dns_rdatatype_ixfr;
   18710 		}
   18711 	}
   18712 
   18713 	/*
   18714 	 * Determine if we should attempt to sign the request with TSIG.
   18715 	 */
   18716 	result = ISC_R_NOTFOUND;
   18717 
   18718 	/*
   18719 	 * First, look for a tsig key in the primaries statement, then
   18720 	 * try for a server key.
   18721 	 */
   18722 	if (dns_remote_keyname(&zone->primaries) != NULL) {
   18723 		dns_view_t *view = dns_zone_getview(zone);
   18724 		dns_name_t *keyname = dns_remote_keyname(&zone->primaries);
   18725 		result = dns_view_gettsig(view, keyname, &zone->tsigkey);
   18726 	}
   18727 	if (result != ISC_R_SUCCESS) {
   18728 		INSIST(zone->tsigkey == NULL);
   18729 		result = dns_view_getpeertsig(zone->view, &primaryip,
   18730 					      &zone->tsigkey);
   18731 	}
   18732 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   18733 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
   18734 			      "could not get TSIG key for zone transfer: %s",
   18735 			      isc_result_totext(result));
   18736 	}
   18737 
   18738 	/*
   18739 	 * Get the TLS transport for the primary, if configured.
   18740 	 */
   18741 	if (dns_remote_tlsname(&zone->primaries) != NULL) {
   18742 		dns_view_t *view = dns_zone_getview(zone);
   18743 		dns_name_t *tlsname = dns_remote_tlsname(&zone->primaries);
   18744 		result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
   18745 					       &zone->transport);
   18746 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   18747 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18748 				      ISC_LOG_ERROR,
   18749 				      "could not get TLS configuration for "
   18750 				      "zone transfer: %s",
   18751 				      isc_result_totext(result));
   18752 		}
   18753 	}
   18754 
   18755 	LOCK_ZONE(zone);
   18756 	if (xfrtype != dns_rdatatype_soa) {
   18757 		/*
   18758 		 * If 'xfrtype' is dns_rdatatype_soa, then the SOA query will be
   18759 		 * performed by xfrin, otherwise, the SOA request performed by
   18760 		 * soa_query() was successful and we should inform the xfrin
   18761 		 * about the transport type used for that query, so that the
   18762 		 * information can be presented in the statistics channel.
   18763 		 */
   18764 		soa_transport_type = get_request_transport_type(zone);
   18765 	}
   18766 	sourceaddr = zone->sourceaddr;
   18767 	UNLOCK_ZONE(zone);
   18768 
   18769 	INSIST(isc_sockaddr_pf(&primaryaddr) == isc_sockaddr_pf(&sourceaddr));
   18770 
   18771 	zmgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
   18772 
   18773 	dns_xfrin_create(zone, xfrtype, &primaryaddr, &sourceaddr,
   18774 			 zone->tsigkey, soa_transport_type, zone->transport,
   18775 			 zmgr_tlsctx_cache, zone->mctx, &xfr);
   18776 	INSIST(xfr != NULL);
   18777 
   18778 	isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
   18779 
   18780 	LOCK_ZONE(zone);
   18781 	if (zone->xfr != NULL) {
   18782 		dns_xfrin_detach(&zone->xfr);
   18783 	}
   18784 	dns_xfrin_attach(xfr, &zone->xfr);
   18785 	UNLOCK_ZONE(zone);
   18786 
   18787 	dns_xfrin_detach(&xfr);
   18788 
   18789 	/*
   18790 	 * Any failure in this function is handled like a failed
   18791 	 * zone transfer.  This ensures that we get removed from
   18792 	 * zmgr->xfrin_in_progress.
   18793 	 */
   18794 	result = dns_xfrin_start(zone->xfr, zone_xfrdone);
   18795 	if (result != ISC_R_SUCCESS) {
   18796 		zone_xfrdone(zone, NULL, result);
   18797 		return;
   18798 	}
   18799 
   18800 	LOCK_ZONE(zone);
   18801 	if (xfrtype == dns_rdatatype_axfr) {
   18802 		if (isc_sockaddr_pf(&primaryaddr) == PF_INET) {
   18803 			inc_stats(zone, dns_zonestatscounter_axfrreqv4);
   18804 		} else {
   18805 			inc_stats(zone, dns_zonestatscounter_axfrreqv6);
   18806 		}
   18807 	} else if (xfrtype == dns_rdatatype_ixfr) {
   18808 		if (isc_sockaddr_pf(&primaryaddr) == PF_INET) {
   18809 			inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
   18810 		} else {
   18811 			inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
   18812 		}
   18813 	}
   18814 	UNLOCK_ZONE(zone);
   18815 }
   18816 
   18817 /*
   18818  * Update forwarding support.
   18819  */
   18820 
   18821 static void
   18822 forward_destroy(dns_forward_t *forward) {
   18823 	forward->magic = 0;
   18824 	if (forward->request != NULL) {
   18825 		dns_request_destroy(&forward->request);
   18826 	}
   18827 	if (forward->msgbuf != NULL) {
   18828 		isc_buffer_free(&forward->msgbuf);
   18829 	}
   18830 	if (forward->transport != NULL) {
   18831 		dns_transport_detach(&forward->transport);
   18832 	}
   18833 	if (forward->zone != NULL) {
   18834 		LOCK(&forward->zone->lock);
   18835 		if (ISC_LINK_LINKED(forward, link)) {
   18836 			ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
   18837 		}
   18838 		UNLOCK(&forward->zone->lock);
   18839 		dns_zone_idetach(&forward->zone);
   18840 	}
   18841 	isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
   18842 }
   18843 
   18844 static isc_result_t
   18845 sendtoprimary(dns_forward_t *forward) {
   18846 	isc_result_t result;
   18847 	isc_sockaddr_t src, any;
   18848 	dns_zone_t *zone = forward->zone;
   18849 	bool tls_transport_invalid = false;
   18850 	isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
   18851 
   18852 	LOCK_ZONE(zone);
   18853 
   18854 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   18855 		UNLOCK_ZONE(zone);
   18856 		return ISC_R_CANCELED;
   18857 	}
   18858 
   18859 next:
   18860 	if (forward->which >= dns_remote_count(&forward->zone->primaries)) {
   18861 		UNLOCK_ZONE(zone);
   18862 		return ISC_R_NOMORE;
   18863 	}
   18864 
   18865 	forward->addr = dns_remote_addr(&zone->primaries, forward->which);
   18866 
   18867 	if (isc_sockaddr_disabled(&forward->addr)) {
   18868 		forward->which++;
   18869 		goto next;
   18870 	}
   18871 
   18872 	/*
   18873 	 * Always use TCP regardless of whether the original update
   18874 	 * used TCP.
   18875 	 * XXX The timeout may but a bit small if we are far down a
   18876 	 * transfer graph and have to try several primaries.
   18877 	 */
   18878 	switch (isc_sockaddr_pf(&forward->addr)) {
   18879 	case PF_INET:
   18880 		isc_sockaddr_any(&any);
   18881 		src = zone->primaries.sources[forward->which];
   18882 		if (isc_sockaddr_equal(&src, &any)) {
   18883 			src = zone->xfrsource4;
   18884 		}
   18885 		break;
   18886 	case PF_INET6:
   18887 		isc_sockaddr_any6(&any);
   18888 		src = zone->primaries.sources[forward->which];
   18889 		if (isc_sockaddr_equal(&src, &any)) {
   18890 			src = zone->xfrsource6;
   18891 		}
   18892 		break;
   18893 	default:
   18894 		result = ISC_R_NOTIMPLEMENTED;
   18895 		goto unlock;
   18896 	}
   18897 
   18898 	if (forward->transport != NULL) {
   18899 		dns_transport_detach(&forward->transport);
   18900 	}
   18901 
   18902 	if (dns_remote_tlsname(&zone->primaries) != NULL &&
   18903 	    zone->primaries.tlsnames[forward->which] != NULL)
   18904 	{
   18905 		dns_view_t *view = dns_zone_getview(zone);
   18906 		dns_name_t *tlsname = zone->primaries.tlsnames[forward->which];
   18907 
   18908 		result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
   18909 					       &forward->transport);
   18910 
   18911 		if (result != ISC_R_SUCCESS) {
   18912 			/* Log the error message when unlocked. */
   18913 			tls_transport_invalid = true;
   18914 			goto unlock;
   18915 		}
   18916 	}
   18917 
   18918 	zmgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
   18919 
   18920 	result = dns_request_createraw(
   18921 		forward->zone->view->requestmgr, forward->msgbuf, &src,
   18922 		&forward->addr, forward->transport, zmgr_tlsctx_cache,
   18923 		forward->options, 15 /* XXX */, 0, 0, forward->zone->loop,
   18924 		forward_callback, forward, &forward->request);
   18925 
   18926 	isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
   18927 
   18928 	if (result == ISC_R_SUCCESS) {
   18929 		if (!ISC_LINK_LINKED(forward, link)) {
   18930 			ISC_LIST_APPEND(zone->forwards, forward, link);
   18931 		}
   18932 	}
   18933 
   18934 unlock:
   18935 	UNLOCK_ZONE(zone);
   18936 
   18937 	if (tls_transport_invalid) {
   18938 		dns_zone_log(zone, ISC_LOG_ERROR,
   18939 			     "could not get TLS configuration "
   18940 			     "for dynamic update: %s",
   18941 			     isc_result_totext(result));
   18942 	}
   18943 
   18944 	return result;
   18945 }
   18946 
   18947 static void
   18948 forward_callback(void *arg) {
   18949 	dns_request_t *request = (dns_request_t *)arg;
   18950 	dns_forward_t *forward = dns_request_getarg(request);
   18951 	dns_message_t *msg = NULL;
   18952 	char primary[ISC_SOCKADDR_FORMATSIZE];
   18953 	isc_result_t result;
   18954 	dns_zone_t *zone;
   18955 
   18956 	INSIST(DNS_FORWARD_VALID(forward));
   18957 	zone = forward->zone;
   18958 	INSIST(DNS_ZONE_VALID(zone));
   18959 
   18960 	ENTER;
   18961 
   18962 	isc_sockaddr_format(&forward->addr, primary, sizeof(primary));
   18963 
   18964 	result = dns_request_getresult(request);
   18965 	if (result != ISC_R_SUCCESS) {
   18966 		dns_zone_log(zone, ISC_LOG_INFO,
   18967 			     "could not forward dynamic update to %s: %s",
   18968 			     primary, isc_result_totext(result));
   18969 		goto next_primary;
   18970 	}
   18971 
   18972 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
   18973 			   &msg);
   18974 
   18975 	result = dns_request_getresponse(request, msg,
   18976 					 DNS_MESSAGEPARSE_PRESERVEORDER |
   18977 						 DNS_MESSAGEPARSE_CLONEBUFFER);
   18978 	if (result != ISC_R_SUCCESS) {
   18979 		goto next_primary;
   18980 	}
   18981 
   18982 	/*
   18983 	 * Unexpected opcode.
   18984 	 */
   18985 	if (msg->opcode != dns_opcode_update) {
   18986 		char opcode[128];
   18987 		isc_buffer_t rb;
   18988 
   18989 		isc_buffer_init(&rb, opcode, sizeof(opcode));
   18990 		(void)dns_opcode_totext(msg->opcode, &rb);
   18991 
   18992 		dns_zone_log(zone, ISC_LOG_INFO,
   18993 			     "forwarding dynamic update: "
   18994 			     "unexpected opcode (%.*s) from %s",
   18995 			     (int)rb.used, opcode, primary);
   18996 		goto next_primary;
   18997 	}
   18998 
   18999 	switch (msg->rcode) {
   19000 	/*
   19001 	 * Pass these rcodes back to client.
   19002 	 */
   19003 	case dns_rcode_noerror:
   19004 	case dns_rcode_yxdomain:
   19005 	case dns_rcode_yxrrset:
   19006 	case dns_rcode_nxrrset:
   19007 	case dns_rcode_refused:
   19008 	case dns_rcode_nxdomain: {
   19009 		char rcode[128];
   19010 		isc_buffer_t rb;
   19011 
   19012 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   19013 		(void)dns_rcode_totext(msg->rcode, &rb);
   19014 		dns_zone_log(zone, ISC_LOG_INFO,
   19015 			     "forwarded dynamic update: "
   19016 			     "primary %s returned: %.*s",
   19017 			     primary, (int)rb.used, rcode);
   19018 		break;
   19019 	}
   19020 
   19021 	/* These should not occur if the primaries/zone are valid. */
   19022 	case dns_rcode_notzone:
   19023 	case dns_rcode_notauth: {
   19024 		char rcode[128];
   19025 		isc_buffer_t rb;
   19026 
   19027 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   19028 		(void)dns_rcode_totext(msg->rcode, &rb);
   19029 		dns_zone_log(zone, ISC_LOG_WARNING,
   19030 			     "forwarding dynamic update: "
   19031 			     "unexpected response: primary %s returned: %.*s",
   19032 			     primary, (int)rb.used, rcode);
   19033 		goto next_primary;
   19034 	}
   19035 
   19036 	/* Try another server for these rcodes. */
   19037 	case dns_rcode_formerr:
   19038 	case dns_rcode_servfail:
   19039 	case dns_rcode_notimp:
   19040 	case dns_rcode_badvers:
   19041 	default:
   19042 		goto next_primary;
   19043 	}
   19044 
   19045 	/* call callback */
   19046 	(forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
   19047 	msg = NULL;
   19048 	dns_request_destroy(&forward->request);
   19049 	forward_destroy(forward);
   19050 	return;
   19051 
   19052 next_primary:
   19053 	if (msg != NULL) {
   19054 		dns_message_detach(&msg);
   19055 	}
   19056 	forward->which++;
   19057 	dns_request_destroy(&forward->request);
   19058 	result = sendtoprimary(forward);
   19059 	if (result != ISC_R_SUCCESS) {
   19060 		/* call callback */
   19061 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   19062 			     "exhausted dynamic update forwarder list");
   19063 		(forward->callback)(forward->callback_arg, result, NULL);
   19064 		forward_destroy(forward);
   19065 	}
   19066 }
   19067 
   19068 isc_result_t
   19069 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
   19070 		       dns_updatecallback_t callback, void *callback_arg) {
   19071 	dns_forward_t *forward;
   19072 	isc_result_t result;
   19073 	isc_region_t *mr;
   19074 
   19075 	REQUIRE(DNS_ZONE_VALID(zone));
   19076 	REQUIRE(msg != NULL);
   19077 	REQUIRE(callback != NULL);
   19078 
   19079 	forward = isc_mem_get(zone->mctx, sizeof(*forward));
   19080 	*forward = (dns_forward_t){ .callback = callback,
   19081 				    .callback_arg = callback_arg,
   19082 				    .options = DNS_REQUESTOPT_TCP };
   19083 	ISC_LINK_INIT(forward, link);
   19084 	forward->magic = FORWARD_MAGIC;
   19085 
   19086 	/*
   19087 	 * If we have a SIG(0) signed message we need to preserve the
   19088 	 * query id as that is included in the SIG(0) computation.
   19089 	 */
   19090 	if (msg->sig0 != NULL) {
   19091 		forward->options |= DNS_REQUESTOPT_FIXEDID;
   19092 	}
   19093 
   19094 	mr = dns_message_getrawmessage(msg);
   19095 	if (mr == NULL) {
   19096 		result = ISC_R_UNEXPECTEDEND;
   19097 		goto cleanup;
   19098 	}
   19099 
   19100 	isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
   19101 	result = isc_buffer_copyregion(forward->msgbuf, mr);
   19102 	if (result != ISC_R_SUCCESS) {
   19103 		goto cleanup;
   19104 	}
   19105 
   19106 	isc_mem_attach(zone->mctx, &forward->mctx);
   19107 	dns_zone_iattach(zone, &forward->zone);
   19108 	result = sendtoprimary(forward);
   19109 
   19110 cleanup:
   19111 	if (result != ISC_R_SUCCESS) {
   19112 		forward_destroy(forward);
   19113 	}
   19114 	return result;
   19115 }
   19116 
   19117 isc_result_t
   19118 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
   19119 	REQUIRE(DNS_ZONE_VALID(zone));
   19120 	REQUIRE(next != NULL && *next == NULL);
   19121 
   19122 	*next = ISC_LIST_NEXT(zone, link);
   19123 	if (*next == NULL) {
   19124 		return ISC_R_NOMORE;
   19125 	} else {
   19126 		return ISC_R_SUCCESS;
   19127 	}
   19128 }
   19129 
   19130 isc_result_t
   19131 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
   19132 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19133 	REQUIRE(first != NULL && *first == NULL);
   19134 
   19135 	*first = ISC_LIST_HEAD(zmgr->zones);
   19136 	if (*first == NULL) {
   19137 		return ISC_R_NOMORE;
   19138 	} else {
   19139 		return ISC_R_SUCCESS;
   19140 	}
   19141 }
   19142 
   19143 /***
   19144  ***	Zone manager.
   19145  ***/
   19146 
   19147 static void
   19148 zonemgr_keymgmt_init(dns_zonemgr_t *zmgr) {
   19149 	dns_keymgmt_t *mgmt = isc_mem_get(zmgr->mctx, sizeof(*mgmt));
   19150 
   19151 	*mgmt = (dns_keymgmt_t){
   19152 		.magic = KEYMGMT_MAGIC,
   19153 	};
   19154 
   19155 	isc_mem_attach(zmgr->mctx, &mgmt->mctx);
   19156 	isc_rwlock_init(&mgmt->lock);
   19157 	isc_hashmap_create(mgmt->mctx, DNS_KEYMGMT_HASH_BITS, &mgmt->table);
   19158 
   19159 	zmgr->keymgmt = mgmt;
   19160 }
   19161 
   19162 static void
   19163 zonemgr_keymgmt_destroy(dns_zonemgr_t *zmgr) {
   19164 	dns_keymgmt_t *mgmt = zmgr->keymgmt;
   19165 
   19166 	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
   19167 
   19168 	mgmt->magic = 0;
   19169 
   19170 	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
   19171 	INSIST(isc_hashmap_count(mgmt->table) == 0);
   19172 	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
   19173 	isc_hashmap_destroy(&mgmt->table);
   19174 
   19175 	isc_rwlock_destroy(&mgmt->lock);
   19176 	isc_mem_putanddetach(&mgmt->mctx, mgmt, sizeof(dns_keymgmt_t));
   19177 }
   19178 
   19179 static bool
   19180 kfio_match(void *node, const void *key) {
   19181 	const dns_keyfileio_t *kfio = node;
   19182 
   19183 	return dns_name_equal(kfio->name, key);
   19184 }
   19185 
   19186 static void
   19187 zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
   19188 		    dns_keyfileio_t **added) {
   19189 	dns_keymgmt_t *mgmt = zmgr->keymgmt;
   19190 	dns_keyfileio_t *kfio = NULL;
   19191 	isc_result_t result;
   19192 	dns_fixedname_t fname;
   19193 	dns_name_t *name;
   19194 
   19195 	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
   19196 	REQUIRE(added != NULL && *added == NULL);
   19197 
   19198 	name = dns_fixedname_initname(&fname);
   19199 	dns_name_downcase(&zone->origin, name, NULL);
   19200 
   19201 	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
   19202 
   19203 	result = isc_hashmap_find(mgmt->table, dns_name_hash(name), kfio_match,
   19204 				  name, (void **)&kfio);
   19205 	switch (result) {
   19206 	case ISC_R_SUCCESS:
   19207 		isc_refcount_increment(&kfio->references);
   19208 		break;
   19209 	case ISC_R_NOTFOUND:
   19210 		kfio = isc_mem_get(mgmt->mctx, sizeof(*kfio));
   19211 		*kfio = (dns_keyfileio_t){
   19212 			.magic = KEYFILEIO_MAGIC,
   19213 		};
   19214 		isc_refcount_init(&kfio->references, 1);
   19215 		kfio->name = dns_fixedname_initname(&kfio->fname);
   19216 		dns_name_copy(name, kfio->name);
   19217 
   19218 		isc_mutex_init(&kfio->lock);
   19219 		result = isc_hashmap_add(mgmt->table, dns_name_hash(kfio->name),
   19220 					 kfio_match, kfio->name, kfio, NULL);
   19221 		INSIST(result == ISC_R_SUCCESS);
   19222 		break;
   19223 	default:
   19224 		UNREACHABLE();
   19225 	}
   19226 	*added = kfio;
   19227 	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
   19228 }
   19229 
   19230 static bool
   19231 match_ptr(void *node, const void *key) {
   19232 	return node == key;
   19233 }
   19234 
   19235 static void
   19236 zonemgr_keymgmt_delete(dns_zonemgr_t *zmgr, dns_keyfileio_t **deleted) {
   19237 	REQUIRE(DNS_KEYMGMT_VALID(zmgr->keymgmt));
   19238 	REQUIRE(deleted != NULL && DNS_KEYFILEIO_VALID(*deleted));
   19239 
   19240 	dns_keymgmt_t *mgmt = zmgr->keymgmt;
   19241 	dns_keyfileio_t *kfio = *deleted;
   19242 	isc_result_t result;
   19243 
   19244 	*deleted = NULL;
   19245 
   19246 	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
   19247 
   19248 	if (isc_refcount_decrement(&kfio->references) == 1) {
   19249 		isc_refcount_destroy(&kfio->references);
   19250 		kfio->magic = 0;
   19251 		isc_mutex_destroy(&kfio->lock);
   19252 
   19253 		result = isc_hashmap_delete(mgmt->table,
   19254 					    dns_name_hash(kfio->name),
   19255 					    match_ptr, kfio);
   19256 		INSIST(result == ISC_R_SUCCESS);
   19257 
   19258 		isc_mem_put(mgmt->mctx, kfio, sizeof(*kfio));
   19259 	}
   19260 
   19261 	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
   19262 }
   19263 
   19264 void
   19265 dns_zonemgr_create(isc_mem_t *mctx, isc_nm_t *netmgr, dns_zonemgr_t **zmgrp) {
   19266 	dns_zonemgr_t *zmgr = NULL;
   19267 	isc_loop_t *loop = isc_loop();
   19268 	isc_loopmgr_t *loopmgr = isc_loop_getloopmgr(loop);
   19269 
   19270 	REQUIRE(mctx != NULL);
   19271 	REQUIRE(netmgr != NULL);
   19272 	REQUIRE(zmgrp != NULL && *zmgrp == NULL);
   19273 
   19274 	zmgr = isc_mem_get(mctx, sizeof(*zmgr));
   19275 
   19276 	*zmgr = (dns_zonemgr_t){
   19277 		.loopmgr = loopmgr,
   19278 		.netmgr = netmgr,
   19279 		.workers = isc_loopmgr_nloops(loopmgr),
   19280 		.transfersin = 10,
   19281 		.transfersperns = 2,
   19282 	};
   19283 
   19284 	isc_refcount_init(&zmgr->refs, 1);
   19285 	isc_mem_attach(mctx, &zmgr->mctx);
   19286 
   19287 	ISC_LIST_INIT(zmgr->zones);
   19288 	ISC_LIST_INIT(zmgr->waiting_for_xfrin);
   19289 	ISC_LIST_INIT(zmgr->xfrin_in_progress);
   19290 	memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
   19291 	for (size_t i = 0; i < UNREACH_CACHE_SIZE; i++) {
   19292 		atomic_init(&zmgr->unreachable[i].expire, 0);
   19293 	}
   19294 	isc_rwlock_init(&zmgr->rwlock);
   19295 
   19296 	/* Unreachable lock. */
   19297 	isc_rwlock_init(&zmgr->urlock);
   19298 
   19299 	isc_ratelimiter_create(loop, &zmgr->checkdsrl);
   19300 	isc_ratelimiter_create(loop, &zmgr->notifyrl);
   19301 	isc_ratelimiter_create(loop, &zmgr->refreshrl);
   19302 	isc_ratelimiter_create(loop, &zmgr->startupnotifyrl);
   19303 	isc_ratelimiter_create(loop, &zmgr->startuprefreshrl);
   19304 
   19305 	zmgr->mctxpool = isc_mem_cget(zmgr->mctx, zmgr->workers,
   19306 				      sizeof(zmgr->mctxpool[0]));
   19307 	for (size_t i = 0; i < zmgr->workers; i++) {
   19308 		isc_mem_create(&zmgr->mctxpool[i]);
   19309 		isc_mem_setname(zmgr->mctxpool[i], "zonemgr-mctxpool");
   19310 	}
   19311 
   19312 	/* Key file I/O locks. */
   19313 	zonemgr_keymgmt_init(zmgr);
   19314 
   19315 	/* Default to 20 refresh queries / notifies / checkds per second. */
   19316 	setrl(zmgr->checkdsrl, &zmgr->checkdsrate, 20);
   19317 	setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
   19318 	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
   19319 	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
   19320 	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
   19321 	isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
   19322 	isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
   19323 
   19324 	zmgr->tlsctx_cache = NULL;
   19325 	isc_rwlock_init(&zmgr->tlsctx_cache_rwlock);
   19326 
   19327 	zmgr->magic = ZONEMGR_MAGIC;
   19328 
   19329 	*zmgrp = zmgr;
   19330 }
   19331 
   19332 isc_result_t
   19333 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
   19334 	isc_mem_t *mctx = NULL;
   19335 	dns_zone_t *zone = NULL;
   19336 	unsigned int tid;
   19337 
   19338 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19339 	REQUIRE(zonep != NULL && *zonep == NULL);
   19340 
   19341 	if (zmgr->mctxpool == NULL) {
   19342 		return ISC_R_FAILURE;
   19343 	}
   19344 
   19345 	tid = isc_random_uniform(zmgr->workers);
   19346 
   19347 	mctx = zmgr->mctxpool[tid];
   19348 	if (mctx == NULL) {
   19349 		return ISC_R_FAILURE;
   19350 	}
   19351 
   19352 	dns_zone_create(&zone, mctx, tid);
   19353 
   19354 	*zonep = zone;
   19355 
   19356 	return ISC_R_SUCCESS;
   19357 }
   19358 
   19359 isc_result_t
   19360 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
   19361 	REQUIRE(DNS_ZONE_VALID(zone));
   19362 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19363 
   19364 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19365 	LOCK_ZONE(zone);
   19366 	REQUIRE(zone->timer == NULL);
   19367 	REQUIRE(zone->zmgr == NULL);
   19368 
   19369 	isc_loop_t *loop = isc_loop_get(zmgr->loopmgr, zone->tid);
   19370 	isc_loop_attach(loop, &zone->loop);
   19371 
   19372 	zonemgr_keymgmt_add(zmgr, zone, &zone->kfio);
   19373 	INSIST(zone->kfio != NULL);
   19374 
   19375 	ISC_LIST_APPEND(zmgr->zones, zone, link);
   19376 	zone->zmgr = zmgr;
   19377 
   19378 	isc_refcount_increment(&zmgr->refs);
   19379 
   19380 	UNLOCK_ZONE(zone);
   19381 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19382 	return ISC_R_SUCCESS;
   19383 }
   19384 
   19385 void
   19386 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
   19387 	REQUIRE(DNS_ZONE_VALID(zone));
   19388 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19389 	REQUIRE(zone->zmgr == zmgr);
   19390 
   19391 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19392 	LOCK_ZONE(zone);
   19393 
   19394 	ISC_LIST_UNLINK(zmgr->zones, zone, link);
   19395 
   19396 	if (zone->kfio != NULL) {
   19397 		zonemgr_keymgmt_delete(zmgr, &zone->kfio);
   19398 		ENSURE(zone->kfio == NULL);
   19399 	}
   19400 
   19401 	if (zone->timer != NULL) {
   19402 		isc_refcount_decrement(&zone->irefs);
   19403 		isc_timer_destroy(&zone->timer);
   19404 	}
   19405 
   19406 	isc_loop_detach(&zone->loop);
   19407 
   19408 	/* Detach below, outside of the write lock. */
   19409 	zone->zmgr = NULL;
   19410 
   19411 	UNLOCK_ZONE(zone);
   19412 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19413 
   19414 	dns_zonemgr_detach(&zmgr);
   19415 }
   19416 
   19417 void
   19418 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
   19419 	REQUIRE(DNS_ZONEMGR_VALID(source));
   19420 	REQUIRE(target != NULL && *target == NULL);
   19421 
   19422 	isc_refcount_increment(&source->refs);
   19423 
   19424 	*target = source;
   19425 }
   19426 
   19427 void
   19428 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
   19429 	dns_zonemgr_t *zmgr;
   19430 
   19431 	REQUIRE(zmgrp != NULL);
   19432 	zmgr = *zmgrp;
   19433 	*zmgrp = NULL;
   19434 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19435 
   19436 	if (isc_refcount_decrement(&zmgr->refs) == 1) {
   19437 		zonemgr_free(zmgr);
   19438 	}
   19439 }
   19440 
   19441 isc_result_t
   19442 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
   19443 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19444 
   19445 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   19446 	for (dns_zone_t *zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
   19447 	     zone = ISC_LIST_NEXT(zone, link))
   19448 	{
   19449 		isc_time_t now;
   19450 
   19451 		LOCK_ZONE(zone);
   19452 		now = isc_time_now();
   19453 		zone_settimer(zone, &now);
   19454 		UNLOCK_ZONE(zone);
   19455 	}
   19456 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   19457 
   19458 	/*
   19459 	 * Recent configuration changes may have increased the
   19460 	 * amount of available transfers quota.  Make sure any
   19461 	 * transfers currently blocked on quota get started if
   19462 	 * possible.
   19463 	 */
   19464 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19465 	zmgr_resume_xfrs(zmgr, true);
   19466 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19467 	return ISC_R_SUCCESS;
   19468 }
   19469 
   19470 void
   19471 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
   19472 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19473 
   19474 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19475 	zmgr_resume_xfrs(zmgr, true);
   19476 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19477 }
   19478 
   19479 void
   19480 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
   19481 	dns_zone_t *zone;
   19482 
   19483 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19484 
   19485 	isc_ratelimiter_shutdown(zmgr->checkdsrl);
   19486 	isc_ratelimiter_shutdown(zmgr->notifyrl);
   19487 	isc_ratelimiter_shutdown(zmgr->refreshrl);
   19488 	isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
   19489 	isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
   19490 
   19491 	for (size_t i = 0; i < zmgr->workers; i++) {
   19492 		isc_mem_detach(&zmgr->mctxpool[i]);
   19493 	}
   19494 
   19495 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   19496 	for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
   19497 	     zone = ISC_LIST_NEXT(zone, link))
   19498 	{
   19499 		LOCK_ZONE(zone);
   19500 		forward_cancel(zone);
   19501 		UNLOCK_ZONE(zone);
   19502 	}
   19503 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   19504 }
   19505 
   19506 static void
   19507 zonemgr_free(dns_zonemgr_t *zmgr) {
   19508 	REQUIRE(ISC_LIST_EMPTY(zmgr->zones));
   19509 
   19510 	zmgr->magic = 0;
   19511 
   19512 	isc_refcount_destroy(&zmgr->refs);
   19513 	isc_ratelimiter_detach(&zmgr->checkdsrl);
   19514 	isc_ratelimiter_detach(&zmgr->notifyrl);
   19515 	isc_ratelimiter_detach(&zmgr->refreshrl);
   19516 	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
   19517 	isc_ratelimiter_detach(&zmgr->startuprefreshrl);
   19518 
   19519 	isc_mem_cput(zmgr->mctx, zmgr->mctxpool, zmgr->workers,
   19520 		     sizeof(zmgr->mctxpool[0]));
   19521 
   19522 	isc_rwlock_destroy(&zmgr->urlock);
   19523 	isc_rwlock_destroy(&zmgr->rwlock);
   19524 	isc_rwlock_destroy(&zmgr->tlsctx_cache_rwlock);
   19525 
   19526 	zonemgr_keymgmt_destroy(zmgr);
   19527 
   19528 	if (zmgr->tlsctx_cache != NULL) {
   19529 		isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
   19530 	}
   19531 	isc_mem_putanddetach(&zmgr->mctx, zmgr, sizeof(*zmgr));
   19532 }
   19533 
   19534 void
   19535 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
   19536 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19537 
   19538 	zmgr->transfersin = value;
   19539 }
   19540 
   19541 uint32_t
   19542 dns_zonemgr_gettransfersin(dns_zonemgr_t *zmgr) {
   19543 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19544 
   19545 	return zmgr->transfersin;
   19546 }
   19547 
   19548 void
   19549 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
   19550 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19551 
   19552 	zmgr->transfersperns = value;
   19553 }
   19554 
   19555 uint32_t
   19556 dns_zonemgr_gettransfersperns(dns_zonemgr_t *zmgr) {
   19557 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19558 
   19559 	return zmgr->transfersperns;
   19560 }
   19561 
   19562 /*
   19563  * Try to start a new incoming zone transfer to fill a quota
   19564  * slot that was just vacated.
   19565  *
   19566  * Requires:
   19567  *	The zone manager is locked by the caller.
   19568  */
   19569 static void
   19570 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
   19571 	dns_zone_t *zone;
   19572 	dns_zone_t *next;
   19573 
   19574 	for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); zone != NULL;
   19575 	     zone = next)
   19576 	{
   19577 		isc_result_t result;
   19578 		next = ISC_LIST_NEXT(zone, statelink);
   19579 		result = zmgr_start_xfrin_ifquota(zmgr, zone);
   19580 		if (result == ISC_R_SUCCESS) {
   19581 			if (multi) {
   19582 				continue;
   19583 			}
   19584 			/*
   19585 			 * We successfully filled the slot.  We're done.
   19586 			 */
   19587 			break;
   19588 		} else if (result == ISC_R_QUOTA) {
   19589 			/*
   19590 			 * Not enough quota.  This is probably the per-server
   19591 			 * quota, because we usually get called when a unit of
   19592 			 * global quota has just been freed.  Try the next
   19593 			 * zone, it may succeed if it uses another primary.
   19594 			 */
   19595 			continue;
   19596 		} else {
   19597 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   19598 				      ISC_LOG_DEBUG(1),
   19599 				      "starting zone transfer: %s",
   19600 				      isc_result_totext(result));
   19601 			break;
   19602 		}
   19603 	}
   19604 }
   19605 
   19606 /*
   19607  * Try to start an incoming zone transfer for 'zone', quota permitting.
   19608  *
   19609  * Requires:
   19610  *	The zone manager is locked by the caller.
   19611  *
   19612  * Returns:
   19613  *	ISC_R_SUCCESS	There was enough quota and we attempted to
   19614  *			start a transfer.  zone_xfrdone() has been or will
   19615  *			be called.
   19616  *	ISC_R_QUOTA	Not enough quota.
   19617  *	Others		Failure.
   19618  */
   19619 static isc_result_t
   19620 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
   19621 	dns_peer_t *peer = NULL;
   19622 	isc_netaddr_t primaryip;
   19623 	isc_sockaddr_t curraddr;
   19624 	uint32_t nxfrsin, nxfrsperns;
   19625 	dns_zone_t *x = NULL;
   19626 	uint32_t maxtransfersin, maxtransfersperns;
   19627 
   19628 	/*
   19629 	 * If we are exiting just pretend we got quota so the zone will
   19630 	 * be cleaned up in the zone's loop context.
   19631 	 */
   19632 	LOCK_ZONE(zone);
   19633 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   19634 		UNLOCK_ZONE(zone);
   19635 		goto gotquota;
   19636 	}
   19637 
   19638 	/*
   19639 	 * Find any configured information about the server we'd
   19640 	 * like to transfer this zone from.
   19641 	 */
   19642 	curraddr = dns_remote_curraddr(&zone->primaries);
   19643 	isc_netaddr_fromsockaddr(&primaryip, &curraddr);
   19644 	(void)dns_peerlist_peerbyaddr(zone->view->peers, &primaryip, &peer);
   19645 	UNLOCK_ZONE(zone);
   19646 
   19647 	/*
   19648 	 * Determine the total maximum number of simultaneous
   19649 	 * transfers allowed, and the maximum for this specific
   19650 	 * primary.
   19651 	 */
   19652 	maxtransfersin = zmgr->transfersin;
   19653 	maxtransfersperns = zmgr->transfersperns;
   19654 	if (peer != NULL) {
   19655 		(void)dns_peer_gettransfers(peer, &maxtransfersperns);
   19656 	}
   19657 
   19658 	/*
   19659 	 * Count the total number of transfers that are in progress,
   19660 	 * and the number of transfers in progress from this primary.
   19661 	 * We linearly scan a list of all transfers; if this turns
   19662 	 * out to be too slow, we could hash on the primary address.
   19663 	 */
   19664 	nxfrsin = nxfrsperns = 0;
   19665 	for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress); x != NULL;
   19666 	     x = ISC_LIST_NEXT(x, statelink))
   19667 	{
   19668 		isc_netaddr_t xip;
   19669 		isc_sockaddr_t xaddr;
   19670 
   19671 		LOCK_ZONE(x);
   19672 		xaddr = dns_remote_curraddr(&x->primaries);
   19673 		isc_netaddr_fromsockaddr(&xip, &xaddr);
   19674 		UNLOCK_ZONE(x);
   19675 
   19676 		nxfrsin++;
   19677 		if (isc_netaddr_equal(&xip, &primaryip)) {
   19678 			nxfrsperns++;
   19679 		}
   19680 	}
   19681 
   19682 	/* Enforce quota. */
   19683 	if (nxfrsin >= maxtransfersin) {
   19684 		return ISC_R_QUOTA;
   19685 	}
   19686 
   19687 	if (nxfrsperns >= maxtransfersperns) {
   19688 		return ISC_R_QUOTA;
   19689 	}
   19690 
   19691 gotquota:
   19692 	/*
   19693 	 * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
   19694 	 * list and start the actual transfer asynchronously.
   19695 	 */
   19696 	LOCK_ZONE(zone);
   19697 	INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
   19698 	ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
   19699 	ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
   19700 	zone->statelist = &zmgr->xfrin_in_progress;
   19701 	isc_async_run(zone->loop, got_transfer_quota, zone);
   19702 	dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   19703 		      "Transfer started.");
   19704 	UNLOCK_ZONE(zone);
   19705 
   19706 	return ISC_R_SUCCESS;
   19707 }
   19708 
   19709 static void
   19710 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
   19711 	char *buf;
   19712 	int buflen;
   19713 	isc_result_t result;
   19714 
   19715 	buflen = strlen(path) + strlen(templat) + 2;
   19716 
   19717 	buf = isc_mem_get(zone->mctx, buflen);
   19718 
   19719 	result = isc_file_template(path, templat, buf, buflen);
   19720 	if (result != ISC_R_SUCCESS) {
   19721 		goto cleanup;
   19722 	}
   19723 
   19724 	result = isc_file_renameunique(path, buf);
   19725 	if (result != ISC_R_SUCCESS) {
   19726 		goto cleanup;
   19727 	}
   19728 
   19729 	dns_zone_log(zone, ISC_LOG_WARNING,
   19730 		     "unable to load from '%s'; "
   19731 		     "renaming file to '%s' for failure analysis and "
   19732 		     "retransferring.",
   19733 		     path, buf);
   19734 
   19735 cleanup:
   19736 	isc_mem_put(zone->mctx, buf, buflen);
   19737 }
   19738 
   19739 static void
   19740 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
   19741 	isc_interval_t interval;
   19742 	uint32_t s, ns;
   19743 	uint32_t pertic;
   19744 
   19745 	if (value == 0) {
   19746 		value = 1;
   19747 	}
   19748 
   19749 	if (value == 1) {
   19750 		s = 1;
   19751 		ns = 0;
   19752 		pertic = 1;
   19753 	} else if (value <= 10) {
   19754 		s = 0;
   19755 		ns = 1000000000 / value;
   19756 		pertic = 1;
   19757 	} else {
   19758 		s = 0;
   19759 		ns = (1000000000 / value) * 10;
   19760 		pertic = 10;
   19761 	}
   19762 
   19763 	isc_interval_set(&interval, s, ns);
   19764 
   19765 	isc_ratelimiter_setinterval(rl, &interval);
   19766 	isc_ratelimiter_setpertic(rl, pertic);
   19767 
   19768 	*rate = value;
   19769 }
   19770 
   19771 void
   19772 dns_zonemgr_setcheckdsrate(dns_zonemgr_t *zmgr, unsigned int value) {
   19773 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19774 
   19775 	setrl(zmgr->checkdsrl, &zmgr->checkdsrate, value);
   19776 }
   19777 
   19778 void
   19779 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
   19780 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19781 
   19782 	setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
   19783 }
   19784 
   19785 void
   19786 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
   19787 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19788 
   19789 	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
   19790 }
   19791 
   19792 void
   19793 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
   19794 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19795 
   19796 	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
   19797 	/* XXXMPA separate out once we have the code to support this. */
   19798 	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
   19799 }
   19800 
   19801 unsigned int
   19802 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
   19803 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19804 
   19805 	return zmgr->notifyrate;
   19806 }
   19807 
   19808 unsigned int
   19809 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
   19810 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19811 
   19812 	return zmgr->startupnotifyrate;
   19813 }
   19814 
   19815 unsigned int
   19816 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
   19817 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19818 
   19819 	return zmgr->serialqueryrate;
   19820 }
   19821 
   19822 bool
   19823 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
   19824 			isc_sockaddr_t *local, isc_time_t *now) {
   19825 	unsigned int i;
   19826 	uint32_t seconds = isc_time_seconds(now);
   19827 	uint32_t count = 0;
   19828 
   19829 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19830 
   19831 	RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
   19832 	for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
   19833 		if (atomic_load(&zmgr->unreachable[i].expire) >= seconds &&
   19834 		    isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
   19835 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
   19836 		{
   19837 			atomic_store_relaxed(&zmgr->unreachable[i].last,
   19838 					     seconds);
   19839 			count = zmgr->unreachable[i].count;
   19840 			break;
   19841 		}
   19842 	}
   19843 	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
   19844 	return i < UNREACH_CACHE_SIZE && count > 1U;
   19845 }
   19846 
   19847 void
   19848 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
   19849 			   isc_sockaddr_t *local) {
   19850 	unsigned int i;
   19851 
   19852 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19853 
   19854 	RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
   19855 	for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
   19856 		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
   19857 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
   19858 		{
   19859 			atomic_store_relaxed(&zmgr->unreachable[i].expire, 0);
   19860 			break;
   19861 		}
   19862 	}
   19863 	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
   19864 }
   19865 
   19866 void
   19867 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
   19868 			   isc_sockaddr_t *local, isc_time_t *now) {
   19869 	uint32_t seconds = isc_time_seconds(now);
   19870 	uint32_t expire = 0, last = seconds;
   19871 	unsigned int slot = UNREACH_CACHE_SIZE, oldest = 0;
   19872 	bool update_entry = true;
   19873 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19874 
   19875 	RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
   19876 	for (unsigned int i = 0; i < UNREACH_CACHE_SIZE; i++) {
   19877 		/* Existing entry? */
   19878 		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
   19879 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
   19880 		{
   19881 			update_entry = false;
   19882 			slot = i;
   19883 			expire = atomic_load_relaxed(
   19884 				&zmgr->unreachable[i].expire);
   19885 			break;
   19886 		}
   19887 		/* Pick first empty slot? */
   19888 		if (atomic_load_relaxed(&zmgr->unreachable[i].expire) < seconds)
   19889 		{
   19890 			slot = i;
   19891 			break;
   19892 		}
   19893 		/* The worst case, least recently used slot? */
   19894 		if (atomic_load_relaxed(&zmgr->unreachable[i].last) < last) {
   19895 			last = atomic_load_relaxed(&zmgr->unreachable[i].last);
   19896 			oldest = i;
   19897 		}
   19898 	}
   19899 
   19900 	/* We haven't found any existing or free slots, use the oldest */
   19901 	if (slot == UNREACH_CACHE_SIZE) {
   19902 		slot = oldest;
   19903 	}
   19904 
   19905 	if (expire < seconds) {
   19906 		/* Expired or new entry, reset count to 1 */
   19907 		zmgr->unreachable[slot].count = 1;
   19908 	} else {
   19909 		zmgr->unreachable[slot].count++;
   19910 	}
   19911 	atomic_store_relaxed(&zmgr->unreachable[slot].expire,
   19912 			     seconds + UNREACH_HOLD_TIME);
   19913 	atomic_store_relaxed(&zmgr->unreachable[slot].last, seconds);
   19914 	if (update_entry) {
   19915 		zmgr->unreachable[slot].remote = *remote;
   19916 		zmgr->unreachable[slot].local = *local;
   19917 	}
   19918 
   19919 	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
   19920 }
   19921 
   19922 void
   19923 dns_zone_stopxfr(dns_zone_t *zone) {
   19924 	dns_xfrin_t *xfr = NULL;
   19925 
   19926 	REQUIRE(DNS_ZONE_VALID(zone));
   19927 
   19928 	RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
   19929 	LOCK_ZONE(zone);
   19930 	if (zone->statelist == &zone->zmgr->xfrin_in_progress &&
   19931 	    zone->xfr != NULL)
   19932 	{
   19933 		dns_xfrin_attach(zone->xfr, &xfr);
   19934 	}
   19935 	UNLOCK_ZONE(zone);
   19936 	RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
   19937 
   19938 	if (xfr != NULL) {
   19939 		dns_xfrin_shutdown(xfr);
   19940 		dns_xfrin_detach(&xfr);
   19941 	}
   19942 }
   19943 
   19944 void
   19945 dns_zone_forcexfr(dns_zone_t *zone) {
   19946 	REQUIRE(DNS_ZONE_VALID(zone));
   19947 
   19948 	if (zone->type == dns_zone_primary ||
   19949 	    (zone->type == dns_zone_redirect &&
   19950 	     dns_remote_addresses(&zone->primaries) == NULL))
   19951 	{
   19952 		return;
   19953 	}
   19954 
   19955 	LOCK_ZONE(zone);
   19956 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
   19957 	UNLOCK_ZONE(zone);
   19958 	dns_zone_refresh(zone);
   19959 }
   19960 
   19961 bool
   19962 dns_zone_isforced(dns_zone_t *zone) {
   19963 	REQUIRE(DNS_ZONE_VALID(zone));
   19964 
   19965 	return DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER);
   19966 }
   19967 
   19968 isc_result_t
   19969 dns_zone_setstatistics(dns_zone_t *zone, bool on) {
   19970 	/*
   19971 	 * This function is obsoleted.
   19972 	 */
   19973 	UNUSED(zone);
   19974 	UNUSED(on);
   19975 	return ISC_R_NOTIMPLEMENTED;
   19976 }
   19977 
   19978 uint64_t *
   19979 dns_zone_getstatscounters(dns_zone_t *zone) {
   19980 	/*
   19981 	 * This function is obsoleted.
   19982 	 */
   19983 	UNUSED(zone);
   19984 	return NULL;
   19985 }
   19986 
   19987 void
   19988 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
   19989 	REQUIRE(DNS_ZONE_VALID(zone));
   19990 	REQUIRE(zone->stats == NULL);
   19991 
   19992 	LOCK_ZONE(zone);
   19993 	zone->stats = NULL;
   19994 	isc_stats_attach(stats, &zone->stats);
   19995 	UNLOCK_ZONE(zone);
   19996 }
   19997 
   19998 void
   19999 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
   20000 	REQUIRE(DNS_ZONE_VALID(zone));
   20001 
   20002 	LOCK_ZONE(zone);
   20003 	if (zone->requeststats_on && stats == NULL) {
   20004 		zone->requeststats_on = false;
   20005 	} else if (!zone->requeststats_on && stats != NULL) {
   20006 		if (zone->requeststats == NULL) {
   20007 			isc_stats_attach(stats, &zone->requeststats);
   20008 		}
   20009 		zone->requeststats_on = true;
   20010 	}
   20011 	UNLOCK_ZONE(zone);
   20012 }
   20013 
   20014 void
   20015 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
   20016 	REQUIRE(DNS_ZONE_VALID(zone));
   20017 
   20018 	LOCK_ZONE(zone);
   20019 	if (zone->requeststats_on && stats != NULL) {
   20020 		if (zone->rcvquerystats == NULL) {
   20021 			dns_stats_attach(stats, &zone->rcvquerystats);
   20022 			zone->requeststats_on = true;
   20023 		}
   20024 	}
   20025 	UNLOCK_ZONE(zone);
   20026 }
   20027 
   20028 void
   20029 dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
   20030 	REQUIRE(DNS_ZONE_VALID(zone));
   20031 
   20032 	LOCK_ZONE(zone);
   20033 	if (stats != NULL && zone->dnssecsignstats == NULL) {
   20034 		dns_stats_attach(stats, &zone->dnssecsignstats);
   20035 	}
   20036 	UNLOCK_ZONE(zone);
   20037 }
   20038 
   20039 dns_stats_t *
   20040 dns_zone_getdnssecsignstats(dns_zone_t *zone) {
   20041 	REQUIRE(DNS_ZONE_VALID(zone));
   20042 
   20043 	return zone->dnssecsignstats;
   20044 }
   20045 
   20046 isc_stats_t *
   20047 dns_zone_getrequeststats(dns_zone_t *zone) {
   20048 	/*
   20049 	 * We don't lock zone for efficiency reason.  This is not catastrophic
   20050 	 * because requeststats must always be valid when requeststats_on is
   20051 	 * true.
   20052 	 * Some counters may be incremented while requeststats_on is becoming
   20053 	 * false, or some cannot be incremented just after the statistics are
   20054 	 * installed, but it shouldn't matter much in practice.
   20055 	 */
   20056 	if (zone->requeststats_on) {
   20057 		return zone->requeststats;
   20058 	} else {
   20059 		return NULL;
   20060 	}
   20061 }
   20062 
   20063 /*
   20064  * Return the received query stats bucket
   20065  * see note from dns_zone_getrequeststats()
   20066  */
   20067 dns_stats_t *
   20068 dns_zone_getrcvquerystats(dns_zone_t *zone) {
   20069 	if (zone->requeststats_on) {
   20070 		return zone->rcvquerystats;
   20071 	} else {
   20072 		return NULL;
   20073 	}
   20074 }
   20075 
   20076 void
   20077 dns_zone_dialup(dns_zone_t *zone) {
   20078 	REQUIRE(DNS_ZONE_VALID(zone));
   20079 
   20080 	zone_debuglog(zone, __func__, 3, "notify = %d, refresh = %d",
   20081 		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
   20082 		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
   20083 
   20084 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
   20085 		dns_zone_notify(zone, true);
   20086 	}
   20087 	if (zone->type != dns_zone_primary &&
   20088 	    dns_remote_addresses(&zone->primaries) != NULL &&
   20089 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
   20090 	{
   20091 		dns_zone_refresh(zone);
   20092 	}
   20093 }
   20094 
   20095 void
   20096 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
   20097 	REQUIRE(DNS_ZONE_VALID(zone));
   20098 
   20099 	LOCK_ZONE(zone);
   20100 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
   20101 				       DNS_ZONEFLG_DIALREFRESH |
   20102 				       DNS_ZONEFLG_NOREFRESH);
   20103 	switch (dialup) {
   20104 	case dns_dialuptype_no:
   20105 		break;
   20106 	case dns_dialuptype_yes:
   20107 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
   20108 					       DNS_ZONEFLG_DIALREFRESH |
   20109 					       DNS_ZONEFLG_NOREFRESH);
   20110 		break;
   20111 	case dns_dialuptype_notify:
   20112 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
   20113 		break;
   20114 	case dns_dialuptype_notifypassive:
   20115 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
   20116 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
   20117 		break;
   20118 	case dns_dialuptype_refresh:
   20119 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
   20120 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
   20121 		break;
   20122 	case dns_dialuptype_passive:
   20123 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
   20124 		break;
   20125 	default:
   20126 		UNREACHABLE();
   20127 	}
   20128 	UNLOCK_ZONE(zone);
   20129 }
   20130 
   20131 isc_result_t
   20132 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
   20133 	isc_result_t result = ISC_R_SUCCESS;
   20134 
   20135 	REQUIRE(DNS_ZONE_VALID(zone));
   20136 
   20137 	LOCK_ZONE(zone);
   20138 	result = dns_zone_setstring(zone, &zone->keydirectory, directory);
   20139 	UNLOCK_ZONE(zone);
   20140 
   20141 	return result;
   20142 }
   20143 
   20144 const char *
   20145 dns_zone_getkeydirectory(dns_zone_t *zone) {
   20146 	REQUIRE(DNS_ZONE_VALID(zone));
   20147 
   20148 	return zone->keydirectory;
   20149 }
   20150 
   20151 void
   20152 dns_zone_setkeystores(dns_zone_t *zone, dns_keystorelist_t *keystores) {
   20153 	REQUIRE(DNS_ZONE_VALID(zone));
   20154 
   20155 	LOCK_ZONE(zone);
   20156 	zone->keystores = keystores;
   20157 	UNLOCK_ZONE(zone);
   20158 }
   20159 
   20160 dns_keystorelist_t *
   20161 dns_zone_getkeystores(dns_zone_t *zone) {
   20162 	dns_keystorelist_t *ks = NULL;
   20163 
   20164 	REQUIRE(DNS_ZONE_VALID(zone));
   20165 
   20166 	LOCK_ZONE(zone);
   20167 	if (inline_raw(zone) && zone->secure != NULL) {
   20168 		ks = zone->secure->keystores;
   20169 	} else {
   20170 		ks = zone->keystores;
   20171 	}
   20172 	UNLOCK_ZONE(zone);
   20173 
   20174 	return ks;
   20175 }
   20176 
   20177 unsigned int
   20178 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, dns_zonestate_t state) {
   20179 	dns_zone_t *zone;
   20180 	unsigned int count = 0;
   20181 
   20182 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   20183 
   20184 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   20185 	switch (state) {
   20186 	case DNS_ZONESTATE_XFERRUNNING:
   20187 		for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
   20188 		     zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
   20189 		{
   20190 			count++;
   20191 		}
   20192 		break;
   20193 	case DNS_ZONESTATE_XFERDEFERRED:
   20194 		for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
   20195 		     zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
   20196 		{
   20197 			count++;
   20198 		}
   20199 		break;
   20200 	case DNS_ZONESTATE_XFERFIRSTREFRESH:
   20201 		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
   20202 		     zone = ISC_LIST_NEXT(zone, link))
   20203 		{
   20204 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIRSTREFRESH)) {
   20205 				count++;
   20206 			}
   20207 		}
   20208 		break;
   20209 	case DNS_ZONESTATE_SOAQUERY:
   20210 		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
   20211 		     zone = ISC_LIST_NEXT(zone, link))
   20212 		{
   20213 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
   20214 				count++;
   20215 			}
   20216 		}
   20217 		break;
   20218 	case DNS_ZONESTATE_ANY:
   20219 		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
   20220 		     zone = ISC_LIST_NEXT(zone, link))
   20221 		{
   20222 			dns_view_t *view = zone->view;
   20223 			if (view != NULL && strcmp(view->name, "_bind") == 0) {
   20224 				continue;
   20225 			}
   20226 			count++;
   20227 		}
   20228 		break;
   20229 	case DNS_ZONESTATE_AUTOMATIC:
   20230 		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
   20231 		     zone = ISC_LIST_NEXT(zone, link))
   20232 		{
   20233 			dns_view_t *view = zone->view;
   20234 			if (view != NULL && strcmp(view->name, "_bind") == 0) {
   20235 				continue;
   20236 			}
   20237 			if (zone->automatic) {
   20238 				count++;
   20239 			}
   20240 		}
   20241 		break;
   20242 	default:
   20243 		UNREACHABLE();
   20244 	}
   20245 
   20246 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   20247 
   20248 	return count;
   20249 }
   20250 
   20251 isc_result_t
   20252 dns_zone_getxfr(dns_zone_t *zone, dns_xfrin_t **xfrp, bool *is_firstrefresh,
   20253 		bool *is_running, bool *is_deferred, bool *is_presoa,
   20254 		bool *is_pending, bool *needs_refresh) {
   20255 	REQUIRE(DNS_ZONE_VALID(zone));
   20256 	REQUIRE(xfrp != NULL && *xfrp == NULL);
   20257 
   20258 	if (zone->zmgr == NULL) {
   20259 		return ISC_R_FAILURE;
   20260 	}
   20261 
   20262 	/* Reset. */
   20263 	*is_firstrefresh = false;
   20264 	*is_running = false;
   20265 	*is_deferred = false;
   20266 	*is_presoa = false;
   20267 	*is_pending = false;
   20268 	*needs_refresh = false;
   20269 
   20270 	RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
   20271 	LOCK_ZONE(zone);
   20272 	*is_firstrefresh = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIRSTREFRESH);
   20273 	if (zone->xfr != NULL) {
   20274 		dns_xfrin_attach(zone->xfr, xfrp);
   20275 	}
   20276 	if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
   20277 		*is_running = true;
   20278 		/*
   20279 		 * The NEEDREFRESH flag is set only when a notify was received
   20280 		 * while the current zone transfer is running.
   20281 		 */
   20282 		*needs_refresh = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   20283 	} else if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
   20284 		*is_deferred = true;
   20285 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
   20286 		if (zone->request != NULL) {
   20287 			*is_presoa = true;
   20288 		} else {
   20289 			*is_pending = true;
   20290 		}
   20291 	} else {
   20292 		/*
   20293 		 * No operation is ongoing or pending, just check if the zone
   20294 		 * needs a refresh by looking at the refresh and expire times.
   20295 		 */
   20296 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
   20297 		    (zone->type == dns_zone_secondary ||
   20298 		     zone->type == dns_zone_mirror ||
   20299 		     zone->type == dns_zone_stub))
   20300 		{
   20301 			isc_time_t now = isc_time_now();
   20302 			if (isc_time_compare(&now, &zone->refreshtime) >= 0 ||
   20303 			    isc_time_compare(&now, &zone->expiretime) >= 0)
   20304 			{
   20305 				*needs_refresh = true;
   20306 			}
   20307 		}
   20308 	}
   20309 	UNLOCK_ZONE(zone);
   20310 	RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
   20311 
   20312 	return ISC_R_SUCCESS;
   20313 }
   20314 
   20315 void
   20316 dns_zone_lock_keyfiles(dns_zone_t *zone) {
   20317 	REQUIRE(DNS_ZONE_VALID(zone));
   20318 
   20319 	if (zone->kasp == NULL) {
   20320 		/* No need to lock, nothing is writing key files. */
   20321 		return;
   20322 	}
   20323 
   20324 	REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
   20325 	isc_mutex_lock(&zone->kfio->lock);
   20326 }
   20327 
   20328 void
   20329 dns_zone_unlock_keyfiles(dns_zone_t *zone) {
   20330 	REQUIRE(DNS_ZONE_VALID(zone));
   20331 
   20332 	if (zone->kasp == NULL) {
   20333 		/* No need to lock, nothing is writing key files. */
   20334 		return;
   20335 	}
   20336 
   20337 	REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
   20338 	isc_mutex_unlock(&zone->kfio->lock);
   20339 }
   20340 
   20341 isc_result_t
   20342 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
   20343 		    dns_rdata_t *rdata) {
   20344 	bool ok = true;
   20345 	bool fail = false;
   20346 	char namebuf[DNS_NAME_FORMATSIZE];
   20347 	char namebuf2[DNS_NAME_FORMATSIZE];
   20348 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
   20349 	int level = ISC_LOG_WARNING;
   20350 	dns_name_t bad;
   20351 
   20352 	REQUIRE(DNS_ZONE_VALID(zone));
   20353 
   20354 	if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
   20355 	    rdata->type != dns_rdatatype_nsec3)
   20356 	{
   20357 		return ISC_R_SUCCESS;
   20358 	}
   20359 
   20360 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
   20361 	    rdata->type == dns_rdatatype_nsec3)
   20362 	{
   20363 		level = ISC_LOG_ERROR;
   20364 		fail = true;
   20365 	}
   20366 
   20367 	ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
   20368 	if (!ok) {
   20369 		dns_name_format(name, namebuf, sizeof(namebuf));
   20370 		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
   20371 		dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
   20372 			     isc_result_totext(DNS_R_BADOWNERNAME));
   20373 		if (fail) {
   20374 			return DNS_R_BADOWNERNAME;
   20375 		}
   20376 	}
   20377 
   20378 	dns_name_init(&bad, NULL);
   20379 	ok = dns_rdata_checknames(rdata, name, &bad);
   20380 	if (!ok) {
   20381 		dns_name_format(name, namebuf, sizeof(namebuf));
   20382 		dns_name_format(&bad, namebuf2, sizeof(namebuf2));
   20383 		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
   20384 		dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
   20385 			     namebuf2, isc_result_totext(DNS_R_BADNAME));
   20386 		if (fail) {
   20387 			return DNS_R_BADNAME;
   20388 		}
   20389 	}
   20390 
   20391 	return ISC_R_SUCCESS;
   20392 }
   20393 
   20394 void
   20395 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
   20396 	REQUIRE(DNS_ZONE_VALID(zone));
   20397 	zone->checkmx = checkmx;
   20398 }
   20399 
   20400 void
   20401 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
   20402 	REQUIRE(DNS_ZONE_VALID(zone));
   20403 	zone->checksrv = checksrv;
   20404 }
   20405 
   20406 void
   20407 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
   20408 	REQUIRE(DNS_ZONE_VALID(zone));
   20409 	zone->checkns = checkns;
   20410 }
   20411 
   20412 void
   20413 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
   20414 	REQUIRE(DNS_ZONE_VALID(zone));
   20415 
   20416 	LOCK_ZONE(zone);
   20417 	zone->isself = isself;
   20418 	zone->isselfarg = arg;
   20419 	UNLOCK_ZONE(zone);
   20420 }
   20421 
   20422 void
   20423 dns_zone_setnotifydefer(dns_zone_t *zone, uint32_t defer) {
   20424 	REQUIRE(DNS_ZONE_VALID(zone));
   20425 
   20426 	LOCK_ZONE(zone);
   20427 	zone->notifydefer = defer;
   20428 	UNLOCK_ZONE(zone);
   20429 }
   20430 
   20431 void
   20432 dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
   20433 	REQUIRE(DNS_ZONE_VALID(zone));
   20434 
   20435 	LOCK_ZONE(zone);
   20436 	zone->notifydelay = delay;
   20437 	UNLOCK_ZONE(zone);
   20438 }
   20439 
   20440 /*
   20441  * Called when a dynamic update for an NSEC3PARAM record is received.
   20442  *
   20443  * If set, transform the NSEC3 salt into human-readable form so that it can be
   20444  * logged.  Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
   20445  */
   20446 isc_result_t
   20447 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
   20448 	isc_result_t result;
   20449 	char salt[255 * 2 + 1];
   20450 
   20451 	REQUIRE(DNS_ZONE_VALID(zone));
   20452 
   20453 	result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
   20454 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   20455 	dnssec_log(zone, ISC_LOG_NOTICE,
   20456 		   "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
   20457 		   nsec3param->hash, nsec3param->iterations, salt);
   20458 	LOCK_ZONE(zone);
   20459 	result = zone_addnsec3chain(zone, nsec3param);
   20460 	UNLOCK_ZONE(zone);
   20461 
   20462 	return result;
   20463 }
   20464 
   20465 void
   20466 dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
   20467 	REQUIRE(DNS_ZONE_VALID(zone));
   20468 
   20469 	if (nodes == 0) {
   20470 		nodes = 1;
   20471 	}
   20472 	zone->nodes = nodes;
   20473 }
   20474 
   20475 void
   20476 dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
   20477 	REQUIRE(DNS_ZONE_VALID(zone));
   20478 
   20479 	/*
   20480 	 * We treat signatures as a signed value so explicitly
   20481 	 * limit its range here.
   20482 	 */
   20483 	if (signatures > INT32_MAX) {
   20484 		signatures = INT32_MAX;
   20485 	} else if (signatures == 0) {
   20486 		signatures = 1;
   20487 	}
   20488 	zone->signatures = signatures;
   20489 }
   20490 
   20491 uint32_t
   20492 dns_zone_getsignatures(dns_zone_t *zone) {
   20493 	REQUIRE(DNS_ZONE_VALID(zone));
   20494 	return zone->signatures;
   20495 }
   20496 
   20497 void
   20498 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
   20499 	REQUIRE(DNS_ZONE_VALID(zone));
   20500 	zone->privatetype = type;
   20501 }
   20502 
   20503 dns_rdatatype_t
   20504 dns_zone_getprivatetype(dns_zone_t *zone) {
   20505 	REQUIRE(DNS_ZONE_VALID(zone));
   20506 	return zone->privatetype;
   20507 }
   20508 
   20509 static isc_result_t
   20510 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
   20511 		 bool deleteit, bool fullsign) {
   20512 	dns_signing_t *signing;
   20513 	dns_signing_t *current;
   20514 	isc_result_t result = ISC_R_SUCCESS;
   20515 	isc_time_t now;
   20516 	dns_db_t *db = NULL;
   20517 
   20518 	signing = isc_mem_get(zone->mctx, sizeof *signing);
   20519 
   20520 	signing->magic = 0;
   20521 	signing->db = NULL;
   20522 	signing->dbiterator = NULL;
   20523 	signing->algorithm = algorithm;
   20524 	signing->keyid = keyid;
   20525 	signing->deleteit = deleteit;
   20526 	signing->fullsign = fullsign;
   20527 	signing->done = false;
   20528 
   20529 	now = isc_time_now();
   20530 
   20531 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   20532 	if (zone->db != NULL) {
   20533 		dns_db_attach(zone->db, &db);
   20534 	}
   20535 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   20536 
   20537 	if (db == NULL) {
   20538 		result = ISC_R_NOTFOUND;
   20539 		goto cleanup;
   20540 	}
   20541 
   20542 	dns_db_attach(db, &signing->db);
   20543 
   20544 	for (current = ISC_LIST_HEAD(zone->signing); current != NULL;
   20545 	     current = ISC_LIST_NEXT(current, link))
   20546 	{
   20547 		if (current->db == signing->db &&
   20548 		    current->algorithm == signing->algorithm &&
   20549 		    current->keyid == signing->keyid)
   20550 		{
   20551 			if (current->deleteit != signing->deleteit) {
   20552 				current->done = true;
   20553 			} else {
   20554 				goto cleanup;
   20555 			}
   20556 		}
   20557 	}
   20558 
   20559 	result = dns_db_createiterator(signing->db, 0, &signing->dbiterator);
   20560 
   20561 	if (result == ISC_R_SUCCESS) {
   20562 		result = dns_dbiterator_first(signing->dbiterator);
   20563 	}
   20564 	if (result == ISC_R_SUCCESS) {
   20565 		dns_dbiterator_pause(signing->dbiterator);
   20566 		ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
   20567 		signing = NULL;
   20568 		if (isc_time_isepoch(&zone->signingtime)) {
   20569 			zone->signingtime = now;
   20570 			if (zone->loop != NULL) {
   20571 				zone_settimer(zone, &now);
   20572 			}
   20573 		}
   20574 	}
   20575 
   20576 cleanup:
   20577 	if (signing != NULL) {
   20578 		if (signing->db != NULL) {
   20579 			dns_db_detach(&signing->db);
   20580 		}
   20581 		if (signing->dbiterator != NULL) {
   20582 			dns_dbiterator_destroy(&signing->dbiterator);
   20583 		}
   20584 		isc_mem_put(zone->mctx, signing, sizeof *signing);
   20585 	}
   20586 	if (db != NULL) {
   20587 		dns_db_detach(&db);
   20588 	}
   20589 	return result;
   20590 }
   20591 
   20592 /* Called once; *timep should be set to the current time. */
   20593 static isc_result_t
   20594 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
   20595 	isc_result_t result;
   20596 	isc_stdtime_t now, then = 0, event;
   20597 	int i;
   20598 
   20599 	now = *timep;
   20600 
   20601 	for (i = 0; i < DST_MAX_TIMES; i++) {
   20602 		result = dst_key_gettime(key, i, &event);
   20603 		if (result == ISC_R_SUCCESS && event > now &&
   20604 		    (then == 0 || event < then))
   20605 		{
   20606 			then = event;
   20607 		}
   20608 	}
   20609 
   20610 	if (then != 0) {
   20611 		*timep = then;
   20612 		return ISC_R_SUCCESS;
   20613 	}
   20614 
   20615 	return ISC_R_NOTFOUND;
   20616 }
   20617 
   20618 static isc_result_t
   20619 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
   20620 	  const dns_rdata_t *rdata, bool *flag) {
   20621 	dns_rdataset_t rdataset;
   20622 	dns_dbnode_t *node = NULL;
   20623 	isc_result_t result;
   20624 
   20625 	dns_rdataset_init(&rdataset);
   20626 	if (rdata->type == dns_rdatatype_nsec3) {
   20627 		CHECK(dns_db_findnsec3node(db, name, false, &node));
   20628 	} else {
   20629 		CHECK(dns_db_findnode(db, name, false, &node));
   20630 	}
   20631 	result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
   20632 				     (isc_stdtime_t)0, &rdataset, NULL);
   20633 	if (result == ISC_R_NOTFOUND) {
   20634 		*flag = false;
   20635 		result = ISC_R_SUCCESS;
   20636 		goto cleanup;
   20637 	}
   20638 
   20639 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   20640 	     result = dns_rdataset_next(&rdataset))
   20641 	{
   20642 		dns_rdata_t myrdata = DNS_RDATA_INIT;
   20643 		dns_rdataset_current(&rdataset, &myrdata);
   20644 		if (!dns_rdata_compare(&myrdata, rdata)) {
   20645 			break;
   20646 		}
   20647 	}
   20648 	dns_rdataset_disassociate(&rdataset);
   20649 	if (result == ISC_R_SUCCESS) {
   20650 		*flag = true;
   20651 	} else if (result == ISC_R_NOMORE) {
   20652 		*flag = false;
   20653 		result = ISC_R_SUCCESS;
   20654 	}
   20655 
   20656 cleanup:
   20657 	if (node != NULL) {
   20658 		dns_db_detachnode(db, &node);
   20659 	}
   20660 	return result;
   20661 }
   20662 
   20663 /*
   20664  * Add records to signal the state of signing or of key removal.
   20665  */
   20666 static isc_result_t
   20667 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
   20668 		    dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) {
   20669 	dns_difftuple_t *tuple = NULL, *newtuple = NULL, *next = NULL;
   20670 	dns_difftuple_t *addtuple = NULL, *deltuple = NULL;
   20671 	dns_rdata_dnskey_t dnskey;
   20672 	dns_rdata_t rdata = DNS_RDATA_INIT;
   20673 	bool flag;
   20674 	isc_region_t r;
   20675 	isc_result_t result = ISC_R_SUCCESS;
   20676 	uint16_t keyid;
   20677 	unsigned char buf[5];
   20678 	dns_name_t *name = dns_db_origin(db);
   20679 	dns_difftuplelist_t add = ISC_LIST_INITIALIZER;
   20680 	dns_difftuplelist_t del = ISC_LIST_INITIALIZER;
   20681 	dns_difftuplelist_t tuples = ISC_LIST_INITIALIZER;
   20682 
   20683 	/*
   20684 	 * Move non DNSKEY and not DNSSEC DNSKEY records to tuples
   20685 	 * and sort the remaining DNSKEY records to add and del.
   20686 	 */
   20687 	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
   20688 	     tuple = ISC_LIST_HEAD(diff->tuples))
   20689 	{
   20690 		if (tuple->rdata.type != dns_rdatatype_dnskey) {
   20691 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
   20692 			ISC_LIST_APPEND(tuples, tuple, link);
   20693 			continue;
   20694 		}
   20695 
   20696 		result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
   20697 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   20698 		if ((dnskey.flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
   20699 		{
   20700 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
   20701 			ISC_LIST_APPEND(tuples, tuple, link);
   20702 			continue;
   20703 		}
   20704 
   20705 		ISC_LIST_UNLINK(diff->tuples, tuple, link);
   20706 		switch (tuple->op) {
   20707 		case DNS_DIFFOP_DEL:
   20708 		case DNS_DIFFOP_DELRESIGN:
   20709 			ISC_LIST_APPEND(del, tuple, link);
   20710 			break;
   20711 		case DNS_DIFFOP_ADD:
   20712 		case DNS_DIFFOP_ADDRESIGN:
   20713 			ISC_LIST_APPEND(add, tuple, link);
   20714 			break;
   20715 		default:
   20716 			UNREACHABLE();
   20717 		}
   20718 	}
   20719 
   20720 	/*
   20721 	 * Put the tuples that don't need more processing back onto
   20722 	 * diff->tuples.
   20723 	 */
   20724 	ISC_LIST_APPENDLIST(diff->tuples, tuples, link);
   20725 
   20726 	/*
   20727 	 * Filter out DNSKEY TTL changes and put them back onto diff->tuples.
   20728 	 */
   20729 	for (deltuple = ISC_LIST_HEAD(del); deltuple != NULL; deltuple = next) {
   20730 		next = ISC_LIST_NEXT(deltuple, link);
   20731 		for (addtuple = ISC_LIST_HEAD(add); addtuple != NULL;
   20732 		     addtuple = ISC_LIST_NEXT(addtuple, link))
   20733 		{
   20734 			int n = dns_rdata_compare(&deltuple->rdata,
   20735 						  &addtuple->rdata);
   20736 			if (n == 0) {
   20737 				ISC_LIST_UNLINK(del, deltuple, link);
   20738 				ISC_LIST_APPEND(diff->tuples, deltuple, link);
   20739 				ISC_LIST_UNLINK(add, addtuple, link);
   20740 				ISC_LIST_APPEND(diff->tuples, addtuple, link);
   20741 				break;
   20742 			}
   20743 		}
   20744 	}
   20745 
   20746 	/*
   20747 	 * Combine any remaining DNSKEY changes together.
   20748 	 */
   20749 	ISC_LIST_APPENDLIST(tuples, add, link);
   20750 	ISC_LIST_APPENDLIST(tuples, del, link);
   20751 
   20752 	/*
   20753 	 * Add private records for keys that have been removed
   20754 	 * or added.
   20755 	 */
   20756 	for (tuple = ISC_LIST_HEAD(tuples); tuple != NULL;
   20757 	     tuple = ISC_LIST_NEXT(tuple, link))
   20758 	{
   20759 		dns_rdata_toregion(&tuple->rdata, &r);
   20760 
   20761 		keyid = dst_region_computeid(&r);
   20762 
   20763 		buf[0] = dnskey.algorithm;
   20764 		buf[1] = (keyid & 0xff00) >> 8;
   20765 		buf[2] = (keyid & 0xff);
   20766 		buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
   20767 		buf[4] = 0;
   20768 		rdata.data = buf;
   20769 		rdata.length = sizeof(buf);
   20770 		rdata.type = privatetype;
   20771 		rdata.rdclass = tuple->rdata.rdclass;
   20772 
   20773 		if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
   20774 			CHECK(rr_exists(db, ver, name, &rdata, &flag));
   20775 			if (flag) {
   20776 				continue;
   20777 			}
   20778 
   20779 			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
   20780 						   name, 0, &rdata, &newtuple));
   20781 			CHECK(do_one_tuple(&newtuple, db, ver, diff));
   20782 			INSIST(newtuple == NULL);
   20783 		}
   20784 
   20785 		/*
   20786 		 * Remove any record which says this operation has already
   20787 		 * completed.
   20788 		 */
   20789 		buf[4] = 1;
   20790 		CHECK(rr_exists(db, ver, name, &rdata, &flag));
   20791 		if (flag) {
   20792 			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
   20793 						   name, 0, &rdata, &newtuple));
   20794 			CHECK(do_one_tuple(&newtuple, db, ver, diff));
   20795 			INSIST(newtuple == NULL);
   20796 		}
   20797 	}
   20798 
   20799 cleanup:
   20800 	/*
   20801 	 * Put the DNSKEY changes we cared about back on diff->tuples.
   20802 	 */
   20803 	ISC_LIST_APPENDLIST(diff->tuples, tuples, link);
   20804 	INSIST(ISC_LIST_EMPTY(add));
   20805 	INSIST(ISC_LIST_EMPTY(del));
   20806 	INSIST(ISC_LIST_EMPTY(tuples));
   20807 	return result;
   20808 }
   20809 
   20810 /*
   20811  * See if dns__zone_updatesigs() will update signature for RRset 'rrtype' at
   20812  * the apex, and if not tickle them and cause to sign so that newly activated
   20813  * keys are used.
   20814  */
   20815 static isc_result_t
   20816 tickle_apex_rrset(dns_rdatatype_t rrtype, dns_zone_t *zone, dns_db_t *db,
   20817 		  dns_dbversion_t *ver, isc_stdtime_t now, dns_diff_t *diff,
   20818 		  dns__zonediff_t *zonediff, dst_key_t **keys,
   20819 		  unsigned int nkeys, isc_stdtime_t inception,
   20820 		  isc_stdtime_t keyexpire) {
   20821 	dns_difftuple_t *tuple;
   20822 	isc_result_t result;
   20823 
   20824 	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
   20825 	     tuple = ISC_LIST_NEXT(tuple, link))
   20826 	{
   20827 		if (tuple->rdata.type == rrtype &&
   20828 		    dns_name_equal(&tuple->name, &zone->origin))
   20829 		{
   20830 			break;
   20831 		}
   20832 	}
   20833 
   20834 	if (tuple == NULL) {
   20835 		result = del_sigs(zone, db, ver, &zone->origin, rrtype,
   20836 				  zonediff, keys, nkeys, now, false);
   20837 		if (result != ISC_R_SUCCESS) {
   20838 			dnssec_log(zone, ISC_LOG_ERROR,
   20839 				   "sign_apex:del_sigs -> %s",
   20840 				   isc_result_totext(result));
   20841 			return result;
   20842 		}
   20843 		result = add_sigs(db, ver, &zone->origin, zone, rrtype,
   20844 				  zonediff->diff, keys, nkeys, zone->mctx, now,
   20845 				  inception, keyexpire);
   20846 		if (result != ISC_R_SUCCESS) {
   20847 			dnssec_log(zone, ISC_LOG_ERROR,
   20848 				   "sign_apex:add_sigs -> %s",
   20849 				   isc_result_totext(result));
   20850 			return result;
   20851 		}
   20852 	}
   20853 
   20854 	return ISC_R_SUCCESS;
   20855 }
   20856 
   20857 static isc_result_t
   20858 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   20859 	  isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff) {
   20860 	isc_result_t result;
   20861 	isc_stdtime_t inception, soaexpire, keyexpire;
   20862 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   20863 	unsigned int nkeys = 0, i;
   20864 
   20865 	result = dns_zone_findkeys(zone, db, ver, now, zone->mctx,
   20866 				   DNS_MAXZONEKEYS, zone_keys, &nkeys);
   20867 	if (result != ISC_R_SUCCESS) {
   20868 		dnssec_log(zone, ISC_LOG_ERROR,
   20869 			   "sign_apex:dns_zone_findkeys -> %s",
   20870 			   isc_result_totext(result));
   20871 		return result;
   20872 	}
   20873 
   20874 	inception = now - 3600; /* Allow for clock skew. */
   20875 	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
   20876 
   20877 	keyexpire = dns_zone_getkeyvalidityinterval(zone);
   20878 	if (keyexpire == 0) {
   20879 		keyexpire = soaexpire - 1;
   20880 	} else {
   20881 		keyexpire += now;
   20882 	}
   20883 
   20884 	/*
   20885 	 * See if dns__zone_updatesigs() will update DNSKEY/CDS/CDNSKEY
   20886 	 * signature and if not cause them to sign so that newly activated
   20887 	 * keys are used.
   20888 	 */
   20889 	CHECK(tickle_apex_rrset(dns_rdatatype_dnskey, zone, db, ver, now, diff,
   20890 				zonediff, zone_keys, nkeys, inception,
   20891 				keyexpire));
   20892 	CHECK(tickle_apex_rrset(dns_rdatatype_cds, zone, db, ver, now, diff,
   20893 				zonediff, zone_keys, nkeys, inception,
   20894 				keyexpire));
   20895 	CHECK(tickle_apex_rrset(dns_rdatatype_cdnskey, zone, db, ver, now, diff,
   20896 				zonediff, zone_keys, nkeys, inception,
   20897 				keyexpire));
   20898 
   20899 	result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
   20900 				      inception, soaexpire, keyexpire, now,
   20901 				      zonediff);
   20902 	if (result != ISC_R_SUCCESS) {
   20903 		dnssec_log(zone, ISC_LOG_ERROR,
   20904 			   "sign_apex:dns__zone_updatesigs -> %s",
   20905 			   isc_result_totext(result));
   20906 	}
   20907 
   20908 cleanup:
   20909 	for (i = 0; i < nkeys; i++) {
   20910 		dst_key_free(&zone_keys[i]);
   20911 	}
   20912 	return result;
   20913 }
   20914 
   20915 static isc_result_t
   20916 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   20917 		 dns_diff_t *diff) {
   20918 	isc_result_t result;
   20919 	dns_dbnode_t *node = NULL;
   20920 	dns_rdataset_t rdataset;
   20921 
   20922 	dns_rdataset_init(&rdataset);
   20923 	CHECK(dns_db_getoriginnode(db, &node));
   20924 
   20925 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
   20926 				     dns_rdatatype_none, 0, &rdataset, NULL);
   20927 	if (dns_rdataset_isassociated(&rdataset)) {
   20928 		dns_rdataset_disassociate(&rdataset);
   20929 	}
   20930 	if (result != ISC_R_NOTFOUND) {
   20931 		goto cleanup;
   20932 	}
   20933 
   20934 	result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
   20935 
   20936 cleanup:
   20937 	if (node != NULL) {
   20938 		dns_db_detachnode(db, &node);
   20939 	}
   20940 	return result;
   20941 }
   20942 
   20943 /*
   20944  * Given an RRSIG rdataset and an algorithm, determine whether there
   20945  * are any signatures using that algorithm.
   20946  */
   20947 static bool
   20948 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
   20949 	dns_rdata_t rdata = DNS_RDATA_INIT;
   20950 	dns_rdata_rrsig_t rrsig;
   20951 	isc_result_t result;
   20952 
   20953 	REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
   20954 	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
   20955 		return false;
   20956 	}
   20957 
   20958 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   20959 	     result = dns_rdataset_next(rdataset))
   20960 	{
   20961 		dns_rdataset_current(rdataset, &rdata);
   20962 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   20963 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   20964 		dns_rdata_reset(&rdata);
   20965 		if (rrsig.algorithm == alg) {
   20966 			return true;
   20967 		}
   20968 	}
   20969 
   20970 	return false;
   20971 }
   20972 
   20973 static isc_result_t
   20974 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   20975 	   dns_diff_t *diff) {
   20976 	dns_name_t *origin;
   20977 	bool build_nsec3;
   20978 	isc_result_t result;
   20979 
   20980 	origin = dns_db_origin(db);
   20981 	CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
   20982 				 &build_nsec3));
   20983 	if (build_nsec3) {
   20984 		CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone_nsecttl(zone),
   20985 					   false, zone->privatetype, diff));
   20986 	}
   20987 	CHECK(updatesecure(db, ver, origin, zone_nsecttl(zone), true, diff));
   20988 
   20989 cleanup:
   20990 	return result;
   20991 }
   20992 
   20993 static void
   20994 dnssec_report(const char *format, ...) {
   20995 	va_list args;
   20996 	va_start(args, format);
   20997 	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
   20998 		       ISC_LOG_INFO, format, args);
   20999 	va_end(args);
   21000 }
   21001 
   21002 static void
   21003 checkds_destroy(dns_checkds_t *checkds, bool locked) {
   21004 	REQUIRE(DNS_CHECKDS_VALID(checkds));
   21005 
   21006 	dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
   21007 		     "checkds: destroy DS query");
   21008 
   21009 	if (checkds->zone != NULL) {
   21010 		if (!locked) {
   21011 			LOCK_ZONE(checkds->zone);
   21012 		}
   21013 		REQUIRE(LOCKED_ZONE(checkds->zone));
   21014 		if (ISC_LINK_LINKED(checkds, link)) {
   21015 			ISC_LIST_UNLINK(checkds->zone->checkds_requests,
   21016 					checkds, link);
   21017 		}
   21018 		if (!locked) {
   21019 			UNLOCK_ZONE(checkds->zone);
   21020 		}
   21021 		if (locked) {
   21022 			zone_idetach(&checkds->zone);
   21023 		} else {
   21024 			dns_zone_idetach(&checkds->zone);
   21025 		}
   21026 	}
   21027 	if (checkds->find != NULL) {
   21028 		dns_adb_destroyfind(&checkds->find);
   21029 	}
   21030 	if (checkds->request != NULL) {
   21031 		dns_request_destroy(&checkds->request);
   21032 	}
   21033 	if (dns_name_dynamic(&checkds->ns)) {
   21034 		dns_name_free(&checkds->ns, checkds->mctx);
   21035 	}
   21036 	if (checkds->key != NULL) {
   21037 		dns_tsigkey_detach(&checkds->key);
   21038 	}
   21039 	if (checkds->transport != NULL) {
   21040 		dns_transport_detach(&checkds->transport);
   21041 	}
   21042 	INSIST(checkds->rlevent == NULL);
   21043 	isc_mem_putanddetach(&checkds->mctx, checkds, sizeof(*checkds));
   21044 }
   21045 
   21046 static isc_result_t
   21047 make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
   21048 	    dns_rdata_t *target) {
   21049 	isc_result_t result;
   21050 	isc_buffer_t b;
   21051 	isc_region_t r;
   21052 
   21053 	isc_buffer_init(&b, buf, bufsize);
   21054 	result = dst_key_todns(key, &b);
   21055 	if (result != ISC_R_SUCCESS) {
   21056 		return result;
   21057 	}
   21058 
   21059 	dns_rdata_reset(target);
   21060 	isc_buffer_usedregion(&b, &r);
   21061 	dns_rdata_fromregion(target, dst_key_class(key), dns_rdatatype_dnskey,
   21062 			     &r);
   21063 	return ISC_R_SUCCESS;
   21064 }
   21065 
   21066 static bool
   21067 do_checkds(dns_zone_t *zone, dst_key_t *key, isc_stdtime_t now,
   21068 	   bool dspublish) {
   21069 	dns_kasp_t *kasp = zone->kasp;
   21070 	isc_result_t result;
   21071 	uint32_t count = 0;
   21072 	uint32_t num;
   21073 
   21074 	switch (zone->checkdstype) {
   21075 	case dns_checkdstype_yes:
   21076 		num = zone->parent_nscount;
   21077 		break;
   21078 	case dns_checkdstype_explicit:
   21079 		num = dns_remote_count(&zone->parentals);
   21080 		break;
   21081 	case dns_checkdstype_no:
   21082 	default:
   21083 		dns_zone_log(zone, ISC_LOG_WARNING,
   21084 			     "checkds: option is disabled");
   21085 		return false;
   21086 	}
   21087 
   21088 	if (dspublish) {
   21089 		(void)dst_key_getnum(key, DST_NUM_DSPUBCOUNT, &count);
   21090 		count += 1;
   21091 		dst_key_setnum(key, DST_NUM_DSPUBCOUNT, count);
   21092 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21093 			     "checkds: %u DS published "
   21094 			     "for key %u",
   21095 			     count, dst_key_id(key));
   21096 
   21097 		if (count != num) {
   21098 			return false;
   21099 		}
   21100 	} else {
   21101 		(void)dst_key_getnum(key, DST_NUM_DSDELCOUNT, &count);
   21102 		count += 1;
   21103 		dst_key_setnum(key, DST_NUM_DSDELCOUNT, count);
   21104 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21105 			     "checkds: %u DS withdrawn "
   21106 			     "for key %u",
   21107 			     count, dst_key_id(key));
   21108 
   21109 		if (count != num) {
   21110 			return false;
   21111 		}
   21112 	}
   21113 
   21114 	dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21115 		     "checkds: checkds %s for key "
   21116 		     "%u",
   21117 		     dspublish ? "published" : "withdrawn", dst_key_id(key));
   21118 
   21119 	dns_zone_lock_keyfiles(zone);
   21120 	result = dns_keymgr_checkds_id(kasp, &zone->checkds_ok, now, now,
   21121 				       dspublish, dst_key_id(key),
   21122 				       dst_key_alg(key));
   21123 	dns_zone_unlock_keyfiles(zone);
   21124 
   21125 	if (result != ISC_R_SUCCESS) {
   21126 		dns_zone_log(zone, ISC_LOG_WARNING,
   21127 			     "checkds: checkds for key %u failed: %s",
   21128 			     dst_key_id(key), isc_result_totext(result));
   21129 		return false;
   21130 	}
   21131 
   21132 	return true;
   21133 }
   21134 
   21135 static isc_result_t
   21136 validate_ds(dns_zone_t *zone, dns_message_t *message) {
   21137 	UNUSED(zone);
   21138 	UNUSED(message);
   21139 
   21140 	/* Get closest trust anchor */
   21141 
   21142 	/* Check that trust anchor is (grand)parent of zone. */
   21143 
   21144 	/* Find the DNSKEY signing the message. */
   21145 
   21146 	/* Check that DNSKEY is in chain of trust. */
   21147 
   21148 	/* Validate DS RRset. */
   21149 
   21150 	return ISC_R_SUCCESS;
   21151 }
   21152 
   21153 static void
   21154 checkds_done(void *arg) {
   21155 	dns_request_t *request = (dns_request_t *)arg;
   21156 	dns_checkds_t *checkds = dns_request_getarg(request);
   21157 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   21158 	char rcode[128];
   21159 	dns_zone_t *zone = NULL;
   21160 	dns_db_t *db = NULL;
   21161 	dns_dbversion_t *version = NULL;
   21162 	dns_dnsseckey_t *key = NULL;
   21163 	dns_dnsseckeylist_t keys;
   21164 	dns_kasp_t *kasp = NULL;
   21165 	dns_message_t *message = NULL;
   21166 	dns_rdataset_t *ds_rrset = NULL;
   21167 	isc_buffer_t buf;
   21168 	isc_result_t result;
   21169 	isc_stdtime_t now;
   21170 	isc_time_t timenow;
   21171 	bool rekey = false;
   21172 	bool empty = false;
   21173 
   21174 	REQUIRE(DNS_CHECKDS_VALID(checkds));
   21175 
   21176 	zone = checkds->zone;
   21177 
   21178 	ISC_LIST_INIT(keys);
   21179 
   21180 	kasp = zone->kasp;
   21181 	INSIST(kasp != NULL);
   21182 
   21183 	isc_buffer_init(&buf, rcode, sizeof(rcode));
   21184 	isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
   21185 
   21186 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "checkds: DS query to %s: done",
   21187 		     addrbuf);
   21188 
   21189 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
   21190 			   &message);
   21191 	INSIST(message != NULL);
   21192 
   21193 	CHECK(dns_request_getresult(request));
   21194 	CHECK(dns_request_getresponse(request, message,
   21195 				      DNS_MESSAGEPARSE_PRESERVEORDER));
   21196 	CHECK(dns_rcode_totext(message->rcode, &buf));
   21197 
   21198 	dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21199 		     "checkds: DS response from %s: %.*s", addrbuf,
   21200 		     (int)buf.used, rcode);
   21201 
   21202 	/* Validate response. */
   21203 	CHECK(validate_ds(zone, message));
   21204 
   21205 	/* Check RCODE. */
   21206 	if (message->rcode != dns_rcode_noerror) {
   21207 		dns_zone_log(zone, ISC_LOG_NOTICE,
   21208 			     "checkds: bad DS response from %s: %.*s", addrbuf,
   21209 			     (int)buf.used, rcode);
   21210 		goto cleanup;
   21211 	}
   21212 
   21213 	/* Make sure that either AA or RA bit is set. */
   21214 	if ((message->flags & DNS_MESSAGEFLAG_AA) == 0 &&
   21215 	    (message->flags & DNS_MESSAGEFLAG_RA) == 0)
   21216 	{
   21217 		dns_zone_log(zone, ISC_LOG_NOTICE,
   21218 			     "checkds: bad DS response from %s: expected AA or "
   21219 			     "RA bit set",
   21220 			     addrbuf);
   21221 		goto cleanup;
   21222 	}
   21223 
   21224 	/* Lookup DS RRset. */
   21225 	result = dns_message_firstname(message, DNS_SECTION_ANSWER);
   21226 	while (result == ISC_R_SUCCESS) {
   21227 		dns_name_t *name = NULL;
   21228 		dns_rdataset_t *rdataset;
   21229 
   21230 		dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
   21231 		if (dns_name_compare(&zone->origin, name) != 0) {
   21232 			goto next;
   21233 		}
   21234 
   21235 		for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
   21236 		     rdataset = ISC_LIST_NEXT(rdataset, link))
   21237 		{
   21238 			if (rdataset->type != dns_rdatatype_ds) {
   21239 				goto next;
   21240 			}
   21241 
   21242 			ds_rrset = rdataset;
   21243 			break;
   21244 		}
   21245 
   21246 		if (ds_rrset != NULL) {
   21247 			break;
   21248 		}
   21249 
   21250 	next:
   21251 		result = dns_message_nextname(message, DNS_SECTION_ANSWER);
   21252 	}
   21253 
   21254 	if (ds_rrset == NULL) {
   21255 		empty = true;
   21256 		dns_zone_log(zone, ISC_LOG_NOTICE,
   21257 			     "checkds: empty DS response from %s", addrbuf);
   21258 	}
   21259 
   21260 	timenow = isc_time_now();
   21261 	now = isc_time_seconds(&timenow);
   21262 
   21263 	CHECK(dns_zone_getdb(zone, &db));
   21264 	dns_db_currentversion(db, &version);
   21265 
   21266 	KASP_LOCK(kasp);
   21267 	LOCK_ZONE(zone);
   21268 	for (key = ISC_LIST_HEAD(zone->checkds_ok); key != NULL;
   21269 	     key = ISC_LIST_NEXT(key, link))
   21270 	{
   21271 		bool alldone = false, found = false;
   21272 		bool checkdspub = false, checkdsdel = false, ksk = false;
   21273 		dst_key_state_t ds_state = DST_KEY_STATE_NA;
   21274 		isc_stdtime_t published = 0, withdrawn = 0;
   21275 		isc_result_t ret = ISC_R_SUCCESS;
   21276 
   21277 		/* Is this key have the KSK role? */
   21278 		(void)dst_key_role(key->key, &ksk, NULL);
   21279 		if (!ksk) {
   21280 			continue;
   21281 		}
   21282 
   21283 		/* Do we need to check the DS RRset for this key? */
   21284 		(void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
   21285 		(void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
   21286 		(void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
   21287 
   21288 		if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
   21289 			checkdspub = true;
   21290 		} else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
   21291 			   withdrawn == 0)
   21292 		{
   21293 			checkdsdel = true;
   21294 		}
   21295 		if (!checkdspub && !checkdsdel) {
   21296 			continue;
   21297 		}
   21298 
   21299 		if (empty) {
   21300 			goto dswithdrawn;
   21301 		}
   21302 
   21303 		/* Find the appropriate DS record. */
   21304 		ret = dns_rdataset_first(ds_rrset);
   21305 		while (ret == ISC_R_SUCCESS) {
   21306 			dns_rdata_ds_t ds;
   21307 			dns_rdata_t dnskey = DNS_RDATA_INIT;
   21308 			dns_rdata_t dsrdata = DNS_RDATA_INIT;
   21309 			dns_rdata_t rdata = DNS_RDATA_INIT;
   21310 			isc_result_t r;
   21311 			unsigned char dsbuf[DNS_DS_BUFFERSIZE];
   21312 			unsigned char keybuf[DST_KEY_MAXSIZE];
   21313 
   21314 			dns_rdataset_current(ds_rrset, &rdata);
   21315 			r = dns_rdata_tostruct(&rdata, &ds, NULL);
   21316 			if (r != ISC_R_SUCCESS) {
   21317 				goto nextds;
   21318 			}
   21319 			/* Check key tag and algorithm. */
   21320 			if (dst_key_id(key->key) != ds.key_tag) {
   21321 				goto nextds;
   21322 			}
   21323 			if (dst_key_alg(key->key) != ds.algorithm) {
   21324 				goto nextds;
   21325 			}
   21326 			/* Derive DS from DNSKEY, see if the rdata is equal. */
   21327 			make_dnskey(key->key, keybuf, sizeof(keybuf), &dnskey);
   21328 			r = dns_ds_buildrdata(&zone->origin, &dnskey,
   21329 					      ds.digest_type, dsbuf, &dsrdata);
   21330 			if (r != ISC_R_SUCCESS) {
   21331 				goto nextds;
   21332 			}
   21333 			if (dns_rdata_compare(&rdata, &dsrdata) == 0) {
   21334 				found = true;
   21335 				if (checkdspub) {
   21336 					/* DS Published. */
   21337 					alldone = do_checkds(zone, key->key,
   21338 							     now, true);
   21339 					if (alldone) {
   21340 						rekey = true;
   21341 					}
   21342 				}
   21343 			}
   21344 
   21345 		nextds:
   21346 			ret = dns_rdataset_next(ds_rrset);
   21347 		}
   21348 
   21349 	dswithdrawn:
   21350 		/* DS withdrawn. */
   21351 		if (checkdsdel && !found) {
   21352 			alldone = do_checkds(zone, key->key, now, false);
   21353 			if (alldone) {
   21354 				rekey = true;
   21355 			}
   21356 		}
   21357 	}
   21358 	UNLOCK_ZONE(zone);
   21359 	KASP_UNLOCK(kasp);
   21360 
   21361 	/* Rekey after checkds. */
   21362 	if (rekey) {
   21363 		dns_zone_rekey(zone, false, false);
   21364 	}
   21365 
   21366 cleanup:
   21367 	if (result != ISC_R_SUCCESS) {
   21368 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21369 			     "checkds: DS request failed: %s",
   21370 			     isc_result_totext(result));
   21371 	}
   21372 
   21373 	if (version != NULL) {
   21374 		dns_db_closeversion(db, &version, false);
   21375 	}
   21376 	if (db != NULL) {
   21377 		dns_db_detach(&db);
   21378 	}
   21379 
   21380 	while (!ISC_LIST_EMPTY(keys)) {
   21381 		key = ISC_LIST_HEAD(keys);
   21382 		ISC_LIST_UNLINK(keys, key, link);
   21383 		dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
   21384 	}
   21385 
   21386 	checkds_destroy(checkds, false);
   21387 	dns_message_detach(&message);
   21388 }
   21389 
   21390 static bool
   21391 checkds_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr,
   21392 		 dns_tsigkey_t *key, dns_transport_t *transport) {
   21393 	dns_checkds_t *checkds;
   21394 
   21395 	for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
   21396 	     checkds = ISC_LIST_NEXT(checkds, link))
   21397 	{
   21398 		if (checkds->request != NULL) {
   21399 			continue;
   21400 		}
   21401 		if (name != NULL && dns_name_equal(name, &checkds->ns)) {
   21402 			return true;
   21403 		}
   21404 		if (addr != NULL && isc_sockaddr_equal(addr, &checkds->dst) &&
   21405 		    checkds->key == key && checkds->transport == transport)
   21406 		{
   21407 			return true;
   21408 		}
   21409 	}
   21410 	return false;
   21411 }
   21412 
   21413 static void
   21414 checkds_create(isc_mem_t *mctx, unsigned int flags, dns_checkds_t **checkdsp) {
   21415 	dns_checkds_t *checkds;
   21416 
   21417 	REQUIRE(checkdsp != NULL && *checkdsp == NULL);
   21418 
   21419 	checkds = isc_mem_get(mctx, sizeof(*checkds));
   21420 	*checkds = (dns_checkds_t){
   21421 		.magic = CHECKDS_MAGIC,
   21422 		.flags = flags,
   21423 		.link = ISC_LINK_INITIALIZER,
   21424 		.ns = DNS_NAME_INITEMPTY,
   21425 	};
   21426 
   21427 	isc_mem_attach(mctx, &checkds->mctx);
   21428 
   21429 	isc_sockaddr_any(&checkds->dst);
   21430 
   21431 	*checkdsp = checkds;
   21432 }
   21433 
   21434 static void
   21435 checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep) {
   21436 	dns_message_t *message = NULL;
   21437 
   21438 	dns_name_t *tempname = NULL;
   21439 	dns_rdataset_t *temprdataset = NULL;
   21440 
   21441 	REQUIRE(DNS_ZONE_VALID(zone));
   21442 	REQUIRE(messagep != NULL && *messagep == NULL);
   21443 
   21444 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER,
   21445 			   &message);
   21446 
   21447 	message->opcode = dns_opcode_query;
   21448 	message->rdclass = zone->rdclass;
   21449 	message->flags |= DNS_MESSAGEFLAG_RD;
   21450 
   21451 	dns_message_gettempname(message, &tempname);
   21452 
   21453 	dns_message_gettemprdataset(message, &temprdataset);
   21454 
   21455 	/*
   21456 	 * Make question.
   21457 	 */
   21458 	dns_name_init(tempname, NULL);
   21459 	dns_name_clone(&zone->origin, tempname);
   21460 	dns_rdataset_makequestion(temprdataset, zone->rdclass,
   21461 				  dns_rdatatype_ds);
   21462 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
   21463 	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
   21464 	tempname = NULL;
   21465 	temprdataset = NULL;
   21466 
   21467 	*messagep = message;
   21468 }
   21469 
   21470 /*
   21471  * XXXAG should check for DNS_ZONEFLG_EXITING
   21472  */
   21473 static void
   21474 process_checkds_adb_event(void *arg) {
   21475 	dns_adbfind_t *find = (dns_adbfind_t *)arg;
   21476 	dns_checkds_t *checkds = (dns_checkds_t *)find->cbarg;
   21477 	dns_adbstatus_t astat = find->status;
   21478 
   21479 	REQUIRE(DNS_CHECKDS_VALID(checkds));
   21480 	REQUIRE(find == checkds->find);
   21481 
   21482 	switch (astat) {
   21483 	case DNS_ADB_MOREADDRESSES:
   21484 		dns_adb_destroyfind(&checkds->find);
   21485 		checkds_find_address(checkds);
   21486 		return;
   21487 
   21488 	case DNS_ADB_NOMOREADDRESSES:
   21489 		LOCK_ZONE(checkds->zone);
   21490 		checkds_send_tons(checkds);
   21491 		UNLOCK_ZONE(checkds->zone);
   21492 		break;
   21493 
   21494 	default:
   21495 		break;
   21496 	}
   21497 
   21498 	checkds_destroy(checkds, false);
   21499 }
   21500 
   21501 static void
   21502 checkds_find_address(dns_checkds_t *checkds) {
   21503 	isc_result_t result;
   21504 	unsigned int options;
   21505 	dns_adb_t *adb = NULL;
   21506 
   21507 	REQUIRE(DNS_CHECKDS_VALID(checkds));
   21508 
   21509 	options = DNS_ADBFIND_WANTEVENT;
   21510 	if (isc_net_probeipv4() != ISC_R_DISABLED) {
   21511 		options |= DNS_ADBFIND_INET;
   21512 	}
   21513 	if (isc_net_probeipv6() != ISC_R_DISABLED) {
   21514 		options |= DNS_ADBFIND_INET6;
   21515 	}
   21516 
   21517 	dns_view_getadb(checkds->zone->view, &adb);
   21518 	if (adb == NULL) {
   21519 		goto destroy;
   21520 	}
   21521 
   21522 	result = dns_adb_createfind(adb, checkds->zone->loop,
   21523 				    process_checkds_adb_event, checkds,
   21524 				    &checkds->ns, dns_rootname, 0, options, 0,
   21525 				    NULL, checkds->zone->view->dstport, 0, NULL,
   21526 				    NULL, NULL, &checkds->find);
   21527 	dns_adb_detach(&adb);
   21528 
   21529 	/* Something failed? */
   21530 	if (result != ISC_R_SUCCESS) {
   21531 		goto destroy;
   21532 	}
   21533 
   21534 	/* More addresses pending? */
   21535 	if ((checkds->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
   21536 		return;
   21537 	}
   21538 
   21539 	/* We have as many addresses as we can get. */
   21540 	LOCK_ZONE(checkds->zone);
   21541 	checkds_send_tons(checkds);
   21542 	UNLOCK_ZONE(checkds->zone);
   21543 
   21544 destroy:
   21545 	checkds_destroy(checkds, false);
   21546 }
   21547 
   21548 static void
   21549 checkds_send_toaddr(void *arg) {
   21550 	dns_checkds_t *checkds = (dns_checkds_t *)arg;
   21551 	isc_result_t result;
   21552 	dns_message_t *message = NULL;
   21553 	isc_netaddr_t dstip;
   21554 	dns_tsigkey_t *key = NULL;
   21555 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   21556 	isc_sockaddr_t src;
   21557 	unsigned int options, timeout;
   21558 	bool have_checkdssource = false;
   21559 	bool canceled = checkds->rlevent->canceled;
   21560 
   21561 	REQUIRE(DNS_CHECKDS_VALID(checkds));
   21562 
   21563 	isc_rlevent_free(&checkds->rlevent);
   21564 
   21565 	LOCK_ZONE(checkds->zone);
   21566 
   21567 	if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_LOADED) == 0 || canceled ||
   21568 	    DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_EXITING) ||
   21569 	    checkds->zone->view->requestmgr == NULL ||
   21570 	    checkds->zone->db == NULL)
   21571 	{
   21572 		result = ISC_R_CANCELED;
   21573 		goto cleanup;
   21574 	}
   21575 
   21576 	/*
   21577 	 * The raw IPv4 address should also exist.  Don't send to the
   21578 	 * mapped form.
   21579 	 */
   21580 	if (isc_sockaddr_pf(&checkds->dst) == PF_INET6 &&
   21581 	    IN6_IS_ADDR_V4MAPPED(&checkds->dst.type.sin6.sin6_addr))
   21582 	{
   21583 		isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
   21584 		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
   21585 			     "checkds: ignoring IPv6 mapped IPV4 address: %s",
   21586 			     addrbuf);
   21587 		result = ISC_R_CANCELED;
   21588 		goto cleanup;
   21589 	}
   21590 
   21591 	checkds_createmessage(checkds->zone, &message);
   21592 
   21593 	isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
   21594 	if (checkds->key != NULL) {
   21595 		/* Transfer ownership of key */
   21596 		key = checkds->key;
   21597 		checkds->key = NULL;
   21598 	} else {
   21599 		isc_netaddr_fromsockaddr(&dstip, &checkds->dst);
   21600 		result = dns_view_getpeertsig(checkds->zone->view, &dstip,
   21601 					      &key);
   21602 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   21603 			dns_zone_log(checkds->zone, ISC_LOG_ERROR,
   21604 				     "checkds: DS query to %s not sent. "
   21605 				     "Peer TSIG key lookup failure.",
   21606 				     addrbuf);
   21607 			goto cleanup_message;
   21608 		}
   21609 	}
   21610 
   21611 	if (key != NULL) {
   21612 		char namebuf[DNS_NAME_FORMATSIZE];
   21613 
   21614 		dns_name_format(key->name, namebuf, sizeof(namebuf));
   21615 		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
   21616 			     "checkds: sending DS query to %s : TSIG (%s)",
   21617 			     addrbuf, namebuf);
   21618 	} else {
   21619 		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
   21620 			     "checkds: sending DS query to %s", addrbuf);
   21621 	}
   21622 	options = 0;
   21623 	if (checkds->zone->view->peers != NULL) {
   21624 		dns_peer_t *peer = NULL;
   21625 		bool usetcp = false;
   21626 		result = dns_peerlist_peerbyaddr(checkds->zone->view->peers,
   21627 						 &dstip, &peer);
   21628 		if (result == ISC_R_SUCCESS) {
   21629 			result = dns_peer_getquerysource(peer, &src);
   21630 			if (result == ISC_R_SUCCESS) {
   21631 				have_checkdssource = true;
   21632 			}
   21633 			result = dns_peer_getforcetcp(peer, &usetcp);
   21634 			if (result == ISC_R_SUCCESS && usetcp) {
   21635 				options |= DNS_FETCHOPT_TCP;
   21636 			}
   21637 		}
   21638 	}
   21639 	switch (isc_sockaddr_pf(&checkds->dst)) {
   21640 	case PF_INET:
   21641 		if (!have_checkdssource) {
   21642 			isc_sockaddr_t any;
   21643 			isc_sockaddr_any(&any);
   21644 
   21645 			src = checkds->src;
   21646 			if (isc_sockaddr_equal(&src, &any)) {
   21647 				src = checkds->zone->parentalsrc4;
   21648 			}
   21649 		}
   21650 		break;
   21651 	case PF_INET6:
   21652 		if (!have_checkdssource) {
   21653 			isc_sockaddr_t any;
   21654 			isc_sockaddr_any6(&any);
   21655 
   21656 			src = checkds->src;
   21657 			if (isc_sockaddr_equal(&src, &any)) {
   21658 				src = checkds->zone->parentalsrc6;
   21659 			}
   21660 		}
   21661 		break;
   21662 	default:
   21663 		result = ISC_R_NOTIMPLEMENTED;
   21664 		goto cleanup_key;
   21665 	}
   21666 
   21667 	dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
   21668 		     "checkds: create request for DS query to %s", addrbuf);
   21669 
   21670 	timeout = 5;
   21671 	options |= DNS_REQUESTOPT_TCP;
   21672 	result = dns_request_create(
   21673 		checkds->zone->view->requestmgr, message, &src, &checkds->dst,
   21674 		NULL, NULL, options, key, timeout * 3 + 1, timeout, 2,
   21675 		checkds->zone->loop, checkds_done, checkds, &checkds->request);
   21676 	if (result != ISC_R_SUCCESS) {
   21677 		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
   21678 			     "checkds: dns_request_create() to %s failed: %s",
   21679 			     addrbuf, isc_result_totext(result));
   21680 	}
   21681 
   21682 cleanup_key:
   21683 	if (key != NULL) {
   21684 		dns_tsigkey_detach(&key);
   21685 	}
   21686 cleanup_message:
   21687 	dns_message_detach(&message);
   21688 cleanup:
   21689 	UNLOCK_ZONE(checkds->zone);
   21690 	if (result != ISC_R_SUCCESS) {
   21691 		checkds_destroy(checkds, false);
   21692 	}
   21693 }
   21694 
   21695 static void
   21696 checkds_send_tons(dns_checkds_t *checkds) {
   21697 	dns_adbaddrinfo_t *ai;
   21698 	isc_sockaddr_t dst;
   21699 	isc_result_t result;
   21700 	dns_checkds_t *newcheckds = NULL;
   21701 	dns_zone_t *zone = NULL;
   21702 
   21703 	/*
   21704 	 * Zone lock held by caller.
   21705 	 */
   21706 	REQUIRE(DNS_CHECKDS_VALID(checkds));
   21707 	REQUIRE(LOCKED_ZONE(checkds->zone));
   21708 
   21709 	zone = checkds->zone;
   21710 
   21711 	if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_EXITING)) {
   21712 		return;
   21713 	}
   21714 
   21715 	for (ai = ISC_LIST_HEAD(checkds->find->list); ai != NULL;
   21716 	     ai = ISC_LIST_NEXT(ai, publink))
   21717 	{
   21718 		dst = ai->sockaddr;
   21719 		if (checkds_isqueued(zone, NULL, &dst, NULL, NULL)) {
   21720 			continue;
   21721 		}
   21722 
   21723 		newcheckds = NULL;
   21724 		checkds_create(checkds->mctx, 0, &newcheckds);
   21725 		zone_iattach(zone, &newcheckds->zone);
   21726 		ISC_LIST_APPEND(newcheckds->zone->checkds_requests, newcheckds,
   21727 				link);
   21728 		newcheckds->dst = dst;
   21729 		dns_name_dup(&checkds->ns, checkds->mctx, &newcheckds->ns);
   21730 		switch (isc_sockaddr_pf(&newcheckds->dst)) {
   21731 		case PF_INET:
   21732 			isc_sockaddr_any(&newcheckds->src);
   21733 			break;
   21734 		case PF_INET6:
   21735 			isc_sockaddr_any6(&newcheckds->src);
   21736 			break;
   21737 		default:
   21738 			UNREACHABLE();
   21739 		}
   21740 		/*
   21741 		 * XXXWMM: Should we attach key and transport here?
   21742 		 * Probably not, because we expect the name servers to be
   21743 		 * publicly available on the default transport protocol.
   21744 		 */
   21745 
   21746 		result = isc_ratelimiter_enqueue(
   21747 			newcheckds->zone->zmgr->checkdsrl,
   21748 			newcheckds->zone->loop, checkds_send_toaddr, newcheckds,
   21749 			&newcheckds->rlevent);
   21750 		if (result != ISC_R_SUCCESS) {
   21751 			goto cleanup;
   21752 		}
   21753 		newcheckds = NULL;
   21754 	}
   21755 
   21756 cleanup:
   21757 	if (newcheckds != NULL) {
   21758 		checkds_destroy(newcheckds, true);
   21759 	}
   21760 }
   21761 
   21762 static void
   21763 checkds_send(dns_zone_t *zone) {
   21764 	dns_view_t *view = dns_zone_getview(zone);
   21765 	isc_result_t result;
   21766 	unsigned int flags = 0;
   21767 	unsigned int i = 0;
   21768 
   21769 	/*
   21770 	 * Zone lock held by caller.
   21771 	 */
   21772 	REQUIRE(LOCKED_ZONE(zone));
   21773 
   21774 	dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21775 		     "checkds: start sending DS queries to %u parentals",
   21776 		     dns_remote_count(&zone->parentals));
   21777 
   21778 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   21779 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21780 			     "checkds: abort, named exiting");
   21781 		return;
   21782 	}
   21783 
   21784 	dns_remote_reset(&zone->parentals, false);
   21785 	while (!dns_remote_done(&zone->parentals)) {
   21786 		dns_tsigkey_t *key = NULL;
   21787 		dns_transport_t *transport = NULL;
   21788 		isc_sockaddr_t src, dst;
   21789 		dns_checkds_t *checkds = NULL;
   21790 
   21791 		i++;
   21792 
   21793 		if (dns_remote_keyname(&zone->parentals) != NULL) {
   21794 			dns_name_t *keyname =
   21795 				dns_remote_keyname(&zone->parentals);
   21796 			(void)dns_view_gettsig(view, keyname, &key);
   21797 		}
   21798 
   21799 		if (dns_remote_tlsname(&zone->parentals) != NULL) {
   21800 			dns_name_t *tlsname =
   21801 				dns_remote_tlsname(&zone->parentals);
   21802 			(void)dns_view_gettransport(view, DNS_TRANSPORT_TLS,
   21803 						    tlsname, &transport);
   21804 			dns_zone_logc(
   21805 				zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   21806 				"got TLS configuration for zone transfer");
   21807 		}
   21808 
   21809 		dst = dns_remote_curraddr(&zone->parentals);
   21810 		src = dns_remote_sourceaddr(&zone->parentals);
   21811 		INSIST(isc_sockaddr_pf(&src) == isc_sockaddr_pf(&dst));
   21812 
   21813 		if (isc_sockaddr_disabled(&dst)) {
   21814 			if (key != NULL) {
   21815 				dns_tsigkey_detach(&key);
   21816 			}
   21817 			if (transport != NULL) {
   21818 				dns_transport_detach(&transport);
   21819 			}
   21820 			goto next;
   21821 		}
   21822 
   21823 		/* TODO: glue the transport to the checkds request */
   21824 
   21825 		if (checkds_isqueued(zone, NULL, &dst, key, transport)) {
   21826 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21827 				     "checkds: DS query to parent "
   21828 				     "%d is queued",
   21829 				     i);
   21830 			if (key != NULL) {
   21831 				dns_tsigkey_detach(&key);
   21832 			}
   21833 			if (transport != NULL) {
   21834 				dns_transport_detach(&transport);
   21835 			}
   21836 			goto next;
   21837 		}
   21838 
   21839 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21840 			     "checkds: create DS query for "
   21841 			     "parent %d",
   21842 			     i);
   21843 
   21844 		checkds_create(zone->mctx, flags, &checkds);
   21845 		zone_iattach(zone, &checkds->zone);
   21846 		dns_name_dup(dns_rootname, checkds->mctx, &checkds->ns);
   21847 		checkds->src = src;
   21848 		checkds->dst = dst;
   21849 
   21850 		INSIST(checkds->key == NULL);
   21851 		if (key != NULL) {
   21852 			checkds->key = key;
   21853 			key = NULL;
   21854 		}
   21855 
   21856 		INSIST(checkds->transport == NULL);
   21857 		if (transport != NULL) {
   21858 			checkds->transport = transport;
   21859 			transport = NULL;
   21860 		}
   21861 
   21862 		ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
   21863 		result = isc_ratelimiter_enqueue(
   21864 			checkds->zone->zmgr->checkdsrl, checkds->zone->loop,
   21865 			checkds_send_toaddr, checkds, &checkds->rlevent);
   21866 		if (result != ISC_R_SUCCESS) {
   21867 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21868 				     "checkds: send DS query to "
   21869 				     "parent %d failed",
   21870 				     i);
   21871 			checkds_destroy(checkds, true);
   21872 		}
   21873 
   21874 	next:
   21875 		dns_remote_next(&zone->parentals, false);
   21876 	}
   21877 }
   21878 
   21879 /*
   21880  * An NS RRset has been fetched from the parent of a zone whose DS RRset needs
   21881  * to be checked; scan the RRset and start sending queries to the parental
   21882  * agents.
   21883  */
   21884 static void
   21885 nsfetch_done(void *arg) {
   21886 	dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
   21887 	isc_result_t result, eresult;
   21888 	dns_nsfetch_t *nsfetch = NULL;
   21889 	dns_zone_t *zone = NULL;
   21890 	isc_mem_t *mctx = NULL;
   21891 	dns_name_t *zname = NULL;
   21892 	dns_name_t *pname = NULL;
   21893 	char pnamebuf[DNS_NAME_FORMATSIZE];
   21894 	bool free_needed, levelup = false;
   21895 	dns_rdataset_t *nsrrset = NULL;
   21896 	dns_rdataset_t *nssigset = NULL;
   21897 
   21898 	INSIST(resp != NULL);
   21899 
   21900 	nsfetch = resp->arg;
   21901 
   21902 	INSIST(nsfetch != NULL);
   21903 
   21904 	zone = nsfetch->zone;
   21905 	mctx = nsfetch->mctx;
   21906 	zname = dns_fixedname_name(&nsfetch->name);
   21907 	pname = &nsfetch->pname;
   21908 	nsrrset = &nsfetch->nsrrset;
   21909 	nssigset = &nsfetch->nssigset;
   21910 	eresult = resp->result;
   21911 
   21912 	/* Free resources which are not of interest */
   21913 	if (resp->node != NULL) {
   21914 		dns_db_detachnode(resp->db, &resp->node);
   21915 	}
   21916 	if (resp->db != NULL) {
   21917 		dns_db_detach(&resp->db);
   21918 	}
   21919 	dns_resolver_destroyfetch(&nsfetch->fetch);
   21920 
   21921 	LOCK_ZONE(zone);
   21922 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
   21923 		goto cleanup;
   21924 	}
   21925 
   21926 	zone->nsfetchcount--;
   21927 
   21928 	dns_name_format(pname, pnamebuf, sizeof(pnamebuf));
   21929 	dnssec_log(zone, ISC_LOG_DEBUG(3),
   21930 		   "Returned from '%s' NS fetch in nsfetch_done(): %s",
   21931 		   pnamebuf, isc_result_totext(eresult));
   21932 
   21933 	if (eresult == DNS_R_NCACHENXRRSET || eresult == DNS_R_NXRRSET) {
   21934 		dnssec_log(zone, ISC_LOG_DEBUG(3),
   21935 			   "NODATA response for NS '%s', level up", pnamebuf);
   21936 		levelup = true;
   21937 		goto cleanup;
   21938 
   21939 	} else if (eresult != ISC_R_SUCCESS) {
   21940 		dnssec_log(zone, ISC_LOG_WARNING,
   21941 			   "Unable to fetch NS set '%s': %s", pnamebuf,
   21942 			   isc_result_totext(eresult));
   21943 		result = eresult;
   21944 		goto done;
   21945 	}
   21946 
   21947 	/* No NS records found */
   21948 	if (!dns_rdataset_isassociated(nsrrset)) {
   21949 		dnssec_log(zone, ISC_LOG_WARNING,
   21950 			   "No NS records found for '%s'", pnamebuf);
   21951 		result = ISC_R_NOTFOUND;
   21952 		goto done;
   21953 	}
   21954 
   21955 	/* No RRSIGs found */
   21956 	if (!dns_rdataset_isassociated(nssigset)) {
   21957 		dnssec_log(zone, ISC_LOG_WARNING, "No NS RRSIGs found for '%s'",
   21958 			   pnamebuf);
   21959 		result = DNS_R_MUSTBESECURE;
   21960 		goto done;
   21961 	}
   21962 
   21963 	/* Check trust level */
   21964 	if (nsrrset->trust < dns_trust_secure) {
   21965 		dnssec_log(zone, ISC_LOG_WARNING,
   21966 			   "Invalid NS RRset for '%s' trust level %u", pnamebuf,
   21967 			   nsrrset->trust);
   21968 		result = DNS_R_MUSTBESECURE;
   21969 		goto done;
   21970 	}
   21971 
   21972 	/* Record the number of NS records we found. */
   21973 	zone->parent_nscount = dns_rdataset_count(nsrrset);
   21974 
   21975 	UNLOCK_ZONE(zone);
   21976 
   21977 	/* Look up the addresses for the found parental name servers. */
   21978 	for (result = dns_rdataset_first(nsrrset); result == ISC_R_SUCCESS;
   21979 	     result = dns_rdataset_next(nsrrset))
   21980 	{
   21981 		dns_checkds_t *checkds = NULL;
   21982 		dns_rdata_t rdata = DNS_RDATA_INIT;
   21983 		dns_rdata_ns_t ns;
   21984 		bool isqueued;
   21985 
   21986 		dns_rdataset_current(nsrrset, &rdata);
   21987 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
   21988 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   21989 
   21990 		dns_rdata_reset(&rdata);
   21991 
   21992 		LOCK_ZONE(zone);
   21993 		isqueued = checkds_isqueued(zone, &ns.name, NULL, NULL, NULL);
   21994 		UNLOCK_ZONE(zone);
   21995 		if (isqueued) {
   21996 			continue;
   21997 		}
   21998 		checkds_create(zone->mctx, 0, &checkds);
   21999 
   22000 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   22001 			char nsnamebuf[DNS_NAME_FORMATSIZE];
   22002 			dns_name_format(&ns.name, nsnamebuf, sizeof(nsnamebuf));
   22003 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
   22004 				     "checkds: send DS query to NS %s",
   22005 				     nsnamebuf);
   22006 		}
   22007 
   22008 		LOCK_ZONE(zone);
   22009 		zone_iattach(zone, &checkds->zone);
   22010 		dns_name_dup(&ns.name, zone->mctx, &checkds->ns);
   22011 		ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
   22012 		UNLOCK_ZONE(zone);
   22013 
   22014 		checkds_find_address(checkds);
   22015 	}
   22016 	if (result == ISC_R_NOMORE) {
   22017 		result = ISC_R_SUCCESS;
   22018 	}
   22019 
   22020 	LOCK_ZONE(zone);
   22021 
   22022 done:
   22023 	if (result != ISC_R_SUCCESS) {
   22024 		dnssec_log(
   22025 			zone, ISC_LOG_ERROR,
   22026 			"checkds: error during parental-agents processing: %s",
   22027 			isc_result_totext(result));
   22028 	}
   22029 
   22030 cleanup:
   22031 	isc_refcount_decrement(&zone->irefs);
   22032 
   22033 	if (dns_rdataset_isassociated(nsrrset)) {
   22034 		dns_rdataset_disassociate(nsrrset);
   22035 	}
   22036 	if (dns_rdataset_isassociated(nssigset)) {
   22037 		dns_rdataset_disassociate(nssigset);
   22038 	}
   22039 
   22040 	dns_resolver_freefresp(&resp);
   22041 
   22042 	if (levelup) {
   22043 		UNLOCK_ZONE(zone);
   22044 		nsfetch_levelup(nsfetch);
   22045 		return;
   22046 	}
   22047 
   22048 	dns_name_free(zname, mctx);
   22049 	isc_mem_putanddetach(&nsfetch->mctx, nsfetch, sizeof(dns_nsfetch_t));
   22050 
   22051 	free_needed = exit_check(zone);
   22052 	UNLOCK_ZONE(zone);
   22053 
   22054 	if (free_needed) {
   22055 		zone_free(zone);
   22056 	}
   22057 }
   22058 
   22059 static void
   22060 do_nsfetch(void *arg) {
   22061 	dns_nsfetch_t *nsfetch = (dns_nsfetch_t *)arg;
   22062 	isc_result_t result;
   22063 	unsigned int nlabels = 1;
   22064 	dns_resolver_t *resolver = NULL;
   22065 	dns_zone_t *zone = nsfetch->zone;
   22066 	unsigned int options = DNS_FETCHOPT_UNSHARED | DNS_FETCHOPT_NOCACHED;
   22067 
   22068 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   22069 		result = ISC_R_SHUTTINGDOWN;
   22070 		goto cleanup;
   22071 	}
   22072 
   22073 	result = dns_view_getresolver(zone->view, &resolver);
   22074 	if (result != ISC_R_SUCCESS) {
   22075 		goto cleanup;
   22076 	}
   22077 
   22078 	if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   22079 		char namebuf[DNS_NAME_FORMATSIZE];
   22080 		dns_name_format(&nsfetch->pname, namebuf, sizeof(namebuf));
   22081 		dnssec_log(zone, ISC_LOG_DEBUG(3),
   22082 			   "Create fetch for '%s' NS request", namebuf);
   22083 	}
   22084 
   22085 	/* Derive parent domain. XXXWMM: Check for root domain */
   22086 	dns_name_split(&nsfetch->pname,
   22087 		       dns_name_countlabels(&nsfetch->pname) - nlabels, NULL,
   22088 		       &nsfetch->pname);
   22089 
   22090 	/*
   22091 	 * Use of DNS_FETCHOPT_NOCACHED is essential here.  If it is not
   22092 	 * set and the cache still holds a non-expired, validated version
   22093 	 * of the RRset being queried for by the time the response is
   22094 	 * received, the cached RRset will be passed to nsfetch_done()
   22095 	 * instead of the one received in the response as the latter will
   22096 	 * have a lower trust level due to not being validated until
   22097 	 * nsfetch_done() is called.
   22098 	 */
   22099 	result = dns_resolver_createfetch(
   22100 		resolver, &nsfetch->pname, dns_rdatatype_ns, NULL, NULL, NULL,
   22101 		NULL, 0, options, 0, NULL, NULL, NULL, zone->loop, nsfetch_done,
   22102 		nsfetch, NULL, &nsfetch->nsrrset, &nsfetch->nssigset,
   22103 		&nsfetch->fetch);
   22104 
   22105 	dns_resolver_detach(&resolver);
   22106 
   22107 cleanup:
   22108 	if (result != ISC_R_SUCCESS) {
   22109 		dns_name_t *zname = dns_fixedname_name(&nsfetch->name);
   22110 		bool free_needed;
   22111 		char namebuf[DNS_NAME_FORMATSIZE];
   22112 		dns_name_format(&nsfetch->pname, namebuf, sizeof(namebuf));
   22113 		dnssec_log(zone, ISC_LOG_WARNING,
   22114 			   "Failed to create fetch for '%s' NS request",
   22115 			   namebuf);
   22116 		LOCK_ZONE(zone);
   22117 		zone->nsfetchcount--;
   22118 		isc_refcount_decrement(&zone->irefs);
   22119 
   22120 		dns_name_free(zname, zone->mctx);
   22121 		isc_mem_putanddetach(&nsfetch->mctx, nsfetch, sizeof(*nsfetch));
   22122 
   22123 		free_needed = exit_check(zone);
   22124 		UNLOCK_ZONE(zone);
   22125 		if (free_needed) {
   22126 			zone_free(zone);
   22127 		}
   22128 	}
   22129 }
   22130 
   22131 /*
   22132  * Retry an NS RRset lookup, one level up. In other words, this function should
   22133  * be called on an dns_nsfetch structure where the response yielded in a NODATA
   22134  * response. This must be because there is an empty non-terminal inbetween the
   22135  * child and parent zone.
   22136  */
   22137 static void
   22138 nsfetch_levelup(dns_nsfetch_t *nsfetch) {
   22139 	dns_zone_t *zone = nsfetch->zone;
   22140 
   22141 #ifdef ENABLE_AFL
   22142 	if (!dns_fuzzing_resolver) {
   22143 #endif /* ifdef ENABLE_AFL */
   22144 		LOCK_ZONE(zone);
   22145 		zone->nsfetchcount++;
   22146 		isc_refcount_increment0(&zone->irefs);
   22147 
   22148 		dns_rdataset_init(&nsfetch->nsrrset);
   22149 		dns_rdataset_init(&nsfetch->nssigset);
   22150 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   22151 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   22152 				   "Creating parent NS fetch in "
   22153 				   "nsfetch_levelup()");
   22154 		}
   22155 		isc_async_run(zone->loop, do_nsfetch, nsfetch);
   22156 		UNLOCK_ZONE(zone);
   22157 #ifdef ENABLE_AFL
   22158 	}
   22159 #endif /* ifdef ENABLE_AFL */
   22160 }
   22161 
   22162 static void
   22163 zone_checkds(dns_zone_t *zone) {
   22164 	bool cdscheck = false;
   22165 	dns_checkdstype_t checkdstype = zone->checkdstype;
   22166 
   22167 	if (checkdstype == dns_checkdstype_no) {
   22168 		return;
   22169 	}
   22170 
   22171 	for (dns_dnsseckey_t *key = ISC_LIST_HEAD(zone->checkds_ok);
   22172 	     key != NULL; key = ISC_LIST_NEXT(key, link))
   22173 	{
   22174 		dst_key_state_t ds_state = DST_KEY_STATE_NA;
   22175 		bool ksk = false;
   22176 		isc_stdtime_t published = 0, withdrawn = 0;
   22177 
   22178 		/* Is this key have the KSK role? */
   22179 		(void)dst_key_role(key->key, &ksk, NULL);
   22180 		if (!ksk) {
   22181 			continue;
   22182 		}
   22183 
   22184 		/* Do we need to check the DS RRset? */
   22185 		(void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
   22186 		(void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
   22187 		(void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
   22188 
   22189 		if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
   22190 			dst_key_setnum(key->key, DST_NUM_DSPUBCOUNT, 0);
   22191 			cdscheck = true;
   22192 		} else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
   22193 			   withdrawn == 0)
   22194 		{
   22195 			dst_key_setnum(key->key, DST_NUM_DSDELCOUNT, 0);
   22196 			cdscheck = true;
   22197 		}
   22198 	}
   22199 
   22200 	if (!cdscheck) {
   22201 		return;
   22202 	}
   22203 
   22204 	if (checkdstype == dns_checkdstype_explicit) {
   22205 		/* Request the DS RRset. */
   22206 		LOCK_ZONE(zone);
   22207 		checkds_send(zone);
   22208 		UNLOCK_ZONE(zone);
   22209 		return;
   22210 	}
   22211 
   22212 	INSIST(checkdstype == dns_checkdstype_yes);
   22213 
   22214 #ifdef ENABLE_AFL
   22215 	if (!dns_fuzzing_resolver) {
   22216 #endif /* ifdef ENABLE_AFL */
   22217 		dns_nsfetch_t *nsfetch;
   22218 		dns_name_t *name = NULL;
   22219 
   22220 		nsfetch = isc_mem_get(zone->mctx, sizeof(dns_nsfetch_t));
   22221 		*nsfetch = (dns_nsfetch_t){ .zone = zone };
   22222 		isc_mem_attach(zone->mctx, &nsfetch->mctx);
   22223 		LOCK_ZONE(zone);
   22224 		zone->nsfetchcount++;
   22225 		isc_refcount_increment0(&zone->irefs);
   22226 		name = dns_fixedname_initname(&nsfetch->name);
   22227 		dns_name_init(&nsfetch->pname, NULL);
   22228 		dns_name_clone(&zone->origin, &nsfetch->pname);
   22229 		dns_name_dup(&zone->origin, zone->mctx, name);
   22230 		dns_rdataset_init(&nsfetch->nsrrset);
   22231 		dns_rdataset_init(&nsfetch->nssigset);
   22232 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   22233 			dnssec_log(
   22234 				zone, ISC_LOG_DEBUG(3),
   22235 				"Creating parent NS fetch in zone_checkds()");
   22236 		}
   22237 		isc_async_run(zone->loop, do_nsfetch, nsfetch);
   22238 		UNLOCK_ZONE(zone);
   22239 #ifdef ENABLE_AFL
   22240 	}
   22241 #endif /* ifdef ENABLE_AFL */
   22242 }
   22243 
   22244 static isc_result_t
   22245 update_ttl(dns_rdataset_t *rdataset, dns_name_t *name, dns_ttl_t ttl,
   22246 	   dns_diff_t *diff) {
   22247 	isc_result_t result;
   22248 
   22249 	/*
   22250 	 * Delete everything using the existing TTL.
   22251 	 */
   22252 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   22253 	     result = dns_rdataset_next(rdataset))
   22254 	{
   22255 		dns_difftuple_t *tuple = NULL;
   22256 		dns_rdata_t rdata = DNS_RDATA_INIT;
   22257 
   22258 		dns_rdataset_current(rdataset, &rdata);
   22259 		result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
   22260 					      rdataset->ttl, &rdata, &tuple);
   22261 		if (result != ISC_R_SUCCESS) {
   22262 			return result;
   22263 		}
   22264 		dns_diff_appendminimal(diff, &tuple);
   22265 	}
   22266 	if (result != ISC_R_NOMORE) {
   22267 		return result;
   22268 	}
   22269 
   22270 	/*
   22271 	 * Add everything using the new TTL.
   22272 	 */
   22273 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   22274 	     result = dns_rdataset_next(rdataset))
   22275 	{
   22276 		dns_difftuple_t *tuple = NULL;
   22277 		dns_rdata_t rdata = DNS_RDATA_INIT;
   22278 
   22279 		dns_rdataset_current(rdataset, &rdata);
   22280 		result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
   22281 					      ttl, &rdata, &tuple);
   22282 		if (result != ISC_R_SUCCESS) {
   22283 			return result;
   22284 		}
   22285 		dns_diff_appendminimal(diff, &tuple);
   22286 	}
   22287 	if (result != ISC_R_NOMORE) {
   22288 		return result;
   22289 	}
   22290 	return ISC_R_SUCCESS;
   22291 }
   22292 
   22293 static isc_result_t
   22294 zone_verifykeys(dns_zone_t *zone, dns_dnsseckeylist_t *newkeys,
   22295 		uint32_t purgeval, isc_stdtime_t now) {
   22296 	dns_dnsseckey_t *key1, *key2, *next;
   22297 
   22298 	/*
   22299 	 * Make sure that the existing keys are also present in the new keylist.
   22300 	 */
   22301 	for (key1 = ISC_LIST_HEAD(zone->keyring); key1 != NULL; key1 = next) {
   22302 		bool found = false;
   22303 		next = ISC_LIST_NEXT(key1, link);
   22304 
   22305 		if (dst_key_is_unused(key1->key)) {
   22306 			continue;
   22307 		}
   22308 		if (dns_keymgr_key_may_be_purged(key1->key, purgeval, now)) {
   22309 			continue;
   22310 		}
   22311 		if (key1->purge) {
   22312 			continue;
   22313 		}
   22314 
   22315 		for (key2 = ISC_LIST_HEAD(*newkeys); key2 != NULL;
   22316 		     key2 = ISC_LIST_NEXT(key2, link))
   22317 		{
   22318 			if (dst_key_compare(key1->key, key2->key)) {
   22319 				found = true;
   22320 				break;
   22321 			}
   22322 		}
   22323 
   22324 		if (!found) {
   22325 			char keystr[DST_KEY_FORMATSIZE];
   22326 			dst_key_format(key1->key, keystr, sizeof(keystr));
   22327 			dnssec_log(zone, ISC_LOG_DEBUG(1),
   22328 				   "verifykeys: key %s - not available",
   22329 				   keystr);
   22330 			return ISC_R_NOTFOUND;
   22331 		}
   22332 	}
   22333 
   22334 	/* All good. */
   22335 	return ISC_R_SUCCESS;
   22336 }
   22337 
   22338 static void
   22339 remove_rdataset(dns_zone_t *zone, dns_diff_t *diff, dns_rdataset_t *rdataset) {
   22340 	if (!dns_rdataset_isassociated(rdataset)) {
   22341 		return;
   22342 	}
   22343 
   22344 	for (isc_result_t result = dns_rdataset_first(rdataset);
   22345 	     result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset))
   22346 	{
   22347 		dns_rdata_t rdata = DNS_RDATA_INIT;
   22348 		dns_difftuple_t *tuple = NULL;
   22349 
   22350 		dns_rdataset_current(rdataset, &rdata);
   22351 		dns_difftuple_create(zone->mctx, DNS_DIFFOP_DEL, &zone->origin,
   22352 				     rdataset->ttl, &rdata, &tuple);
   22353 		dns_diff_append(diff, &tuple);
   22354 	}
   22355 	return;
   22356 }
   22357 
   22358 static void
   22359 add_tuple(dns_diff_t *diff, dns_difftuple_t *tuple) {
   22360 	dns_difftuple_t *copy = NULL;
   22361 
   22362 	dns_difftuple_copy(tuple, &copy);
   22363 	dns_diff_appendminimal(diff, &copy);
   22364 }
   22365 
   22366 static void
   22367 zone_apply_skrbundle(dns_zone_t *zone, dns_skrbundle_t *bundle,
   22368 		     dns_rdataset_t *dnskeyset, dns_rdataset_t *cdsset,
   22369 		     dns_rdataset_t *cdnskeyset, dns_diff_t *diff) {
   22370 	dns_kasp_t *kasp = zone->kasp;
   22371 
   22372 	REQUIRE(DNS_ZONE_VALID(zone));
   22373 	REQUIRE(DNS_KASP_VALID(kasp));
   22374 	REQUIRE(DNS_SKRBUNDLE_VALID(bundle));
   22375 
   22376 	/* Remove existing DNSKEY, CDS, and CDNSKEY records. */
   22377 	remove_rdataset(zone, diff, dnskeyset);
   22378 	remove_rdataset(zone, diff, cdsset);
   22379 	remove_rdataset(zone, diff, cdnskeyset);
   22380 
   22381 	/* Add the records from the bundle. */
   22382 	dns_difftuple_t *tuple = ISC_LIST_HEAD(bundle->diff.tuples);
   22383 	while (tuple != NULL) {
   22384 		switch (tuple->rdata.type) {
   22385 		case dns_rdatatype_dnskey:
   22386 			add_tuple(diff, tuple);
   22387 			break;
   22388 		case dns_rdatatype_cdnskey:
   22389 		case dns_rdatatype_cds:
   22390 			add_tuple(diff, tuple);
   22391 			break;
   22392 		case dns_rdatatype_rrsig:
   22393 			/* Not interested in right now */
   22394 			break;
   22395 		default:
   22396 			INSIST(0);
   22397 		}
   22398 
   22399 		tuple = ISC_LIST_NEXT(tuple, link);
   22400 	}
   22401 }
   22402 
   22403 static void
   22404 zone_rekey(dns_zone_t *zone) {
   22405 	isc_result_t result;
   22406 	dns_db_t *db = NULL;
   22407 	dns_dbnode_t *node = NULL;
   22408 	dns_dbversion_t *ver = NULL;
   22409 	dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
   22410 	dns_dnsseckeylist_t dnskeys, keys, rmkeys;
   22411 	dns_dnsseckey_t *key = NULL;
   22412 	dns_diff_t diff, _sig_diff;
   22413 	dns_kasp_t *kasp;
   22414 	dns_skrbundle_t *bundle = NULL;
   22415 	dns__zonediff_t zonediff;
   22416 	bool commit = false, newactive = false;
   22417 	bool newalg = false;
   22418 	bool fullsign;
   22419 	bool offlineksk = false;
   22420 	bool kasp_change = false;
   22421 	uint8_t options = 0;
   22422 	uint32_t sigval = 0;
   22423 	dns_ttl_t ttl = 3600;
   22424 	const char *dir = NULL;
   22425 	isc_mem_t *mctx = NULL;
   22426 	isc_stdtime_t now, nexttime = 0;
   22427 	isc_time_t timenow;
   22428 	isc_interval_t ival;
   22429 	char timebuf[80];
   22430 
   22431 	REQUIRE(DNS_ZONE_VALID(zone));
   22432 
   22433 	ISC_LIST_INIT(dnskeys);
   22434 	ISC_LIST_INIT(keys);
   22435 	ISC_LIST_INIT(rmkeys);
   22436 	dns_rdataset_init(&soaset);
   22437 	dns_rdataset_init(&soasigs);
   22438 	dns_rdataset_init(&keyset);
   22439 	dns_rdataset_init(&keysigs);
   22440 	dns_rdataset_init(&cdsset);
   22441 	dns_rdataset_init(&cdnskeyset);
   22442 	mctx = zone->mctx;
   22443 	dns_diff_init(mctx, &diff);
   22444 	dns_diff_init(mctx, &_sig_diff);
   22445 	zonediff_init(&zonediff, &_sig_diff);
   22446 
   22447 	CHECK(dns_zone_getdb(zone, &db));
   22448 	CHECK(dns_db_newversion(db, &ver));
   22449 	CHECK(dns_db_getoriginnode(db, &node));
   22450 
   22451 	timenow = isc_time_now();
   22452 	now = isc_time_seconds(&timenow);
   22453 
   22454 	kasp = zone->kasp;
   22455 	dir = dns_zone_getkeydirectory(zone);
   22456 
   22457 	dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
   22458 
   22459 	/* Get the SOA record's TTL */
   22460 	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
   22461 				  dns_rdatatype_none, 0, &soaset, &soasigs));
   22462 	ttl = soaset.ttl;
   22463 	dns_rdataset_disassociate(&soaset);
   22464 
   22465 	if (kasp != NULL) {
   22466 		ttl = dns_kasp_dnskeyttl(kasp);
   22467 		offlineksk = dns_kasp_offlineksk(kasp);
   22468 		sigval = dns_kasp_sigvalidity_dnskey(kasp);
   22469 	}
   22470 
   22471 	/* Get the current DNSKEY rdataset */
   22472 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
   22473 				     dns_rdatatype_none, 0, &keyset, &keysigs);
   22474 	if (result == ISC_R_SUCCESS) {
   22475 		/*
   22476 		 * If we don't have a policy then use the DNSKEY ttl
   22477 		 * if it exists.  Otherwise update the DNSKEY ttl if
   22478 		 * needed.
   22479 		 */
   22480 		if (kasp == NULL) {
   22481 			ttl = keyset.ttl;
   22482 		} else if (ttl != keyset.ttl && !offlineksk) {
   22483 			result = update_ttl(&keyset, &zone->origin, ttl, &diff);
   22484 			if (result != ISC_R_SUCCESS) {
   22485 				dnssec_log(zone, ISC_LOG_ERROR,
   22486 					   "Updating DNSKEY TTL from %u to %u "
   22487 					   "failed: %s",
   22488 					   keyset.ttl, ttl,
   22489 					   isc_result_totext(result));
   22490 				goto cleanup;
   22491 			}
   22492 			dnssec_log(zone, ISC_LOG_INFO,
   22493 				   "Updating DNSKEY TTL from %u to %u",
   22494 				   keyset.ttl, ttl);
   22495 			keyset.ttl = ttl;
   22496 		}
   22497 
   22498 		dns_zone_lock_keyfiles(zone);
   22499 
   22500 		result = dns_dnssec_keylistfromrdataset(
   22501 			&zone->origin, kasp, dir, mctx, &keyset, &keysigs,
   22502 			&soasigs, false, false, &dnskeys);
   22503 
   22504 		dns_zone_unlock_keyfiles(zone);
   22505 
   22506 		CHECK(result);
   22507 	} else if (result != ISC_R_NOTFOUND) {
   22508 		goto cleanup;
   22509 	}
   22510 
   22511 	/* Get the current CDS rdataset */
   22512 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
   22513 				     dns_rdatatype_none, 0, &cdsset, NULL);
   22514 	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
   22515 		dns_rdataset_disassociate(&cdsset);
   22516 	} else if (result == ISC_R_SUCCESS && kasp != NULL &&
   22517 		   ttl != cdsset.ttl && !offlineksk)
   22518 	{
   22519 		result = update_ttl(&cdsset, &zone->origin, ttl, &diff);
   22520 		if (result != ISC_R_SUCCESS) {
   22521 			dnssec_log(zone, ISC_LOG_ERROR,
   22522 				   "Updating CDS TTL from %u to %u failed: %s",
   22523 				   cdsset.ttl, ttl, isc_result_totext(result));
   22524 			goto cleanup;
   22525 		}
   22526 		dnssec_log(zone, ISC_LOG_INFO, "Updating CDS TTL from %u to %u",
   22527 			   cdsset.ttl, ttl);
   22528 		cdsset.ttl = ttl;
   22529 	}
   22530 
   22531 	/* Get the current CDNSKEY rdataset */
   22532 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
   22533 				     dns_rdatatype_none, 0, &cdnskeyset, NULL);
   22534 	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
   22535 		dns_rdataset_disassociate(&cdnskeyset);
   22536 	} else if (result == ISC_R_SUCCESS && kasp != NULL &&
   22537 		   ttl != cdnskeyset.ttl && !offlineksk)
   22538 	{
   22539 		result = update_ttl(&cdnskeyset, &zone->origin, ttl, &diff);
   22540 		if (result != ISC_R_SUCCESS) {
   22541 			dnssec_log(
   22542 				zone, ISC_LOG_ERROR,
   22543 				"Updating CDNSKEY TTL from %u to %u failed: %s",
   22544 				cdnskeyset.ttl, ttl, isc_result_totext(result));
   22545 			goto cleanup;
   22546 		}
   22547 		dnssec_log(zone, ISC_LOG_INFO,
   22548 			   "Updating CDNSKEY TTL from %u to %u", cdnskeyset.ttl,
   22549 			   ttl);
   22550 		cdnskeyset.ttl = ttl;
   22551 	}
   22552 
   22553 	/*
   22554 	 * True when called from "rndc sign".  Indicates the zone should be
   22555 	 * fully signed now.
   22556 	 */
   22557 	fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
   22558 	if (fullsign) {
   22559 		options |= DNS_KEYMGRATTR_FULLSIGN;
   22560 	}
   22561 
   22562 	/*
   22563 	 * True when called from "rndc dnssec -step". Indicates the zone
   22564 	 * is allowed to do the next step(s) in the keymgr process.
   22565 	 */
   22566 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FORCEKEYMGR)) {
   22567 		options |= DNS_KEYMGRATTR_FORCESTEP;
   22568 	}
   22569 
   22570 	if (offlineksk) {
   22571 		/* Lookup the correct bundle in the SKR. */
   22572 		LOCK_ZONE(zone);
   22573 		if (zone->skr == NULL) {
   22574 			UNLOCK_ZONE(zone);
   22575 			dnssec_log(zone, ISC_LOG_DEBUG(1),
   22576 				   "zone_rekey:dns_skr_lookup failed: "
   22577 				   "no SKR available");
   22578 			CHECK(DNS_R_NOSKRFILE);
   22579 		}
   22580 		bundle = dns_skr_lookup(zone->skr, now, sigval);
   22581 		zone->skrbundle = bundle;
   22582 		UNLOCK_ZONE(zone);
   22583 
   22584 		if (bundle == NULL) {
   22585 			char nowstr[26]; /* Minimal buf per ctime_r() spec. */
   22586 			char utc[sizeof("YYYYMMDDHHSSMM")];
   22587 			isc_buffer_t b;
   22588 			isc_region_t r;
   22589 			isc_buffer_init(&b, utc, sizeof(utc));
   22590 
   22591 			isc_stdtime_tostring(now, nowstr, sizeof(nowstr));
   22592 			(void)dns_time32_totext(now, &b);
   22593 			isc_buffer_usedregion(&b, &r);
   22594 			dnssec_log(zone, ISC_LOG_DEBUG(1),
   22595 				   "zone_rekey:dns_skr_lookup failed: "
   22596 				   "no available SKR bundle for time "
   22597 				   "%.*s (%s)",
   22598 				   (int)r.length, r.base, nowstr);
   22599 			CHECK(DNS_R_NOSKRBUNDLE);
   22600 		}
   22601 
   22602 		zone_apply_skrbundle(zone, bundle, &keyset, &cdsset,
   22603 				     &cdnskeyset, &diff);
   22604 
   22605 		dns_skrbundle_t *next = ISC_LIST_NEXT(bundle, link);
   22606 		if (next != NULL) {
   22607 			if (nexttime == 0) {
   22608 				nexttime = next->inception;
   22609 			}
   22610 		} else {
   22611 			dnssec_log(zone, ISC_LOG_WARNING,
   22612 				   "zone_rekey: last bundle in skr, please "
   22613 				   "import new skr file");
   22614 		}
   22615 	}
   22616 
   22617 	/*
   22618 	 * DNSSEC Key and Signing Policy
   22619 	 */
   22620 
   22621 	KASP_LOCK(kasp);
   22622 
   22623 	dns_zone_lock_keyfiles(zone);
   22624 	result = dns_dnssec_findmatchingkeys(&zone->origin, kasp, dir,
   22625 					     zone->keystores, now, false, mctx,
   22626 					     &keys);
   22627 	dns_zone_unlock_keyfiles(zone);
   22628 
   22629 	if (result != ISC_R_SUCCESS) {
   22630 		dnssec_log(zone, ISC_LOG_DEBUG(1),
   22631 			   "zone_rekey:dns_dnssec_findmatchingkeys failed: %s",
   22632 			   isc_result_totext(result));
   22633 	}
   22634 
   22635 	if (kasp != NULL && !offlineksk) {
   22636 		/* Verify new keys. */
   22637 		isc_result_t ret = zone_verifykeys(
   22638 			zone, &keys, dns_kasp_purgekeys(kasp), now);
   22639 		if (ret != ISC_R_SUCCESS) {
   22640 			dnssec_log(zone, ISC_LOG_ERROR,
   22641 				   "zone_rekey:zone_verifykeys failed: "
   22642 				   "some key files are missing");
   22643 			KASP_UNLOCK(kasp);
   22644 			goto cleanup;
   22645 		}
   22646 
   22647 		/*
   22648 		 * Check DS at parental agents. Clear ongoing checks.
   22649 		 */
   22650 		LOCK_ZONE(zone);
   22651 		checkds_cancel(zone);
   22652 		clear_keylist(&zone->checkds_ok, zone->mctx);
   22653 		ISC_LIST_INIT(zone->checkds_ok);
   22654 		UNLOCK_ZONE(zone);
   22655 
   22656 		ret = dns_zone_getdnsseckeys(zone, db, ver, now,
   22657 					     &zone->checkds_ok);
   22658 		if (ret == ISC_R_SUCCESS) {
   22659 			zone_checkds(zone);
   22660 		} else {
   22661 			dnssec_log(zone,
   22662 				   (ret == ISC_R_NOTFOUND) ? ISC_LOG_DEBUG(1)
   22663 							   : ISC_LOG_ERROR,
   22664 				   "zone_rekey:dns_zone_getdnsseckeys failed: "
   22665 				   "%s",
   22666 				   isc_result_totext(ret));
   22667 		}
   22668 
   22669 		/* Run keymgr. */
   22670 		if (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND) {
   22671 			dns_zone_lock_keyfiles(zone);
   22672 			result = dns_keymgr_run(&zone->origin, zone->rdclass,
   22673 						mctx, &keys, &dnskeys, dir,
   22674 						kasp, options, now, &nexttime);
   22675 			dns_zone_unlock_keyfiles(zone);
   22676 
   22677 			if (result == ISC_R_SUCCESS) {
   22678 				kasp_change = true;
   22679 			} else if (result == DNS_R_UNCHANGED) {
   22680 				result = ISC_R_SUCCESS;
   22681 			} else {
   22682 				dnssec_log(zone, ISC_LOG_ERROR,
   22683 					   "zone_rekey:dns_keymgr_run "
   22684 					   "failed: %s",
   22685 					   isc_result_totext(result));
   22686 				KASP_UNLOCK(kasp);
   22687 				goto cleanup;
   22688 			}
   22689 		}
   22690 	} else if (offlineksk) {
   22691 		/*
   22692 		 * With offline-ksk enabled we don't run the keymgr.
   22693 		 * Instead we derive the states from the timing metadata.
   22694 		 */
   22695 		dns_zone_lock_keyfiles(zone);
   22696 		result = dns_keymgr_offline(&zone->origin, &keys, kasp, now,
   22697 					    &nexttime);
   22698 		dns_zone_unlock_keyfiles(zone);
   22699 
   22700 		if (result != ISC_R_SUCCESS) {
   22701 			dnssec_log(zone, ISC_LOG_ERROR,
   22702 				   "zone_rekey:dns_keymgr_offline "
   22703 				   "failed: %s",
   22704 				   isc_result_totext(result));
   22705 		}
   22706 	}
   22707 
   22708 	KASP_UNLOCK(kasp);
   22709 
   22710 	/*
   22711 	 * Update CDS, CDNSKEY and DNSKEY record sets if the keymgr ran
   22712 	 * successfully (dns_keymgr_run returned ISC_R_SUCCESS), or in
   22713 	 * case of DNSSEC management without dnssec-policy if we have keys
   22714 	 * (dns_dnssec_findmatchingkeys returned ISC_R_SUCCESS).
   22715 	 */
   22716 	if (result == ISC_R_SUCCESS) {
   22717 		dns_kasp_digestlist_t digests;
   22718 		bool cdsdel = false;
   22719 		bool cdnskeydel = false;
   22720 		bool cdnskeypub = true;
   22721 		bool sane_diff, sane_dnskey;
   22722 		isc_stdtime_t when;
   22723 
   22724 		result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
   22725 					       &zone->origin, ttl, &diff, mctx,
   22726 					       dnssec_report);
   22727 		/*
   22728 		 * Keys couldn't be updated for some reason;
   22729 		 * try again later.
   22730 		 */
   22731 		if (result != ISC_R_SUCCESS) {
   22732 			dnssec_log(zone, ISC_LOG_ERROR,
   22733 				   "zone_rekey:couldn't update zone keys: %s",
   22734 				   isc_result_totext(result));
   22735 			goto cleanup;
   22736 		}
   22737 
   22738 		if (offlineksk) {
   22739 			/* We can skip a lot of things */
   22740 			goto post_sync;
   22741 		}
   22742 
   22743 		/*
   22744 		 * Publish CDS/CDNSKEY DELETE records if the zone is
   22745 		 * transitioning from secure to insecure.
   22746 		 */
   22747 		if (kasp != NULL) {
   22748 			if (strcmp(dns_kasp_getname(kasp), "insecure") == 0) {
   22749 				cdsdel = true;
   22750 				cdnskeydel = true;
   22751 			}
   22752 			digests = dns_kasp_digests(kasp);
   22753 			cdnskeypub = dns_kasp_cdnskey(kasp);
   22754 		} else {
   22755 			/* Check if there is a CDS DELETE record. */
   22756 			if (dns_rdataset_isassociated(&cdsset)) {
   22757 				for (result = dns_rdataset_first(&cdsset);
   22758 				     result == ISC_R_SUCCESS;
   22759 				     result = dns_rdataset_next(&cdsset))
   22760 				{
   22761 					dns_rdata_t crdata = DNS_RDATA_INIT;
   22762 					dns_rdataset_current(&cdsset, &crdata);
   22763 					/*
   22764 					 * CDS deletion record has this form
   22765 					 * "0 0 0 00" which is 5 zero octets.
   22766 					 */
   22767 					if (crdata.length == 5U &&
   22768 					    memcmp(crdata.data,
   22769 						   (unsigned char[5]){ 0, 0, 0,
   22770 								       0, 0 },
   22771 						   5) == 0)
   22772 					{
   22773 						cdsdel = true;
   22774 						break;
   22775 					}
   22776 				}
   22777 			}
   22778 
   22779 			/* Check if there is a CDNSKEY DELETE record. */
   22780 			if (dns_rdataset_isassociated(&cdnskeyset)) {
   22781 				for (result = dns_rdataset_first(&cdnskeyset);
   22782 				     result == ISC_R_SUCCESS;
   22783 				     result = dns_rdataset_next(&cdnskeyset))
   22784 				{
   22785 					dns_rdata_t crdata = DNS_RDATA_INIT;
   22786 					dns_rdataset_current(&cdnskeyset,
   22787 							     &crdata);
   22788 					/*
   22789 					 * CDNSKEY deletion record has this form
   22790 					 * "0 3 0 AA==" which is 2 zero octets,
   22791 					 * a 3, and 2 zero octets.
   22792 					 */
   22793 					if (crdata.length == 5U &&
   22794 					    memcmp(crdata.data,
   22795 						   (unsigned char[5]){ 0, 0, 3,
   22796 								       0, 0 },
   22797 						   5) == 0)
   22798 					{
   22799 						cdnskeydel = true;
   22800 						break;
   22801 					}
   22802 				}
   22803 			}
   22804 
   22805 			digests = dns_kasp_digests(zone->defaultkasp);
   22806 		}
   22807 
   22808 		/*
   22809 		 * Update CDS / CDNSKEY records.
   22810 		 */
   22811 		result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
   22812 					       &cdnskeyset, now, &digests,
   22813 					       cdnskeypub, ttl, &diff, mctx);
   22814 		if (result != ISC_R_SUCCESS) {
   22815 			dnssec_log(zone, ISC_LOG_ERROR,
   22816 				   "zone_rekey:couldn't update CDS/CDNSKEY: %s",
   22817 				   isc_result_totext(result));
   22818 			goto cleanup;
   22819 		}
   22820 
   22821 		if (cdsdel || cdnskeydel) {
   22822 			/*
   22823 			 * Only publish CDS/CDNSKEY DELETE records if there is
   22824 			 * a KSK that can be used to verify the RRset. This
   22825 			 * means there must be a key with the KSK role that is
   22826 			 * published and is used for signing.
   22827 			 */
   22828 			bool allow = false;
   22829 			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
   22830 			     key = ISC_LIST_NEXT(key, link))
   22831 			{
   22832 				dst_key_t *dstk = key->key;
   22833 
   22834 				if (dst_key_is_published(dstk, now, &when) &&
   22835 				    dst_key_is_signing(dstk, DST_BOOL_KSK, now,
   22836 						       &when))
   22837 				{
   22838 					allow = true;
   22839 					break;
   22840 				}
   22841 			}
   22842 			if (cdsdel) {
   22843 				cdsdel = allow;
   22844 			}
   22845 			if (cdnskeydel) {
   22846 				cdnskeydel = allow;
   22847 			}
   22848 		}
   22849 		result = dns_dnssec_syncdelete(
   22850 			&cdsset, &cdnskeyset, &zone->origin, zone->rdclass, ttl,
   22851 			&diff, mctx, cdsdel, cdnskeydel);
   22852 		if (result != ISC_R_SUCCESS) {
   22853 			dnssec_log(zone, ISC_LOG_ERROR,
   22854 				   "zone_rekey:couldn't update CDS/CDNSKEY "
   22855 				   "DELETE records: %s",
   22856 				   isc_result_totext(result));
   22857 			goto cleanup;
   22858 		}
   22859 
   22860 	post_sync:
   22861 		/*
   22862 		 * See if any pre-existing keys have newly become active;
   22863 		 * also, see if any new key is for a new algorithm, as in that
   22864 		 * event, we need to sign the zone fully.  (If there's a new
   22865 		 * key, but it's for an already-existing algorithm, then
   22866 		 * the zone signing can be handled incrementally.)
   22867 		 */
   22868 		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
   22869 		     key = ISC_LIST_NEXT(key, link))
   22870 		{
   22871 			if (!key->first_sign) {
   22872 				continue;
   22873 			}
   22874 
   22875 			newactive = true;
   22876 
   22877 			if (!dns_rdataset_isassociated(&keysigs)) {
   22878 				newalg = true;
   22879 				break;
   22880 			}
   22881 
   22882 			if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
   22883 				/*
   22884 				 * This isn't a new algorithm; clear
   22885 				 * first_sign so we won't sign the
   22886 				 * whole zone with this key later.
   22887 				 */
   22888 				key->first_sign = false;
   22889 			} else {
   22890 				newalg = true;
   22891 				break;
   22892 			}
   22893 		}
   22894 
   22895 		/*
   22896 		 * A sane diff is one that is not empty, and that does not
   22897 		 * introduce a zone with NSEC only DNSKEYs along with NSEC3
   22898 		 * chains.
   22899 		 */
   22900 		sane_dnskey = dns_zone_check_dnskey_nsec3(zone, db, ver, &diff,
   22901 							  NULL, 0);
   22902 		sane_diff = !ISC_LIST_EMPTY(diff.tuples) && sane_dnskey;
   22903 		if (!sane_dnskey) {
   22904 			dnssec_log(zone, ISC_LOG_ERROR,
   22905 				   "NSEC only DNSKEYs and NSEC3 chains not "
   22906 				   "allowed");
   22907 		}
   22908 
   22909 		if (newactive || fullsign || sane_diff || kasp_change) {
   22910 			CHECK(dns_diff_apply(&diff, db, ver));
   22911 			CHECK(clean_nsec3param(zone, db, ver, &diff));
   22912 			CHECK(add_signing_records(db, zone->privatetype, ver,
   22913 						  &diff, newalg || fullsign));
   22914 			CHECK(update_soa_serial(zone, db, ver, &diff, mctx,
   22915 						zone->updatemethod));
   22916 			CHECK(add_chains(zone, db, ver, &diff));
   22917 			CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
   22918 			CHECK(zone_journal(zone, zonediff.diff, NULL,
   22919 					   "zone_rekey"));
   22920 			commit = true;
   22921 		}
   22922 	}
   22923 
   22924 	dns_db_closeversion(db, &ver, true);
   22925 
   22926 	LOCK_ZONE(zone);
   22927 
   22928 	if (commit) {
   22929 		dns_difftuple_t *tuple;
   22930 		dns_stats_t *dnssecsignstats =
   22931 			dns_zone_getdnssecsignstats(zone);
   22932 
   22933 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   22934 
   22935 		zone_needdump(zone, DNS_DUMP_DELAY);
   22936 
   22937 		zone_settimer(zone, &timenow);
   22938 
   22939 		/* Remove any signatures from removed keys.  */
   22940 		if (!ISC_LIST_EMPTY(rmkeys)) {
   22941 			for (key = ISC_LIST_HEAD(rmkeys); key != NULL;
   22942 			     key = ISC_LIST_NEXT(key, link))
   22943 			{
   22944 				result = zone_signwithkey(
   22945 					zone, dst_key_alg(key->key),
   22946 					dst_key_id(key->key), true, false);
   22947 				if (result != ISC_R_SUCCESS) {
   22948 					dnssec_log(zone, ISC_LOG_ERROR,
   22949 						   "zone_signwithkey failed: "
   22950 						   "%s",
   22951 						   isc_result_totext(result));
   22952 				}
   22953 
   22954 				/* Clear DNSSEC sign statistics. */
   22955 				if (dnssecsignstats != NULL) {
   22956 					dns_dnssecsignstats_clear(
   22957 						dnssecsignstats,
   22958 						dst_key_id(key->key),
   22959 						dst_key_alg(key->key));
   22960 					/*
   22961 					 * Also clear the dnssec-sign
   22962 					 * statistics of the revoked key id.
   22963 					 */
   22964 					dns_dnssecsignstats_clear(
   22965 						dnssecsignstats,
   22966 						dst_key_rid(key->key),
   22967 						dst_key_alg(key->key));
   22968 				}
   22969 			}
   22970 		}
   22971 
   22972 		if (fullsign) {
   22973 			/*
   22974 			 * "rndc sign" was called, so we now sign the zone
   22975 			 * with all active keys, whether they're new or not.
   22976 			 */
   22977 			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
   22978 			     key = ISC_LIST_NEXT(key, link))
   22979 			{
   22980 				if (!key->force_sign && !key->hint_sign) {
   22981 					continue;
   22982 				}
   22983 
   22984 				result = zone_signwithkey(
   22985 					zone, dst_key_alg(key->key),
   22986 					dst_key_id(key->key), false, true);
   22987 				if (result != ISC_R_SUCCESS) {
   22988 					dnssec_log(zone, ISC_LOG_ERROR,
   22989 						   "zone_signwithkey failed: "
   22990 						   "%s",
   22991 						   isc_result_totext(result));
   22992 				}
   22993 			}
   22994 			/*
   22995 			 * ...and remove signatures for all inactive keys.
   22996 			 */
   22997 			ISC_LIST_FOREACH(dnskeys, key, link) {
   22998 				if (!key->force_sign && !key->hint_sign) {
   22999 					result = zone_signwithkey(
   23000 						zone, dst_key_alg(key->key),
   23001 						dst_key_id(key->key), true,
   23002 						false);
   23003 					if (result != ISC_R_SUCCESS) {
   23004 						dnssec_log(zone, ISC_LOG_ERROR,
   23005 							   "zone_signwithkey "
   23006 							   "failed: "
   23007 							   "%s",
   23008 							   isc_result_totext(
   23009 								   result));
   23010 					}
   23011 				}
   23012 			}
   23013 
   23014 		} else if (newalg) {
   23015 			/*
   23016 			 * We haven't been told to sign fully, but a new
   23017 			 * algorithm was added to the DNSKEY.  We sign
   23018 			 * the full zone, but only with newly active
   23019 			 * keys.
   23020 			 */
   23021 			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
   23022 			     key = ISC_LIST_NEXT(key, link))
   23023 			{
   23024 				if (!key->first_sign) {
   23025 					continue;
   23026 				}
   23027 
   23028 				result = zone_signwithkey(
   23029 					zone, dst_key_alg(key->key),
   23030 					dst_key_id(key->key), false, false);
   23031 				if (result != ISC_R_SUCCESS) {
   23032 					dnssec_log(zone, ISC_LOG_ERROR,
   23033 						   "zone_signwithkey failed: "
   23034 						   "%s",
   23035 						   isc_result_totext(result));
   23036 				}
   23037 			}
   23038 		}
   23039 
   23040 		/*
   23041 		 * Clear fullsign flag, if it was set, so we don't do
   23042 		 * another full signing next time.
   23043 		 */
   23044 		DNS_ZONEKEY_CLROPTION(zone, DNS_ZONEKEY_FULLSIGN);
   23045 
   23046 		/*
   23047 		 * Cause the zone to add/delete NSEC3 chains for the
   23048 		 * deferred NSEC3PARAM changes.
   23049 		 */
   23050 		for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
   23051 		     tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
   23052 		{
   23053 			unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   23054 			dns_rdata_t rdata = DNS_RDATA_INIT;
   23055 			dns_rdata_nsec3param_t nsec3param;
   23056 
   23057 			if (tuple->rdata.type != zone->privatetype ||
   23058 			    tuple->op != DNS_DIFFOP_ADD)
   23059 			{
   23060 				continue;
   23061 			}
   23062 
   23063 			if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
   23064 							buf, sizeof(buf)))
   23065 			{
   23066 				continue;
   23067 			}
   23068 
   23069 			result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   23070 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   23071 			if (nsec3param.flags == 0) {
   23072 				continue;
   23073 			}
   23074 
   23075 			result = zone_addnsec3chain(zone, &nsec3param);
   23076 			if (result != ISC_R_SUCCESS) {
   23077 				dnssec_log(zone, ISC_LOG_ERROR,
   23078 					   "zone_addnsec3chain failed: %s",
   23079 					   isc_result_totext(result));
   23080 			}
   23081 		}
   23082 
   23083 		/*
   23084 		 * Activate any NSEC3 chain updates that may have
   23085 		 * been scheduled before this rekey.
   23086 		 */
   23087 		if (fullsign || newalg) {
   23088 			resume_addnsec3chain(zone);
   23089 		}
   23090 
   23091 		/*
   23092 		 * Schedule the next resigning event
   23093 		 */
   23094 		set_resigntime(zone);
   23095 	}
   23096 
   23097 	isc_time_settoepoch(&zone->refreshkeytime);
   23098 
   23099 	/*
   23100 	 * If keymgr provided a next time, use the calculated next rekey time.
   23101 	 */
   23102 	if (kasp != NULL) {
   23103 		isc_time_t timenext;
   23104 		uint32_t nexttime_seconds;
   23105 
   23106 		/*
   23107 		 * Set the key refresh timer to the next scheduled key event
   23108 		 * or to 'dnssec-loadkeys-interval' seconds in the future
   23109 		 * if no next key event is scheduled (nexttime == 0).
   23110 		 */
   23111 		if (nexttime > 0) {
   23112 			nexttime_seconds = nexttime - now;
   23113 		} else {
   23114 			nexttime_seconds = zone->refreshkeyinterval;
   23115 		}
   23116 
   23117 		DNS_ZONE_TIME_ADD(&timenow, nexttime_seconds, &timenext);
   23118 		zone->refreshkeytime = timenext;
   23119 		zone_settimer(zone, &timenow);
   23120 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   23121 
   23122 		dnssec_log(zone, ISC_LOG_DEBUG(3),
   23123 			   "next key event in %u seconds", nexttime_seconds);
   23124 		dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
   23125 	}
   23126 	/*
   23127 	 * If we're doing key maintenance, set the key refresh timer to
   23128 	 * the next scheduled key event or to 'dnssec-loadkeys-interval'
   23129 	 * seconds in the future, whichever is sooner.
   23130 	 */
   23131 	else if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
   23132 	{
   23133 		isc_time_t timethen;
   23134 		isc_stdtime_t then;
   23135 
   23136 		DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
   23137 				  &timethen);
   23138 		zone->refreshkeytime = timethen;
   23139 
   23140 		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
   23141 		     key = ISC_LIST_NEXT(key, link))
   23142 		{
   23143 			then = now;
   23144 			result = next_keyevent(key->key, &then);
   23145 			if (result != ISC_R_SUCCESS) {
   23146 				continue;
   23147 			}
   23148 
   23149 			DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
   23150 			if (isc_time_compare(&timethen, &zone->refreshkeytime) <
   23151 			    0)
   23152 			{
   23153 				zone->refreshkeytime = timethen;
   23154 			}
   23155 		}
   23156 
   23157 		zone_settimer(zone, &timenow);
   23158 
   23159 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   23160 		dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
   23161 	}
   23162 	UNLOCK_ZONE(zone);
   23163 
   23164 	/*
   23165 	 * Remember which keys have been used.
   23166 	 */
   23167 	if (!ISC_LIST_EMPTY(zone->keyring)) {
   23168 		clear_keylist(&zone->keyring, zone->mctx);
   23169 	}
   23170 	while ((key = ISC_LIST_HEAD(dnskeys)) != NULL) {
   23171 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   23172 			/* This debug log is used in the kasp system test */
   23173 			char algbuf[DNS_SECALG_FORMATSIZE];
   23174 			dns_secalg_format(dst_key_alg(key->key), algbuf,
   23175 					  sizeof(algbuf));
   23176 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   23177 				   "zone_rekey done: key %d/%s",
   23178 				   dst_key_id(key->key), algbuf);
   23179 		}
   23180 		ISC_LIST_UNLINK(dnskeys, key, link);
   23181 		ISC_LIST_APPEND(zone->keyring, key, link);
   23182 	}
   23183 
   23184 	result = ISC_R_SUCCESS;
   23185 
   23186 cleanup:
   23187 	LOCK_ZONE(zone);
   23188 	if (result != ISC_R_SUCCESS) {
   23189 		/*
   23190 		 * Something went wrong; try again in ten minutes or
   23191 		 * after a key refresh interval, whichever is shorter.
   23192 		 */
   23193 		int loglevel = ISC_LOG_DEBUG(3);
   23194 		if (result != DNS_R_NOTLOADED) {
   23195 			loglevel = ISC_LOG_ERROR;
   23196 		}
   23197 		dnssec_log(zone, loglevel,
   23198 			   "zone_rekey failure: %s (retry in %u seconds)",
   23199 			   isc_result_totext(result),
   23200 			   ISC_MIN(zone->refreshkeyinterval, 600));
   23201 		isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600),
   23202 				 0);
   23203 		isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
   23204 	}
   23205 
   23206 	/*
   23207 	 * Clear forcekeymgr flag, if it was set, so we don't do
   23208 	 * another force next time.
   23209 	 */
   23210 	DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_FORCEKEYMGR);
   23211 
   23212 	UNLOCK_ZONE(zone);
   23213 
   23214 	dns_diff_clear(&diff);
   23215 	dns_diff_clear(&_sig_diff);
   23216 
   23217 	clear_keylist(&dnskeys, mctx);
   23218 	clear_keylist(&keys, mctx);
   23219 	clear_keylist(&rmkeys, mctx);
   23220 
   23221 	if (ver != NULL) {
   23222 		dns_db_closeversion(db, &ver, false);
   23223 	}
   23224 	if (dns_rdataset_isassociated(&cdsset)) {
   23225 		dns_rdataset_disassociate(&cdsset);
   23226 	}
   23227 	if (dns_rdataset_isassociated(&keyset)) {
   23228 		dns_rdataset_disassociate(&keyset);
   23229 	}
   23230 	if (dns_rdataset_isassociated(&keysigs)) {
   23231 		dns_rdataset_disassociate(&keysigs);
   23232 	}
   23233 	if (dns_rdataset_isassociated(&soasigs)) {
   23234 		dns_rdataset_disassociate(&soasigs);
   23235 	}
   23236 	if (dns_rdataset_isassociated(&cdnskeyset)) {
   23237 		dns_rdataset_disassociate(&cdnskeyset);
   23238 	}
   23239 	if (node != NULL) {
   23240 		dns_db_detachnode(db, &node);
   23241 	}
   23242 	if (db != NULL) {
   23243 		dns_db_detach(&db);
   23244 	}
   23245 
   23246 	INSIST(ver == NULL);
   23247 }
   23248 
   23249 void
   23250 dns_zone_rekey(dns_zone_t *zone, bool fullsign, bool forcekeymgr) {
   23251 	isc_time_t now;
   23252 
   23253 	if (zone->type == dns_zone_primary && zone->loop != NULL) {
   23254 		LOCK_ZONE(zone);
   23255 
   23256 		if (fullsign) {
   23257 			DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
   23258 		}
   23259 		if (forcekeymgr) {
   23260 			DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_FORCEKEYMGR);
   23261 		}
   23262 
   23263 		now = isc_time_now();
   23264 		zone->refreshkeytime = now;
   23265 		zone_settimer(zone, &now);
   23266 
   23267 		UNLOCK_ZONE(zone);
   23268 	}
   23269 }
   23270 
   23271 isc_result_t
   23272 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
   23273 		 unsigned int *errors) {
   23274 	isc_result_t result;
   23275 	dns_dbnode_t *node = NULL;
   23276 
   23277 	REQUIRE(DNS_ZONE_VALID(zone));
   23278 	REQUIRE(errors != NULL);
   23279 
   23280 	result = dns_db_getoriginnode(db, &node);
   23281 	if (result != ISC_R_SUCCESS) {
   23282 		return result;
   23283 	}
   23284 	result = zone_count_ns_rr(zone, db, node, version, NULL, errors, false);
   23285 	dns_db_detachnode(db, &node);
   23286 	return result;
   23287 }
   23288 
   23289 isc_result_t
   23290 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
   23291 	isc_result_t result;
   23292 	dns_dbnode_t *node = NULL;
   23293 	dns_rdataset_t dnskey, cds, cdnskey;
   23294 	unsigned char algorithms[256];
   23295 	unsigned int i;
   23296 	bool empty = false;
   23297 
   23298 	enum { notexpected = 0, expected = 1, found = 2 };
   23299 
   23300 	REQUIRE(DNS_ZONE_VALID(zone));
   23301 
   23302 	result = dns_db_getoriginnode(db, &node);
   23303 	if (result != ISC_R_SUCCESS) {
   23304 		return result;
   23305 	}
   23306 
   23307 	dns_rdataset_init(&cds);
   23308 	dns_rdataset_init(&dnskey);
   23309 	dns_rdataset_init(&cdnskey);
   23310 
   23311 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
   23312 				     dns_rdatatype_none, 0, &cds, NULL);
   23313 	if (result != ISC_R_NOTFOUND) {
   23314 		CHECK(result);
   23315 	}
   23316 
   23317 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
   23318 				     dns_rdatatype_none, 0, &cdnskey, NULL);
   23319 	if (result != ISC_R_NOTFOUND) {
   23320 		CHECK(result);
   23321 	}
   23322 
   23323 	if (!dns_rdataset_isassociated(&cds) &&
   23324 	    !dns_rdataset_isassociated(&cdnskey))
   23325 	{
   23326 		result = ISC_R_SUCCESS;
   23327 		goto cleanup;
   23328 	}
   23329 
   23330 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
   23331 				     dns_rdatatype_none, 0, &dnskey, NULL);
   23332 	if (result == ISC_R_NOTFOUND) {
   23333 		empty = true;
   23334 	} else {
   23335 		CHECK(result);
   23336 	}
   23337 
   23338 	/*
   23339 	 * For each DNSSEC algorithm in the CDS RRset there must be
   23340 	 * a matching DNSKEY record with the exception of a CDS deletion
   23341 	 * record which must be by itself.
   23342 	 */
   23343 	if (dns_rdataset_isassociated(&cds)) {
   23344 		bool logged_digest_type[DNS_DSDIGEST_MAX + 1] = { 0 };
   23345 		bool delete = false;
   23346 		memset(algorithms, notexpected, sizeof(algorithms));
   23347 		for (result = dns_rdataset_first(&cds); result == ISC_R_SUCCESS;
   23348 		     result = dns_rdataset_next(&cds))
   23349 		{
   23350 			dns_rdata_t crdata = DNS_RDATA_INIT;
   23351 			dns_rdata_cds_t structcds;
   23352 
   23353 			dns_rdataset_current(&cds, &crdata);
   23354 			/*
   23355 			 * CDS deletion record has this form "0 0 0 00" which
   23356 			 * is 5 zero octets.
   23357 			 */
   23358 			if (crdata.length == 5U &&
   23359 			    memcmp(crdata.data,
   23360 				   (unsigned char[5]){ 0, 0, 0, 0, 0 }, 5) == 0)
   23361 			{
   23362 				delete = true;
   23363 				continue;
   23364 			}
   23365 
   23366 			if (empty) {
   23367 				CHECK(DNS_R_BADCDS);
   23368 			}
   23369 
   23370 			CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
   23371 
   23372 			/*
   23373 			 * Log deprecated CDS digest types.
   23374 			 */
   23375 			switch (structcds.digest_type) {
   23376 			case DNS_DSDIGEST_SHA1:
   23377 			case DNS_DSDIGEST_GOST:
   23378 				if (!logged_digest_type[structcds.digest_type])
   23379 				{
   23380 					char algbuf[DNS_DSDIGEST_FORMATSIZE];
   23381 					dns_dsdigest_format(
   23382 						structcds.digest_type, algbuf,
   23383 						sizeof(algbuf));
   23384 					dnssec_log(zone, ISC_LOG_WARNING,
   23385 						   "deprecated CDS digest type "
   23386 						   "%u (%s)",
   23387 						   structcds.digest_type,
   23388 						   algbuf);
   23389 					logged_digest_type[structcds.digest_type] =
   23390 						true;
   23391 				}
   23392 				break;
   23393 			}
   23394 
   23395 			if (algorithms[structcds.algorithm] == 0) {
   23396 				algorithms[structcds.algorithm] = expected;
   23397 			}
   23398 			for (result = dns_rdataset_first(&dnskey);
   23399 			     result == ISC_R_SUCCESS;
   23400 			     result = dns_rdataset_next(&dnskey))
   23401 			{
   23402 				dns_rdata_t rdata = DNS_RDATA_INIT;
   23403 				dns_rdata_dnskey_t structdnskey;
   23404 
   23405 				dns_rdataset_current(&dnskey, &rdata);
   23406 				CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
   23407 							 NULL));
   23408 
   23409 				if (structdnskey.algorithm ==
   23410 				    structcds.algorithm)
   23411 				{
   23412 					algorithms[structcds.algorithm] = found;
   23413 				}
   23414 			}
   23415 			if (result != ISC_R_NOMORE) {
   23416 				goto cleanup;
   23417 			}
   23418 		}
   23419 		for (i = 0; i < sizeof(algorithms); i++) {
   23420 			if (delete) {
   23421 				if (algorithms[i] != notexpected) {
   23422 					CHECK(DNS_R_BADCDS);
   23423 				}
   23424 			} else if (algorithms[i] == expected) {
   23425 				CHECK(DNS_R_BADCDS);
   23426 			}
   23427 		}
   23428 	}
   23429 
   23430 	/*
   23431 	 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
   23432 	 * a matching DNSKEY record with the exception of a CDNSKEY deletion
   23433 	 * record which must be by itself.
   23434 	 */
   23435 	if (dns_rdataset_isassociated(&cdnskey)) {
   23436 		bool delete = false;
   23437 		memset(algorithms, notexpected, sizeof(algorithms));
   23438 		for (result = dns_rdataset_first(&cdnskey);
   23439 		     result == ISC_R_SUCCESS;
   23440 		     result = dns_rdataset_next(&cdnskey))
   23441 		{
   23442 			dns_rdata_t crdata = DNS_RDATA_INIT;
   23443 			dns_rdata_cdnskey_t structcdnskey;
   23444 
   23445 			dns_rdataset_current(&cdnskey, &crdata);
   23446 			/*
   23447 			 * CDNSKEY deletion record has this form
   23448 			 * "0 3 0 AA==" which is 2 zero octets, a 3,
   23449 			 * and 2 zero octets.
   23450 			 */
   23451 			if (crdata.length == 5U &&
   23452 			    memcmp(crdata.data,
   23453 				   (unsigned char[5]){ 0, 0, 3, 0, 0 }, 5) == 0)
   23454 			{
   23455 				delete = true;
   23456 				continue;
   23457 			}
   23458 
   23459 			if (empty) {
   23460 				CHECK(DNS_R_BADCDNSKEY);
   23461 			}
   23462 
   23463 			CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
   23464 						 NULL));
   23465 			if (algorithms[structcdnskey.algorithm] == 0) {
   23466 				algorithms[structcdnskey.algorithm] = expected;
   23467 			}
   23468 			for (result = dns_rdataset_first(&dnskey);
   23469 			     result == ISC_R_SUCCESS;
   23470 			     result = dns_rdataset_next(&dnskey))
   23471 			{
   23472 				dns_rdata_t rdata = DNS_RDATA_INIT;
   23473 				dns_rdata_dnskey_t structdnskey;
   23474 
   23475 				dns_rdataset_current(&dnskey, &rdata);
   23476 				CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
   23477 							 NULL));
   23478 
   23479 				if (structdnskey.algorithm ==
   23480 				    structcdnskey.algorithm)
   23481 				{
   23482 					algorithms[structcdnskey.algorithm] =
   23483 						found;
   23484 				}
   23485 			}
   23486 			if (result != ISC_R_NOMORE) {
   23487 				goto cleanup;
   23488 			}
   23489 		}
   23490 		for (i = 0; i < sizeof(algorithms); i++) {
   23491 			if (delete) {
   23492 				if (algorithms[i] != notexpected) {
   23493 					CHECK(DNS_R_BADCDNSKEY);
   23494 				}
   23495 			} else if (algorithms[i] == expected) {
   23496 				CHECK(DNS_R_BADCDNSKEY);
   23497 			}
   23498 		}
   23499 	}
   23500 	result = ISC_R_SUCCESS;
   23501 
   23502 cleanup:
   23503 	if (dns_rdataset_isassociated(&cds)) {
   23504 		dns_rdataset_disassociate(&cds);
   23505 	}
   23506 	if (dns_rdataset_isassociated(&dnskey)) {
   23507 		dns_rdataset_disassociate(&dnskey);
   23508 	}
   23509 	if (dns_rdataset_isassociated(&cdnskey)) {
   23510 		dns_rdataset_disassociate(&cdnskey);
   23511 	}
   23512 	dns_db_detachnode(db, &node);
   23513 	return result;
   23514 }
   23515 
   23516 void
   23517 dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
   23518 	REQUIRE(DNS_ZONE_VALID(zone));
   23519 
   23520 	LOCK_ZONE(zone);
   23521 	zone->automatic = automatic;
   23522 	UNLOCK_ZONE(zone);
   23523 }
   23524 
   23525 bool
   23526 dns_zone_getautomatic(dns_zone_t *zone) {
   23527 	REQUIRE(DNS_ZONE_VALID(zone));
   23528 	return zone->automatic;
   23529 }
   23530 
   23531 void
   23532 dns_zone_setadded(dns_zone_t *zone, bool added) {
   23533 	REQUIRE(DNS_ZONE_VALID(zone));
   23534 
   23535 	LOCK_ZONE(zone);
   23536 	zone->added = added;
   23537 	UNLOCK_ZONE(zone);
   23538 }
   23539 
   23540 bool
   23541 dns_zone_getadded(dns_zone_t *zone) {
   23542 	REQUIRE(DNS_ZONE_VALID(zone));
   23543 	return zone->added;
   23544 }
   23545 
   23546 isc_result_t
   23547 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) {
   23548 	isc_time_t loadtime;
   23549 	isc_result_t result;
   23550 	dns_zone_t *secure = NULL;
   23551 
   23552 	loadtime = isc_time_now();
   23553 
   23554 	/*
   23555 	 * Lock hierarchy: zmgr, zone, raw.
   23556 	 */
   23557 again:
   23558 	LOCK_ZONE(zone);
   23559 	INSIST(zone != zone->raw);
   23560 	if (inline_secure(zone)) {
   23561 		LOCK_ZONE(zone->raw);
   23562 	} else if (inline_raw(zone)) {
   23563 		secure = zone->secure;
   23564 		TRYLOCK_ZONE(result, secure);
   23565 		if (result != ISC_R_SUCCESS) {
   23566 			UNLOCK_ZONE(zone);
   23567 			secure = NULL;
   23568 			isc_thread_yield();
   23569 			goto again;
   23570 		}
   23571 	}
   23572 	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
   23573 	if (inline_secure(zone)) {
   23574 		UNLOCK_ZONE(zone->raw);
   23575 	} else if (secure != NULL) {
   23576 		UNLOCK_ZONE(secure);
   23577 	}
   23578 	UNLOCK_ZONE(zone);
   23579 	return result;
   23580 }
   23581 
   23582 isc_result_t
   23583 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
   23584 	REQUIRE(DNS_ZONE_VALID(zone));
   23585 	if (interval == 0) {
   23586 		return ISC_R_RANGE;
   23587 	}
   23588 	/* Maximum value: 24 hours (3600 minutes) */
   23589 	if (interval > (24 * 60)) {
   23590 		interval = (24 * 60);
   23591 	}
   23592 	/* Multiply by 60 for seconds */
   23593 	zone->refreshkeyinterval = interval * 60;
   23594 	return ISC_R_SUCCESS;
   23595 }
   23596 
   23597 void
   23598 dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
   23599 	REQUIRE(DNS_ZONE_VALID(zone));
   23600 	zone->requestixfr = flag;
   23601 }
   23602 
   23603 bool
   23604 dns_zone_getrequestixfr(dns_zone_t *zone) {
   23605 	REQUIRE(DNS_ZONE_VALID(zone));
   23606 	return zone->requestixfr;
   23607 }
   23608 
   23609 void
   23610 dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio) {
   23611 	REQUIRE(DNS_ZONE_VALID(zone));
   23612 	zone->ixfr_ratio = ratio;
   23613 }
   23614 
   23615 uint32_t
   23616 dns_zone_getixfrratio(dns_zone_t *zone) {
   23617 	REQUIRE(DNS_ZONE_VALID(zone));
   23618 	return zone->ixfr_ratio;
   23619 }
   23620 
   23621 void
   23622 dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
   23623 	REQUIRE(DNS_ZONE_VALID(zone));
   23624 	zone->requestexpire = flag;
   23625 }
   23626 
   23627 bool
   23628 dns_zone_getrequestexpire(dns_zone_t *zone) {
   23629 	REQUIRE(DNS_ZONE_VALID(zone));
   23630 	return zone->requestexpire;
   23631 }
   23632 
   23633 void
   23634 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
   23635 	REQUIRE(DNS_ZONE_VALID(zone));
   23636 	zone->updatemethod = method;
   23637 }
   23638 
   23639 dns_updatemethod_t
   23640 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
   23641 	REQUIRE(DNS_ZONE_VALID(zone));
   23642 	return zone->updatemethod;
   23643 }
   23644 
   23645 /*
   23646  * Lock hierarchy: zmgr, zone, raw.
   23647  */
   23648 isc_result_t
   23649 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
   23650 	dns_zonemgr_t *zmgr;
   23651 
   23652 	REQUIRE(DNS_ZONE_VALID(zone));
   23653 	REQUIRE(zone->zmgr != NULL);
   23654 	REQUIRE(zone->loop != NULL);
   23655 	REQUIRE(zone->raw == NULL);
   23656 
   23657 	REQUIRE(DNS_ZONE_VALID(raw));
   23658 	REQUIRE(raw->zmgr == NULL);
   23659 	REQUIRE(raw->loop == NULL);
   23660 	REQUIRE(raw->secure == NULL);
   23661 
   23662 	REQUIRE(zone != raw);
   23663 
   23664 	/*
   23665 	 * Lock hierarchy: zmgr, zone, raw.
   23666 	 */
   23667 	zmgr = zone->zmgr;
   23668 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   23669 	LOCK_ZONE(zone);
   23670 	LOCK_ZONE(raw);
   23671 
   23672 	isc_loop_attach(zone->loop, &raw->loop);
   23673 
   23674 	/* dns_zone_attach(raw, &zone->raw); */
   23675 	isc_refcount_increment(&raw->references);
   23676 	zone->raw = raw;
   23677 
   23678 	/* dns_zone_iattach(zone, &raw->secure); */
   23679 	zone_iattach(zone, &raw->secure);
   23680 
   23681 	ISC_LIST_APPEND(zmgr->zones, raw, link);
   23682 	raw->zmgr = zmgr;
   23683 	isc_refcount_increment(&zmgr->refs);
   23684 
   23685 	UNLOCK_ZONE(raw);
   23686 	UNLOCK_ZONE(zone);
   23687 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   23688 	return ISC_R_SUCCESS;
   23689 }
   23690 
   23691 void
   23692 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
   23693 	REQUIRE(DNS_ZONE_VALID(zone));
   23694 	REQUIRE(raw != NULL && *raw == NULL);
   23695 
   23696 	LOCK(&zone->lock);
   23697 	INSIST(zone != zone->raw);
   23698 	if (zone->raw != NULL) {
   23699 		dns_zone_attach(zone->raw, raw);
   23700 	}
   23701 	UNLOCK(&zone->lock);
   23702 }
   23703 
   23704 bool
   23705 dns_zone_israw(dns_zone_t *zone) {
   23706 	bool israw;
   23707 	REQUIRE(DNS_ZONE_VALID(zone));
   23708 	LOCK(&zone->lock);
   23709 	israw = zone->secure != NULL;
   23710 	UNLOCK(&zone->lock);
   23711 	return israw;
   23712 }
   23713 
   23714 bool
   23715 dns_zone_issecure(dns_zone_t *zone) {
   23716 	bool issecure;
   23717 	REQUIRE(DNS_ZONE_VALID(zone));
   23718 	LOCK(&zone->lock);
   23719 	issecure = zone->raw != NULL;
   23720 	UNLOCK(&zone->lock);
   23721 	return issecure;
   23722 }
   23723 
   23724 struct keydone {
   23725 	bool all;
   23726 	unsigned char data[5];
   23727 	dns_zone_t *zone;
   23728 };
   23729 
   23730 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL)
   23731 
   23732 static void
   23733 keydone(void *arg) {
   23734 	bool commit = false;
   23735 	isc_result_t result;
   23736 	dns_rdata_t rdata = DNS_RDATA_INIT;
   23737 	dns_dbversion_t *oldver = NULL, *newver = NULL;
   23738 	dns_db_t *db = NULL;
   23739 	dns_dbnode_t *node = NULL;
   23740 	dns_rdataset_t rdataset;
   23741 	dns_diff_t diff;
   23742 	struct keydone *kd = (struct keydone *)arg;
   23743 	dns_zone_t *zone = kd->zone;
   23744 	dns_update_log_t log = { update_log_cb, NULL };
   23745 	bool clear_pending = false;
   23746 
   23747 	INSIST(DNS_ZONE_VALID(zone));
   23748 
   23749 	ENTER;
   23750 
   23751 	dns_rdataset_init(&rdataset);
   23752 	dns_diff_init(zone->mctx, &diff);
   23753 
   23754 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   23755 	if (zone->db != NULL) {
   23756 		dns_db_attach(zone->db, &db);
   23757 	}
   23758 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   23759 	if (db == NULL) {
   23760 		goto cleanup;
   23761 	}
   23762 
   23763 	dns_db_currentversion(db, &oldver);
   23764 	result = dns_db_newversion(db, &newver);
   23765 	if (result != ISC_R_SUCCESS) {
   23766 		dnssec_log(zone, ISC_LOG_ERROR,
   23767 			   "keydone:dns_db_newversion -> %s",
   23768 			   isc_result_totext(result));
   23769 		goto cleanup;
   23770 	}
   23771 
   23772 	CHECK(dns_db_getoriginnode(db, &node));
   23773 
   23774 	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
   23775 				     dns_rdatatype_none, 0, &rdataset, NULL);
   23776 	if (result != ISC_R_SUCCESS) {
   23777 		INSIST(!dns_rdataset_isassociated(&rdataset));
   23778 		goto cleanup;
   23779 	}
   23780 
   23781 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   23782 	     result = dns_rdataset_next(&rdataset))
   23783 	{
   23784 		bool found = false;
   23785 
   23786 		dns_rdataset_current(&rdataset, &rdata);
   23787 
   23788 		if (kd->all) {
   23789 			if (rdata.length == 5 && rdata.data[0] != 0 &&
   23790 			    rdata.data[3] == 0 && rdata.data[4] == 1)
   23791 			{
   23792 				found = true;
   23793 			} else if (rdata.data[0] == 0 &&
   23794 				   (rdata.data[2] & PENDINGFLAGS) != 0)
   23795 			{
   23796 				found = true;
   23797 				clear_pending = true;
   23798 			}
   23799 		} else if (rdata.length == 5 &&
   23800 			   memcmp(rdata.data, kd->data, 5) == 0)
   23801 		{
   23802 			found = true;
   23803 		}
   23804 
   23805 		if (found) {
   23806 			CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
   23807 					    &zone->origin, rdataset.ttl,
   23808 					    &rdata));
   23809 		}
   23810 		dns_rdata_reset(&rdata);
   23811 	}
   23812 
   23813 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   23814 		/* Write changes to journal file. */
   23815 		CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
   23816 					zone->updatemethod));
   23817 
   23818 		result = dns_update_signatures(&log, zone, db, oldver, newver,
   23819 					       &diff,
   23820 					       zone->sigvalidityinterval);
   23821 		if (!clear_pending) {
   23822 			CHECK(result);
   23823 		}
   23824 
   23825 		CHECK(zone_journal(zone, &diff, NULL, "keydone"));
   23826 		commit = true;
   23827 
   23828 		LOCK_ZONE(zone);
   23829 		DNS_ZONE_SETFLAG(zone,
   23830 				 DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
   23831 		zone_needdump(zone, 30);
   23832 		UNLOCK_ZONE(zone);
   23833 	}
   23834 
   23835 cleanup:
   23836 	if (dns_rdataset_isassociated(&rdataset)) {
   23837 		dns_rdataset_disassociate(&rdataset);
   23838 	}
   23839 	if (db != NULL) {
   23840 		if (node != NULL) {
   23841 			dns_db_detachnode(db, &node);
   23842 		}
   23843 		if (oldver != NULL) {
   23844 			dns_db_closeversion(db, &oldver, false);
   23845 		}
   23846 		if (newver != NULL) {
   23847 			dns_db_closeversion(db, &newver, commit);
   23848 		}
   23849 		dns_db_detach(&db);
   23850 	}
   23851 	dns_diff_clear(&diff);
   23852 	isc_mem_put(zone->mctx, kd, sizeof(*kd));
   23853 	dns_zone_idetach(&zone);
   23854 
   23855 	INSIST(oldver == NULL);
   23856 	INSIST(newver == NULL);
   23857 }
   23858 
   23859 isc_result_t
   23860 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
   23861 	isc_result_t result = ISC_R_SUCCESS;
   23862 	struct keydone *kd = NULL;
   23863 	isc_buffer_t b;
   23864 
   23865 	REQUIRE(DNS_ZONE_VALID(zone));
   23866 
   23867 	LOCK_ZONE(zone);
   23868 
   23869 	kd = isc_mem_get(zone->mctx, sizeof(*kd));
   23870 	*kd = (struct keydone){ .all = false };
   23871 
   23872 	if (strcasecmp(keystr, "all") == 0) {
   23873 		kd->all = true;
   23874 	} else {
   23875 		isc_textregion_t r;
   23876 		const char *algstr = NULL;
   23877 		dns_keytag_t keyid;
   23878 		dns_secalg_t alg;
   23879 		size_t n;
   23880 
   23881 		n = sscanf(keystr, "%hu/", &keyid);
   23882 		if (n == 0U) {
   23883 			CHECK(ISC_R_FAILURE);
   23884 		}
   23885 
   23886 		algstr = strchr(keystr, '/');
   23887 		if (algstr != NULL) {
   23888 			algstr++;
   23889 		} else {
   23890 			CHECK(ISC_R_FAILURE);
   23891 		}
   23892 
   23893 		n = sscanf(algstr, "%hhu", &alg);
   23894 		if (n == 0U) {
   23895 			r.base = UNCONST(algstr);
   23896 			r.length = strlen(algstr);
   23897 			CHECK(dns_secalg_fromtext(&alg, &r));
   23898 		}
   23899 
   23900 		/* construct a private-type rdata */
   23901 		isc_buffer_init(&b, kd->data, sizeof(kd->data));
   23902 		isc_buffer_putuint8(&b, alg);
   23903 		isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
   23904 		isc_buffer_putuint8(&b, keyid & 0xff);
   23905 		isc_buffer_putuint8(&b, 0);
   23906 		isc_buffer_putuint8(&b, 1);
   23907 	}
   23908 
   23909 	zone_iattach(zone, &kd->zone);
   23910 	isc_async_run(zone->loop, keydone, kd);
   23911 	kd = NULL;
   23912 
   23913 cleanup:
   23914 	if (kd != NULL) {
   23915 		isc_mem_put(zone->mctx, kd, sizeof(*kd));
   23916 	}
   23917 	UNLOCK_ZONE(zone);
   23918 	return result;
   23919 }
   23920 
   23921 /*
   23922  * Called from the zone loop's queue after the relevant event is posted by
   23923  * dns_zone_setnsec3param().
   23924  */
   23925 static void
   23926 setnsec3param(void *arg) {
   23927 	struct np3 *npe = (struct np3 *)arg;
   23928 	dns_zone_t *zone = npe->zone;
   23929 	bool loadpending;
   23930 
   23931 	INSIST(DNS_ZONE_VALID(zone));
   23932 
   23933 	ENTER;
   23934 
   23935 	LOCK_ZONE(zone);
   23936 	loadpending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
   23937 	UNLOCK_ZONE(zone);
   23938 
   23939 	/*
   23940 	 * The receive_secure_serial() and setnsec3param() calls are
   23941 	 * loop-serialized for the zone. Make sure there's no processing
   23942 	 * currently running.
   23943 	 */
   23944 	INSIST(zone->rss_newver == NULL);
   23945 
   23946 	bool rescheduled = false;
   23947 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   23948 	/*
   23949 	 * The zone is not yet fully loaded. Reschedule the event to
   23950 	 * be picked up later. This turns this function into a busy
   23951 	 * wait, but it only happens at startup.
   23952 	 */
   23953 	if (zone->db == NULL && loadpending) {
   23954 		rescheduled = true;
   23955 		isc_async_run(zone->loop, setnsec3param, npe);
   23956 	}
   23957 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   23958 	if (rescheduled) {
   23959 		return;
   23960 	}
   23961 
   23962 	rss_post(npe);
   23963 
   23964 	dns_zone_idetach(&zone);
   23965 }
   23966 
   23967 static void
   23968 salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text,
   23969 	  unsigned int textlen) {
   23970 	isc_region_t r;
   23971 	isc_buffer_t buf;
   23972 	isc_result_t result;
   23973 
   23974 	r.base = salt;
   23975 	r.length = (unsigned int)saltlen;
   23976 
   23977 	isc_buffer_init(&buf, text, textlen);
   23978 	result = isc_hex_totext(&r, 2, "", &buf);
   23979 	if (result == ISC_R_SUCCESS) {
   23980 		text[saltlen * 2] = 0;
   23981 	} else {
   23982 		text[0] = 0;
   23983 	}
   23984 }
   23985 
   23986 /*
   23987  * Check whether NSEC3 chain addition or removal specified by the private-type
   23988  * record passed with the event was already queued (or even fully performed).
   23989  * If not, modify the relevant private-type records at the zone apex and call
   23990  * resume_addnsec3chain().
   23991  */
   23992 static void
   23993 rss_post(void *arg) {
   23994 	struct np3 *npe = (struct np3 *)arg;
   23995 	dns_zone_t *zone = npe->zone;
   23996 	nsec3param_t *np = &npe->params;
   23997 	bool commit = false;
   23998 	isc_result_t result;
   23999 	dns_dbversion_t *oldver = NULL, *newver = NULL;
   24000 	dns_db_t *db = NULL;
   24001 	dns_dbnode_t *node = NULL;
   24002 	dns_rdataset_t prdataset, nrdataset;
   24003 	dns_diff_t diff;
   24004 	dns_update_log_t log = { update_log_cb, NULL };
   24005 	dns_rdata_t rdata;
   24006 	bool nseconly;
   24007 	bool exists = false;
   24008 
   24009 	ENTER;
   24010 
   24011 	dns_rdataset_init(&prdataset);
   24012 	dns_rdataset_init(&nrdataset);
   24013 	dns_diff_init(zone->mctx, &diff);
   24014 
   24015 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   24016 	if (zone->db != NULL) {
   24017 		dns_db_attach(zone->db, &db);
   24018 	}
   24019 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   24020 	if (db == NULL) {
   24021 		goto cleanup;
   24022 	}
   24023 
   24024 	dns_db_currentversion(db, &oldver);
   24025 	result = dns_db_newversion(db, &newver);
   24026 	if (result != ISC_R_SUCCESS) {
   24027 		dnssec_log(zone, ISC_LOG_ERROR,
   24028 			   "setnsec3param:dns_db_newversion -> %s",
   24029 			   isc_result_totext(result));
   24030 		goto cleanup;
   24031 	}
   24032 
   24033 	CHECK(dns_db_getoriginnode(db, &node));
   24034 
   24035 	/*
   24036 	 * Do we need to look up the NSEC3 parameters?
   24037 	 */
   24038 	if (np->lookup) {
   24039 		dns_rdata_nsec3param_t param;
   24040 		dns_rdata_t nrdata = DNS_RDATA_INIT;
   24041 		dns_rdata_t prdata = DNS_RDATA_INIT;
   24042 		unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
   24043 		unsigned char saltbuf[255];
   24044 		isc_buffer_t b;
   24045 
   24046 		param.salt = NULL;
   24047 		result = dns__zone_lookup_nsec3param(zone, &np->rdata, &param,
   24048 						     saltbuf, np->resalt);
   24049 		if (result == ISC_R_SUCCESS) {
   24050 			/*
   24051 			 * Success because the NSEC3PARAM already exists, but
   24052 			 * function returns void, so goto cleanup.
   24053 			 */
   24054 			goto cleanup;
   24055 		}
   24056 		if (result != DNS_R_NSEC3RESALT && result != ISC_R_NOTFOUND) {
   24057 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   24058 				   "setnsec3param:lookup nsec3param -> %s",
   24059 				   isc_result_totext(result));
   24060 			goto cleanup;
   24061 		}
   24062 
   24063 		INSIST(param.salt != NULL);
   24064 
   24065 		/* Update NSEC3 parameters. */
   24066 		np->rdata.hash = param.hash;
   24067 		np->rdata.flags = param.flags;
   24068 		np->rdata.iterations = param.iterations;
   24069 		np->rdata.salt_length = param.salt_length;
   24070 		np->rdata.salt = param.salt;
   24071 
   24072 		isc_buffer_init(&b, nbuf, sizeof(nbuf));
   24073 		CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
   24074 					   dns_rdatatype_nsec3param, &np->rdata,
   24075 					   &b));
   24076 		dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
   24077 					 np->data, sizeof(np->data));
   24078 		np->length = prdata.length;
   24079 		np->nsec = false;
   24080 	}
   24081 
   24082 	/*
   24083 	 * Does a private-type record already exist for this chain?
   24084 	 */
   24085 	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
   24086 				     dns_rdatatype_none, 0, &prdataset, NULL);
   24087 	if (result == ISC_R_SUCCESS) {
   24088 		for (result = dns_rdataset_first(&prdataset);
   24089 		     result == ISC_R_SUCCESS;
   24090 		     result = dns_rdataset_next(&prdataset))
   24091 		{
   24092 			dns_rdata_init(&rdata);
   24093 			dns_rdataset_current(&prdataset, &rdata);
   24094 
   24095 			if (np->length == rdata.length &&
   24096 			    memcmp(rdata.data, np->data, np->length) == 0)
   24097 			{
   24098 				exists = true;
   24099 				break;
   24100 			}
   24101 		}
   24102 	} else if (result != ISC_R_NOTFOUND) {
   24103 		INSIST(!dns_rdataset_isassociated(&prdataset));
   24104 		goto cleanup;
   24105 	}
   24106 
   24107 	/*
   24108 	 * Does the chain already exist?
   24109 	 */
   24110 	result = dns_db_findrdataset(db, node, newver, dns_rdatatype_nsec3param,
   24111 				     dns_rdatatype_none, 0, &nrdataset, NULL);
   24112 	if (result == ISC_R_SUCCESS) {
   24113 		for (result = dns_rdataset_first(&nrdataset);
   24114 		     result == ISC_R_SUCCESS;
   24115 		     result = dns_rdataset_next(&nrdataset))
   24116 		{
   24117 			dns_rdata_init(&rdata);
   24118 			dns_rdataset_current(&nrdataset, &rdata);
   24119 
   24120 			if (np->length == ((unsigned int)rdata.length + 1) &&
   24121 			    memcmp(rdata.data, np->data + 1, np->length - 1) ==
   24122 				    0)
   24123 			{
   24124 				exists = true;
   24125 				break;
   24126 			}
   24127 		}
   24128 	} else if (result != ISC_R_NOTFOUND) {
   24129 		INSIST(!dns_rdataset_isassociated(&nrdataset));
   24130 		goto cleanup;
   24131 	}
   24132 
   24133 	/*
   24134 	 * We need to remove any existing NSEC3 chains if the supplied NSEC3
   24135 	 * parameters are supposed to replace the current ones or if we are
   24136 	 * switching to NSEC.
   24137 	 */
   24138 	if (!exists && np->replace && (np->length != 0 || np->nsec)) {
   24139 		CHECK(dns_nsec3param_deletechains(db, newver, zone, !np->nsec,
   24140 						  &diff));
   24141 	}
   24142 
   24143 	if (!exists && np->length != 0) {
   24144 		/*
   24145 		 * We're creating an NSEC3 chain.  Add the private-type record
   24146 		 * passed in the event handler's argument to the zone apex.
   24147 		 *
   24148 		 * If the zone is not currently capable of supporting an NSEC3
   24149 		 * chain (due to the DNSKEY RRset at the zone apex not existing
   24150 		 * or containing at least one key using an NSEC-only
   24151 		 * algorithm), add the INITIAL flag, so these parameters can be
   24152 		 * used later when NSEC3 becomes available.
   24153 		 */
   24154 		dns_rdata_init(&rdata);
   24155 
   24156 		np->data[2] |= DNS_NSEC3FLAG_CREATE;
   24157 		result = dns_nsec_nseconly(db, newver, NULL, &nseconly);
   24158 		if (result == ISC_R_NOTFOUND || nseconly) {
   24159 			np->data[2] |= DNS_NSEC3FLAG_INITIAL;
   24160 		}
   24161 
   24162 		rdata.length = np->length;
   24163 		rdata.data = np->data;
   24164 		rdata.type = zone->privatetype;
   24165 		rdata.rdclass = zone->rdclass;
   24166 		CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
   24167 				    &zone->origin, 0, &rdata));
   24168 	}
   24169 
   24170 	/*
   24171 	 * If we changed anything in the zone, write changes to journal file
   24172 	 * and set commit to true so that resume_addnsec3chain() will be
   24173 	 * called below in order to kick off adding/removing relevant NSEC3
   24174 	 * records.
   24175 	 */
   24176 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   24177 		CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
   24178 					zone->updatemethod));
   24179 		result = dns_update_signatures(&log, zone, db, oldver, newver,
   24180 					       &diff,
   24181 					       zone->sigvalidityinterval);
   24182 		if (result != ISC_R_NOTFOUND) {
   24183 			CHECK(result);
   24184 		}
   24185 		CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
   24186 		commit = true;
   24187 
   24188 		LOCK_ZONE(zone);
   24189 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   24190 		zone_needdump(zone, 30);
   24191 		UNLOCK_ZONE(zone);
   24192 	}
   24193 
   24194 cleanup:
   24195 	if (dns_rdataset_isassociated(&prdataset)) {
   24196 		dns_rdataset_disassociate(&prdataset);
   24197 	}
   24198 	if (dns_rdataset_isassociated(&nrdataset)) {
   24199 		dns_rdataset_disassociate(&nrdataset);
   24200 	}
   24201 	if (node != NULL) {
   24202 		dns_db_detachnode(db, &node);
   24203 	}
   24204 	if (oldver != NULL) {
   24205 		dns_db_closeversion(db, &oldver, false);
   24206 	}
   24207 	if (newver != NULL) {
   24208 		dns_db_closeversion(db, &newver, commit);
   24209 	}
   24210 	if (db != NULL) {
   24211 		dns_db_detach(&db);
   24212 	}
   24213 	if (commit) {
   24214 		LOCK_ZONE(zone);
   24215 		resume_addnsec3chain(zone);
   24216 		UNLOCK_ZONE(zone);
   24217 	}
   24218 	dns_diff_clear(&diff);
   24219 	isc_mem_put(zone->mctx, npe, sizeof(*npe));
   24220 
   24221 	INSIST(oldver == NULL);
   24222 	INSIST(newver == NULL);
   24223 }
   24224 
   24225 /*
   24226  * Check if zone has NSEC3PARAM (and thus a chain) with the right parameters.
   24227  *
   24228  * If 'salt' is NULL, a match is found if the salt has the requested length,
   24229  * otherwise the NSEC3 salt must match the requested salt value too.
   24230  *
   24231  * Returns  ISC_R_SUCCESS, if a match is found, or an error if no match is
   24232  * found, or if the db lookup failed.
   24233  */
   24234 isc_result_t
   24235 dns__zone_lookup_nsec3param(dns_zone_t *zone, dns_rdata_nsec3param_t *lookup,
   24236 			    dns_rdata_nsec3param_t *param,
   24237 			    unsigned char saltbuf[255], bool resalt) {
   24238 	isc_result_t result = ISC_R_UNEXPECTED;
   24239 	dns_dbnode_t *node = NULL;
   24240 	dns_db_t *db = NULL;
   24241 	dns_dbversion_t *version = NULL;
   24242 	dns_rdataset_t rdataset;
   24243 	dns_rdata_nsec3param_t nsec3param;
   24244 	dns_rdata_t rdata = DNS_RDATA_INIT;
   24245 
   24246 	REQUIRE(DNS_ZONE_VALID(zone));
   24247 
   24248 	dns_rdataset_init(&rdataset);
   24249 
   24250 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   24251 	if (zone->db != NULL) {
   24252 		dns_db_attach(zone->db, &db);
   24253 	}
   24254 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   24255 	if (db == NULL) {
   24256 		result = ISC_R_FAILURE;
   24257 		goto setparam;
   24258 	}
   24259 
   24260 	result = dns_db_findnode(db, &zone->origin, false, &node);
   24261 	if (result != ISC_R_SUCCESS) {
   24262 		dns_zone_log(zone, ISC_LOG_ERROR,
   24263 			     "dns__zone_lookup_nsec3param:"
   24264 			     "dns_db_findnode -> %s",
   24265 			     isc_result_totext(result));
   24266 		result = ISC_R_FAILURE;
   24267 		goto setparam;
   24268 	}
   24269 	dns_db_currentversion(db, &version);
   24270 
   24271 	result = dns_db_findrdataset(db, node, version,
   24272 				     dns_rdatatype_nsec3param,
   24273 				     dns_rdatatype_none, 0, &rdataset, NULL);
   24274 	if (result != ISC_R_SUCCESS) {
   24275 		INSIST(!dns_rdataset_isassociated(&rdataset));
   24276 		if (result != ISC_R_NOTFOUND) {
   24277 			dns_zone_log(zone, ISC_LOG_ERROR,
   24278 				     "dns__zone_lookup_nsec3param:"
   24279 				     "dns_db_findrdataset -> %s",
   24280 				     isc_result_totext(result));
   24281 		}
   24282 		goto setparam;
   24283 	}
   24284 
   24285 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   24286 	     result = dns_rdataset_next(&rdataset))
   24287 	{
   24288 		dns_rdataset_current(&rdataset, &rdata);
   24289 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   24290 		INSIST(result == ISC_R_SUCCESS);
   24291 		dns_rdata_reset(&rdata);
   24292 
   24293 		/* Check parameters. */
   24294 		if (nsec3param.hash != lookup->hash) {
   24295 			continue;
   24296 		}
   24297 		if (nsec3param.iterations != lookup->iterations) {
   24298 			continue;
   24299 		}
   24300 		if (nsec3param.salt_length != lookup->salt_length) {
   24301 			continue;
   24302 		}
   24303 		if (lookup->salt != NULL) {
   24304 			if (memcmp(nsec3param.salt, lookup->salt,
   24305 				   lookup->salt_length) != 0)
   24306 			{
   24307 				continue;
   24308 			}
   24309 		}
   24310 		/* Found a match. */
   24311 		result = ISC_R_SUCCESS;
   24312 		param->hash = nsec3param.hash;
   24313 		param->flags = nsec3param.flags;
   24314 		param->iterations = nsec3param.iterations;
   24315 		param->salt_length = nsec3param.salt_length;
   24316 		param->salt = nsec3param.salt;
   24317 		break;
   24318 	}
   24319 
   24320 	if (result == ISC_R_NOMORE) {
   24321 		result = ISC_R_NOTFOUND;
   24322 	}
   24323 
   24324 setparam:
   24325 	if (result != ISC_R_SUCCESS) {
   24326 		/* Found no match. */
   24327 		param->hash = lookup->hash;
   24328 		param->flags = lookup->flags;
   24329 		param->iterations = lookup->iterations;
   24330 		param->salt_length = lookup->salt_length;
   24331 		param->salt = lookup->salt;
   24332 	}
   24333 
   24334 	if (result != ISC_R_NOTFOUND) {
   24335 		CHECK(result);
   24336 	}
   24337 
   24338 	if (param->salt_length == 0) {
   24339 		param->salt = (unsigned char *)"-";
   24340 	} else if (resalt || param->salt == NULL) {
   24341 		unsigned char *newsalt;
   24342 		unsigned char salttext[255 * 2 + 1];
   24343 		do {
   24344 			/* Generate a new salt. */
   24345 			result = dns_nsec3_generate_salt(saltbuf,
   24346 							 param->salt_length);
   24347 			if (result != ISC_R_SUCCESS) {
   24348 				break;
   24349 			}
   24350 			newsalt = saltbuf;
   24351 			salt2text(newsalt, param->salt_length, salttext,
   24352 				  sizeof(salttext));
   24353 			dnssec_log(zone, ISC_LOG_INFO, "generated salt: %s",
   24354 				   salttext);
   24355 			/* Check for salt conflict. */
   24356 			if (param->salt != NULL &&
   24357 			    memcmp(newsalt, param->salt, param->salt_length) ==
   24358 				    0)
   24359 			{
   24360 				result = ISC_R_SUCCESS;
   24361 			} else {
   24362 				param->salt = newsalt;
   24363 				result = DNS_R_NSEC3RESALT;
   24364 			}
   24365 		} while (result == ISC_R_SUCCESS);
   24366 
   24367 		INSIST(result != ISC_R_SUCCESS);
   24368 	}
   24369 
   24370 cleanup:
   24371 	if (dns_rdataset_isassociated(&rdataset)) {
   24372 		dns_rdataset_disassociate(&rdataset);
   24373 	}
   24374 	if (node != NULL) {
   24375 		dns_db_detachnode(db, &node);
   24376 	}
   24377 	if (version != NULL) {
   24378 		dns_db_closeversion(db, &version, false);
   24379 	}
   24380 	if (db != NULL) {
   24381 		dns_db_detach(&db);
   24382 	}
   24383 
   24384 	return result;
   24385 }
   24386 
   24387 /*
   24388  * Called when an "rndc signing -nsec3param ..." command is received, or the
   24389  * 'dnssec-policy' has changed.
   24390  *
   24391  * Allocate and prepare an nsec3param_t structure which holds information about
   24392  * the NSEC3 changes requested for the zone:
   24393  *
   24394  *   - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
   24395  *     field of the structure to true and the "replace" field to the value
   24396  *     of the "replace" argument, leaving other fields initialized to zeros, to
   24397  *     signal that the zone should be signed using NSEC instead of NSEC3,
   24398  *
   24399  *   - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
   24400  *     the zone apex, convert it to a private-type record and store the latter
   24401  *     in the "data" field of the nsec3param_t structure.
   24402  *
   24403  * Once the nsec3param_t structure is prepared, post an event to the zone's
   24404  * loop which will cause setnsec3param() to be called with the prepared
   24405  * structure passed as an argument.
   24406  */
   24407 isc_result_t
   24408 dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
   24409 		       uint16_t iter, uint8_t saltlen, unsigned char *salt,
   24410 		       bool replace, bool resalt) {
   24411 	isc_result_t result = ISC_R_SUCCESS;
   24412 	dns_rdata_nsec3param_t param, lookup;
   24413 	dns_rdata_t nrdata = DNS_RDATA_INIT;
   24414 	dns_rdata_t prdata = DNS_RDATA_INIT;
   24415 	unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
   24416 	unsigned char saltbuf[255];
   24417 	struct np3 *npe = NULL;
   24418 	nsec3param_t *np = NULL;
   24419 	isc_buffer_t b;
   24420 	bool do_lookup = false;
   24421 
   24422 	REQUIRE(DNS_ZONE_VALID(zone));
   24423 
   24424 	LOCK_ZONE(zone);
   24425 
   24426 	/*
   24427 	 * First check if the requested NSEC3 parameters are already
   24428 	 * set, if so, no need to set again.
   24429 	 */
   24430 	if (hash != 0) {
   24431 		lookup.hash = hash;
   24432 		lookup.flags = flags;
   24433 		lookup.iterations = iter;
   24434 		lookup.salt_length = saltlen;
   24435 		lookup.salt = salt;
   24436 		param.salt = NULL;
   24437 		result = dns__zone_lookup_nsec3param(zone, &lookup, &param,
   24438 						     saltbuf, resalt);
   24439 		if (result == ISC_R_SUCCESS) {
   24440 			UNLOCK_ZONE(zone);
   24441 			return ISC_R_SUCCESS;
   24442 		}
   24443 		/*
   24444 		 * Schedule lookup if lookup above failed (may happen if
   24445 		 * zone db is NULL for example).
   24446 		 */
   24447 		do_lookup = (param.salt == NULL) ? true : false;
   24448 	}
   24449 
   24450 	npe = isc_mem_get(zone->mctx, sizeof(*npe));
   24451 	*npe = (struct np3){
   24452 		.link = ISC_LINK_INITIALIZER,
   24453 	};
   24454 
   24455 	np = &npe->params;
   24456 	*np = (struct nsec3param){
   24457 		.replace = replace,
   24458 		.resalt = resalt,
   24459 		.lookup = do_lookup,
   24460 	};
   24461 
   24462 	if (hash == 0) {
   24463 		np->nsec = true;
   24464 		dnssec_log(zone, ISC_LOG_DEBUG(3), "setnsec3param:nsec");
   24465 	} else {
   24466 		param.common.rdclass = zone->rdclass;
   24467 		param.common.rdtype = dns_rdatatype_nsec3param;
   24468 		ISC_LINK_INIT(&param.common, link);
   24469 		param.mctx = NULL;
   24470 		/*
   24471 		 * nsec3 specific param set in
   24472 		 * dns__zone_lookup_nsec3param()
   24473 		 */
   24474 		isc_buffer_init(&b, nbuf, sizeof(nbuf));
   24475 
   24476 		if (param.salt != NULL) {
   24477 			CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
   24478 						   dns_rdatatype_nsec3param,
   24479 						   &param, &b));
   24480 			dns_nsec3param_toprivate(&nrdata, &prdata,
   24481 						 zone->privatetype, np->data,
   24482 						 sizeof(np->data));
   24483 			np->length = prdata.length;
   24484 		}
   24485 
   24486 		np->rdata = param;
   24487 
   24488 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   24489 			unsigned char salttext[255 * 2 + 1];
   24490 			if (param.salt != NULL) {
   24491 				salt2text(param.salt, param.salt_length,
   24492 					  salttext, sizeof(salttext));
   24493 			}
   24494 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   24495 				   "setnsec3param:nsec3 %u %u %u %u:%s",
   24496 				   param.hash, param.flags, param.iterations,
   24497 				   param.salt_length,
   24498 				   param.salt == NULL ? "unknown"
   24499 						      : (char *)salttext);
   24500 		}
   24501 	}
   24502 
   24503 	/*
   24504 	 * setnsec3param() will silently return early if the zone does
   24505 	 * not yet have a database.  Prevent that by queueing the event
   24506 	 * up if zone->db is NULL.  All events queued here are
   24507 	 * subsequently processed by receive_secure_db() if it ever gets
   24508 	 * called or simply freed by zone_free() otherwise.
   24509 	 */
   24510 
   24511 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   24512 	if (zone->db != NULL) {
   24513 		zone_iattach(zone, &npe->zone);
   24514 		isc_async_run(zone->loop, setnsec3param, npe);
   24515 	} else {
   24516 		ISC_LIST_APPEND(zone->setnsec3param_queue, npe, link);
   24517 	}
   24518 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   24519 
   24520 	result = ISC_R_SUCCESS;
   24521 
   24522 cleanup:
   24523 	UNLOCK_ZONE(zone);
   24524 	return result;
   24525 }
   24526 
   24527 isc_result_t
   24528 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
   24529 	REQUIRE(DNS_ZONE_VALID(zone));
   24530 	REQUIRE(loadtime != NULL);
   24531 
   24532 	LOCK_ZONE(zone);
   24533 	*loadtime = zone->loadtime;
   24534 	UNLOCK_ZONE(zone);
   24535 	return ISC_R_SUCCESS;
   24536 }
   24537 
   24538 isc_result_t
   24539 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
   24540 	REQUIRE(DNS_ZONE_VALID(zone));
   24541 	REQUIRE(expiretime != NULL);
   24542 
   24543 	LOCK_ZONE(zone);
   24544 	*expiretime = zone->expiretime;
   24545 	UNLOCK_ZONE(zone);
   24546 	return ISC_R_SUCCESS;
   24547 }
   24548 
   24549 isc_result_t
   24550 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
   24551 	REQUIRE(DNS_ZONE_VALID(zone));
   24552 	REQUIRE(refreshtime != NULL);
   24553 
   24554 	LOCK_ZONE(zone);
   24555 	*refreshtime = zone->refreshtime;
   24556 	UNLOCK_ZONE(zone);
   24557 	return ISC_R_SUCCESS;
   24558 }
   24559 
   24560 isc_result_t
   24561 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
   24562 	REQUIRE(DNS_ZONE_VALID(zone));
   24563 	REQUIRE(refreshkeytime != NULL);
   24564 
   24565 	LOCK_ZONE(zone);
   24566 	*refreshkeytime = zone->refreshkeytime;
   24567 	UNLOCK_ZONE(zone);
   24568 	return ISC_R_SUCCESS;
   24569 }
   24570 
   24571 unsigned int
   24572 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
   24573 	dns_include_t *include;
   24574 	char **array = NULL;
   24575 	unsigned int n = 0;
   24576 
   24577 	REQUIRE(DNS_ZONE_VALID(zone));
   24578 	REQUIRE(includesp != NULL && *includesp == NULL);
   24579 
   24580 	LOCK_ZONE(zone);
   24581 	if (zone->nincludes == 0) {
   24582 		goto done;
   24583 	}
   24584 
   24585 	array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
   24586 	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
   24587 	     include = ISC_LIST_NEXT(include, link))
   24588 	{
   24589 		INSIST(n < zone->nincludes);
   24590 		array[n++] = isc_mem_strdup(zone->mctx, include->name);
   24591 	}
   24592 	INSIST(n == zone->nincludes);
   24593 	*includesp = array;
   24594 
   24595 done:
   24596 	UNLOCK_ZONE(zone);
   24597 	return n;
   24598 }
   24599 
   24600 void
   24601 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
   24602 	REQUIRE(DNS_ZONE_VALID(zone));
   24603 
   24604 	zone->statlevel = level;
   24605 }
   24606 
   24607 dns_zonestat_level_t
   24608 dns_zone_getstatlevel(dns_zone_t *zone) {
   24609 	REQUIRE(DNS_ZONE_VALID(zone));
   24610 
   24611 	return zone->statlevel;
   24612 }
   24613 
   24614 static void
   24615 setserial(void *arg) {
   24616 	uint32_t oldserial, desired;
   24617 	bool commit = false;
   24618 	isc_result_t result;
   24619 	dns_dbversion_t *oldver = NULL, *newver = NULL;
   24620 	dns_db_t *db = NULL;
   24621 	dns_diff_t diff;
   24622 	struct setserial *sse = (struct setserial *)arg;
   24623 	dns_zone_t *zone = sse->zone;
   24624 	dns_update_log_t log = { update_log_cb, NULL };
   24625 	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
   24626 
   24627 	INSIST(DNS_ZONE_VALID(zone));
   24628 
   24629 	ENTER;
   24630 
   24631 	if (zone->update_disabled) {
   24632 		goto disabled;
   24633 	}
   24634 
   24635 	desired = sse->serial;
   24636 
   24637 	dns_diff_init(zone->mctx, &diff);
   24638 
   24639 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   24640 	if (zone->db != NULL) {
   24641 		dns_db_attach(zone->db, &db);
   24642 	}
   24643 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   24644 	if (db == NULL) {
   24645 		goto cleanup;
   24646 	}
   24647 
   24648 	dns_db_currentversion(db, &oldver);
   24649 	result = dns_db_newversion(db, &newver);
   24650 	if (result != ISC_R_SUCCESS) {
   24651 		dns_zone_log(zone, ISC_LOG_ERROR,
   24652 			     "setserial:dns_db_newversion -> %s",
   24653 			     isc_result_totext(result));
   24654 		goto cleanup;
   24655 	}
   24656 
   24657 	CHECK(dns_db_createsoatuple(db, oldver, diff.mctx, DNS_DIFFOP_DEL,
   24658 				    &oldtuple));
   24659 	CHECK(dns_difftuple_copy(oldtuple, &newtuple));
   24660 	newtuple->op = DNS_DIFFOP_ADD;
   24661 
   24662 	oldserial = dns_soa_getserial(&oldtuple->rdata);
   24663 	if (desired == 0U) {
   24664 		desired = 1;
   24665 	}
   24666 	if (!isc_serial_gt(desired, oldserial)) {
   24667 		if (desired != oldserial) {
   24668 			dns_zone_log(zone, ISC_LOG_INFO,
   24669 				     "setserial: desired serial (%u) "
   24670 				     "out of range (%u-%u)",
   24671 				     desired, oldserial + 1,
   24672 				     oldserial + 0x7fffffff);
   24673 		}
   24674 		goto cleanup;
   24675 	}
   24676 
   24677 	dns_soa_setserial(desired, &newtuple->rdata);
   24678 	CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
   24679 	CHECK(do_one_tuple(&newtuple, db, newver, &diff));
   24680 	result = dns_update_signatures(&log, zone, db, oldver, newver, &diff,
   24681 				       zone->sigvalidityinterval);
   24682 	if (result != ISC_R_NOTFOUND) {
   24683 		CHECK(result);
   24684 	}
   24685 
   24686 	/* Write changes to journal file. */
   24687 	CHECK(zone_journal(zone, &diff, NULL, "setserial"));
   24688 	commit = true;
   24689 
   24690 	LOCK_ZONE(zone);
   24691 	zone_needdump(zone, 30);
   24692 	UNLOCK_ZONE(zone);
   24693 
   24694 cleanup:
   24695 	if (oldtuple != NULL) {
   24696 		dns_difftuple_free(&oldtuple);
   24697 	}
   24698 	if (newtuple != NULL) {
   24699 		dns_difftuple_free(&newtuple);
   24700 	}
   24701 	if (oldver != NULL) {
   24702 		dns_db_closeversion(db, &oldver, false);
   24703 	}
   24704 	if (newver != NULL) {
   24705 		dns_db_closeversion(db, &newver, commit);
   24706 	}
   24707 	if (db != NULL) {
   24708 		dns_db_detach(&db);
   24709 	}
   24710 	dns_diff_clear(&diff);
   24711 
   24712 disabled:
   24713 	isc_mem_put(zone->mctx, sse, sizeof(*sse));
   24714 	dns_zone_idetach(&zone);
   24715 
   24716 	INSIST(oldver == NULL);
   24717 	INSIST(newver == NULL);
   24718 }
   24719 
   24720 isc_result_t
   24721 dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
   24722 	isc_result_t result = ISC_R_SUCCESS;
   24723 	struct setserial *sse = NULL;
   24724 
   24725 	REQUIRE(DNS_ZONE_VALID(zone));
   24726 
   24727 	LOCK_ZONE(zone);
   24728 
   24729 	if (!inline_secure(zone)) {
   24730 		if (!dns_zone_isdynamic(zone, true)) {
   24731 			CHECK(DNS_R_NOTDYNAMIC);
   24732 		}
   24733 	}
   24734 
   24735 	if (zone->update_disabled) {
   24736 		CHECK(DNS_R_FROZEN);
   24737 	}
   24738 
   24739 	sse = isc_mem_get(zone->mctx, sizeof(*sse));
   24740 	*sse = (struct setserial){ .serial = serial };
   24741 	zone_iattach(zone, &sse->zone);
   24742 	isc_async_run(zone->loop, setserial, sse);
   24743 
   24744 cleanup:
   24745 	UNLOCK_ZONE(zone);
   24746 	return result;
   24747 }
   24748 
   24749 isc_stats_t *
   24750 dns_zone_getgluecachestats(dns_zone_t *zone) {
   24751 	REQUIRE(DNS_ZONE_VALID(zone));
   24752 
   24753 	return zone->gluecachestats;
   24754 }
   24755 
   24756 bool
   24757 dns_zone_isloaded(dns_zone_t *zone) {
   24758 	REQUIRE(DNS_ZONE_VALID(zone));
   24759 
   24760 	return DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED);
   24761 }
   24762 
   24763 isc_result_t
   24764 dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
   24765 	dns_dbversion_t *version = NULL;
   24766 	dns_keytable_t *secroots = NULL;
   24767 	isc_result_t result;
   24768 	dns_name_t *origin;
   24769 
   24770 	REQUIRE(DNS_ZONE_VALID(zone));
   24771 	REQUIRE(db != NULL);
   24772 
   24773 	ENTER;
   24774 
   24775 	if (dns_zone_gettype(zone) != dns_zone_mirror) {
   24776 		return ISC_R_SUCCESS;
   24777 	}
   24778 
   24779 	if (ver == NULL) {
   24780 		dns_db_currentversion(db, &version);
   24781 	} else {
   24782 		version = ver;
   24783 	}
   24784 
   24785 	if (zone->view != NULL) {
   24786 		result = dns_view_getsecroots(zone->view, &secroots);
   24787 		CHECK(result);
   24788 	}
   24789 
   24790 	origin = dns_db_origin(db);
   24791 	result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
   24792 				       zone->mctx, true, false, dnssec_report);
   24793 
   24794 cleanup:
   24795 	if (secroots != NULL) {
   24796 		dns_keytable_detach(&secroots);
   24797 	}
   24798 
   24799 	if (ver == NULL) {
   24800 		dns_db_closeversion(db, &version, false);
   24801 	}
   24802 
   24803 	if (result != ISC_R_SUCCESS) {
   24804 		dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
   24805 			   isc_result_totext(result));
   24806 		result = DNS_R_VERIFYFAILURE;
   24807 	}
   24808 
   24809 	return result;
   24810 }
   24811 
   24812 static dns_ttl_t
   24813 zone_nsecttl(dns_zone_t *zone) {
   24814 	REQUIRE(DNS_ZONE_VALID(zone));
   24815 
   24816 	return ISC_MIN(zone->minimum, zone->soattl);
   24817 }
   24818 
   24819 void
   24820 dns_zonemgr_set_tlsctx_cache(dns_zonemgr_t *zmgr,
   24821 			     isc_tlsctx_cache_t *tlsctx_cache) {
   24822 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   24823 	REQUIRE(tlsctx_cache != NULL);
   24824 
   24825 	RWLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_write);
   24826 
   24827 	if (zmgr->tlsctx_cache != NULL) {
   24828 		isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
   24829 	}
   24830 
   24831 	isc_tlsctx_cache_attach(tlsctx_cache, &zmgr->tlsctx_cache);
   24832 
   24833 	RWUNLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_write);
   24834 }
   24835 
   24836 static void
   24837 zmgr_tlsctx_attach(dns_zonemgr_t *zmgr, isc_tlsctx_cache_t **ptlsctx_cache) {
   24838 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   24839 	REQUIRE(ptlsctx_cache != NULL && *ptlsctx_cache == NULL);
   24840 
   24841 	RWLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_read);
   24842 
   24843 	INSIST(zmgr->tlsctx_cache != NULL);
   24844 	isc_tlsctx_cache_attach(zmgr->tlsctx_cache, ptlsctx_cache);
   24845 
   24846 	RWUNLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_read);
   24847 }
   24848 
   24849 isc_mem_t *
   24850 dns_zone_getmem(dns_zone_t *zone) {
   24851 	return zone->mctx;
   24852 }
   24853 
   24854 unsigned int
   24855 dns_zone_gettid(dns_zone_t *zone) {
   24856 	return zone->tid;
   24857 }
   24858 
   24859 isc_loop_t *
   24860 dns_zone_getloop(dns_zone_t *zone) {
   24861 	return zone->loop;
   24862 }
   24863 
   24864 isc_result_t
   24865 dns_zone_makedb(dns_zone_t *zone, dns_db_t **dbp) {
   24866 	REQUIRE(DNS_ZONE_VALID(zone));
   24867 	REQUIRE(dbp != NULL && *dbp == NULL);
   24868 
   24869 	dns_db_t *db = NULL;
   24870 
   24871 	isc_result_t result = dns_db_create(
   24872 		zone->mctx, zone->db_argv[0], &zone->origin,
   24873 		(zone->type == dns_zone_stub) ? dns_dbtype_stub
   24874 					      : dns_dbtype_zone,
   24875 		zone->rdclass, zone->db_argc - 1, zone->db_argv + 1, &db);
   24876 	if (result != ISC_R_SUCCESS) {
   24877 		return result;
   24878 	}
   24879 
   24880 	switch (zone->type) {
   24881 	case dns_zone_primary:
   24882 	case dns_zone_secondary:
   24883 	case dns_zone_mirror:
   24884 		result = dns_db_setgluecachestats(db, zone->gluecachestats);
   24885 		if (result == ISC_R_NOTIMPLEMENTED) {
   24886 			result = ISC_R_SUCCESS;
   24887 		}
   24888 		if (result != ISC_R_SUCCESS) {
   24889 			dns_db_detach(&db);
   24890 			return result;
   24891 		}
   24892 		break;
   24893 	default:
   24894 		break;
   24895 	}
   24896 
   24897 	dns_db_setloop(db, zone->loop);
   24898 	dns_db_setmaxrrperset(db, zone->maxrrperset);
   24899 	dns_db_setmaxtypepername(db, zone->maxtypepername);
   24900 
   24901 	*dbp = db;
   24902 
   24903 	return ISC_R_SUCCESS;
   24904 }
   24905 
   24906 isc_result_t
   24907 dns_zone_import_skr(dns_zone_t *zone, const char *file) {
   24908 	dns_skr_t *skr = NULL;
   24909 	isc_result_t result;
   24910 
   24911 	REQUIRE(DNS_ZONE_VALID(zone));
   24912 	REQUIRE(zone->kasp != NULL);
   24913 	REQUIRE(file != NULL);
   24914 
   24915 	dns_skr_create(zone->mctx, file, &zone->origin, zone->rdclass, &skr);
   24916 
   24917 	CHECK(dns_skr_read(zone->mctx, file, &zone->origin, zone->rdclass,
   24918 			   dns_kasp_dnskeyttl(zone->kasp), &skr));
   24919 
   24920 	dns_zone_setskr(zone, skr);
   24921 	dnssec_log(zone, ISC_LOG_DEBUG(1), "imported skr file %s", file);
   24922 
   24923 cleanup:
   24924 	dns_skr_detach(&skr);
   24925 
   24926 	return result;
   24927 }
   24928