Home | History | Annotate | Line # | Download | only in dns
zone.c revision 1.26
      1 /*	$NetBSD: zone.c,v 1.26 2026/01/29 18:37:50 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/loop.h>
     29 #include <isc/md.h>
     30 #include <isc/mutex.h>
     31 #include <isc/overflow.h>
     32 #include <isc/random.h>
     33 #include <isc/ratelimiter.h>
     34 #include <isc/refcount.h>
     35 #include <isc/result.h>
     36 #include <isc/rwlock.h>
     37 #include <isc/serial.h>
     38 #include <isc/stats.h>
     39 #include <isc/stdtime.h>
     40 #include <isc/strerr.h>
     41 #include <isc/string.h>
     42 #include <isc/thread.h>
     43 #include <isc/tid.h>
     44 #include <isc/timer.h>
     45 #include <isc/tls.h>
     46 #include <isc/util.h>
     47 
     48 #include <dns/acl.h>
     49 #include <dns/adb.h>
     50 #include <dns/callbacks.h>
     51 #include <dns/catz.h>
     52 #include <dns/db.h>
     53 #include <dns/dbiterator.h>
     54 #include <dns/dlz.h>
     55 #include <dns/dnssec.h>
     56 #include <dns/journal.h>
     57 #include <dns/kasp.h>
     58 #include <dns/keydata.h>
     59 #include <dns/keymgr.h>
     60 #include <dns/keytable.h>
     61 #include <dns/keyvalues.h>
     62 #include <dns/log.h>
     63 #include <dns/master.h>
     64 #include <dns/masterdump.h>
     65 #include <dns/message.h>
     66 #include <dns/name.h>
     67 #include <dns/nsec.h>
     68 #include <dns/nsec3.h>
     69 #include <dns/opcode.h>
     70 #include <dns/peer.h>
     71 #include <dns/private.h>
     72 #include <dns/rcode.h>
     73 #include <dns/rdata.h>
     74 #include <dns/rdataclass.h>
     75 #include <dns/rdatalist.h>
     76 #include <dns/rdataset.h>
     77 #include <dns/rdatasetiter.h>
     78 #include <dns/rdatastruct.h>
     79 #include <dns/rdatatype.h>
     80 #include <dns/remote.h>
     81 #include <dns/request.h>
     82 #include <dns/resolver.h>
     83 #include <dns/rriterator.h>
     84 #include <dns/skr.h>
     85 #include <dns/soa.h>
     86 #include <dns/ssu.h>
     87 #include <dns/stats.h>
     88 #include <dns/time.h>
     89 #include <dns/tsig.h>
     90 #include <dns/ttl.h>
     91 #include <dns/update.h>
     92 #include <dns/xfrin.h>
     93 #include <dns/zone.h>
     94 #include <dns/zoneverify.h>
     95 #include <dns/zt.h>
     96 
     97 #include <dst/dst.h>
     98 
     99 #include "zone_p.h"
    100 
    101 #define ZONE_MAGIC	     ISC_MAGIC('Z', 'O', 'N', 'E')
    102 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
    103 
    104 #define NOTIFY_MAGIC		 ISC_MAGIC('N', 't', 'f', 'y')
    105 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
    106 
    107 #define CHECKDS_MAGIC		   ISC_MAGIC('C', 'h', 'D', 'S')
    108 #define DNS_CHECKDS_VALID(checkds) ISC_MAGIC_VALID(checkds, CHECKDS_MAGIC)
    109 
    110 #define STUB_MAGIC	     ISC_MAGIC('S', 't', 'u', 'b')
    111 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
    112 
    113 #define ZONEMGR_MAGIC		ISC_MAGIC('Z', 'm', 'g', 'r')
    114 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
    115 
    116 #define FORWARD_MAGIC		ISC_MAGIC('F', 'o', 'r', 'w')
    117 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
    118 
    119 #define IO_MAGIC	   ISC_MAGIC('Z', 'm', 'I', 'O')
    120 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
    121 
    122 #define KEYMGMT_MAGIC		ISC_MAGIC('M', 'g', 'm', 't')
    123 #define DNS_KEYMGMT_VALID(load) ISC_MAGIC_VALID(load, KEYMGMT_MAGIC)
    124 
    125 #define KEYFILEIO_MAGIC		  ISC_MAGIC('K', 'y', 'I', 'O')
    126 #define DNS_KEYFILEIO_VALID(kfio) ISC_MAGIC_VALID(kfio, KEYFILEIO_MAGIC)
    127 
    128 /*%
    129  * Ensure 'a' is at least 'min' but not more than 'max'.
    130  */
    131 #define RANGE(a, min, max) (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
    132 
    133 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
    134 
    135 /*%
    136  * Key flags
    137  */
    138 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
    139 #define KSK(x)	  ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
    140 #define ID(x)	  dst_key_id(x)
    141 #define ALG(x)	  dst_key_alg(x)
    142 
    143 /*%
    144  * KASP flags
    145  */
    146 #define KASP_LOCK(k)                \
    147 	if ((k) != NULL) {          \
    148 		LOCK(&((k)->lock)); \
    149 	}
    150 
    151 #define KASP_UNLOCK(k)                \
    152 	if ((k) != NULL) {            \
    153 		UNLOCK(&((k)->lock)); \
    154 	}
    155 
    156 /*
    157  * Default values.
    158  */
    159 #define DNS_DEFAULT_IDLEIN  3600       /*%< 1 hour */
    160 #define DNS_DEFAULT_IDLEOUT 3600       /*%< 1 hour */
    161 #define MAX_XFER_TIME	    (2 * 3600) /*%< Documented default is 2 hours */
    162 #define RESIGN_DELAY	    3600       /*%< 1 hour */
    163 
    164 #ifndef DNS_MAX_EXPIRE
    165 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
    166 #endif				/* ifndef DNS_MAX_EXPIRE */
    167 
    168 #ifndef DNS_DUMP_DELAY
    169 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
    170 #endif			   /* ifndef DNS_DUMP_DELAY */
    171 
    172 typedef struct dns_notify dns_notify_t;
    173 typedef struct dns_checkds dns_checkds_t;
    174 typedef struct dns_stub dns_stub_t;
    175 typedef struct dns_load dns_load_t;
    176 typedef struct dns_forward dns_forward_t;
    177 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
    178 typedef struct dns_keymgmt dns_keymgmt_t;
    179 typedef struct dns_signing dns_signing_t;
    180 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
    181 typedef struct dns_nsec3chain dns_nsec3chain_t;
    182 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
    183 typedef struct dns_nsfetch dns_nsfetch_t;
    184 typedef struct dns_keyfetch dns_keyfetch_t;
    185 typedef struct dns_asyncload dns_asyncload_t;
    186 typedef struct dns_include dns_include_t;
    187 
    188 #define DNS_ZONE_CHECKLOCK
    189 #ifdef DNS_ZONE_CHECKLOCK
    190 #define LOCK_ZONE(z)                  \
    191 	do {                          \
    192 		LOCK(&(z)->lock);     \
    193 		INSIST(!(z)->locked); \
    194 		(z)->locked = true;   \
    195 	} while (0)
    196 #define UNLOCK_ZONE(z)               \
    197 	do {                         \
    198 		INSIST((z)->locked); \
    199 		(z)->locked = false; \
    200 		UNLOCK(&(z)->lock);  \
    201 	} while (0)
    202 #define LOCKED_ZONE(z) ((z)->locked)
    203 #define TRYLOCK_ZONE(result, z)                         \
    204 	do {                                            \
    205 		result = isc_mutex_trylock(&(z)->lock); \
    206 		if (result == ISC_R_SUCCESS) {          \
    207 			INSIST(!(z)->locked);           \
    208 			(z)->locked = true;             \
    209 		}                                       \
    210 	} while (0)
    211 #else /* ifdef DNS_ZONE_CHECKLOCK */
    212 #define LOCK_ZONE(z)   LOCK(&(z)->lock)
    213 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
    214 #define LOCKED_ZONE(z) true
    215 #define TRYLOCK_ZONE(result, z)                         \
    216 	do {                                            \
    217 		result = isc_mutex_trylock(&(z)->lock); \
    218 	} while (0)
    219 #endif /* ifdef DNS_ZONE_CHECKLOCK */
    220 
    221 #define ZONEDB_INITLOCK(l)    isc_rwlock_init(l)
    222 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
    223 #define ZONEDB_LOCK(l, t)     RWLOCK((l), (t))
    224 #define ZONEDB_UNLOCK(l, t)   RWUNLOCK((l), (t))
    225 
    226 #ifdef ENABLE_AFL
    227 extern bool dns_fuzzing_resolver;
    228 #endif /* ifdef ENABLE_AFL */
    229 
    230 /*%
    231  *	Hold key file IO locks.
    232  */
    233 typedef struct dns_keyfileio {
    234 	unsigned int magic;
    235 	isc_mutex_t lock;
    236 	isc_refcount_t references;
    237 	dns_name_t *name;
    238 	dns_fixedname_t fname;
    239 } dns_keyfileio_t;
    240 
    241 struct dns_keymgmt {
    242 	unsigned int magic;
    243 	isc_rwlock_t lock;
    244 	isc_mem_t *mctx;
    245 	isc_hashmap_t *table;
    246 };
    247 
    248 /*
    249  * Initial size of the keymgmt hash table.
    250  */
    251 #define DNS_KEYMGMT_HASH_BITS 12
    252 
    253 struct dns_zone {
    254 	/* Unlocked */
    255 	unsigned int magic;
    256 	isc_mutex_t lock;
    257 #ifndef _LP64
    258 	isc_mutex_t atomic_lock;
    259 #endif
    260 #ifdef DNS_ZONE_CHECKLOCK
    261 	bool locked;
    262 #endif /* ifdef DNS_ZONE_CHECKLOCK */
    263 	isc_mem_t *mctx;
    264 	isc_refcount_t references;
    265 
    266 	isc_rwlock_t dblock;
    267 	dns_db_t *db; /* Locked by dblock */
    268 
    269 	unsigned int tid;
    270 
    271 	/* Locked */
    272 	dns_zonemgr_t *zmgr;
    273 	ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
    274 	isc_loop_t *loop;
    275 	isc_timer_t *timer;
    276 	isc_refcount_t irefs;
    277 	dns_name_t origin;
    278 	char *masterfile;
    279 	const FILE *stream;		     /* loading from a stream? */
    280 	ISC_LIST(dns_include_t) includes;    /* Include files */
    281 	ISC_LIST(dns_include_t) newincludes; /* Loading */
    282 	unsigned int nincludes;
    283 	dns_masterformat_t masterformat;
    284 	const dns_master_style_t *masterstyle;
    285 	char *journal;
    286 	int32_t journalsize;
    287 	dns_rdataclass_t rdclass;
    288 	dns_zonetype_t type;
    289 #ifdef _LP64
    290 	atomic_uint_fast64_t flags;
    291 	atomic_uint_fast64_t options;
    292 #else
    293 	uint64_t flags;
    294 	uint64_t options;
    295 #endif
    296 	unsigned int db_argc;
    297 	char **db_argv;
    298 	isc_time_t expiretime;
    299 	isc_time_t refreshtime;
    300 	isc_time_t dumptime;
    301 	isc_time_t loadtime;
    302 	isc_time_t notifytime;
    303 	isc_time_t resigntime;
    304 	isc_time_t keywarntime;
    305 	isc_time_t signingtime;
    306 	isc_time_t nsec3chaintime;
    307 	isc_time_t refreshkeytime;
    308 	isc_time_t xfrintime;
    309 	uint32_t refreshkeyinterval;
    310 	uint32_t refreshkeycount;
    311 	uint32_t refresh;
    312 	uint32_t retry;
    313 	uint32_t expire;
    314 	uint32_t minimum;
    315 	isc_stdtime_t key_expiry;
    316 	isc_stdtime_t log_key_expired_timer;
    317 	char *keydirectory;
    318 	dns_keyfileio_t *kfio;
    319 	dns_keystorelist_t *keystores;
    320 	dns_xfrin_t *xfr;
    321 
    322 	uint32_t maxrefresh;
    323 	uint32_t minrefresh;
    324 	uint32_t maxretry;
    325 	uint32_t minretry;
    326 
    327 	uint32_t maxrecords;
    328 	uint32_t maxrrperset;
    329 	uint32_t maxtypepername;
    330 
    331 	dns_remote_t primaries;
    332 
    333 	dns_remote_t parentals;
    334 	dns_dnsseckeylist_t checkds_ok;
    335 	dns_checkdstype_t checkdstype;
    336 	uint32_t nsfetchcount;
    337 	uint32_t parent_nscount;
    338 
    339 	dns_remote_t notify;
    340 	dns_notifytype_t notifytype;
    341 	isc_sockaddr_t notifyfrom;
    342 	isc_sockaddr_t notifysrc4;
    343 	isc_sockaddr_t notifysrc6;
    344 	isc_sockaddr_t parentalsrc4;
    345 	isc_sockaddr_t parentalsrc6;
    346 	isc_sockaddr_t xfrsource4;
    347 	isc_sockaddr_t xfrsource6;
    348 	isc_sockaddr_t sourceaddr;
    349 	dns_tsigkey_t *tsigkey;	    /* key used for xfr */
    350 	dns_transport_t *transport; /* transport used for xfr */
    351 	/* Access Control Lists */
    352 	dns_acl_t *update_acl;
    353 	dns_acl_t *forward_acl;
    354 	dns_acl_t *notify_acl;
    355 	dns_acl_t *query_acl;
    356 	dns_acl_t *queryon_acl;
    357 	dns_acl_t *xfr_acl;
    358 	bool update_disabled;
    359 	bool zero_no_soa_ttl;
    360 	dns_severity_t check_names;
    361 	ISC_LIST(dns_notify_t) notifies;
    362 	ISC_LIST(dns_checkds_t) checkds_requests;
    363 	dns_request_t *request;
    364 	dns_loadctx_t *loadctx;
    365 	dns_dumpctx_t *dumpctx;
    366 	uint32_t minxfrratebytesin;
    367 	uint32_t minxfrratesecondsin;
    368 	uint32_t maxxfrin;
    369 	uint32_t maxxfrout;
    370 	uint32_t idlein;
    371 	uint32_t idleout;
    372 	dns_ssutable_t *ssutable;
    373 	uint32_t sigvalidityinterval;
    374 	uint32_t keyvalidityinterval;
    375 	uint32_t sigresigninginterval;
    376 	dns_view_t *view;
    377 	dns_view_t *prev_view;
    378 	dns_kasp_t *kasp;
    379 	dns_kasp_t *defaultkasp;
    380 	dns_dnsseckeylist_t keyring;
    381 	dns_checkmxfunc_t checkmx;
    382 	dns_checksrvfunc_t checksrv;
    383 	dns_checknsfunc_t checkns;
    384 	/*%
    385 	 * Zones in certain states such as "waiting for zone transfer"
    386 	 * or "zone transfer in progress" are kept on per-state linked lists
    387 	 * in the zone manager using the 'statelink' field.  The 'statelist'
    388 	 * field points at the list the zone is currently on.  It the zone
    389 	 * is not on any such list, statelist is NULL.
    390 	 */
    391 	ISC_LINK(dns_zone_t) statelink;
    392 	dns_zonelist_t *statelist;
    393 	/*%
    394 	 * Statistics counters about zone management.
    395 	 */
    396 	isc_stats_t *stats;
    397 	/*%
    398 	 * Optional per-zone statistics counters.  Counted outside of this
    399 	 * module.
    400 	 */
    401 	dns_zonestat_level_t statlevel;
    402 	bool requeststats_on;
    403 	isc_stats_t *requeststats;
    404 	dns_stats_t *rcvquerystats;
    405 	dns_stats_t *dnssecsignstats;
    406 	uint32_t notifydelay;
    407 	uint32_t notifydefer;
    408 	dns_isselffunc_t isself;
    409 	void *isselfarg;
    410 
    411 	char *strnamerd;
    412 	char *strname;
    413 	char *strrdclass;
    414 	char *strviewname;
    415 
    416 	/*%
    417 	 * Serial number for deferred journal compaction.
    418 	 */
    419 	uint32_t compact_serial;
    420 	/*%
    421 	 * Keys that are signing the zone for the first time.
    422 	 */
    423 	dns_signinglist_t signing;
    424 	dns_nsec3chainlist_t nsec3chain;
    425 	/*%
    426 	 * List of outstanding NSEC3PARAM change requests.
    427 	 */
    428 	ISC_LIST(struct np3) setnsec3param_queue;
    429 	/*%
    430 	 * Signing / re-signing quantum stopping parameters.
    431 	 */
    432 	uint32_t signatures;
    433 	uint32_t nodes;
    434 	dns_rdatatype_t privatetype;
    435 
    436 	/*%
    437 	 * Autosigning/key-maintenance options
    438 	 */
    439 #ifdef _LP64
    440 	atomic_uint_fast64_t keyopts;
    441 #else
    442 	uint64_t keyopts;
    443 #endif
    444 
    445 	/*%
    446 	 * True if added by "rndc addzone"
    447 	 */
    448 	bool added;
    449 
    450 	/*%
    451 	 * True if added by automatically by named.
    452 	 */
    453 	bool automatic;
    454 
    455 	/*%
    456 	 * response policy data to be relayed to the database
    457 	 */
    458 	dns_rpz_zones_t *rpzs;
    459 	dns_rpz_num_t rpz_num;
    460 
    461 	/*%
    462 	 * catalog zone data
    463 	 */
    464 	dns_catz_zones_t *catzs;
    465 
    466 	/*%
    467 	 * parent catalog zone
    468 	 */
    469 	dns_catz_zone_t *parentcatz;
    470 
    471 	/*%
    472 	 * Serial number update method.
    473 	 */
    474 	dns_updatemethod_t updatemethod;
    475 
    476 	/*%
    477 	 * whether ixfr is requested
    478 	 */
    479 	bool requestixfr;
    480 	uint32_t ixfr_ratio;
    481 
    482 	/*%
    483 	 * whether EDNS EXPIRE is requested
    484 	 */
    485 	bool requestexpire;
    486 
    487 	/*%
    488 	 * Outstanding forwarded UPDATE requests.
    489 	 */
    490 	dns_forwardlist_t forwards;
    491 
    492 	dns_zone_t *raw;
    493 	dns_zone_t *secure;
    494 
    495 	bool sourceserialset;
    496 	uint32_t sourceserial;
    497 
    498 	/*%
    499 	 * soa and maximum zone ttl
    500 	 */
    501 	dns_ttl_t soattl;
    502 	dns_ttl_t maxttl;
    503 
    504 	/*
    505 	 * Inline zone signing state.
    506 	 */
    507 	dns_diff_t rss_diff;
    508 	dns_dbversion_t *rss_newver;
    509 	dns_dbversion_t *rss_oldver;
    510 	dns_db_t *rss_db;
    511 	dns_zone_t *rss_raw;
    512 	struct rss *rss;
    513 	dns_update_state_t *rss_state;
    514 
    515 	isc_stats_t *gluecachestats;
    516 
    517 	/*%
    518 	 * Offline KSK signed key responses.
    519 	 */
    520 	dns_skr_t *skr;
    521 	dns_skrbundle_t *skrbundle;
    522 };
    523 
    524 #define zonediff_init(z, d)                \
    525 	do {                               \
    526 		dns__zonediff_t *_z = (z); \
    527 		(_z)->diff = (d);          \
    528 		(_z)->offline = false;     \
    529 	} while (0)
    530 #ifdef _LP64
    531 #define ISC_ZONE_GET(z, f) atomic_load_relaxed(&(z)->f)
    532 #define ISC_ZONE_SET(z, f, o) atomic_fetch_or(&(z)->f, (o))
    533 #define ISC_ZONE_CLR(z, f, o) atomic_fetch_and(&(z)->f, ~(o))
    534 #else
    535 #define ISC_ZONE_GET(z, f) \
    536 	({ \
    537 		isc_mutex_lock(&(z)->atomic_lock); \
    538 		uint64_t x = (z)->f; \
    539 		isc_mutex_unlock(&(z)->atomic_lock); \
    540 		x; \
    541 	})
    542 #define ISC_ZONE_SET(z, f, o) \
    543 	({ \
    544 		isc_mutex_lock(&(z)->atomic_lock); \
    545 		uint64_t x = ((z)->f | (o)); \
    546 		isc_mutex_unlock(&(z)->atomic_lock); \
    547 		x; \
    548 	})
    549 #define ISC_ZONE_CLR(z, f, o) \
    550 	({ \
    551 		isc_mutex_lock(&(z)->atomic_lock); \
    552 		uint64_t x = ((z)->f & ~(o)); \
    553 		isc_mutex_unlock(&(z)->atomic_lock); \
    554 		x; \
    555 	})
    556 #endif
    557 #define ISC_ZONE_TEST(z, f, o) ((ISC_ZONE_GET(z, f) & (o)) != 0)
    558 
    559 #define DNS_ZONE_FLAG(z, f)    ISC_ZONE_TEST(z, flags, f)
    560 #define DNS_ZONE_SETFLAG(z, f) ISC_ZONE_SET(z, flags, f)
    561 #define DNS_ZONE_CLRFLAG(z, f) ISC_ZONE_CLR(z, flags, f)
    562 typedef enum {
    563 	DNS_ZONEFLG_REFRESH = 0x00000001U,     /*%< refresh check in progress */
    564 	DNS_ZONEFLG_NEEDDUMP = 0x00000002U,    /*%< zone need consolidation */
    565 	DNS_ZONEFLG_USEVC = 0x00000004U,       /*%< use tcp for refresh query */
    566 	DNS_ZONEFLG_DUMPING = 0x00000008U,     /*%< a dump is in progress */
    567 	DNS_ZONEFLG_HASINCLUDE = 0x00000010U,  /*%< $INCLUDE in zone file */
    568 	DNS_ZONEFLG_LOADED = 0x00000020U,      /*%< database has loaded */
    569 	DNS_ZONEFLG_EXITING = 0x00000040U,     /*%< zone is being destroyed */
    570 	DNS_ZONEFLG_EXPIRED = 0x00000080U,     /*%< zone has expired */
    571 	DNS_ZONEFLG_NEEDREFRESH = 0x00000100U, /*%< refresh check needed */
    572 	DNS_ZONEFLG_UPTODATE = 0x00000200U,    /*%< zone contents are
    573 						* up-to-date */
    574 	DNS_ZONEFLG_NEEDNOTIFY = 0x00000400U,  /*%< need to send out notify
    575 						* messages */
    576 	DNS_ZONEFLG_FIXJOURNAL = 0x00000800U,  /*%< journal file had
    577 						* recoverable error,
    578 						* needs rewriting */
    579 	DNS_ZONEFLG_NOPRIMARIES = 0x00001000U, /*%< an attempt to refresh a
    580 						* zone with no primaries
    581 						* occurred */
    582 	DNS_ZONEFLG_LOADING = 0x00002000U,     /*%< load from disk in progress*/
    583 	DNS_ZONEFLG_HAVETIMERS = 0x00004000U,  /*%< timer values have been set
    584 						* from SOA (if not set, we
    585 						* are still using
    586 						* default timer values) */
    587 	DNS_ZONEFLG_FORCEXFER = 0x00008000U,   /*%< Force a zone xfer */
    588 	DNS_ZONEFLG_NOREFRESH = 0x00010000U,
    589 	DNS_ZONEFLG_DIALNOTIFY = 0x00020000U,
    590 	DNS_ZONEFLG_DIALREFRESH = 0x00040000U,
    591 	DNS_ZONEFLG_SHUTDOWN = 0x00080000U,
    592 	DNS_ZONEFLG_NOIXFR = 0x00100000U, /*%< IXFR failed, force AXFR */
    593 	DNS_ZONEFLG_FLUSH = 0x00200000U,
    594 	DNS_ZONEFLG_NOEDNS = 0x00400000U,
    595 	DNS_ZONEFLG_USEALTXFRSRC = 0x00800000U, /*%< Obsoleted. */
    596 	DNS_ZONEFLG_SOABEFOREAXFR = 0x01000000U,
    597 	DNS_ZONEFLG_NEEDCOMPACT = 0x02000000U,
    598 	DNS_ZONEFLG_REFRESHING = 0x04000000U, /*%< Refreshing keydata */
    599 	DNS_ZONEFLG_THAW = 0x08000000U,
    600 	DNS_ZONEFLG_LOADPENDING = 0x10000000U, /*%< Loading scheduled */
    601 	DNS_ZONEFLG_NODELAY = 0x20000000U,
    602 	DNS_ZONEFLG_SENDSECURE = 0x40000000U,
    603 	DNS_ZONEFLG_NEEDSTARTUPNOTIFY = 0x80000000U, /*%< need to send out
    604 						      * notify due to the zone
    605 						      * just being loaded for
    606 						      * the first time. */
    607 	DNS_ZONEFLG_NOTIFYNODEFER = 0x100000000U,    /*%< ignore the
    608 						      * notify-defer option. */
    609 	DNS_ZONEFLG_NOTIFYDEFERRED = 0x200000000U,   /*%< notify was deferred
    610 						      * according to the
    611 						      * notify-defer option. */
    612 	DNS_ZONEFLG_FIRSTREFRESH = 0x400000000U, /*%< First refresh pending */
    613 	DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
    614 } dns_zoneflg_t;
    615 
    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 
    625 /* Flags for zone_load() */
    626 typedef enum {
    627 	DNS_ZONELOADFLAG_NOSTAT = 0x00000001U, /* Do not stat() master files */
    628 	DNS_ZONELOADFLAG_THAW = 0x00000002U,   /* Thaw the zone on successful
    629 						* load. */
    630 } dns_zoneloadflag_t;
    631 
    632 #define UNREACH_CACHE_SIZE 10U
    633 #define UNREACH_HOLD_TIME  600 /* 10 minutes */
    634 
    635 struct dns_unreachable {
    636 	isc_sockaddr_t remote;
    637 	isc_sockaddr_t local;
    638 	atomic_uint_fast32_t expire;
    639 	atomic_uint_fast32_t last;
    640 	uint32_t count;
    641 };
    642 
    643 struct dns_zonemgr {
    644 	unsigned int magic;
    645 	isc_mem_t *mctx;
    646 	isc_refcount_t refs;
    647 	isc_loopmgr_t *loopmgr;
    648 	isc_nm_t *netmgr;
    649 	uint32_t workers;
    650 	isc_mem_t **mctxpool;
    651 	isc_ratelimiter_t *checkdsrl;
    652 	isc_ratelimiter_t *notifyrl;
    653 	isc_ratelimiter_t *refreshrl;
    654 	isc_ratelimiter_t *startupnotifyrl;
    655 	isc_ratelimiter_t *startuprefreshrl;
    656 	isc_rwlock_t rwlock;
    657 	isc_rwlock_t urlock;
    658 
    659 	/* Locked by rwlock. */
    660 	dns_zonelist_t zones;
    661 	dns_zonelist_t waiting_for_xfrin;
    662 	dns_zonelist_t xfrin_in_progress;
    663 
    664 	/* Configuration data. */
    665 	uint32_t transfersin;
    666 	uint32_t transfersperns;
    667 	unsigned int checkdsrate;
    668 	unsigned int notifyrate;
    669 	unsigned int startupnotifyrate;
    670 	unsigned int serialqueryrate;
    671 	unsigned int startupserialqueryrate;
    672 
    673 	/* Locked by urlock. */
    674 	/* LRU cache */
    675 	struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
    676 
    677 	dns_keymgmt_t *keymgmt;
    678 
    679 	isc_tlsctx_cache_t *tlsctx_cache;
    680 	isc_rwlock_t tlsctx_cache_rwlock;
    681 };
    682 
    683 /*%
    684  * Hold notify state.
    685  */
    686 struct dns_notify {
    687 	unsigned int magic;
    688 	unsigned int flags;
    689 	isc_mem_t *mctx;
    690 	dns_zone_t *zone;
    691 	dns_adbfind_t *find;
    692 	dns_request_t *request;
    693 	dns_name_t ns;
    694 	isc_sockaddr_t src;
    695 	isc_sockaddr_t dst;
    696 	dns_tsigkey_t *key;
    697 	dns_transport_t *transport;
    698 	ISC_LINK(dns_notify_t) link;
    699 	isc_rlevent_t *rlevent;
    700 };
    701 
    702 typedef enum dns_notify_flags {
    703 	DNS_NOTIFY_NOSOA = 1 << 0,
    704 	DNS_NOTIFY_STARTUP = 1 << 1,
    705 	DNS_NOTIFY_TCP = 1 << 2,
    706 } dns_notify_flags_t;
    707 
    708 /*%
    709  * Hold checkds state.
    710  */
    711 struct dns_checkds {
    712 	unsigned int magic;
    713 	dns_notify_flags_t flags;
    714 	isc_mem_t *mctx;
    715 	dns_zone_t *zone;
    716 	dns_adbfind_t *find;
    717 	dns_request_t *request;
    718 	dns_name_t ns;
    719 	isc_sockaddr_t src;
    720 	isc_sockaddr_t dst;
    721 	dns_tsigkey_t *key;
    722 	dns_transport_t *transport;
    723 	ISC_LINK(dns_checkds_t) link;
    724 	isc_rlevent_t *rlevent;
    725 };
    726 
    727 /*%
    728  *	dns_stub holds state while performing a 'stub' transfer.
    729  *	'db' is the zone's 'db' or a new one if this is the initial
    730  *	transfer.
    731  */
    732 
    733 struct dns_stub {
    734 	unsigned int magic;
    735 	isc_mem_t *mctx;
    736 	dns_zone_t *zone;
    737 	dns_db_t *db;
    738 	dns_dbversion_t *version;
    739 	atomic_uint_fast32_t pending_requests;
    740 };
    741 
    742 /*%
    743  *	Hold load state.
    744  */
    745 struct dns_load {
    746 	dns_zone_t *zone;
    747 	dns_db_t *db;
    748 	isc_time_t loadtime;
    749 	dns_rdatacallbacks_t callbacks;
    750 };
    751 
    752 /*%
    753  *	Hold forward state.
    754  */
    755 struct dns_forward {
    756 	unsigned int magic;
    757 	isc_mem_t *mctx;
    758 	dns_zone_t *zone;
    759 	isc_buffer_t *msgbuf;
    760 	dns_request_t *request;
    761 	uint32_t which;
    762 	isc_sockaddr_t addr;
    763 	dns_transport_t *transport;
    764 	dns_updatecallback_t callback;
    765 	void *callback_arg;
    766 	unsigned int options;
    767 	ISC_LINK(dns_forward_t) link;
    768 };
    769 
    770 /*%
    771  *	Hold state for when we are signing a zone with a new
    772  *	DNSKEY as result of an update.
    773  */
    774 struct dns_signing {
    775 	unsigned int magic;
    776 	dns_db_t *db;
    777 	dns_dbiterator_t *dbiterator;
    778 	dns_secalg_t algorithm;
    779 	uint16_t keyid;
    780 	bool deleteit;
    781 	bool fullsign;
    782 	bool done;
    783 	ISC_LINK(dns_signing_t) link;
    784 };
    785 
    786 struct dns_nsec3chain {
    787 	unsigned int magic;
    788 	dns_db_t *db;
    789 	dns_dbiterator_t *dbiterator;
    790 	dns_rdata_nsec3param_t nsec3param;
    791 	unsigned char salt[255];
    792 	bool done;
    793 	bool seen_nsec;
    794 	bool delete_nsec;
    795 	bool save_delete_nsec;
    796 	ISC_LINK(dns_nsec3chain_t) link;
    797 };
    798 
    799 /*%<
    800  * 'dbiterator' contains a iterator for the database.  If we are creating
    801  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
    802  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
    803  * iterated.
    804  *
    805  * 'nsec3param' contains the parameters of the NSEC3 chain being created
    806  * or removed.
    807  *
    808  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
    809  *
    810  * 'seen_nsec' will be set to true if, while iterating the zone to create a
    811  * NSEC3 chain, a NSEC record is seen.
    812  *
    813  * 'delete_nsec' will be set to true if, at the completion of the creation
    814  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
    815  * are in the process of deleting the NSEC chain.
    816  *
    817  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
    818  * so it can be recovered in the event of a error.
    819  */
    820 
    821 struct dns_keyfetch {
    822 	isc_mem_t *mctx;
    823 	dns_fixedname_t name;
    824 	dns_rdataset_t keydataset;
    825 	dns_rdataset_t dnskeyset;
    826 	dns_rdataset_t dnskeysigset;
    827 	dns_zone_t *zone;
    828 	dns_db_t *db;
    829 	dns_fetch_t *fetch;
    830 };
    831 
    832 struct dns_nsfetch {
    833 	isc_mem_t *mctx;
    834 	dns_fixedname_t name;
    835 	dns_name_t pname;
    836 	dns_rdataset_t nsrrset;
    837 	dns_rdataset_t nssigset;
    838 	dns_zone_t *zone;
    839 	dns_fetch_t *fetch;
    840 };
    841 
    842 /*%
    843  * Hold state for an asynchronous load
    844  */
    845 struct dns_asyncload {
    846 	dns_zone_t *zone;
    847 	unsigned int flags;
    848 	dns_zt_callback_t *loaded;
    849 	void *loaded_arg;
    850 };
    851 
    852 /*%
    853  * Reference to an include file encountered during loading
    854  */
    855 struct dns_include {
    856 	char *name;
    857 	isc_time_t filetime;
    858 	ISC_LINK(dns_include_t) link;
    859 };
    860 
    861 /*
    862  * These can be overridden by the -T mkeytimers option on the command
    863  * line, so that we can test with shorter periods than specified in
    864  * RFC 5011.
    865  */
    866 #define HOUR  3600
    867 #define DAY   (24 * HOUR)
    868 #define MONTH (30 * DAY)
    869 unsigned int dns_zone_mkey_hour = HOUR;
    870 unsigned int dns_zone_mkey_day = DAY;
    871 unsigned int dns_zone_mkey_month = MONTH;
    872 
    873 #define SEND_BUFFER_SIZE 2048
    874 
    875 static void
    876 zone_timer_set(dns_zone_t *zone, isc_time_t *next, isc_time_t *now);
    877 
    878 typedef struct zone_settimer {
    879 	dns_zone_t *zone;
    880 	isc_time_t now;
    881 } zone_settimer_t;
    882 
    883 static void
    884 zone_settimer(dns_zone_t *, isc_time_t *);
    885 static void
    886 cancel_refresh(dns_zone_t *);
    887 static void
    888 zone_debuglogc(dns_zone_t *zone, isc_logcategory_t *category, const char *me,
    889 	       int debuglevel, const char *fmt, ...);
    890 static void
    891 zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg,
    892 	      ...) ISC_FORMAT_PRINTF(4, 5);
    893 static void
    894 notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
    895 	ISC_FORMAT_PRINTF(3, 4);
    896 static void
    897 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
    898 	ISC_FORMAT_PRINTF(3, 4);
    899 static void
    900 queue_xfrin(dns_zone_t *zone);
    901 static isc_result_t
    902 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
    903 	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
    904 	      dns_rdata_t *rdata);
    905 static void
    906 zone_unload(dns_zone_t *zone);
    907 static void
    908 zone_expire(dns_zone_t *zone);
    909 static void
    910 zone_refresh(dns_zone_t *zone);
    911 static void
    912 zone_iattach(dns_zone_t *source, dns_zone_t **target);
    913 static void
    914 zone_idetach(dns_zone_t **zonep);
    915 static isc_result_t
    916 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump);
    917 static void
    918 zone_attachdb(dns_zone_t *zone, dns_db_t *db);
    919 static void
    920 zone_detachdb(dns_zone_t *zone);
    921 static void
    922 zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs);
    923 static void
    924 zone_catz_disable(dns_zone_t *zone);
    925 static isc_result_t
    926 default_journal(dns_zone_t *zone);
    927 static void
    928 zone_xfrdone(dns_zone_t *zone, uint32_t *expireopt, isc_result_t result);
    929 static isc_result_t
    930 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
    931 	      isc_result_t result);
    932 static void
    933 zone_needdump(dns_zone_t *zone, unsigned int delay);
    934 static void
    935 zone_shutdown(void *arg);
    936 static void
    937 zone_loaddone(void *arg, isc_result_t result);
    938 static isc_result_t
    939 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime);
    940 static void
    941 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
    942 static void
    943 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
    944 static void
    945 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
    946 static void
    947 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
    948 static isc_result_t
    949 zone_send_secureserial(dns_zone_t *zone, uint32_t serial);
    950 static void
    951 refresh_callback(void *arg);
    952 static void
    953 stub_callback(void *arg);
    954 static void
    955 queue_soa_query(dns_zone_t *zone);
    956 static void
    957 soa_query(void *arg);
    958 static void
    959 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub);
    960 static int
    961 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type);
    962 static void
    963 checkds_cancel(dns_zone_t *zone);
    964 static void
    965 checkds_find_address(dns_checkds_t *checkds);
    966 static void
    967 checkds_send(dns_zone_t *zone);
    968 static void
    969 checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep);
    970 static void
    971 checkds_done(void *arg);
    972 static void
    973 checkds_send_tons(dns_checkds_t *checkds);
    974 static void
    975 checkds_send_toaddr(void *arg);
    976 static void
    977 nsfetch_levelup(dns_nsfetch_t *nsfetch);
    978 static void
    979 notify_cancel(dns_zone_t *zone);
    980 static void
    981 notify_find_address(dns_notify_t *notify);
    982 static void
    983 notify_send(dns_notify_t *notify);
    984 static isc_result_t
    985 notify_createmessage(dns_zone_t *zone, unsigned int flags,
    986 		     dns_message_t **messagep);
    987 static void
    988 notify_done(void *arg);
    989 static void
    990 notify_send_toaddr(void *arg);
    991 static isc_result_t
    992 zone_dump(dns_zone_t *, bool);
    993 static void
    994 got_transfer_quota(void *arg);
    995 static isc_result_t
    996 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone);
    997 static void
    998 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
    999 static void
   1000 zonemgr_free(dns_zonemgr_t *zmgr);
   1001 static void
   1002 rss_post(void *arg);
   1003 
   1004 static isc_result_t
   1005 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
   1006 		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
   1007 		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
   1008 		 uint32_t *minimum, unsigned int *errors);
   1009 
   1010 static void
   1011 zone_freedbargs(dns_zone_t *zone);
   1012 static void
   1013 forward_callback(void *arg);
   1014 static void
   1015 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat);
   1016 static void
   1017 zone_maintenance(dns_zone_t *zone);
   1018 static void
   1019 zone_notify(dns_zone_t *zone, isc_time_t *now);
   1020 static void
   1021 dump_done(void *arg, isc_result_t result);
   1022 static isc_result_t
   1023 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
   1024 		 bool deleteit, bool fullsign);
   1025 static isc_result_t
   1026 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
   1027 	    dns_name_t *name, dns_diff_t *diff);
   1028 static void
   1029 zone_rekey(dns_zone_t *zone);
   1030 static isc_result_t
   1031 zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
   1032 static dns_ttl_t
   1033 zone_nsecttl(dns_zone_t *zone);
   1034 static void
   1035 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value);
   1036 static void
   1037 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial);
   1038 static isc_result_t
   1039 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
   1040 			 bool *fixjournal);
   1041 static void
   1042 setnsec3param(void *arg);
   1043 
   1044 static void
   1045 zmgr_tlsctx_attach(dns_zonemgr_t *zmgr, isc_tlsctx_cache_t **ptlsctx_cache);
   1046 /*%<
   1047  *	Attach to TLS client context cache used for zone transfers via
   1048  *	encrypted transports (e.g. XoT).
   1049  *
   1050  * The obtained reference needs to be detached by a call to
   1051  * 'isc_tlsctx_cache_detach()' when not needed anymore.
   1052  *
   1053  * Requires:
   1054  *\li	'zmgr' is a valid zone manager.
   1055  *\li	'ptlsctx_cache' is not 'NULL' and points to 'NULL'.
   1056  */
   1057 
   1058 #define ENTER zone_debuglog(zone, __func__, 1, "enter")
   1059 
   1060 static const unsigned int dbargc_default = 1;
   1061 static const char *dbargv_default[] = { ZONEDB_DEFAULT };
   1062 
   1063 #define DNS_ZONE_JITTER_ADD(a, b, c)                                         \
   1064 	do {                                                                 \
   1065 		isc_interval_t _i;                                           \
   1066 		uint32_t _j;                                                 \
   1067 		_j = (b) - isc_random_uniform((b) / 4);                      \
   1068 		isc_interval_set(&_i, _j, 0);                                \
   1069 		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) {          \
   1070 			dns_zone_log(zone, ISC_LOG_WARNING,                  \
   1071 				     "epoch approaching: upgrade required: " \
   1072 				     "now + %s failed",                      \
   1073 				     #b);                                    \
   1074 			isc_interval_set(&_i, _j / 2, 0);                    \
   1075 			(void)isc_time_add((a), &_i, (c));                   \
   1076 		}                                                            \
   1077 	} while (0)
   1078 
   1079 #define DNS_ZONE_TIME_ADD(a, b, c)                                           \
   1080 	do {                                                                 \
   1081 		isc_interval_t _i;                                           \
   1082 		isc_interval_set(&_i, (b), 0);                               \
   1083 		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) {          \
   1084 			dns_zone_log(zone, ISC_LOG_WARNING,                  \
   1085 				     "epoch approaching: upgrade required: " \
   1086 				     "now + %s failed",                      \
   1087 				     #b);                                    \
   1088 			isc_interval_set(&_i, (b) / 2, 0);                   \
   1089 			(void)isc_time_add((a), &_i, (c));                   \
   1090 		}                                                            \
   1091 	} while (0)
   1092 
   1093 #define DNS_ZONE_TIME_SUBTRACT(a, b, c)                                      \
   1094 	do {                                                                 \
   1095 		isc_interval_t _i;                                           \
   1096 		isc_interval_set(&_i, (b), 0);                               \
   1097 		if (isc_time_subtract((a), &_i, (c)) != ISC_R_SUCCESS) {     \
   1098 			dns_zone_log(zone, ISC_LOG_WARNING,                  \
   1099 				     "epoch approaching: upgrade required: " \
   1100 				     "isc_time_subtract() failed");          \
   1101 			isc_interval_set(&_i, (b) / 2, 0);                   \
   1102 			(void)isc_time_subtract((a), &_i, (c));              \
   1103 		}                                                            \
   1104 	} while (0)
   1105 
   1106 typedef struct nsec3param nsec3param_t;
   1107 struct nsec3param {
   1108 	dns_rdata_nsec3param_t rdata;
   1109 	unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
   1110 	unsigned int length;
   1111 	bool nsec;
   1112 	bool replace;
   1113 	bool resalt;
   1114 	bool lookup;
   1115 	ISC_LINK(nsec3param_t) link;
   1116 };
   1117 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
   1118 
   1119 struct np3 {
   1120 	dns_zone_t *zone;
   1121 	nsec3param_t params;
   1122 	ISC_LINK(struct np3) link;
   1123 };
   1124 
   1125 struct setserial {
   1126 	dns_zone_t *zone;
   1127 	uint32_t serial;
   1128 };
   1129 
   1130 struct stub_cb_args {
   1131 	dns_stub_t *stub;
   1132 	dns_tsigkey_t *tsig_key;
   1133 	uint16_t udpsize;
   1134 	int timeout;
   1135 	bool reqnsid;
   1136 };
   1137 
   1138 struct stub_glue_request {
   1139 	dns_request_t *request;
   1140 	dns_name_t name;
   1141 	struct stub_cb_args *args;
   1142 	bool ipv4;
   1143 };
   1144 
   1145 /*%
   1146  * Increment resolver-related statistics counters.  Zone must be locked.
   1147  */
   1148 static void
   1149 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
   1150 	if (zone->stats != NULL) {
   1151 		isc_stats_increment(zone->stats, counter);
   1152 	}
   1153 }
   1154 
   1155 /***
   1156  ***	Public functions.
   1157  ***/
   1158 
   1159 void
   1160 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx, unsigned int tid) {
   1161 	isc_time_t now;
   1162 	dns_zone_t *zone = NULL;
   1163 
   1164 	REQUIRE(zonep != NULL && *zonep == NULL);
   1165 	REQUIRE(mctx != NULL);
   1166 
   1167 	now = isc_time_now();
   1168 	zone = isc_mem_get(mctx, sizeof(*zone));
   1169 	*zone = (dns_zone_t){
   1170 		.masterformat = dns_masterformat_none,
   1171 		.journalsize = -1,
   1172 		.rdclass = dns_rdataclass_none,
   1173 		.type = dns_zone_none,
   1174 		.refresh = DNS_ZONE_DEFAULTREFRESH,
   1175 		.retry = DNS_ZONE_DEFAULTRETRY,
   1176 		.maxrefresh = DNS_ZONE_MAXREFRESH,
   1177 		.minrefresh = DNS_ZONE_MINREFRESH,
   1178 		.maxretry = DNS_ZONE_MAXRETRY,
   1179 		.minretry = DNS_ZONE_MINRETRY,
   1180 		.checkdstype = dns_checkdstype_yes,
   1181 		.notifytype = dns_notifytype_yes,
   1182 		.zero_no_soa_ttl = true,
   1183 		.check_names = dns_severity_ignore,
   1184 		.idlein = DNS_DEFAULT_IDLEIN,
   1185 		.idleout = DNS_DEFAULT_IDLEOUT,
   1186 		.maxxfrin = MAX_XFER_TIME,
   1187 		.maxxfrout = MAX_XFER_TIME,
   1188 		.sigvalidityinterval = 30 * 24 * 3600,
   1189 		.sigresigninginterval = 7 * 24 * 3600,
   1190 		.statlevel = dns_zonestat_none,
   1191 		.notifydelay = 5,
   1192 		.signatures = 10,
   1193 		.nodes = 100,
   1194 		.privatetype = (dns_rdatatype_t)0xffffU,
   1195 		.rpz_num = DNS_RPZ_INVALID_NUM,
   1196 		.requestixfr = true,
   1197 		.ixfr_ratio = 100,
   1198 		.requestexpire = true,
   1199 		.updatemethod = dns_updatemethod_increment,
   1200 		.tid = tid,
   1201 		.notifytime = now,
   1202 		.newincludes = ISC_LIST_INITIALIZER,
   1203 		.notifies = ISC_LIST_INITIALIZER,
   1204 		.checkds_requests = ISC_LIST_INITIALIZER,
   1205 		.signing = ISC_LIST_INITIALIZER,
   1206 		.nsec3chain = ISC_LIST_INITIALIZER,
   1207 		.setnsec3param_queue = ISC_LIST_INITIALIZER,
   1208 		.forwards = ISC_LIST_INITIALIZER,
   1209 		.link = ISC_LINK_INITIALIZER,
   1210 		.statelink = ISC_LINK_INITIALIZER,
   1211 	};
   1212 	dns_remote_t r = {
   1213 		.magic = DNS_REMOTE_MAGIC,
   1214 	};
   1215 
   1216 	isc_mem_attach(mctx, &zone->mctx);
   1217 	isc_mutex_init(&zone->lock);
   1218 #ifndef _LP64
   1219 	isc_mutex_init(&zone->atomic_lock);
   1220 #endif
   1221 	ZONEDB_INITLOCK(&zone->dblock);
   1222 
   1223 	isc_refcount_init(&zone->references, 1);
   1224 	isc_refcount_init(&zone->irefs, 0);
   1225 	dns_name_init(&zone->origin, NULL);
   1226 	isc_sockaddr_any(&zone->notifysrc4);
   1227 	isc_sockaddr_any6(&zone->notifysrc6);
   1228 	isc_sockaddr_any(&zone->parentalsrc4);
   1229 	isc_sockaddr_any6(&zone->parentalsrc6);
   1230 	isc_sockaddr_any(&zone->xfrsource4);
   1231 	isc_sockaddr_any6(&zone->xfrsource6);
   1232 
   1233 	zone->primaries = r;
   1234 	zone->parentals = r;
   1235 	zone->notify = r;
   1236 	zone->defaultkasp = NULL;
   1237 	ISC_LIST_INIT(zone->keyring);
   1238 
   1239 	isc_stats_create(mctx, &zone->gluecachestats,
   1240 			 dns_gluecachestatscounter_max);
   1241 
   1242 	zone->magic = ZONE_MAGIC;
   1243 
   1244 	/* Must be after magic is set. */
   1245 	dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
   1246 
   1247 	*zonep = zone;
   1248 }
   1249 
   1250 static void
   1251 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
   1252 	dns_dnsseckey_t *key;
   1253 	while (!ISC_LIST_EMPTY(*list)) {
   1254 		key = ISC_LIST_HEAD(*list);
   1255 		ISC_LIST_UNLINK(*list, key, link);
   1256 		dns_dnsseckey_destroy(mctx, &key);
   1257 	}
   1258 }
   1259 
   1260 /*
   1261  * Free a zone.  Because we require that there be no more
   1262  * outstanding events or references, no locking is necessary.
   1263  */
   1264 static void
   1265 zone_free(dns_zone_t *zone) {
   1266 	dns_signing_t *signing = NULL;
   1267 	dns_nsec3chain_t *nsec3chain = NULL;
   1268 	dns_include_t *include = NULL;
   1269 
   1270 	REQUIRE(DNS_ZONE_VALID(zone));
   1271 	REQUIRE(!LOCKED_ZONE(zone));
   1272 	REQUIRE(zone->timer == NULL);
   1273 	REQUIRE(zone->zmgr == NULL);
   1274 
   1275 	isc_refcount_destroy(&zone->references);
   1276 	isc_refcount_destroy(&zone->irefs);
   1277 
   1278 	/*
   1279 	 * Managed objects.  Order is important.
   1280 	 */
   1281 	if (zone->request != NULL) {
   1282 		dns_request_destroy(&zone->request); /* XXXMPA */
   1283 	}
   1284 	INSIST(zone->statelist == NULL);
   1285 	INSIST(zone->view == NULL);
   1286 	INSIST(zone->prev_view == NULL);
   1287 
   1288 	/* Unmanaged objects */
   1289 	for (struct np3 *npe = ISC_LIST_HEAD(zone->setnsec3param_queue);
   1290 	     npe != NULL; npe = ISC_LIST_HEAD(zone->setnsec3param_queue))
   1291 	{
   1292 		ISC_LIST_UNLINK(zone->setnsec3param_queue, npe, link);
   1293 		isc_mem_put(zone->mctx, npe, sizeof(*npe));
   1294 	}
   1295 
   1296 	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
   1297 	     signing = ISC_LIST_HEAD(zone->signing))
   1298 	{
   1299 		ISC_LIST_UNLINK(zone->signing, signing, link);
   1300 		dns_db_detach(&signing->db);
   1301 		dns_dbiterator_destroy(&signing->dbiterator);
   1302 		isc_mem_put(zone->mctx, signing, sizeof *signing);
   1303 	}
   1304 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
   1305 	     nsec3chain = ISC_LIST_HEAD(zone->nsec3chain))
   1306 	{
   1307 		ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
   1308 		dns_db_detach(&nsec3chain->db);
   1309 		dns_dbiterator_destroy(&nsec3chain->dbiterator);
   1310 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   1311 	}
   1312 	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
   1313 	     include = ISC_LIST_HEAD(zone->includes))
   1314 	{
   1315 		ISC_LIST_UNLINK(zone->includes, include, link);
   1316 		isc_mem_free(zone->mctx, include->name);
   1317 		isc_mem_put(zone->mctx, include, sizeof *include);
   1318 	}
   1319 	for (include = ISC_LIST_HEAD(zone->newincludes); include != NULL;
   1320 	     include = ISC_LIST_HEAD(zone->newincludes))
   1321 	{
   1322 		ISC_LIST_UNLINK(zone->newincludes, include, link);
   1323 		isc_mem_free(zone->mctx, include->name);
   1324 		isc_mem_put(zone->mctx, include, sizeof *include);
   1325 	}
   1326 	if (zone->masterfile != NULL) {
   1327 		isc_mem_free(zone->mctx, zone->masterfile);
   1328 	}
   1329 	zone->masterfile = NULL;
   1330 	if (zone->keydirectory != NULL) {
   1331 		isc_mem_free(zone->mctx, zone->keydirectory);
   1332 	}
   1333 	zone->keydirectory = NULL;
   1334 	if (zone->kasp != NULL) {
   1335 		dns_kasp_detach(&zone->kasp);
   1336 	}
   1337 	if (zone->defaultkasp != NULL) {
   1338 		dns_kasp_detach(&zone->defaultkasp);
   1339 	}
   1340 	if (!ISC_LIST_EMPTY(zone->keyring)) {
   1341 		clear_keylist(&zone->keyring, zone->mctx);
   1342 	}
   1343 	if (!ISC_LIST_EMPTY(zone->checkds_ok)) {
   1344 		clear_keylist(&zone->checkds_ok, zone->mctx);
   1345 	}
   1346 	if (zone->skr != NULL) {
   1347 		zone->skrbundle = NULL;
   1348 		dns_skr_detach(&zone->skr);
   1349 	}
   1350 
   1351 	zone->journalsize = -1;
   1352 	if (zone->journal != NULL) {
   1353 		isc_mem_free(zone->mctx, zone->journal);
   1354 	}
   1355 	zone->journal = NULL;
   1356 	if (zone->stats != NULL) {
   1357 		isc_stats_detach(&zone->stats);
   1358 	}
   1359 	if (zone->requeststats != NULL) {
   1360 		isc_stats_detach(&zone->requeststats);
   1361 	}
   1362 	if (zone->rcvquerystats != NULL) {
   1363 		dns_stats_detach(&zone->rcvquerystats);
   1364 	}
   1365 	if (zone->dnssecsignstats != NULL) {
   1366 		dns_stats_detach(&zone->dnssecsignstats);
   1367 	}
   1368 	if (zone->db != NULL) {
   1369 		zone_detachdb(zone);
   1370 	}
   1371 	if (zone->rpzs != NULL) {
   1372 		REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
   1373 		dns_rpz_zones_detach(&zone->rpzs);
   1374 		zone->rpz_num = DNS_RPZ_INVALID_NUM;
   1375 	}
   1376 	if (zone->catzs != NULL) {
   1377 		dns_catz_zones_detach(&zone->catzs);
   1378 	}
   1379 	zone_freedbargs(zone);
   1380 
   1381 	dns_zone_setparentals(zone, NULL, NULL, NULL, NULL, 0);
   1382 	dns_zone_setprimaries(zone, NULL, NULL, NULL, NULL, 0);
   1383 	dns_zone_setalsonotify(zone, NULL, NULL, NULL, NULL, 0);
   1384 
   1385 	zone->check_names = dns_severity_ignore;
   1386 	if (zone->update_acl != NULL) {
   1387 		dns_acl_detach(&zone->update_acl);
   1388 	}
   1389 	if (zone->forward_acl != NULL) {
   1390 		dns_acl_detach(&zone->forward_acl);
   1391 	}
   1392 	if (zone->notify_acl != NULL) {
   1393 		dns_acl_detach(&zone->notify_acl);
   1394 	}
   1395 	if (zone->query_acl != NULL) {
   1396 		dns_acl_detach(&zone->query_acl);
   1397 	}
   1398 	if (zone->queryon_acl != NULL) {
   1399 		dns_acl_detach(&zone->queryon_acl);
   1400 	}
   1401 	if (zone->xfr_acl != NULL) {
   1402 		dns_acl_detach(&zone->xfr_acl);
   1403 	}
   1404 	if (dns_name_dynamic(&zone->origin)) {
   1405 		dns_name_free(&zone->origin, zone->mctx);
   1406 	}
   1407 	if (zone->strnamerd != NULL) {
   1408 		isc_mem_free(zone->mctx, zone->strnamerd);
   1409 	}
   1410 	if (zone->strname != NULL) {
   1411 		isc_mem_free(zone->mctx, zone->strname);
   1412 	}
   1413 	if (zone->strrdclass != NULL) {
   1414 		isc_mem_free(zone->mctx, zone->strrdclass);
   1415 	}
   1416 	if (zone->strviewname != NULL) {
   1417 		isc_mem_free(zone->mctx, zone->strviewname);
   1418 	}
   1419 	if (zone->ssutable != NULL) {
   1420 		dns_ssutable_detach(&zone->ssutable);
   1421 	}
   1422 	if (zone->gluecachestats != NULL) {
   1423 		isc_stats_detach(&zone->gluecachestats);
   1424 	}
   1425 
   1426 	/* last stuff */
   1427 	ZONEDB_DESTROYLOCK(&zone->dblock);
   1428 	isc_mutex_destroy(&zone->lock);
   1429 #ifndef _LP64
   1430 	isc_mutex_destroy(&zone->atomic_lock);
   1431 #endif
   1432 	zone->magic = 0;
   1433 	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
   1434 }
   1435 
   1436 /*
   1437  * Returns true iff this the signed side of an inline-signing zone.
   1438  * Caller should hold zone lock.
   1439  */
   1440 static bool
   1441 inline_secure(dns_zone_t *zone) {
   1442 	REQUIRE(DNS_ZONE_VALID(zone));
   1443 	if (zone->raw != NULL) {
   1444 		return true;
   1445 	}
   1446 	return false;
   1447 }
   1448 
   1449 /*
   1450  * Returns true iff this the unsigned side of an inline-signing zone
   1451  * Caller should hold zone lock.
   1452  */
   1453 static bool
   1454 inline_raw(dns_zone_t *zone) {
   1455 	REQUIRE(DNS_ZONE_VALID(zone));
   1456 	if (zone->secure != NULL) {
   1457 		return true;
   1458 	}
   1459 	return false;
   1460 }
   1461 
   1462 /*
   1463  *	Single shot.
   1464  */
   1465 void
   1466 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
   1467 	char namebuf[1024];
   1468 
   1469 	REQUIRE(DNS_ZONE_VALID(zone));
   1470 	REQUIRE(rdclass != dns_rdataclass_none);
   1471 
   1472 	/*
   1473 	 * Test and set.
   1474 	 */
   1475 	LOCK_ZONE(zone);
   1476 	INSIST(zone != zone->raw);
   1477 	REQUIRE(zone->rdclass == dns_rdataclass_none ||
   1478 		zone->rdclass == rdclass);
   1479 	zone->rdclass = rdclass;
   1480 
   1481 	if (zone->strnamerd != NULL) {
   1482 		isc_mem_free(zone->mctx, zone->strnamerd);
   1483 	}
   1484 	if (zone->strrdclass != NULL) {
   1485 		isc_mem_free(zone->mctx, zone->strrdclass);
   1486 	}
   1487 
   1488 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1489 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1490 	zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
   1491 	zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
   1492 
   1493 	if (inline_secure(zone)) {
   1494 		dns_zone_setclass(zone->raw, rdclass);
   1495 	}
   1496 	UNLOCK_ZONE(zone);
   1497 }
   1498 
   1499 dns_rdataclass_t
   1500 dns_zone_getclass(dns_zone_t *zone) {
   1501 	REQUIRE(DNS_ZONE_VALID(zone));
   1502 
   1503 	return zone->rdclass;
   1504 }
   1505 
   1506 void
   1507 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
   1508 	REQUIRE(DNS_ZONE_VALID(zone));
   1509 
   1510 	LOCK_ZONE(zone);
   1511 	zone->notifytype = notifytype;
   1512 	UNLOCK_ZONE(zone);
   1513 }
   1514 
   1515 void
   1516 dns_zone_setcheckdstype(dns_zone_t *zone, dns_checkdstype_t checkdstype) {
   1517 	REQUIRE(DNS_ZONE_VALID(zone));
   1518 
   1519 	LOCK_ZONE(zone);
   1520 	zone->checkdstype = checkdstype;
   1521 	UNLOCK_ZONE(zone);
   1522 }
   1523 
   1524 isc_result_t
   1525 dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
   1526 	isc_result_t result;
   1527 	unsigned int soacount;
   1528 
   1529 	REQUIRE(DNS_ZONE_VALID(zone));
   1530 	REQUIRE(serialp != NULL);
   1531 
   1532 	LOCK_ZONE(zone);
   1533 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   1534 	if (zone->db != NULL) {
   1535 		result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
   1536 					  serialp, NULL, NULL, NULL, NULL,
   1537 					  NULL);
   1538 		if (result == ISC_R_SUCCESS && soacount == 0) {
   1539 			result = ISC_R_FAILURE;
   1540 		}
   1541 	} else {
   1542 		result = DNS_R_NOTLOADED;
   1543 	}
   1544 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   1545 	UNLOCK_ZONE(zone);
   1546 
   1547 	return result;
   1548 }
   1549 
   1550 /*
   1551  *	Single shot.
   1552  */
   1553 void
   1554 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
   1555 	char namebuf[1024];
   1556 
   1557 	REQUIRE(DNS_ZONE_VALID(zone));
   1558 	REQUIRE(type != dns_zone_none);
   1559 
   1560 	/*
   1561 	 * Test and set.
   1562 	 */
   1563 	LOCK_ZONE(zone);
   1564 	REQUIRE(zone->type == dns_zone_none || zone->type == type);
   1565 	zone->type = type;
   1566 
   1567 	if (zone->strnamerd != NULL) {
   1568 		isc_mem_free(zone->mctx, zone->strnamerd);
   1569 	}
   1570 
   1571 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1572 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1573 	UNLOCK_ZONE(zone);
   1574 }
   1575 
   1576 static void
   1577 zone_freedbargs(dns_zone_t *zone) {
   1578 	unsigned int i;
   1579 
   1580 	/* Free the old database argument list. */
   1581 	if (zone->db_argv != NULL) {
   1582 		for (i = 0; i < zone->db_argc; i++) {
   1583 			isc_mem_free(zone->mctx, zone->db_argv[i]);
   1584 		}
   1585 		isc_mem_cput(zone->mctx, zone->db_argv, zone->db_argc,
   1586 			     sizeof(*zone->db_argv));
   1587 	}
   1588 	zone->db_argc = 0;
   1589 	zone->db_argv = NULL;
   1590 }
   1591 
   1592 isc_result_t
   1593 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
   1594 	size_t size = 0;
   1595 	unsigned int i;
   1596 	isc_result_t result = ISC_R_SUCCESS;
   1597 	void *mem;
   1598 	char **tmp, *tmp2, *base;
   1599 
   1600 	REQUIRE(DNS_ZONE_VALID(zone));
   1601 	REQUIRE(argv != NULL && *argv == NULL);
   1602 
   1603 	LOCK_ZONE(zone);
   1604 	size = ISC_CHECKED_MUL(zone->db_argc + 1, sizeof(char *));
   1605 	for (i = 0; i < zone->db_argc; i++) {
   1606 		size += strlen(zone->db_argv[i]) + 1;
   1607 	}
   1608 	mem = isc_mem_allocate(mctx, size);
   1609 	{
   1610 		tmp = mem;
   1611 		tmp2 = mem;
   1612 		base = mem;
   1613 		tmp2 += ISC_CHECKED_MUL(zone->db_argc + 1, sizeof(char *));
   1614 		for (i = 0; i < zone->db_argc; i++) {
   1615 			*tmp++ = tmp2;
   1616 			strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
   1617 			tmp2 += strlen(tmp2) + 1;
   1618 		}
   1619 		*tmp = NULL;
   1620 	}
   1621 	UNLOCK_ZONE(zone);
   1622 	*argv = mem;
   1623 	return result;
   1624 }
   1625 
   1626 void
   1627 dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc,
   1628 		   const char *const *dbargv) {
   1629 	char **argv = NULL;
   1630 	unsigned int i;
   1631 
   1632 	REQUIRE(DNS_ZONE_VALID(zone));
   1633 	REQUIRE(dbargc >= 1);
   1634 	REQUIRE(dbargv != NULL);
   1635 
   1636 	LOCK_ZONE(zone);
   1637 
   1638 	/* Set up a new database argument list. */
   1639 	argv = isc_mem_cget(zone->mctx, dbargc, sizeof(*argv));
   1640 	for (i = 0; i < dbargc; i++) {
   1641 		argv[i] = NULL;
   1642 	}
   1643 	for (i = 0; i < dbargc; i++) {
   1644 		argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
   1645 	}
   1646 
   1647 	/* Free the old list. */
   1648 	zone_freedbargs(zone);
   1649 
   1650 	zone->db_argc = dbargc;
   1651 	zone->db_argv = argv;
   1652 
   1653 	UNLOCK_ZONE(zone);
   1654 }
   1655 
   1656 static void
   1657 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
   1658 	char namebuf[1024];
   1659 
   1660 	if (zone->prev_view == NULL && zone->view != NULL) {
   1661 		dns_view_weakattach(zone->view, &zone->prev_view);
   1662 	}
   1663 
   1664 	INSIST(zone != zone->raw);
   1665 	if (zone->view != NULL) {
   1666 		dns_view_sfd_del(zone->view, &zone->origin);
   1667 		dns_view_weakdetach(&zone->view);
   1668 	}
   1669 	dns_view_weakattach(view, &zone->view);
   1670 	dns_view_sfd_add(view, &zone->origin);
   1671 
   1672 	if (zone->strviewname != NULL) {
   1673 		isc_mem_free(zone->mctx, zone->strviewname);
   1674 	}
   1675 	if (zone->strnamerd != NULL) {
   1676 		isc_mem_free(zone->mctx, zone->strnamerd);
   1677 	}
   1678 
   1679 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1680 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1681 	zone_viewname_tostr(zone, namebuf, sizeof namebuf);
   1682 	zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
   1683 
   1684 	if (inline_secure(zone)) {
   1685 		dns_zone_setview(zone->raw, view);
   1686 	}
   1687 }
   1688 
   1689 void
   1690 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
   1691 	REQUIRE(DNS_ZONE_VALID(zone));
   1692 
   1693 	LOCK_ZONE(zone);
   1694 	dns_zone_setview_helper(zone, view);
   1695 	UNLOCK_ZONE(zone);
   1696 }
   1697 
   1698 dns_view_t *
   1699 dns_zone_getview(dns_zone_t *zone) {
   1700 	REQUIRE(DNS_ZONE_VALID(zone));
   1701 
   1702 	return zone->view;
   1703 }
   1704 
   1705 void
   1706 dns_zone_setviewcommit(dns_zone_t *zone) {
   1707 	REQUIRE(DNS_ZONE_VALID(zone));
   1708 
   1709 	LOCK_ZONE(zone);
   1710 	if (zone->prev_view != NULL) {
   1711 		dns_view_weakdetach(&zone->prev_view);
   1712 	}
   1713 	if (inline_secure(zone)) {
   1714 		dns_zone_setviewcommit(zone->raw);
   1715 	}
   1716 	UNLOCK_ZONE(zone);
   1717 }
   1718 
   1719 void
   1720 dns_zone_setviewrevert(dns_zone_t *zone) {
   1721 	REQUIRE(DNS_ZONE_VALID(zone));
   1722 
   1723 	LOCK_ZONE(zone);
   1724 	if (zone->prev_view != NULL) {
   1725 		dns_zone_setview_helper(zone, zone->prev_view);
   1726 		dns_view_weakdetach(&zone->prev_view);
   1727 	}
   1728 	if (zone->catzs != NULL) {
   1729 		zone_catz_enable(zone, zone->catzs);
   1730 	}
   1731 	if (inline_secure(zone)) {
   1732 		dns_zone_setviewrevert(zone->raw);
   1733 	}
   1734 	UNLOCK_ZONE(zone);
   1735 }
   1736 
   1737 isc_result_t
   1738 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
   1739 	isc_result_t result = ISC_R_SUCCESS;
   1740 	char namebuf[1024];
   1741 
   1742 	REQUIRE(DNS_ZONE_VALID(zone));
   1743 	REQUIRE(origin != NULL);
   1744 
   1745 	LOCK_ZONE(zone);
   1746 	INSIST(zone != zone->raw);
   1747 	if (dns_name_dynamic(&zone->origin)) {
   1748 		dns_name_free(&zone->origin, zone->mctx);
   1749 		dns_name_init(&zone->origin, NULL);
   1750 	}
   1751 	dns_name_dup(origin, zone->mctx, &zone->origin);
   1752 
   1753 	if (zone->strnamerd != NULL) {
   1754 		isc_mem_free(zone->mctx, zone->strnamerd);
   1755 	}
   1756 	if (zone->strname != NULL) {
   1757 		isc_mem_free(zone->mctx, zone->strname);
   1758 	}
   1759 
   1760 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1761 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1762 	zone_name_tostr(zone, namebuf, sizeof namebuf);
   1763 	zone->strname = isc_mem_strdup(zone->mctx, namebuf);
   1764 
   1765 	if (inline_secure(zone)) {
   1766 		result = dns_zone_setorigin(zone->raw, origin);
   1767 	}
   1768 	UNLOCK_ZONE(zone);
   1769 	return result;
   1770 }
   1771 
   1772 static isc_result_t
   1773 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
   1774 	char *copy;
   1775 
   1776 	if (value != NULL) {
   1777 		copy = isc_mem_strdup(zone->mctx, value);
   1778 	} else {
   1779 		copy = NULL;
   1780 	}
   1781 
   1782 	if (*field != NULL) {
   1783 		isc_mem_free(zone->mctx, *field);
   1784 	}
   1785 
   1786 	*field = copy;
   1787 	return ISC_R_SUCCESS;
   1788 }
   1789 
   1790 isc_result_t
   1791 dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
   1792 		 const dns_master_style_t *style) {
   1793 	isc_result_t result = ISC_R_SUCCESS;
   1794 
   1795 	REQUIRE(DNS_ZONE_VALID(zone));
   1796 	REQUIRE(zone->stream == NULL);
   1797 
   1798 	LOCK_ZONE(zone);
   1799 	result = dns_zone_setstring(zone, &zone->masterfile, file);
   1800 	if (result == ISC_R_SUCCESS) {
   1801 		zone->masterformat = format;
   1802 		if (format == dns_masterformat_text) {
   1803 			zone->masterstyle = style;
   1804 		}
   1805 		result = default_journal(zone);
   1806 	}
   1807 	UNLOCK_ZONE(zone);
   1808 
   1809 	return result;
   1810 }
   1811 
   1812 const char *
   1813 dns_zone_getfile(dns_zone_t *zone) {
   1814 	REQUIRE(DNS_ZONE_VALID(zone));
   1815 
   1816 	return zone->masterfile;
   1817 }
   1818 
   1819 isc_result_t
   1820 dns_zone_setstream(dns_zone_t *zone, const FILE *stream,
   1821 		   dns_masterformat_t format, const dns_master_style_t *style) {
   1822 	isc_result_t result = ISC_R_SUCCESS;
   1823 
   1824 	REQUIRE(DNS_ZONE_VALID(zone));
   1825 	REQUIRE(stream != NULL);
   1826 	REQUIRE(zone->masterfile == NULL);
   1827 
   1828 	LOCK_ZONE(zone);
   1829 	zone->stream = stream;
   1830 	zone->masterformat = format;
   1831 	if (format == dns_masterformat_text) {
   1832 		zone->masterstyle = style;
   1833 	}
   1834 	result = default_journal(zone);
   1835 	UNLOCK_ZONE(zone);
   1836 
   1837 	return result;
   1838 }
   1839 
   1840 dns_ttl_t
   1841 dns_zone_getmaxttl(dns_zone_t *zone) {
   1842 	REQUIRE(DNS_ZONE_VALID(zone));
   1843 
   1844 	return zone->maxttl;
   1845 }
   1846 
   1847 void
   1848 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
   1849 	REQUIRE(DNS_ZONE_VALID(zone));
   1850 
   1851 	LOCK_ZONE(zone);
   1852 	if (maxttl != 0) {
   1853 		DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_CHECKTTL);
   1854 	} else {
   1855 		DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_CHECKTTL);
   1856 	}
   1857 	zone->maxttl = maxttl;
   1858 	UNLOCK_ZONE(zone);
   1859 
   1860 	return;
   1861 }
   1862 
   1863 static isc_result_t
   1864 default_journal(dns_zone_t *zone) {
   1865 	isc_result_t result;
   1866 	char *journal;
   1867 
   1868 	REQUIRE(DNS_ZONE_VALID(zone));
   1869 	REQUIRE(LOCKED_ZONE(zone));
   1870 
   1871 	if (zone->masterfile != NULL) {
   1872 		/* Calculate string length including '\0'. */
   1873 		int len = strlen(zone->masterfile) + sizeof(".jnl");
   1874 		journal = isc_mem_allocate(zone->mctx, len);
   1875 		strlcpy(journal, zone->masterfile, len);
   1876 		strlcat(journal, ".jnl", len);
   1877 	} else {
   1878 		journal = NULL;
   1879 	}
   1880 	result = dns_zone_setstring(zone, &zone->journal, journal);
   1881 	if (journal != NULL) {
   1882 		isc_mem_free(zone->mctx, journal);
   1883 	}
   1884 	return result;
   1885 }
   1886 
   1887 isc_result_t
   1888 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
   1889 	isc_result_t result = ISC_R_SUCCESS;
   1890 
   1891 	REQUIRE(DNS_ZONE_VALID(zone));
   1892 
   1893 	LOCK_ZONE(zone);
   1894 	result = dns_zone_setstring(zone, &zone->journal, myjournal);
   1895 	UNLOCK_ZONE(zone);
   1896 
   1897 	return result;
   1898 }
   1899 
   1900 char *
   1901 dns_zone_getjournal(dns_zone_t *zone) {
   1902 	REQUIRE(DNS_ZONE_VALID(zone));
   1903 
   1904 	return zone->journal;
   1905 }
   1906 
   1907 /*
   1908  * Return true iff the zone is "dynamic", in the sense that the zone's
   1909  * master file (if any) is written by the server, rather than being
   1910  * updated manually and read by the server.
   1911  *
   1912  * This is true for secondary zones, mirror zones, stub zones, key zones,
   1913  * and zones that allow dynamic updates either by having an update
   1914  * policy ("ssutable") or an "allow-update" ACL with a value other than
   1915  * exactly "{ none; }".
   1916  */
   1917 bool
   1918 dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
   1919 	REQUIRE(DNS_ZONE_VALID(zone));
   1920 
   1921 	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
   1922 	    zone->type == dns_zone_stub || zone->type == dns_zone_key ||
   1923 	    (zone->type == dns_zone_redirect &&
   1924 	     dns_remote_addresses(&zone->primaries) != NULL))
   1925 	{
   1926 		return true;
   1927 	}
   1928 
   1929 	/* Inline zones are always dynamic. */
   1930 	if (zone->type == dns_zone_primary && zone->raw != NULL) {
   1931 		return true;
   1932 	}
   1933 
   1934 	/* If !ignore_freeze, we need check whether updates are disabled.  */
   1935 	if (zone->type == dns_zone_primary &&
   1936 	    (!zone->update_disabled || ignore_freeze) &&
   1937 	    ((zone->ssutable != NULL) ||
   1938 	     (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
   1939 	{
   1940 		return true;
   1941 	}
   1942 
   1943 	return false;
   1944 }
   1945 
   1946 /*
   1947  * Set the response policy index and information for a zone.
   1948  */
   1949 isc_result_t
   1950 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
   1951 		    dns_rpz_num_t rpz_num) {
   1952 	/*
   1953 	 * This must happen only once or be redundant.
   1954 	 */
   1955 	LOCK_ZONE(zone);
   1956 	if (zone->rpzs != NULL) {
   1957 		REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
   1958 	} else {
   1959 		REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
   1960 		dns_rpz_zones_attach(rpzs, &zone->rpzs);
   1961 		zone->rpz_num = rpz_num;
   1962 	}
   1963 	rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
   1964 	UNLOCK_ZONE(zone);
   1965 
   1966 	return ISC_R_SUCCESS;
   1967 }
   1968 
   1969 dns_rpz_num_t
   1970 dns_zone_get_rpz_num(dns_zone_t *zone) {
   1971 	return zone->rpz_num;
   1972 }
   1973 
   1974 /*
   1975  * If a zone is a response policy zone, mark its new database.
   1976  */
   1977 void
   1978 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
   1979 	if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
   1980 		return;
   1981 	}
   1982 	REQUIRE(zone->rpzs != NULL);
   1983 	dns_rpz_dbupdate_register(db, zone->rpzs->zones[zone->rpz_num]);
   1984 }
   1985 
   1986 static void
   1987 dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
   1988 	if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
   1989 		return;
   1990 	}
   1991 	REQUIRE(zone->rpzs != NULL);
   1992 	dns_rpz_dbupdate_unregister(db, zone->rpzs->zones[zone->rpz_num]);
   1993 }
   1994 
   1995 /*
   1996  * If a zone is a catalog zone, attach it to update notification in database.
   1997  */
   1998 void
   1999 dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
   2000 	REQUIRE(DNS_ZONE_VALID(zone));
   2001 	REQUIRE(db != NULL);
   2002 
   2003 	if (zone->catzs != NULL) {
   2004 		dns_catz_dbupdate_register(db, zone->catzs);
   2005 	}
   2006 }
   2007 
   2008 static void
   2009 dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
   2010 	REQUIRE(DNS_ZONE_VALID(zone));
   2011 	REQUIRE(db != NULL);
   2012 
   2013 	if (zone->catzs != NULL) {
   2014 		dns_catz_dbupdate_unregister(db, zone->catzs);
   2015 	}
   2016 }
   2017 
   2018 static void
   2019 zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
   2020 	REQUIRE(DNS_ZONE_VALID(zone));
   2021 	REQUIRE(catzs != NULL);
   2022 
   2023 	INSIST(zone->catzs == NULL || zone->catzs == catzs);
   2024 	dns_catz_catzs_set_view(catzs, zone->view);
   2025 	if (zone->catzs == NULL) {
   2026 		dns_catz_zones_attach(catzs, &zone->catzs);
   2027 	}
   2028 }
   2029 
   2030 void
   2031 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
   2032 	REQUIRE(DNS_ZONE_VALID(zone));
   2033 
   2034 	LOCK_ZONE(zone);
   2035 	zone_catz_enable(zone, catzs);
   2036 	UNLOCK_ZONE(zone);
   2037 }
   2038 
   2039 static void
   2040 zone_catz_disable(dns_zone_t *zone) {
   2041 	REQUIRE(DNS_ZONE_VALID(zone));
   2042 
   2043 	if (zone->catzs != NULL) {
   2044 		if (zone->db != NULL) {
   2045 			dns_zone_catz_disable_db(zone, zone->db);
   2046 		}
   2047 		dns_catz_zones_detach(&zone->catzs);
   2048 	}
   2049 }
   2050 
   2051 void
   2052 dns_zone_catz_disable(dns_zone_t *zone) {
   2053 	REQUIRE(DNS_ZONE_VALID(zone));
   2054 
   2055 	LOCK_ZONE(zone);
   2056 	zone_catz_disable(zone);
   2057 	UNLOCK_ZONE(zone);
   2058 }
   2059 
   2060 bool
   2061 dns_zone_catz_is_enabled(dns_zone_t *zone) {
   2062 	REQUIRE(DNS_ZONE_VALID(zone));
   2063 
   2064 	return zone->catzs != NULL;
   2065 }
   2066 
   2067 /*
   2068  * Set catalog zone ownership of the zone
   2069  */
   2070 void
   2071 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
   2072 	REQUIRE(DNS_ZONE_VALID(zone));
   2073 	REQUIRE(catz != NULL);
   2074 	LOCK_ZONE(zone);
   2075 	INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
   2076 	zone->parentcatz = catz;
   2077 	UNLOCK_ZONE(zone);
   2078 }
   2079 
   2080 dns_catz_zone_t *
   2081 dns_zone_get_parentcatz(dns_zone_t *zone) {
   2082 	REQUIRE(DNS_ZONE_VALID(zone));
   2083 
   2084 	dns_catz_zone_t *parentcatz = NULL;
   2085 
   2086 	LOCK_ZONE(zone);
   2087 	parentcatz = zone->parentcatz;
   2088 	UNLOCK_ZONE(zone);
   2089 
   2090 	return parentcatz;
   2091 }
   2092 
   2093 static bool
   2094 zone_touched(dns_zone_t *zone) {
   2095 	isc_result_t result;
   2096 	isc_time_t modtime;
   2097 	dns_include_t *include;
   2098 
   2099 	REQUIRE(DNS_ZONE_VALID(zone));
   2100 
   2101 	result = isc_file_getmodtime(zone->masterfile, &modtime);
   2102 	if (result != ISC_R_SUCCESS ||
   2103 	    isc_time_compare(&modtime, &zone->loadtime) > 0)
   2104 	{
   2105 		return true;
   2106 	}
   2107 
   2108 	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
   2109 	     include = ISC_LIST_NEXT(include, link))
   2110 	{
   2111 		result = isc_file_getmodtime(include->name, &modtime);
   2112 		if (result != ISC_R_SUCCESS ||
   2113 		    isc_time_compare(&modtime, &include->filetime) > 0)
   2114 		{
   2115 			return true;
   2116 		}
   2117 	}
   2118 
   2119 	return false;
   2120 }
   2121 
   2122 /*
   2123  * Note: when dealing with inline-signed zones, external callers will always
   2124  * call zone_load() for the secure zone; zone_load() calls itself recursively
   2125  * in order to load the raw zone.
   2126  */
   2127 static isc_result_t
   2128 zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
   2129 	isc_result_t result;
   2130 	isc_time_t now;
   2131 	isc_time_t loadtime;
   2132 	dns_db_t *db = NULL;
   2133 	bool rbt, hasraw, is_dynamic;
   2134 
   2135 	REQUIRE(DNS_ZONE_VALID(zone));
   2136 
   2137 	if (!locked) {
   2138 		LOCK_ZONE(zone);
   2139 	}
   2140 
   2141 	INSIST(zone != zone->raw);
   2142 	hasraw = inline_secure(zone);
   2143 	if (hasraw) {
   2144 		/*
   2145 		 * We are trying to load an inline-signed zone.  First call
   2146 		 * self recursively to try loading the raw version of the zone.
   2147 		 * Assuming the raw zone file is readable, there are two
   2148 		 * possibilities:
   2149 		 *
   2150 		 *  a) the raw zone was not yet loaded and thus it will be
   2151 		 *     loaded now, synchronously; if this succeeds, a
   2152 		 *     subsequent attempt to load the signed zone file will
   2153 		 *     take place and thus zone_postload() will be called
   2154 		 *     twice: first for the raw zone and then for the secure
   2155 		 *     zone; the latter call will take care of syncing the raw
   2156 		 *     version with the secure version,
   2157 		 *
   2158 		 *  b) the raw zone was already loaded and we are trying to
   2159 		 *     reload it, which will happen asynchronously; this means
   2160 		 *     zone_postload() will only be called for the raw zone
   2161 		 *     because "result" returned by the zone_load() call below
   2162 		 *     will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
   2163 		 *     zone_postload() called for the raw zone will take care
   2164 		 *     of syncing the raw version with the secure version.
   2165 		 */
   2166 		result = zone_load(zone->raw, flags, false);
   2167 		if (result != ISC_R_SUCCESS) {
   2168 			if (!locked) {
   2169 				UNLOCK_ZONE(zone);
   2170 			}
   2171 			return result;
   2172 		}
   2173 		LOCK_ZONE(zone->raw);
   2174 	}
   2175 
   2176 	now = isc_time_now();
   2177 
   2178 	INSIST(zone->type != dns_zone_none);
   2179 
   2180 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
   2181 		if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
   2182 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
   2183 		}
   2184 		result = DNS_R_CONTINUE;
   2185 		goto cleanup;
   2186 	}
   2187 
   2188 	INSIST(zone->db_argc >= 1);
   2189 
   2190 	rbt = strcmp(zone->db_argv[0], ZONEDB_DEFAULT) == 0;
   2191 
   2192 	if (zone->db != NULL && zone->masterfile == NULL && rbt) {
   2193 		/*
   2194 		 * The zone has no master file configured.
   2195 		 */
   2196 		result = ISC_R_SUCCESS;
   2197 		goto cleanup;
   2198 	}
   2199 
   2200 	is_dynamic = dns_zone_isdynamic(zone, false);
   2201 	if (zone->db != NULL && is_dynamic) {
   2202 		/*
   2203 		 * This is a secondary, stub, or dynamically updated zone
   2204 		 * being reloaded.  Do nothing - the database we already
   2205 		 * have is guaranteed to be up-to-date.
   2206 		 */
   2207 		if (zone->type == dns_zone_primary && !hasraw) {
   2208 			result = DNS_R_DYNAMIC;
   2209 		} else {
   2210 			result = ISC_R_SUCCESS;
   2211 		}
   2212 		goto cleanup;
   2213 	}
   2214 
   2215 	/*
   2216 	 * Store the current time before the zone is loaded, so that if the
   2217 	 * file changes between the time of the load and the time that
   2218 	 * zone->loadtime is set, then the file will still be reloaded
   2219 	 * the next time dns_zone_load is called.
   2220 	 */
   2221 	loadtime = isc_time_now();
   2222 
   2223 	/*
   2224 	 * Don't do the load if the file that stores the zone is older
   2225 	 * than the last time the zone was loaded.  If the zone has not
   2226 	 * been loaded yet, zone->loadtime will be the epoch.
   2227 	 */
   2228 	if (zone->masterfile != NULL) {
   2229 		isc_time_t filetime;
   2230 
   2231 		/*
   2232 		 * The file is already loaded.	If we are just doing a
   2233 		 * "rndc reconfig", we are done.
   2234 		 */
   2235 		if (!isc_time_isepoch(&zone->loadtime) &&
   2236 		    (flags & DNS_ZONELOADFLAG_NOSTAT) != 0)
   2237 		{
   2238 			result = ISC_R_SUCCESS;
   2239 			goto cleanup;
   2240 		}
   2241 
   2242 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   2243 		    !zone_touched(zone))
   2244 		{
   2245 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2246 				      ISC_LOG_DEBUG(1),
   2247 				      "skipping load: master file "
   2248 				      "older than last load");
   2249 			result = DNS_R_UPTODATE;
   2250 			goto cleanup;
   2251 		}
   2252 
   2253 		/*
   2254 		 * If the file modification time is in the past
   2255 		 * set loadtime to that value.
   2256 		 */
   2257 		result = isc_file_getmodtime(zone->masterfile, &filetime);
   2258 		if (result == ISC_R_SUCCESS &&
   2259 		    isc_time_compare(&loadtime, &filetime) > 0)
   2260 		{
   2261 			loadtime = filetime;
   2262 		}
   2263 	}
   2264 
   2265 	/*
   2266 	 * Built in zones (with the exception of empty zones) don't need
   2267 	 * to be reloaded.
   2268 	 */
   2269 	if (zone->type == dns_zone_primary &&
   2270 	    strcmp(zone->db_argv[0], "_builtin") == 0 &&
   2271 	    (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
   2272 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   2273 	{
   2274 		result = ISC_R_SUCCESS;
   2275 		goto cleanup;
   2276 	}
   2277 
   2278 	/*
   2279 	 * Zones associated with a DLZ don't need to be loaded either,
   2280 	 * but we need to associate the database with the zone object.
   2281 	 */
   2282 	if (strcmp(zone->db_argv[0], "dlz") == 0) {
   2283 		dns_dlzdb_t *dlzdb;
   2284 		dns_dlzfindzone_t findzone;
   2285 
   2286 		for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
   2287 		     dlzdb != NULL; dlzdb = ISC_LIST_NEXT(dlzdb, link))
   2288 		{
   2289 			INSIST(DNS_DLZ_VALID(dlzdb));
   2290 			if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0) {
   2291 				break;
   2292 			}
   2293 		}
   2294 
   2295 		if (dlzdb == NULL) {
   2296 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2297 				      ISC_LOG_ERROR,
   2298 				      "DLZ %s does not exist or is set "
   2299 				      "to 'search yes;'",
   2300 				      zone->db_argv[1]);
   2301 			result = ISC_R_NOTFOUND;
   2302 			goto cleanup;
   2303 		}
   2304 
   2305 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   2306 		/* ask SDLZ driver if the zone is supported */
   2307 		findzone = dlzdb->implementation->methods->findzone;
   2308 		result = (*findzone)(dlzdb->implementation->driverarg,
   2309 				     dlzdb->dbdata, dlzdb->mctx,
   2310 				     zone->view->rdclass, &zone->origin, NULL,
   2311 				     NULL, &db);
   2312 		if (result != ISC_R_NOTFOUND) {
   2313 			if (zone->db != NULL) {
   2314 				zone_detachdb(zone);
   2315 			}
   2316 			zone_attachdb(zone, db);
   2317 			dns_db_detach(&db);
   2318 			result = ISC_R_SUCCESS;
   2319 		}
   2320 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   2321 
   2322 		if (result == ISC_R_SUCCESS) {
   2323 			if (dlzdb->configure_callback == NULL) {
   2324 				goto cleanup;
   2325 			}
   2326 
   2327 			result = (*dlzdb->configure_callback)(zone->view, dlzdb,
   2328 							      zone);
   2329 			if (result != ISC_R_SUCCESS) {
   2330 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2331 					      ISC_LOG_ERROR,
   2332 					      "DLZ configuration callback: %s",
   2333 					      isc_result_totext(result));
   2334 			}
   2335 		}
   2336 		goto cleanup;
   2337 	}
   2338 
   2339 	if ((zone->type == dns_zone_secondary ||
   2340 	     zone->type == dns_zone_mirror || zone->type == dns_zone_stub ||
   2341 	     (zone->type == dns_zone_redirect &&
   2342 	      dns_remote_addresses(&zone->primaries) != NULL)) &&
   2343 	    rbt)
   2344 	{
   2345 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIRSTREFRESH);
   2346 
   2347 		if (zone->stream == NULL &&
   2348 		    (zone->masterfile == NULL ||
   2349 		     !isc_file_exists(zone->masterfile)))
   2350 		{
   2351 			if (zone->masterfile != NULL) {
   2352 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2353 					      ISC_LOG_DEBUG(1),
   2354 					      "no master file");
   2355 			}
   2356 			zone->refreshtime = now;
   2357 			if (zone->loop != NULL) {
   2358 				zone_settimer(zone, &now);
   2359 			}
   2360 			result = ISC_R_SUCCESS;
   2361 			goto cleanup;
   2362 		}
   2363 	}
   2364 
   2365 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
   2366 		      "starting load");
   2367 
   2368 	result = dns_zone_makedb(zone, &db);
   2369 	if (result != ISC_R_SUCCESS) {
   2370 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   2371 			      "loading zone: creating database: %s",
   2372 			      isc_result_totext(result));
   2373 		goto cleanup;
   2374 	}
   2375 
   2376 	if (!dns_db_ispersistent(db)) {
   2377 		if (zone->masterfile != NULL || zone->stream != NULL) {
   2378 			result = zone_startload(db, zone, loadtime);
   2379 		} else {
   2380 			result = DNS_R_NOMASTERFILE;
   2381 			if (zone->type == dns_zone_primary ||
   2382 			    (zone->type == dns_zone_redirect &&
   2383 			     dns_remote_addresses(&zone->primaries) == NULL))
   2384 			{
   2385 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2386 					      ISC_LOG_ERROR,
   2387 					      "loading zone: "
   2388 					      "no master file configured");
   2389 				goto cleanup;
   2390 			}
   2391 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2392 				      ISC_LOG_INFO,
   2393 				      "loading zone: "
   2394 				      "no master file configured: continuing");
   2395 		}
   2396 	}
   2397 
   2398 	if (result == DNS_R_CONTINUE) {
   2399 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
   2400 		if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
   2401 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
   2402 		}
   2403 		goto cleanup;
   2404 	}
   2405 
   2406 	result = zone_postload(zone, db, loadtime, result);
   2407 
   2408 cleanup:
   2409 	if (hasraw) {
   2410 		UNLOCK_ZONE(zone->raw);
   2411 	}
   2412 	if (!locked) {
   2413 		UNLOCK_ZONE(zone);
   2414 	}
   2415 	if (db != NULL) {
   2416 		dns_db_detach(&db);
   2417 	}
   2418 	return result;
   2419 }
   2420 
   2421 isc_result_t
   2422 dns_zone_load(dns_zone_t *zone, bool newonly) {
   2423 	return zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false);
   2424 }
   2425 
   2426 static void
   2427 zone_asyncload(void *arg) {
   2428 	dns_asyncload_t *asl = arg;
   2429 	dns_zone_t *zone = asl->zone;
   2430 	isc_result_t result;
   2431 
   2432 	REQUIRE(DNS_ZONE_VALID(zone));
   2433 
   2434 	LOCK_ZONE(zone);
   2435 	result = zone_load(zone, asl->flags, true);
   2436 	if (result != DNS_R_CONTINUE) {
   2437 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
   2438 	}
   2439 	UNLOCK_ZONE(zone);
   2440 
   2441 	/* Inform the zone table we've finished loading */
   2442 	if (asl->loaded != NULL) {
   2443 		asl->loaded(asl->loaded_arg);
   2444 	}
   2445 
   2446 	isc_mem_put(zone->mctx, asl, sizeof(*asl));
   2447 	dns_zone_idetach(&zone);
   2448 }
   2449 
   2450 isc_result_t
   2451 dns_zone_asyncload(dns_zone_t *zone, bool newonly, dns_zt_callback_t *done,
   2452 		   void *arg) {
   2453 	dns_asyncload_t *asl = NULL;
   2454 
   2455 	REQUIRE(DNS_ZONE_VALID(zone));
   2456 
   2457 	if (zone->zmgr == NULL) {
   2458 		return ISC_R_FAILURE;
   2459 	}
   2460 
   2461 	/* If we already have a load pending, stop now */
   2462 	LOCK_ZONE(zone);
   2463 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
   2464 		UNLOCK_ZONE(zone);
   2465 		return ISC_R_ALREADYRUNNING;
   2466 	}
   2467 
   2468 	asl = isc_mem_get(zone->mctx, sizeof(*asl));
   2469 
   2470 	asl->zone = NULL;
   2471 	asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
   2472 	asl->loaded = done;
   2473 	asl->loaded_arg = arg;
   2474 
   2475 	zone_iattach(zone, &asl->zone);
   2476 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
   2477 	isc_async_run(zone->loop, zone_asyncload, asl);
   2478 	UNLOCK_ZONE(zone);
   2479 
   2480 	return ISC_R_SUCCESS;
   2481 }
   2482 
   2483 bool
   2484 dns__zone_loadpending(dns_zone_t *zone) {
   2485 	REQUIRE(DNS_ZONE_VALID(zone));
   2486 
   2487 	return DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
   2488 }
   2489 
   2490 isc_result_t
   2491 dns_zone_loadandthaw(dns_zone_t *zone) {
   2492 	isc_result_t result;
   2493 
   2494 	if (inline_raw(zone)) {
   2495 		result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW, false);
   2496 	} else {
   2497 		/*
   2498 		 * When thawing a zone, we don't know what changes
   2499 		 * have been made. If we do DNSSEC maintenance on this
   2500 		 * zone, schedule a full sign for this zone.
   2501 		 */
   2502 		if (zone->type == dns_zone_primary &&
   2503 		    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
   2504 		{
   2505 			DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
   2506 		}
   2507 		result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
   2508 	}
   2509 
   2510 	switch (result) {
   2511 	case DNS_R_CONTINUE:
   2512 		/* Deferred thaw. */
   2513 		break;
   2514 	case DNS_R_UPTODATE:
   2515 	case ISC_R_SUCCESS:
   2516 	case DNS_R_SEENINCLUDE:
   2517 		zone->update_disabled = false;
   2518 		break;
   2519 	case DNS_R_NOMASTERFILE:
   2520 		zone->update_disabled = false;
   2521 		break;
   2522 	default:
   2523 		/* Error, remain in disabled state. */
   2524 		break;
   2525 	}
   2526 	return result;
   2527 }
   2528 
   2529 static unsigned int
   2530 get_primary_options(dns_zone_t *zone) {
   2531 	unsigned int options;
   2532 
   2533 	options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
   2534 	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
   2535 	    (zone->type == dns_zone_redirect &&
   2536 	     dns_remote_addresses(&zone->primaries) == NULL))
   2537 	{
   2538 		options |= DNS_MASTER_SECONDARY;
   2539 	}
   2540 	if (zone->type == dns_zone_key) {
   2541 		options |= DNS_MASTER_KEY;
   2542 	}
   2543 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
   2544 		options |= DNS_MASTER_CHECKNS;
   2545 	}
   2546 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
   2547 		options |= DNS_MASTER_FATALNS;
   2548 	}
   2549 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
   2550 		options |= DNS_MASTER_CHECKNAMES;
   2551 	}
   2552 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
   2553 		options |= DNS_MASTER_CHECKNAMESFAIL;
   2554 	}
   2555 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
   2556 		options |= DNS_MASTER_CHECKMX;
   2557 	}
   2558 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
   2559 		options |= DNS_MASTER_CHECKMXFAIL;
   2560 	}
   2561 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
   2562 		options |= DNS_MASTER_CHECKWILDCARD;
   2563 	}
   2564 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
   2565 		options |= DNS_MASTER_CHECKTTL;
   2566 	}
   2567 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSVCB)) {
   2568 		options |= DNS_MASTER_CHECKSVCB;
   2569 	}
   2570 
   2571 	return options;
   2572 }
   2573 
   2574 static void
   2575 zone_registerinclude(const char *filename, void *arg) {
   2576 	isc_result_t result;
   2577 	dns_zone_t *zone = (dns_zone_t *)arg;
   2578 	dns_include_t *inc = NULL;
   2579 
   2580 	REQUIRE(DNS_ZONE_VALID(zone));
   2581 
   2582 	if (filename == NULL) {
   2583 		return;
   2584 	}
   2585 
   2586 	/*
   2587 	 * Suppress duplicates.
   2588 	 */
   2589 	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
   2590 	     inc = ISC_LIST_NEXT(inc, link))
   2591 	{
   2592 		if (strcmp(filename, inc->name) == 0) {
   2593 			return;
   2594 		}
   2595 	}
   2596 
   2597 	inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
   2598 	inc->name = isc_mem_strdup(zone->mctx, filename);
   2599 	ISC_LINK_INIT(inc, link);
   2600 
   2601 	result = isc_file_getmodtime(filename, &inc->filetime);
   2602 	if (result != ISC_R_SUCCESS) {
   2603 		isc_time_settoepoch(&inc->filetime);
   2604 	}
   2605 
   2606 	ISC_LIST_APPEND(zone->newincludes, inc, link);
   2607 }
   2608 
   2609 static void
   2610 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
   2611 	isc_result_t result;
   2612 	unsigned int soacount;
   2613 
   2614 	LOCK(&raw->lock);
   2615 	if (raw->db != NULL) {
   2616 		result = zone_get_from_db(raw, raw->db, NULL, &soacount, NULL,
   2617 					  &rawdata->sourceserial, NULL, NULL,
   2618 					  NULL, NULL, NULL);
   2619 		if (result == ISC_R_SUCCESS && soacount > 0U) {
   2620 			rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
   2621 		}
   2622 	}
   2623 	UNLOCK(&raw->lock);
   2624 }
   2625 
   2626 /*
   2627  * Save the raw serial number for inline-signing zones.
   2628  * (XXX: Other information from the header will be used
   2629  * for other purposes in the future, but for now this is
   2630  * all we're interested in.)
   2631  */
   2632 static void
   2633 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
   2634 	if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) {
   2635 		return;
   2636 	}
   2637 
   2638 	zone->sourceserial = header->sourceserial;
   2639 	zone->sourceserialset = true;
   2640 }
   2641 
   2642 void
   2643 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
   2644 	if (zone == NULL) {
   2645 		return;
   2646 	}
   2647 
   2648 	LOCK_ZONE(zone);
   2649 	zone_setrawdata(zone, header);
   2650 	UNLOCK_ZONE(zone);
   2651 }
   2652 
   2653 static isc_result_t
   2654 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
   2655 	isc_result_t result;
   2656 	isc_result_t tresult;
   2657 	unsigned int options;
   2658 	dns_load_t *load = isc_mem_get(zone->mctx, sizeof(*load));
   2659 
   2660 	ENTER;
   2661 
   2662 	*load = (dns_load_t){
   2663 		.loadtime = loadtime,
   2664 	};
   2665 
   2666 	dns_zone_rpz_enable_db(zone, db);
   2667 	dns_zone_catz_enable_db(zone, db);
   2668 
   2669 	options = get_primary_options(zone);
   2670 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
   2671 		options |= DNS_MASTER_MANYERRORS;
   2672 	}
   2673 
   2674 	zone_iattach(zone, &load->zone);
   2675 	dns_db_attach(db, &load->db);
   2676 
   2677 	dns_rdatacallbacks_init(&load->callbacks);
   2678 	load->callbacks.rawdata = zone_setrawdata;
   2679 	zone_iattach(zone, &load->callbacks.zone);
   2680 
   2681 	result = dns_db_beginload(db, &load->callbacks);
   2682 	if (result != ISC_R_SUCCESS) {
   2683 		goto cleanup;
   2684 	}
   2685 
   2686 	if (zone->zmgr != NULL && zone->db != NULL) {
   2687 		result = dns_master_loadfileasync(
   2688 			zone->masterfile, dns_db_origin(db), dns_db_origin(db),
   2689 			zone->rdclass, options, 0, &load->callbacks, zone->loop,
   2690 			zone_loaddone, load, &zone->loadctx,
   2691 			zone_registerinclude, zone, zone->mctx,
   2692 			zone->masterformat, zone->maxttl);
   2693 		if (result != ISC_R_SUCCESS) {
   2694 			goto cleanup;
   2695 		}
   2696 
   2697 		return DNS_R_CONTINUE;
   2698 	} else if (zone->stream != NULL) {
   2699 		FILE *stream = UNCONST(zone->stream);
   2700 		result = dns_master_loadstream(
   2701 			stream, &zone->origin, &zone->origin, zone->rdclass,
   2702 			options, &load->callbacks, zone->mctx);
   2703 	} else {
   2704 		result = dns_master_loadfile(
   2705 			zone->masterfile, &zone->origin, &zone->origin,
   2706 			zone->rdclass, options, 0, &load->callbacks,
   2707 			zone_registerinclude, zone, zone->mctx,
   2708 			zone->masterformat, zone->maxttl);
   2709 	}
   2710 
   2711 cleanup:
   2712 	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
   2713 		dns_zone_rpz_disable_db(zone, load->db);
   2714 		dns_zone_catz_disable_db(zone, load->db);
   2715 	}
   2716 
   2717 	tresult = dns_db_endload(db, &load->callbacks);
   2718 	if (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) {
   2719 		result = tresult;
   2720 	}
   2721 
   2722 	zone_idetach(&load->callbacks.zone);
   2723 	dns_db_detach(&load->db);
   2724 	zone_idetach(&load->zone);
   2725 
   2726 	isc_mem_put(zone->mctx, load, sizeof(*load));
   2727 	return result;
   2728 }
   2729 
   2730 static bool
   2731 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
   2732 	      dns_name_t *owner) {
   2733 	isc_result_t result;
   2734 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2735 	char namebuf[DNS_NAME_FORMATSIZE];
   2736 	char altbuf[DNS_NAME_FORMATSIZE];
   2737 	dns_fixedname_t fixed;
   2738 	dns_name_t *foundname;
   2739 	int level;
   2740 
   2741 	/*
   2742 	 * "." means the services does not exist.
   2743 	 */
   2744 	if (dns_name_equal(name, dns_rootname)) {
   2745 		return true;
   2746 	}
   2747 
   2748 	/*
   2749 	 * Outside of zone.
   2750 	 */
   2751 	if (!dns_name_issubdomain(name, &zone->origin)) {
   2752 		if (zone->checkmx != NULL) {
   2753 			return (zone->checkmx)(zone, name, owner);
   2754 		}
   2755 		return true;
   2756 	}
   2757 
   2758 	if (zone->type == dns_zone_primary) {
   2759 		level = ISC_LOG_ERROR;
   2760 	} else {
   2761 		level = ISC_LOG_WARNING;
   2762 	}
   2763 
   2764 	foundname = dns_fixedname_initname(&fixed);
   2765 
   2766 	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
   2767 			     foundname, NULL, NULL);
   2768 	if (result == ISC_R_SUCCESS) {
   2769 		return true;
   2770 	}
   2771 
   2772 	if (result == DNS_R_NXRRSET) {
   2773 		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
   2774 				     NULL, foundname, NULL, NULL);
   2775 		if (result == ISC_R_SUCCESS) {
   2776 			return true;
   2777 		}
   2778 	}
   2779 
   2780 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
   2781 	dns_name_format(name, namebuf, sizeof namebuf);
   2782 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   2783 	    result == DNS_R_EMPTYNAME)
   2784 	{
   2785 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
   2786 			level = ISC_LOG_WARNING;
   2787 		}
   2788 		dns_zone_log(zone, level,
   2789 			     "%s/MX '%s' has no address records (A or AAAA)",
   2790 			     ownerbuf, namebuf);
   2791 		return (level == ISC_LOG_WARNING) ? true : false;
   2792 	}
   2793 
   2794 	if (result == DNS_R_CNAME) {
   2795 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
   2796 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
   2797 		{
   2798 			level = ISC_LOG_WARNING;
   2799 		}
   2800 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
   2801 			dns_zone_log(zone, level,
   2802 				     "%s/MX '%s' is a CNAME (illegal)",
   2803 				     ownerbuf, namebuf);
   2804 		}
   2805 		return (level == ISC_LOG_WARNING) ? true : false;
   2806 	}
   2807 
   2808 	if (result == DNS_R_DNAME) {
   2809 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
   2810 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
   2811 		{
   2812 			level = ISC_LOG_WARNING;
   2813 		}
   2814 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
   2815 			dns_name_format(foundname, altbuf, sizeof altbuf);
   2816 			dns_zone_log(zone, level,
   2817 				     "%s/MX '%s' is below a DNAME"
   2818 				     " '%s' (illegal)",
   2819 				     ownerbuf, namebuf, altbuf);
   2820 		}
   2821 		return (level == ISC_LOG_WARNING) ? true : false;
   2822 	}
   2823 
   2824 	if (zone->checkmx != NULL && result == DNS_R_DELEGATION) {
   2825 		return (zone->checkmx)(zone, name, owner);
   2826 	}
   2827 
   2828 	return true;
   2829 }
   2830 
   2831 static bool
   2832 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
   2833 	       dns_name_t *owner) {
   2834 	isc_result_t result;
   2835 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2836 	char namebuf[DNS_NAME_FORMATSIZE];
   2837 	char altbuf[DNS_NAME_FORMATSIZE];
   2838 	dns_fixedname_t fixed;
   2839 	dns_name_t *foundname;
   2840 	int level;
   2841 
   2842 	/*
   2843 	 * "." means the services does not exist.
   2844 	 */
   2845 	if (dns_name_equal(name, dns_rootname)) {
   2846 		return true;
   2847 	}
   2848 
   2849 	/*
   2850 	 * Outside of zone.
   2851 	 */
   2852 	if (!dns_name_issubdomain(name, &zone->origin)) {
   2853 		if (zone->checksrv != NULL) {
   2854 			return (zone->checksrv)(zone, name, owner);
   2855 		}
   2856 		return true;
   2857 	}
   2858 
   2859 	if (zone->type == dns_zone_primary) {
   2860 		level = ISC_LOG_ERROR;
   2861 	} else {
   2862 		level = ISC_LOG_WARNING;
   2863 	}
   2864 
   2865 	foundname = dns_fixedname_initname(&fixed);
   2866 
   2867 	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
   2868 			     foundname, NULL, NULL);
   2869 	if (result == ISC_R_SUCCESS) {
   2870 		return true;
   2871 	}
   2872 
   2873 	if (result == DNS_R_NXRRSET) {
   2874 		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
   2875 				     NULL, foundname, NULL, NULL);
   2876 		if (result == ISC_R_SUCCESS) {
   2877 			return true;
   2878 		}
   2879 	}
   2880 
   2881 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
   2882 	dns_name_format(name, namebuf, sizeof namebuf);
   2883 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   2884 	    result == DNS_R_EMPTYNAME)
   2885 	{
   2886 		dns_zone_log(zone, level,
   2887 			     "%s/SRV '%s' has no address records (A or AAAA)",
   2888 			     ownerbuf, namebuf);
   2889 		/* XXX950 make fatal for 9.5.0. */
   2890 		return true;
   2891 	}
   2892 
   2893 	if (result == DNS_R_CNAME) {
   2894 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
   2895 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
   2896 		{
   2897 			level = ISC_LOG_WARNING;
   2898 		}
   2899 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
   2900 			dns_zone_log(zone, level,
   2901 				     "%s/SRV '%s' is a CNAME (illegal)",
   2902 				     ownerbuf, namebuf);
   2903 		}
   2904 		return (level == ISC_LOG_WARNING) ? true : false;
   2905 	}
   2906 
   2907 	if (result == DNS_R_DNAME) {
   2908 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
   2909 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
   2910 		{
   2911 			level = ISC_LOG_WARNING;
   2912 		}
   2913 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
   2914 			dns_name_format(foundname, altbuf, sizeof altbuf);
   2915 			dns_zone_log(zone, level,
   2916 				     "%s/SRV '%s' is below a "
   2917 				     "DNAME '%s' (illegal)",
   2918 				     ownerbuf, namebuf, altbuf);
   2919 		}
   2920 		return (level == ISC_LOG_WARNING) ? true : false;
   2921 	}
   2922 
   2923 	if (zone->checksrv != NULL && result == DNS_R_DELEGATION) {
   2924 		return (zone->checksrv)(zone, name, owner);
   2925 	}
   2926 
   2927 	return true;
   2928 }
   2929 
   2930 static bool
   2931 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
   2932 		dns_name_t *owner) {
   2933 	bool answer = true;
   2934 	isc_result_t result, tresult;
   2935 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2936 	char namebuf[DNS_NAME_FORMATSIZE];
   2937 	char altbuf[DNS_NAME_FORMATSIZE];
   2938 	dns_fixedname_t fixed;
   2939 	dns_name_t *foundname;
   2940 	dns_rdataset_t a;
   2941 	dns_rdataset_t aaaa;
   2942 	int level;
   2943 
   2944 	/*
   2945 	 * Outside of zone.
   2946 	 */
   2947 	if (!dns_name_issubdomain(name, &zone->origin)) {
   2948 		if (zone->checkns != NULL) {
   2949 			return (zone->checkns)(zone, name, owner, NULL, NULL);
   2950 		}
   2951 		return true;
   2952 	}
   2953 
   2954 	if (zone->type == dns_zone_primary) {
   2955 		level = ISC_LOG_ERROR;
   2956 	} else {
   2957 		level = ISC_LOG_WARNING;
   2958 	}
   2959 
   2960 	foundname = dns_fixedname_initname(&fixed);
   2961 	dns_rdataset_init(&a);
   2962 	dns_rdataset_init(&aaaa);
   2963 
   2964 	/*
   2965 	 * Perform a regular lookup to catch DNAME records then look
   2966 	 * for glue.
   2967 	 */
   2968 	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
   2969 			     foundname, &a, NULL);
   2970 	switch (result) {
   2971 	case ISC_R_SUCCESS:
   2972 	case DNS_R_DNAME:
   2973 	case DNS_R_CNAME:
   2974 		break;
   2975 	default:
   2976 		if (dns_rdataset_isassociated(&a)) {
   2977 			dns_rdataset_disassociate(&a);
   2978 		}
   2979 		result = dns_db_find(db, name, NULL, dns_rdatatype_a,
   2980 				     DNS_DBFIND_GLUEOK, 0, NULL, foundname, &a,
   2981 				     NULL);
   2982 	}
   2983 	if (result == ISC_R_SUCCESS) {
   2984 		dns_rdataset_disassociate(&a);
   2985 		return true;
   2986 	} else if (result == DNS_R_DELEGATION) {
   2987 		dns_rdataset_disassociate(&a);
   2988 	}
   2989 
   2990 	if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
   2991 	    result == DNS_R_GLUE)
   2992 	{
   2993 		tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
   2994 				      DNS_DBFIND_GLUEOK, 0, NULL, foundname,
   2995 				      &aaaa, NULL);
   2996 		if (tresult == ISC_R_SUCCESS) {
   2997 			if (dns_rdataset_isassociated(&a)) {
   2998 				dns_rdataset_disassociate(&a);
   2999 			}
   3000 			dns_rdataset_disassociate(&aaaa);
   3001 			return true;
   3002 		}
   3003 		if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME) {
   3004 			dns_rdataset_disassociate(&aaaa);
   3005 		}
   3006 		if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
   3007 			/*
   3008 			 * Check glue against child zone.
   3009 			 */
   3010 			if (zone->checkns != NULL) {
   3011 				answer = (zone->checkns)(zone, name, owner, &a,
   3012 							 &aaaa);
   3013 			}
   3014 			if (dns_rdataset_isassociated(&a)) {
   3015 				dns_rdataset_disassociate(&a);
   3016 			}
   3017 			if (dns_rdataset_isassociated(&aaaa)) {
   3018 				dns_rdataset_disassociate(&aaaa);
   3019 			}
   3020 			return answer;
   3021 		}
   3022 	}
   3023 
   3024 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
   3025 	dns_name_format(name, namebuf, sizeof namebuf);
   3026 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   3027 	    result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION)
   3028 	{
   3029 		const char *what;
   3030 		bool required = false;
   3031 		if (dns_name_issubdomain(name, owner)) {
   3032 			what = "REQUIRED GLUE ";
   3033 			required = true;
   3034 		} else if (result == DNS_R_DELEGATION) {
   3035 			what = "SIBLING GLUE ";
   3036 		} else {
   3037 			what = "";
   3038 		}
   3039 
   3040 		if (result != DNS_R_DELEGATION || required ||
   3041 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING))
   3042 		{
   3043 			dns_zone_log(zone, level,
   3044 				     "%s/NS '%s' has no %s"
   3045 				     "address records (A or AAAA)",
   3046 				     ownerbuf, namebuf, what);
   3047 			/*
   3048 			 * Log missing address record.
   3049 			 */
   3050 			if (result == DNS_R_DELEGATION && zone->checkns != NULL)
   3051 			{
   3052 				(void)(zone->checkns)(zone, name, owner, &a,
   3053 						      &aaaa);
   3054 			}
   3055 			/* XXX950 make fatal for 9.5.0. */
   3056 			/* answer = false; */
   3057 		}
   3058 	} else if (result == DNS_R_CNAME) {
   3059 		dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
   3060 			     ownerbuf, namebuf);
   3061 		/* XXX950 make fatal for 9.5.0. */
   3062 		/* answer = false; */
   3063 	} else if (result == DNS_R_DNAME) {
   3064 		dns_name_format(foundname, altbuf, sizeof altbuf);
   3065 		dns_zone_log(zone, level,
   3066 			     "%s/NS '%s' is below a DNAME '%s' (illegal)",
   3067 			     ownerbuf, namebuf, altbuf);
   3068 		/* XXX950 make fatal for 9.5.0. */
   3069 		/* answer = false; */
   3070 	}
   3071 
   3072 	if (dns_rdataset_isassociated(&a)) {
   3073 		dns_rdataset_disassociate(&a);
   3074 	}
   3075 	if (dns_rdataset_isassociated(&aaaa)) {
   3076 		dns_rdataset_disassociate(&aaaa);
   3077 	}
   3078 	return answer;
   3079 }
   3080 
   3081 static bool
   3082 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
   3083 		     dns_rdataset_t *rdataset) {
   3084 	dns_rdataset_t tmprdataset;
   3085 	isc_result_t result;
   3086 	bool answer = true;
   3087 	bool format = true;
   3088 	int level = ISC_LOG_WARNING;
   3089 	char ownerbuf[DNS_NAME_FORMATSIZE];
   3090 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
   3091 	unsigned int count1 = 0;
   3092 
   3093 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL)) {
   3094 		level = ISC_LOG_ERROR;
   3095 	}
   3096 
   3097 	dns_rdataset_init(&tmprdataset);
   3098 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   3099 	     result = dns_rdataset_next(rdataset))
   3100 	{
   3101 		dns_rdata_t rdata1 = DNS_RDATA_INIT;
   3102 		unsigned int count2 = 0;
   3103 
   3104 		count1++;
   3105 		dns_rdataset_current(rdataset, &rdata1);
   3106 		dns_rdataset_clone(rdataset, &tmprdataset);
   3107 		for (result = dns_rdataset_first(&tmprdataset);
   3108 		     result == ISC_R_SUCCESS;
   3109 		     result = dns_rdataset_next(&tmprdataset))
   3110 		{
   3111 			dns_rdata_t rdata2 = DNS_RDATA_INIT;
   3112 			count2++;
   3113 			if (count1 >= count2) {
   3114 				continue;
   3115 			}
   3116 			dns_rdataset_current(&tmprdataset, &rdata2);
   3117 			if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
   3118 				if (format) {
   3119 					dns_name_format(owner, ownerbuf,
   3120 							sizeof ownerbuf);
   3121 					dns_rdatatype_format(rdata1.type,
   3122 							     typebuf,
   3123 							     sizeof(typebuf));
   3124 					format = false;
   3125 				}
   3126 				dns_zone_log(zone, level,
   3127 					     "%s/%s has "
   3128 					     "semantically identical records",
   3129 					     ownerbuf, typebuf);
   3130 				if (level == ISC_LOG_ERROR) {
   3131 					answer = false;
   3132 				}
   3133 				break;
   3134 			}
   3135 		}
   3136 		dns_rdataset_disassociate(&tmprdataset);
   3137 		if (!format) {
   3138 			break;
   3139 		}
   3140 	}
   3141 	return answer;
   3142 }
   3143 
   3144 static bool
   3145 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
   3146 	dns_dbiterator_t *dbiterator = NULL;
   3147 	dns_dbnode_t *node = NULL;
   3148 	dns_fixedname_t fixed;
   3149 	dns_name_t *name;
   3150 	dns_rdataset_t rdataset;
   3151 	dns_rdatasetiter_t *rdsit = NULL;
   3152 	bool ok = true;
   3153 	isc_result_t result;
   3154 
   3155 	name = dns_fixedname_initname(&fixed);
   3156 	dns_rdataset_init(&rdataset);
   3157 
   3158 	result = dns_db_createiterator(db, 0, &dbiterator);
   3159 	if (result != ISC_R_SUCCESS) {
   3160 		return true;
   3161 	}
   3162 
   3163 	for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
   3164 	     result = dns_dbiterator_next(dbiterator))
   3165 	{
   3166 		result = dns_dbiterator_current(dbiterator, &node, name);
   3167 		if (result != ISC_R_SUCCESS) {
   3168 			continue;
   3169 		}
   3170 
   3171 		result = dns_db_allrdatasets(db, node, NULL, 0, 0, &rdsit);
   3172 		if (result != ISC_R_SUCCESS) {
   3173 			continue;
   3174 		}
   3175 
   3176 		for (result = dns_rdatasetiter_first(rdsit);
   3177 		     result == ISC_R_SUCCESS;
   3178 		     result = dns_rdatasetiter_next(rdsit))
   3179 		{
   3180 			dns_rdatasetiter_current(rdsit, &rdataset);
   3181 			if (!zone_rrset_check_dup(zone, name, &rdataset)) {
   3182 				ok = false;
   3183 			}
   3184 			dns_rdataset_disassociate(&rdataset);
   3185 		}
   3186 		dns_rdatasetiter_destroy(&rdsit);
   3187 		dns_db_detachnode(db, &node);
   3188 	}
   3189 
   3190 	if (node != NULL) {
   3191 		dns_db_detachnode(db, &node);
   3192 	}
   3193 	dns_dbiterator_destroy(&dbiterator);
   3194 
   3195 	return ok;
   3196 }
   3197 
   3198 static bool
   3199 isspf(const dns_rdata_t *rdata) {
   3200 	char buf[1024];
   3201 	const unsigned char *data = rdata->data;
   3202 	unsigned int rdl = rdata->length, i = 0, tl, len;
   3203 
   3204 	while (rdl > 0U) {
   3205 		len = tl = *data;
   3206 		++data;
   3207 		--rdl;
   3208 		INSIST(tl <= rdl);
   3209 		if (len > sizeof(buf) - i - 1) {
   3210 			len = sizeof(buf) - i - 1;
   3211 		}
   3212 		memmove(buf + i, data, len);
   3213 		i += len;
   3214 		data += tl;
   3215 		rdl -= tl;
   3216 	}
   3217 
   3218 	if (i < 6U) {
   3219 		return false;
   3220 	}
   3221 
   3222 	buf[i] = 0;
   3223 	if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' ')) {
   3224 		return true;
   3225 	}
   3226 	return false;
   3227 }
   3228 
   3229 static bool
   3230 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
   3231 	dns_dbiterator_t *dbiterator = NULL;
   3232 	dns_dbnode_t *node = NULL;
   3233 	dns_rdataset_t rdataset;
   3234 	dns_fixedname_t fixed;
   3235 	dns_fixedname_t fixedbottom;
   3236 	dns_rdata_mx_t mx;
   3237 	dns_rdata_ns_t ns;
   3238 	dns_rdata_in_srv_t srv;
   3239 	dns_name_t *name;
   3240 	dns_name_t *bottom;
   3241 	isc_result_t result;
   3242 	bool ok = true, have_spf, have_txt;
   3243 	int level;
   3244 	char namebuf[DNS_NAME_FORMATSIZE];
   3245 	bool logged_algorithm[DST_MAX_ALGS];
   3246 	bool logged_digest_type[DNS_DSDIGEST_MAX + 1];
   3247 
   3248 	name = dns_fixedname_initname(&fixed);
   3249 	bottom = dns_fixedname_initname(&fixedbottom);
   3250 	dns_rdataset_init(&rdataset);
   3251 
   3252 	result = dns_db_createiterator(db, 0, &dbiterator);
   3253 	if (result != ISC_R_SUCCESS) {
   3254 		return true;
   3255 	}
   3256 
   3257 	result = dns_dbiterator_first(dbiterator);
   3258 	while (result == ISC_R_SUCCESS) {
   3259 		result = dns_dbiterator_current(dbiterator, &node, name);
   3260 		if (result != ISC_R_SUCCESS) {
   3261 			goto cleanup;
   3262 		}
   3263 
   3264 		/*
   3265 		 * Is this name visible in the zone?
   3266 		 */
   3267 		if (!dns_name_issubdomain(name, &zone->origin) ||
   3268 		    (dns_name_countlabels(bottom) > 0 &&
   3269 		     dns_name_issubdomain(name, bottom)))
   3270 		{
   3271 			goto next;
   3272 		}
   3273 
   3274 		dns_dbiterator_pause(dbiterator);
   3275 
   3276 		/*
   3277 		 * Check for deprecated KEY algorithms
   3278 		 */
   3279 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_key,
   3280 					     0, 0, &rdataset, NULL);
   3281 		if (result != ISC_R_SUCCESS) {
   3282 			goto checkforns;
   3283 		}
   3284 
   3285 		memset(logged_algorithm, 0, sizeof(logged_algorithm));
   3286 		for (result = dns_rdataset_first(&rdataset);
   3287 		     result == ISC_R_SUCCESS;
   3288 		     result = dns_rdataset_next(&rdataset))
   3289 		{
   3290 			dns_rdata_t rdata = DNS_RDATA_INIT;
   3291 			dns_rdata_key_t key;
   3292 			dns_rdataset_current(&rdataset, &rdata);
   3293 
   3294 			result = dns_rdata_tostruct(&rdata, &key, NULL);
   3295 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3296 
   3297 			/*
   3298 			 * If we ever deprecate a private algorithm use
   3299 			 * dst_algorithm_fromdata() here.
   3300 			 */
   3301 			switch (key.algorithm) {
   3302 			case DNS_KEYALG_RSASHA1:
   3303 			case DNS_KEYALG_NSEC3RSASHA1:
   3304 				if (!logged_algorithm[key.algorithm]) {
   3305 					char algbuf[DNS_SECALG_FORMATSIZE];
   3306 					dns_name_format(name, namebuf,
   3307 							sizeof(namebuf));
   3308 					dns_secalg_format(key.algorithm, algbuf,
   3309 							  sizeof(algbuf));
   3310 					dnssec_log(zone, ISC_LOG_WARNING,
   3311 						   "%s/KEY deprecated "
   3312 						   "algorithm %u (%s)",
   3313 						   namebuf, key.algorithm,
   3314 						   algbuf);
   3315 					logged_algorithm[key.algorithm] = true;
   3316 				}
   3317 				break;
   3318 			default:
   3319 				break;
   3320 			}
   3321 		}
   3322 		dns_rdataset_disassociate(&rdataset);
   3323 
   3324 	checkforns:
   3325 		/*
   3326 		 * Don't check the NS records at the origin.
   3327 		 */
   3328 		if (dns_name_equal(name, &zone->origin)) {
   3329 			goto checkfords;
   3330 		}
   3331 
   3332 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
   3333 					     0, 0, &rdataset, NULL);
   3334 		if (result != ISC_R_SUCCESS) {
   3335 			goto checkfords;
   3336 		}
   3337 
   3338 		/*
   3339 		 * Remember bottom of zone due to NS.
   3340 		 */
   3341 		dns_name_copy(name, bottom);
   3342 
   3343 		result = dns_rdataset_first(&rdataset);
   3344 		while (result == ISC_R_SUCCESS) {
   3345 			dns_rdata_t rdata = DNS_RDATA_INIT;
   3346 			dns_rdataset_current(&rdataset, &rdata);
   3347 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
   3348 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3349 			if (!zone_check_glue(zone, db, &ns.name, name)) {
   3350 				ok = false;
   3351 			}
   3352 			dns_rdata_reset(&rdata);
   3353 			result = dns_rdataset_next(&rdataset);
   3354 		}
   3355 		dns_rdataset_disassociate(&rdataset);
   3356 
   3357 		/*
   3358 		 * Check for deprecated DS digest types.
   3359 		 */
   3360 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds,
   3361 					     0, 0, &rdataset, NULL);
   3362 		if (result != ISC_R_SUCCESS) {
   3363 			goto next;
   3364 		}
   3365 
   3366 		memset(logged_algorithm, 0, sizeof(logged_algorithm));
   3367 		memset(logged_digest_type, 0, sizeof(logged_digest_type));
   3368 		for (result = dns_rdataset_first(&rdataset);
   3369 		     result == ISC_R_SUCCESS;
   3370 		     result = dns_rdataset_next(&rdataset))
   3371 		{
   3372 			dns_rdata_t rdata = DNS_RDATA_INIT;
   3373 			dns_rdataset_current(&rdataset, &rdata);
   3374 			dns_rdata_ds_t ds;
   3375 
   3376 			result = dns_rdata_tostruct(&rdata, &ds, NULL);
   3377 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3378 			switch (ds.digest_type) {
   3379 			case DNS_DSDIGEST_SHA1:
   3380 			case DNS_DSDIGEST_GOST:
   3381 				if (!logged_digest_type[ds.digest_type]) {
   3382 					char algbuf[DNS_DSDIGEST_FORMATSIZE];
   3383 					dns_name_format(name, namebuf,
   3384 							sizeof(namebuf));
   3385 					dns_dsdigest_format(ds.digest_type,
   3386 							    algbuf,
   3387 							    sizeof(algbuf));
   3388 					dnssec_log(zone, ISC_LOG_WARNING,
   3389 						   "%s/DS deprecated digest "
   3390 						   "type %u (%s)",
   3391 						   namebuf, ds.digest_type,
   3392 						   algbuf);
   3393 					logged_digest_type[ds.digest_type] =
   3394 						true;
   3395 				}
   3396 				break;
   3397 			}
   3398 
   3399 			/*
   3400 			 * If we ever deprecate a private algorithm use
   3401 			 * dst_algorithm_fromdata() here.
   3402 			 */
   3403 			switch (ds.algorithm) {
   3404 			case DNS_KEYALG_RSASHA1:
   3405 			case DNS_KEYALG_NSEC3RSASHA1:
   3406 				if (!logged_algorithm[ds.algorithm]) {
   3407 					char algbuf[DNS_SECALG_FORMATSIZE];
   3408 					dns_name_format(name, namebuf,
   3409 							sizeof(namebuf));
   3410 					dns_secalg_format(ds.algorithm, algbuf,
   3411 							  sizeof(algbuf));
   3412 					dnssec_log(zone, ISC_LOG_WARNING,
   3413 						   "%s/DS deprecated algorithm "
   3414 						   "%u (%s)",
   3415 						   namebuf, ds.algorithm,
   3416 						   algbuf);
   3417 					logged_algorithm[ds.algorithm] = true;
   3418 				}
   3419 				break;
   3420 			}
   3421 		}
   3422 		dns_rdataset_disassociate(&rdataset);
   3423 
   3424 		goto next;
   3425 
   3426 	checkfords:
   3427 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds,
   3428 					     0, 0, &rdataset, NULL);
   3429 		if (result != ISC_R_SUCCESS) {
   3430 			goto checkfordname;
   3431 		}
   3432 		dns_rdataset_disassociate(&rdataset);
   3433 
   3434 		if (zone->type == dns_zone_primary) {
   3435 			level = ISC_LOG_ERROR;
   3436 			ok = false;
   3437 		} else {
   3438 			level = ISC_LOG_WARNING;
   3439 		}
   3440 		dns_name_format(name, namebuf, sizeof(namebuf));
   3441 		dns_zone_log(zone, level, "DS not at delegation point (%s)",
   3442 			     namebuf);
   3443 
   3444 	checkfordname:
   3445 		result = dns_db_findrdataset(db, node, NULL,
   3446 					     dns_rdatatype_dname, 0, 0,
   3447 					     &rdataset, NULL);
   3448 		if (result == ISC_R_SUCCESS) {
   3449 			/*
   3450 			 * Remember bottom of zone due to DNAME.
   3451 			 */
   3452 			dns_name_copy(name, bottom);
   3453 			dns_rdataset_disassociate(&rdataset);
   3454 		}
   3455 
   3456 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
   3457 					     0, 0, &rdataset, NULL);
   3458 		if (result != ISC_R_SUCCESS) {
   3459 			goto checksrv;
   3460 		}
   3461 		result = dns_rdataset_first(&rdataset);
   3462 		while (result == ISC_R_SUCCESS) {
   3463 			dns_rdata_t rdata = DNS_RDATA_INIT;
   3464 			dns_rdataset_current(&rdataset, &rdata);
   3465 			result = dns_rdata_tostruct(&rdata, &mx, NULL);
   3466 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3467 			if (!zone_check_mx(zone, db, &mx.mx, name)) {
   3468 				ok = false;
   3469 			}
   3470 			dns_rdata_reset(&rdata);
   3471 			result = dns_rdataset_next(&rdataset);
   3472 		}
   3473 		dns_rdataset_disassociate(&rdataset);
   3474 
   3475 	checksrv:
   3476 		if (zone->rdclass != dns_rdataclass_in) {
   3477 			goto next;
   3478 		}
   3479 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
   3480 					     0, 0, &rdataset, NULL);
   3481 		if (result != ISC_R_SUCCESS) {
   3482 			goto checkspf;
   3483 		}
   3484 		result = dns_rdataset_first(&rdataset);
   3485 		while (result == ISC_R_SUCCESS) {
   3486 			dns_rdata_t rdata = DNS_RDATA_INIT;
   3487 			dns_rdataset_current(&rdataset, &rdata);
   3488 			result = dns_rdata_tostruct(&rdata, &srv, NULL);
   3489 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3490 			if (!zone_check_srv(zone, db, &srv.target, name)) {
   3491 				ok = false;
   3492 			}
   3493 			dns_rdata_reset(&rdata);
   3494 			result = dns_rdataset_next(&rdataset);
   3495 		}
   3496 		dns_rdataset_disassociate(&rdataset);
   3497 
   3498 	checkspf:
   3499 		/*
   3500 		 * Check if there is a type SPF record without an
   3501 		 * SPF-formatted type TXT record also being present.
   3502 		 */
   3503 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) {
   3504 			goto next;
   3505 		}
   3506 		if (zone->rdclass != dns_rdataclass_in) {
   3507 			goto next;
   3508 		}
   3509 		have_spf = have_txt = false;
   3510 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
   3511 					     0, 0, &rdataset, NULL);
   3512 		if (result == ISC_R_SUCCESS) {
   3513 			dns_rdataset_disassociate(&rdataset);
   3514 			have_spf = true;
   3515 		}
   3516 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
   3517 					     0, 0, &rdataset, NULL);
   3518 		if (result != ISC_R_SUCCESS) {
   3519 			goto notxt;
   3520 		}
   3521 		result = dns_rdataset_first(&rdataset);
   3522 		while (result == ISC_R_SUCCESS) {
   3523 			dns_rdata_t rdata = DNS_RDATA_INIT;
   3524 			dns_rdataset_current(&rdataset, &rdata);
   3525 			have_txt = isspf(&rdata);
   3526 			dns_rdata_reset(&rdata);
   3527 			if (have_txt) {
   3528 				break;
   3529 			}
   3530 			result = dns_rdataset_next(&rdataset);
   3531 		}
   3532 		dns_rdataset_disassociate(&rdataset);
   3533 
   3534 	notxt:
   3535 		if (have_spf && !have_txt) {
   3536 			dns_name_format(name, namebuf, sizeof(namebuf));
   3537 			dns_zone_log(zone, ISC_LOG_WARNING,
   3538 				     "'%s' found type "
   3539 				     "SPF record but no SPF TXT record found, "
   3540 				     "add matching type TXT record",
   3541 				     namebuf);
   3542 		}
   3543 
   3544 	next:
   3545 		dns_db_detachnode(db, &node);
   3546 		result = dns_dbiterator_next(dbiterator);
   3547 	}
   3548 
   3549 cleanup:
   3550 	if (node != NULL) {
   3551 		dns_db_detachnode(db, &node);
   3552 	}
   3553 	dns_dbiterator_destroy(&dbiterator);
   3554 
   3555 	return ok;
   3556 }
   3557 
   3558 /*
   3559  * OpenSSL verification of RSA keys with exponent 3 is known to be
   3560  * broken prior OpenSSL 0.9.8c/0.9.7k.	Look for such keys and warn
   3561  * if they are in use.
   3562  */
   3563 static void
   3564 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
   3565 	dns_dbnode_t *node = NULL;
   3566 	dns_dbversion_t *version = NULL;
   3567 	dns_rdata_dnskey_t dnskey;
   3568 	dns_rdataset_t rdataset;
   3569 	isc_result_t result;
   3570 	bool logged_algorithm[DST_MAX_ALGS] = { 0 };
   3571 	bool alldeprecated = true;
   3572 
   3573 	result = dns_db_findnode(db, &zone->origin, false, &node);
   3574 	if (result != ISC_R_SUCCESS) {
   3575 		goto cleanup;
   3576 	}
   3577 
   3578 	dns_db_currentversion(db, &version);
   3579 	dns_rdataset_init(&rdataset);
   3580 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
   3581 				     dns_rdatatype_none, 0, &rdataset, NULL);
   3582 	if (result != ISC_R_SUCCESS) {
   3583 		goto cleanup;
   3584 	}
   3585 
   3586 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   3587 	     result = dns_rdataset_next(&rdataset))
   3588 	{
   3589 		char algbuf[DNS_SECALG_FORMATSIZE];
   3590 		dns_rdata_t rdata = DNS_RDATA_INIT;
   3591 		dns_rdataset_current(&rdataset, &rdata);
   3592 		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
   3593 		INSIST(result == ISC_R_SUCCESS);
   3594 
   3595 		/*
   3596 		 * RFC 3110, section 4: Performance Considerations:
   3597 		 *
   3598 		 * A public exponent of 3 minimizes the effort needed to verify
   3599 		 * a signature.  Use of 3 as the public exponent is weak for
   3600 		 * confidentiality uses since, if the same data can be collected
   3601 		 * encrypted under three different keys with an exponent of 3
   3602 		 * then, using the Chinese Remainder Theorem [NETSEC], the
   3603 		 * original plain text can be easily recovered.  If a key is
   3604 		 * known to be used only for authentication, as is the case with
   3605 		 * DNSSEC, then an exponent of 3 is acceptable.  However other
   3606 		 * applications in the future may wish to leverage DNS
   3607 		 * distributed keys for applications that do require
   3608 		 * confidentiality.  For keys which might have such other uses,
   3609 		 * a more conservative choice would be 65537 (F4, the fourth
   3610 		 * fermat number).
   3611 		 */
   3612 		if (dnskey.datalen > 1 && dnskey.data[0] == 1 &&
   3613 		    dnskey.data[1] == 3 &&
   3614 		    (dnskey.algorithm == DNS_KEYALG_RSAMD5 ||
   3615 		     dnskey.algorithm == DNS_KEYALG_RSASHA1 ||
   3616 		     dnskey.algorithm == DNS_KEYALG_NSEC3RSASHA1 ||
   3617 		     dnskey.algorithm == DNS_KEYALG_RSASHA256 ||
   3618 		     dnskey.algorithm == DNS_KEYALG_RSASHA512))
   3619 		{
   3620 			char algorithm[DNS_SECALG_FORMATSIZE];
   3621 			isc_region_t r;
   3622 
   3623 			dns_rdata_toregion(&rdata, &r);
   3624 			dns_secalg_format(dnskey.algorithm, algorithm,
   3625 					  sizeof(algorithm));
   3626 
   3627 			dnssec_log(zone, ISC_LOG_WARNING,
   3628 				   "weak %s (%u) key found (exponent=3, id=%u)",
   3629 				   algorithm, dnskey.algorithm,
   3630 				   dst_region_computeid(&r));
   3631 		}
   3632 
   3633 		switch (dnskey.algorithm) {
   3634 		case DNS_KEYALG_RSAMD5:
   3635 		case DNS_KEYALG_DSA:
   3636 		case DNS_KEYALG_RSASHA1:
   3637 		case DNS_KEYALG_NSEC3DSA:
   3638 		case DNS_KEYALG_NSEC3RSASHA1:
   3639 		case DNS_KEYALG_ECCGOST:
   3640 			if (!logged_algorithm[dnskey.algorithm]) {
   3641 				dns_secalg_format(dnskey.algorithm, algbuf,
   3642 						  sizeof(algbuf));
   3643 				dnssec_log(zone, ISC_LOG_WARNING,
   3644 					   "deprecated DNSKEY algorithm found: "
   3645 					   "%u (%s)\n",
   3646 					   dnskey.algorithm, algbuf);
   3647 				logged_algorithm[dnskey.algorithm] = true;
   3648 			}
   3649 			break;
   3650 		default:
   3651 			alldeprecated = false;
   3652 			break;
   3653 		}
   3654 	}
   3655 	dns_rdataset_disassociate(&rdataset);
   3656 
   3657 	if (alldeprecated) {
   3658 		dnssec_log(zone, ISC_LOG_WARNING,
   3659 			   "all DNSKEY algorithms found are deprecated");
   3660 	}
   3661 
   3662 cleanup:
   3663 	if (node != NULL) {
   3664 		dns_db_detachnode(db, &node);
   3665 	}
   3666 	if (version != NULL) {
   3667 		dns_db_closeversion(db, &version, false);
   3668 	}
   3669 }
   3670 
   3671 static void
   3672 resume_signingwithkey(dns_zone_t *zone) {
   3673 	dns_dbnode_t *node = NULL;
   3674 	dns_dbversion_t *version = NULL;
   3675 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3676 	dns_rdataset_t rdataset;
   3677 	isc_result_t result;
   3678 	dns_db_t *db = NULL;
   3679 
   3680 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3681 	if (zone->db != NULL) {
   3682 		dns_db_attach(zone->db, &db);
   3683 	}
   3684 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3685 	if (db == NULL) {
   3686 		goto cleanup;
   3687 	}
   3688 
   3689 	result = dns_db_findnode(db, &zone->origin, false, &node);
   3690 	if (result != ISC_R_SUCCESS) {
   3691 		goto cleanup;
   3692 	}
   3693 
   3694 	dns_db_currentversion(db, &version);
   3695 	dns_rdataset_init(&rdataset);
   3696 	result = dns_db_findrdataset(db, node, version, zone->privatetype,
   3697 				     dns_rdatatype_none, 0, &rdataset, NULL);
   3698 	if (result != ISC_R_SUCCESS) {
   3699 		INSIST(!dns_rdataset_isassociated(&rdataset));
   3700 		goto cleanup;
   3701 	}
   3702 
   3703 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   3704 	     result = dns_rdataset_next(&rdataset))
   3705 	{
   3706 		dns_rdataset_current(&rdataset, &rdata);
   3707 		if (rdata.length != 5 || rdata.data[0] == 0 ||
   3708 		    rdata.data[4] != 0)
   3709 		{
   3710 			dns_rdata_reset(&rdata);
   3711 			continue;
   3712 		}
   3713 
   3714 		result = zone_signwithkey(zone, rdata.data[0],
   3715 					  (rdata.data[1] << 8) | rdata.data[2],
   3716 					  rdata.data[3], false);
   3717 		if (result != ISC_R_SUCCESS) {
   3718 			dnssec_log(zone, ISC_LOG_ERROR,
   3719 				   "zone_signwithkey failed: %s",
   3720 				   isc_result_totext(result));
   3721 		}
   3722 		dns_rdata_reset(&rdata);
   3723 	}
   3724 	dns_rdataset_disassociate(&rdataset);
   3725 
   3726 cleanup:
   3727 	if (db != NULL) {
   3728 		if (node != NULL) {
   3729 			dns_db_detachnode(db, &node);
   3730 		}
   3731 		if (version != NULL) {
   3732 			dns_db_closeversion(db, &version, false);
   3733 		}
   3734 		dns_db_detach(&db);
   3735 	}
   3736 }
   3737 
   3738 /*
   3739  * Initiate adding/removing NSEC3 records belonging to the chain defined by the
   3740  * supplied NSEC3PARAM RDATA.
   3741  *
   3742  * Zone must be locked by caller.
   3743  */
   3744 static isc_result_t
   3745 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
   3746 	dns_nsec3chain_t *nsec3chain, *current;
   3747 	dns_dbversion_t *version = NULL;
   3748 	bool nseconly = false, nsec3ok = false;
   3749 	isc_result_t result;
   3750 	isc_time_t now;
   3751 	unsigned int options = 0;
   3752 	char saltbuf[255 * 2 + 1];
   3753 	char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
   3754 	dns_db_t *db = NULL;
   3755 
   3756 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3757 	if (zone->db != NULL) {
   3758 		dns_db_attach(zone->db, &db);
   3759 	}
   3760 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3761 
   3762 	if (db == NULL) {
   3763 		result = ISC_R_SUCCESS;
   3764 		goto cleanup;
   3765 	}
   3766 
   3767 	/*
   3768 	 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
   3769 	 * chain from it is pointless as it would not be possible for the
   3770 	 * latter to exist in the first place.
   3771 	 */
   3772 	dns_db_currentversion(db, &version);
   3773 	result = dns_nsec_nseconly(db, version, NULL, &nseconly);
   3774 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
   3775 	dns_db_closeversion(db, &version, false);
   3776 	if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
   3777 		result = ISC_R_SUCCESS;
   3778 		goto cleanup;
   3779 	}
   3780 
   3781 	/*
   3782 	 * Allocate and initialize structure preserving state of
   3783 	 * adding/removing records belonging to this NSEC3 chain between
   3784 	 * separate zone_nsec3chain() calls.
   3785 	 */
   3786 	nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
   3787 
   3788 	nsec3chain->magic = 0;
   3789 	nsec3chain->done = false;
   3790 	nsec3chain->db = NULL;
   3791 	nsec3chain->dbiterator = NULL;
   3792 	nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
   3793 	nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
   3794 	nsec3chain->nsec3param.hash = nsec3param->hash;
   3795 	nsec3chain->nsec3param.iterations = nsec3param->iterations;
   3796 	nsec3chain->nsec3param.flags = nsec3param->flags;
   3797 	nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
   3798 	memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
   3799 	nsec3chain->nsec3param.salt = nsec3chain->salt;
   3800 	nsec3chain->seen_nsec = false;
   3801 	nsec3chain->delete_nsec = false;
   3802 	nsec3chain->save_delete_nsec = false;
   3803 
   3804 	/*
   3805 	 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
   3806 	 */
   3807 	if (nsec3param->flags == 0) {
   3808 		strlcpy(flags, "NONE", sizeof(flags));
   3809 	} else {
   3810 		flags[0] = '\0';
   3811 		if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
   3812 			strlcat(flags, "REMOVE", sizeof(flags));
   3813 		}
   3814 		if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
   3815 			if (flags[0] == '\0') {
   3816 				strlcpy(flags, "INITIAL", sizeof(flags));
   3817 			} else {
   3818 				strlcat(flags, "|INITIAL", sizeof(flags));
   3819 			}
   3820 		}
   3821 		if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
   3822 			if (flags[0] == '\0') {
   3823 				strlcpy(flags, "CREATE", sizeof(flags));
   3824 			} else {
   3825 				strlcat(flags, "|CREATE", sizeof(flags));
   3826 			}
   3827 		}
   3828 		if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
   3829 			if (flags[0] == '\0') {
   3830 				strlcpy(flags, "NONSEC", sizeof(flags));
   3831 			} else {
   3832 				strlcat(flags, "|NONSEC", sizeof(flags));
   3833 			}
   3834 		}
   3835 		if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
   3836 			if (flags[0] == '\0') {
   3837 				strlcpy(flags, "OPTOUT", sizeof(flags));
   3838 			} else {
   3839 				strlcat(flags, "|OPTOUT", sizeof(flags));
   3840 			}
   3841 		}
   3842 	}
   3843 	result = dns_nsec3param_salttotext(nsec3param, saltbuf,
   3844 					   sizeof(saltbuf));
   3845 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3846 	dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
   3847 		   nsec3param->hash, flags, nsec3param->iterations, saltbuf);
   3848 
   3849 	/*
   3850 	 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
   3851 	 * currently being processed, interrupt its processing to avoid
   3852 	 * simultaneously adding and removing records for the same NSEC3 chain.
   3853 	 */
   3854 	for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL;
   3855 	     current = ISC_LIST_NEXT(current, link))
   3856 	{
   3857 		if ((current->db == db) &&
   3858 		    (current->nsec3param.hash == nsec3param->hash) &&
   3859 		    (current->nsec3param.iterations ==
   3860 		     nsec3param->iterations) &&
   3861 		    (current->nsec3param.salt_length ==
   3862 		     nsec3param->salt_length) &&
   3863 		    memcmp(current->nsec3param.salt, nsec3param->salt,
   3864 			   nsec3param->salt_length) == 0)
   3865 		{
   3866 			current->done = true;
   3867 		}
   3868 	}
   3869 
   3870 	/*
   3871 	 * Attach zone database to the structure initialized above and create
   3872 	 * an iterator for it with appropriate options in order to avoid
   3873 	 * creating NSEC3 records for NSEC3 records.
   3874 	 */
   3875 	dns_db_attach(db, &nsec3chain->db);
   3876 	if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
   3877 		options = DNS_DB_NONSEC3;
   3878 	}
   3879 	result = dns_db_createiterator(nsec3chain->db, options,
   3880 				       &nsec3chain->dbiterator);
   3881 	if (result == ISC_R_SUCCESS) {
   3882 		result = dns_dbiterator_first(nsec3chain->dbiterator);
   3883 	}
   3884 	if (result == ISC_R_SUCCESS) {
   3885 		/*
   3886 		 * Database iterator initialization succeeded.  We are now
   3887 		 * ready to kick off adding/removing records belonging to this
   3888 		 * NSEC3 chain.  Append the structure initialized above to the
   3889 		 * "nsec3chain" list for the zone and set the appropriate zone
   3890 		 * timer so that zone_nsec3chain() is called as soon as
   3891 		 * possible.
   3892 		 */
   3893 		dns_dbiterator_pause(nsec3chain->dbiterator);
   3894 		ISC_LIST_INITANDAPPEND(zone->nsec3chain, nsec3chain, link);
   3895 		nsec3chain = NULL;
   3896 		if (isc_time_isepoch(&zone->nsec3chaintime)) {
   3897 			now = isc_time_now();
   3898 			zone->nsec3chaintime = now;
   3899 			if (zone->loop != NULL) {
   3900 				zone_settimer(zone, &now);
   3901 			}
   3902 		}
   3903 	}
   3904 
   3905 	if (nsec3chain != NULL) {
   3906 		if (nsec3chain->db != NULL) {
   3907 			dns_db_detach(&nsec3chain->db);
   3908 		}
   3909 		if (nsec3chain->dbiterator != NULL) {
   3910 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
   3911 		}
   3912 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   3913 	}
   3914 
   3915 cleanup:
   3916 	if (db != NULL) {
   3917 		dns_db_detach(&db);
   3918 	}
   3919 	return result;
   3920 }
   3921 
   3922 /*
   3923  * Find private-type records at the zone apex which signal that an NSEC3 chain
   3924  * should be added or removed.  For each such record, extract NSEC3PARAM RDATA
   3925  * and pass it to zone_addnsec3chain().
   3926  *
   3927  * Zone must be locked by caller.
   3928  */
   3929 static void
   3930 resume_addnsec3chain(dns_zone_t *zone) {
   3931 	dns_dbnode_t *node = NULL;
   3932 	dns_dbversion_t *version = NULL;
   3933 	dns_rdataset_t rdataset;
   3934 	isc_result_t result;
   3935 	dns_rdata_nsec3param_t nsec3param;
   3936 	bool nseconly = false, nsec3ok = false;
   3937 	dns_db_t *db = NULL;
   3938 
   3939 	INSIST(LOCKED_ZONE(zone));
   3940 
   3941 	if (zone->privatetype == 0) {
   3942 		return;
   3943 	}
   3944 
   3945 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3946 	if (zone->db != NULL) {
   3947 		dns_db_attach(zone->db, &db);
   3948 	}
   3949 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3950 	if (db == NULL) {
   3951 		goto cleanup;
   3952 	}
   3953 
   3954 	result = dns_db_findnode(db, &zone->origin, false, &node);
   3955 	if (result != ISC_R_SUCCESS) {
   3956 		goto cleanup;
   3957 	}
   3958 
   3959 	dns_db_currentversion(db, &version);
   3960 
   3961 	/*
   3962 	 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
   3963 	 * apex to exist and contain no keys using NSEC-only algorithms.
   3964 	 */
   3965 	result = dns_nsec_nseconly(db, version, NULL, &nseconly);
   3966 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
   3967 
   3968 	/*
   3969 	 * Get the RRset containing all private-type records at the zone apex.
   3970 	 */
   3971 	dns_rdataset_init(&rdataset);
   3972 	result = dns_db_findrdataset(db, node, version, zone->privatetype,
   3973 				     dns_rdatatype_none, 0, &rdataset, NULL);
   3974 	if (result != ISC_R_SUCCESS) {
   3975 		INSIST(!dns_rdataset_isassociated(&rdataset));
   3976 		goto cleanup;
   3977 	}
   3978 
   3979 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   3980 	     result = dns_rdataset_next(&rdataset))
   3981 	{
   3982 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   3983 		dns_rdata_t rdata = DNS_RDATA_INIT;
   3984 		dns_rdata_t private = DNS_RDATA_INIT;
   3985 
   3986 		dns_rdataset_current(&rdataset, &private);
   3987 		/*
   3988 		 * Try extracting NSEC3PARAM RDATA from this private-type
   3989 		 * record.  Failure means this private-type record does not
   3990 		 * represent an NSEC3PARAM record, so skip it.
   3991 		 */
   3992 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
   3993 						sizeof(buf)))
   3994 		{
   3995 			continue;
   3996 		}
   3997 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   3998 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3999 		if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
   4000 		    ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
   4001 		{
   4002 			/*
   4003 			 * Pass the NSEC3PARAM RDATA contained in this
   4004 			 * private-type record to zone_addnsec3chain() so that
   4005 			 * it can kick off adding or removing NSEC3 records.
   4006 			 */
   4007 			result = zone_addnsec3chain(zone, &nsec3param);
   4008 			if (result != ISC_R_SUCCESS) {
   4009 				dnssec_log(zone, ISC_LOG_ERROR,
   4010 					   "zone_addnsec3chain failed: %s",
   4011 					   isc_result_totext(result));
   4012 			}
   4013 		}
   4014 	}
   4015 	dns_rdataset_disassociate(&rdataset);
   4016 
   4017 cleanup:
   4018 	if (db != NULL) {
   4019 		if (node != NULL) {
   4020 			dns_db_detachnode(db, &node);
   4021 		}
   4022 		if (version != NULL) {
   4023 			dns_db_closeversion(db, &version, false);
   4024 		}
   4025 		dns_db_detach(&db);
   4026 	}
   4027 }
   4028 
   4029 static void
   4030 set_resigntime(dns_zone_t *zone) {
   4031 	dns_fixedname_t fixed;
   4032 	isc_stdtime_t resign;
   4033 	isc_result_t result;
   4034 	uint32_t nanosecs;
   4035 	dns_db_t *db = NULL;
   4036 	dns_typepair_t typepair;
   4037 
   4038 	INSIST(LOCKED_ZONE(zone));
   4039 
   4040 	/* We only re-sign zones that can be dynamically updated */
   4041 	if (!dns_zone_isdynamic(zone, false)) {
   4042 		return;
   4043 	}
   4044 
   4045 	if (inline_raw(zone)) {
   4046 		return;
   4047 	}
   4048 
   4049 	dns_fixedname_init(&fixed);
   4050 
   4051 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   4052 	if (zone->db != NULL) {
   4053 		dns_db_attach(zone->db, &db);
   4054 	}
   4055 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   4056 	if (db == NULL) {
   4057 		isc_time_settoepoch(&zone->resigntime);
   4058 		return;
   4059 	}
   4060 
   4061 	result = dns_db_getsigningtime(db, &resign, dns_fixedname_name(&fixed),
   4062 				       &typepair);
   4063 	if (result != ISC_R_SUCCESS) {
   4064 		isc_time_settoepoch(&zone->resigntime);
   4065 		goto cleanup;
   4066 	}
   4067 
   4068 	resign -= dns_zone_getsigresigninginterval(zone);
   4069 	nanosecs = isc_random_uniform(1000000000);
   4070 	isc_time_set(&zone->resigntime, resign, nanosecs);
   4071 
   4072 cleanup:
   4073 	dns_db_detach(&db);
   4074 	return;
   4075 }
   4076 
   4077 static isc_result_t
   4078 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
   4079 	bool ok = false;
   4080 	dns_dbnode_t *node = NULL;
   4081 	dns_dbversion_t *version = NULL;
   4082 	dns_rdata_nsec3param_t nsec3param;
   4083 	dns_rdataset_t rdataset;
   4084 	isc_result_t result;
   4085 	bool dynamic = (zone->type == dns_zone_primary)
   4086 			       ? dns_zone_isdynamic(zone, false)
   4087 			       : false;
   4088 
   4089 	dns_rdataset_init(&rdataset);
   4090 	result = dns_db_findnode(db, &zone->origin, false, &node);
   4091 	if (result != ISC_R_SUCCESS) {
   4092 		dns_zone_log(zone, ISC_LOG_ERROR,
   4093 			     "nsec3param lookup failure: %s",
   4094 			     isc_result_totext(result));
   4095 		return result;
   4096 	}
   4097 	dns_db_currentversion(db, &version);
   4098 
   4099 	result = dns_db_findrdataset(db, node, version,
   4100 				     dns_rdatatype_nsec3param,
   4101 				     dns_rdatatype_none, 0, &rdataset, NULL);
   4102 	if (result == ISC_R_NOTFOUND) {
   4103 		INSIST(!dns_rdataset_isassociated(&rdataset));
   4104 		result = ISC_R_SUCCESS;
   4105 		goto cleanup;
   4106 	}
   4107 	if (result != ISC_R_SUCCESS) {
   4108 		INSIST(!dns_rdataset_isassociated(&rdataset));
   4109 		dns_zone_log(zone, ISC_LOG_ERROR,
   4110 			     "nsec3param lookup failure: %s",
   4111 			     isc_result_totext(result));
   4112 		goto cleanup;
   4113 	}
   4114 
   4115 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   4116 	     result = dns_rdataset_next(&rdataset))
   4117 	{
   4118 		dns_rdata_t rdata = DNS_RDATA_INIT;
   4119 
   4120 		dns_rdataset_current(&rdataset, &rdata);
   4121 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   4122 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4123 
   4124 		/*
   4125 		 * For dynamic zones we must support every algorithm so we
   4126 		 * can regenerate all the NSEC3 chains.
   4127 		 * For non-dynamic zones we only need to find a supported
   4128 		 * algorithm.
   4129 		 */
   4130 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
   4131 		    nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
   4132 		{
   4133 			dns_zone_log(zone, ISC_LOG_WARNING,
   4134 				     "nsec3 test \"unknown\" hash algorithm "
   4135 				     "found: %u",
   4136 				     nsec3param.hash);
   4137 			ok = true;
   4138 		} else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
   4139 			if (dynamic) {
   4140 				dns_zone_log(zone, ISC_LOG_ERROR,
   4141 					     "unsupported nsec3 hash algorithm"
   4142 					     " in dynamic zone: %u",
   4143 					     nsec3param.hash);
   4144 				result = DNS_R_BADZONE;
   4145 				/* Stop second error message. */
   4146 				ok = true;
   4147 				break;
   4148 			} else {
   4149 				dns_zone_log(zone, ISC_LOG_WARNING,
   4150 					     "unsupported nsec3 hash "
   4151 					     "algorithm: %u",
   4152 					     nsec3param.hash);
   4153 			}
   4154 		} else {
   4155 			ok = true;
   4156 		}
   4157 
   4158 		/*
   4159 		 * Warn if the zone has excessive NSEC3 iterations.
   4160 		 */
   4161 		if (nsec3param.iterations > dns_nsec3_maxiterations()) {
   4162 			dnssec_log(zone, ISC_LOG_WARNING,
   4163 				   "excessive NSEC3PARAM iterations %u > %u",
   4164 				   nsec3param.iterations,
   4165 				   dns_nsec3_maxiterations());
   4166 		}
   4167 	}
   4168 	if (result == ISC_R_NOMORE) {
   4169 		result = ISC_R_SUCCESS;
   4170 	}
   4171 
   4172 	if (!ok) {
   4173 		result = DNS_R_BADZONE;
   4174 		dns_zone_log(zone, ISC_LOG_ERROR,
   4175 			     "no supported nsec3 hash algorithm");
   4176 	}
   4177 
   4178 cleanup:
   4179 	if (dns_rdataset_isassociated(&rdataset)) {
   4180 		dns_rdataset_disassociate(&rdataset);
   4181 	}
   4182 	dns_db_closeversion(db, &version, false);
   4183 	dns_db_detachnode(db, &node);
   4184 	return result;
   4185 }
   4186 
   4187 /*
   4188  * Set the timer for refreshing the key zone to the soonest future time
   4189  * of the set (current timer, keydata->refresh, keydata->addhd,
   4190  * keydata->removehd).
   4191  */
   4192 static void
   4193 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
   4194 		    isc_stdtime_t now, bool force) {
   4195 	isc_stdtime_t then;
   4196 	isc_time_t timenow, timethen;
   4197 	char timebuf[80];
   4198 
   4199 	ENTER;
   4200 	then = key->refresh;
   4201 	if (force) {
   4202 		then = now;
   4203 	}
   4204 	if (key->addhd > now && key->addhd < then) {
   4205 		then = key->addhd;
   4206 	}
   4207 	if (key->removehd > now && key->removehd < then) {
   4208 		then = key->removehd;
   4209 	}
   4210 
   4211 	timenow = isc_time_now();
   4212 	if (then > now) {
   4213 		DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
   4214 	} else {
   4215 		timethen = timenow;
   4216 	}
   4217 	if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
   4218 	    isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
   4219 	{
   4220 		zone->refreshkeytime = timethen;
   4221 	}
   4222 
   4223 	isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   4224 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
   4225 	zone_settimer(zone, &timenow);
   4226 }
   4227 
   4228 /*
   4229  * If keynode references a key or a DS rdataset, and if the key
   4230  * zone does not contain a KEYDATA record for the corresponding name,
   4231  * then create an empty KEYDATA and push it into the zone as a placeholder,
   4232  * then schedule a key refresh immediately. This new KEYDATA record will be
   4233  * updated during the refresh.
   4234  *
   4235  * If the key zone is changed, set '*changed' to true.
   4236  */
   4237 static isc_result_t
   4238 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   4239 	       dns_diff_t *diff, dns_keynode_t *keynode, dns_name_t *keyname,
   4240 	       bool *changed) {
   4241 	isc_result_t result = ISC_R_SUCCESS;
   4242 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4243 	dns_rdata_keydata_t kd;
   4244 	unsigned char rrdata[4096];
   4245 	isc_buffer_t rrdatabuf;
   4246 	isc_stdtime_t now = isc_stdtime_now();
   4247 
   4248 	REQUIRE(keynode != NULL);
   4249 
   4250 	ENTER;
   4251 
   4252 	/*
   4253 	 * If the keynode has no trust anchor set, we shouldn't be here.
   4254 	 */
   4255 	if (!dns_keynode_dsset(keynode, NULL)) {
   4256 		return ISC_R_FAILURE;
   4257 	}
   4258 
   4259 	memset(&kd, 0, sizeof(kd));
   4260 	kd.common.rdclass = zone->rdclass;
   4261 	kd.common.rdtype = dns_rdatatype_keydata;
   4262 	ISC_LINK_INIT(&kd.common, link);
   4263 
   4264 	isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
   4265 
   4266 	CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass, dns_rdatatype_keydata,
   4267 				   &kd, &rrdatabuf));
   4268 	/* Add rdata to zone. */
   4269 	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, keyname, 0, &rdata));
   4270 	*changed = true;
   4271 
   4272 	/* Refresh new keys from the zone apex as soon as possible. */
   4273 	set_refreshkeytimer(zone, &kd, now, true);
   4274 	return ISC_R_SUCCESS;
   4275 
   4276 cleanup:
   4277 	return result;
   4278 }
   4279 
   4280 /*
   4281  * Remove from the key zone all the KEYDATA records found in rdataset.
   4282  */
   4283 static isc_result_t
   4284 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
   4285 	       dns_name_t *name, dns_rdataset_t *rdataset) {
   4286 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4287 	isc_result_t result, uresult;
   4288 
   4289 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   4290 	     result = dns_rdataset_next(rdataset))
   4291 	{
   4292 		dns_rdata_reset(&rdata);
   4293 		dns_rdataset_current(rdataset, &rdata);
   4294 		uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name, 0,
   4295 					&rdata);
   4296 		if (uresult != ISC_R_SUCCESS) {
   4297 			return uresult;
   4298 		}
   4299 	}
   4300 	if (result == ISC_R_NOMORE) {
   4301 		result = ISC_R_SUCCESS;
   4302 	}
   4303 	return result;
   4304 }
   4305 
   4306 /*
   4307  * Compute the DNSSEC key ID for a DNSKEY record.
   4308  */
   4309 static isc_result_t
   4310 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
   4311 	    dns_keytag_t *tag) {
   4312 	isc_result_t result;
   4313 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4314 	unsigned char data[4096];
   4315 	isc_buffer_t buffer;
   4316 	dst_key_t *dstkey = NULL;
   4317 
   4318 	isc_buffer_init(&buffer, data, sizeof(data));
   4319 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
   4320 			     dns_rdatatype_dnskey, dnskey, &buffer);
   4321 
   4322 	result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
   4323 	if (result == ISC_R_SUCCESS) {
   4324 		*tag = dst_key_id(dstkey);
   4325 		dst_key_free(&dstkey);
   4326 	}
   4327 
   4328 	return result;
   4329 }
   4330 
   4331 /*
   4332  * Synth-from-dnssec callbacks to add/delete names from namespace tree.
   4333  */
   4334 static void
   4335 sfd_add(const dns_name_t *name, void *arg) {
   4336 	if (arg != NULL) {
   4337 		dns_view_sfd_add(arg, name);
   4338 	}
   4339 }
   4340 
   4341 static void
   4342 sfd_del(const dns_name_t *name, void *arg) {
   4343 	if (arg != NULL) {
   4344 		dns_view_sfd_del(arg, name);
   4345 	}
   4346 }
   4347 
   4348 /*
   4349  * Add key to the security roots.
   4350  */
   4351 static void
   4352 trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
   4353 	  bool initial) {
   4354 	isc_result_t result;
   4355 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4356 	unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
   4357 	isc_buffer_t buffer;
   4358 	dns_keytable_t *sr = NULL;
   4359 	dns_rdata_ds_t ds;
   4360 
   4361 	result = dns_view_getsecroots(zone->view, &sr);
   4362 	if (result != ISC_R_SUCCESS) {
   4363 		return;
   4364 	}
   4365 
   4366 	/* Build DS record for key. */
   4367 	isc_buffer_init(&buffer, data, sizeof(data));
   4368 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
   4369 			     dns_rdatatype_dnskey, dnskey, &buffer);
   4370 	CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
   4371 				  &ds));
   4372 	CHECK(dns_keytable_add(sr, true, initial, keyname, &ds, sfd_add,
   4373 			       zone->view));
   4374 
   4375 	dns_keytable_detach(&sr);
   4376 
   4377 cleanup:
   4378 	if (sr != NULL) {
   4379 		dns_keytable_detach(&sr);
   4380 	}
   4381 	return;
   4382 }
   4383 
   4384 /*
   4385  * Add a null key to the security roots for so that all queries
   4386  * to the zone will fail.
   4387  */
   4388 static void
   4389 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
   4390 	isc_result_t result;
   4391 	dns_keytable_t *sr = NULL;
   4392 
   4393 	result = dns_view_getsecroots(zone->view, &sr);
   4394 	if (result == ISC_R_SUCCESS) {
   4395 		dns_keytable_marksecure(sr, keyname);
   4396 		dns_keytable_detach(&sr);
   4397 	}
   4398 }
   4399 
   4400 /*
   4401  * Scan a set of KEYDATA records from the key zone.  The ones that are
   4402  * valid (i.e., the add holddown timer has expired) become trusted keys.
   4403  */
   4404 static void
   4405 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
   4406 	isc_result_t result;
   4407 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4408 	dns_rdata_keydata_t keydata;
   4409 	dns_rdata_dnskey_t dnskey;
   4410 	int trusted = 0, revoked = 0, pending = 0;
   4411 	isc_stdtime_t now = isc_stdtime_now();
   4412 	dns_keytable_t *sr = NULL;
   4413 
   4414 	result = dns_view_getsecroots(zone->view, &sr);
   4415 	if (result == ISC_R_SUCCESS) {
   4416 		dns_keytable_delete(sr, name, sfd_del, zone->view);
   4417 		dns_keytable_detach(&sr);
   4418 	}
   4419 
   4420 	/* Now insert all the accepted trust anchors from this keydata set. */
   4421 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   4422 	     result = dns_rdataset_next(rdataset))
   4423 	{
   4424 		dns_rdata_reset(&rdata);
   4425 		dns_rdataset_current(rdataset, &rdata);
   4426 
   4427 		/* Convert rdata to keydata. */
   4428 		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
   4429 		if (result == ISC_R_NOTIMPLEMENTED) {
   4430 			continue;
   4431 		}
   4432 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4433 
   4434 		/* Set the key refresh timer to force a fast refresh. */
   4435 		set_refreshkeytimer(zone, &keydata, now, true);
   4436 
   4437 		/* If the removal timer is nonzero, this key was revoked. */
   4438 		if (keydata.removehd != 0) {
   4439 			revoked++;
   4440 			continue;
   4441 		}
   4442 
   4443 		/*
   4444 		 * If the add timer is still pending, this key is not
   4445 		 * trusted yet.
   4446 		 */
   4447 		if (now < keydata.addhd) {
   4448 			pending++;
   4449 			continue;
   4450 		}
   4451 
   4452 		/* Convert keydata to dnskey. */
   4453 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
   4454 
   4455 		/* Add to keytables. */
   4456 		trusted++;
   4457 		trust_key(zone, name, &dnskey, keydata.addhd == 0);
   4458 	}
   4459 
   4460 	if (trusted == 0 && pending != 0) {
   4461 		char namebuf[DNS_NAME_FORMATSIZE];
   4462 		dns_name_format(name, namebuf, sizeof namebuf);
   4463 		dnssec_log(zone, ISC_LOG_ERROR,
   4464 			   "No valid trust anchors for '%s'!", namebuf);
   4465 		dnssec_log(zone, ISC_LOG_ERROR,
   4466 			   "%d key(s) revoked, %d still pending", revoked,
   4467 			   pending);
   4468 		dnssec_log(zone, ISC_LOG_ERROR, "All queries to '%s' will fail",
   4469 			   namebuf);
   4470 		fail_secure(zone, name);
   4471 	}
   4472 }
   4473 
   4474 static isc_result_t
   4475 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
   4476 	     dns_diff_t *diff) {
   4477 	dns_diff_t temp_diff;
   4478 	isc_result_t result;
   4479 
   4480 	/*
   4481 	 * Create a singleton diff.
   4482 	 */
   4483 	dns_diff_init(diff->mctx, &temp_diff);
   4484 	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
   4485 
   4486 	/*
   4487 	 * Apply it to the database.
   4488 	 */
   4489 	result = dns_diff_apply(&temp_diff, db, ver);
   4490 	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
   4491 	if (result != ISC_R_SUCCESS) {
   4492 		dns_difftuple_free(tuple);
   4493 		return result;
   4494 	}
   4495 
   4496 	/*
   4497 	 * Merge it into the current pending journal entry.
   4498 	 */
   4499 	dns_diff_appendminimal(diff, tuple);
   4500 
   4501 	/*
   4502 	 * Do not clear temp_diff.
   4503 	 */
   4504 	return ISC_R_SUCCESS;
   4505 }
   4506 
   4507 static isc_result_t
   4508 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
   4509 	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
   4510 	      dns_rdata_t *rdata) {
   4511 	dns_difftuple_t *tuple = NULL;
   4512 	isc_result_t result;
   4513 	result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
   4514 	if (result != ISC_R_SUCCESS) {
   4515 		return result;
   4516 	}
   4517 	return do_one_tuple(&tuple, db, ver, diff);
   4518 }
   4519 
   4520 static isc_result_t
   4521 update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   4522 		  dns_diff_t *diff, isc_mem_t *mctx,
   4523 		  dns_updatemethod_t method) {
   4524 	dns_difftuple_t *deltuple = NULL;
   4525 	dns_difftuple_t *addtuple = NULL;
   4526 	uint32_t serial;
   4527 	isc_result_t result;
   4528 	dns_updatemethod_t used = dns_updatemethod_none;
   4529 
   4530 	INSIST(method != dns_updatemethod_none);
   4531 
   4532 	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
   4533 	CHECK(dns_difftuple_copy(deltuple, &addtuple));
   4534 	addtuple->op = DNS_DIFFOP_ADD;
   4535 
   4536 	serial = dns_soa_getserial(&addtuple->rdata);
   4537 	serial = dns_update_soaserial(serial, method, &used);
   4538 	if (method != used) {
   4539 		dns_zone_log(zone, ISC_LOG_WARNING,
   4540 			     "update_soa_serial:new serial would be lower than "
   4541 			     "old serial, using increment method instead");
   4542 	}
   4543 	dns_soa_setserial(serial, &addtuple->rdata);
   4544 	CHECK(do_one_tuple(&deltuple, db, ver, diff));
   4545 	CHECK(do_one_tuple(&addtuple, db, ver, diff));
   4546 	result = ISC_R_SUCCESS;
   4547 
   4548 cleanup:
   4549 	if (addtuple != NULL) {
   4550 		dns_difftuple_free(&addtuple);
   4551 	}
   4552 	if (deltuple != NULL) {
   4553 		dns_difftuple_free(&deltuple);
   4554 	}
   4555 	return result;
   4556 }
   4557 
   4558 /*
   4559  * Write all transactions in 'diff' to the zone journal file.
   4560  */
   4561 static isc_result_t
   4562 zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
   4563 	     const char *caller) {
   4564 	const char *journalfile;
   4565 	isc_result_t result = ISC_R_SUCCESS;
   4566 	dns_journal_t *journal = NULL;
   4567 	unsigned int mode = DNS_JOURNAL_CREATE | DNS_JOURNAL_WRITE;
   4568 
   4569 	ENTER;
   4570 	journalfile = dns_zone_getjournal(zone);
   4571 	if (journalfile != NULL) {
   4572 		result = dns_journal_open(zone->mctx, journalfile, mode,
   4573 					  &journal);
   4574 		if (result != ISC_R_SUCCESS) {
   4575 			dns_zone_log(zone, ISC_LOG_ERROR,
   4576 				     "%s:dns_journal_open -> %s", caller,
   4577 				     isc_result_totext(result));
   4578 			return result;
   4579 		}
   4580 
   4581 		if (sourceserial != NULL) {
   4582 			dns_journal_set_sourceserial(journal, *sourceserial);
   4583 		}
   4584 
   4585 		result = dns_journal_write_transaction(journal, diff);
   4586 		if (result != ISC_R_SUCCESS) {
   4587 			dns_zone_log(zone, ISC_LOG_ERROR,
   4588 				     "%s:dns_journal_write_transaction -> %s",
   4589 				     caller, isc_result_totext(result));
   4590 		}
   4591 		dns_journal_destroy(&journal);
   4592 	}
   4593 
   4594 	return result;
   4595 }
   4596 
   4597 /*
   4598  * Create an SOA record for a newly-created zone
   4599  */
   4600 static isc_result_t
   4601 add_soa(dns_zone_t *zone, dns_db_t *db) {
   4602 	isc_result_t result;
   4603 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4604 	unsigned char buf[DNS_SOA_BUFFERSIZE];
   4605 	dns_dbversion_t *ver = NULL;
   4606 	dns_diff_t diff;
   4607 
   4608 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
   4609 
   4610 	dns_diff_init(zone->mctx, &diff);
   4611 	result = dns_db_newversion(db, &ver);
   4612 	if (result != ISC_R_SUCCESS) {
   4613 		dns_zone_log(zone, ISC_LOG_ERROR,
   4614 			     "add_soa:dns_db_newversion -> %s",
   4615 			     isc_result_totext(result));
   4616 		goto cleanup;
   4617 	}
   4618 
   4619 	/* Build SOA record */
   4620 	result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
   4621 				    0, 0, 0, 0, 0, buf, &rdata);
   4622 	if (result != ISC_R_SUCCESS) {
   4623 		dns_zone_log(zone, ISC_LOG_ERROR,
   4624 			     "add_soa:dns_soa_buildrdata -> %s",
   4625 			     isc_result_totext(result));
   4626 		goto cleanup;
   4627 	}
   4628 
   4629 	result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, &zone->origin, 0,
   4630 			       &rdata);
   4631 
   4632 cleanup:
   4633 	dns_diff_clear(&diff);
   4634 	if (ver != NULL) {
   4635 		dns_db_closeversion(db, &ver, result == ISC_R_SUCCESS);
   4636 	}
   4637 
   4638 	INSIST(ver == NULL);
   4639 
   4640 	return result;
   4641 }
   4642 
   4643 struct addifmissing_arg {
   4644 	dns_db_t *db;
   4645 	dns_dbversion_t *ver;
   4646 	dns_diff_t *diff;
   4647 	dns_zone_t *zone;
   4648 	bool *changed;
   4649 	isc_result_t result;
   4650 };
   4651 
   4652 static void
   4653 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
   4654 	     dns_name_t *keyname, void *arg) {
   4655 	dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
   4656 	dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
   4657 	dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
   4658 	dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
   4659 	bool *changed = ((struct addifmissing_arg *)arg)->changed;
   4660 	isc_result_t result;
   4661 	dns_fixedname_t fname;
   4662 
   4663 	UNUSED(keytable);
   4664 
   4665 	if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS) {
   4666 		return;
   4667 	}
   4668 
   4669 	if (!dns_keynode_managed(keynode)) {
   4670 		return;
   4671 	}
   4672 
   4673 	/*
   4674 	 * If the keynode has no trust anchor set, return.
   4675 	 */
   4676 	if (!dns_keynode_dsset(keynode, NULL)) {
   4677 		return;
   4678 	}
   4679 
   4680 	/*
   4681 	 * Check whether there's already a KEYDATA entry for this name;
   4682 	 * if so, we don't need to add another.
   4683 	 */
   4684 	dns_fixedname_init(&fname);
   4685 	result = dns_db_find(db, keyname, ver, dns_rdatatype_keydata,
   4686 			     DNS_DBFIND_NOWILD, 0, NULL,
   4687 			     dns_fixedname_name(&fname), NULL, NULL);
   4688 	if (result == ISC_R_SUCCESS) {
   4689 		return;
   4690 	}
   4691 
   4692 	/*
   4693 	 * Create the keydata.
   4694 	 */
   4695 	result = create_keydata(zone, db, ver, diff, keynode, keyname, changed);
   4696 	if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
   4697 		((struct addifmissing_arg *)arg)->result = result;
   4698 	}
   4699 }
   4700 
   4701 /*
   4702  * Synchronize the set of initializing keys found in managed-keys {}
   4703  * statements with the set of trust anchors found in the managed-keys.bind
   4704  * zone.  If a domain is no longer named in managed-keys, delete all keys
   4705  * from that domain from the key zone.	If a domain is configured as an
   4706  * initial-key in trust-anchors, but there are no references to it in the
   4707  * key zone, load the key zone with the initializing key(s) for that
   4708  * domain and schedule a key refresh. If a domain is configured as
   4709  * an initial-ds in trust-anchors, fetch the DNSKEY RRset, load the key
   4710  * zone with the matching key, and schedule a key refresh.
   4711  */
   4712 static isc_result_t
   4713 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
   4714 	isc_result_t result = ISC_R_SUCCESS;
   4715 	bool changed = false;
   4716 	bool commit = false;
   4717 	dns_keynode_t *keynode = NULL;
   4718 	dns_view_t *view = zone->view;
   4719 	dns_keytable_t *sr = NULL;
   4720 	dns_dbversion_t *ver = NULL;
   4721 	dns_diff_t diff;
   4722 	dns_rriterator_t rrit;
   4723 	struct addifmissing_arg arg;
   4724 
   4725 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
   4726 
   4727 	dns_diff_init(zone->mctx, &diff);
   4728 
   4729 	CHECK(dns_view_getsecroots(view, &sr));
   4730 
   4731 	result = dns_db_newversion(db, &ver);
   4732 	if (result != ISC_R_SUCCESS) {
   4733 		dnssec_log(zone, ISC_LOG_ERROR,
   4734 			   "sync_keyzone:dns_db_newversion -> %s",
   4735 			   isc_result_totext(result));
   4736 		goto cleanup;
   4737 	}
   4738 
   4739 	/*
   4740 	 * Walk the zone DB.  If we find any keys whose names are no longer
   4741 	 * in trust-anchors, or which have been changed from initial to static,
   4742 	 * (meaning they are permanent and not RFC5011-maintained), delete
   4743 	 * them from the zone.  Otherwise call load_secroots(), which
   4744 	 * loads keys into secroots as appropriate.
   4745 	 */
   4746 	dns_rriterator_init(&rrit, db, ver, 0);
   4747 	for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
   4748 	     result = dns_rriterator_nextrrset(&rrit))
   4749 	{
   4750 		dns_rdataset_t *rdataset = NULL;
   4751 		dns_rdata_t rdata = DNS_RDATA_INIT;
   4752 		dns_rdata_keydata_t keydata;
   4753 		isc_stdtime_t now = isc_stdtime_now();
   4754 		bool load = true;
   4755 		dns_name_t *rrname = NULL;
   4756 		uint32_t ttl;
   4757 
   4758 		dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
   4759 		if (!dns_rdataset_isassociated(rdataset)) {
   4760 			dns_rriterator_destroy(&rrit);
   4761 			goto cleanup;
   4762 		}
   4763 
   4764 		if (rdataset->type != dns_rdatatype_keydata) {
   4765 			continue;
   4766 		}
   4767 
   4768 		/*
   4769 		 * The managed-keys zone can contain a placeholder instead of
   4770 		 * legitimate data, in which case we will not use it, and we
   4771 		 * will try to refresh it.
   4772 		 */
   4773 		for (result = dns_rdataset_first(rdataset);
   4774 		     result == ISC_R_SUCCESS;
   4775 		     result = dns_rdataset_next(rdataset))
   4776 		{
   4777 			isc_result_t iresult;
   4778 
   4779 			dns_rdata_reset(&rdata);
   4780 			dns_rdataset_current(rdataset, &rdata);
   4781 
   4782 			iresult = dns_rdata_tostruct(&rdata, &keydata, NULL);
   4783 			/* Do we have a valid placeholder KEYDATA record? */
   4784 			if (iresult == ISC_R_SUCCESS && keydata.flags == 0 &&
   4785 			    keydata.protocol == 0 && keydata.algorithm == 0)
   4786 			{
   4787 				set_refreshkeytimer(zone, &keydata, now, true);
   4788 				load = false;
   4789 			}
   4790 		}
   4791 
   4792 		/*
   4793 		 * Release db wrlock to prevent LOR reports against
   4794 		 * dns_keytable_forall() call below.
   4795 		 */
   4796 		dns_rriterator_pause(&rrit);
   4797 		result = dns_keytable_find(sr, rrname, &keynode);
   4798 		if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
   4799 			CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
   4800 			changed = true;
   4801 		} else if (load) {
   4802 			load_secroots(zone, rrname, rdataset);
   4803 		}
   4804 
   4805 		if (keynode != NULL) {
   4806 			dns_keynode_detach(&keynode);
   4807 		}
   4808 	}
   4809 	dns_rriterator_destroy(&rrit);
   4810 
   4811 	/*
   4812 	 * Walk secroots to find any initial keys that aren't in
   4813 	 * the zone.  If we find any, add them to the zone directly.
   4814 	 * If any DS-style initial keys are found, refresh the key
   4815 	 * zone so that they'll be looked up.
   4816 	 */
   4817 	arg.db = db;
   4818 	arg.ver = ver;
   4819 	arg.result = ISC_R_SUCCESS;
   4820 	arg.diff = &diff;
   4821 	arg.zone = zone;
   4822 	arg.changed = &changed;
   4823 	dns_keytable_forall(sr, addifmissing, &arg);
   4824 	result = arg.result;
   4825 	if (changed) {
   4826 		/* Write changes to journal file. */
   4827 		CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
   4828 					zone->updatemethod));
   4829 		CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
   4830 
   4831 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   4832 		zone_needdump(zone, 30);
   4833 		commit = true;
   4834 	}
   4835 
   4836 cleanup:
   4837 	if (result != ISC_R_SUCCESS) {
   4838 		dnssec_log(zone, ISC_LOG_ERROR,
   4839 			   "unable to synchronize managed keys: %s",
   4840 			   isc_result_totext(result));
   4841 		isc_time_settoepoch(&zone->refreshkeytime);
   4842 	}
   4843 	if (keynode != NULL) {
   4844 		dns_keynode_detach(&keynode);
   4845 	}
   4846 	if (sr != NULL) {
   4847 		dns_keytable_detach(&sr);
   4848 	}
   4849 	if (ver != NULL) {
   4850 		dns_db_closeversion(db, &ver, commit);
   4851 	}
   4852 	dns_diff_clear(&diff);
   4853 
   4854 	INSIST(ver == NULL);
   4855 
   4856 	return result;
   4857 }
   4858 
   4859 isc_result_t
   4860 dns_zone_synckeyzone(dns_zone_t *zone) {
   4861 	isc_result_t result;
   4862 	dns_db_t *db = NULL;
   4863 
   4864 	if (zone->type != dns_zone_key) {
   4865 		return DNS_R_BADZONE;
   4866 	}
   4867 
   4868 	CHECK(dns_zone_getdb(zone, &db));
   4869 
   4870 	LOCK_ZONE(zone);
   4871 	result = sync_keyzone(zone, db);
   4872 	UNLOCK_ZONE(zone);
   4873 
   4874 cleanup:
   4875 	if (db != NULL) {
   4876 		dns_db_detach(&db);
   4877 	}
   4878 	return result;
   4879 }
   4880 
   4881 static void
   4882 maybe_send_secure(dns_zone_t *zone) {
   4883 	isc_result_t result;
   4884 
   4885 	/*
   4886 	 * We've finished loading, or else failed to load, an inline-signing
   4887 	 * 'secure' zone.  We now need information about the status of the
   4888 	 * 'raw' zone.  If we failed to load, then we need it to send a
   4889 	 * copy of its database; if we succeeded, we need it to send its
   4890 	 * serial number so that we can sync with it.  If it has not yet
   4891 	 * loaded, we set a flag so that it will send the necessary
   4892 	 * information when it has finished loading.
   4893 	 */
   4894 	if (zone->raw->db != NULL) {
   4895 		if (zone->db != NULL) {
   4896 			uint32_t serial;
   4897 			unsigned int soacount;
   4898 
   4899 			result = zone_get_from_db(
   4900 				zone->raw, zone->raw->db, NULL, &soacount, NULL,
   4901 				&serial, NULL, NULL, NULL, NULL, NULL);
   4902 			if (result == ISC_R_SUCCESS && soacount > 0U) {
   4903 				zone_send_secureserial(zone->raw, serial);
   4904 			}
   4905 		} else {
   4906 			zone_send_securedb(zone->raw, zone->raw->db);
   4907 		}
   4908 	} else {
   4909 		DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
   4910 	}
   4911 }
   4912 
   4913 static bool
   4914 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
   4915 	isc_result_t result;
   4916 	bool answer = false;
   4917 	dns_diff_t diff;
   4918 
   4919 	dns_diff_init(mctx, &diff);
   4920 	result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
   4921 	if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) {
   4922 		answer = true;
   4923 	}
   4924 	dns_diff_clear(&diff);
   4925 	return answer;
   4926 }
   4927 
   4928 static void
   4929 process_zone_setnsec3param(dns_zone_t *zone) {
   4930 	struct np3 *npe = NULL;
   4931 	while ((npe = ISC_LIST_HEAD(zone->setnsec3param_queue)) != NULL) {
   4932 		ISC_LIST_UNLINK(zone->setnsec3param_queue, npe, link);
   4933 		zone_iattach(zone, &npe->zone);
   4934 		isc_async_run(zone->loop, setnsec3param, npe);
   4935 	}
   4936 }
   4937 
   4938 /*
   4939  * The zone is presumed to be locked.
   4940  * If this is a inline_raw zone the secure version is also locked.
   4941  */
   4942 static isc_result_t
   4943 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
   4944 	      isc_result_t result) {
   4945 	unsigned int soacount = 0;
   4946 	unsigned int nscount = 0;
   4947 	unsigned int errors = 0;
   4948 	uint32_t serial, oldserial, refresh, retry, expire, minimum, soattl;
   4949 	isc_time_t now;
   4950 	bool needdump = false;
   4951 	bool fixjournal = false;
   4952 	bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
   4953 	bool noprimary = false;
   4954 	bool had_db = false;
   4955 	dns_include_t *inc;
   4956 	bool is_dynamic = false;
   4957 
   4958 	INSIST(LOCKED_ZONE(zone));
   4959 	if (inline_raw(zone)) {
   4960 		INSIST(LOCKED_ZONE(zone->secure));
   4961 	}
   4962 
   4963 	now = isc_time_now();
   4964 
   4965 	/*
   4966 	 * Initiate zone transfer?  We may need a error code that
   4967 	 * indicates that the "permanent" form does not exist.
   4968 	 * XXX better error feedback to log.
   4969 	 */
   4970 	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
   4971 		if (zone->type == dns_zone_secondary ||
   4972 		    zone->type == dns_zone_mirror ||
   4973 		    zone->type == dns_zone_stub ||
   4974 		    (zone->type == dns_zone_redirect &&
   4975 		     dns_remote_addresses(&zone->primaries) == NULL))
   4976 		{
   4977 			if (result == ISC_R_FILENOTFOUND) {
   4978 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4979 					      ISC_LOG_DEBUG(1),
   4980 					      "no master file");
   4981 			} else if (result != DNS_R_NOMASTERFILE) {
   4982 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4983 					      ISC_LOG_ERROR,
   4984 					      "loading from master file %s "
   4985 					      "failed: %s",
   4986 					      zone->masterfile,
   4987 					      isc_result_totext(result));
   4988 			}
   4989 		} else if (zone->type == dns_zone_primary &&
   4990 			   inline_secure(zone) && result == ISC_R_FILENOTFOUND)
   4991 		{
   4992 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4993 				      ISC_LOG_DEBUG(1),
   4994 				      "no master file, requesting db");
   4995 			maybe_send_secure(zone);
   4996 		} else {
   4997 			int level = ISC_LOG_ERROR;
   4998 			if (zone->type == dns_zone_key &&
   4999 			    result == ISC_R_FILENOTFOUND)
   5000 			{
   5001 				level = ISC_LOG_DEBUG(1);
   5002 			}
   5003 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
   5004 				      "loading from master file %s failed: %s",
   5005 				      zone->masterfile,
   5006 				      isc_result_totext(result));
   5007 			noprimary = true;
   5008 		}
   5009 
   5010 		if (zone->type != dns_zone_key) {
   5011 			goto cleanup;
   5012 		}
   5013 	}
   5014 
   5015 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
   5016 		      "number of nodes in database: %u",
   5017 		      dns_db_nodecount(db, dns_dbtree_main));
   5018 
   5019 	if (result == DNS_R_SEENINCLUDE) {
   5020 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
   5021 	} else {
   5022 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
   5023 	}
   5024 
   5025 	/*
   5026 	 * If there's no master file for a key zone, then the zone is new:
   5027 	 * create an SOA record.  (We do this now, instead of later, so that
   5028 	 * if there happens to be a journal file, we can roll forward from
   5029 	 * a sane starting point.)
   5030 	 */
   5031 	if (noprimary && zone->type == dns_zone_key) {
   5032 		result = add_soa(zone, db);
   5033 		if (result != ISC_R_SUCCESS) {
   5034 			goto cleanup;
   5035 		}
   5036 	}
   5037 
   5038 	/*
   5039 	 * Apply update log, if any, on initial load.
   5040 	 */
   5041 	if (zone->journal != NULL &&
   5042 	    !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
   5043 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   5044 	{
   5045 		result = zone_journal_rollforward(zone, db, &needdump,
   5046 						  &fixjournal);
   5047 		if (result != ISC_R_SUCCESS) {
   5048 			goto cleanup;
   5049 		}
   5050 	}
   5051 
   5052 	/*
   5053 	 * Obtain ns, soa and cname counts for top of zone.
   5054 	 */
   5055 	INSIST(db != NULL);
   5056 	result = zone_get_from_db(zone, db, &nscount, &soacount, &soattl,
   5057 				  &serial, &refresh, &retry, &expire, &minimum,
   5058 				  &errors);
   5059 	if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
   5060 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   5061 			      "could not find NS and/or SOA records");
   5062 	}
   5063 
   5064 	/*
   5065 	 * Process any queued NSEC3PARAM change requests. Only for dynamic
   5066 	 * zones, an inline-signing zone will perform this action when
   5067 	 * receiving the secure db (receive_secure_db).
   5068 	 */
   5069 	is_dynamic = dns_zone_isdynamic(zone, true);
   5070 	if (is_dynamic) {
   5071 		process_zone_setnsec3param(zone);
   5072 	}
   5073 
   5074 	/*
   5075 	 * Check to make sure the journal is up to date, and remove the
   5076 	 * journal file if it isn't, as we wouldn't be able to apply
   5077 	 * updates otherwise.
   5078 	 */
   5079 	if (zone->journal != NULL && is_dynamic &&
   5080 	    !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
   5081 	{
   5082 		uint32_t jserial;
   5083 		dns_journal_t *journal = NULL;
   5084 		bool empty = false;
   5085 
   5086 		result = dns_journal_open(zone->mctx, zone->journal,
   5087 					  DNS_JOURNAL_READ, &journal);
   5088 		if (result == ISC_R_SUCCESS) {
   5089 			jserial = dns_journal_last_serial(journal);
   5090 			empty = dns_journal_empty(journal);
   5091 			dns_journal_destroy(&journal);
   5092 		} else {
   5093 			jserial = serial;
   5094 			result = ISC_R_SUCCESS;
   5095 		}
   5096 
   5097 		if (jserial != serial) {
   5098 			if (!empty) {
   5099 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5100 					      ISC_LOG_INFO,
   5101 					      "journal file is out of date: "
   5102 					      "removing journal file");
   5103 			}
   5104 			if (remove(zone->journal) < 0 && errno != ENOENT) {
   5105 				char strbuf[ISC_STRERRORSIZE];
   5106 				strerror_r(errno, strbuf, sizeof(strbuf));
   5107 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   5108 					      DNS_LOGMODULE_ZONE,
   5109 					      ISC_LOG_WARNING,
   5110 					      "unable to remove journal "
   5111 					      "'%s': '%s'",
   5112 					      zone->journal, strbuf);
   5113 			}
   5114 		}
   5115 	}
   5116 
   5117 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
   5118 		      "loaded; checking validity");
   5119 
   5120 	/*
   5121 	 * Primary / Secondary / Mirror / Stub zones require both NS and SOA
   5122 	 * records at the top of the zone.
   5123 	 */
   5124 
   5125 	switch (zone->type) {
   5126 	case dns_zone_dlz:
   5127 	case dns_zone_primary:
   5128 	case dns_zone_secondary:
   5129 	case dns_zone_mirror:
   5130 	case dns_zone_stub:
   5131 	case dns_zone_redirect:
   5132 		if (soacount != 1) {
   5133 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5134 				      ISC_LOG_ERROR, "has %d SOA records",
   5135 				      soacount);
   5136 			result = DNS_R_BADZONE;
   5137 		}
   5138 		if (nscount == 0) {
   5139 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5140 				      ISC_LOG_ERROR, "has no NS records");
   5141 			result = DNS_R_BADZONE;
   5142 		}
   5143 		if (result != ISC_R_SUCCESS) {
   5144 			goto cleanup;
   5145 		}
   5146 		if (zone->type == dns_zone_primary && errors != 0) {
   5147 			result = DNS_R_BADZONE;
   5148 			goto cleanup;
   5149 		}
   5150 		if (zone->type != dns_zone_stub &&
   5151 		    zone->type != dns_zone_redirect)
   5152 		{
   5153 			result = check_nsec3param(zone, db);
   5154 			if (result != ISC_R_SUCCESS) {
   5155 				goto cleanup;
   5156 			}
   5157 		}
   5158 		if (zone->type == dns_zone_primary &&
   5159 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
   5160 		    !integrity_checks(zone, db))
   5161 		{
   5162 			result = DNS_R_BADZONE;
   5163 			goto cleanup;
   5164 		}
   5165 		if (zone->type == dns_zone_primary &&
   5166 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
   5167 		    !zone_check_dup(zone, db))
   5168 		{
   5169 			result = DNS_R_BADZONE;
   5170 			goto cleanup;
   5171 		}
   5172 
   5173 		if (zone->type == dns_zone_primary) {
   5174 			result = dns_zone_cdscheck(zone, db, NULL);
   5175 			if (result != ISC_R_SUCCESS) {
   5176 				dns_zone_log(zone, ISC_LOG_ERROR,
   5177 					     "CDS/CDNSKEY consistency checks "
   5178 					     "failed");
   5179 				goto cleanup;
   5180 			}
   5181 		}
   5182 
   5183 		result = dns_zone_verifydb(zone, db, NULL);
   5184 		if (result != ISC_R_SUCCESS) {
   5185 			goto cleanup;
   5186 		}
   5187 
   5188 		if (zone->db != NULL) {
   5189 			unsigned int oldsoacount;
   5190 
   5191 			/*
   5192 			 * This is checked in zone_replacedb() for
   5193 			 * secondary zones as they don't reload from disk.
   5194 			 */
   5195 			result = zone_get_from_db(
   5196 				zone, zone->db, NULL, &oldsoacount, NULL,
   5197 				&oldserial, NULL, NULL, NULL, NULL, NULL);
   5198 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   5199 			RUNTIME_CHECK(oldsoacount > 0U);
   5200 			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
   5201 			    !isc_serial_gt(serial, oldserial))
   5202 			{
   5203 				uint32_t serialmin, serialmax;
   5204 
   5205 				INSIST(zone->type == dns_zone_primary);
   5206 				INSIST(zone->raw == NULL);
   5207 
   5208 				if (serial == oldserial &&
   5209 				    zone_unchanged(zone->db, db, zone->mctx))
   5210 				{
   5211 					dns_zone_logc(zone,
   5212 						      DNS_LOGCATEGORY_ZONELOAD,
   5213 						      ISC_LOG_INFO,
   5214 						      "ixfr-from-differences: "
   5215 						      "unchanged");
   5216 					zone->loadtime = loadtime;
   5217 					goto done;
   5218 				}
   5219 
   5220 				serialmin = (oldserial + 1) & 0xffffffffU;
   5221 				serialmax = (oldserial + 0x7fffffffU) &
   5222 					    0xffffffffU;
   5223 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5224 					      ISC_LOG_ERROR,
   5225 					      "ixfr-from-differences: "
   5226 					      "new serial (%u) out of range "
   5227 					      "[%u - %u]",
   5228 					      serial, serialmin, serialmax);
   5229 				result = DNS_R_BADZONE;
   5230 				goto cleanup;
   5231 			} else if (!isc_serial_ge(serial, oldserial)) {
   5232 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5233 					      ISC_LOG_ERROR,
   5234 					      "zone serial (%u/%u) has gone "
   5235 					      "backwards",
   5236 					      serial, oldserial);
   5237 			} else if (serial == oldserial && !hasinclude &&
   5238 				   strcmp(zone->db_argv[0], "_builtin") != 0)
   5239 			{
   5240 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5241 					      ISC_LOG_ERROR,
   5242 					      "zone serial (%u) unchanged. "
   5243 					      "zone may fail to transfer "
   5244 					      "to secondaries.",
   5245 					      serial);
   5246 			}
   5247 		}
   5248 
   5249 		if (zone->type == dns_zone_primary &&
   5250 		    (zone->update_acl != NULL || zone->ssutable != NULL) &&
   5251 		    dns_zone_getsigresigninginterval(zone) < (3 * refresh) &&
   5252 		    dns_db_issecure(db))
   5253 		{
   5254 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5255 				      ISC_LOG_WARNING,
   5256 				      "sig-re-signing-interval less than "
   5257 				      "3 * refresh.");
   5258 		}
   5259 
   5260 		zone->refresh = RANGE(refresh, zone->minrefresh,
   5261 				      zone->maxrefresh);
   5262 		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
   5263 		zone->expire = RANGE(expire, zone->refresh + zone->retry,
   5264 				     DNS_MAX_EXPIRE);
   5265 		zone->soattl = soattl;
   5266 		zone->minimum = minimum;
   5267 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   5268 
   5269 		if (zone->type == dns_zone_secondary ||
   5270 		    zone->type == dns_zone_mirror ||
   5271 		    zone->type == dns_zone_stub ||
   5272 		    (zone->type == dns_zone_redirect &&
   5273 		     dns_remote_addresses(&zone->primaries) != NULL))
   5274 		{
   5275 			isc_time_t t;
   5276 			uint32_t delay;
   5277 
   5278 			result = isc_file_getmodtime(zone->journal, &t);
   5279 			if (result != ISC_R_SUCCESS) {
   5280 				result = isc_file_getmodtime(zone->masterfile,
   5281 							     &t);
   5282 			}
   5283 			if (result == ISC_R_SUCCESS) {
   5284 				DNS_ZONE_TIME_ADD(&t, zone->expire,
   5285 						  &zone->expiretime);
   5286 			} else {
   5287 				DNS_ZONE_TIME_ADD(&now, zone->retry,
   5288 						  &zone->expiretime);
   5289 			}
   5290 
   5291 			delay = (zone->retry -
   5292 				 isc_random_uniform((zone->retry * 3) / 4));
   5293 			DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
   5294 			if (isc_time_compare(&zone->refreshtime,
   5295 					     &zone->expiretime) >= 0)
   5296 			{
   5297 				DNS_ZONE_SETFLAG(zone,
   5298 						 DNS_ZONEFLG_FIRSTREFRESH);
   5299 				zone->refreshtime = now;
   5300 			} else {
   5301 				/* The zone is up to date. */
   5302 				DNS_ZONE_CLRFLAG(zone,
   5303 						 DNS_ZONEFLG_FIRSTREFRESH);
   5304 			}
   5305 		}
   5306 
   5307 		break;
   5308 
   5309 	case dns_zone_key:
   5310 		/* Nothing needs to be done now */
   5311 		break;
   5312 
   5313 	default:
   5314 		UNEXPECTED_ERROR("unexpected zone type %d", zone->type);
   5315 		result = ISC_R_UNEXPECTED;
   5316 		goto cleanup;
   5317 	}
   5318 
   5319 	/*
   5320 	 * Check for weak DNSKEY's.
   5321 	 */
   5322 	if (zone->type == dns_zone_primary) {
   5323 		zone_check_dnskeys(zone, db);
   5324 	}
   5325 
   5326 	/*
   5327 	 * Schedule DNSSEC key refresh.
   5328 	 */
   5329 	if (zone->type == dns_zone_primary &&
   5330 	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
   5331 	{
   5332 		zone->refreshkeytime = now;
   5333 	}
   5334 
   5335 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   5336 	if (zone->db != NULL) {
   5337 		had_db = true;
   5338 		result = zone_replacedb(zone, db, false);
   5339 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   5340 		if (result != ISC_R_SUCCESS) {
   5341 			goto cleanup;
   5342 		}
   5343 	} else {
   5344 		zone_attachdb(zone, db);
   5345 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   5346 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED |
   5347 					       DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
   5348 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
   5349 		    inline_raw(zone))
   5350 		{
   5351 			if (zone->secure->db == NULL) {
   5352 				zone_send_securedb(zone, db);
   5353 			} else {
   5354 				zone_send_secureserial(zone, serial);
   5355 			}
   5356 		}
   5357 	}
   5358 
   5359 	/*
   5360 	 * Finished loading inline-signing zone; need to get status
   5361 	 * from the raw side now.
   5362 	 */
   5363 	if (zone->type == dns_zone_primary && inline_secure(zone)) {
   5364 		maybe_send_secure(zone);
   5365 	}
   5366 
   5367 	result = ISC_R_SUCCESS;
   5368 
   5369 	if (fixjournal) {
   5370 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
   5371 		zone_journal_compact(zone, zone->db, 0);
   5372 	}
   5373 	if (needdump) {
   5374 		if (zone->type == dns_zone_key) {
   5375 			zone_needdump(zone, 30);
   5376 		} else {
   5377 			zone_needdump(zone, DNS_DUMP_DELAY);
   5378 		}
   5379 	}
   5380 
   5381 	if (zone->loop != NULL) {
   5382 		if (zone->type == dns_zone_primary) {
   5383 			set_resigntime(zone);
   5384 			resume_signingwithkey(zone);
   5385 			resume_addnsec3chain(zone);
   5386 		}
   5387 
   5388 		is_dynamic = dns_zone_isdynamic(zone, false);
   5389 		if (zone->type == dns_zone_primary && is_dynamic &&
   5390 		    dns_db_issecure(db) && !inline_raw(zone))
   5391 		{
   5392 			isc_stdtime_t resign;
   5393 			dns_name_t *name;
   5394 			dns_fixedname_t fixed;
   5395 			dns_typepair_t typepair;
   5396 
   5397 			name = dns_fixedname_initname(&fixed);
   5398 
   5399 			result = dns_db_getsigningtime(db, &resign, name,
   5400 						       &typepair);
   5401 			if (result == ISC_R_SUCCESS) {
   5402 				isc_stdtime_t timenow = isc_stdtime_now();
   5403 				char namebuf[DNS_NAME_FORMATSIZE];
   5404 				char typebuf[DNS_RDATATYPE_FORMATSIZE];
   5405 
   5406 				dns_name_format(name, namebuf, sizeof(namebuf));
   5407 				dns_rdatatype_format(
   5408 					DNS_TYPEPAIR_COVERS(typepair), typebuf,
   5409 					sizeof(typebuf));
   5410 				dnssec_log(
   5411 					zone, ISC_LOG_DEBUG(3),
   5412 					"next resign: %s/%s "
   5413 					"in %d seconds",
   5414 					namebuf, typebuf,
   5415 					resign - timenow -
   5416 						dns_zone_getsigresigninginterval(
   5417 							zone));
   5418 			} else {
   5419 				dnssec_log(zone, ISC_LOG_WARNING,
   5420 					   "signed dynamic zone has no "
   5421 					   "resign event scheduled");
   5422 			}
   5423 		}
   5424 
   5425 		zone_settimer(zone, &now);
   5426 	}
   5427 
   5428 	/*
   5429 	 * Clear old include list.
   5430 	 */
   5431 	for (inc = ISC_LIST_HEAD(zone->includes); inc != NULL;
   5432 	     inc = ISC_LIST_HEAD(zone->includes))
   5433 	{
   5434 		ISC_LIST_UNLINK(zone->includes, inc, link);
   5435 		isc_mem_free(zone->mctx, inc->name);
   5436 		isc_mem_put(zone->mctx, inc, sizeof(*inc));
   5437 	}
   5438 	zone->nincludes = 0;
   5439 
   5440 	/*
   5441 	 * Transfer new include list.
   5442 	 */
   5443 	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
   5444 	     inc = ISC_LIST_HEAD(zone->newincludes))
   5445 	{
   5446 		ISC_LIST_UNLINK(zone->newincludes, inc, link);
   5447 		ISC_LIST_APPEND(zone->includes, inc, link);
   5448 		zone->nincludes++;
   5449 	}
   5450 
   5451 	if (!dns_db_ispersistent(db)) {
   5452 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
   5453 			      "loaded serial %u%s", serial,
   5454 			      dns_db_issecure(db) ? " (DNSSEC signed)" : "");
   5455 	}
   5456 
   5457 	if (!had_db && zone->type == dns_zone_mirror) {
   5458 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
   5459 			      "mirror zone is now in use");
   5460 	}
   5461 
   5462 	zone->loadtime = loadtime;
   5463 	goto done;
   5464 
   5465 cleanup:
   5466 	if (result != ISC_R_SUCCESS) {
   5467 		dns_zone_rpz_disable_db(zone, db);
   5468 		dns_zone_catz_disable_db(zone, db);
   5469 	}
   5470 
   5471 	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
   5472 	     inc = ISC_LIST_HEAD(zone->newincludes))
   5473 	{
   5474 		ISC_LIST_UNLINK(zone->newincludes, inc, link);
   5475 		isc_mem_free(zone->mctx, inc->name);
   5476 		isc_mem_put(zone->mctx, inc, sizeof(*inc));
   5477 	}
   5478 	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
   5479 	    zone->type == dns_zone_stub || zone->type == dns_zone_key ||
   5480 	    (zone->type == dns_zone_redirect &&
   5481 	     dns_remote_addresses(&zone->primaries) != NULL))
   5482 	{
   5483 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIRSTREFRESH);
   5484 
   5485 		if (result != ISC_R_NOMEMORY) {
   5486 			if (zone->journal != NULL) {
   5487 				zone_saveunique(zone, zone->journal,
   5488 						"jn-XXXXXXXX");
   5489 			}
   5490 			if (zone->masterfile != NULL) {
   5491 				zone_saveunique(zone, zone->masterfile,
   5492 						"db-XXXXXXXX");
   5493 			}
   5494 		}
   5495 
   5496 		/* Mark the zone for immediate refresh. */
   5497 		zone->refreshtime = now;
   5498 		if (zone->loop != NULL) {
   5499 			zone_settimer(zone, &now);
   5500 		}
   5501 		result = ISC_R_SUCCESS;
   5502 	} else if (zone->type == dns_zone_primary ||
   5503 		   zone->type == dns_zone_redirect)
   5504 	{
   5505 		if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
   5506 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5507 				      ISC_LOG_ERROR,
   5508 				      "not loaded due to errors.");
   5509 		} else if (zone->type == dns_zone_primary) {
   5510 			result = ISC_R_SUCCESS;
   5511 		}
   5512 	}
   5513 
   5514 done:
   5515 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
   5516 	/*
   5517 	 * If this is an inline-signed zone and we were called for the raw
   5518 	 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
   5519 	 * as well, but only if this is a reload, not an initial zone load: in
   5520 	 * the former case, zone_postload() will not be run for the secure
   5521 	 * zone; in the latter case, it will be.  Check which case we are
   5522 	 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
   5523 	 * secure zone: if it is set, this must be a reload.
   5524 	 */
   5525 	if (inline_raw(zone) && DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
   5526 	{
   5527 		DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
   5528 		/*
   5529 		 * Re-start zone maintenance if it had been stalled
   5530 		 * due to DNS_ZONEFLG_LOADPENDING being set when
   5531 		 * zone_maintenance was called.
   5532 		 */
   5533 		if (zone->secure->loop != NULL) {
   5534 			zone_settimer(zone->secure, &now);
   5535 		}
   5536 	}
   5537 
   5538 	zone_debuglog(zone, __func__, 99, "done");
   5539 
   5540 	return result;
   5541 }
   5542 
   5543 static bool
   5544 exit_check(dns_zone_t *zone) {
   5545 	REQUIRE(LOCKED_ZONE(zone));
   5546 
   5547 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
   5548 	    isc_refcount_current(&zone->irefs) == 0)
   5549 	{
   5550 		/*
   5551 		 * DNS_ZONEFLG_SHUTDOWN can only be set if references == 0.
   5552 		 */
   5553 		INSIST(isc_refcount_current(&zone->references) == 0);
   5554 		return true;
   5555 	}
   5556 	return false;
   5557 }
   5558 
   5559 static bool
   5560 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
   5561 	      dns_name_t *name, bool logit) {
   5562 	isc_result_t result;
   5563 	char namebuf[DNS_NAME_FORMATSIZE];
   5564 	char altbuf[DNS_NAME_FORMATSIZE];
   5565 	dns_fixedname_t fixed;
   5566 	dns_name_t *foundname;
   5567 	int level;
   5568 
   5569 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS)) {
   5570 		return true;
   5571 	}
   5572 
   5573 	if (zone->type == dns_zone_primary) {
   5574 		level = ISC_LOG_ERROR;
   5575 	} else {
   5576 		level = ISC_LOG_WARNING;
   5577 	}
   5578 
   5579 	foundname = dns_fixedname_initname(&fixed);
   5580 
   5581 	result = dns_db_find(db, name, version, dns_rdatatype_a, 0, 0, NULL,
   5582 			     foundname, NULL, NULL);
   5583 	if (result == ISC_R_SUCCESS) {
   5584 		return true;
   5585 	}
   5586 
   5587 	if (result == DNS_R_NXRRSET) {
   5588 		result = dns_db_find(db, name, version, dns_rdatatype_aaaa, 0,
   5589 				     0, NULL, foundname, NULL, NULL);
   5590 		if (result == ISC_R_SUCCESS) {
   5591 			return true;
   5592 		}
   5593 	}
   5594 
   5595 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   5596 	    result == DNS_R_EMPTYNAME)
   5597 	{
   5598 		if (logit) {
   5599 			dns_name_format(name, namebuf, sizeof namebuf);
   5600 			dns_zone_log(zone, level,
   5601 				     "NS '%s' has no address "
   5602 				     "records (A or AAAA)",
   5603 				     namebuf);
   5604 		}
   5605 		return false;
   5606 	}
   5607 
   5608 	if (result == DNS_R_CNAME) {
   5609 		if (logit) {
   5610 			dns_name_format(name, namebuf, sizeof namebuf);
   5611 			dns_zone_log(zone, level,
   5612 				     "NS '%s' is a CNAME "
   5613 				     "(illegal)",
   5614 				     namebuf);
   5615 		}
   5616 		return false;
   5617 	}
   5618 
   5619 	if (result == DNS_R_DNAME) {
   5620 		if (logit) {
   5621 			dns_name_format(name, namebuf, sizeof namebuf);
   5622 			dns_name_format(foundname, altbuf, sizeof altbuf);
   5623 			dns_zone_log(zone, level,
   5624 				     "NS '%s' is below a DNAME "
   5625 				     "'%s' (illegal)",
   5626 				     namebuf, altbuf);
   5627 		}
   5628 		return false;
   5629 	}
   5630 
   5631 	return true;
   5632 }
   5633 
   5634 static isc_result_t
   5635 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
   5636 		 dns_dbversion_t *version, unsigned int *nscount,
   5637 		 unsigned int *errors, bool logit) {
   5638 	isc_result_t result;
   5639 	unsigned int count = 0;
   5640 	unsigned int ecount = 0;
   5641 	dns_rdataset_t rdataset;
   5642 	dns_rdata_t rdata;
   5643 	dns_rdata_ns_t ns;
   5644 
   5645 	dns_rdataset_init(&rdataset);
   5646 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
   5647 				     dns_rdatatype_none, 0, &rdataset, NULL);
   5648 	if (result == ISC_R_NOTFOUND) {
   5649 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5650 		goto success;
   5651 	}
   5652 	if (result != ISC_R_SUCCESS) {
   5653 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5654 		goto invalidate_rdataset;
   5655 	}
   5656 
   5657 	result = dns_rdataset_first(&rdataset);
   5658 	while (result == ISC_R_SUCCESS) {
   5659 		if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
   5660 		    (zone->type == dns_zone_primary ||
   5661 		     zone->type == dns_zone_secondary ||
   5662 		     zone->type == dns_zone_mirror))
   5663 		{
   5664 			dns_rdata_init(&rdata);
   5665 			dns_rdataset_current(&rdataset, &rdata);
   5666 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
   5667 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   5668 			if (dns_name_issubdomain(&ns.name, &zone->origin) &&
   5669 			    !zone_check_ns(zone, db, version, &ns.name, logit))
   5670 			{
   5671 				ecount++;
   5672 			}
   5673 		}
   5674 		count++;
   5675 		result = dns_rdataset_next(&rdataset);
   5676 	}
   5677 	dns_rdataset_disassociate(&rdataset);
   5678 
   5679 success:
   5680 	SET_IF_NOT_NULL(nscount, count);
   5681 	SET_IF_NOT_NULL(errors, ecount);
   5682 
   5683 	result = ISC_R_SUCCESS;
   5684 
   5685 invalidate_rdataset:
   5686 	dns_rdataset_invalidate(&rdataset);
   5687 
   5688 	return result;
   5689 }
   5690 
   5691 #define SET_SOA_VALUES(soattl_v, serial_v, refresh_v, retry_v, expire_v, \
   5692 		       minimum_v)                                        \
   5693 	{                                                                \
   5694 		SET_IF_NOT_NULL(soattl, soattl_v);                       \
   5695 		SET_IF_NOT_NULL(serial, serial_v);                       \
   5696 		SET_IF_NOT_NULL(refresh, refresh_v);                     \
   5697 		SET_IF_NOT_NULL(retry, retry_v);                         \
   5698 		SET_IF_NOT_NULL(expire, expire_v);                       \
   5699 		SET_IF_NOT_NULL(minimum, minimum_v);                     \
   5700 	}
   5701 
   5702 #define CLR_SOA_VALUES()                          \
   5703 	{                                         \
   5704 		SET_SOA_VALUES(0, 0, 0, 0, 0, 0); \
   5705 	}
   5706 
   5707 static isc_result_t
   5708 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   5709 		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
   5710 		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
   5711 		 uint32_t *minimum) {
   5712 	isc_result_t result;
   5713 	unsigned int count = 0;
   5714 	dns_rdataset_t rdataset;
   5715 	dns_rdata_t rdata = DNS_RDATA_INIT;
   5716 
   5717 	dns_rdataset_init(&rdataset);
   5718 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
   5719 				     dns_rdatatype_none, 0, &rdataset, NULL);
   5720 	if (result == ISC_R_NOTFOUND) {
   5721 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5722 		result = ISC_R_SUCCESS;
   5723 		goto invalidate_rdataset;
   5724 	}
   5725 	if (result != ISC_R_SUCCESS) {
   5726 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5727 		goto invalidate_rdataset;
   5728 	}
   5729 
   5730 	result = dns_rdataset_first(&rdataset);
   5731 	while (result == ISC_R_SUCCESS) {
   5732 		dns_rdata_init(&rdata);
   5733 		dns_rdataset_current(&rdataset, &rdata);
   5734 		count++;
   5735 		if (count == 1) {
   5736 			dns_rdata_soa_t soa;
   5737 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
   5738 			SET_SOA_VALUES(rdataset.ttl, soa.serial, soa.refresh,
   5739 				       soa.retry, soa.expire, soa.minimum);
   5740 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   5741 		}
   5742 
   5743 		result = dns_rdataset_next(&rdataset);
   5744 		dns_rdata_reset(&rdata);
   5745 	}
   5746 	dns_rdataset_disassociate(&rdataset);
   5747 
   5748 	result = ISC_R_SUCCESS;
   5749 
   5750 invalidate_rdataset:
   5751 	SET_IF_NOT_NULL(soacount, count);
   5752 	if (count == 0) {
   5753 		CLR_SOA_VALUES();
   5754 	}
   5755 
   5756 	dns_rdataset_invalidate(&rdataset);
   5757 
   5758 	return result;
   5759 }
   5760 
   5761 /*
   5762  * zone must be locked.
   5763  */
   5764 static isc_result_t
   5765 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
   5766 		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
   5767 		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
   5768 		 uint32_t *minimum, unsigned int *errors) {
   5769 	isc_result_t result;
   5770 	isc_result_t answer = ISC_R_SUCCESS;
   5771 	dns_dbversion_t *version = NULL;
   5772 	dns_dbnode_t *node;
   5773 
   5774 	REQUIRE(db != NULL);
   5775 	REQUIRE(zone != NULL);
   5776 
   5777 	dns_db_currentversion(db, &version);
   5778 
   5779 	SET_IF_NOT_NULL(nscount, 0);
   5780 	SET_IF_NOT_NULL(soacount, 0);
   5781 	SET_IF_NOT_NULL(errors, 0);
   5782 	CLR_SOA_VALUES();
   5783 
   5784 	node = NULL;
   5785 	result = dns_db_findnode(db, &zone->origin, false, &node);
   5786 	if (result != ISC_R_SUCCESS) {
   5787 		answer = result;
   5788 		goto closeversion;
   5789 	}
   5790 
   5791 	if (nscount != NULL || errors != NULL) {
   5792 		result = zone_count_ns_rr(zone, db, node, version, nscount,
   5793 					  errors, true);
   5794 		if (result != ISC_R_SUCCESS) {
   5795 			answer = result;
   5796 		}
   5797 	}
   5798 
   5799 	if (soacount != NULL || soattl != NULL || serial != NULL ||
   5800 	    refresh != NULL || retry != NULL || expire != NULL ||
   5801 	    minimum != NULL)
   5802 	{
   5803 		result = zone_load_soa_rr(db, node, version, soacount, soattl,
   5804 					  serial, refresh, retry, expire,
   5805 					  minimum);
   5806 		if (result != ISC_R_SUCCESS) {
   5807 			answer = result;
   5808 		}
   5809 	}
   5810 
   5811 	dns_db_detachnode(db, &node);
   5812 closeversion:
   5813 	dns_db_closeversion(db, &version, false);
   5814 
   5815 	return answer;
   5816 }
   5817 
   5818 static void
   5819 zone_destroy(dns_zone_t *zone) {
   5820 	/*
   5821 	 * Stop things being restarted after we cancel them below.
   5822 	 */
   5823 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
   5824 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "final reference detached");
   5825 
   5826 	if (zone->loop == NULL) {
   5827 		/*
   5828 		 * This zone is unmanaged; we're probably running in
   5829 		 * named-checkzone or a unit test. There's no loop, so we
   5830 		 * need to free it immediately.
   5831 		 */
   5832 		zone_shutdown(zone);
   5833 	} else {
   5834 		/*
   5835 		 * This zone has a loop; it can clean
   5836 		 * itself up asynchronously.
   5837 		 */
   5838 		isc_async_run(zone->loop, zone_shutdown, zone);
   5839 	}
   5840 }
   5841 
   5842 #if DNS_ZONE_TRACE
   5843 ISC_REFCOUNT_TRACE_IMPL(dns_zone, zone_destroy);
   5844 #else
   5845 ISC_REFCOUNT_IMPL(dns_zone, zone_destroy);
   5846 #endif
   5847 
   5848 void
   5849 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
   5850 	REQUIRE(DNS_ZONE_VALID(source));
   5851 
   5852 	LOCK_ZONE(source);
   5853 	zone_iattach(source, target);
   5854 	UNLOCK_ZONE(source);
   5855 }
   5856 
   5857 static void
   5858 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
   5859 	REQUIRE(DNS_ZONE_VALID(source));
   5860 	REQUIRE(LOCKED_ZONE(source));
   5861 	REQUIRE(target != NULL && *target == NULL);
   5862 	INSIST(isc_refcount_increment0(&source->irefs) +
   5863 		       isc_refcount_current(&source->references) >
   5864 	       0);
   5865 	*target = source;
   5866 }
   5867 
   5868 static void
   5869 zone_idetach(dns_zone_t **zonep) {
   5870 	dns_zone_t *zone;
   5871 
   5872 	/*
   5873 	 * 'zone' locked by caller.
   5874 	 */
   5875 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
   5876 	REQUIRE(LOCKED_ZONE(*zonep));
   5877 
   5878 	zone = *zonep;
   5879 	*zonep = NULL;
   5880 
   5881 	INSIST(isc_refcount_decrement(&zone->irefs) - 1 +
   5882 		       isc_refcount_current(&zone->references) >
   5883 	       0);
   5884 }
   5885 
   5886 void
   5887 dns_zone_idetach(dns_zone_t **zonep) {
   5888 	dns_zone_t *zone;
   5889 
   5890 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
   5891 
   5892 	zone = *zonep;
   5893 	*zonep = NULL;
   5894 
   5895 	if (isc_refcount_decrement(&zone->irefs) == 1) {
   5896 		bool free_needed;
   5897 		LOCK_ZONE(zone);
   5898 		free_needed = exit_check(zone);
   5899 		UNLOCK_ZONE(zone);
   5900 		if (free_needed) {
   5901 			zone_free(zone);
   5902 		}
   5903 	}
   5904 }
   5905 
   5906 isc_mem_t *
   5907 dns_zone_getmctx(dns_zone_t *zone) {
   5908 	REQUIRE(DNS_ZONE_VALID(zone));
   5909 
   5910 	return zone->mctx;
   5911 }
   5912 
   5913 dns_zonemgr_t *
   5914 dns_zone_getmgr(dns_zone_t *zone) {
   5915 	REQUIRE(DNS_ZONE_VALID(zone));
   5916 
   5917 	return zone->zmgr;
   5918 }
   5919 
   5920 void
   5921 dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
   5922 	REQUIRE(DNS_ZONE_VALID(zone));
   5923 
   5924 	LOCK_ZONE(zone);
   5925 	if (zone->kasp != NULL) {
   5926 		dns_kasp_detach(&zone->kasp);
   5927 	}
   5928 	if (kasp != NULL) {
   5929 		dns_kasp_attach(kasp, &zone->kasp);
   5930 	}
   5931 	UNLOCK_ZONE(zone);
   5932 }
   5933 
   5934 void
   5935 dns_zone_setdefaultkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
   5936 	REQUIRE(DNS_ZONE_VALID(zone));
   5937 
   5938 	LOCK_ZONE(zone);
   5939 	if (zone->defaultkasp != NULL) {
   5940 		dns_kasp_detach(&zone->defaultkasp);
   5941 	}
   5942 	if (kasp != NULL) {
   5943 		dns_kasp_attach(kasp, &zone->defaultkasp);
   5944 	}
   5945 	UNLOCK_ZONE(zone);
   5946 }
   5947 
   5948 dns_kasp_t *
   5949 dns_zone_getkasp(dns_zone_t *zone) {
   5950 	dns_kasp_t *kasp;
   5951 
   5952 	REQUIRE(DNS_ZONE_VALID(zone));
   5953 
   5954 	LOCK_ZONE(zone);
   5955 	if (inline_raw(zone) && zone->secure != NULL) {
   5956 		kasp = zone->secure->kasp;
   5957 	} else {
   5958 		kasp = zone->kasp;
   5959 	}
   5960 	UNLOCK_ZONE(zone);
   5961 
   5962 	return kasp;
   5963 }
   5964 
   5965 static void
   5966 dns_zone_setskr(dns_zone_t *zone, dns_skr_t *skr) {
   5967 	REQUIRE(DNS_ZONE_VALID(zone));
   5968 
   5969 	LOCK_ZONE(zone);
   5970 	zone->skrbundle = NULL;
   5971 	if (zone->skr != NULL) {
   5972 		dns_skr_detach(&zone->skr);
   5973 	}
   5974 	if (skr != NULL) {
   5975 		dns_skr_attach(skr, &zone->skr);
   5976 	}
   5977 	UNLOCK_ZONE(zone);
   5978 }
   5979 
   5980 dns_skrbundle_t *
   5981 dns_zone_getskrbundle(dns_zone_t *zone) {
   5982 	dns_skrbundle_t *bundle;
   5983 
   5984 	REQUIRE(DNS_ZONE_VALID(zone));
   5985 
   5986 	LOCK_ZONE(zone);
   5987 	if (inline_raw(zone) && zone->secure != NULL) {
   5988 		bundle = zone->secure->skrbundle;
   5989 	} else {
   5990 		bundle = zone->skrbundle;
   5991 	}
   5992 	UNLOCK_ZONE(zone);
   5993 
   5994 	return bundle;
   5995 }
   5996 
   5997 void
   5998 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
   5999 	REQUIRE(DNS_ZONE_VALID(zone));
   6000 
   6001 	if (value) {
   6002 		DNS_ZONE_SETOPTION(zone, option);
   6003 	} else {
   6004 		DNS_ZONE_CLROPTION(zone, option);
   6005 	}
   6006 }
   6007 
   6008 dns_zoneopt_t
   6009 dns_zone_getoptions(dns_zone_t *zone) {
   6010 	REQUIRE(DNS_ZONE_VALID(zone));
   6011 
   6012 	return ISC_ZONE_GET(zone, options);
   6013 }
   6014 
   6015 void
   6016 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value) {
   6017 	REQUIRE(DNS_ZONE_VALID(zone));
   6018 
   6019 	if (value) {
   6020 		DNS_ZONEKEY_SETOPTION(zone, keyopt);
   6021 	} else {
   6022 		DNS_ZONEKEY_CLROPTION(zone, keyopt);
   6023 	}
   6024 }
   6025 
   6026 unsigned int
   6027 dns_zone_getkeyopts(dns_zone_t *zone) {
   6028 	REQUIRE(DNS_ZONE_VALID(zone));
   6029 
   6030 	return ISC_ZONE_GET(zone, keyopts);
   6031 }
   6032 
   6033 void
   6034 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
   6035 	REQUIRE(DNS_ZONE_VALID(zone));
   6036 	REQUIRE(xfrsource != NULL);
   6037 
   6038 	LOCK_ZONE(zone);
   6039 	zone->xfrsource4 = *xfrsource;
   6040 	UNLOCK_ZONE(zone);
   6041 }
   6042 
   6043 void
   6044 dns_zone_getxfrsource4(dns_zone_t *zone, isc_sockaddr_t *xfrsource) {
   6045 	REQUIRE(DNS_ZONE_VALID(zone));
   6046 	REQUIRE(xfrsource != NULL);
   6047 
   6048 	LOCK_ZONE(zone);
   6049 	*xfrsource = zone->xfrsource4;
   6050 	UNLOCK_ZONE(zone);
   6051 }
   6052 
   6053 void
   6054 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
   6055 	REQUIRE(DNS_ZONE_VALID(zone));
   6056 	REQUIRE(xfrsource != NULL);
   6057 
   6058 	LOCK_ZONE(zone);
   6059 	zone->xfrsource6 = *xfrsource;
   6060 	UNLOCK_ZONE(zone);
   6061 }
   6062 
   6063 void
   6064 dns_zone_getxfrsource6(dns_zone_t *zone, isc_sockaddr_t *xfrsource) {
   6065 	REQUIRE(DNS_ZONE_VALID(zone));
   6066 	REQUIRE(xfrsource != NULL);
   6067 
   6068 	LOCK_ZONE(zone);
   6069 	*xfrsource = zone->xfrsource6;
   6070 	UNLOCK_ZONE(zone);
   6071 }
   6072 
   6073 void
   6074 dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
   6075 	REQUIRE(DNS_ZONE_VALID(zone));
   6076 	REQUIRE(parentalsrc != NULL);
   6077 
   6078 	LOCK_ZONE(zone);
   6079 	zone->parentalsrc4 = *parentalsrc;
   6080 	UNLOCK_ZONE(zone);
   6081 }
   6082 
   6083 void
   6084 dns_zone_getparentalsrc4(dns_zone_t *zone, isc_sockaddr_t *parentalsrc) {
   6085 	REQUIRE(DNS_ZONE_VALID(zone));
   6086 	REQUIRE(parentalsrc != NULL);
   6087 
   6088 	LOCK_ZONE(zone);
   6089 	*parentalsrc = zone->parentalsrc4;
   6090 	UNLOCK_ZONE(zone);
   6091 }
   6092 
   6093 void
   6094 dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
   6095 	REQUIRE(DNS_ZONE_VALID(zone));
   6096 
   6097 	LOCK_ZONE(zone);
   6098 	zone->parentalsrc6 = *parentalsrc;
   6099 	UNLOCK_ZONE(zone);
   6100 }
   6101 
   6102 void
   6103 dns_zone_getparentalsrc6(dns_zone_t *zone, isc_sockaddr_t *parentalsrc) {
   6104 	REQUIRE(DNS_ZONE_VALID(zone));
   6105 	REQUIRE(parentalsrc != NULL);
   6106 
   6107 	LOCK_ZONE(zone);
   6108 	*parentalsrc = zone->parentalsrc6;
   6109 	UNLOCK_ZONE(zone);
   6110 }
   6111 
   6112 void
   6113 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
   6114 	REQUIRE(DNS_ZONE_VALID(zone));
   6115 	REQUIRE(notifysrc != NULL);
   6116 
   6117 	LOCK_ZONE(zone);
   6118 	zone->notifysrc4 = *notifysrc;
   6119 	UNLOCK_ZONE(zone);
   6120 }
   6121 
   6122 void
   6123 dns_zone_getnotifysrc4(dns_zone_t *zone, isc_sockaddr_t *notifysrc) {
   6124 	REQUIRE(DNS_ZONE_VALID(zone));
   6125 	REQUIRE(notifysrc != NULL);
   6126 
   6127 	LOCK_ZONE(zone);
   6128 	*notifysrc = zone->notifysrc4;
   6129 	UNLOCK_ZONE(zone);
   6130 }
   6131 
   6132 void
   6133 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
   6134 	REQUIRE(DNS_ZONE_VALID(zone));
   6135 	REQUIRE(notifysrc != NULL);
   6136 
   6137 	LOCK_ZONE(zone);
   6138 	zone->notifysrc6 = *notifysrc;
   6139 	UNLOCK_ZONE(zone);
   6140 }
   6141 
   6142 void
   6143 dns_zone_getnotifysrc6(dns_zone_t *zone, isc_sockaddr_t *notifysrc) {
   6144 	REQUIRE(DNS_ZONE_VALID(zone));
   6145 	REQUIRE(notifysrc != NULL);
   6146 
   6147 	LOCK_ZONE(zone);
   6148 	*notifysrc = zone->notifysrc6;
   6149 	UNLOCK_ZONE(zone);
   6150 }
   6151 
   6152 void
   6153 dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *addresses,
   6154 		       isc_sockaddr_t *sources, dns_name_t **keynames,
   6155 		       dns_name_t **tlsnames, uint32_t count) {
   6156 	dns_remote_t remote;
   6157 
   6158 	REQUIRE(DNS_ZONE_VALID(zone));
   6159 
   6160 	LOCK_ZONE(zone);
   6161 
   6162 	remote.magic = DNS_REMOTE_MAGIC;
   6163 	remote.addresses = addresses;
   6164 	remote.sources = sources;
   6165 	remote.keynames = keynames;
   6166 	remote.tlsnames = tlsnames;
   6167 	remote.addrcnt = count;
   6168 
   6169 	if (dns_remote_equal(&zone->notify, &remote)) {
   6170 		goto unlock;
   6171 	}
   6172 
   6173 	dns_remote_clear(&zone->notify);
   6174 
   6175 	/*
   6176 	 * If count == 0, don't allocate any space for servers to notify.
   6177 	 */
   6178 	if (count == 0) {
   6179 		goto unlock;
   6180 	}
   6181 
   6182 	/*
   6183 	 * Now set up the notify address and key lists.
   6184 	 */
   6185 	dns_remote_init(&zone->notify, count, addresses, sources, keynames,
   6186 			tlsnames, true, zone->mctx);
   6187 
   6188 unlock:
   6189 	UNLOCK_ZONE(zone);
   6190 }
   6191 
   6192 static bool
   6193 has_pf(isc_sockaddr_t *addresses, size_t count, int pf) {
   6194 	for (size_t i = 0; i < count; i++) {
   6195 		if (isc_sockaddr_pf(&addresses[i]) == pf) {
   6196 			return true;
   6197 		}
   6198 	}
   6199 	return false;
   6200 }
   6201 
   6202 static void
   6203 report_no_active_addresses(dns_zone_t *zone, isc_sockaddr_t *addresses,
   6204 			   size_t count, const char *what) {
   6205 	if (isc_net_probeipv4() == ISC_R_DISABLED) {
   6206 		if (!has_pf(addresses, count, AF_INET6)) {
   6207 			dns_zone_log(zone, ISC_LOG_NOTICE,
   6208 				     "IPv4 disabled and no IPv6 %s", what);
   6209 		}
   6210 	} else if (isc_net_probeipv6() == ISC_R_DISABLED) {
   6211 		if (!has_pf(addresses, count, AF_INET)) {
   6212 			dns_zone_log(zone, ISC_LOG_NOTICE,
   6213 				     "IPv6 disabled and no IPv4 %s", what);
   6214 		}
   6215 	}
   6216 }
   6217 
   6218 void
   6219 dns_zone_setprimaries(dns_zone_t *zone, isc_sockaddr_t *addresses,
   6220 		      isc_sockaddr_t *sources, dns_name_t **keynames,
   6221 		      dns_name_t **tlsnames, uint32_t count) {
   6222 	dns_remote_t remote;
   6223 
   6224 	REQUIRE(DNS_ZONE_VALID(zone));
   6225 
   6226 	LOCK_ZONE(zone);
   6227 
   6228 	remote.magic = DNS_REMOTE_MAGIC;
   6229 	remote.addresses = addresses;
   6230 	remote.sources = sources;
   6231 	remote.keynames = keynames;
   6232 	remote.tlsnames = tlsnames;
   6233 	remote.addrcnt = count;
   6234 
   6235 	/*
   6236 	 * The refresh code assumes that 'primaries' wouldn't change under it.
   6237 	 * If it will change then kill off any current refresh in progress
   6238 	 * and update the primaries info.  If it won't change then we can just
   6239 	 * unlock and exit.
   6240 	 */
   6241 	if (!dns_remote_equal(&zone->primaries, &remote)) {
   6242 		if (zone->request != NULL) {
   6243 			dns_request_cancel(zone->request);
   6244 		}
   6245 	} else {
   6246 		goto unlock;
   6247 	}
   6248 
   6249 	dns_remote_clear(&zone->primaries);
   6250 
   6251 	/*
   6252 	 * If count == 0, don't allocate any space for primaries.
   6253 	 */
   6254 	if (count == 0) {
   6255 		goto unlock;
   6256 	}
   6257 
   6258 	report_no_active_addresses(zone, addresses, count, "primaries");
   6259 
   6260 	/*
   6261 	 * Now set up the primaries and primary key lists.
   6262 	 */
   6263 	dns_remote_init(&zone->primaries, count, addresses, sources, keynames,
   6264 			tlsnames, true, zone->mctx);
   6265 
   6266 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
   6267 
   6268 unlock:
   6269 	UNLOCK_ZONE(zone);
   6270 }
   6271 
   6272 void
   6273 dns_zone_setparentals(dns_zone_t *zone, isc_sockaddr_t *addresses,
   6274 		      isc_sockaddr_t *sources, dns_name_t **keynames,
   6275 		      dns_name_t **tlsnames, uint32_t count) {
   6276 	dns_remote_t remote;
   6277 
   6278 	REQUIRE(DNS_ZONE_VALID(zone));
   6279 
   6280 	LOCK_ZONE(zone);
   6281 
   6282 	remote.magic = DNS_REMOTE_MAGIC;
   6283 	remote.addresses = addresses;
   6284 	remote.sources = sources;
   6285 	remote.keynames = keynames;
   6286 	remote.tlsnames = tlsnames;
   6287 	remote.addrcnt = count;
   6288 
   6289 	if (dns_remote_equal(&zone->parentals, &remote)) {
   6290 		goto unlock;
   6291 	}
   6292 
   6293 	dns_remote_clear(&zone->parentals);
   6294 
   6295 	/*
   6296 	 * If count == 0, don't allocate any space for parentals.
   6297 	 */
   6298 	if (count == 0) {
   6299 		goto unlock;
   6300 	}
   6301 
   6302 	report_no_active_addresses(zone, addresses, count, "parental-agents");
   6303 
   6304 	/*
   6305 	 * Now set up the parentals and parental key lists.
   6306 	 */
   6307 	dns_remote_init(&zone->parentals, count, addresses, sources, keynames,
   6308 			tlsnames, true, zone->mctx);
   6309 
   6310 	dns_zone_log(zone, ISC_LOG_NOTICE, "checkds: set %u parentals", count);
   6311 
   6312 unlock:
   6313 	UNLOCK_ZONE(zone);
   6314 }
   6315 
   6316 isc_result_t
   6317 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
   6318 	isc_result_t result = ISC_R_SUCCESS;
   6319 
   6320 	REQUIRE(DNS_ZONE_VALID(zone));
   6321 
   6322 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   6323 	if (zone->db == NULL) {
   6324 		result = DNS_R_NOTLOADED;
   6325 	} else {
   6326 		dns_db_attach(zone->db, dpb);
   6327 	}
   6328 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   6329 
   6330 	return result;
   6331 }
   6332 
   6333 void
   6334 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
   6335 	REQUIRE(DNS_ZONE_VALID(zone));
   6336 	REQUIRE(zone->type == dns_zone_staticstub);
   6337 
   6338 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   6339 	REQUIRE(zone->db == NULL);
   6340 	dns_db_attach(db, &zone->db);
   6341 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   6342 }
   6343 
   6344 static bool
   6345 was_dumping(dns_zone_t *zone) {
   6346 	REQUIRE(LOCKED_ZONE(zone));
   6347 
   6348 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   6349 		return true;
   6350 	}
   6351 
   6352 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
   6353 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   6354 	isc_time_settoepoch(&zone->dumptime);
   6355 	return false;
   6356 }
   6357 
   6358 static isc_result_t
   6359 keyfromfile(dns_zone_t *zone, dst_key_t *pubkey, isc_mem_t *mctx,
   6360 	    dst_key_t **key) {
   6361 	const char *directory = zone->keydirectory;
   6362 	dns_kasp_t *kasp = zone->kasp;
   6363 	dst_key_t *foundkey = NULL;
   6364 	isc_result_t result = ISC_R_NOTFOUND;
   6365 
   6366 	if (kasp == NULL || (strcmp(dns_kasp_getname(kasp), "none") == 0) ||
   6367 	    (strcmp(dns_kasp_getname(kasp), "insecure") == 0))
   6368 	{
   6369 		result = dst_key_fromfile(
   6370 			dst_key_name(pubkey), dst_key_id(pubkey),
   6371 			dst_key_alg(pubkey),
   6372 			DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE,
   6373 			directory, mctx, &foundkey);
   6374 	} else {
   6375 		for (dns_kasp_key_t *kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp));
   6376 		     kkey != NULL; kkey = ISC_LIST_NEXT(kkey, link))
   6377 		{
   6378 			dns_keystore_t *ks = dns_kasp_key_keystore(kkey);
   6379 			directory = dns_keystore_directory(ks,
   6380 							   zone->keydirectory);
   6381 
   6382 			result = dst_key_fromfile(
   6383 				dst_key_name(pubkey), dst_key_id(pubkey),
   6384 				dst_key_alg(pubkey),
   6385 				DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
   6386 					DST_TYPE_STATE,
   6387 				directory, mctx, &foundkey);
   6388 			if (result == ISC_R_SUCCESS) {
   6389 				break;
   6390 			}
   6391 		}
   6392 	}
   6393 
   6394 	*key = foundkey;
   6395 	return result;
   6396 }
   6397 
   6398 #define is_zone_key(key) \
   6399 	((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE)
   6400 
   6401 static isc_result_t
   6402 findzonekeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   6403 	     dns_dbnode_t *node, const dns_name_t *name, isc_stdtime_t now,
   6404 	     isc_mem_t *mctx, unsigned int maxkeys, dst_key_t **keys,
   6405 	     unsigned int *nkeys) {
   6406 	dns_rdataset_t rdataset;
   6407 	dns_rdata_t rdata = DNS_RDATA_INIT;
   6408 	isc_result_t result;
   6409 	dst_key_t *pubkey = NULL;
   6410 	unsigned int count = 0;
   6411 
   6412 	*nkeys = 0;
   6413 	memset(keys, 0, sizeof(*keys) * maxkeys);
   6414 	dns_rdataset_init(&rdataset);
   6415 	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
   6416 				  &rdataset, NULL));
   6417 	CHECK(dns_rdataset_first(&rdataset));
   6418 	while (result == ISC_R_SUCCESS && count < maxkeys) {
   6419 		pubkey = NULL;
   6420 		dns_rdataset_current(&rdataset, &rdata);
   6421 		CHECK(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey));
   6422 		dst_key_setttl(pubkey, rdataset.ttl);
   6423 
   6424 		if (!is_zone_key(pubkey)) {
   6425 			goto next;
   6426 		}
   6427 		/* Corrupted .key file? */
   6428 		if (!dns_name_equal(name, dst_key_name(pubkey))) {
   6429 			goto next;
   6430 		}
   6431 		keys[count] = NULL;
   6432 		result = keyfromfile(zone, pubkey, mctx, &keys[count]);
   6433 
   6434 		/*
   6435 		 * If the key was revoked and the private file
   6436 		 * doesn't exist, maybe it was revoked internally
   6437 		 * by named.  Try loading the unrevoked version.
   6438 		 */
   6439 		if (result == ISC_R_FILENOTFOUND) {
   6440 			uint32_t flags;
   6441 			flags = dst_key_flags(pubkey);
   6442 			if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
   6443 				dst_key_setflags(pubkey,
   6444 						 flags & ~DNS_KEYFLAG_REVOKE);
   6445 				result = keyfromfile(zone, pubkey, mctx,
   6446 						     &keys[count]);
   6447 				if (result == ISC_R_SUCCESS &&
   6448 				    dst_key_pubcompare(pubkey, keys[count],
   6449 						       false))
   6450 				{
   6451 					dst_key_setflags(keys[count], flags);
   6452 				}
   6453 				dst_key_setflags(pubkey, flags);
   6454 			}
   6455 		}
   6456 
   6457 		if (result != ISC_R_SUCCESS) {
   6458 			char filename[DNS_NAME_FORMATSIZE +
   6459 				      DNS_SECALG_FORMATSIZE +
   6460 				      sizeof("key file for //65535")];
   6461 			isc_result_t result2;
   6462 			isc_buffer_t buf;
   6463 
   6464 			isc_buffer_init(&buf, filename, sizeof(filename));
   6465 			result2 = dst_key_getfilename(
   6466 				dst_key_name(pubkey), dst_key_id(pubkey),
   6467 				dst_key_alg(pubkey),
   6468 				DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
   6469 					DST_TYPE_STATE,
   6470 				NULL, mctx, &buf);
   6471 			if (result2 != ISC_R_SUCCESS) {
   6472 				char namebuf[DNS_NAME_FORMATSIZE];
   6473 				char algbuf[DNS_SECALG_FORMATSIZE];
   6474 
   6475 				dns_name_format(dst_key_name(pubkey), namebuf,
   6476 						sizeof(namebuf));
   6477 				dns_secalg_format(dst_key_alg(pubkey), algbuf,
   6478 						  sizeof(algbuf));
   6479 				snprintf(filename, sizeof(filename) - 1,
   6480 					 "key file for %s/%s/%d", namebuf,
   6481 					 algbuf, dst_key_id(pubkey));
   6482 			}
   6483 
   6484 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   6485 				      DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
   6486 				      "dns_zone_findkeys: error reading %s: %s",
   6487 				      filename, isc_result_totext(result));
   6488 		}
   6489 
   6490 		if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
   6491 			keys[count] = pubkey;
   6492 			pubkey = NULL;
   6493 			count++;
   6494 			goto next;
   6495 		}
   6496 
   6497 		CHECK(result);
   6498 
   6499 		/*
   6500 		 * If a key is marked inactive, skip it
   6501 		 */
   6502 		if (!dns_dnssec_keyactive(keys[count], now)) {
   6503 			dst_key_setinactive(pubkey, true);
   6504 			dst_key_free(&keys[count]);
   6505 			keys[count] = pubkey;
   6506 			pubkey = NULL;
   6507 			count++;
   6508 			goto next;
   6509 		}
   6510 
   6511 		/*
   6512 		 * Whatever the key's default TTL may have
   6513 		 * been, the rdataset TTL takes priority.
   6514 		 */
   6515 		dst_key_setttl(keys[count], rdataset.ttl);
   6516 		count++;
   6517 	next:
   6518 		if (pubkey != NULL) {
   6519 			dst_key_free(&pubkey);
   6520 		}
   6521 		dns_rdata_reset(&rdata);
   6522 		result = dns_rdataset_next(&rdataset);
   6523 	}
   6524 	if (result != ISC_R_NOMORE) {
   6525 		CHECK(result);
   6526 	}
   6527 	if (count == 0) {
   6528 		result = ISC_R_NOTFOUND;
   6529 	} else {
   6530 		result = ISC_R_SUCCESS;
   6531 	}
   6532 
   6533 cleanup:
   6534 	if (dns_rdataset_isassociated(&rdataset)) {
   6535 		dns_rdataset_disassociate(&rdataset);
   6536 	}
   6537 	if (pubkey != NULL) {
   6538 		dst_key_free(&pubkey);
   6539 	}
   6540 	if (result != ISC_R_SUCCESS) {
   6541 		while (count > 0) {
   6542 			dst_key_free(&keys[--count]);
   6543 		}
   6544 	}
   6545 	*nkeys = count;
   6546 	return result;
   6547 }
   6548 
   6549 /*%
   6550  * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
   6551  * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
   6552  * Only load the public part of a given key if it is not active at timestamp
   6553  * 'now'.  Store the number of keys found in 'nkeys'.
   6554  */
   6555 isc_result_t
   6556 dns_zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   6557 		  isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
   6558 		  dst_key_t **keys, unsigned int *nkeys) {
   6559 	isc_result_t result;
   6560 	dns_dbnode_t *node = NULL;
   6561 
   6562 	REQUIRE(DNS_ZONE_VALID(zone));
   6563 	REQUIRE(mctx != NULL);
   6564 	REQUIRE(nkeys != NULL);
   6565 	REQUIRE(keys != NULL);
   6566 
   6567 	CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
   6568 
   6569 	dns_zone_lock_keyfiles(zone);
   6570 
   6571 	result = findzonekeys(zone, db, ver, node, dns_db_origin(db), now, mctx,
   6572 			      maxkeys, keys, nkeys);
   6573 
   6574 	dns_zone_unlock_keyfiles(zone);
   6575 
   6576 	if (result == ISC_R_NOTFOUND) {
   6577 		result = ISC_R_SUCCESS;
   6578 	}
   6579 
   6580 cleanup:
   6581 
   6582 	if (node != NULL) {
   6583 		dns_db_detachnode(db, &node);
   6584 	}
   6585 	return result;
   6586 }
   6587 
   6588 void
   6589 dns_zone_prepare_shutdown(dns_zone_t *zone) {
   6590 	REQUIRE(DNS_ZONE_VALID(zone));
   6591 
   6592 	LOCK_ZONE(zone);
   6593 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
   6594 	UNLOCK_ZONE(zone);
   6595 }
   6596 
   6597 /*%
   6598  * Find DNSSEC keys used for signing zone with dnssec-policy. Load these keys
   6599  * into 'keys'. Requires KASP to be locked.
   6600  */
   6601 isc_result_t
   6602 dns_zone_getdnsseckeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   6603 		       isc_stdtime_t now, dns_dnsseckeylist_t *keys) {
   6604 	isc_result_t result;
   6605 	const char *dir = dns_zone_getkeydirectory(zone);
   6606 	dns_dbnode_t *node = NULL;
   6607 	dns_dnsseckey_t *key, *key_next;
   6608 	dns_dnsseckeylist_t dnskeys;
   6609 	dns_name_t *origin = dns_zone_getorigin(zone);
   6610 	dns_kasp_t *kasp = zone->kasp;
   6611 	dns_rdataset_t keyset;
   6612 
   6613 	REQUIRE(DNS_ZONE_VALID(zone));
   6614 	REQUIRE(kasp != NULL);
   6615 
   6616 	ISC_LIST_INIT(dnskeys);
   6617 
   6618 	dns_rdataset_init(&keyset);
   6619 
   6620 	CHECK(dns_db_findnode(db, origin, false, &node));
   6621 
   6622 	/* Get keys from private key files. */
   6623 	dns_zone_lock_keyfiles(zone);
   6624 	result = dns_dnssec_findmatchingkeys(origin, kasp, dir, zone->keystores,
   6625 					     now, false, dns_zone_getmctx(zone),
   6626 					     keys);
   6627 	dns_zone_unlock_keyfiles(zone);
   6628 
   6629 	if (result != ISC_R_NOTFOUND) {
   6630 		CHECK(result);
   6631 	}
   6632 
   6633 	/* Get public keys (dnskeys). */
   6634 	dns_rdataset_init(&keyset);
   6635 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
   6636 				     dns_rdatatype_none, 0, &keyset, NULL);
   6637 	if (result == ISC_R_SUCCESS) {
   6638 		CHECK(dns_dnssec_keylistfromrdataset(
   6639 			origin, kasp, dir, dns_zone_getmctx(zone), &keyset,
   6640 			NULL, NULL, false, false, &dnskeys));
   6641 	} else if (result != ISC_R_NOTFOUND) {
   6642 		CHECK(result);
   6643 	}
   6644 
   6645 	/* Add new 'dnskeys' to 'keys'. */
   6646 	for (dns_dnsseckey_t *k1 = ISC_LIST_HEAD(dnskeys); k1 != NULL;
   6647 	     k1 = key_next)
   6648 	{
   6649 		dns_dnsseckey_t *k2 = NULL;
   6650 		key_next = ISC_LIST_NEXT(k1, link);
   6651 
   6652 		for (k2 = ISC_LIST_HEAD(*keys); k2 != NULL;
   6653 		     k2 = ISC_LIST_NEXT(k2, link))
   6654 		{
   6655 			if (dst_key_compare(k1->key, k2->key)) {
   6656 				break;
   6657 			}
   6658 		}
   6659 		/* No match found, add the new key. */
   6660 		if (k2 == NULL) {
   6661 			ISC_LIST_UNLINK(dnskeys, k1, link);
   6662 			ISC_LIST_APPEND(*keys, k1, link);
   6663 		}
   6664 	}
   6665 
   6666 cleanup:
   6667 	if (dns_rdataset_isassociated(&keyset)) {
   6668 		dns_rdataset_disassociate(&keyset);
   6669 	}
   6670 	if (node != NULL) {
   6671 		dns_db_detachnode(db, &node);
   6672 	}
   6673 	while (!ISC_LIST_EMPTY(dnskeys)) {
   6674 		key = ISC_LIST_HEAD(dnskeys);
   6675 		ISC_LIST_UNLINK(dnskeys, key, link);
   6676 		dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
   6677 	}
   6678 	return result;
   6679 }
   6680 
   6681 static isc_result_t
   6682 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
   6683 	dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) {
   6684 	isc_result_t result;
   6685 
   6686 	if ((rdata->flags & DNS_RDATA_OFFLINE) != 0) {
   6687 		return ISC_R_SUCCESS;
   6688 	}
   6689 	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
   6690 			       name, ttl, rdata);
   6691 	if (result != ISC_R_SUCCESS) {
   6692 		return result;
   6693 	}
   6694 	rdata->flags |= DNS_RDATA_OFFLINE;
   6695 	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
   6696 			       name, ttl, rdata);
   6697 	zonediff->offline = true;
   6698 	return result;
   6699 }
   6700 
   6701 static void
   6702 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when,
   6703 		       isc_stdtime_t now) {
   6704 	unsigned int delta;
   6705 	char timebuf[80];
   6706 
   6707 	LOCK_ZONE(zone);
   6708 	zone->key_expiry = when;
   6709 	if (when <= now) {
   6710 		dns_zone_log(zone, ISC_LOG_ERROR,
   6711 			     "DNSKEY RRSIG(s) have expired");
   6712 		isc_time_settoepoch(&zone->keywarntime);
   6713 	} else if (when < now + 7 * 24 * 3600) {
   6714 		isc_time_t t;
   6715 		isc_time_set(&t, when, 0);
   6716 		isc_time_formattimestamp(&t, timebuf, 80);
   6717 		dns_zone_log(zone, ISC_LOG_WARNING,
   6718 			     "DNSKEY RRSIG(s) will expire within 7 days: %s",
   6719 			     timebuf);
   6720 		delta = when - now;
   6721 		delta--;	    /* loop prevention */
   6722 		delta /= 24 * 3600; /* to whole days */
   6723 		delta *= 24 * 3600; /* to seconds */
   6724 		isc_time_set(&zone->keywarntime, when - delta, 0);
   6725 	} else {
   6726 		isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
   6727 		isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
   6728 		dns_zone_log(zone, ISC_LOG_NOTICE, "setting keywarntime to %s",
   6729 			     timebuf);
   6730 	}
   6731 	UNLOCK_ZONE(zone);
   6732 }
   6733 
   6734 /*
   6735  * Helper function to del_sigs(). We don't want to delete RRSIGs that
   6736  * have no new key.
   6737  */
   6738 static bool
   6739 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
   6740 	  bool kasp, bool *warn) {
   6741 	unsigned int i = 0;
   6742 	isc_result_t ret;
   6743 	bool have_ksk = false, have_zsk = false;
   6744 	bool have_pksk = false, have_pzsk = false;
   6745 
   6746 	for (i = 0; i < nkeys; i++) {
   6747 		bool ksk, zsk;
   6748 
   6749 		if (have_pksk && have_ksk && have_pzsk && have_zsk) {
   6750 			break;
   6751 		}
   6752 
   6753 		if (rrsig_ptr->algorithm != dst_key_alg(keys[i])) {
   6754 			continue;
   6755 		}
   6756 
   6757 		ret = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
   6758 		if (ret != ISC_R_SUCCESS) {
   6759 			ksk = KSK(keys[i]);
   6760 		}
   6761 		ret = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
   6762 		if (ret != ISC_R_SUCCESS) {
   6763 			zsk = !KSK(keys[i]);
   6764 		}
   6765 
   6766 		if (ksk) {
   6767 			have_ksk = true;
   6768 			if (dst_key_isprivate(keys[i])) {
   6769 				have_pksk = true;
   6770 			}
   6771 		}
   6772 		if (zsk) {
   6773 			have_zsk = true;
   6774 			if (dst_key_isprivate(keys[i])) {
   6775 				have_pzsk = true;
   6776 			}
   6777 		}
   6778 	}
   6779 
   6780 	if (have_zsk && have_ksk && !have_pzsk) {
   6781 		*warn = true;
   6782 	}
   6783 
   6784 	if (have_pksk && have_pzsk) {
   6785 		return true;
   6786 	}
   6787 
   6788 	/*
   6789 	 * Deleting the SOA RRSIG is always okay.
   6790 	 */
   6791 	if (rrsig_ptr->covered == dns_rdatatype_soa) {
   6792 		return true;
   6793 	}
   6794 
   6795 	/*
   6796 	 * It's okay to delete a signature if there is an active key with the
   6797 	 * same algorithm to replace it, unless that violates the DNSSEC
   6798 	 * policy.
   6799 	 */
   6800 	if (have_pksk || have_pzsk) {
   6801 		if (kasp && have_pzsk) {
   6802 			return true;
   6803 		}
   6804 		return !kasp;
   6805 	}
   6806 
   6807 	/*
   6808 	 * Failing that, it is *not* okay to delete a signature
   6809 	 * if the associated public key is still in the DNSKEY RRset
   6810 	 */
   6811 	for (i = 0; i < nkeys; i++) {
   6812 		if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
   6813 		    (rrsig_ptr->keyid == dst_key_id(keys[i])))
   6814 		{
   6815 			return false;
   6816 		}
   6817 	}
   6818 
   6819 	/*
   6820 	 * But if the key is gone, then go ahead.
   6821 	 */
   6822 	return true;
   6823 }
   6824 
   6825 /*
   6826  * Delete expired RRsigs and any RRsigs we are about to re-sign.
   6827  * See also update.c:del_keysigs().
   6828  */
   6829 static isc_result_t
   6830 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
   6831 	 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
   6832 	 unsigned int nkeys, isc_stdtime_t now, bool incremental) {
   6833 	isc_result_t result;
   6834 	dns_dbnode_t *node = NULL;
   6835 	dns_rdataset_t rdataset;
   6836 	unsigned int i;
   6837 	dns_rdata_rrsig_t rrsig;
   6838 	dns_kasp_t *kasp = zone->kasp;
   6839 	bool found;
   6840 	bool offlineksk = false;
   6841 	int64_t timewarn = 0, timemaybe = 0;
   6842 
   6843 	dns_rdataset_init(&rdataset);
   6844 
   6845 	if (kasp != NULL) {
   6846 		offlineksk = dns_kasp_offlineksk(kasp);
   6847 	}
   6848 
   6849 	if (type == dns_rdatatype_nsec3) {
   6850 		result = dns_db_findnsec3node(db, name, false, &node);
   6851 	} else {
   6852 		result = dns_db_findnode(db, name, false, &node);
   6853 	}
   6854 	if (result == ISC_R_NOTFOUND) {
   6855 		return ISC_R_SUCCESS;
   6856 	}
   6857 	CHECK(result);
   6858 
   6859 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
   6860 				     (isc_stdtime_t)0, &rdataset, NULL);
   6861 	dns_db_detachnode(db, &node);
   6862 
   6863 	if (result == ISC_R_NOTFOUND) {
   6864 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6865 		return ISC_R_SUCCESS;
   6866 	}
   6867 	if (result != ISC_R_SUCCESS) {
   6868 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6869 		goto cleanup;
   6870 	}
   6871 
   6872 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   6873 	     result = dns_rdataset_next(&rdataset))
   6874 	{
   6875 		dns_rdata_t rdata = DNS_RDATA_INIT;
   6876 
   6877 		dns_rdataset_current(&rdataset, &rdata);
   6878 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   6879 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   6880 
   6881 		if (!dns_rdatatype_iskeymaterial(type)) {
   6882 			bool warn = false, deleted = false;
   6883 			if (delsig_ok(&rrsig, keys, nkeys, kasp != NULL, &warn))
   6884 			{
   6885 				result = update_one_rr(db, ver, zonediff->diff,
   6886 						       DNS_DIFFOP_DELRESIGN,
   6887 						       name, rdataset.ttl,
   6888 						       &rdata);
   6889 				if (result != ISC_R_SUCCESS) {
   6890 					break;
   6891 				}
   6892 				deleted = true;
   6893 			}
   6894 			if (warn && !deleted) {
   6895 				/*
   6896 				 * At this point, we've got an RRSIG,
   6897 				 * which is signed by an inactive key.
   6898 				 * An administrator needs to provide a new
   6899 				 * key/alg, but until that time, we want to
   6900 				 * keep the old RRSIG.  Marking the key as
   6901 				 * offline will prevent us spinning waiting
   6902 				 * for the private part.
   6903 				 */
   6904 				if (incremental) {
   6905 					result = offline(db, ver, zonediff,
   6906 							 name, rdataset.ttl,
   6907 							 &rdata);
   6908 					if (result != ISC_R_SUCCESS) {
   6909 						break;
   6910 					}
   6911 				}
   6912 
   6913 				/*
   6914 				 * Log the key id and algorithm of
   6915 				 * the inactive key with no replacement
   6916 				 */
   6917 				if (zone->log_key_expired_timer <= now) {
   6918 					char origin[DNS_NAME_FORMATSIZE];
   6919 					char algbuf[DNS_NAME_FORMATSIZE];
   6920 					dns_name_format(&zone->origin, origin,
   6921 							sizeof(origin));
   6922 					dns_secalg_format(rrsig.algorithm,
   6923 							  algbuf,
   6924 							  sizeof(algbuf));
   6925 					dns_zone_log(zone, ISC_LOG_WARNING,
   6926 						     "Key %s/%s/%d "
   6927 						     "missing or inactive "
   6928 						     "and has no replacement: "
   6929 						     "retaining signatures.",
   6930 						     origin, algbuf,
   6931 						     rrsig.keyid);
   6932 					zone->log_key_expired_timer = now +
   6933 								      3600;
   6934 				}
   6935 			}
   6936 			continue;
   6937 		}
   6938 
   6939 		/*
   6940 		 * KSK RRSIGs requires special processing.
   6941 		 */
   6942 		found = false;
   6943 		for (i = 0; i < nkeys; i++) {
   6944 			if (rrsig.algorithm == dst_key_alg(keys[i]) &&
   6945 			    rrsig.keyid == dst_key_id(keys[i]))
   6946 			{
   6947 				found = true;
   6948 				/*
   6949 				 * Mark offline DNSKEY.
   6950 				 * We want the earliest offline expire time
   6951 				 * iff there is a new offline signature.
   6952 				 */
   6953 				if (!dst_key_inactive(keys[i]) &&
   6954 				    !dst_key_isprivate(keys[i]) && !offlineksk)
   6955 				{
   6956 					int64_t timeexpire = dns_time64_from32(
   6957 						rrsig.timeexpire);
   6958 					if (timewarn != 0 &&
   6959 					    timewarn > timeexpire)
   6960 					{
   6961 						timewarn = timeexpire;
   6962 					}
   6963 					if (rdata.flags & DNS_RDATA_OFFLINE) {
   6964 						if (timemaybe == 0 ||
   6965 						    timemaybe > timeexpire)
   6966 						{
   6967 							timemaybe = timeexpire;
   6968 						}
   6969 						break;
   6970 					}
   6971 					if (timewarn == 0) {
   6972 						timewarn = timemaybe;
   6973 					}
   6974 					if (timewarn == 0 ||
   6975 					    timewarn > timeexpire)
   6976 					{
   6977 						timewarn = timeexpire;
   6978 					}
   6979 					result = offline(db, ver, zonediff,
   6980 							 name, rdataset.ttl,
   6981 							 &rdata);
   6982 					break;
   6983 				}
   6984 				result = update_one_rr(db, ver, zonediff->diff,
   6985 						       DNS_DIFFOP_DELRESIGN,
   6986 						       name, rdataset.ttl,
   6987 						       &rdata);
   6988 				break;
   6989 			}
   6990 		}
   6991 
   6992 		/*
   6993 		 * If there is not a matching DNSKEY then
   6994 		 * delete the RRSIG.
   6995 		 */
   6996 		if (!found) {
   6997 			result = update_one_rr(db, ver, zonediff->diff,
   6998 					       DNS_DIFFOP_DELRESIGN, name,
   6999 					       rdataset.ttl, &rdata);
   7000 		}
   7001 		if (result != ISC_R_SUCCESS) {
   7002 			break;
   7003 		}
   7004 	}
   7005 
   7006 	dns_rdataset_disassociate(&rdataset);
   7007 	if (result == ISC_R_NOMORE) {
   7008 		result = ISC_R_SUCCESS;
   7009 	}
   7010 	if (timewarn > 0) {
   7011 		isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
   7012 		if (timewarn == stdwarn) {
   7013 			set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
   7014 					       now);
   7015 		} else {
   7016 			dns_zone_log(zone, ISC_LOG_ERROR,
   7017 				     "key expiry warning time out of range");
   7018 		}
   7019 	}
   7020 cleanup:
   7021 	if (node != NULL) {
   7022 		dns_db_detachnode(db, &node);
   7023 	}
   7024 	return result;
   7025 }
   7026 
   7027 static isc_result_t
   7028 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
   7029 	 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
   7030 	 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t now,
   7031 	 isc_stdtime_t inception, isc_stdtime_t expire) {
   7032 	isc_result_t result;
   7033 	dns_dbnode_t *node = NULL;
   7034 	dns_stats_t *dnssecsignstats;
   7035 	dns_rdataset_t rdataset;
   7036 	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
   7037 	unsigned char data[1024]; /* XXX */
   7038 	isc_buffer_t buffer;
   7039 	unsigned int i;
   7040 	bool use_kasp = false;
   7041 	bool offlineksk = false;
   7042 
   7043 	if (zone->kasp != NULL) {
   7044 		use_kasp = true;
   7045 		offlineksk = dns_kasp_offlineksk(zone->kasp);
   7046 	}
   7047 
   7048 	dns_rdataset_init(&rdataset);
   7049 	isc_buffer_init(&buffer, data, sizeof(data));
   7050 
   7051 	if (type == dns_rdatatype_nsec3) {
   7052 		result = dns_db_findnsec3node(db, name, false, &node);
   7053 	} else {
   7054 		result = dns_db_findnode(db, name, false, &node);
   7055 	}
   7056 	if (result == ISC_R_NOTFOUND) {
   7057 		return ISC_R_SUCCESS;
   7058 	}
   7059 	CHECK(result);
   7060 
   7061 	result = dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t)0,
   7062 				     &rdataset, NULL);
   7063 	dns_db_detachnode(db, &node);
   7064 	if (result == ISC_R_NOTFOUND) {
   7065 		INSIST(!dns_rdataset_isassociated(&rdataset));
   7066 		return ISC_R_SUCCESS;
   7067 	}
   7068 	if (result != ISC_R_SUCCESS) {
   7069 		INSIST(!dns_rdataset_isassociated(&rdataset));
   7070 		goto cleanup;
   7071 	}
   7072 
   7073 	for (i = 0; i < nkeys; i++) {
   7074 		/* Don't add signatures for offline or inactive keys */
   7075 		if (!dst_key_isprivate(keys[i]) && !offlineksk) {
   7076 			continue;
   7077 		}
   7078 		if (dst_key_inactive(keys[i]) && !offlineksk) {
   7079 			continue;
   7080 		}
   7081 
   7082 		if (use_kasp) {
   7083 			/*
   7084 			 * A dnssec-policy is found. Check what RRsets this
   7085 			 * key should sign.
   7086 			 */
   7087 			isc_result_t kresult;
   7088 			isc_stdtime_t when;
   7089 			bool ksk = false;
   7090 			bool zsk = false;
   7091 			bool have_zsk = false;
   7092 
   7093 			kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
   7094 			if (kresult != ISC_R_SUCCESS) {
   7095 				if (KSK(keys[i])) {
   7096 					ksk = true;
   7097 				}
   7098 			}
   7099 			kresult = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
   7100 			if (kresult != ISC_R_SUCCESS) {
   7101 				if (!KSK(keys[i])) {
   7102 					zsk = true;
   7103 				}
   7104 			}
   7105 
   7106 			/*
   7107 			 * Don't consider inactive keys or offline keys.
   7108 			 */
   7109 			if (!dst_key_isprivate(keys[i]) && offlineksk && zsk) {
   7110 				continue;
   7111 			}
   7112 			if (dst_key_inactive(keys[i]) && offlineksk && zsk) {
   7113 				continue;
   7114 			}
   7115 
   7116 			if (offlineksk) {
   7117 				have_zsk = true;
   7118 			} else {
   7119 				(void)dst_key_have_ksk_and_zsk(keys, nkeys, i,
   7120 							       true, ksk, zsk,
   7121 							       NULL, &have_zsk);
   7122 			}
   7123 
   7124 			if (dns_rdatatype_iskeymaterial(type)) {
   7125 				/*
   7126 				 * DNSKEY RRset is signed with KSK.
   7127 				 * CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
   7128 				 */
   7129 				if (!ksk) {
   7130 					continue;
   7131 				}
   7132 			} else if (!zsk) {
   7133 				/*
   7134 				 * Other RRsets are signed with ZSK.
   7135 				 */
   7136 				if (type != dns_rdatatype_soa &&
   7137 				    type != zone->privatetype)
   7138 				{
   7139 					continue;
   7140 				}
   7141 				if (have_zsk) {
   7142 					continue;
   7143 				}
   7144 			} else if (!dst_key_is_signing(keys[i], DST_BOOL_ZSK,
   7145 						       now, &when))
   7146 			{
   7147 				/*
   7148 				 * This key is not active for zone-signing.
   7149 				 */
   7150 				continue;
   7151 			}
   7152 		} else if (!REVOKE(keys[i])) {
   7153 			/*
   7154 			 * Don't consider inactive keys, however the KSK may be
   7155 			 * temporary offline, so do consider keys which private
   7156 			 * key files are unavailable.
   7157 			 */
   7158 			bool both = dst_key_have_ksk_and_zsk(
   7159 				keys, nkeys, i, false, KSK(keys[i]),
   7160 				!KSK(keys[i]), NULL, NULL);
   7161 			if (both) {
   7162 				/*
   7163 				 * CDS and CDNSKEY are signed with KSK (RFC
   7164 				 * 7344, 4.1).
   7165 				 */
   7166 				if (dns_rdatatype_iskeymaterial(type)) {
   7167 					if (!KSK(keys[i])) {
   7168 						continue;
   7169 					}
   7170 				} else if (KSK(keys[i])) {
   7171 					continue;
   7172 				}
   7173 			}
   7174 		}
   7175 
   7176 		/*
   7177 		 * If this key is revoked, it may only sign the DNSKEY RRset.
   7178 		 */
   7179 		if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
   7180 			continue;
   7181 		}
   7182 
   7183 		/* Calculate the signature, creating a RRSIG RDATA. */
   7184 		isc_buffer_clear(&buffer);
   7185 
   7186 		if (offlineksk && dns_rdatatype_iskeymaterial(type)) {
   7187 			/* Look up the signature in the SKR bundle */
   7188 			dns_skrbundle_t *bundle = dns_zone_getskrbundle(zone);
   7189 			if (bundle == NULL) {
   7190 				CHECK(DNS_R_NOSKRBUNDLE);
   7191 			}
   7192 			CHECK(dns_skrbundle_getsig(bundle, keys[i], type,
   7193 						   &sig_rdata));
   7194 		} else {
   7195 			CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
   7196 					      &inception, &expire, mctx,
   7197 					      &buffer, &sig_rdata));
   7198 		}
   7199 
   7200 		/* Update the database and journal with the RRSIG. */
   7201 		/* XXX inefficient - will cause dataset merging */
   7202 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
   7203 				    rdataset.ttl, &sig_rdata));
   7204 		dns_rdata_reset(&sig_rdata);
   7205 		isc_buffer_init(&buffer, data, sizeof(data));
   7206 
   7207 		/* Update DNSSEC sign statistics. */
   7208 		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
   7209 		if (dnssecsignstats != NULL) {
   7210 			/* Generated a new signature. */
   7211 			dns_dnssecsignstats_increment(dnssecsignstats,
   7212 						      ID(keys[i]),
   7213 						      (uint8_t)ALG(keys[i]),
   7214 						      dns_dnssecsignstats_sign);
   7215 			/* This is a refresh. */
   7216 			dns_dnssecsignstats_increment(
   7217 				dnssecsignstats, ID(keys[i]),
   7218 				(uint8_t)ALG(keys[i]),
   7219 				dns_dnssecsignstats_refresh);
   7220 		}
   7221 	}
   7222 
   7223 cleanup:
   7224 	if (dns_rdataset_isassociated(&rdataset)) {
   7225 		dns_rdataset_disassociate(&rdataset);
   7226 	}
   7227 	if (node != NULL) {
   7228 		dns_db_detachnode(db, &node);
   7229 	}
   7230 	return result;
   7231 }
   7232 
   7233 static void
   7234 calculate_rrsig_validity(dns_zone_t *zone, isc_stdtime_t now,
   7235 			 isc_stdtime_t *inception, isc_stdtime_t *soaexpire,
   7236 			 isc_stdtime_t *expire, isc_stdtime_t *fullexpire) {
   7237 	REQUIRE(inception != NULL);
   7238 	REQUIRE(soaexpire != NULL);
   7239 	/* expire and fullexpire are optional */
   7240 
   7241 	isc_stdtime_t jitter = DEFAULT_JITTER;
   7242 	isc_stdtime_t sigvalidity = dns_zone_getsigvalidityinterval(zone);
   7243 	isc_stdtime_t shortjitter = 0, fulljitter = 0;
   7244 
   7245 	if (zone->kasp != NULL) {
   7246 		jitter = dns_kasp_sigjitter(zone->kasp);
   7247 		sigvalidity = dns_kasp_sigvalidity(zone->kasp);
   7248 		INSIST(jitter <= sigvalidity);
   7249 	}
   7250 
   7251 	if (jitter > sigvalidity) {
   7252 		jitter = sigvalidity;
   7253 	}
   7254 
   7255 	*inception = now - 3600; /* Allow for clock skew. */
   7256 	*soaexpire = now + sigvalidity;
   7257 
   7258 	/*
   7259 	 * Spread out signatures over time if they happen to be
   7260 	 * clumped.  We don't do this for each add_sigs() call as
   7261 	 * we still want some clustering to occur.  In normal operations
   7262 	 * the records should be re-signed as they fall due and they should
   7263 	 * already be spread out.  However if the server is off for a
   7264 	 * period we need to ensure that the clusters don't become
   7265 	 * synchronised by using the full jitter range.
   7266 	 */
   7267 	if (sigvalidity >= 3600U) {
   7268 		if (sigvalidity > 7200U) {
   7269 			shortjitter = isc_random_uniform(3600);
   7270 			fulljitter = isc_random_uniform(jitter);
   7271 		} else {
   7272 			shortjitter = fulljitter = isc_random_uniform(1200);
   7273 		}
   7274 	}
   7275 
   7276 	SET_IF_NOT_NULL(expire, *soaexpire - shortjitter - 1);
   7277 	SET_IF_NOT_NULL(fullexpire, *soaexpire - fulljitter - 1);
   7278 }
   7279 
   7280 static void
   7281 zone_resigninc(dns_zone_t *zone) {
   7282 	dns_db_t *db = NULL;
   7283 	dns_dbversion_t *version = NULL;
   7284 	dns_diff_t _sig_diff;
   7285 	dns__zonediff_t zonediff;
   7286 	dns_fixedname_t fixed;
   7287 	dns_name_t *name;
   7288 	dns_typepair_t typepair;
   7289 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   7290 	isc_result_t result;
   7291 	isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
   7292 	unsigned int i;
   7293 	unsigned int nkeys = 0;
   7294 	isc_stdtime_t resign;
   7295 
   7296 	ENTER;
   7297 
   7298 	dns_diff_init(zone->mctx, &_sig_diff);
   7299 	zonediff_init(&zonediff, &_sig_diff);
   7300 
   7301 	/*
   7302 	 * Zone is frozen. Pause for 5 minutes.
   7303 	 */
   7304 	if (zone->update_disabled) {
   7305 		CHECK(ISC_R_FAILURE);
   7306 	}
   7307 
   7308 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   7309 	if (zone->db != NULL) {
   7310 		dns_db_attach(zone->db, &db);
   7311 	}
   7312 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   7313 	if (db == NULL) {
   7314 		CHECK(ISC_R_FAILURE);
   7315 	}
   7316 
   7317 	result = dns_db_newversion(db, &version);
   7318 	if (result != ISC_R_SUCCESS) {
   7319 		dns_zone_log(zone, ISC_LOG_ERROR,
   7320 			     "zone_resigninc:dns_db_newversion -> %s",
   7321 			     isc_result_totext(result));
   7322 		goto cleanup;
   7323 	}
   7324 
   7325 	now = isc_stdtime_now();
   7326 
   7327 	result = dns_zone_findkeys(zone, db, version, now, zone->mctx,
   7328 				   DNS_MAXZONEKEYS, zone_keys, &nkeys);
   7329 	if (result != ISC_R_SUCCESS) {
   7330 		dns_zone_log(zone, ISC_LOG_ERROR,
   7331 			     "zone_resigninc:dns_zone_findkeys -> %s",
   7332 			     isc_result_totext(result));
   7333 		goto cleanup;
   7334 	}
   7335 
   7336 	calculate_rrsig_validity(zone, now, &inception, &soaexpire, &expire,
   7337 				 &fullexpire);
   7338 
   7339 	stop = now + 5;
   7340 
   7341 	name = dns_fixedname_initname(&fixed);
   7342 	result = dns_db_getsigningtime(db, &resign, name, &typepair);
   7343 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   7344 		dns_zone_log(zone, ISC_LOG_ERROR,
   7345 			     "zone_resigninc:dns_db_getsigningtime -> %s",
   7346 			     isc_result_totext(result));
   7347 	}
   7348 
   7349 	i = 0;
   7350 	while (result == ISC_R_SUCCESS) {
   7351 		dns_rdatatype_t covers = DNS_TYPEPAIR_COVERS(typepair);
   7352 
   7353 		resign -= dns_zone_getsigresigninginterval(zone);
   7354 
   7355 		/*
   7356 		 * Stop if we hit the SOA as that means we have walked the
   7357 		 * entire zone.  The SOA record should always be the most
   7358 		 * recent signature.
   7359 		 */
   7360 		/* XXXMPA increase number of RRsets signed pre call */
   7361 		if ((covers == dns_rdatatype_soa &&
   7362 		     dns_name_equal(name, &zone->origin)) ||
   7363 		    i++ > zone->signatures || resign > stop)
   7364 		{
   7365 			break;
   7366 		}
   7367 
   7368 		result = del_sigs(zone, db, version, name, covers, &zonediff,
   7369 				  zone_keys, nkeys, now, true);
   7370 		if (result != ISC_R_SUCCESS) {
   7371 			dns_zone_log(zone, ISC_LOG_ERROR,
   7372 				     "zone_resigninc:del_sigs -> %s",
   7373 				     isc_result_totext(result));
   7374 			break;
   7375 		}
   7376 
   7377 		/*
   7378 		 * If re-signing is over 5 minutes late use 'fullexpire'
   7379 		 * to redistribute the signature over the complete
   7380 		 * re-signing window, otherwise only add a small amount
   7381 		 * of jitter.
   7382 		 */
   7383 		result = add_sigs(db, version, name, zone, covers,
   7384 				  zonediff.diff, zone_keys, nkeys, zone->mctx,
   7385 				  now, inception,
   7386 				  resign > (now - 300) ? expire : fullexpire);
   7387 		if (result != ISC_R_SUCCESS) {
   7388 			dns_zone_log(zone, ISC_LOG_ERROR,
   7389 				     "zone_resigninc:add_sigs -> %s",
   7390 				     isc_result_totext(result));
   7391 			break;
   7392 		}
   7393 		result = dns_db_getsigningtime(db, &resign, name, &typepair);
   7394 		if (nkeys == 0 && result == ISC_R_NOTFOUND) {
   7395 			result = ISC_R_SUCCESS;
   7396 			break;
   7397 		}
   7398 		if (result != ISC_R_SUCCESS) {
   7399 			dns_zone_log(zone, ISC_LOG_ERROR,
   7400 				     "zone_resigninc:dns_db_getsigningtime -> "
   7401 				     "%s",
   7402 				     isc_result_totext(result));
   7403 		}
   7404 	}
   7405 
   7406 	if (result != ISC_R_NOMORE) {
   7407 		CHECK(result);
   7408 	}
   7409 
   7410 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
   7411 			  &zonediff, zone_keys, nkeys, now, true);
   7412 	if (result != ISC_R_SUCCESS) {
   7413 		dns_zone_log(zone, ISC_LOG_ERROR,
   7414 			     "zone_resigninc:del_sigs -> %s",
   7415 			     isc_result_totext(result));
   7416 		goto cleanup;
   7417 	}
   7418 
   7419 	/*
   7420 	 * Did we change anything in the zone?
   7421 	 */
   7422 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
   7423 		/*
   7424 		 * Commit the changes if any key has been marked as offline.
   7425 		 */
   7426 		if (zonediff.offline) {
   7427 			dns_db_closeversion(db, &version, true);
   7428 		}
   7429 		goto cleanup;
   7430 	}
   7431 
   7432 	/* Increment SOA serial if we have made changes */
   7433 	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
   7434 				   zone->updatemethod);
   7435 	if (result != ISC_R_SUCCESS) {
   7436 		dns_zone_log(zone, ISC_LOG_ERROR,
   7437 			     "zone_resigninc:update_soa_serial -> %s",
   7438 			     isc_result_totext(result));
   7439 		goto cleanup;
   7440 	}
   7441 
   7442 	/*
   7443 	 * Generate maximum life time signatures so that the above loop
   7444 	 * termination is sensible.
   7445 	 */
   7446 	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
   7447 			  zonediff.diff, zone_keys, nkeys, zone->mctx, now,
   7448 			  inception, soaexpire);
   7449 	if (result != ISC_R_SUCCESS) {
   7450 		dns_zone_log(zone, ISC_LOG_ERROR,
   7451 			     "zone_resigninc:add_sigs -> %s",
   7452 			     isc_result_totext(result));
   7453 		goto cleanup;
   7454 	}
   7455 
   7456 	/* Write changes to journal file. */
   7457 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
   7458 
   7459 	/* Everything has succeeded. Commit the changes. */
   7460 	dns_db_closeversion(db, &version, true);
   7461 
   7462 cleanup:
   7463 	dns_diff_clear(&_sig_diff);
   7464 	for (i = 0; i < nkeys; i++) {
   7465 		dst_key_free(&zone_keys[i]);
   7466 	}
   7467 	if (version != NULL) {
   7468 		dns_db_closeversion(db, &version, false);
   7469 		dns_db_detach(&db);
   7470 	} else if (db != NULL) {
   7471 		dns_db_detach(&db);
   7472 	}
   7473 
   7474 	LOCK_ZONE(zone);
   7475 	if (result == ISC_R_SUCCESS) {
   7476 		set_resigntime(zone);
   7477 		zone_needdump(zone, DNS_DUMP_DELAY);
   7478 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   7479 	} else {
   7480 		/*
   7481 		 * Something failed.  Retry in 5 minutes.
   7482 		 */
   7483 		isc_interval_t ival;
   7484 		isc_interval_set(&ival, 300, 0);
   7485 		isc_time_nowplusinterval(&zone->resigntime, &ival);
   7486 	}
   7487 	UNLOCK_ZONE(zone);
   7488 
   7489 	INSIST(version == NULL);
   7490 }
   7491 
   7492 static isc_result_t
   7493 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
   7494 	    dns_name_t *newname, bool bottom) {
   7495 	isc_result_t result;
   7496 	dns_dbiterator_t *dbit = NULL;
   7497 	dns_rdatasetiter_t *rdsit = NULL;
   7498 	dns_dbnode_t *node = NULL;
   7499 
   7500 	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
   7501 	CHECK(dns_dbiterator_seek(dbit, oldname));
   7502 	do {
   7503 		result = dns_dbiterator_next(dbit);
   7504 		if (result == ISC_R_NOMORE) {
   7505 			CHECK(dns_dbiterator_first(dbit));
   7506 		}
   7507 		CHECK(dns_dbiterator_current(dbit, &node, newname));
   7508 		if (bottom && dns_name_issubdomain(newname, oldname) &&
   7509 		    !dns_name_equal(newname, oldname))
   7510 		{
   7511 			dns_db_detachnode(db, &node);
   7512 			continue;
   7513 		}
   7514 		/*
   7515 		 * Is this node empty?
   7516 		 */
   7517 		CHECK(dns_db_allrdatasets(db, node, version, 0, 0, &rdsit));
   7518 		result = dns_rdatasetiter_first(rdsit);
   7519 		dns_db_detachnode(db, &node);
   7520 		dns_rdatasetiter_destroy(&rdsit);
   7521 		if (result != ISC_R_NOMORE) {
   7522 			break;
   7523 		}
   7524 	} while (1);
   7525 cleanup:
   7526 	if (node != NULL) {
   7527 		dns_db_detachnode(db, &node);
   7528 	}
   7529 	if (dbit != NULL) {
   7530 		dns_dbiterator_destroy(&dbit);
   7531 	}
   7532 	return result;
   7533 }
   7534 
   7535 static bool
   7536 signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
   7537 		     dns_dbversion_t *version, dns_rdatatype_t type,
   7538 		     dst_key_t *key, bool fullsign) {
   7539 	isc_result_t result;
   7540 	dns_rdataset_t rdataset;
   7541 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7542 	dns_rdata_rrsig_t rrsig;
   7543 	int count = 0;
   7544 	dns_kasp_t *kasp = zone->kasp;
   7545 
   7546 	dns_rdataset_init(&rdataset);
   7547 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
   7548 				     type, 0, &rdataset, NULL);
   7549 	if (result != ISC_R_SUCCESS) {
   7550 		INSIST(!dns_rdataset_isassociated(&rdataset));
   7551 		return false;
   7552 	}
   7553 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   7554 	     result = dns_rdataset_next(&rdataset))
   7555 	{
   7556 		dns_rdataset_current(&rdataset, &rdata);
   7557 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   7558 		INSIST(result == ISC_R_SUCCESS);
   7559 		if (rrsig.algorithm == dst_key_alg(key) &&
   7560 		    rrsig.keyid == dst_key_id(key))
   7561 		{
   7562 			dns_rdataset_disassociate(&rdataset);
   7563 			return true;
   7564 		}
   7565 		if (rrsig.algorithm == dst_key_alg(key)) {
   7566 			count++;
   7567 		}
   7568 		dns_rdata_reset(&rdata);
   7569 	}
   7570 
   7571 	if (zone->kasp != NULL && !fullsign) {
   7572 		dns_kasp_key_t *kkey;
   7573 		int zsk_count = 0;
   7574 		bool approved;
   7575 
   7576 		KASP_LOCK(kasp);
   7577 		for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
   7578 		     kkey = ISC_LIST_NEXT(kkey, link))
   7579 		{
   7580 			if (dns_kasp_key_algorithm(kkey) != dst_key_alg(key)) {
   7581 				continue;
   7582 			}
   7583 			if (dns_kasp_key_zsk(kkey)) {
   7584 				zsk_count++;
   7585 			}
   7586 		}
   7587 		KASP_UNLOCK(kasp);
   7588 
   7589 		if (dns_rdatatype_iskeymaterial(type)) {
   7590 			/*
   7591 			 * CDS and CDNSKEY are signed with KSK like DNSKEY.
   7592 			 * (RFC 7344, section 4.1 specifies that they must
   7593 			 * be signed with a key in the current DS RRset,
   7594 			 * which would only include KSK's.)
   7595 			 */
   7596 			approved = false;
   7597 		} else {
   7598 			approved = (zsk_count == count);
   7599 		}
   7600 
   7601 		dns_rdataset_disassociate(&rdataset);
   7602 		return approved;
   7603 	}
   7604 
   7605 	dns_rdataset_disassociate(&rdataset);
   7606 	return false;
   7607 }
   7608 
   7609 static isc_result_t
   7610 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
   7611 	 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom, dns_diff_t *diff) {
   7612 	dns_fixedname_t fixed;
   7613 	dns_name_t *next;
   7614 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7615 	isc_result_t result;
   7616 	unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
   7617 
   7618 	next = dns_fixedname_initname(&fixed);
   7619 
   7620 	CHECK(next_active(db, version, name, next, bottom));
   7621 	CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer, &rdata));
   7622 	CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
   7623 			    &rdata));
   7624 cleanup:
   7625 	return result;
   7626 }
   7627 
   7628 static isc_result_t
   7629 check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
   7630 			dns_dbversion_t *version, bool *is_bottom_of_zone) {
   7631 	isc_result_t result;
   7632 	dns_rdatasetiter_t *iterator = NULL;
   7633 	dns_rdataset_t rdataset;
   7634 	bool seen_soa = false, seen_ns = false, seen_dname = false;
   7635 
   7636 	REQUIRE(is_bottom_of_zone != NULL);
   7637 
   7638 	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
   7639 	if (result != ISC_R_SUCCESS) {
   7640 		if (result == ISC_R_NOTFOUND) {
   7641 			result = ISC_R_SUCCESS;
   7642 		}
   7643 		return result;
   7644 	}
   7645 
   7646 	dns_rdataset_init(&rdataset);
   7647 	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
   7648 	     result = dns_rdatasetiter_next(iterator))
   7649 	{
   7650 		dns_rdatasetiter_current(iterator, &rdataset);
   7651 		switch (rdataset.type) {
   7652 		case dns_rdatatype_soa:
   7653 			seen_soa = true;
   7654 			break;
   7655 		case dns_rdatatype_ns:
   7656 			seen_ns = true;
   7657 			break;
   7658 		case dns_rdatatype_dname:
   7659 			seen_dname = true;
   7660 			break;
   7661 		}
   7662 		dns_rdataset_disassociate(&rdataset);
   7663 	}
   7664 	if (result != ISC_R_NOMORE) {
   7665 		goto cleanup;
   7666 	}
   7667 	if ((seen_ns && !seen_soa) || seen_dname) {
   7668 		*is_bottom_of_zone = true;
   7669 	}
   7670 	result = ISC_R_SUCCESS;
   7671 
   7672 cleanup:
   7673 	dns_rdatasetiter_destroy(&iterator);
   7674 
   7675 	return result;
   7676 }
   7677 
   7678 typedef struct seen {
   7679 	bool rr;
   7680 	bool soa;
   7681 	bool ns;
   7682 	bool nsec;
   7683 	bool nsec3;
   7684 	bool ds;
   7685 	bool dname;
   7686 } seen_t;
   7687 
   7688 static isc_result_t
   7689 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   7690 	     dns_rdatasetiter_t **iterp, seen_t *seen) {
   7691 	isc_result_t result;
   7692 	dns_rdataset_t rdataset = DNS_RDATASET_INIT;
   7693 
   7694 	*seen = (seen_t){};
   7695 
   7696 	RETERR(dns_db_allrdatasets(db, node, version, 0, 0, iterp));
   7697 
   7698 	for (result = dns_rdatasetiter_first(*iterp); result == ISC_R_SUCCESS;
   7699 	     result = dns_rdatasetiter_next(*iterp))
   7700 	{
   7701 		dns_rdatasetiter_current(*iterp, &rdataset);
   7702 
   7703 		if (rdataset.type == dns_rdatatype_rrsig) {
   7704 			dns_rdataset_disassociate(&rdataset);
   7705 			continue;
   7706 		}
   7707 
   7708 		(*seen).rr = true;
   7709 
   7710 		if (rdataset.type == dns_rdatatype_soa) {
   7711 			(*seen).soa = true;
   7712 		} else if (rdataset.type == dns_rdatatype_ns) {
   7713 			(*seen).ns = true;
   7714 		} else if (rdataset.type == dns_rdatatype_ds) {
   7715 			(*seen).ds = true;
   7716 		} else if (rdataset.type == dns_rdatatype_dname) {
   7717 			(*seen).dname = true;
   7718 		} else if (rdataset.type == dns_rdatatype_nsec) {
   7719 			(*seen).nsec = true;
   7720 		} else if (rdataset.type == dns_rdatatype_nsec3) {
   7721 			(*seen).nsec3 = true;
   7722 		}
   7723 
   7724 		dns_rdataset_disassociate(&rdataset);
   7725 	}
   7726 
   7727 	return ISC_R_SUCCESS;
   7728 }
   7729 
   7730 static isc_result_t
   7731 sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
   7732 	    dns_dbnode_t *node, dns_dbversion_t *version, bool build_nsec3,
   7733 	    bool build_nsec, dst_key_t *key, isc_stdtime_t now,
   7734 	    isc_stdtime_t inception, isc_stdtime_t expire, dns_ttl_t nsecttl,
   7735 	    bool both, bool is_ksk, bool is_zsk, bool fullsign,
   7736 	    bool is_bottom_of_zone, dns_diff_t *diff, int32_t *signatures,
   7737 	    isc_mem_t *mctx) {
   7738 	isc_result_t result;
   7739 	dns_rdatasetiter_t *iterator = NULL;
   7740 	dns_rdataset_t rdataset;
   7741 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7742 	dns_stats_t *dnssecsignstats;
   7743 	bool offlineksk = false;
   7744 	isc_buffer_t buffer;
   7745 	unsigned char data[1024];
   7746 	seen_t seen;
   7747 
   7748 	if (zone->kasp != NULL) {
   7749 		offlineksk = dns_kasp_offlineksk(zone->kasp);
   7750 	}
   7751 
   7752 	result = allrdatasets(db, node, version, &iterator, &seen);
   7753 	if (result != ISC_R_SUCCESS) {
   7754 		if (result == ISC_R_NOTFOUND) {
   7755 			result = ISC_R_SUCCESS;
   7756 		}
   7757 		return result;
   7758 	}
   7759 
   7760 	dns_rdataset_init(&rdataset);
   7761 	isc_buffer_init(&buffer, data, sizeof(data));
   7762 
   7763 	/*
   7764 	 * Going from insecure to NSEC3.
   7765 	 * Don't generate NSEC3 records for NSEC3 records.
   7766 	 */
   7767 	if (build_nsec3 && !seen.nsec3 && seen.rr) {
   7768 		bool unsecure = !seen.ds && seen.ns && !seen.soa;
   7769 		CHECK(dns_nsec3_addnsec3s(db, version, name, nsecttl, unsecure,
   7770 					  diff));
   7771 		(*signatures)--;
   7772 	}
   7773 	/*
   7774 	 * Going from insecure to NSEC.
   7775 	 * Don't generate NSEC records for NSEC3 records.
   7776 	 */
   7777 	if (build_nsec && !seen.nsec3 && !seen.nsec && seen.rr) {
   7778 		/*
   7779 		 * Build a NSEC record except at the origin.
   7780 		 */
   7781 		if (!dns_name_equal(name, dns_db_origin(db))) {
   7782 			CHECK(add_nsec(db, version, name, node, nsecttl,
   7783 				       is_bottom_of_zone, diff));
   7784 			/* Count a NSEC generation as a signature generation. */
   7785 			(*signatures)--;
   7786 		}
   7787 	}
   7788 	result = dns_rdatasetiter_first(iterator);
   7789 	while (result == ISC_R_SUCCESS) {
   7790 		isc_stdtime_t when;
   7791 
   7792 		dns_rdatasetiter_current(iterator, &rdataset);
   7793 		if (rdataset.type == dns_rdatatype_soa ||
   7794 		    rdataset.type == dns_rdatatype_rrsig)
   7795 		{
   7796 			goto next_rdataset;
   7797 		}
   7798 		if (dns_rdatatype_iskeymaterial(rdataset.type)) {
   7799 			/*
   7800 			 * CDS and CDNSKEY are signed with KSK like DNSKEY.
   7801 			 * (RFC 7344, section 4.1 specifies that they must
   7802 			 * be signed with a key in the current DS RRset,
   7803 			 * which would only include KSK's.)
   7804 			 */
   7805 			if (!is_ksk && both) {
   7806 				goto next_rdataset;
   7807 			}
   7808 		} else if (!is_zsk && both) {
   7809 			goto next_rdataset;
   7810 		} else if (is_zsk &&
   7811 			   !dst_key_is_signing(key, DST_BOOL_ZSK, now, &when))
   7812 		{
   7813 			/* Only applies to dnssec-policy. */
   7814 			if (zone->kasp != NULL) {
   7815 				goto next_rdataset;
   7816 			}
   7817 		}
   7818 
   7819 		if (seen.ns && !seen.soa && rdataset.type != dns_rdatatype_ds &&
   7820 		    rdataset.type != dns_rdatatype_nsec)
   7821 		{
   7822 			goto next_rdataset;
   7823 		}
   7824 		if (signed_with_good_key(zone, db, node, version, rdataset.type,
   7825 					 key, fullsign))
   7826 		{
   7827 			goto next_rdataset;
   7828 		}
   7829 
   7830 		/* Calculate the signature, creating a RRSIG RDATA. */
   7831 		isc_buffer_clear(&buffer);
   7832 		if (offlineksk && dns_rdatatype_iskeymaterial(rdataset.type)) {
   7833 			/* Look up the signature in the SKR bundle */
   7834 			dns_skrbundle_t *bundle = dns_zone_getskrbundle(zone);
   7835 			if (bundle == NULL) {
   7836 				CHECK(DNS_R_NOSKRBUNDLE);
   7837 			}
   7838 			CHECK(dns_skrbundle_getsig(bundle, key, rdataset.type,
   7839 						   &rdata));
   7840 		} else {
   7841 			CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
   7842 					      &expire, mctx, &buffer, &rdata));
   7843 		}
   7844 
   7845 		/* Update the database and journal with the RRSIG. */
   7846 		/* XXX inefficient - will cause dataset merging */
   7847 		CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
   7848 				    name, rdataset.ttl, &rdata));
   7849 		dns_rdata_reset(&rdata);
   7850 
   7851 		/* Update DNSSEC sign statistics. */
   7852 		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
   7853 		if (dnssecsignstats != NULL) {
   7854 			/* Generated a new signature. */
   7855 			dns_dnssecsignstats_increment(dnssecsignstats, ID(key),
   7856 						      ALG(key),
   7857 						      dns_dnssecsignstats_sign);
   7858 			/* This is a refresh. */
   7859 			dns_dnssecsignstats_increment(
   7860 				dnssecsignstats, ID(key), ALG(key),
   7861 				dns_dnssecsignstats_refresh);
   7862 		}
   7863 
   7864 		(*signatures)--;
   7865 	next_rdataset:
   7866 		dns_rdataset_disassociate(&rdataset);
   7867 		result = dns_rdatasetiter_next(iterator);
   7868 	}
   7869 	if (result == ISC_R_NOMORE) {
   7870 		result = ISC_R_SUCCESS;
   7871 	}
   7872 
   7873 cleanup:
   7874 	if (dns_rdataset_isassociated(&rdataset)) {
   7875 		dns_rdataset_disassociate(&rdataset);
   7876 	}
   7877 	if (iterator != NULL) {
   7878 		dns_rdatasetiter_destroy(&iterator);
   7879 	}
   7880 	return result;
   7881 }
   7882 
   7883 /*
   7884  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
   7885  */
   7886 static isc_result_t
   7887 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
   7888 	     dns_ttl_t nsecttl, bool update_only, dns_diff_t *diff) {
   7889 	isc_result_t result;
   7890 	dns_rdataset_t rdataset;
   7891 	dns_dbnode_t *node = NULL;
   7892 
   7893 	CHECK(dns_db_getoriginnode(db, &node));
   7894 	if (update_only) {
   7895 		dns_rdataset_init(&rdataset);
   7896 		result = dns_db_findrdataset(
   7897 			db, node, version, dns_rdatatype_nsec,
   7898 			dns_rdatatype_none, 0, &rdataset, NULL);
   7899 		if (dns_rdataset_isassociated(&rdataset)) {
   7900 			dns_rdataset_disassociate(&rdataset);
   7901 		}
   7902 		if (result == ISC_R_NOTFOUND) {
   7903 			goto success;
   7904 		}
   7905 		CHECK(result);
   7906 	}
   7907 	CHECK(delete_nsec(db, version, node, name, diff));
   7908 	CHECK(add_nsec(db, version, name, node, nsecttl, false, diff));
   7909 success:
   7910 	result = ISC_R_SUCCESS;
   7911 cleanup:
   7912 	if (node != NULL) {
   7913 		dns_db_detachnode(db, &node);
   7914 	}
   7915 	return result;
   7916 }
   7917 
   7918 static isc_result_t
   7919 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
   7920 		  dns_dbversion_t *version, bool build_nsec3, dns_ttl_t nsecttl,
   7921 		  dns_diff_t *diff) {
   7922 	isc_result_t result;
   7923 	dns_dbnode_t *node = NULL;
   7924 	dns_rdataset_t rdataset;
   7925 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7926 	unsigned char data[5];
   7927 	bool seen_done = false;
   7928 	bool have_rr = false;
   7929 
   7930 	dns_rdataset_init(&rdataset);
   7931 	CHECK(dns_db_getoriginnode(signing->db, &node));
   7932 
   7933 	result = dns_db_findrdataset(signing->db, node, version,
   7934 				     zone->privatetype, dns_rdatatype_none, 0,
   7935 				     &rdataset, NULL);
   7936 	if (result == ISC_R_NOTFOUND) {
   7937 		INSIST(!dns_rdataset_isassociated(&rdataset));
   7938 		result = ISC_R_SUCCESS;
   7939 		goto cleanup;
   7940 	}
   7941 	if (result != ISC_R_SUCCESS) {
   7942 		INSIST(!dns_rdataset_isassociated(&rdataset));
   7943 		goto cleanup;
   7944 	}
   7945 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   7946 	     result = dns_rdataset_next(&rdataset))
   7947 	{
   7948 		dns_rdataset_current(&rdataset, &rdata);
   7949 		/*
   7950 		 * If we don't match the algorithm or keyid skip the record.
   7951 		 */
   7952 		if (rdata.length != 5 || rdata.data[0] != signing->algorithm ||
   7953 		    rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
   7954 		    rdata.data[2] != (signing->keyid & 0xff))
   7955 		{
   7956 			have_rr = true;
   7957 			dns_rdata_reset(&rdata);
   7958 			continue;
   7959 		}
   7960 		/*
   7961 		 * We have a match.  If we were signing (!signing->deleteit)
   7962 		 * and we already have a record indicating that we have
   7963 		 * finished signing (rdata.data[4] != 0) then keep it.
   7964 		 * Otherwise it needs to be deleted as we have removed all
   7965 		 * the signatures (signing->deleteit), so any record indicating
   7966 		 * completion is now out of date, or we have finished signing
   7967 		 * with the new record so we no longer need to remember that
   7968 		 * we need to sign the zone with the matching key across a
   7969 		 * nameserver re-start.
   7970 		 */
   7971 		if (!signing->deleteit && rdata.data[4] != 0) {
   7972 			seen_done = true;
   7973 			have_rr = true;
   7974 		} else {
   7975 			CHECK(update_one_rr(signing->db, version, diff,
   7976 					    DNS_DIFFOP_DEL, &zone->origin,
   7977 					    rdataset.ttl, &rdata));
   7978 		}
   7979 		dns_rdata_reset(&rdata);
   7980 	}
   7981 	if (result == ISC_R_NOMORE) {
   7982 		result = ISC_R_SUCCESS;
   7983 	}
   7984 	if (!signing->deleteit && !seen_done) {
   7985 		/*
   7986 		 * If we were signing then we need to indicate that we have
   7987 		 * finished signing the zone with this key.  If it is already
   7988 		 * there we don't need to add it a second time.
   7989 		 */
   7990 		data[0] = signing->algorithm;
   7991 		data[1] = (signing->keyid >> 8) & 0xff;
   7992 		data[2] = signing->keyid & 0xff;
   7993 		data[3] = 0;
   7994 		data[4] = 1;
   7995 		rdata.length = sizeof(data);
   7996 		rdata.data = data;
   7997 		rdata.type = zone->privatetype;
   7998 		rdata.rdclass = dns_db_class(signing->db);
   7999 		CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
   8000 				    &zone->origin, rdataset.ttl, &rdata));
   8001 	} else if (!have_rr) {
   8002 		dns_name_t *origin = dns_db_origin(signing->db);
   8003 		/*
   8004 		 * Rebuild the NSEC/NSEC3 record for the origin as we no
   8005 		 * longer have any private records.
   8006 		 */
   8007 		if (build_nsec3) {
   8008 			CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
   8009 						  nsecttl, false, diff));
   8010 		}
   8011 		CHECK(updatesecure(signing->db, version, origin, nsecttl, true,
   8012 				   diff));
   8013 	}
   8014 
   8015 cleanup:
   8016 	if (dns_rdataset_isassociated(&rdataset)) {
   8017 		dns_rdataset_disassociate(&rdataset);
   8018 	}
   8019 	if (node != NULL) {
   8020 		dns_db_detachnode(signing->db, &node);
   8021 	}
   8022 	return result;
   8023 }
   8024 
   8025 /*
   8026  * Called from zone_nsec3chain() in order to update zone records indicating
   8027  * processing status of given NSEC3 chain:
   8028  *
   8029  *   - If the supplied dns_nsec3chain_t structure has been fully processed
   8030  *     (which is indicated by "active" being set to false):
   8031  *
   8032  *       - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
   8033  *
   8034  *       - remove all private-type records containing NSEC3PARAM RDATA matching
   8035  *         the relevant NSEC3 chain.
   8036  *
   8037  *   - If the supplied dns_nsec3chain_t structure has not been fully processed
   8038  *     (which is indicated by "active" being set to true), only remove the
   8039  *     NSEC3PARAM record which matches the relevant NSEC3 chain and has the
   8040  *     "flags" field set to 0.
   8041  *
   8042  *   - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
   8043  *     in the relevant private-type record, but with the "flags" field set to
   8044  *     0, indicating that this NSEC3 chain is now complete for this zone.
   8045  *
   8046  * Note that this function is called at different processing stages for NSEC3
   8047  * chain additions vs. removals and needs to handle all cases properly.
   8048  */
   8049 static isc_result_t
   8050 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
   8051 		 bool active, dns_rdatatype_t privatetype, dns_diff_t *diff) {
   8052 	dns_dbnode_t *node = NULL;
   8053 	dns_name_t *name = dns_db_origin(db);
   8054 	dns_rdata_t rdata = DNS_RDATA_INIT;
   8055 	dns_rdataset_t rdataset;
   8056 	dns_rdata_nsec3param_t nsec3param;
   8057 	dns_rdata_soa_t soa;
   8058 	isc_result_t result;
   8059 	isc_buffer_t buffer;
   8060 	unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
   8061 	dns_ttl_t ttl = 0;
   8062 	bool nseconly = false, nsec3ok = false;
   8063 
   8064 	dns_rdataset_init(&rdataset);
   8065 
   8066 	result = dns_db_getoriginnode(db, &node);
   8067 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8068 
   8069 	/* Default TTL is SOA MINIMUM */
   8070 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0, 0,
   8071 				     &rdataset, NULL);
   8072 	if (result == ISC_R_SUCCESS) {
   8073 		CHECK(dns_rdataset_first(&rdataset));
   8074 		dns_rdataset_current(&rdataset, &rdata);
   8075 		CHECK(dns_rdata_tostruct(&rdata, &soa, NULL));
   8076 		ttl = soa.minimum;
   8077 		dns_rdata_reset(&rdata);
   8078 	}
   8079 	if (dns_rdataset_isassociated(&rdataset)) {
   8080 		dns_rdataset_disassociate(&rdataset);
   8081 	}
   8082 
   8083 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
   8084 				     0, &rdataset, NULL);
   8085 	if (result == ISC_R_NOTFOUND) {
   8086 		goto try_private;
   8087 	}
   8088 	if (result != ISC_R_SUCCESS) {
   8089 		goto cleanup;
   8090 	}
   8091 
   8092 	/*
   8093 	 * Delete all NSEC3PARAM records which match that in nsec3chain.
   8094 	 */
   8095 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   8096 	     result = dns_rdataset_next(&rdataset))
   8097 	{
   8098 		dns_rdataset_current(&rdataset, &rdata);
   8099 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
   8100 
   8101 		if (nsec3param.hash != chain->nsec3param.hash ||
   8102 		    (active && nsec3param.flags != 0) ||
   8103 		    nsec3param.iterations != chain->nsec3param.iterations ||
   8104 		    nsec3param.salt_length != chain->nsec3param.salt_length ||
   8105 		    memcmp(nsec3param.salt, chain->nsec3param.salt,
   8106 			   nsec3param.salt_length))
   8107 		{
   8108 			/*
   8109 			 * If the SOA minimum is different to the current TTL,
   8110 			 * delete the record.  We will re-add it with the new
   8111 			 * TTL below.
   8112 			 */
   8113 			if (rdataset.ttl != ttl) {
   8114 				CHECK(update_one_rr(db, ver, diff,
   8115 						    DNS_DIFFOP_DEL, name,
   8116 						    rdataset.ttl, &rdata));
   8117 			}
   8118 			dns_rdata_reset(&rdata);
   8119 			continue;
   8120 		}
   8121 
   8122 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
   8123 				    rdataset.ttl, &rdata));
   8124 		dns_rdata_reset(&rdata);
   8125 	}
   8126 	if (result != ISC_R_NOMORE) {
   8127 		goto cleanup;
   8128 	}
   8129 
   8130 	/*
   8131 	 * Restore any NSEC3PARAM records that we deleted to change the TTL.
   8132 	 */
   8133 	if (rdataset.ttl != ttl) {
   8134 		for (result = dns_rdataset_first(&rdataset);
   8135 		     result == ISC_R_SUCCESS;
   8136 		     result = dns_rdataset_next(&rdataset))
   8137 		{
   8138 			dns_rdataset_current(&rdataset, &rdata);
   8139 			CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
   8140 
   8141 			if (nsec3param.hash != chain->nsec3param.hash ||
   8142 			    (active && nsec3param.flags != 0) ||
   8143 			    nsec3param.iterations !=
   8144 				    chain->nsec3param.iterations ||
   8145 			    nsec3param.salt_length !=
   8146 				    chain->nsec3param.salt_length ||
   8147 			    memcmp(nsec3param.salt, chain->nsec3param.salt,
   8148 				   nsec3param.salt_length))
   8149 			{
   8150 				CHECK(update_one_rr(db, ver, diff,
   8151 						    DNS_DIFFOP_ADD, name, ttl,
   8152 						    &rdata));
   8153 			}
   8154 			dns_rdata_reset(&rdata);
   8155 		}
   8156 	}
   8157 
   8158 	dns_rdataset_disassociate(&rdataset);
   8159 
   8160 try_private:
   8161 
   8162 	if (active) {
   8163 		goto add;
   8164 	}
   8165 
   8166 	result = dns_nsec_nseconly(db, ver, diff, &nseconly);
   8167 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
   8168 
   8169 	/*
   8170 	 * Delete all private records which match that in nsec3chain.
   8171 	 */
   8172 	result = dns_db_findrdataset(db, node, ver, privatetype, 0, 0,
   8173 				     &rdataset, NULL);
   8174 	if (result == ISC_R_NOTFOUND) {
   8175 		goto add;
   8176 	}
   8177 	CHECK(result);
   8178 
   8179 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   8180 	     result = dns_rdataset_next(&rdataset))
   8181 	{
   8182 		dns_rdata_t private = DNS_RDATA_INIT;
   8183 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   8184 
   8185 		dns_rdataset_current(&rdataset, &private);
   8186 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
   8187 						sizeof(buf)))
   8188 		{
   8189 			continue;
   8190 		}
   8191 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
   8192 
   8193 		if ((!nsec3ok &&
   8194 		     (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
   8195 		    nsec3param.hash != chain->nsec3param.hash ||
   8196 		    nsec3param.iterations != chain->nsec3param.iterations ||
   8197 		    nsec3param.salt_length != chain->nsec3param.salt_length ||
   8198 		    memcmp(nsec3param.salt, chain->nsec3param.salt,
   8199 			   nsec3param.salt_length))
   8200 		{
   8201 			dns_rdata_reset(&rdata);
   8202 			continue;
   8203 		}
   8204 
   8205 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
   8206 				    rdataset.ttl, &private));
   8207 		dns_rdata_reset(&rdata);
   8208 	}
   8209 	if (result != ISC_R_NOMORE) {
   8210 		goto cleanup;
   8211 	}
   8212 
   8213 add:
   8214 	if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
   8215 		result = ISC_R_SUCCESS;
   8216 		goto cleanup;
   8217 	}
   8218 
   8219 	/*
   8220 	 * Add a NSEC3PARAM record which matches that in nsec3chain but
   8221 	 * with all flags bits cleared.
   8222 	 *
   8223 	 * Note: we do not clear chain->nsec3param.flags as this change
   8224 	 * may be reversed.
   8225 	 */
   8226 	isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
   8227 	CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
   8228 				   dns_rdatatype_nsec3param, &chain->nsec3param,
   8229 				   &buffer));
   8230 	rdata.data[1] = 0; /* Clear flag bits. */
   8231 	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
   8232 
   8233 cleanup:
   8234 	dns_db_detachnode(db, &node);
   8235 	if (dns_rdataset_isassociated(&rdataset)) {
   8236 		dns_rdataset_disassociate(&rdataset);
   8237 	}
   8238 	return result;
   8239 }
   8240 
   8241 static isc_result_t
   8242 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
   8243 	    dns_name_t *name, dns_diff_t *diff) {
   8244 	dns_rdataset_t rdataset;
   8245 	isc_result_t result;
   8246 
   8247 	dns_rdataset_init(&rdataset);
   8248 
   8249 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
   8250 				     &rdataset, NULL);
   8251 	if (result == ISC_R_NOTFOUND) {
   8252 		return ISC_R_SUCCESS;
   8253 	}
   8254 	if (result != ISC_R_SUCCESS) {
   8255 		return result;
   8256 	}
   8257 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   8258 	     result = dns_rdataset_next(&rdataset))
   8259 	{
   8260 		dns_rdata_t rdata = DNS_RDATA_INIT;
   8261 
   8262 		dns_rdataset_current(&rdataset, &rdata);
   8263 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
   8264 				    rdataset.ttl, &rdata));
   8265 	}
   8266 	if (result == ISC_R_NOMORE) {
   8267 		result = ISC_R_SUCCESS;
   8268 	}
   8269 
   8270 cleanup:
   8271 	dns_rdataset_disassociate(&rdataset);
   8272 	return result;
   8273 }
   8274 
   8275 static isc_result_t
   8276 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
   8277 		    dns_name_t *name, const dns_rdata_nsec3param_t *param,
   8278 		    dns_diff_t *diff) {
   8279 	dns_rdataset_t rdataset;
   8280 	dns_rdata_nsec3_t nsec3;
   8281 	isc_result_t result;
   8282 
   8283 	dns_rdataset_init(&rdataset);
   8284 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0,
   8285 				     &rdataset, NULL);
   8286 	if (result == ISC_R_NOTFOUND) {
   8287 		return ISC_R_SUCCESS;
   8288 	}
   8289 	if (result != ISC_R_SUCCESS) {
   8290 		return result;
   8291 	}
   8292 
   8293 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   8294 	     result = dns_rdataset_next(&rdataset))
   8295 	{
   8296 		dns_rdata_t rdata = DNS_RDATA_INIT;
   8297 
   8298 		dns_rdataset_current(&rdataset, &rdata);
   8299 		CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
   8300 		if (nsec3.hash != param->hash ||
   8301 		    nsec3.iterations != param->iterations ||
   8302 		    nsec3.salt_length != param->salt_length ||
   8303 		    memcmp(nsec3.salt, param->salt, nsec3.salt_length))
   8304 		{
   8305 			continue;
   8306 		}
   8307 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
   8308 				    rdataset.ttl, &rdata));
   8309 	}
   8310 	if (result == ISC_R_NOMORE) {
   8311 		result = ISC_R_SUCCESS;
   8312 	}
   8313 
   8314 cleanup:
   8315 	dns_rdataset_disassociate(&rdataset);
   8316 	return result;
   8317 }
   8318 
   8319 static isc_result_t
   8320 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
   8321 		const dns_rdata_nsec3param_t *param, bool *answer) {
   8322 	dns_dbnode_t *node = NULL;
   8323 	dns_rdata_t rdata = DNS_RDATA_INIT;
   8324 	dns_rdata_nsec3param_t myparam;
   8325 	dns_rdataset_t rdataset;
   8326 	isc_result_t result;
   8327 
   8328 	*answer = false;
   8329 
   8330 	result = dns_db_getoriginnode(db, &node);
   8331 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8332 
   8333 	dns_rdataset_init(&rdataset);
   8334 
   8335 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
   8336 				     &rdataset, NULL);
   8337 	if (result == ISC_R_SUCCESS) {
   8338 		dns_rdataset_disassociate(&rdataset);
   8339 		dns_db_detachnode(db, &node);
   8340 		return result;
   8341 	}
   8342 	if (result != ISC_R_NOTFOUND) {
   8343 		dns_db_detachnode(db, &node);
   8344 		return result;
   8345 	}
   8346 
   8347 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
   8348 				     0, &rdataset, NULL);
   8349 	if (result == ISC_R_NOTFOUND) {
   8350 		*answer = true;
   8351 		dns_db_detachnode(db, &node);
   8352 		return ISC_R_SUCCESS;
   8353 	}
   8354 	if (result != ISC_R_SUCCESS) {
   8355 		dns_db_detachnode(db, &node);
   8356 		return result;
   8357 	}
   8358 
   8359 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   8360 	     result = dns_rdataset_next(&rdataset))
   8361 	{
   8362 		dns_rdataset_current(&rdataset, &rdata);
   8363 		CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
   8364 		dns_rdata_reset(&rdata);
   8365 		/*
   8366 		 * Ignore any NSEC3PARAM removals.
   8367 		 */
   8368 		if (NSEC3REMOVE(myparam.flags)) {
   8369 			continue;
   8370 		}
   8371 		/*
   8372 		 * Ignore the chain that we are in the process of deleting.
   8373 		 */
   8374 		if (myparam.hash == param->hash &&
   8375 		    myparam.iterations == param->iterations &&
   8376 		    myparam.salt_length == param->salt_length &&
   8377 		    !memcmp(myparam.salt, param->salt, myparam.salt_length))
   8378 		{
   8379 			continue;
   8380 		}
   8381 		/*
   8382 		 * Found an active NSEC3 chain.
   8383 		 */
   8384 		break;
   8385 	}
   8386 	if (result == ISC_R_NOMORE) {
   8387 		*answer = true;
   8388 		result = ISC_R_SUCCESS;
   8389 	}
   8390 
   8391 cleanup:
   8392 	if (dns_rdataset_isassociated(&rdataset)) {
   8393 		dns_rdataset_disassociate(&rdataset);
   8394 	}
   8395 	dns_db_detachnode(db, &node);
   8396 	return result;
   8397 }
   8398 
   8399 /*%
   8400  * Given a tuple which is part of a diff, return a pointer to the next tuple in
   8401  * that diff which has the same name and type (or NULL if no such tuple is
   8402  * found).
   8403  */
   8404 static dns_difftuple_t *
   8405 find_next_matching_tuple(dns_difftuple_t *cur) {
   8406 	dns_difftuple_t *next = cur;
   8407 
   8408 	while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
   8409 		if (cur->rdata.type == next->rdata.type &&
   8410 		    dns_name_equal(&cur->name, &next->name))
   8411 		{
   8412 			return next;
   8413 		}
   8414 	}
   8415 
   8416 	return NULL;
   8417 }
   8418 
   8419 /*%
   8420  * Remove all tuples with the same name and type as 'cur' from 'src' and append
   8421  * them to 'dst'.
   8422  */
   8423 static void
   8424 move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
   8425 	do {
   8426 		dns_difftuple_t *next = find_next_matching_tuple(cur);
   8427 		ISC_LIST_UNLINK(src->tuples, cur, link);
   8428 		dns_diff_appendminimal(dst, &cur);
   8429 		cur = next;
   8430 	} while (cur != NULL);
   8431 }
   8432 
   8433 /*%
   8434  * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
   8435  * 'diff'.  Gradually remove tuples from 'diff' and append them to 'zonediff'
   8436  * along with tuples representing relevant signature changes.
   8437  */
   8438 isc_result_t
   8439 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
   8440 		     dst_key_t *zone_keys[], unsigned int nkeys,
   8441 		     dns_zone_t *zone, isc_stdtime_t inception,
   8442 		     isc_stdtime_t expire, isc_stdtime_t keyexpire,
   8443 		     isc_stdtime_t now, dns__zonediff_t *zonediff) {
   8444 	dns_difftuple_t *tuple;
   8445 	isc_result_t result;
   8446 
   8447 	while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
   8448 		isc_stdtime_t exp = expire;
   8449 
   8450 		if (keyexpire != 0 &&
   8451 		    dns_rdatatype_iskeymaterial(tuple->rdata.type))
   8452 		{
   8453 			exp = keyexpire;
   8454 		}
   8455 
   8456 		result = del_sigs(zone, db, version, &tuple->name,
   8457 				  tuple->rdata.type, zonediff, zone_keys, nkeys,
   8458 				  now, false);
   8459 		if (result != ISC_R_SUCCESS) {
   8460 			dns_zone_log(zone, ISC_LOG_ERROR,
   8461 				     "dns__zone_updatesigs:del_sigs -> %s",
   8462 				     isc_result_totext(result));
   8463 			return result;
   8464 		}
   8465 		result = add_sigs(db, version, &tuple->name, zone,
   8466 				  tuple->rdata.type, zonediff->diff, zone_keys,
   8467 				  nkeys, zone->mctx, now, inception, exp);
   8468 		if (result != ISC_R_SUCCESS) {
   8469 			dns_zone_log(zone, ISC_LOG_ERROR,
   8470 				     "dns__zone_updatesigs:add_sigs -> %s",
   8471 				     isc_result_totext(result));
   8472 			return result;
   8473 		}
   8474 
   8475 		/*
   8476 		 * Signature changes for all RRs with name tuple->name and type
   8477 		 * tuple->rdata.type were appended to zonediff->diff.  Now we
   8478 		 * remove all the "raw" changes with the same name and type
   8479 		 * from diff (so that they are not processed by this loop
   8480 		 * again) and append them to zonediff so that they get applied.
   8481 		 */
   8482 		move_matching_tuples(tuple, diff, zonediff->diff);
   8483 	}
   8484 	return ISC_R_SUCCESS;
   8485 }
   8486 
   8487 /*
   8488  * Incrementally build and sign a new NSEC3 chain using the parameters
   8489  * requested.
   8490  */
   8491 static void
   8492 zone_nsec3chain(dns_zone_t *zone) {
   8493 	dns_db_t *db = NULL;
   8494 	dns_dbnode_t *node = NULL;
   8495 	dns_dbversion_t *version = NULL;
   8496 	dns_diff_t _sig_diff;
   8497 	dns_diff_t nsec_diff;
   8498 	dns_diff_t nsec3_diff;
   8499 	dns_diff_t param_diff;
   8500 	dns__zonediff_t zonediff;
   8501 	dns_fixedname_t fixed;
   8502 	dns_fixedname_t nextfixed;
   8503 	dns_name_t *name, *nextname;
   8504 	dns_rdataset_t rdataset;
   8505 	dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
   8506 	dns_nsec3chainlist_t cleanup;
   8507 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   8508 	int32_t signatures;
   8509 	bool delegation;
   8510 	bool first;
   8511 	isc_result_t result;
   8512 	isc_stdtime_t now, inception, soaexpire, expire;
   8513 	unsigned int i;
   8514 	unsigned int nkeys = 0;
   8515 	uint32_t nodes;
   8516 	bool unsecure = false;
   8517 	seen_t seen;
   8518 	dns_rdatasetiter_t *iterator = NULL;
   8519 	bool buildnsecchain;
   8520 	bool updatensec = false;
   8521 	dns_rdatatype_t privatetype = zone->privatetype;
   8522 
   8523 	ENTER;
   8524 
   8525 	dns_rdataset_init(&rdataset);
   8526 	name = dns_fixedname_initname(&fixed);
   8527 	nextname = dns_fixedname_initname(&nextfixed);
   8528 	dns_diff_init(zone->mctx, &param_diff);
   8529 	dns_diff_init(zone->mctx, &nsec3_diff);
   8530 	dns_diff_init(zone->mctx, &nsec_diff);
   8531 	dns_diff_init(zone->mctx, &_sig_diff);
   8532 	zonediff_init(&zonediff, &_sig_diff);
   8533 	ISC_LIST_INIT(cleanup);
   8534 
   8535 	/*
   8536 	 * Updates are disabled.  Pause for 5 minutes.
   8537 	 */
   8538 	if (zone->update_disabled) {
   8539 		CHECK(ISC_R_FAILURE);
   8540 	}
   8541 
   8542 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   8543 	/*
   8544 	 * This function is called when zone timer fires, after the latter gets
   8545 	 * set by zone_addnsec3chain().  If the action triggering the call to
   8546 	 * zone_addnsec3chain() is closely followed by a zone deletion request,
   8547 	 * it might turn out that the timer thread will not be woken up until
   8548 	 * after the zone is deleted by rmzone(), which calls dns_db_detach()
   8549 	 * for zone->db, causing the latter to become NULL.  Return immediately
   8550 	 * if that happens.
   8551 	 */
   8552 	if (zone->db != NULL) {
   8553 		dns_db_attach(zone->db, &db);
   8554 	}
   8555 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   8556 	if (db == NULL) {
   8557 		return;
   8558 	}
   8559 
   8560 	result = dns_db_newversion(db, &version);
   8561 	if (result != ISC_R_SUCCESS) {
   8562 		dnssec_log(zone, ISC_LOG_ERROR,
   8563 			   "zone_nsec3chain:dns_db_newversion -> %s",
   8564 			   isc_result_totext(result));
   8565 		goto cleanup;
   8566 	}
   8567 
   8568 	now = isc_stdtime_now();
   8569 
   8570 	result = dns_zone_findkeys(zone, db, version, now, zone->mctx,
   8571 				   DNS_MAXZONEKEYS, zone_keys, &nkeys);
   8572 	if (result != ISC_R_SUCCESS) {
   8573 		dnssec_log(zone, ISC_LOG_ERROR,
   8574 			   "zone_nsec3chain:dns_zone_findkeys -> %s",
   8575 			   isc_result_totext(result));
   8576 		goto cleanup;
   8577 	}
   8578 
   8579 	calculate_rrsig_validity(zone, now, &inception, &soaexpire, NULL,
   8580 				 &expire);
   8581 
   8582 	/*
   8583 	 * We keep pulling nodes off each iterator in turn until
   8584 	 * we have no more nodes to pull off or we reach the limits
   8585 	 * for this quantum.
   8586 	 */
   8587 	nodes = zone->nodes;
   8588 	signatures = zone->signatures;
   8589 	LOCK_ZONE(zone);
   8590 	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   8591 	UNLOCK_ZONE(zone);
   8592 	first = true;
   8593 
   8594 	if (nsec3chain != NULL) {
   8595 		nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
   8596 	}
   8597 	/*
   8598 	 * Generate new NSEC3 chains first.
   8599 	 *
   8600 	 * The following while loop iterates over nodes in the zone database,
   8601 	 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
   8602 	 * them.  Once all nodes are processed, the "delete_nsec" field is
   8603 	 * consulted to check whether we are supposed to remove NSEC records
   8604 	 * from the zone database; if so, the database iterator is reset to
   8605 	 * point to the first node and the loop traverses all of them again,
   8606 	 * this time removing NSEC records.  If we hit a node which is obscured
   8607 	 * by a delegation or a DNAME, nodes are skipped over until we find one
   8608 	 * that is not obscured by the same obscuring name and then normal
   8609 	 * processing is resumed.
   8610 	 *
   8611 	 * The above is repeated until all requested NSEC3 chain changes are
   8612 	 * applied or when we reach the limits for this quantum, whichever
   8613 	 * happens first.
   8614 	 *
   8615 	 * Note that the "signatures" variable is only used here to limit the
   8616 	 * amount of work performed.  Actual DNSSEC signatures are only
   8617 	 * generated by dns__zone_updatesigs() calls later in this function.
   8618 	 */
   8619 	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
   8620 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8621 
   8622 		LOCK_ZONE(zone);
   8623 		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
   8624 
   8625 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   8626 		if (nsec3chain->done || nsec3chain->db != zone->db) {
   8627 			ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
   8628 			ISC_LIST_APPEND(cleanup, nsec3chain, link);
   8629 		}
   8630 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   8631 		UNLOCK_ZONE(zone);
   8632 		if (ISC_LIST_TAIL(cleanup) == nsec3chain) {
   8633 			goto next_addchain;
   8634 		}
   8635 
   8636 		/*
   8637 		 * Possible future db.
   8638 		 */
   8639 		if (nsec3chain->db != db) {
   8640 			goto next_addchain;
   8641 		}
   8642 
   8643 		if (NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
   8644 			goto next_addchain;
   8645 		}
   8646 
   8647 		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
   8648 
   8649 		if (nsec3chain->delete_nsec) {
   8650 			delegation = false;
   8651 			dns_dbiterator_pause(nsec3chain->dbiterator);
   8652 			CHECK(delete_nsec(db, version, node, name, &nsec_diff));
   8653 			goto next_addnode;
   8654 		}
   8655 		/*
   8656 		 * On the first pass we need to check if the current node
   8657 		 * has not been obscured.
   8658 		 */
   8659 		delegation = false;
   8660 		unsecure = false;
   8661 		if (first) {
   8662 			dns_fixedname_t ffound;
   8663 			dns_name_t *found;
   8664 			found = dns_fixedname_initname(&ffound);
   8665 			result = dns_db_find(
   8666 				db, name, version, dns_rdatatype_soa,
   8667 				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
   8668 			if ((result == DNS_R_DELEGATION ||
   8669 			     result == DNS_R_DNAME) &&
   8670 			    !dns_name_equal(name, found))
   8671 			{
   8672 				/*
   8673 				 * Remember the obscuring name so that
   8674 				 * we skip all obscured names.
   8675 				 */
   8676 				dns_name_copy(found, name);
   8677 				delegation = true;
   8678 				goto next_addnode;
   8679 			}
   8680 		}
   8681 
   8682 		/*
   8683 		 * Check to see if this is a bottom of zone node.
   8684 		 */
   8685 		result = allrdatasets(db, node, version, &iterator, &seen);
   8686 		if (result == ISC_R_NOTFOUND) {
   8687 			/* Empty node? */
   8688 			goto next_addnode;
   8689 		}
   8690 		CHECK(result);
   8691 
   8692 		INSIST(!seen.nsec3);
   8693 
   8694 		dns_rdatasetiter_destroy(&iterator);
   8695 		/*
   8696 		 * Is there a NSEC chain than needs to be cleaned up?
   8697 		 */
   8698 		if (seen.nsec) {
   8699 			nsec3chain->seen_nsec = true;
   8700 		}
   8701 
   8702 		if (seen.ns && !seen.soa && !seen.ds) {
   8703 			unsecure = true;
   8704 		}
   8705 		if ((seen.ns && !seen.soa) || seen.dname) {
   8706 			delegation = true;
   8707 		}
   8708 
   8709 		/*
   8710 		 * Process one node.
   8711 		 */
   8712 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8713 		result = dns_nsec3_addnsec3(
   8714 			db, version, name, &nsec3chain->nsec3param,
   8715 			zone_nsecttl(zone), unsecure, &nsec3_diff);
   8716 		if (result != ISC_R_SUCCESS) {
   8717 			dnssec_log(zone, ISC_LOG_ERROR,
   8718 				   "zone_nsec3chain:"
   8719 				   "dns_nsec3_addnsec3 -> %s",
   8720 				   isc_result_totext(result));
   8721 			goto cleanup;
   8722 		}
   8723 
   8724 		/*
   8725 		 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
   8726 		 * two signatures.  Additionally there will, in general, be
   8727 		 * two signature generated below.
   8728 		 *
   8729 		 * If we are only changing the optout flag the cost is half
   8730 		 * that of the cost of generating a completely new chain.
   8731 		 */
   8732 		signatures -= 4;
   8733 
   8734 		/*
   8735 		 * Go onto next node.
   8736 		 */
   8737 	next_addnode:
   8738 		first = false;
   8739 		dns_db_detachnode(db, &node);
   8740 		do {
   8741 			result = dns_dbiterator_next(nsec3chain->dbiterator);
   8742 
   8743 			if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
   8744 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8745 				CHECK(fixup_nsec3param(db, version, nsec3chain,
   8746 						       false, privatetype,
   8747 						       &param_diff));
   8748 				LOCK_ZONE(zone);
   8749 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
   8750 						link);
   8751 				UNLOCK_ZONE(zone);
   8752 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
   8753 				goto next_addchain;
   8754 			}
   8755 			if (result == ISC_R_NOMORE) {
   8756 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8757 				if (nsec3chain->seen_nsec) {
   8758 					CHECK(fixup_nsec3param(
   8759 						db, version, nsec3chain, true,
   8760 						privatetype, &param_diff));
   8761 					nsec3chain->delete_nsec = true;
   8762 					goto same_addchain;
   8763 				}
   8764 				CHECK(fixup_nsec3param(db, version, nsec3chain,
   8765 						       false, privatetype,
   8766 						       &param_diff));
   8767 				LOCK_ZONE(zone);
   8768 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
   8769 						link);
   8770 				UNLOCK_ZONE(zone);
   8771 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
   8772 				goto next_addchain;
   8773 			} else if (result != ISC_R_SUCCESS) {
   8774 				dnssec_log(zone, ISC_LOG_ERROR,
   8775 					   "zone_nsec3chain:"
   8776 					   "dns_dbiterator_next -> %s",
   8777 					   isc_result_totext(result));
   8778 				goto cleanup;
   8779 			} else if (delegation) {
   8780 				dns_dbiterator_current(nsec3chain->dbiterator,
   8781 						       &node, nextname);
   8782 				dns_db_detachnode(db, &node);
   8783 				if (!dns_name_issubdomain(nextname, name)) {
   8784 					break;
   8785 				}
   8786 			} else {
   8787 				break;
   8788 			}
   8789 		} while (1);
   8790 		continue;
   8791 
   8792 	same_addchain:
   8793 		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
   8794 		first = true;
   8795 		continue;
   8796 
   8797 	next_addchain:
   8798 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8799 		nsec3chain = nextnsec3chain;
   8800 		first = true;
   8801 		if (nsec3chain != NULL) {
   8802 			nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
   8803 		}
   8804 	}
   8805 
   8806 	if (nsec3chain != NULL) {
   8807 		goto skip_removals;
   8808 	}
   8809 
   8810 	/*
   8811 	 * Process removals.
   8812 	 *
   8813 	 * This is a counterpart of the above while loop which takes care of
   8814 	 * removing an NSEC3 chain.  It starts with determining whether the
   8815 	 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
   8816 	 * NSEC chain by iterating over all nodes in the zone database and only
   8817 	 * then goes on to remove NSEC3 records be iterating over all nodes
   8818 	 * again and calling deletematchingnsec3() for each of them; otherwise,
   8819 	 * it starts removing NSEC3 records immediately.  Rules for processing
   8820 	 * obscured nodes and interrupting work are the same as for the while
   8821 	 * loop above.
   8822 	 */
   8823 	LOCK_ZONE(zone);
   8824 	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   8825 	UNLOCK_ZONE(zone);
   8826 	first = true;
   8827 	buildnsecchain = false;
   8828 	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
   8829 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8830 
   8831 		LOCK_ZONE(zone);
   8832 		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
   8833 		UNLOCK_ZONE(zone);
   8834 
   8835 		if (nsec3chain->db != db) {
   8836 			goto next_removechain;
   8837 		}
   8838 
   8839 		if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
   8840 			goto next_removechain;
   8841 		}
   8842 
   8843 		/*
   8844 		 * Work out if we need to build a NSEC chain as a consequence
   8845 		 * of removing this NSEC3 chain.
   8846 		 */
   8847 		if (first && !updatensec &&
   8848 		    (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
   8849 		{
   8850 			result = need_nsec_chain(db, version,
   8851 						 &nsec3chain->nsec3param,
   8852 						 &buildnsecchain);
   8853 			if (result != ISC_R_SUCCESS) {
   8854 				dnssec_log(zone, ISC_LOG_ERROR,
   8855 					   "zone_nsec3chain:"
   8856 					   "need_nsec_chain -> %s",
   8857 					   isc_result_totext(result));
   8858 				goto cleanup;
   8859 			}
   8860 		}
   8861 
   8862 		if (first) {
   8863 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   8864 				   "zone_nsec3chain:buildnsecchain = %u",
   8865 				   buildnsecchain);
   8866 		}
   8867 
   8868 		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
   8869 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8870 		delegation = false;
   8871 
   8872 		if (!buildnsecchain) {
   8873 			/*
   8874 			 * Delete the NSEC3PARAM record matching this chain.
   8875 			 */
   8876 			if (first) {
   8877 				result = fixup_nsec3param(
   8878 					db, version, nsec3chain, true,
   8879 					privatetype, &param_diff);
   8880 				if (result != ISC_R_SUCCESS) {
   8881 					dnssec_log(zone, ISC_LOG_ERROR,
   8882 						   "zone_nsec3chain:"
   8883 						   "fixup_nsec3param -> %s",
   8884 						   isc_result_totext(result));
   8885 					goto cleanup;
   8886 				}
   8887 			}
   8888 
   8889 			/*
   8890 			 * Delete the NSEC3 records.
   8891 			 */
   8892 			result = deletematchingnsec3(db, version, node, name,
   8893 						     &nsec3chain->nsec3param,
   8894 						     &nsec3_diff);
   8895 			if (result != ISC_R_SUCCESS) {
   8896 				dnssec_log(zone, ISC_LOG_ERROR,
   8897 					   "zone_nsec3chain:"
   8898 					   "deletematchingnsec3 -> %s",
   8899 					   isc_result_totext(result));
   8900 				goto cleanup;
   8901 			}
   8902 			goto next_removenode;
   8903 		}
   8904 
   8905 		if (first) {
   8906 			dns_fixedname_t ffound;
   8907 			dns_name_t *found;
   8908 			found = dns_fixedname_initname(&ffound);
   8909 			result = dns_db_find(
   8910 				db, name, version, dns_rdatatype_soa,
   8911 				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
   8912 			if ((result == DNS_R_DELEGATION ||
   8913 			     result == DNS_R_DNAME) &&
   8914 			    !dns_name_equal(name, found))
   8915 			{
   8916 				/*
   8917 				 * Remember the obscuring name so that
   8918 				 * we skip all obscured names.
   8919 				 */
   8920 				dns_name_copy(found, name);
   8921 				delegation = true;
   8922 				goto next_removenode;
   8923 			}
   8924 		}
   8925 
   8926 		/*
   8927 		 * Check to see if this is a bottom of zone node.
   8928 		 */
   8929 		result = allrdatasets(db, node, version, &iterator, &seen);
   8930 		if (result == ISC_R_NOTFOUND) {
   8931 			/* Empty node? */
   8932 			goto next_removenode;
   8933 		}
   8934 		CHECK(result);
   8935 
   8936 		dns_rdatasetiter_destroy(&iterator);
   8937 
   8938 		if (!seen.rr || seen.nsec3 || seen.nsec) {
   8939 			goto next_removenode;
   8940 		}
   8941 		if ((seen.ns && !seen.soa) || seen.dname) {
   8942 			delegation = true;
   8943 		}
   8944 
   8945 		/*
   8946 		 * Add a NSEC record except at the origin.
   8947 		 */
   8948 		if (!dns_name_equal(name, dns_db_origin(db))) {
   8949 			dns_dbiterator_pause(nsec3chain->dbiterator);
   8950 			CHECK(add_nsec(db, version, name, node,
   8951 				       zone_nsecttl(zone), delegation,
   8952 				       &nsec_diff));
   8953 			signatures--;
   8954 		}
   8955 
   8956 	next_removenode:
   8957 		first = false;
   8958 		dns_db_detachnode(db, &node);
   8959 		do {
   8960 			result = dns_dbiterator_next(nsec3chain->dbiterator);
   8961 			if (result == ISC_R_NOMORE && buildnsecchain) {
   8962 				/*
   8963 				 * The NSEC chain should now be built.
   8964 				 * We can now remove the NSEC3 chain.
   8965 				 */
   8966 				updatensec = true;
   8967 				goto same_removechain;
   8968 			}
   8969 			if (result == ISC_R_NOMORE) {
   8970 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8971 				LOCK_ZONE(zone);
   8972 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
   8973 						link);
   8974 				UNLOCK_ZONE(zone);
   8975 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
   8976 				result = fixup_nsec3param(
   8977 					db, version, nsec3chain, false,
   8978 					privatetype, &param_diff);
   8979 				if (result != ISC_R_SUCCESS) {
   8980 					dnssec_log(zone, ISC_LOG_ERROR,
   8981 						   "zone_nsec3chain:"
   8982 						   "fixup_nsec3param -> %s",
   8983 						   isc_result_totext(result));
   8984 					goto cleanup;
   8985 				}
   8986 				goto next_removechain;
   8987 			} else if (result != ISC_R_SUCCESS) {
   8988 				dnssec_log(zone, ISC_LOG_ERROR,
   8989 					   "zone_nsec3chain:"
   8990 					   "dns_dbiterator_next -> %s",
   8991 					   isc_result_totext(result));
   8992 				goto cleanup;
   8993 			} else if (delegation) {
   8994 				dns_dbiterator_current(nsec3chain->dbiterator,
   8995 						       &node, nextname);
   8996 				dns_db_detachnode(db, &node);
   8997 				if (!dns_name_issubdomain(nextname, name)) {
   8998 					break;
   8999 				}
   9000 			} else {
   9001 				break;
   9002 			}
   9003 		} while (1);
   9004 		continue;
   9005 
   9006 	same_removechain:
   9007 		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
   9008 		buildnsecchain = false;
   9009 		first = true;
   9010 		continue;
   9011 
   9012 	next_removechain:
   9013 		dns_dbiterator_pause(nsec3chain->dbiterator);
   9014 		nsec3chain = nextnsec3chain;
   9015 		first = true;
   9016 	}
   9017 
   9018 skip_removals:
   9019 	/*
   9020 	 * We may need to update the NSEC/NSEC3 records for the zone apex.
   9021 	 */
   9022 	if (!ISC_LIST_EMPTY(param_diff.tuples)) {
   9023 		bool rebuild_nsec = false, rebuild_nsec3 = false;
   9024 		result = dns_db_getoriginnode(db, &node);
   9025 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9026 		result = dns_db_allrdatasets(db, node, version, 0, 0,
   9027 					     &iterator);
   9028 		if (result != ISC_R_SUCCESS) {
   9029 			dnssec_log(zone, ISC_LOG_ERROR,
   9030 				   "zone_nsec3chain:dns_db_allrdatasets -> %s",
   9031 				   isc_result_totext(result));
   9032 			goto cleanup;
   9033 		}
   9034 		for (result = dns_rdatasetiter_first(iterator);
   9035 		     result == ISC_R_SUCCESS;
   9036 		     result = dns_rdatasetiter_next(iterator))
   9037 		{
   9038 			dns_rdatasetiter_current(iterator, &rdataset);
   9039 			if (rdataset.type == dns_rdatatype_nsec) {
   9040 				rebuild_nsec = true;
   9041 			} else if (rdataset.type == dns_rdatatype_nsec3param) {
   9042 				rebuild_nsec3 = true;
   9043 			}
   9044 			dns_rdataset_disassociate(&rdataset);
   9045 		}
   9046 		dns_rdatasetiter_destroy(&iterator);
   9047 		dns_db_detachnode(db, &node);
   9048 
   9049 		if (rebuild_nsec) {
   9050 			if (nsec3chain != NULL) {
   9051 				dns_dbiterator_pause(nsec3chain->dbiterator);
   9052 			}
   9053 
   9054 			result = updatesecure(db, version, &zone->origin,
   9055 					      zone_nsecttl(zone), true,
   9056 					      &nsec_diff);
   9057 			if (result != ISC_R_SUCCESS) {
   9058 				dnssec_log(zone, ISC_LOG_ERROR,
   9059 					   "zone_nsec3chain:updatesecure -> %s",
   9060 					   isc_result_totext(result));
   9061 				goto cleanup;
   9062 			}
   9063 		}
   9064 
   9065 		if (rebuild_nsec3) {
   9066 			if (nsec3chain != NULL) {
   9067 				dns_dbiterator_pause(nsec3chain->dbiterator);
   9068 			}
   9069 
   9070 			result = dns_nsec3_addnsec3s(
   9071 				db, version, dns_db_origin(db),
   9072 				zone_nsecttl(zone), false, &nsec3_diff);
   9073 			if (result != ISC_R_SUCCESS) {
   9074 				dnssec_log(zone, ISC_LOG_ERROR,
   9075 					   "zone_nsec3chain:"
   9076 					   "dns_nsec3_addnsec3s -> %s",
   9077 					   isc_result_totext(result));
   9078 				goto cleanup;
   9079 			}
   9080 		}
   9081 	}
   9082 
   9083 	/*
   9084 	 * Add / update signatures for the NSEC3 records.
   9085 	 */
   9086 	if (nsec3chain != NULL) {
   9087 		dns_dbiterator_pause(nsec3chain->dbiterator);
   9088 	}
   9089 	result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
   9090 				      nkeys, zone, inception, expire, 0, now,
   9091 				      &zonediff);
   9092 	if (result != ISC_R_SUCCESS) {
   9093 		dnssec_log(zone, ISC_LOG_ERROR,
   9094 			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
   9095 			   isc_result_totext(result));
   9096 		goto cleanup;
   9097 	}
   9098 
   9099 	/*
   9100 	 * We have changed the NSEC3PARAM or private RRsets
   9101 	 * above so we need to update the signatures.
   9102 	 */
   9103 	result = dns__zone_updatesigs(&param_diff, db, version, zone_keys,
   9104 				      nkeys, zone, inception, expire, 0, now,
   9105 				      &zonediff);
   9106 	if (result != ISC_R_SUCCESS) {
   9107 		dnssec_log(zone, ISC_LOG_ERROR,
   9108 			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
   9109 			   isc_result_totext(result));
   9110 		goto cleanup;
   9111 	}
   9112 
   9113 	if (updatensec) {
   9114 		result = updatesecure(db, version, &zone->origin,
   9115 				      zone_nsecttl(zone), false, &nsec_diff);
   9116 		if (result != ISC_R_SUCCESS) {
   9117 			dnssec_log(zone, ISC_LOG_ERROR,
   9118 				   "zone_nsec3chain:updatesecure -> %s",
   9119 				   isc_result_totext(result));
   9120 			goto cleanup;
   9121 		}
   9122 	}
   9123 
   9124 	result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys, nkeys,
   9125 				      zone, inception, expire, 0, now,
   9126 				      &zonediff);
   9127 	if (result != ISC_R_SUCCESS) {
   9128 		dnssec_log(zone, ISC_LOG_ERROR,
   9129 			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
   9130 			   isc_result_totext(result));
   9131 		goto cleanup;
   9132 	}
   9133 
   9134 	/*
   9135 	 * If we made no effective changes to the zone then we can just
   9136 	 * cleanup otherwise we need to increment the serial.
   9137 	 */
   9138 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
   9139 		/*
   9140 		 * No need to call dns_db_closeversion() here as it is
   9141 		 * called with commit = true below.
   9142 		 */
   9143 		goto closeversion;
   9144 	}
   9145 
   9146 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
   9147 			  &zonediff, zone_keys, nkeys, now, false);
   9148 	if (result != ISC_R_SUCCESS) {
   9149 		dnssec_log(zone, ISC_LOG_ERROR,
   9150 			   "zone_nsec3chain:del_sigs -> %s",
   9151 			   isc_result_totext(result));
   9152 		goto cleanup;
   9153 	}
   9154 
   9155 	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
   9156 				   zone->updatemethod);
   9157 	if (result != ISC_R_SUCCESS) {
   9158 		dnssec_log(zone, ISC_LOG_ERROR,
   9159 			   "zone_nsec3chain:update_soa_serial -> %s",
   9160 			   isc_result_totext(result));
   9161 		goto cleanup;
   9162 	}
   9163 
   9164 	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
   9165 			  zonediff.diff, zone_keys, nkeys, zone->mctx, now,
   9166 			  inception, soaexpire);
   9167 	if (result != ISC_R_SUCCESS) {
   9168 		dnssec_log(zone, ISC_LOG_ERROR,
   9169 			   "zone_nsec3chain:add_sigs -> %s",
   9170 			   isc_result_totext(result));
   9171 		goto cleanup;
   9172 	}
   9173 
   9174 	/* Write changes to journal file. */
   9175 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
   9176 
   9177 	LOCK_ZONE(zone);
   9178 	zone_needdump(zone, DNS_DUMP_DELAY);
   9179 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   9180 	UNLOCK_ZONE(zone);
   9181 
   9182 closeversion:
   9183 	/*
   9184 	 * Pause all iterators so that dns_db_closeversion() can succeed.
   9185 	 */
   9186 	LOCK_ZONE(zone);
   9187 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
   9188 	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
   9189 	{
   9190 		dns_dbiterator_pause(nsec3chain->dbiterator);
   9191 	}
   9192 	UNLOCK_ZONE(zone);
   9193 
   9194 	/*
   9195 	 * Everything has succeeded. Commit the changes.
   9196 	 * Unconditionally commit as zonediff.offline not checked above.
   9197 	 */
   9198 	dns_db_closeversion(db, &version, true);
   9199 
   9200 	/*
   9201 	 * Everything succeeded so we can clean these up now.
   9202 	 */
   9203 	nsec3chain = ISC_LIST_HEAD(cleanup);
   9204 	while (nsec3chain != NULL) {
   9205 		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
   9206 		dns_db_detach(&nsec3chain->db);
   9207 		dns_dbiterator_destroy(&nsec3chain->dbiterator);
   9208 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   9209 		nsec3chain = ISC_LIST_HEAD(cleanup);
   9210 	}
   9211 
   9212 	LOCK_ZONE(zone);
   9213 	set_resigntime(zone);
   9214 	UNLOCK_ZONE(zone);
   9215 
   9216 cleanup:
   9217 	if (result != ISC_R_SUCCESS) {
   9218 		dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
   9219 			   isc_result_totext(result));
   9220 	}
   9221 
   9222 	/*
   9223 	 * On error roll back the current nsec3chain.
   9224 	 */
   9225 	if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
   9226 		if (nsec3chain->done) {
   9227 			dns_db_detach(&nsec3chain->db);
   9228 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
   9229 			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   9230 		} else {
   9231 			result = dns_dbiterator_first(nsec3chain->dbiterator);
   9232 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9233 			dns_dbiterator_pause(nsec3chain->dbiterator);
   9234 			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
   9235 		}
   9236 	}
   9237 
   9238 	/*
   9239 	 * Rollback the cleanup list.
   9240 	 */
   9241 	nsec3chain = ISC_LIST_TAIL(cleanup);
   9242 	while (nsec3chain != NULL) {
   9243 		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
   9244 		if (nsec3chain->done) {
   9245 			dns_db_detach(&nsec3chain->db);
   9246 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
   9247 			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   9248 		} else {
   9249 			LOCK_ZONE(zone);
   9250 			ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
   9251 			UNLOCK_ZONE(zone);
   9252 			result = dns_dbiterator_first(nsec3chain->dbiterator);
   9253 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9254 			dns_dbiterator_pause(nsec3chain->dbiterator);
   9255 			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
   9256 		}
   9257 		nsec3chain = ISC_LIST_TAIL(cleanup);
   9258 	}
   9259 
   9260 	LOCK_ZONE(zone);
   9261 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
   9262 	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
   9263 	{
   9264 		dns_dbiterator_pause(nsec3chain->dbiterator);
   9265 	}
   9266 	UNLOCK_ZONE(zone);
   9267 
   9268 	dns_diff_clear(&param_diff);
   9269 	dns_diff_clear(&nsec3_diff);
   9270 	dns_diff_clear(&nsec_diff);
   9271 	dns_diff_clear(&_sig_diff);
   9272 
   9273 	if (iterator != NULL) {
   9274 		dns_rdatasetiter_destroy(&iterator);
   9275 	}
   9276 
   9277 	for (i = 0; i < nkeys; i++) {
   9278 		dst_key_free(&zone_keys[i]);
   9279 	}
   9280 
   9281 	if (node != NULL) {
   9282 		dns_db_detachnode(db, &node);
   9283 	}
   9284 	if (version != NULL) {
   9285 		dns_db_closeversion(db, &version, false);
   9286 		dns_db_detach(&db);
   9287 	} else if (db != NULL) {
   9288 		dns_db_detach(&db);
   9289 	}
   9290 
   9291 	LOCK_ZONE(zone);
   9292 	if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
   9293 		isc_interval_t interval;
   9294 		if (zone->update_disabled || result != ISC_R_SUCCESS) {
   9295 			isc_interval_set(&interval, 60, 0); /* 1 minute */
   9296 		} else {
   9297 			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
   9298 		}
   9299 		isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
   9300 	} else {
   9301 		isc_time_settoepoch(&zone->nsec3chaintime);
   9302 	}
   9303 	UNLOCK_ZONE(zone);
   9304 
   9305 	INSIST(version == NULL);
   9306 }
   9307 
   9308 /*%
   9309  * Delete all RRSIG records with the given algorithm and keyid.
   9310  * Remove the NSEC record and RRSIGs if nkeys is zero.
   9311  * If all remaining RRsets are signed with the given algorithm
   9312  * set *has_algp to true.
   9313  */
   9314 static isc_result_t
   9315 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
   9316 	dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
   9317 	uint16_t keyid, bool *has_algp, dns_diff_t *diff) {
   9318 	dns_rdata_rrsig_t rrsig;
   9319 	dns_rdataset_t rdataset;
   9320 	dns_rdatasetiter_t *iterator = NULL;
   9321 	isc_result_t result;
   9322 	bool alg_missed = false;
   9323 	bool alg_found = false;
   9324 
   9325 	char namebuf[DNS_NAME_FORMATSIZE];
   9326 	dns_name_format(name, namebuf, sizeof(namebuf));
   9327 
   9328 	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
   9329 	if (result != ISC_R_SUCCESS) {
   9330 		if (result == ISC_R_NOTFOUND) {
   9331 			result = ISC_R_SUCCESS;
   9332 		}
   9333 		return result;
   9334 	}
   9335 
   9336 	dns_rdataset_init(&rdataset);
   9337 	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
   9338 	     result = dns_rdatasetiter_next(iterator))
   9339 	{
   9340 		bool has_alg = false;
   9341 		dns_rdatasetiter_current(iterator, &rdataset);
   9342 		if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
   9343 			for (result = dns_rdataset_first(&rdataset);
   9344 			     result == ISC_R_SUCCESS;
   9345 			     result = dns_rdataset_next(&rdataset))
   9346 			{
   9347 				dns_rdata_t rdata = DNS_RDATA_INIT;
   9348 				dns_rdataset_current(&rdataset, &rdata);
   9349 				CHECK(update_one_rr(db, version, diff,
   9350 						    DNS_DIFFOP_DEL, name,
   9351 						    rdataset.ttl, &rdata));
   9352 			}
   9353 			if (result != ISC_R_NOMORE) {
   9354 				goto cleanup;
   9355 			}
   9356 			dns_rdataset_disassociate(&rdataset);
   9357 			continue;
   9358 		}
   9359 		if (rdataset.type != dns_rdatatype_rrsig) {
   9360 			dns_rdataset_disassociate(&rdataset);
   9361 			continue;
   9362 		}
   9363 		for (result = dns_rdataset_first(&rdataset);
   9364 		     result == ISC_R_SUCCESS;
   9365 		     result = dns_rdataset_next(&rdataset))
   9366 		{
   9367 			dns_rdata_t rdata = DNS_RDATA_INIT;
   9368 			dns_rdataset_current(&rdataset, &rdata);
   9369 			CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
   9370 			if (nkeys != 0 && (rrsig.algorithm != algorithm ||
   9371 					   rrsig.keyid != keyid))
   9372 			{
   9373 				if (rrsig.algorithm == algorithm) {
   9374 					has_alg = true;
   9375 				}
   9376 				continue;
   9377 			}
   9378 			CHECK(update_one_rr(db, version, diff,
   9379 					    DNS_DIFFOP_DELRESIGN, name,
   9380 					    rdataset.ttl, &rdata));
   9381 		}
   9382 		dns_rdataset_disassociate(&rdataset);
   9383 		if (result != ISC_R_NOMORE) {
   9384 			break;
   9385 		}
   9386 
   9387 		/*
   9388 		 * After deleting, if there's still a signature for
   9389 		 * 'algorithm', set alg_found; if not, set alg_missed.
   9390 		 */
   9391 		if (has_alg) {
   9392 			alg_found = true;
   9393 		} else {
   9394 			alg_missed = true;
   9395 		}
   9396 	}
   9397 	if (result == ISC_R_NOMORE) {
   9398 		result = ISC_R_SUCCESS;
   9399 	}
   9400 
   9401 	/*
   9402 	 * Set `has_algp` if the algorithm was found in every RRset:
   9403 	 * i.e., found in at least one, and not missing from any.
   9404 	 */
   9405 	*has_algp = (alg_found && !alg_missed);
   9406 cleanup:
   9407 	if (dns_rdataset_isassociated(&rdataset)) {
   9408 		dns_rdataset_disassociate(&rdataset);
   9409 	}
   9410 	dns_rdatasetiter_destroy(&iterator);
   9411 	return result;
   9412 }
   9413 
   9414 /*
   9415  * Prevent the zone entering a inconsistent state where
   9416  * NSEC only DNSKEYs are present with NSEC3 chains.
   9417  */
   9418 bool
   9419 dns_zone_check_dnskey_nsec3(dns_zone_t *zone, dns_db_t *db,
   9420 			    dns_dbversion_t *ver, dns_diff_t *diff,
   9421 			    dst_key_t **keys, unsigned int numkeys) {
   9422 	uint8_t alg;
   9423 	dns_rdatatype_t privatetype;
   9424 	;
   9425 	bool nseconly = false, nsec3 = false;
   9426 	isc_result_t result;
   9427 
   9428 	REQUIRE(DNS_ZONE_VALID(zone));
   9429 	REQUIRE(db != NULL);
   9430 
   9431 	privatetype = dns_zone_getprivatetype(zone);
   9432 
   9433 	/* Scan the tuples for an NSEC-only DNSKEY */
   9434 	if (diff != NULL) {
   9435 		for (dns_difftuple_t *tuple = ISC_LIST_HEAD(diff->tuples);
   9436 		     tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
   9437 		{
   9438 			if (nseconly && nsec3) {
   9439 				break;
   9440 			}
   9441 
   9442 			if (tuple->op != DNS_DIFFOP_ADD) {
   9443 				continue;
   9444 			}
   9445 
   9446 			if (tuple->rdata.type == dns_rdatatype_nsec3param) {
   9447 				nsec3 = true;
   9448 			}
   9449 
   9450 			if (tuple->rdata.type != dns_rdatatype_dnskey) {
   9451 				continue;
   9452 			}
   9453 
   9454 			alg = tuple->rdata.data[3];
   9455 			if (alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_DSA ||
   9456 			    alg == DNS_KEYALG_RSASHA1)
   9457 			{
   9458 				nseconly = true;
   9459 			}
   9460 		}
   9461 	}
   9462 	/* Scan the zone keys for an NSEC-only DNSKEY */
   9463 	if (keys != NULL && !nseconly) {
   9464 		for (unsigned int i = 0; i < numkeys; i++) {
   9465 			alg = dst_key_alg(keys[i]);
   9466 			if (alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_DSA ||
   9467 			    alg == DNS_KEYALG_RSASHA1)
   9468 			{
   9469 				nseconly = true;
   9470 				break;
   9471 			}
   9472 		}
   9473 	}
   9474 
   9475 	/* Check DB for NSEC-only DNSKEY */
   9476 	if (!nseconly) {
   9477 		result = dns_nsec_nseconly(db, ver, diff, &nseconly);
   9478 		/*
   9479 		 * Adding an NSEC3PARAM record can proceed without a
   9480 		 * DNSKEY (it will trigger a delayed change), so we can
   9481 		 * ignore ISC_R_NOTFOUND here.
   9482 		 */
   9483 		if (result == ISC_R_NOTFOUND) {
   9484 			result = ISC_R_SUCCESS;
   9485 		}
   9486 		CHECK(result);
   9487 	}
   9488 
   9489 	/* Check existing DB for NSEC3 */
   9490 	if (!nsec3) {
   9491 		CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3));
   9492 	}
   9493 
   9494 	/* Check kasp for NSEC3PARAM settings */
   9495 	if (!nsec3) {
   9496 		dns_kasp_t *kasp = zone->kasp;
   9497 		if (kasp != NULL) {
   9498 			nsec3 = dns_kasp_nsec3(kasp);
   9499 		}
   9500 	}
   9501 
   9502 	/* Refuse to allow NSEC3 with NSEC-only keys */
   9503 	if (nseconly && nsec3) {
   9504 		goto cleanup;
   9505 	}
   9506 
   9507 	return true;
   9508 
   9509 cleanup:
   9510 	return false;
   9511 }
   9512 
   9513 /*
   9514  * Incrementally sign the zone using the keys requested.
   9515  * Builds the NSEC chain if required.
   9516  */
   9517 static void
   9518 zone_sign(dns_zone_t *zone) {
   9519 	dns_db_t *db = NULL;
   9520 	dns_dbnode_t *node = NULL;
   9521 	dns_dbversion_t *version = NULL;
   9522 	dns_diff_t _sig_diff;
   9523 	dns_diff_t post_diff;
   9524 	dns__zonediff_t zonediff;
   9525 	dns_fixedname_t fixed;
   9526 	dns_fixedname_t nextfixed;
   9527 	dns_kasp_t *kasp;
   9528 	dns_name_t *name, *nextname;
   9529 	dns_rdataset_t rdataset;
   9530 	dns_signing_t *signing, *nextsigning;
   9531 	dns_signinglist_t cleanup;
   9532 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   9533 	int32_t signatures;
   9534 	bool is_ksk, is_zsk;
   9535 	bool with_ksk, with_zsk;
   9536 	bool commit = false;
   9537 	bool is_bottom_of_zone;
   9538 	bool build_nsec = false;
   9539 	bool build_nsec3 = false;
   9540 	bool use_kasp = false;
   9541 	bool first;
   9542 	isc_result_t result;
   9543 	isc_stdtime_t now, inception, soaexpire, expire;
   9544 	unsigned int i, j;
   9545 	unsigned int nkeys = 0;
   9546 	uint32_t nodes;
   9547 
   9548 	ENTER;
   9549 
   9550 	dns_rdataset_init(&rdataset);
   9551 	name = dns_fixedname_initname(&fixed);
   9552 	nextname = dns_fixedname_initname(&nextfixed);
   9553 	dns_diff_init(zone->mctx, &_sig_diff);
   9554 	dns_diff_init(zone->mctx, &post_diff);
   9555 	zonediff_init(&zonediff, &_sig_diff);
   9556 	ISC_LIST_INIT(cleanup);
   9557 
   9558 	/*
   9559 	 * Updates are disabled.  Pause for 1 minute.
   9560 	 */
   9561 	if (zone->update_disabled) {
   9562 		result = ISC_R_FAILURE;
   9563 		goto done;
   9564 	}
   9565 
   9566 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   9567 	if (zone->db != NULL) {
   9568 		dns_db_attach(zone->db, &db);
   9569 	}
   9570 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   9571 	if (db == NULL) {
   9572 		result = ISC_R_FAILURE;
   9573 		goto done;
   9574 	}
   9575 
   9576 	result = dns_db_newversion(db, &version);
   9577 	if (result != ISC_R_SUCCESS) {
   9578 		dnssec_log(zone, ISC_LOG_ERROR,
   9579 			   "zone_sign:dns_db_newversion -> %s",
   9580 			   isc_result_totext(result));
   9581 		goto done;
   9582 	}
   9583 
   9584 	now = isc_stdtime_now();
   9585 
   9586 	result = dns_zone_findkeys(zone, db, version, now, zone->mctx,
   9587 				   DNS_MAXZONEKEYS, zone_keys, &nkeys);
   9588 	if (result != ISC_R_SUCCESS) {
   9589 		dnssec_log(zone, ISC_LOG_ERROR,
   9590 			   "zone_sign:dns_zone_findkeys -> %s",
   9591 			   isc_result_totext(result));
   9592 		goto done;
   9593 	}
   9594 
   9595 	kasp = zone->kasp;
   9596 
   9597 	calculate_rrsig_validity(zone, now, &inception, &soaexpire, NULL,
   9598 				 &expire);
   9599 
   9600 	/*
   9601 	 * We keep pulling nodes off each iterator in turn until
   9602 	 * we have no more nodes to pull off or we reach the limits
   9603 	 * for this quantum.
   9604 	 */
   9605 	nodes = zone->nodes;
   9606 	signatures = zone->signatures;
   9607 	signing = ISC_LIST_HEAD(zone->signing);
   9608 	first = true;
   9609 
   9610 	if (kasp != NULL) {
   9611 		use_kasp = true;
   9612 	}
   9613 	dnssec_log(zone, ISC_LOG_DEBUG(3), "zone_sign:use kasp -> %s",
   9614 		   use_kasp ? "yes" : "no");
   9615 
   9616 	/* Determine which type of chain to build */
   9617 	CHECK(dns_private_chains(db, version, zone->privatetype, &build_nsec,
   9618 				 &build_nsec3));
   9619 	if (!build_nsec && !build_nsec3) {
   9620 		if (use_kasp) {
   9621 			build_nsec3 = dns_kasp_nsec3(kasp);
   9622 			if (!dns_zone_check_dnskey_nsec3(
   9623 				    zone, db, version, NULL,
   9624 				    (dst_key_t **)&zone_keys, nkeys))
   9625 			{
   9626 				dnssec_log(zone, ISC_LOG_INFO,
   9627 					   "wait building NSEC3 chain until "
   9628 					   "NSEC only DNSKEYs are removed");
   9629 				build_nsec3 = false;
   9630 			}
   9631 			build_nsec = !build_nsec3;
   9632 		} else {
   9633 			/* If neither chain is found, default to NSEC */
   9634 			build_nsec = true;
   9635 		}
   9636 	}
   9637 
   9638 	while (signing != NULL && nodes-- > 0 && signatures > 0) {
   9639 		bool has_alg = false;
   9640 
   9641 		dns_dbiterator_pause(signing->dbiterator);
   9642 		nextsigning = ISC_LIST_NEXT(signing, link);
   9643 
   9644 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   9645 		if (signing->done || signing->db != zone->db) {
   9646 			/*
   9647 			 * The zone has been reloaded.	We will have to
   9648 			 * created new signings as part of the reload
   9649 			 * process so we can destroy this one.
   9650 			 */
   9651 			ISC_LIST_UNLINK(zone->signing, signing, link);
   9652 			ISC_LIST_APPEND(cleanup, signing, link);
   9653 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   9654 			goto next_signing;
   9655 		}
   9656 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   9657 
   9658 		if (signing->db != db) {
   9659 			goto next_signing;
   9660 		}
   9661 
   9662 		is_bottom_of_zone = false;
   9663 
   9664 		if (first && signing->deleteit) {
   9665 			/*
   9666 			 * Remove the key we are deleting from consideration.
   9667 			 */
   9668 			for (i = 0, j = 0; i < nkeys; i++) {
   9669 				/*
   9670 				 * Find the key we want to remove.
   9671 				 */
   9672 				if (ALG(zone_keys[i]) == signing->algorithm &&
   9673 				    dst_key_id(zone_keys[i]) == signing->keyid)
   9674 				{
   9675 					dst_key_free(&zone_keys[i]);
   9676 					continue;
   9677 				}
   9678 				zone_keys[j] = zone_keys[i];
   9679 				j++;
   9680 			}
   9681 			for (i = j; i < nkeys; i++) {
   9682 				zone_keys[i] = NULL;
   9683 			}
   9684 			nkeys = j;
   9685 		}
   9686 
   9687 		dns_dbiterator_current(signing->dbiterator, &node, name);
   9688 
   9689 		if (signing->deleteit) {
   9690 			dns_dbiterator_pause(signing->dbiterator);
   9691 			CHECK(del_sig(db, version, name, node, nkeys,
   9692 				      signing->algorithm, signing->keyid,
   9693 				      &has_alg, zonediff.diff));
   9694 		}
   9695 
   9696 		/*
   9697 		 * On the first pass we need to check if the current node
   9698 		 * has not been obscured.
   9699 		 */
   9700 		if (first) {
   9701 			dns_fixedname_t ffound;
   9702 			dns_name_t *found;
   9703 			found = dns_fixedname_initname(&ffound);
   9704 			result = dns_db_find(
   9705 				db, name, version, dns_rdatatype_soa,
   9706 				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
   9707 			if ((result == DNS_R_DELEGATION ||
   9708 			     result == DNS_R_DNAME) &&
   9709 			    !dns_name_equal(name, found))
   9710 			{
   9711 				/*
   9712 				 * Remember the obscuring name so that
   9713 				 * we skip all obscured names.
   9714 				 */
   9715 				dns_name_copy(found, name);
   9716 				is_bottom_of_zone = true;
   9717 				goto next_node;
   9718 			}
   9719 		}
   9720 
   9721 		/*
   9722 		 * Process one node.
   9723 		 */
   9724 		with_ksk = false;
   9725 		with_zsk = false;
   9726 		dns_dbiterator_pause(signing->dbiterator);
   9727 
   9728 		CHECK(check_if_bottom_of_zone(db, node, version,
   9729 					      &is_bottom_of_zone));
   9730 
   9731 		for (i = 0; !has_alg && i < nkeys; i++) {
   9732 			bool both = false;
   9733 			/*
   9734 			 * Find the keys we want to sign with.
   9735 			 */
   9736 			if (!dst_key_isprivate(zone_keys[i])) {
   9737 				continue;
   9738 			}
   9739 			if (dst_key_inactive(zone_keys[i])) {
   9740 				continue;
   9741 			}
   9742 
   9743 			/*
   9744 			 * When adding look for the specific key.
   9745 			 */
   9746 			if (!signing->deleteit &&
   9747 			    (dst_key_alg(zone_keys[i]) != signing->algorithm ||
   9748 			     dst_key_id(zone_keys[i]) != signing->keyid))
   9749 			{
   9750 				continue;
   9751 			}
   9752 
   9753 			/*
   9754 			 * When deleting make sure we are properly signed
   9755 			 * with the algorithm that was being removed.
   9756 			 */
   9757 			if (signing->deleteit &&
   9758 			    ALG(zone_keys[i]) != signing->algorithm)
   9759 			{
   9760 				continue;
   9761 			}
   9762 
   9763 			/*
   9764 			 * We do KSK processing.
   9765 			 */
   9766 			if (use_kasp) {
   9767 				/*
   9768 				 * A dnssec-policy is found. Check what
   9769 				 * RRsets this key can sign.
   9770 				 */
   9771 				isc_result_t kresult;
   9772 				is_ksk = false;
   9773 				kresult = dst_key_getbool(
   9774 					zone_keys[i], DST_BOOL_KSK, &is_ksk);
   9775 				if (kresult != ISC_R_SUCCESS) {
   9776 					if (KSK(zone_keys[i])) {
   9777 						is_ksk = true;
   9778 					}
   9779 				}
   9780 
   9781 				is_zsk = false;
   9782 				kresult = dst_key_getbool(
   9783 					zone_keys[i], DST_BOOL_ZSK, &is_zsk);
   9784 				if (kresult != ISC_R_SUCCESS) {
   9785 					if (!KSK(zone_keys[i])) {
   9786 						is_zsk = true;
   9787 					}
   9788 				}
   9789 				both = true;
   9790 			} else {
   9791 				is_ksk = KSK(zone_keys[i]);
   9792 				is_zsk = !is_ksk;
   9793 
   9794 				/*
   9795 				 * Don't consider inactive keys, however the key
   9796 				 * may be temporary offline, so do consider KSKs
   9797 				 * which private key files are unavailable.
   9798 				 */
   9799 				both = dst_key_have_ksk_and_zsk(
   9800 					zone_keys, nkeys, i, false, is_ksk,
   9801 					is_zsk, NULL, NULL);
   9802 				if (both || REVOKE(zone_keys[i])) {
   9803 					is_ksk = KSK(zone_keys[i]);
   9804 					is_zsk = !KSK(zone_keys[i]);
   9805 				} else {
   9806 					is_ksk = false;
   9807 					is_zsk = false;
   9808 				}
   9809 			}
   9810 
   9811 			/*
   9812 			 * If deleting signatures, we need to ensure that
   9813 			 * the RRset is still signed at least once by a
   9814 			 * KSK and a ZSK.
   9815 			 */
   9816 			if (signing->deleteit && is_zsk && with_zsk) {
   9817 				continue;
   9818 			}
   9819 
   9820 			if (signing->deleteit && is_ksk && with_ksk) {
   9821 				continue;
   9822 			}
   9823 
   9824 			CHECK(sign_a_node(
   9825 				db, zone, name, node, version, build_nsec3,
   9826 				build_nsec, zone_keys[i], now, inception,
   9827 				expire, zone_nsecttl(zone), both, is_ksk,
   9828 				is_zsk, signing->fullsign, is_bottom_of_zone,
   9829 				zonediff.diff, &signatures, zone->mctx));
   9830 			/*
   9831 			 * If we are adding we are done.  Look for other keys
   9832 			 * of the same algorithm if deleting.
   9833 			 */
   9834 			if (!signing->deleteit) {
   9835 				break;
   9836 			}
   9837 			if (is_zsk) {
   9838 				with_zsk = true;
   9839 			}
   9840 			if (is_ksk) {
   9841 				with_ksk = true;
   9842 			}
   9843 		}
   9844 
   9845 		/*
   9846 		 * Go onto next node.
   9847 		 */
   9848 	next_node:
   9849 		first = false;
   9850 		dns_db_detachnode(db, &node);
   9851 		do {
   9852 			result = dns_dbiterator_next(signing->dbiterator);
   9853 			if (result == ISC_R_NOMORE) {
   9854 				ISC_LIST_UNLINK(zone->signing, signing, link);
   9855 				ISC_LIST_APPEND(cleanup, signing, link);
   9856 				dns_dbiterator_pause(signing->dbiterator);
   9857 				if (nkeys != 0 && build_nsec) {
   9858 					/*
   9859 					 * We have finished regenerating the
   9860 					 * zone with a zone signing key.
   9861 					 * The NSEC chain is now complete and
   9862 					 * there is a full set of signatures
   9863 					 * for the zone.  We can now clear the
   9864 					 * OPT bit from the NSEC record.
   9865 					 */
   9866 					result = updatesecure(
   9867 						db, version, &zone->origin,
   9868 						zone_nsecttl(zone), false,
   9869 						&post_diff);
   9870 					if (result != ISC_R_SUCCESS) {
   9871 						dnssec_log(zone, ISC_LOG_ERROR,
   9872 							   "updatesecure -> %s",
   9873 							   isc_result_totext(
   9874 								   result));
   9875 						goto done;
   9876 					}
   9877 				}
   9878 				result = updatesignwithkey(
   9879 					zone, signing, version, build_nsec3,
   9880 					zone_nsecttl(zone), &post_diff);
   9881 				if (result != ISC_R_SUCCESS) {
   9882 					dnssec_log(zone, ISC_LOG_ERROR,
   9883 						   "updatesignwithkey -> %s",
   9884 						   isc_result_totext(result));
   9885 					goto done;
   9886 				}
   9887 				build_nsec = false;
   9888 				goto next_signing;
   9889 			} else if (result != ISC_R_SUCCESS) {
   9890 				dnssec_log(zone, ISC_LOG_ERROR,
   9891 					   "zone_sign:"
   9892 					   "dns_dbiterator_next -> %s",
   9893 					   isc_result_totext(result));
   9894 				goto done;
   9895 			} else if (is_bottom_of_zone) {
   9896 				dns_dbiterator_current(signing->dbiterator,
   9897 						       &node, nextname);
   9898 				dns_db_detachnode(db, &node);
   9899 				if (!dns_name_issubdomain(nextname, name)) {
   9900 					break;
   9901 				}
   9902 			} else {
   9903 				break;
   9904 			}
   9905 		} while (1);
   9906 		continue;
   9907 
   9908 	next_signing:
   9909 		dns_dbiterator_pause(signing->dbiterator);
   9910 		signing = nextsigning;
   9911 		first = true;
   9912 	}
   9913 
   9914 	if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
   9915 		result = dns__zone_updatesigs(&post_diff, db, version,
   9916 					      zone_keys, nkeys, zone, inception,
   9917 					      expire, 0, now, &zonediff);
   9918 		if (result != ISC_R_SUCCESS) {
   9919 			dnssec_log(zone, ISC_LOG_ERROR,
   9920 				   "zone_sign:dns__zone_updatesigs -> %s",
   9921 				   isc_result_totext(result));
   9922 			goto done;
   9923 		}
   9924 	}
   9925 
   9926 	/*
   9927 	 * Have we changed anything?
   9928 	 */
   9929 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
   9930 		if (zonediff.offline) {
   9931 			commit = true;
   9932 		}
   9933 		result = ISC_R_SUCCESS;
   9934 		goto pauseall;
   9935 	}
   9936 
   9937 	commit = true;
   9938 
   9939 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
   9940 			  &zonediff, zone_keys, nkeys, now, false);
   9941 	if (result != ISC_R_SUCCESS) {
   9942 		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
   9943 			   isc_result_totext(result));
   9944 		goto done;
   9945 	}
   9946 
   9947 	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
   9948 				   zone->updatemethod);
   9949 	if (result != ISC_R_SUCCESS) {
   9950 		dnssec_log(zone, ISC_LOG_ERROR,
   9951 			   "zone_sign:update_soa_serial -> %s",
   9952 			   isc_result_totext(result));
   9953 		goto done;
   9954 	}
   9955 
   9956 	/*
   9957 	 * Generate maximum life time signatures so that the above loop
   9958 	 * termination is sensible.
   9959 	 */
   9960 	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
   9961 			  zonediff.diff, zone_keys, nkeys, zone->mctx, now,
   9962 			  inception, soaexpire);
   9963 	if (result != ISC_R_SUCCESS) {
   9964 		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
   9965 			   isc_result_totext(result));
   9966 		goto done;
   9967 	}
   9968 
   9969 	/*
   9970 	 * Write changes to journal file.
   9971 	 */
   9972 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
   9973 
   9974 pauseall:
   9975 	/*
   9976 	 * Pause all iterators so that dns_db_closeversion() can succeed.
   9977 	 */
   9978 	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
   9979 	     signing = ISC_LIST_NEXT(signing, link))
   9980 	{
   9981 		dns_dbiterator_pause(signing->dbiterator);
   9982 	}
   9983 
   9984 	for (signing = ISC_LIST_HEAD(cleanup); signing != NULL;
   9985 	     signing = ISC_LIST_NEXT(signing, link))
   9986 	{
   9987 		dns_dbiterator_pause(signing->dbiterator);
   9988 	}
   9989 
   9990 	/*
   9991 	 * Everything has succeeded. Commit the changes.
   9992 	 */
   9993 	dns_db_closeversion(db, &version, commit);
   9994 
   9995 	/*
   9996 	 * Everything succeeded so we can clean these up now.
   9997 	 */
   9998 	signing = ISC_LIST_HEAD(cleanup);
   9999 	while (signing != NULL) {
   10000 		ISC_LIST_UNLINK(cleanup, signing, link);
   10001 		dns_db_detach(&signing->db);
   10002 		dns_dbiterator_destroy(&signing->dbiterator);
   10003 		isc_mem_put(zone->mctx, signing, sizeof *signing);
   10004 		signing = ISC_LIST_HEAD(cleanup);
   10005 	}
   10006 
   10007 	LOCK_ZONE(zone);
   10008 	set_resigntime(zone);
   10009 	if (commit) {
   10010 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   10011 		zone_needdump(zone, DNS_DUMP_DELAY);
   10012 	}
   10013 	UNLOCK_ZONE(zone);
   10014 
   10015 cleanup:
   10016 	if (result != ISC_R_SUCCESS) {
   10017 		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
   10018 			   isc_result_totext(result));
   10019 	}
   10020 
   10021 done:
   10022 	/*
   10023 	 * Pause all dbiterators.
   10024 	 */
   10025 	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
   10026 	     signing = ISC_LIST_NEXT(signing, link))
   10027 	{
   10028 		dns_dbiterator_pause(signing->dbiterator);
   10029 	}
   10030 
   10031 	/*
   10032 	 * Rollback the cleanup list.
   10033 	 */
   10034 	signing = ISC_LIST_HEAD(cleanup);
   10035 	while (signing != NULL) {
   10036 		ISC_LIST_UNLINK(cleanup, signing, link);
   10037 		ISC_LIST_PREPEND(zone->signing, signing, link);
   10038 		dns_dbiterator_first(signing->dbiterator);
   10039 		dns_dbiterator_pause(signing->dbiterator);
   10040 		signing = ISC_LIST_HEAD(cleanup);
   10041 	}
   10042 
   10043 	dns_diff_clear(&_sig_diff);
   10044 	dns_diff_clear(&post_diff);
   10045 
   10046 	for (i = 0; i < nkeys; i++) {
   10047 		dst_key_free(&zone_keys[i]);
   10048 	}
   10049 
   10050 	if (node != NULL) {
   10051 		dns_db_detachnode(db, &node);
   10052 	}
   10053 
   10054 	if (version != NULL) {
   10055 		dns_db_closeversion(db, &version, false);
   10056 		dns_db_detach(&db);
   10057 	} else if (db != NULL) {
   10058 		dns_db_detach(&db);
   10059 	}
   10060 
   10061 	LOCK_ZONE(zone);
   10062 	if (ISC_LIST_HEAD(zone->signing) != NULL) {
   10063 		isc_interval_t interval;
   10064 		if (zone->update_disabled || result != ISC_R_SUCCESS) {
   10065 			isc_interval_set(&interval, 60, 0); /* 1 minute */
   10066 		} else {
   10067 			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
   10068 		}
   10069 		isc_time_nowplusinterval(&zone->signingtime, &interval);
   10070 	} else {
   10071 		isc_time_settoepoch(&zone->signingtime);
   10072 	}
   10073 	UNLOCK_ZONE(zone);
   10074 
   10075 	INSIST(version == NULL);
   10076 }
   10077 
   10078 static isc_result_t
   10079 normalize_key(dns_rdata_t *rr, dns_rdata_t *target, unsigned char *data,
   10080 	      int size) {
   10081 	dns_rdata_dnskey_t dnskey;
   10082 	dns_rdata_keydata_t keydata;
   10083 	isc_buffer_t buf;
   10084 	isc_result_t result;
   10085 
   10086 	dns_rdata_reset(target);
   10087 	isc_buffer_init(&buf, data, size);
   10088 
   10089 	switch (rr->type) {
   10090 	case dns_rdatatype_dnskey:
   10091 		result = dns_rdata_tostruct(rr, &dnskey, NULL);
   10092 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10093 		dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
   10094 		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
   10095 				     &dnskey, &buf);
   10096 		break;
   10097 	case dns_rdatatype_keydata:
   10098 		result = dns_rdata_tostruct(rr, &keydata, NULL);
   10099 		if (result == ISC_R_UNEXPECTEDEND) {
   10100 			return result;
   10101 		}
   10102 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10103 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
   10104 		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
   10105 				     &dnskey, &buf);
   10106 		break;
   10107 	default:
   10108 		UNREACHABLE();
   10109 	}
   10110 	return ISC_R_SUCCESS;
   10111 }
   10112 
   10113 /*
   10114  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
   10115  * a KEYDATA rdataset from the key zone.
   10116  *
   10117  * 'rr' contains either a DNSKEY record, or a KEYDATA record
   10118  *
   10119  * After normalizing keys to the same format (DNSKEY, with revoke bit
   10120  * cleared), return true if a key that matches 'rr' is found in
   10121  * 'rdset', or false if not.
   10122  */
   10123 
   10124 static bool
   10125 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
   10126 	unsigned char data1[4096], data2[4096];
   10127 	dns_rdata_t rdata, rdata1, rdata2;
   10128 	isc_result_t result;
   10129 
   10130 	dns_rdata_init(&rdata);
   10131 	dns_rdata_init(&rdata1);
   10132 	dns_rdata_init(&rdata2);
   10133 
   10134 	result = normalize_key(rr, &rdata1, data1, sizeof(data1));
   10135 	if (result != ISC_R_SUCCESS) {
   10136 		return false;
   10137 	}
   10138 
   10139 	for (result = dns_rdataset_first(rdset); result == ISC_R_SUCCESS;
   10140 	     result = dns_rdataset_next(rdset))
   10141 	{
   10142 		dns_rdata_reset(&rdata);
   10143 		dns_rdataset_current(rdset, &rdata);
   10144 		result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
   10145 		if (result != ISC_R_SUCCESS) {
   10146 			continue;
   10147 		}
   10148 		if (dns_rdata_compare(&rdata1, &rdata2) == 0) {
   10149 			return true;
   10150 		}
   10151 	}
   10152 
   10153 	return false;
   10154 }
   10155 
   10156 /*
   10157  * Calculate the refresh interval for a keydata zone, per
   10158  * RFC5011: MAX(1 hr,
   10159  *		MIN(15 days,
   10160  *		    1/2 * OrigTTL,
   10161  *		    1/2 * RRSigExpirationInterval))
   10162  * or for retries: MAX(1 hr,
   10163  *		       MIN(1 day,
   10164  *			   1/10 * OrigTTL,
   10165  *			   1/10 * RRSigExpirationInterval))
   10166  */
   10167 static isc_stdtime_t
   10168 refresh_time(dns_keyfetch_t *kfetch, bool retry) {
   10169 	isc_result_t result;
   10170 	uint32_t t;
   10171 	dns_rdataset_t *rdset;
   10172 	dns_rdata_t sigrr = DNS_RDATA_INIT;
   10173 	dns_rdata_sig_t sig;
   10174 	isc_stdtime_t now = isc_stdtime_now();
   10175 
   10176 	if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
   10177 		rdset = &kfetch->dnskeysigset;
   10178 	} else {
   10179 		return now + dns_zone_mkey_hour;
   10180 	}
   10181 
   10182 	result = dns_rdataset_first(rdset);
   10183 	if (result != ISC_R_SUCCESS) {
   10184 		return now + dns_zone_mkey_hour;
   10185 	}
   10186 
   10187 	dns_rdataset_current(rdset, &sigrr);
   10188 	result = dns_rdata_tostruct(&sigrr, &sig, NULL);
   10189 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10190 
   10191 	if (!retry) {
   10192 		t = sig.originalttl / 2;
   10193 
   10194 		if (isc_serial_gt(sig.timeexpire, now)) {
   10195 			uint32_t exp = (sig.timeexpire - now) / 2;
   10196 			if (t > exp) {
   10197 				t = exp;
   10198 			}
   10199 		}
   10200 
   10201 		if (t > (15 * dns_zone_mkey_day)) {
   10202 			t = (15 * dns_zone_mkey_day);
   10203 		}
   10204 
   10205 		if (t < dns_zone_mkey_hour) {
   10206 			t = dns_zone_mkey_hour;
   10207 		}
   10208 	} else {
   10209 		t = sig.originalttl / 10;
   10210 
   10211 		if (isc_serial_gt(sig.timeexpire, now)) {
   10212 			uint32_t exp = (sig.timeexpire - now) / 10;
   10213 			if (t > exp) {
   10214 				t = exp;
   10215 			}
   10216 		}
   10217 
   10218 		if (t > dns_zone_mkey_day) {
   10219 			t = dns_zone_mkey_day;
   10220 		}
   10221 
   10222 		if (t < dns_zone_mkey_hour) {
   10223 			t = dns_zone_mkey_hour;
   10224 		}
   10225 	}
   10226 
   10227 	return now + t;
   10228 }
   10229 
   10230 /*
   10231  * This routine is called when no changes are needed in a KEYDATA
   10232  * record except to simply update the refresh timer.  Caller should
   10233  * hold zone lock.
   10234  */
   10235 static isc_result_t
   10236 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) {
   10237 	isc_result_t result;
   10238 	isc_buffer_t keyb;
   10239 	unsigned char key_buf[4096];
   10240 	dns_rdata_t rdata = DNS_RDATA_INIT;
   10241 	dns_rdata_keydata_t keydata;
   10242 	dns_name_t *name;
   10243 	dns_zone_t *zone = kfetch->zone;
   10244 	isc_stdtime_t now = isc_stdtime_now();
   10245 
   10246 	name = dns_fixedname_name(&kfetch->name);
   10247 
   10248 	for (result = dns_rdataset_first(&kfetch->keydataset);
   10249 	     result == ISC_R_SUCCESS;
   10250 	     result = dns_rdataset_next(&kfetch->keydataset))
   10251 	{
   10252 		dns_rdata_reset(&rdata);
   10253 		dns_rdataset_current(&kfetch->keydataset, &rdata);
   10254 
   10255 		/* Delete old version */
   10256 		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL, name,
   10257 				    0, &rdata));
   10258 
   10259 		/* Update refresh timer */
   10260 		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
   10261 		if (result == ISC_R_UNEXPECTEDEND) {
   10262 			continue;
   10263 		}
   10264 		CHECK(result);
   10265 
   10266 		keydata.refresh = refresh_time(kfetch, true);
   10267 		set_refreshkeytimer(zone, &keydata, now, false);
   10268 
   10269 		dns_rdata_reset(&rdata);
   10270 		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   10271 		CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass,
   10272 					   dns_rdatatype_keydata, &keydata,
   10273 					   &keyb));
   10274 
   10275 		/* Insert updated version */
   10276 		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD, name,
   10277 				    0, &rdata));
   10278 	}
   10279 	result = ISC_R_SUCCESS;
   10280 cleanup:
   10281 	return result;
   10282 }
   10283 
   10284 /*
   10285  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
   10286  */
   10287 static bool
   10288 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
   10289 	isc_result_t result;
   10290 	dns_name_t *keyname;
   10291 	isc_mem_t *mctx;
   10292 	dns_rdata_t sigrr = DNS_RDATA_INIT;
   10293 	dns_rdata_t rr = DNS_RDATA_INIT;
   10294 	dns_rdata_rrsig_t sig;
   10295 	dns_rdata_dnskey_t dnskey;
   10296 	dst_key_t *dstkey = NULL;
   10297 	unsigned char key_buf[4096];
   10298 	isc_buffer_t keyb;
   10299 	bool answer = false;
   10300 
   10301 	REQUIRE(kfetch != NULL && keydata != NULL);
   10302 	REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
   10303 
   10304 	keyname = dns_fixedname_name(&kfetch->name);
   10305 	mctx = kfetch->zone->view->mctx;
   10306 
   10307 	/* Generate a key from keydata */
   10308 	isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   10309 	dns_keydata_todnskey(keydata, &dnskey, NULL);
   10310 	dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
   10311 			     &dnskey, &keyb);
   10312 	result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
   10313 	if (result != ISC_R_SUCCESS) {
   10314 		return false;
   10315 	}
   10316 
   10317 	/* See if that key generated any of the signatures */
   10318 	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
   10319 	     result == ISC_R_SUCCESS;
   10320 	     result = dns_rdataset_next(&kfetch->dnskeysigset))
   10321 	{
   10322 		dns_fixedname_t fixed;
   10323 		dns_fixedname_init(&fixed);
   10324 
   10325 		dns_rdata_reset(&sigrr);
   10326 		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
   10327 		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
   10328 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10329 
   10330 		if (dst_key_alg(dstkey) == sig.algorithm &&
   10331 		    dst_key_rid(dstkey) == sig.keyid)
   10332 		{
   10333 			result = dns_dnssec_verify(
   10334 				keyname, &kfetch->dnskeyset, dstkey, false, 0,
   10335 				mctx, &sigrr, dns_fixedname_name(&fixed));
   10336 
   10337 			dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
   10338 				   "Confirm revoked DNSKEY is self-signed: %s",
   10339 				   isc_result_totext(result));
   10340 
   10341 			if (result == ISC_R_SUCCESS) {
   10342 				answer = true;
   10343 				break;
   10344 			}
   10345 		}
   10346 	}
   10347 
   10348 	dst_key_free(&dstkey);
   10349 	return answer;
   10350 }
   10351 
   10352 /*
   10353  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
   10354  * anchors are being managed; scan the keyset, and update the key zone and the
   10355  * local trust anchors according to RFC5011.
   10356  */
   10357 static void
   10358 keyfetch_done(void *arg) {
   10359 	dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
   10360 	isc_result_t result, eresult;
   10361 	dns_keyfetch_t *kfetch = NULL;
   10362 	dns_zone_t *zone = NULL;
   10363 	isc_mem_t *mctx = NULL;
   10364 	dns_keytable_t *secroots = NULL;
   10365 	dns_dbversion_t *ver = NULL;
   10366 	dns_diff_t diff;
   10367 	bool alldone = false;
   10368 	bool commit = false;
   10369 	dns_name_t *keyname = NULL;
   10370 	dns_rdata_t sigrr = DNS_RDATA_INIT;
   10371 	dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
   10372 	dns_rdata_t keydatarr = DNS_RDATA_INIT;
   10373 	dns_rdata_rrsig_t sig;
   10374 	dns_rdata_dnskey_t dnskey;
   10375 	dns_rdata_keydata_t keydata;
   10376 	bool initializing;
   10377 	char namebuf[DNS_NAME_FORMATSIZE];
   10378 	unsigned char key_buf[4096];
   10379 	isc_buffer_t keyb;
   10380 	dst_key_t *dstkey = NULL;
   10381 	isc_stdtime_t now;
   10382 	int pending = 0;
   10383 	bool secure = false, initial = false;
   10384 	bool free_needed;
   10385 	dns_keynode_t *keynode = NULL;
   10386 	dns_rdataset_t *dnskeys = NULL, *dnskeysigs = NULL;
   10387 	dns_rdataset_t *keydataset = NULL, dsset;
   10388 
   10389 	INSIST(resp != NULL);
   10390 
   10391 	kfetch = resp->arg;
   10392 
   10393 	INSIST(kfetch != NULL);
   10394 
   10395 	zone = kfetch->zone;
   10396 	mctx = kfetch->mctx;
   10397 	keyname = dns_fixedname_name(&kfetch->name);
   10398 	dnskeys = &kfetch->dnskeyset;
   10399 	dnskeysigs = &kfetch->dnskeysigset;
   10400 	keydataset = &kfetch->keydataset;
   10401 
   10402 	eresult = resp->result;
   10403 
   10404 	/* Free resources which are not of interest */
   10405 	if (resp->node != NULL) {
   10406 		dns_db_detachnode(resp->db, &resp->node);
   10407 	}
   10408 	if (resp->db != NULL) {
   10409 		dns_db_detach(&resp->db);
   10410 	}
   10411 
   10412 	dns_resolver_destroyfetch(&kfetch->fetch);
   10413 
   10414 	LOCK_ZONE(zone);
   10415 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
   10416 		goto out;
   10417 	}
   10418 
   10419 	now = isc_stdtime_now();
   10420 	dns_name_format(keyname, namebuf, sizeof(namebuf));
   10421 
   10422 	result = dns_view_getsecroots(zone->view, &secroots);
   10423 	INSIST(result == ISC_R_SUCCESS);
   10424 
   10425 	dns_diff_init(mctx, &diff);
   10426 
   10427 	CHECK(dns_db_newversion(kfetch->db, &ver));
   10428 
   10429 	zone->refreshkeycount--;
   10430 	alldone = (zone->refreshkeycount == 0);
   10431 
   10432 	if (alldone) {
   10433 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
   10434 	}
   10435 
   10436 	dnssec_log(zone, ISC_LOG_DEBUG(3),
   10437 		   "Returned from key fetch in keyfetch_done() for '%s': %s",
   10438 		   namebuf, isc_result_totext(eresult));
   10439 
   10440 	/* Fetch failed */
   10441 	if (eresult != ISC_R_SUCCESS || !dns_rdataset_isassociated(dnskeys)) {
   10442 		dnssec_log(zone, ISC_LOG_WARNING,
   10443 			   "Unable to fetch DNSKEY set '%s': %s", namebuf,
   10444 			   isc_result_totext(eresult));
   10445 		CHECK(minimal_update(kfetch, ver, &diff));
   10446 		goto done;
   10447 	}
   10448 
   10449 	/* No RRSIGs found */
   10450 	if (!dns_rdataset_isassociated(dnskeysigs)) {
   10451 		dnssec_log(zone, ISC_LOG_WARNING,
   10452 			   "No DNSKEY RRSIGs found for '%s': %s", namebuf,
   10453 			   isc_result_totext(eresult));
   10454 		CHECK(minimal_update(kfetch, ver, &diff));
   10455 		goto done;
   10456 	}
   10457 
   10458 	/*
   10459 	 * Clear any cached trust level, as we need to run validation
   10460 	 * over again; trusted keys might have changed.
   10461 	 */
   10462 	dnskeys->trust = dnskeysigs->trust = dns_trust_none;
   10463 
   10464 	/* Look up the trust anchor */
   10465 	result = dns_keytable_find(secroots, keyname, &keynode);
   10466 	if (result != ISC_R_SUCCESS) {
   10467 		goto anchors_done;
   10468 	}
   10469 
   10470 	/*
   10471 	 * If the keynode has a DS trust anchor, use it for verification.
   10472 	 */
   10473 	dns_rdataset_init(&dsset);
   10474 	if (dns_keynode_dsset(keynode, &dsset)) {
   10475 		for (result = dns_rdataset_first(dnskeysigs);
   10476 		     result == ISC_R_SUCCESS;
   10477 		     result = dns_rdataset_next(dnskeysigs))
   10478 		{
   10479 			isc_result_t tresult;
   10480 			dns_rdata_t keyrdata = DNS_RDATA_INIT;
   10481 
   10482 			dns_rdata_reset(&sigrr);
   10483 			dns_rdataset_current(dnskeysigs, &sigrr);
   10484 			result = dns_rdata_tostruct(&sigrr, &sig, NULL);
   10485 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10486 
   10487 			for (tresult = dns_rdataset_first(&dsset);
   10488 			     tresult == ISC_R_SUCCESS;
   10489 			     tresult = dns_rdataset_next(&dsset))
   10490 			{
   10491 				dns_rdata_t dsrdata = DNS_RDATA_INIT;
   10492 				dns_rdata_ds_t ds;
   10493 
   10494 				dns_rdata_reset(&dsrdata);
   10495 				dns_rdataset_current(&dsset, &dsrdata);
   10496 				tresult = dns_rdata_tostruct(&dsrdata, &ds,
   10497 							     NULL);
   10498 				RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
   10499 
   10500 				if (ds.key_tag != sig.keyid ||
   10501 				    ds.algorithm != sig.algorithm)
   10502 				{
   10503 					continue;
   10504 				}
   10505 
   10506 				result = dns_dnssec_matchdskey(
   10507 					keyname, &dsrdata, dnskeys, &keyrdata);
   10508 				if (result == ISC_R_SUCCESS) {
   10509 					break;
   10510 				}
   10511 			}
   10512 
   10513 			if (tresult == ISC_R_NOMORE) {
   10514 				continue;
   10515 			}
   10516 
   10517 			result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
   10518 							 mctx, &dstkey);
   10519 			if (result != ISC_R_SUCCESS) {
   10520 				continue;
   10521 			}
   10522 
   10523 			result = dns_dnssec_verify(keyname, dnskeys, dstkey,
   10524 						   false, 0, mctx, &sigrr,
   10525 						   NULL);
   10526 			dst_key_free(&dstkey);
   10527 
   10528 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   10529 				   "Verifying DNSKEY set for zone "
   10530 				   "'%s' using DS %d/%d: %s",
   10531 				   namebuf, sig.keyid, sig.algorithm,
   10532 				   isc_result_totext(result));
   10533 
   10534 			if (result == ISC_R_SUCCESS) {
   10535 				dnskeys->trust = dns_trust_secure;
   10536 				dnskeysigs->trust = dns_trust_secure;
   10537 				initial = dns_keynode_initial(keynode);
   10538 				dns_keynode_trust(keynode);
   10539 				secure = true;
   10540 				break;
   10541 			}
   10542 		}
   10543 		dns_rdataset_disassociate(&dsset);
   10544 	}
   10545 
   10546 anchors_done:
   10547 	if (keynode != NULL) {
   10548 		dns_keynode_detach(&keynode);
   10549 	}
   10550 
   10551 	/*
   10552 	 * If we were not able to verify the answer using the current
   10553 	 * trusted keys then all we can do is look at any revoked keys.
   10554 	 */
   10555 	if (!secure) {
   10556 		dnssec_log(zone, ISC_LOG_INFO,
   10557 			   "DNSKEY set for zone '%s' could not be verified "
   10558 			   "with current keys",
   10559 			   namebuf);
   10560 	}
   10561 
   10562 	/*
   10563 	 * First scan keydataset to find keys that are not in dnskeyset
   10564 	 *   - Missing keys which are not scheduled for removal,
   10565 	 *     log a warning
   10566 	 *   - Missing keys which are scheduled for removal and
   10567 	 *     the remove hold-down timer has completed should
   10568 	 *     be removed from the key zone
   10569 	 *   - Missing keys whose acceptance timers have not yet
   10570 	 *     completed, log a warning and reset the acceptance
   10571 	 *     timer to 30 days in the future
   10572 	 *   - All keys not being removed have their refresh timers
   10573 	 *     updated
   10574 	 */
   10575 	initializing = true;
   10576 	for (result = dns_rdataset_first(keydataset); result == ISC_R_SUCCESS;
   10577 	     result = dns_rdataset_next(keydataset))
   10578 	{
   10579 		dns_keytag_t keytag;
   10580 
   10581 		dns_rdata_reset(&keydatarr);
   10582 		dns_rdataset_current(keydataset, &keydatarr);
   10583 		result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
   10584 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10585 
   10586 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
   10587 		result = compute_tag(keyname, &dnskey, mctx, &keytag);
   10588 		if (result != ISC_R_SUCCESS) {
   10589 			/*
   10590 			 * Skip if we cannot compute the key tag.
   10591 			 * This may happen if the algorithm is unsupported
   10592 			 */
   10593 			dns_zone_log(zone, ISC_LOG_ERROR,
   10594 				     "Cannot compute tag for key in zone %s: "
   10595 				     "%s "
   10596 				     "(skipping)",
   10597 				     namebuf, isc_result_totext(result));
   10598 			continue;
   10599 		}
   10600 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10601 
   10602 		/*
   10603 		 * If any keydata record has a nonzero add holddown, then
   10604 		 * there was a pre-existing trust anchor for this domain;
   10605 		 * that means we are *not* initializing it and shouldn't
   10606 		 * automatically trust all the keys we find at the zone apex.
   10607 		 */
   10608 		initializing = initializing && (keydata.addhd == 0);
   10609 
   10610 		if (!matchkey(dnskeys, &keydatarr)) {
   10611 			bool deletekey = false;
   10612 
   10613 			if (!secure) {
   10614 				if (keydata.removehd != 0 &&
   10615 				    keydata.removehd <= now)
   10616 				{
   10617 					deletekey = true;
   10618 				}
   10619 			} else if (keydata.addhd == 0) {
   10620 				deletekey = true;
   10621 			} else if (keydata.addhd > now) {
   10622 				dnssec_log(zone, ISC_LOG_INFO,
   10623 					   "Pending key %d for zone %s "
   10624 					   "unexpectedly missing from DNSKEY "
   10625 					   "RRset: restarting 30-day "
   10626 					   "acceptance timer",
   10627 					   keytag, namebuf);
   10628 				if (keydata.addhd < now + dns_zone_mkey_month) {
   10629 					keydata.addhd = now +
   10630 							dns_zone_mkey_month;
   10631 				}
   10632 				keydata.refresh = refresh_time(kfetch, false);
   10633 			} else if (keydata.removehd == 0) {
   10634 				dnssec_log(zone, ISC_LOG_INFO,
   10635 					   "Active key %d for zone %s "
   10636 					   "unexpectedly missing from DNSKEY "
   10637 					   "RRset",
   10638 					   keytag, namebuf);
   10639 				keydata.refresh = now + dns_zone_mkey_hour;
   10640 			} else if (keydata.removehd <= now) {
   10641 				deletekey = true;
   10642 				dnssec_log(
   10643 					zone, ISC_LOG_INFO,
   10644 					"Revoked key %d for zone %s no longer "
   10645 					"present in DNSKEY RRset: deleting "
   10646 					"from managed keys database",
   10647 					keytag, namebuf);
   10648 			} else {
   10649 				keydata.refresh = refresh_time(kfetch, false);
   10650 			}
   10651 
   10652 			if (secure || deletekey) {
   10653 				/* Delete old version */
   10654 				CHECK(update_one_rr(kfetch->db, ver, &diff,
   10655 						    DNS_DIFFOP_DEL, keyname, 0,
   10656 						    &keydatarr));
   10657 			}
   10658 
   10659 			if (!secure || deletekey) {
   10660 				continue;
   10661 			}
   10662 
   10663 			dns_rdata_reset(&keydatarr);
   10664 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   10665 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
   10666 					     dns_rdatatype_keydata, &keydata,
   10667 					     &keyb);
   10668 
   10669 			/* Insert updated version */
   10670 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   10671 					    DNS_DIFFOP_ADD, keyname, 0,
   10672 					    &keydatarr));
   10673 
   10674 			set_refreshkeytimer(zone, &keydata, now, false);
   10675 		}
   10676 	}
   10677 
   10678 	/*
   10679 	 * Next scan dnskeyset:
   10680 	 *   - If new keys are found (i.e., lacking a match in keydataset)
   10681 	 *     add them to the key zone and set the acceptance timer
   10682 	 *     to 30 days in the future (or to immediately if we've
   10683 	 *     determined that we're initializing the zone for the
   10684 	 *     first time)
   10685 	 *   - Previously-known keys that have been revoked
   10686 	 *     must be scheduled for removal from the key zone (or,
   10687 	 *     if they hadn't been accepted as trust anchors yet
   10688 	 *     anyway, removed at once)
   10689 	 *   - Previously-known unrevoked keys whose acceptance timers
   10690 	 *     have completed are promoted to trust anchors
   10691 	 *   - All keys not being removed have their refresh
   10692 	 *     timers updated
   10693 	 */
   10694 	for (result = dns_rdataset_first(dnskeys); result == ISC_R_SUCCESS;
   10695 	     result = dns_rdataset_next(dnskeys))
   10696 	{
   10697 		bool revoked = false;
   10698 		bool newkey = false;
   10699 		bool updatekey = false;
   10700 		bool deletekey = false;
   10701 		bool trustkey = false;
   10702 		dns_keytag_t keytag;
   10703 
   10704 		dns_rdata_reset(&dnskeyrr);
   10705 		dns_rdataset_current(dnskeys, &dnskeyrr);
   10706 		result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
   10707 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10708 
   10709 		/* Skip ZSK's */
   10710 		if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
   10711 			continue;
   10712 		}
   10713 
   10714 		result = compute_tag(keyname, &dnskey, mctx, &keytag);
   10715 		if (result != ISC_R_SUCCESS) {
   10716 			/*
   10717 			 * Skip if we cannot compute the key tag.
   10718 			 * This may happen if the algorithm is unsupported
   10719 			 */
   10720 			dns_zone_log(zone, ISC_LOG_ERROR,
   10721 				     "Cannot compute tag for key in zone %s: "
   10722 				     "%s "
   10723 				     "(skipping)",
   10724 				     namebuf, isc_result_totext(result));
   10725 			continue;
   10726 		}
   10727 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10728 
   10729 		revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
   10730 
   10731 		if (matchkey(keydataset, &dnskeyrr)) {
   10732 			dns_rdata_reset(&keydatarr);
   10733 			dns_rdataset_current(keydataset, &keydatarr);
   10734 			result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
   10735 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10736 
   10737 			if (revoked && revocable(kfetch, &keydata)) {
   10738 				if (keydata.addhd > now) {
   10739 					/*
   10740 					 * Key wasn't trusted yet, and now
   10741 					 * it's been revoked?  Just remove it
   10742 					 */
   10743 					deletekey = true;
   10744 					dnssec_log(zone, ISC_LOG_INFO,
   10745 						   "Pending key %d for "
   10746 						   "zone %s is now revoked: "
   10747 						   "deleting from the "
   10748 						   "managed keys database",
   10749 						   keytag, namebuf);
   10750 				} else if (keydata.removehd == 0) {
   10751 					/*
   10752 					 * Remove key from secroots.
   10753 					 */
   10754 					dns_view_untrust(zone->view, keyname,
   10755 							 &dnskey);
   10756 
   10757 					/* If initializing, delete now */
   10758 					if (keydata.addhd == 0) {
   10759 						deletekey = true;
   10760 					} else {
   10761 						keydata.removehd =
   10762 							now +
   10763 							dns_zone_mkey_month;
   10764 						keydata.flags |=
   10765 							DNS_KEYFLAG_REVOKE;
   10766 					}
   10767 
   10768 					dnssec_log(zone, ISC_LOG_INFO,
   10769 						   "Trusted key %d for "
   10770 						   "zone %s is now revoked",
   10771 						   keytag, namebuf);
   10772 				} else if (keydata.removehd < now) {
   10773 					/* Scheduled for removal */
   10774 					deletekey = true;
   10775 
   10776 					dnssec_log(zone, ISC_LOG_INFO,
   10777 						   "Revoked key %d for "
   10778 						   "zone %s removal timer "
   10779 						   "complete: deleting from "
   10780 						   "the managed keys database",
   10781 						   keytag, namebuf);
   10782 				}
   10783 			} else if (revoked && keydata.removehd == 0) {
   10784 				dnssec_log(zone, ISC_LOG_WARNING,
   10785 					   "Active key %d for zone "
   10786 					   "%s is revoked but "
   10787 					   "did not self-sign; "
   10788 					   "ignoring",
   10789 					   keytag, namebuf);
   10790 				continue;
   10791 			} else if (secure) {
   10792 				if (keydata.removehd != 0) {
   10793 					/*
   10794 					 * Key isn't revoked--but it
   10795 					 * seems it used to be.
   10796 					 * Remove it now and add it
   10797 					 * back as if it were a fresh key,
   10798 					 * with a 30-day acceptance timer.
   10799 					 */
   10800 					deletekey = true;
   10801 					newkey = true;
   10802 					keydata.removehd = 0;
   10803 					keydata.addhd = now +
   10804 							dns_zone_mkey_month;
   10805 
   10806 					dnssec_log(zone, ISC_LOG_INFO,
   10807 						   "Revoked key %d for "
   10808 						   "zone %s has returned: "
   10809 						   "starting 30-day "
   10810 						   "acceptance timer",
   10811 						   keytag, namebuf);
   10812 				} else if (keydata.addhd > now) {
   10813 					pending++;
   10814 				} else if (keydata.addhd == 0) {
   10815 					keydata.addhd = now;
   10816 				}
   10817 
   10818 				if (keydata.addhd <= now) {
   10819 					trustkey = true;
   10820 					dnssec_log(zone, ISC_LOG_INFO,
   10821 						   "Key %d for zone %s "
   10822 						   "is now trusted (%s)",
   10823 						   keytag, namebuf,
   10824 						   initial ? "initializing key "
   10825 							     "verified"
   10826 							   : "acceptance timer "
   10827 							     "complete");
   10828 				}
   10829 			} else if (keydata.addhd > now) {
   10830 				/*
   10831 				 * Not secure, and key is pending:
   10832 				 * reset the acceptance timer
   10833 				 */
   10834 				pending++;
   10835 				keydata.addhd = now + dns_zone_mkey_month;
   10836 				dnssec_log(zone, ISC_LOG_INFO,
   10837 					   "Pending key %d "
   10838 					   "for zone %s was "
   10839 					   "not validated: restarting "
   10840 					   "30-day acceptance timer",
   10841 					   keytag, namebuf);
   10842 			}
   10843 
   10844 			if (!deletekey && !newkey) {
   10845 				updatekey = true;
   10846 			}
   10847 		} else if (secure) {
   10848 			/*
   10849 			 * Key wasn't in the key zone but it's
   10850 			 * revoked now anyway, so just skip it
   10851 			 */
   10852 			if (revoked) {
   10853 				continue;
   10854 			}
   10855 
   10856 			/* Key wasn't in the key zone: add it */
   10857 			newkey = true;
   10858 
   10859 			if (initializing) {
   10860 				dnssec_log(zone, ISC_LOG_WARNING,
   10861 					   "Initializing automatic trust "
   10862 					   "anchor management for zone '%s'; "
   10863 					   "DNSKEY ID %d is now trusted, "
   10864 					   "waiving the normal 30-day "
   10865 					   "waiting period.",
   10866 					   namebuf, keytag);
   10867 				trustkey = true;
   10868 			} else {
   10869 				dnssec_log(zone, ISC_LOG_INFO,
   10870 					   "New key %d observed "
   10871 					   "for zone '%s': "
   10872 					   "starting 30-day "
   10873 					   "acceptance timer",
   10874 					   keytag, namebuf);
   10875 			}
   10876 		} else {
   10877 			/*
   10878 			 * No previously known key, and the key is not
   10879 			 * secure, so skip it.
   10880 			 */
   10881 			continue;
   10882 		}
   10883 
   10884 		/* Delete old version */
   10885 		if (deletekey || !newkey) {
   10886 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   10887 					    DNS_DIFFOP_DEL, keyname, 0,
   10888 					    &keydatarr));
   10889 		}
   10890 
   10891 		if (updatekey) {
   10892 			/* Set refresh timer */
   10893 			keydata.refresh = refresh_time(kfetch, false);
   10894 			dns_rdata_reset(&keydatarr);
   10895 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   10896 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
   10897 					     dns_rdatatype_keydata, &keydata,
   10898 					     &keyb);
   10899 
   10900 			/* Insert updated version */
   10901 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   10902 					    DNS_DIFFOP_ADD, keyname, 0,
   10903 					    &keydatarr));
   10904 		} else if (newkey) {
   10905 			/* Convert DNSKEY to KEYDATA */
   10906 			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
   10907 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10908 			dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
   10909 					       NULL);
   10910 			keydata.addhd = initializing
   10911 						? now
   10912 						: now + dns_zone_mkey_month;
   10913 			keydata.refresh = refresh_time(kfetch, false);
   10914 			dns_rdata_reset(&keydatarr);
   10915 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   10916 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
   10917 					     dns_rdatatype_keydata, &keydata,
   10918 					     &keyb);
   10919 
   10920 			/* Insert into key zone */
   10921 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   10922 					    DNS_DIFFOP_ADD, keyname, 0,
   10923 					    &keydatarr));
   10924 		}
   10925 
   10926 		if (trustkey) {
   10927 			/* Trust this key. */
   10928 			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
   10929 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10930 			trust_key(zone, keyname, &dnskey, false);
   10931 		}
   10932 
   10933 		if (secure && !deletekey) {
   10934 			INSIST(newkey || updatekey);
   10935 			set_refreshkeytimer(zone, &keydata, now, false);
   10936 		}
   10937 	}
   10938 
   10939 	/*
   10940 	 * RFC5011 says, "A trust point that has all of its trust anchors
   10941 	 * revoked is considered deleted and is treated as if the trust
   10942 	 * point was never configured."  But if someone revoked their
   10943 	 * active key before the standby was trusted, that would mean the
   10944 	 * zone would suddenly be nonsecured.  We avoid this by checking to
   10945 	 * see if there's pending keydata.  If so, we put a null key in
   10946 	 * the security roots; then all queries to the zone will fail.
   10947 	 */
   10948 	if (pending != 0) {
   10949 		fail_secure(zone, keyname);
   10950 	}
   10951 
   10952 done:
   10953 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   10954 		/* Write changes to journal file. */
   10955 		CHECK(update_soa_serial(zone, kfetch->db, ver, &diff, mctx,
   10956 					zone->updatemethod));
   10957 		CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
   10958 		commit = true;
   10959 
   10960 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   10961 		zone_needdump(zone, 30);
   10962 	} else if (result == ISC_R_NOMORE) {
   10963 		/*
   10964 		 * If "updatekey" was true for all keys found in the DNSKEY
   10965 		 * response and the previous update of those keys happened
   10966 		 * during the same second (only possible if a key refresh was
   10967 		 * externally triggered), it may happen that all relevant
   10968 		 * update_one_rr() calls will return ISC_R_SUCCESS, but
   10969 		 * diff.tuples will remain empty.  Reset result to
   10970 		 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
   10971 		 */
   10972 		result = ISC_R_SUCCESS;
   10973 	}
   10974 
   10975 cleanup:
   10976 	if (result != ISC_R_SUCCESS) {
   10977 		dnssec_log(zone, ISC_LOG_ERROR,
   10978 			   "error during managed-keys processing (%s): "
   10979 			   "DNSSEC validation may be at risk",
   10980 			   isc_result_totext(result));
   10981 	}
   10982 	dns_diff_clear(&diff);
   10983 	if (ver != NULL) {
   10984 		dns_db_closeversion(kfetch->db, &ver, commit);
   10985 	}
   10986 
   10987 out:
   10988 	dns_db_detach(&kfetch->db);
   10989 
   10990 	isc_refcount_decrement(&zone->irefs);
   10991 
   10992 	if (dns_rdataset_isassociated(keydataset)) {
   10993 		dns_rdataset_disassociate(keydataset);
   10994 	}
   10995 	if (dns_rdataset_isassociated(dnskeys)) {
   10996 		dns_rdataset_disassociate(dnskeys);
   10997 	}
   10998 	if (dns_rdataset_isassociated(dnskeysigs)) {
   10999 		dns_rdataset_disassociate(dnskeysigs);
   11000 	}
   11001 
   11002 	dns_resolver_freefresp(&resp);
   11003 	dns_name_free(keyname, mctx);
   11004 	isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(dns_keyfetch_t));
   11005 
   11006 	if (secroots != NULL) {
   11007 		dns_keytable_detach(&secroots);
   11008 	}
   11009 
   11010 	free_needed = exit_check(zone);
   11011 	UNLOCK_ZONE(zone);
   11012 
   11013 	if (free_needed) {
   11014 		zone_free(zone);
   11015 	}
   11016 
   11017 	INSIST(ver == NULL);
   11018 }
   11019 
   11020 static void
   11021 retry_keyfetch(dns_keyfetch_t *kfetch, dns_name_t *kname) {
   11022 	isc_time_t timenow, timethen;
   11023 	dns_zone_t *zone = kfetch->zone;
   11024 	bool free_needed;
   11025 	char namebuf[DNS_NAME_FORMATSIZE];
   11026 
   11027 	dns_name_format(kname, namebuf, sizeof(namebuf));
   11028 	dnssec_log(zone, ISC_LOG_WARNING,
   11029 		   "Failed to create fetch for %s DNSKEY update", namebuf);
   11030 
   11031 	/*
   11032 	 * Error during a key fetch; cancel and retry in an hour.
   11033 	 */
   11034 	LOCK_ZONE(zone);
   11035 	zone->refreshkeycount--;
   11036 	isc_refcount_decrement(&zone->irefs);
   11037 	dns_db_detach(&kfetch->db);
   11038 	dns_rdataset_disassociate(&kfetch->keydataset);
   11039 	dns_name_free(kname, zone->mctx);
   11040 	isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(*kfetch));
   11041 
   11042 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   11043 		/* Don't really retry if we are exiting */
   11044 		char timebuf[80];
   11045 
   11046 		timenow = isc_time_now();
   11047 		DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
   11048 		zone->refreshkeytime = timethen;
   11049 		zone_settimer(zone, &timenow);
   11050 
   11051 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   11052 		dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
   11053 			   timebuf);
   11054 	}
   11055 
   11056 	free_needed = exit_check(zone);
   11057 	UNLOCK_ZONE(zone);
   11058 
   11059 	if (free_needed) {
   11060 		zone_free(zone);
   11061 	}
   11062 }
   11063 
   11064 static void
   11065 do_keyfetch(void *arg) {
   11066 	isc_result_t result;
   11067 	dns_keyfetch_t *kfetch = (dns_keyfetch_t *)arg;
   11068 	dns_name_t *kname = dns_fixedname_name(&kfetch->name);
   11069 	dns_resolver_t *resolver = NULL;
   11070 	dns_zone_t *zone = kfetch->zone;
   11071 	unsigned int options = DNS_FETCHOPT_NOVALIDATE | DNS_FETCHOPT_UNSHARED |
   11072 			       DNS_FETCHOPT_NOCACHED;
   11073 
   11074 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   11075 		goto retry;
   11076 	}
   11077 
   11078 	result = dns_view_getresolver(zone->view, &resolver);
   11079 	if (result != ISC_R_SUCCESS) {
   11080 		goto retry;
   11081 	}
   11082 
   11083 	/*
   11084 	 * Use of DNS_FETCHOPT_NOCACHED is essential here.  If it is not
   11085 	 * set and the cache still holds a non-expired, validated version
   11086 	 * of the RRset being queried for by the time the response is
   11087 	 * received, the cached RRset will be passed to keyfetch_done()
   11088 	 * instead of the one received in the response as the latter will
   11089 	 * have a lower trust level due to not being validated until
   11090 	 * keyfetch_done() is called.
   11091 	 */
   11092 	result = dns_resolver_createfetch(
   11093 		resolver, kname, dns_rdatatype_dnskey, NULL, NULL, NULL, NULL,
   11094 		0, options, 0, NULL, NULL, NULL, zone->loop, keyfetch_done,
   11095 		kfetch, NULL, &kfetch->dnskeyset, &kfetch->dnskeysigset,
   11096 		&kfetch->fetch);
   11097 
   11098 	dns_resolver_detach(&resolver);
   11099 	if (result == ISC_R_SUCCESS) {
   11100 		return;
   11101 	}
   11102 retry:
   11103 	retry_keyfetch(kfetch, kname);
   11104 }
   11105 
   11106 /*
   11107  * Refresh the data in the key zone.  Initiate a fetch to look up
   11108  * DNSKEY records at the trust anchor name.
   11109  */
   11110 static void
   11111 zone_refreshkeys(dns_zone_t *zone) {
   11112 	isc_result_t result;
   11113 	dns_rriterator_t rrit;
   11114 	dns_db_t *db = NULL;
   11115 	dns_dbversion_t *ver = NULL;
   11116 	dns_diff_t diff;
   11117 	dns_rdata_t rdata = DNS_RDATA_INIT;
   11118 	dns_rdata_keydata_t kd;
   11119 	isc_stdtime_t now = isc_stdtime_now();
   11120 	bool commit = false;
   11121 	bool fetching = false;
   11122 	bool timerset = false;
   11123 
   11124 	ENTER;
   11125 	REQUIRE(zone->db != NULL);
   11126 
   11127 	LOCK_ZONE(zone);
   11128 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   11129 		isc_time_settoepoch(&zone->refreshkeytime);
   11130 		UNLOCK_ZONE(zone);
   11131 		return;
   11132 	}
   11133 
   11134 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   11135 	dns_db_attach(zone->db, &db);
   11136 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   11137 
   11138 	dns_diff_init(zone->mctx, &diff);
   11139 
   11140 	CHECK(dns_db_newversion(db, &ver));
   11141 
   11142 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
   11143 
   11144 	dns_rriterator_init(&rrit, db, ver, 0);
   11145 	for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
   11146 	     result = dns_rriterator_nextrrset(&rrit))
   11147 	{
   11148 		isc_stdtime_t timer = 0xffffffff;
   11149 		dns_name_t *name = NULL, *kname = NULL;
   11150 		dns_rdataset_t *kdset = NULL;
   11151 		uint32_t ttl;
   11152 
   11153 		dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
   11154 		if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
   11155 		    !dns_rdataset_isassociated(kdset))
   11156 		{
   11157 			continue;
   11158 		}
   11159 
   11160 		/*
   11161 		 * Scan the stored keys looking for ones that need
   11162 		 * removal or refreshing
   11163 		 */
   11164 		for (result = dns_rdataset_first(kdset);
   11165 		     result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset))
   11166 		{
   11167 			dns_rdata_reset(&rdata);
   11168 			dns_rdataset_current(kdset, &rdata);
   11169 			result = dns_rdata_tostruct(&rdata, &kd, NULL);
   11170 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   11171 
   11172 			/* Removal timer expired? */
   11173 			if (kd.removehd != 0 && kd.removehd < now) {
   11174 				dns_rriterator_pause(&rrit);
   11175 				CHECK(update_one_rr(db, ver, &diff,
   11176 						    DNS_DIFFOP_DEL, name, ttl,
   11177 						    &rdata));
   11178 				continue;
   11179 			}
   11180 
   11181 			/* Acceptance timer expired? */
   11182 			if (kd.addhd <= now) {
   11183 				timer = kd.addhd;
   11184 			}
   11185 
   11186 			/* Or do we just need to refresh the keyset? */
   11187 			if (timer > kd.refresh) {
   11188 				timer = kd.refresh;
   11189 			}
   11190 
   11191 			dns_rriterator_pause(&rrit);
   11192 			set_refreshkeytimer(zone, &kd, now, false);
   11193 			timerset = true;
   11194 		}
   11195 
   11196 		if (timer > now) {
   11197 			continue;
   11198 		}
   11199 
   11200 		dns_rriterator_pause(&rrit);
   11201 
   11202 #ifdef ENABLE_AFL
   11203 		if (!dns_fuzzing_resolver) {
   11204 #endif /* ifdef ENABLE_AFL */
   11205 			dns_keyfetch_t *kfetch = NULL;
   11206 
   11207 			kfetch = isc_mem_get(zone->mctx,
   11208 					     sizeof(dns_keyfetch_t));
   11209 			*kfetch = (dns_keyfetch_t){ .zone = zone };
   11210 			isc_mem_attach(zone->mctx, &kfetch->mctx);
   11211 
   11212 			zone->refreshkeycount++;
   11213 			isc_refcount_increment0(&zone->irefs);
   11214 			kname = dns_fixedname_initname(&kfetch->name);
   11215 			dns_name_dup(name, zone->mctx, kname);
   11216 			dns_rdataset_init(&kfetch->dnskeyset);
   11217 			dns_rdataset_init(&kfetch->dnskeysigset);
   11218 			dns_rdataset_init(&kfetch->keydataset);
   11219 			dns_rdataset_clone(kdset, &kfetch->keydataset);
   11220 			dns_db_attach(db, &kfetch->db);
   11221 
   11222 			if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   11223 				char namebuf[DNS_NAME_FORMATSIZE];
   11224 				dns_name_format(kname, namebuf,
   11225 						sizeof(namebuf));
   11226 				dnssec_log(zone, ISC_LOG_DEBUG(3),
   11227 					   "Creating key fetch in "
   11228 					   "zone_refreshkeys() for '%s'",
   11229 					   namebuf);
   11230 			}
   11231 
   11232 			isc_async_run(zone->loop, do_keyfetch, kfetch);
   11233 			fetching = true;
   11234 #ifdef ENABLE_AFL
   11235 		}
   11236 #endif /* ifdef ENABLE_AFL */
   11237 	}
   11238 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   11239 		CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
   11240 					zone->updatemethod));
   11241 		CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
   11242 		commit = true;
   11243 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   11244 		zone_needdump(zone, 30);
   11245 	}
   11246 
   11247 cleanup:
   11248 	if (!timerset) {
   11249 		isc_time_settoepoch(&zone->refreshkeytime);
   11250 	}
   11251 
   11252 	if (!fetching) {
   11253 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
   11254 	}
   11255 
   11256 	dns_diff_clear(&diff);
   11257 	if (ver != NULL) {
   11258 		dns_rriterator_destroy(&rrit);
   11259 		dns_db_closeversion(db, &ver, commit);
   11260 	}
   11261 	dns_db_detach(&db);
   11262 
   11263 	UNLOCK_ZONE(zone);
   11264 
   11265 	INSIST(ver == NULL);
   11266 }
   11267 
   11268 static void
   11269 zone_maintenance(dns_zone_t *zone) {
   11270 	isc_time_t now;
   11271 	isc_result_t result;
   11272 	bool load_pending, exiting, dumping, viewok = false, notify;
   11273 	bool refreshkeys, sign, resign, rekey, chain, warn_expire;
   11274 
   11275 	REQUIRE(DNS_ZONE_VALID(zone));
   11276 	ENTER;
   11277 
   11278 	/*
   11279 	 * Are we pending load/reload, exiting, or unconfigured
   11280 	 * (e.g. because of a syntax failure in the config file)?
   11281 	 * If so, don't attempt maintenance.
   11282 	 */
   11283 	LOCK_ZONE(zone);
   11284 	load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
   11285 	exiting = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING);
   11286 	if (!load_pending && !exiting && zone->view != NULL) {
   11287 		dns_adb_t *adb = NULL;
   11288 		dns_view_getadb(zone->view, &adb);
   11289 		if (adb != NULL) {
   11290 			dns_adb_detach(&adb);
   11291 			viewok = true;
   11292 		}
   11293 	}
   11294 	UNLOCK_ZONE(zone);
   11295 
   11296 	if (load_pending || exiting || !viewok) {
   11297 		return;
   11298 	}
   11299 
   11300 	now = isc_time_now();
   11301 
   11302 	/*
   11303 	 * Expire check.
   11304 	 */
   11305 	switch (zone->type) {
   11306 	case dns_zone_redirect:
   11307 		if (dns_remote_addresses(&zone->primaries) == NULL) {
   11308 			break;
   11309 		}
   11310 		FALLTHROUGH;
   11311 	case dns_zone_secondary:
   11312 	case dns_zone_mirror:
   11313 	case dns_zone_stub:
   11314 		LOCK_ZONE(zone);
   11315 		if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
   11316 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   11317 		{
   11318 			zone_expire(zone);
   11319 			zone->refreshtime = now;
   11320 		}
   11321 		UNLOCK_ZONE(zone);
   11322 		break;
   11323 	default:
   11324 		break;
   11325 	}
   11326 
   11327 	/*
   11328 	 * Up to date check.
   11329 	 */
   11330 	switch (zone->type) {
   11331 	case dns_zone_redirect:
   11332 		if (dns_remote_addresses(&zone->primaries) == NULL) {
   11333 			break;
   11334 		}
   11335 		FALLTHROUGH;
   11336 	case dns_zone_secondary:
   11337 	case dns_zone_mirror:
   11338 	case dns_zone_stub:
   11339 		LOCK_ZONE(zone);
   11340 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
   11341 		    isc_time_compare(&now, &zone->refreshtime) >= 0)
   11342 		{
   11343 			zone_refresh(zone);
   11344 		}
   11345 		UNLOCK_ZONE(zone);
   11346 		break;
   11347 	default:
   11348 		break;
   11349 	}
   11350 
   11351 	/*
   11352 	 * Secondaries send notifies before backing up to disk,
   11353 	 * primaries after.
   11354 	 */
   11355 	LOCK_ZONE(zone);
   11356 	if (zone->notifydefer != 0 &&
   11357 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYNODEFER) &&
   11358 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED))
   11359 	{
   11360 		if (isc_time_compare(&now, &zone->notifytime) > 0) {
   11361 			zone->notifytime = now;
   11362 		}
   11363 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED);
   11364 		DNS_ZONE_TIME_ADD(&zone->notifytime, zone->notifydefer,
   11365 				  &zone->notifytime);
   11366 	}
   11367 	notify = (zone->type == dns_zone_secondary ||
   11368 		  zone->type == dns_zone_mirror) &&
   11369 		 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   11370 		  DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
   11371 		 isc_time_compare(&now, &zone->notifytime) >= 0;
   11372 	UNLOCK_ZONE(zone);
   11373 
   11374 	if (notify) {
   11375 		zone_notify(zone, &now);
   11376 	}
   11377 
   11378 	/*
   11379 	 * Do we need to consolidate the backing store?
   11380 	 */
   11381 	switch (zone->type) {
   11382 	case dns_zone_primary:
   11383 	case dns_zone_secondary:
   11384 	case dns_zone_mirror:
   11385 	case dns_zone_key:
   11386 	case dns_zone_redirect:
   11387 	case dns_zone_stub:
   11388 		LOCK_ZONE(zone);
   11389 		if (zone->masterfile != NULL &&
   11390 		    isc_time_compare(&now, &zone->dumptime) >= 0 &&
   11391 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   11392 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
   11393 		{
   11394 			dumping = was_dumping(zone);
   11395 		} else {
   11396 			dumping = true;
   11397 		}
   11398 		UNLOCK_ZONE(zone);
   11399 		if (!dumping) {
   11400 			result = zone_dump(zone, true); /* loop locked */
   11401 			if (result != ISC_R_SUCCESS) {
   11402 				dns_zone_log(zone, ISC_LOG_WARNING,
   11403 					     "dump failed: %s",
   11404 					     isc_result_totext(result));
   11405 			}
   11406 		}
   11407 		break;
   11408 	default:
   11409 		break;
   11410 	}
   11411 
   11412 	/*
   11413 	 * Primary/redirect zones send notifies now, if needed
   11414 	 */
   11415 	switch (zone->type) {
   11416 	case dns_zone_primary:
   11417 	case dns_zone_redirect:
   11418 		LOCK_ZONE(zone);
   11419 		notify = (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   11420 			  DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
   11421 			 isc_time_compare(&now, &zone->notifytime) >= 0;
   11422 		UNLOCK_ZONE(zone);
   11423 		if (notify) {
   11424 			zone_notify(zone, &now);
   11425 		}
   11426 	default:
   11427 		break;
   11428 	}
   11429 
   11430 	/*
   11431 	 * Do we need to refresh keys?
   11432 	 */
   11433 	switch (zone->type) {
   11434 	case dns_zone_key:
   11435 		LOCK_ZONE(zone);
   11436 		refreshkeys = isc_time_compare(&now, &zone->refreshkeytime) >=
   11437 				      0 &&
   11438 			      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   11439 			      !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING);
   11440 		UNLOCK_ZONE(zone);
   11441 		if (refreshkeys) {
   11442 			zone_refreshkeys(zone);
   11443 		}
   11444 		break;
   11445 	case dns_zone_primary:
   11446 		LOCK_ZONE(zone);
   11447 		if (zone->rss != NULL) {
   11448 			isc_time_settoepoch(&zone->refreshkeytime);
   11449 			UNLOCK_ZONE(zone);
   11450 			break;
   11451 		}
   11452 		rekey = (!isc_time_isepoch(&zone->refreshkeytime) &&
   11453 			 isc_time_compare(&now, &zone->refreshkeytime) >= 0);
   11454 		UNLOCK_ZONE(zone);
   11455 		if (rekey) {
   11456 			zone_rekey(zone);
   11457 		}
   11458 	default:
   11459 		break;
   11460 	}
   11461 
   11462 	switch (zone->type) {
   11463 	case dns_zone_primary:
   11464 	case dns_zone_redirect:
   11465 	case dns_zone_secondary:
   11466 		/*
   11467 		 * Do we need to sign/resign some RRsets?
   11468 		 */
   11469 		LOCK_ZONE(zone);
   11470 		if (zone->rss != NULL) {
   11471 			isc_time_settoepoch(&zone->signingtime);
   11472 			isc_time_settoepoch(&zone->resigntime);
   11473 			isc_time_settoepoch(&zone->nsec3chaintime);
   11474 			isc_time_settoepoch(&zone->keywarntime);
   11475 			UNLOCK_ZONE(zone);
   11476 			break;
   11477 		}
   11478 		sign = !isc_time_isepoch(&zone->signingtime) &&
   11479 		       isc_time_compare(&now, &zone->signingtime) >= 0;
   11480 		resign = !isc_time_isepoch(&zone->resigntime) &&
   11481 			 isc_time_compare(&now, &zone->resigntime) >= 0;
   11482 		chain = !isc_time_isepoch(&zone->nsec3chaintime) &&
   11483 			isc_time_compare(&now, &zone->nsec3chaintime) >= 0;
   11484 		warn_expire = !isc_time_isepoch(&zone->keywarntime) &&
   11485 			      isc_time_compare(&now, &zone->keywarntime) >= 0;
   11486 		UNLOCK_ZONE(zone);
   11487 
   11488 		if (sign) {
   11489 			zone_sign(zone);
   11490 		} else if (resign) {
   11491 			zone_resigninc(zone);
   11492 		} else if (chain) {
   11493 			zone_nsec3chain(zone);
   11494 		}
   11495 
   11496 		/*
   11497 		 * Do we need to issue a key expiry warning?
   11498 		 */
   11499 		if (warn_expire) {
   11500 			set_key_expiry_warning(zone, zone->key_expiry,
   11501 					       isc_time_seconds(&now));
   11502 		}
   11503 		break;
   11504 
   11505 	default:
   11506 		break;
   11507 	}
   11508 	LOCK_ZONE(zone);
   11509 	zone_settimer(zone, &now);
   11510 	UNLOCK_ZONE(zone);
   11511 }
   11512 
   11513 void
   11514 dns_zone_markdirty(dns_zone_t *zone) {
   11515 	uint32_t serial;
   11516 	isc_result_t result = ISC_R_SUCCESS;
   11517 	dns_zone_t *secure = NULL;
   11518 
   11519 	/*
   11520 	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
   11521 	 * could result in a deadlock due to a LOR so we will spin if we
   11522 	 * can't obtain the both locks.
   11523 	 */
   11524 again:
   11525 	LOCK_ZONE(zone);
   11526 	if (zone->type == dns_zone_primary) {
   11527 		if (inline_raw(zone)) {
   11528 			unsigned int soacount;
   11529 			secure = zone->secure;
   11530 			INSIST(secure != zone);
   11531 			TRYLOCK_ZONE(result, secure);
   11532 			if (result != ISC_R_SUCCESS) {
   11533 				UNLOCK_ZONE(zone);
   11534 				secure = NULL;
   11535 				isc_thread_yield();
   11536 				goto again;
   11537 			}
   11538 
   11539 			ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   11540 			if (zone->db != NULL) {
   11541 				result = zone_get_from_db(
   11542 					zone, zone->db, NULL, &soacount, NULL,
   11543 					&serial, NULL, NULL, NULL, NULL, NULL);
   11544 			} else {
   11545 				result = DNS_R_NOTLOADED;
   11546 			}
   11547 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   11548 			if (result == ISC_R_SUCCESS && soacount > 0U) {
   11549 				zone_send_secureserial(zone, serial);
   11550 			}
   11551 		}
   11552 
   11553 		/* XXXMPA make separate call back */
   11554 		if (result == ISC_R_SUCCESS) {
   11555 			set_resigntime(zone);
   11556 			if (zone->loop != NULL) {
   11557 				isc_time_t now;
   11558 				now = isc_time_now();
   11559 				zone_settimer(zone, &now);
   11560 			}
   11561 		}
   11562 	}
   11563 	if (secure != NULL) {
   11564 		UNLOCK_ZONE(secure);
   11565 	}
   11566 	zone_needdump(zone, DNS_DUMP_DELAY);
   11567 	UNLOCK_ZONE(zone);
   11568 }
   11569 
   11570 void
   11571 dns_zone_expire(dns_zone_t *zone) {
   11572 	REQUIRE(DNS_ZONE_VALID(zone));
   11573 
   11574 	LOCK_ZONE(zone);
   11575 	zone_expire(zone);
   11576 	UNLOCK_ZONE(zone);
   11577 }
   11578 
   11579 static void
   11580 zone_expire(dns_zone_t *zone) {
   11581 	dns_db_t *db = NULL;
   11582 
   11583 	/*
   11584 	 * 'zone' locked by caller.
   11585 	 */
   11586 
   11587 	REQUIRE(LOCKED_ZONE(zone));
   11588 
   11589 	dns_zone_log(zone, ISC_LOG_WARNING, "expired");
   11590 
   11591 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
   11592 	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
   11593 	zone->retry = DNS_ZONE_DEFAULTRETRY;
   11594 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   11595 
   11596 	/*
   11597 	 * An RPZ zone has expired; before unloading it, we must
   11598 	 * first remove it from the RPZ summary database. The
   11599 	 * easiest way to do this is "update" it with an empty
   11600 	 * database so that the update callback synchronizes
   11601 	 * the diff automatically.
   11602 	 */
   11603 	if (zone->rpzs != NULL && zone->rpz_num != DNS_RPZ_INVALID_NUM) {
   11604 		isc_result_t result;
   11605 		dns_rpz_zone_t *rpz = zone->rpzs->zones[zone->rpz_num];
   11606 
   11607 		CHECK(dns_db_create(zone->mctx, ZONEDB_DEFAULT, &zone->origin,
   11608 				    dns_dbtype_zone, zone->rdclass, 0, NULL,
   11609 				    &db));
   11610 		CHECK(dns_rpz_dbupdate_callback(db, rpz));
   11611 		dns_zone_log(zone, ISC_LOG_WARNING,
   11612 			     "response-policy zone expired; "
   11613 			     "policies unloaded");
   11614 	}
   11615 
   11616 cleanup:
   11617 	if (db != NULL) {
   11618 		dns_db_detach(&db);
   11619 	}
   11620 
   11621 	zone_unload(zone);
   11622 }
   11623 
   11624 static void
   11625 zone_refresh(dns_zone_t *zone) {
   11626 	isc_interval_t i;
   11627 	uint32_t oldflags;
   11628 	isc_result_t result;
   11629 
   11630 	REQUIRE(DNS_ZONE_VALID(zone));
   11631 	REQUIRE(LOCKED_ZONE(zone));
   11632 
   11633 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   11634 		return;
   11635 	}
   11636 
   11637 	/*
   11638 	 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
   11639 	 * in progress at a time.
   11640 	 */
   11641 
   11642 	oldflags = ISC_ZONE_GET(zone, flags);
   11643 	if (dns_remote_addresses(&zone->primaries) == NULL) {
   11644 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
   11645 		if ((oldflags & DNS_ZONEFLG_NOPRIMARIES) == 0) {
   11646 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   11647 				      ISC_LOG_ERROR,
   11648 				      "cannot refresh: no primaries");
   11649 		}
   11650 		return;
   11651 	}
   11652 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
   11653 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
   11654 	if ((oldflags & (DNS_ZONEFLG_REFRESH | DNS_ZONEFLG_LOADING)) != 0) {
   11655 		return;
   11656 	}
   11657 
   11658 	/*
   11659 	 * Set the next refresh time as if refresh check has failed.
   11660 	 * Setting this to the retry time will do that.  XXXMLG
   11661 	 * If we are successful it will be reset using zone->refresh.
   11662 	 */
   11663 	isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
   11664 			 0);
   11665 	result = isc_time_nowplusinterval(&zone->refreshtime, &i);
   11666 	if (result != ISC_R_SUCCESS) {
   11667 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_WARNING,
   11668 			      "isc_time_nowplusinterval() failed: %s",
   11669 			      isc_result_totext(result));
   11670 	}
   11671 
   11672 	/*
   11673 	 * When lacking user-specified timer values from the SOA,
   11674 	 * do exponential backoff of the retry time up to a
   11675 	 * maximum of six hours.
   11676 	 */
   11677 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS)) {
   11678 		zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
   11679 	}
   11680 
   11681 	dns_remote_reset(&zone->primaries, true);
   11682 
   11683 	/* initiate soa query */
   11684 	queue_soa_query(zone);
   11685 }
   11686 
   11687 static void
   11688 zone_refresh_async(void *arg) {
   11689 	dns_zone_t *zone = arg;
   11690 
   11691 	LOCK_ZONE(zone);
   11692 	zone_refresh(zone);
   11693 	UNLOCK_ZONE(zone);
   11694 
   11695 	dns_zone_detach(&zone);
   11696 }
   11697 
   11698 void
   11699 dns_zone_refresh(dns_zone_t *zone) {
   11700 	REQUIRE(DNS_ZONE_VALID(zone));
   11701 
   11702 	dns_zone_ref(zone);
   11703 	isc_async_run(zone->loop, zone_refresh_async, zone);
   11704 }
   11705 
   11706 static isc_result_t
   11707 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
   11708 			 bool *fixjournal) {
   11709 	dns_journal_t *journal = NULL;
   11710 	unsigned int options;
   11711 	isc_result_t result;
   11712 
   11713 	if (zone->type == dns_zone_primary &&
   11714 	    (inline_secure(zone) ||
   11715 	     (zone->update_acl != NULL || zone->ssutable != NULL)))
   11716 	{
   11717 		options = DNS_JOURNALOPT_RESIGN;
   11718 	} else {
   11719 		options = 0;
   11720 	}
   11721 
   11722 	result = dns_journal_open(zone->mctx, zone->journal, DNS_JOURNAL_READ,
   11723 				  &journal);
   11724 	if (result == ISC_R_NOTFOUND) {
   11725 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(3),
   11726 			      "no journal file, but that's OK ");
   11727 		return ISC_R_SUCCESS;
   11728 	} else if (result != ISC_R_SUCCESS) {
   11729 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   11730 			      "journal open failed: %s",
   11731 			      isc_result_totext(result));
   11732 		return result;
   11733 	}
   11734 
   11735 	if (dns_journal_empty(journal)) {
   11736 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
   11737 			      "journal empty");
   11738 		dns_journal_destroy(&journal);
   11739 		return ISC_R_SUCCESS;
   11740 	}
   11741 
   11742 	result = dns_journal_rollforward(journal, db, options);
   11743 	switch (result) {
   11744 	case ISC_R_SUCCESS:
   11745 		*needdump = true;
   11746 		FALLTHROUGH;
   11747 	case DNS_R_UPTODATE:
   11748 		if (dns_journal_recovered(journal)) {
   11749 			*fixjournal = true;
   11750 			dns_zone_logc(
   11751 				zone, DNS_LOGCATEGORY_ZONELOAD,
   11752 				ISC_LOG_DEBUG(1),
   11753 				"journal rollforward completed successfully "
   11754 				"using old journal format: %s",
   11755 				isc_result_totext(result));
   11756 		} else {
   11757 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   11758 				      ISC_LOG_DEBUG(1),
   11759 				      "journal rollforward completed "
   11760 				      "successfully: %s",
   11761 				      isc_result_totext(result));
   11762 		}
   11763 
   11764 		dns_journal_destroy(&journal);
   11765 		return ISC_R_SUCCESS;
   11766 	case ISC_R_NOTFOUND:
   11767 	case ISC_R_RANGE:
   11768 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   11769 			      "journal rollforward failed: journal out of sync "
   11770 			      "with zone");
   11771 		dns_journal_destroy(&journal);
   11772 		return result;
   11773 	default:
   11774 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   11775 			      "journal rollforward failed: %s",
   11776 			      isc_result_totext(result));
   11777 		dns_journal_destroy(&journal);
   11778 		return result;
   11779 	}
   11780 }
   11781 
   11782 static void
   11783 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
   11784 	isc_result_t result;
   11785 	int32_t journalsize;
   11786 	dns_dbversion_t *ver = NULL;
   11787 	uint64_t dbsize;
   11788 	uint32_t options = 0;
   11789 
   11790 	INSIST(LOCKED_ZONE(zone));
   11791 	if (inline_raw(zone)) {
   11792 		INSIST(LOCKED_ZONE(zone->secure));
   11793 	}
   11794 
   11795 	journalsize = zone->journalsize;
   11796 	if (journalsize == -1) {
   11797 		journalsize = DNS_JOURNAL_SIZE_MAX;
   11798 		dns_db_currentversion(db, &ver);
   11799 		result = dns_db_getsize(db, ver, NULL, &dbsize);
   11800 		dns_db_closeversion(db, &ver, false);
   11801 		if (result != ISC_R_SUCCESS) {
   11802 			dns_zone_log(zone, ISC_LOG_ERROR,
   11803 				     "zone_journal_compact: "
   11804 				     "could not get zone size: %s",
   11805 				     isc_result_totext(result));
   11806 		} else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
   11807 			journalsize = (int32_t)dbsize * 2;
   11808 		}
   11809 	}
   11810 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIXJOURNAL)) {
   11811 		options |= DNS_JOURNAL_COMPACTALL;
   11812 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
   11813 		zone_debuglog(zone, __func__, 1, "repair full journal");
   11814 	} else {
   11815 		zone_debuglog(zone, __func__, 1, "target journal size %d",
   11816 			      journalsize);
   11817 	}
   11818 	result = dns_journal_compact(zone->mctx, zone->journal, serial, options,
   11819 				     journalsize);
   11820 	switch (result) {
   11821 	case ISC_R_SUCCESS:
   11822 	case ISC_R_NOSPACE:
   11823 	case ISC_R_NOTFOUND:
   11824 		dns_zone_log(zone, ISC_LOG_DEBUG(3), "dns_journal_compact: %s",
   11825 			     isc_result_totext(result));
   11826 		break;
   11827 	default:
   11828 		dns_zone_log(zone, ISC_LOG_ERROR,
   11829 			     "dns_journal_compact failed: %s",
   11830 			     isc_result_totext(result));
   11831 		break;
   11832 	}
   11833 }
   11834 
   11835 isc_result_t
   11836 dns_zone_flush(dns_zone_t *zone) {
   11837 	isc_result_t result = ISC_R_SUCCESS;
   11838 	bool dumping;
   11839 
   11840 	REQUIRE(DNS_ZONE_VALID(zone));
   11841 
   11842 	LOCK_ZONE(zone);
   11843 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
   11844 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   11845 	    zone->masterfile != NULL)
   11846 	{
   11847 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
   11848 		result = ISC_R_ALREADYRUNNING;
   11849 		dumping = was_dumping(zone);
   11850 	} else {
   11851 		dumping = true;
   11852 	}
   11853 	UNLOCK_ZONE(zone);
   11854 	if (!dumping) {
   11855 		result = zone_dump(zone, true);
   11856 	}
   11857 	return result;
   11858 }
   11859 
   11860 isc_result_t
   11861 dns_zone_dump(dns_zone_t *zone) {
   11862 	isc_result_t result = ISC_R_ALREADYRUNNING;
   11863 	bool dumping;
   11864 
   11865 	REQUIRE(DNS_ZONE_VALID(zone));
   11866 
   11867 	LOCK_ZONE(zone);
   11868 	dumping = was_dumping(zone);
   11869 	UNLOCK_ZONE(zone);
   11870 	if (!dumping) {
   11871 		result = zone_dump(zone, false);
   11872 	}
   11873 	return result;
   11874 }
   11875 
   11876 static void
   11877 zone_needdump(dns_zone_t *zone, unsigned int delay) {
   11878 	isc_time_t dumptime;
   11879 	isc_time_t now;
   11880 
   11881 	/*
   11882 	 * 'zone' locked by caller
   11883 	 */
   11884 
   11885 	REQUIRE(DNS_ZONE_VALID(zone));
   11886 	REQUIRE(LOCKED_ZONE(zone));
   11887 	ENTER;
   11888 
   11889 	/*
   11890 	 * Do we have a place to dump to and are we loaded?
   11891 	 */
   11892 	if (zone->masterfile == NULL ||
   11893 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
   11894 	{
   11895 		return;
   11896 	}
   11897 
   11898 	now = isc_time_now();
   11899 	/* add some noise */
   11900 	DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
   11901 
   11902 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   11903 	if (isc_time_isepoch(&zone->dumptime) ||
   11904 	    isc_time_compare(&zone->dumptime, &dumptime) > 0)
   11905 	{
   11906 		zone->dumptime = dumptime;
   11907 	}
   11908 	if (zone->loop != NULL) {
   11909 		zone_settimer(zone, &now);
   11910 	}
   11911 }
   11912 
   11913 static void
   11914 dump_done(void *arg, isc_result_t result) {
   11915 	dns_zone_t *zone = arg;
   11916 	dns_zone_t *secure = NULL;
   11917 	dns_db_t *db;
   11918 	dns_dbversion_t *version;
   11919 	bool again = false;
   11920 	bool compact = false;
   11921 	uint32_t serial;
   11922 	isc_result_t tresult;
   11923 
   11924 	REQUIRE(DNS_ZONE_VALID(zone));
   11925 
   11926 	ENTER;
   11927 
   11928 	/*
   11929 	 * Adjust modification time of zone file to preserve expire timing.
   11930 	 */
   11931 	if ((zone->type == dns_zone_secondary ||
   11932 	     zone->type == dns_zone_mirror ||
   11933 	     zone->type == dns_zone_redirect) &&
   11934 	    result == ISC_R_SUCCESS)
   11935 	{
   11936 		LOCK_ZONE(zone);
   11937 		isc_time_t when;
   11938 		isc_interval_t i;
   11939 		isc_interval_set(&i, zone->expire, 0);
   11940 		result = isc_time_subtract(&zone->expiretime, &i, &when);
   11941 		if (result == ISC_R_SUCCESS) {
   11942 			(void)isc_file_settime(zone->masterfile, &when);
   11943 		} else {
   11944 			result = ISC_R_SUCCESS;
   11945 		}
   11946 		UNLOCK_ZONE(zone);
   11947 	}
   11948 
   11949 	if (result == ISC_R_SUCCESS && zone->journal != NULL) {
   11950 		/*
   11951 		 * We don't own these, zone->dctx must stay valid.
   11952 		 */
   11953 		db = dns_dumpctx_db(zone->dumpctx);
   11954 		version = dns_dumpctx_version(zone->dumpctx);
   11955 		tresult = dns_db_getsoaserial(db, version, &serial);
   11956 
   11957 		/*
   11958 		 * Handle lock order inversion.
   11959 		 */
   11960 	again:
   11961 		LOCK_ZONE(zone);
   11962 		if (inline_raw(zone)) {
   11963 			secure = zone->secure;
   11964 			INSIST(secure != zone);
   11965 			TRYLOCK_ZONE(result, secure);
   11966 			if (result != ISC_R_SUCCESS) {
   11967 				UNLOCK_ZONE(zone);
   11968 				secure = NULL;
   11969 				isc_thread_yield();
   11970 				goto again;
   11971 			}
   11972 		}
   11973 
   11974 		/*
   11975 		 * If there is a secure version of this zone
   11976 		 * use its serial if it is less than ours.
   11977 		 */
   11978 		if (tresult == ISC_R_SUCCESS && secure != NULL) {
   11979 			uint32_t sserial;
   11980 			isc_result_t mresult;
   11981 
   11982 			ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
   11983 			if (secure->db != NULL) {
   11984 				mresult = dns_db_getsoaserial(zone->secure->db,
   11985 							      NULL, &sserial);
   11986 				if (mresult == ISC_R_SUCCESS &&
   11987 				    isc_serial_lt(sserial, serial))
   11988 				{
   11989 					serial = sserial;
   11990 				}
   11991 			}
   11992 			ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
   11993 		}
   11994 		if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
   11995 			dns_db_t *zdb = NULL;
   11996 			if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
   11997 				zone_journal_compact(zone, zdb, serial);
   11998 				dns_db_detach(&zdb);
   11999 			}
   12000 		} else if (tresult == ISC_R_SUCCESS) {
   12001 			compact = true;
   12002 			zone->compact_serial = serial;
   12003 		}
   12004 		if (secure != NULL) {
   12005 			UNLOCK_ZONE(secure);
   12006 		}
   12007 		UNLOCK_ZONE(zone);
   12008 	}
   12009 
   12010 	LOCK_ZONE(zone);
   12011 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
   12012 	if (compact) {
   12013 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
   12014 	}
   12015 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN)) {
   12016 		/*
   12017 		 * If DNS_ZONEFLG_SHUTDOWN is set, all external references to
   12018 		 * the zone are gone, which means it is in the process of being
   12019 		 * cleaned up, so do not reschedule dumping.
   12020 		 *
   12021 		 * Detach from the raw version of the zone in case this
   12022 		 * operation has been deferred in zone_shutdown().
   12023 		 */
   12024 		if (zone->raw != NULL) {
   12025 			dns_zone_detach(&zone->raw);
   12026 		}
   12027 		if (result == ISC_R_SUCCESS) {
   12028 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
   12029 		}
   12030 	} else if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
   12031 		/*
   12032 		 * Try again in a short while.
   12033 		 */
   12034 		zone_needdump(zone, DNS_DUMP_DELAY);
   12035 	} else if (result == ISC_R_SUCCESS &&
   12036 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
   12037 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   12038 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   12039 	{
   12040 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   12041 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
   12042 		isc_time_settoepoch(&zone->dumptime);
   12043 		again = true;
   12044 	} else if (result == ISC_R_SUCCESS) {
   12045 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
   12046 	}
   12047 
   12048 	if (zone->dumpctx != NULL) {
   12049 		dns_dumpctx_detach(&zone->dumpctx);
   12050 	}
   12051 	UNLOCK_ZONE(zone);
   12052 	if (again) {
   12053 		(void)zone_dump(zone, false);
   12054 	}
   12055 	dns_zone_idetach(&zone);
   12056 }
   12057 
   12058 static isc_result_t
   12059 zone_dump(dns_zone_t *zone, bool compact) {
   12060 	isc_result_t result;
   12061 	dns_dbversion_t *version = NULL;
   12062 	bool again = false;
   12063 	dns_db_t *db = NULL;
   12064 	char *masterfile = NULL;
   12065 	dns_masterformat_t masterformat = dns_masterformat_none;
   12066 	const dns_master_style_t *masterstyle = NULL;
   12067 	dns_masterrawheader_t rawdata;
   12068 
   12069 	/*
   12070 	 * 'compact' MUST only be set if we are loop locked.
   12071 	 */
   12072 
   12073 	REQUIRE(DNS_ZONE_VALID(zone));
   12074 	ENTER;
   12075 
   12076 redo:
   12077 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   12078 	if (zone->db != NULL) {
   12079 		dns_db_attach(zone->db, &db);
   12080 	}
   12081 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   12082 	LOCK_ZONE(zone);
   12083 	if (zone->masterfile != NULL) {
   12084 		masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
   12085 		masterformat = zone->masterformat;
   12086 	}
   12087 	if (zone->type == dns_zone_key) {
   12088 		masterstyle = &dns_master_style_keyzone;
   12089 	} else if (zone->masterstyle != NULL) {
   12090 		masterstyle = zone->masterstyle;
   12091 	} else {
   12092 		masterstyle = &dns_master_style_default;
   12093 	}
   12094 	UNLOCK_ZONE(zone);
   12095 	if (db == NULL) {
   12096 		result = DNS_R_NOTLOADED;
   12097 		goto fail;
   12098 	}
   12099 	if (masterfile == NULL) {
   12100 		result = DNS_R_NOMASTERFILE;
   12101 		goto fail;
   12102 	}
   12103 
   12104 	dns_db_currentversion(db, &version);
   12105 
   12106 	dns_master_initrawheader(&rawdata);
   12107 
   12108 	if (inline_secure(zone)) {
   12109 		get_raw_serial(zone->raw, &rawdata);
   12110 	}
   12111 
   12112 	if (compact && zone->type != dns_zone_stub) {
   12113 		LOCK_ZONE(zone);
   12114 		zone_iattach(zone, &(dns_zone_t *){ NULL });
   12115 
   12116 		INSIST(zone != zone->raw);
   12117 
   12118 		result = dns_master_dumpasync(
   12119 			zone->mctx, db, version, masterstyle, masterfile,
   12120 			zone->loop, dump_done, zone, &zone->dumpctx,
   12121 			masterformat, &rawdata);
   12122 
   12123 		UNLOCK_ZONE(zone);
   12124 		if (result != ISC_R_SUCCESS) {
   12125 			dns_zone_idetach(&(dns_zone_t *){ zone });
   12126 			goto fail;
   12127 		}
   12128 		result = DNS_R_CONTINUE;
   12129 	} else {
   12130 		result = dns_master_dump(zone->mctx, db, version, masterstyle,
   12131 					 masterfile, masterformat, &rawdata);
   12132 		if ((zone->type == dns_zone_secondary ||
   12133 		     zone->type == dns_zone_mirror ||
   12134 		     zone->type == dns_zone_redirect) &&
   12135 		    result == ISC_R_SUCCESS)
   12136 		{
   12137 			isc_time_t when;
   12138 			isc_interval_t i;
   12139 			isc_interval_set(&i, zone->expire, 0);
   12140 			result = isc_time_subtract(&zone->expiretime, &i,
   12141 						   &when);
   12142 			if (result == ISC_R_SUCCESS) {
   12143 				(void)isc_file_settime(zone->masterfile, &when);
   12144 			} else {
   12145 				result = ISC_R_SUCCESS;
   12146 			}
   12147 		}
   12148 	}
   12149 fail:
   12150 	if (version != NULL) {
   12151 		dns_db_closeversion(db, &version, false);
   12152 	}
   12153 	if (db != NULL) {
   12154 		dns_db_detach(&db);
   12155 	}
   12156 	if (masterfile != NULL) {
   12157 		isc_mem_free(zone->mctx, masterfile);
   12158 		masterfile = NULL;
   12159 	}
   12160 
   12161 	if (result == DNS_R_CONTINUE) {
   12162 		/*
   12163 		 * Asyncronous write is in progress.  Zone flags will get
   12164 		 * updated on completion.  Cleanup is complete.  We are done.
   12165 		 */
   12166 		return ISC_R_SUCCESS;
   12167 	}
   12168 
   12169 	again = false;
   12170 	LOCK_ZONE(zone);
   12171 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
   12172 	if (result != ISC_R_SUCCESS) {
   12173 		/*
   12174 		 * Try again in a short while.
   12175 		 */
   12176 		zone_needdump(zone, DNS_DUMP_DELAY);
   12177 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
   12178 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   12179 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   12180 	{
   12181 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   12182 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
   12183 		isc_time_settoepoch(&zone->dumptime);
   12184 		again = true;
   12185 	} else {
   12186 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
   12187 	}
   12188 	UNLOCK_ZONE(zone);
   12189 	if (again) {
   12190 		goto redo;
   12191 	}
   12192 
   12193 	return result;
   12194 }
   12195 
   12196 static isc_result_t
   12197 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
   12198 	     dns_masterformat_t format, const uint32_t rawversion) {
   12199 	isc_result_t result;
   12200 	dns_dbversion_t *version = NULL;
   12201 	dns_db_t *db = NULL;
   12202 	dns_masterrawheader_t rawdata;
   12203 
   12204 	REQUIRE(DNS_ZONE_VALID(zone));
   12205 
   12206 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   12207 	if (zone->db != NULL) {
   12208 		dns_db_attach(zone->db, &db);
   12209 	}
   12210 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   12211 	if (db == NULL) {
   12212 		return DNS_R_NOTLOADED;
   12213 	}
   12214 
   12215 	dns_db_currentversion(db, &version);
   12216 	dns_master_initrawheader(&rawdata);
   12217 	if (rawversion == 0) {
   12218 		rawdata.flags |= DNS_MASTERRAW_COMPAT;
   12219 	} else if (inline_secure(zone)) {
   12220 		get_raw_serial(zone->raw, &rawdata);
   12221 	} else if (zone->sourceserialset) {
   12222 		rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
   12223 		rawdata.sourceserial = zone->sourceserial;
   12224 	}
   12225 	result = dns_master_dumptostream(zone->mctx, db, version, style, format,
   12226 					 &rawdata, fd);
   12227 	dns_db_closeversion(db, &version, false);
   12228 	dns_db_detach(&db);
   12229 	return result;
   12230 }
   12231 
   12232 isc_result_t
   12233 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
   12234 		      const dns_master_style_t *style,
   12235 		      const uint32_t rawversion) {
   12236 	return dumptostream(zone, fd, style, format, rawversion);
   12237 }
   12238 
   12239 void
   12240 dns_zone_unload(dns_zone_t *zone) {
   12241 	REQUIRE(DNS_ZONE_VALID(zone));
   12242 
   12243 	LOCK_ZONE(zone);
   12244 	zone_unload(zone);
   12245 	UNLOCK_ZONE(zone);
   12246 }
   12247 
   12248 static void
   12249 notify_cancel(dns_zone_t *zone) {
   12250 	dns_notify_t *notify;
   12251 
   12252 	/*
   12253 	 * 'zone' locked by caller.
   12254 	 */
   12255 
   12256 	REQUIRE(LOCKED_ZONE(zone));
   12257 
   12258 	for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
   12259 	     notify = ISC_LIST_NEXT(notify, link))
   12260 	{
   12261 		if (notify->find != NULL) {
   12262 			dns_adb_cancelfind(notify->find);
   12263 		}
   12264 		if (notify->request != NULL) {
   12265 			dns_request_cancel(notify->request);
   12266 		}
   12267 	}
   12268 }
   12269 
   12270 static void
   12271 checkds_cancel(dns_zone_t *zone) {
   12272 	dns_checkds_t *checkds;
   12273 
   12274 	/*
   12275 	 * 'zone' locked by caller.
   12276 	 */
   12277 
   12278 	REQUIRE(LOCKED_ZONE(zone));
   12279 
   12280 	for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
   12281 	     checkds = ISC_LIST_NEXT(checkds, link))
   12282 	{
   12283 		if (checkds->find != NULL) {
   12284 			dns_adb_cancelfind(checkds->find);
   12285 		}
   12286 		if (checkds->request != NULL) {
   12287 			dns_request_cancel(checkds->request);
   12288 		}
   12289 	}
   12290 }
   12291 
   12292 static void
   12293 forward_cancel(dns_zone_t *zone) {
   12294 	dns_forward_t *forward;
   12295 
   12296 	/*
   12297 	 * 'zone' locked by caller.
   12298 	 */
   12299 
   12300 	REQUIRE(LOCKED_ZONE(zone));
   12301 
   12302 	for (forward = ISC_LIST_HEAD(zone->forwards); forward != NULL;
   12303 	     forward = ISC_LIST_NEXT(forward, link))
   12304 	{
   12305 		if (forward->request != NULL) {
   12306 			dns_request_cancel(forward->request);
   12307 		}
   12308 	}
   12309 }
   12310 
   12311 static void
   12312 zone_unload(dns_zone_t *zone) {
   12313 	/*
   12314 	 * 'zone' locked by caller.
   12315 	 */
   12316 
   12317 	REQUIRE(LOCKED_ZONE(zone));
   12318 
   12319 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
   12320 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
   12321 	{
   12322 		if (zone->dumpctx != NULL) {
   12323 			dns_dumpctx_cancel(zone->dumpctx);
   12324 		}
   12325 	}
   12326 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   12327 	zone_detachdb(zone);
   12328 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   12329 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
   12330 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   12331 
   12332 	if (zone->type == dns_zone_mirror) {
   12333 		dns_zone_log(zone, ISC_LOG_INFO,
   12334 			     "mirror zone is no longer in use; "
   12335 			     "reverting to normal recursion");
   12336 	}
   12337 }
   12338 
   12339 void
   12340 dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
   12341 	REQUIRE(DNS_ZONE_VALID(zone));
   12342 	REQUIRE(val > 0);
   12343 
   12344 	zone->minrefresh = val;
   12345 }
   12346 
   12347 void
   12348 dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
   12349 	REQUIRE(DNS_ZONE_VALID(zone));
   12350 	REQUIRE(val > 0);
   12351 
   12352 	zone->maxrefresh = val;
   12353 }
   12354 
   12355 void
   12356 dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
   12357 	REQUIRE(DNS_ZONE_VALID(zone));
   12358 	REQUIRE(val > 0);
   12359 
   12360 	zone->minretry = val;
   12361 }
   12362 
   12363 void
   12364 dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
   12365 	REQUIRE(DNS_ZONE_VALID(zone));
   12366 	REQUIRE(val > 0);
   12367 
   12368 	zone->maxretry = val;
   12369 }
   12370 
   12371 uint32_t
   12372 dns_zone_getmaxrecords(dns_zone_t *zone) {
   12373 	REQUIRE(DNS_ZONE_VALID(zone));
   12374 
   12375 	return zone->maxrecords;
   12376 }
   12377 
   12378 void
   12379 dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
   12380 	REQUIRE(DNS_ZONE_VALID(zone));
   12381 
   12382 	zone->maxrecords = val;
   12383 }
   12384 
   12385 void
   12386 dns_zone_setmaxrrperset(dns_zone_t *zone, uint32_t val) {
   12387 	REQUIRE(DNS_ZONE_VALID(zone));
   12388 
   12389 	zone->maxrrperset = val;
   12390 	if (zone->db != NULL) {
   12391 		dns_db_setmaxrrperset(zone->db, val);
   12392 	}
   12393 }
   12394 
   12395 void
   12396 dns_zone_setmaxtypepername(dns_zone_t *zone, uint32_t val) {
   12397 	REQUIRE(DNS_ZONE_VALID(zone));
   12398 
   12399 	zone->maxtypepername = val;
   12400 	if (zone->db != NULL) {
   12401 		dns_db_setmaxtypepername(zone->db, val);
   12402 	}
   12403 }
   12404 
   12405 static bool
   12406 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
   12407 		isc_sockaddr_t *addr, dns_tsigkey_t *key,
   12408 		dns_transport_t *transport) {
   12409 	dns_notify_t *notify;
   12410 	dns_zonemgr_t *zmgr;
   12411 	isc_result_t result;
   12412 
   12413 	for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
   12414 	     notify = ISC_LIST_NEXT(notify, link))
   12415 	{
   12416 		if (notify->request != NULL) {
   12417 			continue;
   12418 		}
   12419 		if (name != NULL && dns_name_dynamic(&notify->ns) &&
   12420 		    dns_name_equal(name, &notify->ns))
   12421 		{
   12422 			goto requeue;
   12423 		}
   12424 		if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst) &&
   12425 		    notify->key == key && notify->transport == transport)
   12426 		{
   12427 			goto requeue;
   12428 		}
   12429 	}
   12430 	return false;
   12431 
   12432 requeue:
   12433 	/*
   12434 	 * If we are enqueued on the startup ratelimiter and this is
   12435 	 * not a startup notify, re-enqueue on the normal notify
   12436 	 * ratelimiter.
   12437 	 */
   12438 	if (notify->rlevent != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
   12439 	    (notify->flags & DNS_NOTIFY_STARTUP) != 0)
   12440 	{
   12441 		zmgr = notify->zone->zmgr;
   12442 		result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
   12443 						 &notify->rlevent);
   12444 		if (result != ISC_R_SUCCESS) {
   12445 			return true;
   12446 		}
   12447 
   12448 		notify->flags &= ~DNS_NOTIFY_STARTUP;
   12449 		result = isc_ratelimiter_enqueue(
   12450 			notify->zone->zmgr->notifyrl, notify->zone->loop,
   12451 			notify_send_toaddr, notify, &notify->rlevent);
   12452 		if (result != ISC_R_SUCCESS) {
   12453 			return false;
   12454 		}
   12455 	}
   12456 
   12457 	return true;
   12458 }
   12459 
   12460 static bool
   12461 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
   12462 	dns_tsigkey_t *key = NULL;
   12463 	isc_sockaddr_t src;
   12464 	isc_sockaddr_t any;
   12465 	bool isself;
   12466 	isc_netaddr_t dstaddr;
   12467 	isc_result_t result;
   12468 
   12469 	if (zone->view == NULL || zone->isself == NULL) {
   12470 		return false;
   12471 	}
   12472 
   12473 	switch (isc_sockaddr_pf(dst)) {
   12474 	case PF_INET:
   12475 		src = zone->notifysrc4;
   12476 		isc_sockaddr_any(&any);
   12477 		break;
   12478 	case PF_INET6:
   12479 		src = zone->notifysrc6;
   12480 		isc_sockaddr_any6(&any);
   12481 		break;
   12482 	default:
   12483 		return false;
   12484 	}
   12485 
   12486 	/*
   12487 	 * When sending from any the kernel will assign a source address
   12488 	 * that matches the destination address.
   12489 	 */
   12490 	if (isc_sockaddr_eqaddr(&any, &src)) {
   12491 		src = *dst;
   12492 	}
   12493 
   12494 	isc_netaddr_fromsockaddr(&dstaddr, dst);
   12495 	result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
   12496 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   12497 		return false;
   12498 	}
   12499 	isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
   12500 				zone->isselfarg);
   12501 	if (key != NULL) {
   12502 		dns_tsigkey_detach(&key);
   12503 	}
   12504 	return isself;
   12505 }
   12506 
   12507 static void
   12508 notify_destroy(dns_notify_t *notify, bool locked) {
   12509 	isc_mem_t *mctx;
   12510 
   12511 	REQUIRE(DNS_NOTIFY_VALID(notify));
   12512 
   12513 	if (notify->zone != NULL) {
   12514 		if (!locked) {
   12515 			LOCK_ZONE(notify->zone);
   12516 		}
   12517 		REQUIRE(LOCKED_ZONE(notify->zone));
   12518 		if (ISC_LINK_LINKED(notify, link)) {
   12519 			ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
   12520 		}
   12521 		if (!locked) {
   12522 			UNLOCK_ZONE(notify->zone);
   12523 		}
   12524 		if (locked) {
   12525 			zone_idetach(&notify->zone);
   12526 		} else {
   12527 			dns_zone_idetach(&notify->zone);
   12528 		}
   12529 	}
   12530 	if (notify->find != NULL) {
   12531 		dns_adb_destroyfind(&notify->find);
   12532 	}
   12533 	if (notify->request != NULL) {
   12534 		dns_request_destroy(&notify->request);
   12535 	}
   12536 	if (dns_name_dynamic(&notify->ns)) {
   12537 		dns_name_free(&notify->ns, notify->mctx);
   12538 	}
   12539 	if (notify->key != NULL) {
   12540 		dns_tsigkey_detach(&notify->key);
   12541 	}
   12542 	if (notify->transport != NULL) {
   12543 		dns_transport_detach(&notify->transport);
   12544 	}
   12545 	mctx = notify->mctx;
   12546 	isc_mem_put(notify->mctx, notify, sizeof(*notify));
   12547 	isc_mem_detach(&mctx);
   12548 }
   12549 
   12550 static isc_result_t
   12551 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
   12552 	dns_notify_t *notify;
   12553 
   12554 	REQUIRE(notifyp != NULL && *notifyp == NULL);
   12555 
   12556 	notify = isc_mem_get(mctx, sizeof(*notify));
   12557 	*notify = (dns_notify_t){
   12558 		.flags = flags,
   12559 	};
   12560 
   12561 	isc_mem_attach(mctx, &notify->mctx);
   12562 	isc_sockaddr_any(&notify->src);
   12563 	isc_sockaddr_any(&notify->dst);
   12564 	dns_name_init(&notify->ns, NULL);
   12565 	ISC_LINK_INIT(notify, link);
   12566 	notify->magic = NOTIFY_MAGIC;
   12567 	*notifyp = notify;
   12568 	return ISC_R_SUCCESS;
   12569 }
   12570 
   12571 /*
   12572  * XXXAG should check for DNS_ZONEFLG_EXITING
   12573  */
   12574 static void
   12575 process_notify_adb_event(void *arg) {
   12576 	dns_adbfind_t *find = (dns_adbfind_t *)arg;
   12577 	dns_notify_t *notify = (dns_notify_t *)find->cbarg;
   12578 	dns_adbstatus_t astat = find->status;
   12579 
   12580 	REQUIRE(DNS_NOTIFY_VALID(notify));
   12581 	REQUIRE(find == notify->find);
   12582 
   12583 	switch (astat) {
   12584 	case DNS_ADB_MOREADDRESSES:
   12585 		dns_adb_destroyfind(&notify->find);
   12586 		notify_find_address(notify);
   12587 		return;
   12588 
   12589 	case DNS_ADB_NOMOREADDRESSES:
   12590 		LOCK_ZONE(notify->zone);
   12591 		notify_send(notify);
   12592 		UNLOCK_ZONE(notify->zone);
   12593 		break;
   12594 
   12595 	default:
   12596 		break;
   12597 	}
   12598 
   12599 	notify_destroy(notify, false);
   12600 }
   12601 
   12602 static void
   12603 notify_find_address(dns_notify_t *notify) {
   12604 	isc_result_t result;
   12605 	unsigned int options;
   12606 	dns_adb_t *adb = NULL;
   12607 
   12608 	REQUIRE(DNS_NOTIFY_VALID(notify));
   12609 
   12610 	options = DNS_ADBFIND_WANTEVENT;
   12611 	if (isc_net_probeipv4() != ISC_R_DISABLED) {
   12612 		options |= DNS_ADBFIND_INET;
   12613 	}
   12614 	if (isc_net_probeipv6() != ISC_R_DISABLED) {
   12615 		options |= DNS_ADBFIND_INET6;
   12616 	}
   12617 
   12618 	dns_view_getadb(notify->zone->view, &adb);
   12619 	if (adb == NULL) {
   12620 		goto destroy;
   12621 	}
   12622 
   12623 	result = dns_adb_createfind(adb, notify->zone->loop,
   12624 				    process_notify_adb_event, notify,
   12625 				    &notify->ns, dns_rootname, 0, options, 0,
   12626 				    NULL, notify->zone->view->dstport, 0, NULL,
   12627 				    NULL, NULL, &notify->find);
   12628 	dns_adb_detach(&adb);
   12629 
   12630 	/* Something failed? */
   12631 	if (result != ISC_R_SUCCESS) {
   12632 		goto destroy;
   12633 	}
   12634 
   12635 	/* More addresses pending? */
   12636 	if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
   12637 		return;
   12638 	}
   12639 
   12640 	/* We have as many addresses as we can get. */
   12641 	LOCK_ZONE(notify->zone);
   12642 	notify_send(notify);
   12643 	UNLOCK_ZONE(notify->zone);
   12644 
   12645 destroy:
   12646 	notify_destroy(notify, false);
   12647 }
   12648 
   12649 static isc_result_t
   12650 notify_send_queue(dns_notify_t *notify, bool startup) {
   12651 	return isc_ratelimiter_enqueue(
   12652 		startup ? notify->zone->zmgr->startupnotifyrl
   12653 			: notify->zone->zmgr->notifyrl,
   12654 		notify->zone->loop, notify_send_toaddr, notify,
   12655 		&notify->rlevent);
   12656 }
   12657 
   12658 static void
   12659 notify_send_toaddr(void *arg) {
   12660 	dns_notify_t *notify = (dns_notify_t *)arg;
   12661 	isc_result_t result;
   12662 	dns_message_t *message = NULL;
   12663 	isc_netaddr_t dstip;
   12664 	dns_tsigkey_t *key = NULL;
   12665 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   12666 	isc_sockaddr_t src;
   12667 	unsigned int options, timeout, udptimeout;
   12668 	bool have_notifysource = false;
   12669 	isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
   12670 
   12671 	REQUIRE(DNS_NOTIFY_VALID(notify));
   12672 
   12673 	LOCK_ZONE(notify->zone);
   12674 
   12675 	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
   12676 
   12677 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0 ||
   12678 	    notify->rlevent->canceled ||
   12679 	    DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
   12680 	    notify->zone->view->requestmgr == NULL || notify->zone->db == NULL)
   12681 	{
   12682 		result = ISC_R_CANCELED;
   12683 		goto cleanup;
   12684 	}
   12685 
   12686 	/*
   12687 	 * The raw IPv4 address should also exist.  Don't send to the
   12688 	 * mapped form.
   12689 	 */
   12690 	if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
   12691 	    IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr))
   12692 	{
   12693 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
   12694 			   "notify: ignoring IPv6 mapped IPV4 address: %s",
   12695 			   addrbuf);
   12696 		result = ISC_R_CANCELED;
   12697 		goto cleanup;
   12698 	}
   12699 
   12700 	result = notify_createmessage(notify->zone, notify->flags, &message);
   12701 	if (result != ISC_R_SUCCESS) {
   12702 		goto cleanup;
   12703 	}
   12704 
   12705 	if (notify->key != NULL) {
   12706 		/* Transfer ownership of key */
   12707 		key = notify->key;
   12708 		notify->key = NULL;
   12709 	} else {
   12710 		isc_netaddr_fromsockaddr(&dstip, &notify->dst);
   12711 		result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
   12712 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   12713 			notify_log(notify->zone, ISC_LOG_ERROR,
   12714 				   "NOTIFY to %s not sent. "
   12715 				   "Peer TSIG key lookup failure.",
   12716 				   addrbuf);
   12717 			goto cleanup_message;
   12718 		}
   12719 	}
   12720 
   12721 	if (key != NULL) {
   12722 		char namebuf[DNS_NAME_FORMATSIZE];
   12723 
   12724 		dns_name_format(key->name, namebuf, sizeof(namebuf));
   12725 		notify_log(notify->zone, ISC_LOG_INFO,
   12726 			   "sending notify to %s : TSIG (%s)", addrbuf,
   12727 			   namebuf);
   12728 	} else {
   12729 		notify_log(notify->zone, ISC_LOG_INFO, "sending notify to %s",
   12730 			   addrbuf);
   12731 	}
   12732 	options = 0;
   12733 	if (notify->zone->view->peers != NULL) {
   12734 		dns_peer_t *peer = NULL;
   12735 		bool usetcp = false;
   12736 		result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
   12737 						 &dstip, &peer);
   12738 		if (result == ISC_R_SUCCESS) {
   12739 			result = dns_peer_getnotifysource(peer, &src);
   12740 			if (result == ISC_R_SUCCESS) {
   12741 				have_notifysource = true;
   12742 			}
   12743 			result = dns_peer_getforcetcp(peer, &usetcp);
   12744 			if (result == ISC_R_SUCCESS && usetcp) {
   12745 				options |= DNS_FETCHOPT_TCP;
   12746 			}
   12747 		}
   12748 	}
   12749 	switch (isc_sockaddr_pf(&notify->dst)) {
   12750 	case PF_INET:
   12751 		if (!have_notifysource) {
   12752 			isc_sockaddr_t any;
   12753 			isc_sockaddr_any(&any);
   12754 
   12755 			src = notify->src;
   12756 			if (isc_sockaddr_equal(&src, &any)) {
   12757 				src = notify->zone->notifysrc4;
   12758 			}
   12759 		}
   12760 		break;
   12761 	case PF_INET6:
   12762 		if (!have_notifysource) {
   12763 			isc_sockaddr_t any;
   12764 			isc_sockaddr_any6(&any);
   12765 
   12766 			src = notify->src;
   12767 			if (isc_sockaddr_equal(&src, &any)) {
   12768 				src = notify->zone->notifysrc6;
   12769 			}
   12770 		}
   12771 		break;
   12772 	default:
   12773 		result = ISC_R_NOTIMPLEMENTED;
   12774 		goto cleanup_key;
   12775 	}
   12776 	udptimeout = 5;
   12777 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY)) {
   12778 		udptimeout = 30;
   12779 	}
   12780 	timeout = 3 * udptimeout + 1;
   12781 again:
   12782 	if ((notify->flags & DNS_NOTIFY_TCP) != 0) {
   12783 		options |= DNS_REQUESTOPT_TCP;
   12784 		udptimeout = 0;
   12785 		timeout = 15;
   12786 	}
   12787 
   12788 	zmgr_tlsctx_attach(notify->zone->zmgr, &zmgr_tlsctx_cache);
   12789 
   12790 	result = dns_request_create(notify->zone->view->requestmgr, message,
   12791 				    &src, &notify->dst, notify->transport,
   12792 				    zmgr_tlsctx_cache, options, key, timeout,
   12793 				    udptimeout, 2, notify->zone->loop,
   12794 				    notify_done, notify, &notify->request);
   12795 
   12796 	isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
   12797 
   12798 	if (result == 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 	} else if (result == ISC_R_SHUTTINGDOWN || result == ISC_R_CANCELED) {
   12807 		goto cleanup_key;
   12808 	} else if ((notify->flags & DNS_NOTIFY_TCP) == 0) {
   12809 		notify_log(notify->zone, ISC_LOG_NOTICE,
   12810 			   "notify to %s failed: %s: retrying over TCP",
   12811 			   addrbuf, isc_result_totext(result));
   12812 		notify->flags |= DNS_NOTIFY_TCP;
   12813 		goto again;
   12814 	}
   12815 
   12816 cleanup_key:
   12817 	if (key != NULL) {
   12818 		dns_tsigkey_detach(&key);
   12819 	}
   12820 cleanup_message:
   12821 	dns_message_detach(&message);
   12822 cleanup:
   12823 	UNLOCK_ZONE(notify->zone);
   12824 	if (notify->rlevent != NULL) {
   12825 		isc_rlevent_free(&notify->rlevent);
   12826 	}
   12827 
   12828 	if (result != ISC_R_SUCCESS) {
   12829 		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
   12830 		notify_log(notify->zone, ISC_LOG_WARNING,
   12831 			   "notify to %s failed: %s", addrbuf,
   12832 			   isc_result_totext(result));
   12833 		notify_destroy(notify, false);
   12834 	}
   12835 }
   12836 
   12837 static void
   12838 notify_send(dns_notify_t *notify) {
   12839 	dns_adbaddrinfo_t *ai;
   12840 	isc_sockaddr_t dst;
   12841 	isc_result_t result;
   12842 	dns_notify_t *newnotify = NULL;
   12843 	unsigned int flags;
   12844 	bool startup;
   12845 
   12846 	/*
   12847 	 * Zone lock held by caller.
   12848 	 */
   12849 	REQUIRE(DNS_NOTIFY_VALID(notify));
   12850 	REQUIRE(LOCKED_ZONE(notify->zone));
   12851 
   12852 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING)) {
   12853 		return;
   12854 	}
   12855 
   12856 	for (ai = ISC_LIST_HEAD(notify->find->list); ai != NULL;
   12857 	     ai = ISC_LIST_NEXT(ai, publink))
   12858 	{
   12859 		dst = ai->sockaddr;
   12860 		if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
   12861 				    NULL, NULL))
   12862 		{
   12863 			continue;
   12864 		}
   12865 		if (notify_isself(notify->zone, &dst)) {
   12866 			continue;
   12867 		}
   12868 		newnotify = NULL;
   12869 		flags = notify->flags & DNS_NOTIFY_NOSOA;
   12870 		result = notify_create(notify->mctx, flags, &newnotify);
   12871 		if (result != ISC_R_SUCCESS) {
   12872 			goto cleanup;
   12873 		}
   12874 		zone_iattach(notify->zone, &newnotify->zone);
   12875 		ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
   12876 		newnotify->dst = dst;
   12877 		if (isc_sockaddr_pf(&dst) == AF_INET6) {
   12878 			isc_sockaddr_any6(&newnotify->src);
   12879 		}
   12880 		startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
   12881 		result = notify_send_queue(newnotify, startup);
   12882 		if (result != ISC_R_SUCCESS) {
   12883 			goto cleanup;
   12884 		}
   12885 		newnotify = NULL;
   12886 	}
   12887 
   12888 cleanup:
   12889 	if (newnotify != NULL) {
   12890 		notify_destroy(newnotify, true);
   12891 	}
   12892 }
   12893 
   12894 void
   12895 dns_zone_notify(dns_zone_t *zone, bool nodefer) {
   12896 	isc_time_t now;
   12897 
   12898 	REQUIRE(DNS_ZONE_VALID(zone));
   12899 
   12900 	LOCK_ZONE(zone);
   12901 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   12902 	if (nodefer) {
   12903 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED)) {
   12904 			/*
   12905 			 * We have previously deferred the notify, but we have a
   12906 			 * new request not to defer it. Reverse the deferring
   12907 			 * operation.
   12908 			 */
   12909 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED);
   12910 			DNS_ZONE_TIME_SUBTRACT(&zone->notifytime,
   12911 					       zone->notifydefer,
   12912 					       &zone->notifytime);
   12913 		}
   12914 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOTIFYNODEFER);
   12915 	}
   12916 	now = isc_time_now();
   12917 	zone_settimer(zone, &now);
   12918 	UNLOCK_ZONE(zone);
   12919 }
   12920 
   12921 static void
   12922 zone_notify(dns_zone_t *zone, isc_time_t *now) {
   12923 	dns_dbnode_t *node = NULL;
   12924 	dns_db_t *zonedb = NULL;
   12925 	dns_dbversion_t *version = NULL;
   12926 	dns_name_t *origin = NULL;
   12927 	dns_name_t primary;
   12928 	dns_rdata_ns_t ns;
   12929 	dns_rdata_soa_t soa;
   12930 	uint32_t serial;
   12931 	dns_rdata_t rdata = DNS_RDATA_INIT;
   12932 	dns_rdataset_t nsrdset;
   12933 	dns_rdataset_t soardset;
   12934 	isc_result_t result;
   12935 	isc_sockaddr_t src;
   12936 	isc_sockaddr_t dst;
   12937 	bool isqueued;
   12938 	dns_notifytype_t notifytype;
   12939 	unsigned int flags = 0;
   12940 	bool loggednotify = false;
   12941 	bool startup;
   12942 
   12943 	REQUIRE(DNS_ZONE_VALID(zone));
   12944 
   12945 	LOCK_ZONE(zone);
   12946 	startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   12947 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY |
   12948 				       DNS_ZONEFLG_NEEDSTARTUPNOTIFY |
   12949 				       DNS_ZONEFLG_NOTIFYNODEFER |
   12950 				       DNS_ZONEFLG_NOTIFYDEFERRED);
   12951 	notifytype = zone->notifytype;
   12952 	DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
   12953 	UNLOCK_ZONE(zone);
   12954 
   12955 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
   12956 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   12957 	{
   12958 		return;
   12959 	}
   12960 
   12961 	if (notifytype == dns_notifytype_no) {
   12962 		return;
   12963 	}
   12964 
   12965 	if (notifytype == dns_notifytype_masteronly &&
   12966 	    zone->type != dns_zone_primary)
   12967 	{
   12968 		return;
   12969 	}
   12970 
   12971 	origin = &zone->origin;
   12972 
   12973 	/*
   12974 	 * If the zone is dialup we are done as we don't want to send
   12975 	 * the current soa so as to force a refresh query.
   12976 	 */
   12977 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
   12978 		flags |= DNS_NOTIFY_NOSOA;
   12979 	}
   12980 
   12981 	/*
   12982 	 * Record that this was a notify due to starting up.
   12983 	 */
   12984 	if (startup) {
   12985 		flags |= DNS_NOTIFY_STARTUP;
   12986 	}
   12987 
   12988 	/*
   12989 	 * Get SOA RRset.
   12990 	 */
   12991 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   12992 	if (zone->db != NULL) {
   12993 		dns_db_attach(zone->db, &zonedb);
   12994 	}
   12995 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   12996 	if (zonedb == NULL) {
   12997 		return;
   12998 	}
   12999 	dns_db_currentversion(zonedb, &version);
   13000 	result = dns_db_findnode(zonedb, origin, false, &node);
   13001 	if (result != ISC_R_SUCCESS) {
   13002 		goto cleanup1;
   13003 	}
   13004 
   13005 	dns_rdataset_init(&soardset);
   13006 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
   13007 				     dns_rdatatype_none, 0, &soardset, NULL);
   13008 	if (result != ISC_R_SUCCESS) {
   13009 		goto cleanup2;
   13010 	}
   13011 
   13012 	/*
   13013 	 * Find serial and primary server's name.
   13014 	 */
   13015 	dns_name_init(&primary, NULL);
   13016 	result = dns_rdataset_first(&soardset);
   13017 	if (result != ISC_R_SUCCESS) {
   13018 		goto cleanup3;
   13019 	}
   13020 	dns_rdataset_current(&soardset, &rdata);
   13021 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   13022 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   13023 	dns_rdata_reset(&rdata);
   13024 	dns_name_dup(&soa.origin, zone->mctx, &primary);
   13025 	serial = soa.serial;
   13026 	dns_rdataset_disassociate(&soardset);
   13027 
   13028 	/*
   13029 	 * Enqueue notify requests for 'also-notify' servers.
   13030 	 */
   13031 	LOCK_ZONE(zone);
   13032 
   13033 	dns_remote_reset(&zone->notify, false);
   13034 	while (!dns_remote_done(&zone->notify)) {
   13035 		dns_tsigkey_t *key = NULL;
   13036 		dns_transport_t *transport = NULL;
   13037 		dns_notify_t *notify = NULL;
   13038 		dns_view_t *view = dns_zone_getview(zone);
   13039 
   13040 		if (dns_remote_keyname(&zone->notify) != NULL) {
   13041 			dns_name_t *keyname = dns_remote_keyname(&zone->notify);
   13042 			(void)dns_view_gettsig(view, keyname, &key);
   13043 		}
   13044 
   13045 		if (dns_remote_tlsname(&zone->notify) != NULL) {
   13046 			dns_name_t *tlsname = dns_remote_tlsname(&zone->notify);
   13047 			result = dns_view_gettransport(view, DNS_TRANSPORT_TLS,
   13048 						       tlsname, &transport);
   13049 
   13050 			if (result == ISC_R_SUCCESS) {
   13051 				notify_log(
   13052 					zone, ISC_LOG_INFO,
   13053 					"got TLS configuration for a notify");
   13054 			} else {
   13055 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   13056 					      ISC_LOG_ERROR,
   13057 					      "could not get TLS configuration "
   13058 					      "for zone transfer: %s",
   13059 					      isc_result_totext(result));
   13060 				goto next;
   13061 			}
   13062 
   13063 			flags |= DNS_NOTIFY_TCP;
   13064 		}
   13065 
   13066 		/* TODO: glue the transport to the notify */
   13067 
   13068 		dst = dns_remote_curraddr(&zone->notify);
   13069 		src = dns_remote_sourceaddr(&zone->notify);
   13070 		INSIST(isc_sockaddr_pf(&src) == isc_sockaddr_pf(&dst));
   13071 
   13072 		if (isc_sockaddr_disabled(&dst)) {
   13073 			goto next;
   13074 		}
   13075 
   13076 		if (notify_isqueued(zone, flags, NULL, &dst, key, transport)) {
   13077 			if (key != NULL) {
   13078 				dns_tsigkey_detach(&key);
   13079 			}
   13080 			if (transport != NULL) {
   13081 				dns_transport_detach(&transport);
   13082 			}
   13083 			goto next;
   13084 		}
   13085 
   13086 		result = notify_create(zone->mctx, flags, &notify);
   13087 		if (result != ISC_R_SUCCESS) {
   13088 			if (key != NULL) {
   13089 				dns_tsigkey_detach(&key);
   13090 			}
   13091 			if (transport != NULL) {
   13092 				dns_transport_detach(&transport);
   13093 			}
   13094 			goto next;
   13095 		}
   13096 
   13097 		zone_iattach(zone, &notify->zone);
   13098 		notify->src = src;
   13099 		notify->dst = dst;
   13100 
   13101 		INSIST(notify->key == NULL);
   13102 
   13103 		if (key != NULL) {
   13104 			notify->key = key;
   13105 			key = NULL;
   13106 		}
   13107 
   13108 		INSIST(notify->transport == NULL);
   13109 		if (transport != NULL) {
   13110 			notify->transport = transport;
   13111 			transport = NULL;
   13112 		}
   13113 
   13114 		ISC_LIST_APPEND(zone->notifies, notify, link);
   13115 		result = notify_send_queue(notify, startup);
   13116 		if (result != ISC_R_SUCCESS) {
   13117 			notify_destroy(notify, true);
   13118 		}
   13119 		if (!loggednotify) {
   13120 			notify_log(zone, ISC_LOG_INFO,
   13121 				   "sending notifies (serial %u)", serial);
   13122 			loggednotify = true;
   13123 		}
   13124 	next:
   13125 		flags &= ~DNS_NOTIFY_TCP;
   13126 		dns_remote_next(&zone->notify, false);
   13127 	}
   13128 	UNLOCK_ZONE(zone);
   13129 
   13130 	if (notifytype == dns_notifytype_explicit) {
   13131 		goto cleanup3;
   13132 	}
   13133 
   13134 	/*
   13135 	 * Process NS RRset to generate notifies.
   13136 	 */
   13137 
   13138 	dns_rdataset_init(&nsrdset);
   13139 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
   13140 				     dns_rdatatype_none, 0, &nsrdset, NULL);
   13141 	if (result != ISC_R_SUCCESS) {
   13142 		goto cleanup3;
   13143 	}
   13144 
   13145 	result = dns_rdataset_first(&nsrdset);
   13146 	while (result == ISC_R_SUCCESS) {
   13147 		dns_notify_t *notify = NULL;
   13148 
   13149 		dns_rdataset_current(&nsrdset, &rdata);
   13150 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
   13151 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   13152 		dns_rdata_reset(&rdata);
   13153 		/*
   13154 		 * Don't notify the primary server unless explicitly
   13155 		 * configured to do so.
   13156 		 */
   13157 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
   13158 		    dns_name_compare(&primary, &ns.name) == 0)
   13159 		{
   13160 			result = dns_rdataset_next(&nsrdset);
   13161 			continue;
   13162 		}
   13163 
   13164 		if (!loggednotify) {
   13165 			notify_log(zone, ISC_LOG_INFO,
   13166 				   "sending notifies (serial %u)", serial);
   13167 			loggednotify = true;
   13168 		}
   13169 
   13170 		LOCK_ZONE(zone);
   13171 		isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL,
   13172 					   NULL);
   13173 		UNLOCK_ZONE(zone);
   13174 		if (isqueued) {
   13175 			result = dns_rdataset_next(&nsrdset);
   13176 			continue;
   13177 		}
   13178 		result = notify_create(zone->mctx, flags, &notify);
   13179 		if (result != ISC_R_SUCCESS) {
   13180 			continue;
   13181 		}
   13182 		dns_zone_iattach(zone, &notify->zone);
   13183 		dns_name_dup(&ns.name, zone->mctx, &notify->ns);
   13184 		LOCK_ZONE(zone);
   13185 		ISC_LIST_APPEND(zone->notifies, notify, link);
   13186 		UNLOCK_ZONE(zone);
   13187 		notify_find_address(notify);
   13188 		result = dns_rdataset_next(&nsrdset);
   13189 	}
   13190 	dns_rdataset_disassociate(&nsrdset);
   13191 
   13192 cleanup3:
   13193 	if (dns_name_dynamic(&primary)) {
   13194 		dns_name_free(&primary, zone->mctx);
   13195 	}
   13196 cleanup2:
   13197 	dns_db_detachnode(zonedb, &node);
   13198 cleanup1:
   13199 	dns_db_closeversion(zonedb, &version, false);
   13200 	dns_db_detach(&zonedb);
   13201 }
   13202 
   13203 /***
   13204  *** Private
   13205  ***/
   13206 static void
   13207 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, dns_name_t *name,
   13208 	     dns_message_t **messagep) {
   13209 	dns_message_t *message = NULL;
   13210 	dns_name_t *qname = NULL;
   13211 	dns_rdataset_t *qrdataset = NULL;
   13212 
   13213 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER,
   13214 			   &message);
   13215 
   13216 	message->opcode = dns_opcode_query;
   13217 	message->rdclass = zone->rdclass;
   13218 
   13219 	dns_message_gettempname(message, &qname);
   13220 
   13221 	dns_message_gettemprdataset(message, &qrdataset);
   13222 
   13223 	/*
   13224 	 * Make question.
   13225 	 */
   13226 	dns_name_clone(name, qname);
   13227 	dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
   13228 	ISC_LIST_APPEND(qname->list, qrdataset, link);
   13229 	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
   13230 
   13231 	*messagep = message;
   13232 }
   13233 
   13234 static isc_result_t
   13235 add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
   13236 	bool reqexpire) {
   13237 	isc_result_t result;
   13238 	dns_rdataset_t *rdataset = NULL;
   13239 	dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
   13240 	int count = 0;
   13241 
   13242 	/* Set EDNS options if applicable. */
   13243 	if (reqnsid) {
   13244 		INSIST(count < DNS_EDNSOPTIONS);
   13245 		ednsopts[count].code = DNS_OPT_NSID;
   13246 		ednsopts[count].length = 0;
   13247 		ednsopts[count].value = NULL;
   13248 		count++;
   13249 	}
   13250 	if (reqexpire) {
   13251 		INSIST(count < DNS_EDNSOPTIONS);
   13252 		ednsopts[count].code = DNS_OPT_EXPIRE;
   13253 		ednsopts[count].length = 0;
   13254 		ednsopts[count].value = NULL;
   13255 		count++;
   13256 	}
   13257 	result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
   13258 				      ednsopts, count);
   13259 	if (result != ISC_R_SUCCESS) {
   13260 		return result;
   13261 	}
   13262 
   13263 	return dns_message_setopt(message, rdataset);
   13264 }
   13265 
   13266 /*
   13267  * Called when stub zone update is finished.
   13268  * Update zone refresh, retry, expire values accordingly with
   13269  * SOA received from primary, sync database to file, restart
   13270  * zone management timer.
   13271  */
   13272 static void
   13273 stub_finish_zone_update(dns_stub_t *stub, isc_time_t now) {
   13274 	uint32_t refresh, retry, expire;
   13275 	isc_result_t result;
   13276 	isc_interval_t i;
   13277 	unsigned int soacount;
   13278 	dns_zone_t *zone = stub->zone;
   13279 
   13280 	/*
   13281 	 * Tidy up.
   13282 	 */
   13283 	dns_db_closeversion(stub->db, &stub->version, true);
   13284 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   13285 	if (zone->db == NULL) {
   13286 		zone_attachdb(zone, stub->db);
   13287 	}
   13288 	result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL, NULL,
   13289 				  &refresh, &retry, &expire, NULL, NULL);
   13290 	if (result == ISC_R_SUCCESS && soacount > 0U) {
   13291 		zone->refresh = RANGE(refresh, zone->minrefresh,
   13292 				      zone->maxrefresh);
   13293 		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
   13294 		zone->expire = RANGE(expire, zone->refresh + zone->retry,
   13295 				     DNS_MAX_EXPIRE);
   13296 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   13297 	}
   13298 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   13299 	dns_db_detach(&stub->db);
   13300 
   13301 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   13302 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   13303 	DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
   13304 	isc_interval_set(&i, zone->expire, 0);
   13305 	DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
   13306 
   13307 	if (zone->masterfile != NULL) {
   13308 		zone_needdump(zone, 0);
   13309 	}
   13310 
   13311 	zone_settimer(zone, &now);
   13312 }
   13313 
   13314 /*
   13315  * Process answers for A and AAAA queries when
   13316  * resolving nameserver addresses for which glue
   13317  * was missing in a previous answer for a NS query.
   13318  */
   13319 static void
   13320 stub_glue_response(void *arg) {
   13321 	dns_request_t *request = (dns_request_t *)arg;
   13322 	struct stub_glue_request *sgr = dns_request_getarg(request);
   13323 	struct stub_cb_args *cb_args = sgr->args;
   13324 	dns_stub_t *stub = cb_args->stub;
   13325 	dns_message_t *msg = NULL;
   13326 	dns_zone_t *zone = NULL;
   13327 	char primary[ISC_SOCKADDR_FORMATSIZE];
   13328 	char source[ISC_SOCKADDR_FORMATSIZE];
   13329 	uint32_t addr_count, cnamecnt;
   13330 	isc_result_t result;
   13331 	isc_sockaddr_t curraddr;
   13332 	isc_time_t now;
   13333 	dns_rdataset_t *addr_rdataset = NULL;
   13334 	dns_dbnode_t *node = NULL;
   13335 
   13336 	INSIST(DNS_STUB_VALID(stub));
   13337 
   13338 	zone = stub->zone;
   13339 
   13340 	ENTER;
   13341 
   13342 	now = isc_time_now();
   13343 
   13344 	LOCK_ZONE(zone);
   13345 
   13346 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   13347 		zone_debuglog(zone, __func__, 1, "exiting");
   13348 		goto cleanup;
   13349 	}
   13350 
   13351 	curraddr = dns_remote_curraddr(&zone->primaries);
   13352 	isc_sockaddr_format(&curraddr, primary, sizeof(primary));
   13353 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   13354 
   13355 	if (dns_request_getresult(request) != ISC_R_SUCCESS) {
   13356 		dns_zonemgr_unreachableadd(zone->zmgr, &curraddr,
   13357 					   &zone->sourceaddr, &now);
   13358 		dns_zone_log(zone, ISC_LOG_INFO,
   13359 			     "could not refresh stub from primary %s"
   13360 			     " (source %s): %s",
   13361 			     primary, source,
   13362 			     isc_result_totext(dns_request_getresult(request)));
   13363 		goto cleanup;
   13364 	}
   13365 
   13366 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
   13367 			   &msg);
   13368 	result = dns_request_getresponse(request, msg, 0);
   13369 	if (result != ISC_R_SUCCESS) {
   13370 		dns_zone_log(zone, ISC_LOG_INFO,
   13371 			     "refreshing stub: unable to parse response (%s)",
   13372 			     isc_result_totext(result));
   13373 		goto cleanup;
   13374 	}
   13375 
   13376 	/*
   13377 	 * Unexpected opcode.
   13378 	 */
   13379 	if (msg->opcode != dns_opcode_query) {
   13380 		char opcode[128];
   13381 		isc_buffer_t rb;
   13382 
   13383 		isc_buffer_init(&rb, opcode, sizeof(opcode));
   13384 		(void)dns_opcode_totext(msg->opcode, &rb);
   13385 
   13386 		dns_zone_log(zone, ISC_LOG_INFO,
   13387 			     "refreshing stub: "
   13388 			     "unexpected opcode (%.*s) from %s (source %s)",
   13389 			     (int)rb.used, opcode, primary, source);
   13390 		goto cleanup;
   13391 	}
   13392 
   13393 	/*
   13394 	 * Unexpected rcode.
   13395 	 */
   13396 	if (msg->rcode != dns_rcode_noerror) {
   13397 		char rcode[128];
   13398 		isc_buffer_t rb;
   13399 
   13400 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   13401 		(void)dns_rcode_totext(msg->rcode, &rb);
   13402 
   13403 		dns_zone_log(zone, ISC_LOG_INFO,
   13404 			     "refreshing stub: "
   13405 			     "unexpected rcode (%.*s) from %s (source %s)",
   13406 			     (int)rb.used, rcode, primary, source);
   13407 		goto cleanup;
   13408 	}
   13409 
   13410 	/*
   13411 	 * We need complete messages.
   13412 	 */
   13413 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
   13414 		if (dns_request_usedtcp(request)) {
   13415 			dns_zone_log(zone, ISC_LOG_INFO,
   13416 				     "refreshing stub: truncated TCP "
   13417 				     "response from primary %s (source %s)",
   13418 				     primary, source);
   13419 		}
   13420 		goto cleanup;
   13421 	}
   13422 
   13423 	/*
   13424 	 * If non-auth log.
   13425 	 */
   13426 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
   13427 		dns_zone_log(zone, ISC_LOG_INFO,
   13428 			     "refreshing stub: "
   13429 			     "non-authoritative answer from "
   13430 			     "primary %s (source %s)",
   13431 			     primary, source);
   13432 		goto cleanup;
   13433 	}
   13434 
   13435 	/*
   13436 	 * Sanity checks.
   13437 	 */
   13438 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
   13439 	addr_count = message_count(msg, DNS_SECTION_ANSWER,
   13440 				   sgr->ipv4 ? dns_rdatatype_a
   13441 					     : dns_rdatatype_aaaa);
   13442 
   13443 	if (cnamecnt != 0) {
   13444 		dns_zone_log(zone, ISC_LOG_INFO,
   13445 			     "refreshing stub: unexpected CNAME response "
   13446 			     "from primary %s (source %s)",
   13447 			     primary, source);
   13448 		goto cleanup;
   13449 	}
   13450 
   13451 	if (addr_count == 0) {
   13452 		dns_zone_log(zone, ISC_LOG_INFO,
   13453 			     "refreshing stub: no %s records in response "
   13454 			     "from primary %s (source %s)",
   13455 			     sgr->ipv4 ? "A" : "AAAA", primary, source);
   13456 		goto cleanup;
   13457 	}
   13458 	/*
   13459 	 * Extract A or AAAA RRset from message.
   13460 	 */
   13461 	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &sgr->name,
   13462 				      sgr->ipv4 ? dns_rdatatype_a
   13463 						: dns_rdatatype_aaaa,
   13464 				      dns_rdatatype_none, NULL, &addr_rdataset);
   13465 	if (result != ISC_R_SUCCESS) {
   13466 		if (result != DNS_R_NXDOMAIN && result != DNS_R_NXRRSET) {
   13467 			char namebuf[DNS_NAME_FORMATSIZE];
   13468 			dns_name_format(&sgr->name, namebuf, sizeof(namebuf));
   13469 			dns_zone_log(
   13470 				zone, ISC_LOG_INFO,
   13471 				"refreshing stub: dns_message_findname(%s/%s) "
   13472 				"failed (%s)",
   13473 				namebuf, sgr->ipv4 ? "A" : "AAAA",
   13474 				isc_result_totext(result));
   13475 		}
   13476 		goto cleanup;
   13477 	}
   13478 
   13479 	result = dns_db_findnode(stub->db, &sgr->name, true, &node);
   13480 	if (result != ISC_R_SUCCESS) {
   13481 		dns_zone_log(zone, ISC_LOG_INFO,
   13482 			     "refreshing stub: "
   13483 			     "dns_db_findnode() failed: %s",
   13484 			     isc_result_totext(result));
   13485 		goto cleanup;
   13486 	}
   13487 
   13488 	result = dns_db_addrdataset(stub->db, node, stub->version, 0,
   13489 				    addr_rdataset, 0, NULL);
   13490 	if (result != ISC_R_SUCCESS) {
   13491 		dns_zone_log(zone, ISC_LOG_INFO,
   13492 			     "refreshing stub: "
   13493 			     "dns_db_addrdataset() failed: %s",
   13494 			     isc_result_totext(result));
   13495 	}
   13496 	dns_db_detachnode(stub->db, &node);
   13497 
   13498 cleanup:
   13499 	if (msg != NULL) {
   13500 		dns_message_detach(&msg);
   13501 	}
   13502 
   13503 	dns_name_free(&sgr->name, zone->mctx);
   13504 	dns_request_destroy(&sgr->request);
   13505 	isc_mem_put(zone->mctx, sgr, sizeof(*sgr));
   13506 
   13507 	/* If last request, release all related resources */
   13508 	if (atomic_fetch_sub_release(&stub->pending_requests, 1) == 1) {
   13509 		isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
   13510 		stub_finish_zone_update(stub, now);
   13511 		UNLOCK_ZONE(zone);
   13512 		stub->magic = 0;
   13513 		dns_zone_idetach(&stub->zone);
   13514 		INSIST(stub->db == NULL);
   13515 		INSIST(stub->version == NULL);
   13516 		isc_mem_put(stub->mctx, stub, sizeof(*stub));
   13517 	} else {
   13518 		UNLOCK_ZONE(zone);
   13519 	}
   13520 }
   13521 
   13522 /*
   13523  * Create and send an A or AAAA query to the primary
   13524  * server of the stub zone given.
   13525  */
   13526 static isc_result_t
   13527 stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4,
   13528 				const dns_name_t *name) {
   13529 	dns_message_t *message = NULL;
   13530 	dns_zone_t *zone;
   13531 	isc_result_t result;
   13532 	struct stub_glue_request *sgr;
   13533 	isc_sockaddr_t curraddr;
   13534 
   13535 	zone = args->stub->zone;
   13536 	sgr = isc_mem_get(zone->mctx, sizeof(*sgr));
   13537 	*sgr = (struct stub_glue_request){
   13538 		.args = args,
   13539 		.name = (dns_name_t)DNS_NAME_INITEMPTY,
   13540 		.ipv4 = ipv4,
   13541 	};
   13542 
   13543 	dns_name_dup(name, zone->mctx, &sgr->name);
   13544 
   13545 	create_query(zone, ipv4 ? dns_rdatatype_a : dns_rdatatype_aaaa,
   13546 		     &sgr->name, &message);
   13547 
   13548 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   13549 		result = add_opt(message, args->udpsize, args->reqnsid, false);
   13550 		if (result != ISC_R_SUCCESS) {
   13551 			zone_debuglog(zone, __func__, 1,
   13552 				      "unable to add opt record: %s",
   13553 				      isc_result_totext(result));
   13554 			goto fail;
   13555 		}
   13556 	}
   13557 
   13558 	atomic_fetch_add_release(&args->stub->pending_requests, 1);
   13559 
   13560 	curraddr = dns_remote_curraddr(&zone->primaries);
   13561 	result = dns_request_create(
   13562 		zone->view->requestmgr, message, &zone->sourceaddr, &curraddr,
   13563 		NULL, NULL, DNS_REQUESTOPT_TCP, args->tsig_key,
   13564 		args->timeout * 3, args->timeout, 2, zone->loop,
   13565 		stub_glue_response, sgr, &sgr->request);
   13566 
   13567 	if (result != ISC_R_SUCCESS) {
   13568 		uint_fast32_t pr;
   13569 		pr = atomic_fetch_sub_release(&args->stub->pending_requests, 1);
   13570 		INSIST(pr > 1);
   13571 		zone_debuglog(zone, __func__, 1,
   13572 			      "dns_request_create() failed: %s",
   13573 			      isc_result_totext(result));
   13574 		goto fail;
   13575 	}
   13576 
   13577 	dns_message_detach(&message);
   13578 
   13579 	return ISC_R_SUCCESS;
   13580 
   13581 fail:
   13582 	dns_name_free(&sgr->name, zone->mctx);
   13583 	isc_mem_put(zone->mctx, sgr, sizeof(*sgr));
   13584 
   13585 	if (message != NULL) {
   13586 		dns_message_detach(&message);
   13587 	}
   13588 
   13589 	return result;
   13590 }
   13591 
   13592 static isc_result_t
   13593 save_nsrrset(dns_message_t *message, dns_name_t *name,
   13594 	     struct stub_cb_args *cb_args, dns_db_t *db,
   13595 	     dns_dbversion_t *version) {
   13596 	dns_rdataset_t *nsrdataset = NULL;
   13597 	dns_rdataset_t *rdataset = NULL;
   13598 	dns_dbnode_t *node = NULL;
   13599 	dns_rdata_ns_t ns;
   13600 	isc_result_t result;
   13601 	dns_rdata_t rdata = DNS_RDATA_INIT;
   13602 	bool has_glue = false;
   13603 	dns_name_t *ns_name;
   13604 	/*
   13605 	 * List of NS entries in answer, keep names that will be used
   13606 	 * to resolve missing A/AAAA glue for each entry.
   13607 	 */
   13608 	dns_namelist_t ns_list;
   13609 	ISC_LIST_INIT(ns_list);
   13610 
   13611 	/*
   13612 	 * Extract NS RRset from message.
   13613 	 */
   13614 	result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
   13615 				      dns_rdatatype_ns, dns_rdatatype_none,
   13616 				      NULL, &nsrdataset);
   13617 	if (result != ISC_R_SUCCESS) {
   13618 		goto done;
   13619 	}
   13620 
   13621 	/*
   13622 	 * Add NS rdataset.
   13623 	 */
   13624 	result = dns_db_findnode(db, name, true, &node);
   13625 	if (result != ISC_R_SUCCESS) {
   13626 		goto done;
   13627 	}
   13628 	result = dns_db_addrdataset(db, node, version, 0, nsrdataset, 0, NULL);
   13629 	dns_db_detachnode(db, &node);
   13630 	if (result != ISC_R_SUCCESS) {
   13631 		goto done;
   13632 	}
   13633 	/*
   13634 	 * Add glue rdatasets.
   13635 	 */
   13636 	for (result = dns_rdataset_first(nsrdataset); result == ISC_R_SUCCESS;
   13637 	     result = dns_rdataset_next(nsrdataset))
   13638 	{
   13639 		dns_rdataset_current(nsrdataset, &rdata);
   13640 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
   13641 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   13642 		dns_rdata_reset(&rdata);
   13643 
   13644 		if (!dns_name_issubdomain(&ns.name, name)) {
   13645 			continue;
   13646 		}
   13647 		rdataset = NULL;
   13648 		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
   13649 					      &ns.name, dns_rdatatype_aaaa,
   13650 					      dns_rdatatype_none, NULL,
   13651 					      &rdataset);
   13652 		if (result == ISC_R_SUCCESS) {
   13653 			has_glue = true;
   13654 			result = dns_db_findnode(db, &ns.name, true, &node);
   13655 			if (result != ISC_R_SUCCESS) {
   13656 				goto done;
   13657 			}
   13658 			result = dns_db_addrdataset(db, node, version, 0,
   13659 						    rdataset, 0, NULL);
   13660 			dns_db_detachnode(db, &node);
   13661 			if (result != ISC_R_SUCCESS) {
   13662 				goto done;
   13663 			}
   13664 		}
   13665 
   13666 		rdataset = NULL;
   13667 		result = dns_message_findname(
   13668 			message, DNS_SECTION_ADDITIONAL, &ns.name,
   13669 			dns_rdatatype_a, dns_rdatatype_none, NULL, &rdataset);
   13670 		if (result == ISC_R_SUCCESS) {
   13671 			has_glue = true;
   13672 			result = dns_db_findnode(db, &ns.name, true, &node);
   13673 			if (result != ISC_R_SUCCESS) {
   13674 				goto done;
   13675 			}
   13676 			result = dns_db_addrdataset(db, node, version, 0,
   13677 						    rdataset, 0, NULL);
   13678 			dns_db_detachnode(db, &node);
   13679 			if (result != ISC_R_SUCCESS) {
   13680 				goto done;
   13681 			}
   13682 		}
   13683 
   13684 		/*
   13685 		 * If no glue is found so far, we add the name to the list to
   13686 		 * resolve the A/AAAA glue later. If any glue is found in any
   13687 		 * iteration step, this list will be discarded and only the glue
   13688 		 * provided in this message will be used.
   13689 		 */
   13690 		if (!has_glue && dns_name_issubdomain(&ns.name, name)) {
   13691 			dns_name_t *tmp_name;
   13692 			tmp_name = isc_mem_get(cb_args->stub->mctx,
   13693 					       sizeof(*tmp_name));
   13694 			dns_name_init(tmp_name, NULL);
   13695 			dns_name_dup(&ns.name, cb_args->stub->mctx, tmp_name);
   13696 			ISC_LIST_APPEND(ns_list, tmp_name, link);
   13697 		}
   13698 	}
   13699 
   13700 	if (result != ISC_R_NOMORE) {
   13701 		goto done;
   13702 	}
   13703 
   13704 	/*
   13705 	 * If no glue records were found, we attempt to resolve A/AAAA
   13706 	 * for each NS entry found in the answer.
   13707 	 */
   13708 	if (!has_glue) {
   13709 		for (ns_name = ISC_LIST_HEAD(ns_list); ns_name != NULL;
   13710 		     ns_name = ISC_LIST_NEXT(ns_name, link))
   13711 		{
   13712 			/*
   13713 			 * Resolve NS IPv4 address/A.
   13714 			 */
   13715 			result = stub_request_nameserver_address(cb_args, true,
   13716 								 ns_name);
   13717 			if (result != ISC_R_SUCCESS) {
   13718 				goto done;
   13719 			}
   13720 			/*
   13721 			 * Resolve NS IPv6 address/AAAA.
   13722 			 */
   13723 			result = stub_request_nameserver_address(cb_args, false,
   13724 								 ns_name);
   13725 			if (result != ISC_R_SUCCESS) {
   13726 				goto done;
   13727 			}
   13728 		}
   13729 	}
   13730 
   13731 	result = ISC_R_SUCCESS;
   13732 
   13733 done:
   13734 	while ((ns_name = ISC_LIST_HEAD(ns_list)) != NULL) {
   13735 		ISC_LIST_UNLINK(ns_list, ns_name, link);
   13736 		dns_name_free(ns_name, cb_args->stub->mctx);
   13737 		isc_mem_put(cb_args->stub->mctx, ns_name, sizeof(*ns_name));
   13738 	}
   13739 	return result;
   13740 }
   13741 
   13742 static void
   13743 stub_callback(void *arg) {
   13744 	dns_request_t *request = (dns_request_t *)arg;
   13745 	struct stub_cb_args *cb_args = dns_request_getarg(request);
   13746 	dns_stub_t *stub = cb_args->stub;
   13747 	dns_message_t *msg = NULL;
   13748 	dns_zone_t *zone = NULL;
   13749 	char primary[ISC_SOCKADDR_FORMATSIZE];
   13750 	char source[ISC_SOCKADDR_FORMATSIZE];
   13751 	uint32_t nscnt, cnamecnt;
   13752 	isc_result_t result;
   13753 	isc_sockaddr_t curraddr;
   13754 	isc_time_t now;
   13755 	bool exiting = false;
   13756 
   13757 	INSIST(DNS_STUB_VALID(stub));
   13758 
   13759 	zone = stub->zone;
   13760 
   13761 	ENTER;
   13762 
   13763 	now = isc_time_now();
   13764 
   13765 	LOCK_ZONE(zone);
   13766 
   13767 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   13768 		goto exiting;
   13769 	}
   13770 
   13771 	curraddr = dns_remote_curraddr(&zone->primaries);
   13772 	isc_sockaddr_format(&curraddr, primary, sizeof(primary));
   13773 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   13774 
   13775 	result = dns_request_getresult(request);
   13776 	switch (result) {
   13777 	case ISC_R_SUCCESS:
   13778 		break;
   13779 	case ISC_R_SHUTTINGDOWN:
   13780 	case ISC_R_CANCELED:
   13781 		goto exiting;
   13782 	case ISC_R_TIMEDOUT:
   13783 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   13784 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   13785 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   13786 				     "refreshing stub: timeout retrying "
   13787 				     "without EDNS primary %s (source %s)",
   13788 				     primary, source);
   13789 			goto same_primary;
   13790 		}
   13791 		FALLTHROUGH;
   13792 	default:
   13793 		dns_zonemgr_unreachableadd(zone->zmgr, &curraddr,
   13794 					   &zone->sourceaddr, &now);
   13795 		dns_zone_log(zone, ISC_LOG_INFO,
   13796 			     "could not refresh stub from primary "
   13797 			     "%s (source %s): %s",
   13798 			     primary, source, isc_result_totext(result));
   13799 		goto next_primary;
   13800 	}
   13801 
   13802 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
   13803 			   &msg);
   13804 
   13805 	result = dns_request_getresponse(request, msg, 0);
   13806 	if (result != ISC_R_SUCCESS) {
   13807 		goto next_primary;
   13808 	}
   13809 
   13810 	/*
   13811 	 * Unexpected opcode.
   13812 	 */
   13813 	if (msg->opcode != dns_opcode_query) {
   13814 		char opcode[128];
   13815 		isc_buffer_t rb;
   13816 
   13817 		isc_buffer_init(&rb, opcode, sizeof(opcode));
   13818 		(void)dns_opcode_totext(msg->opcode, &rb);
   13819 
   13820 		dns_zone_log(zone, ISC_LOG_INFO,
   13821 			     "refreshing stub: "
   13822 			     "unexpected opcode (%.*s) from %s (source %s)",
   13823 			     (int)rb.used, opcode, primary, source);
   13824 		goto next_primary;
   13825 	}
   13826 
   13827 	/*
   13828 	 * Unexpected rcode.
   13829 	 */
   13830 	if (msg->rcode != dns_rcode_noerror) {
   13831 		char rcode[128];
   13832 		isc_buffer_t rb;
   13833 
   13834 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   13835 		(void)dns_rcode_totext(msg->rcode, &rb);
   13836 
   13837 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
   13838 		    (msg->rcode == dns_rcode_servfail ||
   13839 		     msg->rcode == dns_rcode_notimp ||
   13840 		     (msg->rcode == dns_rcode_formerr && msg->opt == NULL)))
   13841 		{
   13842 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   13843 				     "refreshing stub: rcode (%.*s) retrying "
   13844 				     "without EDNS primary %s (source %s)",
   13845 				     (int)rb.used, rcode, primary, source);
   13846 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   13847 			goto same_primary;
   13848 		}
   13849 
   13850 		dns_zone_log(zone, ISC_LOG_INFO,
   13851 			     "refreshing stub: "
   13852 			     "unexpected rcode (%.*s) from %s (source %s)",
   13853 			     (int)rb.used, rcode, primary, source);
   13854 		goto next_primary;
   13855 	}
   13856 
   13857 	/*
   13858 	 * We need complete messages.
   13859 	 */
   13860 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
   13861 		if (dns_request_usedtcp(request)) {
   13862 			dns_zone_log(zone, ISC_LOG_INFO,
   13863 				     "refreshing stub: truncated TCP "
   13864 				     "response from primary %s (source %s)",
   13865 				     primary, source);
   13866 			goto next_primary;
   13867 		}
   13868 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
   13869 		goto same_primary;
   13870 	}
   13871 
   13872 	/*
   13873 	 * If non-auth log and next primary.
   13874 	 */
   13875 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
   13876 		dns_zone_log(zone, ISC_LOG_INFO,
   13877 			     "refreshing stub: "
   13878 			     "non-authoritative answer from "
   13879 			     "primary %s (source %s)",
   13880 			     primary, source);
   13881 		goto next_primary;
   13882 	}
   13883 
   13884 	/*
   13885 	 * Sanity checks.
   13886 	 */
   13887 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
   13888 	nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
   13889 
   13890 	if (cnamecnt != 0) {
   13891 		dns_zone_log(zone, ISC_LOG_INFO,
   13892 			     "refreshing stub: unexpected CNAME response "
   13893 			     "from primary %s (source %s)",
   13894 			     primary, source);
   13895 		goto next_primary;
   13896 	}
   13897 
   13898 	if (nscnt == 0) {
   13899 		dns_zone_log(zone, ISC_LOG_INFO,
   13900 			     "refreshing stub: no NS records in response "
   13901 			     "from primary %s (source %s)",
   13902 			     primary, source);
   13903 		goto next_primary;
   13904 	}
   13905 
   13906 	atomic_fetch_add(&stub->pending_requests, 1);
   13907 
   13908 	/*
   13909 	 * Save answer.
   13910 	 */
   13911 	result = save_nsrrset(msg, &zone->origin, cb_args, stub->db,
   13912 			      stub->version);
   13913 	if (result != ISC_R_SUCCESS) {
   13914 		dns_zone_log(zone, ISC_LOG_INFO,
   13915 			     "refreshing stub: unable to save NS records "
   13916 			     "from primary %s (source %s)",
   13917 			     primary, source);
   13918 		goto next_primary;
   13919 	}
   13920 
   13921 	dns_message_detach(&msg);
   13922 	dns_request_destroy(&zone->request);
   13923 
   13924 	/*
   13925 	 * Check to see if there are no outstanding requests and
   13926 	 * finish off if that is so.
   13927 	 */
   13928 	if (atomic_fetch_sub(&stub->pending_requests, 1) == 1) {
   13929 		isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
   13930 		stub_finish_zone_update(stub, now);
   13931 		goto free_stub;
   13932 	}
   13933 
   13934 	UNLOCK_ZONE(zone);
   13935 	return;
   13936 
   13937 exiting:
   13938 	zone_debuglog(zone, __func__, 1, "exiting");
   13939 	exiting = true;
   13940 
   13941 next_primary:
   13942 	isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
   13943 	if (stub->version != NULL) {
   13944 		dns_db_closeversion(stub->db, &stub->version, false);
   13945 	}
   13946 	if (stub->db != NULL) {
   13947 		dns_db_detach(&stub->db);
   13948 	}
   13949 	if (msg != NULL) {
   13950 		dns_message_detach(&msg);
   13951 	}
   13952 	dns_request_destroy(&zone->request);
   13953 	/*
   13954 	 * Skip to next failed / untried primary.
   13955 	 */
   13956 	dns_remote_next(&zone->primaries, true);
   13957 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
   13958 	if (exiting || dns_remote_done(&zone->primaries)) {
   13959 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   13960 		zone_settimer(zone, &now);
   13961 		goto free_stub;
   13962 	}
   13963 	queue_soa_query(zone);
   13964 	goto free_stub;
   13965 
   13966 same_primary:
   13967 	isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
   13968 	if (msg != NULL) {
   13969 		dns_message_detach(&msg);
   13970 	}
   13971 	dns_request_destroy(&zone->request);
   13972 	ns_query(zone, NULL, stub);
   13973 	UNLOCK_ZONE(zone);
   13974 	return;
   13975 
   13976 free_stub:
   13977 	UNLOCK_ZONE(zone);
   13978 	stub->magic = 0;
   13979 	dns_zone_idetach(&stub->zone);
   13980 	INSIST(stub->db == NULL);
   13981 	INSIST(stub->version == NULL);
   13982 	isc_mem_put(stub->mctx, stub, sizeof(*stub));
   13983 }
   13984 
   13985 /*
   13986  * Get the EDNS EXPIRE option from the response and if it exists trim
   13987  * expire to be not more than it.
   13988  */
   13989 static void
   13990 get_edns_expire(dns_zone_t *zone, dns_message_t *message, uint32_t *expirep) {
   13991 	isc_result_t result;
   13992 	uint32_t expire;
   13993 	dns_rdata_t rdata = DNS_RDATA_INIT;
   13994 	isc_buffer_t optbuf;
   13995 	uint16_t optcode;
   13996 	uint16_t optlen;
   13997 
   13998 	REQUIRE(expirep != NULL);
   13999 	REQUIRE(message != NULL);
   14000 
   14001 	if (message->opt == NULL) {
   14002 		return;
   14003 	}
   14004 
   14005 	result = dns_rdataset_first(message->opt);
   14006 	if (result == ISC_R_SUCCESS) {
   14007 		dns_rdataset_current(message->opt, &rdata);
   14008 		isc_buffer_init(&optbuf, rdata.data, rdata.length);
   14009 		isc_buffer_add(&optbuf, rdata.length);
   14010 		while (isc_buffer_remaininglength(&optbuf) >= 4) {
   14011 			optcode = isc_buffer_getuint16(&optbuf);
   14012 			optlen = isc_buffer_getuint16(&optbuf);
   14013 			/*
   14014 			 * A EDNS EXPIRE response has a length of 4.
   14015 			 */
   14016 			if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
   14017 				isc_buffer_forward(&optbuf, optlen);
   14018 				continue;
   14019 			}
   14020 			expire = isc_buffer_getuint32(&optbuf);
   14021 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   14022 				     "got EDNS EXPIRE of %u", expire);
   14023 			/*
   14024 			 * Trim *expirep?
   14025 			 */
   14026 			if (expire < *expirep) {
   14027 				*expirep = expire;
   14028 			}
   14029 			break;
   14030 		}
   14031 	}
   14032 }
   14033 
   14034 /*
   14035  * Set the file modification time zone->expire seconds before expiretime.
   14036  */
   14037 static void
   14038 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
   14039 	isc_result_t result;
   14040 	isc_time_t when;
   14041 	isc_interval_t i;
   14042 
   14043 	isc_interval_set(&i, zone->expire, 0);
   14044 	result = isc_time_subtract(expiretime, &i, &when);
   14045 	if (result != ISC_R_SUCCESS) {
   14046 		return;
   14047 	}
   14048 
   14049 	result = ISC_R_FAILURE;
   14050 	if (zone->journal != NULL) {
   14051 		result = isc_file_settime(zone->journal, &when);
   14052 	}
   14053 	if (result == ISC_R_SUCCESS &&
   14054 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   14055 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
   14056 	{
   14057 		result = isc_file_settime(zone->masterfile, &when);
   14058 	} else if (result != ISC_R_SUCCESS) {
   14059 		result = isc_file_settime(zone->masterfile, &when);
   14060 	}
   14061 
   14062 	/*
   14063 	 * Someone removed the file from underneath us!
   14064 	 */
   14065 	if (result == ISC_R_FILENOTFOUND) {
   14066 		zone_needdump(zone, DNS_DUMP_DELAY);
   14067 	} else if (result != ISC_R_SUCCESS) {
   14068 		dns_zone_log(zone, ISC_LOG_ERROR,
   14069 			     "refresh: could not set "
   14070 			     "file modification time of '%s': %s",
   14071 			     zone->masterfile, isc_result_totext(result));
   14072 	}
   14073 }
   14074 
   14075 /*
   14076  * An SOA query has finished (successfully or not).
   14077  */
   14078 static void
   14079 refresh_callback(void *arg) {
   14080 	dns_request_t *request = (dns_request_t *)arg;
   14081 	dns_zone_t *zone = dns_request_getarg(request);
   14082 	dns_message_t *msg = NULL;
   14083 	uint32_t soacnt, cnamecnt, soacount, nscount;
   14084 	isc_time_t now;
   14085 	char primary[ISC_SOCKADDR_FORMATSIZE];
   14086 	char source[ISC_SOCKADDR_FORMATSIZE];
   14087 	dns_rdataset_t *rdataset = NULL;
   14088 	dns_rdata_t rdata = DNS_RDATA_INIT;
   14089 	dns_rdata_soa_t soa;
   14090 	isc_result_t result;
   14091 	const isc_result_t eresult = dns_request_getresult(request);
   14092 	isc_sockaddr_t curraddr;
   14093 	uint32_t serial, oldserial = 0;
   14094 	bool do_queue_xfrin = false;
   14095 
   14096 	INSIST(DNS_ZONE_VALID(zone));
   14097 
   14098 	ENTER;
   14099 
   14100 	if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   14101 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(3),
   14102 			      "refresh: request result: %s",
   14103 			      isc_result_totext(eresult));
   14104 	}
   14105 
   14106 	now = isc_time_now();
   14107 
   14108 	LOCK_ZONE(zone);
   14109 
   14110 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   14111 		goto exiting;
   14112 	}
   14113 
   14114 	/*
   14115 	 * If timeout, log and try the next primary
   14116 	 */
   14117 	curraddr = dns_remote_curraddr(&zone->primaries);
   14118 	isc_sockaddr_format(&curraddr, primary, sizeof(primary));
   14119 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   14120 
   14121 	switch (eresult) {
   14122 	case ISC_R_SUCCESS:
   14123 		break;
   14124 	case ISC_R_SHUTTINGDOWN:
   14125 	case ISC_R_CANCELED:
   14126 		goto exiting;
   14127 	case ISC_R_TIMEDOUT:
   14128 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   14129 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   14130 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14131 				      ISC_LOG_DEBUG(1),
   14132 				      "refresh: timeout retrying without EDNS "
   14133 				      "primary %s (source %s)",
   14134 				      primary, source);
   14135 			goto same_primary;
   14136 		} else if (!dns_request_usedtcp(request)) {
   14137 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14138 				      ISC_LOG_INFO,
   14139 				      "refresh: retry limit for "
   14140 				      "primary %s exceeded (source %s)",
   14141 				      primary, source);
   14142 			/* Try with secondary with TCP. */
   14143 			if ((zone->type == dns_zone_secondary ||
   14144 			     zone->type == dns_zone_mirror ||
   14145 			     zone->type == dns_zone_redirect) &&
   14146 			    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
   14147 			{
   14148 				if (!dns_zonemgr_unreachable(
   14149 					    zone->zmgr, &curraddr,
   14150 					    &zone->sourceaddr, &now))
   14151 				{
   14152 					DNS_ZONE_SETFLAG(
   14153 						zone,
   14154 						DNS_ZONEFLG_SOABEFOREAXFR);
   14155 					goto tcp_transfer;
   14156 				}
   14157 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14158 					      ISC_LOG_DEBUG(1),
   14159 					      "refresh: skipped tcp fallback "
   14160 					      "as primary %s (source %s) is "
   14161 					      "unreachable (cached)",
   14162 					      primary, source);
   14163 			}
   14164 			goto next_primary;
   14165 		}
   14166 		FALLTHROUGH;
   14167 	default:
   14168 		result = eresult;
   14169 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14170 			      "refresh: failure trying primary "
   14171 			      "%s (source %s): %s",
   14172 			      primary, source, isc_result_totext(result));
   14173 		goto next_primary;
   14174 	}
   14175 
   14176 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
   14177 			   &msg);
   14178 	result = dns_request_getresponse(request, msg, 0);
   14179 	if (result != ISC_R_SUCCESS) {
   14180 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14181 			      "refresh: failure trying primary "
   14182 			      "%s (source %s): %s",
   14183 			      primary, source, isc_result_totext(result));
   14184 		goto next_primary;
   14185 	}
   14186 
   14187 	/*
   14188 	 * Unexpected opcode.
   14189 	 */
   14190 	if (msg->opcode != dns_opcode_query) {
   14191 		char opcode[128];
   14192 		isc_buffer_t rb;
   14193 
   14194 		isc_buffer_init(&rb, opcode, sizeof(opcode));
   14195 		(void)dns_opcode_totext(msg->opcode, &rb);
   14196 
   14197 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14198 			      "refresh: "
   14199 			      "unexpected opcode (%.*s) from %s (source %s)",
   14200 			      (int)rb.used, opcode, primary, source);
   14201 		goto next_primary;
   14202 	}
   14203 
   14204 	/*
   14205 	 * Unexpected rcode.
   14206 	 */
   14207 	if (msg->rcode != dns_rcode_noerror) {
   14208 		char rcode[128];
   14209 		isc_buffer_t rb;
   14210 
   14211 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   14212 		(void)dns_rcode_totext(msg->rcode, &rb);
   14213 
   14214 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
   14215 		    (msg->rcode == dns_rcode_servfail ||
   14216 		     msg->rcode == dns_rcode_notimp ||
   14217 		     (msg->rcode == dns_rcode_formerr && msg->opt == NULL)))
   14218 		{
   14219 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14220 				      ISC_LOG_DEBUG(1),
   14221 				      "refresh: rcode (%.*s) retrying without "
   14222 				      "EDNS primary %s (source %s)",
   14223 				      (int)rb.used, rcode, primary, source);
   14224 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   14225 			goto same_primary;
   14226 		}
   14227 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
   14228 		    msg->rcode == dns_rcode_badvers)
   14229 		{
   14230 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14231 				      ISC_LOG_DEBUG(1),
   14232 				      "refresh: rcode (%.*s) retrying without "
   14233 				      "EDNS EXPIRE OPTION primary %s "
   14234 				      "(source %s)",
   14235 				      (int)rb.used, rcode, primary, source);
   14236 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   14237 			goto same_primary;
   14238 		}
   14239 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14240 			      "refresh: unexpected rcode (%.*s) from "
   14241 			      "primary %s (source %s)",
   14242 			      (int)rb.used, rcode, primary, source);
   14243 		/*
   14244 		 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
   14245 		 */
   14246 		if (msg->rcode == dns_rcode_refused &&
   14247 		    (zone->type == dns_zone_secondary ||
   14248 		     zone->type == dns_zone_mirror ||
   14249 		     zone->type == dns_zone_redirect))
   14250 		{
   14251 			goto tcp_transfer;
   14252 		}
   14253 		goto next_primary;
   14254 	}
   14255 
   14256 	/*
   14257 	 * If truncated punt to zone transfer which will query again.
   14258 	 */
   14259 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
   14260 		if (zone->type == dns_zone_secondary ||
   14261 		    zone->type == dns_zone_mirror ||
   14262 		    zone->type == dns_zone_redirect)
   14263 		{
   14264 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14265 				      ISC_LOG_INFO,
   14266 				      "refresh: truncated UDP answer, "
   14267 				      "initiating TCP zone xfer "
   14268 				      "for primary %s (source %s)",
   14269 				      primary, source);
   14270 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
   14271 			goto tcp_transfer;
   14272 		} else {
   14273 			INSIST(zone->type == dns_zone_stub);
   14274 			if (dns_request_usedtcp(request)) {
   14275 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14276 					      ISC_LOG_INFO,
   14277 					      "refresh: truncated TCP response "
   14278 					      "from primary %s (source %s)",
   14279 					      primary, source);
   14280 				goto next_primary;
   14281 			}
   14282 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
   14283 			goto same_primary;
   14284 		}
   14285 	}
   14286 
   14287 	/*
   14288 	 * If non-auth, log and try the next primary
   14289 	 */
   14290 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
   14291 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14292 			      "refresh: non-authoritative answer from "
   14293 			      "primary %s (source %s)",
   14294 			      primary, source);
   14295 		goto next_primary;
   14296 	}
   14297 
   14298 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
   14299 	soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
   14300 	nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
   14301 	soacount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_soa);
   14302 
   14303 	/*
   14304 	 * There should not be a CNAME record at top of zone.
   14305 	 */
   14306 	if (cnamecnt != 0) {
   14307 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14308 			      "refresh: CNAME at top of zone "
   14309 			      "in primary %s (source %s)",
   14310 			      primary, source);
   14311 		goto next_primary;
   14312 	}
   14313 
   14314 	/*
   14315 	 * If referral, log and try the next primary;
   14316 	 */
   14317 	if (soacnt == 0 && soacount == 0 && nscount != 0) {
   14318 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14319 			      "refresh: referral response "
   14320 			      "from primary %s (source %s)",
   14321 			      primary, source);
   14322 		goto next_primary;
   14323 	}
   14324 
   14325 	/*
   14326 	 * If nodata, log and try the next primary;
   14327 	 */
   14328 	if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
   14329 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14330 			      "refresh: NODATA response "
   14331 			      "from primary %s (source %s)",
   14332 			      primary, source);
   14333 		goto next_primary;
   14334 	}
   14335 
   14336 	/*
   14337 	 * Only one soa at top of zone.
   14338 	 */
   14339 	if (soacnt != 1) {
   14340 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14341 			      "refresh: answer SOA count (%d) != 1 "
   14342 			      "from primary %s (source %s)",
   14343 			      soacnt, primary, source);
   14344 		goto next_primary;
   14345 	}
   14346 
   14347 	/*
   14348 	 * Extract serial
   14349 	 */
   14350 	rdataset = NULL;
   14351 	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
   14352 				      dns_rdatatype_soa, dns_rdatatype_none,
   14353 				      NULL, &rdataset);
   14354 	if (result != ISC_R_SUCCESS) {
   14355 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14356 			      "refresh: unable to get SOA record "
   14357 			      "from primary %s (source %s)",
   14358 			      primary, source);
   14359 		goto next_primary;
   14360 	}
   14361 
   14362 	result = dns_rdataset_first(rdataset);
   14363 	if (result != ISC_R_SUCCESS) {
   14364 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   14365 			      "refresh: dns_rdataset_first() failed");
   14366 		goto next_primary;
   14367 	}
   14368 
   14369 	dns_rdataset_current(rdataset, &rdata);
   14370 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   14371 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14372 
   14373 	serial = soa.serial;
   14374 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   14375 		unsigned int dbsoacount;
   14376 		result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
   14377 					  NULL, &oldserial, NULL, NULL, NULL,
   14378 					  NULL, NULL);
   14379 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14380 		RUNTIME_CHECK(dbsoacount > 0U);
   14381 		zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__, 1,
   14382 			       "serial: new %u, old %u", serial, oldserial);
   14383 	} else {
   14384 		zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__, 1,
   14385 			       "serial: new %u, old not loaded", serial);
   14386 	}
   14387 
   14388 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
   14389 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
   14390 	    isc_serial_gt(serial, oldserial))
   14391 	{
   14392 		if (dns_zonemgr_unreachable(zone->zmgr, &curraddr,
   14393 					    &zone->sourceaddr, &now))
   14394 		{
   14395 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14396 				      ISC_LOG_INFO,
   14397 				      "refresh: skipping %s as primary %s "
   14398 				      "(source %s) is unreachable (cached)",
   14399 				      (zone->type == dns_zone_secondary ||
   14400 				       zone->type == dns_zone_mirror ||
   14401 				       zone->type == dns_zone_redirect)
   14402 					      ? "zone transfer"
   14403 					      : "NS query",
   14404 				      primary, source);
   14405 			goto next_primary;
   14406 		}
   14407 	tcp_transfer:
   14408 		dns_request_destroy(&zone->request);
   14409 		if (zone->type == dns_zone_secondary ||
   14410 		    zone->type == dns_zone_mirror ||
   14411 		    zone->type == dns_zone_redirect)
   14412 		{
   14413 			do_queue_xfrin = true;
   14414 		} else {
   14415 			INSIST(zone->type == dns_zone_stub);
   14416 			ns_query(zone, rdataset, NULL);
   14417 		}
   14418 		if (msg != NULL) {
   14419 			dns_message_detach(&msg);
   14420 		}
   14421 	} else if (isc_serial_eq(soa.serial, oldserial)) {
   14422 		isc_time_t expiretime;
   14423 		uint32_t expire;
   14424 
   14425 		/*
   14426 		 * Compute the new expire time based on this response.
   14427 		 */
   14428 		expire = zone->expire;
   14429 		get_edns_expire(zone, msg, &expire);
   14430 		DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
   14431 
   14432 		/*
   14433 		 * Has the expire time improved?
   14434 		 */
   14435 		if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
   14436 			zone->expiretime = expiretime;
   14437 			if (zone->masterfile != NULL) {
   14438 				setmodtime(zone, &expiretime);
   14439 			}
   14440 		}
   14441 
   14442 		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
   14443 		dns_remote_mark(&zone->primaries, true);
   14444 		goto next_primary;
   14445 	} else {
   14446 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) {
   14447 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14448 				      ISC_LOG_INFO,
   14449 				      "serial number (%u) "
   14450 				      "received from primary %s < ours (%u)",
   14451 				      soa.serial, primary, oldserial);
   14452 		} else {
   14453 			zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__,
   14454 				       1, "ahead");
   14455 		}
   14456 		dns_remote_mark(&zone->primaries, true);
   14457 		goto next_primary;
   14458 	}
   14459 	if (msg != NULL) {
   14460 		dns_message_detach(&msg);
   14461 	}
   14462 	goto detach;
   14463 
   14464 next_primary:
   14465 	if (msg != NULL) {
   14466 		dns_message_detach(&msg);
   14467 	}
   14468 	dns_request_destroy(&zone->request);
   14469 	/*
   14470 	 * Skip to next failed / untried primary.
   14471 	 */
   14472 	dns_remote_next(&zone->primaries, true);
   14473 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
   14474 	if (dns_remote_done(&zone->primaries)) {
   14475 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   14476 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
   14477 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   14478 			zone->refreshtime = now;
   14479 		}
   14480 		zone_settimer(zone, &now);
   14481 		goto detach;
   14482 	}
   14483 
   14484 	queue_soa_query(zone);
   14485 	goto detach;
   14486 
   14487 exiting:
   14488 	/*
   14489 	 * We can get here not only during shutdown, but also when the refresh
   14490 	 * is canceled during reconfiguration. In that case, make sure to clear
   14491 	 * the DNS_ZONEFLG_REFRESH flag so that future zone refreshes don't get
   14492 	 * stuck, and make sure a new refresh attempt is made again soon after
   14493 	 * the reconfiguration is complete.
   14494 	 */
   14495 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   14496 	zone->refreshtime = now;
   14497 	zone_settimer(zone, &now);
   14498 
   14499 	dns_request_destroy(&zone->request);
   14500 	goto detach;
   14501 
   14502 same_primary:
   14503 	if (msg != NULL) {
   14504 		dns_message_detach(&msg);
   14505 	}
   14506 	dns_request_destroy(&zone->request);
   14507 	queue_soa_query(zone);
   14508 
   14509 detach:
   14510 	if (do_queue_xfrin) {
   14511 		/* Shows in the statistics channel the duration of the step. */
   14512 		zone->xfrintime = isc_time_now();
   14513 	}
   14514 	UNLOCK_ZONE(zone);
   14515 	if (do_queue_xfrin) {
   14516 		queue_xfrin(zone);
   14517 	}
   14518 	dns_zone_idetach(&zone);
   14519 	return;
   14520 }
   14521 
   14522 struct soaquery {
   14523 	dns_zone_t *zone;
   14524 	isc_rlevent_t *rlevent;
   14525 };
   14526 
   14527 static void
   14528 queue_soa_query(dns_zone_t *zone) {
   14529 	isc_result_t result;
   14530 	struct soaquery *sq = NULL;
   14531 
   14532 	ENTER;
   14533 	/*
   14534 	 * Locked by caller
   14535 	 */
   14536 	REQUIRE(LOCKED_ZONE(zone));
   14537 
   14538 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   14539 		cancel_refresh(zone);
   14540 		return;
   14541 	}
   14542 
   14543 	sq = isc_mem_get(zone->mctx, sizeof(*sq));
   14544 	*sq = (struct soaquery){ .zone = NULL };
   14545 
   14546 	/* Shows in the statistics channel the duration of the current step. */
   14547 	zone->xfrintime = isc_time_now();
   14548 
   14549 	/*
   14550 	 * Attach so that we won't clean up until the event is delivered.
   14551 	 */
   14552 	zone_iattach(zone, &sq->zone);
   14553 	result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->loop,
   14554 					 soa_query, sq, &sq->rlevent);
   14555 	if (result != ISC_R_SUCCESS) {
   14556 		zone_idetach(&sq->zone);
   14557 		isc_mem_put(zone->mctx, sq, sizeof(*sq));
   14558 		cancel_refresh(zone);
   14559 	}
   14560 }
   14561 
   14562 static void
   14563 soa_query(void *arg) {
   14564 	struct soaquery *sq = (struct soaquery *)arg;
   14565 	dns_zone_t *zone = sq->zone;
   14566 	isc_result_t result = ISC_R_FAILURE;
   14567 	dns_message_t *message = NULL;
   14568 	isc_netaddr_t primaryip;
   14569 	dns_tsigkey_t *key = NULL;
   14570 	dns_transport_t *transport = NULL;
   14571 	uint32_t options;
   14572 	bool cancel = true;
   14573 	int timeout;
   14574 	bool have_xfrsource = false, reqnsid, reqexpire;
   14575 	uint16_t udpsize = SEND_BUFFER_SIZE;
   14576 	isc_sockaddr_t curraddr, sourceaddr;
   14577 	bool do_queue_xfrin = false;
   14578 
   14579 	REQUIRE(DNS_ZONE_VALID(zone));
   14580 
   14581 	ENTER;
   14582 
   14583 	LOCK_ZONE(zone);
   14584 	if (sq->rlevent->canceled || DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
   14585 	    zone->view->requestmgr == NULL)
   14586 	{
   14587 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   14588 			cancel = false;
   14589 		}
   14590 		goto cleanup;
   14591 	}
   14592 
   14593 again:
   14594 	dns_zone_logc(
   14595 		zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(3),
   14596 		"soa_query: remote server current address index %d count %d",
   14597 		zone->primaries.curraddr, zone->primaries.addrcnt);
   14598 	INSIST(dns_remote_count(&zone->primaries) > 0);
   14599 	INSIST(!dns_remote_done(&zone->primaries));
   14600 
   14601 	sourceaddr = dns_remote_sourceaddr(&zone->primaries);
   14602 	curraddr = dns_remote_curraddr(&zone->primaries);
   14603 	isc_netaddr_fromsockaddr(&primaryip, &curraddr);
   14604 
   14605 	if (isc_sockaddr_disabled(&curraddr)) {
   14606 		goto skip_primary;
   14607 	}
   14608 
   14609 	/*
   14610 	 * First, look for a tsig key in the primaries statement, then
   14611 	 * try for a server key.
   14612 	 */
   14613 	if (dns_remote_keyname(&zone->primaries) != NULL) {
   14614 		dns_view_t *view = dns_zone_getview(zone);
   14615 		dns_name_t *keyname = dns_remote_keyname(&zone->primaries);
   14616 		result = dns_view_gettsig(view, keyname, &key);
   14617 		if (result != ISC_R_SUCCESS) {
   14618 			char namebuf[DNS_NAME_FORMATSIZE];
   14619 			dns_name_format(keyname, namebuf, sizeof(namebuf));
   14620 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14621 				      ISC_LOG_ERROR, "unable to find key: %s",
   14622 				      namebuf);
   14623 			goto skip_primary;
   14624 		}
   14625 	}
   14626 	if (key == NULL) {
   14627 		result = dns_view_getpeertsig(zone->view, &primaryip, &key);
   14628 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   14629 			char addrbuf[ISC_NETADDR_FORMATSIZE];
   14630 			isc_netaddr_format(&primaryip, addrbuf,
   14631 					   sizeof(addrbuf));
   14632 			dns_zone_logc(
   14633 				zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
   14634 				"unable to find TSIG key for %s", addrbuf);
   14635 			goto skip_primary;
   14636 		}
   14637 	}
   14638 
   14639 	if (dns_remote_tlsname(&zone->primaries) != NULL) {
   14640 		dns_view_t *view = dns_zone_getview(zone);
   14641 		dns_name_t *tlsname = dns_remote_tlsname(&zone->primaries);
   14642 		result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
   14643 					       &transport);
   14644 		if (result != ISC_R_SUCCESS) {
   14645 			char namebuf[DNS_NAME_FORMATSIZE];
   14646 			dns_name_format(tlsname, namebuf, sizeof(namebuf));
   14647 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   14648 				      ISC_LOG_ERROR,
   14649 				      "unable to find TLS configuration: %s",
   14650 				      namebuf);
   14651 			goto skip_primary;
   14652 		}
   14653 	}
   14654 
   14655 	options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? DNS_REQUESTOPT_TCP
   14656 							 : 0;
   14657 	reqnsid = zone->view->requestnsid;
   14658 	reqexpire = zone->requestexpire;
   14659 	if (zone->view->peers != NULL) {
   14660 		dns_peer_t *peer = NULL;
   14661 		bool edns, usetcp;
   14662 		result = dns_peerlist_peerbyaddr(zone->view->peers, &primaryip,
   14663 						 &peer);
   14664 		if (result == ISC_R_SUCCESS) {
   14665 			result = dns_peer_getsupportedns(peer, &edns);
   14666 			if (result == ISC_R_SUCCESS && !edns) {
   14667 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   14668 			}
   14669 			result = dns_peer_gettransfersource(peer,
   14670 							    &zone->sourceaddr);
   14671 			if (result == ISC_R_SUCCESS) {
   14672 				have_xfrsource = true;
   14673 			}
   14674 			udpsize = dns_view_getudpsize(zone->view);
   14675 			(void)dns_peer_getudpsize(peer, &udpsize);
   14676 			(void)dns_peer_getrequestnsid(peer, &reqnsid);
   14677 			(void)dns_peer_getrequestexpire(peer, &reqexpire);
   14678 			result = dns_peer_getforcetcp(peer, &usetcp);
   14679 			if (result == ISC_R_SUCCESS && usetcp) {
   14680 				options |= DNS_REQUESTOPT_TCP;
   14681 			}
   14682 		}
   14683 	}
   14684 
   14685 	switch (isc_sockaddr_pf(&curraddr)) {
   14686 	case PF_INET:
   14687 		if (!have_xfrsource) {
   14688 			isc_sockaddr_t any;
   14689 			isc_sockaddr_any(&any);
   14690 
   14691 			zone->sourceaddr = sourceaddr;
   14692 			if (isc_sockaddr_equal(&sourceaddr, &any)) {
   14693 				zone->sourceaddr = zone->xfrsource4;
   14694 			}
   14695 		}
   14696 		break;
   14697 	case PF_INET6:
   14698 		if (!have_xfrsource) {
   14699 			isc_sockaddr_t any;
   14700 			isc_sockaddr_any6(&any);
   14701 
   14702 			zone->sourceaddr = sourceaddr;
   14703 			if (isc_sockaddr_equal(&zone->sourceaddr, &any)) {
   14704 				zone->sourceaddr = zone->xfrsource6;
   14705 			}
   14706 		}
   14707 		break;
   14708 	default:
   14709 		result = ISC_R_NOTIMPLEMENTED;
   14710 		goto cleanup;
   14711 	}
   14712 
   14713 	/*
   14714 	 * FIXME(OS): This is a bit hackish, but it enforces the SOA query to go
   14715 	 * through the XFR channel instead of doing dns_request that doesn't
   14716 	 * have DoT support yet.
   14717 	 */
   14718 	if (transport != NULL) {
   14719 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
   14720 		do_queue_xfrin = true;
   14721 		cancel = false;
   14722 		result = ISC_R_SUCCESS;
   14723 		goto cleanup;
   14724 	}
   14725 
   14726 	create_query(zone, dns_rdatatype_soa, &zone->origin, &message);
   14727 
   14728 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   14729 		result = add_opt(message, udpsize, reqnsid, reqexpire);
   14730 		if (result != ISC_R_SUCCESS) {
   14731 			zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__,
   14732 				       1, "unable to add opt record: %s",
   14733 				       isc_result_totext(result));
   14734 		}
   14735 	}
   14736 
   14737 	zone_iattach(zone, &(dns_zone_t *){ NULL });
   14738 	timeout = 5;
   14739 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
   14740 		timeout = 30;
   14741 	}
   14742 	result = dns_request_create(
   14743 		zone->view->requestmgr, message, &zone->sourceaddr, &curraddr,
   14744 		NULL, NULL, options, key, timeout * 3 + 1, timeout, 2,
   14745 		zone->loop, refresh_callback, zone, &zone->request);
   14746 	if (result != ISC_R_SUCCESS) {
   14747 		zone_idetach(&(dns_zone_t *){ zone });
   14748 		zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__, 1,
   14749 			       "dns_request_create() failed: %s",
   14750 			       isc_result_totext(result));
   14751 		goto skip_primary;
   14752 	} else {
   14753 		/* Shows in the statistics channel the duration of the query. */
   14754 		zone->xfrintime = isc_time_now();
   14755 
   14756 		if (isc_sockaddr_pf(&curraddr) == PF_INET) {
   14757 			inc_stats(zone, dns_zonestatscounter_soaoutv4);
   14758 		} else {
   14759 			inc_stats(zone, dns_zonestatscounter_soaoutv6);
   14760 		}
   14761 	}
   14762 	cancel = false;
   14763 cleanup:
   14764 	if (transport != NULL) {
   14765 		dns_transport_detach(&transport);
   14766 	}
   14767 	if (key != NULL) {
   14768 		dns_tsigkey_detach(&key);
   14769 	}
   14770 	if (result != ISC_R_SUCCESS) {
   14771 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   14772 	}
   14773 	if (message != NULL) {
   14774 		dns_message_detach(&message);
   14775 	}
   14776 	if (cancel) {
   14777 		cancel_refresh(zone);
   14778 	}
   14779 	if (do_queue_xfrin) {
   14780 		/* Shows in the statistics channel the duration of the step. */
   14781 		zone->xfrintime = isc_time_now();
   14782 	}
   14783 	UNLOCK_ZONE(zone);
   14784 	if (do_queue_xfrin) {
   14785 		queue_xfrin(zone);
   14786 	}
   14787 	isc_rlevent_free(&sq->rlevent);
   14788 	isc_mem_put(zone->mctx, sq, sizeof(*sq));
   14789 	dns_zone_idetach(&zone);
   14790 	return;
   14791 
   14792 skip_primary:
   14793 	if (transport != NULL) {
   14794 		dns_transport_detach(&transport);
   14795 	}
   14796 	if (key != NULL) {
   14797 		dns_tsigkey_detach(&key);
   14798 	}
   14799 	if (message != NULL) {
   14800 		dns_message_detach(&message);
   14801 	}
   14802 	/*
   14803 	 * Skip to next failed / untried primary.
   14804 	 */
   14805 	dns_remote_next(&zone->primaries, true);
   14806 	if (!dns_remote_done(&zone->primaries)) {
   14807 		goto again;
   14808 	}
   14809 	dns_remote_reset(&zone->primaries, false);
   14810 	goto cleanup;
   14811 }
   14812 
   14813 static void
   14814 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
   14815 	isc_result_t result;
   14816 	dns_message_t *message = NULL;
   14817 	isc_netaddr_t primaryip;
   14818 	dns_tsigkey_t *key = NULL;
   14819 	dns_dbnode_t *node = NULL;
   14820 	int timeout;
   14821 	bool have_xfrsource = false;
   14822 	bool reqnsid;
   14823 	uint16_t udpsize = SEND_BUFFER_SIZE;
   14824 	isc_sockaddr_t curraddr, sourceaddr;
   14825 	struct stub_cb_args *cb_args;
   14826 
   14827 	REQUIRE(DNS_ZONE_VALID(zone));
   14828 	REQUIRE(LOCKED_ZONE(zone));
   14829 	REQUIRE((soardataset != NULL && stub == NULL) ||
   14830 		(soardataset == NULL && stub != NULL));
   14831 	REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
   14832 
   14833 	ENTER;
   14834 
   14835 	if (stub == NULL) {
   14836 		stub = isc_mem_get(zone->mctx, sizeof(*stub));
   14837 		stub->magic = STUB_MAGIC;
   14838 		stub->mctx = zone->mctx;
   14839 		stub->zone = NULL;
   14840 		stub->db = NULL;
   14841 		stub->version = NULL;
   14842 		atomic_init(&stub->pending_requests, 0);
   14843 
   14844 		/*
   14845 		 * Attach so that the zone won't disappear from under us.
   14846 		 */
   14847 		zone_iattach(zone, &stub->zone);
   14848 
   14849 		/*
   14850 		 * If a db exists we will update it, otherwise we create a
   14851 		 * new one and attach it to the zone once we have the NS
   14852 		 * RRset and glue.
   14853 		 */
   14854 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   14855 		if (zone->db != NULL) {
   14856 			dns_db_attach(zone->db, &stub->db);
   14857 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   14858 		} else {
   14859 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   14860 
   14861 			INSIST(zone->db_argc >= 1);
   14862 			result = dns_db_create(zone->mctx, zone->db_argv[0],
   14863 					       &zone->origin, dns_dbtype_stub,
   14864 					       zone->rdclass, zone->db_argc - 1,
   14865 					       zone->db_argv + 1, &stub->db);
   14866 			if (result != ISC_R_SUCCESS) {
   14867 				dns_zone_log(zone, ISC_LOG_ERROR,
   14868 					     "refreshing stub: "
   14869 					     "could not create "
   14870 					     "database: %s",
   14871 					     isc_result_totext(result));
   14872 				goto cleanup;
   14873 			}
   14874 			dns_db_setloop(stub->db, zone->loop);
   14875 			dns_db_setmaxrrperset(stub->db, zone->maxrrperset);
   14876 			dns_db_setmaxtypepername(stub->db,
   14877 						 zone->maxtypepername);
   14878 		}
   14879 
   14880 		result = dns_db_newversion(stub->db, &stub->version);
   14881 		if (result != ISC_R_SUCCESS) {
   14882 			dns_zone_log(zone, ISC_LOG_INFO,
   14883 				     "refreshing stub: "
   14884 				     "dns_db_newversion() failed: %s",
   14885 				     isc_result_totext(result));
   14886 			goto cleanup;
   14887 		}
   14888 
   14889 		/*
   14890 		 * Update SOA record.
   14891 		 */
   14892 		result = dns_db_findnode(stub->db, &zone->origin, true, &node);
   14893 		if (result != ISC_R_SUCCESS) {
   14894 			dns_zone_log(zone, ISC_LOG_INFO,
   14895 				     "refreshing stub: "
   14896 				     "dns_db_findnode() failed: %s",
   14897 				     isc_result_totext(result));
   14898 			goto cleanup;
   14899 		}
   14900 
   14901 		result = dns_db_addrdataset(stub->db, node, stub->version, 0,
   14902 					    soardataset, 0, NULL);
   14903 		dns_db_detachnode(stub->db, &node);
   14904 		if (result != ISC_R_SUCCESS) {
   14905 			dns_zone_log(zone, ISC_LOG_INFO,
   14906 				     "refreshing stub: "
   14907 				     "dns_db_addrdataset() failed: %s",
   14908 				     isc_result_totext(result));
   14909 			goto cleanup;
   14910 		}
   14911 	}
   14912 
   14913 	/*
   14914 	 * XXX Optimisation: Create message when zone is setup and reuse.
   14915 	 */
   14916 	create_query(zone, dns_rdatatype_ns, &zone->origin, &message);
   14917 
   14918 	INSIST(dns_remote_count(&zone->primaries) > 0);
   14919 	INSIST(!dns_remote_done(&zone->primaries));
   14920 
   14921 	sourceaddr = dns_remote_sourceaddr(&zone->primaries);
   14922 	curraddr = dns_remote_curraddr(&zone->primaries);
   14923 	isc_netaddr_fromsockaddr(&primaryip, &curraddr);
   14924 	/*
   14925 	 * First, look for a tsig key in the primaries statement, then
   14926 	 * try for a server key.
   14927 	 */
   14928 	if (dns_remote_keyname(&zone->primaries) != NULL) {
   14929 		dns_view_t *view = dns_zone_getview(zone);
   14930 		dns_name_t *keyname = dns_remote_keyname(&zone->primaries);
   14931 		result = dns_view_gettsig(view, keyname, &key);
   14932 		if (result != ISC_R_SUCCESS) {
   14933 			char namebuf[DNS_NAME_FORMATSIZE];
   14934 			dns_name_format(keyname, namebuf, sizeof(namebuf));
   14935 			dns_zone_log(zone, ISC_LOG_ERROR,
   14936 				     "unable to find key: %s", namebuf);
   14937 		}
   14938 	}
   14939 	if (key == NULL) {
   14940 		(void)dns_view_getpeertsig(zone->view, &primaryip, &key);
   14941 	}
   14942 
   14943 	/* FIXME(OS): Do we need the transport here too? Most probably yes */
   14944 
   14945 	reqnsid = zone->view->requestnsid;
   14946 	if (zone->view->peers != NULL) {
   14947 		dns_peer_t *peer = NULL;
   14948 		bool edns;
   14949 		result = dns_peerlist_peerbyaddr(zone->view->peers, &primaryip,
   14950 						 &peer);
   14951 		if (result == ISC_R_SUCCESS) {
   14952 			result = dns_peer_getsupportedns(peer, &edns);
   14953 			if (result == ISC_R_SUCCESS && !edns) {
   14954 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   14955 			}
   14956 			result = dns_peer_gettransfersource(peer,
   14957 							    &zone->sourceaddr);
   14958 			if (result == ISC_R_SUCCESS) {
   14959 				have_xfrsource = true;
   14960 			}
   14961 			udpsize = dns_view_getudpsize(zone->view);
   14962 			(void)dns_peer_getudpsize(peer, &udpsize);
   14963 			(void)dns_peer_getrequestnsid(peer, &reqnsid);
   14964 		}
   14965 	}
   14966 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   14967 		result = add_opt(message, udpsize, reqnsid, false);
   14968 		if (result != ISC_R_SUCCESS) {
   14969 			zone_debuglog(zone, __func__, 1,
   14970 				      "unable to add opt record: %s",
   14971 				      isc_result_totext(result));
   14972 		}
   14973 	}
   14974 
   14975 	/*
   14976 	 * Always use TCP so that we shouldn't truncate in additional section.
   14977 	 */
   14978 	switch (isc_sockaddr_pf(&curraddr)) {
   14979 	case PF_INET:
   14980 		if (!have_xfrsource) {
   14981 			isc_sockaddr_t any;
   14982 			isc_sockaddr_any(&any);
   14983 
   14984 			zone->sourceaddr = sourceaddr;
   14985 			if (isc_sockaddr_equal(&zone->sourceaddr, &any)) {
   14986 				zone->sourceaddr = zone->xfrsource4;
   14987 			}
   14988 		}
   14989 		break;
   14990 	case PF_INET6:
   14991 		if (!have_xfrsource) {
   14992 			isc_sockaddr_t any;
   14993 			isc_sockaddr_any6(&any);
   14994 
   14995 			zone->sourceaddr = sourceaddr;
   14996 			if (isc_sockaddr_equal(&zone->sourceaddr, &any)) {
   14997 				zone->sourceaddr = zone->xfrsource6;
   14998 			}
   14999 		}
   15000 		break;
   15001 	default:
   15002 		result = ISC_R_NOTIMPLEMENTED;
   15003 		POST(result);
   15004 		goto cleanup;
   15005 	}
   15006 	timeout = 5;
   15007 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
   15008 		timeout = 30;
   15009 	}
   15010 
   15011 	/*
   15012 	 * Save request parameters so we can reuse them later on
   15013 	 * for resolving missing glue A/AAAA records.
   15014 	 */
   15015 	cb_args = isc_mem_get(zone->mctx, sizeof(*cb_args));
   15016 	cb_args->stub = stub;
   15017 	cb_args->tsig_key = key;
   15018 	cb_args->udpsize = udpsize;
   15019 	cb_args->timeout = timeout;
   15020 	cb_args->reqnsid = reqnsid;
   15021 
   15022 	result = dns_request_create(
   15023 		zone->view->requestmgr, message, &zone->sourceaddr, &curraddr,
   15024 		NULL, NULL, DNS_REQUESTOPT_TCP, key, timeout * 3 + 1, timeout,
   15025 		2, zone->loop, stub_callback, cb_args, &zone->request);
   15026 	if (result != ISC_R_SUCCESS) {
   15027 		zone_debuglog(zone, __func__, 1,
   15028 			      "dns_request_create() failed: %s",
   15029 			      isc_result_totext(result));
   15030 		goto cleanup;
   15031 	}
   15032 	dns_message_detach(&message);
   15033 	goto unlock;
   15034 
   15035 cleanup:
   15036 	cancel_refresh(zone);
   15037 	stub->magic = 0;
   15038 	if (stub->version != NULL) {
   15039 		dns_db_closeversion(stub->db, &stub->version, false);
   15040 	}
   15041 	if (stub->db != NULL) {
   15042 		dns_db_detach(&stub->db);
   15043 	}
   15044 	if (stub->zone != NULL) {
   15045 		zone_idetach(&stub->zone);
   15046 	}
   15047 	isc_mem_put(stub->mctx, stub, sizeof(*stub));
   15048 	if (message != NULL) {
   15049 		dns_message_detach(&message);
   15050 	}
   15051 unlock:
   15052 	if (key != NULL) {
   15053 		dns_tsigkey_detach(&key);
   15054 	}
   15055 	return;
   15056 }
   15057 
   15058 /*
   15059  * Shut the zone down.
   15060  */
   15061 static void
   15062 zone_shutdown(void *arg) {
   15063 	dns_zone_t *zone = (dns_zone_t *)arg;
   15064 	bool free_needed, linked = false;
   15065 	dns_zone_t *raw = NULL, *secure = NULL;
   15066 	dns_view_t *view = NULL, *prev_view = NULL;
   15067 
   15068 	REQUIRE(DNS_ZONE_VALID(zone));
   15069 	INSIST(isc_refcount_current(&zone->references) == 0);
   15070 
   15071 	zone_debuglog(zone, __func__, 3, "shutting down");
   15072 
   15073 	/*
   15074 	 * If we were waiting for xfrin quota, step out of
   15075 	 * the queue.
   15076 	 * If there's no zone manager, we can't be waiting for the
   15077 	 * xfrin quota
   15078 	 */
   15079 	if (zone->zmgr != NULL) {
   15080 		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   15081 		if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
   15082 			ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
   15083 					statelink);
   15084 			linked = true;
   15085 			zone->statelist = NULL;
   15086 		}
   15087 		if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
   15088 			ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
   15089 					statelink);
   15090 			zone->statelist = NULL;
   15091 			zmgr_resume_xfrs(zone->zmgr, false);
   15092 		}
   15093 		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   15094 	}
   15095 
   15096 	/*
   15097 	 * In loop context, no locking required.  See zone_xfrdone().
   15098 	 */
   15099 	if (zone->xfr != NULL) {
   15100 		/* The final detach will happen in zone_xfrdone() */
   15101 		dns_xfrin_shutdown(zone->xfr);
   15102 	}
   15103 
   15104 	/* Safe to release the zone now */
   15105 	if (zone->zmgr != NULL) {
   15106 		dns_zonemgr_releasezone(zone->zmgr, zone);
   15107 	}
   15108 
   15109 	LOCK_ZONE(zone);
   15110 	INSIST(zone != zone->raw);
   15111 
   15112 	/*
   15113 	 * Detach the views early, we don't need them anymore.  However, we need
   15114 	 * to detach them outside of the zone lock to break the lock loop
   15115 	 * between view, adb and zone locks.
   15116 	 */
   15117 	view = zone->view;
   15118 	zone->view = NULL;
   15119 	prev_view = zone->prev_view;
   15120 	zone->prev_view = NULL;
   15121 
   15122 	if (linked) {
   15123 		isc_refcount_decrement(&zone->irefs);
   15124 	}
   15125 	if (zone->request != NULL) {
   15126 		dns_request_cancel(zone->request);
   15127 	}
   15128 
   15129 	if (zone->loadctx != NULL) {
   15130 		dns_loadctx_cancel(zone->loadctx);
   15131 	}
   15132 
   15133 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
   15134 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
   15135 	{
   15136 		if (zone->dumpctx != NULL) {
   15137 			dns_dumpctx_cancel(zone->dumpctx);
   15138 		}
   15139 	}
   15140 
   15141 	checkds_cancel(zone);
   15142 
   15143 	notify_cancel(zone);
   15144 
   15145 	forward_cancel(zone);
   15146 
   15147 	if (zone->timer != NULL) {
   15148 		isc_refcount_decrement(&zone->irefs);
   15149 		isc_timer_destroy(&zone->timer);
   15150 	}
   15151 
   15152 	/*
   15153 	 * We have now canceled everything set the flag to allow exit_check()
   15154 	 * to succeed.	We must not unlock between setting this flag and
   15155 	 * calling exit_check().
   15156 	 */
   15157 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
   15158 	free_needed = exit_check(zone);
   15159 	/*
   15160 	 * If a dump is in progress for the secure zone, defer detaching from
   15161 	 * the raw zone as it may prevent the unsigned serial number from being
   15162 	 * stored in the raw-format dump of the secure zone.  In this scenario,
   15163 	 * dump_done() takes care of cleaning up the zone->raw reference.
   15164 	 */
   15165 	if (inline_secure(zone) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   15166 		raw = zone->raw;
   15167 		zone->raw = NULL;
   15168 	}
   15169 	if (inline_raw(zone)) {
   15170 		secure = zone->secure;
   15171 		zone->secure = NULL;
   15172 	}
   15173 	UNLOCK_ZONE(zone);
   15174 
   15175 	if (view != NULL) {
   15176 		dns_view_weakdetach(&view);
   15177 	}
   15178 	if (prev_view != NULL) {
   15179 		dns_view_weakdetach(&prev_view);
   15180 	}
   15181 
   15182 	if (raw != NULL) {
   15183 		dns_zone_detach(&raw);
   15184 	}
   15185 	if (secure != NULL) {
   15186 		dns_zone_idetach(&secure);
   15187 	}
   15188 	if (free_needed) {
   15189 		zone_free(zone);
   15190 	}
   15191 }
   15192 
   15193 static void
   15194 zone_timer(void *arg) {
   15195 	dns_zone_t *zone = (dns_zone_t *)arg;
   15196 
   15197 	REQUIRE(DNS_ZONE_VALID(zone));
   15198 
   15199 	zone_maintenance(zone);
   15200 }
   15201 
   15202 static void
   15203 zone_timer_stop(dns_zone_t *zone) {
   15204 	zone_debuglog(zone, __func__, 10, "stop zone timer");
   15205 	if (zone->timer != NULL) {
   15206 		isc_timer_stop(zone->timer);
   15207 	}
   15208 }
   15209 
   15210 static void
   15211 zone_timer_set(dns_zone_t *zone, isc_time_t *next, isc_time_t *now) {
   15212 	isc_interval_t interval;
   15213 
   15214 	if (isc_time_compare(next, now) <= 0) {
   15215 		isc_interval_set(&interval, 0, 0);
   15216 	} else {
   15217 		isc_time_subtract(next, now, &interval);
   15218 	}
   15219 
   15220 	if (zone->loop == NULL) {
   15221 		zone_debuglog(zone, __func__, 10, "zone is not managed");
   15222 	} else if (zone->timer == NULL) {
   15223 		isc_refcount_increment0(&zone->irefs);
   15224 		isc_timer_create(zone->loop, zone_timer, zone, &zone->timer);
   15225 	}
   15226 	if (zone->timer != NULL) {
   15227 		isc_timer_start(zone->timer, isc_timertype_once, &interval);
   15228 	}
   15229 }
   15230 
   15231 static void
   15232 zone__settimer(void *arg) {
   15233 	zone_settimer_t *data = arg;
   15234 	dns_zone_t *zone = data->zone;
   15235 	isc_time_t *now = &data->now;
   15236 	isc_time_t next;
   15237 	bool free_needed = false;
   15238 
   15239 	REQUIRE(DNS_ZONE_VALID(zone));
   15240 	ENTER;
   15241 
   15242 	LOCK_ZONE(zone);
   15243 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   15244 		goto free;
   15245 	}
   15246 	isc_time_settoepoch(&next);
   15247 
   15248 	switch (zone->type) {
   15249 	case dns_zone_redirect:
   15250 		if (dns_remote_addresses(&zone->primaries) != NULL) {
   15251 			goto treat_as_secondary;
   15252 		}
   15253 		FALLTHROUGH;
   15254 	case dns_zone_primary:
   15255 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   15256 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
   15257 		{
   15258 			next = zone->notifytime;
   15259 		}
   15260 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   15261 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
   15262 		{
   15263 			INSIST(!isc_time_isepoch(&zone->dumptime));
   15264 			if (isc_time_isepoch(&next) ||
   15265 			    isc_time_compare(&zone->dumptime, &next) < 0)
   15266 			{
   15267 				next = zone->dumptime;
   15268 			}
   15269 		}
   15270 		if (zone->type == dns_zone_redirect) {
   15271 			break;
   15272 		}
   15273 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
   15274 		    !isc_time_isepoch(&zone->refreshkeytime))
   15275 		{
   15276 			if (isc_time_isepoch(&next) ||
   15277 			    isc_time_compare(&zone->refreshkeytime, &next) < 0)
   15278 			{
   15279 				next = zone->refreshkeytime;
   15280 			}
   15281 		}
   15282 		if (!isc_time_isepoch(&zone->resigntime)) {
   15283 			if (isc_time_isepoch(&next) ||
   15284 			    isc_time_compare(&zone->resigntime, &next) < 0)
   15285 			{
   15286 				next = zone->resigntime;
   15287 			}
   15288 		}
   15289 		if (!isc_time_isepoch(&zone->keywarntime)) {
   15290 			if (isc_time_isepoch(&next) ||
   15291 			    isc_time_compare(&zone->keywarntime, &next) < 0)
   15292 			{
   15293 				next = zone->keywarntime;
   15294 			}
   15295 		}
   15296 		if (!isc_time_isepoch(&zone->signingtime)) {
   15297 			if (isc_time_isepoch(&next) ||
   15298 			    isc_time_compare(&zone->signingtime, &next) < 0)
   15299 			{
   15300 				next = zone->signingtime;
   15301 			}
   15302 		}
   15303 		if (!isc_time_isepoch(&zone->nsec3chaintime)) {
   15304 			if (isc_time_isepoch(&next) ||
   15305 			    isc_time_compare(&zone->nsec3chaintime, &next) < 0)
   15306 			{
   15307 				next = zone->nsec3chaintime;
   15308 			}
   15309 		}
   15310 		break;
   15311 
   15312 	case dns_zone_secondary:
   15313 	case dns_zone_mirror:
   15314 	treat_as_secondary:
   15315 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   15316 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
   15317 		{
   15318 			next = zone->notifytime;
   15319 		}
   15320 		FALLTHROUGH;
   15321 	case dns_zone_stub:
   15322 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
   15323 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOPRIMARIES) &&
   15324 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
   15325 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
   15326 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
   15327 		    !isc_time_isepoch(&zone->refreshtime) &&
   15328 		    (isc_time_isepoch(&next) ||
   15329 		     isc_time_compare(&zone->refreshtime, &next) < 0))
   15330 		{
   15331 			next = zone->refreshtime;
   15332 		}
   15333 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   15334 		    !isc_time_isepoch(&zone->expiretime))
   15335 		{
   15336 			if (isc_time_isepoch(&next) ||
   15337 			    isc_time_compare(&zone->expiretime, &next) < 0)
   15338 			{
   15339 				next = zone->expiretime;
   15340 			}
   15341 		}
   15342 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   15343 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
   15344 		{
   15345 			INSIST(!isc_time_isepoch(&zone->dumptime));
   15346 			if (isc_time_isepoch(&next) ||
   15347 			    isc_time_compare(&zone->dumptime, &next) < 0)
   15348 			{
   15349 				next = zone->dumptime;
   15350 			}
   15351 		}
   15352 		break;
   15353 
   15354 	case dns_zone_key:
   15355 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   15356 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
   15357 		{
   15358 			INSIST(!isc_time_isepoch(&zone->dumptime));
   15359 			if (isc_time_isepoch(&next) ||
   15360 			    isc_time_compare(&zone->dumptime, &next) < 0)
   15361 			{
   15362 				next = zone->dumptime;
   15363 			}
   15364 		}
   15365 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
   15366 			if (isc_time_isepoch(&next) ||
   15367 			    (!isc_time_isepoch(&zone->refreshkeytime) &&
   15368 			     isc_time_compare(&zone->refreshkeytime, &next) <
   15369 				     0))
   15370 			{
   15371 				next = zone->refreshkeytime;
   15372 			}
   15373 		}
   15374 		break;
   15375 
   15376 	default:
   15377 		break;
   15378 	}
   15379 
   15380 	if (isc_time_isepoch(&next)) {
   15381 		zone_timer_stop(zone);
   15382 	} else {
   15383 		zone_timer_set(zone, &next, now);
   15384 	}
   15385 
   15386 free:
   15387 	isc_mem_put(zone->mctx, data, sizeof(*data));
   15388 	isc_refcount_decrement(&zone->irefs);
   15389 	free_needed = exit_check(zone);
   15390 	UNLOCK_ZONE(zone);
   15391 	if (free_needed) {
   15392 		zone_free(zone);
   15393 	}
   15394 }
   15395 
   15396 static void
   15397 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
   15398 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   15399 		return;
   15400 	}
   15401 
   15402 	zone_settimer_t *arg = isc_mem_get(zone->mctx, sizeof(*arg));
   15403 	*arg = (zone_settimer_t){
   15404 		.zone = zone,
   15405 		.now = *now,
   15406 	};
   15407 	isc_refcount_increment0(&zone->irefs);
   15408 	isc_async_run(zone->loop, zone__settimer, arg);
   15409 }
   15410 
   15411 static void
   15412 cancel_refresh(dns_zone_t *zone) {
   15413 	isc_time_t now;
   15414 
   15415 	/*
   15416 	 * 'zone' locked by caller.
   15417 	 */
   15418 
   15419 	REQUIRE(DNS_ZONE_VALID(zone));
   15420 	REQUIRE(LOCKED_ZONE(zone));
   15421 
   15422 	ENTER;
   15423 
   15424 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   15425 	now = isc_time_now();
   15426 	zone_settimer(zone, &now);
   15427 }
   15428 
   15429 static isc_result_t
   15430 notify_createmessage(dns_zone_t *zone, unsigned int flags,
   15431 		     dns_message_t **messagep) {
   15432 	dns_db_t *zonedb = NULL;
   15433 	dns_dbnode_t *node = NULL;
   15434 	dns_dbversion_t *version = NULL;
   15435 	dns_message_t *message = NULL;
   15436 	dns_rdataset_t rdataset;
   15437 	dns_rdata_t rdata = DNS_RDATA_INIT;
   15438 
   15439 	dns_name_t *tempname = NULL;
   15440 	dns_rdata_t *temprdata = NULL;
   15441 	dns_rdatalist_t *temprdatalist = NULL;
   15442 	dns_rdataset_t *temprdataset = NULL;
   15443 
   15444 	isc_result_t result;
   15445 	isc_region_t r;
   15446 	isc_buffer_t *b = NULL;
   15447 
   15448 	REQUIRE(DNS_ZONE_VALID(zone));
   15449 	REQUIRE(messagep != NULL && *messagep == NULL);
   15450 
   15451 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER,
   15452 			   &message);
   15453 
   15454 	message->opcode = dns_opcode_notify;
   15455 	message->flags |= DNS_MESSAGEFLAG_AA;
   15456 	message->rdclass = zone->rdclass;
   15457 
   15458 	dns_message_gettempname(message, &tempname);
   15459 
   15460 	dns_message_gettemprdataset(message, &temprdataset);
   15461 
   15462 	/*
   15463 	 * Make question.
   15464 	 */
   15465 	dns_name_clone(&zone->origin, tempname);
   15466 	dns_rdataset_makequestion(temprdataset, zone->rdclass,
   15467 				  dns_rdatatype_soa);
   15468 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
   15469 	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
   15470 	tempname = NULL;
   15471 	temprdataset = NULL;
   15472 
   15473 	if ((flags & DNS_NOTIFY_NOSOA) != 0) {
   15474 		goto done;
   15475 	}
   15476 
   15477 	dns_message_gettempname(message, &tempname);
   15478 	dns_message_gettemprdata(message, &temprdata);
   15479 	dns_message_gettemprdataset(message, &temprdataset);
   15480 	dns_message_gettemprdatalist(message, &temprdatalist);
   15481 
   15482 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   15483 	INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
   15484 	dns_db_attach(zone->db, &zonedb);
   15485 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   15486 
   15487 	dns_name_clone(&zone->origin, tempname);
   15488 	dns_db_currentversion(zonedb, &version);
   15489 	result = dns_db_findnode(zonedb, tempname, false, &node);
   15490 	if (result != ISC_R_SUCCESS) {
   15491 		goto soa_cleanup;
   15492 	}
   15493 
   15494 	dns_rdataset_init(&rdataset);
   15495 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
   15496 				     dns_rdatatype_none, 0, &rdataset, NULL);
   15497 	if (result != ISC_R_SUCCESS) {
   15498 		goto soa_cleanup;
   15499 	}
   15500 	result = dns_rdataset_first(&rdataset);
   15501 	if (result != ISC_R_SUCCESS) {
   15502 		goto soa_cleanup;
   15503 	}
   15504 	dns_rdataset_current(&rdataset, &rdata);
   15505 	dns_rdata_toregion(&rdata, &r);
   15506 	isc_buffer_allocate(zone->mctx, &b, r.length);
   15507 	isc_buffer_putmem(b, r.base, r.length);
   15508 	isc_buffer_usedregion(b, &r);
   15509 	dns_rdata_init(temprdata);
   15510 	dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
   15511 	dns_message_takebuffer(message, &b);
   15512 	result = dns_rdataset_next(&rdataset);
   15513 	dns_rdataset_disassociate(&rdataset);
   15514 	if (result != ISC_R_NOMORE) {
   15515 		goto soa_cleanup;
   15516 	}
   15517 	temprdatalist->rdclass = rdata.rdclass;
   15518 	temprdatalist->type = rdata.type;
   15519 	temprdatalist->ttl = rdataset.ttl;
   15520 	ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
   15521 
   15522 	dns_rdatalist_tordataset(temprdatalist, temprdataset);
   15523 
   15524 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
   15525 	dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
   15526 	temprdatalist = NULL;
   15527 	temprdataset = NULL;
   15528 	temprdata = NULL;
   15529 	tempname = NULL;
   15530 
   15531 soa_cleanup:
   15532 	if (node != NULL) {
   15533 		dns_db_detachnode(zonedb, &node);
   15534 	}
   15535 	if (version != NULL) {
   15536 		dns_db_closeversion(zonedb, &version, false);
   15537 	}
   15538 	if (zonedb != NULL) {
   15539 		dns_db_detach(&zonedb);
   15540 	}
   15541 	if (tempname != NULL) {
   15542 		dns_message_puttempname(message, &tempname);
   15543 	}
   15544 	if (temprdata != NULL) {
   15545 		dns_message_puttemprdata(message, &temprdata);
   15546 	}
   15547 	if (temprdataset != NULL) {
   15548 		dns_message_puttemprdataset(message, &temprdataset);
   15549 	}
   15550 	if (temprdatalist != NULL) {
   15551 		dns_message_puttemprdatalist(message, &temprdatalist);
   15552 	}
   15553 
   15554 done:
   15555 	*messagep = message;
   15556 	return ISC_R_SUCCESS;
   15557 }
   15558 
   15559 isc_result_t
   15560 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
   15561 		       isc_sockaddr_t *to, dns_message_t *msg) {
   15562 	unsigned int i;
   15563 	dns_rdata_soa_t soa;
   15564 	dns_rdataset_t *rdataset = NULL;
   15565 	dns_rdata_t rdata = DNS_RDATA_INIT;
   15566 	isc_result_t result;
   15567 	char fromtext[ISC_SOCKADDR_FORMATSIZE];
   15568 	int match = 0;
   15569 	isc_netaddr_t netaddr;
   15570 	uint32_t serial = 0;
   15571 	bool have_serial = false;
   15572 	dns_tsigkey_t *tsigkey;
   15573 	const dns_name_t *tsig;
   15574 
   15575 	REQUIRE(DNS_ZONE_VALID(zone));
   15576 
   15577 	/*
   15578 	 * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
   15579 	 * ROLLOVER.
   15580 	 *
   15581 	 * SOA:	RFC1996
   15582 	 * Check that 'from' is a valid notify source, (zone->primaries).
   15583 	 *	Return DNS_R_REFUSED if not.
   15584 	 *
   15585 	 * If the notify message contains a serial number check it
   15586 	 * against the zones serial and return if <= current serial
   15587 	 *
   15588 	 * If a refresh check is progress, if so just record the
   15589 	 * fact we received a NOTIFY and from where and return.
   15590 	 * We will perform a new refresh check when the current one
   15591 	 * completes. Return ISC_R_SUCCESS.
   15592 	 *
   15593 	 * Otherwise initiate a refresh check using 'from' as the
   15594 	 * first address to check.  Return ISC_R_SUCCESS.
   15595 	 */
   15596 
   15597 	isc_sockaddr_format(from, fromtext, sizeof(fromtext));
   15598 
   15599 	/*
   15600 	 * Notify messages are processed by the raw zone.
   15601 	 */
   15602 	LOCK_ZONE(zone);
   15603 	INSIST(zone != zone->raw);
   15604 	if (inline_secure(zone)) {
   15605 		result = dns_zone_notifyreceive(zone->raw, from, to, msg);
   15606 		UNLOCK_ZONE(zone);
   15607 		return result;
   15608 	}
   15609 	/*
   15610 	 *  We only handle NOTIFY (SOA) at the present.
   15611 	 */
   15612 	if (isc_sockaddr_pf(from) == PF_INET) {
   15613 		inc_stats(zone, dns_zonestatscounter_notifyinv4);
   15614 	} else {
   15615 		inc_stats(zone, dns_zonestatscounter_notifyinv6);
   15616 	}
   15617 	if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
   15618 	    dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
   15619 				 dns_rdatatype_soa, dns_rdatatype_none, NULL,
   15620 				 NULL) != ISC_R_SUCCESS)
   15621 	{
   15622 		UNLOCK_ZONE(zone);
   15623 		if (msg->counts[DNS_SECTION_QUESTION] == 0) {
   15624 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   15625 				      ISC_LOG_NOTICE,
   15626 				      "NOTIFY with no question "
   15627 				      "section from: %s",
   15628 				      fromtext);
   15629 			return DNS_R_FORMERR;
   15630 		}
   15631 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_NOTICE,
   15632 			      "NOTIFY zone does not match");
   15633 		return DNS_R_NOTIMP;
   15634 	}
   15635 
   15636 	/*
   15637 	 * If we are a primary zone just succeed.
   15638 	 */
   15639 	if (zone->type == dns_zone_primary) {
   15640 		UNLOCK_ZONE(zone);
   15641 		return ISC_R_SUCCESS;
   15642 	}
   15643 
   15644 	isc_netaddr_fromsockaddr(&netaddr, from);
   15645 	for (i = 0; i < dns_remote_count(&zone->primaries); i++) {
   15646 		isc_sockaddr_t sockaddr = dns_remote_addr(&zone->primaries, i);
   15647 		if (isc_sockaddr_eqaddr(from, &sockaddr)) {
   15648 			break;
   15649 		}
   15650 		if (zone->view->aclenv->match_mapped &&
   15651 		    IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
   15652 		    isc_sockaddr_pf(&sockaddr) == AF_INET)
   15653 		{
   15654 			isc_netaddr_t na1, na2;
   15655 			isc_netaddr_fromv4mapped(&na1, &netaddr);
   15656 			isc_netaddr_fromsockaddr(&na2, &sockaddr);
   15657 			if (isc_netaddr_equal(&na1, &na2)) {
   15658 				break;
   15659 			}
   15660 		}
   15661 	}
   15662 
   15663 	/*
   15664 	 * Accept notify requests from non primaries if they are on
   15665 	 * 'zone->notify_acl'.
   15666 	 */
   15667 	tsigkey = dns_message_gettsigkey(msg);
   15668 	tsig = dns_tsigkey_identity(tsigkey);
   15669 	if (i >= dns_remote_count(&zone->primaries) &&
   15670 	    zone->notify_acl != NULL &&
   15671 	    (dns_acl_match(&netaddr, tsig, zone->notify_acl, zone->view->aclenv,
   15672 			   &match, NULL) == ISC_R_SUCCESS) &&
   15673 	    match > 0)
   15674 	{
   15675 		/* Accept notify. */
   15676 	} else if (i >= dns_remote_count(&zone->primaries)) {
   15677 		UNLOCK_ZONE(zone);
   15678 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   15679 			      "refused notify from non-primary: %s", fromtext);
   15680 		inc_stats(zone, dns_zonestatscounter_notifyrej);
   15681 		return DNS_R_REFUSED;
   15682 	}
   15683 
   15684 	/*
   15685 	 * If the zone is loaded and there are answers check the serial
   15686 	 * to see if we need to do a refresh.  Do not worry about this
   15687 	 * check if we are a dialup zone as we use the notify request
   15688 	 * to trigger a refresh check.
   15689 	 */
   15690 	if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
   15691 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   15692 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH))
   15693 	{
   15694 		result = dns_message_findname(
   15695 			msg, DNS_SECTION_ANSWER, &zone->origin,
   15696 			dns_rdatatype_soa, dns_rdatatype_none, NULL, &rdataset);
   15697 		if (result == ISC_R_SUCCESS) {
   15698 			result = dns_rdataset_first(rdataset);
   15699 		}
   15700 		if (result == ISC_R_SUCCESS) {
   15701 			uint32_t oldserial;
   15702 			unsigned int soacount;
   15703 
   15704 			dns_rdataset_current(rdataset, &rdata);
   15705 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
   15706 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   15707 			serial = soa.serial;
   15708 			have_serial = true;
   15709 			/*
   15710 			 * The following should safely be performed without DB
   15711 			 * lock and succeed in this context.
   15712 			 */
   15713 			result = zone_get_from_db(zone, zone->db, NULL,
   15714 						  &soacount, NULL, &oldserial,
   15715 						  NULL, NULL, NULL, NULL, NULL);
   15716 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   15717 			RUNTIME_CHECK(soacount > 0U);
   15718 			if (isc_serial_le(serial, oldserial)) {
   15719 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   15720 					      ISC_LOG_INFO,
   15721 					      "notify from %s: "
   15722 					      "zone is up to date",
   15723 					      fromtext);
   15724 				UNLOCK_ZONE(zone);
   15725 				return ISC_R_SUCCESS;
   15726 			}
   15727 		}
   15728 	}
   15729 
   15730 	/*
   15731 	 * If we got this far and there was a refresh in progress just
   15732 	 * let it complete.  Record where we got the notify from so we
   15733 	 * can perform a refresh check when the current one completes
   15734 	 */
   15735 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
   15736 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   15737 		zone->notifyfrom = *from;
   15738 		UNLOCK_ZONE(zone);
   15739 		if (have_serial) {
   15740 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   15741 				      ISC_LOG_INFO,
   15742 				      "notify from %s: "
   15743 				      "serial %u: refresh in progress, "
   15744 				      "refresh check queued",
   15745 				      fromtext, serial);
   15746 		} else {
   15747 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   15748 				      ISC_LOG_INFO,
   15749 				      "notify from %s: "
   15750 				      "refresh in progress, "
   15751 				      "refresh check queued",
   15752 				      fromtext);
   15753 		}
   15754 		return ISC_R_SUCCESS;
   15755 	}
   15756 	if (have_serial) {
   15757 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   15758 			      "notify from %s: serial %u", fromtext, serial);
   15759 	} else {
   15760 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   15761 			      "notify from %s: no serial", fromtext);
   15762 	}
   15763 	zone->notifyfrom = *from;
   15764 	UNLOCK_ZONE(zone);
   15765 
   15766 	if (to != NULL) {
   15767 		dns_zonemgr_unreachabledel(zone->zmgr, from, to);
   15768 	}
   15769 	dns_zone_refresh(zone);
   15770 	return ISC_R_SUCCESS;
   15771 }
   15772 
   15773 void
   15774 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
   15775 	REQUIRE(DNS_ZONE_VALID(zone));
   15776 
   15777 	LOCK_ZONE(zone);
   15778 	if (zone->notify_acl != NULL) {
   15779 		dns_acl_detach(&zone->notify_acl);
   15780 	}
   15781 	dns_acl_attach(acl, &zone->notify_acl);
   15782 	UNLOCK_ZONE(zone);
   15783 }
   15784 
   15785 void
   15786 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
   15787 	REQUIRE(DNS_ZONE_VALID(zone));
   15788 
   15789 	LOCK_ZONE(zone);
   15790 	if (zone->query_acl != NULL) {
   15791 		dns_acl_detach(&zone->query_acl);
   15792 	}
   15793 	dns_acl_attach(acl, &zone->query_acl);
   15794 	UNLOCK_ZONE(zone);
   15795 }
   15796 
   15797 void
   15798 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
   15799 	REQUIRE(DNS_ZONE_VALID(zone));
   15800 
   15801 	LOCK_ZONE(zone);
   15802 	if (zone->queryon_acl != NULL) {
   15803 		dns_acl_detach(&zone->queryon_acl);
   15804 	}
   15805 	dns_acl_attach(acl, &zone->queryon_acl);
   15806 	UNLOCK_ZONE(zone);
   15807 }
   15808 
   15809 void
   15810 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
   15811 	REQUIRE(DNS_ZONE_VALID(zone));
   15812 
   15813 	LOCK_ZONE(zone);
   15814 	if (zone->update_acl != NULL) {
   15815 		dns_acl_detach(&zone->update_acl);
   15816 	}
   15817 	dns_acl_attach(acl, &zone->update_acl);
   15818 	UNLOCK_ZONE(zone);
   15819 }
   15820 
   15821 void
   15822 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
   15823 	REQUIRE(DNS_ZONE_VALID(zone));
   15824 
   15825 	LOCK_ZONE(zone);
   15826 	if (zone->forward_acl != NULL) {
   15827 		dns_acl_detach(&zone->forward_acl);
   15828 	}
   15829 	dns_acl_attach(acl, &zone->forward_acl);
   15830 	UNLOCK_ZONE(zone);
   15831 }
   15832 
   15833 void
   15834 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
   15835 	REQUIRE(DNS_ZONE_VALID(zone));
   15836 
   15837 	LOCK_ZONE(zone);
   15838 	if (zone->xfr_acl != NULL) {
   15839 		dns_acl_detach(&zone->xfr_acl);
   15840 	}
   15841 	dns_acl_attach(acl, &zone->xfr_acl);
   15842 	UNLOCK_ZONE(zone);
   15843 }
   15844 
   15845 dns_acl_t *
   15846 dns_zone_getnotifyacl(dns_zone_t *zone) {
   15847 	REQUIRE(DNS_ZONE_VALID(zone));
   15848 
   15849 	return zone->notify_acl;
   15850 }
   15851 
   15852 dns_acl_t *
   15853 dns_zone_getqueryacl(dns_zone_t *zone) {
   15854 	REQUIRE(DNS_ZONE_VALID(zone));
   15855 
   15856 	return zone->query_acl;
   15857 }
   15858 
   15859 dns_acl_t *
   15860 dns_zone_getqueryonacl(dns_zone_t *zone) {
   15861 	REQUIRE(DNS_ZONE_VALID(zone));
   15862 
   15863 	return zone->queryon_acl;
   15864 }
   15865 
   15866 dns_acl_t *
   15867 dns_zone_getupdateacl(dns_zone_t *zone) {
   15868 	REQUIRE(DNS_ZONE_VALID(zone));
   15869 
   15870 	return zone->update_acl;
   15871 }
   15872 
   15873 dns_acl_t *
   15874 dns_zone_getforwardacl(dns_zone_t *zone) {
   15875 	REQUIRE(DNS_ZONE_VALID(zone));
   15876 
   15877 	return zone->forward_acl;
   15878 }
   15879 
   15880 dns_acl_t *
   15881 dns_zone_getxfracl(dns_zone_t *zone) {
   15882 	REQUIRE(DNS_ZONE_VALID(zone));
   15883 
   15884 	return zone->xfr_acl;
   15885 }
   15886 
   15887 void
   15888 dns_zone_clearupdateacl(dns_zone_t *zone) {
   15889 	REQUIRE(DNS_ZONE_VALID(zone));
   15890 
   15891 	LOCK_ZONE(zone);
   15892 	if (zone->update_acl != NULL) {
   15893 		dns_acl_detach(&zone->update_acl);
   15894 	}
   15895 	UNLOCK_ZONE(zone);
   15896 }
   15897 
   15898 void
   15899 dns_zone_clearforwardacl(dns_zone_t *zone) {
   15900 	REQUIRE(DNS_ZONE_VALID(zone));
   15901 
   15902 	LOCK_ZONE(zone);
   15903 	if (zone->forward_acl != NULL) {
   15904 		dns_acl_detach(&zone->forward_acl);
   15905 	}
   15906 	UNLOCK_ZONE(zone);
   15907 }
   15908 
   15909 void
   15910 dns_zone_clearnotifyacl(dns_zone_t *zone) {
   15911 	REQUIRE(DNS_ZONE_VALID(zone));
   15912 
   15913 	LOCK_ZONE(zone);
   15914 	if (zone->notify_acl != NULL) {
   15915 		dns_acl_detach(&zone->notify_acl);
   15916 	}
   15917 	UNLOCK_ZONE(zone);
   15918 }
   15919 
   15920 void
   15921 dns_zone_clearqueryacl(dns_zone_t *zone) {
   15922 	REQUIRE(DNS_ZONE_VALID(zone));
   15923 
   15924 	LOCK_ZONE(zone);
   15925 	if (zone->query_acl != NULL) {
   15926 		dns_acl_detach(&zone->query_acl);
   15927 	}
   15928 	UNLOCK_ZONE(zone);
   15929 }
   15930 
   15931 void
   15932 dns_zone_clearqueryonacl(dns_zone_t *zone) {
   15933 	REQUIRE(DNS_ZONE_VALID(zone));
   15934 
   15935 	LOCK_ZONE(zone);
   15936 	if (zone->queryon_acl != NULL) {
   15937 		dns_acl_detach(&zone->queryon_acl);
   15938 	}
   15939 	UNLOCK_ZONE(zone);
   15940 }
   15941 
   15942 void
   15943 dns_zone_clearxfracl(dns_zone_t *zone) {
   15944 	REQUIRE(DNS_ZONE_VALID(zone));
   15945 
   15946 	LOCK_ZONE(zone);
   15947 	if (zone->xfr_acl != NULL) {
   15948 		dns_acl_detach(&zone->xfr_acl);
   15949 	}
   15950 	UNLOCK_ZONE(zone);
   15951 }
   15952 
   15953 bool
   15954 dns_zone_getupdatedisabled(dns_zone_t *zone) {
   15955 	REQUIRE(DNS_ZONE_VALID(zone));
   15956 	return zone->update_disabled;
   15957 }
   15958 
   15959 void
   15960 dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
   15961 	REQUIRE(DNS_ZONE_VALID(zone));
   15962 	zone->update_disabled = state;
   15963 }
   15964 
   15965 bool
   15966 dns_zone_getzeronosoattl(dns_zone_t *zone) {
   15967 	REQUIRE(DNS_ZONE_VALID(zone));
   15968 	return zone->zero_no_soa_ttl;
   15969 }
   15970 
   15971 void
   15972 dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
   15973 	REQUIRE(DNS_ZONE_VALID(zone));
   15974 	zone->zero_no_soa_ttl = state;
   15975 }
   15976 
   15977 void
   15978 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
   15979 	REQUIRE(DNS_ZONE_VALID(zone));
   15980 
   15981 	zone->check_names = severity;
   15982 }
   15983 
   15984 dns_severity_t
   15985 dns_zone_getchecknames(dns_zone_t *zone) {
   15986 	REQUIRE(DNS_ZONE_VALID(zone));
   15987 
   15988 	return zone->check_names;
   15989 }
   15990 
   15991 void
   15992 dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
   15993 	REQUIRE(DNS_ZONE_VALID(zone));
   15994 
   15995 	zone->journalsize = size;
   15996 }
   15997 
   15998 int32_t
   15999 dns_zone_getjournalsize(dns_zone_t *zone) {
   16000 	REQUIRE(DNS_ZONE_VALID(zone));
   16001 
   16002 	return zone->journalsize;
   16003 }
   16004 
   16005 static void
   16006 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
   16007 	isc_result_t result = ISC_R_FAILURE;
   16008 	isc_buffer_t buffer;
   16009 
   16010 	REQUIRE(buf != NULL);
   16011 	REQUIRE(length > 1U);
   16012 
   16013 	/*
   16014 	 * Leave space for terminating '\0'.
   16015 	 */
   16016 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   16017 	if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
   16018 		if (dns_name_dynamic(&zone->origin)) {
   16019 			result = dns_name_totext(
   16020 				&zone->origin, DNS_NAME_OMITFINALDOT, &buffer);
   16021 		}
   16022 		if (result != ISC_R_SUCCESS &&
   16023 		    isc_buffer_availablelength(&buffer) >=
   16024 			    (sizeof("<UNKNOWN>") - 1))
   16025 		{
   16026 			isc_buffer_putstr(&buffer, "<UNKNOWN>");
   16027 		}
   16028 
   16029 		if (isc_buffer_availablelength(&buffer) > 0) {
   16030 			isc_buffer_putstr(&buffer, "/");
   16031 		}
   16032 		(void)dns_rdataclass_totext(zone->rdclass, &buffer);
   16033 	}
   16034 
   16035 	if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
   16036 	    strcmp(zone->view->name, "_default") != 0 &&
   16037 	    strlen(zone->view->name) < isc_buffer_availablelength(&buffer))
   16038 	{
   16039 		isc_buffer_putstr(&buffer, "/");
   16040 		isc_buffer_putstr(&buffer, zone->view->name);
   16041 	}
   16042 	if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer)) {
   16043 		isc_buffer_putstr(&buffer, " (signed)");
   16044 	}
   16045 	if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer)) {
   16046 		isc_buffer_putstr(&buffer, " (unsigned)");
   16047 	}
   16048 
   16049 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   16050 }
   16051 
   16052 static void
   16053 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
   16054 	isc_result_t result = ISC_R_FAILURE;
   16055 	isc_buffer_t buffer;
   16056 
   16057 	REQUIRE(buf != NULL);
   16058 	REQUIRE(length > 1U);
   16059 
   16060 	/*
   16061 	 * Leave space for terminating '\0'.
   16062 	 */
   16063 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   16064 	if (dns_name_dynamic(&zone->origin)) {
   16065 		result = dns_name_totext(&zone->origin, DNS_NAME_OMITFINALDOT,
   16066 					 &buffer);
   16067 	}
   16068 	if (result != ISC_R_SUCCESS &&
   16069 	    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
   16070 	{
   16071 		isc_buffer_putstr(&buffer, "<UNKNOWN>");
   16072 	}
   16073 
   16074 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   16075 }
   16076 
   16077 static void
   16078 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
   16079 	isc_buffer_t buffer;
   16080 
   16081 	REQUIRE(buf != NULL);
   16082 	REQUIRE(length > 1U);
   16083 
   16084 	/*
   16085 	 * Leave space for terminating '\0'.
   16086 	 */
   16087 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   16088 	(void)dns_rdataclass_totext(zone->rdclass, &buffer);
   16089 
   16090 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   16091 }
   16092 
   16093 static void
   16094 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
   16095 	isc_buffer_t buffer;
   16096 
   16097 	REQUIRE(buf != NULL);
   16098 	REQUIRE(length > 1U);
   16099 
   16100 	/*
   16101 	 * Leave space for terminating '\0'.
   16102 	 */
   16103 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   16104 
   16105 	if (zone->view == NULL) {
   16106 		isc_buffer_putstr(&buffer, "_none");
   16107 	} else if (strlen(zone->view->name) <
   16108 		   isc_buffer_availablelength(&buffer))
   16109 	{
   16110 		isc_buffer_putstr(&buffer, zone->view->name);
   16111 	} else {
   16112 		isc_buffer_putstr(&buffer, "_toolong");
   16113 	}
   16114 
   16115 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   16116 }
   16117 
   16118 void
   16119 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
   16120 	REQUIRE(DNS_ZONE_VALID(zone));
   16121 	REQUIRE(buf != NULL);
   16122 
   16123 	LOCK_ZONE(zone);
   16124 	zone_namerd_tostr(zone, buf, length);
   16125 	UNLOCK_ZONE(zone);
   16126 }
   16127 
   16128 void
   16129 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
   16130 	REQUIRE(DNS_ZONE_VALID(zone));
   16131 	REQUIRE(buf != NULL);
   16132 	zone_name_tostr(zone, buf, length);
   16133 }
   16134 
   16135 void
   16136 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
   16137 	      const char *prefix, const char *fmt, va_list ap) {
   16138 	char message[4096];
   16139 	const char *zstr;
   16140 
   16141 	REQUIRE(DNS_ZONE_VALID(zone));
   16142 
   16143 	if (!isc_log_wouldlog(dns_lctx, level)) {
   16144 		return;
   16145 	}
   16146 
   16147 	vsnprintf(message, sizeof(message), fmt, ap);
   16148 
   16149 	switch (zone->type) {
   16150 	case dns_zone_key:
   16151 		zstr = "managed-keys-zone";
   16152 		break;
   16153 	case dns_zone_redirect:
   16154 		zstr = "redirect-zone";
   16155 		break;
   16156 	default:
   16157 		zstr = "zone ";
   16158 	}
   16159 
   16160 	isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
   16161 		      "%s%s%s%s: %s", prefix != NULL ? prefix : "",
   16162 		      prefix != NULL ? ": " : "", zstr, zone->strnamerd,
   16163 		      message);
   16164 }
   16165 
   16166 static void
   16167 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
   16168 	va_list ap;
   16169 
   16170 	va_start(ap, fmt);
   16171 	dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
   16172 	va_end(ap);
   16173 }
   16174 
   16175 void
   16176 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, int level,
   16177 	      const char *fmt, ...) {
   16178 	va_list ap;
   16179 
   16180 	va_start(ap, fmt);
   16181 	dns_zone_logv(zone, category, level, NULL, fmt, ap);
   16182 	va_end(ap);
   16183 }
   16184 
   16185 void
   16186 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
   16187 	va_list ap;
   16188 
   16189 	va_start(ap, fmt);
   16190 	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
   16191 	va_end(ap);
   16192 }
   16193 
   16194 static void
   16195 zone_debuglogc(dns_zone_t *zone, isc_logcategory_t *category, const char *me,
   16196 	       int debuglevel, const char *fmt, ...) {
   16197 	int level = ISC_LOG_DEBUG(debuglevel);
   16198 	va_list ap;
   16199 
   16200 	va_start(ap, fmt);
   16201 	dns_zone_logv(zone, category, level, me, fmt, ap);
   16202 	va_end(ap);
   16203 }
   16204 
   16205 static void
   16206 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, const char *fmt,
   16207 	      ...) {
   16208 	int level = ISC_LOG_DEBUG(debuglevel);
   16209 	va_list ap;
   16210 
   16211 	va_start(ap, fmt);
   16212 	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
   16213 	va_end(ap);
   16214 }
   16215 
   16216 static void
   16217 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
   16218 	va_list ap;
   16219 
   16220 	va_start(ap, fmt);
   16221 	dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
   16222 	va_end(ap);
   16223 }
   16224 
   16225 static int
   16226 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) {
   16227 	isc_result_t result;
   16228 	dns_name_t *name;
   16229 	dns_rdataset_t *curr;
   16230 	int count = 0;
   16231 
   16232 	result = dns_message_firstname(msg, section);
   16233 	while (result == ISC_R_SUCCESS) {
   16234 		name = NULL;
   16235 		dns_message_currentname(msg, section, &name);
   16236 
   16237 		for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
   16238 		     curr = ISC_LIST_PREV(curr, link))
   16239 		{
   16240 			if (curr->type == type) {
   16241 				count++;
   16242 			}
   16243 		}
   16244 		result = dns_message_nextname(msg, section);
   16245 	}
   16246 
   16247 	return count;
   16248 }
   16249 
   16250 void
   16251 dns_zone_setminxfrratein(dns_zone_t *zone, uint32_t bytes, uint32_t seconds) {
   16252 	REQUIRE(DNS_ZONE_VALID(zone));
   16253 
   16254 	zone->minxfrratebytesin = bytes;
   16255 	zone->minxfrratesecondsin = seconds;
   16256 }
   16257 
   16258 uint32_t
   16259 dns_zone_getminxfrratebytesin(dns_zone_t *zone) {
   16260 	REQUIRE(DNS_ZONE_VALID(zone));
   16261 
   16262 	return zone->minxfrratebytesin;
   16263 }
   16264 
   16265 uint32_t
   16266 dns_zone_getminxfrratesecondsin(dns_zone_t *zone) {
   16267 	REQUIRE(DNS_ZONE_VALID(zone));
   16268 
   16269 	return zone->minxfrratesecondsin;
   16270 }
   16271 
   16272 void
   16273 dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
   16274 	REQUIRE(DNS_ZONE_VALID(zone));
   16275 
   16276 	zone->maxxfrin = maxxfrin;
   16277 }
   16278 
   16279 uint32_t
   16280 dns_zone_getmaxxfrin(dns_zone_t *zone) {
   16281 	REQUIRE(DNS_ZONE_VALID(zone));
   16282 
   16283 	return zone->maxxfrin;
   16284 }
   16285 
   16286 void
   16287 dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
   16288 	REQUIRE(DNS_ZONE_VALID(zone));
   16289 	zone->maxxfrout = maxxfrout;
   16290 }
   16291 
   16292 uint32_t
   16293 dns_zone_getmaxxfrout(dns_zone_t *zone) {
   16294 	REQUIRE(DNS_ZONE_VALID(zone));
   16295 
   16296 	return zone->maxxfrout;
   16297 }
   16298 
   16299 dns_zonetype_t
   16300 dns_zone_gettype(dns_zone_t *zone) {
   16301 	REQUIRE(DNS_ZONE_VALID(zone));
   16302 
   16303 	return zone->type;
   16304 }
   16305 
   16306 const char *
   16307 dns_zonetype_name(dns_zonetype_t type) {
   16308 	switch (type) {
   16309 	case dns_zone_none:
   16310 		return "none";
   16311 	case dns_zone_primary:
   16312 		return "primary";
   16313 	case dns_zone_secondary:
   16314 		return "secondary";
   16315 	case dns_zone_mirror:
   16316 		return "mirror";
   16317 	case dns_zone_stub:
   16318 		return "stub";
   16319 	case dns_zone_staticstub:
   16320 		return "static-stub";
   16321 	case dns_zone_key:
   16322 		return "key";
   16323 	case dns_zone_dlz:
   16324 		return "dlz";
   16325 	case dns_zone_redirect:
   16326 		return "redirect";
   16327 	default:
   16328 		return "unknown";
   16329 	}
   16330 }
   16331 
   16332 dns_zonetype_t
   16333 dns_zone_getredirecttype(dns_zone_t *zone) {
   16334 	REQUIRE(DNS_ZONE_VALID(zone));
   16335 	REQUIRE(zone->type == dns_zone_redirect);
   16336 
   16337 	return dns_remote_addresses(&zone->primaries) == NULL
   16338 		       ? dns_zone_primary
   16339 		       : dns_zone_secondary;
   16340 }
   16341 
   16342 dns_name_t *
   16343 dns_zone_getorigin(dns_zone_t *zone) {
   16344 	REQUIRE(DNS_ZONE_VALID(zone));
   16345 
   16346 	return &zone->origin;
   16347 }
   16348 
   16349 void
   16350 dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
   16351 	REQUIRE(DNS_ZONE_VALID(zone));
   16352 
   16353 	if (idlein == 0) {
   16354 		idlein = DNS_DEFAULT_IDLEIN;
   16355 	}
   16356 	zone->idlein = idlein;
   16357 }
   16358 
   16359 uint32_t
   16360 dns_zone_getidlein(dns_zone_t *zone) {
   16361 	REQUIRE(DNS_ZONE_VALID(zone));
   16362 
   16363 	return zone->idlein;
   16364 }
   16365 
   16366 void
   16367 dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
   16368 	REQUIRE(DNS_ZONE_VALID(zone));
   16369 
   16370 	zone->idleout = idleout;
   16371 }
   16372 
   16373 uint32_t
   16374 dns_zone_getidleout(dns_zone_t *zone) {
   16375 	REQUIRE(DNS_ZONE_VALID(zone));
   16376 
   16377 	return zone->idleout;
   16378 }
   16379 
   16380 static void
   16381 notify_done(void *arg) {
   16382 	dns_request_t *request = (dns_request_t *)arg;
   16383 	dns_notify_t *notify = dns_request_getarg(request);
   16384 	isc_result_t result;
   16385 	dns_message_t *message = NULL;
   16386 	isc_buffer_t buf;
   16387 	char rcode[128];
   16388 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   16389 
   16390 	REQUIRE(DNS_NOTIFY_VALID(notify));
   16391 
   16392 	isc_buffer_init(&buf, rcode, sizeof(rcode));
   16393 	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
   16394 	dns_message_create(notify->zone->mctx, NULL, NULL,
   16395 			   DNS_MESSAGE_INTENTPARSE, &message);
   16396 
   16397 	result = dns_request_getresult(request);
   16398 	if (result != ISC_R_SUCCESS) {
   16399 		goto fail;
   16400 	}
   16401 
   16402 	result = dns_request_getresponse(request, message,
   16403 					 DNS_MESSAGEPARSE_PRESERVEORDER);
   16404 	if (result != ISC_R_SUCCESS) {
   16405 		goto fail;
   16406 	}
   16407 
   16408 	result = dns_rcode_totext(message->rcode, &buf);
   16409 	if (result == ISC_R_SUCCESS) {
   16410 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
   16411 			   "notify response from %s: %.*s", addrbuf,
   16412 			   (int)buf.used, rcode);
   16413 	}
   16414 
   16415 fail:
   16416 	dns_message_detach(&message);
   16417 
   16418 	if (result == ISC_R_SUCCESS) {
   16419 		notify_log(notify->zone, ISC_LOG_DEBUG(1),
   16420 			   "notify to %s successful", addrbuf);
   16421 	} else if (result == ISC_R_SHUTTINGDOWN || result == ISC_R_CANCELED) {
   16422 		/* just destroy the notify */
   16423 	} else if ((notify->flags & DNS_NOTIFY_TCP) == 0) {
   16424 		notify_log(notify->zone, ISC_LOG_NOTICE,
   16425 			   "notify to %s failed: %s: retrying over TCP",
   16426 			   addrbuf, isc_result_totext(result));
   16427 		notify->flags |= DNS_NOTIFY_TCP;
   16428 		dns_request_destroy(&notify->request);
   16429 		notify_send_queue(notify, notify->flags & DNS_NOTIFY_STARTUP);
   16430 		return;
   16431 	} else if (result == ISC_R_TIMEDOUT) {
   16432 		notify_log(notify->zone, ISC_LOG_WARNING,
   16433 			   "notify to %s failed: %s: retries exceeded", addrbuf,
   16434 			   isc_result_totext(result));
   16435 	} else {
   16436 		notify_log(notify->zone, ISC_LOG_WARNING,
   16437 			   "notify to %s failed: %s", addrbuf,
   16438 			   isc_result_totext(result));
   16439 	}
   16440 	notify_destroy(notify, false);
   16441 }
   16442 
   16443 struct rss {
   16444 	dns_zone_t *zone;
   16445 	dns_db_t *db;
   16446 	uint32_t serial;
   16447 	ISC_LINK(struct rss) link;
   16448 };
   16449 
   16450 static void
   16451 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
   16452 	UNUSED(arg);
   16453 	dns_zone_log(zone, level, "%s", message);
   16454 }
   16455 
   16456 static isc_result_t
   16457 dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, isc_mem_t *mctx,
   16458 	     dns_dnsseckeylist_t *keylist, bool *inuse) {
   16459 	isc_result_t result;
   16460 	dst_key_t *dstkey = NULL;
   16461 
   16462 	result = dns_dnssec_keyfromrdata(dns_zone_getorigin(zone), rdata, mctx,
   16463 					 &dstkey);
   16464 	if (result != ISC_R_SUCCESS) {
   16465 		dns_zone_log(zone, ISC_LOG_ERROR,
   16466 			     "dns_dnssec_keyfromrdata() failed: %s",
   16467 			     isc_result_totext(result));
   16468 		return result;
   16469 	}
   16470 
   16471 	for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL;
   16472 	     k = ISC_LIST_NEXT(k, link))
   16473 	{
   16474 		if (dst_key_pubcompare(k->key, dstkey, false)) {
   16475 			*inuse = true;
   16476 			break;
   16477 		}
   16478 	}
   16479 
   16480 	dst_key_free(&dstkey);
   16481 	return ISC_R_SUCCESS;
   16482 }
   16483 
   16484 static isc_result_t
   16485 cdnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata,
   16486 	      dns_dnsseckeylist_t *keylist, bool *inuse) {
   16487 	isc_result_t result;
   16488 	dns_rdata_cdnskey_t cdnskey;
   16489 
   16490 	result = dns_rdata_tostruct(rdata, &cdnskey, NULL);
   16491 	if (result != ISC_R_SUCCESS) {
   16492 		dns_zone_log(zone, ISC_LOG_ERROR,
   16493 			     "dns_rdata_tostruct(cdnskey) failed: %s",
   16494 			     isc_result_totext(result));
   16495 		return result;
   16496 	}
   16497 
   16498 	for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL;
   16499 	     k = ISC_LIST_NEXT(k, link))
   16500 	{
   16501 		dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT;
   16502 		unsigned char keybuf[DST_KEY_MAXSIZE];
   16503 
   16504 		result = dns_dnssec_make_dnskey(k->key, keybuf, sizeof(keybuf),
   16505 						&cdnskeyrdata);
   16506 		if (result != ISC_R_SUCCESS) {
   16507 			dns_zone_log(zone, ISC_LOG_ERROR,
   16508 				     "dns_dnssec_make_dnskey() failed: %s",
   16509 				     isc_result_totext(result));
   16510 			return result;
   16511 		}
   16512 
   16513 		cdnskeyrdata.type = dns_rdatatype_cdnskey;
   16514 		if (dns_rdata_compare(rdata, &cdnskeyrdata) == 0) {
   16515 			*inuse = true;
   16516 			break;
   16517 		}
   16518 	}
   16519 
   16520 	return ISC_R_SUCCESS;
   16521 }
   16522 
   16523 static isc_result_t
   16524 cds_inuse(dns_zone_t *zone, dns_rdata_t *rdata, dns_dnsseckeylist_t *keylist,
   16525 	  bool *inuse) {
   16526 	isc_result_t result;
   16527 	dns_rdata_ds_t cds;
   16528 
   16529 	result = dns_rdata_tostruct(rdata, &cds, NULL);
   16530 	if (result != ISC_R_SUCCESS) {
   16531 		dns_zone_log(zone, ISC_LOG_ERROR,
   16532 			     "dns_rdata_tostruct(cds) failed: %s",
   16533 			     isc_result_totext(result));
   16534 		return result;
   16535 	}
   16536 
   16537 	for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL;
   16538 	     k = ISC_LIST_NEXT(k, link))
   16539 	{
   16540 		dns_rdata_t dnskey = DNS_RDATA_INIT;
   16541 		dns_rdata_t cdsrdata = DNS_RDATA_INIT;
   16542 		unsigned char keybuf[DST_KEY_MAXSIZE];
   16543 		unsigned char cdsbuf[DNS_DS_BUFFERSIZE];
   16544 
   16545 		if (dst_key_id(k->key) != cds.key_tag ||
   16546 		    dst_key_alg(k->key) != cds.algorithm)
   16547 		{
   16548 			continue;
   16549 		}
   16550 		result = dns_dnssec_make_dnskey(k->key, keybuf, sizeof(keybuf),
   16551 						&dnskey);
   16552 		if (result != ISC_R_SUCCESS) {
   16553 			dns_zone_log(zone, ISC_LOG_ERROR,
   16554 				     "dns_dnssec_make_dnskey() failed: %s",
   16555 				     isc_result_totext(result));
   16556 			return result;
   16557 		}
   16558 		result = dns_ds_buildrdata(dns_zone_getorigin(zone), &dnskey,
   16559 					   cds.digest_type, cdsbuf, &cdsrdata);
   16560 		if (result != ISC_R_SUCCESS) {
   16561 			dns_zone_log(zone, ISC_LOG_ERROR,
   16562 				     "dns_ds_buildrdata(keytag=%d, algo=%d, "
   16563 				     "digest=%d) failed: %s",
   16564 				     cds.key_tag, cds.algorithm,
   16565 				     cds.digest_type,
   16566 				     isc_result_totext(result));
   16567 			return result;
   16568 		}
   16569 
   16570 		cdsrdata.type = dns_rdatatype_cds;
   16571 		if (dns_rdata_compare(rdata, &cdsrdata) == 0) {
   16572 			*inuse = true;
   16573 			break;
   16574 		}
   16575 	}
   16576 
   16577 	return ISC_R_SUCCESS;
   16578 }
   16579 
   16580 isc_result_t
   16581 dns_zone_dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, bool *inuse) {
   16582 	dns_dnsseckeylist_t keylist;
   16583 	dns_dnsseckey_t *key = NULL;
   16584 	isc_result_t result = ISC_R_SUCCESS;
   16585 	isc_stdtime_t now = isc_stdtime_now();
   16586 	isc_mem_t *mctx;
   16587 	dns_kasp_t *kasp;
   16588 	dns_keystorelist_t *keystores;
   16589 	const char *keydir;
   16590 
   16591 	REQUIRE(DNS_ZONE_VALID(zone));
   16592 	REQUIRE(dns_rdatatype_iskeymaterial(rdata->type));
   16593 
   16594 	mctx = zone->mctx;
   16595 
   16596 	ISC_LIST_INIT(keylist);
   16597 
   16598 	*inuse = false;
   16599 
   16600 	kasp = dns_zone_getkasp(zone);
   16601 	keydir = dns_zone_getkeydirectory(zone);
   16602 	keystores = dns_zone_getkeystores(zone);
   16603 
   16604 	dns_zone_lock_keyfiles(zone);
   16605 	result = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone), kasp,
   16606 					     keydir, keystores, now, false,
   16607 					     mctx, &keylist);
   16608 	dns_zone_unlock_keyfiles(zone);
   16609 	if (result == ISC_R_NOTFOUND) {
   16610 		return ISC_R_SUCCESS;
   16611 	} else if (result != ISC_R_SUCCESS) {
   16612 		dns_zone_log(zone, ISC_LOG_ERROR,
   16613 			     "dns_dnssec_findmatchingkeys() failed: %s",
   16614 			     isc_result_totext(result));
   16615 		return result;
   16616 	}
   16617 
   16618 	switch (rdata->type) {
   16619 	case dns_rdatatype_dnskey:
   16620 		result = dnskey_inuse(zone, rdata, mctx, &keylist, inuse);
   16621 		break;
   16622 	case dns_rdatatype_cdnskey:
   16623 		result = cdnskey_inuse(zone, rdata, &keylist, inuse);
   16624 		break;
   16625 	case dns_rdatatype_cds:
   16626 		result = cds_inuse(zone, rdata, &keylist, inuse);
   16627 		break;
   16628 	default:
   16629 		UNREACHABLE();
   16630 		break;
   16631 	}
   16632 
   16633 	while (!ISC_LIST_EMPTY(keylist)) {
   16634 		key = ISC_LIST_HEAD(keylist);
   16635 		ISC_LIST_UNLINK(keylist, key, link);
   16636 		dns_dnsseckey_destroy(mctx, &key);
   16637 	}
   16638 	return result;
   16639 }
   16640 
   16641 static isc_result_t
   16642 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
   16643 		    uint32_t start, uint32_t end, dns_difftuple_t **soatuplep,
   16644 		    dns_diff_t *diff) {
   16645 	isc_result_t result;
   16646 	dns_difftuple_t *tuple = NULL;
   16647 	dns_diffop_t op = DNS_DIFFOP_ADD;
   16648 	int n_soa = 0;
   16649 
   16650 	REQUIRE(soatuplep != NULL);
   16651 
   16652 	if (start == end) {
   16653 		return DNS_R_UNCHANGED;
   16654 	}
   16655 
   16656 	CHECK(dns_journal_iter_init(journal, start, end, NULL));
   16657 	for (result = dns_journal_first_rr(journal); result == ISC_R_SUCCESS;
   16658 	     result = dns_journal_next_rr(journal))
   16659 	{
   16660 		dns_name_t *name = NULL;
   16661 		uint32_t ttl;
   16662 		dns_rdata_t *rdata = NULL;
   16663 		dns_journal_current_rr(journal, &name, &ttl, &rdata);
   16664 
   16665 		if (rdata->type == dns_rdatatype_soa) {
   16666 			n_soa++;
   16667 			if (n_soa == 2) {
   16668 				/*
   16669 				 * Save the latest raw SOA record.
   16670 				 */
   16671 				if (*soatuplep != NULL) {
   16672 					dns_difftuple_free(soatuplep);
   16673 				}
   16674 				CHECK(dns_difftuple_create(
   16675 					diff->mctx, DNS_DIFFOP_ADD, name, ttl,
   16676 					rdata, soatuplep));
   16677 			}
   16678 			if (n_soa == 3) {
   16679 				n_soa = 1;
   16680 			}
   16681 			continue;
   16682 		}
   16683 
   16684 		/* Sanity. */
   16685 		if (n_soa == 0) {
   16686 			dns_zone_log(raw, ISC_LOG_ERROR,
   16687 				     "corrupt journal file: '%s'\n",
   16688 				     raw->journal);
   16689 			return ISC_R_FAILURE;
   16690 		}
   16691 
   16692 		if (zone->privatetype != 0 && rdata->type == zone->privatetype)
   16693 		{
   16694 			continue;
   16695 		}
   16696 
   16697 		/*
   16698 		 * Skip DNSSEC records that BIND maintains with inline-signing.
   16699 		 */
   16700 		if (rdata->type == dns_rdatatype_nsec ||
   16701 		    rdata->type == dns_rdatatype_rrsig ||
   16702 		    rdata->type == dns_rdatatype_nsec3 ||
   16703 		    rdata->type == dns_rdatatype_nsec3param)
   16704 		{
   16705 			continue;
   16706 		}
   16707 		/*
   16708 		 * Allow DNSKEY, CDNSKEY, CDS because users should be able to
   16709 		 * update the zone with these records from a different provider,
   16710 		 * but skip records that are under our control.
   16711 		 */
   16712 		if (dns_rdatatype_iskeymaterial(rdata->type)) {
   16713 			bool inuse = false;
   16714 			isc_result_t r = dns_zone_dnskey_inuse(zone, rdata,
   16715 							       &inuse);
   16716 			if (r == ISC_R_SUCCESS && inuse) {
   16717 				continue;
   16718 			}
   16719 		}
   16720 
   16721 		op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
   16722 
   16723 		CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
   16724 					   &tuple));
   16725 		dns_diff_appendminimal(diff, &tuple);
   16726 	}
   16727 	if (result == ISC_R_NOMORE) {
   16728 		result = ISC_R_SUCCESS;
   16729 	}
   16730 
   16731 cleanup:
   16732 	return result;
   16733 }
   16734 
   16735 /*
   16736  * Filter the key material preserving TTL changes.  If kasp in effect honour the
   16737  * existing ttl.  The lists returned by sync_secure_db/dns_db_diffx should be
   16738  * DNSSEC RRset order so we can process 'del' and 'add' in parallel rather than
   16739  * searching for TTL only changes first and processing them, then checking the
   16740  * 'in use' status on a subsequent pass.
   16741  */
   16742 
   16743 static void
   16744 filter_keymaterial(dns_zone_t *zone, dns_difftuplelist_t *del,
   16745 		   dns_difftuplelist_t *add, bool kasp, dns_ttl_t ttl) {
   16746 	dns_difftuple_t *deltuple = ISC_LIST_HEAD(*del);
   16747 	dns_difftuple_t *addtuple = ISC_LIST_HEAD(*add);
   16748 	isc_result_t result;
   16749 
   16750 	while (deltuple != NULL || addtuple != NULL) {
   16751 		dns_difftuple_t *delnext = NULL, *addnext = NULL;
   16752 		bool inuse = false;
   16753 		if (deltuple != NULL) {
   16754 			delnext = ISC_LIST_NEXT(deltuple, link);
   16755 		}
   16756 		if (addtuple != NULL) {
   16757 			addnext = ISC_LIST_NEXT(addtuple, link);
   16758 		}
   16759 		if (deltuple != NULL && addtuple != NULL) {
   16760 			int n = dns_rdata_compare(&deltuple->rdata,
   16761 						  &addtuple->rdata);
   16762 			if (n == 0) {
   16763 				/*
   16764 				 * If the rdata is equal then the only
   16765 				 * difference will be a TTL change.
   16766 				 */
   16767 				if (kasp) {
   16768 					/* TTL is managed by dnssec-policy */
   16769 					ISC_LIST_UNLINK(*del, deltuple, link);
   16770 					dns_difftuple_free(&deltuple);
   16771 					ISC_LIST_UNLINK(*add, addtuple, link);
   16772 					dns_difftuple_free(&addtuple);
   16773 				}
   16774 				deltuple = delnext;
   16775 				addtuple = addnext;
   16776 				continue;
   16777 			}
   16778 			if (n < 0) {
   16779 				goto checkdel;
   16780 			}
   16781 			goto checkadd;
   16782 		} else if (deltuple != NULL) {
   16783 		checkdel:
   16784 			result = dns_zone_dnskey_inuse(zone, &deltuple->rdata,
   16785 						       &inuse);
   16786 			if (result == ISC_R_SUCCESS && inuse) {
   16787 				ISC_LIST_UNLINK(*del, deltuple, link);
   16788 				dns_difftuple_free(&deltuple);
   16789 			}
   16790 			deltuple = delnext;
   16791 		} else {
   16792 		checkadd:
   16793 			result = dns_zone_dnskey_inuse(zone, &addtuple->rdata,
   16794 						       &inuse);
   16795 			if (result == ISC_R_SUCCESS && inuse) {
   16796 				ISC_LIST_UNLINK(*add, addtuple, link);
   16797 				dns_difftuple_free(&addtuple);
   16798 			} else if (kasp) {
   16799 				addtuple->ttl = ttl;
   16800 			}
   16801 			addtuple = addnext;
   16802 		}
   16803 	}
   16804 }
   16805 
   16806 static isc_result_t
   16807 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
   16808 	       dns_dbversion_t *secver, dns_difftuple_t **soatuple,
   16809 	       dns_diff_t *diff) {
   16810 	isc_result_t result;
   16811 	dns_db_t *rawdb = NULL;
   16812 	dns_dbversion_t *rawver = NULL;
   16813 	dns_difftuple_t *tuple = NULL, *next;
   16814 	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
   16815 	dns_rdata_soa_t oldsoa, newsoa;
   16816 	dns_difftuplelist_t add = ISC_LIST_INITIALIZER;
   16817 	dns_difftuplelist_t del = ISC_LIST_INITIALIZER;
   16818 	dns_difftuplelist_t keyadd = ISC_LIST_INITIALIZER;
   16819 	dns_difftuplelist_t keydel = ISC_LIST_INITIALIZER;
   16820 	dns_difftuplelist_t ckeyadd = ISC_LIST_INITIALIZER;
   16821 	dns_difftuplelist_t ckeydel = ISC_LIST_INITIALIZER;
   16822 	dns_difftuplelist_t cdsadd = ISC_LIST_INITIALIZER;
   16823 	dns_difftuplelist_t cdsdel = ISC_LIST_INITIALIZER;
   16824 	dns_kasp_t *kasp = NULL;
   16825 	dns_ttl_t keyttl = 0, ckeyttl = 0, cdsttl = 0;
   16826 
   16827 	REQUIRE(DNS_ZONE_VALID(seczone));
   16828 	REQUIRE(soatuple != NULL && *soatuple == NULL);
   16829 
   16830 	if (!seczone->sourceserialset) {
   16831 		return DNS_R_UNCHANGED;
   16832 	}
   16833 
   16834 	dns_db_attach(raw->db, &rawdb);
   16835 	dns_db_currentversion(rawdb, &rawver);
   16836 	result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
   16837 	dns_db_closeversion(rawdb, &rawver, false);
   16838 	dns_db_detach(&rawdb);
   16839 
   16840 	if (result != ISC_R_SUCCESS) {
   16841 		return result;
   16842 	}
   16843 
   16844 	/*
   16845 	 * If kasp is in effect honour the existing DNSKEY, CDNSKEY and CDS
   16846 	 * TTLs.
   16847 	 */
   16848 	kasp = seczone->kasp;
   16849 	if (kasp != NULL) {
   16850 		dns_rdataset_t rdataset;
   16851 		dns_dbnode_t *node = NULL;
   16852 		dns_ttl_t ttl = dns_kasp_dnskeyttl(kasp);
   16853 
   16854 		dns_rdataset_init(&rdataset);
   16855 
   16856 		result = dns_db_getoriginnode(secdb, &node);
   16857 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   16858 
   16859 		result = dns_db_findrdataset(
   16860 			secdb, node, secver, dns_rdatatype_dnskey,
   16861 			dns_rdatatype_none, 0, &rdataset, NULL);
   16862 		keyttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl;
   16863 		if (dns_rdataset_isassociated(&rdataset)) {
   16864 			dns_rdataset_disassociate(&rdataset);
   16865 		}
   16866 
   16867 		result = dns_db_findrdataset(
   16868 			secdb, node, secver, dns_rdatatype_cdnskey,
   16869 			dns_rdatatype_none, 0, &rdataset, NULL);
   16870 		ckeyttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl;
   16871 		if (dns_rdataset_isassociated(&rdataset)) {
   16872 			dns_rdataset_disassociate(&rdataset);
   16873 		}
   16874 
   16875 		result = dns_db_findrdataset(
   16876 			secdb, node, secver, dns_rdatatype_cds,
   16877 			dns_rdatatype_none, 0, &rdataset, NULL);
   16878 		cdsttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl;
   16879 		if (dns_rdataset_isassociated(&rdataset)) {
   16880 			dns_rdataset_disassociate(&rdataset);
   16881 		}
   16882 		dns_db_detachnode(secdb, &node);
   16883 	}
   16884 
   16885 	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) {
   16886 		dns_difftuplelist_t *al = &add, *dl = &del;
   16887 
   16888 		next = ISC_LIST_NEXT(tuple, link);
   16889 
   16890 		/*
   16891 		 * Skip private records that BIND maintains with inline-signing.
   16892 		 */
   16893 		if (seczone->privatetype != 0 &&
   16894 		    tuple->rdata.type == seczone->privatetype)
   16895 		{
   16896 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
   16897 			dns_difftuple_free(&tuple);
   16898 			continue;
   16899 		}
   16900 
   16901 		/*
   16902 		 * Skip DNSSEC records that BIND maintains with inline-signing.
   16903 		 */
   16904 		if (tuple->rdata.type == dns_rdatatype_nsec ||
   16905 		    tuple->rdata.type == dns_rdatatype_rrsig ||
   16906 		    tuple->rdata.type == dns_rdatatype_nsec3 ||
   16907 		    tuple->rdata.type == dns_rdatatype_nsec3param)
   16908 		{
   16909 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
   16910 			dns_difftuple_free(&tuple);
   16911 			continue;
   16912 		}
   16913 
   16914 		/*
   16915 		 * Apex DNSKEY, CDNSKEY and CDS need special processing so
   16916 		 * split them out.
   16917 		 */
   16918 		if (dns_rdatatype_iskeymaterial(tuple->rdata.type) &&
   16919 		    dns_name_equal(&tuple->name, &seczone->origin))
   16920 		{
   16921 			switch (tuple->rdata.type) {
   16922 			case dns_rdatatype_dnskey:
   16923 				al = &keyadd;
   16924 				dl = &keydel;
   16925 				break;
   16926 			case dns_rdatatype_cdnskey:
   16927 				al = &ckeyadd;
   16928 				dl = &ckeydel;
   16929 				break;
   16930 			case dns_rdatatype_cds:
   16931 				al = &cdsadd;
   16932 				dl = &cdsdel;
   16933 				break;
   16934 			default:
   16935 				UNREACHABLE();
   16936 			}
   16937 		}
   16938 
   16939 		if (tuple->rdata.type == dns_rdatatype_soa) {
   16940 			if (tuple->op == DNS_DIFFOP_DEL) {
   16941 				INSIST(oldtuple == NULL);
   16942 				oldtuple = tuple;
   16943 			}
   16944 			if (tuple->op == DNS_DIFFOP_ADD) {
   16945 				INSIST(newtuple == NULL);
   16946 				newtuple = tuple;
   16947 			}
   16948 		}
   16949 
   16950 		/*
   16951 		 * Split into deletions and additions.
   16952 		 */
   16953 		ISC_LIST_UNLINK(diff->tuples, tuple, link);
   16954 		switch (tuple->op) {
   16955 		case DNS_DIFFOP_DEL:
   16956 		case DNS_DIFFOP_DELRESIGN:
   16957 			ISC_LIST_APPEND(*dl, tuple, link);
   16958 			break;
   16959 		case DNS_DIFFOP_ADD:
   16960 		case DNS_DIFFOP_ADDRESIGN:
   16961 			ISC_LIST_APPEND(*al, tuple, link);
   16962 			break;
   16963 		default:
   16964 			UNREACHABLE();
   16965 		}
   16966 	}
   16967 
   16968 	if (oldtuple != NULL && newtuple != NULL) {
   16969 		result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
   16970 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   16971 
   16972 		result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
   16973 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   16974 
   16975 		/*
   16976 		 * If the SOA records are the same except for the serial
   16977 		 * remove them from the diff.
   16978 		 */
   16979 		if (oldtuple->ttl == newtuple->ttl &&
   16980 		    oldsoa.refresh == newsoa.refresh &&
   16981 		    oldsoa.retry == newsoa.retry &&
   16982 		    oldsoa.minimum == newsoa.minimum &&
   16983 		    oldsoa.expire == newsoa.expire &&
   16984 		    dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
   16985 		    dns_name_equal(&oldsoa.contact, &newsoa.contact))
   16986 		{
   16987 			ISC_LIST_UNLINK(del, oldtuple, link);
   16988 			dns_difftuple_free(&oldtuple);
   16989 			ISC_LIST_UNLINK(add, newtuple, link);
   16990 			dns_difftuple_free(&newtuple);
   16991 		}
   16992 	}
   16993 
   16994 	/*
   16995 	 * Filter out keys we manage but still allow TTL changes.
   16996 	 */
   16997 	filter_keymaterial(seczone, &keydel, &keyadd, kasp != NULL, keyttl);
   16998 	filter_keymaterial(seczone, &ckeydel, &ckeyadd, kasp != NULL, ckeyttl);
   16999 	filter_keymaterial(seczone, &cdsdel, &cdsadd, kasp != NULL, cdsttl);
   17000 
   17001 	/*
   17002 	 * Rebuild the diff now that we have filtered it
   17003 	 */
   17004 	ISC_LIST_APPENDLIST(diff->tuples, del, link);
   17005 	ISC_LIST_APPENDLIST(diff->tuples, keydel, link);
   17006 	ISC_LIST_APPENDLIST(diff->tuples, ckeydel, link);
   17007 	ISC_LIST_APPENDLIST(diff->tuples, cdsdel, link);
   17008 	ISC_LIST_APPENDLIST(diff->tuples, add, link);
   17009 	ISC_LIST_APPENDLIST(diff->tuples, keyadd, link);
   17010 	ISC_LIST_APPENDLIST(diff->tuples, ckeyadd, link);
   17011 	ISC_LIST_APPENDLIST(diff->tuples, cdsadd, link);
   17012 
   17013 	if (ISC_LIST_EMPTY(diff->tuples)) {
   17014 		return DNS_R_UNCHANGED;
   17015 	}
   17016 
   17017 	/*
   17018 	 * If there are still SOA records in the diff they can now be removed
   17019 	 * saving the new SOA record.
   17020 	 */
   17021 	if (oldtuple != NULL) {
   17022 		ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
   17023 		dns_difftuple_free(&oldtuple);
   17024 	}
   17025 
   17026 	if (newtuple != NULL) {
   17027 		ISC_LIST_UNLINK(diff->tuples, newtuple, link);
   17028 		*soatuple = newtuple;
   17029 	}
   17030 
   17031 	return ISC_R_SUCCESS;
   17032 }
   17033 
   17034 static void
   17035 receive_secure_serial(void *arg) {
   17036 	struct rss *rss = (struct rss *)arg;
   17037 	dns_zone_t *zone = rss->zone;
   17038 	isc_result_t result = ISC_R_SUCCESS;
   17039 	dns_journal_t *rjournal = NULL;
   17040 	dns_journal_t *sjournal = NULL;
   17041 	uint32_t start, end = rss->serial;
   17042 	dns_difftuple_t *tuple = NULL, *soatuple = NULL;
   17043 	dns_update_log_t log = { update_log_cb, NULL };
   17044 	uint32_t newserial = 0, desired = 0;
   17045 	isc_time_t timenow;
   17046 	int level = ISC_LOG_ERROR;
   17047 
   17048 	ENTER;
   17049 
   17050 	LOCK_ZONE(zone);
   17051 
   17052 	/*
   17053 	 * The receive_secure_serial() is loop-serialized for the zone.  Make
   17054 	 * sure there's no processing currently running.
   17055 	 */
   17056 
   17057 	INSIST(zone->rss == NULL || zone->rss == rss);
   17058 
   17059 	if (zone->rss != NULL) {
   17060 		INSIST(zone->rss == rss);
   17061 		UNLOCK_ZONE(zone);
   17062 	} else {
   17063 		zone->rss = rss;
   17064 		dns_diff_init(zone->mctx, &zone->rss_diff);
   17065 
   17066 		/*
   17067 		 * zone->db may be NULL, if the load from disk failed.
   17068 		 */
   17069 		result = ISC_R_SUCCESS;
   17070 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   17071 		if (zone->db != NULL) {
   17072 			dns_db_attach(zone->db, &zone->rss_db);
   17073 		} else {
   17074 			result = ISC_R_FAILURE;
   17075 		}
   17076 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   17077 
   17078 		if (result == ISC_R_SUCCESS && zone->raw != NULL) {
   17079 			dns_zone_attach(zone->raw, &zone->rss_raw);
   17080 		} else {
   17081 			result = ISC_R_FAILURE;
   17082 		}
   17083 
   17084 		UNLOCK_ZONE(zone);
   17085 
   17086 		CHECK(result);
   17087 
   17088 		/*
   17089 		 * We first attempt to sync the raw zone to the secure zone
   17090 		 * by using the raw zone's journal, applying all the deltas
   17091 		 * from the latest source-serial of the secure zone up to
   17092 		 * the current serial number of the raw zone.
   17093 		 *
   17094 		 * If that fails, then we'll fall back to a direct comparison
   17095 		 * between raw and secure zones.
   17096 		 */
   17097 		CHECK(dns_journal_open(zone->rss_raw->mctx,
   17098 				       zone->rss_raw->journal,
   17099 				       DNS_JOURNAL_WRITE, &rjournal));
   17100 
   17101 		result = dns_journal_open(zone->mctx, zone->journal,
   17102 					  DNS_JOURNAL_READ, &sjournal);
   17103 		if (result != ISC_R_NOTFOUND) {
   17104 			CHECK(result);
   17105 		}
   17106 
   17107 		if (!dns_journal_get_sourceserial(rjournal, &start)) {
   17108 			start = dns_journal_first_serial(rjournal);
   17109 			dns_journal_set_sourceserial(rjournal, start);
   17110 		}
   17111 		if (sjournal != NULL) {
   17112 			uint32_t serial;
   17113 			/*
   17114 			 * We read the secure journal first, if that
   17115 			 * exists use its value provided it is greater
   17116 			 * that from the raw journal.
   17117 			 */
   17118 			if (dns_journal_get_sourceserial(sjournal, &serial)) {
   17119 				if (isc_serial_gt(serial, start)) {
   17120 					start = serial;
   17121 				}
   17122 			}
   17123 			dns_journal_destroy(&sjournal);
   17124 		}
   17125 
   17126 		dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
   17127 		CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
   17128 
   17129 		/*
   17130 		 * Try to apply diffs from the raw zone's journal to the secure
   17131 		 * zone.  If that fails, we recover by syncing up the databases
   17132 		 * directly.
   17133 		 */
   17134 		result = sync_secure_journal(zone, zone->rss_raw, rjournal,
   17135 					     start, end, &soatuple,
   17136 					     &zone->rss_diff);
   17137 		if (result == DNS_R_UNCHANGED) {
   17138 			goto cleanup;
   17139 		} else if (result != ISC_R_SUCCESS) {
   17140 			CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
   17141 					     zone->rss_oldver, &soatuple,
   17142 					     &zone->rss_diff));
   17143 		}
   17144 
   17145 		CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
   17146 				     zone->rss_newver));
   17147 
   17148 		if (soatuple != NULL) {
   17149 			uint32_t oldserial;
   17150 
   17151 			CHECK(dns_db_createsoatuple(
   17152 				zone->rss_db, zone->rss_oldver,
   17153 				zone->rss_diff.mctx, DNS_DIFFOP_DEL, &tuple));
   17154 			oldserial = dns_soa_getserial(&tuple->rdata);
   17155 			newserial = desired =
   17156 				dns_soa_getserial(&soatuple->rdata);
   17157 			if (!isc_serial_gt(newserial, oldserial)) {
   17158 				newserial = oldserial + 1;
   17159 				if (newserial == 0) {
   17160 					newserial++;
   17161 				}
   17162 				dns_soa_setserial(newserial, &soatuple->rdata);
   17163 			}
   17164 			CHECK(do_one_tuple(&tuple, zone->rss_db,
   17165 					   zone->rss_newver, &zone->rss_diff));
   17166 			CHECK(do_one_tuple(&soatuple, zone->rss_db,
   17167 					   zone->rss_newver, &zone->rss_diff));
   17168 		} else {
   17169 			CHECK(update_soa_serial(zone, zone->rss_db,
   17170 						zone->rss_newver,
   17171 						&zone->rss_diff, zone->mctx,
   17172 						zone->updatemethod));
   17173 		}
   17174 	}
   17175 	result = dns_update_signaturesinc(
   17176 		&log, zone, zone->rss_db, zone->rss_oldver, zone->rss_newver,
   17177 		&zone->rss_diff, zone->sigvalidityinterval, &zone->rss_state);
   17178 	if (result == DNS_R_CONTINUE) {
   17179 		if (rjournal != NULL) {
   17180 			dns_journal_destroy(&rjournal);
   17181 		}
   17182 		isc_async_run(zone->loop, receive_secure_serial, rss);
   17183 		return;
   17184 	}
   17185 
   17186 	/*
   17187 	 * If something went wrong while trying to update the secure zone and
   17188 	 * the latter was already signed before, do not apply raw zone deltas
   17189 	 * to it as that would break existing DNSSEC signatures.  However, if
   17190 	 * the secure zone was not yet signed (e.g. because no signing keys
   17191 	 * were created for it), commence applying raw zone deltas to it so
   17192 	 * that contents of the raw zone and the secure zone are kept in sync.
   17193 	 */
   17194 	if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
   17195 		goto cleanup;
   17196 	}
   17197 
   17198 	if (rjournal == NULL) {
   17199 		CHECK(dns_journal_open(zone->rss_raw->mctx,
   17200 				       zone->rss_raw->journal,
   17201 				       DNS_JOURNAL_WRITE, &rjournal));
   17202 	}
   17203 	CHECK(zone_journal(zone, &zone->rss_diff, &end,
   17204 			   "receive_secure_serial"));
   17205 
   17206 	dns_journal_set_sourceserial(rjournal, end);
   17207 	dns_journal_commit(rjournal);
   17208 
   17209 	LOCK_ZONE(zone);
   17210 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   17211 
   17212 	zone->sourceserial = end;
   17213 	zone->sourceserialset = true;
   17214 	zone_needdump(zone, DNS_DUMP_DELAY);
   17215 
   17216 	/*
   17217 	 * Set resign time to make sure it is set to the earliest
   17218 	 * signature expiration.
   17219 	 */
   17220 	set_resigntime(zone);
   17221 	timenow = isc_time_now();
   17222 	zone_settimer(zone, &timenow);
   17223 	UNLOCK_ZONE(zone);
   17224 
   17225 	dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
   17226 	dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
   17227 
   17228 	if (newserial != 0) {
   17229 		dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
   17230 			     newserial, desired);
   17231 	}
   17232 
   17233 cleanup:
   17234 	isc_mem_put(zone->mctx, rss, sizeof(*rss));
   17235 	zone->rss = NULL;
   17236 
   17237 	if (zone->rss_raw != NULL) {
   17238 		dns_zone_detach(&zone->rss_raw);
   17239 	}
   17240 	if (result != ISC_R_SUCCESS) {
   17241 		LOCK_ZONE(zone);
   17242 		set_resigntime(zone);
   17243 		timenow = isc_time_now();
   17244 		zone_settimer(zone, &timenow);
   17245 		UNLOCK_ZONE(zone);
   17246 		if (result == DNS_R_UNCHANGED) {
   17247 			level = ISC_LOG_INFO;
   17248 		}
   17249 		dns_zone_log(zone, level, "receive_secure_serial: %s",
   17250 			     isc_result_totext(result));
   17251 	}
   17252 	if (tuple != NULL) {
   17253 		dns_difftuple_free(&tuple);
   17254 	}
   17255 	if (soatuple != NULL) {
   17256 		dns_difftuple_free(&soatuple);
   17257 	}
   17258 	if (zone->rss_db != NULL) {
   17259 		if (zone->rss_oldver != NULL) {
   17260 			dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
   17261 					    false);
   17262 		}
   17263 		if (zone->rss_newver != NULL) {
   17264 			dns_db_closeversion(zone->rss_db, &zone->rss_newver,
   17265 					    false);
   17266 		}
   17267 		dns_db_detach(&zone->rss_db);
   17268 	}
   17269 	INSIST(zone->rss_oldver == NULL);
   17270 	INSIST(zone->rss_newver == NULL);
   17271 	if (rjournal != NULL) {
   17272 		dns_journal_destroy(&rjournal);
   17273 	}
   17274 	dns_diff_clear(&zone->rss_diff);
   17275 
   17276 	dns_zone_idetach(&zone);
   17277 }
   17278 
   17279 static isc_result_t
   17280 zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
   17281 	struct rss *rss = NULL;
   17282 
   17283 	rss = isc_mem_get(zone->secure->mctx, sizeof(*rss));
   17284 	*rss = (struct rss){
   17285 		.serial = serial,
   17286 		.link = ISC_LINK_INITIALIZER,
   17287 	};
   17288 
   17289 	INSIST(LOCKED_ZONE(zone->secure));
   17290 	zone_iattach(zone->secure, &rss->zone);
   17291 	isc_async_run(zone->secure->loop, receive_secure_serial, rss);
   17292 
   17293 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
   17294 	return ISC_R_SUCCESS;
   17295 }
   17296 
   17297 static isc_result_t
   17298 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   17299 	       dns_name_t *name, dns_rdataset_t *rdataset, uint32_t oldserial) {
   17300 	dns_rdata_soa_t soa;
   17301 	dns_rdata_t rdata = DNS_RDATA_INIT;
   17302 	dns_rdatalist_t temprdatalist;
   17303 	dns_rdataset_t temprdataset;
   17304 	isc_buffer_t b;
   17305 	isc_result_t result;
   17306 	unsigned char buf[DNS_SOA_BUFFERSIZE];
   17307 
   17308 	result = dns_rdataset_first(rdataset);
   17309 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17310 	dns_rdataset_current(rdataset, &rdata);
   17311 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   17312 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17313 
   17314 	if (isc_serial_gt(soa.serial, oldserial)) {
   17315 		return dns_db_addrdataset(db, node, version, 0, rdataset, 0,
   17316 					  NULL);
   17317 	}
   17318 	/*
   17319 	 * Always bump the serial.
   17320 	 */
   17321 	oldserial++;
   17322 	if (oldserial == 0) {
   17323 		oldserial++;
   17324 	}
   17325 	soa.serial = oldserial;
   17326 
   17327 	/*
   17328 	 * Construct a replacement rdataset.
   17329 	 */
   17330 	dns_rdata_reset(&rdata);
   17331 	isc_buffer_init(&b, buf, sizeof(buf));
   17332 	result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
   17333 				      dns_rdatatype_soa, &soa, &b);
   17334 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17335 	dns_rdatalist_init(&temprdatalist);
   17336 	temprdatalist.rdclass = rdata.rdclass;
   17337 	temprdatalist.type = rdata.type;
   17338 	temprdatalist.ttl = rdataset->ttl;
   17339 	ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
   17340 
   17341 	dns_rdataset_init(&temprdataset);
   17342 	dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
   17343 
   17344 	dns_rdataset_getownercase(rdataset, name);
   17345 	dns_rdataset_setownercase(&temprdataset, name);
   17346 	return dns_db_addrdataset(db, node, version, 0, &temprdataset, 0, NULL);
   17347 }
   17348 
   17349 /*
   17350  * This function should populate an nsec3paramlist_t with the
   17351  * nsecparam_t data from a zone.
   17352  */
   17353 static isc_result_t
   17354 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
   17355 	isc_result_t result;
   17356 	dns_dbnode_t *node = NULL;
   17357 	dns_rdataset_t rdataset, prdataset;
   17358 	dns_dbversion_t *version = NULL;
   17359 	nsec3param_t *nsec3param = NULL;
   17360 	nsec3param_t *nsec3p = NULL;
   17361 	nsec3param_t *next;
   17362 	dns_db_t *db = NULL;
   17363 	unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   17364 
   17365 	REQUIRE(DNS_ZONE_VALID(zone));
   17366 	REQUIRE(nsec3list != NULL);
   17367 	REQUIRE(ISC_LIST_EMPTY(*nsec3list));
   17368 
   17369 	dns_rdataset_init(&rdataset);
   17370 	dns_rdataset_init(&prdataset);
   17371 
   17372 	dns_db_attach(zone->db, &db);
   17373 	CHECK(dns_db_getoriginnode(db, &node));
   17374 
   17375 	dns_db_currentversion(db, &version);
   17376 	result = dns_db_findrdataset(db, node, version,
   17377 				     dns_rdatatype_nsec3param,
   17378 				     dns_rdatatype_none, 0, &rdataset, NULL);
   17379 
   17380 	if (result != ISC_R_SUCCESS) {
   17381 		goto getprivate;
   17382 	}
   17383 
   17384 	/*
   17385 	 * Walk nsec3param rdataset making a list of parameters (note that
   17386 	 * multiple simultaneous nsec3 chains are annoyingly legal -- this
   17387 	 * is why we use an nsec3list, even though we will usually only
   17388 	 * have one).
   17389 	 */
   17390 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   17391 	     result = dns_rdataset_next(&rdataset))
   17392 	{
   17393 		dns_rdata_t rdata = DNS_RDATA_INIT;
   17394 		dns_rdata_t private = DNS_RDATA_INIT;
   17395 
   17396 		dns_rdataset_current(&rdataset, &rdata);
   17397 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   17398 			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   17399 			      "looping through nsec3param data");
   17400 		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
   17401 		ISC_LINK_INIT(nsec3param, link);
   17402 
   17403 		/*
   17404 		 * now transfer the data from the rdata to
   17405 		 * the nsec3param
   17406 		 */
   17407 		dns_nsec3param_toprivate(&rdata, &private, zone->privatetype,
   17408 					 nsec3param->data,
   17409 					 sizeof(nsec3param->data));
   17410 		nsec3param->length = private.length;
   17411 		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
   17412 	}
   17413 
   17414 getprivate:
   17415 	result = dns_db_findrdataset(db, node, version, zone->privatetype,
   17416 				     dns_rdatatype_none, 0, &prdataset, NULL);
   17417 	if (result != ISC_R_SUCCESS) {
   17418 		goto done;
   17419 	}
   17420 
   17421 	/*
   17422 	 * walk private type records, converting them to nsec3 parameters
   17423 	 * using dns_nsec3param_fromprivate(), do the right thing based on
   17424 	 * CREATE and REMOVE flags
   17425 	 */
   17426 	for (result = dns_rdataset_first(&prdataset); result == ISC_R_SUCCESS;
   17427 	     result = dns_rdataset_next(&prdataset))
   17428 	{
   17429 		dns_rdata_t rdata = DNS_RDATA_INIT;
   17430 		dns_rdata_t private = DNS_RDATA_INIT;
   17431 
   17432 		dns_rdataset_current(&prdataset, &private);
   17433 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   17434 			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   17435 			      "looping through nsec3param private data");
   17436 
   17437 		/*
   17438 		 * Do we have a valid private record?
   17439 		 */
   17440 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
   17441 						sizeof(buf)))
   17442 		{
   17443 			continue;
   17444 		}
   17445 
   17446 		/*
   17447 		 * Remove any NSEC3PARAM records scheduled to be removed.
   17448 		 */
   17449 		if (NSEC3REMOVE(rdata.data[1])) {
   17450 			/*
   17451 			 * Zero out the flags.
   17452 			 */
   17453 			rdata.data[1] = 0;
   17454 
   17455 			for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL;
   17456 			     nsec3p = next)
   17457 			{
   17458 				next = ISC_LIST_NEXT(nsec3p, link);
   17459 
   17460 				if (nsec3p->length ==
   17461 					    (unsigned int)rdata.length + 1 &&
   17462 				    memcmp(rdata.data, nsec3p->data + 1,
   17463 					   nsec3p->length - 1) == 0)
   17464 				{
   17465 					ISC_LIST_UNLINK(*nsec3list, nsec3p,
   17466 							link);
   17467 					isc_mem_put(zone->mctx, nsec3p,
   17468 						    sizeof(nsec3param_t));
   17469 				}
   17470 			}
   17471 			continue;
   17472 		}
   17473 
   17474 		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
   17475 		ISC_LINK_INIT(nsec3param, link);
   17476 
   17477 		/*
   17478 		 * Copy the remaining private records so the nsec/nsec3
   17479 		 * chain gets created.
   17480 		 */
   17481 		INSIST(private.length <= sizeof(nsec3param->data));
   17482 		memmove(nsec3param->data, private.data, private.length);
   17483 		nsec3param->length = private.length;
   17484 		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
   17485 	}
   17486 
   17487 done:
   17488 	if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND) {
   17489 		result = ISC_R_SUCCESS;
   17490 	}
   17491 
   17492 cleanup:
   17493 	if (node != NULL) {
   17494 		dns_db_detachnode(db, &node);
   17495 	}
   17496 	if (version != NULL) {
   17497 		dns_db_closeversion(db, &version, false);
   17498 	}
   17499 	if (db != NULL) {
   17500 		dns_db_detach(&db);
   17501 	}
   17502 	if (dns_rdataset_isassociated(&rdataset)) {
   17503 		dns_rdataset_disassociate(&rdataset);
   17504 	}
   17505 	if (dns_rdataset_isassociated(&prdataset)) {
   17506 		dns_rdataset_disassociate(&prdataset);
   17507 	}
   17508 	return result;
   17509 }
   17510 
   17511 /*
   17512  * Populate new zone db with private type records found by save_nsec3param().
   17513  */
   17514 static isc_result_t
   17515 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
   17516 		   nsec3paramlist_t *nsec3list) {
   17517 	isc_result_t result = ISC_R_SUCCESS;
   17518 	dns_diff_t diff;
   17519 	dns_rdata_t rdata;
   17520 	nsec3param_t *nsec3p = NULL;
   17521 	nsec3param_t *next;
   17522 
   17523 	REQUIRE(DNS_ZONE_VALID(zone));
   17524 	REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
   17525 
   17526 	dns_diff_init(zone->mctx, &diff);
   17527 
   17528 	/*
   17529 	 * Loop through the list of private-type records, set the INITIAL
   17530 	 * and CREATE flags, and the add the record to the apex of the tree
   17531 	 * in db.
   17532 	 */
   17533 	for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL; nsec3p = next)
   17534 	{
   17535 		next = ISC_LIST_NEXT(nsec3p, link);
   17536 		dns_rdata_init(&rdata);
   17537 		nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
   17538 		rdata.length = nsec3p->length;
   17539 		rdata.data = nsec3p->data;
   17540 		rdata.type = zone->privatetype;
   17541 		rdata.rdclass = zone->rdclass;
   17542 		result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
   17543 				       &zone->origin, 0, &rdata);
   17544 		if (result != ISC_R_SUCCESS) {
   17545 			break;
   17546 		}
   17547 	}
   17548 
   17549 	dns_diff_clear(&diff);
   17550 	return result;
   17551 }
   17552 
   17553 static isc_result_t
   17554 copy_non_dnssec_records(dns_db_t *db, dns_db_t *version, dns_db_t *rawdb,
   17555 			dns_dbiterator_t *dbiterator, unsigned int *oldserial) {
   17556 	dns_dbnode_t *rawnode = NULL, *node = NULL;
   17557 	dns_fixedname_t fixed;
   17558 	dns_name_t *name = dns_fixedname_initname(&fixed);
   17559 	dns_rdataset_t rdataset;
   17560 	dns_rdatasetiter_t *rdsit = NULL;
   17561 	isc_result_t result;
   17562 
   17563 	result = dns_dbiterator_current(dbiterator, &rawnode, name);
   17564 	if (result != ISC_R_SUCCESS) {
   17565 		return ISC_R_SUCCESS;
   17566 	}
   17567 
   17568 	dns_dbiterator_pause(dbiterator);
   17569 
   17570 	result = dns_db_findnode(db, name, true, &node);
   17571 	if (result != ISC_R_SUCCESS) {
   17572 		goto cleanup;
   17573 	}
   17574 
   17575 	result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, 0, &rdsit);
   17576 	if (result != ISC_R_SUCCESS) {
   17577 		goto cleanup;
   17578 	}
   17579 
   17580 	dns_rdataset_init(&rdataset);
   17581 
   17582 	for (result = dns_rdatasetiter_first(rdsit); result == ISC_R_SUCCESS;
   17583 	     result = dns_rdatasetiter_next(rdsit))
   17584 	{
   17585 		dns_rdatasetiter_current(rdsit, &rdataset);
   17586 		if (rdataset.type == dns_rdatatype_nsec ||
   17587 		    rdataset.type == dns_rdatatype_rrsig ||
   17588 		    rdataset.type == dns_rdatatype_nsec3 ||
   17589 		    rdataset.type == dns_rdatatype_nsec3param)
   17590 		{
   17591 			dns_rdataset_disassociate(&rdataset);
   17592 			continue;
   17593 		}
   17594 		/*
   17595 		 * Allow DNSKEY, CDNSKEY, CDS because users should be able to
   17596 		 * update the zone with these records from a different provider,
   17597 		 * and thus they may exist in the raw version of the zone.
   17598 		 */
   17599 
   17600 		if (rdataset.type == dns_rdatatype_soa && oldserial != NULL) {
   17601 			result = checkandaddsoa(db, node, version, name,
   17602 						&rdataset, *oldserial);
   17603 		} else {
   17604 			result = dns_db_addrdataset(db, node, version, 0,
   17605 						    &rdataset, 0, NULL);
   17606 		}
   17607 		dns_rdataset_disassociate(&rdataset);
   17608 		if (result != ISC_R_SUCCESS) {
   17609 			goto cleanup;
   17610 		}
   17611 	}
   17612 	if (result == ISC_R_NOMORE) {
   17613 		result = ISC_R_SUCCESS;
   17614 	}
   17615 
   17616 cleanup:
   17617 	if (rdsit != NULL) {
   17618 		dns_rdatasetiter_destroy(&rdsit);
   17619 	}
   17620 	if (rawnode) {
   17621 		dns_db_detachnode(rawdb, &rawnode);
   17622 	}
   17623 	if (node) {
   17624 		dns_db_detachnode(db, &node);
   17625 	}
   17626 	return result;
   17627 }
   17628 
   17629 static void
   17630 receive_secure_db(void *arg) {
   17631 	isc_result_t result;
   17632 	struct rss *rss = (struct rss *)arg;
   17633 	dns_zone_t *zone = rss->zone;
   17634 	dns_db_t *rawdb = rss->db, *db = NULL;
   17635 	dns_dbiterator_t *dbiterator = NULL;
   17636 	dns_dbversion_t *version = NULL;
   17637 	isc_time_t loadtime;
   17638 	unsigned int oldserial = 0, *oldserialp = NULL;
   17639 	nsec3paramlist_t nsec3list;
   17640 
   17641 	ISC_LIST_INIT(nsec3list);
   17642 
   17643 	LOCK_ZONE(zone);
   17644 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
   17645 		CHECK(ISC_R_SHUTTINGDOWN);
   17646 	}
   17647 
   17648 	loadtime = isc_time_now();
   17649 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   17650 	if (zone->db != NULL) {
   17651 		result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
   17652 		if (result == ISC_R_SUCCESS) {
   17653 			oldserialp = &oldserial;
   17654 		}
   17655 
   17656 		/*
   17657 		 * assemble nsec3parameters from the old zone, and set a flag
   17658 		 * if any are found
   17659 		 */
   17660 		result = save_nsec3param(zone, &nsec3list);
   17661 		if (result != ISC_R_SUCCESS) {
   17662 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   17663 			goto cleanup;
   17664 		}
   17665 	}
   17666 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   17667 
   17668 	CHECK(dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
   17669 			    dns_dbtype_zone, zone->rdclass, zone->db_argc - 1,
   17670 			    zone->db_argv + 1, &db));
   17671 
   17672 	result = dns_db_setgluecachestats(db, zone->gluecachestats);
   17673 	if (result != ISC_R_NOTIMPLEMENTED) {
   17674 		CHECK(result);
   17675 	}
   17676 
   17677 	CHECK(dns_db_newversion(db, &version));
   17678 	CHECK(dns_db_createiterator(rawdb, DNS_DB_NONSEC3, &dbiterator));
   17679 
   17680 	for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
   17681 	     result = dns_dbiterator_next(dbiterator))
   17682 	{
   17683 		CHECK(copy_non_dnssec_records(db, version, rawdb, dbiterator,
   17684 					      oldserialp));
   17685 	}
   17686 	dns_dbiterator_destroy(&dbiterator);
   17687 	if (result != ISC_R_NOMORE) {
   17688 		goto cleanup;
   17689 	}
   17690 
   17691 	/*
   17692 	 * Call restore_nsec3param() to create private-type records from
   17693 	 * the old nsec3 parameters and insert them into db
   17694 	 */
   17695 	if (!ISC_LIST_EMPTY(nsec3list)) {
   17696 		CHECK(restore_nsec3param(zone, db, version, &nsec3list));
   17697 	}
   17698 
   17699 	dns_db_closeversion(db, &version, true);
   17700 
   17701 	/*
   17702 	 * Lock hierarchy: zmgr, zone, raw.
   17703 	 */
   17704 	INSIST(zone != zone->raw);
   17705 	LOCK_ZONE(zone->raw);
   17706 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   17707 	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
   17708 	zone_needdump(zone, 0); /* XXXMPA */
   17709 	UNLOCK_ZONE(zone->raw);
   17710 
   17711 	/*
   17712 	 * Process any queued NSEC3PARAM change requests.
   17713 	 */
   17714 	process_zone_setnsec3param(zone);
   17715 
   17716 cleanup:
   17717 	UNLOCK_ZONE(zone);
   17718 	if (dbiterator != NULL) {
   17719 		dns_dbiterator_destroy(&dbiterator);
   17720 	}
   17721 	if (result != ISC_R_SUCCESS) {
   17722 		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
   17723 			     isc_result_totext(result));
   17724 	}
   17725 
   17726 	while (!ISC_LIST_EMPTY(nsec3list)) {
   17727 		nsec3param_t *nsec3p;
   17728 		nsec3p = ISC_LIST_HEAD(nsec3list);
   17729 		ISC_LIST_UNLINK(nsec3list, nsec3p, link);
   17730 		isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
   17731 	}
   17732 	if (db != NULL) {
   17733 		if (version != NULL) {
   17734 			dns_db_closeversion(db, &version, false);
   17735 		}
   17736 		dns_db_detach(&db);
   17737 	}
   17738 
   17739 	dns_db_detach(&rawdb);
   17740 	isc_mem_put(zone->mctx, rss, sizeof(*rss));
   17741 	dns_zone_idetach(&zone);
   17742 
   17743 	INSIST(version == NULL);
   17744 }
   17745 
   17746 static isc_result_t
   17747 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
   17748 	struct rss *rss = NULL;
   17749 
   17750 	rss = isc_mem_get(zone->secure->mctx, sizeof(*rss));
   17751 	*rss = (struct rss){ .link = ISC_LINK_INITIALIZER };
   17752 
   17753 	INSIST(LOCKED_ZONE(zone->secure));
   17754 	zone_iattach(zone->secure, &rss->zone);
   17755 	dns_db_attach(db, &rss->db);
   17756 	isc_async_run(zone->secure->loop, receive_secure_db, rss);
   17757 
   17758 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
   17759 	return ISC_R_SUCCESS;
   17760 }
   17761 
   17762 isc_result_t
   17763 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
   17764 	isc_result_t result;
   17765 	dns_zone_t *secure = NULL;
   17766 
   17767 	REQUIRE(DNS_ZONE_VALID(zone));
   17768 again:
   17769 	LOCK_ZONE(zone);
   17770 	if (inline_raw(zone)) {
   17771 		secure = zone->secure;
   17772 		INSIST(secure != zone);
   17773 		TRYLOCK_ZONE(result, secure);
   17774 		if (result != ISC_R_SUCCESS) {
   17775 			UNLOCK_ZONE(zone);
   17776 			secure = NULL;
   17777 			isc_thread_yield();
   17778 			goto again;
   17779 		}
   17780 	}
   17781 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   17782 	result = zone_replacedb(zone, db, dump);
   17783 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   17784 	if (secure != NULL) {
   17785 		UNLOCK_ZONE(secure);
   17786 	}
   17787 	UNLOCK_ZONE(zone);
   17788 	return result;
   17789 }
   17790 
   17791 static isc_result_t
   17792 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
   17793 	dns_dbversion_t *ver;
   17794 	isc_result_t result;
   17795 	unsigned int soacount = 0;
   17796 	unsigned int nscount = 0;
   17797 
   17798 	/*
   17799 	 * 'zone' and 'zone->db' locked by caller.
   17800 	 */
   17801 	REQUIRE(DNS_ZONE_VALID(zone));
   17802 	REQUIRE(LOCKED_ZONE(zone));
   17803 	if (inline_raw(zone)) {
   17804 		REQUIRE(LOCKED_ZONE(zone->secure));
   17805 	}
   17806 
   17807 	result = zone_get_from_db(zone, db, &nscount, &soacount, NULL, NULL,
   17808 				  NULL, NULL, NULL, NULL, NULL);
   17809 	if (result == ISC_R_SUCCESS) {
   17810 		if (soacount != 1) {
   17811 			dns_zone_log(zone, ISC_LOG_ERROR, "has %d SOA records",
   17812 				     soacount);
   17813 			result = DNS_R_BADZONE;
   17814 		}
   17815 		if (nscount == 0 && zone->type != dns_zone_key) {
   17816 			dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
   17817 			result = DNS_R_BADZONE;
   17818 		}
   17819 		if (result != ISC_R_SUCCESS) {
   17820 			return result;
   17821 		}
   17822 	} else {
   17823 		dns_zone_log(zone, ISC_LOG_ERROR,
   17824 			     "retrieving SOA and NS records failed: %s",
   17825 			     isc_result_totext(result));
   17826 		return result;
   17827 	}
   17828 
   17829 	result = check_nsec3param(zone, db);
   17830 	if (result != ISC_R_SUCCESS) {
   17831 		return result;
   17832 	}
   17833 
   17834 	ver = NULL;
   17835 	dns_db_currentversion(db, &ver);
   17836 
   17837 	/*
   17838 	 * The initial version of a secondary zone is always dumped;
   17839 	 * subsequent versions may be journaled instead if this
   17840 	 * is enabled in the configuration.
   17841 	 */
   17842 	if (zone->db != NULL && zone->journal != NULL &&
   17843 	    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
   17844 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
   17845 	{
   17846 		uint32_t serial, oldserial;
   17847 
   17848 		dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
   17849 
   17850 		result = dns_db_getsoaserial(db, ver, &serial);
   17851 		if (result != ISC_R_SUCCESS) {
   17852 			dns_zone_log(zone, ISC_LOG_ERROR,
   17853 				     "ixfr-from-differences: unable to get "
   17854 				     "new serial");
   17855 			goto fail;
   17856 		}
   17857 
   17858 		/*
   17859 		 * This is checked in zone_postload() for primary zones.
   17860 		 */
   17861 		result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
   17862 					  &oldserial, NULL, NULL, NULL, NULL,
   17863 					  NULL);
   17864 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17865 		RUNTIME_CHECK(soacount > 0U);
   17866 		if ((zone->type == dns_zone_secondary ||
   17867 		     (zone->type == dns_zone_redirect &&
   17868 		      dns_remote_addresses(&zone->primaries) != NULL)) &&
   17869 		    !isc_serial_gt(serial, oldserial))
   17870 		{
   17871 			uint32_t serialmin, serialmax;
   17872 			serialmin = (oldserial + 1) & 0xffffffffU;
   17873 			serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
   17874 			dns_zone_log(zone, ISC_LOG_ERROR,
   17875 				     "ixfr-from-differences: failed: "
   17876 				     "new serial (%u) out of range [%u - %u]",
   17877 				     serial, serialmin, serialmax);
   17878 			result = ISC_R_RANGE;
   17879 			goto fail;
   17880 		}
   17881 
   17882 		result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
   17883 				     zone->journal);
   17884 		if (result != ISC_R_SUCCESS) {
   17885 			char strbuf[ISC_STRERRORSIZE];
   17886 			strerror_r(errno, strbuf, sizeof(strbuf));
   17887 			dns_zone_log(zone, ISC_LOG_ERROR,
   17888 				     "ixfr-from-differences: failed: "
   17889 				     "%s",
   17890 				     strbuf);
   17891 			goto fallback;
   17892 		}
   17893 		if (dump) {
   17894 			zone_needdump(zone, DNS_DUMP_DELAY);
   17895 		} else {
   17896 			zone_journal_compact(zone, zone->db, serial);
   17897 		}
   17898 		if (zone->type == dns_zone_primary && inline_raw(zone)) {
   17899 			zone_send_secureserial(zone, serial);
   17900 		}
   17901 	} else {
   17902 	fallback:
   17903 		if (dump && zone->masterfile != NULL) {
   17904 			/*
   17905 			 * If DNS_ZONEFLG_FORCEXFER was set we don't want
   17906 			 * to keep the old masterfile.
   17907 			 */
   17908 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
   17909 			    remove(zone->masterfile) < 0 && errno != ENOENT)
   17910 			{
   17911 				char strbuf[ISC_STRERRORSIZE];
   17912 				strerror_r(errno, strbuf, sizeof(strbuf));
   17913 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   17914 					      DNS_LOGMODULE_ZONE,
   17915 					      ISC_LOG_WARNING,
   17916 					      "unable to remove masterfile "
   17917 					      "'%s': '%s'",
   17918 					      zone->masterfile, strbuf);
   17919 			}
   17920 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) {
   17921 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
   17922 			} else {
   17923 				zone_needdump(zone, 0);
   17924 			}
   17925 		}
   17926 		if (dump && zone->journal != NULL) {
   17927 			/*
   17928 			 * The in-memory database just changed, and
   17929 			 * because 'dump' is set, it didn't change by
   17930 			 * being loaded from disk.  Also, we have not
   17931 			 * journaled diffs for this change.
   17932 			 * Therefore, the on-disk journal is missing
   17933 			 * the deltas for this change.	Since it can
   17934 			 * no longer be used to bring the zone
   17935 			 * up-to-date, it is useless and should be
   17936 			 * removed.
   17937 			 */
   17938 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   17939 				      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   17940 				      "removing journal file");
   17941 			if (remove(zone->journal) < 0 && errno != ENOENT) {
   17942 				char strbuf[ISC_STRERRORSIZE];
   17943 				strerror_r(errno, strbuf, sizeof(strbuf));
   17944 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   17945 					      DNS_LOGMODULE_ZONE,
   17946 					      ISC_LOG_WARNING,
   17947 					      "unable to remove journal "
   17948 					      "'%s': '%s'",
   17949 					      zone->journal, strbuf);
   17950 			}
   17951 		}
   17952 
   17953 		if (inline_raw(zone)) {
   17954 			zone_send_securedb(zone, db);
   17955 		}
   17956 	}
   17957 
   17958 	dns_db_closeversion(db, &ver, false);
   17959 
   17960 	dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
   17961 
   17962 	if (zone->db != NULL) {
   17963 		zone_detachdb(zone);
   17964 	}
   17965 	zone_attachdb(zone, db);
   17966 	dns_db_setloop(zone->db, zone->loop);
   17967 	dns_db_setmaxrrperset(zone->db, zone->maxrrperset);
   17968 	dns_db_setmaxtypepername(zone->db, zone->maxtypepername);
   17969 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
   17970 	return ISC_R_SUCCESS;
   17971 
   17972 fail:
   17973 	dns_db_closeversion(db, &ver, false);
   17974 	return result;
   17975 }
   17976 
   17977 /* The caller must hold the dblock as a writer. */
   17978 static void
   17979 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
   17980 	REQUIRE(zone->db == NULL && db != NULL);
   17981 
   17982 	dns_db_attach(db, &zone->db);
   17983 }
   17984 
   17985 /* The caller must hold the dblock as a writer. */
   17986 static void
   17987 zone_detachdb(dns_zone_t *zone) {
   17988 	REQUIRE(zone->db != NULL);
   17989 
   17990 	dns_zone_rpz_disable_db(zone, zone->db);
   17991 	dns_zone_catz_disable_db(zone, zone->db);
   17992 	dns_db_detach(&zone->db);
   17993 }
   17994 
   17995 static void
   17996 zone_xfrdone(dns_zone_t *zone, uint32_t *expireopt, isc_result_t result) {
   17997 	isc_time_t now, expiretime;
   17998 	bool again = false;
   17999 	unsigned int soacount;
   18000 	unsigned int nscount;
   18001 	uint32_t serial, refresh, retry, expire, minimum, soattl, oldexpire;
   18002 	isc_result_t xfrresult = result;
   18003 	bool free_needed;
   18004 	dns_zone_t *secure = NULL;
   18005 
   18006 	REQUIRE(DNS_ZONE_VALID(zone));
   18007 
   18008 	dns_zone_logc(
   18009 		zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
   18010 		expireopt == NULL ? "zone transfer finished: %s"
   18011 				  : "zone transfer finished: %s, expire=%u",
   18012 		isc_result_totext(result), expireopt != NULL ? *expireopt : 0);
   18013 
   18014 	/*
   18015 	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
   18016 	 * could result in a deadlock due to a LOR so we will spin if we
   18017 	 * can't obtain both locks.
   18018 	 */
   18019 again:
   18020 	LOCK_ZONE(zone);
   18021 	if (inline_raw(zone)) {
   18022 		secure = zone->secure;
   18023 		INSIST(secure != zone);
   18024 		TRYLOCK_ZONE(result, secure);
   18025 		if (result != ISC_R_SUCCESS) {
   18026 			UNLOCK_ZONE(zone);
   18027 			secure = NULL;
   18028 			isc_thread_yield();
   18029 			goto again;
   18030 		}
   18031 	}
   18032 
   18033 	INSIST(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH));
   18034 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   18035 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
   18036 
   18037 	now = isc_time_now();
   18038 	switch (xfrresult) {
   18039 	case ISC_R_SUCCESS:
   18040 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   18041 		FALLTHROUGH;
   18042 	case DNS_R_UPTODATE:
   18043 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER |
   18044 					       DNS_ZONEFLG_FIRSTREFRESH);
   18045 		/*
   18046 		 * Has the zone expired underneath us?
   18047 		 */
   18048 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   18049 		if (zone->db == NULL) {
   18050 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   18051 			goto same_primary;
   18052 		}
   18053 
   18054 		oldexpire = zone->expire;
   18055 
   18056 		/*
   18057 		 * Update the zone structure's data from the actual
   18058 		 * SOA received.
   18059 		 */
   18060 		nscount = 0;
   18061 		soacount = 0;
   18062 		INSIST(zone->db != NULL);
   18063 		result = zone_get_from_db(zone, zone->db, &nscount, &soacount,
   18064 					  &soattl, &serial, &refresh, &retry,
   18065 					  &expire, &minimum, NULL);
   18066 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   18067 		if (result == ISC_R_SUCCESS) {
   18068 			if (soacount != 1) {
   18069 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18070 					      ISC_LOG_ERROR,
   18071 					      "transferred zone "
   18072 					      "has %d SOA records",
   18073 					      soacount);
   18074 				if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
   18075 				{
   18076 					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
   18077 					zone->retry = DNS_ZONE_DEFAULTRETRY;
   18078 				}
   18079 				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   18080 				zone_unload(zone);
   18081 				goto next_primary;
   18082 			}
   18083 			if (nscount == 0) {
   18084 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18085 					      ISC_LOG_ERROR,
   18086 					      "transferred zone "
   18087 					      "has no NS records");
   18088 				if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
   18089 				{
   18090 					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
   18091 					zone->retry = DNS_ZONE_DEFAULTRETRY;
   18092 				}
   18093 				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   18094 				zone_unload(zone);
   18095 				goto next_primary;
   18096 			}
   18097 			zone->refresh = RANGE(refresh, zone->minrefresh,
   18098 					      zone->maxrefresh);
   18099 			zone->retry = RANGE(retry, zone->minretry,
   18100 					    zone->maxretry);
   18101 			zone->expire = RANGE(expire,
   18102 					     zone->refresh + zone->retry,
   18103 					     DNS_MAX_EXPIRE);
   18104 			zone->soattl = soattl;
   18105 			zone->minimum = minimum;
   18106 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   18107 		}
   18108 
   18109 		/*
   18110 		 * Set our next refresh time.
   18111 		 */
   18112 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
   18113 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   18114 			zone->refreshtime = now;
   18115 		} else {
   18116 			DNS_ZONE_JITTER_ADD(&now, zone->refresh,
   18117 					    &zone->refreshtime);
   18118 		}
   18119 
   18120 		/*
   18121 		 * Set our next expire time. If the parent returned
   18122 		 * an EXPIRE option use that to update zone->expiretime.
   18123 		 */
   18124 		expire = zone->expire;
   18125 		if (expireopt != NULL && *expireopt < expire) {
   18126 			expire = *expireopt;
   18127 		}
   18128 		DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
   18129 		if (oldexpire != zone->expire ||
   18130 		    isc_time_compare(&expiretime, &zone->expiretime) > 0)
   18131 		{
   18132 			zone->expiretime = expiretime;
   18133 		}
   18134 
   18135 		/*
   18136 		 * Set loadtime.
   18137 		 */
   18138 		zone->loadtime = now;
   18139 
   18140 		if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
   18141 			char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
   18142 			if (zone->tsigkey != NULL) {
   18143 				char namebuf[DNS_NAME_FORMATSIZE];
   18144 				dns_name_format(zone->tsigkey->name, namebuf,
   18145 						sizeof(namebuf));
   18146 				snprintf(buf, sizeof(buf), ": TSIG '%s'",
   18147 					 namebuf);
   18148 			} else {
   18149 				buf[0] = '\0';
   18150 			}
   18151 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18152 				      ISC_LOG_INFO, "transferred serial %u%s",
   18153 				      serial, buf);
   18154 			if (inline_raw(zone)) {
   18155 				zone_send_secureserial(zone, serial);
   18156 			}
   18157 		}
   18158 
   18159 		/*
   18160 		 * This is not necessary if we just performed a AXFR
   18161 		 * however it is necessary for an IXFR / UPTODATE and
   18162 		 * won't hurt with an AXFR.
   18163 		 */
   18164 		if (zone->masterfile != NULL || zone->journal != NULL) {
   18165 			unsigned int delay = DNS_DUMP_DELAY;
   18166 			isc_interval_t i;
   18167 			isc_time_t when;
   18168 
   18169 			/*
   18170 			 * Compute effective modification time.
   18171 			 */
   18172 			isc_interval_set(&i, zone->expire, 0);
   18173 			result = isc_time_subtract(&zone->expiretime, &i,
   18174 						   &when);
   18175 			if (result != ISC_R_SUCCESS) {
   18176 				when = now;
   18177 			}
   18178 
   18179 			result = ISC_R_FAILURE;
   18180 			if (zone->journal != NULL) {
   18181 				result = isc_file_settime(zone->journal, &when);
   18182 			}
   18183 			if (result != ISC_R_SUCCESS && zone->masterfile != NULL)
   18184 			{
   18185 				result = isc_file_settime(zone->masterfile,
   18186 							  &when);
   18187 			}
   18188 
   18189 			if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
   18190 			    result == ISC_R_FILENOTFOUND)
   18191 			{
   18192 				delay = 0;
   18193 			}
   18194 
   18195 			if ((result == ISC_R_SUCCESS ||
   18196 			     result == ISC_R_FILENOTFOUND) &&
   18197 			    zone->masterfile != NULL)
   18198 			{
   18199 				zone_needdump(zone, delay);
   18200 			} else if (result != ISC_R_SUCCESS) {
   18201 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18202 					      ISC_LOG_ERROR,
   18203 					      "transfer: could not set file "
   18204 					      "modification time of '%s': %s",
   18205 					      zone->masterfile,
   18206 					      isc_result_totext(result));
   18207 			}
   18208 		}
   18209 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
   18210 		inc_stats(zone, dns_zonestatscounter_xfrsuccess);
   18211 		break;
   18212 
   18213 	case DNS_R_BADIXFR:
   18214 		/* Force retry with AXFR. */
   18215 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOIXFR);
   18216 		goto same_primary;
   18217 
   18218 	case DNS_R_TOOMANYRECORDS:
   18219 	case DNS_R_VERIFYFAILURE:
   18220 		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
   18221 		inc_stats(zone, dns_zonestatscounter_xfrfail);
   18222 		break;
   18223 
   18224 	case ISC_R_SHUTTINGDOWN:
   18225 		dns_remote_reset(&zone->primaries, true);
   18226 		break;
   18227 
   18228 	default:
   18229 	next_primary:
   18230 		/*
   18231 		 * Skip to next failed / untried primary.
   18232 		 */
   18233 		dns_remote_next(&zone->primaries, true);
   18234 	same_primary:
   18235 		if (dns_remote_done(&zone->primaries)) {
   18236 			dns_remote_reset(&zone->primaries, false);
   18237 		} else {
   18238 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
   18239 			again = true;
   18240 		}
   18241 		inc_stats(zone, dns_zonestatscounter_xfrfail);
   18242 		break;
   18243 	}
   18244 	zone_settimer(zone, &now);
   18245 
   18246 	/*
   18247 	 * We are called as the done callback of a zone
   18248 	 * transfer object that just entered its shutting-down state or
   18249 	 * failed to start.  Since we are no longer responsible for shutting
   18250 	 * it down, we can detach our reference.
   18251 	 */
   18252 	if (zone->xfr != NULL) {
   18253 		dns_xfrin_detach(&zone->xfr);
   18254 	}
   18255 
   18256 	if (zone->tsigkey != NULL) {
   18257 		dns_tsigkey_detach(&zone->tsigkey);
   18258 	}
   18259 
   18260 	if (zone->transport != NULL) {
   18261 		dns_transport_detach(&zone->transport);
   18262 	}
   18263 
   18264 	/*
   18265 	 * Handle any deferred journal compaction.
   18266 	 */
   18267 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
   18268 		dns_db_t *db = NULL;
   18269 		if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
   18270 			zone_journal_compact(zone, db, zone->compact_serial);
   18271 			dns_db_detach(&db);
   18272 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
   18273 		}
   18274 	}
   18275 
   18276 	if (secure != NULL) {
   18277 		UNLOCK_ZONE(secure);
   18278 	}
   18279 	/*
   18280 	 * This transfer finishing freed up a transfer quota slot.
   18281 	 * Let any other zones waiting for quota have it.
   18282 	 */
   18283 	if (zone->zmgr != NULL &&
   18284 	    zone->statelist == &zone->zmgr->xfrin_in_progress)
   18285 	{
   18286 		UNLOCK_ZONE(zone);
   18287 		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   18288 		ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
   18289 		zone->statelist = NULL;
   18290 		zmgr_resume_xfrs(zone->zmgr, false);
   18291 		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   18292 		LOCK_ZONE(zone);
   18293 	}
   18294 
   18295 	/*
   18296 	 * Retry with a different server if necessary.
   18297 	 */
   18298 	if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   18299 		queue_soa_query(zone);
   18300 	}
   18301 
   18302 	isc_refcount_decrement(&zone->irefs);
   18303 	free_needed = exit_check(zone);
   18304 	UNLOCK_ZONE(zone);
   18305 	if (free_needed) {
   18306 		zone_free(zone);
   18307 	}
   18308 }
   18309 
   18310 static void
   18311 zone_loaddone(void *arg, isc_result_t result) {
   18312 	dns_load_t *load = arg;
   18313 	dns_zone_t *zone;
   18314 	isc_result_t tresult;
   18315 	dns_zone_t *secure = NULL;
   18316 
   18317 	zone = load->zone;
   18318 
   18319 	ENTER;
   18320 
   18321 	/*
   18322 	 * If zone loading failed, remove the update db callbacks prior
   18323 	 * to calling the list of callbacks in the zone load structure.
   18324 	 */
   18325 	if (result != ISC_R_SUCCESS) {
   18326 		dns_zone_rpz_disable_db(zone, load->db);
   18327 		dns_zone_catz_disable_db(zone, load->db);
   18328 	}
   18329 
   18330 	tresult = dns_db_endload(load->db, &load->callbacks);
   18331 	if (tresult != ISC_R_SUCCESS &&
   18332 	    (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
   18333 	{
   18334 		result = tresult;
   18335 	}
   18336 
   18337 	/*
   18338 	 * Lock hierarchy: zmgr, zone, raw.
   18339 	 */
   18340 again:
   18341 	LOCK_ZONE(zone);
   18342 	INSIST(zone != zone->raw);
   18343 	if (inline_secure(zone)) {
   18344 		LOCK_ZONE(zone->raw);
   18345 	} else if (inline_raw(zone)) {
   18346 		secure = zone->secure;
   18347 		TRYLOCK_ZONE(tresult, secure);
   18348 		if (tresult != ISC_R_SUCCESS) {
   18349 			UNLOCK_ZONE(zone);
   18350 			secure = NULL;
   18351 			isc_thread_yield();
   18352 			goto again;
   18353 		}
   18354 	}
   18355 	(void)zone_postload(zone, load->db, load->loadtime, result);
   18356 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
   18357 	zone_idetach(&load->callbacks.zone);
   18358 	/*
   18359 	 * Leave the zone frozen if the reload fails.
   18360 	 */
   18361 	if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
   18362 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
   18363 	{
   18364 		zone->update_disabled = false;
   18365 	}
   18366 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
   18367 	if (inline_secure(zone)) {
   18368 		UNLOCK_ZONE(zone->raw);
   18369 	} else if (secure != NULL) {
   18370 		UNLOCK_ZONE(secure);
   18371 	}
   18372 	UNLOCK_ZONE(zone);
   18373 
   18374 	dns_db_detach(&load->db);
   18375 	if (zone->loadctx != NULL) {
   18376 		dns_loadctx_detach(&zone->loadctx);
   18377 	}
   18378 	isc_mem_put(zone->mctx, load, sizeof(*load));
   18379 
   18380 	dns_zone_idetach(&zone);
   18381 }
   18382 
   18383 void
   18384 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
   18385 	REQUIRE(DNS_ZONE_VALID(zone));
   18386 	REQUIRE(table != NULL);
   18387 	REQUIRE(*table == NULL);
   18388 
   18389 	LOCK_ZONE(zone);
   18390 	if (zone->ssutable != NULL) {
   18391 		dns_ssutable_attach(zone->ssutable, table);
   18392 	}
   18393 	UNLOCK_ZONE(zone);
   18394 }
   18395 
   18396 void
   18397 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
   18398 	REQUIRE(DNS_ZONE_VALID(zone));
   18399 
   18400 	LOCK_ZONE(zone);
   18401 	if (zone->ssutable != NULL) {
   18402 		dns_ssutable_detach(&zone->ssutable);
   18403 	}
   18404 	if (table != NULL) {
   18405 		dns_ssutable_attach(table, &zone->ssutable);
   18406 	}
   18407 	UNLOCK_ZONE(zone);
   18408 }
   18409 
   18410 void
   18411 dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
   18412 	REQUIRE(DNS_ZONE_VALID(zone));
   18413 
   18414 	zone->sigvalidityinterval = interval;
   18415 }
   18416 
   18417 uint32_t
   18418 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
   18419 	REQUIRE(DNS_ZONE_VALID(zone));
   18420 
   18421 	return zone->sigvalidityinterval;
   18422 }
   18423 
   18424 void
   18425 dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
   18426 	REQUIRE(DNS_ZONE_VALID(zone));
   18427 
   18428 	zone->keyvalidityinterval = interval;
   18429 }
   18430 
   18431 uint32_t
   18432 dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
   18433 	REQUIRE(DNS_ZONE_VALID(zone));
   18434 
   18435 	return zone->keyvalidityinterval;
   18436 }
   18437 
   18438 void
   18439 dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
   18440 	isc_time_t now;
   18441 
   18442 	REQUIRE(DNS_ZONE_VALID(zone));
   18443 
   18444 	LOCK_ZONE(zone);
   18445 	zone->sigresigninginterval = interval;
   18446 	set_resigntime(zone);
   18447 	if (zone->loop != NULL) {
   18448 		now = isc_time_now();
   18449 		zone_settimer(zone, &now);
   18450 	}
   18451 	UNLOCK_ZONE(zone);
   18452 }
   18453 
   18454 uint32_t
   18455 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
   18456 	REQUIRE(DNS_ZONE_VALID(zone));
   18457 
   18458 	return zone->sigresigninginterval;
   18459 }
   18460 
   18461 void
   18462 dns_zone_getsourceaddr(dns_zone_t *zone, isc_sockaddr_t *sourceaddr) {
   18463 	REQUIRE(DNS_ZONE_VALID(zone));
   18464 	REQUIRE(sourceaddr != NULL);
   18465 
   18466 	LOCK_ZONE(zone);
   18467 	INSIST(dns_remote_count(&zone->primaries) > 0);
   18468 	*sourceaddr = zone->sourceaddr;
   18469 	UNLOCK_ZONE(zone);
   18470 }
   18471 
   18472 isc_result_t
   18473 dns_zone_getprimaryaddr(dns_zone_t *zone, isc_sockaddr_t *primaryaddr) {
   18474 	isc_result_t result = ISC_R_NOMORE;
   18475 
   18476 	REQUIRE(DNS_ZONE_VALID(zone));
   18477 	REQUIRE(primaryaddr != NULL);
   18478 
   18479 	LOCK_ZONE(zone);
   18480 	INSIST(dns_remote_count(&zone->primaries) > 0);
   18481 	if (!dns_remote_done(&zone->primaries)) {
   18482 		*primaryaddr = dns_remote_curraddr(&zone->primaries);
   18483 		result = ISC_R_SUCCESS;
   18484 	}
   18485 	UNLOCK_ZONE(zone);
   18486 
   18487 	return result;
   18488 }
   18489 
   18490 isc_time_t
   18491 dns_zone_getxfrintime(dns_zone_t *zone) {
   18492 	isc_time_t xfrintime;
   18493 
   18494 	REQUIRE(DNS_ZONE_VALID(zone));
   18495 
   18496 	LOCK_ZONE(zone);
   18497 	xfrintime = zone->xfrintime;
   18498 	UNLOCK_ZONE(zone);
   18499 
   18500 	return xfrintime;
   18501 }
   18502 
   18503 static void
   18504 queue_xfrin(dns_zone_t *zone) {
   18505 	isc_result_t result;
   18506 	dns_zonemgr_t *zmgr = zone->zmgr;
   18507 
   18508 	ENTER;
   18509 
   18510 	INSIST(zone->statelist == NULL);
   18511 
   18512 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   18513 	ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
   18514 	isc_refcount_increment0(&zone->irefs);
   18515 	zone->statelist = &zmgr->waiting_for_xfrin;
   18516 	result = zmgr_start_xfrin_ifquota(zmgr, zone);
   18517 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   18518 
   18519 	if (result == ISC_R_QUOTA) {
   18520 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   18521 			      "zone transfer deferred due to quota");
   18522 	} else if (result != ISC_R_SUCCESS) {
   18523 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
   18524 			      "starting zone transfer: %s",
   18525 			      isc_result_totext(result));
   18526 	}
   18527 }
   18528 
   18529 /*
   18530  * Get the transport type used for the SOA query to the current primary server
   18531  * before an ongoing incoming zone transfer.
   18532  *
   18533  * Requires:
   18534  *	The zone is locked by the caller.
   18535  */
   18536 static dns_transport_type_t
   18537 get_request_transport_type(dns_zone_t *zone) {
   18538 	dns_transport_type_t transport_type = DNS_TRANSPORT_NONE;
   18539 
   18540 	if (zone->transport != NULL) {
   18541 		transport_type = dns_transport_get_type(zone->transport);
   18542 	} else {
   18543 		transport_type = (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC))
   18544 					 ? DNS_TRANSPORT_TCP
   18545 					 : DNS_TRANSPORT_UDP;
   18546 
   18547 		/* Check if the peer is forced to always use TCP. */
   18548 		if (transport_type != DNS_TRANSPORT_TCP &&
   18549 		    !dns_remote_done(&zone->primaries))
   18550 		{
   18551 			isc_result_t result;
   18552 			isc_sockaddr_t primaryaddr;
   18553 			isc_netaddr_t primaryip;
   18554 			dns_peer_t *peer = NULL;
   18555 
   18556 			primaryaddr = dns_remote_curraddr(&zone->primaries);
   18557 			isc_netaddr_fromsockaddr(&primaryip, &primaryaddr);
   18558 			result = dns_peerlist_peerbyaddr(zone->view->peers,
   18559 							 &primaryip, &peer);
   18560 			if (result == ISC_R_SUCCESS && peer != NULL) {
   18561 				bool usetcp;
   18562 				result = dns_peer_getforcetcp(peer, &usetcp);
   18563 				if (result == ISC_R_SUCCESS && usetcp) {
   18564 					transport_type = DNS_TRANSPORT_TCP;
   18565 				}
   18566 			}
   18567 		}
   18568 	}
   18569 
   18570 	return transport_type;
   18571 }
   18572 
   18573 dns_transport_type_t
   18574 dns_zone_getrequesttransporttype(dns_zone_t *zone) {
   18575 	dns_transport_type_t transport_type;
   18576 
   18577 	REQUIRE(DNS_ZONE_VALID(zone));
   18578 
   18579 	LOCK_ZONE(zone);
   18580 	transport_type = get_request_transport_type(zone);
   18581 	UNLOCK_ZONE(zone);
   18582 
   18583 	return transport_type;
   18584 }
   18585 
   18586 /*
   18587  * This event callback is called when a zone has received
   18588  * any necessary zone transfer quota.  This is the time
   18589  * to go ahead and start the transfer.
   18590  */
   18591 static void
   18592 got_transfer_quota(void *arg) {
   18593 	dns_zone_t *zone = (dns_zone_t *)arg;
   18594 	isc_result_t result = ISC_R_SUCCESS;
   18595 	dns_peer_t *peer = NULL;
   18596 	char primary[ISC_SOCKADDR_FORMATSIZE];
   18597 	char source[ISC_SOCKADDR_FORMATSIZE];
   18598 	dns_rdatatype_t xfrtype;
   18599 	isc_netaddr_t primaryip;
   18600 	isc_sockaddr_t primaryaddr;
   18601 	isc_sockaddr_t sourceaddr;
   18602 	isc_time_t now;
   18603 	dns_transport_type_t soa_transport_type = DNS_TRANSPORT_NONE;
   18604 	const char *soa_before = "";
   18605 	bool loaded;
   18606 	isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
   18607 	dns_xfrin_t *xfr = NULL;
   18608 
   18609 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   18610 		zone_xfrdone(zone, NULL, ISC_R_CANCELED);
   18611 		return;
   18612 	}
   18613 
   18614 	now = isc_time_now();
   18615 
   18616 	primaryaddr = dns_remote_curraddr(&zone->primaries);
   18617 	isc_sockaddr_format(&primaryaddr, primary, sizeof(primary));
   18618 	if (dns_zonemgr_unreachable(zone->zmgr, &primaryaddr, &zone->sourceaddr,
   18619 				    &now))
   18620 	{
   18621 		isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   18622 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   18623 			      "got_transfer_quota: skipping zone transfer as "
   18624 			      "primary %s (source %s) is unreachable (cached)",
   18625 			      primary, source);
   18626 		zone_xfrdone(zone, NULL, ISC_R_CANCELED);
   18627 		return;
   18628 	}
   18629 
   18630 	isc_netaddr_fromsockaddr(&primaryip, &primaryaddr);
   18631 	(void)dns_peerlist_peerbyaddr(zone->view->peers, &primaryip, &peer);
   18632 
   18633 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
   18634 		soa_before = "SOA before ";
   18635 	}
   18636 	/*
   18637 	 * Decide whether we should request IXFR or AXFR.
   18638 	 */
   18639 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   18640 	loaded = (zone->db != NULL);
   18641 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   18642 
   18643 	if (!loaded) {
   18644 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
   18645 			      "no database exists yet, requesting AXFR of "
   18646 			      "initial version from %s",
   18647 			      primary);
   18648 		xfrtype = dns_rdatatype_axfr;
   18649 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
   18650 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
   18651 			      "forced reload, requesting AXFR of "
   18652 			      "initial version from %s",
   18653 			      primary);
   18654 		xfrtype = dns_rdatatype_axfr;
   18655 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOIXFR)) {
   18656 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
   18657 			      "retrying with AXFR from %s due to "
   18658 			      "previous IXFR failure",
   18659 			      primary);
   18660 		xfrtype = dns_rdatatype_axfr;
   18661 		LOCK_ZONE(zone);
   18662 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOIXFR);
   18663 		UNLOCK_ZONE(zone);
   18664 	} else {
   18665 		bool use_ixfr = true;
   18666 		if (peer != NULL) {
   18667 			result = dns_peer_getrequestixfr(peer, &use_ixfr);
   18668 		}
   18669 		if (peer == NULL || result != ISC_R_SUCCESS) {
   18670 			use_ixfr = zone->requestixfr;
   18671 		}
   18672 		if (!use_ixfr) {
   18673 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18674 				      ISC_LOG_DEBUG(1),
   18675 				      "IXFR disabled, "
   18676 				      "requesting %sAXFR from %s",
   18677 				      soa_before, primary);
   18678 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
   18679 				xfrtype = dns_rdatatype_soa;
   18680 			} else {
   18681 				xfrtype = dns_rdatatype_axfr;
   18682 			}
   18683 		} else {
   18684 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18685 				      ISC_LOG_DEBUG(1),
   18686 				      "requesting IXFR from %s", primary);
   18687 			xfrtype = dns_rdatatype_ixfr;
   18688 		}
   18689 	}
   18690 
   18691 	/*
   18692 	 * Determine if we should attempt to sign the request with TSIG.
   18693 	 */
   18694 	result = ISC_R_NOTFOUND;
   18695 
   18696 	/*
   18697 	 * First, look for a tsig key in the primaries statement, then
   18698 	 * try for a server key.
   18699 	 */
   18700 	if (dns_remote_keyname(&zone->primaries) != NULL) {
   18701 		dns_view_t *view = dns_zone_getview(zone);
   18702 		dns_name_t *keyname = dns_remote_keyname(&zone->primaries);
   18703 		result = dns_view_gettsig(view, keyname, &zone->tsigkey);
   18704 	}
   18705 	if (result != ISC_R_SUCCESS) {
   18706 		INSIST(zone->tsigkey == NULL);
   18707 		result = dns_view_getpeertsig(zone->view, &primaryip,
   18708 					      &zone->tsigkey);
   18709 	}
   18710 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   18711 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
   18712 			      "could not get TSIG key for zone transfer: %s",
   18713 			      isc_result_totext(result));
   18714 	}
   18715 
   18716 	/*
   18717 	 * Get the TLS transport for the primary, if configured.
   18718 	 */
   18719 	if (dns_remote_tlsname(&zone->primaries) != NULL) {
   18720 		dns_view_t *view = dns_zone_getview(zone);
   18721 		dns_name_t *tlsname = dns_remote_tlsname(&zone->primaries);
   18722 		result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
   18723 					       &zone->transport);
   18724 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   18725 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   18726 				      ISC_LOG_ERROR,
   18727 				      "could not get TLS configuration for "
   18728 				      "zone transfer: %s",
   18729 				      isc_result_totext(result));
   18730 		}
   18731 	}
   18732 
   18733 	LOCK_ZONE(zone);
   18734 	if (xfrtype != dns_rdatatype_soa) {
   18735 		/*
   18736 		 * If 'xfrtype' is dns_rdatatype_soa, then the SOA query will be
   18737 		 * performed by xfrin, otherwise, the SOA request performed by
   18738 		 * soa_query() was successful and we should inform the xfrin
   18739 		 * about the transport type used for that query, so that the
   18740 		 * information can be presented in the statistics channel.
   18741 		 */
   18742 		soa_transport_type = get_request_transport_type(zone);
   18743 	}
   18744 	sourceaddr = zone->sourceaddr;
   18745 	UNLOCK_ZONE(zone);
   18746 
   18747 	INSIST(isc_sockaddr_pf(&primaryaddr) == isc_sockaddr_pf(&sourceaddr));
   18748 
   18749 	zmgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
   18750 
   18751 	dns_xfrin_create(zone, xfrtype, &primaryaddr, &sourceaddr,
   18752 			 zone->tsigkey, soa_transport_type, zone->transport,
   18753 			 zmgr_tlsctx_cache, zone->mctx, &xfr);
   18754 	INSIST(xfr != NULL);
   18755 
   18756 	isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
   18757 
   18758 	LOCK_ZONE(zone);
   18759 	if (zone->xfr != NULL) {
   18760 		dns_xfrin_detach(&zone->xfr);
   18761 	}
   18762 	dns_xfrin_attach(xfr, &zone->xfr);
   18763 	UNLOCK_ZONE(zone);
   18764 
   18765 	dns_xfrin_detach(&xfr);
   18766 
   18767 	/*
   18768 	 * Any failure in this function is handled like a failed
   18769 	 * zone transfer.  This ensures that we get removed from
   18770 	 * zmgr->xfrin_in_progress.
   18771 	 */
   18772 	result = dns_xfrin_start(zone->xfr, zone_xfrdone);
   18773 	if (result != ISC_R_SUCCESS) {
   18774 		zone_xfrdone(zone, NULL, result);
   18775 		return;
   18776 	}
   18777 
   18778 	LOCK_ZONE(zone);
   18779 	if (xfrtype == dns_rdatatype_axfr) {
   18780 		if (isc_sockaddr_pf(&primaryaddr) == PF_INET) {
   18781 			inc_stats(zone, dns_zonestatscounter_axfrreqv4);
   18782 		} else {
   18783 			inc_stats(zone, dns_zonestatscounter_axfrreqv6);
   18784 		}
   18785 	} else if (xfrtype == dns_rdatatype_ixfr) {
   18786 		if (isc_sockaddr_pf(&primaryaddr) == PF_INET) {
   18787 			inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
   18788 		} else {
   18789 			inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
   18790 		}
   18791 	}
   18792 	UNLOCK_ZONE(zone);
   18793 }
   18794 
   18795 /*
   18796  * Update forwarding support.
   18797  */
   18798 
   18799 static void
   18800 forward_destroy(dns_forward_t *forward) {
   18801 	forward->magic = 0;
   18802 	if (forward->request != NULL) {
   18803 		dns_request_destroy(&forward->request);
   18804 	}
   18805 	if (forward->msgbuf != NULL) {
   18806 		isc_buffer_free(&forward->msgbuf);
   18807 	}
   18808 	if (forward->transport != NULL) {
   18809 		dns_transport_detach(&forward->transport);
   18810 	}
   18811 	if (forward->zone != NULL) {
   18812 		LOCK(&forward->zone->lock);
   18813 		if (ISC_LINK_LINKED(forward, link)) {
   18814 			ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
   18815 		}
   18816 		UNLOCK(&forward->zone->lock);
   18817 		dns_zone_idetach(&forward->zone);
   18818 	}
   18819 	isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
   18820 }
   18821 
   18822 static isc_result_t
   18823 sendtoprimary(dns_forward_t *forward) {
   18824 	isc_result_t result;
   18825 	isc_sockaddr_t src, any;
   18826 	dns_zone_t *zone = forward->zone;
   18827 	bool tls_transport_invalid = false;
   18828 	isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
   18829 
   18830 	LOCK_ZONE(zone);
   18831 
   18832 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   18833 		UNLOCK_ZONE(zone);
   18834 		return ISC_R_CANCELED;
   18835 	}
   18836 
   18837 next:
   18838 	if (forward->which >= dns_remote_count(&forward->zone->primaries)) {
   18839 		UNLOCK_ZONE(zone);
   18840 		return ISC_R_NOMORE;
   18841 	}
   18842 
   18843 	forward->addr = dns_remote_addr(&zone->primaries, forward->which);
   18844 
   18845 	if (isc_sockaddr_disabled(&forward->addr)) {
   18846 		forward->which++;
   18847 		goto next;
   18848 	}
   18849 
   18850 	/*
   18851 	 * Always use TCP regardless of whether the original update
   18852 	 * used TCP.
   18853 	 * XXX The timeout may but a bit small if we are far down a
   18854 	 * transfer graph and have to try several primaries.
   18855 	 */
   18856 	switch (isc_sockaddr_pf(&forward->addr)) {
   18857 	case PF_INET:
   18858 		isc_sockaddr_any(&any);
   18859 		src = zone->primaries.sources[forward->which];
   18860 		if (isc_sockaddr_equal(&src, &any)) {
   18861 			src = zone->xfrsource4;
   18862 		}
   18863 		break;
   18864 	case PF_INET6:
   18865 		isc_sockaddr_any6(&any);
   18866 		src = zone->primaries.sources[forward->which];
   18867 		if (isc_sockaddr_equal(&src, &any)) {
   18868 			src = zone->xfrsource6;
   18869 		}
   18870 		break;
   18871 	default:
   18872 		result = ISC_R_NOTIMPLEMENTED;
   18873 		goto unlock;
   18874 	}
   18875 
   18876 	if (forward->transport != NULL) {
   18877 		dns_transport_detach(&forward->transport);
   18878 	}
   18879 
   18880 	if (dns_remote_tlsname(&zone->primaries) != NULL &&
   18881 	    zone->primaries.tlsnames[forward->which] != NULL)
   18882 	{
   18883 		dns_view_t *view = dns_zone_getview(zone);
   18884 		dns_name_t *tlsname = zone->primaries.tlsnames[forward->which];
   18885 
   18886 		result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
   18887 					       &forward->transport);
   18888 
   18889 		if (result != ISC_R_SUCCESS) {
   18890 			/* Log the error message when unlocked. */
   18891 			tls_transport_invalid = true;
   18892 			goto unlock;
   18893 		}
   18894 	}
   18895 
   18896 	zmgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
   18897 
   18898 	result = dns_request_createraw(
   18899 		forward->zone->view->requestmgr, forward->msgbuf, &src,
   18900 		&forward->addr, forward->transport, zmgr_tlsctx_cache,
   18901 		forward->options, 15 /* XXX */, 0, 0, forward->zone->loop,
   18902 		forward_callback, forward, &forward->request);
   18903 
   18904 	isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
   18905 
   18906 	if (result == ISC_R_SUCCESS) {
   18907 		if (!ISC_LINK_LINKED(forward, link)) {
   18908 			ISC_LIST_APPEND(zone->forwards, forward, link);
   18909 		}
   18910 	}
   18911 
   18912 unlock:
   18913 	UNLOCK_ZONE(zone);
   18914 
   18915 	if (tls_transport_invalid) {
   18916 		dns_zone_log(zone, ISC_LOG_ERROR,
   18917 			     "could not get TLS configuration "
   18918 			     "for dynamic update: %s",
   18919 			     isc_result_totext(result));
   18920 	}
   18921 
   18922 	return result;
   18923 }
   18924 
   18925 static void
   18926 forward_callback(void *arg) {
   18927 	dns_request_t *request = (dns_request_t *)arg;
   18928 	dns_forward_t *forward = dns_request_getarg(request);
   18929 	dns_message_t *msg = NULL;
   18930 	char primary[ISC_SOCKADDR_FORMATSIZE];
   18931 	isc_result_t result;
   18932 	dns_zone_t *zone;
   18933 
   18934 	INSIST(DNS_FORWARD_VALID(forward));
   18935 	zone = forward->zone;
   18936 	INSIST(DNS_ZONE_VALID(zone));
   18937 
   18938 	ENTER;
   18939 
   18940 	isc_sockaddr_format(&forward->addr, primary, sizeof(primary));
   18941 
   18942 	result = dns_request_getresult(request);
   18943 	if (result != ISC_R_SUCCESS) {
   18944 		dns_zone_log(zone, ISC_LOG_INFO,
   18945 			     "could not forward dynamic update to %s: %s",
   18946 			     primary, isc_result_totext(result));
   18947 		goto next_primary;
   18948 	}
   18949 
   18950 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
   18951 			   &msg);
   18952 
   18953 	result = dns_request_getresponse(request, msg,
   18954 					 DNS_MESSAGEPARSE_PRESERVEORDER |
   18955 						 DNS_MESSAGEPARSE_CLONEBUFFER);
   18956 	if (result != ISC_R_SUCCESS) {
   18957 		goto next_primary;
   18958 	}
   18959 
   18960 	/*
   18961 	 * Unexpected opcode.
   18962 	 */
   18963 	if (msg->opcode != dns_opcode_update) {
   18964 		char opcode[128];
   18965 		isc_buffer_t rb;
   18966 
   18967 		isc_buffer_init(&rb, opcode, sizeof(opcode));
   18968 		(void)dns_opcode_totext(msg->opcode, &rb);
   18969 
   18970 		dns_zone_log(zone, ISC_LOG_INFO,
   18971 			     "forwarding dynamic update: "
   18972 			     "unexpected opcode (%.*s) from %s",
   18973 			     (int)rb.used, opcode, primary);
   18974 		goto next_primary;
   18975 	}
   18976 
   18977 	switch (msg->rcode) {
   18978 	/*
   18979 	 * Pass these rcodes back to client.
   18980 	 */
   18981 	case dns_rcode_noerror:
   18982 	case dns_rcode_yxdomain:
   18983 	case dns_rcode_yxrrset:
   18984 	case dns_rcode_nxrrset:
   18985 	case dns_rcode_refused:
   18986 	case dns_rcode_nxdomain: {
   18987 		char rcode[128];
   18988 		isc_buffer_t rb;
   18989 
   18990 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   18991 		(void)dns_rcode_totext(msg->rcode, &rb);
   18992 		dns_zone_log(zone, ISC_LOG_INFO,
   18993 			     "forwarded dynamic update: "
   18994 			     "primary %s returned: %.*s",
   18995 			     primary, (int)rb.used, rcode);
   18996 		break;
   18997 	}
   18998 
   18999 	/* These should not occur if the primaries/zone are valid. */
   19000 	case dns_rcode_notzone:
   19001 	case dns_rcode_notauth: {
   19002 		char rcode[128];
   19003 		isc_buffer_t rb;
   19004 
   19005 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   19006 		(void)dns_rcode_totext(msg->rcode, &rb);
   19007 		dns_zone_log(zone, ISC_LOG_WARNING,
   19008 			     "forwarding dynamic update: "
   19009 			     "unexpected response: primary %s returned: %.*s",
   19010 			     primary, (int)rb.used, rcode);
   19011 		goto next_primary;
   19012 	}
   19013 
   19014 	/* Try another server for these rcodes. */
   19015 	case dns_rcode_formerr:
   19016 	case dns_rcode_servfail:
   19017 	case dns_rcode_notimp:
   19018 	case dns_rcode_badvers:
   19019 	default:
   19020 		goto next_primary;
   19021 	}
   19022 
   19023 	/* call callback */
   19024 	(forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
   19025 	msg = NULL;
   19026 	dns_request_destroy(&forward->request);
   19027 	forward_destroy(forward);
   19028 	return;
   19029 
   19030 next_primary:
   19031 	if (msg != NULL) {
   19032 		dns_message_detach(&msg);
   19033 	}
   19034 	forward->which++;
   19035 	dns_request_destroy(&forward->request);
   19036 	result = sendtoprimary(forward);
   19037 	if (result != ISC_R_SUCCESS) {
   19038 		/* call callback */
   19039 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   19040 			     "exhausted dynamic update forwarder list");
   19041 		(forward->callback)(forward->callback_arg, result, NULL);
   19042 		forward_destroy(forward);
   19043 	}
   19044 }
   19045 
   19046 isc_result_t
   19047 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
   19048 		       dns_updatecallback_t callback, void *callback_arg) {
   19049 	dns_forward_t *forward;
   19050 	isc_result_t result;
   19051 	isc_region_t *mr;
   19052 
   19053 	REQUIRE(DNS_ZONE_VALID(zone));
   19054 	REQUIRE(msg != NULL);
   19055 	REQUIRE(callback != NULL);
   19056 
   19057 	forward = isc_mem_get(zone->mctx, sizeof(*forward));
   19058 	*forward = (dns_forward_t){ .callback = callback,
   19059 				    .callback_arg = callback_arg,
   19060 				    .options = DNS_REQUESTOPT_TCP };
   19061 	ISC_LINK_INIT(forward, link);
   19062 	forward->magic = FORWARD_MAGIC;
   19063 
   19064 	/*
   19065 	 * If we have a SIG(0) signed message we need to preserve the
   19066 	 * query id as that is included in the SIG(0) computation.
   19067 	 */
   19068 	if (msg->sig0 != NULL) {
   19069 		forward->options |= DNS_REQUESTOPT_FIXEDID;
   19070 	}
   19071 
   19072 	mr = dns_message_getrawmessage(msg);
   19073 	if (mr == NULL) {
   19074 		result = ISC_R_UNEXPECTEDEND;
   19075 		goto cleanup;
   19076 	}
   19077 
   19078 	isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
   19079 	result = isc_buffer_copyregion(forward->msgbuf, mr);
   19080 	if (result != ISC_R_SUCCESS) {
   19081 		goto cleanup;
   19082 	}
   19083 
   19084 	isc_mem_attach(zone->mctx, &forward->mctx);
   19085 	dns_zone_iattach(zone, &forward->zone);
   19086 	result = sendtoprimary(forward);
   19087 
   19088 cleanup:
   19089 	if (result != ISC_R_SUCCESS) {
   19090 		forward_destroy(forward);
   19091 	}
   19092 	return result;
   19093 }
   19094 
   19095 isc_result_t
   19096 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
   19097 	REQUIRE(DNS_ZONE_VALID(zone));
   19098 	REQUIRE(next != NULL && *next == NULL);
   19099 
   19100 	*next = ISC_LIST_NEXT(zone, link);
   19101 	if (*next == NULL) {
   19102 		return ISC_R_NOMORE;
   19103 	} else {
   19104 		return ISC_R_SUCCESS;
   19105 	}
   19106 }
   19107 
   19108 isc_result_t
   19109 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
   19110 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19111 	REQUIRE(first != NULL && *first == NULL);
   19112 
   19113 	*first = ISC_LIST_HEAD(zmgr->zones);
   19114 	if (*first == NULL) {
   19115 		return ISC_R_NOMORE;
   19116 	} else {
   19117 		return ISC_R_SUCCESS;
   19118 	}
   19119 }
   19120 
   19121 /***
   19122  ***	Zone manager.
   19123  ***/
   19124 
   19125 static void
   19126 zonemgr_keymgmt_init(dns_zonemgr_t *zmgr) {
   19127 	dns_keymgmt_t *mgmt = isc_mem_get(zmgr->mctx, sizeof(*mgmt));
   19128 
   19129 	*mgmt = (dns_keymgmt_t){
   19130 		.magic = KEYMGMT_MAGIC,
   19131 	};
   19132 
   19133 	isc_mem_attach(zmgr->mctx, &mgmt->mctx);
   19134 	isc_rwlock_init(&mgmt->lock);
   19135 	isc_hashmap_create(mgmt->mctx, DNS_KEYMGMT_HASH_BITS, &mgmt->table);
   19136 
   19137 	zmgr->keymgmt = mgmt;
   19138 }
   19139 
   19140 static void
   19141 zonemgr_keymgmt_destroy(dns_zonemgr_t *zmgr) {
   19142 	dns_keymgmt_t *mgmt = zmgr->keymgmt;
   19143 
   19144 	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
   19145 
   19146 	mgmt->magic = 0;
   19147 
   19148 	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
   19149 	INSIST(isc_hashmap_count(mgmt->table) == 0);
   19150 	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
   19151 	isc_hashmap_destroy(&mgmt->table);
   19152 
   19153 	isc_rwlock_destroy(&mgmt->lock);
   19154 	isc_mem_putanddetach(&mgmt->mctx, mgmt, sizeof(dns_keymgmt_t));
   19155 }
   19156 
   19157 static bool
   19158 kfio_match(void *node, const void *key) {
   19159 	const dns_keyfileio_t *kfio = node;
   19160 
   19161 	return dns_name_equal(kfio->name, key);
   19162 }
   19163 
   19164 static void
   19165 zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
   19166 		    dns_keyfileio_t **added) {
   19167 	dns_keymgmt_t *mgmt = zmgr->keymgmt;
   19168 	dns_keyfileio_t *kfio = NULL;
   19169 	isc_result_t result;
   19170 	dns_fixedname_t fname;
   19171 	dns_name_t *name;
   19172 
   19173 	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
   19174 	REQUIRE(added != NULL && *added == NULL);
   19175 
   19176 	name = dns_fixedname_initname(&fname);
   19177 	dns_name_downcase(&zone->origin, name, NULL);
   19178 
   19179 	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
   19180 
   19181 	result = isc_hashmap_find(mgmt->table, dns_name_hash(name), kfio_match,
   19182 				  name, (void **)&kfio);
   19183 	switch (result) {
   19184 	case ISC_R_SUCCESS:
   19185 		isc_refcount_increment(&kfio->references);
   19186 		break;
   19187 	case ISC_R_NOTFOUND:
   19188 		kfio = isc_mem_get(mgmt->mctx, sizeof(*kfio));
   19189 		*kfio = (dns_keyfileio_t){
   19190 			.magic = KEYFILEIO_MAGIC,
   19191 		};
   19192 		isc_refcount_init(&kfio->references, 1);
   19193 		kfio->name = dns_fixedname_initname(&kfio->fname);
   19194 		dns_name_copy(name, kfio->name);
   19195 
   19196 		isc_mutex_init(&kfio->lock);
   19197 		result = isc_hashmap_add(mgmt->table, dns_name_hash(kfio->name),
   19198 					 kfio_match, kfio->name, kfio, NULL);
   19199 		INSIST(result == ISC_R_SUCCESS);
   19200 		break;
   19201 	default:
   19202 		UNREACHABLE();
   19203 	}
   19204 	*added = kfio;
   19205 	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
   19206 }
   19207 
   19208 static bool
   19209 match_ptr(void *node, const void *key) {
   19210 	return node == key;
   19211 }
   19212 
   19213 static void
   19214 zonemgr_keymgmt_delete(dns_zonemgr_t *zmgr, dns_keyfileio_t **deleted) {
   19215 	REQUIRE(DNS_KEYMGMT_VALID(zmgr->keymgmt));
   19216 	REQUIRE(deleted != NULL && DNS_KEYFILEIO_VALID(*deleted));
   19217 
   19218 	dns_keymgmt_t *mgmt = zmgr->keymgmt;
   19219 	dns_keyfileio_t *kfio = *deleted;
   19220 	isc_result_t result;
   19221 
   19222 	*deleted = NULL;
   19223 
   19224 	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
   19225 
   19226 	if (isc_refcount_decrement(&kfio->references) == 1) {
   19227 		isc_refcount_destroy(&kfio->references);
   19228 		kfio->magic = 0;
   19229 		isc_mutex_destroy(&kfio->lock);
   19230 
   19231 		result = isc_hashmap_delete(mgmt->table,
   19232 					    dns_name_hash(kfio->name),
   19233 					    match_ptr, kfio);
   19234 		INSIST(result == ISC_R_SUCCESS);
   19235 
   19236 		isc_mem_put(mgmt->mctx, kfio, sizeof(*kfio));
   19237 	}
   19238 
   19239 	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
   19240 }
   19241 
   19242 void
   19243 dns_zonemgr_create(isc_mem_t *mctx, isc_nm_t *netmgr, dns_zonemgr_t **zmgrp) {
   19244 	dns_zonemgr_t *zmgr = NULL;
   19245 	isc_loop_t *loop = isc_loop();
   19246 	isc_loopmgr_t *loopmgr = isc_loop_getloopmgr(loop);
   19247 
   19248 	REQUIRE(mctx != NULL);
   19249 	REQUIRE(netmgr != NULL);
   19250 	REQUIRE(zmgrp != NULL && *zmgrp == NULL);
   19251 
   19252 	zmgr = isc_mem_get(mctx, sizeof(*zmgr));
   19253 
   19254 	*zmgr = (dns_zonemgr_t){
   19255 		.loopmgr = loopmgr,
   19256 		.netmgr = netmgr,
   19257 		.workers = isc_loopmgr_nloops(loopmgr),
   19258 		.transfersin = 10,
   19259 		.transfersperns = 2,
   19260 	};
   19261 
   19262 	isc_refcount_init(&zmgr->refs, 1);
   19263 	isc_mem_attach(mctx, &zmgr->mctx);
   19264 
   19265 	ISC_LIST_INIT(zmgr->zones);
   19266 	ISC_LIST_INIT(zmgr->waiting_for_xfrin);
   19267 	ISC_LIST_INIT(zmgr->xfrin_in_progress);
   19268 	memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
   19269 	for (size_t i = 0; i < UNREACH_CACHE_SIZE; i++) {
   19270 		atomic_init(&zmgr->unreachable[i].expire, 0);
   19271 	}
   19272 	isc_rwlock_init(&zmgr->rwlock);
   19273 
   19274 	/* Unreachable lock. */
   19275 	isc_rwlock_init(&zmgr->urlock);
   19276 
   19277 	isc_ratelimiter_create(loop, &zmgr->checkdsrl);
   19278 	isc_ratelimiter_create(loop, &zmgr->notifyrl);
   19279 	isc_ratelimiter_create(loop, &zmgr->refreshrl);
   19280 	isc_ratelimiter_create(loop, &zmgr->startupnotifyrl);
   19281 	isc_ratelimiter_create(loop, &zmgr->startuprefreshrl);
   19282 
   19283 	zmgr->mctxpool = isc_mem_cget(zmgr->mctx, zmgr->workers,
   19284 				      sizeof(zmgr->mctxpool[0]));
   19285 	for (size_t i = 0; i < zmgr->workers; i++) {
   19286 		isc_mem_create(&zmgr->mctxpool[i]);
   19287 		isc_mem_setname(zmgr->mctxpool[i], "zonemgr-mctxpool");
   19288 	}
   19289 
   19290 	/* Key file I/O locks. */
   19291 	zonemgr_keymgmt_init(zmgr);
   19292 
   19293 	/* Default to 20 refresh queries / notifies / checkds per second. */
   19294 	setrl(zmgr->checkdsrl, &zmgr->checkdsrate, 20);
   19295 	setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
   19296 	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
   19297 	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
   19298 	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
   19299 	isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
   19300 	isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
   19301 
   19302 	zmgr->tlsctx_cache = NULL;
   19303 	isc_rwlock_init(&zmgr->tlsctx_cache_rwlock);
   19304 
   19305 	zmgr->magic = ZONEMGR_MAGIC;
   19306 
   19307 	*zmgrp = zmgr;
   19308 }
   19309 
   19310 isc_result_t
   19311 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
   19312 	isc_mem_t *mctx = NULL;
   19313 	dns_zone_t *zone = NULL;
   19314 	unsigned int tid;
   19315 
   19316 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19317 	REQUIRE(zonep != NULL && *zonep == NULL);
   19318 
   19319 	if (zmgr->mctxpool == NULL) {
   19320 		return ISC_R_FAILURE;
   19321 	}
   19322 
   19323 	tid = isc_random_uniform(zmgr->workers);
   19324 
   19325 	mctx = zmgr->mctxpool[tid];
   19326 	if (mctx == NULL) {
   19327 		return ISC_R_FAILURE;
   19328 	}
   19329 
   19330 	dns_zone_create(&zone, mctx, tid);
   19331 
   19332 	*zonep = zone;
   19333 
   19334 	return ISC_R_SUCCESS;
   19335 }
   19336 
   19337 isc_result_t
   19338 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
   19339 	REQUIRE(DNS_ZONE_VALID(zone));
   19340 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19341 
   19342 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19343 	LOCK_ZONE(zone);
   19344 	REQUIRE(zone->timer == NULL);
   19345 	REQUIRE(zone->zmgr == NULL);
   19346 
   19347 	isc_loop_t *loop = isc_loop_get(zmgr->loopmgr, zone->tid);
   19348 	isc_loop_attach(loop, &zone->loop);
   19349 
   19350 	zonemgr_keymgmt_add(zmgr, zone, &zone->kfio);
   19351 	INSIST(zone->kfio != NULL);
   19352 
   19353 	ISC_LIST_APPEND(zmgr->zones, zone, link);
   19354 	zone->zmgr = zmgr;
   19355 
   19356 	isc_refcount_increment(&zmgr->refs);
   19357 
   19358 	UNLOCK_ZONE(zone);
   19359 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19360 	return ISC_R_SUCCESS;
   19361 }
   19362 
   19363 void
   19364 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
   19365 	REQUIRE(DNS_ZONE_VALID(zone));
   19366 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19367 	REQUIRE(zone->zmgr == zmgr);
   19368 
   19369 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19370 	LOCK_ZONE(zone);
   19371 
   19372 	ISC_LIST_UNLINK(zmgr->zones, zone, link);
   19373 
   19374 	if (zone->kfio != NULL) {
   19375 		zonemgr_keymgmt_delete(zmgr, &zone->kfio);
   19376 		ENSURE(zone->kfio == NULL);
   19377 	}
   19378 
   19379 	if (zone->timer != NULL) {
   19380 		isc_refcount_decrement(&zone->irefs);
   19381 		isc_timer_destroy(&zone->timer);
   19382 	}
   19383 
   19384 	isc_loop_detach(&zone->loop);
   19385 
   19386 	/* Detach below, outside of the write lock. */
   19387 	zone->zmgr = NULL;
   19388 
   19389 	UNLOCK_ZONE(zone);
   19390 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19391 
   19392 	dns_zonemgr_detach(&zmgr);
   19393 }
   19394 
   19395 void
   19396 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
   19397 	REQUIRE(DNS_ZONEMGR_VALID(source));
   19398 	REQUIRE(target != NULL && *target == NULL);
   19399 
   19400 	isc_refcount_increment(&source->refs);
   19401 
   19402 	*target = source;
   19403 }
   19404 
   19405 void
   19406 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
   19407 	dns_zonemgr_t *zmgr;
   19408 
   19409 	REQUIRE(zmgrp != NULL);
   19410 	zmgr = *zmgrp;
   19411 	*zmgrp = NULL;
   19412 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19413 
   19414 	if (isc_refcount_decrement(&zmgr->refs) == 1) {
   19415 		zonemgr_free(zmgr);
   19416 	}
   19417 }
   19418 
   19419 isc_result_t
   19420 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
   19421 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19422 
   19423 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   19424 	for (dns_zone_t *zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
   19425 	     zone = ISC_LIST_NEXT(zone, link))
   19426 	{
   19427 		isc_time_t now;
   19428 
   19429 		LOCK_ZONE(zone);
   19430 		now = isc_time_now();
   19431 		zone_settimer(zone, &now);
   19432 		UNLOCK_ZONE(zone);
   19433 	}
   19434 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   19435 
   19436 	/*
   19437 	 * Recent configuration changes may have increased the
   19438 	 * amount of available transfers quota.  Make sure any
   19439 	 * transfers currently blocked on quota get started if
   19440 	 * possible.
   19441 	 */
   19442 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19443 	zmgr_resume_xfrs(zmgr, true);
   19444 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19445 	return ISC_R_SUCCESS;
   19446 }
   19447 
   19448 void
   19449 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
   19450 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19451 
   19452 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19453 	zmgr_resume_xfrs(zmgr, true);
   19454 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19455 }
   19456 
   19457 void
   19458 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
   19459 	dns_zone_t *zone;
   19460 
   19461 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19462 
   19463 	isc_ratelimiter_shutdown(zmgr->checkdsrl);
   19464 	isc_ratelimiter_shutdown(zmgr->notifyrl);
   19465 	isc_ratelimiter_shutdown(zmgr->refreshrl);
   19466 	isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
   19467 	isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
   19468 
   19469 	for (size_t i = 0; i < zmgr->workers; i++) {
   19470 		isc_mem_detach(&zmgr->mctxpool[i]);
   19471 	}
   19472 
   19473 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   19474 	for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
   19475 	     zone = ISC_LIST_NEXT(zone, link))
   19476 	{
   19477 		LOCK_ZONE(zone);
   19478 		forward_cancel(zone);
   19479 		UNLOCK_ZONE(zone);
   19480 	}
   19481 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   19482 }
   19483 
   19484 static void
   19485 zonemgr_free(dns_zonemgr_t *zmgr) {
   19486 	REQUIRE(ISC_LIST_EMPTY(zmgr->zones));
   19487 
   19488 	zmgr->magic = 0;
   19489 
   19490 	isc_refcount_destroy(&zmgr->refs);
   19491 	isc_ratelimiter_detach(&zmgr->checkdsrl);
   19492 	isc_ratelimiter_detach(&zmgr->notifyrl);
   19493 	isc_ratelimiter_detach(&zmgr->refreshrl);
   19494 	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
   19495 	isc_ratelimiter_detach(&zmgr->startuprefreshrl);
   19496 
   19497 	isc_mem_cput(zmgr->mctx, zmgr->mctxpool, zmgr->workers,
   19498 		     sizeof(zmgr->mctxpool[0]));
   19499 
   19500 	isc_rwlock_destroy(&zmgr->urlock);
   19501 	isc_rwlock_destroy(&zmgr->rwlock);
   19502 	isc_rwlock_destroy(&zmgr->tlsctx_cache_rwlock);
   19503 
   19504 	zonemgr_keymgmt_destroy(zmgr);
   19505 
   19506 	if (zmgr->tlsctx_cache != NULL) {
   19507 		isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
   19508 	}
   19509 	isc_mem_putanddetach(&zmgr->mctx, zmgr, sizeof(*zmgr));
   19510 }
   19511 
   19512 void
   19513 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
   19514 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19515 
   19516 	zmgr->transfersin = value;
   19517 }
   19518 
   19519 uint32_t
   19520 dns_zonemgr_gettransfersin(dns_zonemgr_t *zmgr) {
   19521 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19522 
   19523 	return zmgr->transfersin;
   19524 }
   19525 
   19526 void
   19527 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
   19528 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19529 
   19530 	zmgr->transfersperns = value;
   19531 }
   19532 
   19533 uint32_t
   19534 dns_zonemgr_gettransfersperns(dns_zonemgr_t *zmgr) {
   19535 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19536 
   19537 	return zmgr->transfersperns;
   19538 }
   19539 
   19540 /*
   19541  * Try to start a new incoming zone transfer to fill a quota
   19542  * slot that was just vacated.
   19543  *
   19544  * Requires:
   19545  *	The zone manager is locked by the caller.
   19546  */
   19547 static void
   19548 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
   19549 	dns_zone_t *zone;
   19550 	dns_zone_t *next;
   19551 
   19552 	for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); zone != NULL;
   19553 	     zone = next)
   19554 	{
   19555 		isc_result_t result;
   19556 		next = ISC_LIST_NEXT(zone, statelink);
   19557 		result = zmgr_start_xfrin_ifquota(zmgr, zone);
   19558 		if (result == ISC_R_SUCCESS) {
   19559 			if (multi) {
   19560 				continue;
   19561 			}
   19562 			/*
   19563 			 * We successfully filled the slot.  We're done.
   19564 			 */
   19565 			break;
   19566 		} else if (result == ISC_R_QUOTA) {
   19567 			/*
   19568 			 * Not enough quota.  This is probably the per-server
   19569 			 * quota, because we usually get called when a unit of
   19570 			 * global quota has just been freed.  Try the next
   19571 			 * zone, it may succeed if it uses another primary.
   19572 			 */
   19573 			continue;
   19574 		} else {
   19575 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
   19576 				      ISC_LOG_DEBUG(1),
   19577 				      "starting zone transfer: %s",
   19578 				      isc_result_totext(result));
   19579 			break;
   19580 		}
   19581 	}
   19582 }
   19583 
   19584 /*
   19585  * Try to start an incoming zone transfer for 'zone', quota permitting.
   19586  *
   19587  * Requires:
   19588  *	The zone manager is locked by the caller.
   19589  *
   19590  * Returns:
   19591  *	ISC_R_SUCCESS	There was enough quota and we attempted to
   19592  *			start a transfer.  zone_xfrdone() has been or will
   19593  *			be called.
   19594  *	ISC_R_QUOTA	Not enough quota.
   19595  *	Others		Failure.
   19596  */
   19597 static isc_result_t
   19598 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
   19599 	dns_peer_t *peer = NULL;
   19600 	isc_netaddr_t primaryip;
   19601 	isc_sockaddr_t curraddr;
   19602 	uint32_t nxfrsin, nxfrsperns;
   19603 	dns_zone_t *x = NULL;
   19604 	uint32_t maxtransfersin, maxtransfersperns;
   19605 
   19606 	/*
   19607 	 * If we are exiting just pretend we got quota so the zone will
   19608 	 * be cleaned up in the zone's loop context.
   19609 	 */
   19610 	LOCK_ZONE(zone);
   19611 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   19612 		UNLOCK_ZONE(zone);
   19613 		goto gotquota;
   19614 	}
   19615 
   19616 	/*
   19617 	 * Find any configured information about the server we'd
   19618 	 * like to transfer this zone from.
   19619 	 */
   19620 	curraddr = dns_remote_curraddr(&zone->primaries);
   19621 	isc_netaddr_fromsockaddr(&primaryip, &curraddr);
   19622 	(void)dns_peerlist_peerbyaddr(zone->view->peers, &primaryip, &peer);
   19623 	UNLOCK_ZONE(zone);
   19624 
   19625 	/*
   19626 	 * Determine the total maximum number of simultaneous
   19627 	 * transfers allowed, and the maximum for this specific
   19628 	 * primary.
   19629 	 */
   19630 	maxtransfersin = zmgr->transfersin;
   19631 	maxtransfersperns = zmgr->transfersperns;
   19632 	if (peer != NULL) {
   19633 		(void)dns_peer_gettransfers(peer, &maxtransfersperns);
   19634 	}
   19635 
   19636 	/*
   19637 	 * Count the total number of transfers that are in progress,
   19638 	 * and the number of transfers in progress from this primary.
   19639 	 * We linearly scan a list of all transfers; if this turns
   19640 	 * out to be too slow, we could hash on the primary address.
   19641 	 */
   19642 	nxfrsin = nxfrsperns = 0;
   19643 	for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress); x != NULL;
   19644 	     x = ISC_LIST_NEXT(x, statelink))
   19645 	{
   19646 		isc_netaddr_t xip;
   19647 		isc_sockaddr_t xaddr;
   19648 
   19649 		LOCK_ZONE(x);
   19650 		xaddr = dns_remote_curraddr(&x->primaries);
   19651 		isc_netaddr_fromsockaddr(&xip, &xaddr);
   19652 		UNLOCK_ZONE(x);
   19653 
   19654 		nxfrsin++;
   19655 		if (isc_netaddr_equal(&xip, &primaryip)) {
   19656 			nxfrsperns++;
   19657 		}
   19658 	}
   19659 
   19660 	/* Enforce quota. */
   19661 	if (nxfrsin >= maxtransfersin) {
   19662 		return ISC_R_QUOTA;
   19663 	}
   19664 
   19665 	if (nxfrsperns >= maxtransfersperns) {
   19666 		return ISC_R_QUOTA;
   19667 	}
   19668 
   19669 gotquota:
   19670 	/*
   19671 	 * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
   19672 	 * list and start the actual transfer asynchronously.
   19673 	 */
   19674 	LOCK_ZONE(zone);
   19675 	INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
   19676 	ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
   19677 	ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
   19678 	zone->statelist = &zmgr->xfrin_in_progress;
   19679 	isc_async_run(zone->loop, got_transfer_quota, zone);
   19680 	dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   19681 		      "Transfer started.");
   19682 	UNLOCK_ZONE(zone);
   19683 
   19684 	return ISC_R_SUCCESS;
   19685 }
   19686 
   19687 static void
   19688 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
   19689 	char *buf;
   19690 	int buflen;
   19691 	isc_result_t result;
   19692 
   19693 	buflen = strlen(path) + strlen(templat) + 2;
   19694 
   19695 	buf = isc_mem_get(zone->mctx, buflen);
   19696 
   19697 	result = isc_file_template(path, templat, buf, buflen);
   19698 	if (result != ISC_R_SUCCESS) {
   19699 		goto cleanup;
   19700 	}
   19701 
   19702 	result = isc_file_renameunique(path, buf);
   19703 	if (result != ISC_R_SUCCESS) {
   19704 		goto cleanup;
   19705 	}
   19706 
   19707 	dns_zone_log(zone, ISC_LOG_WARNING,
   19708 		     "unable to load from '%s'; "
   19709 		     "renaming file to '%s' for failure analysis and "
   19710 		     "retransferring.",
   19711 		     path, buf);
   19712 
   19713 cleanup:
   19714 	isc_mem_put(zone->mctx, buf, buflen);
   19715 }
   19716 
   19717 static void
   19718 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
   19719 	isc_interval_t interval;
   19720 	uint32_t s, ns;
   19721 	uint32_t pertic;
   19722 
   19723 	if (value == 0) {
   19724 		value = 1;
   19725 	}
   19726 
   19727 	if (value == 1) {
   19728 		s = 1;
   19729 		ns = 0;
   19730 		pertic = 1;
   19731 	} else if (value <= 10) {
   19732 		s = 0;
   19733 		ns = 1000000000 / value;
   19734 		pertic = 1;
   19735 	} else {
   19736 		s = 0;
   19737 		ns = (1000000000 / value) * 10;
   19738 		pertic = 10;
   19739 	}
   19740 
   19741 	isc_interval_set(&interval, s, ns);
   19742 
   19743 	isc_ratelimiter_setinterval(rl, &interval);
   19744 	isc_ratelimiter_setpertic(rl, pertic);
   19745 
   19746 	*rate = value;
   19747 }
   19748 
   19749 void
   19750 dns_zonemgr_setcheckdsrate(dns_zonemgr_t *zmgr, unsigned int value) {
   19751 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19752 
   19753 	setrl(zmgr->checkdsrl, &zmgr->checkdsrate, value);
   19754 }
   19755 
   19756 void
   19757 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
   19758 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19759 
   19760 	setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
   19761 }
   19762 
   19763 void
   19764 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
   19765 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19766 
   19767 	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
   19768 }
   19769 
   19770 void
   19771 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
   19772 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19773 
   19774 	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
   19775 	/* XXXMPA separate out once we have the code to support this. */
   19776 	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
   19777 }
   19778 
   19779 unsigned int
   19780 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
   19781 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19782 
   19783 	return zmgr->notifyrate;
   19784 }
   19785 
   19786 unsigned int
   19787 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
   19788 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19789 
   19790 	return zmgr->startupnotifyrate;
   19791 }
   19792 
   19793 unsigned int
   19794 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
   19795 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19796 
   19797 	return zmgr->serialqueryrate;
   19798 }
   19799 
   19800 bool
   19801 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
   19802 			isc_sockaddr_t *local, isc_time_t *now) {
   19803 	unsigned int i;
   19804 	uint32_t seconds = isc_time_seconds(now);
   19805 	uint32_t count = 0;
   19806 
   19807 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19808 
   19809 	RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
   19810 	for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
   19811 		if (atomic_load(&zmgr->unreachable[i].expire) >= seconds &&
   19812 		    isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
   19813 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
   19814 		{
   19815 			atomic_store_relaxed(&zmgr->unreachable[i].last,
   19816 					     seconds);
   19817 			count = zmgr->unreachable[i].count;
   19818 			break;
   19819 		}
   19820 	}
   19821 	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
   19822 	return i < UNREACH_CACHE_SIZE && count > 1U;
   19823 }
   19824 
   19825 void
   19826 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
   19827 			   isc_sockaddr_t *local) {
   19828 	unsigned int i;
   19829 
   19830 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19831 
   19832 	RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
   19833 	for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
   19834 		if (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].expire, 0);
   19838 			break;
   19839 		}
   19840 	}
   19841 	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
   19842 }
   19843 
   19844 void
   19845 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
   19846 			   isc_sockaddr_t *local, isc_time_t *now) {
   19847 	uint32_t seconds = isc_time_seconds(now);
   19848 	uint32_t expire = 0, last = seconds;
   19849 	unsigned int slot = UNREACH_CACHE_SIZE, oldest = 0;
   19850 	bool update_entry = true;
   19851 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   19852 
   19853 	RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
   19854 	for (unsigned int i = 0; i < UNREACH_CACHE_SIZE; i++) {
   19855 		/* Existing entry? */
   19856 		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
   19857 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
   19858 		{
   19859 			update_entry = false;
   19860 			slot = i;
   19861 			expire = atomic_load_relaxed(
   19862 				&zmgr->unreachable[i].expire);
   19863 			break;
   19864 		}
   19865 		/* Pick first empty slot? */
   19866 		if (atomic_load_relaxed(&zmgr->unreachable[i].expire) < seconds)
   19867 		{
   19868 			slot = i;
   19869 			break;
   19870 		}
   19871 		/* The worst case, least recently used slot? */
   19872 		if (atomic_load_relaxed(&zmgr->unreachable[i].last) < last) {
   19873 			last = atomic_load_relaxed(&zmgr->unreachable[i].last);
   19874 			oldest = i;
   19875 		}
   19876 	}
   19877 
   19878 	/* We haven't found any existing or free slots, use the oldest */
   19879 	if (slot == UNREACH_CACHE_SIZE) {
   19880 		slot = oldest;
   19881 	}
   19882 
   19883 	if (expire < seconds) {
   19884 		/* Expired or new entry, reset count to 1 */
   19885 		zmgr->unreachable[slot].count = 1;
   19886 	} else {
   19887 		zmgr->unreachable[slot].count++;
   19888 	}
   19889 	atomic_store_relaxed(&zmgr->unreachable[slot].expire,
   19890 			     seconds + UNREACH_HOLD_TIME);
   19891 	atomic_store_relaxed(&zmgr->unreachable[slot].last, seconds);
   19892 	if (update_entry) {
   19893 		zmgr->unreachable[slot].remote = *remote;
   19894 		zmgr->unreachable[slot].local = *local;
   19895 	}
   19896 
   19897 	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
   19898 }
   19899 
   19900 void
   19901 dns_zone_stopxfr(dns_zone_t *zone) {
   19902 	dns_xfrin_t *xfr = NULL;
   19903 
   19904 	REQUIRE(DNS_ZONE_VALID(zone));
   19905 
   19906 	RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
   19907 	LOCK_ZONE(zone);
   19908 	if (zone->statelist == &zone->zmgr->xfrin_in_progress &&
   19909 	    zone->xfr != NULL)
   19910 	{
   19911 		dns_xfrin_attach(zone->xfr, &xfr);
   19912 	}
   19913 	UNLOCK_ZONE(zone);
   19914 	RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
   19915 
   19916 	if (xfr != NULL) {
   19917 		dns_xfrin_shutdown(xfr);
   19918 		dns_xfrin_detach(&xfr);
   19919 	}
   19920 }
   19921 
   19922 void
   19923 dns_zone_forcexfr(dns_zone_t *zone) {
   19924 	REQUIRE(DNS_ZONE_VALID(zone));
   19925 
   19926 	if (zone->type == dns_zone_primary ||
   19927 	    (zone->type == dns_zone_redirect &&
   19928 	     dns_remote_addresses(&zone->primaries) == NULL))
   19929 	{
   19930 		return;
   19931 	}
   19932 
   19933 	LOCK_ZONE(zone);
   19934 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
   19935 	UNLOCK_ZONE(zone);
   19936 	dns_zone_refresh(zone);
   19937 }
   19938 
   19939 bool
   19940 dns_zone_isforced(dns_zone_t *zone) {
   19941 	REQUIRE(DNS_ZONE_VALID(zone));
   19942 
   19943 	return DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER);
   19944 }
   19945 
   19946 isc_result_t
   19947 dns_zone_setstatistics(dns_zone_t *zone, bool on) {
   19948 	/*
   19949 	 * This function is obsoleted.
   19950 	 */
   19951 	UNUSED(zone);
   19952 	UNUSED(on);
   19953 	return ISC_R_NOTIMPLEMENTED;
   19954 }
   19955 
   19956 uint64_t *
   19957 dns_zone_getstatscounters(dns_zone_t *zone) {
   19958 	/*
   19959 	 * This function is obsoleted.
   19960 	 */
   19961 	UNUSED(zone);
   19962 	return NULL;
   19963 }
   19964 
   19965 void
   19966 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
   19967 	REQUIRE(DNS_ZONE_VALID(zone));
   19968 	REQUIRE(zone->stats == NULL);
   19969 
   19970 	LOCK_ZONE(zone);
   19971 	zone->stats = NULL;
   19972 	isc_stats_attach(stats, &zone->stats);
   19973 	UNLOCK_ZONE(zone);
   19974 }
   19975 
   19976 void
   19977 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
   19978 	REQUIRE(DNS_ZONE_VALID(zone));
   19979 
   19980 	LOCK_ZONE(zone);
   19981 	if (zone->requeststats_on && stats == NULL) {
   19982 		zone->requeststats_on = false;
   19983 	} else if (!zone->requeststats_on && stats != NULL) {
   19984 		if (zone->requeststats == NULL) {
   19985 			isc_stats_attach(stats, &zone->requeststats);
   19986 		}
   19987 		zone->requeststats_on = true;
   19988 	}
   19989 	UNLOCK_ZONE(zone);
   19990 }
   19991 
   19992 void
   19993 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
   19994 	REQUIRE(DNS_ZONE_VALID(zone));
   19995 
   19996 	LOCK_ZONE(zone);
   19997 	if (zone->requeststats_on && stats != NULL) {
   19998 		if (zone->rcvquerystats == NULL) {
   19999 			dns_stats_attach(stats, &zone->rcvquerystats);
   20000 			zone->requeststats_on = true;
   20001 		}
   20002 	}
   20003 	UNLOCK_ZONE(zone);
   20004 }
   20005 
   20006 void
   20007 dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
   20008 	REQUIRE(DNS_ZONE_VALID(zone));
   20009 
   20010 	LOCK_ZONE(zone);
   20011 	if (stats != NULL && zone->dnssecsignstats == NULL) {
   20012 		dns_stats_attach(stats, &zone->dnssecsignstats);
   20013 	}
   20014 	UNLOCK_ZONE(zone);
   20015 }
   20016 
   20017 dns_stats_t *
   20018 dns_zone_getdnssecsignstats(dns_zone_t *zone) {
   20019 	REQUIRE(DNS_ZONE_VALID(zone));
   20020 
   20021 	return zone->dnssecsignstats;
   20022 }
   20023 
   20024 isc_stats_t *
   20025 dns_zone_getrequeststats(dns_zone_t *zone) {
   20026 	/*
   20027 	 * We don't lock zone for efficiency reason.  This is not catastrophic
   20028 	 * because requeststats must always be valid when requeststats_on is
   20029 	 * true.
   20030 	 * Some counters may be incremented while requeststats_on is becoming
   20031 	 * false, or some cannot be incremented just after the statistics are
   20032 	 * installed, but it shouldn't matter much in practice.
   20033 	 */
   20034 	if (zone->requeststats_on) {
   20035 		return zone->requeststats;
   20036 	} else {
   20037 		return NULL;
   20038 	}
   20039 }
   20040 
   20041 /*
   20042  * Return the received query stats bucket
   20043  * see note from dns_zone_getrequeststats()
   20044  */
   20045 dns_stats_t *
   20046 dns_zone_getrcvquerystats(dns_zone_t *zone) {
   20047 	if (zone->requeststats_on) {
   20048 		return zone->rcvquerystats;
   20049 	} else {
   20050 		return NULL;
   20051 	}
   20052 }
   20053 
   20054 void
   20055 dns_zone_dialup(dns_zone_t *zone) {
   20056 	REQUIRE(DNS_ZONE_VALID(zone));
   20057 
   20058 	zone_debuglog(zone, __func__, 3, "notify = %d, refresh = %d",
   20059 		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
   20060 		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
   20061 
   20062 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
   20063 		dns_zone_notify(zone, true);
   20064 	}
   20065 	if (zone->type != dns_zone_primary &&
   20066 	    dns_remote_addresses(&zone->primaries) != NULL &&
   20067 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
   20068 	{
   20069 		dns_zone_refresh(zone);
   20070 	}
   20071 }
   20072 
   20073 void
   20074 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
   20075 	REQUIRE(DNS_ZONE_VALID(zone));
   20076 
   20077 	LOCK_ZONE(zone);
   20078 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
   20079 				       DNS_ZONEFLG_DIALREFRESH |
   20080 				       DNS_ZONEFLG_NOREFRESH);
   20081 	switch (dialup) {
   20082 	case dns_dialuptype_no:
   20083 		break;
   20084 	case dns_dialuptype_yes:
   20085 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
   20086 					       DNS_ZONEFLG_DIALREFRESH |
   20087 					       DNS_ZONEFLG_NOREFRESH);
   20088 		break;
   20089 	case dns_dialuptype_notify:
   20090 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
   20091 		break;
   20092 	case dns_dialuptype_notifypassive:
   20093 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
   20094 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
   20095 		break;
   20096 	case dns_dialuptype_refresh:
   20097 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
   20098 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
   20099 		break;
   20100 	case dns_dialuptype_passive:
   20101 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
   20102 		break;
   20103 	default:
   20104 		UNREACHABLE();
   20105 	}
   20106 	UNLOCK_ZONE(zone);
   20107 }
   20108 
   20109 isc_result_t
   20110 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
   20111 	isc_result_t result = ISC_R_SUCCESS;
   20112 
   20113 	REQUIRE(DNS_ZONE_VALID(zone));
   20114 
   20115 	LOCK_ZONE(zone);
   20116 	result = dns_zone_setstring(zone, &zone->keydirectory, directory);
   20117 	UNLOCK_ZONE(zone);
   20118 
   20119 	return result;
   20120 }
   20121 
   20122 const char *
   20123 dns_zone_getkeydirectory(dns_zone_t *zone) {
   20124 	REQUIRE(DNS_ZONE_VALID(zone));
   20125 
   20126 	return zone->keydirectory;
   20127 }
   20128 
   20129 void
   20130 dns_zone_setkeystores(dns_zone_t *zone, dns_keystorelist_t *keystores) {
   20131 	REQUIRE(DNS_ZONE_VALID(zone));
   20132 
   20133 	LOCK_ZONE(zone);
   20134 	zone->keystores = keystores;
   20135 	UNLOCK_ZONE(zone);
   20136 }
   20137 
   20138 dns_keystorelist_t *
   20139 dns_zone_getkeystores(dns_zone_t *zone) {
   20140 	dns_keystorelist_t *ks = NULL;
   20141 
   20142 	REQUIRE(DNS_ZONE_VALID(zone));
   20143 
   20144 	LOCK_ZONE(zone);
   20145 	if (inline_raw(zone) && zone->secure != NULL) {
   20146 		ks = zone->secure->keystores;
   20147 	} else {
   20148 		ks = zone->keystores;
   20149 	}
   20150 	UNLOCK_ZONE(zone);
   20151 
   20152 	return ks;
   20153 }
   20154 
   20155 unsigned int
   20156 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, dns_zonestate_t state) {
   20157 	dns_zone_t *zone;
   20158 	unsigned int count = 0;
   20159 
   20160 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   20161 
   20162 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   20163 	switch (state) {
   20164 	case DNS_ZONESTATE_XFERRUNNING:
   20165 		for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
   20166 		     zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
   20167 		{
   20168 			count++;
   20169 		}
   20170 		break;
   20171 	case DNS_ZONESTATE_XFERDEFERRED:
   20172 		for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
   20173 		     zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
   20174 		{
   20175 			count++;
   20176 		}
   20177 		break;
   20178 	case DNS_ZONESTATE_XFERFIRSTREFRESH:
   20179 		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
   20180 		     zone = ISC_LIST_NEXT(zone, link))
   20181 		{
   20182 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIRSTREFRESH)) {
   20183 				count++;
   20184 			}
   20185 		}
   20186 		break;
   20187 	case DNS_ZONESTATE_SOAQUERY:
   20188 		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
   20189 		     zone = ISC_LIST_NEXT(zone, link))
   20190 		{
   20191 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
   20192 				count++;
   20193 			}
   20194 		}
   20195 		break;
   20196 	case DNS_ZONESTATE_ANY:
   20197 		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
   20198 		     zone = ISC_LIST_NEXT(zone, link))
   20199 		{
   20200 			dns_view_t *view = zone->view;
   20201 			if (view != NULL && strcmp(view->name, "_bind") == 0) {
   20202 				continue;
   20203 			}
   20204 			count++;
   20205 		}
   20206 		break;
   20207 	case DNS_ZONESTATE_AUTOMATIC:
   20208 		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
   20209 		     zone = ISC_LIST_NEXT(zone, link))
   20210 		{
   20211 			dns_view_t *view = zone->view;
   20212 			if (view != NULL && strcmp(view->name, "_bind") == 0) {
   20213 				continue;
   20214 			}
   20215 			if (zone->automatic) {
   20216 				count++;
   20217 			}
   20218 		}
   20219 		break;
   20220 	default:
   20221 		UNREACHABLE();
   20222 	}
   20223 
   20224 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   20225 
   20226 	return count;
   20227 }
   20228 
   20229 isc_result_t
   20230 dns_zone_getxfr(dns_zone_t *zone, dns_xfrin_t **xfrp, bool *is_firstrefresh,
   20231 		bool *is_running, bool *is_deferred, bool *is_presoa,
   20232 		bool *is_pending, bool *needs_refresh) {
   20233 	REQUIRE(DNS_ZONE_VALID(zone));
   20234 	REQUIRE(xfrp != NULL && *xfrp == NULL);
   20235 
   20236 	if (zone->zmgr == NULL) {
   20237 		return ISC_R_FAILURE;
   20238 	}
   20239 
   20240 	/* Reset. */
   20241 	*is_firstrefresh = false;
   20242 	*is_running = false;
   20243 	*is_deferred = false;
   20244 	*is_presoa = false;
   20245 	*is_pending = false;
   20246 	*needs_refresh = false;
   20247 
   20248 	RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
   20249 	LOCK_ZONE(zone);
   20250 	*is_firstrefresh = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIRSTREFRESH);
   20251 	if (zone->xfr != NULL) {
   20252 		dns_xfrin_attach(zone->xfr, xfrp);
   20253 	}
   20254 	if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
   20255 		*is_running = true;
   20256 		/*
   20257 		 * The NEEDREFRESH flag is set only when a notify was received
   20258 		 * while the current zone transfer is running.
   20259 		 */
   20260 		*needs_refresh = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   20261 	} else if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
   20262 		*is_deferred = true;
   20263 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
   20264 		if (zone->request != NULL) {
   20265 			*is_presoa = true;
   20266 		} else {
   20267 			*is_pending = true;
   20268 		}
   20269 	} else {
   20270 		/*
   20271 		 * No operation is ongoing or pending, just check if the zone
   20272 		 * needs a refresh by looking at the refresh and expire times.
   20273 		 */
   20274 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
   20275 		    (zone->type == dns_zone_secondary ||
   20276 		     zone->type == dns_zone_mirror ||
   20277 		     zone->type == dns_zone_stub))
   20278 		{
   20279 			isc_time_t now = isc_time_now();
   20280 			if (isc_time_compare(&now, &zone->refreshtime) >= 0 ||
   20281 			    isc_time_compare(&now, &zone->expiretime) >= 0)
   20282 			{
   20283 				*needs_refresh = true;
   20284 			}
   20285 		}
   20286 	}
   20287 	UNLOCK_ZONE(zone);
   20288 	RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
   20289 
   20290 	return ISC_R_SUCCESS;
   20291 }
   20292 
   20293 void
   20294 dns_zone_lock_keyfiles(dns_zone_t *zone) {
   20295 	REQUIRE(DNS_ZONE_VALID(zone));
   20296 
   20297 	if (zone->kasp == NULL) {
   20298 		/* No need to lock, nothing is writing key files. */
   20299 		return;
   20300 	}
   20301 
   20302 	REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
   20303 	isc_mutex_lock(&zone->kfio->lock);
   20304 }
   20305 
   20306 void
   20307 dns_zone_unlock_keyfiles(dns_zone_t *zone) {
   20308 	REQUIRE(DNS_ZONE_VALID(zone));
   20309 
   20310 	if (zone->kasp == NULL) {
   20311 		/* No need to lock, nothing is writing key files. */
   20312 		return;
   20313 	}
   20314 
   20315 	REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
   20316 	isc_mutex_unlock(&zone->kfio->lock);
   20317 }
   20318 
   20319 isc_result_t
   20320 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
   20321 		    dns_rdata_t *rdata) {
   20322 	bool ok = true;
   20323 	bool fail = false;
   20324 	char namebuf[DNS_NAME_FORMATSIZE];
   20325 	char namebuf2[DNS_NAME_FORMATSIZE];
   20326 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
   20327 	int level = ISC_LOG_WARNING;
   20328 	dns_name_t bad;
   20329 
   20330 	REQUIRE(DNS_ZONE_VALID(zone));
   20331 
   20332 	if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
   20333 	    rdata->type != dns_rdatatype_nsec3)
   20334 	{
   20335 		return ISC_R_SUCCESS;
   20336 	}
   20337 
   20338 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
   20339 	    rdata->type == dns_rdatatype_nsec3)
   20340 	{
   20341 		level = ISC_LOG_ERROR;
   20342 		fail = true;
   20343 	}
   20344 
   20345 	ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
   20346 	if (!ok) {
   20347 		dns_name_format(name, namebuf, sizeof(namebuf));
   20348 		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
   20349 		dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
   20350 			     isc_result_totext(DNS_R_BADOWNERNAME));
   20351 		if (fail) {
   20352 			return DNS_R_BADOWNERNAME;
   20353 		}
   20354 	}
   20355 
   20356 	dns_name_init(&bad, NULL);
   20357 	ok = dns_rdata_checknames(rdata, name, &bad);
   20358 	if (!ok) {
   20359 		dns_name_format(name, namebuf, sizeof(namebuf));
   20360 		dns_name_format(&bad, namebuf2, sizeof(namebuf2));
   20361 		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
   20362 		dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
   20363 			     namebuf2, isc_result_totext(DNS_R_BADNAME));
   20364 		if (fail) {
   20365 			return DNS_R_BADNAME;
   20366 		}
   20367 	}
   20368 
   20369 	return ISC_R_SUCCESS;
   20370 }
   20371 
   20372 void
   20373 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
   20374 	REQUIRE(DNS_ZONE_VALID(zone));
   20375 	zone->checkmx = checkmx;
   20376 }
   20377 
   20378 void
   20379 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
   20380 	REQUIRE(DNS_ZONE_VALID(zone));
   20381 	zone->checksrv = checksrv;
   20382 }
   20383 
   20384 void
   20385 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
   20386 	REQUIRE(DNS_ZONE_VALID(zone));
   20387 	zone->checkns = checkns;
   20388 }
   20389 
   20390 void
   20391 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
   20392 	REQUIRE(DNS_ZONE_VALID(zone));
   20393 
   20394 	LOCK_ZONE(zone);
   20395 	zone->isself = isself;
   20396 	zone->isselfarg = arg;
   20397 	UNLOCK_ZONE(zone);
   20398 }
   20399 
   20400 void
   20401 dns_zone_setnotifydefer(dns_zone_t *zone, uint32_t defer) {
   20402 	REQUIRE(DNS_ZONE_VALID(zone));
   20403 
   20404 	LOCK_ZONE(zone);
   20405 	zone->notifydefer = defer;
   20406 	UNLOCK_ZONE(zone);
   20407 }
   20408 
   20409 void
   20410 dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
   20411 	REQUIRE(DNS_ZONE_VALID(zone));
   20412 
   20413 	LOCK_ZONE(zone);
   20414 	zone->notifydelay = delay;
   20415 	UNLOCK_ZONE(zone);
   20416 }
   20417 
   20418 /*
   20419  * Called when a dynamic update for an NSEC3PARAM record is received.
   20420  *
   20421  * If set, transform the NSEC3 salt into human-readable form so that it can be
   20422  * logged.  Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
   20423  */
   20424 isc_result_t
   20425 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
   20426 	isc_result_t result;
   20427 	char salt[255 * 2 + 1];
   20428 
   20429 	REQUIRE(DNS_ZONE_VALID(zone));
   20430 
   20431 	result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
   20432 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   20433 	dnssec_log(zone, ISC_LOG_NOTICE,
   20434 		   "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
   20435 		   nsec3param->hash, nsec3param->iterations, salt);
   20436 	LOCK_ZONE(zone);
   20437 	result = zone_addnsec3chain(zone, nsec3param);
   20438 	UNLOCK_ZONE(zone);
   20439 
   20440 	return result;
   20441 }
   20442 
   20443 void
   20444 dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
   20445 	REQUIRE(DNS_ZONE_VALID(zone));
   20446 
   20447 	if (nodes == 0) {
   20448 		nodes = 1;
   20449 	}
   20450 	zone->nodes = nodes;
   20451 }
   20452 
   20453 void
   20454 dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
   20455 	REQUIRE(DNS_ZONE_VALID(zone));
   20456 
   20457 	/*
   20458 	 * We treat signatures as a signed value so explicitly
   20459 	 * limit its range here.
   20460 	 */
   20461 	if (signatures > INT32_MAX) {
   20462 		signatures = INT32_MAX;
   20463 	} else if (signatures == 0) {
   20464 		signatures = 1;
   20465 	}
   20466 	zone->signatures = signatures;
   20467 }
   20468 
   20469 uint32_t
   20470 dns_zone_getsignatures(dns_zone_t *zone) {
   20471 	REQUIRE(DNS_ZONE_VALID(zone));
   20472 	return zone->signatures;
   20473 }
   20474 
   20475 void
   20476 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
   20477 	REQUIRE(DNS_ZONE_VALID(zone));
   20478 	zone->privatetype = type;
   20479 }
   20480 
   20481 dns_rdatatype_t
   20482 dns_zone_getprivatetype(dns_zone_t *zone) {
   20483 	REQUIRE(DNS_ZONE_VALID(zone));
   20484 	return zone->privatetype;
   20485 }
   20486 
   20487 static isc_result_t
   20488 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
   20489 		 bool deleteit, bool fullsign) {
   20490 	dns_signing_t *signing;
   20491 	dns_signing_t *current;
   20492 	isc_result_t result = ISC_R_SUCCESS;
   20493 	isc_time_t now;
   20494 	dns_db_t *db = NULL;
   20495 
   20496 	signing = isc_mem_get(zone->mctx, sizeof *signing);
   20497 
   20498 	signing->magic = 0;
   20499 	signing->db = NULL;
   20500 	signing->dbiterator = NULL;
   20501 	signing->algorithm = algorithm;
   20502 	signing->keyid = keyid;
   20503 	signing->deleteit = deleteit;
   20504 	signing->fullsign = fullsign;
   20505 	signing->done = false;
   20506 
   20507 	now = isc_time_now();
   20508 
   20509 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   20510 	if (zone->db != NULL) {
   20511 		dns_db_attach(zone->db, &db);
   20512 	}
   20513 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   20514 
   20515 	if (db == NULL) {
   20516 		result = ISC_R_NOTFOUND;
   20517 		goto cleanup;
   20518 	}
   20519 
   20520 	dns_db_attach(db, &signing->db);
   20521 
   20522 	for (current = ISC_LIST_HEAD(zone->signing); current != NULL;
   20523 	     current = ISC_LIST_NEXT(current, link))
   20524 	{
   20525 		if (current->db == signing->db &&
   20526 		    current->algorithm == signing->algorithm &&
   20527 		    current->keyid == signing->keyid)
   20528 		{
   20529 			if (current->deleteit != signing->deleteit) {
   20530 				current->done = true;
   20531 			} else {
   20532 				goto cleanup;
   20533 			}
   20534 		}
   20535 	}
   20536 
   20537 	result = dns_db_createiterator(signing->db, 0, &signing->dbiterator);
   20538 
   20539 	if (result == ISC_R_SUCCESS) {
   20540 		result = dns_dbiterator_first(signing->dbiterator);
   20541 	}
   20542 	if (result == ISC_R_SUCCESS) {
   20543 		dns_dbiterator_pause(signing->dbiterator);
   20544 		ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
   20545 		signing = NULL;
   20546 		if (isc_time_isepoch(&zone->signingtime)) {
   20547 			zone->signingtime = now;
   20548 			if (zone->loop != NULL) {
   20549 				zone_settimer(zone, &now);
   20550 			}
   20551 		}
   20552 	}
   20553 
   20554 cleanup:
   20555 	if (signing != NULL) {
   20556 		if (signing->db != NULL) {
   20557 			dns_db_detach(&signing->db);
   20558 		}
   20559 		if (signing->dbiterator != NULL) {
   20560 			dns_dbiterator_destroy(&signing->dbiterator);
   20561 		}
   20562 		isc_mem_put(zone->mctx, signing, sizeof *signing);
   20563 	}
   20564 	if (db != NULL) {
   20565 		dns_db_detach(&db);
   20566 	}
   20567 	return result;
   20568 }
   20569 
   20570 /* Called once; *timep should be set to the current time. */
   20571 static isc_result_t
   20572 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
   20573 	isc_result_t result;
   20574 	isc_stdtime_t now, then = 0, event;
   20575 	int i;
   20576 
   20577 	now = *timep;
   20578 
   20579 	for (i = 0; i < DST_MAX_TIMES; i++) {
   20580 		result = dst_key_gettime(key, i, &event);
   20581 		if (result == ISC_R_SUCCESS && event > now &&
   20582 		    (then == 0 || event < then))
   20583 		{
   20584 			then = event;
   20585 		}
   20586 	}
   20587 
   20588 	if (then != 0) {
   20589 		*timep = then;
   20590 		return ISC_R_SUCCESS;
   20591 	}
   20592 
   20593 	return ISC_R_NOTFOUND;
   20594 }
   20595 
   20596 static isc_result_t
   20597 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
   20598 	  const dns_rdata_t *rdata, bool *flag) {
   20599 	dns_rdataset_t rdataset;
   20600 	dns_dbnode_t *node = NULL;
   20601 	isc_result_t result;
   20602 
   20603 	dns_rdataset_init(&rdataset);
   20604 	if (rdata->type == dns_rdatatype_nsec3) {
   20605 		CHECK(dns_db_findnsec3node(db, name, false, &node));
   20606 	} else {
   20607 		CHECK(dns_db_findnode(db, name, false, &node));
   20608 	}
   20609 	result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
   20610 				     (isc_stdtime_t)0, &rdataset, NULL);
   20611 	if (result == ISC_R_NOTFOUND) {
   20612 		*flag = false;
   20613 		result = ISC_R_SUCCESS;
   20614 		goto cleanup;
   20615 	}
   20616 
   20617 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   20618 	     result = dns_rdataset_next(&rdataset))
   20619 	{
   20620 		dns_rdata_t myrdata = DNS_RDATA_INIT;
   20621 		dns_rdataset_current(&rdataset, &myrdata);
   20622 		if (!dns_rdata_compare(&myrdata, rdata)) {
   20623 			break;
   20624 		}
   20625 	}
   20626 	dns_rdataset_disassociate(&rdataset);
   20627 	if (result == ISC_R_SUCCESS) {
   20628 		*flag = true;
   20629 	} else if (result == ISC_R_NOMORE) {
   20630 		*flag = false;
   20631 		result = ISC_R_SUCCESS;
   20632 	}
   20633 
   20634 cleanup:
   20635 	if (node != NULL) {
   20636 		dns_db_detachnode(db, &node);
   20637 	}
   20638 	return result;
   20639 }
   20640 
   20641 /*
   20642  * Add records to signal the state of signing or of key removal.
   20643  */
   20644 static isc_result_t
   20645 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
   20646 		    dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) {
   20647 	dns_difftuple_t *tuple = NULL, *newtuple = NULL, *next = NULL;
   20648 	dns_difftuple_t *addtuple = NULL, *deltuple = NULL;
   20649 	dns_rdata_dnskey_t dnskey;
   20650 	dns_rdata_t rdata = DNS_RDATA_INIT;
   20651 	bool flag;
   20652 	isc_region_t r;
   20653 	isc_result_t result = ISC_R_SUCCESS;
   20654 	uint16_t keyid;
   20655 	unsigned char buf[5];
   20656 	dns_name_t *name = dns_db_origin(db);
   20657 	dns_difftuplelist_t add = ISC_LIST_INITIALIZER;
   20658 	dns_difftuplelist_t del = ISC_LIST_INITIALIZER;
   20659 	dns_difftuplelist_t tuples = ISC_LIST_INITIALIZER;
   20660 
   20661 	/*
   20662 	 * Move non DNSKEY and not DNSSEC DNSKEY records to tuples
   20663 	 * and sort the remaining DNSKEY records to add and del.
   20664 	 */
   20665 	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
   20666 	     tuple = ISC_LIST_HEAD(diff->tuples))
   20667 	{
   20668 		if (tuple->rdata.type != dns_rdatatype_dnskey) {
   20669 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
   20670 			ISC_LIST_APPEND(tuples, tuple, link);
   20671 			continue;
   20672 		}
   20673 
   20674 		result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
   20675 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   20676 		if ((dnskey.flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
   20677 		{
   20678 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
   20679 			ISC_LIST_APPEND(tuples, tuple, link);
   20680 			continue;
   20681 		}
   20682 
   20683 		ISC_LIST_UNLINK(diff->tuples, tuple, link);
   20684 		switch (tuple->op) {
   20685 		case DNS_DIFFOP_DEL:
   20686 		case DNS_DIFFOP_DELRESIGN:
   20687 			ISC_LIST_APPEND(del, tuple, link);
   20688 			break;
   20689 		case DNS_DIFFOP_ADD:
   20690 		case DNS_DIFFOP_ADDRESIGN:
   20691 			ISC_LIST_APPEND(add, tuple, link);
   20692 			break;
   20693 		default:
   20694 			UNREACHABLE();
   20695 		}
   20696 	}
   20697 
   20698 	/*
   20699 	 * Put the tuples that don't need more processing back onto
   20700 	 * diff->tuples.
   20701 	 */
   20702 	ISC_LIST_APPENDLIST(diff->tuples, tuples, link);
   20703 
   20704 	/*
   20705 	 * Filter out DNSKEY TTL changes and put them back onto diff->tuples.
   20706 	 */
   20707 	for (deltuple = ISC_LIST_HEAD(del); deltuple != NULL; deltuple = next) {
   20708 		next = ISC_LIST_NEXT(deltuple, link);
   20709 		for (addtuple = ISC_LIST_HEAD(add); addtuple != NULL;
   20710 		     addtuple = ISC_LIST_NEXT(addtuple, link))
   20711 		{
   20712 			int n = dns_rdata_compare(&deltuple->rdata,
   20713 						  &addtuple->rdata);
   20714 			if (n == 0) {
   20715 				ISC_LIST_UNLINK(del, deltuple, link);
   20716 				ISC_LIST_APPEND(diff->tuples, deltuple, link);
   20717 				ISC_LIST_UNLINK(add, addtuple, link);
   20718 				ISC_LIST_APPEND(diff->tuples, addtuple, link);
   20719 				break;
   20720 			}
   20721 		}
   20722 	}
   20723 
   20724 	/*
   20725 	 * Combine any remaining DNSKEY changes together.
   20726 	 */
   20727 	ISC_LIST_APPENDLIST(tuples, add, link);
   20728 	ISC_LIST_APPENDLIST(tuples, del, link);
   20729 
   20730 	/*
   20731 	 * Add private records for keys that have been removed
   20732 	 * or added.
   20733 	 */
   20734 	for (tuple = ISC_LIST_HEAD(tuples); tuple != NULL;
   20735 	     tuple = ISC_LIST_NEXT(tuple, link))
   20736 	{
   20737 		dns_rdata_toregion(&tuple->rdata, &r);
   20738 
   20739 		keyid = dst_region_computeid(&r);
   20740 
   20741 		buf[0] = dnskey.algorithm;
   20742 		buf[1] = (keyid & 0xff00) >> 8;
   20743 		buf[2] = (keyid & 0xff);
   20744 		buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
   20745 		buf[4] = 0;
   20746 		rdata.data = buf;
   20747 		rdata.length = sizeof(buf);
   20748 		rdata.type = privatetype;
   20749 		rdata.rdclass = tuple->rdata.rdclass;
   20750 
   20751 		if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
   20752 			CHECK(rr_exists(db, ver, name, &rdata, &flag));
   20753 			if (flag) {
   20754 				continue;
   20755 			}
   20756 
   20757 			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
   20758 						   name, 0, &rdata, &newtuple));
   20759 			CHECK(do_one_tuple(&newtuple, db, ver, diff));
   20760 			INSIST(newtuple == NULL);
   20761 		}
   20762 
   20763 		/*
   20764 		 * Remove any record which says this operation has already
   20765 		 * completed.
   20766 		 */
   20767 		buf[4] = 1;
   20768 		CHECK(rr_exists(db, ver, name, &rdata, &flag));
   20769 		if (flag) {
   20770 			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
   20771 						   name, 0, &rdata, &newtuple));
   20772 			CHECK(do_one_tuple(&newtuple, db, ver, diff));
   20773 			INSIST(newtuple == NULL);
   20774 		}
   20775 	}
   20776 
   20777 cleanup:
   20778 	/*
   20779 	 * Put the DNSKEY changes we cared about back on diff->tuples.
   20780 	 */
   20781 	ISC_LIST_APPENDLIST(diff->tuples, tuples, link);
   20782 	INSIST(ISC_LIST_EMPTY(add));
   20783 	INSIST(ISC_LIST_EMPTY(del));
   20784 	INSIST(ISC_LIST_EMPTY(tuples));
   20785 	return result;
   20786 }
   20787 
   20788 /*
   20789  * See if dns__zone_updatesigs() will update signature for RRset 'rrtype' at
   20790  * the apex, and if not tickle them and cause to sign so that newly activated
   20791  * keys are used.
   20792  */
   20793 static isc_result_t
   20794 tickle_apex_rrset(dns_rdatatype_t rrtype, dns_zone_t *zone, dns_db_t *db,
   20795 		  dns_dbversion_t *ver, isc_stdtime_t now, dns_diff_t *diff,
   20796 		  dns__zonediff_t *zonediff, dst_key_t **keys,
   20797 		  unsigned int nkeys, isc_stdtime_t inception,
   20798 		  isc_stdtime_t keyexpire) {
   20799 	dns_difftuple_t *tuple;
   20800 	isc_result_t result;
   20801 
   20802 	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
   20803 	     tuple = ISC_LIST_NEXT(tuple, link))
   20804 	{
   20805 		if (tuple->rdata.type == rrtype &&
   20806 		    dns_name_equal(&tuple->name, &zone->origin))
   20807 		{
   20808 			break;
   20809 		}
   20810 	}
   20811 
   20812 	if (tuple == NULL) {
   20813 		result = del_sigs(zone, db, ver, &zone->origin, rrtype,
   20814 				  zonediff, keys, nkeys, now, false);
   20815 		if (result != ISC_R_SUCCESS) {
   20816 			dnssec_log(zone, ISC_LOG_ERROR,
   20817 				   "sign_apex:del_sigs -> %s",
   20818 				   isc_result_totext(result));
   20819 			return result;
   20820 		}
   20821 		result = add_sigs(db, ver, &zone->origin, zone, rrtype,
   20822 				  zonediff->diff, keys, nkeys, zone->mctx, now,
   20823 				  inception, keyexpire);
   20824 		if (result != ISC_R_SUCCESS) {
   20825 			dnssec_log(zone, ISC_LOG_ERROR,
   20826 				   "sign_apex:add_sigs -> %s",
   20827 				   isc_result_totext(result));
   20828 			return result;
   20829 		}
   20830 	}
   20831 
   20832 	return ISC_R_SUCCESS;
   20833 }
   20834 
   20835 static isc_result_t
   20836 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   20837 	  isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff) {
   20838 	isc_result_t result;
   20839 	isc_stdtime_t inception, soaexpire, keyexpire;
   20840 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   20841 	unsigned int nkeys = 0, i;
   20842 
   20843 	result = dns_zone_findkeys(zone, db, ver, now, zone->mctx,
   20844 				   DNS_MAXZONEKEYS, zone_keys, &nkeys);
   20845 	if (result != ISC_R_SUCCESS) {
   20846 		dnssec_log(zone, ISC_LOG_ERROR,
   20847 			   "sign_apex:dns_zone_findkeys -> %s",
   20848 			   isc_result_totext(result));
   20849 		return result;
   20850 	}
   20851 
   20852 	inception = now - 3600; /* Allow for clock skew. */
   20853 	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
   20854 
   20855 	keyexpire = dns_zone_getkeyvalidityinterval(zone);
   20856 	if (keyexpire == 0) {
   20857 		keyexpire = soaexpire - 1;
   20858 	} else {
   20859 		keyexpire += now;
   20860 	}
   20861 
   20862 	/*
   20863 	 * See if dns__zone_updatesigs() will update DNSKEY/CDS/CDNSKEY
   20864 	 * signature and if not cause them to sign so that newly activated
   20865 	 * keys are used.
   20866 	 */
   20867 	CHECK(tickle_apex_rrset(dns_rdatatype_dnskey, zone, db, ver, now, diff,
   20868 				zonediff, zone_keys, nkeys, inception,
   20869 				keyexpire));
   20870 	CHECK(tickle_apex_rrset(dns_rdatatype_cds, zone, db, ver, now, diff,
   20871 				zonediff, zone_keys, nkeys, inception,
   20872 				keyexpire));
   20873 	CHECK(tickle_apex_rrset(dns_rdatatype_cdnskey, zone, db, ver, now, diff,
   20874 				zonediff, zone_keys, nkeys, inception,
   20875 				keyexpire));
   20876 
   20877 	result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
   20878 				      inception, soaexpire, keyexpire, now,
   20879 				      zonediff);
   20880 	if (result != ISC_R_SUCCESS) {
   20881 		dnssec_log(zone, ISC_LOG_ERROR,
   20882 			   "sign_apex:dns__zone_updatesigs -> %s",
   20883 			   isc_result_totext(result));
   20884 	}
   20885 
   20886 cleanup:
   20887 	for (i = 0; i < nkeys; i++) {
   20888 		dst_key_free(&zone_keys[i]);
   20889 	}
   20890 	return result;
   20891 }
   20892 
   20893 static isc_result_t
   20894 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   20895 		 dns_diff_t *diff) {
   20896 	isc_result_t result;
   20897 	dns_dbnode_t *node = NULL;
   20898 	dns_rdataset_t rdataset;
   20899 
   20900 	dns_rdataset_init(&rdataset);
   20901 	CHECK(dns_db_getoriginnode(db, &node));
   20902 
   20903 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
   20904 				     dns_rdatatype_none, 0, &rdataset, NULL);
   20905 	if (dns_rdataset_isassociated(&rdataset)) {
   20906 		dns_rdataset_disassociate(&rdataset);
   20907 	}
   20908 	if (result != ISC_R_NOTFOUND) {
   20909 		goto cleanup;
   20910 	}
   20911 
   20912 	result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
   20913 
   20914 cleanup:
   20915 	if (node != NULL) {
   20916 		dns_db_detachnode(db, &node);
   20917 	}
   20918 	return result;
   20919 }
   20920 
   20921 /*
   20922  * Given an RRSIG rdataset and an algorithm, determine whether there
   20923  * are any signatures using that algorithm.
   20924  */
   20925 static bool
   20926 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
   20927 	dns_rdata_t rdata = DNS_RDATA_INIT;
   20928 	dns_rdata_rrsig_t rrsig;
   20929 	isc_result_t result;
   20930 
   20931 	REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
   20932 	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
   20933 		return false;
   20934 	}
   20935 
   20936 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   20937 	     result = dns_rdataset_next(rdataset))
   20938 	{
   20939 		dns_rdataset_current(rdataset, &rdata);
   20940 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   20941 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   20942 		dns_rdata_reset(&rdata);
   20943 		if (rrsig.algorithm == alg) {
   20944 			return true;
   20945 		}
   20946 	}
   20947 
   20948 	return false;
   20949 }
   20950 
   20951 static isc_result_t
   20952 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   20953 	   dns_diff_t *diff) {
   20954 	dns_name_t *origin;
   20955 	bool build_nsec3;
   20956 	isc_result_t result;
   20957 
   20958 	origin = dns_db_origin(db);
   20959 	CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
   20960 				 &build_nsec3));
   20961 	if (build_nsec3) {
   20962 		CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone_nsecttl(zone),
   20963 					   false, zone->privatetype, diff));
   20964 	}
   20965 	CHECK(updatesecure(db, ver, origin, zone_nsecttl(zone), true, diff));
   20966 
   20967 cleanup:
   20968 	return result;
   20969 }
   20970 
   20971 static void
   20972 dnssec_report(const char *format, ...) {
   20973 	va_list args;
   20974 	va_start(args, format);
   20975 	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
   20976 		       ISC_LOG_INFO, format, args);
   20977 	va_end(args);
   20978 }
   20979 
   20980 static void
   20981 checkds_destroy(dns_checkds_t *checkds, bool locked) {
   20982 	REQUIRE(DNS_CHECKDS_VALID(checkds));
   20983 
   20984 	dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
   20985 		     "checkds: destroy DS query");
   20986 
   20987 	if (checkds->zone != NULL) {
   20988 		if (!locked) {
   20989 			LOCK_ZONE(checkds->zone);
   20990 		}
   20991 		REQUIRE(LOCKED_ZONE(checkds->zone));
   20992 		if (ISC_LINK_LINKED(checkds, link)) {
   20993 			ISC_LIST_UNLINK(checkds->zone->checkds_requests,
   20994 					checkds, link);
   20995 		}
   20996 		if (!locked) {
   20997 			UNLOCK_ZONE(checkds->zone);
   20998 		}
   20999 		if (locked) {
   21000 			zone_idetach(&checkds->zone);
   21001 		} else {
   21002 			dns_zone_idetach(&checkds->zone);
   21003 		}
   21004 	}
   21005 	if (checkds->find != NULL) {
   21006 		dns_adb_destroyfind(&checkds->find);
   21007 	}
   21008 	if (checkds->request != NULL) {
   21009 		dns_request_destroy(&checkds->request);
   21010 	}
   21011 	if (dns_name_dynamic(&checkds->ns)) {
   21012 		dns_name_free(&checkds->ns, checkds->mctx);
   21013 	}
   21014 	if (checkds->key != NULL) {
   21015 		dns_tsigkey_detach(&checkds->key);
   21016 	}
   21017 	if (checkds->transport != NULL) {
   21018 		dns_transport_detach(&checkds->transport);
   21019 	}
   21020 	INSIST(checkds->rlevent == NULL);
   21021 	isc_mem_putanddetach(&checkds->mctx, checkds, sizeof(*checkds));
   21022 }
   21023 
   21024 static isc_result_t
   21025 make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
   21026 	    dns_rdata_t *target) {
   21027 	isc_result_t result;
   21028 	isc_buffer_t b;
   21029 	isc_region_t r;
   21030 
   21031 	isc_buffer_init(&b, buf, bufsize);
   21032 	result = dst_key_todns(key, &b);
   21033 	if (result != ISC_R_SUCCESS) {
   21034 		return result;
   21035 	}
   21036 
   21037 	dns_rdata_reset(target);
   21038 	isc_buffer_usedregion(&b, &r);
   21039 	dns_rdata_fromregion(target, dst_key_class(key), dns_rdatatype_dnskey,
   21040 			     &r);
   21041 	return ISC_R_SUCCESS;
   21042 }
   21043 
   21044 static bool
   21045 do_checkds(dns_zone_t *zone, dst_key_t *key, isc_stdtime_t now,
   21046 	   bool dspublish) {
   21047 	dns_kasp_t *kasp = zone->kasp;
   21048 	isc_result_t result;
   21049 	uint32_t count = 0;
   21050 	uint32_t num;
   21051 
   21052 	switch (zone->checkdstype) {
   21053 	case dns_checkdstype_yes:
   21054 		num = zone->parent_nscount;
   21055 		break;
   21056 	case dns_checkdstype_explicit:
   21057 		num = dns_remote_count(&zone->parentals);
   21058 		break;
   21059 	case dns_checkdstype_no:
   21060 	default:
   21061 		dns_zone_log(zone, ISC_LOG_WARNING,
   21062 			     "checkds: option is disabled");
   21063 		return false;
   21064 	}
   21065 
   21066 	if (dspublish) {
   21067 		(void)dst_key_getnum(key, DST_NUM_DSPUBCOUNT, &count);
   21068 		count += 1;
   21069 		dst_key_setnum(key, DST_NUM_DSPUBCOUNT, count);
   21070 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21071 			     "checkds: %u DS published "
   21072 			     "for key %u",
   21073 			     count, dst_key_id(key));
   21074 
   21075 		if (count != num) {
   21076 			return false;
   21077 		}
   21078 	} else {
   21079 		(void)dst_key_getnum(key, DST_NUM_DSDELCOUNT, &count);
   21080 		count += 1;
   21081 		dst_key_setnum(key, DST_NUM_DSDELCOUNT, count);
   21082 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21083 			     "checkds: %u DS withdrawn "
   21084 			     "for key %u",
   21085 			     count, dst_key_id(key));
   21086 
   21087 		if (count != num) {
   21088 			return false;
   21089 		}
   21090 	}
   21091 
   21092 	dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21093 		     "checkds: checkds %s for key "
   21094 		     "%u",
   21095 		     dspublish ? "published" : "withdrawn", dst_key_id(key));
   21096 
   21097 	dns_zone_lock_keyfiles(zone);
   21098 	result = dns_keymgr_checkds_id(kasp, &zone->checkds_ok, now, now,
   21099 				       dspublish, dst_key_id(key),
   21100 				       dst_key_alg(key));
   21101 	dns_zone_unlock_keyfiles(zone);
   21102 
   21103 	if (result != ISC_R_SUCCESS) {
   21104 		dns_zone_log(zone, ISC_LOG_WARNING,
   21105 			     "checkds: checkds for key %u failed: %s",
   21106 			     dst_key_id(key), isc_result_totext(result));
   21107 		return false;
   21108 	}
   21109 
   21110 	return true;
   21111 }
   21112 
   21113 static isc_result_t
   21114 validate_ds(dns_zone_t *zone, dns_message_t *message) {
   21115 	UNUSED(zone);
   21116 	UNUSED(message);
   21117 
   21118 	/* Get closest trust anchor */
   21119 
   21120 	/* Check that trust anchor is (grand)parent of zone. */
   21121 
   21122 	/* Find the DNSKEY signing the message. */
   21123 
   21124 	/* Check that DNSKEY is in chain of trust. */
   21125 
   21126 	/* Validate DS RRset. */
   21127 
   21128 	return ISC_R_SUCCESS;
   21129 }
   21130 
   21131 static void
   21132 checkds_done(void *arg) {
   21133 	dns_request_t *request = (dns_request_t *)arg;
   21134 	dns_checkds_t *checkds = dns_request_getarg(request);
   21135 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   21136 	char rcode[128];
   21137 	dns_zone_t *zone = NULL;
   21138 	dns_db_t *db = NULL;
   21139 	dns_dbversion_t *version = NULL;
   21140 	dns_dnsseckey_t *key = NULL;
   21141 	dns_dnsseckeylist_t keys;
   21142 	dns_kasp_t *kasp = NULL;
   21143 	dns_message_t *message = NULL;
   21144 	dns_rdataset_t *ds_rrset = NULL;
   21145 	isc_buffer_t buf;
   21146 	isc_result_t result;
   21147 	isc_stdtime_t now;
   21148 	isc_time_t timenow;
   21149 	bool rekey = false;
   21150 	bool empty = false;
   21151 
   21152 	REQUIRE(DNS_CHECKDS_VALID(checkds));
   21153 
   21154 	zone = checkds->zone;
   21155 
   21156 	ISC_LIST_INIT(keys);
   21157 
   21158 	kasp = zone->kasp;
   21159 	INSIST(kasp != NULL);
   21160 
   21161 	isc_buffer_init(&buf, rcode, sizeof(rcode));
   21162 	isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
   21163 
   21164 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "checkds: DS query to %s: done",
   21165 		     addrbuf);
   21166 
   21167 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
   21168 			   &message);
   21169 	INSIST(message != NULL);
   21170 
   21171 	CHECK(dns_request_getresult(request));
   21172 	CHECK(dns_request_getresponse(request, message,
   21173 				      DNS_MESSAGEPARSE_PRESERVEORDER));
   21174 	CHECK(dns_rcode_totext(message->rcode, &buf));
   21175 
   21176 	dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21177 		     "checkds: DS response from %s: %.*s", addrbuf,
   21178 		     (int)buf.used, rcode);
   21179 
   21180 	/* Validate response. */
   21181 	CHECK(validate_ds(zone, message));
   21182 
   21183 	/* Check RCODE. */
   21184 	if (message->rcode != dns_rcode_noerror) {
   21185 		dns_zone_log(zone, ISC_LOG_NOTICE,
   21186 			     "checkds: bad DS response from %s: %.*s", addrbuf,
   21187 			     (int)buf.used, rcode);
   21188 		goto cleanup;
   21189 	}
   21190 
   21191 	/* Make sure that either AA or RA bit is set. */
   21192 	if ((message->flags & DNS_MESSAGEFLAG_AA) == 0 &&
   21193 	    (message->flags & DNS_MESSAGEFLAG_RA) == 0)
   21194 	{
   21195 		dns_zone_log(zone, ISC_LOG_NOTICE,
   21196 			     "checkds: bad DS response from %s: expected AA or "
   21197 			     "RA bit set",
   21198 			     addrbuf);
   21199 		goto cleanup;
   21200 	}
   21201 
   21202 	/* Lookup DS RRset. */
   21203 	result = dns_message_firstname(message, DNS_SECTION_ANSWER);
   21204 	while (result == ISC_R_SUCCESS) {
   21205 		dns_name_t *name = NULL;
   21206 		dns_rdataset_t *rdataset;
   21207 
   21208 		dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
   21209 		if (dns_name_compare(&zone->origin, name) != 0) {
   21210 			goto next;
   21211 		}
   21212 
   21213 		for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
   21214 		     rdataset = ISC_LIST_NEXT(rdataset, link))
   21215 		{
   21216 			if (rdataset->type != dns_rdatatype_ds) {
   21217 				goto next;
   21218 			}
   21219 
   21220 			ds_rrset = rdataset;
   21221 			break;
   21222 		}
   21223 
   21224 		if (ds_rrset != NULL) {
   21225 			break;
   21226 		}
   21227 
   21228 	next:
   21229 		result = dns_message_nextname(message, DNS_SECTION_ANSWER);
   21230 	}
   21231 
   21232 	if (ds_rrset == NULL) {
   21233 		empty = true;
   21234 		dns_zone_log(zone, ISC_LOG_NOTICE,
   21235 			     "checkds: empty DS response from %s", addrbuf);
   21236 	}
   21237 
   21238 	timenow = isc_time_now();
   21239 	now = isc_time_seconds(&timenow);
   21240 
   21241 	CHECK(dns_zone_getdb(zone, &db));
   21242 	dns_db_currentversion(db, &version);
   21243 
   21244 	KASP_LOCK(kasp);
   21245 	LOCK_ZONE(zone);
   21246 	for (key = ISC_LIST_HEAD(zone->checkds_ok); key != NULL;
   21247 	     key = ISC_LIST_NEXT(key, link))
   21248 	{
   21249 		bool alldone = false, found = false;
   21250 		bool checkdspub = false, checkdsdel = false, ksk = false;
   21251 		dst_key_state_t ds_state = DST_KEY_STATE_NA;
   21252 		isc_stdtime_t published = 0, withdrawn = 0;
   21253 		isc_result_t ret = ISC_R_SUCCESS;
   21254 
   21255 		/* Is this key have the KSK role? */
   21256 		(void)dst_key_role(key->key, &ksk, NULL);
   21257 		if (!ksk) {
   21258 			continue;
   21259 		}
   21260 
   21261 		/* Do we need to check the DS RRset for this key? */
   21262 		(void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
   21263 		(void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
   21264 		(void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
   21265 
   21266 		if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
   21267 			checkdspub = true;
   21268 		} else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
   21269 			   withdrawn == 0)
   21270 		{
   21271 			checkdsdel = true;
   21272 		}
   21273 		if (!checkdspub && !checkdsdel) {
   21274 			continue;
   21275 		}
   21276 
   21277 		if (empty) {
   21278 			goto dswithdrawn;
   21279 		}
   21280 
   21281 		/* Find the appropriate DS record. */
   21282 		ret = dns_rdataset_first(ds_rrset);
   21283 		while (ret == ISC_R_SUCCESS) {
   21284 			dns_rdata_ds_t ds;
   21285 			dns_rdata_t dnskey = DNS_RDATA_INIT;
   21286 			dns_rdata_t dsrdata = DNS_RDATA_INIT;
   21287 			dns_rdata_t rdata = DNS_RDATA_INIT;
   21288 			isc_result_t r;
   21289 			unsigned char dsbuf[DNS_DS_BUFFERSIZE];
   21290 			unsigned char keybuf[DST_KEY_MAXSIZE];
   21291 
   21292 			dns_rdataset_current(ds_rrset, &rdata);
   21293 			r = dns_rdata_tostruct(&rdata, &ds, NULL);
   21294 			if (r != ISC_R_SUCCESS) {
   21295 				goto nextds;
   21296 			}
   21297 			/* Check key tag and algorithm. */
   21298 			if (dst_key_id(key->key) != ds.key_tag) {
   21299 				goto nextds;
   21300 			}
   21301 			if (dst_key_alg(key->key) != ds.algorithm) {
   21302 				goto nextds;
   21303 			}
   21304 			/* Derive DS from DNSKEY, see if the rdata is equal. */
   21305 			make_dnskey(key->key, keybuf, sizeof(keybuf), &dnskey);
   21306 			r = dns_ds_buildrdata(&zone->origin, &dnskey,
   21307 					      ds.digest_type, dsbuf, &dsrdata);
   21308 			if (r != ISC_R_SUCCESS) {
   21309 				goto nextds;
   21310 			}
   21311 			if (dns_rdata_compare(&rdata, &dsrdata) == 0) {
   21312 				found = true;
   21313 				if (checkdspub) {
   21314 					/* DS Published. */
   21315 					alldone = do_checkds(zone, key->key,
   21316 							     now, true);
   21317 					if (alldone) {
   21318 						rekey = true;
   21319 					}
   21320 				}
   21321 			}
   21322 
   21323 		nextds:
   21324 			ret = dns_rdataset_next(ds_rrset);
   21325 		}
   21326 
   21327 	dswithdrawn:
   21328 		/* DS withdrawn. */
   21329 		if (checkdsdel && !found) {
   21330 			alldone = do_checkds(zone, key->key, now, false);
   21331 			if (alldone) {
   21332 				rekey = true;
   21333 			}
   21334 		}
   21335 	}
   21336 	UNLOCK_ZONE(zone);
   21337 	KASP_UNLOCK(kasp);
   21338 
   21339 	/* Rekey after checkds. */
   21340 	if (rekey) {
   21341 		dns_zone_rekey(zone, false, false);
   21342 	}
   21343 
   21344 cleanup:
   21345 	if (result != ISC_R_SUCCESS) {
   21346 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21347 			     "checkds: DS request failed: %s",
   21348 			     isc_result_totext(result));
   21349 	}
   21350 
   21351 	if (version != NULL) {
   21352 		dns_db_closeversion(db, &version, false);
   21353 	}
   21354 	if (db != NULL) {
   21355 		dns_db_detach(&db);
   21356 	}
   21357 
   21358 	while (!ISC_LIST_EMPTY(keys)) {
   21359 		key = ISC_LIST_HEAD(keys);
   21360 		ISC_LIST_UNLINK(keys, key, link);
   21361 		dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
   21362 	}
   21363 
   21364 	checkds_destroy(checkds, false);
   21365 	dns_message_detach(&message);
   21366 }
   21367 
   21368 static bool
   21369 checkds_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr,
   21370 		 dns_tsigkey_t *key, dns_transport_t *transport) {
   21371 	dns_checkds_t *checkds;
   21372 
   21373 	for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
   21374 	     checkds = ISC_LIST_NEXT(checkds, link))
   21375 	{
   21376 		if (checkds->request != NULL) {
   21377 			continue;
   21378 		}
   21379 		if (name != NULL && dns_name_equal(name, &checkds->ns)) {
   21380 			return true;
   21381 		}
   21382 		if (addr != NULL && isc_sockaddr_equal(addr, &checkds->dst) &&
   21383 		    checkds->key == key && checkds->transport == transport)
   21384 		{
   21385 			return true;
   21386 		}
   21387 	}
   21388 	return false;
   21389 }
   21390 
   21391 static isc_result_t
   21392 checkds_create(isc_mem_t *mctx, unsigned int flags, dns_checkds_t **checkdsp) {
   21393 	dns_checkds_t *checkds;
   21394 
   21395 	REQUIRE(checkdsp != NULL && *checkdsp == NULL);
   21396 
   21397 	checkds = isc_mem_get(mctx, sizeof(*checkds));
   21398 	*checkds = (dns_checkds_t){
   21399 		.flags = flags,
   21400 	};
   21401 
   21402 	isc_mem_attach(mctx, &checkds->mctx);
   21403 	isc_sockaddr_any(&checkds->dst);
   21404 	dns_name_init(&checkds->ns, NULL);
   21405 	ISC_LINK_INIT(checkds, link);
   21406 	checkds->magic = CHECKDS_MAGIC;
   21407 	*checkdsp = checkds;
   21408 	return ISC_R_SUCCESS;
   21409 }
   21410 
   21411 static void
   21412 checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep) {
   21413 	dns_message_t *message = NULL;
   21414 
   21415 	dns_name_t *tempname = NULL;
   21416 	dns_rdataset_t *temprdataset = NULL;
   21417 
   21418 	REQUIRE(DNS_ZONE_VALID(zone));
   21419 	REQUIRE(messagep != NULL && *messagep == NULL);
   21420 
   21421 	dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER,
   21422 			   &message);
   21423 
   21424 	message->opcode = dns_opcode_query;
   21425 	message->rdclass = zone->rdclass;
   21426 	message->flags |= DNS_MESSAGEFLAG_RD;
   21427 
   21428 	dns_message_gettempname(message, &tempname);
   21429 
   21430 	dns_message_gettemprdataset(message, &temprdataset);
   21431 
   21432 	/*
   21433 	 * Make question.
   21434 	 */
   21435 	dns_name_init(tempname, NULL);
   21436 	dns_name_clone(&zone->origin, tempname);
   21437 	dns_rdataset_makequestion(temprdataset, zone->rdclass,
   21438 				  dns_rdatatype_ds);
   21439 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
   21440 	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
   21441 	tempname = NULL;
   21442 	temprdataset = NULL;
   21443 
   21444 	*messagep = message;
   21445 }
   21446 
   21447 /*
   21448  * XXXAG should check for DNS_ZONEFLG_EXITING
   21449  */
   21450 static void
   21451 process_checkds_adb_event(void *arg) {
   21452 	dns_adbfind_t *find = (dns_adbfind_t *)arg;
   21453 	dns_checkds_t *checkds = (dns_checkds_t *)find->cbarg;
   21454 	dns_adbstatus_t astat = find->status;
   21455 
   21456 	REQUIRE(DNS_CHECKDS_VALID(checkds));
   21457 	REQUIRE(find == checkds->find);
   21458 
   21459 	switch (astat) {
   21460 	case DNS_ADB_MOREADDRESSES:
   21461 		dns_adb_destroyfind(&checkds->find);
   21462 		checkds_find_address(checkds);
   21463 		return;
   21464 
   21465 	case DNS_ADB_NOMOREADDRESSES:
   21466 		LOCK_ZONE(checkds->zone);
   21467 		checkds_send_tons(checkds);
   21468 		UNLOCK_ZONE(checkds->zone);
   21469 		break;
   21470 
   21471 	default:
   21472 		break;
   21473 	}
   21474 
   21475 	checkds_destroy(checkds, false);
   21476 }
   21477 
   21478 static void
   21479 checkds_find_address(dns_checkds_t *checkds) {
   21480 	isc_result_t result;
   21481 	unsigned int options;
   21482 	dns_adb_t *adb = NULL;
   21483 
   21484 	REQUIRE(DNS_CHECKDS_VALID(checkds));
   21485 
   21486 	options = DNS_ADBFIND_WANTEVENT;
   21487 	if (isc_net_probeipv4() != ISC_R_DISABLED) {
   21488 		options |= DNS_ADBFIND_INET;
   21489 	}
   21490 	if (isc_net_probeipv6() != ISC_R_DISABLED) {
   21491 		options |= DNS_ADBFIND_INET6;
   21492 	}
   21493 
   21494 	dns_view_getadb(checkds->zone->view, &adb);
   21495 	if (adb == NULL) {
   21496 		goto destroy;
   21497 	}
   21498 
   21499 	result = dns_adb_createfind(adb, checkds->zone->loop,
   21500 				    process_checkds_adb_event, checkds,
   21501 				    &checkds->ns, dns_rootname, 0, options, 0,
   21502 				    NULL, checkds->zone->view->dstport, 0, NULL,
   21503 				    NULL, NULL, &checkds->find);
   21504 	dns_adb_detach(&adb);
   21505 
   21506 	/* Something failed? */
   21507 	if (result != ISC_R_SUCCESS) {
   21508 		goto destroy;
   21509 	}
   21510 
   21511 	/* More addresses pending? */
   21512 	if ((checkds->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
   21513 		return;
   21514 	}
   21515 
   21516 	/* We have as many addresses as we can get. */
   21517 	LOCK_ZONE(checkds->zone);
   21518 	checkds_send_tons(checkds);
   21519 	UNLOCK_ZONE(checkds->zone);
   21520 
   21521 destroy:
   21522 	checkds_destroy(checkds, false);
   21523 }
   21524 
   21525 static void
   21526 checkds_send_toaddr(void *arg) {
   21527 	dns_checkds_t *checkds = (dns_checkds_t *)arg;
   21528 	isc_result_t result;
   21529 	dns_message_t *message = NULL;
   21530 	isc_netaddr_t dstip;
   21531 	dns_tsigkey_t *key = NULL;
   21532 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   21533 	isc_sockaddr_t src;
   21534 	unsigned int options, timeout;
   21535 	bool have_checkdssource = false;
   21536 	bool canceled = checkds->rlevent->canceled;
   21537 
   21538 	REQUIRE(DNS_CHECKDS_VALID(checkds));
   21539 
   21540 	isc_rlevent_free(&checkds->rlevent);
   21541 
   21542 	LOCK_ZONE(checkds->zone);
   21543 
   21544 	if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_LOADED) == 0 || canceled ||
   21545 	    DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_EXITING) ||
   21546 	    checkds->zone->view->requestmgr == NULL ||
   21547 	    checkds->zone->db == NULL)
   21548 	{
   21549 		result = ISC_R_CANCELED;
   21550 		goto cleanup;
   21551 	}
   21552 
   21553 	/*
   21554 	 * The raw IPv4 address should also exist.  Don't send to the
   21555 	 * mapped form.
   21556 	 */
   21557 	if (isc_sockaddr_pf(&checkds->dst) == PF_INET6 &&
   21558 	    IN6_IS_ADDR_V4MAPPED(&checkds->dst.type.sin6.sin6_addr))
   21559 	{
   21560 		isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
   21561 		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
   21562 			     "checkds: ignoring IPv6 mapped IPV4 address: %s",
   21563 			     addrbuf);
   21564 		result = ISC_R_CANCELED;
   21565 		goto cleanup;
   21566 	}
   21567 
   21568 	checkds_createmessage(checkds->zone, &message);
   21569 
   21570 	isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
   21571 	if (checkds->key != NULL) {
   21572 		/* Transfer ownership of key */
   21573 		key = checkds->key;
   21574 		checkds->key = NULL;
   21575 	} else {
   21576 		isc_netaddr_fromsockaddr(&dstip, &checkds->dst);
   21577 		result = dns_view_getpeertsig(checkds->zone->view, &dstip,
   21578 					      &key);
   21579 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   21580 			dns_zone_log(checkds->zone, ISC_LOG_ERROR,
   21581 				     "checkds: DS query to %s not sent. "
   21582 				     "Peer TSIG key lookup failure.",
   21583 				     addrbuf);
   21584 			goto cleanup_message;
   21585 		}
   21586 	}
   21587 
   21588 	if (key != NULL) {
   21589 		char namebuf[DNS_NAME_FORMATSIZE];
   21590 
   21591 		dns_name_format(key->name, namebuf, sizeof(namebuf));
   21592 		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
   21593 			     "checkds: sending DS query to %s : TSIG (%s)",
   21594 			     addrbuf, namebuf);
   21595 	} else {
   21596 		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
   21597 			     "checkds: sending DS query to %s", addrbuf);
   21598 	}
   21599 	options = 0;
   21600 	if (checkds->zone->view->peers != NULL) {
   21601 		dns_peer_t *peer = NULL;
   21602 		bool usetcp = false;
   21603 		result = dns_peerlist_peerbyaddr(checkds->zone->view->peers,
   21604 						 &dstip, &peer);
   21605 		if (result == ISC_R_SUCCESS) {
   21606 			result = dns_peer_getquerysource(peer, &src);
   21607 			if (result == ISC_R_SUCCESS) {
   21608 				have_checkdssource = true;
   21609 			}
   21610 			result = dns_peer_getforcetcp(peer, &usetcp);
   21611 			if (result == ISC_R_SUCCESS && usetcp) {
   21612 				options |= DNS_FETCHOPT_TCP;
   21613 			}
   21614 		}
   21615 	}
   21616 	switch (isc_sockaddr_pf(&checkds->dst)) {
   21617 	case PF_INET:
   21618 		if (!have_checkdssource) {
   21619 			isc_sockaddr_t any;
   21620 			isc_sockaddr_any(&any);
   21621 
   21622 			src = checkds->src;
   21623 			if (isc_sockaddr_equal(&src, &any)) {
   21624 				src = checkds->zone->parentalsrc4;
   21625 			}
   21626 		}
   21627 		break;
   21628 	case PF_INET6:
   21629 		if (!have_checkdssource) {
   21630 			isc_sockaddr_t any;
   21631 			isc_sockaddr_any6(&any);
   21632 
   21633 			src = checkds->src;
   21634 			if (isc_sockaddr_equal(&src, &any)) {
   21635 				src = checkds->zone->parentalsrc6;
   21636 			}
   21637 		}
   21638 		break;
   21639 	default:
   21640 		result = ISC_R_NOTIMPLEMENTED;
   21641 		goto cleanup_key;
   21642 	}
   21643 
   21644 	dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
   21645 		     "checkds: create request for DS query to %s", addrbuf);
   21646 
   21647 	timeout = 5;
   21648 	options |= DNS_REQUESTOPT_TCP;
   21649 	result = dns_request_create(
   21650 		checkds->zone->view->requestmgr, message, &src, &checkds->dst,
   21651 		NULL, NULL, options, key, timeout * 3 + 1, timeout, 2,
   21652 		checkds->zone->loop, checkds_done, checkds, &checkds->request);
   21653 	if (result != ISC_R_SUCCESS) {
   21654 		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
   21655 			     "checkds: dns_request_create() to %s failed: %s",
   21656 			     addrbuf, isc_result_totext(result));
   21657 	}
   21658 
   21659 cleanup_key:
   21660 	if (key != NULL) {
   21661 		dns_tsigkey_detach(&key);
   21662 	}
   21663 cleanup_message:
   21664 	dns_message_detach(&message);
   21665 cleanup:
   21666 	UNLOCK_ZONE(checkds->zone);
   21667 	if (result != ISC_R_SUCCESS) {
   21668 		checkds_destroy(checkds, false);
   21669 	}
   21670 }
   21671 
   21672 static void
   21673 checkds_send_tons(dns_checkds_t *checkds) {
   21674 	dns_adbaddrinfo_t *ai;
   21675 	isc_sockaddr_t dst;
   21676 	isc_result_t result;
   21677 	dns_checkds_t *newcheckds = NULL;
   21678 	dns_zone_t *zone = NULL;
   21679 
   21680 	/*
   21681 	 * Zone lock held by caller.
   21682 	 */
   21683 	REQUIRE(DNS_CHECKDS_VALID(checkds));
   21684 	REQUIRE(LOCKED_ZONE(checkds->zone));
   21685 
   21686 	zone = checkds->zone;
   21687 
   21688 	if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_EXITING)) {
   21689 		return;
   21690 	}
   21691 
   21692 	for (ai = ISC_LIST_HEAD(checkds->find->list); ai != NULL;
   21693 	     ai = ISC_LIST_NEXT(ai, publink))
   21694 	{
   21695 		dst = ai->sockaddr;
   21696 		if (checkds_isqueued(zone, NULL, &dst, NULL, NULL)) {
   21697 			continue;
   21698 		}
   21699 
   21700 		newcheckds = NULL;
   21701 		result = checkds_create(checkds->mctx, 0, &newcheckds);
   21702 		if (result != ISC_R_SUCCESS) {
   21703 			goto cleanup;
   21704 		}
   21705 		zone_iattach(zone, &newcheckds->zone);
   21706 		ISC_LIST_APPEND(newcheckds->zone->checkds_requests, newcheckds,
   21707 				link);
   21708 		newcheckds->dst = dst;
   21709 		dns_name_dup(&checkds->ns, checkds->mctx, &newcheckds->ns);
   21710 		switch (isc_sockaddr_pf(&newcheckds->dst)) {
   21711 		case PF_INET:
   21712 			isc_sockaddr_any(&newcheckds->src);
   21713 			break;
   21714 		case PF_INET6:
   21715 			isc_sockaddr_any6(&newcheckds->src);
   21716 			break;
   21717 		default:
   21718 			UNREACHABLE();
   21719 		}
   21720 		/*
   21721 		 * XXXWMM: Should we attach key and transport here?
   21722 		 * Probably not, because we expect the name servers to be
   21723 		 * publicly available on the default transport protocol.
   21724 		 */
   21725 
   21726 		result = isc_ratelimiter_enqueue(
   21727 			newcheckds->zone->zmgr->checkdsrl,
   21728 			newcheckds->zone->loop, checkds_send_toaddr, newcheckds,
   21729 			&newcheckds->rlevent);
   21730 		if (result != ISC_R_SUCCESS) {
   21731 			goto cleanup;
   21732 		}
   21733 		newcheckds = NULL;
   21734 	}
   21735 
   21736 cleanup:
   21737 	if (newcheckds != NULL) {
   21738 		checkds_destroy(newcheckds, true);
   21739 	}
   21740 }
   21741 
   21742 static void
   21743 checkds_send(dns_zone_t *zone) {
   21744 	dns_view_t *view = dns_zone_getview(zone);
   21745 	isc_result_t result;
   21746 	unsigned int flags = 0;
   21747 	unsigned int i = 0;
   21748 
   21749 	/*
   21750 	 * Zone lock held by caller.
   21751 	 */
   21752 	REQUIRE(LOCKED_ZONE(zone));
   21753 
   21754 	dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21755 		     "checkds: start sending DS queries to %u parentals",
   21756 		     dns_remote_count(&zone->parentals));
   21757 
   21758 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   21759 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21760 			     "checkds: abort, named exiting");
   21761 		return;
   21762 	}
   21763 
   21764 	dns_remote_reset(&zone->parentals, false);
   21765 	while (!dns_remote_done(&zone->parentals)) {
   21766 		dns_tsigkey_t *key = NULL;
   21767 		dns_transport_t *transport = NULL;
   21768 		isc_sockaddr_t src, dst;
   21769 		dns_checkds_t *checkds = NULL;
   21770 
   21771 		i++;
   21772 
   21773 		if (dns_remote_keyname(&zone->parentals) != NULL) {
   21774 			dns_name_t *keyname =
   21775 				dns_remote_keyname(&zone->parentals);
   21776 			(void)dns_view_gettsig(view, keyname, &key);
   21777 		}
   21778 
   21779 		if (dns_remote_tlsname(&zone->parentals) != NULL) {
   21780 			dns_name_t *tlsname =
   21781 				dns_remote_tlsname(&zone->parentals);
   21782 			(void)dns_view_gettransport(view, DNS_TRANSPORT_TLS,
   21783 						    tlsname, &transport);
   21784 			dns_zone_logc(
   21785 				zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   21786 				"got TLS configuration for zone transfer");
   21787 		}
   21788 
   21789 		dst = dns_remote_curraddr(&zone->parentals);
   21790 		src = dns_remote_sourceaddr(&zone->parentals);
   21791 		INSIST(isc_sockaddr_pf(&src) == isc_sockaddr_pf(&dst));
   21792 
   21793 		if (isc_sockaddr_disabled(&dst)) {
   21794 			goto next;
   21795 		}
   21796 
   21797 		/* TODO: glue the transport to the checkds request */
   21798 
   21799 		if (checkds_isqueued(zone, NULL, &dst, key, transport)) {
   21800 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21801 				     "checkds: DS query to parent "
   21802 				     "%d is queued",
   21803 				     i);
   21804 			if (key != NULL) {
   21805 				dns_tsigkey_detach(&key);
   21806 			}
   21807 			if (transport != NULL) {
   21808 				dns_transport_detach(&transport);
   21809 			}
   21810 			goto next;
   21811 		}
   21812 
   21813 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21814 			     "checkds: create DS query for "
   21815 			     "parent %d",
   21816 			     i);
   21817 
   21818 		result = checkds_create(zone->mctx, flags, &checkds);
   21819 		if (result != ISC_R_SUCCESS) {
   21820 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21821 				     "checkds: create DS query for "
   21822 				     "parent %d failed",
   21823 				     i);
   21824 			goto next;
   21825 		}
   21826 		zone_iattach(zone, &checkds->zone);
   21827 		dns_name_dup(dns_rootname, checkds->mctx, &checkds->ns);
   21828 		checkds->src = src;
   21829 		checkds->dst = dst;
   21830 
   21831 		INSIST(checkds->key == NULL);
   21832 		if (key != NULL) {
   21833 			checkds->key = key;
   21834 			key = NULL;
   21835 		}
   21836 
   21837 		INSIST(checkds->transport == NULL);
   21838 		if (transport != NULL) {
   21839 			checkds->transport = transport;
   21840 			transport = NULL;
   21841 		}
   21842 
   21843 		ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
   21844 		result = isc_ratelimiter_enqueue(
   21845 			checkds->zone->zmgr->checkdsrl, checkds->zone->loop,
   21846 			checkds_send_toaddr, checkds, &checkds->rlevent);
   21847 		if (result != ISC_R_SUCCESS) {
   21848 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21849 				     "checkds: send DS query to "
   21850 				     "parent %d failed",
   21851 				     i);
   21852 			checkds_destroy(checkds, true);
   21853 		}
   21854 
   21855 	next:
   21856 		dns_remote_next(&zone->parentals, false);
   21857 	}
   21858 }
   21859 
   21860 /*
   21861  * An NS RRset has been fetched from the parent of a zone whose DS RRset needs
   21862  * to be checked; scan the RRset and start sending queries to the parental
   21863  * agents.
   21864  */
   21865 static void
   21866 nsfetch_done(void *arg) {
   21867 	dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
   21868 	isc_result_t result, eresult;
   21869 	dns_nsfetch_t *nsfetch = NULL;
   21870 	dns_zone_t *zone = NULL;
   21871 	isc_mem_t *mctx = NULL;
   21872 	dns_name_t *zname = NULL;
   21873 	dns_name_t *pname = NULL;
   21874 	char pnamebuf[DNS_NAME_FORMATSIZE];
   21875 	bool free_needed, levelup = false;
   21876 	dns_rdataset_t *nsrrset = NULL;
   21877 	dns_rdataset_t *nssigset = NULL;
   21878 
   21879 	INSIST(resp != NULL);
   21880 
   21881 	nsfetch = resp->arg;
   21882 
   21883 	INSIST(nsfetch != NULL);
   21884 
   21885 	zone = nsfetch->zone;
   21886 	mctx = nsfetch->mctx;
   21887 	zname = dns_fixedname_name(&nsfetch->name);
   21888 	pname = &nsfetch->pname;
   21889 	nsrrset = &nsfetch->nsrrset;
   21890 	nssigset = &nsfetch->nssigset;
   21891 	eresult = resp->result;
   21892 
   21893 	/* Free resources which are not of interest */
   21894 	if (resp->node != NULL) {
   21895 		dns_db_detachnode(resp->db, &resp->node);
   21896 	}
   21897 	if (resp->db != NULL) {
   21898 		dns_db_detach(&resp->db);
   21899 	}
   21900 	dns_resolver_destroyfetch(&nsfetch->fetch);
   21901 
   21902 	LOCK_ZONE(zone);
   21903 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
   21904 		goto cleanup;
   21905 	}
   21906 
   21907 	zone->nsfetchcount--;
   21908 
   21909 	dns_name_format(pname, pnamebuf, sizeof(pnamebuf));
   21910 	dnssec_log(zone, ISC_LOG_DEBUG(3),
   21911 		   "Returned from '%s' NS fetch in nsfetch_done(): %s",
   21912 		   pnamebuf, isc_result_totext(eresult));
   21913 
   21914 	if (eresult == DNS_R_NCACHENXRRSET || eresult == DNS_R_NXRRSET) {
   21915 		dnssec_log(zone, ISC_LOG_DEBUG(3),
   21916 			   "NODATA response for NS '%s', level up", pnamebuf);
   21917 		levelup = true;
   21918 		goto cleanup;
   21919 
   21920 	} else if (eresult != ISC_R_SUCCESS) {
   21921 		dnssec_log(zone, ISC_LOG_WARNING,
   21922 			   "Unable to fetch NS set '%s': %s", pnamebuf,
   21923 			   isc_result_totext(eresult));
   21924 		result = eresult;
   21925 		goto done;
   21926 	}
   21927 
   21928 	/* No NS records found */
   21929 	if (!dns_rdataset_isassociated(nsrrset)) {
   21930 		dnssec_log(zone, ISC_LOG_WARNING,
   21931 			   "No NS records found for '%s'", pnamebuf);
   21932 		result = ISC_R_NOTFOUND;
   21933 		goto done;
   21934 	}
   21935 
   21936 	/* No RRSIGs found */
   21937 	if (!dns_rdataset_isassociated(nssigset)) {
   21938 		dnssec_log(zone, ISC_LOG_WARNING, "No NS RRSIGs found for '%s'",
   21939 			   pnamebuf);
   21940 		result = DNS_R_MUSTBESECURE;
   21941 		goto done;
   21942 	}
   21943 
   21944 	/* Check trust level */
   21945 	if (nsrrset->trust < dns_trust_secure) {
   21946 		dnssec_log(zone, ISC_LOG_WARNING,
   21947 			   "Invalid NS RRset for '%s' trust level %u", pnamebuf,
   21948 			   nsrrset->trust);
   21949 		result = DNS_R_MUSTBESECURE;
   21950 		goto done;
   21951 	}
   21952 
   21953 	/* Record the number of NS records we found. */
   21954 	zone->parent_nscount = dns_rdataset_count(nsrrset);
   21955 
   21956 	UNLOCK_ZONE(zone);
   21957 
   21958 	/* Look up the addresses for the found parental name servers. */
   21959 	for (result = dns_rdataset_first(nsrrset); result == ISC_R_SUCCESS;
   21960 	     result = dns_rdataset_next(nsrrset))
   21961 	{
   21962 		dns_checkds_t *checkds = NULL;
   21963 		dns_rdata_t rdata = DNS_RDATA_INIT;
   21964 		dns_rdata_ns_t ns;
   21965 		bool isqueued;
   21966 
   21967 		dns_rdataset_current(nsrrset, &rdata);
   21968 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
   21969 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   21970 
   21971 		dns_rdata_reset(&rdata);
   21972 
   21973 		LOCK_ZONE(zone);
   21974 		isqueued = checkds_isqueued(zone, &ns.name, NULL, NULL, NULL);
   21975 		UNLOCK_ZONE(zone);
   21976 		if (isqueued) {
   21977 			continue;
   21978 		}
   21979 		result = checkds_create(zone->mctx, 0, &checkds);
   21980 		if (result != ISC_R_SUCCESS) {
   21981 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21982 				     "checkds: checkds_create() failed: %s",
   21983 				     isc_result_totext(result));
   21984 			break;
   21985 		}
   21986 
   21987 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   21988 			char nsnamebuf[DNS_NAME_FORMATSIZE];
   21989 			dns_name_format(&ns.name, nsnamebuf, sizeof(nsnamebuf));
   21990 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
   21991 				     "checkds: send DS query to NS %s",
   21992 				     nsnamebuf);
   21993 		}
   21994 
   21995 		LOCK_ZONE(zone);
   21996 		zone_iattach(zone, &checkds->zone);
   21997 		dns_name_dup(&ns.name, zone->mctx, &checkds->ns);
   21998 		ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
   21999 		UNLOCK_ZONE(zone);
   22000 
   22001 		checkds_find_address(checkds);
   22002 	}
   22003 	if (result == ISC_R_NOMORE) {
   22004 		result = ISC_R_SUCCESS;
   22005 	}
   22006 
   22007 	LOCK_ZONE(zone);
   22008 
   22009 done:
   22010 	if (result != ISC_R_SUCCESS) {
   22011 		dnssec_log(
   22012 			zone, ISC_LOG_ERROR,
   22013 			"checkds: error during parental-agents processing: %s",
   22014 			isc_result_totext(result));
   22015 	}
   22016 
   22017 cleanup:
   22018 	isc_refcount_decrement(&zone->irefs);
   22019 
   22020 	if (dns_rdataset_isassociated(nsrrset)) {
   22021 		dns_rdataset_disassociate(nsrrset);
   22022 	}
   22023 	if (dns_rdataset_isassociated(nssigset)) {
   22024 		dns_rdataset_disassociate(nssigset);
   22025 	}
   22026 
   22027 	dns_resolver_freefresp(&resp);
   22028 
   22029 	if (levelup) {
   22030 		UNLOCK_ZONE(zone);
   22031 		nsfetch_levelup(nsfetch);
   22032 		return;
   22033 	}
   22034 
   22035 	dns_name_free(zname, mctx);
   22036 	isc_mem_putanddetach(&nsfetch->mctx, nsfetch, sizeof(dns_nsfetch_t));
   22037 
   22038 	free_needed = exit_check(zone);
   22039 	UNLOCK_ZONE(zone);
   22040 
   22041 	if (free_needed) {
   22042 		zone_free(zone);
   22043 	}
   22044 }
   22045 
   22046 static void
   22047 do_nsfetch(void *arg) {
   22048 	dns_nsfetch_t *nsfetch = (dns_nsfetch_t *)arg;
   22049 	isc_result_t result;
   22050 	unsigned int nlabels = 1;
   22051 	dns_resolver_t *resolver = NULL;
   22052 	dns_zone_t *zone = nsfetch->zone;
   22053 	unsigned int options = DNS_FETCHOPT_UNSHARED | DNS_FETCHOPT_NOCACHED;
   22054 
   22055 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   22056 		result = ISC_R_SHUTTINGDOWN;
   22057 		goto cleanup;
   22058 	}
   22059 
   22060 	result = dns_view_getresolver(zone->view, &resolver);
   22061 	if (result != ISC_R_SUCCESS) {
   22062 		goto cleanup;
   22063 	}
   22064 
   22065 	if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   22066 		char namebuf[DNS_NAME_FORMATSIZE];
   22067 		dns_name_format(&nsfetch->pname, namebuf, sizeof(namebuf));
   22068 		dnssec_log(zone, ISC_LOG_DEBUG(3),
   22069 			   "Create fetch for '%s' NS request", namebuf);
   22070 	}
   22071 
   22072 	/* Derive parent domain. XXXWMM: Check for root domain */
   22073 	dns_name_split(&nsfetch->pname,
   22074 		       dns_name_countlabels(&nsfetch->pname) - nlabels, NULL,
   22075 		       &nsfetch->pname);
   22076 
   22077 	/*
   22078 	 * Use of DNS_FETCHOPT_NOCACHED is essential here.  If it is not
   22079 	 * set and the cache still holds a non-expired, validated version
   22080 	 * of the RRset being queried for by the time the response is
   22081 	 * received, the cached RRset will be passed to nsfetch_done()
   22082 	 * instead of the one received in the response as the latter will
   22083 	 * have a lower trust level due to not being validated until
   22084 	 * nsfetch_done() is called.
   22085 	 */
   22086 	result = dns_resolver_createfetch(
   22087 		resolver, &nsfetch->pname, dns_rdatatype_ns, NULL, NULL, NULL,
   22088 		NULL, 0, options, 0, NULL, NULL, NULL, zone->loop, nsfetch_done,
   22089 		nsfetch, NULL, &nsfetch->nsrrset, &nsfetch->nssigset,
   22090 		&nsfetch->fetch);
   22091 
   22092 	dns_resolver_detach(&resolver);
   22093 
   22094 cleanup:
   22095 	if (result != ISC_R_SUCCESS) {
   22096 		dns_name_t *zname = dns_fixedname_name(&nsfetch->name);
   22097 		bool free_needed;
   22098 		char namebuf[DNS_NAME_FORMATSIZE];
   22099 		dns_name_format(&nsfetch->pname, namebuf, sizeof(namebuf));
   22100 		dnssec_log(zone, ISC_LOG_WARNING,
   22101 			   "Failed to create fetch for '%s' NS request",
   22102 			   namebuf);
   22103 		LOCK_ZONE(zone);
   22104 		zone->nsfetchcount--;
   22105 		isc_refcount_decrement(&zone->irefs);
   22106 
   22107 		dns_name_free(zname, zone->mctx);
   22108 		isc_mem_putanddetach(&nsfetch->mctx, nsfetch, sizeof(*nsfetch));
   22109 
   22110 		free_needed = exit_check(zone);
   22111 		UNLOCK_ZONE(zone);
   22112 		if (free_needed) {
   22113 			zone_free(zone);
   22114 		}
   22115 	}
   22116 }
   22117 
   22118 /*
   22119  * Retry an NS RRset lookup, one level up. In other words, this function should
   22120  * be called on an dns_nsfetch structure where the response yielded in a NODATA
   22121  * response. This must be because there is an empty non-terminal inbetween the
   22122  * child and parent zone.
   22123  */
   22124 static void
   22125 nsfetch_levelup(dns_nsfetch_t *nsfetch) {
   22126 	dns_zone_t *zone = nsfetch->zone;
   22127 
   22128 #ifdef ENABLE_AFL
   22129 	if (!dns_fuzzing_resolver) {
   22130 #endif /* ifdef ENABLE_AFL */
   22131 		LOCK_ZONE(zone);
   22132 		zone->nsfetchcount++;
   22133 		isc_refcount_increment0(&zone->irefs);
   22134 
   22135 		dns_rdataset_init(&nsfetch->nsrrset);
   22136 		dns_rdataset_init(&nsfetch->nssigset);
   22137 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   22138 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   22139 				   "Creating parent NS fetch in "
   22140 				   "nsfetch_levelup()");
   22141 		}
   22142 		isc_async_run(zone->loop, do_nsfetch, nsfetch);
   22143 		UNLOCK_ZONE(zone);
   22144 #ifdef ENABLE_AFL
   22145 	}
   22146 #endif /* ifdef ENABLE_AFL */
   22147 }
   22148 
   22149 static void
   22150 zone_checkds(dns_zone_t *zone) {
   22151 	bool cdscheck = false;
   22152 	dns_checkdstype_t checkdstype = zone->checkdstype;
   22153 
   22154 	if (checkdstype == dns_checkdstype_no) {
   22155 		return;
   22156 	}
   22157 
   22158 	for (dns_dnsseckey_t *key = ISC_LIST_HEAD(zone->checkds_ok);
   22159 	     key != NULL; key = ISC_LIST_NEXT(key, link))
   22160 	{
   22161 		dst_key_state_t ds_state = DST_KEY_STATE_NA;
   22162 		bool ksk = false;
   22163 		isc_stdtime_t published = 0, withdrawn = 0;
   22164 
   22165 		/* Is this key have the KSK role? */
   22166 		(void)dst_key_role(key->key, &ksk, NULL);
   22167 		if (!ksk) {
   22168 			continue;
   22169 		}
   22170 
   22171 		/* Do we need to check the DS RRset? */
   22172 		(void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
   22173 		(void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
   22174 		(void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
   22175 
   22176 		if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
   22177 			dst_key_setnum(key->key, DST_NUM_DSPUBCOUNT, 0);
   22178 			cdscheck = true;
   22179 		} else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
   22180 			   withdrawn == 0)
   22181 		{
   22182 			dst_key_setnum(key->key, DST_NUM_DSDELCOUNT, 0);
   22183 			cdscheck = true;
   22184 		}
   22185 	}
   22186 
   22187 	if (!cdscheck) {
   22188 		return;
   22189 	}
   22190 
   22191 	if (checkdstype == dns_checkdstype_explicit) {
   22192 		/* Request the DS RRset. */
   22193 		LOCK_ZONE(zone);
   22194 		checkds_send(zone);
   22195 		UNLOCK_ZONE(zone);
   22196 		return;
   22197 	}
   22198 
   22199 	INSIST(checkdstype == dns_checkdstype_yes);
   22200 
   22201 #ifdef ENABLE_AFL
   22202 	if (!dns_fuzzing_resolver) {
   22203 #endif /* ifdef ENABLE_AFL */
   22204 		dns_nsfetch_t *nsfetch;
   22205 		dns_name_t *name = NULL;
   22206 
   22207 		nsfetch = isc_mem_get(zone->mctx, sizeof(dns_nsfetch_t));
   22208 		*nsfetch = (dns_nsfetch_t){ .zone = zone };
   22209 		isc_mem_attach(zone->mctx, &nsfetch->mctx);
   22210 		LOCK_ZONE(zone);
   22211 		zone->nsfetchcount++;
   22212 		isc_refcount_increment0(&zone->irefs);
   22213 		name = dns_fixedname_initname(&nsfetch->name);
   22214 		dns_name_init(&nsfetch->pname, NULL);
   22215 		dns_name_clone(&zone->origin, &nsfetch->pname);
   22216 		dns_name_dup(&zone->origin, zone->mctx, name);
   22217 		dns_rdataset_init(&nsfetch->nsrrset);
   22218 		dns_rdataset_init(&nsfetch->nssigset);
   22219 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   22220 			dnssec_log(
   22221 				zone, ISC_LOG_DEBUG(3),
   22222 				"Creating parent NS fetch in zone_checkds()");
   22223 		}
   22224 		isc_async_run(zone->loop, do_nsfetch, nsfetch);
   22225 		UNLOCK_ZONE(zone);
   22226 #ifdef ENABLE_AFL
   22227 	}
   22228 #endif /* ifdef ENABLE_AFL */
   22229 }
   22230 
   22231 static isc_result_t
   22232 update_ttl(dns_rdataset_t *rdataset, dns_name_t *name, dns_ttl_t ttl,
   22233 	   dns_diff_t *diff) {
   22234 	isc_result_t result;
   22235 
   22236 	/*
   22237 	 * Delete everything using the existing TTL.
   22238 	 */
   22239 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   22240 	     result = dns_rdataset_next(rdataset))
   22241 	{
   22242 		dns_difftuple_t *tuple = NULL;
   22243 		dns_rdata_t rdata = DNS_RDATA_INIT;
   22244 
   22245 		dns_rdataset_current(rdataset, &rdata);
   22246 		result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
   22247 					      rdataset->ttl, &rdata, &tuple);
   22248 		if (result != ISC_R_SUCCESS) {
   22249 			return result;
   22250 		}
   22251 		dns_diff_appendminimal(diff, &tuple);
   22252 	}
   22253 	if (result != ISC_R_NOMORE) {
   22254 		return result;
   22255 	}
   22256 
   22257 	/*
   22258 	 * Add everything using the new TTL.
   22259 	 */
   22260 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
   22261 	     result = dns_rdataset_next(rdataset))
   22262 	{
   22263 		dns_difftuple_t *tuple = NULL;
   22264 		dns_rdata_t rdata = DNS_RDATA_INIT;
   22265 
   22266 		dns_rdataset_current(rdataset, &rdata);
   22267 		result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
   22268 					      ttl, &rdata, &tuple);
   22269 		if (result != ISC_R_SUCCESS) {
   22270 			return result;
   22271 		}
   22272 		dns_diff_appendminimal(diff, &tuple);
   22273 	}
   22274 	if (result != ISC_R_NOMORE) {
   22275 		return result;
   22276 	}
   22277 	return ISC_R_SUCCESS;
   22278 }
   22279 
   22280 static isc_result_t
   22281 zone_verifykeys(dns_zone_t *zone, dns_dnsseckeylist_t *newkeys,
   22282 		uint32_t purgeval, isc_stdtime_t now) {
   22283 	dns_dnsseckey_t *key1, *key2, *next;
   22284 
   22285 	/*
   22286 	 * Make sure that the existing keys are also present in the new keylist.
   22287 	 */
   22288 	for (key1 = ISC_LIST_HEAD(zone->keyring); key1 != NULL; key1 = next) {
   22289 		bool found = false;
   22290 		next = ISC_LIST_NEXT(key1, link);
   22291 
   22292 		if (dst_key_is_unused(key1->key)) {
   22293 			continue;
   22294 		}
   22295 		if (dns_keymgr_key_may_be_purged(key1->key, purgeval, now)) {
   22296 			continue;
   22297 		}
   22298 		if (key1->purge) {
   22299 			continue;
   22300 		}
   22301 
   22302 		for (key2 = ISC_LIST_HEAD(*newkeys); key2 != NULL;
   22303 		     key2 = ISC_LIST_NEXT(key2, link))
   22304 		{
   22305 			if (dst_key_compare(key1->key, key2->key)) {
   22306 				found = true;
   22307 				break;
   22308 			}
   22309 		}
   22310 
   22311 		if (!found) {
   22312 			char keystr[DST_KEY_FORMATSIZE];
   22313 			dst_key_format(key1->key, keystr, sizeof(keystr));
   22314 			dnssec_log(zone, ISC_LOG_DEBUG(1),
   22315 				   "verifykeys: key %s - not available",
   22316 				   keystr);
   22317 			return ISC_R_NOTFOUND;
   22318 		}
   22319 	}
   22320 
   22321 	/* All good. */
   22322 	return ISC_R_SUCCESS;
   22323 }
   22324 
   22325 static void
   22326 remove_rdataset(dns_zone_t *zone, dns_diff_t *diff, dns_rdataset_t *rdataset) {
   22327 	if (!dns_rdataset_isassociated(rdataset)) {
   22328 		return;
   22329 	}
   22330 
   22331 	for (isc_result_t result = dns_rdataset_first(rdataset);
   22332 	     result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset))
   22333 	{
   22334 		dns_rdata_t rdata = DNS_RDATA_INIT;
   22335 		dns_difftuple_t *tuple = NULL;
   22336 
   22337 		dns_rdataset_current(rdataset, &rdata);
   22338 		dns_difftuple_create(zone->mctx, DNS_DIFFOP_DEL, &zone->origin,
   22339 				     rdataset->ttl, &rdata, &tuple);
   22340 		dns_diff_append(diff, &tuple);
   22341 	}
   22342 	return;
   22343 }
   22344 
   22345 static void
   22346 add_tuple(dns_diff_t *diff, dns_difftuple_t *tuple) {
   22347 	dns_difftuple_t *copy = NULL;
   22348 
   22349 	dns_difftuple_copy(tuple, &copy);
   22350 	dns_diff_appendminimal(diff, &copy);
   22351 }
   22352 
   22353 static void
   22354 zone_apply_skrbundle(dns_zone_t *zone, dns_skrbundle_t *bundle,
   22355 		     dns_rdataset_t *dnskeyset, dns_rdataset_t *cdsset,
   22356 		     dns_rdataset_t *cdnskeyset, dns_diff_t *diff) {
   22357 	dns_kasp_t *kasp = zone->kasp;
   22358 
   22359 	REQUIRE(DNS_ZONE_VALID(zone));
   22360 	REQUIRE(DNS_KASP_VALID(kasp));
   22361 	REQUIRE(DNS_SKRBUNDLE_VALID(bundle));
   22362 
   22363 	/* Remove existing DNSKEY, CDS, and CDNSKEY records. */
   22364 	remove_rdataset(zone, diff, dnskeyset);
   22365 	remove_rdataset(zone, diff, cdsset);
   22366 	remove_rdataset(zone, diff, cdnskeyset);
   22367 
   22368 	/* Add the records from the bundle. */
   22369 	dns_difftuple_t *tuple = ISC_LIST_HEAD(bundle->diff.tuples);
   22370 	while (tuple != NULL) {
   22371 		switch (tuple->rdata.type) {
   22372 		case dns_rdatatype_dnskey:
   22373 			add_tuple(diff, tuple);
   22374 			break;
   22375 		case dns_rdatatype_cdnskey:
   22376 		case dns_rdatatype_cds:
   22377 			add_tuple(diff, tuple);
   22378 			break;
   22379 		case dns_rdatatype_rrsig:
   22380 			/* Not interested in right now */
   22381 			break;
   22382 		default:
   22383 			INSIST(0);
   22384 		}
   22385 
   22386 		tuple = ISC_LIST_NEXT(tuple, link);
   22387 	}
   22388 }
   22389 
   22390 static void
   22391 zone_rekey(dns_zone_t *zone) {
   22392 	isc_result_t result;
   22393 	dns_db_t *db = NULL;
   22394 	dns_dbnode_t *node = NULL;
   22395 	dns_dbversion_t *ver = NULL;
   22396 	dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
   22397 	dns_dnsseckeylist_t dnskeys, keys, rmkeys;
   22398 	dns_dnsseckey_t *key = NULL;
   22399 	dns_diff_t diff, _sig_diff;
   22400 	dns_kasp_t *kasp;
   22401 	dns_skrbundle_t *bundle = NULL;
   22402 	dns__zonediff_t zonediff;
   22403 	bool commit = false, newactive = false;
   22404 	bool newalg = false;
   22405 	bool fullsign;
   22406 	bool offlineksk = false;
   22407 	bool kasp_change = false;
   22408 	uint8_t options = 0;
   22409 	uint32_t sigval = 0;
   22410 	dns_ttl_t ttl = 3600;
   22411 	const char *dir = NULL;
   22412 	isc_mem_t *mctx = NULL;
   22413 	isc_stdtime_t now, nexttime = 0;
   22414 	isc_time_t timenow;
   22415 	isc_interval_t ival;
   22416 	char timebuf[80];
   22417 
   22418 	REQUIRE(DNS_ZONE_VALID(zone));
   22419 
   22420 	ISC_LIST_INIT(dnskeys);
   22421 	ISC_LIST_INIT(keys);
   22422 	ISC_LIST_INIT(rmkeys);
   22423 	dns_rdataset_init(&soaset);
   22424 	dns_rdataset_init(&soasigs);
   22425 	dns_rdataset_init(&keyset);
   22426 	dns_rdataset_init(&keysigs);
   22427 	dns_rdataset_init(&cdsset);
   22428 	dns_rdataset_init(&cdnskeyset);
   22429 	mctx = zone->mctx;
   22430 	dns_diff_init(mctx, &diff);
   22431 	dns_diff_init(mctx, &_sig_diff);
   22432 	zonediff_init(&zonediff, &_sig_diff);
   22433 
   22434 	CHECK(dns_zone_getdb(zone, &db));
   22435 	CHECK(dns_db_newversion(db, &ver));
   22436 	CHECK(dns_db_getoriginnode(db, &node));
   22437 
   22438 	timenow = isc_time_now();
   22439 	now = isc_time_seconds(&timenow);
   22440 
   22441 	kasp = zone->kasp;
   22442 	dir = dns_zone_getkeydirectory(zone);
   22443 
   22444 	dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
   22445 
   22446 	/* Get the SOA record's TTL */
   22447 	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
   22448 				  dns_rdatatype_none, 0, &soaset, &soasigs));
   22449 	ttl = soaset.ttl;
   22450 	dns_rdataset_disassociate(&soaset);
   22451 
   22452 	if (kasp != NULL) {
   22453 		ttl = dns_kasp_dnskeyttl(kasp);
   22454 		offlineksk = dns_kasp_offlineksk(kasp);
   22455 		sigval = dns_kasp_sigvalidity_dnskey(kasp);
   22456 	}
   22457 
   22458 	/* Get the current DNSKEY rdataset */
   22459 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
   22460 				     dns_rdatatype_none, 0, &keyset, &keysigs);
   22461 	if (result == ISC_R_SUCCESS) {
   22462 		/*
   22463 		 * If we don't have a policy then use the DNSKEY ttl
   22464 		 * if it exists.  Otherwise update the DNSKEY ttl if
   22465 		 * needed.
   22466 		 */
   22467 		if (kasp == NULL) {
   22468 			ttl = keyset.ttl;
   22469 		} else if (ttl != keyset.ttl && !offlineksk) {
   22470 			result = update_ttl(&keyset, &zone->origin, ttl, &diff);
   22471 			if (result != ISC_R_SUCCESS) {
   22472 				dnssec_log(zone, ISC_LOG_ERROR,
   22473 					   "Updating DNSKEY TTL from %u to %u "
   22474 					   "failed: %s",
   22475 					   keyset.ttl, ttl,
   22476 					   isc_result_totext(result));
   22477 				goto cleanup;
   22478 			}
   22479 			dnssec_log(zone, ISC_LOG_INFO,
   22480 				   "Updating DNSKEY TTL from %u to %u",
   22481 				   keyset.ttl, ttl);
   22482 			keyset.ttl = ttl;
   22483 		}
   22484 
   22485 		dns_zone_lock_keyfiles(zone);
   22486 
   22487 		result = dns_dnssec_keylistfromrdataset(
   22488 			&zone->origin, kasp, dir, mctx, &keyset, &keysigs,
   22489 			&soasigs, false, false, &dnskeys);
   22490 
   22491 		dns_zone_unlock_keyfiles(zone);
   22492 
   22493 		CHECK(result);
   22494 	} else if (result != ISC_R_NOTFOUND) {
   22495 		goto cleanup;
   22496 	}
   22497 
   22498 	/* Get the current CDS rdataset */
   22499 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
   22500 				     dns_rdatatype_none, 0, &cdsset, NULL);
   22501 	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
   22502 		dns_rdataset_disassociate(&cdsset);
   22503 	} else if (result == ISC_R_SUCCESS && kasp != NULL &&
   22504 		   ttl != cdsset.ttl && !offlineksk)
   22505 	{
   22506 		result = update_ttl(&cdsset, &zone->origin, ttl, &diff);
   22507 		if (result != ISC_R_SUCCESS) {
   22508 			dnssec_log(zone, ISC_LOG_ERROR,
   22509 				   "Updating CDS TTL from %u to %u failed: %s",
   22510 				   cdsset.ttl, ttl, isc_result_totext(result));
   22511 			goto cleanup;
   22512 		}
   22513 		dnssec_log(zone, ISC_LOG_INFO, "Updating CDS TTL from %u to %u",
   22514 			   cdsset.ttl, ttl);
   22515 		cdsset.ttl = ttl;
   22516 	}
   22517 
   22518 	/* Get the current CDNSKEY rdataset */
   22519 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
   22520 				     dns_rdatatype_none, 0, &cdnskeyset, NULL);
   22521 	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
   22522 		dns_rdataset_disassociate(&cdnskeyset);
   22523 	} else if (result == ISC_R_SUCCESS && kasp != NULL &&
   22524 		   ttl != cdnskeyset.ttl && !offlineksk)
   22525 	{
   22526 		result = update_ttl(&cdnskeyset, &zone->origin, ttl, &diff);
   22527 		if (result != ISC_R_SUCCESS) {
   22528 			dnssec_log(
   22529 				zone, ISC_LOG_ERROR,
   22530 				"Updating CDNSKEY TTL from %u to %u failed: %s",
   22531 				cdnskeyset.ttl, ttl, isc_result_totext(result));
   22532 			goto cleanup;
   22533 		}
   22534 		dnssec_log(zone, ISC_LOG_INFO,
   22535 			   "Updating CDNSKEY TTL from %u to %u", cdnskeyset.ttl,
   22536 			   ttl);
   22537 		cdnskeyset.ttl = ttl;
   22538 	}
   22539 
   22540 	/*
   22541 	 * True when called from "rndc sign".  Indicates the zone should be
   22542 	 * fully signed now.
   22543 	 */
   22544 	fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
   22545 	if (fullsign) {
   22546 		options |= DNS_KEYMGRATTR_FULLSIGN;
   22547 	}
   22548 
   22549 	/*
   22550 	 * True when called from "rndc dnssec -step". Indicates the zone
   22551 	 * is allowed to do the next step(s) in the keymgr process.
   22552 	 */
   22553 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FORCEKEYMGR)) {
   22554 		options |= DNS_KEYMGRATTR_FORCESTEP;
   22555 	}
   22556 
   22557 	if (offlineksk) {
   22558 		/* Lookup the correct bundle in the SKR. */
   22559 		LOCK_ZONE(zone);
   22560 		if (zone->skr == NULL) {
   22561 			UNLOCK_ZONE(zone);
   22562 			dnssec_log(zone, ISC_LOG_DEBUG(1),
   22563 				   "zone_rekey:dns_skr_lookup failed: "
   22564 				   "no SKR available");
   22565 			CHECK(DNS_R_NOSKRFILE);
   22566 		}
   22567 		bundle = dns_skr_lookup(zone->skr, now, sigval);
   22568 		zone->skrbundle = bundle;
   22569 		UNLOCK_ZONE(zone);
   22570 
   22571 		if (bundle == NULL) {
   22572 			char nowstr[26]; /* Minimal buf per ctime_r() spec. */
   22573 			char utc[sizeof("YYYYMMDDHHSSMM")];
   22574 			isc_buffer_t b;
   22575 			isc_region_t r;
   22576 			isc_buffer_init(&b, utc, sizeof(utc));
   22577 
   22578 			isc_stdtime_tostring(now, nowstr, sizeof(nowstr));
   22579 			(void)dns_time32_totext(now, &b);
   22580 			isc_buffer_usedregion(&b, &r);
   22581 			dnssec_log(zone, ISC_LOG_DEBUG(1),
   22582 				   "zone_rekey:dns_skr_lookup failed: "
   22583 				   "no available SKR bundle for time "
   22584 				   "%.*s (%s)",
   22585 				   (int)r.length, r.base, nowstr);
   22586 			CHECK(DNS_R_NOSKRBUNDLE);
   22587 		}
   22588 
   22589 		zone_apply_skrbundle(zone, bundle, &keyset, &cdsset,
   22590 				     &cdnskeyset, &diff);
   22591 
   22592 		dns_skrbundle_t *next = ISC_LIST_NEXT(bundle, link);
   22593 		if (next != NULL) {
   22594 			if (nexttime == 0) {
   22595 				nexttime = next->inception;
   22596 			}
   22597 		} else {
   22598 			dnssec_log(zone, ISC_LOG_WARNING,
   22599 				   "zone_rekey: last bundle in skr, please "
   22600 				   "import new skr file");
   22601 		}
   22602 	}
   22603 
   22604 	/*
   22605 	 * DNSSEC Key and Signing Policy
   22606 	 */
   22607 
   22608 	KASP_LOCK(kasp);
   22609 
   22610 	dns_zone_lock_keyfiles(zone);
   22611 	result = dns_dnssec_findmatchingkeys(&zone->origin, kasp, dir,
   22612 					     zone->keystores, now, false, mctx,
   22613 					     &keys);
   22614 	dns_zone_unlock_keyfiles(zone);
   22615 
   22616 	if (result != ISC_R_SUCCESS) {
   22617 		dnssec_log(zone, ISC_LOG_DEBUG(1),
   22618 			   "zone_rekey:dns_dnssec_findmatchingkeys failed: %s",
   22619 			   isc_result_totext(result));
   22620 	}
   22621 
   22622 	if (kasp != NULL && !offlineksk) {
   22623 		/* Verify new keys. */
   22624 		isc_result_t ret = zone_verifykeys(
   22625 			zone, &keys, dns_kasp_purgekeys(kasp), now);
   22626 		if (ret != ISC_R_SUCCESS) {
   22627 			dnssec_log(zone, ISC_LOG_ERROR,
   22628 				   "zone_rekey:zone_verifykeys failed: "
   22629 				   "some key files are missing");
   22630 			KASP_UNLOCK(kasp);
   22631 			goto cleanup;
   22632 		}
   22633 
   22634 		/*
   22635 		 * Check DS at parental agents. Clear ongoing checks.
   22636 		 */
   22637 		LOCK_ZONE(zone);
   22638 		checkds_cancel(zone);
   22639 		clear_keylist(&zone->checkds_ok, zone->mctx);
   22640 		ISC_LIST_INIT(zone->checkds_ok);
   22641 		UNLOCK_ZONE(zone);
   22642 
   22643 		ret = dns_zone_getdnsseckeys(zone, db, ver, now,
   22644 					     &zone->checkds_ok);
   22645 		if (ret == ISC_R_SUCCESS) {
   22646 			zone_checkds(zone);
   22647 		} else {
   22648 			dnssec_log(zone,
   22649 				   (ret == ISC_R_NOTFOUND) ? ISC_LOG_DEBUG(1)
   22650 							   : ISC_LOG_ERROR,
   22651 				   "zone_rekey:dns_zone_getdnsseckeys failed: "
   22652 				   "%s",
   22653 				   isc_result_totext(ret));
   22654 		}
   22655 
   22656 		/* Run keymgr. */
   22657 		if (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND) {
   22658 			dns_zone_lock_keyfiles(zone);
   22659 			result = dns_keymgr_run(&zone->origin, zone->rdclass,
   22660 						mctx, &keys, &dnskeys, dir,
   22661 						kasp, options, now, &nexttime);
   22662 			dns_zone_unlock_keyfiles(zone);
   22663 
   22664 			if (result == ISC_R_SUCCESS) {
   22665 				kasp_change = true;
   22666 			} else if (result == DNS_R_UNCHANGED) {
   22667 				result = ISC_R_SUCCESS;
   22668 			} else {
   22669 				dnssec_log(zone, ISC_LOG_ERROR,
   22670 					   "zone_rekey:dns_keymgr_run "
   22671 					   "failed: %s",
   22672 					   isc_result_totext(result));
   22673 				KASP_UNLOCK(kasp);
   22674 				goto cleanup;
   22675 			}
   22676 		}
   22677 	} else if (offlineksk) {
   22678 		/*
   22679 		 * With offline-ksk enabled we don't run the keymgr.
   22680 		 * Instead we derive the states from the timing metadata.
   22681 		 */
   22682 		dns_zone_lock_keyfiles(zone);
   22683 		result = dns_keymgr_offline(&zone->origin, &keys, kasp, now,
   22684 					    &nexttime);
   22685 		dns_zone_unlock_keyfiles(zone);
   22686 
   22687 		if (result != ISC_R_SUCCESS) {
   22688 			dnssec_log(zone, ISC_LOG_ERROR,
   22689 				   "zone_rekey:dns_keymgr_offline "
   22690 				   "failed: %s",
   22691 				   isc_result_totext(result));
   22692 		}
   22693 	}
   22694 
   22695 	KASP_UNLOCK(kasp);
   22696 
   22697 	/*
   22698 	 * Update CDS, CDNSKEY and DNSKEY record sets if the keymgr ran
   22699 	 * successfully (dns_keymgr_run returned ISC_R_SUCCESS), or in
   22700 	 * case of DNSSEC management without dnssec-policy if we have keys
   22701 	 * (dns_dnssec_findmatchingkeys returned ISC_R_SUCCESS).
   22702 	 */
   22703 	if (result == ISC_R_SUCCESS) {
   22704 		dns_kasp_digestlist_t digests;
   22705 		bool cdsdel = false;
   22706 		bool cdnskeydel = false;
   22707 		bool cdnskeypub = true;
   22708 		bool sane_diff, sane_dnskey;
   22709 		isc_stdtime_t when;
   22710 
   22711 		result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
   22712 					       &zone->origin, ttl, &diff, mctx,
   22713 					       dnssec_report);
   22714 		/*
   22715 		 * Keys couldn't be updated for some reason;
   22716 		 * try again later.
   22717 		 */
   22718 		if (result != ISC_R_SUCCESS) {
   22719 			dnssec_log(zone, ISC_LOG_ERROR,
   22720 				   "zone_rekey:couldn't update zone keys: %s",
   22721 				   isc_result_totext(result));
   22722 			goto cleanup;
   22723 		}
   22724 
   22725 		if (offlineksk) {
   22726 			/* We can skip a lot of things */
   22727 			goto post_sync;
   22728 		}
   22729 
   22730 		/*
   22731 		 * Publish CDS/CDNSKEY DELETE records if the zone is
   22732 		 * transitioning from secure to insecure.
   22733 		 */
   22734 		if (kasp != NULL) {
   22735 			if (strcmp(dns_kasp_getname(kasp), "insecure") == 0) {
   22736 				cdsdel = true;
   22737 				cdnskeydel = true;
   22738 			}
   22739 			digests = dns_kasp_digests(kasp);
   22740 			cdnskeypub = dns_kasp_cdnskey(kasp);
   22741 		} else {
   22742 			/* Check if there is a CDS DELETE record. */
   22743 			if (dns_rdataset_isassociated(&cdsset)) {
   22744 				for (result = dns_rdataset_first(&cdsset);
   22745 				     result == ISC_R_SUCCESS;
   22746 				     result = dns_rdataset_next(&cdsset))
   22747 				{
   22748 					dns_rdata_t crdata = DNS_RDATA_INIT;
   22749 					dns_rdataset_current(&cdsset, &crdata);
   22750 					/*
   22751 					 * CDS deletion record has this form
   22752 					 * "0 0 0 00" which is 5 zero octets.
   22753 					 */
   22754 					if (crdata.length == 5U &&
   22755 					    memcmp(crdata.data,
   22756 						   (unsigned char[5]){ 0, 0, 0,
   22757 								       0, 0 },
   22758 						   5) == 0)
   22759 					{
   22760 						cdsdel = true;
   22761 						break;
   22762 					}
   22763 				}
   22764 			}
   22765 
   22766 			/* Check if there is a CDNSKEY DELETE record. */
   22767 			if (dns_rdataset_isassociated(&cdnskeyset)) {
   22768 				for (result = dns_rdataset_first(&cdnskeyset);
   22769 				     result == ISC_R_SUCCESS;
   22770 				     result = dns_rdataset_next(&cdnskeyset))
   22771 				{
   22772 					dns_rdata_t crdata = DNS_RDATA_INIT;
   22773 					dns_rdataset_current(&cdnskeyset,
   22774 							     &crdata);
   22775 					/*
   22776 					 * CDNSKEY deletion record has this form
   22777 					 * "0 3 0 AA==" which is 2 zero octets,
   22778 					 * a 3, and 2 zero octets.
   22779 					 */
   22780 					if (crdata.length == 5U &&
   22781 					    memcmp(crdata.data,
   22782 						   (unsigned char[5]){ 0, 0, 3,
   22783 								       0, 0 },
   22784 						   5) == 0)
   22785 					{
   22786 						cdnskeydel = true;
   22787 						break;
   22788 					}
   22789 				}
   22790 			}
   22791 
   22792 			digests = dns_kasp_digests(zone->defaultkasp);
   22793 		}
   22794 
   22795 		/*
   22796 		 * Update CDS / CDNSKEY records.
   22797 		 */
   22798 		result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
   22799 					       &cdnskeyset, now, &digests,
   22800 					       cdnskeypub, ttl, &diff, mctx);
   22801 		if (result != ISC_R_SUCCESS) {
   22802 			dnssec_log(zone, ISC_LOG_ERROR,
   22803 				   "zone_rekey:couldn't update CDS/CDNSKEY: %s",
   22804 				   isc_result_totext(result));
   22805 			goto cleanup;
   22806 		}
   22807 
   22808 		if (cdsdel || cdnskeydel) {
   22809 			/*
   22810 			 * Only publish CDS/CDNSKEY DELETE records if there is
   22811 			 * a KSK that can be used to verify the RRset. This
   22812 			 * means there must be a key with the KSK role that is
   22813 			 * published and is used for signing.
   22814 			 */
   22815 			bool allow = false;
   22816 			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
   22817 			     key = ISC_LIST_NEXT(key, link))
   22818 			{
   22819 				dst_key_t *dstk = key->key;
   22820 
   22821 				if (dst_key_is_published(dstk, now, &when) &&
   22822 				    dst_key_is_signing(dstk, DST_BOOL_KSK, now,
   22823 						       &when))
   22824 				{
   22825 					allow = true;
   22826 					break;
   22827 				}
   22828 			}
   22829 			if (cdsdel) {
   22830 				cdsdel = allow;
   22831 			}
   22832 			if (cdnskeydel) {
   22833 				cdnskeydel = allow;
   22834 			}
   22835 		}
   22836 		result = dns_dnssec_syncdelete(
   22837 			&cdsset, &cdnskeyset, &zone->origin, zone->rdclass, ttl,
   22838 			&diff, mctx, cdsdel, cdnskeydel);
   22839 		if (result != ISC_R_SUCCESS) {
   22840 			dnssec_log(zone, ISC_LOG_ERROR,
   22841 				   "zone_rekey:couldn't update CDS/CDNSKEY "
   22842 				   "DELETE records: %s",
   22843 				   isc_result_totext(result));
   22844 			goto cleanup;
   22845 		}
   22846 
   22847 	post_sync:
   22848 		/*
   22849 		 * See if any pre-existing keys have newly become active;
   22850 		 * also, see if any new key is for a new algorithm, as in that
   22851 		 * event, we need to sign the zone fully.  (If there's a new
   22852 		 * key, but it's for an already-existing algorithm, then
   22853 		 * the zone signing can be handled incrementally.)
   22854 		 */
   22855 		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
   22856 		     key = ISC_LIST_NEXT(key, link))
   22857 		{
   22858 			if (!key->first_sign) {
   22859 				continue;
   22860 			}
   22861 
   22862 			newactive = true;
   22863 
   22864 			if (!dns_rdataset_isassociated(&keysigs)) {
   22865 				newalg = true;
   22866 				break;
   22867 			}
   22868 
   22869 			if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
   22870 				/*
   22871 				 * This isn't a new algorithm; clear
   22872 				 * first_sign so we won't sign the
   22873 				 * whole zone with this key later.
   22874 				 */
   22875 				key->first_sign = false;
   22876 			} else {
   22877 				newalg = true;
   22878 				break;
   22879 			}
   22880 		}
   22881 
   22882 		/*
   22883 		 * A sane diff is one that is not empty, and that does not
   22884 		 * introduce a zone with NSEC only DNSKEYs along with NSEC3
   22885 		 * chains.
   22886 		 */
   22887 		sane_dnskey = dns_zone_check_dnskey_nsec3(zone, db, ver, &diff,
   22888 							  NULL, 0);
   22889 		sane_diff = !ISC_LIST_EMPTY(diff.tuples) && sane_dnskey;
   22890 		if (!sane_dnskey) {
   22891 			dnssec_log(zone, ISC_LOG_ERROR,
   22892 				   "NSEC only DNSKEYs and NSEC3 chains not "
   22893 				   "allowed");
   22894 		}
   22895 
   22896 		if (newactive || fullsign || sane_diff || kasp_change) {
   22897 			CHECK(dns_diff_apply(&diff, db, ver));
   22898 			CHECK(clean_nsec3param(zone, db, ver, &diff));
   22899 			CHECK(add_signing_records(db, zone->privatetype, ver,
   22900 						  &diff, newalg || fullsign));
   22901 			CHECK(update_soa_serial(zone, db, ver, &diff, mctx,
   22902 						zone->updatemethod));
   22903 			CHECK(add_chains(zone, db, ver, &diff));
   22904 			CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
   22905 			CHECK(zone_journal(zone, zonediff.diff, NULL,
   22906 					   "zone_rekey"));
   22907 			commit = true;
   22908 		}
   22909 	}
   22910 
   22911 	dns_db_closeversion(db, &ver, true);
   22912 
   22913 	LOCK_ZONE(zone);
   22914 
   22915 	if (commit) {
   22916 		dns_difftuple_t *tuple;
   22917 		dns_stats_t *dnssecsignstats =
   22918 			dns_zone_getdnssecsignstats(zone);
   22919 
   22920 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   22921 
   22922 		zone_needdump(zone, DNS_DUMP_DELAY);
   22923 
   22924 		zone_settimer(zone, &timenow);
   22925 
   22926 		/* Remove any signatures from removed keys.  */
   22927 		if (!ISC_LIST_EMPTY(rmkeys)) {
   22928 			for (key = ISC_LIST_HEAD(rmkeys); key != NULL;
   22929 			     key = ISC_LIST_NEXT(key, link))
   22930 			{
   22931 				result = zone_signwithkey(
   22932 					zone, dst_key_alg(key->key),
   22933 					dst_key_id(key->key), true, false);
   22934 				if (result != ISC_R_SUCCESS) {
   22935 					dnssec_log(zone, ISC_LOG_ERROR,
   22936 						   "zone_signwithkey failed: "
   22937 						   "%s",
   22938 						   isc_result_totext(result));
   22939 				}
   22940 
   22941 				/* Clear DNSSEC sign statistics. */
   22942 				if (dnssecsignstats != NULL) {
   22943 					dns_dnssecsignstats_clear(
   22944 						dnssecsignstats,
   22945 						dst_key_id(key->key),
   22946 						dst_key_alg(key->key));
   22947 					/*
   22948 					 * Also clear the dnssec-sign
   22949 					 * statistics of the revoked key id.
   22950 					 */
   22951 					dns_dnssecsignstats_clear(
   22952 						dnssecsignstats,
   22953 						dst_key_rid(key->key),
   22954 						dst_key_alg(key->key));
   22955 				}
   22956 			}
   22957 		}
   22958 
   22959 		if (fullsign) {
   22960 			/*
   22961 			 * "rndc sign" was called, so we now sign the zone
   22962 			 * with all active keys, whether they're new or not.
   22963 			 */
   22964 			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
   22965 			     key = ISC_LIST_NEXT(key, link))
   22966 			{
   22967 				if (!key->force_sign && !key->hint_sign) {
   22968 					continue;
   22969 				}
   22970 
   22971 				result = zone_signwithkey(
   22972 					zone, dst_key_alg(key->key),
   22973 					dst_key_id(key->key), false, true);
   22974 				if (result != ISC_R_SUCCESS) {
   22975 					dnssec_log(zone, ISC_LOG_ERROR,
   22976 						   "zone_signwithkey failed: "
   22977 						   "%s",
   22978 						   isc_result_totext(result));
   22979 				}
   22980 			}
   22981 			/*
   22982 			 * ...and remove signatures for all inactive keys.
   22983 			 */
   22984 			ISC_LIST_FOREACH(dnskeys, key, link) {
   22985 				if (!key->force_sign && !key->hint_sign) {
   22986 					result = zone_signwithkey(
   22987 						zone, dst_key_alg(key->key),
   22988 						dst_key_id(key->key), true,
   22989 						false);
   22990 					if (result != ISC_R_SUCCESS) {
   22991 						dnssec_log(zone, ISC_LOG_ERROR,
   22992 							   "zone_signwithkey "
   22993 							   "failed: "
   22994 							   "%s",
   22995 							   isc_result_totext(
   22996 								   result));
   22997 					}
   22998 				}
   22999 			}
   23000 
   23001 		} else if (newalg) {
   23002 			/*
   23003 			 * We haven't been told to sign fully, but a new
   23004 			 * algorithm was added to the DNSKEY.  We sign
   23005 			 * the full zone, but only with newly active
   23006 			 * keys.
   23007 			 */
   23008 			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
   23009 			     key = ISC_LIST_NEXT(key, link))
   23010 			{
   23011 				if (!key->first_sign) {
   23012 					continue;
   23013 				}
   23014 
   23015 				result = zone_signwithkey(
   23016 					zone, dst_key_alg(key->key),
   23017 					dst_key_id(key->key), false, false);
   23018 				if (result != ISC_R_SUCCESS) {
   23019 					dnssec_log(zone, ISC_LOG_ERROR,
   23020 						   "zone_signwithkey failed: "
   23021 						   "%s",
   23022 						   isc_result_totext(result));
   23023 				}
   23024 			}
   23025 		}
   23026 
   23027 		/*
   23028 		 * Clear fullsign flag, if it was set, so we don't do
   23029 		 * another full signing next time.
   23030 		 */
   23031 		DNS_ZONEKEY_CLROPTION(zone, DNS_ZONEKEY_FULLSIGN);
   23032 
   23033 		/*
   23034 		 * Cause the zone to add/delete NSEC3 chains for the
   23035 		 * deferred NSEC3PARAM changes.
   23036 		 */
   23037 		for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
   23038 		     tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
   23039 		{
   23040 			unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   23041 			dns_rdata_t rdata = DNS_RDATA_INIT;
   23042 			dns_rdata_nsec3param_t nsec3param;
   23043 
   23044 			if (tuple->rdata.type != zone->privatetype ||
   23045 			    tuple->op != DNS_DIFFOP_ADD)
   23046 			{
   23047 				continue;
   23048 			}
   23049 
   23050 			if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
   23051 							buf, sizeof(buf)))
   23052 			{
   23053 				continue;
   23054 			}
   23055 
   23056 			result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   23057 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   23058 			if (nsec3param.flags == 0) {
   23059 				continue;
   23060 			}
   23061 
   23062 			result = zone_addnsec3chain(zone, &nsec3param);
   23063 			if (result != ISC_R_SUCCESS) {
   23064 				dnssec_log(zone, ISC_LOG_ERROR,
   23065 					   "zone_addnsec3chain failed: %s",
   23066 					   isc_result_totext(result));
   23067 			}
   23068 		}
   23069 
   23070 		/*
   23071 		 * Activate any NSEC3 chain updates that may have
   23072 		 * been scheduled before this rekey.
   23073 		 */
   23074 		if (fullsign || newalg) {
   23075 			resume_addnsec3chain(zone);
   23076 		}
   23077 
   23078 		/*
   23079 		 * Schedule the next resigning event
   23080 		 */
   23081 		set_resigntime(zone);
   23082 	}
   23083 
   23084 	isc_time_settoepoch(&zone->refreshkeytime);
   23085 
   23086 	/*
   23087 	 * If keymgr provided a next time, use the calculated next rekey time.
   23088 	 */
   23089 	if (kasp != NULL) {
   23090 		isc_time_t timenext;
   23091 		uint32_t nexttime_seconds;
   23092 
   23093 		/*
   23094 		 * Set the key refresh timer to the next scheduled key event
   23095 		 * or to 'dnssec-loadkeys-interval' seconds in the future
   23096 		 * if no next key event is scheduled (nexttime == 0).
   23097 		 */
   23098 		if (nexttime > 0) {
   23099 			nexttime_seconds = nexttime - now;
   23100 		} else {
   23101 			nexttime_seconds = zone->refreshkeyinterval;
   23102 		}
   23103 
   23104 		DNS_ZONE_TIME_ADD(&timenow, nexttime_seconds, &timenext);
   23105 		zone->refreshkeytime = timenext;
   23106 		zone_settimer(zone, &timenow);
   23107 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   23108 
   23109 		dnssec_log(zone, ISC_LOG_DEBUG(3),
   23110 			   "next key event in %u seconds", nexttime_seconds);
   23111 		dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
   23112 	}
   23113 	/*
   23114 	 * If we're doing key maintenance, set the key refresh timer to
   23115 	 * the next scheduled key event or to 'dnssec-loadkeys-interval'
   23116 	 * seconds in the future, whichever is sooner.
   23117 	 */
   23118 	else if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
   23119 	{
   23120 		isc_time_t timethen;
   23121 		isc_stdtime_t then;
   23122 
   23123 		DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
   23124 				  &timethen);
   23125 		zone->refreshkeytime = timethen;
   23126 
   23127 		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
   23128 		     key = ISC_LIST_NEXT(key, link))
   23129 		{
   23130 			then = now;
   23131 			result = next_keyevent(key->key, &then);
   23132 			if (result != ISC_R_SUCCESS) {
   23133 				continue;
   23134 			}
   23135 
   23136 			DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
   23137 			if (isc_time_compare(&timethen, &zone->refreshkeytime) <
   23138 			    0)
   23139 			{
   23140 				zone->refreshkeytime = timethen;
   23141 			}
   23142 		}
   23143 
   23144 		zone_settimer(zone, &timenow);
   23145 
   23146 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   23147 		dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
   23148 	}
   23149 	UNLOCK_ZONE(zone);
   23150 
   23151 	/*
   23152 	 * Remember which keys have been used.
   23153 	 */
   23154 	if (!ISC_LIST_EMPTY(zone->keyring)) {
   23155 		clear_keylist(&zone->keyring, zone->mctx);
   23156 	}
   23157 	while ((key = ISC_LIST_HEAD(dnskeys)) != NULL) {
   23158 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   23159 			/* This debug log is used in the kasp system test */
   23160 			char algbuf[DNS_SECALG_FORMATSIZE];
   23161 			dns_secalg_format(dst_key_alg(key->key), algbuf,
   23162 					  sizeof(algbuf));
   23163 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   23164 				   "zone_rekey done: key %d/%s",
   23165 				   dst_key_id(key->key), algbuf);
   23166 		}
   23167 		ISC_LIST_UNLINK(dnskeys, key, link);
   23168 		ISC_LIST_APPEND(zone->keyring, key, link);
   23169 	}
   23170 
   23171 	result = ISC_R_SUCCESS;
   23172 
   23173 cleanup:
   23174 	LOCK_ZONE(zone);
   23175 	if (result != ISC_R_SUCCESS) {
   23176 		/*
   23177 		 * Something went wrong; try again in ten minutes or
   23178 		 * after a key refresh interval, whichever is shorter.
   23179 		 */
   23180 		int loglevel = ISC_LOG_DEBUG(3);
   23181 		if (result != DNS_R_NOTLOADED) {
   23182 			loglevel = ISC_LOG_ERROR;
   23183 		}
   23184 		dnssec_log(zone, loglevel,
   23185 			   "zone_rekey failure: %s (retry in %u seconds)",
   23186 			   isc_result_totext(result),
   23187 			   ISC_MIN(zone->refreshkeyinterval, 600));
   23188 		isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600),
   23189 				 0);
   23190 		isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
   23191 	}
   23192 
   23193 	/*
   23194 	 * Clear forcekeymgr flag, if it was set, so we don't do
   23195 	 * another force next time.
   23196 	 */
   23197 	DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_FORCEKEYMGR);
   23198 
   23199 	UNLOCK_ZONE(zone);
   23200 
   23201 	dns_diff_clear(&diff);
   23202 	dns_diff_clear(&_sig_diff);
   23203 
   23204 	clear_keylist(&dnskeys, mctx);
   23205 	clear_keylist(&keys, mctx);
   23206 	clear_keylist(&rmkeys, mctx);
   23207 
   23208 	if (ver != NULL) {
   23209 		dns_db_closeversion(db, &ver, false);
   23210 	}
   23211 	if (dns_rdataset_isassociated(&cdsset)) {
   23212 		dns_rdataset_disassociate(&cdsset);
   23213 	}
   23214 	if (dns_rdataset_isassociated(&keyset)) {
   23215 		dns_rdataset_disassociate(&keyset);
   23216 	}
   23217 	if (dns_rdataset_isassociated(&keysigs)) {
   23218 		dns_rdataset_disassociate(&keysigs);
   23219 	}
   23220 	if (dns_rdataset_isassociated(&soasigs)) {
   23221 		dns_rdataset_disassociate(&soasigs);
   23222 	}
   23223 	if (dns_rdataset_isassociated(&cdnskeyset)) {
   23224 		dns_rdataset_disassociate(&cdnskeyset);
   23225 	}
   23226 	if (node != NULL) {
   23227 		dns_db_detachnode(db, &node);
   23228 	}
   23229 	if (db != NULL) {
   23230 		dns_db_detach(&db);
   23231 	}
   23232 
   23233 	INSIST(ver == NULL);
   23234 }
   23235 
   23236 void
   23237 dns_zone_rekey(dns_zone_t *zone, bool fullsign, bool forcekeymgr) {
   23238 	isc_time_t now;
   23239 
   23240 	if (zone->type == dns_zone_primary && zone->loop != NULL) {
   23241 		LOCK_ZONE(zone);
   23242 
   23243 		if (fullsign) {
   23244 			DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
   23245 		}
   23246 		if (forcekeymgr) {
   23247 			DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_FORCEKEYMGR);
   23248 		}
   23249 
   23250 		now = isc_time_now();
   23251 		zone->refreshkeytime = now;
   23252 		zone_settimer(zone, &now);
   23253 
   23254 		UNLOCK_ZONE(zone);
   23255 	}
   23256 }
   23257 
   23258 isc_result_t
   23259 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
   23260 		 unsigned int *errors) {
   23261 	isc_result_t result;
   23262 	dns_dbnode_t *node = NULL;
   23263 
   23264 	REQUIRE(DNS_ZONE_VALID(zone));
   23265 	REQUIRE(errors != NULL);
   23266 
   23267 	result = dns_db_getoriginnode(db, &node);
   23268 	if (result != ISC_R_SUCCESS) {
   23269 		return result;
   23270 	}
   23271 	result = zone_count_ns_rr(zone, db, node, version, NULL, errors, false);
   23272 	dns_db_detachnode(db, &node);
   23273 	return result;
   23274 }
   23275 
   23276 isc_result_t
   23277 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
   23278 	isc_result_t result;
   23279 	dns_dbnode_t *node = NULL;
   23280 	dns_rdataset_t dnskey, cds, cdnskey;
   23281 	unsigned char algorithms[256];
   23282 	unsigned int i;
   23283 	bool empty = false;
   23284 
   23285 	enum { notexpected = 0, expected = 1, found = 2 };
   23286 
   23287 	REQUIRE(DNS_ZONE_VALID(zone));
   23288 
   23289 	result = dns_db_getoriginnode(db, &node);
   23290 	if (result != ISC_R_SUCCESS) {
   23291 		return result;
   23292 	}
   23293 
   23294 	dns_rdataset_init(&cds);
   23295 	dns_rdataset_init(&dnskey);
   23296 	dns_rdataset_init(&cdnskey);
   23297 
   23298 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
   23299 				     dns_rdatatype_none, 0, &cds, NULL);
   23300 	if (result != ISC_R_NOTFOUND) {
   23301 		CHECK(result);
   23302 	}
   23303 
   23304 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
   23305 				     dns_rdatatype_none, 0, &cdnskey, NULL);
   23306 	if (result != ISC_R_NOTFOUND) {
   23307 		CHECK(result);
   23308 	}
   23309 
   23310 	if (!dns_rdataset_isassociated(&cds) &&
   23311 	    !dns_rdataset_isassociated(&cdnskey))
   23312 	{
   23313 		result = ISC_R_SUCCESS;
   23314 		goto cleanup;
   23315 	}
   23316 
   23317 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
   23318 				     dns_rdatatype_none, 0, &dnskey, NULL);
   23319 	if (result == ISC_R_NOTFOUND) {
   23320 		empty = true;
   23321 	} else {
   23322 		CHECK(result);
   23323 	}
   23324 
   23325 	/*
   23326 	 * For each DNSSEC algorithm in the CDS RRset there must be
   23327 	 * a matching DNSKEY record with the exception of a CDS deletion
   23328 	 * record which must be by itself.
   23329 	 */
   23330 	if (dns_rdataset_isassociated(&cds)) {
   23331 		bool logged_digest_type[DNS_DSDIGEST_MAX + 1] = { 0 };
   23332 		bool delete = false;
   23333 		memset(algorithms, notexpected, sizeof(algorithms));
   23334 		for (result = dns_rdataset_first(&cds); result == ISC_R_SUCCESS;
   23335 		     result = dns_rdataset_next(&cds))
   23336 		{
   23337 			dns_rdata_t crdata = DNS_RDATA_INIT;
   23338 			dns_rdata_cds_t structcds;
   23339 
   23340 			dns_rdataset_current(&cds, &crdata);
   23341 			/*
   23342 			 * CDS deletion record has this form "0 0 0 00" which
   23343 			 * is 5 zero octets.
   23344 			 */
   23345 			if (crdata.length == 5U &&
   23346 			    memcmp(crdata.data,
   23347 				   (unsigned char[5]){ 0, 0, 0, 0, 0 }, 5) == 0)
   23348 			{
   23349 				delete = true;
   23350 				continue;
   23351 			}
   23352 
   23353 			if (empty) {
   23354 				CHECK(DNS_R_BADCDS);
   23355 			}
   23356 
   23357 			CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
   23358 
   23359 			/*
   23360 			 * Log deprecated CDS digest types.
   23361 			 */
   23362 			switch (structcds.digest_type) {
   23363 			case DNS_DSDIGEST_SHA1:
   23364 			case DNS_DSDIGEST_GOST:
   23365 				if (!logged_digest_type[structcds.digest_type])
   23366 				{
   23367 					char algbuf[DNS_DSDIGEST_FORMATSIZE];
   23368 					dns_dsdigest_format(
   23369 						structcds.digest_type, algbuf,
   23370 						sizeof(algbuf));
   23371 					dnssec_log(zone, ISC_LOG_WARNING,
   23372 						   "deprecated CDS digest type "
   23373 						   "%u (%s)",
   23374 						   structcds.digest_type,
   23375 						   algbuf);
   23376 					logged_digest_type[structcds.digest_type] =
   23377 						true;
   23378 				}
   23379 				break;
   23380 			}
   23381 
   23382 			if (algorithms[structcds.algorithm] == 0) {
   23383 				algorithms[structcds.algorithm] = expected;
   23384 			}
   23385 			for (result = dns_rdataset_first(&dnskey);
   23386 			     result == ISC_R_SUCCESS;
   23387 			     result = dns_rdataset_next(&dnskey))
   23388 			{
   23389 				dns_rdata_t rdata = DNS_RDATA_INIT;
   23390 				dns_rdata_dnskey_t structdnskey;
   23391 
   23392 				dns_rdataset_current(&dnskey, &rdata);
   23393 				CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
   23394 							 NULL));
   23395 
   23396 				if (structdnskey.algorithm ==
   23397 				    structcds.algorithm)
   23398 				{
   23399 					algorithms[structcds.algorithm] = found;
   23400 				}
   23401 			}
   23402 			if (result != ISC_R_NOMORE) {
   23403 				goto cleanup;
   23404 			}
   23405 		}
   23406 		for (i = 0; i < sizeof(algorithms); i++) {
   23407 			if (delete) {
   23408 				if (algorithms[i] != notexpected) {
   23409 					CHECK(DNS_R_BADCDS);
   23410 				}
   23411 			} else if (algorithms[i] == expected) {
   23412 				CHECK(DNS_R_BADCDS);
   23413 			}
   23414 		}
   23415 	}
   23416 
   23417 	/*
   23418 	 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
   23419 	 * a matching DNSKEY record with the exception of a CDNSKEY deletion
   23420 	 * record which must be by itself.
   23421 	 */
   23422 	if (dns_rdataset_isassociated(&cdnskey)) {
   23423 		bool delete = false;
   23424 		memset(algorithms, notexpected, sizeof(algorithms));
   23425 		for (result = dns_rdataset_first(&cdnskey);
   23426 		     result == ISC_R_SUCCESS;
   23427 		     result = dns_rdataset_next(&cdnskey))
   23428 		{
   23429 			dns_rdata_t crdata = DNS_RDATA_INIT;
   23430 			dns_rdata_cdnskey_t structcdnskey;
   23431 
   23432 			dns_rdataset_current(&cdnskey, &crdata);
   23433 			/*
   23434 			 * CDNSKEY deletion record has this form
   23435 			 * "0 3 0 AA==" which is 2 zero octets, a 3,
   23436 			 * and 2 zero octets.
   23437 			 */
   23438 			if (crdata.length == 5U &&
   23439 			    memcmp(crdata.data,
   23440 				   (unsigned char[5]){ 0, 0, 3, 0, 0 }, 5) == 0)
   23441 			{
   23442 				delete = true;
   23443 				continue;
   23444 			}
   23445 
   23446 			if (empty) {
   23447 				CHECK(DNS_R_BADCDNSKEY);
   23448 			}
   23449 
   23450 			CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
   23451 						 NULL));
   23452 			if (algorithms[structcdnskey.algorithm] == 0) {
   23453 				algorithms[structcdnskey.algorithm] = expected;
   23454 			}
   23455 			for (result = dns_rdataset_first(&dnskey);
   23456 			     result == ISC_R_SUCCESS;
   23457 			     result = dns_rdataset_next(&dnskey))
   23458 			{
   23459 				dns_rdata_t rdata = DNS_RDATA_INIT;
   23460 				dns_rdata_dnskey_t structdnskey;
   23461 
   23462 				dns_rdataset_current(&dnskey, &rdata);
   23463 				CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
   23464 							 NULL));
   23465 
   23466 				if (structdnskey.algorithm ==
   23467 				    structcdnskey.algorithm)
   23468 				{
   23469 					algorithms[structcdnskey.algorithm] =
   23470 						found;
   23471 				}
   23472 			}
   23473 			if (result != ISC_R_NOMORE) {
   23474 				goto cleanup;
   23475 			}
   23476 		}
   23477 		for (i = 0; i < sizeof(algorithms); i++) {
   23478 			if (delete) {
   23479 				if (algorithms[i] != notexpected) {
   23480 					CHECK(DNS_R_BADCDNSKEY);
   23481 				}
   23482 			} else if (algorithms[i] == expected) {
   23483 				CHECK(DNS_R_BADCDNSKEY);
   23484 			}
   23485 		}
   23486 	}
   23487 	result = ISC_R_SUCCESS;
   23488 
   23489 cleanup:
   23490 	if (dns_rdataset_isassociated(&cds)) {
   23491 		dns_rdataset_disassociate(&cds);
   23492 	}
   23493 	if (dns_rdataset_isassociated(&dnskey)) {
   23494 		dns_rdataset_disassociate(&dnskey);
   23495 	}
   23496 	if (dns_rdataset_isassociated(&cdnskey)) {
   23497 		dns_rdataset_disassociate(&cdnskey);
   23498 	}
   23499 	dns_db_detachnode(db, &node);
   23500 	return result;
   23501 }
   23502 
   23503 void
   23504 dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
   23505 	REQUIRE(DNS_ZONE_VALID(zone));
   23506 
   23507 	LOCK_ZONE(zone);
   23508 	zone->automatic = automatic;
   23509 	UNLOCK_ZONE(zone);
   23510 }
   23511 
   23512 bool
   23513 dns_zone_getautomatic(dns_zone_t *zone) {
   23514 	REQUIRE(DNS_ZONE_VALID(zone));
   23515 	return zone->automatic;
   23516 }
   23517 
   23518 void
   23519 dns_zone_setadded(dns_zone_t *zone, bool added) {
   23520 	REQUIRE(DNS_ZONE_VALID(zone));
   23521 
   23522 	LOCK_ZONE(zone);
   23523 	zone->added = added;
   23524 	UNLOCK_ZONE(zone);
   23525 }
   23526 
   23527 bool
   23528 dns_zone_getadded(dns_zone_t *zone) {
   23529 	REQUIRE(DNS_ZONE_VALID(zone));
   23530 	return zone->added;
   23531 }
   23532 
   23533 isc_result_t
   23534 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) {
   23535 	isc_time_t loadtime;
   23536 	isc_result_t result;
   23537 	dns_zone_t *secure = NULL;
   23538 
   23539 	loadtime = isc_time_now();
   23540 
   23541 	/*
   23542 	 * Lock hierarchy: zmgr, zone, raw.
   23543 	 */
   23544 again:
   23545 	LOCK_ZONE(zone);
   23546 	INSIST(zone != zone->raw);
   23547 	if (inline_secure(zone)) {
   23548 		LOCK_ZONE(zone->raw);
   23549 	} else if (inline_raw(zone)) {
   23550 		secure = zone->secure;
   23551 		TRYLOCK_ZONE(result, secure);
   23552 		if (result != ISC_R_SUCCESS) {
   23553 			UNLOCK_ZONE(zone);
   23554 			secure = NULL;
   23555 			isc_thread_yield();
   23556 			goto again;
   23557 		}
   23558 	}
   23559 	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
   23560 	if (inline_secure(zone)) {
   23561 		UNLOCK_ZONE(zone->raw);
   23562 	} else if (secure != NULL) {
   23563 		UNLOCK_ZONE(secure);
   23564 	}
   23565 	UNLOCK_ZONE(zone);
   23566 	return result;
   23567 }
   23568 
   23569 isc_result_t
   23570 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
   23571 	REQUIRE(DNS_ZONE_VALID(zone));
   23572 	if (interval == 0) {
   23573 		return ISC_R_RANGE;
   23574 	}
   23575 	/* Maximum value: 24 hours (3600 minutes) */
   23576 	if (interval > (24 * 60)) {
   23577 		interval = (24 * 60);
   23578 	}
   23579 	/* Multiply by 60 for seconds */
   23580 	zone->refreshkeyinterval = interval * 60;
   23581 	return ISC_R_SUCCESS;
   23582 }
   23583 
   23584 void
   23585 dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
   23586 	REQUIRE(DNS_ZONE_VALID(zone));
   23587 	zone->requestixfr = flag;
   23588 }
   23589 
   23590 bool
   23591 dns_zone_getrequestixfr(dns_zone_t *zone) {
   23592 	REQUIRE(DNS_ZONE_VALID(zone));
   23593 	return zone->requestixfr;
   23594 }
   23595 
   23596 void
   23597 dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio) {
   23598 	REQUIRE(DNS_ZONE_VALID(zone));
   23599 	zone->ixfr_ratio = ratio;
   23600 }
   23601 
   23602 uint32_t
   23603 dns_zone_getixfrratio(dns_zone_t *zone) {
   23604 	REQUIRE(DNS_ZONE_VALID(zone));
   23605 	return zone->ixfr_ratio;
   23606 }
   23607 
   23608 void
   23609 dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
   23610 	REQUIRE(DNS_ZONE_VALID(zone));
   23611 	zone->requestexpire = flag;
   23612 }
   23613 
   23614 bool
   23615 dns_zone_getrequestexpire(dns_zone_t *zone) {
   23616 	REQUIRE(DNS_ZONE_VALID(zone));
   23617 	return zone->requestexpire;
   23618 }
   23619 
   23620 void
   23621 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
   23622 	REQUIRE(DNS_ZONE_VALID(zone));
   23623 	zone->updatemethod = method;
   23624 }
   23625 
   23626 dns_updatemethod_t
   23627 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
   23628 	REQUIRE(DNS_ZONE_VALID(zone));
   23629 	return zone->updatemethod;
   23630 }
   23631 
   23632 /*
   23633  * Lock hierarchy: zmgr, zone, raw.
   23634  */
   23635 isc_result_t
   23636 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
   23637 	dns_zonemgr_t *zmgr;
   23638 
   23639 	REQUIRE(DNS_ZONE_VALID(zone));
   23640 	REQUIRE(zone->zmgr != NULL);
   23641 	REQUIRE(zone->loop != NULL);
   23642 	REQUIRE(zone->raw == NULL);
   23643 
   23644 	REQUIRE(DNS_ZONE_VALID(raw));
   23645 	REQUIRE(raw->zmgr == NULL);
   23646 	REQUIRE(raw->loop == NULL);
   23647 	REQUIRE(raw->secure == NULL);
   23648 
   23649 	REQUIRE(zone != raw);
   23650 
   23651 	/*
   23652 	 * Lock hierarchy: zmgr, zone, raw.
   23653 	 */
   23654 	zmgr = zone->zmgr;
   23655 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   23656 	LOCK_ZONE(zone);
   23657 	LOCK_ZONE(raw);
   23658 
   23659 	isc_loop_attach(zone->loop, &raw->loop);
   23660 
   23661 	/* dns_zone_attach(raw, &zone->raw); */
   23662 	isc_refcount_increment(&raw->references);
   23663 	zone->raw = raw;
   23664 
   23665 	/* dns_zone_iattach(zone, &raw->secure); */
   23666 	zone_iattach(zone, &raw->secure);
   23667 
   23668 	ISC_LIST_APPEND(zmgr->zones, raw, link);
   23669 	raw->zmgr = zmgr;
   23670 	isc_refcount_increment(&zmgr->refs);
   23671 
   23672 	UNLOCK_ZONE(raw);
   23673 	UNLOCK_ZONE(zone);
   23674 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   23675 	return ISC_R_SUCCESS;
   23676 }
   23677 
   23678 void
   23679 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
   23680 	REQUIRE(DNS_ZONE_VALID(zone));
   23681 	REQUIRE(raw != NULL && *raw == NULL);
   23682 
   23683 	LOCK(&zone->lock);
   23684 	INSIST(zone != zone->raw);
   23685 	if (zone->raw != NULL) {
   23686 		dns_zone_attach(zone->raw, raw);
   23687 	}
   23688 	UNLOCK(&zone->lock);
   23689 }
   23690 
   23691 bool
   23692 dns_zone_israw(dns_zone_t *zone) {
   23693 	bool israw;
   23694 	REQUIRE(DNS_ZONE_VALID(zone));
   23695 	LOCK(&zone->lock);
   23696 	israw = zone->secure != NULL;
   23697 	UNLOCK(&zone->lock);
   23698 	return israw;
   23699 }
   23700 
   23701 bool
   23702 dns_zone_issecure(dns_zone_t *zone) {
   23703 	bool issecure;
   23704 	REQUIRE(DNS_ZONE_VALID(zone));
   23705 	LOCK(&zone->lock);
   23706 	issecure = zone->raw != NULL;
   23707 	UNLOCK(&zone->lock);
   23708 	return issecure;
   23709 }
   23710 
   23711 struct keydone {
   23712 	bool all;
   23713 	unsigned char data[5];
   23714 	dns_zone_t *zone;
   23715 };
   23716 
   23717 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL)
   23718 
   23719 static void
   23720 keydone(void *arg) {
   23721 	bool commit = false;
   23722 	isc_result_t result;
   23723 	dns_rdata_t rdata = DNS_RDATA_INIT;
   23724 	dns_dbversion_t *oldver = NULL, *newver = NULL;
   23725 	dns_db_t *db = NULL;
   23726 	dns_dbnode_t *node = NULL;
   23727 	dns_rdataset_t rdataset;
   23728 	dns_diff_t diff;
   23729 	struct keydone *kd = (struct keydone *)arg;
   23730 	dns_zone_t *zone = kd->zone;
   23731 	dns_update_log_t log = { update_log_cb, NULL };
   23732 	bool clear_pending = false;
   23733 
   23734 	INSIST(DNS_ZONE_VALID(zone));
   23735 
   23736 	ENTER;
   23737 
   23738 	dns_rdataset_init(&rdataset);
   23739 	dns_diff_init(zone->mctx, &diff);
   23740 
   23741 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   23742 	if (zone->db != NULL) {
   23743 		dns_db_attach(zone->db, &db);
   23744 	}
   23745 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   23746 	if (db == NULL) {
   23747 		goto cleanup;
   23748 	}
   23749 
   23750 	dns_db_currentversion(db, &oldver);
   23751 	result = dns_db_newversion(db, &newver);
   23752 	if (result != ISC_R_SUCCESS) {
   23753 		dnssec_log(zone, ISC_LOG_ERROR,
   23754 			   "keydone:dns_db_newversion -> %s",
   23755 			   isc_result_totext(result));
   23756 		goto cleanup;
   23757 	}
   23758 
   23759 	CHECK(dns_db_getoriginnode(db, &node));
   23760 
   23761 	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
   23762 				     dns_rdatatype_none, 0, &rdataset, NULL);
   23763 	if (result != ISC_R_SUCCESS) {
   23764 		INSIST(!dns_rdataset_isassociated(&rdataset));
   23765 		goto cleanup;
   23766 	}
   23767 
   23768 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   23769 	     result = dns_rdataset_next(&rdataset))
   23770 	{
   23771 		bool found = false;
   23772 
   23773 		dns_rdataset_current(&rdataset, &rdata);
   23774 
   23775 		if (kd->all) {
   23776 			if (rdata.length == 5 && rdata.data[0] != 0 &&
   23777 			    rdata.data[3] == 0 && rdata.data[4] == 1)
   23778 			{
   23779 				found = true;
   23780 			} else if (rdata.data[0] == 0 &&
   23781 				   (rdata.data[2] & PENDINGFLAGS) != 0)
   23782 			{
   23783 				found = true;
   23784 				clear_pending = true;
   23785 			}
   23786 		} else if (rdata.length == 5 &&
   23787 			   memcmp(rdata.data, kd->data, 5) == 0)
   23788 		{
   23789 			found = true;
   23790 		}
   23791 
   23792 		if (found) {
   23793 			CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
   23794 					    &zone->origin, rdataset.ttl,
   23795 					    &rdata));
   23796 		}
   23797 		dns_rdata_reset(&rdata);
   23798 	}
   23799 
   23800 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   23801 		/* Write changes to journal file. */
   23802 		CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
   23803 					zone->updatemethod));
   23804 
   23805 		result = dns_update_signatures(&log, zone, db, oldver, newver,
   23806 					       &diff,
   23807 					       zone->sigvalidityinterval);
   23808 		if (!clear_pending) {
   23809 			CHECK(result);
   23810 		}
   23811 
   23812 		CHECK(zone_journal(zone, &diff, NULL, "keydone"));
   23813 		commit = true;
   23814 
   23815 		LOCK_ZONE(zone);
   23816 		DNS_ZONE_SETFLAG(zone,
   23817 				 DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
   23818 		zone_needdump(zone, 30);
   23819 		UNLOCK_ZONE(zone);
   23820 	}
   23821 
   23822 cleanup:
   23823 	if (dns_rdataset_isassociated(&rdataset)) {
   23824 		dns_rdataset_disassociate(&rdataset);
   23825 	}
   23826 	if (db != NULL) {
   23827 		if (node != NULL) {
   23828 			dns_db_detachnode(db, &node);
   23829 		}
   23830 		if (oldver != NULL) {
   23831 			dns_db_closeversion(db, &oldver, false);
   23832 		}
   23833 		if (newver != NULL) {
   23834 			dns_db_closeversion(db, &newver, commit);
   23835 		}
   23836 		dns_db_detach(&db);
   23837 	}
   23838 	dns_diff_clear(&diff);
   23839 	isc_mem_put(zone->mctx, kd, sizeof(*kd));
   23840 	dns_zone_idetach(&zone);
   23841 
   23842 	INSIST(oldver == NULL);
   23843 	INSIST(newver == NULL);
   23844 }
   23845 
   23846 isc_result_t
   23847 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
   23848 	isc_result_t result = ISC_R_SUCCESS;
   23849 	struct keydone *kd = NULL;
   23850 	isc_buffer_t b;
   23851 
   23852 	REQUIRE(DNS_ZONE_VALID(zone));
   23853 
   23854 	LOCK_ZONE(zone);
   23855 
   23856 	kd = isc_mem_get(zone->mctx, sizeof(*kd));
   23857 	*kd = (struct keydone){ .all = false };
   23858 
   23859 	if (strcasecmp(keystr, "all") == 0) {
   23860 		kd->all = true;
   23861 	} else {
   23862 		isc_textregion_t r;
   23863 		const char *algstr = NULL;
   23864 		dns_keytag_t keyid;
   23865 		dns_secalg_t alg;
   23866 		size_t n;
   23867 
   23868 		n = sscanf(keystr, "%hu/", &keyid);
   23869 		if (n == 0U) {
   23870 			CHECK(ISC_R_FAILURE);
   23871 		}
   23872 
   23873 		algstr = strchr(keystr, '/');
   23874 		if (algstr != NULL) {
   23875 			algstr++;
   23876 		} else {
   23877 			CHECK(ISC_R_FAILURE);
   23878 		}
   23879 
   23880 		n = sscanf(algstr, "%hhu", &alg);
   23881 		if (n == 0U) {
   23882 			r.base = UNCONST(algstr);
   23883 			r.length = strlen(algstr);
   23884 			CHECK(dns_secalg_fromtext(&alg, &r));
   23885 		}
   23886 
   23887 		/* construct a private-type rdata */
   23888 		isc_buffer_init(&b, kd->data, sizeof(kd->data));
   23889 		isc_buffer_putuint8(&b, alg);
   23890 		isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
   23891 		isc_buffer_putuint8(&b, keyid & 0xff);
   23892 		isc_buffer_putuint8(&b, 0);
   23893 		isc_buffer_putuint8(&b, 1);
   23894 	}
   23895 
   23896 	zone_iattach(zone, &kd->zone);
   23897 	isc_async_run(zone->loop, keydone, kd);
   23898 	kd = NULL;
   23899 
   23900 cleanup:
   23901 	if (kd != NULL) {
   23902 		isc_mem_put(zone->mctx, kd, sizeof(*kd));
   23903 	}
   23904 	UNLOCK_ZONE(zone);
   23905 	return result;
   23906 }
   23907 
   23908 /*
   23909  * Called from the zone loop's queue after the relevant event is posted by
   23910  * dns_zone_setnsec3param().
   23911  */
   23912 static void
   23913 setnsec3param(void *arg) {
   23914 	struct np3 *npe = (struct np3 *)arg;
   23915 	dns_zone_t *zone = npe->zone;
   23916 	bool loadpending;
   23917 
   23918 	INSIST(DNS_ZONE_VALID(zone));
   23919 
   23920 	ENTER;
   23921 
   23922 	LOCK_ZONE(zone);
   23923 	loadpending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
   23924 	UNLOCK_ZONE(zone);
   23925 
   23926 	/*
   23927 	 * The receive_secure_serial() and setnsec3param() calls are
   23928 	 * loop-serialized for the zone. Make sure there's no processing
   23929 	 * currently running.
   23930 	 */
   23931 	INSIST(zone->rss_newver == NULL);
   23932 
   23933 	bool rescheduled = false;
   23934 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   23935 	/*
   23936 	 * The zone is not yet fully loaded. Reschedule the event to
   23937 	 * be picked up later. This turns this function into a busy
   23938 	 * wait, but it only happens at startup.
   23939 	 */
   23940 	if (zone->db == NULL && loadpending) {
   23941 		rescheduled = true;
   23942 		isc_async_run(zone->loop, setnsec3param, npe);
   23943 	}
   23944 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   23945 	if (rescheduled) {
   23946 		return;
   23947 	}
   23948 
   23949 	rss_post(npe);
   23950 
   23951 	dns_zone_idetach(&zone);
   23952 }
   23953 
   23954 static void
   23955 salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text,
   23956 	  unsigned int textlen) {
   23957 	isc_region_t r;
   23958 	isc_buffer_t buf;
   23959 	isc_result_t result;
   23960 
   23961 	r.base = salt;
   23962 	r.length = (unsigned int)saltlen;
   23963 
   23964 	isc_buffer_init(&buf, text, textlen);
   23965 	result = isc_hex_totext(&r, 2, "", &buf);
   23966 	if (result == ISC_R_SUCCESS) {
   23967 		text[saltlen * 2] = 0;
   23968 	} else {
   23969 		text[0] = 0;
   23970 	}
   23971 }
   23972 
   23973 /*
   23974  * Check whether NSEC3 chain addition or removal specified by the private-type
   23975  * record passed with the event was already queued (or even fully performed).
   23976  * If not, modify the relevant private-type records at the zone apex and call
   23977  * resume_addnsec3chain().
   23978  */
   23979 static void
   23980 rss_post(void *arg) {
   23981 	struct np3 *npe = (struct np3 *)arg;
   23982 	dns_zone_t *zone = npe->zone;
   23983 	nsec3param_t *np = &npe->params;
   23984 	bool commit = false;
   23985 	isc_result_t result;
   23986 	dns_dbversion_t *oldver = NULL, *newver = NULL;
   23987 	dns_db_t *db = NULL;
   23988 	dns_dbnode_t *node = NULL;
   23989 	dns_rdataset_t prdataset, nrdataset;
   23990 	dns_diff_t diff;
   23991 	dns_update_log_t log = { update_log_cb, NULL };
   23992 	dns_rdata_t rdata;
   23993 	bool nseconly;
   23994 	bool exists = false;
   23995 
   23996 	ENTER;
   23997 
   23998 	dns_rdataset_init(&prdataset);
   23999 	dns_rdataset_init(&nrdataset);
   24000 	dns_diff_init(zone->mctx, &diff);
   24001 
   24002 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   24003 	if (zone->db != NULL) {
   24004 		dns_db_attach(zone->db, &db);
   24005 	}
   24006 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   24007 	if (db == NULL) {
   24008 		goto cleanup;
   24009 	}
   24010 
   24011 	dns_db_currentversion(db, &oldver);
   24012 	result = dns_db_newversion(db, &newver);
   24013 	if (result != ISC_R_SUCCESS) {
   24014 		dnssec_log(zone, ISC_LOG_ERROR,
   24015 			   "setnsec3param:dns_db_newversion -> %s",
   24016 			   isc_result_totext(result));
   24017 		goto cleanup;
   24018 	}
   24019 
   24020 	CHECK(dns_db_getoriginnode(db, &node));
   24021 
   24022 	/*
   24023 	 * Do we need to look up the NSEC3 parameters?
   24024 	 */
   24025 	if (np->lookup) {
   24026 		dns_rdata_nsec3param_t param;
   24027 		dns_rdata_t nrdata = DNS_RDATA_INIT;
   24028 		dns_rdata_t prdata = DNS_RDATA_INIT;
   24029 		unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
   24030 		unsigned char saltbuf[255];
   24031 		isc_buffer_t b;
   24032 
   24033 		param.salt = NULL;
   24034 		result = dns__zone_lookup_nsec3param(zone, &np->rdata, &param,
   24035 						     saltbuf, np->resalt);
   24036 		if (result == ISC_R_SUCCESS) {
   24037 			/*
   24038 			 * Success because the NSEC3PARAM already exists, but
   24039 			 * function returns void, so goto cleanup.
   24040 			 */
   24041 			goto cleanup;
   24042 		}
   24043 		if (result != DNS_R_NSEC3RESALT && result != ISC_R_NOTFOUND) {
   24044 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   24045 				   "setnsec3param:lookup nsec3param -> %s",
   24046 				   isc_result_totext(result));
   24047 			goto cleanup;
   24048 		}
   24049 
   24050 		INSIST(param.salt != NULL);
   24051 
   24052 		/* Update NSEC3 parameters. */
   24053 		np->rdata.hash = param.hash;
   24054 		np->rdata.flags = param.flags;
   24055 		np->rdata.iterations = param.iterations;
   24056 		np->rdata.salt_length = param.salt_length;
   24057 		np->rdata.salt = param.salt;
   24058 
   24059 		isc_buffer_init(&b, nbuf, sizeof(nbuf));
   24060 		CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
   24061 					   dns_rdatatype_nsec3param, &np->rdata,
   24062 					   &b));
   24063 		dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
   24064 					 np->data, sizeof(np->data));
   24065 		np->length = prdata.length;
   24066 		np->nsec = false;
   24067 	}
   24068 
   24069 	/*
   24070 	 * Does a private-type record already exist for this chain?
   24071 	 */
   24072 	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
   24073 				     dns_rdatatype_none, 0, &prdataset, NULL);
   24074 	if (result == ISC_R_SUCCESS) {
   24075 		for (result = dns_rdataset_first(&prdataset);
   24076 		     result == ISC_R_SUCCESS;
   24077 		     result = dns_rdataset_next(&prdataset))
   24078 		{
   24079 			dns_rdata_init(&rdata);
   24080 			dns_rdataset_current(&prdataset, &rdata);
   24081 
   24082 			if (np->length == rdata.length &&
   24083 			    memcmp(rdata.data, np->data, np->length) == 0)
   24084 			{
   24085 				exists = true;
   24086 				break;
   24087 			}
   24088 		}
   24089 	} else if (result != ISC_R_NOTFOUND) {
   24090 		INSIST(!dns_rdataset_isassociated(&prdataset));
   24091 		goto cleanup;
   24092 	}
   24093 
   24094 	/*
   24095 	 * Does the chain already exist?
   24096 	 */
   24097 	result = dns_db_findrdataset(db, node, newver, dns_rdatatype_nsec3param,
   24098 				     dns_rdatatype_none, 0, &nrdataset, NULL);
   24099 	if (result == ISC_R_SUCCESS) {
   24100 		for (result = dns_rdataset_first(&nrdataset);
   24101 		     result == ISC_R_SUCCESS;
   24102 		     result = dns_rdataset_next(&nrdataset))
   24103 		{
   24104 			dns_rdata_init(&rdata);
   24105 			dns_rdataset_current(&nrdataset, &rdata);
   24106 
   24107 			if (np->length == ((unsigned int)rdata.length + 1) &&
   24108 			    memcmp(rdata.data, np->data + 1, np->length - 1) ==
   24109 				    0)
   24110 			{
   24111 				exists = true;
   24112 				break;
   24113 			}
   24114 		}
   24115 	} else if (result != ISC_R_NOTFOUND) {
   24116 		INSIST(!dns_rdataset_isassociated(&nrdataset));
   24117 		goto cleanup;
   24118 	}
   24119 
   24120 	/*
   24121 	 * We need to remove any existing NSEC3 chains if the supplied NSEC3
   24122 	 * parameters are supposed to replace the current ones or if we are
   24123 	 * switching to NSEC.
   24124 	 */
   24125 	if (!exists && np->replace && (np->length != 0 || np->nsec)) {
   24126 		CHECK(dns_nsec3param_deletechains(db, newver, zone, !np->nsec,
   24127 						  &diff));
   24128 	}
   24129 
   24130 	if (!exists && np->length != 0) {
   24131 		/*
   24132 		 * We're creating an NSEC3 chain.  Add the private-type record
   24133 		 * passed in the event handler's argument to the zone apex.
   24134 		 *
   24135 		 * If the zone is not currently capable of supporting an NSEC3
   24136 		 * chain (due to the DNSKEY RRset at the zone apex not existing
   24137 		 * or containing at least one key using an NSEC-only
   24138 		 * algorithm), add the INITIAL flag, so these parameters can be
   24139 		 * used later when NSEC3 becomes available.
   24140 		 */
   24141 		dns_rdata_init(&rdata);
   24142 
   24143 		np->data[2] |= DNS_NSEC3FLAG_CREATE;
   24144 		result = dns_nsec_nseconly(db, newver, NULL, &nseconly);
   24145 		if (result == ISC_R_NOTFOUND || nseconly) {
   24146 			np->data[2] |= DNS_NSEC3FLAG_INITIAL;
   24147 		}
   24148 
   24149 		rdata.length = np->length;
   24150 		rdata.data = np->data;
   24151 		rdata.type = zone->privatetype;
   24152 		rdata.rdclass = zone->rdclass;
   24153 		CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
   24154 				    &zone->origin, 0, &rdata));
   24155 	}
   24156 
   24157 	/*
   24158 	 * If we changed anything in the zone, write changes to journal file
   24159 	 * and set commit to true so that resume_addnsec3chain() will be
   24160 	 * called below in order to kick off adding/removing relevant NSEC3
   24161 	 * records.
   24162 	 */
   24163 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   24164 		CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
   24165 					zone->updatemethod));
   24166 		result = dns_update_signatures(&log, zone, db, oldver, newver,
   24167 					       &diff,
   24168 					       zone->sigvalidityinterval);
   24169 		if (result != ISC_R_NOTFOUND) {
   24170 			CHECK(result);
   24171 		}
   24172 		CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
   24173 		commit = true;
   24174 
   24175 		LOCK_ZONE(zone);
   24176 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   24177 		zone_needdump(zone, 30);
   24178 		UNLOCK_ZONE(zone);
   24179 	}
   24180 
   24181 cleanup:
   24182 	if (dns_rdataset_isassociated(&prdataset)) {
   24183 		dns_rdataset_disassociate(&prdataset);
   24184 	}
   24185 	if (dns_rdataset_isassociated(&nrdataset)) {
   24186 		dns_rdataset_disassociate(&nrdataset);
   24187 	}
   24188 	if (node != NULL) {
   24189 		dns_db_detachnode(db, &node);
   24190 	}
   24191 	if (oldver != NULL) {
   24192 		dns_db_closeversion(db, &oldver, false);
   24193 	}
   24194 	if (newver != NULL) {
   24195 		dns_db_closeversion(db, &newver, commit);
   24196 	}
   24197 	if (db != NULL) {
   24198 		dns_db_detach(&db);
   24199 	}
   24200 	if (commit) {
   24201 		LOCK_ZONE(zone);
   24202 		resume_addnsec3chain(zone);
   24203 		UNLOCK_ZONE(zone);
   24204 	}
   24205 	dns_diff_clear(&diff);
   24206 	isc_mem_put(zone->mctx, npe, sizeof(*npe));
   24207 
   24208 	INSIST(oldver == NULL);
   24209 	INSIST(newver == NULL);
   24210 }
   24211 
   24212 /*
   24213  * Check if zone has NSEC3PARAM (and thus a chain) with the right parameters.
   24214  *
   24215  * If 'salt' is NULL, a match is found if the salt has the requested length,
   24216  * otherwise the NSEC3 salt must match the requested salt value too.
   24217  *
   24218  * Returns  ISC_R_SUCCESS, if a match is found, or an error if no match is
   24219  * found, or if the db lookup failed.
   24220  */
   24221 isc_result_t
   24222 dns__zone_lookup_nsec3param(dns_zone_t *zone, dns_rdata_nsec3param_t *lookup,
   24223 			    dns_rdata_nsec3param_t *param,
   24224 			    unsigned char saltbuf[255], bool resalt) {
   24225 	isc_result_t result = ISC_R_UNEXPECTED;
   24226 	dns_dbnode_t *node = NULL;
   24227 	dns_db_t *db = NULL;
   24228 	dns_dbversion_t *version = NULL;
   24229 	dns_rdataset_t rdataset;
   24230 	dns_rdata_nsec3param_t nsec3param;
   24231 	dns_rdata_t rdata = DNS_RDATA_INIT;
   24232 
   24233 	REQUIRE(DNS_ZONE_VALID(zone));
   24234 
   24235 	dns_rdataset_init(&rdataset);
   24236 
   24237 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   24238 	if (zone->db != NULL) {
   24239 		dns_db_attach(zone->db, &db);
   24240 	}
   24241 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   24242 	if (db == NULL) {
   24243 		result = ISC_R_FAILURE;
   24244 		goto setparam;
   24245 	}
   24246 
   24247 	result = dns_db_findnode(db, &zone->origin, false, &node);
   24248 	if (result != ISC_R_SUCCESS) {
   24249 		dns_zone_log(zone, ISC_LOG_ERROR,
   24250 			     "dns__zone_lookup_nsec3param:"
   24251 			     "dns_db_findnode -> %s",
   24252 			     isc_result_totext(result));
   24253 		result = ISC_R_FAILURE;
   24254 		goto setparam;
   24255 	}
   24256 	dns_db_currentversion(db, &version);
   24257 
   24258 	result = dns_db_findrdataset(db, node, version,
   24259 				     dns_rdatatype_nsec3param,
   24260 				     dns_rdatatype_none, 0, &rdataset, NULL);
   24261 	if (result != ISC_R_SUCCESS) {
   24262 		INSIST(!dns_rdataset_isassociated(&rdataset));
   24263 		if (result != ISC_R_NOTFOUND) {
   24264 			dns_zone_log(zone, ISC_LOG_ERROR,
   24265 				     "dns__zone_lookup_nsec3param:"
   24266 				     "dns_db_findrdataset -> %s",
   24267 				     isc_result_totext(result));
   24268 		}
   24269 		goto setparam;
   24270 	}
   24271 
   24272 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
   24273 	     result = dns_rdataset_next(&rdataset))
   24274 	{
   24275 		dns_rdataset_current(&rdataset, &rdata);
   24276 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   24277 		INSIST(result == ISC_R_SUCCESS);
   24278 		dns_rdata_reset(&rdata);
   24279 
   24280 		/* Check parameters. */
   24281 		if (nsec3param.hash != lookup->hash) {
   24282 			continue;
   24283 		}
   24284 		if (nsec3param.iterations != lookup->iterations) {
   24285 			continue;
   24286 		}
   24287 		if (nsec3param.salt_length != lookup->salt_length) {
   24288 			continue;
   24289 		}
   24290 		if (lookup->salt != NULL) {
   24291 			if (memcmp(nsec3param.salt, lookup->salt,
   24292 				   lookup->salt_length) != 0)
   24293 			{
   24294 				continue;
   24295 			}
   24296 		}
   24297 		/* Found a match. */
   24298 		result = ISC_R_SUCCESS;
   24299 		param->hash = nsec3param.hash;
   24300 		param->flags = nsec3param.flags;
   24301 		param->iterations = nsec3param.iterations;
   24302 		param->salt_length = nsec3param.salt_length;
   24303 		param->salt = nsec3param.salt;
   24304 		break;
   24305 	}
   24306 
   24307 	if (result == ISC_R_NOMORE) {
   24308 		result = ISC_R_NOTFOUND;
   24309 	}
   24310 
   24311 setparam:
   24312 	if (result != ISC_R_SUCCESS) {
   24313 		/* Found no match. */
   24314 		param->hash = lookup->hash;
   24315 		param->flags = lookup->flags;
   24316 		param->iterations = lookup->iterations;
   24317 		param->salt_length = lookup->salt_length;
   24318 		param->salt = lookup->salt;
   24319 	}
   24320 
   24321 	if (result != ISC_R_NOTFOUND) {
   24322 		CHECK(result);
   24323 	}
   24324 
   24325 	if (param->salt_length == 0) {
   24326 		param->salt = (unsigned char *)"-";
   24327 	} else if (resalt || param->salt == NULL) {
   24328 		unsigned char *newsalt;
   24329 		unsigned char salttext[255 * 2 + 1];
   24330 		do {
   24331 			/* Generate a new salt. */
   24332 			result = dns_nsec3_generate_salt(saltbuf,
   24333 							 param->salt_length);
   24334 			if (result != ISC_R_SUCCESS) {
   24335 				break;
   24336 			}
   24337 			newsalt = saltbuf;
   24338 			salt2text(newsalt, param->salt_length, salttext,
   24339 				  sizeof(salttext));
   24340 			dnssec_log(zone, ISC_LOG_INFO, "generated salt: %s",
   24341 				   salttext);
   24342 			/* Check for salt conflict. */
   24343 			if (param->salt != NULL &&
   24344 			    memcmp(newsalt, param->salt, param->salt_length) ==
   24345 				    0)
   24346 			{
   24347 				result = ISC_R_SUCCESS;
   24348 			} else {
   24349 				param->salt = newsalt;
   24350 				result = DNS_R_NSEC3RESALT;
   24351 			}
   24352 		} while (result == ISC_R_SUCCESS);
   24353 
   24354 		INSIST(result != ISC_R_SUCCESS);
   24355 	}
   24356 
   24357 cleanup:
   24358 	if (dns_rdataset_isassociated(&rdataset)) {
   24359 		dns_rdataset_disassociate(&rdataset);
   24360 	}
   24361 	if (node != NULL) {
   24362 		dns_db_detachnode(db, &node);
   24363 	}
   24364 	if (version != NULL) {
   24365 		dns_db_closeversion(db, &version, false);
   24366 	}
   24367 	if (db != NULL) {
   24368 		dns_db_detach(&db);
   24369 	}
   24370 
   24371 	return result;
   24372 }
   24373 
   24374 /*
   24375  * Called when an "rndc signing -nsec3param ..." command is received, or the
   24376  * 'dnssec-policy' has changed.
   24377  *
   24378  * Allocate and prepare an nsec3param_t structure which holds information about
   24379  * the NSEC3 changes requested for the zone:
   24380  *
   24381  *   - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
   24382  *     field of the structure to true and the "replace" field to the value
   24383  *     of the "replace" argument, leaving other fields initialized to zeros, to
   24384  *     signal that the zone should be signed using NSEC instead of NSEC3,
   24385  *
   24386  *   - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
   24387  *     the zone apex, convert it to a private-type record and store the latter
   24388  *     in the "data" field of the nsec3param_t structure.
   24389  *
   24390  * Once the nsec3param_t structure is prepared, post an event to the zone's
   24391  * loop which will cause setnsec3param() to be called with the prepared
   24392  * structure passed as an argument.
   24393  */
   24394 isc_result_t
   24395 dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
   24396 		       uint16_t iter, uint8_t saltlen, unsigned char *salt,
   24397 		       bool replace, bool resalt) {
   24398 	isc_result_t result = ISC_R_SUCCESS;
   24399 	dns_rdata_nsec3param_t param, lookup;
   24400 	dns_rdata_t nrdata = DNS_RDATA_INIT;
   24401 	dns_rdata_t prdata = DNS_RDATA_INIT;
   24402 	unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
   24403 	unsigned char saltbuf[255];
   24404 	struct np3 *npe = NULL;
   24405 	nsec3param_t *np = NULL;
   24406 	isc_buffer_t b;
   24407 	bool do_lookup = false;
   24408 
   24409 	REQUIRE(DNS_ZONE_VALID(zone));
   24410 
   24411 	LOCK_ZONE(zone);
   24412 
   24413 	/*
   24414 	 * First check if the requested NSEC3 parameters are already
   24415 	 * set, if so, no need to set again.
   24416 	 */
   24417 	if (hash != 0) {
   24418 		lookup.hash = hash;
   24419 		lookup.flags = flags;
   24420 		lookup.iterations = iter;
   24421 		lookup.salt_length = saltlen;
   24422 		lookup.salt = salt;
   24423 		param.salt = NULL;
   24424 		result = dns__zone_lookup_nsec3param(zone, &lookup, &param,
   24425 						     saltbuf, resalt);
   24426 		if (result == ISC_R_SUCCESS) {
   24427 			UNLOCK_ZONE(zone);
   24428 			return ISC_R_SUCCESS;
   24429 		}
   24430 		/*
   24431 		 * Schedule lookup if lookup above failed (may happen if
   24432 		 * zone db is NULL for example).
   24433 		 */
   24434 		do_lookup = (param.salt == NULL) ? true : false;
   24435 	}
   24436 
   24437 	npe = isc_mem_get(zone->mctx, sizeof(*npe));
   24438 	*npe = (struct np3){
   24439 		.link = ISC_LINK_INITIALIZER,
   24440 	};
   24441 
   24442 	np = &npe->params;
   24443 	*np = (struct nsec3param){
   24444 		.replace = replace,
   24445 		.resalt = resalt,
   24446 		.lookup = do_lookup,
   24447 	};
   24448 
   24449 	if (hash == 0) {
   24450 		np->nsec = true;
   24451 		dnssec_log(zone, ISC_LOG_DEBUG(3), "setnsec3param:nsec");
   24452 	} else {
   24453 		param.common.rdclass = zone->rdclass;
   24454 		param.common.rdtype = dns_rdatatype_nsec3param;
   24455 		ISC_LINK_INIT(&param.common, link);
   24456 		param.mctx = NULL;
   24457 		/*
   24458 		 * nsec3 specific param set in
   24459 		 * dns__zone_lookup_nsec3param()
   24460 		 */
   24461 		isc_buffer_init(&b, nbuf, sizeof(nbuf));
   24462 
   24463 		if (param.salt != NULL) {
   24464 			CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
   24465 						   dns_rdatatype_nsec3param,
   24466 						   &param, &b));
   24467 			dns_nsec3param_toprivate(&nrdata, &prdata,
   24468 						 zone->privatetype, np->data,
   24469 						 sizeof(np->data));
   24470 			np->length = prdata.length;
   24471 		}
   24472 
   24473 		np->rdata = param;
   24474 
   24475 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   24476 			unsigned char salttext[255 * 2 + 1];
   24477 			if (param.salt != NULL) {
   24478 				salt2text(param.salt, param.salt_length,
   24479 					  salttext, sizeof(salttext));
   24480 			}
   24481 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   24482 				   "setnsec3param:nsec3 %u %u %u %u:%s",
   24483 				   param.hash, param.flags, param.iterations,
   24484 				   param.salt_length,
   24485 				   param.salt == NULL ? "unknown"
   24486 						      : (char *)salttext);
   24487 		}
   24488 	}
   24489 
   24490 	/*
   24491 	 * setnsec3param() will silently return early if the zone does
   24492 	 * not yet have a database.  Prevent that by queueing the event
   24493 	 * up if zone->db is NULL.  All events queued here are
   24494 	 * subsequently processed by receive_secure_db() if it ever gets
   24495 	 * called or simply freed by zone_free() otherwise.
   24496 	 */
   24497 
   24498 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   24499 	if (zone->db != NULL) {
   24500 		zone_iattach(zone, &npe->zone);
   24501 		isc_async_run(zone->loop, setnsec3param, npe);
   24502 	} else {
   24503 		ISC_LIST_APPEND(zone->setnsec3param_queue, npe, link);
   24504 	}
   24505 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   24506 
   24507 	result = ISC_R_SUCCESS;
   24508 
   24509 cleanup:
   24510 	UNLOCK_ZONE(zone);
   24511 	return result;
   24512 }
   24513 
   24514 isc_result_t
   24515 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
   24516 	REQUIRE(DNS_ZONE_VALID(zone));
   24517 	REQUIRE(loadtime != NULL);
   24518 
   24519 	LOCK_ZONE(zone);
   24520 	*loadtime = zone->loadtime;
   24521 	UNLOCK_ZONE(zone);
   24522 	return ISC_R_SUCCESS;
   24523 }
   24524 
   24525 isc_result_t
   24526 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
   24527 	REQUIRE(DNS_ZONE_VALID(zone));
   24528 	REQUIRE(expiretime != NULL);
   24529 
   24530 	LOCK_ZONE(zone);
   24531 	*expiretime = zone->expiretime;
   24532 	UNLOCK_ZONE(zone);
   24533 	return ISC_R_SUCCESS;
   24534 }
   24535 
   24536 isc_result_t
   24537 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
   24538 	REQUIRE(DNS_ZONE_VALID(zone));
   24539 	REQUIRE(refreshtime != NULL);
   24540 
   24541 	LOCK_ZONE(zone);
   24542 	*refreshtime = zone->refreshtime;
   24543 	UNLOCK_ZONE(zone);
   24544 	return ISC_R_SUCCESS;
   24545 }
   24546 
   24547 isc_result_t
   24548 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
   24549 	REQUIRE(DNS_ZONE_VALID(zone));
   24550 	REQUIRE(refreshkeytime != NULL);
   24551 
   24552 	LOCK_ZONE(zone);
   24553 	*refreshkeytime = zone->refreshkeytime;
   24554 	UNLOCK_ZONE(zone);
   24555 	return ISC_R_SUCCESS;
   24556 }
   24557 
   24558 unsigned int
   24559 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
   24560 	dns_include_t *include;
   24561 	char **array = NULL;
   24562 	unsigned int n = 0;
   24563 
   24564 	REQUIRE(DNS_ZONE_VALID(zone));
   24565 	REQUIRE(includesp != NULL && *includesp == NULL);
   24566 
   24567 	LOCK_ZONE(zone);
   24568 	if (zone->nincludes == 0) {
   24569 		goto done;
   24570 	}
   24571 
   24572 	array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
   24573 	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
   24574 	     include = ISC_LIST_NEXT(include, link))
   24575 	{
   24576 		INSIST(n < zone->nincludes);
   24577 		array[n++] = isc_mem_strdup(zone->mctx, include->name);
   24578 	}
   24579 	INSIST(n == zone->nincludes);
   24580 	*includesp = array;
   24581 
   24582 done:
   24583 	UNLOCK_ZONE(zone);
   24584 	return n;
   24585 }
   24586 
   24587 void
   24588 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
   24589 	REQUIRE(DNS_ZONE_VALID(zone));
   24590 
   24591 	zone->statlevel = level;
   24592 }
   24593 
   24594 dns_zonestat_level_t
   24595 dns_zone_getstatlevel(dns_zone_t *zone) {
   24596 	REQUIRE(DNS_ZONE_VALID(zone));
   24597 
   24598 	return zone->statlevel;
   24599 }
   24600 
   24601 static void
   24602 setserial(void *arg) {
   24603 	uint32_t oldserial, desired;
   24604 	bool commit = false;
   24605 	isc_result_t result;
   24606 	dns_dbversion_t *oldver = NULL, *newver = NULL;
   24607 	dns_db_t *db = NULL;
   24608 	dns_diff_t diff;
   24609 	struct setserial *sse = (struct setserial *)arg;
   24610 	dns_zone_t *zone = sse->zone;
   24611 	dns_update_log_t log = { update_log_cb, NULL };
   24612 	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
   24613 
   24614 	INSIST(DNS_ZONE_VALID(zone));
   24615 
   24616 	ENTER;
   24617 
   24618 	if (zone->update_disabled) {
   24619 		goto disabled;
   24620 	}
   24621 
   24622 	desired = sse->serial;
   24623 
   24624 	dns_diff_init(zone->mctx, &diff);
   24625 
   24626 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   24627 	if (zone->db != NULL) {
   24628 		dns_db_attach(zone->db, &db);
   24629 	}
   24630 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   24631 	if (db == NULL) {
   24632 		goto cleanup;
   24633 	}
   24634 
   24635 	dns_db_currentversion(db, &oldver);
   24636 	result = dns_db_newversion(db, &newver);
   24637 	if (result != ISC_R_SUCCESS) {
   24638 		dns_zone_log(zone, ISC_LOG_ERROR,
   24639 			     "setserial:dns_db_newversion -> %s",
   24640 			     isc_result_totext(result));
   24641 		goto cleanup;
   24642 	}
   24643 
   24644 	CHECK(dns_db_createsoatuple(db, oldver, diff.mctx, DNS_DIFFOP_DEL,
   24645 				    &oldtuple));
   24646 	CHECK(dns_difftuple_copy(oldtuple, &newtuple));
   24647 	newtuple->op = DNS_DIFFOP_ADD;
   24648 
   24649 	oldserial = dns_soa_getserial(&oldtuple->rdata);
   24650 	if (desired == 0U) {
   24651 		desired = 1;
   24652 	}
   24653 	if (!isc_serial_gt(desired, oldserial)) {
   24654 		if (desired != oldserial) {
   24655 			dns_zone_log(zone, ISC_LOG_INFO,
   24656 				     "setserial: desired serial (%u) "
   24657 				     "out of range (%u-%u)",
   24658 				     desired, oldserial + 1,
   24659 				     oldserial + 0x7fffffff);
   24660 		}
   24661 		goto cleanup;
   24662 	}
   24663 
   24664 	dns_soa_setserial(desired, &newtuple->rdata);
   24665 	CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
   24666 	CHECK(do_one_tuple(&newtuple, db, newver, &diff));
   24667 	result = dns_update_signatures(&log, zone, db, oldver, newver, &diff,
   24668 				       zone->sigvalidityinterval);
   24669 	if (result != ISC_R_NOTFOUND) {
   24670 		CHECK(result);
   24671 	}
   24672 
   24673 	/* Write changes to journal file. */
   24674 	CHECK(zone_journal(zone, &diff, NULL, "setserial"));
   24675 	commit = true;
   24676 
   24677 	LOCK_ZONE(zone);
   24678 	zone_needdump(zone, 30);
   24679 	UNLOCK_ZONE(zone);
   24680 
   24681 cleanup:
   24682 	if (oldtuple != NULL) {
   24683 		dns_difftuple_free(&oldtuple);
   24684 	}
   24685 	if (newtuple != NULL) {
   24686 		dns_difftuple_free(&newtuple);
   24687 	}
   24688 	if (oldver != NULL) {
   24689 		dns_db_closeversion(db, &oldver, false);
   24690 	}
   24691 	if (newver != NULL) {
   24692 		dns_db_closeversion(db, &newver, commit);
   24693 	}
   24694 	if (db != NULL) {
   24695 		dns_db_detach(&db);
   24696 	}
   24697 	dns_diff_clear(&diff);
   24698 
   24699 disabled:
   24700 	isc_mem_put(zone->mctx, sse, sizeof(*sse));
   24701 	dns_zone_idetach(&zone);
   24702 
   24703 	INSIST(oldver == NULL);
   24704 	INSIST(newver == NULL);
   24705 }
   24706 
   24707 isc_result_t
   24708 dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
   24709 	isc_result_t result = ISC_R_SUCCESS;
   24710 	struct setserial *sse = NULL;
   24711 
   24712 	REQUIRE(DNS_ZONE_VALID(zone));
   24713 
   24714 	LOCK_ZONE(zone);
   24715 
   24716 	if (!inline_secure(zone)) {
   24717 		if (!dns_zone_isdynamic(zone, true)) {
   24718 			CHECK(DNS_R_NOTDYNAMIC);
   24719 		}
   24720 	}
   24721 
   24722 	if (zone->update_disabled) {
   24723 		CHECK(DNS_R_FROZEN);
   24724 	}
   24725 
   24726 	sse = isc_mem_get(zone->mctx, sizeof(*sse));
   24727 	*sse = (struct setserial){ .serial = serial };
   24728 	zone_iattach(zone, &sse->zone);
   24729 	isc_async_run(zone->loop, setserial, sse);
   24730 
   24731 cleanup:
   24732 	UNLOCK_ZONE(zone);
   24733 	return result;
   24734 }
   24735 
   24736 isc_stats_t *
   24737 dns_zone_getgluecachestats(dns_zone_t *zone) {
   24738 	REQUIRE(DNS_ZONE_VALID(zone));
   24739 
   24740 	return zone->gluecachestats;
   24741 }
   24742 
   24743 bool
   24744 dns_zone_isloaded(dns_zone_t *zone) {
   24745 	REQUIRE(DNS_ZONE_VALID(zone));
   24746 
   24747 	return DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED);
   24748 }
   24749 
   24750 isc_result_t
   24751 dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
   24752 	dns_dbversion_t *version = NULL;
   24753 	dns_keytable_t *secroots = NULL;
   24754 	isc_result_t result;
   24755 	dns_name_t *origin;
   24756 
   24757 	REQUIRE(DNS_ZONE_VALID(zone));
   24758 	REQUIRE(db != NULL);
   24759 
   24760 	ENTER;
   24761 
   24762 	if (dns_zone_gettype(zone) != dns_zone_mirror) {
   24763 		return ISC_R_SUCCESS;
   24764 	}
   24765 
   24766 	if (ver == NULL) {
   24767 		dns_db_currentversion(db, &version);
   24768 	} else {
   24769 		version = ver;
   24770 	}
   24771 
   24772 	if (zone->view != NULL) {
   24773 		result = dns_view_getsecroots(zone->view, &secroots);
   24774 		CHECK(result);
   24775 	}
   24776 
   24777 	origin = dns_db_origin(db);
   24778 	result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
   24779 				       zone->mctx, true, false, dnssec_report);
   24780 
   24781 cleanup:
   24782 	if (secroots != NULL) {
   24783 		dns_keytable_detach(&secroots);
   24784 	}
   24785 
   24786 	if (ver == NULL) {
   24787 		dns_db_closeversion(db, &version, false);
   24788 	}
   24789 
   24790 	if (result != ISC_R_SUCCESS) {
   24791 		dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
   24792 			   isc_result_totext(result));
   24793 		result = DNS_R_VERIFYFAILURE;
   24794 	}
   24795 
   24796 	return result;
   24797 }
   24798 
   24799 static dns_ttl_t
   24800 zone_nsecttl(dns_zone_t *zone) {
   24801 	REQUIRE(DNS_ZONE_VALID(zone));
   24802 
   24803 	return ISC_MIN(zone->minimum, zone->soattl);
   24804 }
   24805 
   24806 void
   24807 dns_zonemgr_set_tlsctx_cache(dns_zonemgr_t *zmgr,
   24808 			     isc_tlsctx_cache_t *tlsctx_cache) {
   24809 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   24810 	REQUIRE(tlsctx_cache != NULL);
   24811 
   24812 	RWLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_write);
   24813 
   24814 	if (zmgr->tlsctx_cache != NULL) {
   24815 		isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
   24816 	}
   24817 
   24818 	isc_tlsctx_cache_attach(tlsctx_cache, &zmgr->tlsctx_cache);
   24819 
   24820 	RWUNLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_write);
   24821 }
   24822 
   24823 static void
   24824 zmgr_tlsctx_attach(dns_zonemgr_t *zmgr, isc_tlsctx_cache_t **ptlsctx_cache) {
   24825 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   24826 	REQUIRE(ptlsctx_cache != NULL && *ptlsctx_cache == NULL);
   24827 
   24828 	RWLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_read);
   24829 
   24830 	INSIST(zmgr->tlsctx_cache != NULL);
   24831 	isc_tlsctx_cache_attach(zmgr->tlsctx_cache, ptlsctx_cache);
   24832 
   24833 	RWUNLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_read);
   24834 }
   24835 
   24836 isc_mem_t *
   24837 dns_zone_getmem(dns_zone_t *zone) {
   24838 	return zone->mctx;
   24839 }
   24840 
   24841 unsigned int
   24842 dns_zone_gettid(dns_zone_t *zone) {
   24843 	return zone->tid;
   24844 }
   24845 
   24846 isc_loop_t *
   24847 dns_zone_getloop(dns_zone_t *zone) {
   24848 	return zone->loop;
   24849 }
   24850 
   24851 isc_result_t
   24852 dns_zone_makedb(dns_zone_t *zone, dns_db_t **dbp) {
   24853 	REQUIRE(DNS_ZONE_VALID(zone));
   24854 	REQUIRE(dbp != NULL && *dbp == NULL);
   24855 
   24856 	dns_db_t *db = NULL;
   24857 
   24858 	isc_result_t result = dns_db_create(
   24859 		zone->mctx, zone->db_argv[0], &zone->origin,
   24860 		(zone->type == dns_zone_stub) ? dns_dbtype_stub
   24861 					      : dns_dbtype_zone,
   24862 		zone->rdclass, zone->db_argc - 1, zone->db_argv + 1, &db);
   24863 	if (result != ISC_R_SUCCESS) {
   24864 		return result;
   24865 	}
   24866 
   24867 	switch (zone->type) {
   24868 	case dns_zone_primary:
   24869 	case dns_zone_secondary:
   24870 	case dns_zone_mirror:
   24871 		result = dns_db_setgluecachestats(db, zone->gluecachestats);
   24872 		if (result == ISC_R_NOTIMPLEMENTED) {
   24873 			result = ISC_R_SUCCESS;
   24874 		}
   24875 		if (result != ISC_R_SUCCESS) {
   24876 			dns_db_detach(&db);
   24877 			return result;
   24878 		}
   24879 		break;
   24880 	default:
   24881 		break;
   24882 	}
   24883 
   24884 	dns_db_setloop(db, zone->loop);
   24885 	dns_db_setmaxrrperset(db, zone->maxrrperset);
   24886 	dns_db_setmaxtypepername(db, zone->maxtypepername);
   24887 
   24888 	*dbp = db;
   24889 
   24890 	return ISC_R_SUCCESS;
   24891 }
   24892 
   24893 isc_result_t
   24894 dns_zone_import_skr(dns_zone_t *zone, const char *file) {
   24895 	dns_skr_t *skr = NULL;
   24896 	isc_result_t result;
   24897 
   24898 	REQUIRE(DNS_ZONE_VALID(zone));
   24899 	REQUIRE(zone->kasp != NULL);
   24900 	REQUIRE(file != NULL);
   24901 
   24902 	dns_skr_create(zone->mctx, file, &zone->origin, zone->rdclass, &skr);
   24903 
   24904 	CHECK(dns_skr_read(zone->mctx, file, &zone->origin, zone->rdclass,
   24905 			   dns_kasp_dnskeyttl(zone->kasp), &skr));
   24906 
   24907 	dns_zone_setskr(zone, skr);
   24908 	dnssec_log(zone, ISC_LOG_DEBUG(1), "imported skr file %s", file);
   24909 
   24910 cleanup:
   24911 	dns_skr_detach(&skr);
   24912 
   24913 	return result;
   24914 }
   24915