Home | History | Annotate | Line # | Download | only in dns
zone.c revision 1.5.2.3
      1 /*	$NetBSD: zone.c,v 1.5.2.3 2020/04/13 08:02:57 martin Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * This Source Code Form is subject to the terms of the Mozilla Public
      7  * License, v. 2.0. If a copy of the MPL was not distributed with this
      8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9  *
     10  * See the COPYRIGHT file distributed with this work for additional
     11  * information regarding copyright ownership.
     12  */
     13 
     14 /*! \file */
     15 
     16 #include <config.h>
     17 
     18 #include <errno.h>
     19 #include <inttypes.h>
     20 #include <stdbool.h>
     21 
     22 #include <isc/file.h>
     23 #include <isc/hex.h>
     24 #include <isc/mutex.h>
     25 #include <isc/pool.h>
     26 #include <isc/print.h>
     27 #include <isc/random.h>
     28 #include <isc/ratelimiter.h>
     29 #include <isc/refcount.h>
     30 #include <isc/rwlock.h>
     31 #include <isc/serial.h>
     32 #include <isc/stats.h>
     33 #include <isc/stdtime.h>
     34 #include <isc/strerr.h>
     35 #include <isc/string.h>
     36 #include <isc/taskpool.h>
     37 #include <isc/thread.h>
     38 #include <isc/timer.h>
     39 #include <isc/util.h>
     40 
     41 #include <dns/acl.h>
     42 #include <dns/adb.h>
     43 #include <dns/callbacks.h>
     44 #include <dns/catz.h>
     45 #include <dns/db.h>
     46 #include <dns/dbiterator.h>
     47 #include <dns/dlz.h>
     48 #include <dns/dnssec.h>
     49 #include <dns/events.h>
     50 #include <dns/journal.h>
     51 #include <dns/keydata.h>
     52 #include <dns/keytable.h>
     53 #include <dns/keyvalues.h>
     54 #include <dns/log.h>
     55 #include <dns/master.h>
     56 #include <dns/masterdump.h>
     57 #include <dns/message.h>
     58 #include <dns/name.h>
     59 #include <dns/nsec.h>
     60 #include <dns/nsec3.h>
     61 #include <dns/peer.h>
     62 #include <dns/private.h>
     63 #include <dns/rcode.h>
     64 #include <dns/rdata.h>
     65 #include <dns/rdataclass.h>
     66 #include <dns/rdatalist.h>
     67 #include <dns/rdataset.h>
     68 #include <dns/rdatasetiter.h>
     69 #include <dns/rdatastruct.h>
     70 #include <dns/rdatatype.h>
     71 #include <dns/request.h>
     72 #include <dns/resolver.h>
     73 #include <dns/result.h>
     74 #include <dns/rriterator.h>
     75 #include <dns/soa.h>
     76 #include <dns/ssu.h>
     77 #include <dns/stats.h>
     78 #include <dns/time.h>
     79 #include <dns/tsig.h>
     80 #include <dns/update.h>
     81 #include <dns/xfrin.h>
     82 #include <dns/zone.h>
     83 #include <dns/zoneverify.h>
     84 #include <dns/zt.h>
     85 
     86 #include <dst/dst.h>
     87 
     88 #include "zone_p.h"
     89 
     90 #define ZONE_MAGIC			ISC_MAGIC('Z', 'O', 'N', 'E')
     91 #define DNS_ZONE_VALID(zone)		ISC_MAGIC_VALID(zone, ZONE_MAGIC)
     92 
     93 #define NOTIFY_MAGIC			ISC_MAGIC('N', 't', 'f', 'y')
     94 #define DNS_NOTIFY_VALID(notify)	ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
     95 
     96 #define STUB_MAGIC			ISC_MAGIC('S', 't', 'u', 'b')
     97 #define DNS_STUB_VALID(stub)		ISC_MAGIC_VALID(stub, STUB_MAGIC)
     98 
     99 #define ZONEMGR_MAGIC			ISC_MAGIC('Z', 'm', 'g', 'r')
    100 #define DNS_ZONEMGR_VALID(stub)		ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
    101 
    102 #define LOAD_MAGIC			ISC_MAGIC('L', 'o', 'a', 'd')
    103 #define DNS_LOAD_VALID(load)		ISC_MAGIC_VALID(load, LOAD_MAGIC)
    104 
    105 #define FORWARD_MAGIC			ISC_MAGIC('F', 'o', 'r', 'w')
    106 #define DNS_FORWARD_VALID(load)		ISC_MAGIC_VALID(load, FORWARD_MAGIC)
    107 
    108 #define IO_MAGIC			ISC_MAGIC('Z', 'm', 'I', 'O')
    109 #define DNS_IO_VALID(load)		ISC_MAGIC_VALID(load, IO_MAGIC)
    110 
    111 /*%
    112  * Ensure 'a' is at least 'min' but not more than 'max'.
    113  */
    114 #define RANGE(a, min, max) \
    115 		(((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
    116 
    117 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
    118 
    119 /*%
    120  * Key flags
    121  */
    122 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
    123 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
    124 #define ALG(x) dst_key_alg(x)
    125 
    126 /*
    127  * Default values.
    128  */
    129 #define DNS_DEFAULT_IDLEIN 3600		/*%< 1 hour */
    130 #define DNS_DEFAULT_IDLEOUT 3600	/*%< 1 hour */
    131 #define MAX_XFER_TIME (2*3600)		/*%< Documented default is 2 hours */
    132 #define RESIGN_DELAY 3600		/*%< 1 hour */
    133 
    134 #ifndef DNS_MAX_EXPIRE
    135 #define DNS_MAX_EXPIRE	14515200	/*%< 24 weeks */
    136 #endif
    137 
    138 #ifndef DNS_DUMP_DELAY
    139 #define DNS_DUMP_DELAY 900		/*%< 15 minutes */
    140 #endif
    141 
    142 typedef struct dns_notify dns_notify_t;
    143 typedef struct dns_stub dns_stub_t;
    144 typedef struct dns_load dns_load_t;
    145 typedef struct dns_forward dns_forward_t;
    146 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
    147 typedef struct dns_io dns_io_t;
    148 typedef ISC_LIST(dns_io_t) dns_iolist_t;
    149 typedef struct dns_signing dns_signing_t;
    150 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
    151 typedef struct dns_nsec3chain dns_nsec3chain_t;
    152 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
    153 typedef struct dns_keyfetch dns_keyfetch_t;
    154 typedef struct dns_asyncload dns_asyncload_t;
    155 typedef struct dns_include dns_include_t;
    156 
    157 #define DNS_ZONE_CHECKLOCK
    158 #ifdef DNS_ZONE_CHECKLOCK
    159 #define LOCK_ZONE(z) \
    160 	 do { LOCK(&(z)->lock); \
    161 	      INSIST((z)->locked == false); \
    162 	     (z)->locked = true; \
    163 		} while (/*CONSTCOND*/0)
    164 #define UNLOCK_ZONE(z) \
    165 	do { (z)->locked = false; UNLOCK(&(z)->lock); } while (/*CONSTCON*/0)
    166 #define LOCKED_ZONE(z) ((z)->locked)
    167 #define TRYLOCK_ZONE(result, z) \
    168 	do { \
    169 	      result = isc_mutex_trylock(&(z)->lock); \
    170 	      if (result == ISC_R_SUCCESS) {  \
    171 		     INSIST((z)->locked == false); \
    172 		     (z)->locked = true; \
    173 	      } \
    174 	} while (/*CONSTCOND*/0)
    175 #else
    176 #define LOCK_ZONE(z) LOCK(&(z)->lock)
    177 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
    178 #define LOCKED_ZONE(z) true
    179 #define TRYLOCK_ZONE(result, z) \
    180 	do { result = isc_mutex_trylock(&(z)->lock); } while (/*CONSTCOND*/0)
    181 #endif
    182 
    183 #define ZONEDB_INITLOCK(l)	isc_rwlock_init((l), 0, 0)
    184 #define ZONEDB_DESTROYLOCK(l)	isc_rwlock_destroy(l)
    185 #define ZONEDB_LOCK(l, t)	RWLOCK((l), (t))
    186 #define ZONEDB_UNLOCK(l, t)	RWUNLOCK((l), (t))
    187 
    188 #ifdef ENABLE_AFL
    189 extern bool dns_fuzzing_resolver;
    190 #endif
    191 
    192 struct dns_zone {
    193 	/* Unlocked */
    194 	unsigned int		magic;
    195 	isc_mutex_t		lock;
    196 #ifdef DNS_ZONE_CHECKLOCK
    197 	bool		locked;
    198 #endif
    199 	isc_mem_t		*mctx;
    200 	isc_refcount_t		erefs;
    201 
    202 	isc_rwlock_t		dblock;
    203 	dns_db_t		*db;		/* Locked by dblock */
    204 
    205 	/* Locked */
    206 	dns_zonemgr_t		*zmgr;
    207 	ISC_LINK(dns_zone_t)	link;		/* Used by zmgr. */
    208 	isc_timer_t		*timer;
    209 	unsigned int		irefs;
    210 	dns_name_t		origin;
    211 	char			*masterfile;
    212 	ISC_LIST(dns_include_t)	includes;	/* Include files */
    213 	ISC_LIST(dns_include_t)	newincludes;	/* Loading */
    214 	unsigned int		nincludes;
    215 	dns_masterformat_t	masterformat;
    216 	const dns_master_style_t *masterstyle;
    217 	char			*journal;
    218 	int32_t		journalsize;
    219 	dns_rdataclass_t	rdclass;
    220 	dns_zonetype_t		type;
    221 	unsigned int		flags;
    222 	dns_zoneopt_t		options;
    223 	unsigned int		db_argc;
    224 	char			**db_argv;
    225 	isc_time_t		expiretime;
    226 	isc_time_t		refreshtime;
    227 	isc_time_t		dumptime;
    228 	isc_time_t		loadtime;
    229 	isc_time_t		notifytime;
    230 	isc_time_t		resigntime;
    231 	isc_time_t		keywarntime;
    232 	isc_time_t		signingtime;
    233 	isc_time_t		nsec3chaintime;
    234 	isc_time_t		refreshkeytime;
    235 	uint32_t		refreshkeyinterval;
    236 	uint32_t		refreshkeycount;
    237 	uint32_t		refresh;
    238 	uint32_t		retry;
    239 	uint32_t		expire;
    240 	uint32_t		minimum;
    241 	isc_stdtime_t		key_expiry;
    242 	isc_stdtime_t		log_key_expired_timer;
    243 	char			*keydirectory;
    244 
    245 	uint32_t		maxrefresh;
    246 	uint32_t		minrefresh;
    247 	uint32_t		maxretry;
    248 	uint32_t		minretry;
    249 
    250 	uint32_t		maxrecords;
    251 
    252 	isc_sockaddr_t		*masters;
    253 	isc_dscp_t		*masterdscps;
    254 	dns_name_t		**masterkeynames;
    255 	bool		*mastersok;
    256 	unsigned int		masterscnt;
    257 	unsigned int		curmaster;
    258 	isc_sockaddr_t		masteraddr;
    259 	dns_notifytype_t	notifytype;
    260 	isc_sockaddr_t		*notify;
    261 	dns_name_t		**notifykeynames;
    262 	isc_dscp_t		*notifydscp;
    263 	unsigned int		notifycnt;
    264 	isc_sockaddr_t		notifyfrom;
    265 	isc_task_t		*task;
    266 	isc_task_t		*loadtask;
    267 	isc_sockaddr_t		notifysrc4;
    268 	isc_sockaddr_t		notifysrc6;
    269 	isc_sockaddr_t		xfrsource4;
    270 	isc_sockaddr_t		xfrsource6;
    271 	isc_sockaddr_t		altxfrsource4;
    272 	isc_sockaddr_t		altxfrsource6;
    273 	isc_sockaddr_t		sourceaddr;
    274 	isc_dscp_t		notifysrc4dscp;
    275 	isc_dscp_t		notifysrc6dscp;
    276 	isc_dscp_t		xfrsource4dscp;
    277 	isc_dscp_t		xfrsource6dscp;
    278 	isc_dscp_t		altxfrsource4dscp;
    279 	isc_dscp_t		altxfrsource6dscp;
    280 	dns_xfrin_ctx_t		*xfr;		/* task locked */
    281 	dns_tsigkey_t		*tsigkey;	/* key used for xfr */
    282 	/* Access Control Lists */
    283 	dns_acl_t		*update_acl;
    284 	dns_acl_t		*forward_acl;
    285 	dns_acl_t		*notify_acl;
    286 	dns_acl_t		*query_acl;
    287 	dns_acl_t		*queryon_acl;
    288 	dns_acl_t		*xfr_acl;
    289 	bool		update_disabled;
    290 	bool		zero_no_soa_ttl;
    291 	dns_severity_t		check_names;
    292 	ISC_LIST(dns_notify_t)	notifies;
    293 	dns_request_t		*request;
    294 	dns_loadctx_t		*lctx;
    295 	dns_io_t		*readio;
    296 	dns_dumpctx_t		*dctx;
    297 	dns_io_t		*writeio;
    298 	uint32_t		maxxfrin;
    299 	uint32_t		maxxfrout;
    300 	uint32_t		idlein;
    301 	uint32_t		idleout;
    302 	isc_event_t		ctlevent;
    303 	dns_ssutable_t		*ssutable;
    304 	uint32_t		sigvalidityinterval;
    305 	uint32_t		keyvalidityinterval;
    306 	uint32_t		sigresigninginterval;
    307 	dns_view_t		*view;
    308 	dns_view_t		*prev_view;
    309 	dns_checkmxfunc_t	checkmx;
    310 	dns_checksrvfunc_t	checksrv;
    311 	dns_checknsfunc_t	checkns;
    312 	/*%
    313 	 * Zones in certain states such as "waiting for zone transfer"
    314 	 * or "zone transfer in progress" are kept on per-state linked lists
    315 	 * in the zone manager using the 'statelink' field.  The 'statelist'
    316 	 * field points at the list the zone is currently on.  It the zone
    317 	 * is not on any such list, statelist is NULL.
    318 	 */
    319 	ISC_LINK(dns_zone_t)	statelink;
    320 	dns_zonelist_t		*statelist;
    321 	/*%
    322 	 * Statistics counters about zone management.
    323 	 */
    324 	isc_stats_t		*stats;
    325 	/*%
    326 	 * Optional per-zone statistics counters.  Counted outside of this
    327 	 * module.
    328 	 */
    329 	dns_zonestat_level_t	statlevel;
    330 	bool			requeststats_on;
    331 	isc_stats_t		*requeststats;
    332 	dns_stats_t		*rcvquerystats;
    333 	dns_stats_t		*dnssecsignstats;
    334 	dns_stats_t		*dnssecrefreshstats;
    335 	uint32_t		notifydelay;
    336 	dns_isselffunc_t	isself;
    337 	void			*isselfarg;
    338 
    339 	char *			strnamerd;
    340 	char *			strname;
    341 	char *			strrdclass;
    342 	char *			strviewname;
    343 
    344 	/*%
    345 	 * Serial number for deferred journal compaction.
    346 	 */
    347 	uint32_t		compact_serial;
    348 	/*%
    349 	 * Keys that are signing the zone for the first time.
    350 	 */
    351 	dns_signinglist_t	signing;
    352 	dns_nsec3chainlist_t	nsec3chain;
    353 	/*%
    354 	 * List of outstanding NSEC3PARAM change requests.
    355 	 */
    356 	isc_eventlist_t		setnsec3param_queue;
    357 	/*%
    358 	 * Signing / re-signing quantum stopping parameters.
    359 	 */
    360 	uint32_t		signatures;
    361 	uint32_t		nodes;
    362 	dns_rdatatype_t		privatetype;
    363 
    364 	/*%
    365 	 * Autosigning/key-maintenance options
    366 	 */
    367 	uint32_t		keyopts;
    368 
    369 	/*%
    370 	 * True if added by "rndc addzone"
    371 	 */
    372 	bool           added;
    373 
    374 	/*%
    375 	 * True if added by automatically by named.
    376 	 */
    377 	bool           automatic;
    378 
    379 	/*%
    380 	 * response policy data to be relayed to the database
    381 	 */
    382 	dns_rpz_zones_t		*rpzs;
    383 	dns_rpz_num_t		rpz_num;
    384 
    385 	/*%
    386 	 * catalog zone data
    387 	 */
    388 	dns_catz_zones_t	*catzs;
    389 
    390 	/*%
    391 	 * parent catalog zone
    392 	 */
    393 	dns_catz_zone_t		*parentcatz;
    394 
    395 	/*%
    396 	 * Serial number update method.
    397 	 */
    398 	dns_updatemethod_t	updatemethod;
    399 
    400 	/*%
    401 	 * whether ixfr is requested
    402 	 */
    403 	bool		requestixfr;
    404 
    405 	/*%
    406 	 * whether EDNS EXPIRE is requested
    407 	 */
    408 	bool		requestexpire;
    409 
    410 	/*%
    411 	 * Outstanding forwarded UPDATE requests.
    412 	 */
    413 	dns_forwardlist_t	forwards;
    414 
    415 	dns_zone_t		*raw;
    416 	dns_zone_t		*secure;
    417 
    418 	bool		sourceserialset;
    419 	uint32_t		sourceserial;
    420 
    421 	/*%
    422 	 * maximum zone ttl
    423 	 */
    424 	dns_ttl_t		maxttl;
    425 
    426 	/*
    427 	 * Inline zone signing state.
    428 	 */
    429 	dns_diff_t		rss_diff;
    430 	isc_eventlist_t		rss_events;
    431 	isc_eventlist_t		rss_post;
    432 	dns_dbversion_t		*rss_newver;
    433 	dns_dbversion_t		*rss_oldver;
    434 	dns_db_t		*rss_db;
    435 	dns_zone_t		*rss_raw;
    436 	isc_event_t		*rss_event;
    437 	dns_update_state_t      *rss_state;
    438 
    439 	isc_stats_t             *gluecachestats;
    440 };
    441 
    442 #define zonediff_init(z, d) \
    443 	do { \
    444 		dns__zonediff_t *_z = (z); \
    445 		(_z)->diff = (d); \
    446 		(_z)->offline = false; \
    447 	} while (/*CONSTCOND*/0)
    448 
    449 #define DNS_ZONE_FLAG(z,f) ((z)->flags & (f))
    450 #define DNS_ZONE_SETFLAG(z,f) do { \
    451 		INSIST(LOCKED_ZONE(z)); \
    452 		(z)->flags |= (f); \
    453 		} while (/*CONSTCOND*/0)
    454 #define DNS_ZONE_CLRFLAG(z,f) do { \
    455 		INSIST(LOCKED_ZONE(z)); \
    456 		(z)->flags &= ~(f); \
    457 		} while (/*CONSTCOND*/0)
    458 	/* XXX MPA these may need to go back into zone.h */
    459 #define DNS_ZONEFLG_REFRESH	0x00000001U	/*%< refresh check in progress */
    460 #define DNS_ZONEFLG_NEEDDUMP	0x00000002U	/*%< zone need consolidation */
    461 #define DNS_ZONEFLG_USEVC	0x00000004U	/*%< use tcp for refresh query */
    462 #define DNS_ZONEFLG_DUMPING	0x00000008U	/*%< a dump is in progress */
    463 #define DNS_ZONEFLG_HASINCLUDE	0x00000010U	/*%< $INCLUDE in zone file */
    464 #define DNS_ZONEFLG_LOADED	0x00000020U	/*%< database has loaded */
    465 #define DNS_ZONEFLG_EXITING	0x00000040U	/*%< zone is being destroyed */
    466 #define DNS_ZONEFLG_EXPIRED	0x00000080U	/*%< zone has expired */
    467 #define DNS_ZONEFLG_NEEDREFRESH	0x00000100U	/*%< refresh check needed */
    468 #define DNS_ZONEFLG_UPTODATE	0x00000200U	/*%< zone contents are
    469 						 * uptodate */
    470 #define DNS_ZONEFLG_NEEDNOTIFY	0x00000400U	/*%< need to send out notify
    471 						 * messages */
    472 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U	/*%< generate a journal diff on
    473 						 * reload */
    474 #define DNS_ZONEFLG_NOMASTERS	0x00001000U	/*%< an attempt to refresh a
    475 						 * zone with no masters
    476 						 * occurred */
    477 #define DNS_ZONEFLG_LOADING	0x00002000U	/*%< load from disk in progress*/
    478 #define DNS_ZONEFLG_HAVETIMERS	0x00004000U	/*%< timer values have been set
    479 						 * from SOA (if not set, we
    480 						 * are still using
    481 						 * default timer values) */
    482 #define DNS_ZONEFLG_FORCEXFER	0x00008000U	/*%< Force a zone xfer */
    483 #define DNS_ZONEFLG_NOREFRESH	0x00010000U
    484 #define DNS_ZONEFLG_DIALNOTIFY	0x00020000U
    485 #define DNS_ZONEFLG_DIALREFRESH	0x00040000U
    486 #define DNS_ZONEFLG_SHUTDOWN	0x00080000U
    487 #define DNS_ZONEFLAG_NOIXFR	0x00100000U	/*%< IXFR failed, force AXFR */
    488 #define DNS_ZONEFLG_FLUSH	0x00200000U
    489 #define DNS_ZONEFLG_NOEDNS	0x00400000U
    490 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
    491 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
    492 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
    493 #define DNS_ZONEFLG_REFRESHING	0x04000000U	/*%< Refreshing keydata */
    494 #define DNS_ZONEFLG_THAW	0x08000000U
    495 #define DNS_ZONEFLG_LOADPENDING	0x10000000U	/*%< Loading scheduled */
    496 #define DNS_ZONEFLG_NODELAY	0x20000000U
    497 #define DNS_ZONEFLG_SENDSECURE  0x40000000U
    498 #define DNS_ZONEFLG_NEEDSTARTUPNOTIFY 0x80000000U /*%< need to send out notify
    499 						   *   due to the zone just
    500 						   *   being loaded for the
    501 						   *   first time.  */
    502 
    503 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
    504 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
    505 
    506 /* Flags for zone_load() */
    507 #define DNS_ZONELOADFLAG_NOSTAT        0x00000001U     /* Do not stat() master files */
    508 #define DNS_ZONELOADFLAG_THAW  0x00000002U     /* Thaw the zone on successful
    509 						  load. */
    510 
    511 #define UNREACH_CHACHE_SIZE	10U
    512 #define UNREACH_HOLD_TIME	600	/* 10 minutes */
    513 
    514 #define CHECK(op) \
    515 	do { result = (op); \
    516 		if (result != ISC_R_SUCCESS) goto failure; \
    517 	} while (/*CONSTCOND*/0)
    518 
    519 struct dns_unreachable {
    520 	isc_sockaddr_t	remote;
    521 	isc_sockaddr_t	local;
    522 	uint32_t	expire;
    523 	uint32_t	last;
    524 	uint32_t	count;
    525 };
    526 
    527 struct dns_zonemgr {
    528 	unsigned int		magic;
    529 	isc_mem_t *		mctx;
    530 	int			refs;		/* Locked by rwlock */
    531 	isc_taskmgr_t *		taskmgr;
    532 	isc_timermgr_t *	timermgr;
    533 	isc_socketmgr_t *	socketmgr;
    534 	isc_taskpool_t *	zonetasks;
    535 	isc_taskpool_t *	loadtasks;
    536 	isc_task_t *		task;
    537 	isc_pool_t *		mctxpool;
    538 	isc_ratelimiter_t *	notifyrl;
    539 	isc_ratelimiter_t *	refreshrl;
    540 	isc_ratelimiter_t *	startupnotifyrl;
    541 	isc_ratelimiter_t *	startuprefreshrl;
    542 	isc_rwlock_t		rwlock;
    543 	isc_mutex_t		iolock;
    544 	isc_rwlock_t		urlock;
    545 
    546 	/* Locked by rwlock. */
    547 	dns_zonelist_t		zones;
    548 	dns_zonelist_t		waiting_for_xfrin;
    549 	dns_zonelist_t		xfrin_in_progress;
    550 
    551 	/* Configuration data. */
    552 	uint32_t		transfersin;
    553 	uint32_t		transfersperns;
    554 	unsigned int		notifyrate;
    555 	unsigned int		startupnotifyrate;
    556 	unsigned int		serialqueryrate;
    557 	unsigned int		startupserialqueryrate;
    558 
    559 	/* Locked by iolock */
    560 	uint32_t		iolimit;
    561 	uint32_t		ioactive;
    562 	dns_iolist_t		high;
    563 	dns_iolist_t		low;
    564 
    565 	/* Locked by urlock. */
    566 	/* LRU cache */
    567 	struct dns_unreachable	unreachable[UNREACH_CHACHE_SIZE];
    568 };
    569 
    570 /*%
    571  * Hold notify state.
    572  */
    573 struct dns_notify {
    574 	unsigned int		magic;
    575 	unsigned int		flags;
    576 	isc_mem_t		*mctx;
    577 	dns_zone_t		*zone;
    578 	dns_adbfind_t		*find;
    579 	dns_request_t		*request;
    580 	dns_name_t		ns;
    581 	isc_sockaddr_t		dst;
    582 	dns_tsigkey_t		*key;
    583 	isc_dscp_t		dscp;
    584 	ISC_LINK(dns_notify_t)	link;
    585 	isc_event_t		*event;
    586 };
    587 
    588 #define DNS_NOTIFY_NOSOA	0x0001U
    589 #define DNS_NOTIFY_STARTUP	0x0002U
    590 
    591 /*%
    592  *	dns_stub holds state while performing a 'stub' transfer.
    593  *	'db' is the zone's 'db' or a new one if this is the initial
    594  *	transfer.
    595  */
    596 
    597 struct dns_stub {
    598 	unsigned int		magic;
    599 	isc_mem_t		*mctx;
    600 	dns_zone_t		*zone;
    601 	dns_db_t		*db;
    602 	dns_dbversion_t		*version;
    603 };
    604 
    605 /*%
    606  *	Hold load state.
    607  */
    608 struct dns_load {
    609 	unsigned int		magic;
    610 	isc_mem_t		*mctx;
    611 	dns_zone_t		*zone;
    612 	dns_db_t		*db;
    613 	isc_time_t		loadtime;
    614 	dns_rdatacallbacks_t	callbacks;
    615 };
    616 
    617 /*%
    618  *	Hold forward state.
    619  */
    620 struct dns_forward {
    621 	unsigned int		magic;
    622 	isc_mem_t		*mctx;
    623 	dns_zone_t		*zone;
    624 	isc_buffer_t		*msgbuf;
    625 	dns_request_t		*request;
    626 	uint32_t		which;
    627 	isc_sockaddr_t		addr;
    628 	dns_updatecallback_t	callback;
    629 	void			*callback_arg;
    630 	unsigned int		options;
    631 	ISC_LINK(dns_forward_t)	link;
    632 };
    633 
    634 /*%
    635  *	Hold IO request state.
    636  */
    637 struct dns_io {
    638 	unsigned int	magic;
    639 	dns_zonemgr_t	*zmgr;
    640 	bool	high;
    641 	isc_task_t	*task;
    642 	ISC_LINK(dns_io_t) link;
    643 	isc_event_t	*event;
    644 };
    645 
    646 /*%
    647  *	Hold state for when we are signing a zone with a new
    648  *	DNSKEY as result of an update.
    649  */
    650 struct dns_signing {
    651 	unsigned int		magic;
    652 	dns_db_t		*db;
    653 	dns_dbiterator_t	*dbiterator;
    654 	dns_secalg_t		algorithm;
    655 	uint16_t		keyid;
    656 	bool		deleteit;
    657 	bool		done;
    658 	ISC_LINK(dns_signing_t)	link;
    659 };
    660 
    661 struct dns_nsec3chain {
    662 	unsigned int			magic;
    663 	dns_db_t			*db;
    664 	dns_dbiterator_t		*dbiterator;
    665 	dns_rdata_nsec3param_t		nsec3param;
    666 	unsigned char			salt[255];
    667 	bool			done;
    668 	bool			seen_nsec;
    669 	bool			delete_nsec;
    670 	bool			save_delete_nsec;
    671 	ISC_LINK(dns_nsec3chain_t)	link;
    672 };
    673 /*%<
    674  * 'dbiterator' contains a iterator for the database.  If we are creating
    675  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
    676  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
    677  * iterated.
    678  *
    679  * 'nsec3param' contains the parameters of the NSEC3 chain being created
    680  * or removed.
    681  *
    682  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
    683  *
    684  * 'seen_nsec' will be set to true if, while iterating the zone to create a
    685  * NSEC3 chain, a NSEC record is seen.
    686  *
    687  * 'delete_nsec' will be set to true if, at the completion of the creation
    688  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
    689  * are in the process of deleting the NSEC chain.
    690  *
    691  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
    692  * so it can be recovered in the event of a error.
    693  */
    694 
    695 struct dns_keyfetch {
    696 	dns_fixedname_t name;
    697 	dns_rdataset_t keydataset;
    698 	dns_rdataset_t dnskeyset;
    699 	dns_rdataset_t dnskeysigset;
    700 	dns_zone_t *zone;
    701 	dns_db_t *db;
    702 	dns_fetch_t *fetch;
    703 };
    704 
    705 /*%
    706  * Hold state for an asynchronous load
    707  */
    708 struct dns_asyncload {
    709 	dns_zone_t *zone;
    710 	unsigned int flags;
    711 	dns_zt_zoneloaded_t loaded;
    712 	void *loaded_arg;
    713 };
    714 
    715 /*%
    716  * Reference to an include file encountered during loading
    717  */
    718 struct dns_include {
    719 	char *name;
    720 	isc_time_t filetime;
    721 	ISC_LINK(dns_include_t)	link;
    722 };
    723 
    724 /*
    725  * These can be overridden by the -T mkeytimers option on the command
    726  * line, so that we can test with shorter periods than specified in
    727  * RFC 5011.
    728  */
    729 #define HOUR 3600
    730 #define DAY (24*HOUR)
    731 #define MONTH (30*DAY)
    732 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_hour = HOUR;
    733 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_day = DAY;
    734 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_month = MONTH;
    735 
    736 #define SEND_BUFFER_SIZE 2048
    737 
    738 static void zone_settimer(dns_zone_t *, isc_time_t *);
    739 static void cancel_refresh(dns_zone_t *);
    740 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
    741 			  const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
    742 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
    743      ISC_FORMAT_PRINTF(3, 4);
    744 static void dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
    745      ISC_FORMAT_PRINTF(3, 4);
    746 static void queue_xfrin(dns_zone_t *zone);
    747 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
    748 				  dns_diff_t *diff, dns_diffop_t op,
    749 				  dns_name_t *name, dns_ttl_t ttl,
    750 				  dns_rdata_t *rdata);
    751 static void zone_unload(dns_zone_t *zone);
    752 static void zone_expire(dns_zone_t *zone);
    753 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
    754 static void zone_idetach(dns_zone_t **zonep);
    755 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
    756 				   bool dump);
    757 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
    758 static inline void zone_detachdb(dns_zone_t *zone);
    759 static isc_result_t default_journal(dns_zone_t *zone);
    760 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
    761 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
    762 				  isc_time_t loadtime, isc_result_t result);
    763 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
    764 static void zone_shutdown(isc_task_t *, isc_event_t *);
    765 static void zone_loaddone(void *arg, isc_result_t result);
    766 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
    767 				   isc_time_t loadtime);
    768 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
    769 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
    770 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
    771 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
    772 static isc_result_t zone_send_secureserial(dns_zone_t *zone,
    773 					   uint32_t serial);
    774 static void refresh_callback(isc_task_t *, isc_event_t *);
    775 static void stub_callback(isc_task_t *, isc_event_t *);
    776 static void queue_soa_query(dns_zone_t *zone);
    777 static void soa_query(isc_task_t *, isc_event_t *);
    778 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
    779 		     dns_stub_t *stub);
    780 static int message_count(dns_message_t *msg, dns_section_t section,
    781 			 dns_rdatatype_t type);
    782 static void notify_cancel(dns_zone_t *zone);
    783 static void notify_find_address(dns_notify_t *notify);
    784 static void notify_send(dns_notify_t *notify);
    785 static isc_result_t notify_createmessage(dns_zone_t *zone,
    786 					 unsigned int flags,
    787 					 dns_message_t **messagep);
    788 static void notify_done(isc_task_t *task, isc_event_t *event);
    789 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
    790 static isc_result_t zone_dump(dns_zone_t *, bool);
    791 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
    792 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
    793 					     dns_zone_t *zone);
    794 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
    795 static void zonemgr_free(dns_zonemgr_t *zmgr);
    796 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, bool high,
    797 				  isc_task_t *task, isc_taskaction_t action,
    798 				  void *arg, dns_io_t **iop);
    799 static void zonemgr_putio(dns_io_t **iop);
    800 static void zonemgr_cancelio(dns_io_t *io);
    801 static void rss_post(dns_zone_t *, isc_event_t *);
    802 
    803 static isc_result_t
    804 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
    805 		 unsigned int *soacount, uint32_t *serial,
    806 		 uint32_t *refresh, uint32_t *retry,
    807 		 uint32_t *expire, uint32_t *minimum,
    808 		 unsigned int *errors);
    809 
    810 static void zone_freedbargs(dns_zone_t *zone);
    811 static void forward_callback(isc_task_t *task, isc_event_t *event);
    812 static void zone_saveunique(dns_zone_t *zone, const char *path,
    813 			    const char *templat);
    814 static void zone_maintenance(dns_zone_t *zone);
    815 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
    816 static void dump_done(void *arg, isc_result_t result);
    817 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
    818 				     uint16_t keyid,
    819 				     bool deleteit);
    820 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
    821 				dns_dbnode_t *node, dns_name_t *name,
    822 				dns_diff_t *diff);
    823 static void zone_rekey(dns_zone_t *zone);
    824 static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
    825 static void setrl(isc_ratelimiter_t *rl, unsigned int *rate,
    826 		  unsigned int value);
    827 
    828 #define ENTER zone_debuglog(zone, me, 1, "enter")
    829 
    830 static const unsigned int dbargc_default = 1;
    831 static const char *dbargv_default[] = { "rbt" };
    832 
    833 #define DNS_ZONE_JITTER_ADD(a, b, c) \
    834 	do { \
    835 		isc_interval_t _i; \
    836 		uint32_t _j; \
    837 		_j = (b) - isc_random_uniform((b)/4);	\
    838 		isc_interval_set(&_i, _j, 0); \
    839 		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
    840 			dns_zone_log(zone, ISC_LOG_WARNING, \
    841 				     "epoch approaching: upgrade required: " \
    842 				     "now + %s failed", #b); \
    843 			isc_interval_set(&_i, _j/2, 0); \
    844 			(void)isc_time_add((a), &_i, (c)); \
    845 		} \
    846 	} while (/*CONSTCOND*/0)
    847 
    848 #define DNS_ZONE_TIME_ADD(a, b, c) \
    849 	do { \
    850 		isc_interval_t _i; \
    851 		isc_interval_set(&_i, (b), 0); \
    852 		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
    853 			dns_zone_log(zone, ISC_LOG_WARNING, \
    854 				     "epoch approaching: upgrade required: " \
    855 				     "now + %s failed", #b); \
    856 			isc_interval_set(&_i, (b)/2, 0); \
    857 			(void)isc_time_add((a), &_i, (c)); \
    858 		} \
    859 	} while (/*CONSTCOND*/0)
    860 
    861 typedef struct nsec3param nsec3param_t;
    862 struct nsec3param {
    863 	unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
    864 	unsigned int length;
    865 	bool nsec;
    866 	bool replace;
    867 	ISC_LINK(nsec3param_t)	link;
    868 };
    869 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
    870 struct np3event {
    871 	isc_event_t event;
    872 	nsec3param_t params;
    873 };
    874 
    875 struct ssevent {
    876 	isc_event_t event;
    877 	uint32_t serial;
    878 };
    879 
    880 /*%
    881  * Increment resolver-related statistics counters.  Zone must be locked.
    882  */
    883 static inline void
    884 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
    885 	if (zone->stats != NULL)
    886 		isc_stats_increment(zone->stats, counter);
    887 }
    888 
    889 /***
    890  ***	Public functions.
    891  ***/
    892 
    893 isc_result_t
    894 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
    895 	isc_result_t result;
    896 	dns_zone_t *zone;
    897 	isc_time_t now;
    898 
    899 	REQUIRE(zonep != NULL && *zonep == NULL);
    900 	REQUIRE(mctx != NULL);
    901 
    902 	TIME_NOW(&now);
    903 	zone = isc_mem_get(mctx, sizeof(*zone));
    904 	if (zone == NULL) {
    905 		return (ISC_R_NOMEMORY);
    906 	}
    907 
    908 	zone->mctx = NULL;
    909 	isc_mem_attach(mctx, &zone->mctx);
    910 
    911 	isc_mutex_init(&zone->lock);
    912 
    913 	result = ZONEDB_INITLOCK(&zone->dblock);
    914 	if (result != ISC_R_SUCCESS) {
    915 		goto free_mutex;
    916 	}
    917 
    918 	/* XXX MPA check that all elements are initialised */
    919 #ifdef DNS_ZONE_CHECKLOCK
    920 	zone->locked = false;
    921 #endif
    922 	zone->db = NULL;
    923 	zone->zmgr = NULL;
    924 	ISC_LINK_INIT(zone, link);
    925 	isc_refcount_init(&zone->erefs, 1);	/* Implicit attach. */
    926 	zone->irefs = 0;
    927 	dns_name_init(&zone->origin, NULL);
    928 	zone->strnamerd = NULL;
    929 	zone->strname = NULL;
    930 	zone->strrdclass = NULL;
    931 	zone->strviewname = NULL;
    932 	zone->masterfile = NULL;
    933 	ISC_LIST_INIT(zone->includes);
    934 	ISC_LIST_INIT(zone->newincludes);
    935 	zone->nincludes = 0;
    936 	zone->masterformat = dns_masterformat_none;
    937 	zone->masterstyle = NULL;
    938 	zone->keydirectory = NULL;
    939 	zone->journalsize = -1;
    940 	zone->journal = NULL;
    941 	zone->rdclass = dns_rdataclass_none;
    942 	zone->type = dns_zone_none;
    943 	zone->flags = 0;
    944 	zone->options = 0;
    945 	zone->keyopts = 0;
    946 	zone->db_argc = 0;
    947 	zone->db_argv = NULL;
    948 	isc_time_settoepoch(&zone->expiretime);
    949 	isc_time_settoepoch(&zone->refreshtime);
    950 	isc_time_settoepoch(&zone->dumptime);
    951 	isc_time_settoepoch(&zone->loadtime);
    952 	zone->notifytime = now;
    953 	isc_time_settoepoch(&zone->resigntime);
    954 	isc_time_settoepoch(&zone->keywarntime);
    955 	isc_time_settoepoch(&zone->signingtime);
    956 	isc_time_settoepoch(&zone->nsec3chaintime);
    957 	isc_time_settoepoch(&zone->refreshkeytime);
    958 	zone->refreshkeyinterval = 0;
    959 	zone->refreshkeycount = 0;
    960 	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
    961 	zone->retry = DNS_ZONE_DEFAULTRETRY;
    962 	zone->expire = 0;
    963 	zone->minimum = 0;
    964 	zone->maxrefresh = DNS_ZONE_MAXREFRESH;
    965 	zone->minrefresh = DNS_ZONE_MINREFRESH;
    966 	zone->maxretry = DNS_ZONE_MAXRETRY;
    967 	zone->minretry = DNS_ZONE_MINRETRY;
    968 	zone->masters = NULL;
    969 	zone->masterdscps = NULL;
    970 	zone->masterkeynames = NULL;
    971 	zone->mastersok = NULL;
    972 	zone->masterscnt = 0;
    973 	zone->curmaster = 0;
    974 	zone->maxttl = 0;
    975 	zone->notify = NULL;
    976 	zone->notifykeynames = NULL;
    977 	zone->notifydscp = NULL;
    978 	zone->notifytype = dns_notifytype_yes;
    979 	zone->notifycnt = 0;
    980 	zone->task = NULL;
    981 	zone->loadtask = NULL;
    982 	zone->update_acl = NULL;
    983 	zone->forward_acl = NULL;
    984 	zone->notify_acl = NULL;
    985 	zone->query_acl = NULL;
    986 	zone->queryon_acl = NULL;
    987 	zone->xfr_acl = NULL;
    988 	zone->update_disabled = false;
    989 	zone->zero_no_soa_ttl = true;
    990 	zone->check_names = dns_severity_ignore;
    991 	zone->request = NULL;
    992 	zone->lctx = NULL;
    993 	zone->readio = NULL;
    994 	zone->dctx = NULL;
    995 	zone->writeio = NULL;
    996 	zone->timer = NULL;
    997 	zone->idlein = DNS_DEFAULT_IDLEIN;
    998 	zone->idleout = DNS_DEFAULT_IDLEOUT;
    999 	zone->log_key_expired_timer = 0;
   1000 	ISC_LIST_INIT(zone->notifies);
   1001 	isc_sockaddr_any(&zone->notifysrc4);
   1002 	isc_sockaddr_any6(&zone->notifysrc6);
   1003 	isc_sockaddr_any(&zone->xfrsource4);
   1004 	isc_sockaddr_any6(&zone->xfrsource6);
   1005 	isc_sockaddr_any(&zone->altxfrsource4);
   1006 	isc_sockaddr_any6(&zone->altxfrsource6);
   1007 	zone->notifysrc4dscp = -1;
   1008 	zone->notifysrc6dscp = -1;
   1009 	zone->xfrsource4dscp = -1;
   1010 	zone->xfrsource6dscp = -1;
   1011 	zone->altxfrsource4dscp = -1;
   1012 	zone->altxfrsource6dscp = -1;
   1013 	zone->xfr = NULL;
   1014 	zone->tsigkey = NULL;
   1015 	zone->maxxfrin = MAX_XFER_TIME;
   1016 	zone->maxxfrout = MAX_XFER_TIME;
   1017 	zone->ssutable = NULL;
   1018 	zone->sigvalidityinterval = 30 * 24 * 3600;
   1019 	zone->keyvalidityinterval = 0;
   1020 	zone->sigresigninginterval = 7 * 24 * 3600;
   1021 	zone->view = NULL;
   1022 	zone->prev_view = NULL;
   1023 	zone->checkmx = NULL;
   1024 	zone->checksrv = NULL;
   1025 	zone->checkns = NULL;
   1026 	ISC_LINK_INIT(zone, statelink);
   1027 	zone->statelist = NULL;
   1028 	zone->stats = NULL;
   1029 	zone->requeststats_on = false;
   1030 	zone->statlevel = dns_zonestat_none;
   1031 	zone->requeststats = NULL;
   1032 	zone->rcvquerystats = NULL;
   1033 	zone->dnssecsignstats = NULL;
   1034 	zone->dnssecrefreshstats = NULL;
   1035 	zone->notifydelay = 5;
   1036 	zone->isself = NULL;
   1037 	zone->isselfarg = NULL;
   1038 	ISC_LIST_INIT(zone->signing);
   1039 	ISC_LIST_INIT(zone->nsec3chain);
   1040 	ISC_LIST_INIT(zone->setnsec3param_queue);
   1041 	zone->signatures = 10;
   1042 	zone->nodes = 100;
   1043 	zone->privatetype = (dns_rdatatype_t)0xffffU;
   1044 	zone->added = false;
   1045 	zone->automatic = false;
   1046 	zone->rpzs = NULL;
   1047 	zone->rpz_num = DNS_RPZ_INVALID_NUM;
   1048 
   1049 	zone->catzs = NULL;
   1050 	zone->parentcatz = NULL;
   1051 
   1052 	ISC_LIST_INIT(zone->forwards);
   1053 	zone->raw = NULL;
   1054 	zone->secure = NULL;
   1055 	zone->sourceserial = 0;
   1056 	zone->sourceserialset = false;
   1057 	zone->requestixfr = true;
   1058 	zone->requestexpire = true;
   1059 	ISC_LIST_INIT(zone->rss_events);
   1060 	ISC_LIST_INIT(zone->rss_post);
   1061 	zone->rss_db = NULL;
   1062 	zone->rss_raw = NULL;
   1063 	zone->rss_newver = NULL;
   1064 	zone->rss_oldver = NULL;
   1065 	zone->rss_event = NULL;
   1066 	zone->rss_state = NULL;
   1067 	zone->updatemethod = dns_updatemethod_increment;
   1068 	zone->maxrecords = 0U;
   1069 
   1070 	zone->magic = ZONE_MAGIC;
   1071 
   1072 	zone->gluecachestats = NULL;
   1073 	result = isc_stats_create(mctx, &zone->gluecachestats,
   1074 				  dns_gluecachestatscounter_max);
   1075 	if (result != ISC_R_SUCCESS) {
   1076 		goto free_erefs;
   1077 	}
   1078 
   1079 	/* Must be after magic is set. */
   1080 	result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
   1081 	if (result != ISC_R_SUCCESS) {
   1082 		goto free_stats;
   1083 	}
   1084 
   1085 	ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
   1086 		       DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
   1087 		       NULL, NULL);
   1088 	*zonep = zone;
   1089 	return (ISC_R_SUCCESS);
   1090 
   1091  free_stats:
   1092 	if (zone->gluecachestats != NULL)
   1093 		isc_stats_detach(&zone->gluecachestats);
   1094 
   1095  free_erefs:
   1096 	INSIST(isc_refcount_decrement(&zone->erefs) > 0);
   1097 	isc_refcount_destroy(&zone->erefs);
   1098 
   1099 	ZONEDB_DESTROYLOCK(&zone->dblock);
   1100 
   1101  free_mutex:
   1102 	isc_mutex_destroy(&zone->lock);
   1103 
   1104 	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
   1105 	return (result);
   1106 }
   1107 
   1108 /*
   1109  * Free a zone.  Because we require that there be no more
   1110  * outstanding events or references, no locking is necessary.
   1111  */
   1112 static void
   1113 zone_free(dns_zone_t *zone) {
   1114 	isc_mem_t *mctx = NULL;
   1115 	dns_signing_t *signing;
   1116 	dns_nsec3chain_t *nsec3chain;
   1117 	isc_event_t *event;
   1118 	dns_include_t *include;
   1119 
   1120 	REQUIRE(DNS_ZONE_VALID(zone));
   1121 	REQUIRE(isc_refcount_current(&zone->erefs) == 0);
   1122 	REQUIRE(zone->irefs == 0);
   1123 	REQUIRE(!LOCKED_ZONE(zone));
   1124 	REQUIRE(zone->timer == NULL);
   1125 	REQUIRE(zone->zmgr == NULL);
   1126 
   1127 	/*
   1128 	 * Managed objects.  Order is important.
   1129 	 */
   1130 	if (zone->request != NULL) {
   1131 		dns_request_destroy(&zone->request); /* XXXMPA */
   1132 	}
   1133 	INSIST(zone->readio == NULL);
   1134 	INSIST(zone->statelist == NULL);
   1135 	INSIST(zone->writeio == NULL);
   1136 
   1137 	if (zone->task != NULL) {
   1138 		isc_task_detach(&zone->task);
   1139 	}
   1140 	if (zone->loadtask != NULL) {
   1141 		isc_task_detach(&zone->loadtask);
   1142 	}
   1143 	if (zone->view != NULL) {
   1144 		dns_view_weakdetach(&zone->view);
   1145 	}
   1146 	if (zone->prev_view != NULL) {
   1147 		dns_view_weakdetach(&zone->prev_view);
   1148 	}
   1149 
   1150 	/* Unmanaged objects */
   1151 	while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
   1152 		event = ISC_LIST_HEAD(zone->setnsec3param_queue);
   1153 		ISC_LIST_UNLINK(zone->setnsec3param_queue, event, ev_link);
   1154 		isc_event_free(&event);
   1155 	}
   1156 	while (!ISC_LIST_EMPTY(zone->rss_post)) {
   1157 		event = ISC_LIST_HEAD(zone->rss_post);
   1158 		ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
   1159 		isc_event_free(&event);
   1160 	}
   1161 	for (signing = ISC_LIST_HEAD(zone->signing);
   1162 	     signing != NULL;
   1163 	     signing = ISC_LIST_HEAD(zone->signing)) {
   1164 		ISC_LIST_UNLINK(zone->signing, signing, link);
   1165 		dns_db_detach(&signing->db);
   1166 		dns_dbiterator_destroy(&signing->dbiterator);
   1167 		isc_mem_put(zone->mctx, signing, sizeof *signing);
   1168 	}
   1169 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   1170 	     nsec3chain != NULL;
   1171 	     nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
   1172 		ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
   1173 		dns_db_detach(&nsec3chain->db);
   1174 		dns_dbiterator_destroy(&nsec3chain->dbiterator);
   1175 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   1176 	}
   1177 	for (include = ISC_LIST_HEAD(zone->includes);
   1178 	     include != NULL;
   1179 	     include = ISC_LIST_HEAD(zone->includes)) {
   1180 		ISC_LIST_UNLINK(zone->includes, include, link);
   1181 		isc_mem_free(zone->mctx, include->name);
   1182 		isc_mem_put(zone->mctx, include, sizeof *include);
   1183 	}
   1184 	for (include = ISC_LIST_HEAD(zone->newincludes);
   1185 	     include != NULL;
   1186 	     include = ISC_LIST_HEAD(zone->newincludes)) {
   1187 		ISC_LIST_UNLINK(zone->newincludes, include, link);
   1188 		isc_mem_free(zone->mctx, include->name);
   1189 		isc_mem_put(zone->mctx, include, sizeof *include);
   1190 	}
   1191 	if (zone->masterfile != NULL) {
   1192 		isc_mem_free(zone->mctx, zone->masterfile);
   1193 	}
   1194 	zone->masterfile = NULL;
   1195 	if (zone->keydirectory != NULL) {
   1196 		isc_mem_free(zone->mctx, zone->keydirectory);
   1197 	}
   1198 	zone->keydirectory = NULL;
   1199 	zone->journalsize = -1;
   1200 	if (zone->journal != NULL) {
   1201 		isc_mem_free(zone->mctx, zone->journal);
   1202 	}
   1203 	zone->journal = NULL;
   1204 	if (zone->stats != NULL) {
   1205 		isc_stats_detach(&zone->stats);
   1206 	}
   1207 	if (zone->requeststats != NULL) {
   1208 		isc_stats_detach(&zone->requeststats);
   1209 	}
   1210 	if (zone->rcvquerystats != NULL){
   1211 		dns_stats_detach(&zone->rcvquerystats);
   1212 	}
   1213 	if (zone->dnssecsignstats != NULL){
   1214 		dns_stats_detach(&zone->dnssecsignstats);
   1215 	}
   1216 	if (zone->dnssecrefreshstats != NULL){
   1217 		dns_stats_detach(&zone->dnssecrefreshstats);
   1218 	}
   1219 	if (zone->db != NULL) {
   1220 		zone_detachdb(zone);
   1221 	}
   1222 	if (zone->rpzs != NULL) {
   1223 		REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
   1224 		dns_rpz_detach_rpzs(&zone->rpzs);
   1225 		zone->rpz_num = DNS_RPZ_INVALID_NUM;
   1226 	}
   1227 	if (zone->catzs != NULL) {
   1228 		dns_catz_catzs_detach(&zone->catzs);
   1229 	}
   1230 	zone_freedbargs(zone);
   1231 	RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL,
   1232 						  NULL, 0) == ISC_R_SUCCESS);
   1233 	RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0) == ISC_R_SUCCESS);
   1234 	zone->check_names = dns_severity_ignore;
   1235 	if (zone->update_acl != NULL) {
   1236 		dns_acl_detach(&zone->update_acl);
   1237 	}
   1238 	if (zone->forward_acl != NULL) {
   1239 		dns_acl_detach(&zone->forward_acl);
   1240 	}
   1241 	if (zone->notify_acl != NULL) {
   1242 		dns_acl_detach(&zone->notify_acl);
   1243 	}
   1244 	if (zone->query_acl != NULL) {
   1245 		dns_acl_detach(&zone->query_acl);
   1246 	}
   1247 	if (zone->queryon_acl != NULL) {
   1248 		dns_acl_detach(&zone->queryon_acl);
   1249 	}
   1250 	if (zone->xfr_acl != NULL) {
   1251 		dns_acl_detach(&zone->xfr_acl);
   1252 	}
   1253 	if (dns_name_dynamic(&zone->origin)) {
   1254 		dns_name_free(&zone->origin, zone->mctx);
   1255 	}
   1256 	if (zone->strnamerd != NULL) {
   1257 		isc_mem_free(zone->mctx, zone->strnamerd);
   1258 	}
   1259 	if (zone->strname != NULL) {
   1260 		isc_mem_free(zone->mctx, zone->strname);
   1261 	}
   1262 	if (zone->strrdclass != NULL) {
   1263 		isc_mem_free(zone->mctx, zone->strrdclass);
   1264 	}
   1265 	if (zone->strviewname != NULL) {
   1266 		isc_mem_free(zone->mctx, zone->strviewname);
   1267 	}
   1268 	if (zone->ssutable != NULL) {
   1269 		dns_ssutable_detach(&zone->ssutable);
   1270 	}
   1271 	if (zone->gluecachestats != NULL) {
   1272 		isc_stats_detach(&zone->gluecachestats);
   1273 	}
   1274 
   1275 	/* last stuff */
   1276 	ZONEDB_DESTROYLOCK(&zone->dblock);
   1277 	isc_mutex_destroy(&zone->lock);
   1278 	zone->magic = 0;
   1279 	mctx = zone->mctx;
   1280 	isc_mem_put(mctx, zone, sizeof(*zone));
   1281 	isc_mem_detach(&mctx);
   1282 }
   1283 
   1284 /*
   1285  * Returns true iff this the signed side of an inline-signing zone.
   1286  * Caller should hold zone lock.
   1287  */
   1288 static inline bool
   1289 inline_secure(dns_zone_t *zone) {
   1290 	REQUIRE(DNS_ZONE_VALID(zone));
   1291 	if (zone->raw != NULL)
   1292 		return (true);
   1293 	return (false);
   1294 }
   1295 
   1296 /*
   1297  * Returns true iff this the unsigned side of an inline-signing zone
   1298  * Caller should hold zone lock.
   1299  */
   1300 static inline bool
   1301 inline_raw(dns_zone_t *zone) {
   1302 	REQUIRE(DNS_ZONE_VALID(zone));
   1303 	if (zone->secure != NULL)
   1304 		return (true);
   1305 	return (false);
   1306 }
   1307 
   1308 /*
   1309  *	Single shot.
   1310  */
   1311 void
   1312 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
   1313 	char namebuf[1024];
   1314 
   1315 	REQUIRE(DNS_ZONE_VALID(zone));
   1316 	REQUIRE(rdclass != dns_rdataclass_none);
   1317 
   1318 	/*
   1319 	 * Test and set.
   1320 	 */
   1321 	LOCK_ZONE(zone);
   1322 	INSIST(zone != zone->raw);
   1323 	REQUIRE(zone->rdclass == dns_rdataclass_none ||
   1324 		zone->rdclass == rdclass);
   1325 	zone->rdclass = rdclass;
   1326 
   1327 	if (zone->strnamerd != NULL)
   1328 		isc_mem_free(zone->mctx, zone->strnamerd);
   1329 	if (zone->strrdclass != NULL)
   1330 		isc_mem_free(zone->mctx, zone->strrdclass);
   1331 
   1332 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1333 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1334 	zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
   1335 	zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
   1336 
   1337 	if (inline_secure(zone))
   1338 		dns_zone_setclass(zone->raw, rdclass);
   1339 	UNLOCK_ZONE(zone);
   1340 }
   1341 
   1342 dns_rdataclass_t
   1343 dns_zone_getclass(dns_zone_t *zone) {
   1344 	REQUIRE(DNS_ZONE_VALID(zone));
   1345 
   1346 	return (zone->rdclass);
   1347 }
   1348 
   1349 void
   1350 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
   1351 	REQUIRE(DNS_ZONE_VALID(zone));
   1352 
   1353 	LOCK_ZONE(zone);
   1354 	zone->notifytype = notifytype;
   1355 	UNLOCK_ZONE(zone);
   1356 }
   1357 
   1358 isc_result_t
   1359 dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
   1360 	isc_result_t result;
   1361 	unsigned int soacount;
   1362 
   1363 	REQUIRE(DNS_ZONE_VALID(zone));
   1364 	REQUIRE(serialp != NULL);
   1365 
   1366 	LOCK_ZONE(zone);
   1367 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   1368 	if (zone->db != NULL) {
   1369 		result = zone_get_from_db(zone, zone->db, NULL, &soacount,
   1370 					  serialp, NULL, NULL, NULL, NULL,
   1371 					  NULL);
   1372 		if (result == ISC_R_SUCCESS && soacount == 0)
   1373 			result = ISC_R_FAILURE;
   1374 	} else
   1375 		result = DNS_R_NOTLOADED;
   1376 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   1377 	UNLOCK_ZONE(zone);
   1378 
   1379 	return (result);
   1380 }
   1381 
   1382 /*
   1383  *	Single shot.
   1384  */
   1385 void
   1386 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
   1387 	char namebuf[1024];
   1388 
   1389 	REQUIRE(DNS_ZONE_VALID(zone));
   1390 	REQUIRE(type != dns_zone_none);
   1391 
   1392 	/*
   1393 	 * Test and set.
   1394 	 */
   1395 	LOCK_ZONE(zone);
   1396 	REQUIRE(zone->type == dns_zone_none || zone->type == type);
   1397 	zone->type = type;
   1398 
   1399 	if (zone->strnamerd != NULL)
   1400 		isc_mem_free(zone->mctx, zone->strnamerd);
   1401 
   1402 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1403 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1404 	UNLOCK_ZONE(zone);
   1405 }
   1406 
   1407 static void
   1408 zone_freedbargs(dns_zone_t *zone) {
   1409 	unsigned int i;
   1410 
   1411 	/* Free the old database argument list. */
   1412 	if (zone->db_argv != NULL) {
   1413 		for (i = 0; i < zone->db_argc; i++)
   1414 			isc_mem_free(zone->mctx, zone->db_argv[i]);
   1415 		isc_mem_put(zone->mctx, zone->db_argv,
   1416 			    zone->db_argc * sizeof(*zone->db_argv));
   1417 	}
   1418 	zone->db_argc = 0;
   1419 	zone->db_argv = NULL;
   1420 }
   1421 
   1422 isc_result_t
   1423 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
   1424 	size_t size = 0;
   1425 	unsigned int i;
   1426 	isc_result_t result = ISC_R_SUCCESS;
   1427 	void *mem;
   1428 	char **tmp, *tmp2, *base;
   1429 
   1430 	REQUIRE(DNS_ZONE_VALID(zone));
   1431 	REQUIRE(argv != NULL && *argv == NULL);
   1432 
   1433 	LOCK_ZONE(zone);
   1434 	size = (zone->db_argc + 1) * sizeof(char *);
   1435 	for (i = 0; i < zone->db_argc; i++)
   1436 		size += strlen(zone->db_argv[i]) + 1;
   1437 	mem = isc_mem_allocate(mctx, size);
   1438 	if (mem != NULL) {
   1439 		tmp = mem;
   1440 		tmp2 = mem;
   1441 		base = mem;
   1442 		tmp2 += (zone->db_argc + 1) * sizeof(char *);
   1443 		for (i = 0; i < zone->db_argc; i++) {
   1444 			*tmp++ = tmp2;
   1445 			strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
   1446 			tmp2 += strlen(tmp2) + 1;
   1447 		}
   1448 		*tmp = NULL;
   1449 	} else
   1450 		result = ISC_R_NOMEMORY;
   1451 	UNLOCK_ZONE(zone);
   1452 	*argv = mem;
   1453 	return (result);
   1454 }
   1455 
   1456 isc_result_t
   1457 dns_zone_setdbtype(dns_zone_t *zone,
   1458 		   unsigned int dbargc, const char * const *dbargv)
   1459 {
   1460 	isc_result_t result = ISC_R_SUCCESS;
   1461 	char **argv = NULL;
   1462 	unsigned int i;
   1463 
   1464 	REQUIRE(DNS_ZONE_VALID(zone));
   1465 	REQUIRE(dbargc >= 1);
   1466 	REQUIRE(dbargv != NULL);
   1467 
   1468 	LOCK_ZONE(zone);
   1469 
   1470 	/* Set up a new database argument list. */
   1471 	argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
   1472 	if (argv == NULL) {
   1473 		goto nomem;
   1474 	}
   1475 	for (i = 0; i < dbargc; i++) {
   1476 		argv[i] = NULL;
   1477 	}
   1478 	for (i = 0; i < dbargc; i++) {
   1479 		argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
   1480 		if (argv[i] == NULL)
   1481 			goto nomem;
   1482 	}
   1483 
   1484 	/* Free the old list. */
   1485 	zone_freedbargs(zone);
   1486 
   1487 	zone->db_argc = dbargc;
   1488 	zone->db_argv = argv;
   1489 	result = ISC_R_SUCCESS;
   1490 	goto unlock;
   1491 
   1492  nomem:
   1493 	if (argv != NULL) {
   1494 		for (i = 0; i < dbargc; i++) {
   1495 			if (argv[i] != NULL) {
   1496 				isc_mem_free(zone->mctx, argv[i]);
   1497 			}
   1498 		}
   1499 		isc_mem_put(zone->mctx, argv, dbargc * sizeof(*argv));
   1500 	}
   1501 	result = ISC_R_NOMEMORY;
   1502 
   1503  unlock:
   1504 	UNLOCK_ZONE(zone);
   1505 	return (result);
   1506 }
   1507 
   1508 static void
   1509 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
   1510 	char namebuf[1024];
   1511 
   1512 	if (zone->prev_view == NULL && zone->view != NULL) {
   1513 		dns_view_weakattach(zone->view, &zone->prev_view);
   1514 	}
   1515 
   1516 	INSIST(zone != zone->raw);
   1517 	if (zone->view != NULL) {
   1518 		dns_view_weakdetach(&zone->view);
   1519 	}
   1520 	dns_view_weakattach(view, &zone->view);
   1521 
   1522 	if (zone->strviewname != NULL) {
   1523 		isc_mem_free(zone->mctx, zone->strviewname);
   1524 	}
   1525 	if (zone->strnamerd != NULL) {
   1526 		isc_mem_free(zone->mctx, zone->strnamerd);
   1527 	}
   1528 
   1529 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1530 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1531 	zone_viewname_tostr(zone, namebuf, sizeof namebuf);
   1532 	zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
   1533 
   1534 	if (inline_secure(zone)) {
   1535 		dns_zone_setview(zone->raw, view);
   1536 	}
   1537 }
   1538 
   1539 void
   1540 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
   1541 	REQUIRE(DNS_ZONE_VALID(zone));
   1542 
   1543 	LOCK_ZONE(zone);
   1544 	dns_zone_setview_helper(zone, view);
   1545 	UNLOCK_ZONE(zone);
   1546 }
   1547 
   1548 dns_view_t *
   1549 dns_zone_getview(dns_zone_t *zone) {
   1550 	REQUIRE(DNS_ZONE_VALID(zone));
   1551 
   1552 	return (zone->view);
   1553 }
   1554 
   1555 void
   1556 dns_zone_setviewcommit(dns_zone_t *zone) {
   1557 	REQUIRE(DNS_ZONE_VALID(zone));
   1558 
   1559 	LOCK_ZONE(zone);
   1560 	if (zone->prev_view != NULL)
   1561 		dns_view_weakdetach(&zone->prev_view);
   1562 	UNLOCK_ZONE(zone);
   1563 }
   1564 
   1565 void
   1566 dns_zone_setviewrevert(dns_zone_t *zone) {
   1567 	REQUIRE(DNS_ZONE_VALID(zone));
   1568 
   1569 	LOCK_ZONE(zone);
   1570 	if (zone->prev_view != NULL) {
   1571 		dns_zone_setview_helper(zone, zone->prev_view);
   1572 		dns_view_weakdetach(&zone->prev_view);
   1573 	}
   1574 	UNLOCK_ZONE(zone);
   1575 }
   1576 
   1577 isc_result_t
   1578 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
   1579 	isc_result_t result;
   1580 	char namebuf[1024];
   1581 
   1582 	REQUIRE(DNS_ZONE_VALID(zone));
   1583 	REQUIRE(origin != NULL);
   1584 
   1585 	LOCK_ZONE(zone);
   1586 	INSIST(zone != zone->raw);
   1587 	if (dns_name_dynamic(&zone->origin)) {
   1588 		dns_name_free(&zone->origin, zone->mctx);
   1589 		dns_name_init(&zone->origin, NULL);
   1590 	}
   1591 	result = dns_name_dup(origin, zone->mctx, &zone->origin);
   1592 
   1593 	if (zone->strnamerd != NULL)
   1594 		isc_mem_free(zone->mctx, zone->strnamerd);
   1595 	if (zone->strname != NULL)
   1596 		isc_mem_free(zone->mctx, zone->strname);
   1597 
   1598 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1599 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1600 	zone_name_tostr(zone, namebuf, sizeof namebuf);
   1601 	zone->strname = isc_mem_strdup(zone->mctx, namebuf);
   1602 
   1603 	if (result == ISC_R_SUCCESS && inline_secure(zone))
   1604 		result = dns_zone_setorigin(zone->raw, origin);
   1605 	UNLOCK_ZONE(zone);
   1606 	return (result);
   1607 }
   1608 
   1609 static isc_result_t
   1610 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
   1611 	char *copy;
   1612 
   1613 	if (value != NULL) {
   1614 		copy = isc_mem_strdup(zone->mctx, value);
   1615 		if (copy == NULL)
   1616 			return (ISC_R_NOMEMORY);
   1617 	} else {
   1618 		copy = NULL;
   1619 	}
   1620 
   1621 	if (*field != NULL)
   1622 		isc_mem_free(zone->mctx, *field);
   1623 
   1624 	*field = copy;
   1625 	return (ISC_R_SUCCESS);
   1626 }
   1627 
   1628 isc_result_t
   1629 dns_zone_setfile(dns_zone_t *zone, const char *file,
   1630 		 dns_masterformat_t format,
   1631 		 const dns_master_style_t *style)
   1632 {
   1633 	isc_result_t result = ISC_R_SUCCESS;
   1634 
   1635 	REQUIRE(DNS_ZONE_VALID(zone));
   1636 
   1637 	LOCK_ZONE(zone);
   1638 	result = dns_zone_setstring(zone, &zone->masterfile, file);
   1639 	if (result == ISC_R_SUCCESS) {
   1640 		zone->masterformat = format;
   1641 		if (format == dns_masterformat_text)
   1642 			zone->masterstyle = style;
   1643 		result = default_journal(zone);
   1644 	}
   1645 	UNLOCK_ZONE(zone);
   1646 
   1647 	return (result);
   1648 }
   1649 
   1650 const char *
   1651 dns_zone_getfile(dns_zone_t *zone) {
   1652 	REQUIRE(DNS_ZONE_VALID(zone));
   1653 
   1654 	return (zone->masterfile);
   1655 }
   1656 
   1657 dns_ttl_t
   1658 dns_zone_getmaxttl(dns_zone_t *zone) {
   1659 	REQUIRE(DNS_ZONE_VALID(zone));
   1660 
   1661 	return (zone->maxttl);
   1662 }
   1663 
   1664 void
   1665 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
   1666 	REQUIRE(DNS_ZONE_VALID(zone));
   1667 
   1668 	LOCK_ZONE(zone);
   1669 	if (maxttl != 0)
   1670 		zone->options |= DNS_ZONEOPT_CHECKTTL;
   1671 	else
   1672 		zone->options &= ~DNS_ZONEOPT_CHECKTTL;
   1673 	zone->maxttl = maxttl;
   1674 	UNLOCK_ZONE(zone);
   1675 
   1676 	return;
   1677 }
   1678 
   1679 static isc_result_t
   1680 default_journal(dns_zone_t *zone) {
   1681 	isc_result_t result;
   1682 	char *journal;
   1683 
   1684 	REQUIRE(DNS_ZONE_VALID(zone));
   1685 	REQUIRE(LOCKED_ZONE(zone));
   1686 
   1687 	if (zone->masterfile != NULL) {
   1688 		/* Calculate string length including '\0'. */
   1689 		int len = strlen(zone->masterfile) + sizeof(".jnl");
   1690 		journal = isc_mem_allocate(zone->mctx, len);
   1691 		if (journal == NULL)
   1692 			return (ISC_R_NOMEMORY);
   1693 		strlcpy(journal, zone->masterfile, len);
   1694 		strlcat(journal, ".jnl", len);
   1695 	} else {
   1696 		journal = NULL;
   1697 	}
   1698 	result = dns_zone_setstring(zone, &zone->journal, journal);
   1699 	if (journal != NULL)
   1700 		isc_mem_free(zone->mctx, journal);
   1701 	return (result);
   1702 }
   1703 
   1704 isc_result_t
   1705 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
   1706 	isc_result_t result = ISC_R_SUCCESS;
   1707 
   1708 	REQUIRE(DNS_ZONE_VALID(zone));
   1709 
   1710 	LOCK_ZONE(zone);
   1711 	result = dns_zone_setstring(zone, &zone->journal, myjournal);
   1712 	UNLOCK_ZONE(zone);
   1713 
   1714 	return (result);
   1715 }
   1716 
   1717 char *
   1718 dns_zone_getjournal(dns_zone_t *zone) {
   1719 	REQUIRE(DNS_ZONE_VALID(zone));
   1720 
   1721 	return (zone->journal);
   1722 }
   1723 
   1724 /*
   1725  * Return true iff the zone is "dynamic", in the sense that the zone's
   1726  * master file (if any) is written by the server, rather than being
   1727  * updated manually and read by the server.
   1728  *
   1729  * This is true for slave zones, mirror zones, stub zones, key zones,
   1730  * and zones that allow dynamic updates either by having an update
   1731  * policy ("ssutable") or an "allow-update" ACL with a value other than
   1732  * exactly "{ none; }".
   1733  */
   1734 bool
   1735 dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
   1736 	REQUIRE(DNS_ZONE_VALID(zone));
   1737 
   1738 	if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
   1739 	    zone->type == dns_zone_stub || zone->type == dns_zone_key ||
   1740 	    (zone->type == dns_zone_redirect && zone->masters != NULL))
   1741 		return (true);
   1742 
   1743 	/* Inline zones are always dynamic. */
   1744 	if (zone->type == dns_zone_master && zone->raw != NULL)
   1745 		return (true);
   1746 
   1747 	/* If !ignore_freeze, we need check whether updates are disabled.  */
   1748 	if (zone->type == dns_zone_master &&
   1749 	    (!zone->update_disabled || ignore_freeze) &&
   1750 	    ((zone->ssutable != NULL) ||
   1751 	     (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
   1752 		return (true);
   1753 
   1754 	return (false);
   1755 
   1756 }
   1757 
   1758 /*
   1759  * Set the response policy index and information for a zone.
   1760  */
   1761 isc_result_t
   1762 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
   1763 		    dns_rpz_num_t rpz_num)
   1764 {
   1765 	/*
   1766 	 * Only RBTDB zones can be used for response policy zones,
   1767 	 * because only they have the code to create the summary data.
   1768 	 * Only zones that are loaded instead of mmap()ed create the
   1769 	 * summary data and so can be policy zones.
   1770 	 */
   1771 	if (strcmp(zone->db_argv[0], "rbt") != 0 &&
   1772 	    strcmp(zone->db_argv[0], "rbt64") != 0)
   1773 		return (ISC_R_NOTIMPLEMENTED);
   1774 	if (zone->masterformat == dns_masterformat_map)
   1775 		return (ISC_R_NOTIMPLEMENTED);
   1776 
   1777 	/*
   1778 	 * This must happen only once or be redundant.
   1779 	 */
   1780 	LOCK_ZONE(zone);
   1781 	if (zone->rpzs != NULL) {
   1782 		REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
   1783 	} else {
   1784 		REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
   1785 		dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
   1786 		zone->rpz_num = rpz_num;
   1787 	}
   1788 	rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
   1789 	UNLOCK_ZONE(zone);
   1790 
   1791 	return (ISC_R_SUCCESS);
   1792 }
   1793 
   1794 dns_rpz_num_t
   1795 dns_zone_get_rpz_num(dns_zone_t *zone) {
   1796 	return (zone->rpz_num);
   1797 }
   1798 
   1799 /*
   1800  * If a zone is a response policy zone, mark its new database.
   1801  */
   1802 void
   1803 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
   1804 	isc_result_t result;
   1805 	if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
   1806 		return;
   1807 	}
   1808 	REQUIRE(zone->rpzs != NULL);
   1809 	result = dns_db_updatenotify_register(db,
   1810 					      dns_rpz_dbupdate_callback,
   1811 					      zone->rpzs->zones[zone->rpz_num]);
   1812 	REQUIRE(result == ISC_R_SUCCESS);
   1813 }
   1814 
   1815 static void
   1816 dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
   1817 	if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
   1818 		return;
   1819 	}
   1820 	REQUIRE(zone->rpzs != NULL);
   1821 	(void) dns_db_updatenotify_unregister(db,
   1822 					      dns_rpz_dbupdate_callback,
   1823 					      zone->rpzs->zones[zone->rpz_num]);
   1824 }
   1825 
   1826 void
   1827 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
   1828 	REQUIRE(DNS_ZONE_VALID(zone));
   1829 	REQUIRE(catzs != NULL);
   1830 
   1831 	LOCK_ZONE(zone);
   1832 	INSIST(zone->catzs == NULL || zone->catzs == catzs);
   1833 	dns_catz_catzs_set_view(catzs, zone->view);
   1834 	if (zone->catzs == NULL) {
   1835 		dns_catz_catzs_attach(catzs, &zone->catzs);
   1836 	}
   1837 	UNLOCK_ZONE(zone);
   1838 }
   1839 
   1840 /*
   1841  * If a zone is a catalog zone, attach it to update notification in database.
   1842  */
   1843 void
   1844 dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
   1845 	REQUIRE(DNS_ZONE_VALID(zone));
   1846 	REQUIRE(db != NULL);
   1847 
   1848 	if (zone->catzs != NULL) {
   1849 		dns_db_updatenotify_register(db, dns_catz_dbupdate_callback,
   1850 					     zone->catzs);
   1851 	}
   1852 }
   1853 
   1854 static void
   1855 dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
   1856 	REQUIRE(DNS_ZONE_VALID(zone));
   1857 	REQUIRE(db != NULL);
   1858 
   1859 	if (zone->catzs != NULL) {
   1860 		dns_db_updatenotify_unregister(db, dns_catz_dbupdate_callback,
   1861 					       zone->catzs);
   1862 	}
   1863 }
   1864 
   1865 /*
   1866  * Set catalog zone ownership of the zone
   1867  */
   1868 void
   1869 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
   1870 	REQUIRE(DNS_ZONE_VALID(zone));
   1871 	REQUIRE(catz != NULL);
   1872 	LOCK_ZONE(zone);
   1873 	INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
   1874 	zone->parentcatz = catz;
   1875 	UNLOCK_ZONE(zone);
   1876 }
   1877 
   1878 dns_catz_zone_t *
   1879 dns_zone_get_parentcatz(const dns_zone_t *zone) {
   1880 	REQUIRE(DNS_ZONE_VALID(zone));
   1881 	return (zone->parentcatz);
   1882 }
   1883 
   1884 
   1885 static bool
   1886 zone_touched(dns_zone_t *zone) {
   1887 	isc_result_t result;
   1888 	isc_time_t modtime;
   1889 	dns_include_t *include;
   1890 
   1891 	REQUIRE(DNS_ZONE_VALID(zone));
   1892 
   1893 	result = isc_file_getmodtime(zone->masterfile, &modtime);
   1894 	if (result != ISC_R_SUCCESS ||
   1895 	    isc_time_compare(&modtime, &zone->loadtime) > 0)
   1896 		return (true);
   1897 
   1898 	for (include = ISC_LIST_HEAD(zone->includes);
   1899 	     include != NULL;
   1900 	     include = ISC_LIST_NEXT(include, link))
   1901 	{
   1902 		result = isc_file_getmodtime(include->name, &modtime);
   1903 		if (result != ISC_R_SUCCESS ||
   1904 		    isc_time_compare(&modtime, &include->filetime) > 0)
   1905 			return (true);
   1906 	}
   1907 
   1908 	return (false);
   1909 }
   1910 
   1911 /*
   1912  * Note: when dealing with inline-signed zones, external callers will always
   1913  * call zone_load() for the secure zone; zone_load() calls itself recursively
   1914  * in order to load the raw zone.
   1915  */
   1916 static isc_result_t
   1917 zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
   1918 	isc_result_t result;
   1919 	isc_time_t now;
   1920 	isc_time_t loadtime;
   1921 	dns_db_t *db = NULL;
   1922 	bool rbt, hasraw;
   1923 
   1924 	REQUIRE(DNS_ZONE_VALID(zone));
   1925 
   1926 	if (!locked)
   1927 		LOCK_ZONE(zone);
   1928 
   1929 	INSIST(zone != zone->raw);
   1930 	hasraw = inline_secure(zone);
   1931 	if (hasraw) {
   1932 		/*
   1933 		 * We are trying to load an inline-signed zone.  First call
   1934 		 * self recursively to try loading the raw version of the zone.
   1935 		 * Assuming the raw zone file is readable, there are two
   1936 		 * possibilities:
   1937 		 *
   1938 		 *  a) the raw zone was not yet loaded and thus it will be
   1939 		 *     loaded now, synchronously; if this succeeds, a
   1940 		 *     subsequent attempt to load the signed zone file will
   1941 		 *     take place and thus zone_postload() will be called
   1942 		 *     twice: first for the raw zone and then for the secure
   1943 		 *     zone; the latter call will take care of syncing the raw
   1944 		 *     version with the secure version,
   1945 		 *
   1946 		 *  b) the raw zone was already loaded and we are trying to
   1947 		 *     reload it, which will happen asynchronously; this means
   1948 		 *     zone_postload() will only be called for the raw zone
   1949 		 *     because "result" returned by the zone_load() call below
   1950 		 *     will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
   1951 		 *     zone_postload() called for the raw zone will take care
   1952 		 *     of syncing the raw version with the secure version.
   1953 		 */
   1954 		result = zone_load(zone->raw, flags, false);
   1955 		if (result != ISC_R_SUCCESS) {
   1956 			if (!locked)
   1957 				UNLOCK_ZONE(zone);
   1958 			return(result);
   1959 		}
   1960 		LOCK_ZONE(zone->raw);
   1961 	}
   1962 
   1963 	TIME_NOW(&now);
   1964 
   1965 	INSIST(zone->type != dns_zone_none);
   1966 
   1967 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
   1968 		if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
   1969 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
   1970 		result = DNS_R_CONTINUE;
   1971 		goto cleanup;
   1972 	}
   1973 
   1974 	INSIST(zone->db_argc >= 1);
   1975 
   1976 	rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
   1977 	      strcmp(zone->db_argv[0], "rbt64") == 0;
   1978 
   1979 	if (zone->db != NULL && zone->masterfile == NULL && rbt) {
   1980 		/*
   1981 		 * The zone has no master file configured.
   1982 		 */
   1983 		result = ISC_R_SUCCESS;
   1984 		goto cleanup;
   1985 	}
   1986 
   1987 	if (zone->db != NULL && dns_zone_isdynamic(zone, false)) {
   1988 		/*
   1989 		 * This is a slave, stub, or dynamically updated
   1990 		 * zone being reloaded.  Do nothing - the database
   1991 		 * we already have is guaranteed to be up-to-date.
   1992 		 */
   1993 		if (zone->type == dns_zone_master && !hasraw)
   1994 			result = DNS_R_DYNAMIC;
   1995 		else
   1996 			result = ISC_R_SUCCESS;
   1997 		goto cleanup;
   1998 	}
   1999 
   2000 	/*
   2001 	 * Store the current time before the zone is loaded, so that if the
   2002 	 * file changes between the time of the load and the time that
   2003 	 * zone->loadtime is set, then the file will still be reloaded
   2004 	 * the next time dns_zone_load is called.
   2005 	 */
   2006 	TIME_NOW(&loadtime);
   2007 
   2008 	/*
   2009 	 * Don't do the load if the file that stores the zone is older
   2010 	 * than the last time the zone was loaded.  If the zone has not
   2011 	 * been loaded yet, zone->loadtime will be the epoch.
   2012 	 */
   2013 	if (zone->masterfile != NULL) {
   2014 		isc_time_t filetime;
   2015 
   2016 		/*
   2017 		 * The file is already loaded.	If we are just doing a
   2018 		 * "rndc reconfig", we are done.
   2019 		 */
   2020 		if (!isc_time_isepoch(&zone->loadtime) &&
   2021 		    (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
   2022 			result = ISC_R_SUCCESS;
   2023 			goto cleanup;
   2024 		}
   2025 
   2026 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   2027 		    !zone_touched(zone))
   2028 		{
   2029 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2030 				      ISC_LOG_DEBUG(1),
   2031 				      "skipping load: master file "
   2032 				      "older than last load");
   2033 			result = DNS_R_UPTODATE;
   2034 			goto cleanup;
   2035 		}
   2036 
   2037 		/*
   2038 		 * If the file modification time is in the past
   2039 		 * set loadtime to that value.
   2040 		 */
   2041 		result = isc_file_getmodtime(zone->masterfile, &filetime);
   2042 		if (result == ISC_R_SUCCESS &&
   2043 		    isc_time_compare(&loadtime, &filetime) > 0)
   2044 			loadtime = filetime;
   2045 	}
   2046 
   2047 	/*
   2048 	 * Built in zones (with the exception of empty zones) don't need
   2049 	 * to be reloaded.
   2050 	 */
   2051 	if (zone->type == dns_zone_master &&
   2052 	    strcmp(zone->db_argv[0], "_builtin") == 0 &&
   2053 	    (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
   2054 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   2055 		result = ISC_R_SUCCESS;
   2056 		goto cleanup;
   2057 	}
   2058 
   2059 	/*
   2060 	 * Zones associated with a DLZ don't need to be loaded either,
   2061 	 * but we need to associate the database with the zone object.
   2062 	 */
   2063 	if (strcmp(zone->db_argv[0], "dlz") == 0) {
   2064 		dns_dlzdb_t *dlzdb;
   2065 		dns_dlzfindzone_t findzone;
   2066 
   2067 		for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
   2068 		     dlzdb != NULL;
   2069 		     dlzdb = ISC_LIST_NEXT(dlzdb, link))
   2070 		{
   2071 			INSIST(DNS_DLZ_VALID(dlzdb));
   2072 			if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0)
   2073 				break;
   2074 		}
   2075 
   2076 		if (dlzdb == NULL) {
   2077 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2078 				      ISC_LOG_ERROR,
   2079 				      "DLZ %s does not exist or is set "
   2080 				      "to 'search yes;'", zone->db_argv[1]);
   2081 			result = ISC_R_NOTFOUND;
   2082 			goto cleanup;
   2083 		}
   2084 
   2085 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   2086 		/* ask SDLZ driver if the zone is supported */
   2087 		findzone = dlzdb->implementation->methods->findzone;
   2088 		result = (*findzone)(dlzdb->implementation->driverarg,
   2089 				     dlzdb->dbdata, dlzdb->mctx,
   2090 				     zone->view->rdclass, &zone->origin,
   2091 				     NULL, NULL, &db);
   2092 		if (result != ISC_R_NOTFOUND) {
   2093 			if (zone->db != NULL)
   2094 				zone_detachdb(zone);
   2095 			zone_attachdb(zone, db);
   2096 			dns_db_detach(&db);
   2097 			result = ISC_R_SUCCESS;
   2098 		}
   2099 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   2100 
   2101 		if (result == ISC_R_SUCCESS) {
   2102 			if (dlzdb->configure_callback == NULL)
   2103 				goto cleanup;
   2104 
   2105 			result = (*dlzdb->configure_callback)(zone->view,
   2106 							      dlzdb, zone);
   2107 			if (result != ISC_R_SUCCESS)
   2108 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2109 					      ISC_LOG_ERROR,
   2110 					      "DLZ configuration callback: %s",
   2111 					      isc_result_totext(result));
   2112 		}
   2113 		goto cleanup;
   2114 	}
   2115 
   2116 	if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
   2117 	     zone->type == dns_zone_stub ||
   2118 	     (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
   2119 	    rbt) {
   2120 		if (zone->masterfile == NULL ||
   2121 		    !isc_file_exists(zone->masterfile)) {
   2122 			if (zone->masterfile != NULL) {
   2123 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2124 					      ISC_LOG_DEBUG(1),
   2125 					     "no master file");
   2126 			}
   2127 			zone->refreshtime = now;
   2128 			if (zone->task != NULL)
   2129 				zone_settimer(zone, &now);
   2130 			result = ISC_R_SUCCESS;
   2131 			goto cleanup;
   2132 		}
   2133 	}
   2134 
   2135 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2136 		      ISC_LOG_DEBUG(1), "starting load");
   2137 
   2138 	result = dns_db_create(zone->mctx, zone->db_argv[0],
   2139 			       &zone->origin, (zone->type == dns_zone_stub) ?
   2140 			       dns_dbtype_stub : dns_dbtype_zone,
   2141 			       zone->rdclass,
   2142 			       zone->db_argc - 1, zone->db_argv + 1,
   2143 			       &db);
   2144 
   2145 	if (result != ISC_R_SUCCESS) {
   2146 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   2147 			     "loading zone: creating database: %s",
   2148 			     isc_result_totext(result));
   2149 		goto cleanup;
   2150 	}
   2151 	dns_db_settask(db, zone->task);
   2152 
   2153 	if (zone->type == dns_zone_master || zone->type == dns_zone_slave ||
   2154 	    zone->type == dns_zone_mirror)
   2155 	{
   2156 		result = dns_db_setgluecachestats(db, zone->gluecachestats);
   2157 		if (result == ISC_R_NOTIMPLEMENTED) {
   2158 			result = ISC_R_SUCCESS;
   2159 		}
   2160 		if (result != ISC_R_SUCCESS) {
   2161 			goto cleanup;
   2162 		}
   2163 	}
   2164 
   2165 	if (!dns_db_ispersistent(db)) {
   2166 		if (zone->masterfile != NULL) {
   2167 			result = zone_startload(db, zone, loadtime);
   2168 		} else {
   2169 			result = DNS_R_NOMASTERFILE;
   2170 			if (zone->type == dns_zone_master ||
   2171 			    (zone->type == dns_zone_redirect &&
   2172 			     zone->masters == NULL)) {
   2173 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2174 					      ISC_LOG_ERROR,
   2175 					     "loading zone: "
   2176 					     "no master file configured");
   2177 				goto cleanup;
   2178 			}
   2179 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2180 				      ISC_LOG_INFO, "loading zone: "
   2181 				      "no master file configured: continuing");
   2182 		}
   2183 	}
   2184 
   2185 	if (result == DNS_R_CONTINUE) {
   2186 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
   2187 		if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
   2188 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
   2189 		goto cleanup;
   2190 	}
   2191 
   2192 	result = zone_postload(zone, db, loadtime, result);
   2193 
   2194  cleanup:
   2195 	if (hasraw)
   2196 		UNLOCK_ZONE(zone->raw);
   2197 	if (!locked)
   2198 		UNLOCK_ZONE(zone);
   2199 	if (db != NULL)
   2200 		dns_db_detach(&db);
   2201 	return (result);
   2202 }
   2203 
   2204 isc_result_t
   2205 dns_zone_load(dns_zone_t *zone, bool newonly) {
   2206 	return (zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false));
   2207 }
   2208 
   2209 static void
   2210 zone_asyncload(isc_task_t *task, isc_event_t *event) {
   2211 	dns_asyncload_t *asl = event->ev_arg;
   2212 	dns_zone_t *zone = asl->zone;
   2213 	isc_result_t result;
   2214 
   2215 	UNUSED(task);
   2216 
   2217 	REQUIRE(DNS_ZONE_VALID(zone));
   2218 
   2219 	isc_event_free(&event);
   2220 
   2221 	LOCK_ZONE(zone);
   2222 	result = zone_load(zone, asl->flags, true);
   2223 	if (result != DNS_R_CONTINUE) {
   2224 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
   2225 	}
   2226 	UNLOCK_ZONE(zone);
   2227 
   2228 	/* Inform the zone table we've finished loading */
   2229 	if (asl->loaded != NULL)
   2230 		(asl->loaded)(asl->loaded_arg, zone, task);
   2231 
   2232 	isc_mem_put(zone->mctx, asl, sizeof (*asl));
   2233 	dns_zone_idetach(&zone);
   2234 }
   2235 
   2236 isc_result_t
   2237 dns_zone_asyncload(dns_zone_t *zone, bool newonly,
   2238 		   dns_zt_zoneloaded_t done, void *arg)
   2239 {
   2240 	isc_event_t *e;
   2241 	dns_asyncload_t *asl = NULL;
   2242 	isc_result_t result = ISC_R_SUCCESS;
   2243 
   2244 	REQUIRE(DNS_ZONE_VALID(zone));
   2245 
   2246 	if (zone->zmgr == NULL)
   2247 		return (ISC_R_FAILURE);
   2248 
   2249 	/* If we already have a load pending, stop now */
   2250 	LOCK_ZONE(zone);
   2251 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
   2252 		UNLOCK_ZONE(zone);
   2253 		return (ISC_R_ALREADYRUNNING);
   2254 	}
   2255 
   2256 	asl = isc_mem_get(zone->mctx, sizeof (*asl));
   2257 	if (asl == NULL)
   2258 		CHECK(ISC_R_NOMEMORY);
   2259 
   2260 	asl->zone = NULL;
   2261 	asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
   2262 	asl->loaded = done;
   2263 	asl->loaded_arg = arg;
   2264 
   2265 	e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
   2266 			       DNS_EVENT_ZONELOAD,
   2267 			       zone_asyncload, asl,
   2268 			       sizeof(isc_event_t));
   2269 	if (e == NULL)
   2270 		CHECK(ISC_R_NOMEMORY);
   2271 
   2272 	zone_iattach(zone, &asl->zone);
   2273 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
   2274 	isc_task_send(zone->loadtask, &e);
   2275 	UNLOCK_ZONE(zone);
   2276 
   2277 	return (ISC_R_SUCCESS);
   2278 
   2279   failure:
   2280 	if (asl != NULL)
   2281 		isc_mem_put(zone->mctx, asl, sizeof (*asl));
   2282 	UNLOCK_ZONE(zone);
   2283 	return (result);
   2284 }
   2285 
   2286 bool
   2287 dns__zone_loadpending(dns_zone_t *zone) {
   2288 	REQUIRE(DNS_ZONE_VALID(zone));
   2289 
   2290 	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
   2291 }
   2292 
   2293 isc_result_t
   2294 dns_zone_loadandthaw(dns_zone_t *zone) {
   2295 	isc_result_t result;
   2296 
   2297 	if (inline_raw(zone))
   2298 		result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW,
   2299 				   false);
   2300 	else
   2301 		result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
   2302 
   2303 	switch (result) {
   2304 	case DNS_R_CONTINUE:
   2305 		/* Deferred thaw. */
   2306 		break;
   2307 	case DNS_R_UPTODATE:
   2308 	case ISC_R_SUCCESS:
   2309 	case DNS_R_SEENINCLUDE:
   2310 		zone->update_disabled = false;
   2311 		break;
   2312 	case DNS_R_NOMASTERFILE:
   2313 		zone->update_disabled = false;
   2314 		break;
   2315 	default:
   2316 		/* Error, remain in disabled state. */
   2317 		break;
   2318 	}
   2319 	return (result);
   2320 }
   2321 
   2322 static unsigned int
   2323 get_master_options(dns_zone_t *zone) {
   2324 	unsigned int options;
   2325 
   2326 	options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
   2327 	if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
   2328 	    (zone->type == dns_zone_redirect && zone->masters == NULL))
   2329 	{
   2330 		options |= DNS_MASTER_SLAVE;
   2331 	}
   2332 	if (zone->type == dns_zone_key) {
   2333 		options |= DNS_MASTER_KEY;
   2334 	}
   2335 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
   2336 		options |= DNS_MASTER_CHECKNS;
   2337 	}
   2338 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
   2339 		options |= DNS_MASTER_FATALNS;
   2340 	}
   2341 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
   2342 		options |= DNS_MASTER_CHECKNAMES;
   2343 	}
   2344 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
   2345 		options |= DNS_MASTER_CHECKNAMESFAIL;
   2346 	}
   2347 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
   2348 		options |= DNS_MASTER_CHECKMX;
   2349 	}
   2350 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
   2351 		options |= DNS_MASTER_CHECKMXFAIL;
   2352 	}
   2353 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
   2354 		options |= DNS_MASTER_CHECKWILDCARD;
   2355 	}
   2356 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
   2357 		options |= DNS_MASTER_CHECKTTL;
   2358 	}
   2359 
   2360 	return (options);
   2361 }
   2362 
   2363 static void
   2364 zone_registerinclude(const char *filename, void *arg) {
   2365 	isc_result_t result;
   2366 	dns_zone_t *zone = (dns_zone_t *) arg;
   2367 	dns_include_t *inc = NULL;
   2368 
   2369 	REQUIRE(DNS_ZONE_VALID(zone));
   2370 
   2371 	if (filename == NULL)
   2372 		return;
   2373 
   2374 	/*
   2375 	 * Suppress duplicates.
   2376 	 */
   2377 	for (inc = ISC_LIST_HEAD(zone->newincludes);
   2378 	     inc != NULL;
   2379 	     inc = ISC_LIST_NEXT(inc, link))
   2380 		if (strcmp(filename, inc->name) == 0)
   2381 			return;
   2382 
   2383 	inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
   2384 	if (inc == NULL)
   2385 		return;
   2386 	inc->name = isc_mem_strdup(zone->mctx, filename);
   2387 	if (inc->name == NULL) {
   2388 		isc_mem_put(zone->mctx, inc, sizeof(dns_include_t));
   2389 		return;
   2390 	}
   2391 	ISC_LINK_INIT(inc, link);
   2392 
   2393 	result = isc_file_getmodtime(filename, &inc->filetime);
   2394 	if (result != ISC_R_SUCCESS)
   2395 		isc_time_settoepoch(&inc->filetime);
   2396 
   2397 	ISC_LIST_APPEND(zone->newincludes, inc, link);
   2398 }
   2399 
   2400 static void
   2401 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
   2402 	dns_load_t *load = event->ev_arg;
   2403 	isc_result_t result = ISC_R_SUCCESS;
   2404 	unsigned int options;
   2405 
   2406 	REQUIRE(DNS_LOAD_VALID(load));
   2407 
   2408 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
   2409 		result = ISC_R_CANCELED;
   2410 	isc_event_free(&event);
   2411 	if (result == ISC_R_CANCELED)
   2412 		goto fail;
   2413 
   2414 	options = get_master_options(load->zone);
   2415 
   2416 	result = dns_master_loadfileinc(load->zone->masterfile,
   2417 					dns_db_origin(load->db),
   2418 					dns_db_origin(load->db),
   2419 					load->zone->rdclass, options, 0,
   2420 					&load->callbacks, task,
   2421 					zone_loaddone, load,
   2422 					&load->zone->lctx,
   2423 					zone_registerinclude,
   2424 					load->zone, load->zone->mctx,
   2425 					load->zone->masterformat,
   2426 					load->zone->maxttl);
   2427 	if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
   2428 	    result != DNS_R_SEENINCLUDE)
   2429 		goto fail;
   2430 	return;
   2431 
   2432  fail:
   2433 	zone_loaddone(load, result);
   2434 }
   2435 
   2436 static void
   2437 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
   2438 	isc_result_t result;
   2439 	unsigned int soacount;
   2440 
   2441 	LOCK(&raw->lock);
   2442 	if (raw->db != NULL) {
   2443 		result = zone_get_from_db(raw, raw->db, NULL, &soacount,
   2444 					  &rawdata->sourceserial,
   2445 					  NULL, NULL, NULL, NULL,
   2446 					  NULL);
   2447 		if (result == ISC_R_SUCCESS && soacount > 0U)
   2448 			rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
   2449 	}
   2450 	UNLOCK(&raw->lock);
   2451 }
   2452 
   2453 static void
   2454 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
   2455 	const char me[] = "zone_gotwritehandle";
   2456 	dns_zone_t *zone = event->ev_arg;
   2457 	isc_result_t result = ISC_R_SUCCESS;
   2458 	dns_dbversion_t *version = NULL;
   2459 	dns_masterrawheader_t rawdata;
   2460 
   2461 	REQUIRE(DNS_ZONE_VALID(zone));
   2462 	INSIST(task == zone->task);
   2463 	ENTER;
   2464 
   2465 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
   2466 		result = ISC_R_CANCELED;
   2467 	isc_event_free(&event);
   2468 	if (result == ISC_R_CANCELED)
   2469 		goto fail;
   2470 
   2471 	LOCK_ZONE(zone);
   2472 	INSIST(zone != zone->raw);
   2473 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   2474 	if (zone->db != NULL) {
   2475 		const dns_master_style_t *output_style;
   2476 
   2477 		dns_db_currentversion(zone->db, &version);
   2478 		dns_master_initrawheader(&rawdata);
   2479 		if (inline_secure(zone))
   2480 			get_raw_serial(zone->raw, &rawdata);
   2481 		if (zone->type == dns_zone_key)
   2482 			output_style = &dns_master_style_keyzone;
   2483 		else if (zone->masterstyle != NULL)
   2484 			output_style = zone->masterstyle;
   2485 		else
   2486 			output_style = &dns_master_style_default;
   2487 		result = dns_master_dumpinc(zone->mctx, zone->db, version,
   2488 					    output_style, zone->masterfile,
   2489 					    zone->task, dump_done, zone,
   2490 					    &zone->dctx, zone->masterformat,
   2491 					    &rawdata);
   2492 		dns_db_closeversion(zone->db, &version, false);
   2493 	} else
   2494 		result = ISC_R_CANCELED;
   2495 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   2496 	UNLOCK_ZONE(zone);
   2497 	if (result != DNS_R_CONTINUE)
   2498 		goto fail;
   2499 	return;
   2500 
   2501  fail:
   2502 	dump_done(zone, result);
   2503 }
   2504 
   2505 /*
   2506  * Save the raw serial number for inline-signing zones.
   2507  * (XXX: Other information from the header will be used
   2508  * for other purposes in the future, but for now this is
   2509  * all we're interested in.)
   2510  */
   2511 static void
   2512 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
   2513 	if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
   2514 		return;
   2515 
   2516 	zone->sourceserial = header->sourceserial;
   2517 	zone->sourceserialset = true;
   2518 }
   2519 
   2520 void
   2521 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
   2522 	if (zone == NULL)
   2523 		return;
   2524 
   2525 	LOCK_ZONE(zone);
   2526 	zone_setrawdata(zone, header);
   2527 	UNLOCK_ZONE(zone);
   2528 }
   2529 
   2530 static isc_result_t
   2531 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
   2532 	const char me[] = "zone_startload";
   2533 	dns_load_t *load;
   2534 	isc_result_t result;
   2535 	isc_result_t tresult;
   2536 	unsigned int options;
   2537 
   2538 	ENTER;
   2539 
   2540 	dns_zone_rpz_enable_db(zone, db);
   2541 	dns_zone_catz_enable_db(zone, db);
   2542 
   2543 	options = get_master_options(zone);
   2544 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
   2545 		options |= DNS_MASTER_MANYERRORS;
   2546 	}
   2547 
   2548 	if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
   2549 		load = isc_mem_get(zone->mctx, sizeof(*load));
   2550 		if (load == NULL)
   2551 			return (ISC_R_NOMEMORY);
   2552 
   2553 		load->mctx = NULL;
   2554 		load->zone = NULL;
   2555 		load->db = NULL;
   2556 		load->loadtime = loadtime;
   2557 		load->magic = LOAD_MAGIC;
   2558 
   2559 		isc_mem_attach(zone->mctx, &load->mctx);
   2560 		zone_iattach(zone, &load->zone);
   2561 		dns_db_attach(db, &load->db);
   2562 		dns_rdatacallbacks_init(&load->callbacks);
   2563 		load->callbacks.rawdata = zone_setrawdata;
   2564 		zone_iattach(zone, &load->callbacks.zone);
   2565 		result = dns_db_beginload(db, &load->callbacks);
   2566 		if (result != ISC_R_SUCCESS) {
   2567 			goto cleanup;
   2568 		}
   2569 		result = zonemgr_getio(zone->zmgr, true, zone->loadtask,
   2570 				       zone_gotreadhandle, load,
   2571 				       &zone->readio);
   2572 		if (result != ISC_R_SUCCESS) {
   2573 			/*
   2574 			 * We can't report multiple errors so ignore
   2575 			 * the result of dns_db_endload().
   2576 			 */
   2577 			(void)dns_db_endload(load->db, &load->callbacks);
   2578 			goto cleanup;
   2579 		} else {
   2580 			result = DNS_R_CONTINUE;
   2581 		}
   2582 	} else {
   2583 		dns_rdatacallbacks_t callbacks;
   2584 
   2585 		dns_rdatacallbacks_init(&callbacks);
   2586 		callbacks.rawdata = zone_setrawdata;
   2587 		zone_iattach(zone, &callbacks.zone);
   2588 		result = dns_db_beginload(db, &callbacks);
   2589 		if (result != ISC_R_SUCCESS) {
   2590 			zone_idetach(&callbacks.zone);
   2591 			return (result);
   2592 		}
   2593 		result = dns_master_loadfile(zone->masterfile,
   2594 					     &zone->origin, &zone->origin,
   2595 					     zone->rdclass, options, 0,
   2596 					     &callbacks,
   2597 					     zone_registerinclude,
   2598 					     zone, zone->mctx,
   2599 					     zone->masterformat,
   2600 					     zone->maxttl);
   2601 		tresult = dns_db_endload(db, &callbacks);
   2602 		if (result == ISC_R_SUCCESS) {
   2603 			result = tresult;
   2604 		}
   2605 		zone_idetach(&callbacks.zone);
   2606 	}
   2607 
   2608 	return (result);
   2609 
   2610  cleanup:
   2611 	load->magic = 0;
   2612 	dns_db_detach(&load->db);
   2613 	zone_idetach(&load->zone);
   2614 	zone_idetach(&load->callbacks.zone);
   2615 	isc_mem_detach(&load->mctx);
   2616 	isc_mem_put(zone->mctx, load, sizeof(*load));
   2617 	return (result);
   2618 }
   2619 
   2620 static bool
   2621 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
   2622 	      dns_name_t *owner)
   2623 {
   2624 	isc_result_t result;
   2625 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2626 	char namebuf[DNS_NAME_FORMATSIZE];
   2627 	char altbuf[DNS_NAME_FORMATSIZE];
   2628 	dns_fixedname_t fixed;
   2629 	dns_name_t *foundname;
   2630 	int level;
   2631 
   2632 	/*
   2633 	 * "." means the services does not exist.
   2634 	 */
   2635 	if (dns_name_equal(name, dns_rootname))
   2636 		return (true);
   2637 
   2638 	/*
   2639 	 * Outside of zone.
   2640 	 */
   2641 	if (!dns_name_issubdomain(name, &zone->origin)) {
   2642 		if (zone->checkmx != NULL)
   2643 			return ((zone->checkmx)(zone, name, owner));
   2644 		return (true);
   2645 	}
   2646 
   2647 	if (zone->type == dns_zone_master)
   2648 		level = ISC_LOG_ERROR;
   2649 	else
   2650 		level = ISC_LOG_WARNING;
   2651 
   2652 	foundname = dns_fixedname_initname(&fixed);
   2653 
   2654 	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
   2655 			     0, 0, NULL, foundname, NULL, NULL);
   2656 	if (result == ISC_R_SUCCESS)
   2657 		return (true);
   2658 
   2659 	if (result == DNS_R_NXRRSET) {
   2660 		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
   2661 				     0, 0, NULL, foundname, NULL, NULL);
   2662 		if (result == ISC_R_SUCCESS)
   2663 			return (true);
   2664 	}
   2665 
   2666 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
   2667 	dns_name_format(name, namebuf, sizeof namebuf);
   2668 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   2669 	    result == DNS_R_EMPTYNAME) {
   2670 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
   2671 			level = ISC_LOG_WARNING;
   2672 		dns_zone_log(zone, level,
   2673 			     "%s/MX '%s' has no address records (A or AAAA)",
   2674 			     ownerbuf, namebuf);
   2675 		return ((level == ISC_LOG_WARNING) ? true : false);
   2676 	}
   2677 
   2678 	if (result == DNS_R_CNAME) {
   2679 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
   2680 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
   2681 			level = ISC_LOG_WARNING;
   2682 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
   2683 			dns_zone_log(zone, level,
   2684 				     "%s/MX '%s' is a CNAME (illegal)",
   2685 				     ownerbuf, namebuf);
   2686 		return ((level == ISC_LOG_WARNING) ? true : false);
   2687 	}
   2688 
   2689 	if (result == DNS_R_DNAME) {
   2690 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
   2691 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
   2692 			level = ISC_LOG_WARNING;
   2693 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
   2694 			dns_name_format(foundname, altbuf, sizeof altbuf);
   2695 			dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
   2696 				     " '%s' (illegal)", ownerbuf, namebuf,
   2697 				     altbuf);
   2698 		}
   2699 		return ((level == ISC_LOG_WARNING) ? true : false);
   2700 	}
   2701 
   2702 	if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
   2703 		return ((zone->checkmx)(zone, name, owner));
   2704 
   2705 	return (true);
   2706 }
   2707 
   2708 static bool
   2709 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
   2710 	       dns_name_t *owner)
   2711 {
   2712 	isc_result_t result;
   2713 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2714 	char namebuf[DNS_NAME_FORMATSIZE];
   2715 	char altbuf[DNS_NAME_FORMATSIZE];
   2716 	dns_fixedname_t fixed;
   2717 	dns_name_t *foundname;
   2718 	int level;
   2719 
   2720 	/*
   2721 	 * "." means the services does not exist.
   2722 	 */
   2723 	if (dns_name_equal(name, dns_rootname))
   2724 		return (true);
   2725 
   2726 	/*
   2727 	 * Outside of zone.
   2728 	 */
   2729 	if (!dns_name_issubdomain(name, &zone->origin)) {
   2730 		if (zone->checksrv != NULL)
   2731 			return ((zone->checksrv)(zone, name, owner));
   2732 		return (true);
   2733 	}
   2734 
   2735 	if (zone->type == dns_zone_master)
   2736 		level = ISC_LOG_ERROR;
   2737 	else
   2738 		level = ISC_LOG_WARNING;
   2739 
   2740 	foundname = dns_fixedname_initname(&fixed);
   2741 
   2742 	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
   2743 			     0, 0, NULL, foundname, NULL, NULL);
   2744 	if (result == ISC_R_SUCCESS)
   2745 		return (true);
   2746 
   2747 	if (result == DNS_R_NXRRSET) {
   2748 		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
   2749 				     0, 0, NULL, foundname, NULL, NULL);
   2750 		if (result == ISC_R_SUCCESS)
   2751 			return (true);
   2752 	}
   2753 
   2754 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
   2755 	dns_name_format(name, namebuf, sizeof namebuf);
   2756 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   2757 	    result == DNS_R_EMPTYNAME) {
   2758 		dns_zone_log(zone, level,
   2759 			     "%s/SRV '%s' has no address records (A or AAAA)",
   2760 			     ownerbuf, namebuf);
   2761 		/* XXX950 make fatal for 9.5.0. */
   2762 		return (true);
   2763 	}
   2764 
   2765 	if (result == DNS_R_CNAME) {
   2766 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
   2767 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
   2768 			level = ISC_LOG_WARNING;
   2769 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
   2770 			dns_zone_log(zone, level,
   2771 				     "%s/SRV '%s' is a CNAME (illegal)",
   2772 				     ownerbuf, namebuf);
   2773 		return ((level == ISC_LOG_WARNING) ? true : false);
   2774 	}
   2775 
   2776 	if (result == DNS_R_DNAME) {
   2777 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
   2778 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
   2779 			level = ISC_LOG_WARNING;
   2780 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
   2781 			dns_name_format(foundname, altbuf, sizeof altbuf);
   2782 			dns_zone_log(zone, level, "%s/SRV '%s' is below a "
   2783 				     "DNAME '%s' (illegal)", ownerbuf, namebuf,
   2784 				     altbuf);
   2785 		}
   2786 		return ((level == ISC_LOG_WARNING) ? true : false);
   2787 	}
   2788 
   2789 	if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
   2790 		return ((zone->checksrv)(zone, name, owner));
   2791 
   2792 	return (true);
   2793 }
   2794 
   2795 static bool
   2796 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
   2797 		dns_name_t *owner)
   2798 {
   2799 	bool answer = true;
   2800 	isc_result_t result, tresult;
   2801 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2802 	char namebuf[DNS_NAME_FORMATSIZE];
   2803 	char altbuf[DNS_NAME_FORMATSIZE];
   2804 	dns_fixedname_t fixed;
   2805 	dns_name_t *foundname;
   2806 	dns_rdataset_t a;
   2807 	dns_rdataset_t aaaa;
   2808 	int level;
   2809 
   2810 	/*
   2811 	 * Outside of zone.
   2812 	 */
   2813 	if (!dns_name_issubdomain(name, &zone->origin)) {
   2814 		if (zone->checkns != NULL)
   2815 			return ((zone->checkns)(zone, name, owner, NULL, NULL));
   2816 		return (true);
   2817 	}
   2818 
   2819 	if (zone->type == dns_zone_master)
   2820 		level = ISC_LOG_ERROR;
   2821 	else
   2822 		level = ISC_LOG_WARNING;
   2823 
   2824 	foundname = dns_fixedname_initname(&fixed);
   2825 	dns_rdataset_init(&a);
   2826 	dns_rdataset_init(&aaaa);
   2827 
   2828 	/*
   2829 	 * Perform a regular lookup to catch DNAME records then look
   2830 	 * for glue.
   2831 	 */
   2832 	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
   2833 			     0, 0, NULL, foundname, &a, NULL);
   2834 	switch (result) {
   2835 	case ISC_R_SUCCESS:
   2836 	case DNS_R_DNAME:
   2837 	case DNS_R_CNAME:
   2838 		break;
   2839 	default:
   2840 		if (dns_rdataset_isassociated(&a))
   2841 			dns_rdataset_disassociate(&a);
   2842 		result = dns_db_find(db, name, NULL, dns_rdatatype_a,
   2843 				     DNS_DBFIND_GLUEOK, 0, NULL,
   2844 				     foundname, &a, NULL);
   2845 	}
   2846 	if (result == ISC_R_SUCCESS) {
   2847 		dns_rdataset_disassociate(&a);
   2848 		return (true);
   2849 	} else if (result == DNS_R_DELEGATION)
   2850 		dns_rdataset_disassociate(&a);
   2851 
   2852 	if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
   2853 	    result == DNS_R_GLUE) {
   2854 		tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
   2855 				     DNS_DBFIND_GLUEOK, 0, NULL,
   2856 				     foundname, &aaaa, NULL);
   2857 		if (tresult == ISC_R_SUCCESS) {
   2858 			if (dns_rdataset_isassociated(&a))
   2859 				dns_rdataset_disassociate(&a);
   2860 			dns_rdataset_disassociate(&aaaa);
   2861 			return (true);
   2862 		}
   2863 		if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME)
   2864 			dns_rdataset_disassociate(&aaaa);
   2865 		if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
   2866 			/*
   2867 			 * Check glue against child zone.
   2868 			 */
   2869 			if (zone->checkns != NULL)
   2870 				answer = (zone->checkns)(zone, name, owner,
   2871 							 &a, &aaaa);
   2872 			if (dns_rdataset_isassociated(&a))
   2873 				dns_rdataset_disassociate(&a);
   2874 			if (dns_rdataset_isassociated(&aaaa))
   2875 				dns_rdataset_disassociate(&aaaa);
   2876 			return (answer);
   2877 		}
   2878 	}
   2879 
   2880 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
   2881 	dns_name_format(name, namebuf, sizeof namebuf);
   2882 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   2883 	    result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
   2884 		const char *what;
   2885 		bool required = false;
   2886 		if (dns_name_issubdomain(name, owner)) {
   2887 			what = "REQUIRED GLUE ";
   2888 			required = true;
   2889 		 } else if (result == DNS_R_DELEGATION)
   2890 			what = "SIBLING GLUE ";
   2891 		else
   2892 			what = "";
   2893 
   2894 		if (result != DNS_R_DELEGATION || required ||
   2895 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
   2896 			dns_zone_log(zone, level, "%s/NS '%s' has no %s"
   2897 				     "address records (A or AAAA)",
   2898 				     ownerbuf, namebuf, what);
   2899 			/*
   2900 			 * Log missing address record.
   2901 			 */
   2902 			if (result == DNS_R_DELEGATION && zone->checkns != NULL)
   2903 				(void)(zone->checkns)(zone, name, owner,
   2904 						      &a, &aaaa);
   2905 			/* XXX950 make fatal for 9.5.0. */
   2906 			/* answer = false; */
   2907 		}
   2908 	} else if (result == DNS_R_CNAME) {
   2909 		dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
   2910 			     ownerbuf, namebuf);
   2911 		/* XXX950 make fatal for 9.5.0. */
   2912 		/* answer = false; */
   2913 	} else if (result == DNS_R_DNAME) {
   2914 		dns_name_format(foundname, altbuf, sizeof altbuf);
   2915 		dns_zone_log(zone, level,
   2916 			     "%s/NS '%s' is below a DNAME '%s' (illegal)",
   2917 			     ownerbuf, namebuf, altbuf);
   2918 		/* XXX950 make fatal for 9.5.0. */
   2919 		/* answer = false; */
   2920 	}
   2921 
   2922 	if (dns_rdataset_isassociated(&a))
   2923 		dns_rdataset_disassociate(&a);
   2924 	if (dns_rdataset_isassociated(&aaaa))
   2925 		dns_rdataset_disassociate(&aaaa);
   2926 	return (answer);
   2927 }
   2928 
   2929 static bool
   2930 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
   2931 		     dns_rdataset_t *rdataset)
   2932 {
   2933 	dns_rdataset_t tmprdataset;
   2934 	isc_result_t result;
   2935 	bool answer = true;
   2936 	bool format = true;
   2937 	int level = ISC_LOG_WARNING;
   2938 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2939 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
   2940 	unsigned int count1 = 0;
   2941 
   2942 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
   2943 		level = ISC_LOG_ERROR;
   2944 
   2945 	dns_rdataset_init(&tmprdataset);
   2946 	for (result = dns_rdataset_first(rdataset);
   2947 	     result == ISC_R_SUCCESS;
   2948 	     result = dns_rdataset_next(rdataset)) {
   2949 		dns_rdata_t rdata1 = DNS_RDATA_INIT;
   2950 		unsigned int count2 = 0;
   2951 
   2952 		count1++;
   2953 		dns_rdataset_current(rdataset, &rdata1);
   2954 		dns_rdataset_clone(rdataset, &tmprdataset);
   2955 		for (result = dns_rdataset_first(&tmprdataset);
   2956 		     result == ISC_R_SUCCESS;
   2957 		     result = dns_rdataset_next(&tmprdataset)) {
   2958 			dns_rdata_t rdata2 = DNS_RDATA_INIT;
   2959 			count2++;
   2960 			if (count1 >= count2)
   2961 				continue;
   2962 			dns_rdataset_current(&tmprdataset, &rdata2);
   2963 			if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
   2964 				if (format) {
   2965 					dns_name_format(owner, ownerbuf,
   2966 							sizeof ownerbuf);
   2967 					dns_rdatatype_format(rdata1.type,
   2968 							     typebuf,
   2969 							     sizeof(typebuf));
   2970 					format = false;
   2971 				}
   2972 				dns_zone_log(zone, level, "%s/%s has "
   2973 					     "semantically identical records",
   2974 					     ownerbuf, typebuf);
   2975 				if (level == ISC_LOG_ERROR)
   2976 					answer = false;
   2977 				break;
   2978 			}
   2979 		}
   2980 		dns_rdataset_disassociate(&tmprdataset);
   2981 		if (!format)
   2982 			break;
   2983 	}
   2984 	return (answer);
   2985 }
   2986 
   2987 static bool
   2988 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
   2989 	dns_dbiterator_t *dbiterator = NULL;
   2990 	dns_dbnode_t *node = NULL;
   2991 	dns_fixedname_t fixed;
   2992 	dns_name_t *name;
   2993 	dns_rdataset_t rdataset;
   2994 	dns_rdatasetiter_t *rdsit = NULL;
   2995 	bool ok = true;
   2996 	isc_result_t result;
   2997 
   2998 	name = dns_fixedname_initname(&fixed);
   2999 	dns_rdataset_init(&rdataset);
   3000 
   3001 	result = dns_db_createiterator(db, 0, &dbiterator);
   3002 	if (result != ISC_R_SUCCESS)
   3003 		return (true);
   3004 
   3005 	for (result = dns_dbiterator_first(dbiterator);
   3006 	     result == ISC_R_SUCCESS;
   3007 	     result = dns_dbiterator_next(dbiterator)) {
   3008 		result = dns_dbiterator_current(dbiterator, &node, name);
   3009 		if (result != ISC_R_SUCCESS)
   3010 			continue;
   3011 
   3012 		result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
   3013 		if (result != ISC_R_SUCCESS)
   3014 			continue;
   3015 
   3016 		for (result = dns_rdatasetiter_first(rdsit);
   3017 		     result == ISC_R_SUCCESS;
   3018 		     result = dns_rdatasetiter_next(rdsit)) {
   3019 			dns_rdatasetiter_current(rdsit, &rdataset);
   3020 			if (!zone_rrset_check_dup(zone, name, &rdataset))
   3021 				ok = false;
   3022 			dns_rdataset_disassociate(&rdataset);
   3023 		}
   3024 		dns_rdatasetiter_destroy(&rdsit);
   3025 		dns_db_detachnode(db, &node);
   3026 	}
   3027 
   3028 	if (node != NULL)
   3029 		dns_db_detachnode(db, &node);
   3030 	dns_dbiterator_destroy(&dbiterator);
   3031 
   3032 	return (ok);
   3033 }
   3034 
   3035 static bool
   3036 isspf(const dns_rdata_t *rdata) {
   3037 	char buf[1024];
   3038 	const unsigned char *data = rdata->data;
   3039 	unsigned int rdl = rdata->length, i = 0, tl, len;
   3040 
   3041 	while (rdl > 0U) {
   3042 		len = tl = *data;
   3043 		++data;
   3044 		--rdl;
   3045 		INSIST(tl <= rdl);
   3046 		if (len > sizeof(buf) - i - 1)
   3047 			len = sizeof(buf) - i - 1;
   3048 		memmove(buf + i, data, len);
   3049 		i += len;
   3050 		data += tl;
   3051 		rdl -= tl;
   3052 	}
   3053 
   3054 	if (i < 6U)
   3055 		return(false);
   3056 
   3057 	buf[i] = 0;
   3058 	if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
   3059 		return (true);
   3060 	return (false);
   3061 }
   3062 
   3063 static bool
   3064 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
   3065 	dns_dbiterator_t *dbiterator = NULL;
   3066 	dns_dbnode_t *node = NULL;
   3067 	dns_rdataset_t rdataset;
   3068 	dns_fixedname_t fixed;
   3069 	dns_fixedname_t fixedbottom;
   3070 	dns_rdata_mx_t mx;
   3071 	dns_rdata_ns_t ns;
   3072 	dns_rdata_in_srv_t srv;
   3073 	dns_rdata_t rdata;
   3074 	dns_name_t *name;
   3075 	dns_name_t *bottom;
   3076 	isc_result_t result;
   3077 	bool ok = true, have_spf, have_txt;
   3078 
   3079 	name = dns_fixedname_initname(&fixed);
   3080 	bottom = dns_fixedname_initname(&fixedbottom);
   3081 	dns_rdataset_init(&rdataset);
   3082 	dns_rdata_init(&rdata);
   3083 
   3084 	result = dns_db_createiterator(db, 0, &dbiterator);
   3085 	if (result != ISC_R_SUCCESS)
   3086 		return (true);
   3087 
   3088 	result = dns_dbiterator_first(dbiterator);
   3089 	while (result == ISC_R_SUCCESS) {
   3090 		result = dns_dbiterator_current(dbiterator, &node, name);
   3091 		if (result != ISC_R_SUCCESS)
   3092 			goto cleanup;
   3093 
   3094 		/*
   3095 		 * Is this name visible in the zone?
   3096 		 */
   3097 		if (!dns_name_issubdomain(name, &zone->origin) ||
   3098 		    (dns_name_countlabels(bottom) > 0 &&
   3099 		     dns_name_issubdomain(name, bottom)))
   3100 			goto next;
   3101 
   3102 		/*
   3103 		 * Don't check the NS records at the origin.
   3104 		 */
   3105 		if (dns_name_equal(name, &zone->origin))
   3106 			goto checkfordname;
   3107 
   3108 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
   3109 					     0, 0, &rdataset, NULL);
   3110 		if (result != ISC_R_SUCCESS)
   3111 			goto checkfordname;
   3112 		/*
   3113 		 * Remember bottom of zone due to NS.
   3114 		 */
   3115 		dns_name_copynf(name, bottom);
   3116 
   3117 		result = dns_rdataset_first(&rdataset);
   3118 		while (result == ISC_R_SUCCESS) {
   3119 			dns_rdataset_current(&rdataset, &rdata);
   3120 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
   3121 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3122 			if (!zone_check_glue(zone, db, &ns.name, name))
   3123 				ok = false;
   3124 			dns_rdata_reset(&rdata);
   3125 			result = dns_rdataset_next(&rdataset);
   3126 		}
   3127 		dns_rdataset_disassociate(&rdataset);
   3128 		goto next;
   3129 
   3130  checkfordname:
   3131 		result = dns_db_findrdataset(db, node, NULL,
   3132 					     dns_rdatatype_dname, 0, 0,
   3133 					     &rdataset, NULL);
   3134 		if (result == ISC_R_SUCCESS) {
   3135 			/*
   3136 			 * Remember bottom of zone due to DNAME.
   3137 			 */
   3138 			dns_name_copynf(name, bottom);
   3139 			dns_rdataset_disassociate(&rdataset);
   3140 		}
   3141 
   3142 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
   3143 					     0, 0, &rdataset, NULL);
   3144 		if (result != ISC_R_SUCCESS)
   3145 			goto checksrv;
   3146 		result = dns_rdataset_first(&rdataset);
   3147 		while (result == ISC_R_SUCCESS) {
   3148 			dns_rdataset_current(&rdataset, &rdata);
   3149 			result = dns_rdata_tostruct(&rdata, &mx, NULL);
   3150 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3151 			if (!zone_check_mx(zone, db, &mx.mx, name))
   3152 				ok = false;
   3153 			dns_rdata_reset(&rdata);
   3154 			result = dns_rdataset_next(&rdataset);
   3155 		}
   3156 		dns_rdataset_disassociate(&rdataset);
   3157 
   3158  checksrv:
   3159 		if (zone->rdclass != dns_rdataclass_in)
   3160 			goto next;
   3161 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
   3162 					     0, 0, &rdataset, NULL);
   3163 		if (result != ISC_R_SUCCESS)
   3164 			goto checkspf;
   3165 		result = dns_rdataset_first(&rdataset);
   3166 		while (result == ISC_R_SUCCESS) {
   3167 			dns_rdataset_current(&rdataset, &rdata);
   3168 			result = dns_rdata_tostruct(&rdata, &srv, NULL);
   3169 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3170 			if (!zone_check_srv(zone, db, &srv.target, name))
   3171 				ok = false;
   3172 			dns_rdata_reset(&rdata);
   3173 			result = dns_rdataset_next(&rdataset);
   3174 		}
   3175 		dns_rdataset_disassociate(&rdataset);
   3176 
   3177  checkspf:
   3178 		/*
   3179 		 * Check if there is a type SPF record without an
   3180 		 * SPF-formatted type TXT record also being present.
   3181 		 */
   3182 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
   3183 			goto next;
   3184 		if (zone->rdclass != dns_rdataclass_in)
   3185 			goto next;
   3186 		have_spf = have_txt = false;
   3187 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
   3188 					     0, 0, &rdataset, NULL);
   3189 		if (result == ISC_R_SUCCESS) {
   3190 			dns_rdataset_disassociate(&rdataset);
   3191 			have_spf = true;
   3192 		}
   3193 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
   3194 					     0, 0, &rdataset, NULL);
   3195 		if (result != ISC_R_SUCCESS)
   3196 			goto notxt;
   3197 		result = dns_rdataset_first(&rdataset);
   3198 		while (result == ISC_R_SUCCESS) {
   3199 			dns_rdataset_current(&rdataset, &rdata);
   3200 			have_txt = isspf(&rdata);
   3201 			dns_rdata_reset(&rdata);
   3202 			if (have_txt)
   3203 				break;
   3204 			result = dns_rdataset_next(&rdataset);
   3205 		}
   3206 		dns_rdataset_disassociate(&rdataset);
   3207 
   3208  notxt:
   3209 		if (have_spf && !have_txt) {
   3210 			char namebuf[DNS_NAME_FORMATSIZE];
   3211 
   3212 			dns_name_format(name, namebuf, sizeof(namebuf));
   3213 			dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type "
   3214 				     "SPF record but no SPF TXT record found, "
   3215 				     "add matching type TXT record", namebuf);
   3216 		}
   3217 
   3218  next:
   3219 		dns_db_detachnode(db, &node);
   3220 		result = dns_dbiterator_next(dbiterator);
   3221 	}
   3222 
   3223  cleanup:
   3224 	if (node != NULL)
   3225 		dns_db_detachnode(db, &node);
   3226 	dns_dbiterator_destroy(&dbiterator);
   3227 
   3228 	return (ok);
   3229 }
   3230 
   3231 /*
   3232  * OpenSSL verification of RSA keys with exponent 3 is known to be
   3233  * broken prior OpenSSL 0.9.8c/0.9.7k.	Look for such keys and warn
   3234  * if they are in use.
   3235  */
   3236 static void
   3237 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
   3238 	dns_dbnode_t *node = NULL;
   3239 	dns_dbversion_t *version = NULL;
   3240 	dns_rdata_dnskey_t dnskey;
   3241 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3242 	dns_rdataset_t rdataset;
   3243 	isc_result_t result;
   3244 	bool logit, foundrsa = false;
   3245 	const char *algorithm;
   3246 
   3247 	result = dns_db_findnode(db, &zone->origin, false, &node);
   3248 	if (result != ISC_R_SUCCESS) {
   3249 		goto cleanup;
   3250 	}
   3251 
   3252 	dns_db_currentversion(db, &version);
   3253 	dns_rdataset_init(&rdataset);
   3254 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
   3255 				     dns_rdatatype_none, 0, &rdataset, NULL);
   3256 	if (result != ISC_R_SUCCESS) {
   3257 		goto cleanup;
   3258 	}
   3259 
   3260 	for (result = dns_rdataset_first(&rdataset);
   3261 	     result == ISC_R_SUCCESS;
   3262 	     result = dns_rdataset_next(&rdataset))
   3263 	{
   3264 		dns_rdataset_current(&rdataset, &rdata);
   3265 		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
   3266 		INSIST(result == ISC_R_SUCCESS);
   3267 
   3268 		/* RFC 3110, section 4: Performance Considerations:
   3269 		 *
   3270 		 * A public exponent of 3 minimizes the effort needed to verify
   3271 		 * a signature.  Use of 3 as the public exponent is weak for
   3272 		 * confidentiality uses since, if the same data can be collected
   3273 		 * encrypted under three different keys with an exponent of 3
   3274 		 * then, using the Chinese Remainder Theorem [NETSEC], the
   3275 		 * original plain text can be easily recovered.  If a key is
   3276 		 * known to be used only for authentication, as is the case with
   3277 		 * DNSSEC, then an exponent of 3 is acceptable.  However other
   3278 		 * applications in the future may wish to leverage DNS
   3279 		 * distributed keys for applications that do require
   3280 		 * confidentiality.  For keys which might have such other uses,
   3281 		 * a more conservative choice would be 65537 (F4, the fourth
   3282 		 * fermat number).
   3283 		 */
   3284 		if (dnskey.algorithm == DST_ALG_RSASHA1 &&
   3285 		    dnskey.datalen > 1 && dnskey.data[0] == 1 &&
   3286 		    dnskey.data[1] == 3)
   3287 		{
   3288 			if (dnskey.algorithm == DST_ALG_RSASHA1) {
   3289 				logit = !foundrsa;
   3290 				foundrsa = true;
   3291 				algorithm = "RSASHA1";
   3292 			}
   3293 			if (logit) {
   3294 				dnssec_log(zone, ISC_LOG_WARNING,
   3295 					   "weak %s (%u) key found "
   3296 					   "(exponent=3)", algorithm,
   3297 					   dnskey.algorithm);
   3298 			}
   3299 		}
   3300 		dns_rdata_reset(&rdata);
   3301 	}
   3302 	dns_rdataset_disassociate(&rdataset);
   3303 
   3304  cleanup:
   3305 	if (node != NULL) {
   3306 		dns_db_detachnode(db, &node);
   3307 	}
   3308 	if (version != NULL) {
   3309 		dns_db_closeversion(db, &version, false);
   3310 	}
   3311 }
   3312 
   3313 static void
   3314 resume_signingwithkey(dns_zone_t *zone) {
   3315 	dns_dbnode_t *node = NULL;
   3316 	dns_dbversion_t *version = NULL;
   3317 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3318 	dns_rdataset_t rdataset;
   3319 	isc_result_t result;
   3320 	dns_db_t *db = NULL;
   3321 
   3322 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3323 	if (zone->db != NULL) {
   3324 		dns_db_attach(zone->db, &db);
   3325 	}
   3326 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3327 	if (db == NULL) {
   3328 		goto cleanup;
   3329 	}
   3330 
   3331 	result = dns_db_findnode(db, &zone->origin, false, &node);
   3332 	if (result != ISC_R_SUCCESS) {
   3333 		goto cleanup;
   3334 	}
   3335 
   3336 	dns_db_currentversion(db, &version);
   3337 	dns_rdataset_init(&rdataset);
   3338 	result = dns_db_findrdataset(db, node, version,
   3339 				     zone->privatetype,
   3340 				     dns_rdatatype_none, 0,
   3341 				     &rdataset, NULL);
   3342 	if (result != ISC_R_SUCCESS) {
   3343 		INSIST(!dns_rdataset_isassociated(&rdataset));
   3344 		goto cleanup;
   3345 	}
   3346 
   3347 	for (result = dns_rdataset_first(&rdataset);
   3348 	     result == ISC_R_SUCCESS;
   3349 	     result = dns_rdataset_next(&rdataset))
   3350 	{
   3351 		dns_rdataset_current(&rdataset, &rdata);
   3352 		if (rdata.length != 5 ||
   3353 		    rdata.data[0] == 0 || rdata.data[4] != 0)
   3354 		{
   3355 			dns_rdata_reset(&rdata);
   3356 			continue;
   3357 		}
   3358 
   3359 		result = zone_signwithkey(zone, rdata.data[0],
   3360 					  (rdata.data[1] << 8) | rdata.data[2],
   3361 					  rdata.data[3]);
   3362 		if (result != ISC_R_SUCCESS) {
   3363 			dnssec_log(zone, ISC_LOG_ERROR,
   3364 				   "zone_signwithkey failed: %s",
   3365 				   dns_result_totext(result));
   3366 		}
   3367 		dns_rdata_reset(&rdata);
   3368 	}
   3369 	dns_rdataset_disassociate(&rdataset);
   3370 
   3371  cleanup:
   3372 	if (db != NULL) {
   3373 		if (node != NULL) {
   3374 			dns_db_detachnode(db, &node);
   3375 		}
   3376 		if (version != NULL) {
   3377 			dns_db_closeversion(db, &version, false);
   3378 		}
   3379 		dns_db_detach(&db);
   3380 	}
   3381 }
   3382 
   3383 /*
   3384  * Initiate adding/removing NSEC3 records belonging to the chain defined by the
   3385  * supplied NSEC3PARAM RDATA.
   3386  *
   3387  * Zone must be locked by caller.
   3388  */
   3389 static isc_result_t
   3390 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
   3391 	dns_nsec3chain_t *nsec3chain, *current;
   3392 	dns_dbversion_t *version = NULL;
   3393 	bool nseconly = false, nsec3ok = false;
   3394 	isc_result_t result;
   3395 	isc_time_t now;
   3396 	unsigned int options = 0;
   3397 	char saltbuf[255*2+1];
   3398 	char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
   3399 	dns_db_t *db = NULL;
   3400 
   3401 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3402 	if (zone->db != NULL) {
   3403 		dns_db_attach(zone->db, &db);
   3404 	}
   3405 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3406 
   3407 	if (db == NULL) {
   3408 		result = ISC_R_SUCCESS;
   3409 		goto cleanup;
   3410 	}
   3411 
   3412 	/*
   3413 	 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
   3414 	 * chain from it is pointless as it would not be possible for the
   3415 	 * latter to exist in the first place.
   3416 	 */
   3417 	dns_db_currentversion(db, &version);
   3418 	result = dns_nsec_nseconly(db, version, &nseconly);
   3419 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
   3420 	dns_db_closeversion(db, &version, false);
   3421 	if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
   3422 		result = ISC_R_SUCCESS;
   3423 		goto cleanup;
   3424 	}
   3425 
   3426 	/*
   3427 	 * Allocate and initialize structure preserving state of
   3428 	 * adding/removing records belonging to this NSEC3 chain between
   3429 	 * separate zone_nsec3chain() calls.
   3430 	 */
   3431 	nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
   3432 	if (nsec3chain == NULL) {
   3433 		result = ISC_R_NOMEMORY;
   3434 		goto cleanup;
   3435 	}
   3436 
   3437 	nsec3chain->magic = 0;
   3438 	nsec3chain->done = false;
   3439 	nsec3chain->db = NULL;
   3440 	nsec3chain->dbiterator = NULL;
   3441 	nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
   3442 	nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
   3443 	nsec3chain->nsec3param.hash = nsec3param->hash;
   3444 	nsec3chain->nsec3param.iterations = nsec3param->iterations;
   3445 	nsec3chain->nsec3param.flags = nsec3param->flags;
   3446 	nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
   3447 	memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
   3448 	nsec3chain->nsec3param.salt = nsec3chain->salt;
   3449 	nsec3chain->seen_nsec = false;
   3450 	nsec3chain->delete_nsec = false;
   3451 	nsec3chain->save_delete_nsec = false;
   3452 
   3453 	/*
   3454 	 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
   3455 	 */
   3456 	if (nsec3param->flags == 0) {
   3457 		strlcpy(flags, "NONE", sizeof(flags));
   3458 	} else {
   3459 		flags[0] = '\0';
   3460 		if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
   3461 			strlcat(flags, "REMOVE", sizeof(flags));
   3462 		}
   3463 		if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
   3464 			if (flags[0] == '\0') {
   3465 				strlcpy(flags, "INITIAL", sizeof(flags));
   3466 			} else {
   3467 				strlcat(flags, "|INITIAL", sizeof(flags));
   3468 			}
   3469 		}
   3470 		if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
   3471 			if (flags[0] == '\0') {
   3472 				strlcpy(flags, "CREATE", sizeof(flags));
   3473 			} else {
   3474 				strlcat(flags, "|CREATE", sizeof(flags));
   3475 			}
   3476 		}
   3477 		if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
   3478 			if (flags[0] == '\0') {
   3479 				strlcpy(flags, "NONSEC", sizeof(flags));
   3480 			} else {
   3481 				strlcat(flags, "|NONSEC", sizeof(flags));
   3482 			}
   3483 		}
   3484 		if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
   3485 			if (flags[0] == '\0') {
   3486 				strlcpy(flags, "OPTOUT", sizeof(flags));
   3487 			} else {
   3488 				strlcat(flags, "|OPTOUT", sizeof(flags));
   3489 			}
   3490 		}
   3491 	}
   3492 	result = dns_nsec3param_salttotext(nsec3param, saltbuf,
   3493 					   sizeof(saltbuf));
   3494 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3495 	dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
   3496 		   nsec3param->hash, flags, nsec3param->iterations, saltbuf);
   3497 
   3498 	/*
   3499 	 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
   3500 	 * currently being processed, interrupt its processing to avoid
   3501 	 * simultaneously adding and removing records for the same NSEC3 chain.
   3502 	 */
   3503 	for (current = ISC_LIST_HEAD(zone->nsec3chain);
   3504 	     current != NULL;
   3505 	     current = ISC_LIST_NEXT(current, link))
   3506 	{
   3507 		if ((current->db == db) &&
   3508 		    (current->nsec3param.hash == nsec3param->hash) &&
   3509 		    (current->nsec3param.iterations ==
   3510 		     nsec3param->iterations) &&
   3511 		    (current->nsec3param.salt_length ==
   3512 		     nsec3param->salt_length) &&
   3513 		    memcmp(current->nsec3param.salt, nsec3param->salt,
   3514 			   nsec3param->salt_length) == 0)
   3515 		{
   3516 			current->done = true;
   3517 		}
   3518 	}
   3519 
   3520 	/*
   3521 	 * Attach zone database to the structure initialized above and create
   3522 	 * an iterator for it with appropriate options in order to avoid
   3523 	 * creating NSEC3 records for NSEC3 records.
   3524 	 */
   3525 	dns_db_attach(db, &nsec3chain->db);
   3526 	if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
   3527 		options = DNS_DB_NONSEC3;
   3528 	}
   3529 	result = dns_db_createiterator(nsec3chain->db, options,
   3530 				       &nsec3chain->dbiterator);
   3531 	if (result == ISC_R_SUCCESS) {
   3532 		result = dns_dbiterator_first(nsec3chain->dbiterator);
   3533 	}
   3534 	if (result == ISC_R_SUCCESS) {
   3535 		/*
   3536 		 * Database iterator initialization succeeded.  We are now
   3537 		 * ready to kick off adding/removing records belonging to this
   3538 		 * NSEC3 chain.  Append the structure initialized above to the
   3539 		 * "nsec3chain" list for the zone and set the appropriate zone
   3540 		 * timer so that zone_nsec3chain() is called as soon as
   3541 		 * possible.
   3542 		 */
   3543 		dns_dbiterator_pause(nsec3chain->dbiterator);
   3544 		ISC_LIST_INITANDAPPEND(zone->nsec3chain,
   3545 				       nsec3chain, link);
   3546 		nsec3chain = NULL;
   3547 		if (isc_time_isepoch(&zone->nsec3chaintime)) {
   3548 			TIME_NOW(&now);
   3549 			zone->nsec3chaintime = now;
   3550 			if (zone->task != NULL) {
   3551 				zone_settimer(zone, &now);
   3552 			}
   3553 		}
   3554 	}
   3555 
   3556 	if (nsec3chain != NULL) {
   3557 		if (nsec3chain->db != NULL) {
   3558 			dns_db_detach(&nsec3chain->db);
   3559 		}
   3560 		if (nsec3chain->dbiterator != NULL) {
   3561 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
   3562 		}
   3563 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   3564 	}
   3565 
   3566  cleanup:
   3567 	if (db != NULL) {
   3568 		dns_db_detach(&db);
   3569 	}
   3570 	return (result);
   3571 }
   3572 
   3573 /*
   3574  * Find private-type records at the zone apex which signal that an NSEC3 chain
   3575  * should be added or removed.  For each such record, extract NSEC3PARAM RDATA
   3576  * and pass it to zone_addnsec3chain().
   3577  *
   3578  * Zone must be locked by caller.
   3579  */
   3580 static void
   3581 resume_addnsec3chain(dns_zone_t *zone) {
   3582 	dns_dbnode_t *node = NULL;
   3583 	dns_dbversion_t *version = NULL;
   3584 	dns_rdataset_t rdataset;
   3585 	isc_result_t result;
   3586 	dns_rdata_nsec3param_t nsec3param;
   3587 	bool nseconly = false, nsec3ok = false;
   3588 	dns_db_t *db = NULL;
   3589 
   3590 	INSIST(LOCKED_ZONE(zone));
   3591 
   3592 	if (zone->privatetype == 0)
   3593 		return;
   3594 
   3595 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3596 	if (zone->db != NULL) {
   3597 		dns_db_attach(zone->db, &db);
   3598 	}
   3599 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3600 	if (db == NULL) {
   3601 		goto cleanup;
   3602 	}
   3603 
   3604 	result = dns_db_findnode(db, &zone->origin, false, &node);
   3605 	if (result != ISC_R_SUCCESS) {
   3606 		goto cleanup;
   3607 	}
   3608 
   3609 	dns_db_currentversion(db, &version);
   3610 
   3611 	/*
   3612 	 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
   3613 	 * apex to exist and contain no keys using NSEC-only algorithms.
   3614 	 */
   3615 	result = dns_nsec_nseconly(db, version, &nseconly);
   3616 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
   3617 
   3618 	/*
   3619 	 * Get the RRset containing all private-type records at the zone apex.
   3620 	 */
   3621 	dns_rdataset_init(&rdataset);
   3622 	result = dns_db_findrdataset(db, node, version,
   3623 				     zone->privatetype, dns_rdatatype_none,
   3624 				     0, &rdataset, NULL);
   3625 	if (result != ISC_R_SUCCESS) {
   3626 		INSIST(!dns_rdataset_isassociated(&rdataset));
   3627 		goto cleanup;
   3628 	}
   3629 
   3630 	for (result = dns_rdataset_first(&rdataset);
   3631 	     result == ISC_R_SUCCESS;
   3632 	     result = dns_rdataset_next(&rdataset))
   3633 	{
   3634 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   3635 		dns_rdata_t rdata = DNS_RDATA_INIT;
   3636 		dns_rdata_t private = DNS_RDATA_INIT;
   3637 
   3638 		dns_rdataset_current(&rdataset, &private);
   3639 		/*
   3640 		 * Try extracting NSEC3PARAM RDATA from this private-type
   3641 		 * record.  Failure means this private-type record does not
   3642 		 * represent an NSEC3PARAM record, so skip it.
   3643 		 */
   3644 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
   3645 						sizeof(buf)))
   3646 		{
   3647 			continue;
   3648 		}
   3649 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   3650 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3651 		if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
   3652 		    ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
   3653 		{
   3654 			/*
   3655 			 * Pass the NSEC3PARAM RDATA contained in this
   3656 			 * private-type record to zone_addnsec3chain() so that
   3657 			 * it can kick off adding or removing NSEC3 records.
   3658 			 */
   3659 			result = zone_addnsec3chain(zone, &nsec3param);
   3660 			if (result != ISC_R_SUCCESS) {
   3661 				dnssec_log(zone, ISC_LOG_ERROR,
   3662 					   "zone_addnsec3chain failed: %s",
   3663 					   dns_result_totext(result));
   3664 			}
   3665 		}
   3666 	}
   3667 	dns_rdataset_disassociate(&rdataset);
   3668 
   3669  cleanup:
   3670 	if (db != NULL) {
   3671 		if (node != NULL) {
   3672 			dns_db_detachnode(db, &node);
   3673 		}
   3674 		if (version != NULL) {
   3675 			dns_db_closeversion(db, &version, false);
   3676 		}
   3677 		dns_db_detach(&db);
   3678 	}
   3679 }
   3680 
   3681 static void
   3682 set_resigntime(dns_zone_t *zone) {
   3683 	dns_rdataset_t rdataset;
   3684 	dns_fixedname_t fixed;
   3685 	unsigned int resign;
   3686 	isc_result_t result;
   3687 	uint32_t nanosecs;
   3688 	dns_db_t *db = NULL;
   3689 
   3690 	/* We only re-sign zones that can be dynamically updated */
   3691 	if (zone->update_disabled)
   3692 		return;
   3693 
   3694 	if (!inline_secure(zone) && (zone->type != dns_zone_master ||
   3695 	    (zone->ssutable == NULL &&
   3696 	     (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
   3697 		return;
   3698 
   3699 	dns_rdataset_init(&rdataset);
   3700 	dns_fixedname_init(&fixed);
   3701 
   3702 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3703 	if (zone->db != NULL)
   3704 		dns_db_attach(zone->db, &db);
   3705 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3706 	if (db == NULL) {
   3707 		isc_time_settoepoch(&zone->resigntime);
   3708 		return;
   3709 	}
   3710 
   3711 	result = dns_db_getsigningtime(db, &rdataset,
   3712 				       dns_fixedname_name(&fixed));
   3713 	if (result != ISC_R_SUCCESS) {
   3714 		isc_time_settoepoch(&zone->resigntime);
   3715 		goto cleanup;
   3716 	}
   3717 
   3718 	resign = rdataset.resign - zone->sigresigninginterval;
   3719 	dns_rdataset_disassociate(&rdataset);
   3720 	nanosecs = isc_random_uniform(1000000000);
   3721 	isc_time_set(&zone->resigntime, resign, nanosecs);
   3722  cleanup:
   3723 	dns_db_detach(&db);
   3724 	return;
   3725 }
   3726 
   3727 static isc_result_t
   3728 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
   3729 	dns_dbnode_t *node = NULL;
   3730 	dns_rdataset_t rdataset;
   3731 	dns_dbversion_t *version = NULL;
   3732 	dns_rdata_nsec3param_t nsec3param;
   3733 	bool ok = false;
   3734 	isc_result_t result;
   3735 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3736 	bool dynamic = (zone->type == dns_zone_master)
   3737 			? dns_zone_isdynamic(zone, false) : false;
   3738 
   3739 	dns_rdataset_init(&rdataset);
   3740 	result = dns_db_findnode(db, &zone->origin, false, &node);
   3741 	if (result != ISC_R_SUCCESS) {
   3742 		dns_zone_log(zone, ISC_LOG_ERROR,
   3743 			     "nsec3param lookup failure: %s",
   3744 			     dns_result_totext(result));
   3745 		return (result);
   3746 	}
   3747 	dns_db_currentversion(db, &version);
   3748 
   3749 	result = dns_db_findrdataset(db, node, version,
   3750 				     dns_rdatatype_nsec3param,
   3751 				     dns_rdatatype_none, 0, &rdataset, NULL);
   3752 	if (result == ISC_R_NOTFOUND) {
   3753 		INSIST(!dns_rdataset_isassociated(&rdataset));
   3754 		result = ISC_R_SUCCESS;
   3755 		goto cleanup;
   3756 	}
   3757 	if (result != ISC_R_SUCCESS) {
   3758 		INSIST(!dns_rdataset_isassociated(&rdataset));
   3759 		dns_zone_log(zone, ISC_LOG_ERROR,
   3760 			     "nsec3param lookup failure: %s",
   3761 			     dns_result_totext(result));
   3762 		goto cleanup;
   3763 	}
   3764 
   3765 	/*
   3766 	 * For dynamic zones we must support every algorithm so we can
   3767 	 * regenerate all the NSEC3 chains.
   3768 	 * For non-dynamic zones we only need to find a supported algorithm.
   3769 	 */
   3770 	for (result = dns_rdataset_first(&rdataset);
   3771 	     result == ISC_R_SUCCESS;
   3772 	     result = dns_rdataset_next(&rdataset))
   3773 	{
   3774 		dns_rdataset_current(&rdataset, &rdata);
   3775 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   3776 		dns_rdata_reset(&rdata);
   3777 		INSIST(result == ISC_R_SUCCESS);
   3778 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
   3779 		    nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
   3780 		{
   3781 			dns_zone_log(zone, ISC_LOG_WARNING,
   3782 			     "nsec3 test \"unknown\" hash algorithm found: %u",
   3783 				     nsec3param.hash);
   3784 			ok = true;
   3785 		} else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
   3786 			if (dynamic) {
   3787 				dns_zone_log(zone, ISC_LOG_ERROR,
   3788 					     "unsupported nsec3 hash algorithm"
   3789 					     " in dynamic zone: %u",
   3790 					     nsec3param.hash);
   3791 				result = DNS_R_BADZONE;
   3792 				/* Stop second error message. */
   3793 				ok = true;
   3794 				break;
   3795 			} else
   3796 				dns_zone_log(zone, ISC_LOG_WARNING,
   3797 				     "unsupported nsec3 hash algorithm: %u",
   3798 					     nsec3param.hash);
   3799 		} else {
   3800 			ok = true;
   3801 		}
   3802 	}
   3803 	if (result == ISC_R_NOMORE) {
   3804 		result = ISC_R_SUCCESS;
   3805 	}
   3806 
   3807 	if (!ok) {
   3808 		result = DNS_R_BADZONE;
   3809 		dns_zone_log(zone, ISC_LOG_ERROR,
   3810 			     "no supported nsec3 hash algorithm");
   3811 	}
   3812 
   3813  cleanup:
   3814 	if (dns_rdataset_isassociated(&rdataset)) {
   3815 		dns_rdataset_disassociate(&rdataset);
   3816 	}
   3817 	dns_db_closeversion(db, &version, false);
   3818 	dns_db_detachnode(db, &node);
   3819 	return (result);
   3820 }
   3821 
   3822 /*
   3823  * Set the timer for refreshing the key zone to the soonest future time
   3824  * of the set (current timer, keydata->refresh, keydata->addhd,
   3825  * keydata->removehd).
   3826  */
   3827 static void
   3828 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
   3829 		    isc_stdtime_t now, bool force)
   3830 {
   3831 	const char me[] = "set_refreshkeytimer";
   3832 	isc_stdtime_t then;
   3833 	isc_time_t timenow, timethen;
   3834 	char timebuf[80];
   3835 
   3836 	ENTER;
   3837 	then = key->refresh;
   3838 	if (force)
   3839 		then = now;
   3840 	if (key->addhd > now && key->addhd < then)
   3841 		then = key->addhd;
   3842 	if (key->removehd > now && key->removehd < then)
   3843 		then = key->removehd;
   3844 
   3845 	TIME_NOW(&timenow);
   3846 	if (then > now)
   3847 		DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
   3848 	else
   3849 		timethen = timenow;
   3850 	if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
   3851 	    isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
   3852 		zone->refreshkeytime = timethen;
   3853 
   3854 	isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   3855 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
   3856 	zone_settimer(zone, &timenow);
   3857 }
   3858 
   3859 /*
   3860  * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
   3861  * If the key zone is changed, set '*changed' to true.
   3862  */
   3863 static isc_result_t
   3864 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   3865 	       dns_diff_t *diff, dns_keytable_t *keytable,
   3866 	       dns_keynode_t **keynodep, bool *changed)
   3867 {
   3868 	const char me[] = "create_keydata";
   3869 	isc_result_t result = ISC_R_SUCCESS;
   3870 	isc_buffer_t keyb, dstb;
   3871 	unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
   3872 	dns_rdata_keydata_t keydata;
   3873 	dns_rdata_dnskey_t dnskey;
   3874 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3875 	dns_keynode_t *keynode;
   3876 	isc_stdtime_t now;
   3877 	isc_region_t r;
   3878 	dst_key_t *key;
   3879 
   3880 	REQUIRE(keynodep != NULL);
   3881 	keynode = *keynodep;
   3882 
   3883 	ENTER;
   3884 	isc_stdtime_get(&now);
   3885 
   3886 	/* Loop in case there's more than one key. */
   3887 	while (result == ISC_R_SUCCESS) {
   3888 		dns_keynode_t *nextnode = NULL;
   3889 
   3890 		key = dns_keynode_key(keynode);
   3891 		if (key == NULL)
   3892 			goto skip;
   3893 
   3894 		isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
   3895 		CHECK(dst_key_todns(key, &dstb));
   3896 
   3897 		/* Convert DST key to DNSKEY. */
   3898 		dns_rdata_reset(&rdata);
   3899 		isc_buffer_usedregion(&dstb, &r);
   3900 		dns_rdata_fromregion(&rdata, dst_key_class(key),
   3901 				     dns_rdatatype_dnskey, &r);
   3902 
   3903 		/* DSTKEY to KEYDATA. */
   3904 		CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
   3905 		CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
   3906 					     NULL));
   3907 
   3908 		/* KEYDATA to rdata. */
   3909 		dns_rdata_reset(&rdata);
   3910 		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   3911 		CHECK(dns_rdata_fromstruct(&rdata,
   3912 					   zone->rdclass, dns_rdatatype_keydata,
   3913 					   &keydata, &keyb));
   3914 
   3915 		/* Add rdata to zone. */
   3916 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
   3917 				    dst_key_name(key), 0, &rdata));
   3918 		*changed = true;
   3919 
   3920 		/* Refresh new keys from the zone apex as soon as possible. */
   3921 		set_refreshkeytimer(zone, &keydata, now, true);
   3922 
   3923  skip:
   3924 		result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
   3925 		if (result != ISC_R_NOTFOUND) {
   3926 			dns_keytable_detachkeynode(keytable, &keynode);
   3927 			keynode = nextnode;
   3928 		}
   3929 	}
   3930 
   3931 	if (keynode != NULL)
   3932 		dns_keytable_detachkeynode(keytable, &keynode);
   3933 	*keynodep = NULL;
   3934 
   3935 	return (ISC_R_SUCCESS);
   3936 
   3937   failure:
   3938 	return (result);
   3939 }
   3940 
   3941 /*
   3942  * Remove from the key zone all the KEYDATA records found in rdataset.
   3943  */
   3944 static isc_result_t
   3945 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
   3946 	       dns_name_t *name, dns_rdataset_t *rdataset)
   3947 {
   3948 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3949 	isc_result_t result, uresult;
   3950 
   3951 	for (result = dns_rdataset_first(rdataset);
   3952 	     result == ISC_R_SUCCESS;
   3953 	     result = dns_rdataset_next(rdataset)) {
   3954 		dns_rdata_reset(&rdata);
   3955 		dns_rdataset_current(rdataset, &rdata);
   3956 		uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
   3957 					name, 0, &rdata);
   3958 		if (uresult != ISC_R_SUCCESS)
   3959 			return (uresult);
   3960 	}
   3961 	if (result == ISC_R_NOMORE)
   3962 		result = ISC_R_SUCCESS;
   3963 	return (result);
   3964 }
   3965 
   3966 /*
   3967  * Compute the DNSSEC key ID for a DNSKEY record.
   3968  */
   3969 static isc_result_t
   3970 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
   3971 	    dns_keytag_t *tag)
   3972 {
   3973 	isc_result_t result;
   3974 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3975 	unsigned char data[4096];
   3976 	isc_buffer_t buffer;
   3977 	dst_key_t *dstkey = NULL;
   3978 
   3979 	isc_buffer_init(&buffer, data, sizeof(data));
   3980 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
   3981 			     dns_rdatatype_dnskey, dnskey, &buffer);
   3982 
   3983 	result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
   3984 	if (result == ISC_R_SUCCESS) {
   3985 		*tag = dst_key_id(dstkey);
   3986 		dst_key_free(&dstkey);
   3987 	}
   3988 
   3989 	return (result);
   3990 }
   3991 
   3992 /*
   3993  * Add key to the security roots.
   3994  */
   3995 static void
   3996 trust_key(dns_zone_t *zone, dns_name_t *keyname,
   3997 	  dns_rdata_dnskey_t *dnskey, bool initial,
   3998 	  isc_mem_t *mctx)
   3999 {
   4000 	isc_result_t result;
   4001 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4002 	unsigned char data[4096];
   4003 	isc_buffer_t buffer;
   4004 	dns_keytable_t *sr = NULL;
   4005 	dst_key_t *dstkey = NULL;
   4006 
   4007 	/* Convert dnskey to DST key. */
   4008 	isc_buffer_init(&buffer, data, sizeof(data));
   4009 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
   4010 			     dns_rdatatype_dnskey, dnskey, &buffer);
   4011 
   4012 	result = dns_view_getsecroots(zone->view, &sr);
   4013 	if (result != ISC_R_SUCCESS)
   4014 		goto failure;
   4015 
   4016 	CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
   4017 	CHECK(dns_keytable_add(sr, true, initial, &dstkey));
   4018 	dns_keytable_detach(&sr);
   4019 
   4020   failure:
   4021 	if (dstkey != NULL)
   4022 		dst_key_free(&dstkey);
   4023 	if (sr != NULL)
   4024 		dns_keytable_detach(&sr);
   4025 	return;
   4026 }
   4027 
   4028 /*
   4029  * Add a null key to the security roots for so that all queries
   4030  * to the zone will fail.
   4031  */
   4032 static void
   4033 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
   4034 	isc_result_t result;
   4035 	dns_keytable_t *sr = NULL;
   4036 
   4037 	result = dns_view_getsecroots(zone->view, &sr);
   4038 	if (result == ISC_R_SUCCESS) {
   4039 		dns_keytable_marksecure(sr, keyname);
   4040 		dns_keytable_detach(&sr);
   4041 	}
   4042 }
   4043 
   4044 /*
   4045  * Scan a set of KEYDATA records from the key zone.  The ones that are
   4046  * valid (i.e., the add holddown timer has expired) become trusted keys.
   4047  */
   4048 static void
   4049 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
   4050 	isc_result_t result;
   4051 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4052 	dns_rdata_keydata_t keydata;
   4053 	dns_rdata_dnskey_t dnskey;
   4054 	isc_mem_t *mctx = zone->mctx;
   4055 	int trusted = 0, revoked = 0, pending = 0;
   4056 	isc_stdtime_t now;
   4057 	dns_keytable_t *sr = NULL;
   4058 
   4059 	isc_stdtime_get(&now);
   4060 
   4061 	result = dns_view_getsecroots(zone->view, &sr);
   4062 	if (result == ISC_R_SUCCESS) {
   4063 		dns_keytable_delete(sr, name);
   4064 		dns_keytable_detach(&sr);
   4065 	}
   4066 
   4067 	/* Now insert all the accepted trust anchors from this keydata set. */
   4068 	for (result = dns_rdataset_first(rdataset);
   4069 	     result == ISC_R_SUCCESS;
   4070 	     result = dns_rdataset_next(rdataset))
   4071 	{
   4072 		dns_rdata_reset(&rdata);
   4073 		dns_rdataset_current(rdataset, &rdata);
   4074 
   4075 		/* Convert rdata to keydata. */
   4076 		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
   4077 		if (result == ISC_R_UNEXPECTEDEND) {
   4078 			continue;
   4079 		}
   4080 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4081 
   4082 		/* Set the key refresh timer to force a fast refresh. */
   4083 		set_refreshkeytimer(zone, &keydata, now, true);
   4084 
   4085 		/* If the removal timer is nonzero, this key was revoked. */
   4086 		if (keydata.removehd != 0) {
   4087 			revoked++;
   4088 			continue;
   4089 		}
   4090 
   4091 		/*
   4092 		 * If the add timer is still pending, this key is not
   4093 		 * trusted yet.
   4094 		 */
   4095 		if (now < keydata.addhd) {
   4096 			pending++;
   4097 			continue;
   4098 		}
   4099 
   4100 		/* Convert keydata to dnskey. */
   4101 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
   4102 
   4103 		/* Add to keytables. */
   4104 		trusted++;
   4105 		trust_key(zone, name, &dnskey, (keydata.addhd == 0), mctx);
   4106 	}
   4107 
   4108 	if (trusted == 0 && pending != 0) {
   4109 		char namebuf[DNS_NAME_FORMATSIZE];
   4110 		dns_name_format(name, namebuf, sizeof namebuf);
   4111 		dnssec_log(zone, ISC_LOG_ERROR,
   4112 			   "No valid trust anchors for '%s'!", namebuf);
   4113 		dnssec_log(zone, ISC_LOG_ERROR,
   4114 			   "%d key(s) revoked, %d still pending",
   4115 			     revoked, pending);
   4116 		dnssec_log(zone, ISC_LOG_ERROR,
   4117 			   "All queries to '%s' will fail", namebuf);
   4118 		fail_secure(zone, name);
   4119 	}
   4120 }
   4121 
   4122 static isc_result_t
   4123 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
   4124 	     dns_diff_t *diff)
   4125 {
   4126 	dns_diff_t temp_diff;
   4127 	isc_result_t result;
   4128 
   4129 	/*
   4130 	 * Create a singleton diff.
   4131 	 */
   4132 	dns_diff_init(diff->mctx, &temp_diff);
   4133 	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
   4134 
   4135 	/*
   4136 	 * Apply it to the database.
   4137 	 */
   4138 	result = dns_diff_apply(&temp_diff, db, ver);
   4139 	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
   4140 	if (result != ISC_R_SUCCESS) {
   4141 		dns_difftuple_free(tuple);
   4142 		return (result);
   4143 	}
   4144 
   4145 	/*
   4146 	 * Merge it into the current pending journal entry.
   4147 	 */
   4148 	dns_diff_appendminimal(diff, tuple);
   4149 
   4150 	/*
   4151 	 * Do not clear temp_diff.
   4152 	 */
   4153 	return (ISC_R_SUCCESS);
   4154 }
   4155 
   4156 static isc_result_t
   4157 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
   4158 	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
   4159 	      dns_rdata_t *rdata)
   4160 {
   4161 	dns_difftuple_t *tuple = NULL;
   4162 	isc_result_t result;
   4163 	result = dns_difftuple_create(diff->mctx, op,
   4164 				      name, ttl, rdata, &tuple);
   4165 	if (result != ISC_R_SUCCESS)
   4166 		return (result);
   4167 	return (do_one_tuple(&tuple, db, ver, diff));
   4168 }
   4169 
   4170 static isc_result_t
   4171 update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
   4172 		  isc_mem_t *mctx, dns_updatemethod_t method) {
   4173 	dns_difftuple_t *deltuple = NULL;
   4174 	dns_difftuple_t *addtuple = NULL;
   4175 	uint32_t serial;
   4176 	isc_result_t result;
   4177 
   4178 	INSIST(method != dns_updatemethod_none);
   4179 
   4180 	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
   4181 	CHECK(dns_difftuple_copy(deltuple, &addtuple));
   4182 	addtuple->op = DNS_DIFFOP_ADD;
   4183 
   4184 	serial = dns_soa_getserial(&addtuple->rdata);
   4185 	serial = dns_update_soaserial(serial, method);
   4186 	dns_soa_setserial(serial, &addtuple->rdata);
   4187 	CHECK(do_one_tuple(&deltuple, db, ver, diff));
   4188 	CHECK(do_one_tuple(&addtuple, db, ver, diff));
   4189 	result = ISC_R_SUCCESS;
   4190 
   4191 	failure:
   4192 	if (addtuple != NULL)
   4193 		dns_difftuple_free(&addtuple);
   4194 	if (deltuple != NULL)
   4195 		dns_difftuple_free(&deltuple);
   4196 	return (result);
   4197 }
   4198 
   4199 /*
   4200  * Write all transactions in 'diff' to the zone journal file.
   4201  */
   4202 static isc_result_t
   4203 zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
   4204 	     const char *caller)
   4205 {
   4206 	const char me[] = "zone_journal";
   4207 	const char *journalfile;
   4208 	isc_result_t result = ISC_R_SUCCESS;
   4209 	dns_journal_t *journal = NULL;
   4210 	unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
   4211 
   4212 	ENTER;
   4213 	journalfile = dns_zone_getjournal(zone);
   4214 	if (journalfile != NULL) {
   4215 		result = dns_journal_open(zone->mctx, journalfile, mode,
   4216 					  &journal);
   4217 		if (result != ISC_R_SUCCESS) {
   4218 			dns_zone_log(zone, ISC_LOG_ERROR,
   4219 				     "%s:dns_journal_open -> %s",
   4220 				     caller, dns_result_totext(result));
   4221 			return (result);
   4222 		}
   4223 
   4224 		if (sourceserial != NULL)
   4225 			dns_journal_set_sourceserial(journal, *sourceserial);
   4226 
   4227 		result = dns_journal_write_transaction(journal, diff);
   4228 		if (result != ISC_R_SUCCESS) {
   4229 			dns_zone_log(zone, ISC_LOG_ERROR,
   4230 				     "%s:dns_journal_write_transaction -> %s",
   4231 				     caller, dns_result_totext(result));
   4232 		}
   4233 		dns_journal_destroy(&journal);
   4234 	}
   4235 
   4236 	return (result);
   4237 }
   4238 
   4239 /*
   4240  * Create an SOA record for a newly-created zone
   4241  */
   4242 static isc_result_t
   4243 add_soa(dns_zone_t *zone, dns_db_t *db) {
   4244 	isc_result_t result;
   4245 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4246 	unsigned char buf[DNS_SOA_BUFFERSIZE];
   4247 	dns_dbversion_t *ver = NULL;
   4248 	dns_diff_t diff;
   4249 
   4250 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
   4251 
   4252 	dns_diff_init(zone->mctx, &diff);
   4253 	result = dns_db_newversion(db, &ver);
   4254 	if (result != ISC_R_SUCCESS) {
   4255 		dns_zone_log(zone, ISC_LOG_ERROR,
   4256 			     "add_soa:dns_db_newversion -> %s",
   4257 			     dns_result_totext(result));
   4258 		goto failure;
   4259 	}
   4260 
   4261 	/* Build SOA record */
   4262 	result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
   4263 				    0, 0, 0, 0, 0, buf, &rdata);
   4264 	if (result != ISC_R_SUCCESS) {
   4265 		dns_zone_log(zone, ISC_LOG_ERROR,
   4266 			     "add_soa:dns_soa_buildrdata -> %s",
   4267 			     dns_result_totext(result));
   4268 		goto failure;
   4269 	}
   4270 
   4271 	result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
   4272 			       &zone->origin, 0, &rdata);
   4273 
   4274 failure:
   4275 	dns_diff_clear(&diff);
   4276 	if (ver != NULL)
   4277 		dns_db_closeversion(db, &ver, (result == ISC_R_SUCCESS));
   4278 
   4279 	INSIST(ver == NULL);
   4280 
   4281 	return (result);
   4282 }
   4283 
   4284 struct addifmissing_arg {
   4285 	dns_db_t *db;
   4286 	dns_dbversion_t *ver;
   4287 	dns_diff_t *diff;
   4288 	dns_zone_t *zone;
   4289 	bool *changed;
   4290 	isc_result_t result;
   4291 };
   4292 
   4293 static void
   4294 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
   4295 	dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
   4296 	dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
   4297 	dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
   4298 	dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
   4299 	bool *changed = ((struct addifmissing_arg *)arg)->changed;
   4300 	isc_result_t result;
   4301 	dns_keynode_t *dummy = NULL;
   4302 
   4303 	if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS)
   4304 		return;
   4305 
   4306 	if (dns_keynode_managed(keynode)) {
   4307 		dns_fixedname_t fname;
   4308 		dns_name_t *keyname;
   4309 		dst_key_t *key;
   4310 
   4311 		key = dns_keynode_key(keynode);
   4312 		if (key == NULL)
   4313 			return;
   4314 		dns_fixedname_init(&fname);
   4315 
   4316 		keyname = dst_key_name(key);
   4317 		result = dns_db_find(db, keyname, ver,
   4318 				     dns_rdatatype_keydata,
   4319 				     DNS_DBFIND_NOWILD, 0, NULL,
   4320 				     dns_fixedname_name(&fname),
   4321 				     NULL, NULL);
   4322 		if (result == ISC_R_SUCCESS)
   4323 			return;
   4324 		dns_keytable_attachkeynode(keytable, keynode, &dummy);
   4325 		result = create_keydata(zone, db, ver, diff, keytable,
   4326 					&dummy, changed);
   4327 		if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
   4328 			((struct addifmissing_arg *)arg)->result = result;
   4329 	}
   4330 };
   4331 
   4332 /*
   4333  * Synchronize the set of initializing keys found in managed-keys {}
   4334  * statements with the set of trust anchors found in the managed-keys.bind
   4335  * zone.  If a domain is no longer named in managed-keys, delete all keys
   4336  * from that domain from the key zone.	If a domain is mentioned in in
   4337  * managed-keys but there are no references to it in the key zone, load
   4338  * the key zone with the initializing key(s) for that domain.
   4339  */
   4340 static isc_result_t
   4341 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
   4342 	isc_result_t result = ISC_R_SUCCESS;
   4343 	bool changed = false;
   4344 	bool commit = false;
   4345 	dns_keynode_t *keynode = NULL;
   4346 	dns_view_t *view = zone->view;
   4347 	dns_keytable_t *sr = NULL;
   4348 	dns_dbversion_t *ver = NULL;
   4349 	dns_diff_t diff;
   4350 	dns_rriterator_t rrit;
   4351 	struct addifmissing_arg arg;
   4352 
   4353 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
   4354 
   4355 	dns_diff_init(zone->mctx, &diff);
   4356 
   4357 	CHECK(dns_view_getsecroots(view, &sr));
   4358 
   4359 	result = dns_db_newversion(db, &ver);
   4360 	if (result != ISC_R_SUCCESS) {
   4361 		dnssec_log(zone, ISC_LOG_ERROR,
   4362 			   "sync_keyzone:dns_db_newversion -> %s",
   4363 			   dns_result_totext(result));
   4364 		goto failure;
   4365 	}
   4366 
   4367 	/*
   4368 	 * Walk the zone DB.  If we find any keys whose names are no longer
   4369 	 * in managed-keys (or *are* in trusted-keys, meaning they are
   4370 	 * permanent and not RFC5011-maintained), delete them from the
   4371 	 * zone.  Otherwise call load_secroots(), which loads keys into
   4372 	 * secroots as appropriate.
   4373 	 */
   4374 	dns_rriterator_init(&rrit, db, ver, 0);
   4375 	for (result = dns_rriterator_first(&rrit);
   4376 	     result == ISC_R_SUCCESS;
   4377 	     result = dns_rriterator_nextrrset(&rrit))
   4378 	{
   4379 		dns_rdataset_t *rdataset = NULL;
   4380 		dns_name_t *rrname = NULL;
   4381 		uint32_t ttl;
   4382 
   4383 		dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
   4384 		if (!dns_rdataset_isassociated(rdataset)) {
   4385 			dns_rriterator_destroy(&rrit);
   4386 			goto failure;
   4387 		}
   4388 
   4389 		if (rdataset->type != dns_rdatatype_keydata) {
   4390 			continue;
   4391 		}
   4392 
   4393 		result = dns_keytable_find(sr, rrname, &keynode);
   4394 		if ((result != ISC_R_SUCCESS &&
   4395 		     result != DNS_R_PARTIALMATCH) ||
   4396 		    dns_keynode_managed(keynode) == false)
   4397 		{
   4398 			CHECK(delete_keydata(db, ver, &diff,
   4399 					     rrname, rdataset));
   4400 			changed = true;
   4401 		} else {
   4402 			load_secroots(zone, rrname, rdataset);
   4403 		}
   4404 
   4405 		if (keynode != NULL) {
   4406 			dns_keytable_detachkeynode(sr, &keynode);
   4407 		}
   4408 	}
   4409 	dns_rriterator_destroy(&rrit);
   4410 
   4411 	/*
   4412 	 * Now walk secroots to find any managed keys that aren't
   4413 	 * in the zone.  If we find any, we add them to the zone.
   4414 	 */
   4415 	arg.db = db;
   4416 	arg.ver = ver;
   4417 	arg.result = ISC_R_SUCCESS;
   4418 	arg.diff = &diff;
   4419 	arg.zone = zone;
   4420 	arg.changed = &changed;
   4421 	dns_keytable_forall(sr, addifmissing, &arg);
   4422 	result = arg.result;
   4423 	if (changed) {
   4424 		/* Write changes to journal file. */
   4425 		CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
   4426 					zone->updatemethod));
   4427 		CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
   4428 
   4429 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   4430 		zone_needdump(zone, 30);
   4431 		commit = true;
   4432 	}
   4433 
   4434  failure:
   4435 	if (result != ISC_R_SUCCESS &&
   4436 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   4437 	{
   4438 		dnssec_log(zone, ISC_LOG_ERROR,
   4439 			   "unable to synchronize managed keys: %s",
   4440 			   dns_result_totext(result));
   4441 		isc_time_settoepoch(&zone->refreshkeytime);
   4442 	}
   4443 	if (keynode != NULL) {
   4444 		dns_keytable_detachkeynode(sr, &keynode);
   4445 	}
   4446 	if (sr != NULL) {
   4447 		dns_keytable_detach(&sr);
   4448 	}
   4449 	if (ver != NULL) {
   4450 		dns_db_closeversion(db, &ver, commit);
   4451 	}
   4452 	dns_diff_clear(&diff);
   4453 
   4454 	INSIST(ver == NULL);
   4455 
   4456 	return (result);
   4457 }
   4458 
   4459 isc_result_t
   4460 dns_zone_synckeyzone(dns_zone_t *zone) {
   4461 	isc_result_t result;
   4462 	dns_db_t *db = NULL;
   4463 
   4464 	if (zone->type != dns_zone_key) {
   4465 		return (DNS_R_BADZONE);
   4466 	}
   4467 
   4468 	CHECK(dns_zone_getdb(zone, &db));
   4469 
   4470 	LOCK_ZONE(zone);
   4471 	result = sync_keyzone(zone, db);
   4472 	UNLOCK_ZONE(zone);
   4473 
   4474  failure:
   4475 	if (db != NULL) {
   4476 		dns_db_detach(&db);
   4477 	}
   4478 	return (result);
   4479 }
   4480 
   4481 static void
   4482 maybe_send_secure(dns_zone_t *zone) {
   4483 	isc_result_t result;
   4484 
   4485 	/*
   4486 	 * We've finished loading, or else failed to load, an inline-signing
   4487 	 * 'secure' zone.  We now need information about the status of the
   4488 	 * 'raw' zone.  If we failed to load, then we need it to send a
   4489 	 * copy of its database; if we succeeded, we need it to send its
   4490 	 * serial number so that we can sync with it.  If it has not yet
   4491 	 * loaded, we set a flag so that it will send the necessary
   4492 	 * information when it has finished loading.
   4493 	 */
   4494 	if (zone->raw->db != NULL) {
   4495 		if (zone->db != NULL) {
   4496 			uint32_t serial;
   4497 			unsigned int soacount;
   4498 
   4499 			result = zone_get_from_db(zone->raw, zone->raw->db,
   4500 						  NULL, &soacount, &serial,
   4501 						  NULL, NULL, NULL, NULL, NULL);
   4502 			if (result == ISC_R_SUCCESS && soacount > 0U)
   4503 				zone_send_secureserial(zone->raw, serial);
   4504 		} else
   4505 			zone_send_securedb(zone->raw, zone->raw->db);
   4506 
   4507 	} else
   4508 		DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
   4509 }
   4510 
   4511 static bool
   4512 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
   4513 	isc_result_t result;
   4514 	bool answer = false;
   4515 	dns_diff_t diff;
   4516 
   4517 	dns_diff_init(mctx, &diff);
   4518 	result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
   4519 	if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
   4520 		answer = true;
   4521 	dns_diff_clear(&diff);
   4522 	return (answer);
   4523 }
   4524 
   4525 /*
   4526  * The zone is presumed to be locked.
   4527  * If this is a inline_raw zone the secure version is also locked.
   4528  */
   4529 static isc_result_t
   4530 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
   4531 	      isc_result_t result)
   4532 {
   4533 	unsigned int soacount = 0;
   4534 	unsigned int nscount = 0;
   4535 	unsigned int errors = 0;
   4536 	uint32_t serial, oldserial, refresh, retry, expire, minimum;
   4537 	isc_time_t now;
   4538 	bool needdump = false;
   4539 	bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
   4540 	bool nomaster = false;
   4541 	bool had_db = false;
   4542 	unsigned int options;
   4543 	dns_include_t *inc;
   4544 
   4545 	INSIST(LOCKED_ZONE(zone));
   4546 	if (inline_raw(zone)) {
   4547 		INSIST(LOCKED_ZONE(zone->secure));
   4548 	}
   4549 
   4550 	TIME_NOW(&now);
   4551 
   4552 	/*
   4553 	 * Initiate zone transfer?  We may need a error code that
   4554 	 * indicates that the "permanent" form does not exist.
   4555 	 * XXX better error feedback to log.
   4556 	 */
   4557 	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
   4558 		if (zone->type == dns_zone_slave ||
   4559 		    zone->type == dns_zone_mirror ||
   4560 		    zone->type == dns_zone_stub ||
   4561 		    (zone->type == dns_zone_redirect &&
   4562 		     zone->masters == NULL))
   4563 		{
   4564 			if (result == ISC_R_FILENOTFOUND) {
   4565 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4566 					      ISC_LOG_DEBUG(1),
   4567 					     "no master file");
   4568 			} else if (result != DNS_R_NOMASTERFILE) {
   4569 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4570 					      ISC_LOG_ERROR,
   4571 					     "loading from master file %s "
   4572 					     "failed: %s",
   4573 					     zone->masterfile,
   4574 					     dns_result_totext(result));
   4575 			}
   4576 		} else if (zone->type == dns_zone_master &&
   4577 			   inline_secure(zone) && result == ISC_R_FILENOTFOUND)
   4578 		{
   4579 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4580 				      ISC_LOG_DEBUG(1),
   4581 				     "no master file, requesting db");
   4582 			maybe_send_secure(zone);
   4583 		} else {
   4584 			int level = ISC_LOG_ERROR;
   4585 			if (zone->type == dns_zone_key &&
   4586 			    result == ISC_R_FILENOTFOUND)
   4587 				level = ISC_LOG_DEBUG(1);
   4588 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
   4589 				     "loading from master file %s failed: %s",
   4590 				     zone->masterfile,
   4591 				     dns_result_totext(result));
   4592 			nomaster = true;
   4593 		}
   4594 
   4595 		if (zone->type != dns_zone_key) {
   4596 			goto cleanup;
   4597 		}
   4598 	}
   4599 
   4600 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
   4601 		     "number of nodes in database: %u",
   4602 		     dns_db_nodecount(db));
   4603 
   4604 	if (result == DNS_R_SEENINCLUDE) {
   4605 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
   4606 	} else {
   4607 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
   4608 	}
   4609 
   4610 	/*
   4611 	 * If there's no master file for a key zone, then the zone is new:
   4612 	 * create an SOA record.  (We do this now, instead of later, so that
   4613 	 * if there happens to be a journal file, we can roll forward from
   4614 	 * a sane starting point.)
   4615 	 */
   4616 	if (nomaster && zone->type == dns_zone_key) {
   4617 		result = add_soa(zone, db);
   4618 		if (result != ISC_R_SUCCESS) {
   4619 			goto cleanup;
   4620 		}
   4621 	}
   4622 
   4623 	/*
   4624 	 * Apply update log, if any, on initial load.
   4625 	 */
   4626 	if (zone->journal != NULL &&
   4627 	    ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
   4628 	    ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   4629 	{
   4630 		if (zone->type == dns_zone_master && (inline_secure(zone) ||
   4631 		    (zone->update_acl != NULL || zone->ssutable != NULL)))
   4632 		{
   4633 			options = DNS_JOURNALOPT_RESIGN;
   4634 		} else {
   4635 			options = 0;
   4636 		}
   4637 		result = dns_journal_rollforward(zone->mctx, db, options,
   4638 						 zone->journal);
   4639 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
   4640 		    result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
   4641 		    result != ISC_R_RANGE)
   4642 		{
   4643 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4644 				      ISC_LOG_ERROR,
   4645 				     "journal rollforward failed: %s",
   4646 				     dns_result_totext(result));
   4647 			goto cleanup;
   4648 
   4649 
   4650 		}
   4651 		if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
   4652 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4653 				      ISC_LOG_ERROR,
   4654 				     "journal rollforward failed: "
   4655 				     "journal out of sync with zone");
   4656 			goto cleanup;
   4657 		}
   4658 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
   4659 			     "journal rollforward completed "
   4660 			     "successfully: %s",
   4661 			     dns_result_totext(result));
   4662 		if (result == ISC_R_SUCCESS) {
   4663 			needdump = true;
   4664 		}
   4665 	}
   4666 
   4667 	/*
   4668 	 * Obtain ns, soa and cname counts for top of zone.
   4669 	 */
   4670 	INSIST(db != NULL);
   4671 	result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
   4672 				  &refresh, &retry, &expire, &minimum,
   4673 				  &errors);
   4674 	if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
   4675 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   4676 			     "could not find NS and/or SOA records");
   4677 	}
   4678 
   4679 	/*
   4680 	 * Check to make sure the journal is up to date, and remove the
   4681 	 * journal file if it isn't, as we wouldn't be able to apply
   4682 	 * updates otherwise.
   4683 	 */
   4684 	if (zone->journal != NULL && dns_zone_isdynamic(zone, true) &&
   4685 	    ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
   4686 	{
   4687 		uint32_t jserial;
   4688 		dns_journal_t *journal = NULL;
   4689 		bool empty = false;
   4690 
   4691 		result = dns_journal_open(zone->mctx, zone->journal,
   4692 					  DNS_JOURNAL_READ, &journal);
   4693 		if (result == ISC_R_SUCCESS) {
   4694 			jserial = dns_journal_last_serial(journal);
   4695 			empty = dns_journal_empty(journal);
   4696 			dns_journal_destroy(&journal);
   4697 		} else {
   4698 			jserial = serial;
   4699 			result = ISC_R_SUCCESS;
   4700 		}
   4701 
   4702 		if (jserial != serial) {
   4703 			if (!empty) {
   4704 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4705 					      ISC_LOG_INFO,
   4706 					     "journal file is out of date: "
   4707 					     "removing journal file");
   4708 			}
   4709 			if (remove(zone->journal) < 0 && errno != ENOENT) {
   4710 				char strbuf[ISC_STRERRORSIZE];
   4711 				strerror_r(errno, strbuf, sizeof(strbuf));
   4712 				isc_log_write(dns_lctx,
   4713 					      DNS_LOGCATEGORY_GENERAL,
   4714 					      DNS_LOGMODULE_ZONE,
   4715 					      ISC_LOG_WARNING,
   4716 					      "unable to remove journal "
   4717 					      "'%s': '%s'",
   4718 					      zone->journal, strbuf);
   4719 			}
   4720 		}
   4721 	}
   4722 
   4723 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
   4724 		      "loaded; checking validity");
   4725 
   4726 	/*
   4727 	 * Master / Slave / Mirror / Stub zones require both NS and SOA records
   4728 	 * at the top of the zone.
   4729 	 */
   4730 
   4731 	switch (zone->type) {
   4732 	case dns_zone_dlz:
   4733 	case dns_zone_master:
   4734 	case dns_zone_slave:
   4735 	case dns_zone_mirror:
   4736 	case dns_zone_stub:
   4737 	case dns_zone_redirect:
   4738 		if (soacount != 1) {
   4739 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4740 				      ISC_LOG_ERROR,
   4741 				     "has %d SOA records", soacount);
   4742 			result = DNS_R_BADZONE;
   4743 		}
   4744 		if (nscount == 0) {
   4745 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4746 				      ISC_LOG_ERROR,
   4747 				     "has no NS records");
   4748 			result = DNS_R_BADZONE;
   4749 		}
   4750 		if (result != ISC_R_SUCCESS) {
   4751 			goto cleanup;
   4752 		}
   4753 		if (zone->type == dns_zone_master && errors != 0) {
   4754 			result = DNS_R_BADZONE;
   4755 			goto cleanup;
   4756 		}
   4757 		if (zone->type != dns_zone_stub &&
   4758 		    zone->type != dns_zone_redirect)
   4759 		{
   4760 			result = check_nsec3param(zone, db);
   4761 			if (result != ISC_R_SUCCESS)
   4762 				goto cleanup;
   4763 		}
   4764 		if (zone->type == dns_zone_master &&
   4765 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
   4766 		    !integrity_checks(zone, db))
   4767 		{
   4768 			result = DNS_R_BADZONE;
   4769 			goto cleanup;
   4770 		}
   4771 		if (zone->type == dns_zone_master &&
   4772 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
   4773 		    !zone_check_dup(zone, db))
   4774 		{
   4775 			result = DNS_R_BADZONE;
   4776 			goto cleanup;
   4777 		}
   4778 
   4779 		if (zone->type == dns_zone_master) {
   4780 			result = dns_zone_cdscheck(zone, db, NULL);
   4781 			if (result != ISC_R_SUCCESS) {
   4782 				dns_zone_log(zone, ISC_LOG_ERROR,
   4783 					     "CDS/CDNSKEY consistency checks "
   4784 					     "failed");
   4785 				goto cleanup;
   4786 			}
   4787 		}
   4788 
   4789 		result = dns_zone_verifydb(zone, db, NULL);
   4790 		if (result != ISC_R_SUCCESS) {
   4791 			goto cleanup;
   4792 		}
   4793 
   4794 		if (zone->db != NULL) {
   4795 			unsigned int oldsoacount;
   4796 
   4797 			/*
   4798 			 * This is checked in zone_replacedb() for slave zones
   4799 			 * as they don't reload from disk.
   4800 			 */
   4801 			result = zone_get_from_db(zone, zone->db, NULL,
   4802 						  &oldsoacount, &oldserial,
   4803 						  NULL, NULL, NULL, NULL,
   4804 						  NULL);
   4805 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4806 			RUNTIME_CHECK(soacount > 0U);
   4807 			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
   4808 			    !isc_serial_gt(serial, oldserial)) {
   4809 				uint32_t serialmin, serialmax;
   4810 
   4811 				INSIST(zone->type == dns_zone_master);
   4812 				INSIST(zone->raw == NULL);
   4813 
   4814 				if (serial == oldserial &&
   4815 				    zone_unchanged(zone->db, db, zone->mctx)) {
   4816 					dns_zone_logc(zone,
   4817 						      DNS_LOGCATEGORY_ZONELOAD,
   4818 						      ISC_LOG_INFO,
   4819 						     "ixfr-from-differences: "
   4820 						     "unchanged");
   4821 					goto done;
   4822 				}
   4823 
   4824 				serialmin = (oldserial + 1) & 0xffffffffU;
   4825 				serialmax = (oldserial + 0x7fffffffU) &
   4826 					     0xffffffffU;
   4827 				dns_zone_logc(zone,
   4828 					      DNS_LOGCATEGORY_ZONELOAD,
   4829 					      ISC_LOG_ERROR,
   4830 					      "ixfr-from-differences: "
   4831 					      "new serial (%u) out of range "
   4832 					      "[%u - %u]", serial, serialmin,
   4833 					      serialmax);
   4834 				result = DNS_R_BADZONE;
   4835 				goto cleanup;
   4836 			} else if (!isc_serial_ge(serial, oldserial)) {
   4837 				dns_zone_logc(zone,
   4838 					      DNS_LOGCATEGORY_ZONELOAD,
   4839 					      ISC_LOG_ERROR,
   4840 					      "zone serial (%u/%u) has gone "
   4841 					      "backwards", serial, oldserial);
   4842 			} else if (serial == oldserial && !hasinclude &&
   4843 				   strcmp(zone->db_argv[0], "_builtin") != 0)
   4844 			{
   4845 				dns_zone_logc(zone,
   4846 					      DNS_LOGCATEGORY_ZONELOAD,
   4847 					      ISC_LOG_ERROR,
   4848 					      "zone serial (%u) unchanged. "
   4849 					      "zone may fail to transfer "
   4850 					      "to slaves.", serial);
   4851 			}
   4852 		}
   4853 
   4854 		if (zone->type == dns_zone_master &&
   4855 		    (zone->update_acl != NULL || zone->ssutable != NULL) &&
   4856 		    zone->sigresigninginterval < (3 * refresh) &&
   4857 		    dns_db_issecure(db))
   4858 		{
   4859 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4860 				      ISC_LOG_WARNING,
   4861 				      "sig-re-signing-interval less than "
   4862 				      "3 * refresh.");
   4863 		}
   4864 
   4865 		zone->refresh = RANGE(refresh,
   4866 				      zone->minrefresh, zone->maxrefresh);
   4867 		zone->retry = RANGE(retry,
   4868 				    zone->minretry, zone->maxretry);
   4869 		zone->expire = RANGE(expire, zone->refresh + zone->retry,
   4870 				     DNS_MAX_EXPIRE);
   4871 		zone->minimum = minimum;
   4872 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   4873 
   4874 		if (zone->type == dns_zone_slave ||
   4875 		    zone->type == dns_zone_mirror ||
   4876 		    zone->type == dns_zone_stub ||
   4877 		    (zone->type == dns_zone_redirect &&
   4878 		     zone->masters != NULL))
   4879 		{
   4880 			isc_time_t t;
   4881 			uint32_t delay;
   4882 
   4883 			result = isc_file_getmodtime(zone->journal, &t);
   4884 			if (result != ISC_R_SUCCESS) {
   4885 				result = isc_file_getmodtime(zone->masterfile,
   4886 							     &t);
   4887 			}
   4888 			if (result == ISC_R_SUCCESS) {
   4889 				DNS_ZONE_TIME_ADD(&t, zone->expire,
   4890 						  &zone->expiretime);
   4891 			} else {
   4892 				DNS_ZONE_TIME_ADD(&now, zone->retry,
   4893 						  &zone->expiretime);
   4894 			}
   4895 
   4896 			delay = (zone->retry -
   4897 				 isc_random_uniform((zone->retry * 3) / 4));
   4898 			DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
   4899 			if (isc_time_compare(&zone->refreshtime,
   4900 					     &zone->expiretime) >= 0)
   4901 			{
   4902 				zone->refreshtime = now;
   4903 			}
   4904 		}
   4905 
   4906 		break;
   4907 
   4908 	case dns_zone_key:
   4909 		result = sync_keyzone(zone, db);
   4910 		if (result != ISC_R_SUCCESS) {
   4911 			goto cleanup;
   4912 		}
   4913 		break;
   4914 
   4915 	default:
   4916 		UNEXPECTED_ERROR(__FILE__, __LINE__,
   4917 				 "unexpected zone type %d", zone->type);
   4918 		result = ISC_R_UNEXPECTED;
   4919 		goto cleanup;
   4920 	}
   4921 
   4922 	/*
   4923 	 * Check for weak DNSKEY's.
   4924 	 */
   4925 	if (zone->type == dns_zone_master) {
   4926 		zone_check_dnskeys(zone, db);
   4927 	}
   4928 
   4929 	/*
   4930 	 * Schedule DNSSEC key refresh.
   4931 	 */
   4932 	if (zone->type == dns_zone_master &&
   4933 	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
   4934 	{
   4935 		zone->refreshkeytime = now;
   4936 	}
   4937 
   4938 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   4939 	if (zone->db != NULL) {
   4940 		had_db = true;
   4941 		result = zone_replacedb(zone, db, false);
   4942 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   4943 		if (result != ISC_R_SUCCESS) {
   4944 			goto cleanup;
   4945 		}
   4946 	} else {
   4947 		zone_attachdb(zone, db);
   4948 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   4949 		DNS_ZONE_SETFLAG(zone,
   4950 				 DNS_ZONEFLG_LOADED|
   4951 				 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
   4952 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
   4953 		    inline_raw(zone))
   4954 		{
   4955 			if (zone->secure->db == NULL) {
   4956 				zone_send_securedb(zone, db);
   4957 			} else {
   4958 				zone_send_secureserial(zone, serial);
   4959 			}
   4960 		}
   4961 	}
   4962 
   4963 	/*
   4964 	 * Finished loading inline-signing zone; need to get status
   4965 	 * from the raw side now.
   4966 	 */
   4967 	if (zone->type == dns_zone_master && inline_secure(zone)) {
   4968 		maybe_send_secure(zone);
   4969 	}
   4970 
   4971 	result = ISC_R_SUCCESS;
   4972 
   4973 	if (needdump) {
   4974 		if (zone->type == dns_zone_key) {
   4975 			zone_needdump(zone, 30);
   4976 		} else {
   4977 			zone_needdump(zone, DNS_DUMP_DELAY);
   4978 		}
   4979 	}
   4980 
   4981 	if (zone->task != NULL) {
   4982 		if (zone->type == dns_zone_master) {
   4983 			set_resigntime(zone);
   4984 			resume_signingwithkey(zone);
   4985 			resume_addnsec3chain(zone);
   4986 		}
   4987 
   4988 		if (zone->type == dns_zone_master &&
   4989 		    !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
   4990 		    dns_zone_isdynamic(zone, false) &&
   4991 		    dns_db_issecure(db))
   4992 		{
   4993 			dns_name_t *name;
   4994 			dns_fixedname_t fixed;
   4995 			dns_rdataset_t next;
   4996 
   4997 			dns_rdataset_init(&next);
   4998 			name = dns_fixedname_initname(&fixed);
   4999 
   5000 			result = dns_db_getsigningtime(db, &next, name);
   5001 			if (result == ISC_R_SUCCESS) {
   5002 				isc_stdtime_t timenow;
   5003 				char namebuf[DNS_NAME_FORMATSIZE];
   5004 				char typebuf[DNS_RDATATYPE_FORMATSIZE];
   5005 
   5006 				isc_stdtime_get(&timenow);
   5007 				dns_name_format(name, namebuf, sizeof(namebuf));
   5008 				dns_rdatatype_format(next.covers,
   5009 						     typebuf, sizeof(typebuf));
   5010 				dnssec_log(zone, ISC_LOG_DEBUG(3),
   5011 					   "next resign: %s/%s "
   5012 					   "in %d seconds", namebuf, typebuf,
   5013 					   next.resign - timenow -
   5014 					    zone->sigresigninginterval);
   5015 				dns_rdataset_disassociate(&next);
   5016 			} else {
   5017 				dnssec_log(zone, ISC_LOG_WARNING,
   5018 					   "signed dynamic zone has no "
   5019 					   "resign event scheduled");
   5020 			}
   5021 		}
   5022 
   5023 		zone_settimer(zone, &now);
   5024 	}
   5025 
   5026 	/*
   5027 	 * Clear old include list.
   5028 	 */
   5029 	for (inc = ISC_LIST_HEAD(zone->includes);
   5030 	     inc != NULL;
   5031 	     inc = ISC_LIST_HEAD(zone->includes))
   5032 	{
   5033 		ISC_LIST_UNLINK(zone->includes, inc, link);
   5034 		isc_mem_free(zone->mctx, inc->name);
   5035 		isc_mem_put(zone->mctx, inc, sizeof(*inc));
   5036 	}
   5037 	zone->nincludes = 0;
   5038 
   5039 	/*
   5040 	 * Transfer new include list.
   5041 	 */
   5042 	for (inc = ISC_LIST_HEAD(zone->newincludes);
   5043 	     inc != NULL;
   5044 	     inc = ISC_LIST_HEAD(zone->newincludes))
   5045 	{
   5046 		ISC_LIST_UNLINK(zone->newincludes, inc, link);
   5047 		ISC_LIST_APPEND(zone->includes, inc, link);
   5048 		zone->nincludes++;
   5049 	}
   5050 
   5051 	if (! dns_db_ispersistent(db)) {
   5052 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5053 			      ISC_LOG_INFO, "loaded serial %u%s", serial,
   5054 			      dns_db_issecure(db) ? " (DNSSEC signed)" : "");
   5055 	}
   5056 
   5057 	if (!had_db && zone->type == dns_zone_mirror) {
   5058 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
   5059 			      "mirror zone is now in use");
   5060 	}
   5061 
   5062 	zone->loadtime = loadtime;
   5063 	goto done;
   5064 
   5065  cleanup:
   5066 	if (zone->type == dns_zone_key && result != ISC_R_SUCCESS) {
   5067 		dnssec_log(zone, ISC_LOG_ERROR,
   5068 			   "failed to initialize managed-keys (%s): "
   5069 			   "DNSSEC validation is at risk",
   5070 			   isc_result_totext(result));
   5071 	}
   5072 
   5073 	for (inc = ISC_LIST_HEAD(zone->newincludes);
   5074 	     inc != NULL;
   5075 	     inc = ISC_LIST_HEAD(zone->newincludes))
   5076 	{
   5077 		ISC_LIST_UNLINK(zone->newincludes, inc, link);
   5078 		isc_mem_free(zone->mctx, inc->name);
   5079 		isc_mem_put(zone->mctx, inc, sizeof(*inc));
   5080 	}
   5081 	if (zone->type == dns_zone_slave ||
   5082 	    zone->type == dns_zone_mirror ||
   5083 	    zone->type == dns_zone_stub ||
   5084 	    zone->type == dns_zone_key ||
   5085 	    (zone->type == dns_zone_redirect && zone->masters != NULL))
   5086 	{
   5087 		if (result != ISC_R_NOMEMORY) {
   5088 			if (zone->journal != NULL) {
   5089 				zone_saveunique(zone, zone->journal,
   5090 						"jn-XXXXXXXX");
   5091 			}
   5092 			if (zone->masterfile != NULL) {
   5093 				zone_saveunique(zone, zone->masterfile,
   5094 						"db-XXXXXXXX");
   5095 			}
   5096 		}
   5097 
   5098 		/* Mark the zone for immediate refresh. */
   5099 		zone->refreshtime = now;
   5100 		if (zone->task != NULL) {
   5101 			zone_settimer(zone, &now);
   5102 		}
   5103 		result = ISC_R_SUCCESS;
   5104 	} else if (zone->type == dns_zone_master ||
   5105 		   zone->type == dns_zone_redirect)
   5106 	{
   5107 		if (! (inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
   5108 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   5109 				      ISC_LOG_ERROR,
   5110 				      "not loaded due to errors.");
   5111 		} else if (zone->type == dns_zone_master) {
   5112 			result = ISC_R_SUCCESS;
   5113 		}
   5114 	}
   5115 
   5116  done:
   5117 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
   5118 	/*
   5119 	 * If this is an inline-signed zone and we were called for the raw
   5120 	 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
   5121 	 * as well, but only if this is a reload, not an initial zone load: in
   5122 	 * the former case, zone_postload() will not be run for the secure
   5123 	 * zone; in the latter case, it will be.  Check which case we are
   5124 	 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
   5125 	 * secure zone: if it is set, this must be a reload.
   5126 	 */
   5127 	if (inline_raw(zone) &&
   5128 	    DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
   5129 	{
   5130 		DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
   5131 	}
   5132 
   5133 	zone_debuglog(zone, "zone_postload", 99, "done");
   5134 
   5135 	return (result);
   5136 }
   5137 
   5138 static bool
   5139 exit_check(dns_zone_t *zone) {
   5140 	REQUIRE(LOCKED_ZONE(zone));
   5141 
   5142 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
   5143 		/*
   5144 		 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
   5145 		 */
   5146 		INSIST(isc_refcount_current(&zone->erefs) == 0);
   5147 		return (true);
   5148 	}
   5149 	return (false);
   5150 }
   5151 
   5152 static bool
   5153 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
   5154 	      dns_name_t *name, bool logit)
   5155 {
   5156 	isc_result_t result;
   5157 	char namebuf[DNS_NAME_FORMATSIZE];
   5158 	char altbuf[DNS_NAME_FORMATSIZE];
   5159 	dns_fixedname_t fixed;
   5160 	dns_name_t *foundname;
   5161 	int level;
   5162 
   5163 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
   5164 		return (true);
   5165 
   5166 	if (zone->type == dns_zone_master)
   5167 		level = ISC_LOG_ERROR;
   5168 	else
   5169 		level = ISC_LOG_WARNING;
   5170 
   5171 	foundname = dns_fixedname_initname(&fixed);
   5172 
   5173 	result = dns_db_find(db, name, version, dns_rdatatype_a,
   5174 			     0, 0, NULL, foundname, NULL, NULL);
   5175 	if (result == ISC_R_SUCCESS)
   5176 		return (true);
   5177 
   5178 	if (result == DNS_R_NXRRSET) {
   5179 		result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
   5180 				     0, 0, NULL, foundname, NULL, NULL);
   5181 		if (result == ISC_R_SUCCESS)
   5182 			return (true);
   5183 	}
   5184 
   5185 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   5186 	    result == DNS_R_EMPTYNAME) {
   5187 		if (logit) {
   5188 			dns_name_format(name, namebuf, sizeof namebuf);
   5189 			dns_zone_log(zone, level, "NS '%s' has no address "
   5190 				     "records (A or AAAA)", namebuf);
   5191 		}
   5192 		return (false);
   5193 	}
   5194 
   5195 	if (result == DNS_R_CNAME) {
   5196 		if (logit) {
   5197 			dns_name_format(name, namebuf, sizeof namebuf);
   5198 			dns_zone_log(zone, level, "NS '%s' is a CNAME "
   5199 				     "(illegal)", namebuf);
   5200 		}
   5201 		return (false);
   5202 	}
   5203 
   5204 	if (result == DNS_R_DNAME) {
   5205 		if (logit) {
   5206 			dns_name_format(name, namebuf, sizeof namebuf);
   5207 			dns_name_format(foundname, altbuf, sizeof altbuf);
   5208 			dns_zone_log(zone, level, "NS '%s' is below a DNAME "
   5209 				     "'%s' (illegal)", namebuf, altbuf);
   5210 		}
   5211 		return (false);
   5212 	}
   5213 
   5214 	return (true);
   5215 }
   5216 
   5217 static isc_result_t
   5218 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
   5219 		 dns_dbversion_t *version, unsigned int *nscount,
   5220 		 unsigned int *errors, bool logit)
   5221 {
   5222 	isc_result_t result;
   5223 	unsigned int count = 0;
   5224 	unsigned int ecount = 0;
   5225 	dns_rdataset_t rdataset;
   5226 	dns_rdata_t rdata;
   5227 	dns_rdata_ns_t ns;
   5228 
   5229 	dns_rdataset_init(&rdataset);
   5230 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
   5231 				     dns_rdatatype_none, 0, &rdataset, NULL);
   5232 	if (result == ISC_R_NOTFOUND) {
   5233 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5234 		goto success;
   5235 	}
   5236 	if (result != ISC_R_SUCCESS) {
   5237 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5238 		goto invalidate_rdataset;
   5239 	}
   5240 
   5241 	result = dns_rdataset_first(&rdataset);
   5242 	while (result == ISC_R_SUCCESS) {
   5243 		if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
   5244 		    (zone->type == dns_zone_master ||
   5245 		     zone->type == dns_zone_slave ||
   5246 		     zone->type == dns_zone_mirror))
   5247 		{
   5248 			dns_rdata_init(&rdata);
   5249 			dns_rdataset_current(&rdataset, &rdata);
   5250 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
   5251 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   5252 			if (dns_name_issubdomain(&ns.name, &zone->origin) &&
   5253 			    !zone_check_ns(zone, db, version, &ns.name, logit))
   5254 				ecount++;
   5255 		}
   5256 		count++;
   5257 		result = dns_rdataset_next(&rdataset);
   5258 	}
   5259 	dns_rdataset_disassociate(&rdataset);
   5260 
   5261  success:
   5262 	if (nscount != NULL)
   5263 		*nscount = count;
   5264 	if (errors != NULL)
   5265 		*errors = ecount;
   5266 
   5267 	result = ISC_R_SUCCESS;
   5268 
   5269  invalidate_rdataset:
   5270 	dns_rdataset_invalidate(&rdataset);
   5271 
   5272 	return (result);
   5273 }
   5274 
   5275 static isc_result_t
   5276 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   5277 		 unsigned int *soacount,
   5278 		 uint32_t *serial, uint32_t *refresh,
   5279 		 uint32_t *retry, uint32_t *expire,
   5280 		 uint32_t *minimum)
   5281 {
   5282 	isc_result_t result;
   5283 	unsigned int count;
   5284 	dns_rdataset_t rdataset;
   5285 	dns_rdata_t rdata = DNS_RDATA_INIT;
   5286 	dns_rdata_soa_t soa;
   5287 
   5288 	dns_rdataset_init(&rdataset);
   5289 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
   5290 				     dns_rdatatype_none, 0, &rdataset, NULL);
   5291 	if (result == ISC_R_NOTFOUND) {
   5292 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5293 		if (soacount != NULL)
   5294 			*soacount = 0;
   5295 		if (serial != NULL)
   5296 			*serial = 0;
   5297 		if (refresh != NULL)
   5298 			*refresh = 0;
   5299 		if (retry != NULL)
   5300 			*retry = 0;
   5301 		if (expire != NULL)
   5302 			*expire = 0;
   5303 		if (minimum != NULL)
   5304 			*minimum = 0;
   5305 		result = ISC_R_SUCCESS;
   5306 		goto invalidate_rdataset;
   5307 	}
   5308 	if (result != ISC_R_SUCCESS) {
   5309 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5310 		goto invalidate_rdataset;
   5311 	}
   5312 
   5313 	count = 0;
   5314 	result = dns_rdataset_first(&rdataset);
   5315 	while (result == ISC_R_SUCCESS) {
   5316 		dns_rdata_init(&rdata);
   5317 		dns_rdataset_current(&rdataset, &rdata);
   5318 		count++;
   5319 		if (count == 1) {
   5320 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
   5321 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   5322 		}
   5323 
   5324 		result = dns_rdataset_next(&rdataset);
   5325 		dns_rdata_reset(&rdata);
   5326 	}
   5327 	dns_rdataset_disassociate(&rdataset);
   5328 
   5329 	if (soacount != NULL)
   5330 		*soacount = count;
   5331 
   5332 	if (count > 0) {
   5333 		if (serial != NULL)
   5334 			*serial = soa.serial;
   5335 		if (refresh != NULL)
   5336 			*refresh = soa.refresh;
   5337 		if (retry != NULL)
   5338 			*retry = soa.retry;
   5339 		if (expire != NULL)
   5340 			*expire = soa.expire;
   5341 		if (minimum != NULL)
   5342 			*minimum = soa.minimum;
   5343 	} else {
   5344 		if (soacount != NULL)
   5345 			*soacount = 0;
   5346 		if (serial != NULL)
   5347 			*serial = 0;
   5348 		if (refresh != NULL)
   5349 			*refresh = 0;
   5350 		if (retry != NULL)
   5351 			*retry = 0;
   5352 		if (expire != NULL)
   5353 			*expire = 0;
   5354 		if (minimum != NULL)
   5355 			*minimum = 0;
   5356 	}
   5357 
   5358 	result = ISC_R_SUCCESS;
   5359 
   5360  invalidate_rdataset:
   5361 	dns_rdataset_invalidate(&rdataset);
   5362 
   5363 	return (result);
   5364 }
   5365 
   5366 /*
   5367  * zone must be locked.
   5368  */
   5369 static isc_result_t
   5370 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
   5371 		 unsigned int *soacount, uint32_t *serial,
   5372 		 uint32_t *refresh, uint32_t *retry,
   5373 		 uint32_t *expire, uint32_t *minimum,
   5374 		 unsigned int *errors)
   5375 {
   5376 	isc_result_t result;
   5377 	isc_result_t answer = ISC_R_SUCCESS;
   5378 	dns_dbversion_t *version = NULL;
   5379 	dns_dbnode_t *node;
   5380 
   5381 	REQUIRE(db != NULL);
   5382 	REQUIRE(zone != NULL);
   5383 
   5384 	dns_db_currentversion(db, &version);
   5385 
   5386 	if (nscount != NULL)
   5387 		*nscount = 0;
   5388 	if (soacount != NULL)
   5389 		*soacount = 0;
   5390 	if (serial != NULL)
   5391 		*serial = 0;
   5392 	if (refresh != NULL)
   5393 		*refresh = 0;
   5394 	if (retry != NULL)
   5395 		*retry = 0;
   5396 	if (expire != NULL)
   5397 		*expire = 0;
   5398 	if (errors != NULL)
   5399 		*errors = 0;
   5400 
   5401 	node = NULL;
   5402 	result = dns_db_findnode(db, &zone->origin, false, &node);
   5403 	if (result != ISC_R_SUCCESS) {
   5404 		answer = result;
   5405 		goto closeversion;
   5406 	}
   5407 
   5408 	if (nscount != NULL || errors != NULL) {
   5409 		result = zone_count_ns_rr(zone, db, node, version,
   5410 					  nscount, errors, true);
   5411 		if (result != ISC_R_SUCCESS)
   5412 			answer = result;
   5413 	}
   5414 
   5415 	if (soacount != NULL || serial != NULL || refresh != NULL
   5416 	    || retry != NULL || expire != NULL || minimum != NULL) {
   5417 		result = zone_load_soa_rr(db, node, version, soacount,
   5418 					  serial, refresh, retry, expire,
   5419 					  minimum);
   5420 		if (result != ISC_R_SUCCESS)
   5421 			answer = result;
   5422 	}
   5423 
   5424 	dns_db_detachnode(db, &node);
   5425  closeversion:
   5426 	dns_db_closeversion(db, &version, false);
   5427 
   5428 	return (answer);
   5429 }
   5430 
   5431 void
   5432 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
   5433 	REQUIRE(DNS_ZONE_VALID(source));
   5434 	REQUIRE(target != NULL && *target == NULL);
   5435 	isc_refcount_increment(&source->erefs);
   5436 	*target = source;
   5437 }
   5438 
   5439 void
   5440 dns_zone_detach(dns_zone_t **zonep) {
   5441 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
   5442 	dns_zone_t *zone = *zonep;
   5443 	*zonep = NULL;
   5444 
   5445 	bool free_now = false;
   5446 	dns_zone_t *raw = NULL;
   5447 	dns_zone_t *secure = NULL;
   5448 	if (isc_refcount_decrement(&zone->erefs) == 1) {
   5449 		isc_refcount_destroy(&zone->erefs);
   5450 
   5451 		LOCK_ZONE(zone);
   5452 		INSIST(zone != zone->raw);
   5453 		/*
   5454 		 * We just detached the last external reference.
   5455 		 */
   5456 		if (zone->task != NULL) {
   5457 			/*
   5458 			 * This zone is being managed.	Post
   5459 			 * its control event and let it clean
   5460 			 * up synchronously in the context of
   5461 			 * its task.
   5462 			 */
   5463 			isc_event_t *ev = &zone->ctlevent;
   5464 			isc_task_send(zone->task, &ev);
   5465 		} else {
   5466 			/*
   5467 			 * This zone is not being managed; it has
   5468 			 * no task and can have no outstanding
   5469 			 * events.  Free it immediately.
   5470 			 */
   5471 			/*
   5472 			 * Unmanaged zones should not have non-null views;
   5473 			 * we have no way of detaching from the view here
   5474 			 * without causing deadlock because this code is called
   5475 			 * with the view already locked.
   5476 			 */
   5477 			INSIST(zone->view == NULL);
   5478 			free_now = true;
   5479 			raw = zone->raw;
   5480 			zone->raw = NULL;
   5481 			secure = zone->secure;
   5482 			zone->secure = NULL;
   5483 		}
   5484 		UNLOCK_ZONE(zone);
   5485 	}
   5486 	if (free_now) {
   5487 		if (raw != NULL) {
   5488 			dns_zone_detach(&raw);
   5489 		}
   5490 		if (secure != NULL) {
   5491 			dns_zone_idetach(&secure);
   5492 		}
   5493 		zone_free(zone);
   5494 	}
   5495 }
   5496 
   5497 void
   5498 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
   5499 	REQUIRE(DNS_ZONE_VALID(source));
   5500 	REQUIRE(target != NULL && *target == NULL);
   5501 	LOCK_ZONE(source);
   5502 	zone_iattach(source, target);
   5503 	UNLOCK_ZONE(source);
   5504 }
   5505 
   5506 static void
   5507 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
   5508 
   5509 	/*
   5510 	 * 'source' locked by caller.
   5511 	 */
   5512 	REQUIRE(DNS_ZONE_VALID(source));
   5513 	REQUIRE(LOCKED_ZONE(source));
   5514 	REQUIRE(target != NULL && *target == NULL);
   5515 	INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
   5516 	source->irefs++;
   5517 	INSIST(source->irefs != 0);
   5518 	*target = source;
   5519 }
   5520 
   5521 static void
   5522 zone_idetach(dns_zone_t **zonep) {
   5523 	dns_zone_t *zone;
   5524 
   5525 	/*
   5526 	 * 'zone' locked by caller.
   5527 	 */
   5528 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
   5529 	zone = *zonep;
   5530 	REQUIRE(LOCKED_ZONE(*zonep));
   5531 	*zonep = NULL;
   5532 
   5533 	INSIST(zone->irefs > 0);
   5534 	zone->irefs--;
   5535 	INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
   5536 }
   5537 
   5538 void
   5539 dns_zone_idetach(dns_zone_t **zonep) {
   5540 	dns_zone_t *zone;
   5541 	bool free_needed;
   5542 
   5543 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
   5544 	zone = *zonep;
   5545 	*zonep = NULL;
   5546 
   5547 	LOCK_ZONE(zone);
   5548 	INSIST(zone->irefs > 0);
   5549 	zone->irefs--;
   5550 	free_needed = exit_check(zone);
   5551 	UNLOCK_ZONE(zone);
   5552 	if (free_needed)
   5553 		zone_free(zone);
   5554 }
   5555 
   5556 isc_mem_t *
   5557 dns_zone_getmctx(dns_zone_t *zone) {
   5558 	REQUIRE(DNS_ZONE_VALID(zone));
   5559 
   5560 	return (zone->mctx);
   5561 }
   5562 
   5563 dns_zonemgr_t *
   5564 dns_zone_getmgr(dns_zone_t *zone) {
   5565 	REQUIRE(DNS_ZONE_VALID(zone));
   5566 
   5567 	return (zone->zmgr);
   5568 }
   5569 
   5570 void
   5571 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, bool value) {
   5572 	REQUIRE(DNS_ZONE_VALID(zone));
   5573 
   5574 	LOCK_ZONE(zone);
   5575 	if (value)
   5576 		DNS_ZONE_SETFLAG(zone, flags);
   5577 	else
   5578 		DNS_ZONE_CLRFLAG(zone, flags);
   5579 	UNLOCK_ZONE(zone);
   5580 }
   5581 
   5582 void
   5583 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option,
   5584 		   bool value)
   5585 {
   5586 	REQUIRE(DNS_ZONE_VALID(zone));
   5587 
   5588 	LOCK_ZONE(zone);
   5589 	if (value)
   5590 		zone->options |= option;
   5591 	else
   5592 		zone->options &= ~option;
   5593 	UNLOCK_ZONE(zone);
   5594 }
   5595 
   5596 dns_zoneopt_t
   5597 dns_zone_getoptions(dns_zone_t *zone) {
   5598 	REQUIRE(DNS_ZONE_VALID(zone));
   5599 
   5600 	return (zone->options);
   5601 }
   5602 
   5603 void
   5604 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value)
   5605 {
   5606 	REQUIRE(DNS_ZONE_VALID(zone));
   5607 
   5608 	LOCK_ZONE(zone);
   5609 	if (value)
   5610 		zone->keyopts |= keyopt;
   5611 	else
   5612 		zone->keyopts &= ~keyopt;
   5613 	UNLOCK_ZONE(zone);
   5614 }
   5615 
   5616 unsigned int
   5617 dns_zone_getkeyopts(dns_zone_t *zone) {
   5618 
   5619 	REQUIRE(DNS_ZONE_VALID(zone));
   5620 
   5621 	return (zone->keyopts);
   5622 }
   5623 
   5624 isc_result_t
   5625 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
   5626 	REQUIRE(DNS_ZONE_VALID(zone));
   5627 
   5628 	LOCK_ZONE(zone);
   5629 	zone->xfrsource4 = *xfrsource;
   5630 	UNLOCK_ZONE(zone);
   5631 
   5632 	return (ISC_R_SUCCESS);
   5633 }
   5634 
   5635 isc_sockaddr_t *
   5636 dns_zone_getxfrsource4(dns_zone_t *zone) {
   5637 	REQUIRE(DNS_ZONE_VALID(zone));
   5638 	return (&zone->xfrsource4);
   5639 }
   5640 
   5641 isc_result_t
   5642 dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
   5643 	REQUIRE(DNS_ZONE_VALID(zone));
   5644 
   5645 	LOCK_ZONE(zone);
   5646 	zone->xfrsource4dscp = dscp;
   5647 	UNLOCK_ZONE(zone);
   5648 
   5649 	return (ISC_R_SUCCESS);
   5650 }
   5651 
   5652 isc_dscp_t
   5653 dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
   5654 	REQUIRE(DNS_ZONE_VALID(zone));
   5655 	return (zone->xfrsource4dscp);
   5656 }
   5657 
   5658 isc_result_t
   5659 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
   5660 	REQUIRE(DNS_ZONE_VALID(zone));
   5661 
   5662 	LOCK_ZONE(zone);
   5663 	zone->xfrsource6 = *xfrsource;
   5664 	UNLOCK_ZONE(zone);
   5665 
   5666 	return (ISC_R_SUCCESS);
   5667 }
   5668 
   5669 isc_sockaddr_t *
   5670 dns_zone_getxfrsource6(dns_zone_t *zone) {
   5671 	REQUIRE(DNS_ZONE_VALID(zone));
   5672 	return (&zone->xfrsource6);
   5673 }
   5674 
   5675 isc_dscp_t
   5676 dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
   5677 	REQUIRE(DNS_ZONE_VALID(zone));
   5678 	return (zone->xfrsource6dscp);
   5679 }
   5680 
   5681 isc_result_t
   5682 dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
   5683 	REQUIRE(DNS_ZONE_VALID(zone));
   5684 
   5685 	LOCK_ZONE(zone);
   5686 	zone->xfrsource6dscp = dscp;
   5687 	UNLOCK_ZONE(zone);
   5688 
   5689 	return (ISC_R_SUCCESS);
   5690 }
   5691 
   5692 isc_result_t
   5693 dns_zone_setaltxfrsource4(dns_zone_t *zone,
   5694 			  const isc_sockaddr_t *altxfrsource)
   5695 {
   5696 	REQUIRE(DNS_ZONE_VALID(zone));
   5697 
   5698 	LOCK_ZONE(zone);
   5699 	zone->altxfrsource4 = *altxfrsource;
   5700 	UNLOCK_ZONE(zone);
   5701 
   5702 	return (ISC_R_SUCCESS);
   5703 }
   5704 
   5705 isc_sockaddr_t *
   5706 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
   5707 	REQUIRE(DNS_ZONE_VALID(zone));
   5708 	return (&zone->altxfrsource4);
   5709 }
   5710 
   5711 isc_result_t
   5712 dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
   5713 	REQUIRE(DNS_ZONE_VALID(zone));
   5714 
   5715 	LOCK_ZONE(zone);
   5716 	zone->altxfrsource4dscp = dscp;
   5717 	UNLOCK_ZONE(zone);
   5718 
   5719 	return (ISC_R_SUCCESS);
   5720 }
   5721 
   5722 isc_dscp_t
   5723 dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
   5724 	REQUIRE(DNS_ZONE_VALID(zone));
   5725 	return (zone->altxfrsource4dscp);
   5726 }
   5727 
   5728 isc_result_t
   5729 dns_zone_setaltxfrsource6(dns_zone_t *zone,
   5730 			  const isc_sockaddr_t *altxfrsource)
   5731 {
   5732 	REQUIRE(DNS_ZONE_VALID(zone));
   5733 
   5734 	LOCK_ZONE(zone);
   5735 	zone->altxfrsource6 = *altxfrsource;
   5736 	UNLOCK_ZONE(zone);
   5737 
   5738 	return (ISC_R_SUCCESS);
   5739 }
   5740 
   5741 isc_sockaddr_t *
   5742 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
   5743 	REQUIRE(DNS_ZONE_VALID(zone));
   5744 	return (&zone->altxfrsource6);
   5745 }
   5746 
   5747 isc_result_t
   5748 dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
   5749 	REQUIRE(DNS_ZONE_VALID(zone));
   5750 
   5751 	LOCK_ZONE(zone);
   5752 	zone->altxfrsource6dscp = dscp;
   5753 	UNLOCK_ZONE(zone);
   5754 
   5755 	return (ISC_R_SUCCESS);
   5756 }
   5757 
   5758 isc_dscp_t
   5759 dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
   5760 	REQUIRE(DNS_ZONE_VALID(zone));
   5761 	return (zone->altxfrsource6dscp);
   5762 }
   5763 
   5764 isc_result_t
   5765 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
   5766 	REQUIRE(DNS_ZONE_VALID(zone));
   5767 
   5768 	LOCK_ZONE(zone);
   5769 	zone->notifysrc4 = *notifysrc;
   5770 	UNLOCK_ZONE(zone);
   5771 
   5772 	return (ISC_R_SUCCESS);
   5773 }
   5774 
   5775 isc_sockaddr_t *
   5776 dns_zone_getnotifysrc4(dns_zone_t *zone) {
   5777 	REQUIRE(DNS_ZONE_VALID(zone));
   5778 	return (&zone->notifysrc4);
   5779 }
   5780 
   5781 isc_result_t
   5782 dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
   5783 	REQUIRE(DNS_ZONE_VALID(zone));
   5784 
   5785 	LOCK_ZONE(zone);
   5786 	zone->notifysrc4dscp = dscp;
   5787 	UNLOCK_ZONE(zone);
   5788 
   5789 	return (ISC_R_SUCCESS);
   5790 }
   5791 
   5792 isc_dscp_t
   5793 dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
   5794 	REQUIRE(DNS_ZONE_VALID(zone));
   5795 	return (zone->notifysrc4dscp);
   5796 }
   5797 
   5798 isc_result_t
   5799 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
   5800 	REQUIRE(DNS_ZONE_VALID(zone));
   5801 
   5802 	LOCK_ZONE(zone);
   5803 	zone->notifysrc6 = *notifysrc;
   5804 	UNLOCK_ZONE(zone);
   5805 
   5806 	return (ISC_R_SUCCESS);
   5807 }
   5808 
   5809 isc_sockaddr_t *
   5810 dns_zone_getnotifysrc6(dns_zone_t *zone) {
   5811 	REQUIRE(DNS_ZONE_VALID(zone));
   5812 	return (&zone->notifysrc6);
   5813 }
   5814 
   5815 static bool
   5816 same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
   5817 	   uint32_t count)
   5818 {
   5819 	unsigned int i;
   5820 
   5821 	for (i = 0; i < count; i++)
   5822 		if (!isc_sockaddr_equal(&oldlist[i], &newlist[i]))
   5823 			return (false);
   5824 	return (true);
   5825 }
   5826 
   5827 static bool
   5828 same_keynames(dns_name_t * const *oldlist, dns_name_t * const *newlist,
   5829 	      uint32_t count)
   5830 {
   5831 	unsigned int i;
   5832 
   5833 	if (oldlist == NULL && newlist == NULL)
   5834 		return (true);
   5835 	if (oldlist == NULL || newlist == NULL)
   5836 		return (false);
   5837 
   5838 	for (i = 0; i < count; i++) {
   5839 		if (oldlist[i] == NULL && newlist[i] == NULL)
   5840 			continue;
   5841 		if (oldlist[i] == NULL || newlist[i] == NULL ||
   5842 		    !dns_name_equal(oldlist[i], newlist[i]))
   5843 			return (false);
   5844 	}
   5845 	return (true);
   5846 }
   5847 
   5848 static void
   5849 clear_addresskeylist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
   5850 		     dns_name_t ***keynamesp, unsigned int *countp,
   5851 		     isc_mem_t *mctx)
   5852 {
   5853 	unsigned int count;
   5854 	isc_sockaddr_t *addrs;
   5855 	isc_dscp_t *dscps;
   5856 	dns_name_t **keynames;
   5857 
   5858 	REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
   5859 		keynamesp != NULL);
   5860 
   5861 	count = *countp;
   5862 	*countp = 0;
   5863 	addrs = *addrsp;
   5864 	*addrsp = NULL;
   5865 	dscps = *dscpsp;
   5866 	*dscpsp = NULL;
   5867 	keynames = *keynamesp;
   5868 	*keynamesp = NULL;
   5869 
   5870 	if (addrs != NULL)
   5871 		isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
   5872 
   5873 	if (dscps != NULL)
   5874 		isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
   5875 
   5876 	if (keynames != NULL) {
   5877 		unsigned int i;
   5878 		for (i = 0; i < count; i++) {
   5879 			if (keynames[i] != NULL) {
   5880 				dns_name_free(keynames[i], mctx);
   5881 				isc_mem_put(mctx, keynames[i],
   5882 					    sizeof(dns_name_t));
   5883 				keynames[i] = NULL;
   5884 			}
   5885 		}
   5886 		isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
   5887 	}
   5888 }
   5889 
   5890 static isc_result_t
   5891 set_addrkeylist(unsigned int count,
   5892 		const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
   5893 		const isc_dscp_t *dscp, isc_dscp_t **newdscpp,
   5894 		dns_name_t **names, dns_name_t ***newnamesp,
   5895 		isc_mem_t *mctx)
   5896 {
   5897 	isc_result_t result;
   5898 	isc_sockaddr_t *newaddrs = NULL;
   5899 	isc_dscp_t *newdscp = NULL;
   5900 	dns_name_t **newnames = NULL;
   5901 	unsigned int i;
   5902 
   5903 	REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
   5904 	REQUIRE(newdscpp != NULL && *newdscpp == NULL);
   5905 	REQUIRE(newnamesp != NULL && *newnamesp == NULL);
   5906 
   5907 	newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
   5908 	if (newaddrs == NULL)
   5909 		return (ISC_R_NOMEMORY);
   5910 	memmove(newaddrs, addrs, count * sizeof(*newaddrs));
   5911 
   5912 	if (dscp != NULL) {
   5913 		newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
   5914 		if (newdscp == NULL) {
   5915 			isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
   5916 			return (ISC_R_NOMEMORY);
   5917 		}
   5918 		memmove(newdscp, dscp, count * sizeof(*newdscp));
   5919 	} else
   5920 		newdscp = NULL;
   5921 
   5922 	if (names != NULL) {
   5923 		newnames = isc_mem_get(mctx, count * sizeof(*newnames));
   5924 		if (newnames == NULL) {
   5925 			if (newdscp != NULL)
   5926 				isc_mem_put(mctx, newdscp,
   5927 					    count * sizeof(*newdscp));
   5928 			isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
   5929 			return (ISC_R_NOMEMORY);
   5930 		}
   5931 		for (i = 0; i < count; i++)
   5932 			newnames[i] = NULL;
   5933 		for (i = 0; i < count; i++) {
   5934 			if (names[i] != NULL) {
   5935 				newnames[i] = isc_mem_get(mctx,
   5936 							 sizeof(dns_name_t));
   5937 				if (newnames[i] == NULL)
   5938 					goto allocfail;
   5939 				dns_name_init(newnames[i], NULL);
   5940 				result = dns_name_dup(names[i], mctx,
   5941 						      newnames[i]);
   5942 				if (result != ISC_R_SUCCESS) {
   5943 				allocfail:
   5944 					for (i = 0; i < count; i++)
   5945 						if (newnames[i] != NULL)
   5946 							dns_name_free(
   5947 							       newnames[i],
   5948 							       mctx);
   5949 					isc_mem_put(mctx, newaddrs,
   5950 						    count * sizeof(*newaddrs));
   5951 					isc_mem_put(mctx, newdscp,
   5952 						    count * sizeof(*newdscp));
   5953 					isc_mem_put(mctx, newnames,
   5954 						    count * sizeof(*newnames));
   5955 					return (ISC_R_NOMEMORY);
   5956 				}
   5957 			}
   5958 		}
   5959 	} else
   5960 		newnames = NULL;
   5961 
   5962 	*newdscpp = newdscp;
   5963 	*newaddrsp = newaddrs;
   5964 	*newnamesp = newnames;
   5965 	return (ISC_R_SUCCESS);
   5966 }
   5967 
   5968 isc_result_t
   5969 dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
   5970 	REQUIRE(DNS_ZONE_VALID(zone));
   5971 
   5972 	LOCK_ZONE(zone);
   5973 	zone->notifysrc6dscp = dscp;
   5974 	UNLOCK_ZONE(zone);
   5975 
   5976 	return (ISC_R_SUCCESS);
   5977 }
   5978 
   5979 isc_dscp_t
   5980 dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
   5981 	REQUIRE(DNS_ZONE_VALID(zone));
   5982 	return (zone->notifysrc6dscp);
   5983 }
   5984 
   5985 isc_result_t
   5986 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
   5987 		       uint32_t count)
   5988 {
   5989 	return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
   5990 					       count));
   5991 }
   5992 
   5993 isc_result_t
   5994 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
   5995 			       dns_name_t **keynames, uint32_t count)
   5996 {
   5997 	return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
   5998 					       count));
   5999 }
   6000 
   6001 isc_result_t
   6002 dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
   6003 			       const isc_dscp_t *dscps, dns_name_t **keynames,
   6004 			       uint32_t count)
   6005 {
   6006 	isc_result_t result;
   6007 	isc_sockaddr_t *newaddrs = NULL;
   6008 	isc_dscp_t *newdscps = NULL;
   6009 	dns_name_t **newnames = NULL;
   6010 
   6011 	REQUIRE(DNS_ZONE_VALID(zone));
   6012 	REQUIRE(count == 0 || notify != NULL);
   6013 	if (keynames != NULL)
   6014 		REQUIRE(count != 0);
   6015 
   6016 	LOCK_ZONE(zone);
   6017 
   6018 	if (count == zone->notifycnt &&
   6019 	    same_addrs(zone->notify, notify, count) &&
   6020 	    same_keynames(zone->notifykeynames, keynames, count))
   6021 		goto unlock;
   6022 
   6023 	clear_addresskeylist(&zone->notify, &zone->notifydscp,
   6024 			     &zone->notifykeynames, &zone->notifycnt,
   6025 			     zone->mctx);
   6026 
   6027 	if (count == 0)
   6028 		goto unlock;
   6029 
   6030 	/*
   6031 	 * Set up the notify and notifykey lists
   6032 	 */
   6033 	result = set_addrkeylist(count, notify, &newaddrs, dscps, &newdscps,
   6034 				 keynames, &newnames, zone->mctx);
   6035 	if (result != ISC_R_SUCCESS)
   6036 		goto unlock;
   6037 
   6038 	/*
   6039 	 * Everything is ok so attach to the zone.
   6040 	 */
   6041 	zone->notify = newaddrs;
   6042 	zone->notifydscp = newdscps;
   6043 	zone->notifykeynames = newnames;
   6044 	zone->notifycnt = count;
   6045  unlock:
   6046 	UNLOCK_ZONE(zone);
   6047 	return (ISC_R_SUCCESS);
   6048 }
   6049 
   6050 isc_result_t
   6051 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
   6052 		    uint32_t count)
   6053 {
   6054 	isc_result_t result;
   6055 
   6056 	result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
   6057 	return (result);
   6058 }
   6059 
   6060 isc_result_t
   6061 dns_zone_setmasterswithkeys(dns_zone_t *zone,
   6062 			    const isc_sockaddr_t *masters,
   6063 			    dns_name_t **keynames,
   6064 			    uint32_t count)
   6065 {
   6066 	isc_result_t result = ISC_R_SUCCESS;
   6067 	isc_sockaddr_t *newaddrs = NULL;
   6068 	isc_dscp_t *newdscps = NULL;
   6069 	dns_name_t **newnames = NULL;
   6070 	bool *newok;
   6071 	unsigned int i;
   6072 
   6073 	REQUIRE(DNS_ZONE_VALID(zone));
   6074 	REQUIRE(count == 0 || masters != NULL);
   6075 	if (keynames != NULL) {
   6076 		REQUIRE(count != 0);
   6077 	}
   6078 
   6079 	LOCK_ZONE(zone);
   6080 	/*
   6081 	 * The refresh code assumes that 'masters' wouldn't change under it.
   6082 	 * If it will change then kill off any current refresh in progress
   6083 	 * and update the masters info.  If it won't change then we can just
   6084 	 * unlock and exit.
   6085 	 */
   6086 	if (count != zone->masterscnt ||
   6087 	    !same_addrs(zone->masters, masters, count) ||
   6088 	    !same_keynames(zone->masterkeynames, keynames, count)) {
   6089 		if (zone->request != NULL)
   6090 			dns_request_cancel(zone->request);
   6091 	} else
   6092 		goto unlock;
   6093 
   6094 	/*
   6095 	 * This needs to happen before clear_addresskeylist() sets
   6096 	 * zone->masterscnt to 0:
   6097 	 */
   6098 	if (zone->mastersok != NULL) {
   6099 		isc_mem_put(zone->mctx, zone->mastersok,
   6100 			    zone->masterscnt * sizeof(bool));
   6101 		zone->mastersok = NULL;
   6102 	}
   6103 	clear_addresskeylist(&zone->masters, &zone->masterdscps,
   6104 			     &zone->masterkeynames, &zone->masterscnt,
   6105 			     zone->mctx);
   6106 	/*
   6107 	 * If count == 0, don't allocate any space for masters, mastersok or
   6108 	 * keynames so internally, those pointers are NULL if count == 0
   6109 	 */
   6110 	if (count == 0)
   6111 		goto unlock;
   6112 
   6113 	/*
   6114 	 * mastersok must contain count elements
   6115 	 */
   6116 	newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
   6117 	if (newok == NULL) {
   6118 		result = ISC_R_NOMEMORY;
   6119 		isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
   6120 		goto unlock;
   6121 	};
   6122 	for (i = 0; i < count; i++)
   6123 		newok[i] = false;
   6124 
   6125 	/*
   6126 	 * Now set up the masters and masterkey lists
   6127 	 */
   6128 	result = set_addrkeylist(count, masters, &newaddrs, NULL, &newdscps,
   6129 				 keynames, &newnames, zone->mctx);
   6130 	INSIST(newdscps == NULL);
   6131 	if (result != ISC_R_SUCCESS) {
   6132 		isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
   6133 		goto unlock;
   6134 	}
   6135 
   6136 	/*
   6137 	 * Everything is ok so attach to the zone.
   6138 	 */
   6139 	zone->curmaster = 0;
   6140 	zone->mastersok = newok;
   6141 	zone->masters = newaddrs;
   6142 	zone->masterdscps = newdscps;
   6143 	zone->masterkeynames = newnames;
   6144 	zone->masterscnt = count;
   6145 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
   6146 
   6147  unlock:
   6148 	UNLOCK_ZONE(zone);
   6149 	return (result);
   6150 }
   6151 
   6152 isc_result_t
   6153 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
   6154 	isc_result_t result = ISC_R_SUCCESS;
   6155 
   6156 	REQUIRE(DNS_ZONE_VALID(zone));
   6157 
   6158 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   6159 	if (zone->db == NULL)
   6160 		result = DNS_R_NOTLOADED;
   6161 	else
   6162 		dns_db_attach(zone->db, dpb);
   6163 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   6164 
   6165 	return (result);
   6166 }
   6167 
   6168 void
   6169 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
   6170 	REQUIRE(DNS_ZONE_VALID(zone));
   6171 	REQUIRE(zone->type == dns_zone_staticstub);
   6172 
   6173 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   6174 	REQUIRE(zone->db == NULL);
   6175 	dns_db_attach(db, &zone->db);
   6176 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   6177 }
   6178 
   6179 /*
   6180  * Co-ordinates the starting of routine jobs.
   6181  */
   6182 void
   6183 dns_zone_maintenance(dns_zone_t *zone) {
   6184 	const char me[] = "dns_zone_maintenance";
   6185 	isc_time_t now;
   6186 
   6187 	REQUIRE(DNS_ZONE_VALID(zone));
   6188 	ENTER;
   6189 
   6190 	LOCK_ZONE(zone);
   6191 	TIME_NOW(&now);
   6192 	zone_settimer(zone, &now);
   6193 	UNLOCK_ZONE(zone);
   6194 }
   6195 
   6196 static inline bool
   6197 was_dumping(dns_zone_t *zone) {
   6198 
   6199 	REQUIRE(LOCKED_ZONE(zone));
   6200 
   6201 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   6202 		return (true);
   6203 	}
   6204 
   6205 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
   6206 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   6207 	isc_time_settoepoch(&zone->dumptime);
   6208 	return (false);
   6209 }
   6210 
   6211 /*%
   6212  * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
   6213  * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
   6214  * Only load the public part of a given key if it is not active at timestamp
   6215  * 'now'.  Store the number of keys found in 'nkeys'.
   6216  */
   6217 isc_result_t
   6218 dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   6219 		   isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
   6220 		   dst_key_t **keys, unsigned int *nkeys)
   6221 {
   6222 	isc_result_t result;
   6223 	dns_dbnode_t *node = NULL;
   6224 	const char *directory = dns_zone_getkeydirectory(zone);
   6225 
   6226 	CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
   6227 	memset(keys, 0, sizeof(*keys) * maxkeys);
   6228 	result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
   6229 					 directory, now, mctx, maxkeys, keys,
   6230 					 nkeys);
   6231 	if (result == ISC_R_NOTFOUND)
   6232 		result = ISC_R_SUCCESS;
   6233  failure:
   6234 	if (node != NULL)
   6235 		dns_db_detachnode(db, &node);
   6236 	return (result);
   6237 }
   6238 
   6239 static isc_result_t
   6240 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
   6241 	dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
   6242 {
   6243 	isc_result_t result;
   6244 
   6245 	if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
   6246 		return (ISC_R_SUCCESS);
   6247 	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
   6248 			       name, ttl, rdata);
   6249 	if (result != ISC_R_SUCCESS)
   6250 		return (result);
   6251 	rdata->flags |= DNS_RDATA_OFFLINE;
   6252 	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
   6253 			       name, ttl, rdata);
   6254 	zonediff->offline = true;
   6255 	return (result);
   6256 }
   6257 
   6258 static void
   6259 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
   6260 {
   6261 	unsigned int delta;
   6262 	char timebuf[80];
   6263 
   6264 	zone->key_expiry = when;
   6265 	if (when <= now) {
   6266 		dns_zone_log(zone, ISC_LOG_ERROR,
   6267 			     "DNSKEY RRSIG(s) have expired");
   6268 		isc_time_settoepoch(&zone->keywarntime);
   6269 	} else if (when < now + 7 * 24 * 3600) {
   6270 		isc_time_t t;
   6271 		isc_time_set(&t, when, 0);
   6272 		isc_time_formattimestamp(&t, timebuf, 80);
   6273 		dns_zone_log(zone, ISC_LOG_WARNING,
   6274 			     "DNSKEY RRSIG(s) will expire within 7 days: %s",
   6275 			     timebuf);
   6276 		delta = when - now;
   6277 		delta--;		/* loop prevention */
   6278 		delta /= 24 * 3600;	/* to whole days */
   6279 		delta *= 24 * 3600;	/* to seconds */
   6280 		isc_time_set(&zone->keywarntime, when - delta, 0);
   6281 	}  else {
   6282 		isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
   6283 		isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
   6284 		dns_zone_log(zone, ISC_LOG_NOTICE,
   6285 			     "setting keywarntime to %s", timebuf);
   6286 	}
   6287 }
   6288 
   6289 /*
   6290  * Helper function to del_sigs(). We don't want to delete RRSIGs that
   6291  * have no new key.
   6292  */
   6293 static bool
   6294 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
   6295 	  bool *warn)
   6296 {
   6297 	unsigned int i = 0;
   6298 	bool have_ksk = false, have_zsk = false;
   6299 	bool have_pksk = false, have_pzsk = false;
   6300 
   6301 	for (i = 0; i < nkeys; i++) {
   6302 		if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
   6303 			continue;
   6304 		if (dst_key_isprivate(keys[i])) {
   6305 			if (KSK(keys[i]))
   6306 				have_ksk = have_pksk = true;
   6307 			else
   6308 				have_zsk = have_pzsk = true;
   6309 		} else {
   6310 			if (KSK(keys[i]))
   6311 				have_ksk = true;
   6312 			else
   6313 				have_zsk = true;
   6314 		}
   6315 	}
   6316 
   6317 	if (have_zsk && have_ksk && !have_pzsk)
   6318 		*warn = true;
   6319 
   6320 	/*
   6321 	 * It's okay to delete a signature if there is an active key
   6322 	 * with the same algorithm to replace it.
   6323 	 */
   6324 	if (have_pksk || have_pzsk)
   6325 		return (true);
   6326 
   6327 	/*
   6328 	 * Failing that, it is *not* okay to delete a signature
   6329 	 * if the associated public key is still in the DNSKEY RRset
   6330 	 */
   6331 	for (i = 0; i < nkeys; i++) {
   6332 		if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
   6333 		    (rrsig_ptr->keyid == dst_key_id(keys[i])))
   6334 			return (false);
   6335 	}
   6336 
   6337 	/*
   6338 	 * But if the key is gone, then go ahead.
   6339 	 */
   6340 	return (true);
   6341 }
   6342 
   6343 /*
   6344  * Delete expired RRsigs and any RRsigs we are about to re-sign.
   6345  * See also update.c:del_keysigs().
   6346  */
   6347 static isc_result_t
   6348 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
   6349 	 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
   6350 	 unsigned int nkeys, isc_stdtime_t now, bool incremental)
   6351 {
   6352 	isc_result_t result;
   6353 	dns_dbnode_t *node = NULL;
   6354 	dns_rdataset_t rdataset;
   6355 	unsigned int i;
   6356 	dns_rdata_rrsig_t rrsig;
   6357 	bool found;
   6358 	int64_t timewarn = 0, timemaybe = 0;
   6359 
   6360 	dns_rdataset_init(&rdataset);
   6361 
   6362 	if (type == dns_rdatatype_nsec3)
   6363 		result = dns_db_findnsec3node(db, name, false, &node);
   6364 	else
   6365 		result = dns_db_findnode(db, name, false, &node);
   6366 	if (result == ISC_R_NOTFOUND)
   6367 		return (ISC_R_SUCCESS);
   6368 	if (result != ISC_R_SUCCESS)
   6369 		goto failure;
   6370 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
   6371 				     (isc_stdtime_t) 0, &rdataset, NULL);
   6372 	dns_db_detachnode(db, &node);
   6373 
   6374 	if (result == ISC_R_NOTFOUND) {
   6375 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6376 		return (ISC_R_SUCCESS);
   6377 	}
   6378 	if (result != ISC_R_SUCCESS) {
   6379 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6380 		goto failure;
   6381 	}
   6382 
   6383 	for (result = dns_rdataset_first(&rdataset);
   6384 	     result == ISC_R_SUCCESS;
   6385 	     result = dns_rdataset_next(&rdataset)) {
   6386 		dns_rdata_t rdata = DNS_RDATA_INIT;
   6387 
   6388 		dns_rdataset_current(&rdataset, &rdata);
   6389 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   6390 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   6391 
   6392 		if (type != dns_rdatatype_dnskey) {
   6393 			bool warn = false, deleted = false;
   6394 			if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
   6395 				result = update_one_rr(db, ver, zonediff->diff,
   6396 					       DNS_DIFFOP_DELRESIGN, name,
   6397 					       rdataset.ttl, &rdata);
   6398 				if (result != ISC_R_SUCCESS)
   6399 					break;
   6400 				deleted = true;
   6401 			}
   6402 			if (warn) {
   6403 				/*
   6404 				 * At this point, we've got an RRSIG,
   6405 				 * which is signed by an inactive key.
   6406 				 * An administrator needs to provide a new
   6407 				 * key/alg, but until that time, we want to
   6408 				 * keep the old RRSIG.  Marking the key as
   6409 				 * offline will prevent us spinning waiting
   6410 				 * for the private part.
   6411 				 */
   6412 				if (incremental && !deleted) {
   6413 					result = offline(db, ver, zonediff,
   6414 							 name, rdataset.ttl,
   6415 							 &rdata);
   6416 					if (result != ISC_R_SUCCESS)
   6417 						break;
   6418 				}
   6419 
   6420 				/*
   6421 				 * Log the key id and algorithm of
   6422 				 * the inactive key with no replacement
   6423 				 */
   6424 				if (zone->log_key_expired_timer <= now) {
   6425 					char origin[DNS_NAME_FORMATSIZE];
   6426 					char algbuf[DNS_NAME_FORMATSIZE];
   6427 					dns_name_format(&zone->origin, origin,
   6428 							sizeof(origin));
   6429 					dns_secalg_format(rrsig.algorithm,
   6430 							  algbuf,
   6431 							  sizeof(algbuf));
   6432 					dns_zone_log(zone, ISC_LOG_WARNING,
   6433 						     "Key %s/%s/%d "
   6434 						     "missing or inactive "
   6435 						     "and has no replacement: "
   6436 						     "retaining signatures.",
   6437 						     origin, algbuf,
   6438 						     rrsig.keyid);
   6439 					zone->log_key_expired_timer = now +
   6440 									3600;
   6441 				}
   6442 			}
   6443 			continue;
   6444 		}
   6445 
   6446 		/*
   6447 		 * RRSIG(DNSKEY) requires special processing.
   6448 		 */
   6449 		found = false;
   6450 		for (i = 0; i < nkeys; i++) {
   6451 			if (rrsig.algorithm == dst_key_alg(keys[i]) &&
   6452 			    rrsig.keyid == dst_key_id(keys[i])) {
   6453 				found = true;
   6454 				/*
   6455 				 * Mark offline RRSIG(DNSKEY).
   6456 				 * We want the earliest offline expire time
   6457 				 * iff there is a new offline signature.
   6458 				 */
   6459 				if (!dst_key_inactive(keys[i]) &&
   6460 				    !dst_key_isprivate(keys[i]))
   6461 				{
   6462 					int64_t timeexpire =
   6463 					   dns_time64_from32(rrsig.timeexpire);
   6464 					if (timewarn != 0 &&
   6465 					    timewarn > timeexpire)
   6466 						timewarn = timeexpire;
   6467 					if (rdata.flags & DNS_RDATA_OFFLINE) {
   6468 						if (timemaybe == 0 ||
   6469 						    timemaybe > timeexpire)
   6470 							timemaybe = timeexpire;
   6471 						break;
   6472 					}
   6473 					if (timewarn == 0)
   6474 						timewarn = timemaybe;
   6475 					if (timewarn == 0 ||
   6476 					    timewarn > timeexpire)
   6477 						timewarn = timeexpire;
   6478 					result = offline(db, ver, zonediff,
   6479 							 name, rdataset.ttl,
   6480 							 &rdata);
   6481 					break;
   6482 				}
   6483 				result = update_one_rr(db, ver, zonediff->diff,
   6484 						       DNS_DIFFOP_DELRESIGN,
   6485 						       name, rdataset.ttl,
   6486 						       &rdata);
   6487 				break;
   6488 			}
   6489 		}
   6490 
   6491 		/*
   6492 		 * If there is not a matching DNSKEY then
   6493 		 * delete the RRSIG.
   6494 		 */
   6495 		if (!found) {
   6496 			result = update_one_rr(db, ver, zonediff->diff,
   6497 					       DNS_DIFFOP_DELRESIGN, name,
   6498 					       rdataset.ttl, &rdata);
   6499 		}
   6500 		if (result != ISC_R_SUCCESS)
   6501 			break;
   6502 	}
   6503 
   6504 	dns_rdataset_disassociate(&rdataset);
   6505 	if (result == ISC_R_NOMORE)
   6506 		result = ISC_R_SUCCESS;
   6507 	if (timewarn > 0) {
   6508 		isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
   6509 		if (timewarn == stdwarn) {
   6510 			set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
   6511 					       now);
   6512 		} else {
   6513 			dns_zone_log(zone, ISC_LOG_ERROR,
   6514 				     "key expiry warning time out of range");
   6515 		}
   6516 	}
   6517  failure:
   6518 	if (node != NULL)
   6519 		dns_db_detachnode(db, &node);
   6520 	return (result);
   6521 }
   6522 
   6523 static isc_result_t
   6524 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
   6525 	 dns_zone_t* zone, dns_rdatatype_t type, dns_diff_t *diff,
   6526 	 dst_key_t **keys, unsigned int nkeys, isc_mem_t *mctx,
   6527 	 isc_stdtime_t inception, isc_stdtime_t expire,
   6528 	 bool check_ksk, bool keyset_kskonly)
   6529 {
   6530 	isc_result_t result;
   6531 	dns_dbnode_t *node = NULL;
   6532 	dns_stats_t* dnssecsignstats;
   6533 	dns_stats_t* dnssecrefreshstats;
   6534 	dns_rdataset_t rdataset;
   6535 	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
   6536 	unsigned char data[1024]; /* XXX */
   6537 	isc_buffer_t buffer;
   6538 	unsigned int i, j;
   6539 
   6540 	dns_rdataset_init(&rdataset);
   6541 	isc_buffer_init(&buffer, data, sizeof(data));
   6542 
   6543 	if (type == dns_rdatatype_nsec3)
   6544 		result = dns_db_findnsec3node(db, name, false, &node);
   6545 	else
   6546 		result = dns_db_findnode(db, name, false, &node);
   6547 	if (result == ISC_R_NOTFOUND)
   6548 		return (ISC_R_SUCCESS);
   6549 	if (result != ISC_R_SUCCESS)
   6550 		goto failure;
   6551 	result = dns_db_findrdataset(db, node, ver, type, 0,
   6552 				     (isc_stdtime_t) 0, &rdataset, NULL);
   6553 	dns_db_detachnode(db, &node);
   6554 	if (result == ISC_R_NOTFOUND) {
   6555 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6556 		return (ISC_R_SUCCESS);
   6557 	}
   6558 	if (result != ISC_R_SUCCESS) {
   6559 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6560 		goto failure;
   6561 	}
   6562 
   6563 	for (i = 0; i < nkeys; i++) {
   6564 		bool both = false;
   6565 
   6566 		/* Don't add signatures for offline or inactive keys */
   6567 		if (!dst_key_isprivate(keys[i])) {
   6568 			continue;
   6569 		}
   6570 		if (dst_key_inactive(keys[i])) {
   6571 			continue;
   6572 		}
   6573 
   6574 		if (check_ksk && !REVOKE(keys[i])) {
   6575 			bool have_ksk, have_nonksk;
   6576 			if (KSK(keys[i])) {
   6577 				have_ksk = true;
   6578 				have_nonksk = false;
   6579 			} else {
   6580 				have_ksk = false;
   6581 				have_nonksk = true;
   6582 			}
   6583 
   6584 			for (j = 0; j < nkeys; j++) {
   6585 				if (j == i || ALG(keys[i]) != ALG(keys[j])) {
   6586 					continue;
   6587 				}
   6588 
   6589 				/* Don't consider inactive keys, however
   6590 				 * the key may be temporary offline, so do
   6591 				 * consider keys which private key files are
   6592 				 * unavailable.
   6593 				 */
   6594 				if (dst_key_inactive(keys[j])) {
   6595 					continue;
   6596 				}
   6597 
   6598 				if (REVOKE(keys[j])) {
   6599 					continue;
   6600 				}
   6601 				if (KSK(keys[j])) {
   6602 					have_ksk = true;
   6603 				} else {
   6604 					have_nonksk = true;
   6605 				}
   6606 				both = have_ksk && have_nonksk;
   6607 				if (both) {
   6608 					break;
   6609 				}
   6610 			}
   6611 		}
   6612 
   6613 		if (both) {
   6614 			/*
   6615 			 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
   6616 			 */
   6617 			if (type == dns_rdatatype_dnskey ||
   6618 			    type == dns_rdatatype_cdnskey ||
   6619 			    type == dns_rdatatype_cds)
   6620 			{
   6621 				if (!KSK(keys[i]) && keyset_kskonly)
   6622 					continue;
   6623 			} else if (KSK(keys[i])) {
   6624 				continue;
   6625 			}
   6626 		} else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
   6627 			continue;
   6628 		}
   6629 
   6630 		/* Calculate the signature, creating a RRSIG RDATA. */
   6631 		isc_buffer_clear(&buffer);
   6632 		CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
   6633 				      &inception, &expire,
   6634 				      mctx, &buffer, &sig_rdata));
   6635 
   6636 		/* Update the database and journal with the RRSIG. */
   6637 		/* XXX inefficient - will cause dataset merging */
   6638 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
   6639 				    name, rdataset.ttl, &sig_rdata));
   6640 		dns_rdata_reset(&sig_rdata);
   6641 		isc_buffer_init(&buffer, data, sizeof(data));
   6642 
   6643 		/* Update DNSSEC sign statistics. */
   6644 		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
   6645 		dnssecrefreshstats = dns_zone_getdnssecrefreshstats(zone);
   6646 		if (dnssecsignstats != NULL) {
   6647 			dns_dnssecsignstats_increment(
   6648 				dns_zone_getdnssecsignstats(zone),
   6649 				dst_key_id(keys[i]));
   6650 		}
   6651 		if (dnssecrefreshstats != NULL) {
   6652 			dns_dnssecsignstats_increment(
   6653 				dns_zone_getdnssecrefreshstats(zone),
   6654 				dst_key_id(keys[i]));
   6655 		}
   6656 	}
   6657 
   6658  failure:
   6659 	if (dns_rdataset_isassociated(&rdataset))
   6660 		dns_rdataset_disassociate(&rdataset);
   6661 	if (node != NULL)
   6662 		dns_db_detachnode(db, &node);
   6663 	return (result);
   6664 }
   6665 
   6666 static void
   6667 zone_resigninc(dns_zone_t *zone) {
   6668 	const char *me = "zone_resigninc";
   6669 	dns_db_t *db = NULL;
   6670 	dns_dbversion_t *version = NULL;
   6671 	dns_diff_t _sig_diff;
   6672 	dns__zonediff_t zonediff;
   6673 	dns_fixedname_t fixed;
   6674 	dns_name_t *name;
   6675 	dns_rdataset_t rdataset;
   6676 	dns_rdatatype_t covers;
   6677 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   6678 	bool check_ksk, keyset_kskonly = false;
   6679 	isc_result_t result;
   6680 	isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
   6681 	uint32_t sigvalidityinterval, expiryinterval;
   6682 	unsigned int i;
   6683 	unsigned int nkeys = 0;
   6684 	unsigned int resign;
   6685 
   6686 	ENTER;
   6687 
   6688 	dns_rdataset_init(&rdataset);
   6689 	dns_diff_init(zone->mctx, &_sig_diff);
   6690 	zonediff_init(&zonediff, &_sig_diff);
   6691 
   6692 	/*
   6693 	 * Zone is frozen or automatic resigning is disabled.
   6694 	 * Pause for 5 minutes.
   6695 	 */
   6696 	if (zone->update_disabled ||
   6697 	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
   6698 	{
   6699 		result = ISC_R_FAILURE;
   6700 		goto failure;
   6701 	}
   6702 
   6703 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   6704 	dns_db_attach(zone->db, &db);
   6705 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   6706 
   6707 	result = dns_db_newversion(db, &version);
   6708 	if (result != ISC_R_SUCCESS) {
   6709 		dns_zone_log(zone, ISC_LOG_ERROR,
   6710 			     "zone_resigninc:dns_db_newversion -> %s",
   6711 			     dns_result_totext(result));
   6712 		goto failure;
   6713 	}
   6714 
   6715 	isc_stdtime_get(&now);
   6716 
   6717 	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
   6718 				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
   6719 	if (result != ISC_R_SUCCESS) {
   6720 		dns_zone_log(zone, ISC_LOG_ERROR,
   6721 			     "zone_resigninc:dns__zone_findkeys -> %s",
   6722 			     dns_result_totext(result));
   6723 		goto failure;
   6724 	}
   6725 
   6726 	sigvalidityinterval = zone->sigvalidityinterval;
   6727 	inception = now - 3600;	/* Allow for clock skew. */
   6728 	soaexpire = now + sigvalidityinterval;
   6729 	expiryinterval = dns_zone_getsigresigninginterval(zone);
   6730 	if (expiryinterval > sigvalidityinterval) {
   6731 		expiryinterval = sigvalidityinterval;
   6732 	} else {
   6733 		expiryinterval = sigvalidityinterval - expiryinterval;
   6734 	}
   6735 
   6736 	/*
   6737 	 * Spread out signatures over time if they happen to be
   6738 	 * clumped.  We don't do this for each add_sigs() call as
   6739 	 * we still want some clustering to occur.  In normal operations
   6740 	 * the records should be re-signed as they fall due and they should
   6741 	 * already be spread out.  However if the server is off for a
   6742 	 * period we need to ensure that the clusters don't become
   6743 	 * synchronised by using the full jitter range.
   6744 	 */
   6745 	if (sigvalidityinterval >= 3600U) {
   6746 		uint32_t normaljitter, fulljitter;
   6747 		if (sigvalidityinterval > 7200U) {
   6748 			normaljitter = isc_random_uniform(3600);
   6749 			fulljitter = isc_random_uniform(expiryinterval);
   6750 		} else {
   6751 			normaljitter = fulljitter = isc_random_uniform(1200);
   6752 		}
   6753 		expire = soaexpire - normaljitter - 1;
   6754 		fullexpire = soaexpire - fulljitter - 1;
   6755 	} else {
   6756 		expire = fullexpire = soaexpire - 1;
   6757 	}
   6758 	stop = now + 5;
   6759 
   6760 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
   6761 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
   6762 
   6763 	name = dns_fixedname_initname(&fixed);
   6764 	result = dns_db_getsigningtime(db, &rdataset, name);
   6765 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   6766 		dns_zone_log(zone, ISC_LOG_ERROR,
   6767 			     "zone_resigninc:dns_db_getsigningtime -> %s",
   6768 			     dns_result_totext(result));
   6769 	}
   6770 
   6771 	i = 0;
   6772 	while (result == ISC_R_SUCCESS) {
   6773 		resign = rdataset.resign - zone->sigresigninginterval;
   6774 		covers = rdataset.covers;
   6775 		dns_rdataset_disassociate(&rdataset);
   6776 
   6777 		/*
   6778 		 * Stop if we hit the SOA as that means we have walked the
   6779 		 * entire zone.  The SOA record should always be the most
   6780 		 * recent signature.
   6781 		 */
   6782 		/* XXXMPA increase number of RRsets signed pre call */
   6783 		if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
   6784 		    resign > stop)
   6785 			break;
   6786 
   6787 		result = del_sigs(zone, db, version, name, covers, &zonediff,
   6788 				  zone_keys, nkeys, now, true);
   6789 		if (result != ISC_R_SUCCESS) {
   6790 			dns_zone_log(zone, ISC_LOG_ERROR,
   6791 				     "zone_resigninc:del_sigs -> %s",
   6792 				     dns_result_totext(result));
   6793 			break;
   6794 		}
   6795 
   6796 		/*
   6797 		 * If re-signing is over 5 minutes late use 'fullexpire'
   6798 		 * to redistribute the signature over the complete
   6799 		 * re-signing window, otherwise only add a small amount
   6800 		 * of jitter.
   6801 		 */
   6802 		result = add_sigs(db, version, name, zone, covers,
   6803 				  zonediff.diff, zone_keys, nkeys, zone->mctx,
   6804 				  inception,
   6805 				  resign > (now - 300) ? expire : fullexpire,
   6806 				  check_ksk, keyset_kskonly);
   6807 		if (result != ISC_R_SUCCESS) {
   6808 			dns_zone_log(zone, ISC_LOG_ERROR,
   6809 				     "zone_resigninc:add_sigs -> %s",
   6810 				     dns_result_totext(result));
   6811 			break;
   6812 		}
   6813 		result	= dns_db_getsigningtime(db, &rdataset, name);
   6814 		if (nkeys == 0 && result == ISC_R_NOTFOUND) {
   6815 			result = ISC_R_SUCCESS;
   6816 			break;
   6817 		}
   6818 		if (result != ISC_R_SUCCESS)
   6819 			dns_zone_log(zone, ISC_LOG_ERROR,
   6820 			     "zone_resigninc:dns_db_getsigningtime -> %s",
   6821 				     dns_result_totext(result));
   6822 	}
   6823 
   6824 	if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
   6825 		goto failure;
   6826 
   6827 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
   6828 			  &zonediff, zone_keys, nkeys, now, true);
   6829 	if (result != ISC_R_SUCCESS) {
   6830 		dns_zone_log(zone, ISC_LOG_ERROR,
   6831 			     "zone_resigninc:del_sigs -> %s",
   6832 			     dns_result_totext(result));
   6833 		goto failure;
   6834 	}
   6835 
   6836 	/*
   6837 	 * Did we change anything in the zone?
   6838 	 */
   6839 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
   6840 		/*
   6841 		 * Commit the changes if any key has been marked as offline.
   6842 		 */
   6843 		if (zonediff.offline)
   6844 			dns_db_closeversion(db, &version, true);
   6845 		goto failure;
   6846 	}
   6847 
   6848 	/* Increment SOA serial if we have made changes */
   6849 	result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
   6850 				   zone->updatemethod);
   6851 	if (result != ISC_R_SUCCESS) {
   6852 		dns_zone_log(zone, ISC_LOG_ERROR,
   6853 			     "zone_resigninc:update_soa_serial -> %s",
   6854 			     dns_result_totext(result));
   6855 		goto failure;
   6856 	}
   6857 
   6858 	/*
   6859 	 * Generate maximum life time signatures so that the above loop
   6860 	 * termination is sensible.
   6861 	 */
   6862 	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
   6863 			  zonediff.diff, zone_keys, nkeys, zone->mctx,
   6864 			  inception, soaexpire, check_ksk, keyset_kskonly);
   6865 	if (result != ISC_R_SUCCESS) {
   6866 		dns_zone_log(zone, ISC_LOG_ERROR,
   6867 			     "zone_resigninc:add_sigs -> %s",
   6868 			     dns_result_totext(result));
   6869 		goto failure;
   6870 	}
   6871 
   6872 	/* Write changes to journal file. */
   6873 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
   6874 
   6875 	/* Everything has succeeded. Commit the changes. */
   6876 	dns_db_closeversion(db, &version, true);
   6877 
   6878  failure:
   6879 	dns_diff_clear(&_sig_diff);
   6880 	for (i = 0; i < nkeys; i++)
   6881 		dst_key_free(&zone_keys[i]);
   6882 	if (version != NULL) {
   6883 		dns_db_closeversion(db, &version, false);
   6884 		dns_db_detach(&db);
   6885 	} else if (db != NULL)
   6886 		dns_db_detach(&db);
   6887 	if (result == ISC_R_SUCCESS) {
   6888 		set_resigntime(zone);
   6889 		LOCK_ZONE(zone);
   6890 		zone_needdump(zone, DNS_DUMP_DELAY);
   6891 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   6892 		UNLOCK_ZONE(zone);
   6893 	} else {
   6894 		/*
   6895 		 * Something failed.  Retry in 5 minutes.
   6896 		 */
   6897 		isc_interval_t ival;
   6898 		isc_interval_set(&ival, 300, 0);
   6899 		isc_time_nowplusinterval(&zone->resigntime, &ival);
   6900 	}
   6901 
   6902 	INSIST(version == NULL);
   6903 }
   6904 
   6905 static isc_result_t
   6906 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
   6907 	    dns_name_t *newname, bool bottom)
   6908 {
   6909 	isc_result_t result;
   6910 	dns_dbiterator_t *dbit = NULL;
   6911 	dns_rdatasetiter_t *rdsit = NULL;
   6912 	dns_dbnode_t *node = NULL;
   6913 
   6914 	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
   6915 	CHECK(dns_dbiterator_seek(dbit, oldname));
   6916 	do {
   6917 		result = dns_dbiterator_next(dbit);
   6918 		if (result == ISC_R_NOMORE)
   6919 			CHECK(dns_dbiterator_first(dbit));
   6920 		CHECK(dns_dbiterator_current(dbit, &node, newname));
   6921 		if (bottom && dns_name_issubdomain(newname, oldname) &&
   6922 		    !dns_name_equal(newname, oldname)) {
   6923 			dns_db_detachnode(db, &node);
   6924 			continue;
   6925 		}
   6926 		/*
   6927 		 * Is this node empty?
   6928 		 */
   6929 		CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
   6930 		result = dns_rdatasetiter_first(rdsit);
   6931 		dns_db_detachnode(db, &node);
   6932 		dns_rdatasetiter_destroy(&rdsit);
   6933 		if (result != ISC_R_NOMORE)
   6934 			break;
   6935 	} while (1);
   6936  failure:
   6937 	if (node != NULL)
   6938 		dns_db_detachnode(db, &node);
   6939 	if (dbit != NULL)
   6940 		dns_dbiterator_destroy(&dbit);
   6941 	return (result);
   6942 }
   6943 
   6944 static bool
   6945 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   6946 		dns_rdatatype_t type, dst_key_t *key)
   6947 {
   6948 	isc_result_t result;
   6949 	dns_rdataset_t rdataset;
   6950 	dns_rdata_t rdata = DNS_RDATA_INIT;
   6951 	dns_rdata_rrsig_t rrsig;
   6952 
   6953 	dns_rdataset_init(&rdataset);
   6954 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
   6955 				     type, 0, &rdataset, NULL);
   6956 	if (result != ISC_R_SUCCESS) {
   6957 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6958 		return (false);
   6959 	}
   6960 	for (result = dns_rdataset_first(&rdataset);
   6961 	     result == ISC_R_SUCCESS;
   6962 	     result = dns_rdataset_next(&rdataset)) {
   6963 		dns_rdataset_current(&rdataset, &rdata);
   6964 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   6965 		INSIST(result == ISC_R_SUCCESS);
   6966 		if (rrsig.algorithm == dst_key_alg(key) &&
   6967 		    rrsig.keyid == dst_key_id(key)) {
   6968 			dns_rdataset_disassociate(&rdataset);
   6969 			return (true);
   6970 		}
   6971 		dns_rdata_reset(&rdata);
   6972 	}
   6973 	dns_rdataset_disassociate(&rdataset);
   6974 	return (false);
   6975 }
   6976 
   6977 static isc_result_t
   6978 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
   6979 	 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom,
   6980 	 dns_diff_t *diff)
   6981 {
   6982 	dns_fixedname_t fixed;
   6983 	dns_name_t *next;
   6984 	dns_rdata_t rdata = DNS_RDATA_INIT;
   6985 	isc_result_t result;
   6986 	unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
   6987 
   6988 	next = dns_fixedname_initname(&fixed);
   6989 
   6990 	CHECK(next_active(db, version, name, next, bottom));
   6991 	CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
   6992 				  &rdata));
   6993 	CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
   6994 			    &rdata));
   6995  failure:
   6996 	return (result);
   6997 }
   6998 
   6999 static isc_result_t
   7000 check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
   7001 			dns_dbversion_t *version, bool *is_bottom_of_zone)
   7002 {
   7003 	isc_result_t result;
   7004 	dns_rdatasetiter_t *iterator = NULL;
   7005 	dns_rdataset_t rdataset;
   7006 	bool seen_soa = false, seen_ns = false, seen_dname = false;
   7007 
   7008 	REQUIRE(is_bottom_of_zone != NULL);
   7009 
   7010 	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
   7011 	if (result != ISC_R_SUCCESS) {
   7012 		if (result == ISC_R_NOTFOUND) {
   7013 			result = ISC_R_SUCCESS;
   7014 		}
   7015 		return (result);
   7016 	}
   7017 
   7018 	dns_rdataset_init(&rdataset);
   7019 	for (result = dns_rdatasetiter_first(iterator);
   7020 	     result == ISC_R_SUCCESS;
   7021 	     result = dns_rdatasetiter_next(iterator)) {
   7022 		dns_rdatasetiter_current(iterator, &rdataset);
   7023 		switch (rdataset.type) {
   7024 		case dns_rdatatype_soa:
   7025 			seen_soa = true;
   7026 			break;
   7027 		case dns_rdatatype_ns:
   7028 			seen_ns = true;
   7029 			break;
   7030 		case dns_rdatatype_dname:
   7031 			seen_dname = true;
   7032 			break;
   7033 		}
   7034 		dns_rdataset_disassociate(&rdataset);
   7035 	}
   7036 	if (result != ISC_R_NOMORE) {
   7037 		goto failure;
   7038 	}
   7039 	if ((seen_ns && !seen_soa) || seen_dname) {
   7040 		*is_bottom_of_zone = true;
   7041 	}
   7042 	result = ISC_R_SUCCESS;
   7043 
   7044  failure:
   7045 	dns_rdatasetiter_destroy(&iterator);
   7046 
   7047 	return (result);
   7048 }
   7049 
   7050 static isc_result_t
   7051 sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
   7052 	    dns_dbnode_t *node, dns_dbversion_t *version,
   7053 	    bool build_nsec3, bool build_nsec, dst_key_t *key,
   7054 	    isc_stdtime_t inception, isc_stdtime_t expire,
   7055 	    unsigned int minimum, bool is_ksk,
   7056 	    bool keyset_kskonly, bool is_bottom_of_zone,
   7057 	    dns_diff_t *diff, int32_t *signatures, isc_mem_t *mctx)
   7058 {
   7059 	isc_result_t result;
   7060 	dns_rdatasetiter_t *iterator = NULL;
   7061 	dns_rdataset_t rdataset;
   7062 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7063 	dns_stats_t* dnssecsignstats;
   7064 	dns_stats_t* dnssecrefreshstats;
   7065 
   7066 	isc_buffer_t buffer;
   7067 	unsigned char data[1024];
   7068 	bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds;
   7069 
   7070 	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
   7071 	if (result != ISC_R_SUCCESS) {
   7072 		if (result == ISC_R_NOTFOUND)
   7073 			result = ISC_R_SUCCESS;
   7074 		return (result);
   7075 	}
   7076 
   7077 	dns_rdataset_init(&rdataset);
   7078 	isc_buffer_init(&buffer, data, sizeof(data));
   7079 	seen_rr = seen_soa = seen_ns = seen_nsec = seen_nsec3 = seen_ds = false;
   7080 	for (result = dns_rdatasetiter_first(iterator);
   7081 	     result == ISC_R_SUCCESS;
   7082 	     result = dns_rdatasetiter_next(iterator)) {
   7083 		dns_rdatasetiter_current(iterator, &rdataset);
   7084 		if (rdataset.type == dns_rdatatype_soa)
   7085 			seen_soa = true;
   7086 		else if (rdataset.type == dns_rdatatype_ns)
   7087 			seen_ns = true;
   7088 		else if (rdataset.type == dns_rdatatype_ds)
   7089 			seen_ds = true;
   7090 		else if (rdataset.type == dns_rdatatype_nsec)
   7091 			seen_nsec = true;
   7092 		else if (rdataset.type == dns_rdatatype_nsec3)
   7093 			seen_nsec3 = true;
   7094 		if (rdataset.type != dns_rdatatype_rrsig)
   7095 			seen_rr = true;
   7096 		dns_rdataset_disassociate(&rdataset);
   7097 	}
   7098 	if (result != ISC_R_NOMORE)
   7099 		goto failure;
   7100 	/*
   7101 	 * Going from insecure to NSEC3.
   7102 	 * Don't generate NSEC3 records for NSEC3 records.
   7103 	 */
   7104 	if (build_nsec3 && !seen_nsec3 && seen_rr) {
   7105 		bool unsecure = !seen_ds && seen_ns && !seen_soa;
   7106 		CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
   7107 					  unsecure, diff));
   7108 		(*signatures)--;
   7109 	}
   7110 	/*
   7111 	 * Going from insecure to NSEC.
   7112 	 * Don't generate NSEC records for NSEC3 records.
   7113 	 */
   7114 	if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
   7115 		/*
   7116 		 * Build a NSEC record except at the origin.
   7117 		 */
   7118 		if (!dns_name_equal(name, dns_db_origin(db))) {
   7119 			CHECK(add_nsec(db, version, name, node, minimum,
   7120 				       is_bottom_of_zone, diff));
   7121 			/* Count a NSEC generation as a signature generation. */
   7122 			(*signatures)--;
   7123 		}
   7124 	}
   7125 	result = dns_rdatasetiter_first(iterator);
   7126 	while (result == ISC_R_SUCCESS) {
   7127 		dns_rdatasetiter_current(iterator, &rdataset);
   7128 		if (rdataset.type == dns_rdatatype_soa ||
   7129 		    rdataset.type == dns_rdatatype_rrsig)
   7130 		{
   7131 			goto next_rdataset;
   7132 		}
   7133 		if (rdataset.type == dns_rdatatype_dnskey ||
   7134 		    rdataset.type == dns_rdatatype_cdnskey ||
   7135 		    rdataset.type == dns_rdatatype_cds)
   7136 		{
   7137 			/*
   7138 			 * CDS and CDNSKEY are signed with KSK like DNSKEY.
   7139 			 * (RFC 7344, section 4.1 specifies that they must
   7140 			 * be signed with a key in the current DS RRset,
   7141 			 * which would only include KSK's.)
   7142 			 */
   7143 			if (!is_ksk && keyset_kskonly) {
   7144 				goto next_rdataset;
   7145 			}
   7146 		} else if (is_ksk) {
   7147 			goto next_rdataset;
   7148 		}
   7149 		if (seen_ns && !seen_soa &&
   7150 		    rdataset.type != dns_rdatatype_ds &&
   7151 		    rdataset.type != dns_rdatatype_nsec)
   7152 		{
   7153 			goto next_rdataset;
   7154 		}
   7155 		if (signed_with_key(db, node, version, rdataset.type, key)) {
   7156 			goto next_rdataset;
   7157 		}
   7158 		/* Calculate the signature, creating a RRSIG RDATA. */
   7159 		isc_buffer_clear(&buffer);
   7160 		CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
   7161 				      &expire, mctx, &buffer, &rdata));
   7162 		/* Update the database and journal with the RRSIG. */
   7163 		/* XXX inefficient - will cause dataset merging */
   7164 		CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
   7165 				    name, rdataset.ttl, &rdata));
   7166 		dns_rdata_reset(&rdata);
   7167 
   7168 		/* Update DNSSEC sign statistics. */
   7169 		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
   7170 		dnssecrefreshstats = dns_zone_getdnssecrefreshstats(zone);
   7171 		if (dnssecsignstats != NULL) {
   7172 			dns_dnssecsignstats_increment(
   7173 				dns_zone_getdnssecsignstats(zone),
   7174 				dst_key_id(key));
   7175 		}
   7176 		if (dnssecrefreshstats != NULL) {
   7177 			dns_dnssecsignstats_increment(
   7178 				dns_zone_getdnssecrefreshstats(zone),
   7179 				dst_key_id(key));
   7180 		}
   7181 
   7182 		(*signatures)--;
   7183  next_rdataset:
   7184 		dns_rdataset_disassociate(&rdataset);
   7185 		result = dns_rdatasetiter_next(iterator);
   7186 	}
   7187 	if (result == ISC_R_NOMORE)
   7188 		result = ISC_R_SUCCESS;
   7189  failure:
   7190 	if (dns_rdataset_isassociated(&rdataset))
   7191 		dns_rdataset_disassociate(&rdataset);
   7192 	if (iterator != NULL)
   7193 		dns_rdatasetiter_destroy(&iterator);
   7194 	return (result);
   7195 }
   7196 
   7197 /*
   7198  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
   7199  */
   7200 static isc_result_t
   7201 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
   7202 	     dns_ttl_t minimum, bool update_only, dns_diff_t *diff)
   7203 {
   7204 	isc_result_t result;
   7205 	dns_rdataset_t rdataset;
   7206 	dns_dbnode_t *node = NULL;
   7207 
   7208 	CHECK(dns_db_getoriginnode(db, &node));
   7209 	if (update_only) {
   7210 		dns_rdataset_init(&rdataset);
   7211 		result = dns_db_findrdataset(db, node, version,
   7212 					     dns_rdatatype_nsec,
   7213 					     dns_rdatatype_none,
   7214 					     0, &rdataset, NULL);
   7215 		if (dns_rdataset_isassociated(&rdataset))
   7216 			dns_rdataset_disassociate(&rdataset);
   7217 		if (result == ISC_R_NOTFOUND)
   7218 			goto success;
   7219 		if (result != ISC_R_SUCCESS)
   7220 			goto failure;
   7221 	}
   7222 	CHECK(delete_nsec(db, version, node, name, diff));
   7223 	CHECK(add_nsec(db, version, name, node, minimum, false, diff));
   7224  success:
   7225 	result = ISC_R_SUCCESS;
   7226  failure:
   7227 	if (node != NULL)
   7228 		dns_db_detachnode(db, &node);
   7229 	return (result);
   7230 }
   7231 
   7232 static isc_result_t
   7233 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
   7234 		  dns_dbversion_t *version, bool build_nsec3,
   7235 		  dns_ttl_t minimum, dns_diff_t *diff)
   7236 {
   7237 	isc_result_t result;
   7238 	dns_dbnode_t *node = NULL;
   7239 	dns_rdataset_t rdataset;
   7240 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7241 	unsigned char data[5];
   7242 	bool seen_done = false;
   7243 	bool have_rr = false;
   7244 
   7245 	dns_rdataset_init(&rdataset);
   7246 	result = dns_db_getoriginnode(signing->db, &node);
   7247 	if (result != ISC_R_SUCCESS)
   7248 		goto failure;
   7249 
   7250 	result = dns_db_findrdataset(signing->db, node, version,
   7251 				     zone->privatetype, dns_rdatatype_none,
   7252 				     0, &rdataset, NULL);
   7253 	if (result == ISC_R_NOTFOUND) {
   7254 		INSIST(!dns_rdataset_isassociated(&rdataset));
   7255 		result = ISC_R_SUCCESS;
   7256 		goto failure;
   7257 	}
   7258 	if (result != ISC_R_SUCCESS) {
   7259 		INSIST(!dns_rdataset_isassociated(&rdataset));
   7260 		goto failure;
   7261 	}
   7262 	for (result = dns_rdataset_first(&rdataset);
   7263 	     result == ISC_R_SUCCESS;
   7264 	     result = dns_rdataset_next(&rdataset)) {
   7265 		dns_rdataset_current(&rdataset, &rdata);
   7266 		/*
   7267 		 * If we don't match the algorithm or keyid skip the record.
   7268 		 */
   7269 		if (rdata.length != 5 ||
   7270 		    rdata.data[0] != signing->algorithm ||
   7271 		    rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
   7272 		    rdata.data[2] != (signing->keyid & 0xff)) {
   7273 			have_rr = true;
   7274 			dns_rdata_reset(&rdata);
   7275 			continue;
   7276 		}
   7277 		/*
   7278 		 * We have a match.  If we were signing (!signing->deleteit)
   7279 		 * and we already have a record indicating that we have
   7280 		 * finished signing (rdata.data[4] != 0) then keep it.
   7281 		 * Otherwise it needs to be deleted as we have removed all
   7282 		 * the signatures (signing->deleteit), so any record indicating
   7283 		 * completion is now out of date, or we have finished signing
   7284 		 * with the new record so we no longer need to remember that
   7285 		 * we need to sign the zone with the matching key across a
   7286 		 * nameserver re-start.
   7287 		 */
   7288 		if (!signing->deleteit && rdata.data[4] != 0) {
   7289 			seen_done = true;
   7290 			have_rr = true;
   7291 		} else
   7292 			CHECK(update_one_rr(signing->db, version, diff,
   7293 					    DNS_DIFFOP_DEL, &zone->origin,
   7294 					    rdataset.ttl, &rdata));
   7295 		dns_rdata_reset(&rdata);
   7296 	}
   7297 	if (result == ISC_R_NOMORE)
   7298 		result = ISC_R_SUCCESS;
   7299 	if (!signing->deleteit && !seen_done) {
   7300 		/*
   7301 		 * If we were signing then we need to indicate that we have
   7302 		 * finished signing the zone with this key.  If it is already
   7303 		 * there we don't need to add it a second time.
   7304 		 */
   7305 		data[0] = signing->algorithm;
   7306 		data[1] = (signing->keyid >> 8) & 0xff;
   7307 		data[2] = signing->keyid & 0xff;
   7308 		data[3] = 0;
   7309 		data[4] = 1;
   7310 		rdata.length = sizeof(data);
   7311 		rdata.data = data;
   7312 		rdata.type = zone->privatetype;
   7313 		rdata.rdclass = dns_db_class(signing->db);
   7314 		CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
   7315 				    &zone->origin, rdataset.ttl, &rdata));
   7316 	} else if (!have_rr) {
   7317 		dns_name_t *origin = dns_db_origin(signing->db);
   7318 		/*
   7319 		 * Rebuild the NSEC/NSEC3 record for the origin as we no
   7320 		 * longer have any private records.
   7321 		 */
   7322 		if (build_nsec3)
   7323 			CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
   7324 						  minimum, false, diff));
   7325 		CHECK(updatesecure(signing->db, version, origin, minimum,
   7326 				   true, diff));
   7327 	}
   7328 
   7329  failure:
   7330 	if (dns_rdataset_isassociated(&rdataset))
   7331 		dns_rdataset_disassociate(&rdataset);
   7332 	if (node != NULL)
   7333 		dns_db_detachnode(signing->db, &node);
   7334 	return (result);
   7335 }
   7336 
   7337 /*
   7338  * Called from zone_nsec3chain() in order to update zone records indicating
   7339  * processing status of given NSEC3 chain:
   7340  *
   7341  *   - If the supplied dns_nsec3chain_t structure has been fully processed
   7342  *     (which is indicated by "active" being set to false):
   7343  *
   7344  *       - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
   7345  *
   7346  *       - remove all private-type records containing NSEC3PARAM RDATA matching
   7347  *         the relevant NSEC3 chain.
   7348  *
   7349  *   - If the supplied dns_nsec3chain_t structure has not been fully processed
   7350  *     (which is indicated by "active" being set to true), only remove the
   7351  *     NSEC3PARAM record which matches the relevant NSEC3 chain and has the
   7352  *     "flags" field set to 0.
   7353  *
   7354  *   - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
   7355  *     in the relevant private-type record, but with the "flags" field set to
   7356  *     0, indicating that this NSEC3 chain is now complete for this zone.
   7357  *
   7358  * Note that this function is called at different processing stages for NSEC3
   7359  * chain additions vs. removals and needs to handle all cases properly.
   7360  */
   7361 static isc_result_t
   7362 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
   7363 		 bool active, dns_rdatatype_t privatetype,
   7364 		 dns_diff_t *diff)
   7365 {
   7366 	dns_dbnode_t *node = NULL;
   7367 	dns_name_t *name = dns_db_origin(db);
   7368 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7369 	dns_rdataset_t rdataset;
   7370 	dns_rdata_nsec3param_t nsec3param;
   7371 	isc_result_t result;
   7372 	isc_buffer_t buffer;
   7373 	unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
   7374 	dns_ttl_t ttl = 0;
   7375 	bool nseconly = false, nsec3ok = false;
   7376 
   7377 	dns_rdataset_init(&rdataset);
   7378 
   7379 	result = dns_db_getoriginnode(db, &node);
   7380 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   7381 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
   7382 				     0, 0, &rdataset, NULL);
   7383 	if (result == ISC_R_NOTFOUND)
   7384 		goto try_private;
   7385 	if (result != ISC_R_SUCCESS)
   7386 		goto failure;
   7387 
   7388 	/*
   7389 	 * Preserve the existing ttl.
   7390 	 */
   7391 	ttl = rdataset.ttl;
   7392 
   7393 	/*
   7394 	 * Delete all NSEC3PARAM records which match that in nsec3chain.
   7395 	 */
   7396 	for (result = dns_rdataset_first(&rdataset);
   7397 	     result == ISC_R_SUCCESS;
   7398 	     result = dns_rdataset_next(&rdataset)) {
   7399 
   7400 		dns_rdataset_current(&rdataset, &rdata);
   7401 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
   7402 
   7403 		if (nsec3param.hash != chain->nsec3param.hash ||
   7404 		    (active && nsec3param.flags != 0) ||
   7405 		    nsec3param.iterations != chain->nsec3param.iterations ||
   7406 		    nsec3param.salt_length != chain->nsec3param.salt_length ||
   7407 		    memcmp(nsec3param.salt, chain->nsec3param.salt,
   7408 			   nsec3param.salt_length)) {
   7409 			dns_rdata_reset(&rdata);
   7410 			continue;
   7411 		}
   7412 
   7413 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
   7414 				    name, rdataset.ttl, &rdata));
   7415 		dns_rdata_reset(&rdata);
   7416 	}
   7417 	if (result != ISC_R_NOMORE)
   7418 		goto failure;
   7419 
   7420 	dns_rdataset_disassociate(&rdataset);
   7421 
   7422  try_private:
   7423 
   7424 	if (active)
   7425 		goto add;
   7426 
   7427 	result = dns_nsec_nseconly(db, ver, &nseconly);
   7428 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
   7429 
   7430 	/*
   7431 	 * Delete all private records which match that in nsec3chain.
   7432 	 */
   7433 	result = dns_db_findrdataset(db, node, ver, privatetype,
   7434 				     0, 0, &rdataset, NULL);
   7435 	if (result == ISC_R_NOTFOUND)
   7436 		goto add;
   7437 	if (result != ISC_R_SUCCESS)
   7438 		goto failure;
   7439 
   7440 	for (result = dns_rdataset_first(&rdataset);
   7441 	     result == ISC_R_SUCCESS;
   7442 	     result = dns_rdataset_next(&rdataset)) {
   7443 		dns_rdata_t private = DNS_RDATA_INIT;
   7444 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   7445 
   7446 		dns_rdataset_current(&rdataset, &private);
   7447 		if (!dns_nsec3param_fromprivate(&private, &rdata,
   7448 						buf, sizeof(buf)))
   7449 			continue;
   7450 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
   7451 
   7452 		if ((!nsec3ok &&
   7453 		     (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
   7454 		    nsec3param.hash != chain->nsec3param.hash ||
   7455 		    nsec3param.iterations != chain->nsec3param.iterations ||
   7456 		    nsec3param.salt_length != chain->nsec3param.salt_length ||
   7457 		    memcmp(nsec3param.salt, chain->nsec3param.salt,
   7458 			   nsec3param.salt_length)) {
   7459 			dns_rdata_reset(&rdata);
   7460 			continue;
   7461 		}
   7462 
   7463 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
   7464 				    name, rdataset.ttl, &private));
   7465 		dns_rdata_reset(&rdata);
   7466 	}
   7467 	if (result != ISC_R_NOMORE)
   7468 		goto failure;
   7469 
   7470   add:
   7471 	if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
   7472 		result = ISC_R_SUCCESS;
   7473 		goto failure;
   7474 	}
   7475 
   7476 	/*
   7477 	 * Add a NSEC3PARAM record which matches that in nsec3chain but
   7478 	 * with all flags bits cleared.
   7479 	 *
   7480 	 * Note: we do not clear chain->nsec3param.flags as this change
   7481 	 * may be reversed.
   7482 	 */
   7483 	isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
   7484 	CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
   7485 				   dns_rdatatype_nsec3param,
   7486 				   &chain->nsec3param, &buffer));
   7487 	rdata.data[1] = 0;	/* Clear flag bits. */
   7488 	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
   7489 
   7490   failure:
   7491 	dns_db_detachnode(db, &node);
   7492 	if (dns_rdataset_isassociated(&rdataset))
   7493 		dns_rdataset_disassociate(&rdataset);
   7494 	return (result);
   7495 }
   7496 
   7497 static isc_result_t
   7498 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
   7499 	    dns_name_t *name, dns_diff_t *diff)
   7500 {
   7501 	dns_rdataset_t rdataset;
   7502 	isc_result_t result;
   7503 
   7504 	dns_rdataset_init(&rdataset);
   7505 
   7506 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
   7507 				     0, 0, &rdataset, NULL);
   7508 	if (result == ISC_R_NOTFOUND)
   7509 		return (ISC_R_SUCCESS);
   7510 	if (result != ISC_R_SUCCESS)
   7511 		return (result);
   7512 	for (result = dns_rdataset_first(&rdataset);
   7513 	     result == ISC_R_SUCCESS;
   7514 	     result = dns_rdataset_next(&rdataset)) {
   7515 		dns_rdata_t rdata = DNS_RDATA_INIT;
   7516 
   7517 		dns_rdataset_current(&rdataset, &rdata);
   7518 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
   7519 				    rdataset.ttl, &rdata));
   7520 	}
   7521 	if (result == ISC_R_NOMORE)
   7522 		result = ISC_R_SUCCESS;
   7523  failure:
   7524 	dns_rdataset_disassociate(&rdataset);
   7525 	return (result);
   7526 }
   7527 
   7528 static isc_result_t
   7529 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
   7530 		    dns_name_t *name, const dns_rdata_nsec3param_t *param,
   7531 		    dns_diff_t *diff)
   7532 {
   7533 	dns_rdataset_t rdataset;
   7534 	dns_rdata_nsec3_t nsec3;
   7535 	isc_result_t result;
   7536 
   7537 	dns_rdataset_init(&rdataset);
   7538 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
   7539 				     0, 0, &rdataset, NULL);
   7540 	if (result == ISC_R_NOTFOUND)
   7541 		return (ISC_R_SUCCESS);
   7542 	if (result != ISC_R_SUCCESS)
   7543 		return (result);
   7544 
   7545 	for (result = dns_rdataset_first(&rdataset);
   7546 	     result == ISC_R_SUCCESS;
   7547 	     result = dns_rdataset_next(&rdataset)) {
   7548 		dns_rdata_t rdata = DNS_RDATA_INIT;
   7549 
   7550 		dns_rdataset_current(&rdataset, &rdata);
   7551 		CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
   7552 		if (nsec3.hash != param->hash ||
   7553 		    nsec3.iterations != param->iterations ||
   7554 		    nsec3.salt_length != param->salt_length ||
   7555 		    memcmp(nsec3.salt, param->salt, nsec3.salt_length))
   7556 			continue;
   7557 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
   7558 				    rdataset.ttl, &rdata));
   7559 	}
   7560 	if (result == ISC_R_NOMORE)
   7561 		result = ISC_R_SUCCESS;
   7562  failure:
   7563 	dns_rdataset_disassociate(&rdataset);
   7564 	return (result);
   7565 }
   7566 
   7567 static isc_result_t
   7568 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
   7569 		const dns_rdata_nsec3param_t *param,
   7570 		bool *answer)
   7571 {
   7572 	dns_dbnode_t *node = NULL;
   7573 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7574 	dns_rdata_nsec3param_t myparam;
   7575 	dns_rdataset_t rdataset;
   7576 	isc_result_t result;
   7577 
   7578 	*answer = false;
   7579 
   7580 	result = dns_db_getoriginnode(db, &node);
   7581 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   7582 
   7583 	dns_rdataset_init(&rdataset);
   7584 
   7585 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
   7586 				     0, 0, &rdataset, NULL);
   7587 	if (result == ISC_R_SUCCESS) {
   7588 		dns_rdataset_disassociate(&rdataset);
   7589 		dns_db_detachnode(db, &node);
   7590 		return (result);
   7591 	}
   7592 	if (result != ISC_R_NOTFOUND) {
   7593 		dns_db_detachnode(db, &node);
   7594 		return (result);
   7595 	}
   7596 
   7597 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
   7598 				     0, 0, &rdataset, NULL);
   7599 	if (result == ISC_R_NOTFOUND) {
   7600 		*answer = true;
   7601 		dns_db_detachnode(db, &node);
   7602 		return (ISC_R_SUCCESS);
   7603 	}
   7604 	if (result != ISC_R_SUCCESS) {
   7605 		dns_db_detachnode(db, &node);
   7606 		return (result);
   7607 	}
   7608 
   7609 	for (result = dns_rdataset_first(&rdataset);
   7610 	     result == ISC_R_SUCCESS;
   7611 	     result = dns_rdataset_next(&rdataset)) {
   7612 		dns_rdataset_current(&rdataset, &rdata);
   7613 		CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
   7614 		dns_rdata_reset(&rdata);
   7615 		/*
   7616 		 * Ignore any NSEC3PARAM removals.
   7617 		 */
   7618 		if (NSEC3REMOVE(myparam.flags))
   7619 			continue;
   7620 		/*
   7621 		 * Ignore the chain that we are in the process of deleting.
   7622 		 */
   7623 		if (myparam.hash == param->hash &&
   7624 		    myparam.iterations == param->iterations &&
   7625 		    myparam.salt_length == param->salt_length &&
   7626 		    !memcmp(myparam.salt, param->salt, myparam.salt_length))
   7627 			continue;
   7628 		/*
   7629 		 * Found an active NSEC3 chain.
   7630 		 */
   7631 		break;
   7632 	}
   7633 	if (result == ISC_R_NOMORE) {
   7634 		*answer = true;
   7635 		result = ISC_R_SUCCESS;
   7636 	}
   7637 
   7638  failure:
   7639 	if (dns_rdataset_isassociated(&rdataset))
   7640 		dns_rdataset_disassociate(&rdataset);
   7641 	dns_db_detachnode(db, &node);
   7642 	return (result);
   7643 }
   7644 
   7645 /*%
   7646  * Given a tuple which is part of a diff, return a pointer to the next tuple in
   7647  * that diff which has the same name and type (or NULL if no such tuple is
   7648  * found).
   7649  */
   7650 static dns_difftuple_t *
   7651 find_next_matching_tuple(dns_difftuple_t *cur) {
   7652 	dns_difftuple_t *next = cur;
   7653 
   7654 	while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
   7655 		if (cur->rdata.type == next->rdata.type &&
   7656 		    dns_name_equal(&cur->name, &next->name))
   7657 		{
   7658 			return (next);
   7659 		}
   7660 	}
   7661 
   7662 	return (NULL);
   7663 }
   7664 
   7665 /*%
   7666  * Remove all tuples with the same name and type as 'cur' from 'src' and append
   7667  * them to 'dst'.
   7668  */
   7669 static void
   7670 move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
   7671 	do {
   7672 		dns_difftuple_t *next = find_next_matching_tuple(cur);
   7673 		ISC_LIST_UNLINK(src->tuples, cur, link);
   7674 		dns_diff_appendminimal(dst, &cur);
   7675 		cur = next;
   7676 	} while (cur != NULL);
   7677 }
   7678 
   7679 /*%
   7680  * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
   7681  * 'diff'.  Gradually remove tuples from 'diff' and append them to 'zonediff'
   7682  * along with tuples representing relevant signature changes.
   7683  */
   7684 isc_result_t
   7685 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
   7686 		     dst_key_t *zone_keys[], unsigned int nkeys,
   7687 		     dns_zone_t *zone, isc_stdtime_t inception,
   7688 		     isc_stdtime_t expire, isc_stdtime_t keyexpire,
   7689 		     isc_stdtime_t now, bool check_ksk,
   7690 		     bool keyset_kskonly, dns__zonediff_t *zonediff)
   7691 {
   7692 	dns_difftuple_t *tuple;
   7693 	isc_result_t result;
   7694 
   7695 	while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
   7696 		isc_stdtime_t exp = expire;
   7697 
   7698 		if (keyexpire != 0 &&
   7699 		    (tuple->rdata.type == dns_rdatatype_dnskey ||
   7700 		     tuple->rdata.type == dns_rdatatype_cdnskey ||
   7701 		     tuple->rdata.type == dns_rdatatype_cds))
   7702 		{
   7703 			exp = keyexpire;
   7704 		}
   7705 
   7706 		result = del_sigs(zone, db, version, &tuple->name,
   7707 				  tuple->rdata.type, zonediff,
   7708 				  zone_keys, nkeys, now, false);
   7709 		if (result != ISC_R_SUCCESS) {
   7710 			dns_zone_log(zone, ISC_LOG_ERROR,
   7711 				     "dns__zone_updatesigs:del_sigs -> %s",
   7712 				     dns_result_totext(result));
   7713 			return (result);
   7714 		}
   7715 		result = add_sigs(db, version, &tuple->name, zone,
   7716 				  tuple->rdata.type, zonediff->diff,
   7717 				  zone_keys, nkeys, zone->mctx, inception,
   7718 				  exp, check_ksk, keyset_kskonly);
   7719 		if (result != ISC_R_SUCCESS) {
   7720 			dns_zone_log(zone, ISC_LOG_ERROR,
   7721 				     "dns__zone_updatesigs:add_sigs -> %s",
   7722 				     dns_result_totext(result));
   7723 			return (result);
   7724 		}
   7725 
   7726 		/*
   7727 		 * Signature changes for all RRs with name tuple->name and type
   7728 		 * tuple->rdata.type were appended to zonediff->diff.  Now we
   7729 		 * remove all the "raw" changes with the same name and type
   7730 		 * from diff (so that they are not processed by this loop
   7731 		 * again) and append them to zonediff so that they get applied.
   7732 		 */
   7733 		move_matching_tuples(tuple, diff, zonediff->diff);
   7734 	}
   7735 	return (ISC_R_SUCCESS);
   7736 }
   7737 
   7738 /*
   7739  * Incrementally build and sign a new NSEC3 chain using the parameters
   7740  * requested.
   7741  */
   7742 static void
   7743 zone_nsec3chain(dns_zone_t *zone) {
   7744 	const char *me = "zone_nsec3chain";
   7745 	dns_db_t *db = NULL;
   7746 	dns_dbnode_t *node = NULL;
   7747 	dns_dbversion_t *version = NULL;
   7748 	dns_diff_t _sig_diff;
   7749 	dns_diff_t nsec_diff;
   7750 	dns_diff_t nsec3_diff;
   7751 	dns_diff_t param_diff;
   7752 	dns__zonediff_t zonediff;
   7753 	dns_fixedname_t fixed;
   7754 	dns_fixedname_t nextfixed;
   7755 	dns_name_t *name, *nextname;
   7756 	dns_rdataset_t rdataset;
   7757 	dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
   7758 	dns_nsec3chainlist_t cleanup;
   7759 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   7760 	int32_t signatures;
   7761 	bool check_ksk, keyset_kskonly;
   7762 	bool delegation;
   7763 	bool first;
   7764 	isc_result_t result;
   7765 	isc_stdtime_t now, inception, soaexpire, expire;
   7766 	uint32_t jitter, sigvalidityinterval, expiryinterval;
   7767 	unsigned int i;
   7768 	unsigned int nkeys = 0;
   7769 	uint32_t nodes;
   7770 	bool unsecure = false;
   7771 	bool seen_soa, seen_ns, seen_dname, seen_ds;
   7772 	bool seen_nsec, seen_nsec3, seen_rr;
   7773 	dns_rdatasetiter_t *iterator = NULL;
   7774 	bool buildnsecchain;
   7775 	bool updatensec = false;
   7776 	dns_rdatatype_t privatetype = zone->privatetype;
   7777 
   7778 	ENTER;
   7779 
   7780 	dns_rdataset_init(&rdataset);
   7781 	name = dns_fixedname_initname(&fixed);
   7782 	nextname = dns_fixedname_initname(&nextfixed);
   7783 	dns_diff_init(zone->mctx, &param_diff);
   7784 	dns_diff_init(zone->mctx, &nsec3_diff);
   7785 	dns_diff_init(zone->mctx, &nsec_diff);
   7786 	dns_diff_init(zone->mctx, &_sig_diff);
   7787 	zonediff_init(&zonediff, &_sig_diff);
   7788 	ISC_LIST_INIT(cleanup);
   7789 
   7790 	/*
   7791 	 * Updates are disabled.  Pause for 5 minutes.
   7792 	 */
   7793 	if (zone->update_disabled) {
   7794 		result = ISC_R_FAILURE;
   7795 		goto failure;
   7796 	}
   7797 
   7798 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   7799 	/*
   7800 	 * This function is called when zone timer fires, after the latter gets
   7801 	 * set by zone_addnsec3chain().  If the action triggering the call to
   7802 	 * zone_addnsec3chain() is closely followed by a zone deletion request,
   7803 	 * it might turn out that the timer thread will not be woken up until
   7804 	 * after the zone is deleted by rmzone(), which calls dns_db_detach()
   7805 	 * for zone->db, causing the latter to become NULL.  Return immediately
   7806 	 * if that happens.
   7807 	 */
   7808 	if (zone->db != NULL) {
   7809 		dns_db_attach(zone->db, &db);
   7810 	}
   7811 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   7812 	if (db == NULL) {
   7813 		return;
   7814 	}
   7815 
   7816 	result = dns_db_newversion(db, &version);
   7817 	if (result != ISC_R_SUCCESS) {
   7818 		dnssec_log(zone, ISC_LOG_ERROR,
   7819 			   "zone_nsec3chain:dns_db_newversion -> %s",
   7820 			   dns_result_totext(result));
   7821 		goto failure;
   7822 	}
   7823 
   7824 	isc_stdtime_get(&now);
   7825 
   7826 	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
   7827 				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
   7828 	if (result != ISC_R_SUCCESS) {
   7829 		dnssec_log(zone, ISC_LOG_ERROR,
   7830 			   "zone_nsec3chain:dns__zone_findkeys -> %s",
   7831 			   dns_result_totext(result));
   7832 		goto failure;
   7833 	}
   7834 
   7835 	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
   7836 	inception = now - 3600;	/* Allow for clock skew. */
   7837 	soaexpire = now + sigvalidityinterval;
   7838 	expiryinterval = dns_zone_getsigresigninginterval(zone);
   7839 	if (expiryinterval > sigvalidityinterval) {
   7840 		expiryinterval = sigvalidityinterval;
   7841 	} else {
   7842 		expiryinterval = sigvalidityinterval - expiryinterval;
   7843 	}
   7844 
   7845 	/*
   7846 	 * Spread out signatures over time if they happen to be
   7847 	 * clumped.  We don't do this for each add_sigs() call as
   7848 	 * we still want some clustering to occur.
   7849 	 */
   7850 	if (sigvalidityinterval >= 3600U) {
   7851 		if (sigvalidityinterval > 7200U) {
   7852 			jitter = isc_random_uniform(expiryinterval);
   7853 		} else {
   7854 			jitter = isc_random_uniform(1200);
   7855 		}
   7856 		expire = soaexpire - jitter - 1;
   7857 	} else {
   7858 		expire = soaexpire - 1;
   7859 	}
   7860 
   7861 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
   7862 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
   7863 
   7864 	/*
   7865 	 * We keep pulling nodes off each iterator in turn until
   7866 	 * we have no more nodes to pull off or we reach the limits
   7867 	 * for this quantum.
   7868 	 */
   7869 	nodes = zone->nodes;
   7870 	signatures = zone->signatures;
   7871 	LOCK_ZONE(zone);
   7872 	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   7873 	UNLOCK_ZONE(zone);
   7874 	first = true;
   7875 
   7876 	if (nsec3chain != NULL) {
   7877 		nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
   7878 	}
   7879 	/*
   7880 	 * Generate new NSEC3 chains first.
   7881 	 *
   7882 	 * The following while loop iterates over nodes in the zone database,
   7883 	 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
   7884 	 * them.  Once all nodes are processed, the "delete_nsec" field is
   7885 	 * consulted to check whether we are supposed to remove NSEC records
   7886 	 * from the zone database; if so, the database iterator is reset to
   7887 	 * point to the first node and the loop traverses all of them again,
   7888 	 * this time removing NSEC records.  If we hit a node which is obscured
   7889 	 * by a delegation or a DNAME, nodes are skipped over until we find one
   7890 	 * that is not obscured by the same obscuring name and then normal
   7891 	 * processing is resumed.
   7892 	 *
   7893 	 * The above is repeated until all requested NSEC3 chain changes are
   7894 	 * applied or when we reach the limits for this quantum, whichever
   7895 	 * happens first.
   7896 	 *
   7897 	 * Note that the "signatures" variable is only used here to limit the
   7898 	 * amount of work performed.  Actual DNSSEC signatures are only
   7899 	 * generated by dns__zone_updatesigs() calls later in this function.
   7900 	 */
   7901 	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
   7902 		LOCK_ZONE(zone);
   7903 		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
   7904 
   7905 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   7906 		if (nsec3chain->done || nsec3chain->db != zone->db) {
   7907 			ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
   7908 			ISC_LIST_APPEND(cleanup, nsec3chain, link);
   7909 		}
   7910 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   7911 		UNLOCK_ZONE(zone);
   7912 		if (ISC_LIST_TAIL(cleanup) == nsec3chain)
   7913 			goto next_addchain;
   7914 
   7915 		/*
   7916 		 * Possible future db.
   7917 		 */
   7918 		if (nsec3chain->db != db) {
   7919 			goto next_addchain;
   7920 		}
   7921 
   7922 		if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
   7923 			goto next_addchain;
   7924 
   7925 		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
   7926 
   7927 		if (nsec3chain->delete_nsec) {
   7928 			delegation = false;
   7929 			dns_dbiterator_pause(nsec3chain->dbiterator);
   7930 			CHECK(delete_nsec(db, version, node, name, &nsec_diff));
   7931 			goto next_addnode;
   7932 		}
   7933 		/*
   7934 		 * On the first pass we need to check if the current node
   7935 		 * has not been obscured.
   7936 		 */
   7937 		delegation = false;
   7938 		unsecure = false;
   7939 		if (first) {
   7940 			dns_fixedname_t ffound;
   7941 			dns_name_t *found;
   7942 			found = dns_fixedname_initname(&ffound);
   7943 			result = dns_db_find(db, name, version,
   7944 					     dns_rdatatype_soa,
   7945 					     DNS_DBFIND_NOWILD, 0, NULL, found,
   7946 					     NULL, NULL);
   7947 			if ((result == DNS_R_DELEGATION ||
   7948 			    result == DNS_R_DNAME) &&
   7949 			    !dns_name_equal(name, found)) {
   7950 				/*
   7951 				 * Remember the obscuring name so that
   7952 				 * we skip all obscured names.
   7953 				 */
   7954 				dns_name_copynf(found, name);
   7955 				delegation = true;
   7956 				goto next_addnode;
   7957 			}
   7958 		}
   7959 
   7960 		/*
   7961 		 * Check to see if this is a bottom of zone node.
   7962 		 */
   7963 		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
   7964 		if (result == ISC_R_NOTFOUND) {
   7965 			/* Empty node? */
   7966 			goto next_addnode;
   7967 		}
   7968 		if (result != ISC_R_SUCCESS) {
   7969 			goto failure;
   7970 		}
   7971 
   7972 		seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec = false;
   7973 		for (result = dns_rdatasetiter_first(iterator);
   7974 		     result == ISC_R_SUCCESS;
   7975 		     result = dns_rdatasetiter_next(iterator))
   7976 		{
   7977 			dns_rdatasetiter_current(iterator, &rdataset);
   7978 			INSIST(rdataset.type != dns_rdatatype_nsec3);
   7979 			if (rdataset.type == dns_rdatatype_soa) {
   7980 				seen_soa = true;
   7981 			} else if (rdataset.type == dns_rdatatype_ns) {
   7982 				seen_ns = true;
   7983 			} else if (rdataset.type == dns_rdatatype_dname) {
   7984 				seen_dname = true;
   7985 			} else if (rdataset.type == dns_rdatatype_ds) {
   7986 				seen_ds = true;
   7987 			} else if (rdataset.type == dns_rdatatype_nsec) {
   7988 				seen_nsec = true;
   7989 			}
   7990 			dns_rdataset_disassociate(&rdataset);
   7991 		}
   7992 		dns_rdatasetiter_destroy(&iterator);
   7993 		/*
   7994 		 * Is there a NSEC chain than needs to be cleaned up?
   7995 		 */
   7996 		if (seen_nsec) {
   7997 			nsec3chain->seen_nsec = true;
   7998 		}
   7999 		if (seen_ns && !seen_soa && !seen_ds) {
   8000 			unsecure = true;
   8001 		}
   8002 		if ((seen_ns && !seen_soa) || seen_dname) {
   8003 			delegation = true;
   8004 		}
   8005 
   8006 		/*
   8007 		 * Process one node.
   8008 		 */
   8009 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8010 		result = dns_nsec3_addnsec3(db, version, name,
   8011 					    &nsec3chain->nsec3param,
   8012 					    zone->minimum, unsecure,
   8013 					    &nsec3_diff);
   8014 		if (result != ISC_R_SUCCESS) {
   8015 			dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
   8016 				   "dns_nsec3_addnsec3 -> %s",
   8017 				   dns_result_totext(result));
   8018 			goto failure;
   8019 		}
   8020 
   8021 		/*
   8022 		 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
   8023 		 * two signatures.  Additionally there will, in general, be
   8024 		 * two signature generated below.
   8025 		 *
   8026 		 * If we are only changing the optout flag the cost is half
   8027 		 * that of the cost of generating a completely new chain.
   8028 		 */
   8029 		signatures -= 4;
   8030 
   8031 		/*
   8032 		 * Go onto next node.
   8033 		 */
   8034  next_addnode:
   8035 		first = false;
   8036 		dns_db_detachnode(db, &node);
   8037 		do {
   8038 			result = dns_dbiterator_next(nsec3chain->dbiterator);
   8039 
   8040 			if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
   8041 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8042 				CHECK(fixup_nsec3param(db, version, nsec3chain,
   8043 						       false, privatetype,
   8044 						       &param_diff));
   8045 				LOCK_ZONE(zone);
   8046 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
   8047 						link);
   8048 				UNLOCK_ZONE(zone);
   8049 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
   8050 				goto next_addchain;
   8051 			}
   8052 			if (result == ISC_R_NOMORE) {
   8053 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8054 				if (nsec3chain->seen_nsec) {
   8055 					CHECK(fixup_nsec3param(db, version,
   8056 							       nsec3chain,
   8057 							       true,
   8058 							       privatetype,
   8059 							       &param_diff));
   8060 					nsec3chain->delete_nsec = true;
   8061 					goto same_addchain;
   8062 				}
   8063 				CHECK(fixup_nsec3param(db, version, nsec3chain,
   8064 						       false, privatetype,
   8065 						       &param_diff));
   8066 				LOCK_ZONE(zone);
   8067 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
   8068 						link);
   8069 				UNLOCK_ZONE(zone);
   8070 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
   8071 				goto next_addchain;
   8072 			} else if (result != ISC_R_SUCCESS) {
   8073 				dnssec_log(zone, ISC_LOG_ERROR,
   8074 					   "zone_nsec3chain:"
   8075 					   "dns_dbiterator_next -> %s",
   8076 					   dns_result_totext(result));
   8077 				goto failure;
   8078 			} else if (delegation) {
   8079 				dns_dbiterator_current(nsec3chain->dbiterator,
   8080 						       &node, nextname);
   8081 				dns_db_detachnode(db, &node);
   8082 				if (!dns_name_issubdomain(nextname, name))
   8083 					break;
   8084 			} else {
   8085 				break;
   8086 			}
   8087 		} while (1);
   8088 		continue;
   8089 
   8090  same_addchain:
   8091 		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
   8092 		first = true;
   8093 		continue;
   8094 
   8095  next_addchain:
   8096 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8097 		nsec3chain = nextnsec3chain;
   8098 		first = true;
   8099 		if (nsec3chain != NULL) {
   8100 			nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
   8101 		}
   8102 	}
   8103 
   8104 	if (nsec3chain != NULL) {
   8105 		goto skip_removals;
   8106 	}
   8107 
   8108 	/*
   8109 	 * Process removals.
   8110 	 *
   8111 	 * This is a counterpart of the above while loop which takes care of
   8112 	 * removing an NSEC3 chain.  It starts with determining whether the
   8113 	 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
   8114 	 * NSEC chain by iterating over all nodes in the zone database and only
   8115 	 * then goes on to remove NSEC3 records be iterating over all nodes
   8116 	 * again and calling deletematchingnsec3() for each of them; otherwise,
   8117 	 * it starts removing NSEC3 records immediately.  Rules for processing
   8118 	 * obscured nodes and interrupting work are the same as for the while
   8119 	 * loop above.
   8120 	 */
   8121 	LOCK_ZONE(zone);
   8122 	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   8123 	UNLOCK_ZONE(zone);
   8124 	first = true;
   8125 	buildnsecchain = false;
   8126 	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
   8127 		LOCK_ZONE(zone);
   8128 		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
   8129 		UNLOCK_ZONE(zone);
   8130 
   8131 		if (nsec3chain->db != db) {
   8132 			goto next_removechain;
   8133 		}
   8134 
   8135 		if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
   8136 			goto next_removechain;
   8137 		}
   8138 
   8139 		/*
   8140 		 * Work out if we need to build a NSEC chain as a consequence
   8141 		 * of removing this NSEC3 chain.
   8142 		 */
   8143 		if (first && !updatensec &&
   8144 		    (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
   8145 		{
   8146 			result = need_nsec_chain(db, version,
   8147 						 &nsec3chain->nsec3param,
   8148 						 &buildnsecchain);
   8149 			if (result != ISC_R_SUCCESS) {
   8150 				dnssec_log(zone, ISC_LOG_ERROR,
   8151 					   "zone_nsec3chain:"
   8152 					   "need_nsec_chain -> %s",
   8153 					   dns_result_totext(result));
   8154 				goto failure;
   8155 			}
   8156 		}
   8157 
   8158 		if (first) {
   8159 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   8160 				   "zone_nsec3chain:buildnsecchain = %u\n",
   8161 				   buildnsecchain);
   8162 		}
   8163 
   8164 		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
   8165 		delegation = false;
   8166 
   8167 		if (!buildnsecchain) {
   8168 			/*
   8169 			 * Delete the NSEC3PARAM record matching this chain.
   8170 			 */
   8171 			if (first) {
   8172 				result = fixup_nsec3param(db, version,
   8173 							  nsec3chain,
   8174 							  true, privatetype,
   8175 							  &param_diff);
   8176 				if (result != ISC_R_SUCCESS) {
   8177 					dnssec_log(zone, ISC_LOG_ERROR,
   8178 						   "zone_nsec3chain:"
   8179 						   "fixup_nsec3param -> %s",
   8180 						   dns_result_totext(result));
   8181 					goto failure;
   8182 				}
   8183 			}
   8184 
   8185 			/*
   8186 			 * Delete the NSEC3 records.
   8187 			 */
   8188 			result = deletematchingnsec3(db, version, node, name,
   8189 						     &nsec3chain->nsec3param,
   8190 						     &nsec3_diff);
   8191 			if (result != ISC_R_SUCCESS) {
   8192 				dnssec_log(zone, ISC_LOG_ERROR,
   8193 					   "zone_nsec3chain:"
   8194 					   "deletematchingnsec3 -> %s",
   8195 					   dns_result_totext(result));
   8196 				goto failure;
   8197 			}
   8198 			goto next_removenode;
   8199 		}
   8200 
   8201 		if (first) {
   8202 			dns_fixedname_t ffound;
   8203 			dns_name_t *found;
   8204 			found = dns_fixedname_initname(&ffound);
   8205 			result = dns_db_find(db, name, version,
   8206 					     dns_rdatatype_soa,
   8207 					     DNS_DBFIND_NOWILD, 0, NULL, found,
   8208 					     NULL, NULL);
   8209 			if ((result == DNS_R_DELEGATION ||
   8210 			     result == DNS_R_DNAME) &&
   8211 			    !dns_name_equal(name, found))
   8212 			{
   8213 				/*
   8214 				 * Remember the obscuring name so that
   8215 				 * we skip all obscured names.
   8216 				 */
   8217 				dns_name_copynf(found, name);
   8218 				delegation = true;
   8219 				goto next_removenode;
   8220 			}
   8221 		}
   8222 
   8223 		/*
   8224 		 * Check to see if this is a bottom of zone node.
   8225 		 */
   8226 		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
   8227 		if (result == ISC_R_NOTFOUND) {
   8228 			/* Empty node? */
   8229 			goto next_removenode;
   8230 		}
   8231 		if (result != ISC_R_SUCCESS) {
   8232 			goto failure;
   8233 		}
   8234 
   8235 		seen_soa = seen_ns = seen_dname = seen_nsec3 =
   8236 			   seen_nsec = seen_rr = false;
   8237 		for (result = dns_rdatasetiter_first(iterator);
   8238 		     result == ISC_R_SUCCESS;
   8239 		     result = dns_rdatasetiter_next(iterator))
   8240 		{
   8241 			dns_rdatasetiter_current(iterator, &rdataset);
   8242 			if (rdataset.type == dns_rdatatype_soa) {
   8243 				seen_soa = true;
   8244 			} else if (rdataset.type == dns_rdatatype_ns) {
   8245 				seen_ns = true;
   8246 			} else if (rdataset.type == dns_rdatatype_dname) {
   8247 				seen_dname = true;
   8248 			} else if (rdataset.type == dns_rdatatype_nsec) {
   8249 				seen_nsec = true;
   8250 			} else if (rdataset.type == dns_rdatatype_nsec3) {
   8251 				seen_nsec3 = true;
   8252 			} else if (rdataset.type != dns_rdatatype_rrsig) {
   8253 				seen_rr = true;
   8254 			}
   8255 			dns_rdataset_disassociate(&rdataset);
   8256 		}
   8257 		dns_rdatasetiter_destroy(&iterator);
   8258 
   8259 		if (!seen_rr || seen_nsec3 || seen_nsec) {
   8260 			goto next_removenode;
   8261 		}
   8262 		if ((seen_ns && !seen_soa) || seen_dname) {
   8263 			delegation = true;
   8264 		}
   8265 
   8266 		/*
   8267 		 * Add a NSEC record except at the origin.
   8268 		 */
   8269 		if (!dns_name_equal(name, dns_db_origin(db))) {
   8270 			dns_dbiterator_pause(nsec3chain->dbiterator);
   8271 			CHECK(add_nsec(db, version, name, node, zone->minimum,
   8272 				       delegation, &nsec_diff));
   8273 			signatures--;
   8274 		}
   8275 
   8276  next_removenode:
   8277 		first = false;
   8278 		dns_db_detachnode(db, &node);
   8279 		do {
   8280 			result = dns_dbiterator_next(nsec3chain->dbiterator);
   8281 			if (result == ISC_R_NOMORE && buildnsecchain) {
   8282 				/*
   8283 				 * The NSEC chain should now be built.
   8284 				 * We can now remove the NSEC3 chain.
   8285 				 */
   8286 				updatensec = true;
   8287 				goto same_removechain;
   8288 			}
   8289 			if (result == ISC_R_NOMORE) {
   8290 				LOCK_ZONE(zone);
   8291 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
   8292 						link);
   8293 				UNLOCK_ZONE(zone);
   8294 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
   8295 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8296 				result = fixup_nsec3param(db, version,
   8297 							  nsec3chain, false,
   8298 							  privatetype,
   8299 							  &param_diff);
   8300 				if (result != ISC_R_SUCCESS) {
   8301 					dnssec_log(zone, ISC_LOG_ERROR,
   8302 						   "zone_nsec3chain:"
   8303 						   "fixup_nsec3param -> %s",
   8304 						   dns_result_totext(result));
   8305 					goto failure;
   8306 				}
   8307 				goto next_removechain;
   8308 			} else if (result != ISC_R_SUCCESS) {
   8309 				dnssec_log(zone, ISC_LOG_ERROR,
   8310 					   "zone_nsec3chain:"
   8311 					   "dns_dbiterator_next -> %s",
   8312 					   dns_result_totext(result));
   8313 				goto failure;
   8314 			} else if (delegation) {
   8315 				dns_dbiterator_current(nsec3chain->dbiterator,
   8316 						       &node, nextname);
   8317 				dns_db_detachnode(db, &node);
   8318 				if (!dns_name_issubdomain(nextname, name)) {
   8319 					break;
   8320 				}
   8321 			} else {
   8322 				break;
   8323 			}
   8324 		} while (1);
   8325 		continue;
   8326 
   8327  same_removechain:
   8328 		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
   8329 		buildnsecchain = false;
   8330 		first = true;
   8331 		continue;
   8332 
   8333  next_removechain:
   8334 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8335 		nsec3chain = nextnsec3chain;
   8336 		first = true;
   8337 	}
   8338 
   8339  skip_removals:
   8340 	/*
   8341 	 * We may need to update the NSEC/NSEC3 records for the zone apex.
   8342 	 */
   8343 	if (!ISC_LIST_EMPTY(param_diff.tuples)) {
   8344 		bool rebuild_nsec = false,
   8345 			      rebuild_nsec3 = false;
   8346 		result = dns_db_getoriginnode(db, &node);
   8347 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8348 		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
   8349 		if (result != ISC_R_SUCCESS) {
   8350 			dnssec_log(zone, ISC_LOG_ERROR,
   8351 				   "zone_nsec3chain:dns_db_allrdatasets -> %s",
   8352 				   dns_result_totext(result));
   8353 			goto failure;
   8354 		}
   8355 		for (result = dns_rdatasetiter_first(iterator);
   8356 		     result == ISC_R_SUCCESS;
   8357 		     result = dns_rdatasetiter_next(iterator))
   8358 		{
   8359 			dns_rdatasetiter_current(iterator, &rdataset);
   8360 			if (rdataset.type == dns_rdatatype_nsec) {
   8361 				rebuild_nsec = true;
   8362 			} else if (rdataset.type == dns_rdatatype_nsec3param) {
   8363 				rebuild_nsec3 = true;
   8364 			}
   8365 			dns_rdataset_disassociate(&rdataset);
   8366 		}
   8367 		dns_rdatasetiter_destroy(&iterator);
   8368 		dns_db_detachnode(db, &node);
   8369 
   8370 		if (rebuild_nsec) {
   8371 			if (nsec3chain != NULL) {
   8372 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8373 			}
   8374 
   8375 			result = updatesecure(db, version, &zone->origin,
   8376 					      zone->minimum, true,
   8377 					      &nsec_diff);
   8378 			if (result != ISC_R_SUCCESS) {
   8379 				dnssec_log(zone, ISC_LOG_ERROR,
   8380 					   "zone_nsec3chain:updatesecure -> %s",
   8381 					   dns_result_totext(result));
   8382 				goto failure;
   8383 			}
   8384 		}
   8385 
   8386 		if (rebuild_nsec3) {
   8387 			if (nsec3chain != NULL) {
   8388 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8389 			}
   8390 
   8391 			result = dns_nsec3_addnsec3s(db, version,
   8392 						     dns_db_origin(db),
   8393 						     zone->minimum, false,
   8394 						     &nsec3_diff);
   8395 			if (result != ISC_R_SUCCESS) {
   8396 				dnssec_log(zone, ISC_LOG_ERROR,
   8397 					   "zone_nsec3chain:"
   8398 					   "dns_nsec3_addnsec3s -> %s",
   8399 					   dns_result_totext(result));
   8400 				goto failure;
   8401 			}
   8402 		}
   8403 	}
   8404 
   8405 	/*
   8406 	 * Add / update signatures for the NSEC3 records.
   8407 	 */
   8408 	if (nsec3chain != NULL) {
   8409 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8410 	}
   8411 	result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
   8412 				      nkeys, zone, inception, expire, 0, now,
   8413 				      check_ksk, keyset_kskonly, &zonediff);
   8414 	if (result != ISC_R_SUCCESS) {
   8415 		dnssec_log(zone, ISC_LOG_ERROR,
   8416 			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
   8417 			   dns_result_totext(result));
   8418 		goto failure;
   8419 	}
   8420 
   8421 	/*
   8422 	 * We have changed the NSEC3PARAM or private RRsets
   8423 	 * above so we need to update the signatures.
   8424 	 */
   8425 	result = dns__zone_updatesigs(&param_diff, db, version, zone_keys,
   8426 				      nkeys, zone, inception, expire, 0, now,
   8427 				      check_ksk, keyset_kskonly, &zonediff);
   8428 	if (result != ISC_R_SUCCESS) {
   8429 		dnssec_log(zone, ISC_LOG_ERROR,
   8430 			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
   8431 			   dns_result_totext(result));
   8432 		goto failure;
   8433 	}
   8434 
   8435 	if (updatensec) {
   8436 		result = updatesecure(db, version, &zone->origin,
   8437 				      zone->minimum, false, &nsec_diff);
   8438 		if (result != ISC_R_SUCCESS) {
   8439 			dnssec_log(zone, ISC_LOG_ERROR,
   8440 				   "zone_nsec3chain:updatesecure -> %s",
   8441 				   dns_result_totext(result));
   8442 			goto failure;
   8443 		}
   8444 	}
   8445 
   8446 	result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys,
   8447 				      nkeys, zone, inception, expire, 0, now,
   8448 				      check_ksk, keyset_kskonly, &zonediff);
   8449 	if (result != ISC_R_SUCCESS) {
   8450 		dnssec_log(zone, ISC_LOG_ERROR,
   8451 			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
   8452 			   dns_result_totext(result));
   8453 		goto failure;
   8454 	}
   8455 
   8456 	/*
   8457 	 * If we made no effective changes to the zone then we can just
   8458 	 * cleanup otherwise we need to increment the serial.
   8459 	 */
   8460 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
   8461 		/*
   8462 		 * No need to call dns_db_closeversion() here as it is
   8463 		 * called with commit = true below.
   8464 		 */
   8465 		goto done;
   8466 	}
   8467 
   8468 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
   8469 			  &zonediff, zone_keys, nkeys, now, false);
   8470 	if (result != ISC_R_SUCCESS) {
   8471 		dnssec_log(zone, ISC_LOG_ERROR,
   8472 			   "zone_nsec3chain:del_sigs -> %s",
   8473 			   dns_result_totext(result));
   8474 		goto failure;
   8475 	}
   8476 
   8477 	result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
   8478 				   zone->updatemethod);
   8479 	if (result != ISC_R_SUCCESS) {
   8480 		dnssec_log(zone, ISC_LOG_ERROR,
   8481 			   "zone_nsec3chain:update_soa_serial -> %s",
   8482 			   dns_result_totext(result));
   8483 		goto failure;
   8484 	}
   8485 
   8486 	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
   8487 			  zonediff.diff, zone_keys, nkeys, zone->mctx,
   8488 			  inception, soaexpire, check_ksk, keyset_kskonly);
   8489 	if (result != ISC_R_SUCCESS) {
   8490 		dnssec_log(zone, ISC_LOG_ERROR,
   8491 			   "zone_nsec3chain:add_sigs -> %s",
   8492 			   dns_result_totext(result));
   8493 		goto failure;
   8494 	}
   8495 
   8496 	/* Write changes to journal file. */
   8497 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
   8498 
   8499 	LOCK_ZONE(zone);
   8500 	zone_needdump(zone, DNS_DUMP_DELAY);
   8501 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   8502 	UNLOCK_ZONE(zone);
   8503 
   8504  done:
   8505 	/*
   8506 	 * Pause all iterators so that dns_db_closeversion() can succeed.
   8507 	 */
   8508 	LOCK_ZONE(zone);
   8509 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   8510 	     nsec3chain != NULL;
   8511 	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
   8512 	{
   8513 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8514 	}
   8515 	UNLOCK_ZONE(zone);
   8516 
   8517 	/*
   8518 	 * Everything has succeeded. Commit the changes.
   8519 	 * Unconditionally commit as zonediff.offline not checked above.
   8520 	 */
   8521 	dns_db_closeversion(db, &version, true);
   8522 
   8523 	/*
   8524 	 * Everything succeeded so we can clean these up now.
   8525 	 */
   8526 	nsec3chain = ISC_LIST_HEAD(cleanup);
   8527 	while (nsec3chain != NULL) {
   8528 		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
   8529 		dns_db_detach(&nsec3chain->db);
   8530 		dns_dbiterator_destroy(&nsec3chain->dbiterator);
   8531 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   8532 		nsec3chain = ISC_LIST_HEAD(cleanup);
   8533 	}
   8534 
   8535 	set_resigntime(zone);
   8536 
   8537  failure:
   8538 	if (result != ISC_R_SUCCESS) {
   8539 		dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
   8540 			   dns_result_totext(result));
   8541 	}
   8542 
   8543 	/*
   8544 	 * On error roll back the current nsec3chain.
   8545 	 */
   8546 	if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
   8547 		if (nsec3chain->done) {
   8548 			dns_db_detach(&nsec3chain->db);
   8549 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
   8550 			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   8551 		} else {
   8552 			result = dns_dbiterator_first(nsec3chain->dbiterator);
   8553 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8554 			dns_dbiterator_pause(nsec3chain->dbiterator);
   8555 			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
   8556 		}
   8557 	}
   8558 
   8559 	/*
   8560 	 * Rollback the cleanup list.
   8561 	 */
   8562 	nsec3chain = ISC_LIST_TAIL(cleanup);
   8563 	while (nsec3chain != NULL) {
   8564 		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
   8565 		if (nsec3chain->done) {
   8566 			dns_db_detach(&nsec3chain->db);
   8567 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
   8568 			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   8569 		} else {
   8570 			LOCK_ZONE(zone);
   8571 			ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
   8572 			UNLOCK_ZONE(zone);
   8573 			result = dns_dbiterator_first(nsec3chain->dbiterator);
   8574 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8575 			dns_dbiterator_pause(nsec3chain->dbiterator);
   8576 			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
   8577 		}
   8578 		nsec3chain = ISC_LIST_TAIL(cleanup);
   8579 	}
   8580 
   8581 	LOCK_ZONE(zone);
   8582 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   8583 	     nsec3chain != NULL;
   8584 	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
   8585 	{
   8586 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8587 	}
   8588 	UNLOCK_ZONE(zone);
   8589 
   8590 	dns_diff_clear(&param_diff);
   8591 	dns_diff_clear(&nsec3_diff);
   8592 	dns_diff_clear(&nsec_diff);
   8593 	dns_diff_clear(&_sig_diff);
   8594 
   8595 	if (iterator != NULL) {
   8596 		dns_rdatasetiter_destroy(&iterator);
   8597 	}
   8598 
   8599 	for (i = 0; i < nkeys; i++) {
   8600 		dst_key_free(&zone_keys[i]);
   8601 	}
   8602 
   8603 	if (node != NULL) {
   8604 		dns_db_detachnode(db, &node);
   8605 	}
   8606 	if (version != NULL) {
   8607 		dns_db_closeversion(db, &version, false);
   8608 		dns_db_detach(&db);
   8609 	} else if (db != NULL) {
   8610 		dns_db_detach(&db);
   8611 	}
   8612 
   8613 	LOCK_ZONE(zone);
   8614 	if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
   8615 		isc_interval_t interval;
   8616 		if (zone->update_disabled || result != ISC_R_SUCCESS) {
   8617 			isc_interval_set(&interval, 60, 0);	  /* 1 minute */
   8618 		} else {
   8619 			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
   8620 		}
   8621 		isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
   8622 	} else {
   8623 		isc_time_settoepoch(&zone->nsec3chaintime);
   8624 	}
   8625 	UNLOCK_ZONE(zone);
   8626 
   8627 	INSIST(version == NULL);
   8628 }
   8629 
   8630 /*%
   8631  * Delete all RRSIG records with the given algorithm and keyid.
   8632  * Remove the NSEC record and RRSIGs if nkeys is zero.
   8633  * If all remaining RRsets are signed with the given algorithm
   8634  * set *has_algp to true.
   8635  */
   8636 static isc_result_t
   8637 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
   8638 	dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
   8639 	uint16_t keyid, bool *has_algp, dns_diff_t *diff)
   8640 {
   8641 	dns_rdata_rrsig_t rrsig;
   8642 	dns_rdataset_t rdataset;
   8643 	dns_rdatasetiter_t *iterator = NULL;
   8644 	isc_result_t result;
   8645 	bool alg_missed = false;
   8646 	bool alg_found = false;
   8647 
   8648 	char namebuf[DNS_NAME_FORMATSIZE];
   8649 	dns_name_format(name, namebuf, sizeof(namebuf));
   8650 
   8651 	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
   8652 	if (result != ISC_R_SUCCESS) {
   8653 		if (result == ISC_R_NOTFOUND)
   8654 			result = ISC_R_SUCCESS;
   8655 		return (result);
   8656 	}
   8657 
   8658 	dns_rdataset_init(&rdataset);
   8659 	for (result = dns_rdatasetiter_first(iterator);
   8660 	     result == ISC_R_SUCCESS;
   8661 	     result = dns_rdatasetiter_next(iterator)) {
   8662 		bool has_alg = false;
   8663 		dns_rdatasetiter_current(iterator, &rdataset);
   8664 		if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
   8665 			for (result = dns_rdataset_first(&rdataset);
   8666 			     result == ISC_R_SUCCESS;
   8667 			     result = dns_rdataset_next(&rdataset)) {
   8668 				dns_rdata_t rdata = DNS_RDATA_INIT;
   8669 				dns_rdataset_current(&rdataset, &rdata);
   8670 				CHECK(update_one_rr(db, version, diff,
   8671 						    DNS_DIFFOP_DEL, name,
   8672 						    rdataset.ttl, &rdata));
   8673 			}
   8674 			if (result != ISC_R_NOMORE)
   8675 				goto failure;
   8676 			dns_rdataset_disassociate(&rdataset);
   8677 			continue;
   8678 		}
   8679 		if (rdataset.type != dns_rdatatype_rrsig) {
   8680 			dns_rdataset_disassociate(&rdataset);
   8681 			continue;
   8682 		}
   8683 		for (result = dns_rdataset_first(&rdataset);
   8684 		     result == ISC_R_SUCCESS;
   8685 		     result = dns_rdataset_next(&rdataset))
   8686 		{
   8687 			dns_rdata_t rdata = DNS_RDATA_INIT;
   8688 			dns_rdataset_current(&rdataset, &rdata);
   8689 			CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
   8690 			if (nkeys != 0 &&
   8691 			    (rrsig.algorithm != algorithm ||
   8692 			     rrsig.keyid != keyid))
   8693 			{
   8694 				if (rrsig.algorithm == algorithm) {
   8695 					has_alg = true;
   8696 				}
   8697 				continue;
   8698 			}
   8699 			CHECK(update_one_rr(db, version, diff,
   8700 					    DNS_DIFFOP_DELRESIGN, name,
   8701 					    rdataset.ttl, &rdata));
   8702 		}
   8703 		dns_rdataset_disassociate(&rdataset);
   8704 		if (result != ISC_R_NOMORE)
   8705 			break;
   8706 
   8707 		/*
   8708 		 * After deleting, if there's still a signature for
   8709 		 * 'algorithm', set alg_found; if not, set alg_missed.
   8710 		 */
   8711 		if (has_alg) {
   8712 			alg_found = true;
   8713 		} else {
   8714 			alg_missed = true;
   8715 		}
   8716 	}
   8717 	if (result == ISC_R_NOMORE)
   8718 		result = ISC_R_SUCCESS;
   8719 
   8720 	/*
   8721 	 * Set `has_algp` if the algorithm was found in every RRset:
   8722 	 * i.e., found in at least one, and not missing from any.
   8723 	 */
   8724 	*has_algp = (alg_found && !alg_missed);
   8725  failure:
   8726 	if (dns_rdataset_isassociated(&rdataset))
   8727 		dns_rdataset_disassociate(&rdataset);
   8728 	dns_rdatasetiter_destroy(&iterator);
   8729 	return (result);
   8730 }
   8731 
   8732 /*
   8733  * Incrementally sign the zone using the keys requested.
   8734  * Builds the NSEC chain if required.
   8735  */
   8736 static void
   8737 zone_sign(dns_zone_t *zone) {
   8738 	const char *me = "zone_sign";
   8739 	dns_db_t *db = NULL;
   8740 	dns_dbnode_t *node = NULL;
   8741 	dns_dbversion_t *version = NULL;
   8742 	dns_diff_t _sig_diff;
   8743 	dns_diff_t post_diff;
   8744 	dns__zonediff_t zonediff;
   8745 	dns_fixedname_t fixed;
   8746 	dns_fixedname_t nextfixed;
   8747 	dns_name_t *name, *nextname;
   8748 	dns_rdataset_t rdataset;
   8749 	dns_signing_t *signing, *nextsigning;
   8750 	dns_signinglist_t cleanup;
   8751 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   8752 	int32_t signatures;
   8753 	bool check_ksk, keyset_kskonly, is_ksk;
   8754 	bool with_ksk, with_zsk;
   8755 	bool commit = false;
   8756 	bool is_bottom_of_zone;
   8757 	bool build_nsec = false;
   8758 	bool build_nsec3 = false;
   8759 	bool first;
   8760 	isc_result_t result;
   8761 	isc_stdtime_t now, inception, soaexpire, expire;
   8762 	uint32_t jitter, sigvalidityinterval, expiryinterval;
   8763 	unsigned int i, j;
   8764 	unsigned int nkeys = 0;
   8765 	uint32_t nodes;
   8766 
   8767 	ENTER;
   8768 
   8769 	dns_rdataset_init(&rdataset);
   8770 	name = dns_fixedname_initname(&fixed);
   8771 	nextname = dns_fixedname_initname(&nextfixed);
   8772 	dns_diff_init(zone->mctx, &_sig_diff);
   8773 	dns_diff_init(zone->mctx, &post_diff);
   8774 	zonediff_init(&zonediff, &_sig_diff);
   8775 	ISC_LIST_INIT(cleanup);
   8776 
   8777 	/*
   8778 	 * Updates are disabled.  Pause for 1 minute.
   8779 	 */
   8780 	if (zone->update_disabled) {
   8781 		result = ISC_R_FAILURE;
   8782 		goto cleanup;
   8783 	}
   8784 
   8785 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   8786 	if (zone->db != NULL) {
   8787 		dns_db_attach(zone->db, &db);
   8788 	}
   8789 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   8790 	if (db == NULL) {
   8791 		result = ISC_R_FAILURE;
   8792 		goto cleanup;
   8793 	}
   8794 
   8795 	result = dns_db_newversion(db, &version);
   8796 	if (result != ISC_R_SUCCESS) {
   8797 		dnssec_log(zone, ISC_LOG_ERROR,
   8798 			   "zone_sign:dns_db_newversion -> %s",
   8799 			   dns_result_totext(result));
   8800 		goto cleanup;
   8801 	}
   8802 
   8803 	isc_stdtime_get(&now);
   8804 
   8805 	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
   8806 				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
   8807 	if (result != ISC_R_SUCCESS) {
   8808 		dnssec_log(zone, ISC_LOG_ERROR,
   8809 			   "zone_sign:dns__zone_findkeys -> %s",
   8810 			   dns_result_totext(result));
   8811 		goto cleanup;
   8812 	}
   8813 
   8814 	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
   8815 	inception = now - 3600;	/* Allow for clock skew. */
   8816 	soaexpire = now + sigvalidityinterval;
   8817 	expiryinterval = dns_zone_getsigresigninginterval(zone);
   8818 	if (expiryinterval > sigvalidityinterval) {
   8819 		expiryinterval = sigvalidityinterval;
   8820 	} else {
   8821 		expiryinterval = sigvalidityinterval - expiryinterval;
   8822 	}
   8823 
   8824 	/*
   8825 	 * Spread out signatures over time if they happen to be
   8826 	 * clumped.  We don't do this for each add_sigs() call as
   8827 	 * we still want some clustering to occur.
   8828 	 */
   8829 	if (sigvalidityinterval >= 3600U) {
   8830 		if (sigvalidityinterval > 7200U) {
   8831 			jitter = isc_random_uniform(expiryinterval);
   8832 		} else {
   8833 			jitter = isc_random_uniform(1200);
   8834 		}
   8835 		expire = soaexpire - jitter - 1;
   8836 	} else {
   8837 		expire = soaexpire - 1;
   8838 	}
   8839 
   8840 	/*
   8841 	 * We keep pulling nodes off each iterator in turn until
   8842 	 * we have no more nodes to pull off or we reach the limits
   8843 	 * for this quantum.
   8844 	 */
   8845 	nodes = zone->nodes;
   8846 	signatures = zone->signatures;
   8847 	signing = ISC_LIST_HEAD(zone->signing);
   8848 	first = true;
   8849 
   8850 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
   8851 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
   8852 
   8853 	/* Determine which type of chain to build */
   8854 	CHECK(dns_private_chains(db, version, zone->privatetype,
   8855 				 &build_nsec, &build_nsec3));
   8856 
   8857 	/* If neither chain is found, default to NSEC */
   8858 	if (!build_nsec && !build_nsec3) {
   8859 		build_nsec = true;
   8860 	}
   8861 
   8862 	while (signing != NULL && nodes-- > 0 && signatures > 0) {
   8863 		bool has_alg = false;
   8864 		nextsigning = ISC_LIST_NEXT(signing, link);
   8865 
   8866 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   8867 		if (signing->done || signing->db != zone->db) {
   8868 			/*
   8869 			 * The zone has been reloaded.	We will have
   8870 			 * created new signings as part of the reload
   8871 			 * process so we can destroy this one.
   8872 			 */
   8873 			ISC_LIST_UNLINK(zone->signing, signing, link);
   8874 			ISC_LIST_APPEND(cleanup, signing, link);
   8875 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   8876 			goto next_signing;
   8877 		}
   8878 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   8879 
   8880 		if (signing->db != db) {
   8881 			goto next_signing;
   8882 		}
   8883 
   8884 		is_bottom_of_zone = false;
   8885 
   8886 		if (first && signing->deleteit) {
   8887 			/*
   8888 			 * Remove the key we are deleting from consideration.
   8889 			 */
   8890 			for (i = 0, j = 0; i < nkeys; i++) {
   8891 				/*
   8892 				 * Find the key we want to remove.
   8893 				 */
   8894 				if (ALG(zone_keys[i]) == signing->algorithm &&
   8895 				    dst_key_id(zone_keys[i]) == signing->keyid)
   8896 				{
   8897 					if (KSK(zone_keys[i]))
   8898 						dst_key_free(&zone_keys[i]);
   8899 					continue;
   8900 				}
   8901 				zone_keys[j] = zone_keys[i];
   8902 				j++;
   8903 			}
   8904 			for (i = j; i < nkeys; i++) {
   8905 				zone_keys[i] = NULL;
   8906 			}
   8907 			nkeys = j;
   8908 		}
   8909 
   8910 		dns_dbiterator_current(signing->dbiterator, &node, name);
   8911 
   8912 		if (signing->deleteit) {
   8913 			dns_dbiterator_pause(signing->dbiterator);
   8914 			CHECK(del_sig(db, version, name, node, nkeys,
   8915 				      signing->algorithm, signing->keyid,
   8916 				      &has_alg, zonediff.diff));
   8917 		}
   8918 
   8919 		/*
   8920 		 * On the first pass we need to check if the current node
   8921 		 * has not been obscured.
   8922 		 */
   8923 		if (first) {
   8924 			dns_fixedname_t ffound;
   8925 			dns_name_t *found;
   8926 			found = dns_fixedname_initname(&ffound);
   8927 			result = dns_db_find(db, name, version,
   8928 					     dns_rdatatype_soa,
   8929 					     DNS_DBFIND_NOWILD, 0, NULL, found,
   8930 					     NULL, NULL);
   8931 			if ((result == DNS_R_DELEGATION ||
   8932 			     result == DNS_R_DNAME) &&
   8933 			    !dns_name_equal(name, found))
   8934 			{
   8935 				/*
   8936 				 * Remember the obscuring name so that
   8937 				 * we skip all obscured names.
   8938 				 */
   8939 				dns_name_copynf(found, name);
   8940 				is_bottom_of_zone = true;
   8941 				goto next_node;
   8942 			}
   8943 		}
   8944 
   8945 		/*
   8946 		 * Process one node.
   8947 		 */
   8948 		with_ksk = false;
   8949 		with_zsk = false;
   8950 		dns_dbiterator_pause(signing->dbiterator);
   8951 
   8952 		CHECK(check_if_bottom_of_zone(db, node, version,
   8953 					      &is_bottom_of_zone));
   8954 
   8955 		for (i = 0; !has_alg && i < nkeys; i++) {
   8956 			bool both = false;
   8957 
   8958 			/*
   8959 			 * Find the keys we want to sign with.
   8960 			 */
   8961 			if (!dst_key_isprivate(zone_keys[i])) {
   8962 				continue;
   8963 			}
   8964 			if (dst_key_inactive(zone_keys[i])) {
   8965 				continue;
   8966 			}
   8967 
   8968 			/*
   8969 			 * When adding look for the specific key.
   8970 			 */
   8971 			if (!signing->deleteit &&
   8972 			    (dst_key_alg(zone_keys[i]) != signing->algorithm ||
   8973 			     dst_key_id(zone_keys[i]) != signing->keyid))
   8974 			{
   8975 				continue;
   8976 			}
   8977 
   8978 			/*
   8979 			 * When deleting make sure we are properly signed
   8980 			 * with the algorithm that was being removed.
   8981 			 */
   8982 			if (signing->deleteit &&
   8983 			    ALG(zone_keys[i]) != signing->algorithm)
   8984 			{
   8985 				continue;
   8986 			}
   8987 
   8988 			/*
   8989 			 * Do we do KSK processing?
   8990 			 */
   8991 			if (check_ksk && !REVOKE(zone_keys[i])) {
   8992 				bool have_ksk, have_nonksk;
   8993 				if (KSK(zone_keys[i])) {
   8994 					have_ksk = true;
   8995 					have_nonksk = false;
   8996 				} else {
   8997 					have_ksk = false;
   8998 					have_nonksk = true;
   8999 				}
   9000 				for (j = 0; j < nkeys; j++) {
   9001 					if (j == i ||
   9002 					    (ALG(zone_keys[i]) !=
   9003 					     ALG(zone_keys[j])))
   9004 					{
   9005 						continue;
   9006 					}
   9007 					/* Don't consider inactive keys, however
   9008 					 * the key may be temporary offline, so do
   9009 					 * consider keys which private key files are
   9010 					 * unavailable.
   9011 					 */
   9012 					if (dst_key_inactive(zone_keys[j])) {
   9013 						continue;
   9014 					}
   9015 					if (REVOKE(zone_keys[j])) {
   9016 						continue;
   9017 					}
   9018 					if (KSK(zone_keys[j])) {
   9019 						have_ksk = true;
   9020 					} else {
   9021 						have_nonksk = true;
   9022 					}
   9023 					both = have_ksk && have_nonksk;
   9024 					if (both) {
   9025 						break;
   9026 					}
   9027 				}
   9028 			}
   9029 			if (both || REVOKE(zone_keys[i])) {
   9030 				is_ksk = KSK(zone_keys[i]);
   9031 			} else {
   9032 				is_ksk = false;
   9033 			}
   9034 
   9035 			/*
   9036 			 * If deleting signatures, we need to ensure that
   9037 			 * the RRset is still signed at least once by a
   9038 			 * KSK and a ZSK.
   9039 			 */
   9040 			if (signing->deleteit && !is_ksk && with_zsk) {
   9041 				continue;
   9042 			}
   9043 
   9044 			if (signing->deleteit && is_ksk && with_ksk) {
   9045 				continue;
   9046 			}
   9047 
   9048 			CHECK(sign_a_node(db, zone, name, node, version,
   9049 					  build_nsec3, build_nsec,
   9050 					  zone_keys[i], inception, expire,
   9051 					  zone->minimum, is_ksk,
   9052 					  (both && keyset_kskonly),
   9053 					  is_bottom_of_zone, zonediff.diff,
   9054 					  &signatures, zone->mctx));
   9055 			/*
   9056 			 * If we are adding we are done.  Look for other keys
   9057 			 * of the same algorithm if deleting.
   9058 			 */
   9059 			if (!signing->deleteit) {
   9060 				break;
   9061 			}
   9062 			if (!is_ksk) {
   9063 				with_zsk = true;
   9064 			}
   9065 			if (KSK(zone_keys[i])) {
   9066 				with_ksk = true;
   9067 			}
   9068 		}
   9069 
   9070 		/*
   9071 		 * Go onto next node.
   9072 		 */
   9073  next_node:
   9074 		first = false;
   9075 		dns_db_detachnode(db, &node);
   9076 		do {
   9077 			result = dns_dbiterator_next(signing->dbiterator);
   9078 			if (result == ISC_R_NOMORE) {
   9079 				ISC_LIST_UNLINK(zone->signing, signing, link);
   9080 				ISC_LIST_APPEND(cleanup, signing, link);
   9081 				dns_dbiterator_pause(signing->dbiterator);
   9082 				if (nkeys != 0 && build_nsec) {
   9083 					/*
   9084 					 * We have finished regenerating the
   9085 					 * zone with a zone signing key.
   9086 					 * The NSEC chain is now complete and
   9087 					 * there is a full set of signatures
   9088 					 * for the zone.  We can now clear the
   9089 					 * OPT bit from the NSEC record.
   9090 					 */
   9091 					result = updatesecure(db, version,
   9092 							      &zone->origin,
   9093 							      zone->minimum,
   9094 							      false,
   9095 							      &post_diff);
   9096 					if (result != ISC_R_SUCCESS) {
   9097 						dnssec_log(zone, ISC_LOG_ERROR,
   9098 						   "updatesecure -> %s",
   9099 						    dns_result_totext(result));
   9100 						goto cleanup;
   9101 					}
   9102 				}
   9103 				result = updatesignwithkey(zone, signing,
   9104 							   version,
   9105 							   build_nsec3,
   9106 							   zone->minimum,
   9107 							   &post_diff);
   9108 				if (result != ISC_R_SUCCESS) {
   9109 					dnssec_log(zone, ISC_LOG_ERROR,
   9110 						   "updatesignwithkey -> %s",
   9111 						   dns_result_totext(result));
   9112 					goto cleanup;
   9113 				}
   9114 				build_nsec = false;
   9115 				goto next_signing;
   9116 			} else if (result != ISC_R_SUCCESS) {
   9117 				dnssec_log(zone, ISC_LOG_ERROR,
   9118 					   "zone_sign:"
   9119 					   "dns_dbiterator_next -> %s",
   9120 					   dns_result_totext(result));
   9121 				goto cleanup;
   9122 			} else if (is_bottom_of_zone) {
   9123 				dns_dbiterator_current(signing->dbiterator,
   9124 						       &node, nextname);
   9125 				dns_db_detachnode(db, &node);
   9126 				if (!dns_name_issubdomain(nextname, name)) {
   9127 					break;
   9128 				}
   9129 			} else {
   9130 				break;
   9131 			}
   9132 		} while (1);
   9133 		continue;
   9134 
   9135  next_signing:
   9136 		dns_dbiterator_pause(signing->dbiterator);
   9137 		signing = nextsigning;
   9138 		first = true;
   9139 	}
   9140 
   9141 	if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
   9142 		result = dns__zone_updatesigs(&post_diff, db, version,
   9143 					      zone_keys, nkeys, zone,
   9144 					      inception, expire, 0, now,
   9145 					      check_ksk, keyset_kskonly,
   9146 					      &zonediff);
   9147 		if (result != ISC_R_SUCCESS) {
   9148 			dnssec_log(zone, ISC_LOG_ERROR,
   9149 				   "zone_sign:dns__zone_updatesigs -> %s",
   9150 				   dns_result_totext(result));
   9151 			goto cleanup;
   9152 		}
   9153 	}
   9154 
   9155 	/*
   9156 	 * Have we changed anything?
   9157 	 */
   9158 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
   9159 		if (zonediff.offline) {
   9160 			commit = true;
   9161 		}
   9162 		result = ISC_R_SUCCESS;
   9163 		goto pauseall;
   9164 	}
   9165 
   9166 	commit = true;
   9167 
   9168 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
   9169 			  &zonediff, zone_keys, nkeys, now, false);
   9170 	if (result != ISC_R_SUCCESS) {
   9171 		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
   9172 			   dns_result_totext(result));
   9173 		goto cleanup;
   9174 	}
   9175 
   9176 	result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
   9177 				   zone->updatemethod);
   9178 	if (result != ISC_R_SUCCESS) {
   9179 		dnssec_log(zone, ISC_LOG_ERROR,
   9180 			   "zone_sign:update_soa_serial -> %s",
   9181 			   dns_result_totext(result));
   9182 		goto cleanup;
   9183 	}
   9184 
   9185 	/*
   9186 	 * Generate maximum life time signatures so that the above loop
   9187 	 * termination is sensible.
   9188 	 */
   9189 	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
   9190 			  zonediff.diff, zone_keys, nkeys, zone->mctx,
   9191 			  inception, soaexpire, check_ksk, keyset_kskonly);
   9192 	if (result != ISC_R_SUCCESS) {
   9193 		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
   9194 			   dns_result_totext(result));
   9195 		goto cleanup;
   9196 	}
   9197 
   9198 	/*
   9199 	 * Write changes to journal file.
   9200 	 */
   9201 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
   9202 
   9203  pauseall:
   9204 	/*
   9205 	 * Pause all iterators so that dns_db_closeversion() can succeed.
   9206 	 */
   9207 	for (signing = ISC_LIST_HEAD(zone->signing);
   9208 	     signing != NULL;
   9209 	     signing = ISC_LIST_NEXT(signing, link))
   9210 	{
   9211 		dns_dbiterator_pause(signing->dbiterator);
   9212 	}
   9213 
   9214 	for (signing = ISC_LIST_HEAD(cleanup);
   9215 	     signing != NULL;
   9216 	     signing = ISC_LIST_NEXT(signing, link))
   9217 	{
   9218 		dns_dbiterator_pause(signing->dbiterator);
   9219 	}
   9220 
   9221 	/*
   9222 	 * Everything has succeeded. Commit the changes.
   9223 	 */
   9224 	dns_db_closeversion(db, &version, commit);
   9225 
   9226 	/*
   9227 	 * Everything succeeded so we can clean these up now.
   9228 	 */
   9229 	signing = ISC_LIST_HEAD(cleanup);
   9230 	while (signing != NULL) {
   9231 		ISC_LIST_UNLINK(cleanup, signing, link);
   9232 		dns_db_detach(&signing->db);
   9233 		dns_dbiterator_destroy(&signing->dbiterator);
   9234 		isc_mem_put(zone->mctx, signing, sizeof *signing);
   9235 		signing = ISC_LIST_HEAD(cleanup);
   9236 	}
   9237 
   9238 	set_resigntime(zone);
   9239 
   9240 	if (commit) {
   9241 		LOCK_ZONE(zone);
   9242 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   9243 		zone_needdump(zone, DNS_DUMP_DELAY);
   9244 		UNLOCK_ZONE(zone);
   9245 	}
   9246 
   9247  failure:
   9248 	if (result != ISC_R_SUCCESS) {
   9249 		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
   9250 			   dns_result_totext(result));
   9251 	}
   9252 
   9253  cleanup:
   9254 	/*
   9255 	 * Pause all dbiterators.
   9256 	 */
   9257 	for (signing = ISC_LIST_HEAD(zone->signing);
   9258 	     signing != NULL;
   9259 	     signing = ISC_LIST_NEXT(signing, link))
   9260 	{
   9261 		dns_dbiterator_pause(signing->dbiterator);
   9262 	}
   9263 
   9264 	/*
   9265 	 * Rollback the cleanup list.
   9266 	 */
   9267 	signing = ISC_LIST_HEAD(cleanup);
   9268 	while (signing != NULL) {
   9269 		ISC_LIST_UNLINK(cleanup, signing, link);
   9270 		ISC_LIST_PREPEND(zone->signing, signing, link);
   9271 		dns_dbiterator_first(signing->dbiterator);
   9272 		dns_dbiterator_pause(signing->dbiterator);
   9273 		signing = ISC_LIST_HEAD(cleanup);
   9274 	}
   9275 
   9276 	dns_diff_clear(&_sig_diff);
   9277 
   9278 	for (i = 0; i < nkeys; i++) {
   9279 		dst_key_free(&zone_keys[i]);
   9280 	}
   9281 
   9282 	if (node != NULL) {
   9283 		dns_db_detachnode(db, &node);
   9284 	}
   9285 
   9286 	if (version != NULL) {
   9287 		dns_db_closeversion(db, &version, false);
   9288 		dns_db_detach(&db);
   9289 	} else if (db != NULL) {
   9290 		dns_db_detach(&db);
   9291 	}
   9292 
   9293 	if (ISC_LIST_HEAD(zone->signing) != NULL) {
   9294 		isc_interval_t interval;
   9295 		if (zone->update_disabled || result != ISC_R_SUCCESS) {
   9296 			isc_interval_set(&interval, 60, 0);	  /* 1 minute */
   9297 		} else {
   9298 			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
   9299 		}
   9300 		isc_time_nowplusinterval(&zone->signingtime, &interval);
   9301 	} else {
   9302 		isc_time_settoepoch(&zone->signingtime);
   9303 	}
   9304 
   9305 	INSIST(version == NULL);
   9306 }
   9307 
   9308 static isc_result_t
   9309 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
   9310 	      unsigned char *data, int size)
   9311 {
   9312 	dns_rdata_dnskey_t dnskey;
   9313 	dns_rdata_keydata_t keydata;
   9314 	isc_buffer_t buf;
   9315 	isc_result_t result;
   9316 
   9317 	dns_rdata_reset(target);
   9318 	isc_buffer_init(&buf, data, size);
   9319 
   9320 	switch (rr->type) {
   9321 	    case dns_rdatatype_dnskey:
   9322 		result = dns_rdata_tostruct(rr, &dnskey, NULL);
   9323 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9324 		dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
   9325 		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
   9326 				     &dnskey, &buf);
   9327 		break;
   9328 	    case dns_rdatatype_keydata:
   9329 		result = dns_rdata_tostruct(rr, &keydata, NULL);
   9330 		if (result == ISC_R_UNEXPECTEDEND)
   9331 			return (result);
   9332 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9333 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
   9334 		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
   9335 				     &dnskey, &buf);
   9336 		break;
   9337 	    default:
   9338 		INSIST(0);
   9339 		ISC_UNREACHABLE();
   9340 	}
   9341 	return (ISC_R_SUCCESS);
   9342 }
   9343 
   9344 /*
   9345  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
   9346  * a KEYDATA rdataset from the key zone.
   9347  *
   9348  * 'rr' contains either a DNSKEY record, or a KEYDATA record
   9349  *
   9350  * After normalizing keys to the same format (DNSKEY, with revoke bit
   9351  * cleared), return true if a key that matches 'rr' is found in
   9352  * 'rdset', or false if not.
   9353  */
   9354 
   9355 static bool
   9356 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
   9357 	unsigned char data1[4096], data2[4096];
   9358 	dns_rdata_t rdata, rdata1, rdata2;
   9359 	isc_result_t result;
   9360 
   9361 	dns_rdata_init(&rdata);
   9362 	dns_rdata_init(&rdata1);
   9363 	dns_rdata_init(&rdata2);
   9364 
   9365 	result = normalize_key(rr, &rdata1, data1, sizeof(data1));
   9366 	if (result != ISC_R_SUCCESS)
   9367 		return (false);
   9368 
   9369 	for (result = dns_rdataset_first(rdset);
   9370 	     result == ISC_R_SUCCESS;
   9371 	     result = dns_rdataset_next(rdset)) {
   9372 		dns_rdata_reset(&rdata);
   9373 		dns_rdataset_current(rdset, &rdata);
   9374 		result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
   9375 		if (result != ISC_R_SUCCESS)
   9376 			continue;
   9377 		if (dns_rdata_compare(&rdata1, &rdata2) == 0)
   9378 			return (true);
   9379 	}
   9380 
   9381 	return (false);
   9382 }
   9383 
   9384 /*
   9385  * Calculate the refresh interval for a keydata zone, per
   9386  * RFC5011: MAX(1 hr,
   9387  *		MIN(15 days,
   9388  *		    1/2 * OrigTTL,
   9389  *		    1/2 * RRSigExpirationInterval))
   9390  * or for retries: MAX(1 hr,
   9391  *		       MIN(1 day,
   9392  *			   1/10 * OrigTTL,
   9393  *			   1/10 * RRSigExpirationInterval))
   9394  */
   9395 static inline isc_stdtime_t
   9396 refresh_time(dns_keyfetch_t *kfetch, bool retry) {
   9397 	isc_result_t result;
   9398 	uint32_t t;
   9399 	dns_rdataset_t *rdset;
   9400 	dns_rdata_t sigrr = DNS_RDATA_INIT;
   9401 	dns_rdata_sig_t sig;
   9402 	isc_stdtime_t now;
   9403 
   9404 	isc_stdtime_get(&now);
   9405 
   9406 	if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
   9407 		rdset = &kfetch->dnskeysigset;
   9408 	else
   9409 		return (now + dns_zone_mkey_hour);
   9410 
   9411 	result = dns_rdataset_first(rdset);
   9412 	if (result != ISC_R_SUCCESS)
   9413 		return (now + dns_zone_mkey_hour);
   9414 
   9415 	dns_rdataset_current(rdset, &sigrr);
   9416 	result = dns_rdata_tostruct(&sigrr, &sig, NULL);
   9417 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9418 
   9419 	if (!retry) {
   9420 		t = sig.originalttl / 2;
   9421 
   9422 		if (isc_serial_gt(sig.timeexpire, now)) {
   9423 			uint32_t exp = (sig.timeexpire - now) / 2;
   9424 			if (t > exp)
   9425 				t = exp;
   9426 		}
   9427 
   9428 		if (t > (15 * dns_zone_mkey_day))
   9429 			t = (15 * dns_zone_mkey_day);
   9430 
   9431 		if (t < dns_zone_mkey_hour)
   9432 			t = dns_zone_mkey_hour;
   9433 	} else {
   9434 		t = sig.originalttl / 10;
   9435 
   9436 		if (isc_serial_gt(sig.timeexpire, now)) {
   9437 			uint32_t exp = (sig.timeexpire - now) / 10;
   9438 			if (t > exp)
   9439 				t = exp;
   9440 		}
   9441 
   9442 		if (t > dns_zone_mkey_day)
   9443 			t = dns_zone_mkey_day;
   9444 
   9445 		if (t < dns_zone_mkey_hour)
   9446 			t = dns_zone_mkey_hour;
   9447 	}
   9448 
   9449 	return (now + t);
   9450 }
   9451 
   9452 /*
   9453  * This routine is called when no changes are needed in a KEYDATA
   9454  * record except to simply update the refresh timer.  Caller should
   9455  * hold zone lock.
   9456  */
   9457 static isc_result_t
   9458 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
   9459 {
   9460 	isc_result_t result;
   9461 	isc_buffer_t keyb;
   9462 	unsigned char key_buf[4096];
   9463 	dns_rdata_t rdata = DNS_RDATA_INIT;
   9464 	dns_rdata_keydata_t keydata;
   9465 	dns_name_t *name;
   9466 	dns_zone_t *zone = kfetch->zone;
   9467 	isc_stdtime_t now;
   9468 
   9469 	name = dns_fixedname_name(&kfetch->name);
   9470 	isc_stdtime_get(&now);
   9471 
   9472 	for (result = dns_rdataset_first(&kfetch->keydataset);
   9473 	     result == ISC_R_SUCCESS;
   9474 	     result = dns_rdataset_next(&kfetch->keydataset)) {
   9475 		dns_rdata_reset(&rdata);
   9476 		dns_rdataset_current(&kfetch->keydataset, &rdata);
   9477 
   9478 		/* Delete old version */
   9479 		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
   9480 				    name, 0, &rdata));
   9481 
   9482 		/* Update refresh timer */
   9483 		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
   9484 		if (result == ISC_R_UNEXPECTEDEND)
   9485 			continue;
   9486 		if (result != ISC_R_SUCCESS)
   9487 			goto failure;
   9488 		keydata.refresh = refresh_time(kfetch, true);
   9489 		set_refreshkeytimer(zone, &keydata, now, false);
   9490 
   9491 		dns_rdata_reset(&rdata);
   9492 		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   9493 		CHECK(dns_rdata_fromstruct(&rdata,
   9494 					   zone->rdclass, dns_rdatatype_keydata,
   9495 					   &keydata, &keyb));
   9496 
   9497 		/* Insert updated version */
   9498 		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
   9499 				    name, 0, &rdata));
   9500 	}
   9501 	result = ISC_R_SUCCESS;
   9502   failure:
   9503 	return (result);
   9504 }
   9505 
   9506 /*
   9507  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
   9508  */
   9509 static bool
   9510 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
   9511 	isc_result_t result;
   9512 	dns_name_t *keyname;
   9513 	isc_mem_t *mctx;
   9514 	dns_rdata_t sigrr = DNS_RDATA_INIT;
   9515 	dns_rdata_t rr = DNS_RDATA_INIT;
   9516 	dns_rdata_rrsig_t sig;
   9517 	dns_rdata_dnskey_t dnskey;
   9518 	dst_key_t *dstkey = NULL;
   9519 	unsigned char key_buf[4096];
   9520 	isc_buffer_t keyb;
   9521 	bool answer = false;
   9522 
   9523 	REQUIRE(kfetch != NULL && keydata != NULL);
   9524 	REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
   9525 
   9526 	keyname = dns_fixedname_name(&kfetch->name);
   9527 	mctx = kfetch->zone->view->mctx;
   9528 
   9529 	/* Generate a key from keydata */
   9530 	isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   9531 	dns_keydata_todnskey(keydata, &dnskey, NULL);
   9532 	dns_rdata_fromstruct(&rr, keydata->common.rdclass,
   9533 			     dns_rdatatype_dnskey, &dnskey, &keyb);
   9534 	result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
   9535 	if (result != ISC_R_SUCCESS) {
   9536 		return (false);
   9537 	}
   9538 
   9539 	/* See if that key generated any of the signatures */
   9540 	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
   9541 	     result == ISC_R_SUCCESS;
   9542 	     result = dns_rdataset_next(&kfetch->dnskeysigset))
   9543 	{
   9544 		dns_fixedname_t fixed;
   9545 		dns_fixedname_init(&fixed);
   9546 
   9547 		dns_rdata_reset(&sigrr);
   9548 		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
   9549 		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
   9550 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9551 
   9552 		if (dst_key_alg(dstkey) == sig.algorithm &&
   9553 		    dst_key_rid(dstkey) == sig.keyid)
   9554 		{
   9555 			result = dns_dnssec_verify(keyname,
   9556 						   &kfetch->dnskeyset,
   9557 						   dstkey, false, 0, mctx,
   9558 						   &sigrr,
   9559 						   dns_fixedname_name(&fixed));
   9560 
   9561 			dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
   9562 				   "Confirm revoked DNSKEY is self-signed: %s",
   9563 				   dns_result_totext(result));
   9564 
   9565 			if (result == ISC_R_SUCCESS) {
   9566 				answer = true;
   9567 				break;
   9568 			}
   9569 		}
   9570 	}
   9571 
   9572 	dst_key_free(&dstkey);
   9573 	return (answer);
   9574 }
   9575 
   9576 /*
   9577  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
   9578  * anchors are being managed; scan the keyset, and update the key zone and the
   9579  * local trust anchors according to RFC5011.
   9580  */
   9581 static void
   9582 keyfetch_done(isc_task_t *task, isc_event_t *event) {
   9583 	isc_result_t result, eresult;
   9584 	dns_fetchevent_t *devent;
   9585 	dns_keyfetch_t *kfetch;
   9586 	dns_zone_t *zone;
   9587 	isc_mem_t *mctx = NULL;
   9588 	dns_keytable_t *secroots = NULL;
   9589 	dns_dbversion_t *ver = NULL;
   9590 	dns_diff_t diff;
   9591 	bool alldone = false;
   9592 	bool commit = false;
   9593 	dns_name_t *keyname;
   9594 	dns_rdata_t sigrr = DNS_RDATA_INIT;
   9595 	dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
   9596 	dns_rdata_t keydatarr = DNS_RDATA_INIT;
   9597 	dns_rdata_rrsig_t sig;
   9598 	dns_rdata_dnskey_t dnskey;
   9599 	dns_rdata_keydata_t keydata;
   9600 	bool initializing;
   9601 	char namebuf[DNS_NAME_FORMATSIZE];
   9602 	unsigned char key_buf[4096];
   9603 	isc_buffer_t keyb;
   9604 	dst_key_t *dstkey;
   9605 	isc_stdtime_t now;
   9606 	int pending = 0;
   9607 	bool secure = false, initial = false;
   9608 	bool free_needed;
   9609 
   9610 	UNUSED(task);
   9611 	INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
   9612 	INSIST(event->ev_arg != NULL);
   9613 
   9614 	kfetch = event->ev_arg;
   9615 	zone = kfetch->zone;
   9616 	isc_mem_attach(zone->mctx, &mctx);
   9617 	keyname = dns_fixedname_name(&kfetch->name);
   9618 
   9619 	devent = (dns_fetchevent_t *) event;
   9620 	eresult = devent->result;
   9621 
   9622 	/* Free resources which are not of interest */
   9623 	if (devent->node != NULL) {
   9624 		dns_db_detachnode(devent->db, &devent->node);
   9625 	}
   9626 	if (devent->db != NULL) {
   9627 		dns_db_detach(&devent->db);
   9628 	}
   9629 	isc_event_free(&event);
   9630 	dns_resolver_destroyfetch(&kfetch->fetch);
   9631 
   9632 	LOCK_ZONE(zone);
   9633 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
   9634 		goto cleanup;
   9635 	}
   9636 
   9637 	isc_stdtime_get(&now);
   9638 	dns_name_format(keyname, namebuf, sizeof(namebuf));
   9639 
   9640 	result = dns_view_getsecroots(zone->view, &secroots);
   9641 	INSIST(result == ISC_R_SUCCESS);
   9642 
   9643 	dns_diff_init(mctx, &diff);
   9644 
   9645 	CHECK(dns_db_newversion(kfetch->db, &ver));
   9646 
   9647 	zone->refreshkeycount--;
   9648 	alldone = (zone->refreshkeycount == 0);
   9649 
   9650 	if (alldone) {
   9651 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
   9652 	}
   9653 
   9654 	dnssec_log(zone, ISC_LOG_DEBUG(3),
   9655 		   "Returned from key fetch in keyfetch_done() for '%s': %s",
   9656 		   namebuf, dns_result_totext(eresult));
   9657 
   9658 	/* Fetch failed */
   9659 	if (eresult != ISC_R_SUCCESS ||
   9660 	    !dns_rdataset_isassociated(&kfetch->dnskeyset))
   9661 	{
   9662 		dnssec_log(zone, ISC_LOG_WARNING,
   9663 			   "Unable to fetch DNSKEY set '%s': %s",
   9664 			   namebuf, dns_result_totext(eresult));
   9665 		CHECK(minimal_update(kfetch, ver, &diff));
   9666 		goto done;
   9667 	}
   9668 
   9669 	/* No RRSIGs found */
   9670 	if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
   9671 		dnssec_log(zone, ISC_LOG_WARNING,
   9672 			   "No DNSKEY RRSIGs found for '%s': %s",
   9673 			   namebuf, dns_result_totext(eresult));
   9674 		CHECK(minimal_update(kfetch, ver, &diff));
   9675 		goto done;
   9676 	}
   9677 
   9678 	/*
   9679 	 * Clear any cached trust level, as we need to run validation
   9680 	 * over again; trusted keys might have changed.
   9681 	 */
   9682 	kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none;
   9683 
   9684 	/*
   9685 	 * Validate the dnskeyset against the current trusted keys.
   9686 	 */
   9687 	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
   9688 	     result == ISC_R_SUCCESS;
   9689 	     result = dns_rdataset_next(&kfetch->dnskeysigset))
   9690 	{
   9691 		dns_keynode_t *keynode = NULL;
   9692 
   9693 		dns_rdata_reset(&sigrr);
   9694 		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
   9695 		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
   9696 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9697 
   9698 		result = dns_keytable_find(secroots, keyname, &keynode);
   9699 		while (result == ISC_R_SUCCESS) {
   9700 			dns_keynode_t *nextnode = NULL;
   9701 			dns_fixedname_t fixed;
   9702 			dns_fixedname_init(&fixed);
   9703 
   9704 			dstkey = dns_keynode_key(keynode);
   9705 			if (dstkey == NULL) {
   9706 				/* fail_secure() was called */
   9707 				break;
   9708 			}
   9709 
   9710 			if (dst_key_alg(dstkey) == sig.algorithm &&
   9711 			    dst_key_id(dstkey) == sig.keyid)
   9712 			{
   9713 				result = dns_dnssec_verify(keyname,
   9714 							   &kfetch->dnskeyset,
   9715 							   dstkey, false,
   9716 							   0,
   9717 							   zone->view->mctx,
   9718 							   &sigrr,
   9719 							   dns_fixedname_name(
   9720 							   &fixed));
   9721 
   9722 				dnssec_log(zone, ISC_LOG_DEBUG(3),
   9723 					   "Verifying DNSKEY set for zone "
   9724 					   "'%s' using key %d/%d: %s",
   9725 					   namebuf, sig.keyid, sig.algorithm,
   9726 					   dns_result_totext(result));
   9727 
   9728 				if (result == ISC_R_SUCCESS) {
   9729 					kfetch->dnskeyset.trust =
   9730 						dns_trust_secure;
   9731 					kfetch->dnskeysigset.trust =
   9732 						dns_trust_secure;
   9733 					secure = true;
   9734 					initial = dns_keynode_initial(keynode);
   9735 					dns_keynode_trust(keynode);
   9736 					break;
   9737 				}
   9738 			}
   9739 
   9740 			result = dns_keytable_nextkeynode(secroots,
   9741 							  keynode, &nextnode);
   9742 			dns_keytable_detachkeynode(secroots, &keynode);
   9743 			keynode = nextnode;
   9744 		}
   9745 
   9746 		if (keynode != NULL) {
   9747 			dns_keytable_detachkeynode(secroots, &keynode);
   9748 		}
   9749 
   9750 		if (secure) {
   9751 			break;
   9752 		}
   9753 	}
   9754 
   9755 	/*
   9756 	 * If we were not able to verify the answer using the current
   9757 	 * trusted keys then all we can do is look at any revoked keys.
   9758 	 */
   9759 	if (!secure) {
   9760 		dnssec_log(zone, ISC_LOG_INFO,
   9761 			   "DNSKEY set for zone '%s' could not be verified "
   9762 			   "with current keys", namebuf);
   9763 	}
   9764 
   9765 	/*
   9766 	 * First scan keydataset to find keys that are not in dnskeyset
   9767 	 *   - Missing keys which are not scheduled for removal,
   9768 	 *     log a warning
   9769 	 *   - Missing keys which are scheduled for removal and
   9770 	 *     the remove hold-down timer has completed should
   9771 	 *     be removed from the key zone
   9772 	 *   - Missing keys whose acceptance timers have not yet
   9773 	 *     completed, log a warning and reset the acceptance
   9774 	 *     timer to 30 days in the future
   9775 	 *   - All keys not being removed have their refresh timers
   9776 	 *     updated
   9777 	 */
   9778 	initializing = true;
   9779 	for (result = dns_rdataset_first(&kfetch->keydataset);
   9780 	     result == ISC_R_SUCCESS;
   9781 	     result = dns_rdataset_next(&kfetch->keydataset))
   9782 	{
   9783 		dns_keytag_t keytag;
   9784 
   9785 		dns_rdata_reset(&keydatarr);
   9786 		dns_rdataset_current(&kfetch->keydataset, &keydatarr);
   9787 		result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
   9788 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9789 
   9790 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
   9791 		result = compute_tag(keyname, &dnskey, mctx, &keytag);
   9792 		if (result != ISC_R_SUCCESS) {
   9793 			/*
   9794 			 * Skip if we cannot compute the key tag.
   9795 			 * This may happen if the algorithm is unsupported
   9796 			 */
   9797 			dns_zone_log(zone, ISC_LOG_ERROR,
   9798 				"Cannot compute tag for key in zone %s: %s "
   9799 				"(skipping)",
   9800 				namebuf, dns_result_totext(result));
   9801 			continue;
   9802 		}
   9803 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9804 
   9805 		/*
   9806 		 * If any keydata record has a nonzero add holddown, then
   9807 		 * there was a pre-existing trust anchor for this domain;
   9808 		 * that means we are *not* initializing it and shouldn't
   9809 		 * automatically trust all the keys we find at the zone apex.
   9810 		 */
   9811 		initializing = initializing && (keydata.addhd == 0);
   9812 
   9813 		if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
   9814 			bool deletekey = false;
   9815 
   9816 			if (!secure) {
   9817 				if (keydata.removehd != 0 &&
   9818 				    keydata.removehd <= now)
   9819 				{
   9820 					deletekey = true;
   9821 				}
   9822 			} else if (keydata.addhd == 0) {
   9823 				deletekey = true;
   9824 			} else if (keydata.addhd > now) {
   9825 				dnssec_log(zone, ISC_LOG_INFO,
   9826 					   "Pending key %d for zone %s "
   9827 					   "unexpectedly missing "
   9828 					   "restarting 30-day acceptance "
   9829 					   "timer", keytag, namebuf);
   9830 				if (keydata.addhd < now + dns_zone_mkey_month) {
   9831 					keydata.addhd =
   9832 						now + dns_zone_mkey_month;
   9833 				}
   9834 				keydata.refresh = refresh_time(kfetch, false);
   9835 			} else if (keydata.removehd == 0) {
   9836 				dnssec_log(zone, ISC_LOG_INFO,
   9837 					   "Active key %d for zone %s "
   9838 					   "unexpectedly missing",
   9839 					   keytag, namebuf);
   9840 				keydata.refresh = now + dns_zone_mkey_hour;
   9841 			} else if (keydata.removehd <= now) {
   9842 				deletekey = true;
   9843 				dnssec_log(zone, ISC_LOG_INFO,
   9844 					   "Revoked key %d for zone %s "
   9845 					   "missing: deleting from "
   9846 					   "managed keys database",
   9847 					   keytag, namebuf);
   9848 			} else {
   9849 				keydata.refresh = refresh_time(kfetch, false);
   9850 			}
   9851 
   9852 			if (secure || deletekey) {
   9853 				/* Delete old version */
   9854 				CHECK(update_one_rr(kfetch->db, ver, &diff,
   9855 						    DNS_DIFFOP_DEL, keyname, 0,
   9856 						    &keydatarr));
   9857 			}
   9858 
   9859 			if (!secure || deletekey) {
   9860 				continue;
   9861 			}
   9862 
   9863 			dns_rdata_reset(&keydatarr);
   9864 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   9865 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
   9866 					     dns_rdatatype_keydata,
   9867 					     &keydata, &keyb);
   9868 
   9869 			/* Insert updated version */
   9870 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   9871 					    DNS_DIFFOP_ADD, keyname, 0,
   9872 					    &keydatarr));
   9873 
   9874 			set_refreshkeytimer(zone, &keydata, now, false);
   9875 		}
   9876 	}
   9877 
   9878 	/*
   9879 	 * Next scan dnskeyset:
   9880 	 *   - If new keys are found (i.e., lacking a match in keydataset)
   9881 	 *     add them to the key zone and set the acceptance timer
   9882 	 *     to 30 days in the future (or to immediately if we've
   9883 	 *     determined that we're initializing the zone for the
   9884 	 *     first time)
   9885 	 *   - Previously-known keys that have been revoked
   9886 	 *     must be scheduled for removal from the key zone (or,
   9887 	 *     if they hadn't been accepted as trust anchors yet
   9888 	 *     anyway, removed at once)
   9889 	 *   - Previously-known unrevoked keys whose acceptance timers
   9890 	 *     have completed are promoted to trust anchors
   9891 	 *   - All keys not being removed have their refresh
   9892 	 *     timers updated
   9893 	 */
   9894 	for (result = dns_rdataset_first(&kfetch->dnskeyset);
   9895 	     result == ISC_R_SUCCESS;
   9896 	     result = dns_rdataset_next(&kfetch->dnskeyset))
   9897 	{
   9898 		bool revoked = false;
   9899 		bool newkey = false;
   9900 		bool updatekey = false;
   9901 		bool deletekey = false;
   9902 		bool trustkey = false;
   9903 		dns_keytag_t keytag;
   9904 
   9905 		dns_rdata_reset(&dnskeyrr);
   9906 		dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
   9907 		result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
   9908 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9909 
   9910 		/* Skip ZSK's */
   9911 		if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
   9912 			continue;
   9913 		}
   9914 
   9915 		result = compute_tag(keyname, &dnskey, mctx, &keytag);
   9916 		if (result != ISC_R_SUCCESS) {
   9917 			/*
   9918 			 * Skip if we cannot compute the key tag.
   9919 			 * This may happen if the algorithm is unsupported
   9920 			 */
   9921 			dns_zone_log(zone, ISC_LOG_ERROR,
   9922 				"Cannot compute tag for key in zone %s: %s "
   9923 				"(skipping)",
   9924 				namebuf, dns_result_totext(result));
   9925 			continue;
   9926 		}
   9927 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9928 
   9929 		revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
   9930 
   9931 		if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
   9932 			dns_rdata_reset(&keydatarr);
   9933 			dns_rdataset_current(&kfetch->keydataset, &keydatarr);
   9934 			result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
   9935 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9936 
   9937 			if (revoked && revocable(kfetch, &keydata)) {
   9938 				if (keydata.addhd > now) {
   9939 					/*
   9940 					 * Key wasn't trusted yet, and now
   9941 					 * it's been revoked?  Just remove it
   9942 					 */
   9943 					deletekey = true;
   9944 					dnssec_log(zone, ISC_LOG_INFO,
   9945 						   "Pending key %d for "
   9946 						   "zone %s is now revoked: "
   9947 						   "deleting from the "
   9948 						   "managed keys database",
   9949 						   keytag, namebuf);
   9950 				} else if (keydata.removehd == 0) {
   9951 					/*
   9952 					 * Remove key from secroots.
   9953 					 */
   9954 					dns_view_untrust(zone->view, keyname,
   9955 							 &dnskey, mctx);
   9956 
   9957 					/* If initializing, delete now */
   9958 					if (keydata.addhd == 0) {
   9959 						deletekey = true;
   9960 					} else {
   9961 						keydata.removehd = now +
   9962 							dns_zone_mkey_month;
   9963 						keydata.flags |=
   9964 							DNS_KEYFLAG_REVOKE;
   9965 					}
   9966 
   9967 					dnssec_log(zone, ISC_LOG_INFO,
   9968 						   "Trusted key %d for "
   9969 						   "zone %s is now revoked",
   9970 						   keytag, namebuf);
   9971 				} else if (keydata.removehd < now) {
   9972 					/* Scheduled for removal */
   9973 					deletekey = true;
   9974 
   9975 					dnssec_log(zone, ISC_LOG_INFO,
   9976 						   "Revoked key %d for "
   9977 						   "zone %s removal timer "
   9978 						   "complete: deleting from "
   9979 						   "the managed keys database",
   9980 						   keytag, namebuf);
   9981 				}
   9982 			} else if (revoked && keydata.removehd == 0) {
   9983 				dnssec_log(zone, ISC_LOG_WARNING,
   9984 					   "Active key %d for zone "
   9985 					   "%s is revoked but "
   9986 					   "did not self-sign; "
   9987 					   "ignoring", keytag, namebuf);
   9988 				continue;
   9989 			} else if (secure) {
   9990 				if (keydata.removehd != 0) {
   9991 					/*
   9992 					 * Key isn't revoked--but it
   9993 					 * seems it used to be.
   9994 					 * Remove it now and add it
   9995 					 * back as if it were a fresh key,
   9996 					 * with a 30-day acceptance timer.
   9997 					 */
   9998 					deletekey = true;
   9999 					newkey = true;
   10000 					keydata.removehd = 0;
   10001 					keydata.addhd =
   10002 						now + dns_zone_mkey_month;
   10003 
   10004 					dnssec_log(zone, ISC_LOG_INFO,
   10005 						   "Revoked key %d for "
   10006 						   "zone %s has returned: "
   10007 						   "starting 30-day "
   10008 						   "acceptance timer",
   10009 						   keytag, namebuf);
   10010 				} else if (keydata.addhd > now) {
   10011 					pending++;
   10012 				} else if (keydata.addhd == 0) {
   10013 					keydata.addhd = now;
   10014 				}
   10015 
   10016 				if (keydata.addhd <= now) {
   10017 					trustkey = true;
   10018 					dnssec_log(zone, ISC_LOG_INFO,
   10019 						   "Key %d for zone %s "
   10020 						   "is now trusted (%s)",
   10021 						   keytag, namebuf,
   10022 						   initial
   10023 						    ? "initializing key "
   10024 						       "verified"
   10025 						    : "acceptance timer "
   10026 						       "complete");
   10027 				}
   10028 			} else if (keydata.addhd > now) {
   10029 				/*
   10030 				 * Not secure, and key is pending:
   10031 				 * reset the acceptance timer
   10032 				 */
   10033 				pending++;
   10034 				keydata.addhd = now + dns_zone_mkey_month;
   10035 				dnssec_log(zone, ISC_LOG_INFO,
   10036 					   "Pending key %d "
   10037 					   "for zone %s was "
   10038 					   "not validated: restarting "
   10039 					   "30-day acceptance timer",
   10040 					   keytag, namebuf);
   10041 			}
   10042 
   10043 			if (!deletekey && !newkey) {
   10044 				updatekey = true;
   10045 			}
   10046 		} else if (secure) {
   10047 			/*
   10048 			 * Key wasn't in the key zone but it's
   10049 			 * revoked now anyway, so just skip it
   10050 			 */
   10051 			if (revoked) {
   10052 				continue;
   10053 			}
   10054 
   10055 			/* Key wasn't in the key zone: add it */
   10056 			newkey = true;
   10057 
   10058 			if (initializing) {
   10059 				dnssec_log(zone, ISC_LOG_WARNING,
   10060 					   "Initializing automatic trust "
   10061 					   "anchor management for zone '%s'; "
   10062 					   "DNSKEY ID %d is now trusted, "
   10063 					   "waiving the normal 30-day "
   10064 					   "waiting period.",
   10065 					   namebuf, keytag);
   10066 				trustkey = true;
   10067 			} else {
   10068 				dnssec_log(zone, ISC_LOG_INFO,
   10069 					   "New key %d observed "
   10070 					   "for zone '%s': "
   10071 					   "starting 30-day "
   10072 					   "acceptance timer",
   10073 					   keytag, namebuf);
   10074 			}
   10075 		} else {
   10076 			/*
   10077 			 * No previously known key, and the key is not
   10078 			 * secure, so skip it.
   10079 			 */
   10080 			continue;
   10081 		}
   10082 
   10083 		/* Delete old version */
   10084 		if (deletekey || !newkey) {
   10085 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   10086 					    DNS_DIFFOP_DEL, keyname, 0,
   10087 					    &keydatarr));
   10088 		}
   10089 
   10090 		if (updatekey) {
   10091 			/* Set refresh timer */
   10092 			keydata.refresh = refresh_time(kfetch, false);
   10093 			dns_rdata_reset(&keydatarr);
   10094 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   10095 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
   10096 					     dns_rdatatype_keydata,
   10097 					     &keydata, &keyb);
   10098 
   10099 			/* Insert updated version */
   10100 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   10101 					    DNS_DIFFOP_ADD, keyname, 0,
   10102 					    &keydatarr));
   10103 		} else if (newkey) {
   10104 			/* Convert DNSKEY to KEYDATA */
   10105 			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
   10106 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10107 			dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
   10108 					       NULL);
   10109 			keydata.addhd = initializing
   10110 					 ? now : now + dns_zone_mkey_month;
   10111 			keydata.refresh = refresh_time(kfetch, false);
   10112 			dns_rdata_reset(&keydatarr);
   10113 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   10114 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
   10115 					     dns_rdatatype_keydata,
   10116 					     &keydata, &keyb);
   10117 
   10118 			/* Insert into key zone */
   10119 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   10120 					    DNS_DIFFOP_ADD, keyname, 0,
   10121 					    &keydatarr));
   10122 		}
   10123 
   10124 		if (trustkey) {
   10125 			/* Trust this key. */
   10126 			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
   10127 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10128 			trust_key(zone, keyname, &dnskey, false, mctx);
   10129 		}
   10130 
   10131 		if (secure && !deletekey) {
   10132 			INSIST(newkey || updatekey);
   10133 			set_refreshkeytimer(zone, &keydata, now, false);
   10134 		}
   10135 	}
   10136 
   10137 	/*
   10138 	 * RFC5011 says, "A trust point that has all of its trust anchors
   10139 	 * revoked is considered deleted and is treated as if the trust
   10140 	 * point was never configured."  But if someone revoked their
   10141 	 * active key before the standby was trusted, that would mean the
   10142 	 * zone would suddenly be nonsecured.  We avoid this by checking to
   10143 	 * see if there's pending keydata.  If so, we put a null key in
   10144 	 * the security roots; then all queries to the zone will fail.
   10145 	 */
   10146 	if (pending != 0) {
   10147 		fail_secure(zone, keyname);
   10148 	}
   10149 
   10150  done:
   10151 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   10152 		/* Write changes to journal file. */
   10153 		CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
   10154 					zone->updatemethod));
   10155 		CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
   10156 		commit = true;
   10157 
   10158 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   10159 		zone_needdump(zone, 30);
   10160 	} else if (result == ISC_R_NOMORE) {
   10161 		/*
   10162 		 * If "updatekey" was true for all keys found in the DNSKEY
   10163 		 * response and the previous update of those keys happened
   10164 		 * during the same second (only possible if a key refresh was
   10165 		 * externally triggered), it may happen that all relevant
   10166 		 * update_one_rr() calls will return ISC_R_SUCCESS, but
   10167 		 * diff.tuples will remain empty.  Reset result to
   10168 		 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
   10169 		 */
   10170 		result = ISC_R_SUCCESS;
   10171 	}
   10172 
   10173  failure:
   10174 	if (result != ISC_R_SUCCESS) {
   10175 		dnssec_log(zone, ISC_LOG_ERROR,
   10176 			   "error during managed-keys processing (%s): "
   10177 			   "DNSSEC validation may be at risk",
   10178 			   isc_result_totext(result));
   10179 	}
   10180 	dns_diff_clear(&diff);
   10181 	if (ver != NULL) {
   10182 		dns_db_closeversion(kfetch->db, &ver, commit);
   10183 	}
   10184 
   10185  cleanup:
   10186 	dns_db_detach(&kfetch->db);
   10187 
   10188 	INSIST(zone->irefs > 0);
   10189 	zone->irefs--;
   10190 	kfetch->zone = NULL;
   10191 
   10192 	if (dns_rdataset_isassociated(&kfetch->keydataset)) {
   10193 		dns_rdataset_disassociate(&kfetch->keydataset);
   10194 	}
   10195 	if (dns_rdataset_isassociated(&kfetch->dnskeyset)) {
   10196 		dns_rdataset_disassociate(&kfetch->dnskeyset);
   10197 	}
   10198 	if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
   10199 		dns_rdataset_disassociate(&kfetch->dnskeysigset);
   10200 	}
   10201 
   10202 	dns_name_free(keyname, mctx);
   10203 	isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
   10204 	isc_mem_detach(&mctx);
   10205 
   10206 	if (secroots != NULL) {
   10207 		dns_keytable_detach(&secroots);
   10208 	}
   10209 
   10210 	free_needed = exit_check(zone);
   10211 	UNLOCK_ZONE(zone);
   10212 	if (free_needed) {
   10213 		zone_free(zone);
   10214 	}
   10215 
   10216 	INSIST(ver == NULL);
   10217 }
   10218 
   10219 /*
   10220  * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
   10221  * records from the zone apex.
   10222  */
   10223 static void
   10224 zone_refreshkeys(dns_zone_t *zone) {
   10225 	const char me[] = "zone_refreshkeys";
   10226 	isc_result_t result;
   10227 	dns_rriterator_t rrit;
   10228 	dns_db_t *db = NULL;
   10229 	dns_dbversion_t *ver = NULL;
   10230 	dns_diff_t diff;
   10231 	dns_rdata_t rdata = DNS_RDATA_INIT;
   10232 	dns_rdata_keydata_t kd;
   10233 	isc_stdtime_t now;
   10234 	bool commit = false;
   10235 	bool fetching = false, fetch_err = false;
   10236 	bool timerset = false;
   10237 
   10238 	ENTER;
   10239 	REQUIRE(zone->db != NULL);
   10240 
   10241 	isc_stdtime_get(&now);
   10242 
   10243 	LOCK_ZONE(zone);
   10244 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   10245 		isc_time_settoepoch(&zone->refreshkeytime);
   10246 		UNLOCK_ZONE(zone);
   10247 		return;
   10248 	}
   10249 
   10250 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   10251 	dns_db_attach(zone->db, &db);
   10252 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   10253 
   10254 	dns_diff_init(zone->mctx, &diff);
   10255 
   10256 	CHECK(dns_db_newversion(db, &ver));
   10257 
   10258 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
   10259 
   10260 	dns_rriterator_init(&rrit, db, ver, 0);
   10261 	for (result = dns_rriterator_first(&rrit);
   10262 	     result == ISC_R_SUCCESS;
   10263 	     result = dns_rriterator_nextrrset(&rrit))
   10264 	{
   10265 		isc_stdtime_t timer = 0xffffffff;
   10266 		dns_name_t *name = NULL, *kname = NULL;
   10267 		dns_rdataset_t *kdset = NULL;
   10268 		dns_keyfetch_t *kfetch;
   10269 		uint32_t ttl;
   10270 
   10271 		dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
   10272 		if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
   10273 		    !dns_rdataset_isassociated(kdset))
   10274 		{
   10275 			continue;
   10276 		}
   10277 
   10278 		/*
   10279 		 * Scan the stored keys looking for ones that need
   10280 		 * removal or refreshing
   10281 		 */
   10282 		for (result = dns_rdataset_first(kdset);
   10283 		     result == ISC_R_SUCCESS;
   10284 		     result = dns_rdataset_next(kdset))
   10285 		{
   10286 			dns_rdata_reset(&rdata);
   10287 			dns_rdataset_current(kdset, &rdata);
   10288 			result = dns_rdata_tostruct(&rdata, &kd, NULL);
   10289 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   10290 
   10291 			/* Removal timer expired? */
   10292 			if (kd.removehd != 0 && kd.removehd < now) {
   10293 				CHECK(update_one_rr(db, ver, &diff,
   10294 						    DNS_DIFFOP_DEL, name, ttl,
   10295 						    &rdata));
   10296 				continue;
   10297 			}
   10298 
   10299 			/* Acceptance timer expired? */
   10300 			if (kd.addhd <= now) {
   10301 				timer = kd.addhd;
   10302 			}
   10303 
   10304 			/* Or do we just need to refresh the keyset? */
   10305 			if (timer > kd.refresh) {
   10306 				timer = kd.refresh;
   10307 			}
   10308 
   10309 			set_refreshkeytimer(zone, &kd, now, false);
   10310 			timerset = true;
   10311 		}
   10312 
   10313 		if (timer > now) {
   10314 			continue;
   10315 		}
   10316 
   10317 		kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
   10318 		if (kfetch == NULL) {
   10319 			fetch_err = true;
   10320 			goto failure;
   10321 		}
   10322 
   10323 		zone->refreshkeycount++;
   10324 		kfetch->zone = zone;
   10325 		zone->irefs++;
   10326 		INSIST(zone->irefs != 0);
   10327 		kname = dns_fixedname_initname(&kfetch->name);
   10328 		dns_name_dup(name, zone->mctx, kname);
   10329 		dns_rdataset_init(&kfetch->dnskeyset);
   10330 		dns_rdataset_init(&kfetch->dnskeysigset);
   10331 		dns_rdataset_init(&kfetch->keydataset);
   10332 		dns_rdataset_clone(kdset, &kfetch->keydataset);
   10333 		kfetch->db = NULL;
   10334 		dns_db_attach(db, &kfetch->db);
   10335 		kfetch->fetch = NULL;
   10336 
   10337 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   10338 			char namebuf[DNS_NAME_FORMATSIZE];
   10339 			dns_name_format(kname, namebuf,
   10340 					sizeof(namebuf));
   10341 			dnssec_log(zone, ISC_LOG_DEBUG(3),
   10342 				   "Creating key fetch in "
   10343 				   "zone_refreshkeys() for '%s'",
   10344 				   namebuf);
   10345 		}
   10346 
   10347 		/*
   10348 		 * Use of DNS_FETCHOPT_NOCACHED is essential here.  If it is
   10349 		 * not set and the cache still holds a non-expired, validated
   10350 		 * version of the RRset being queried for by the time the
   10351 		 * response is received, the cached RRset will be passed to
   10352 		 * keyfetch_done() instead of the one received in the response
   10353 		 * as the latter will have a lower trust level due to not being
   10354 		 * validated until keyfetch_done() is called.
   10355 		 */
   10356 
   10357 #ifdef ENABLE_AFL
   10358 		if (dns_fuzzing_resolver == false) {
   10359 #endif
   10360 		result = dns_resolver_createfetch(zone->view->resolver,
   10361 						  kname, dns_rdatatype_dnskey,
   10362 						  NULL, NULL, NULL, NULL, 0,
   10363 						  DNS_FETCHOPT_NOVALIDATE |
   10364 						  DNS_FETCHOPT_UNSHARED |
   10365 						  DNS_FETCHOPT_NOCACHED,
   10366 						  0, NULL, zone->task,
   10367 						  keyfetch_done, kfetch,
   10368 						  &kfetch->dnskeyset,
   10369 						  &kfetch->dnskeysigset,
   10370 						  &kfetch->fetch);
   10371 #ifdef ENABLE_AFL
   10372 		} else {
   10373 			result = ISC_R_FAILURE;
   10374 		}
   10375 #endif
   10376 		if (result == ISC_R_SUCCESS) {
   10377 			fetching = true;
   10378 		} else {
   10379 			zone->refreshkeycount--;
   10380 			zone->irefs--;
   10381 			dns_db_detach(&kfetch->db);
   10382 			dns_rdataset_disassociate(&kfetch->keydataset);
   10383 			dns_name_free(kname, zone->mctx);
   10384 			isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
   10385 			dnssec_log(zone, ISC_LOG_WARNING,
   10386 				   "Failed to create fetch for DNSKEY update");
   10387 			fetch_err = true;
   10388 		}
   10389 	}
   10390 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   10391 		CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
   10392 					zone->updatemethod));
   10393 		CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
   10394 		commit = true;
   10395 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   10396 		zone_needdump(zone, 30);
   10397 	}
   10398 
   10399   failure:
   10400 	if (fetch_err) {
   10401 		/*
   10402 		 * Error during a key fetch; retry in an hour.
   10403 		 */
   10404 		isc_time_t timenow, timethen;
   10405 		char timebuf[80];
   10406 
   10407 		TIME_NOW(&timenow);
   10408 		DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
   10409 		zone->refreshkeytime = timethen;
   10410 		zone_settimer(zone, &timenow);
   10411 
   10412 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   10413 		dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
   10414 			   timebuf);
   10415 	} else if (!timerset) {
   10416 		isc_time_settoepoch(&zone->refreshkeytime);
   10417 	}
   10418 
   10419 	if (!fetching) {
   10420 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
   10421 	}
   10422 
   10423 	dns_diff_clear(&diff);
   10424 	if (ver != NULL) {
   10425 		dns_rriterator_destroy(&rrit);
   10426 		dns_db_closeversion(db, &ver, commit);
   10427 	}
   10428 	dns_db_detach(&db);
   10429 
   10430 	UNLOCK_ZONE(zone);
   10431 
   10432 	INSIST(ver == NULL);
   10433 }
   10434 
   10435 static void
   10436 zone_maintenance(dns_zone_t *zone) {
   10437 	const char me[] = "zone_maintenance";
   10438 	isc_time_t now;
   10439 	isc_result_t result;
   10440 	bool dumping, load_pending;
   10441 
   10442 	REQUIRE(DNS_ZONE_VALID(zone));
   10443 	ENTER;
   10444 
   10445 	/*
   10446 	 * Are we pending load/reload?
   10447 	 */
   10448 	LOCK_ZONE(zone);
   10449 	load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
   10450 	UNLOCK_ZONE(zone);
   10451 
   10452 	if (load_pending) {
   10453 		return;
   10454 	}
   10455 
   10456 	/*
   10457 	 * Configuring the view of this zone may have
   10458 	 * failed, for example because the config file
   10459 	 * had a syntax error.	In that case, the view
   10460 	 * adb or resolver will be NULL, and we had better not try
   10461 	 * to do further maintenance on it.
   10462 	 */
   10463 	if (zone->view == NULL || zone->view->adb == NULL)
   10464 		return;
   10465 
   10466 	TIME_NOW(&now);
   10467 
   10468 	/*
   10469 	 * Expire check.
   10470 	 */
   10471 	switch (zone->type) {
   10472 	case dns_zone_redirect:
   10473 		if (zone->masters == NULL)
   10474 			break;
   10475 		/* FALLTHROUGH */
   10476 	case dns_zone_slave:
   10477 	case dns_zone_mirror:
   10478 	case dns_zone_stub:
   10479 		LOCK_ZONE(zone);
   10480 		if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
   10481 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   10482 			zone_expire(zone);
   10483 			zone->refreshtime = now;
   10484 		}
   10485 		UNLOCK_ZONE(zone);
   10486 		break;
   10487 	default:
   10488 		break;
   10489 	}
   10490 
   10491 	/*
   10492 	 * Up to date check.
   10493 	 */
   10494 	switch (zone->type) {
   10495 	case dns_zone_redirect:
   10496 		if (zone->masters == NULL)
   10497 			break;
   10498 		/* FALLTHROUGH */
   10499 	case dns_zone_slave:
   10500 	case dns_zone_mirror:
   10501 	case dns_zone_stub:
   10502 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
   10503 		    isc_time_compare(&now, &zone->refreshtime) >= 0)
   10504 			dns_zone_refresh(zone);
   10505 		break;
   10506 	default:
   10507 		break;
   10508 	}
   10509 
   10510 	/*
   10511 	 * Slaves send notifies before backing up to disk, masters after.
   10512 	 */
   10513 	if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror) &&
   10514 	    (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   10515 	     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
   10516 	    isc_time_compare(&now, &zone->notifytime) >= 0)
   10517 		zone_notify(zone, &now);
   10518 
   10519 	/*
   10520 	 * Do we need to consolidate the backing store?
   10521 	 */
   10522 	switch (zone->type) {
   10523 	case dns_zone_master:
   10524 	case dns_zone_slave:
   10525 	case dns_zone_mirror:
   10526 	case dns_zone_key:
   10527 	case dns_zone_redirect:
   10528 	case dns_zone_stub:
   10529 		LOCK_ZONE(zone);
   10530 		if (zone->masterfile != NULL &&
   10531 		    isc_time_compare(&now, &zone->dumptime) >= 0 &&
   10532 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   10533 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
   10534 			dumping = was_dumping(zone);
   10535 		} else
   10536 			dumping = true;
   10537 		UNLOCK_ZONE(zone);
   10538 		if (!dumping) {
   10539 			result = zone_dump(zone, true); /* task locked */
   10540 			if (result != ISC_R_SUCCESS)
   10541 				dns_zone_log(zone, ISC_LOG_WARNING,
   10542 					     "dump failed: %s",
   10543 					     dns_result_totext(result));
   10544 		}
   10545 		break;
   10546 	default:
   10547 		break;
   10548 	}
   10549 
   10550 	/*
   10551 	 * Master/redirect zones send notifies now, if needed
   10552 	 */
   10553 	switch (zone->type) {
   10554 	case dns_zone_master:
   10555 	case dns_zone_redirect:
   10556 		if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   10557 		     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))&&
   10558 		    isc_time_compare(&now, &zone->notifytime) >= 0)
   10559 			zone_notify(zone, &now);
   10560 	default:
   10561 		break;
   10562 	}
   10563 
   10564 	/*
   10565 	 * Do we need to refresh keys?
   10566 	 */
   10567 	switch (zone->type) {
   10568 	case dns_zone_key:
   10569 		if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
   10570 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   10571 			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
   10572 				zone_refreshkeys(zone);
   10573 			}
   10574 		}
   10575 		break;
   10576 	case dns_zone_master:
   10577 		if (!isc_time_isepoch(&zone->refreshkeytime) &&
   10578 		    isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
   10579 		    zone->rss_event == NULL)
   10580 			zone_rekey(zone);
   10581 	default:
   10582 		break;
   10583 	}
   10584 
   10585 	switch (zone->type) {
   10586 	case dns_zone_master:
   10587 	case dns_zone_redirect:
   10588 	case dns_zone_slave:
   10589 		/*
   10590 		 * Do we need to sign/resign some RRsets?
   10591 		 */
   10592 		if (zone->rss_event != NULL)
   10593 			break;
   10594 		if (!isc_time_isepoch(&zone->signingtime) &&
   10595 		    isc_time_compare(&now, &zone->signingtime) >= 0) {
   10596 			zone_sign(zone);
   10597 		}
   10598 		else if (!isc_time_isepoch(&zone->resigntime) &&
   10599 		    isc_time_compare(&now, &zone->resigntime) >= 0) {
   10600 			zone_resigninc(zone);
   10601 		}
   10602 		else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
   10603 			isc_time_compare(&now, &zone->nsec3chaintime) >= 0) {
   10604 			zone_nsec3chain(zone);
   10605 		}
   10606 		/*
   10607 		 * Do we need to issue a key expiry warning?
   10608 		 */
   10609 		if (!isc_time_isepoch(&zone->keywarntime) &&
   10610 		    isc_time_compare(&now, &zone->keywarntime) >= 0)
   10611 			set_key_expiry_warning(zone, zone->key_expiry,
   10612 					       isc_time_seconds(&now));
   10613 		break;
   10614 
   10615 	default:
   10616 		break;
   10617 	}
   10618 	zone_settimer(zone, &now);
   10619 }
   10620 
   10621 void
   10622 dns_zone_markdirty(dns_zone_t *zone) {
   10623 	uint32_t serial;
   10624 	isc_result_t result = ISC_R_SUCCESS;
   10625 	dns_zone_t *secure = NULL;
   10626 
   10627 	/*
   10628 	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
   10629 	 * could result in a deadlock due to a LOR so we will spin if we
   10630 	 * can't obtain the both locks.
   10631 	 */
   10632  again:
   10633 	LOCK_ZONE(zone);
   10634 	if (zone->type == dns_zone_master) {
   10635 		if (inline_raw(zone)) {
   10636 			unsigned int soacount;
   10637 			secure = zone->secure;
   10638 			INSIST(secure != zone);
   10639 			TRYLOCK_ZONE(result, secure);
   10640 			if (result != ISC_R_SUCCESS) {
   10641 				UNLOCK_ZONE(zone);
   10642 				secure = NULL;
   10643 				isc_thread_yield();
   10644 				goto again;
   10645 			}
   10646 
   10647 			ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   10648 			if (zone->db != NULL) {
   10649 				result = zone_get_from_db(zone, zone->db, NULL,
   10650 							  &soacount, &serial,
   10651 							  NULL, NULL, NULL,
   10652 							  NULL, NULL);
   10653 			} else
   10654 				result = DNS_R_NOTLOADED;
   10655 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   10656 			if (result == ISC_R_SUCCESS && soacount > 0U)
   10657 				zone_send_secureserial(zone, serial);
   10658 		}
   10659 
   10660 		/* XXXMPA make separate call back */
   10661 		if (result == ISC_R_SUCCESS)
   10662 			set_resigntime(zone);
   10663 	}
   10664 	if (secure != NULL)
   10665 		UNLOCK_ZONE(secure);
   10666 	zone_needdump(zone, DNS_DUMP_DELAY);
   10667 	UNLOCK_ZONE(zone);
   10668 }
   10669 
   10670 void
   10671 dns_zone_expire(dns_zone_t *zone) {
   10672 	REQUIRE(DNS_ZONE_VALID(zone));
   10673 
   10674 	LOCK_ZONE(zone);
   10675 	zone_expire(zone);
   10676 	UNLOCK_ZONE(zone);
   10677 }
   10678 
   10679 static void
   10680 zone_expire(dns_zone_t *zone) {
   10681 	dns_db_t *db = NULL;
   10682 
   10683 	/*
   10684 	 * 'zone' locked by caller.
   10685 	 */
   10686 
   10687 	REQUIRE(LOCKED_ZONE(zone));
   10688 
   10689 	dns_zone_log(zone, ISC_LOG_WARNING, "expired");
   10690 
   10691 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
   10692 	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
   10693 	zone->retry = DNS_ZONE_DEFAULTRETRY;
   10694 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   10695 
   10696 	/*
   10697 	 * An RPZ zone has expired; before unloading it, we must
   10698 	 * first remove it from the RPZ summary database. The
   10699 	 * easiest way to do this is "update" it with an empty
   10700 	 * database so that the update callback synchonizes
   10701 	 * the diff automatically.
   10702 	 */
   10703 	if (zone->rpzs != NULL && zone->rpz_num != DNS_RPZ_INVALID_NUM) {
   10704 		isc_result_t result;
   10705 		dns_rpz_zone_t *rpz = zone->rpzs->zones[zone->rpz_num];
   10706 
   10707 		CHECK(dns_db_create(zone->mctx, "rbt", &zone->origin,
   10708 				    dns_dbtype_zone, zone->rdclass,
   10709 				    0, NULL, &db));
   10710 		CHECK(dns_rpz_dbupdate_callback(db, rpz));
   10711 		dns_zone_log(zone, ISC_LOG_WARNING,
   10712 			     "response-policy zone expired; "
   10713 			     "policies unloaded");
   10714 	}
   10715 
   10716  failure:
   10717 	if (db != NULL) {
   10718 		dns_db_detach(&db);
   10719 	}
   10720 
   10721 	zone_unload(zone);
   10722 }
   10723 
   10724 void
   10725 dns_zone_refresh(dns_zone_t *zone) {
   10726 	isc_interval_t i;
   10727 	uint32_t oldflags;
   10728 	unsigned int j;
   10729 	isc_result_t result;
   10730 
   10731 	REQUIRE(DNS_ZONE_VALID(zone));
   10732 
   10733 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
   10734 		return;
   10735 
   10736 	/*
   10737 	 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
   10738 	 * in progress at a time.
   10739 	 */
   10740 
   10741 	LOCK_ZONE(zone);
   10742 	oldflags = zone->flags;
   10743 	if (zone->masterscnt == 0) {
   10744 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
   10745 		if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
   10746 			dns_zone_log(zone, ISC_LOG_ERROR,
   10747 				     "cannot refresh: no masters");
   10748 		goto unlock;
   10749 	}
   10750 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
   10751 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
   10752 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
   10753 	if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
   10754 		goto unlock;
   10755 
   10756 	/*
   10757 	 * Set the next refresh time as if refresh check has failed.
   10758 	 * Setting this to the retry time will do that.  XXXMLG
   10759 	 * If we are successful it will be reset using zone->refresh.
   10760 	 */
   10761 	isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
   10762 			 0);
   10763 	result = isc_time_nowplusinterval(&zone->refreshtime, &i);
   10764 	if (result != ISC_R_SUCCESS)
   10765 		dns_zone_log(zone, ISC_LOG_WARNING,
   10766 			     "isc_time_nowplusinterval() failed: %s",
   10767 			     dns_result_totext(result));
   10768 
   10769 	/*
   10770 	 * When lacking user-specified timer values from the SOA,
   10771 	 * do exponential backoff of the retry time up to a
   10772 	 * maximum of six hours.
   10773 	 */
   10774 	if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
   10775 		zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
   10776 
   10777 	zone->curmaster = 0;
   10778 	for (j = 0; j < zone->masterscnt; j++)
   10779 		zone->mastersok[j] = false;
   10780 	/* initiate soa query */
   10781 	queue_soa_query(zone);
   10782  unlock:
   10783 	UNLOCK_ZONE(zone);
   10784 }
   10785 
   10786 static void
   10787 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
   10788 	isc_result_t result;
   10789 	int32_t journalsize;
   10790 	dns_dbversion_t *ver = NULL;
   10791 	uint64_t dbsize;
   10792 
   10793 	INSIST(LOCKED_ZONE(zone));
   10794 	if (inline_raw(zone))
   10795 		INSIST(LOCKED_ZONE(zone->secure));
   10796 
   10797 	journalsize = zone->journalsize;
   10798 	if (journalsize == -1) {
   10799 		journalsize = DNS_JOURNAL_SIZE_MAX;
   10800 		dns_db_currentversion(db, &ver);
   10801 		result = dns_db_getsize(db, ver, NULL, &dbsize);
   10802 		dns_db_closeversion(db, &ver, false);
   10803 		if (result != ISC_R_SUCCESS) {
   10804 			dns_zone_log(zone, ISC_LOG_ERROR,
   10805 				     "zone_journal_compact: "
   10806 				     "could not get zone size: %s",
   10807 				     isc_result_totext(result));
   10808 		} else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
   10809 			journalsize = (int32_t)dbsize * 2;
   10810 		}
   10811 	}
   10812 	zone_debuglog(zone, "zone_journal_compact", 1,
   10813 		      "target journal size %d", journalsize);
   10814 	result = dns_journal_compact(zone->mctx, zone->journal,
   10815 				     serial, journalsize);
   10816 	switch (result) {
   10817 	case ISC_R_SUCCESS:
   10818 	case ISC_R_NOSPACE:
   10819 	case ISC_R_NOTFOUND:
   10820 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   10821 			     "dns_journal_compact: %s",
   10822 			     dns_result_totext(result));
   10823 		break;
   10824 	default:
   10825 		dns_zone_log(zone, ISC_LOG_ERROR,
   10826 			     "dns_journal_compact failed: %s",
   10827 			     dns_result_totext(result));
   10828 		break;
   10829 	}
   10830 }
   10831 
   10832 isc_result_t
   10833 dns_zone_flush(dns_zone_t *zone) {
   10834 	isc_result_t result = ISC_R_SUCCESS;
   10835 	bool dumping;
   10836 
   10837 	REQUIRE(DNS_ZONE_VALID(zone));
   10838 
   10839 	LOCK_ZONE(zone);
   10840 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
   10841 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   10842 	    zone->masterfile != NULL) {
   10843 		result = ISC_R_ALREADYRUNNING;
   10844 		dumping = was_dumping(zone);
   10845 	} else
   10846 		dumping = true;
   10847 	UNLOCK_ZONE(zone);
   10848 	if (!dumping)
   10849 		result = zone_dump(zone, true);	/* Unknown task. */
   10850 	return (result);
   10851 }
   10852 
   10853 isc_result_t
   10854 dns_zone_dump(dns_zone_t *zone) {
   10855 	isc_result_t result = ISC_R_ALREADYRUNNING;
   10856 	bool dumping;
   10857 
   10858 	REQUIRE(DNS_ZONE_VALID(zone));
   10859 
   10860 	LOCK_ZONE(zone);
   10861 	dumping = was_dumping(zone);
   10862 	UNLOCK_ZONE(zone);
   10863 	if (!dumping)
   10864 		result = zone_dump(zone, false);	/* Unknown task. */
   10865 	return (result);
   10866 }
   10867 
   10868 static void
   10869 zone_needdump(dns_zone_t *zone, unsigned int delay) {
   10870 	const char me[] = "zone_needdump";
   10871 	isc_time_t dumptime;
   10872 	isc_time_t now;
   10873 
   10874 	/*
   10875 	 * 'zone' locked by caller
   10876 	 */
   10877 
   10878 	REQUIRE(DNS_ZONE_VALID(zone));
   10879 	REQUIRE(LOCKED_ZONE(zone));
   10880 	ENTER;
   10881 
   10882 	/*
   10883 	 * Do we have a place to dump to and are we loaded?
   10884 	 */
   10885 	if (zone->masterfile == NULL ||
   10886 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
   10887 		return;
   10888 
   10889 	TIME_NOW(&now);
   10890 	/* add some noise */
   10891 	DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
   10892 
   10893 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   10894 	if (isc_time_isepoch(&zone->dumptime) ||
   10895 	    isc_time_compare(&zone->dumptime, &dumptime) > 0)
   10896 		zone->dumptime = dumptime;
   10897 	if (zone->task != NULL)
   10898 		zone_settimer(zone, &now);
   10899 }
   10900 
   10901 static void
   10902 dump_done(void *arg, isc_result_t result) {
   10903 	const char me[] = "dump_done";
   10904 	dns_zone_t *zone = arg;
   10905 	dns_zone_t *secure = NULL;
   10906 	dns_db_t *db;
   10907 	dns_dbversion_t *version;
   10908 	bool again = false;
   10909 	bool compact = false;
   10910 	uint32_t serial;
   10911 	isc_result_t tresult;
   10912 
   10913 	REQUIRE(DNS_ZONE_VALID(zone));
   10914 
   10915 	ENTER;
   10916 
   10917 	if (result == ISC_R_SUCCESS && zone->journal != NULL) {
   10918 		/*
   10919 		 * We don't own these, zone->dctx must stay valid.
   10920 		 */
   10921 		db = dns_dumpctx_db(zone->dctx);
   10922 		version = dns_dumpctx_version(zone->dctx);
   10923 		tresult = dns_db_getsoaserial(db, version, &serial);
   10924 
   10925 		/*
   10926 		 * Handle lock order inversion.
   10927 		 */
   10928  again:
   10929 		LOCK_ZONE(zone);
   10930 		if (inline_raw(zone)) {
   10931 			secure = zone->secure;
   10932 			INSIST(secure != zone);
   10933 			TRYLOCK_ZONE(result, secure);
   10934 			if (result != ISC_R_SUCCESS) {
   10935 				UNLOCK_ZONE(zone);
   10936 				secure = NULL;
   10937 				isc_thread_yield();
   10938 				goto again;
   10939 			}
   10940 		}
   10941 
   10942 		/*
   10943 		 * If there is a secure version of this zone
   10944 		 * use its serial if it is less than ours.
   10945 		 */
   10946 		if (tresult == ISC_R_SUCCESS && secure != NULL) {
   10947 			uint32_t sserial;
   10948 			isc_result_t mresult;
   10949 
   10950 			ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
   10951 			if (secure->db != NULL) {
   10952 				mresult = dns_db_getsoaserial(zone->secure->db,
   10953 							      NULL, &sserial);
   10954 				if (mresult == ISC_R_SUCCESS &&
   10955 				    isc_serial_lt(sserial, serial))
   10956 					serial = sserial;
   10957 			}
   10958 			ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
   10959 		}
   10960 		if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
   10961 			dns_db_t *zdb = NULL;
   10962 			if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
   10963 				zone_journal_compact(zone, zdb, serial);
   10964 				dns_db_detach(&zdb);
   10965 			}
   10966 		} else if (tresult == ISC_R_SUCCESS) {
   10967 			compact = true;
   10968 			zone->compact_serial = serial;
   10969 		}
   10970 		if (secure != NULL)
   10971 			UNLOCK_ZONE(secure);
   10972 		UNLOCK_ZONE(zone);
   10973 	}
   10974 
   10975 	LOCK_ZONE(zone);
   10976 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
   10977 	if (compact)
   10978 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
   10979 	if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
   10980 		/*
   10981 		 * Try again in a short while.
   10982 		 */
   10983 		zone_needdump(zone, DNS_DUMP_DELAY);
   10984 	} else if (result == ISC_R_SUCCESS &&
   10985 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
   10986 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   10987 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   10988 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   10989 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
   10990 		isc_time_settoepoch(&zone->dumptime);
   10991 		again = true;
   10992 	} else if (result == ISC_R_SUCCESS)
   10993 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
   10994 
   10995 	if (zone->dctx != NULL)
   10996 		dns_dumpctx_detach(&zone->dctx);
   10997 	zonemgr_putio(&zone->writeio);
   10998 	UNLOCK_ZONE(zone);
   10999 	if (again)
   11000 		(void)zone_dump(zone, false);
   11001 	dns_zone_idetach(&zone);
   11002 }
   11003 
   11004 static isc_result_t
   11005 zone_dump(dns_zone_t *zone, bool compact) {
   11006 	const char me[] = "zone_dump";
   11007 	isc_result_t result;
   11008 	dns_dbversion_t *version = NULL;
   11009 	bool again;
   11010 	dns_db_t *db = NULL;
   11011 	char *masterfile = NULL;
   11012 	dns_masterformat_t masterformat = dns_masterformat_none;
   11013 
   11014 /*
   11015  * 'compact' MUST only be set if we are task locked.
   11016  */
   11017 
   11018 	REQUIRE(DNS_ZONE_VALID(zone));
   11019 	ENTER;
   11020 
   11021  redo:
   11022 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   11023 	if (zone->db != NULL)
   11024 		dns_db_attach(zone->db, &db);
   11025 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   11026 	LOCK_ZONE(zone);
   11027 	if (zone->masterfile != NULL) {
   11028 		masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
   11029 		masterformat = zone->masterformat;
   11030 	}
   11031 	UNLOCK_ZONE(zone);
   11032 	if (db == NULL) {
   11033 		result = DNS_R_NOTLOADED;
   11034 		goto fail;
   11035 	}
   11036 	if (masterfile == NULL) {
   11037 		result = DNS_R_NOMASTERFILE;
   11038 		goto fail;
   11039 	}
   11040 
   11041 	if (compact && zone->type != dns_zone_stub) {
   11042 		dns_zone_t *dummy = NULL;
   11043 		LOCK_ZONE(zone);
   11044 		zone_iattach(zone, &dummy);
   11045 		result = zonemgr_getio(zone->zmgr, false, zone->task,
   11046 				       zone_gotwritehandle, zone,
   11047 				       &zone->writeio);
   11048 		if (result != ISC_R_SUCCESS)
   11049 			zone_idetach(&dummy);
   11050 		else
   11051 			result = DNS_R_CONTINUE;
   11052 		UNLOCK_ZONE(zone);
   11053 	} else {
   11054 		const dns_master_style_t *output_style;
   11055 
   11056 		dns_masterrawheader_t rawdata;
   11057 		dns_db_currentversion(db, &version);
   11058 		dns_master_initrawheader(&rawdata);
   11059 		if (inline_secure(zone))
   11060 			get_raw_serial(zone->raw, &rawdata);
   11061 		if (zone->type == dns_zone_key)
   11062 			output_style = &dns_master_style_keyzone;
   11063 		else
   11064 			output_style = &dns_master_style_default;
   11065 		result = dns_master_dump(zone->mctx, db, version,
   11066 					 output_style, masterfile,
   11067 					 masterformat, &rawdata);
   11068 		dns_db_closeversion(db, &version, false);
   11069 	}
   11070  fail:
   11071 	if (db != NULL)
   11072 		dns_db_detach(&db);
   11073 	if (masterfile != NULL)
   11074 		isc_mem_free(zone->mctx, masterfile);
   11075 	masterfile = NULL;
   11076 
   11077 	if (result == DNS_R_CONTINUE)
   11078 		return (ISC_R_SUCCESS); /* XXXMPA */
   11079 
   11080 	again = false;
   11081 	LOCK_ZONE(zone);
   11082 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
   11083 	if (result != ISC_R_SUCCESS) {
   11084 		/*
   11085 		 * Try again in a short while.
   11086 		 */
   11087 		zone_needdump(zone, DNS_DUMP_DELAY);
   11088 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
   11089 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   11090 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   11091 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   11092 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
   11093 		isc_time_settoepoch(&zone->dumptime);
   11094 		again = true;
   11095 	} else
   11096 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
   11097 	UNLOCK_ZONE(zone);
   11098 	if (again)
   11099 		goto redo;
   11100 
   11101 	return (result);
   11102 }
   11103 
   11104 static isc_result_t
   11105 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
   11106 	     dns_masterformat_t format, const uint32_t rawversion)
   11107 {
   11108 	isc_result_t result;
   11109 	dns_dbversion_t *version = NULL;
   11110 	dns_db_t *db = NULL;
   11111 	dns_masterrawheader_t rawdata;
   11112 
   11113 	REQUIRE(DNS_ZONE_VALID(zone));
   11114 
   11115 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   11116 	if (zone->db != NULL)
   11117 		dns_db_attach(zone->db, &db);
   11118 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   11119 	if (db == NULL)
   11120 		return (DNS_R_NOTLOADED);
   11121 
   11122 	dns_db_currentversion(db, &version);
   11123 	dns_master_initrawheader(&rawdata);
   11124 	if (rawversion == 0)
   11125 		rawdata.flags |= DNS_MASTERRAW_COMPAT;
   11126 	else if (inline_secure(zone))
   11127 		get_raw_serial(zone->raw, &rawdata);
   11128 	else if (zone->sourceserialset) {
   11129 		rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
   11130 		rawdata.sourceserial = zone->sourceserial;
   11131 	}
   11132 	result = dns_master_dumptostream(zone->mctx, db, version, style,
   11133 					 format, &rawdata, fd);
   11134 	dns_db_closeversion(db, &version, false);
   11135 	dns_db_detach(&db);
   11136 	return (result);
   11137 }
   11138 
   11139 isc_result_t
   11140 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
   11141 		      const dns_master_style_t *style,
   11142 		      const uint32_t rawversion)
   11143 {
   11144 	return (dumptostream(zone, fd, style, format, rawversion));
   11145 }
   11146 
   11147 void
   11148 dns_zone_unload(dns_zone_t *zone) {
   11149 	REQUIRE(DNS_ZONE_VALID(zone));
   11150 
   11151 	LOCK_ZONE(zone);
   11152 	zone_unload(zone);
   11153 	UNLOCK_ZONE(zone);
   11154 }
   11155 
   11156 static void
   11157 notify_cancel(dns_zone_t *zone) {
   11158 	dns_notify_t *notify;
   11159 
   11160 	/*
   11161 	 * 'zone' locked by caller.
   11162 	 */
   11163 
   11164 	REQUIRE(LOCKED_ZONE(zone));
   11165 
   11166 	for (notify = ISC_LIST_HEAD(zone->notifies);
   11167 	     notify != NULL;
   11168 	     notify = ISC_LIST_NEXT(notify, link)) {
   11169 		if (notify->find != NULL)
   11170 			dns_adb_cancelfind(notify->find);
   11171 		if (notify->request != NULL)
   11172 			dns_request_cancel(notify->request);
   11173 	}
   11174 }
   11175 
   11176 static void
   11177 forward_cancel(dns_zone_t *zone) {
   11178 	dns_forward_t *forward;
   11179 
   11180 	/*
   11181 	 * 'zone' locked by caller.
   11182 	 */
   11183 
   11184 	REQUIRE(LOCKED_ZONE(zone));
   11185 
   11186 	for (forward = ISC_LIST_HEAD(zone->forwards);
   11187 	     forward != NULL;
   11188 	     forward = ISC_LIST_NEXT(forward, link)) {
   11189 		if (forward->request != NULL)
   11190 			dns_request_cancel(forward->request);
   11191 	}
   11192 }
   11193 
   11194 static void
   11195 zone_unload(dns_zone_t *zone) {
   11196 	/*
   11197 	 * 'zone' locked by caller.
   11198 	 */
   11199 
   11200 	REQUIRE(LOCKED_ZONE(zone));
   11201 
   11202 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
   11203 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   11204 		if (zone->writeio != NULL)
   11205 			zonemgr_cancelio(zone->writeio);
   11206 
   11207 		if (zone->dctx != NULL)
   11208 			dns_dumpctx_cancel(zone->dctx);
   11209 	}
   11210 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   11211 	zone_detachdb(zone);
   11212 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   11213 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
   11214 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   11215 
   11216 	if (zone->type == dns_zone_mirror) {
   11217 		dns_zone_log(zone, ISC_LOG_INFO,
   11218 			     "mirror zone is no longer in use; "
   11219 			     "reverting to normal recursion");
   11220 	}
   11221 }
   11222 
   11223 void
   11224 dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
   11225 	REQUIRE(DNS_ZONE_VALID(zone));
   11226 	REQUIRE(val > 0);
   11227 
   11228 	zone->minrefresh = val;
   11229 }
   11230 
   11231 void
   11232 dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
   11233 	REQUIRE(DNS_ZONE_VALID(zone));
   11234 	REQUIRE(val > 0);
   11235 
   11236 	zone->maxrefresh = val;
   11237 }
   11238 
   11239 void
   11240 dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
   11241 	REQUIRE(DNS_ZONE_VALID(zone));
   11242 	REQUIRE(val > 0);
   11243 
   11244 	zone->minretry = val;
   11245 }
   11246 
   11247 void
   11248 dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
   11249 	REQUIRE(DNS_ZONE_VALID(zone));
   11250 	REQUIRE(val > 0);
   11251 
   11252 	zone->maxretry = val;
   11253 }
   11254 
   11255 uint32_t
   11256 dns_zone_getmaxrecords(dns_zone_t *zone) {
   11257 	REQUIRE(DNS_ZONE_VALID(zone));
   11258 
   11259 	return (zone->maxrecords);
   11260 }
   11261 
   11262 void
   11263 dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
   11264 	REQUIRE(DNS_ZONE_VALID(zone));
   11265 
   11266 	zone->maxrecords = val;
   11267 }
   11268 
   11269 static bool
   11270 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
   11271 		isc_sockaddr_t *addr, dns_tsigkey_t *key)
   11272 {
   11273 	dns_notify_t *notify;
   11274 	dns_zonemgr_t *zmgr;
   11275 	isc_result_t result;
   11276 
   11277 	for (notify = ISC_LIST_HEAD(zone->notifies);
   11278 	     notify != NULL;
   11279 	     notify = ISC_LIST_NEXT(notify, link)) {
   11280 		if (notify->request != NULL)
   11281 			continue;
   11282 		if (name != NULL && dns_name_dynamic(&notify->ns) &&
   11283 		    dns_name_equal(name, &notify->ns))
   11284 			goto requeue;
   11285 		if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst) &&
   11286 		    notify->key == key)
   11287 			goto requeue;
   11288 	}
   11289 	return (false);
   11290 
   11291 requeue:
   11292 	/*
   11293 	 * If we are enqueued on the startup ratelimiter and this is
   11294 	 * not a startup notify, re-enqueue on the normal notify
   11295 	 * ratelimiter.
   11296 	 */
   11297 	if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
   11298 	    (notify->flags & DNS_NOTIFY_STARTUP) != 0) {
   11299 		zmgr = notify->zone->zmgr;
   11300 		result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
   11301 						 notify->event);
   11302 		if (result != ISC_R_SUCCESS)
   11303 			return (true);
   11304 
   11305 		notify->flags &= ~DNS_NOTIFY_STARTUP;
   11306 		result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
   11307 						 notify->zone->task,
   11308 						 &notify->event);
   11309 		if (result != ISC_R_SUCCESS) {
   11310 			isc_event_free(&notify->event);
   11311 			return (false);
   11312 		}
   11313 	}
   11314 
   11315 	return (true);
   11316 }
   11317 
   11318 static bool
   11319 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
   11320 	dns_tsigkey_t *key = NULL;
   11321 	isc_sockaddr_t src;
   11322 	isc_sockaddr_t any;
   11323 	bool isself;
   11324 	isc_netaddr_t dstaddr;
   11325 	isc_result_t result;
   11326 
   11327 	if (zone->view == NULL || zone->isself == NULL)
   11328 		return (false);
   11329 
   11330 	switch (isc_sockaddr_pf(dst)) {
   11331 	case PF_INET:
   11332 		src = zone->notifysrc4;
   11333 		isc_sockaddr_any(&any);
   11334 		break;
   11335 	case PF_INET6:
   11336 		src = zone->notifysrc6;
   11337 		isc_sockaddr_any6(&any);
   11338 		break;
   11339 	default:
   11340 		return (false);
   11341 	}
   11342 
   11343 	/*
   11344 	 * When sending from any the kernel will assign a source address
   11345 	 * that matches the destination address.
   11346 	 */
   11347 	if (isc_sockaddr_eqaddr(&any, &src))
   11348 		src = *dst;
   11349 
   11350 	isc_netaddr_fromsockaddr(&dstaddr, dst);
   11351 	result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
   11352 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
   11353 		return (false);
   11354 	isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
   11355 				zone->isselfarg);
   11356 	if (key != NULL)
   11357 		dns_tsigkey_detach(&key);
   11358 	return (isself);
   11359 }
   11360 
   11361 static void
   11362 notify_destroy(dns_notify_t *notify, bool locked) {
   11363 	isc_mem_t *mctx;
   11364 
   11365 	REQUIRE(DNS_NOTIFY_VALID(notify));
   11366 
   11367 	if (notify->zone != NULL) {
   11368 		if (!locked)
   11369 			LOCK_ZONE(notify->zone);
   11370 		REQUIRE(LOCKED_ZONE(notify->zone));
   11371 		if (ISC_LINK_LINKED(notify, link))
   11372 			ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
   11373 		if (!locked)
   11374 			UNLOCK_ZONE(notify->zone);
   11375 		if (locked)
   11376 			zone_idetach(&notify->zone);
   11377 		else
   11378 			dns_zone_idetach(&notify->zone);
   11379 	}
   11380 	if (notify->find != NULL)
   11381 		dns_adb_destroyfind(&notify->find);
   11382 	if (notify->request != NULL)
   11383 		dns_request_destroy(&notify->request);
   11384 	if (dns_name_dynamic(&notify->ns))
   11385 		dns_name_free(&notify->ns, notify->mctx);
   11386 	if (notify->key != NULL)
   11387 		dns_tsigkey_detach(&notify->key);
   11388 	mctx = notify->mctx;
   11389 	isc_mem_put(notify->mctx, notify, sizeof(*notify));
   11390 	isc_mem_detach(&mctx);
   11391 }
   11392 
   11393 static isc_result_t
   11394 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
   11395 	dns_notify_t *notify;
   11396 
   11397 	REQUIRE(notifyp != NULL && *notifyp == NULL);
   11398 
   11399 	notify = isc_mem_get(mctx, sizeof(*notify));
   11400 	if (notify == NULL)
   11401 		return (ISC_R_NOMEMORY);
   11402 
   11403 	notify->mctx = NULL;
   11404 	isc_mem_attach(mctx, &notify->mctx);
   11405 	notify->flags = flags;
   11406 	notify->zone = NULL;
   11407 	notify->find = NULL;
   11408 	notify->request = NULL;
   11409 	notify->key = NULL;
   11410 	notify->event = NULL;
   11411 	isc_sockaddr_any(&notify->dst);
   11412 	dns_name_init(&notify->ns, NULL);
   11413 	ISC_LINK_INIT(notify, link);
   11414 	notify->magic = NOTIFY_MAGIC;
   11415 	*notifyp = notify;
   11416 	return (ISC_R_SUCCESS);
   11417 }
   11418 
   11419 /*
   11420  * XXXAG should check for DNS_ZONEFLG_EXITING
   11421  */
   11422 static void
   11423 process_adb_event(isc_task_t *task, isc_event_t *ev) {
   11424 	dns_notify_t *notify;
   11425 	isc_eventtype_t result;
   11426 
   11427 	UNUSED(task);
   11428 
   11429 	notify = ev->ev_arg;
   11430 	REQUIRE(DNS_NOTIFY_VALID(notify));
   11431 	INSIST(task == notify->zone->task);
   11432 	result = ev->ev_type;
   11433 	isc_event_free(&ev);
   11434 	if (result == DNS_EVENT_ADBMOREADDRESSES) {
   11435 		dns_adb_destroyfind(&notify->find);
   11436 		notify_find_address(notify);
   11437 		return;
   11438 	}
   11439 	if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
   11440 		LOCK_ZONE(notify->zone);
   11441 		notify_send(notify);
   11442 		UNLOCK_ZONE(notify->zone);
   11443 	}
   11444 	notify_destroy(notify, false);
   11445 }
   11446 
   11447 static void
   11448 notify_find_address(dns_notify_t *notify) {
   11449 	isc_result_t result;
   11450 	unsigned int options;
   11451 
   11452 	REQUIRE(DNS_NOTIFY_VALID(notify));
   11453 	options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
   11454 		  DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
   11455 
   11456 	if (notify->zone->view->adb == NULL)
   11457 		goto destroy;
   11458 
   11459 	result = dns_adb_createfind(notify->zone->view->adb,
   11460 				    notify->zone->task,
   11461 				    process_adb_event, notify,
   11462 				    &notify->ns, dns_rootname, 0,
   11463 				    options, 0, NULL,
   11464 				    notify->zone->view->dstport,
   11465 				    0, NULL, &notify->find);
   11466 
   11467 	/* Something failed? */
   11468 	if (result != ISC_R_SUCCESS)
   11469 		goto destroy;
   11470 
   11471 	/* More addresses pending? */
   11472 	if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
   11473 		return;
   11474 
   11475 	/* We have as many addresses as we can get. */
   11476 	LOCK_ZONE(notify->zone);
   11477 	notify_send(notify);
   11478 	UNLOCK_ZONE(notify->zone);
   11479 
   11480  destroy:
   11481 	notify_destroy(notify, false);
   11482 }
   11483 
   11484 
   11485 static isc_result_t
   11486 notify_send_queue(dns_notify_t *notify, bool startup) {
   11487 	isc_event_t *e;
   11488 	isc_result_t result;
   11489 
   11490 	INSIST(notify->event == NULL);
   11491 	e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
   11492 			       notify_send_toaddr, notify, sizeof(isc_event_t));
   11493 	if (e == NULL)
   11494 		return (ISC_R_NOMEMORY);
   11495 	if (startup)
   11496 		notify->event = e;
   11497 	e->ev_arg = notify;
   11498 	e->ev_sender = NULL;
   11499 	result = isc_ratelimiter_enqueue(startup
   11500 					  ? notify->zone->zmgr->startupnotifyrl
   11501 					  : notify->zone->zmgr->notifyrl,
   11502 					 notify->zone->task, &e);
   11503 	if (result != ISC_R_SUCCESS) {
   11504 		isc_event_free(&e);
   11505 		notify->event = NULL;
   11506 	}
   11507 	return (result);
   11508 }
   11509 
   11510 static void
   11511 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
   11512 	dns_notify_t *notify;
   11513 	isc_result_t result;
   11514 	dns_message_t *message = NULL;
   11515 	isc_netaddr_t dstip;
   11516 	dns_tsigkey_t *key = NULL;
   11517 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   11518 	isc_sockaddr_t src;
   11519 	unsigned int options, timeout;
   11520 	bool have_notifysource = false;
   11521 	bool have_notifydscp = false;
   11522 	isc_dscp_t dscp = -1;
   11523 
   11524 	notify = event->ev_arg;
   11525 	REQUIRE(DNS_NOTIFY_VALID(notify));
   11526 
   11527 	UNUSED(task);
   11528 
   11529 	LOCK_ZONE(notify->zone);
   11530 
   11531 	notify->event = NULL;
   11532 
   11533 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
   11534 		result = ISC_R_CANCELED;
   11535 		goto cleanup;
   11536 	}
   11537 
   11538 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
   11539 	    DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
   11540 	    notify->zone->view->requestmgr == NULL ||
   11541 	    notify->zone->db == NULL) {
   11542 		result = ISC_R_CANCELED;
   11543 		goto cleanup;
   11544 	}
   11545 
   11546 	/*
   11547 	 * The raw IPv4 address should also exist.  Don't send to the
   11548 	 * mapped form.
   11549 	 */
   11550 	if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
   11551 	    IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
   11552 		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
   11553 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
   11554 			   "notify: ignoring IPv6 mapped IPV4 address: %s",
   11555 			   addrbuf);
   11556 		result = ISC_R_CANCELED;
   11557 		goto cleanup;
   11558 	}
   11559 
   11560 	result = notify_createmessage(notify->zone, notify->flags, &message);
   11561 	if (result != ISC_R_SUCCESS)
   11562 		goto cleanup;
   11563 
   11564 	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
   11565 	if (notify->key != NULL) {
   11566 		/* Transfer ownership of key */
   11567 		key = notify->key;
   11568 		notify->key = NULL;
   11569 	} else {
   11570 		isc_netaddr_fromsockaddr(&dstip, &notify->dst);
   11571 		result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
   11572 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   11573 			notify_log(notify->zone, ISC_LOG_ERROR,
   11574 				   "NOTIFY to %s not sent. "
   11575 				   "Peer TSIG key lookup failure.", addrbuf);
   11576 			goto cleanup_message;
   11577 		}
   11578 	}
   11579 
   11580 	/* XXX: should we log the tsig key too? */
   11581 	notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
   11582 		   addrbuf);
   11583 	options = 0;
   11584 	if (notify->zone->view->peers != NULL) {
   11585 		dns_peer_t *peer = NULL;
   11586 		bool usetcp = false;
   11587 		result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
   11588 						 &dstip, &peer);
   11589 		if (result == ISC_R_SUCCESS) {
   11590 			result = dns_peer_getnotifysource(peer, &src);
   11591 			if (result == ISC_R_SUCCESS)
   11592 				have_notifysource = true;
   11593 			dns_peer_getnotifydscp(peer, &dscp);
   11594 			if (dscp != -1)
   11595 				have_notifydscp = true;
   11596 			result = dns_peer_getforcetcp(peer, &usetcp);
   11597 			if (result == ISC_R_SUCCESS && usetcp)
   11598 				options |= DNS_FETCHOPT_TCP;
   11599 		}
   11600 	}
   11601 	switch (isc_sockaddr_pf(&notify->dst)) {
   11602 	case PF_INET:
   11603 		if (!have_notifysource)
   11604 			src = notify->zone->notifysrc4;
   11605 		if (!have_notifydscp)
   11606 			dscp = notify->zone->notifysrc4dscp;
   11607 		break;
   11608 	case PF_INET6:
   11609 		if (!have_notifysource)
   11610 			src = notify->zone->notifysrc6;
   11611 		if (!have_notifydscp)
   11612 			dscp = notify->zone->notifysrc6dscp;
   11613 		break;
   11614 	default:
   11615 		result = ISC_R_NOTIMPLEMENTED;
   11616 		goto cleanup_key;
   11617 	}
   11618 	timeout = 15;
   11619 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
   11620 		timeout = 30;
   11621 	result = dns_request_createvia(notify->zone->view->requestmgr,
   11622 				       message, &src, &notify->dst, dscp,
   11623 				       options, key, timeout * 3, timeout,
   11624 				       0, notify->zone->task, notify_done,
   11625 				       notify, &notify->request);
   11626 	if (result == ISC_R_SUCCESS) {
   11627 		if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
   11628 			inc_stats(notify->zone,
   11629 				  dns_zonestatscounter_notifyoutv4);
   11630 		} else {
   11631 			inc_stats(notify->zone,
   11632 				  dns_zonestatscounter_notifyoutv6);
   11633 		}
   11634 	}
   11635 
   11636  cleanup_key:
   11637 	if (key != NULL)
   11638 		dns_tsigkey_detach(&key);
   11639  cleanup_message:
   11640 	dns_message_destroy(&message);
   11641  cleanup:
   11642 	UNLOCK_ZONE(notify->zone);
   11643 	isc_event_free(&event);
   11644 	if (result != ISC_R_SUCCESS)
   11645 		notify_destroy(notify, false);
   11646 }
   11647 
   11648 static void
   11649 notify_send(dns_notify_t *notify) {
   11650 	dns_adbaddrinfo_t *ai;
   11651 	isc_sockaddr_t dst;
   11652 	isc_result_t result;
   11653 	dns_notify_t *newnotify = NULL;
   11654 	unsigned int flags;
   11655 	bool startup;
   11656 
   11657 	/*
   11658 	 * Zone lock held by caller.
   11659 	 */
   11660 	REQUIRE(DNS_NOTIFY_VALID(notify));
   11661 	REQUIRE(LOCKED_ZONE(notify->zone));
   11662 
   11663 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING))
   11664 		return;
   11665 
   11666 	for (ai = ISC_LIST_HEAD(notify->find->list);
   11667 	     ai != NULL;
   11668 	     ai = ISC_LIST_NEXT(ai, publink)) {
   11669 		dst = ai->sockaddr;
   11670 		if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
   11671 				    NULL))
   11672 			continue;
   11673 		if (notify_isself(notify->zone, &dst))
   11674 			continue;
   11675 		newnotify = NULL;
   11676 		flags = notify->flags & DNS_NOTIFY_NOSOA;
   11677 		result = notify_create(notify->mctx, flags, &newnotify);
   11678 		if (result != ISC_R_SUCCESS)
   11679 			goto cleanup;
   11680 		zone_iattach(notify->zone, &newnotify->zone);
   11681 		ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
   11682 		newnotify->dst = dst;
   11683 		startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
   11684 		result = notify_send_queue(newnotify, startup);
   11685 		if (result != ISC_R_SUCCESS)
   11686 			goto cleanup;
   11687 		newnotify = NULL;
   11688 	}
   11689 
   11690  cleanup:
   11691 	if (newnotify != NULL)
   11692 		notify_destroy(newnotify, true);
   11693 }
   11694 
   11695 void
   11696 dns_zone_notify(dns_zone_t *zone) {
   11697 	isc_time_t now;
   11698 
   11699 	REQUIRE(DNS_ZONE_VALID(zone));
   11700 
   11701 	LOCK_ZONE(zone);
   11702 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   11703 
   11704 	TIME_NOW(&now);
   11705 	zone_settimer(zone, &now);
   11706 	UNLOCK_ZONE(zone);
   11707 }
   11708 
   11709 static void
   11710 zone_notify(dns_zone_t *zone, isc_time_t *now) {
   11711 	dns_dbnode_t *node = NULL;
   11712 	dns_db_t *zonedb = NULL;
   11713 	dns_dbversion_t *version = NULL;
   11714 	dns_name_t *origin = NULL;
   11715 	dns_name_t master;
   11716 	dns_rdata_ns_t ns;
   11717 	dns_rdata_soa_t soa;
   11718 	uint32_t serial;
   11719 	dns_rdata_t rdata = DNS_RDATA_INIT;
   11720 	dns_rdataset_t nsrdset;
   11721 	dns_rdataset_t soardset;
   11722 	isc_result_t result;
   11723 	unsigned int i;
   11724 	isc_sockaddr_t dst;
   11725 	bool isqueued;
   11726 	dns_notifytype_t notifytype;
   11727 	unsigned int flags = 0;
   11728 	bool loggednotify = false;
   11729 	bool startup;
   11730 
   11731 	REQUIRE(DNS_ZONE_VALID(zone));
   11732 
   11733 	LOCK_ZONE(zone);
   11734 	startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   11735 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   11736 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
   11737 	notifytype = zone->notifytype;
   11738 	DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
   11739 	UNLOCK_ZONE(zone);
   11740 
   11741 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
   11742 	    ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   11743 		return;
   11744 
   11745 	if (notifytype == dns_notifytype_no)
   11746 		return;
   11747 
   11748 	if (notifytype == dns_notifytype_masteronly &&
   11749 	    zone->type != dns_zone_master)
   11750 		return;
   11751 
   11752 	origin = &zone->origin;
   11753 
   11754 	/*
   11755 	 * If the zone is dialup we are done as we don't want to send
   11756 	 * the current soa so as to force a refresh query.
   11757 	 */
   11758 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
   11759 		flags |= DNS_NOTIFY_NOSOA;
   11760 
   11761 	/*
   11762 	 * Record that this was a notify due to starting up.
   11763 	 */
   11764 	if (startup)
   11765 		flags |= DNS_NOTIFY_STARTUP;
   11766 
   11767 	/*
   11768 	 * Get SOA RRset.
   11769 	 */
   11770 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   11771 	if (zone->db != NULL)
   11772 		dns_db_attach(zone->db, &zonedb);
   11773 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   11774 	if (zonedb == NULL)
   11775 		return;
   11776 	dns_db_currentversion(zonedb, &version);
   11777 	result = dns_db_findnode(zonedb, origin, false, &node);
   11778 	if (result != ISC_R_SUCCESS)
   11779 		goto cleanup1;
   11780 
   11781 	dns_rdataset_init(&soardset);
   11782 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
   11783 				     dns_rdatatype_none, 0, &soardset, NULL);
   11784 	if (result != ISC_R_SUCCESS)
   11785 		goto cleanup2;
   11786 
   11787 	/*
   11788 	 * Find serial and master server's name.
   11789 	 */
   11790 	dns_name_init(&master, NULL);
   11791 	result = dns_rdataset_first(&soardset);
   11792 	if (result != ISC_R_SUCCESS)
   11793 		goto cleanup3;
   11794 	dns_rdataset_current(&soardset, &rdata);
   11795 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   11796 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   11797 	dns_rdata_reset(&rdata);
   11798 	result = dns_name_dup(&soa.origin, zone->mctx, &master);
   11799 	serial = soa.serial;
   11800 	dns_rdataset_disassociate(&soardset);
   11801 	if (result != ISC_R_SUCCESS)
   11802 		goto cleanup3;
   11803 
   11804 	/*
   11805 	 * Enqueue notify requests for 'also-notify' servers.
   11806 	 */
   11807 	LOCK_ZONE(zone);
   11808 	for (i = 0; i < zone->notifycnt; i++) {
   11809 		dns_tsigkey_t *key = NULL;
   11810 		dns_notify_t *notify = NULL;
   11811 
   11812 		if ((zone->notifykeynames != NULL) &&
   11813 		    (zone->notifykeynames[i] != NULL)) {
   11814 			dns_view_t *view = dns_zone_getview(zone);
   11815 			dns_name_t *keyname = zone->notifykeynames[i];
   11816 			(void)dns_view_gettsig(view, keyname, &key);
   11817 		}
   11818 
   11819 		dst = zone->notify[i];
   11820 		if (notify_isqueued(zone, flags, NULL, &dst, key)) {
   11821 			if (key != NULL)
   11822 				dns_tsigkey_detach(&key);
   11823 			continue;
   11824 		}
   11825 
   11826 		result = notify_create(zone->mctx, flags, &notify);
   11827 		if (result != ISC_R_SUCCESS) {
   11828 			if (key != NULL)
   11829 				dns_tsigkey_detach(&key);
   11830 			continue;
   11831 		}
   11832 
   11833 		zone_iattach(zone, &notify->zone);
   11834 		notify->dst = dst;
   11835 
   11836 		INSIST(notify->key == NULL);
   11837 
   11838 		if (key != NULL) {
   11839 			notify->key = key;
   11840 			key = NULL;
   11841 		}
   11842 
   11843 		ISC_LIST_APPEND(zone->notifies, notify, link);
   11844 		result = notify_send_queue(notify, startup);
   11845 		if (result != ISC_R_SUCCESS)
   11846 			notify_destroy(notify, true);
   11847 		if (!loggednotify) {
   11848 			notify_log(zone, ISC_LOG_INFO,
   11849 				   "sending notifies (serial %u)",
   11850 				   serial);
   11851 			loggednotify = true;
   11852 		}
   11853 	}
   11854 	UNLOCK_ZONE(zone);
   11855 
   11856 	if (notifytype == dns_notifytype_explicit)
   11857 		goto cleanup3;
   11858 
   11859 	/*
   11860 	 * Process NS RRset to generate notifies.
   11861 	 */
   11862 
   11863 	dns_rdataset_init(&nsrdset);
   11864 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
   11865 				     dns_rdatatype_none, 0, &nsrdset, NULL);
   11866 	if (result != ISC_R_SUCCESS)
   11867 		goto cleanup3;
   11868 
   11869 	result = dns_rdataset_first(&nsrdset);
   11870 	while (result == ISC_R_SUCCESS) {
   11871 		dns_notify_t *notify = NULL;
   11872 
   11873 		dns_rdataset_current(&nsrdset, &rdata);
   11874 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
   11875 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   11876 		dns_rdata_reset(&rdata);
   11877 		/*
   11878 		 * Don't notify the master server unless explicitly
   11879 		 * configured to do so.
   11880 		 */
   11881 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
   11882 		    dns_name_compare(&master, &ns.name) == 0) {
   11883 			result = dns_rdataset_next(&nsrdset);
   11884 			continue;
   11885 		}
   11886 
   11887 		if (!loggednotify) {
   11888 			notify_log(zone, ISC_LOG_INFO,
   11889 				   "sending notifies (serial %u)",
   11890 				   serial);
   11891 			loggednotify = true;
   11892 		}
   11893 
   11894 		LOCK_ZONE(zone);
   11895 		isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
   11896 		UNLOCK_ZONE(zone);
   11897 		if (isqueued) {
   11898 			result = dns_rdataset_next(&nsrdset);
   11899 			continue;
   11900 		}
   11901 		result = notify_create(zone->mctx, flags, &notify);
   11902 		if (result != ISC_R_SUCCESS)
   11903 			continue;
   11904 		dns_zone_iattach(zone, &notify->zone);
   11905 		result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
   11906 		if (result != ISC_R_SUCCESS) {
   11907 			LOCK_ZONE(zone);
   11908 			notify_destroy(notify, true);
   11909 			UNLOCK_ZONE(zone);
   11910 			continue;
   11911 		}
   11912 		LOCK_ZONE(zone);
   11913 		ISC_LIST_APPEND(zone->notifies, notify, link);
   11914 		UNLOCK_ZONE(zone);
   11915 		notify_find_address(notify);
   11916 		result = dns_rdataset_next(&nsrdset);
   11917 	}
   11918 	dns_rdataset_disassociate(&nsrdset);
   11919 
   11920  cleanup3:
   11921 	if (dns_name_dynamic(&master))
   11922 		dns_name_free(&master, zone->mctx);
   11923  cleanup2:
   11924 	dns_db_detachnode(zonedb, &node);
   11925  cleanup1:
   11926 	dns_db_closeversion(zonedb, &version, false);
   11927 	dns_db_detach(&zonedb);
   11928 }
   11929 
   11930 /***
   11931  *** Private
   11932  ***/
   11933 
   11934 static inline isc_result_t
   11935 save_nsrrset(dns_message_t *message, dns_name_t *name,
   11936 	     dns_db_t *db, dns_dbversion_t *version)
   11937 {
   11938 	dns_rdataset_t *nsrdataset = NULL;
   11939 	dns_rdataset_t *rdataset = NULL;
   11940 	dns_dbnode_t *node = NULL;
   11941 	dns_rdata_ns_t ns;
   11942 	isc_result_t result;
   11943 	dns_rdata_t rdata = DNS_RDATA_INIT;
   11944 
   11945 	/*
   11946 	 * Extract NS RRset from message.
   11947 	 */
   11948 	result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
   11949 				      dns_rdatatype_ns, dns_rdatatype_none,
   11950 				      NULL, &nsrdataset);
   11951 	if (result != ISC_R_SUCCESS)
   11952 		goto fail;
   11953 
   11954 	/*
   11955 	 * Add NS rdataset.
   11956 	 */
   11957 	result = dns_db_findnode(db, name, true, &node);
   11958 	if (result != ISC_R_SUCCESS)
   11959 		goto fail;
   11960 	result = dns_db_addrdataset(db, node, version, 0,
   11961 				    nsrdataset, 0, NULL);
   11962 	dns_db_detachnode(db, &node);
   11963 	if (result != ISC_R_SUCCESS)
   11964 		goto fail;
   11965 	/*
   11966 	 * Add glue rdatasets.
   11967 	 */
   11968 	for (result = dns_rdataset_first(nsrdataset);
   11969 	     result == ISC_R_SUCCESS;
   11970 	     result = dns_rdataset_next(nsrdataset)) {
   11971 		dns_rdataset_current(nsrdataset, &rdata);
   11972 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
   11973 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   11974 		dns_rdata_reset(&rdata);
   11975 		if (!dns_name_issubdomain(&ns.name, name))
   11976 			continue;
   11977 		rdataset = NULL;
   11978 		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
   11979 					      &ns.name, dns_rdatatype_aaaa,
   11980 					      dns_rdatatype_none, NULL,
   11981 					      &rdataset);
   11982 		if (result == ISC_R_SUCCESS) {
   11983 			result = dns_db_findnode(db, &ns.name,
   11984 						 true, &node);
   11985 			if (result != ISC_R_SUCCESS)
   11986 				goto fail;
   11987 			result = dns_db_addrdataset(db, node, version, 0,
   11988 						    rdataset, 0, NULL);
   11989 			dns_db_detachnode(db, &node);
   11990 			if (result != ISC_R_SUCCESS)
   11991 				goto fail;
   11992 		}
   11993 		rdataset = NULL;
   11994 		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
   11995 					      &ns.name, dns_rdatatype_a,
   11996 					      dns_rdatatype_none, NULL,
   11997 					      &rdataset);
   11998 		if (result == ISC_R_SUCCESS) {
   11999 			result = dns_db_findnode(db, &ns.name,
   12000 						 true, &node);
   12001 			if (result != ISC_R_SUCCESS)
   12002 				goto fail;
   12003 			result = dns_db_addrdataset(db, node, version, 0,
   12004 						    rdataset, 0, NULL);
   12005 			dns_db_detachnode(db, &node);
   12006 			if (result != ISC_R_SUCCESS)
   12007 				goto fail;
   12008 		}
   12009 	}
   12010 	if (result != ISC_R_NOMORE)
   12011 		goto fail;
   12012 
   12013 	return (ISC_R_SUCCESS);
   12014 
   12015 fail:
   12016 	return (result);
   12017 }
   12018 
   12019 static void
   12020 stub_callback(isc_task_t *task, isc_event_t *event) {
   12021 	const char me[] = "stub_callback";
   12022 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
   12023 	dns_stub_t *stub = NULL;
   12024 	dns_message_t *msg = NULL;
   12025 	dns_zone_t *zone = NULL;
   12026 	char master[ISC_SOCKADDR_FORMATSIZE];
   12027 	char source[ISC_SOCKADDR_FORMATSIZE];
   12028 	uint32_t nscnt, cnamecnt, refresh, retry, expire;
   12029 	isc_result_t result;
   12030 	isc_time_t now;
   12031 	bool exiting = false;
   12032 	isc_interval_t i;
   12033 	unsigned int j, soacount;
   12034 
   12035 	stub = revent->ev_arg;
   12036 	INSIST(DNS_STUB_VALID(stub));
   12037 
   12038 	UNUSED(task);
   12039 
   12040 	zone = stub->zone;
   12041 
   12042 	ENTER;
   12043 
   12044 	TIME_NOW(&now);
   12045 
   12046 	LOCK_ZONE(zone);
   12047 
   12048 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   12049 		zone_debuglog(zone, me, 1, "exiting");
   12050 		exiting = true;
   12051 		goto next_master;
   12052 	}
   12053 
   12054 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
   12055 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   12056 
   12057 	if (revent->result != ISC_R_SUCCESS) {
   12058 		if (revent->result == ISC_R_TIMEDOUT &&
   12059 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   12060 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   12061 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   12062 				     "refreshing stub: timeout retrying "
   12063 				     " without EDNS master %s (source %s)",
   12064 				     master, source);
   12065 			goto same_master;
   12066 		}
   12067 		dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
   12068 					   &zone->sourceaddr, &now);
   12069 		dns_zone_log(zone, ISC_LOG_INFO,
   12070 			     "could not refresh stub from master %s"
   12071 			     " (source %s): %s", master, source,
   12072 			     dns_result_totext(revent->result));
   12073 		goto next_master;
   12074 	}
   12075 
   12076 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
   12077 	if (result != ISC_R_SUCCESS)
   12078 		goto next_master;
   12079 
   12080 	result = dns_request_getresponse(revent->request, msg, 0);
   12081 	if (result != ISC_R_SUCCESS)
   12082 		goto next_master;
   12083 
   12084 	/*
   12085 	 * Unexpected rcode.
   12086 	 */
   12087 	if (msg->rcode != dns_rcode_noerror) {
   12088 		char rcode[128];
   12089 		isc_buffer_t rb;
   12090 
   12091 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   12092 		(void)dns_rcode_totext(msg->rcode, &rb);
   12093 
   12094 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
   12095 		    (msg->rcode == dns_rcode_servfail ||
   12096 		     msg->rcode == dns_rcode_notimp ||
   12097 		     msg->rcode == dns_rcode_formerr)) {
   12098 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   12099 				     "refreshing stub: rcode (%.*s) retrying "
   12100 				     "without EDNS master %s (source %s)",
   12101 				     (int)rb.used, rcode, master, source);
   12102 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   12103 			goto same_master;
   12104 		}
   12105 
   12106 		dns_zone_log(zone, ISC_LOG_INFO,
   12107 			     "refreshing stub: "
   12108 			     "unexpected rcode (%.*s) from %s (source %s)",
   12109 			     (int)rb.used, rcode, master, source);
   12110 		goto next_master;
   12111 	}
   12112 
   12113 	/*
   12114 	 * We need complete messages.
   12115 	 */
   12116 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
   12117 		if (dns_request_usedtcp(revent->request)) {
   12118 			dns_zone_log(zone, ISC_LOG_INFO,
   12119 				     "refreshing stub: truncated TCP "
   12120 				     "response from master %s (source %s)",
   12121 				     master, source);
   12122 			goto next_master;
   12123 		}
   12124 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
   12125 		goto same_master;
   12126 	}
   12127 
   12128 	/*
   12129 	 * If non-auth log and next master.
   12130 	 */
   12131 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
   12132 		dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
   12133 			     "non-authoritative answer from "
   12134 			     "master %s (source %s)", master, source);
   12135 		goto next_master;
   12136 	}
   12137 
   12138 	/*
   12139 	 * Sanity checks.
   12140 	 */
   12141 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
   12142 	nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
   12143 
   12144 	if (cnamecnt != 0) {
   12145 		dns_zone_log(zone, ISC_LOG_INFO,
   12146 			     "refreshing stub: unexpected CNAME response "
   12147 			     "from master %s (source %s)", master, source);
   12148 		goto next_master;
   12149 	}
   12150 
   12151 	if (nscnt == 0) {
   12152 		dns_zone_log(zone, ISC_LOG_INFO,
   12153 			     "refreshing stub: no NS records in response "
   12154 			     "from master %s (source %s)", master, source);
   12155 		goto next_master;
   12156 	}
   12157 
   12158 	/*
   12159 	 * Save answer.
   12160 	 */
   12161 	result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
   12162 	if (result != ISC_R_SUCCESS) {
   12163 		dns_zone_log(zone, ISC_LOG_INFO,
   12164 			     "refreshing stub: unable to save NS records "
   12165 			     "from master %s (source %s)", master, source);
   12166 		goto next_master;
   12167 	}
   12168 
   12169 	/*
   12170 	 * Tidy up.
   12171 	 */
   12172 	dns_db_closeversion(stub->db, &stub->version, true);
   12173 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   12174 	if (zone->db == NULL)
   12175 		zone_attachdb(zone, stub->db);
   12176 	result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
   12177 				  &refresh, &retry, &expire, NULL, NULL);
   12178 	if (result == ISC_R_SUCCESS && soacount > 0U) {
   12179 		zone->refresh = RANGE(refresh, zone->minrefresh,
   12180 				      zone->maxrefresh);
   12181 		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
   12182 		zone->expire = RANGE(expire, zone->refresh + zone->retry,
   12183 				     DNS_MAX_EXPIRE);
   12184 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   12185 	}
   12186 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   12187 	dns_db_detach(&stub->db);
   12188 
   12189 	dns_message_destroy(&msg);
   12190 	isc_event_free(&event);
   12191 	dns_request_destroy(&zone->request);
   12192 
   12193 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   12194 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   12195 	DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
   12196 	isc_interval_set(&i, zone->expire, 0);
   12197 	DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
   12198 
   12199 	if (zone->masterfile != NULL)
   12200 		zone_needdump(zone, 0);
   12201 
   12202 	zone_settimer(zone, &now);
   12203 	goto free_stub;
   12204 
   12205  next_master:
   12206 	if (stub->version != NULL)
   12207 		dns_db_closeversion(stub->db, &stub->version, false);
   12208 	if (stub->db != NULL)
   12209 		dns_db_detach(&stub->db);
   12210 	if (msg != NULL)
   12211 		dns_message_destroy(&msg);
   12212 	isc_event_free(&event);
   12213 	dns_request_destroy(&zone->request);
   12214 	/*
   12215 	 * Skip to next failed / untried master.
   12216 	 */
   12217 	do {
   12218 		zone->curmaster++;
   12219 	} while (zone->curmaster < zone->masterscnt &&
   12220 		 zone->mastersok[zone->curmaster]);
   12221 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
   12222 	if (exiting || zone->curmaster >= zone->masterscnt) {
   12223 		bool done = true;
   12224 		if (!exiting &&
   12225 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
   12226 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   12227 			/*
   12228 			 * Did we get a good answer from all the masters?
   12229 			 */
   12230 			for (j = 0; j < zone->masterscnt; j++)
   12231 				if (zone->mastersok[j] == false) {
   12232 					done = false;
   12233 					break;
   12234 				}
   12235 		} else
   12236 			done = true;
   12237 		if (!done) {
   12238 			zone->curmaster = 0;
   12239 			/*
   12240 			 * Find the next failed master.
   12241 			 */
   12242 			while (zone->curmaster < zone->masterscnt &&
   12243 			       zone->mastersok[zone->curmaster])
   12244 				zone->curmaster++;
   12245 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
   12246 		} else {
   12247 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   12248 
   12249 			zone_settimer(zone, &now);
   12250 			goto free_stub;
   12251 		}
   12252 	}
   12253 	queue_soa_query(zone);
   12254 	goto free_stub;
   12255 
   12256  same_master:
   12257 	if (msg != NULL)
   12258 		dns_message_destroy(&msg);
   12259 	isc_event_free(&event);
   12260 	dns_request_destroy(&zone->request);
   12261 	ns_query(zone, NULL, stub);
   12262 	UNLOCK_ZONE(zone);
   12263 	goto done;
   12264 
   12265  free_stub:
   12266 	UNLOCK_ZONE(zone);
   12267 	stub->magic = 0;
   12268 	dns_zone_idetach(&stub->zone);
   12269 	INSIST(stub->db == NULL);
   12270 	INSIST(stub->version == NULL);
   12271 	isc_mem_put(stub->mctx, stub, sizeof(*stub));
   12272 
   12273  done:
   12274 	INSIST(event == NULL);
   12275 	return;
   12276 }
   12277 
   12278 /*
   12279  * Get the EDNS EXPIRE option from the response and if it exists trim
   12280  * expire to be not more than it.
   12281  */
   12282 static void
   12283 get_edns_expire(dns_zone_t * zone, dns_message_t *message,
   12284 		uint32_t *expirep)
   12285 {
   12286 	isc_result_t result;
   12287 	uint32_t expire;
   12288 	dns_rdata_t rdata = DNS_RDATA_INIT;
   12289 	isc_buffer_t optbuf;
   12290 	uint16_t optcode;
   12291 	uint16_t optlen;
   12292 
   12293 	REQUIRE(expirep != NULL);
   12294 	REQUIRE(message != NULL);
   12295 
   12296 	if (message->opt == NULL)
   12297 		return;
   12298 
   12299 	result = dns_rdataset_first(message->opt);
   12300 	if (result == ISC_R_SUCCESS) {
   12301 		dns_rdataset_current(message->opt, &rdata);
   12302 		isc_buffer_init(&optbuf, rdata.data, rdata.length);
   12303 		isc_buffer_add(&optbuf, rdata.length);
   12304 		while (isc_buffer_remaininglength(&optbuf) >= 4) {
   12305 			optcode = isc_buffer_getuint16(&optbuf);
   12306 			optlen = isc_buffer_getuint16(&optbuf);
   12307 			/*
   12308 			 * A EDNS EXPIRE response has a length of 4.
   12309 			 */
   12310 			if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
   12311 				isc_buffer_forward(&optbuf, optlen);
   12312 				continue;
   12313 			}
   12314 			expire = isc_buffer_getuint32(&optbuf);
   12315 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   12316 				     "got EDNS EXPIRE of %u", expire);
   12317 			/*
   12318 			 * Trim *expirep?
   12319 			 */
   12320 			if (expire < *expirep)
   12321 				*expirep = expire;
   12322 			break;
   12323 		}
   12324 	}
   12325 }
   12326 
   12327 /*
   12328  * Set the file modification time zone->expire seconds before expiretime.
   12329  */
   12330 static void
   12331 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
   12332 	isc_result_t result;
   12333 	isc_time_t when;
   12334 	isc_interval_t i;
   12335 
   12336 	isc_interval_set(&i, zone->expire, 0);
   12337 	result = isc_time_subtract(expiretime, &i, &when);
   12338 	if (result != ISC_R_SUCCESS)
   12339 		return;
   12340 
   12341 	result = ISC_R_FAILURE;
   12342 	if (zone->journal != NULL)
   12343 		result = isc_file_settime(zone->journal, &when);
   12344 	if (result == ISC_R_SUCCESS &&
   12345 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   12346 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
   12347 		result = isc_file_settime(zone->masterfile, &when);
   12348 	else if (result != ISC_R_SUCCESS)
   12349 		result = isc_file_settime(zone->masterfile, &when);
   12350 
   12351 	/*
   12352 	 * Someone removed the file from underneath us!
   12353 	 */
   12354 	if (result == ISC_R_FILENOTFOUND) {
   12355 		zone_needdump(zone, DNS_DUMP_DELAY);
   12356 	} else if (result != ISC_R_SUCCESS)
   12357 		dns_zone_log(zone, ISC_LOG_ERROR, "refresh: could not set "
   12358 			     "file modification time of '%s': %s",
   12359 			     zone->masterfile, dns_result_totext(result));
   12360 }
   12361 
   12362 /*
   12363  * An SOA query has finished (successfully or not).
   12364  */
   12365 static void
   12366 refresh_callback(isc_task_t *task, isc_event_t *event) {
   12367 	const char me[] = "refresh_callback";
   12368 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
   12369 	dns_zone_t *zone;
   12370 	dns_message_t *msg = NULL;
   12371 	uint32_t soacnt, cnamecnt, soacount, nscount;
   12372 	isc_time_t now;
   12373 	char master[ISC_SOCKADDR_FORMATSIZE];
   12374 	char source[ISC_SOCKADDR_FORMATSIZE];
   12375 	dns_rdataset_t *rdataset = NULL;
   12376 	dns_rdata_t rdata = DNS_RDATA_INIT;
   12377 	dns_rdata_soa_t soa;
   12378 	isc_result_t result;
   12379 	uint32_t serial, oldserial = 0;
   12380 	unsigned int j;
   12381 	bool do_queue_xfrin = false;
   12382 
   12383 	zone = revent->ev_arg;
   12384 	INSIST(DNS_ZONE_VALID(zone));
   12385 
   12386 	UNUSED(task);
   12387 
   12388 	ENTER;
   12389 
   12390 	TIME_NOW(&now);
   12391 
   12392 	LOCK_ZONE(zone);
   12393 
   12394 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   12395 		isc_event_free(&event);
   12396 		dns_request_destroy(&zone->request);
   12397 		goto detach;
   12398 	}
   12399 
   12400 	/*
   12401 	 * if timeout log and next master;
   12402 	 */
   12403 
   12404 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
   12405 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   12406 
   12407 	if (revent->result != ISC_R_SUCCESS) {
   12408 		if (revent->result == ISC_R_TIMEDOUT &&
   12409 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   12410 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   12411 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   12412 				     "refresh: timeout retrying without EDNS "
   12413 				     "master %s (source %s)", master, source);
   12414 			goto same_master;
   12415 		}
   12416 		if (revent->result == ISC_R_TIMEDOUT &&
   12417 		    !dns_request_usedtcp(revent->request)) {
   12418 			dns_zone_log(zone, ISC_LOG_INFO,
   12419 				     "refresh: retry limit for "
   12420 				     "master %s exceeded (source %s)",
   12421 				     master, source);
   12422 			/* Try with slave with TCP. */
   12423 			if ((zone->type == dns_zone_slave ||
   12424 			     zone->type == dns_zone_mirror ||
   12425 			     zone->type == dns_zone_redirect) &&
   12426 			    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
   12427 			{
   12428 				if (!dns_zonemgr_unreachable(zone->zmgr,
   12429 							     &zone->masteraddr,
   12430 							     &zone->sourceaddr,
   12431 							     &now))
   12432 				{
   12433 					DNS_ZONE_SETFLAG(zone,
   12434 						     DNS_ZONEFLG_SOABEFOREAXFR);
   12435 					goto tcp_transfer;
   12436 				}
   12437 				dns_zone_log(zone, ISC_LOG_DEBUG(1),
   12438 					     "refresh: skipped tcp fallback "
   12439 					     "as master %s (source %s) is "
   12440 					     "unreachable (cached)",
   12441 					      master, source);
   12442 			}
   12443 		} else
   12444 			dns_zone_log(zone, ISC_LOG_INFO,
   12445 				     "refresh: failure trying master "
   12446 				     "%s (source %s): %s", master, source,
   12447 				     dns_result_totext(revent->result));
   12448 		goto next_master;
   12449 	}
   12450 
   12451 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
   12452 	if (result != ISC_R_SUCCESS)
   12453 		goto next_master;
   12454 	result = dns_request_getresponse(revent->request, msg, 0);
   12455 	if (result != ISC_R_SUCCESS) {
   12456 		dns_zone_log(zone, ISC_LOG_INFO,
   12457 			     "refresh: failure trying master "
   12458 			     "%s (source %s): %s", master, source,
   12459 			     dns_result_totext(result));
   12460 		goto next_master;
   12461 	}
   12462 
   12463 	/*
   12464 	 * Unexpected rcode.
   12465 	 */
   12466 	if (msg->rcode != dns_rcode_noerror) {
   12467 		char rcode[128];
   12468 		isc_buffer_t rb;
   12469 
   12470 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   12471 		(void)dns_rcode_totext(msg->rcode, &rb);
   12472 
   12473 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
   12474 		    (msg->rcode == dns_rcode_servfail ||
   12475 		     msg->rcode == dns_rcode_notimp ||
   12476 		     msg->rcode == dns_rcode_formerr)) {
   12477 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   12478 				     "refresh: rcode (%.*s) retrying without "
   12479 				     "EDNS master %s (source %s)",
   12480 				     (int)rb.used, rcode, master, source);
   12481 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   12482 			goto same_master;
   12483 		}
   12484 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
   12485 		    msg->rcode == dns_rcode_badvers) {
   12486 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   12487 				     "refresh: rcode (%.*s) retrying without "
   12488 				     "EDNS EXPIRE OPTION master %s (source %s)",
   12489 				     (int)rb.used, rcode, master, source);
   12490 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   12491 			goto same_master;
   12492 		}
   12493 		dns_zone_log(zone, ISC_LOG_INFO,
   12494 			     "refresh: unexpected rcode (%.*s) from "
   12495 			     "master %s (source %s)", (int)rb.used, rcode,
   12496 			     master, source);
   12497 		/*
   12498 		 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
   12499 		 */
   12500 		if (msg->rcode == dns_rcode_refused &&
   12501 		    (zone->type == dns_zone_slave ||
   12502 		     zone->type == dns_zone_mirror ||
   12503 		     zone->type == dns_zone_redirect))
   12504 		{
   12505 			goto tcp_transfer;
   12506 		}
   12507 		goto next_master;
   12508 	}
   12509 
   12510 	/*
   12511 	 * If truncated punt to zone transfer which will query again.
   12512 	 */
   12513 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
   12514 		if (zone->type == dns_zone_slave ||
   12515 		    zone->type == dns_zone_mirror ||
   12516 		    zone->type == dns_zone_redirect)
   12517 		{
   12518 			dns_zone_log(zone, ISC_LOG_INFO,
   12519 				     "refresh: truncated UDP answer, "
   12520 				     "initiating TCP zone xfer "
   12521 				     "for master %s (source %s)",
   12522 				     master, source);
   12523 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
   12524 			goto tcp_transfer;
   12525 		} else {
   12526 			INSIST(zone->type == dns_zone_stub);
   12527 			if (dns_request_usedtcp(revent->request)) {
   12528 				dns_zone_log(zone, ISC_LOG_INFO,
   12529 					     "refresh: truncated TCP response "
   12530 					     "from master %s (source %s)",
   12531 					     master, source);
   12532 				goto next_master;
   12533 			}
   12534 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
   12535 			goto same_master;
   12536 		}
   12537 	}
   12538 
   12539 	/*
   12540 	 * if non-auth log and next master;
   12541 	 */
   12542 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
   12543 		dns_zone_log(zone, ISC_LOG_INFO,
   12544 			     "refresh: non-authoritative answer from "
   12545 			     "master %s (source %s)", master, source);
   12546 		goto next_master;
   12547 	}
   12548 
   12549 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
   12550 	soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
   12551 	nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
   12552 	soacount = message_count(msg, DNS_SECTION_AUTHORITY,
   12553 				 dns_rdatatype_soa);
   12554 
   12555 	/*
   12556 	 * There should not be a CNAME record at top of zone.
   12557 	 */
   12558 	if (cnamecnt != 0) {
   12559 		dns_zone_log(zone, ISC_LOG_INFO,
   12560 			     "refresh: CNAME at top of zone "
   12561 			     "in master %s (source %s)", master, source);
   12562 		goto next_master;
   12563 	}
   12564 
   12565 	/*
   12566 	 * if referral log and next master;
   12567 	 */
   12568 	if (soacnt == 0 && soacount == 0 && nscount != 0) {
   12569 		dns_zone_log(zone, ISC_LOG_INFO,
   12570 			     "refresh: referral response "
   12571 			     "from master %s (source %s)", master, source);
   12572 		goto next_master;
   12573 	}
   12574 
   12575 	/*
   12576 	 * if nodata log and next master;
   12577 	 */
   12578 	if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
   12579 		dns_zone_log(zone, ISC_LOG_INFO,
   12580 			     "refresh: NODATA response "
   12581 			     "from master %s (source %s)", master, source);
   12582 		goto next_master;
   12583 	}
   12584 
   12585 	/*
   12586 	 * Only one soa at top of zone.
   12587 	 */
   12588 	if (soacnt != 1) {
   12589 		dns_zone_log(zone, ISC_LOG_INFO,
   12590 			     "refresh: answer SOA count (%d) != 1 "
   12591 			     "from master %s (source %s)",
   12592 			     soacnt, master, source);
   12593 		goto next_master;
   12594 	}
   12595 
   12596 	/*
   12597 	 * Extract serial
   12598 	 */
   12599 	rdataset = NULL;
   12600 	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
   12601 				      dns_rdatatype_soa, dns_rdatatype_none,
   12602 				      NULL, &rdataset);
   12603 	if (result != ISC_R_SUCCESS) {
   12604 		dns_zone_log(zone, ISC_LOG_INFO,
   12605 			     "refresh: unable to get SOA record "
   12606 			     "from master %s (source %s)", master, source);
   12607 		goto next_master;
   12608 	}
   12609 
   12610 	result = dns_rdataset_first(rdataset);
   12611 	if (result != ISC_R_SUCCESS) {
   12612 		dns_zone_log(zone, ISC_LOG_INFO,
   12613 			     "refresh: dns_rdataset_first() failed");
   12614 		goto next_master;
   12615 	}
   12616 
   12617 	dns_rdataset_current(rdataset, &rdata);
   12618 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   12619 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   12620 
   12621 	serial = soa.serial;
   12622 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   12623 		unsigned int dbsoacount;
   12624 		result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
   12625 					  &oldserial, NULL, NULL, NULL, NULL,
   12626 					  NULL);
   12627 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   12628 		RUNTIME_CHECK(dbsoacount > 0U);
   12629 		zone_debuglog(zone, me, 1, "serial: new %u, old %u",
   12630 			      serial, oldserial);
   12631 	} else
   12632 		zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
   12633 			      serial);
   12634 
   12635 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
   12636 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
   12637 	    isc_serial_gt(serial, oldserial)) {
   12638 		if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
   12639 					    &zone->sourceaddr, &now))
   12640 		{
   12641 			dns_zone_log(zone, ISC_LOG_INFO,
   12642 				     "refresh: skipping %s as master %s "
   12643 				     "(source %s) is unreachable (cached)",
   12644 				     (zone->type == dns_zone_slave ||
   12645 				      zone->type == dns_zone_mirror ||
   12646 				      zone->type == dns_zone_redirect) ?
   12647 				     "zone transfer" : "NS query",
   12648 				     master, source);
   12649 			goto next_master;
   12650 		}
   12651  tcp_transfer:
   12652 		isc_event_free(&event);
   12653 		dns_request_destroy(&zone->request);
   12654 		if (zone->type == dns_zone_slave ||
   12655 		    zone->type == dns_zone_mirror ||
   12656 		    zone->type == dns_zone_redirect)
   12657 		{
   12658 			do_queue_xfrin = true;
   12659 		} else {
   12660 			INSIST(zone->type == dns_zone_stub);
   12661 			ns_query(zone, rdataset, NULL);
   12662 		}
   12663 		if (msg != NULL)
   12664 			dns_message_destroy(&msg);
   12665 	} else if (isc_serial_eq(soa.serial, oldserial)) {
   12666 		isc_time_t expiretime;
   12667 		uint32_t expire;
   12668 
   12669 		/*
   12670 		 * Compute the new expire time based on this response.
   12671 		 */
   12672 		expire = zone->expire;
   12673 		get_edns_expire(zone, msg, &expire);
   12674 		DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
   12675 
   12676 		/*
   12677 		 * Has the expire time improved?
   12678 		 */
   12679 		if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
   12680 			zone->expiretime = expiretime;
   12681 			if (zone->masterfile != NULL)
   12682 				setmodtime(zone, &expiretime);
   12683 		}
   12684 
   12685 		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
   12686 		zone->mastersok[zone->curmaster] = true;
   12687 		goto next_master;
   12688 	} else {
   12689 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
   12690 			dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
   12691 				     "received from master %s < ours (%u)",
   12692 				     soa.serial, master, oldserial);
   12693 		else
   12694 			zone_debuglog(zone, me, 1, "ahead");
   12695 		zone->mastersok[zone->curmaster] = true;
   12696 		goto next_master;
   12697 	}
   12698 	if (msg != NULL)
   12699 		dns_message_destroy(&msg);
   12700 	goto detach;
   12701 
   12702  next_master:
   12703 	if (msg != NULL)
   12704 		dns_message_destroy(&msg);
   12705 	isc_event_free(&event);
   12706 	dns_request_destroy(&zone->request);
   12707 	/*
   12708 	 * Skip to next failed / untried master.
   12709 	 */
   12710 	do {
   12711 		zone->curmaster++;
   12712 	} while (zone->curmaster < zone->masterscnt &&
   12713 		 zone->mastersok[zone->curmaster]);
   12714 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
   12715 	if (zone->curmaster >= zone->masterscnt) {
   12716 		bool done = true;
   12717 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
   12718 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   12719 			/*
   12720 			 * Did we get a good answer from all the masters?
   12721 			 */
   12722 			for (j = 0; j < zone->masterscnt; j++)
   12723 				if (zone->mastersok[j] == false) {
   12724 					done = false;
   12725 					break;
   12726 				}
   12727 		} else
   12728 			done = true;
   12729 		if (!done) {
   12730 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
   12731 			zone->curmaster = 0;
   12732 			/*
   12733 			 * Find the next failed master.
   12734 			 */
   12735 			while (zone->curmaster < zone->masterscnt &&
   12736 			       zone->mastersok[zone->curmaster])
   12737 				zone->curmaster++;
   12738 			goto requeue;
   12739 		}
   12740 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   12741 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
   12742 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   12743 			zone->refreshtime = now;
   12744 		}
   12745 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
   12746 		zone_settimer(zone, &now);
   12747 		goto detach;
   12748 	}
   12749 
   12750  requeue:
   12751 	queue_soa_query(zone);
   12752 	goto detach;
   12753 
   12754  same_master:
   12755 	if (msg != NULL)
   12756 		dns_message_destroy(&msg);
   12757 	isc_event_free(&event);
   12758 	dns_request_destroy(&zone->request);
   12759 	queue_soa_query(zone);
   12760 
   12761  detach:
   12762 	UNLOCK_ZONE(zone);
   12763 	if (do_queue_xfrin)
   12764 		queue_xfrin(zone);
   12765 	dns_zone_idetach(&zone);
   12766 	return;
   12767 }
   12768 
   12769 static void
   12770 queue_soa_query(dns_zone_t *zone) {
   12771 	const char me[] = "queue_soa_query";
   12772 	isc_event_t *e;
   12773 	dns_zone_t *dummy = NULL;
   12774 	isc_result_t result;
   12775 
   12776 	ENTER;
   12777 	/*
   12778 	 * Locked by caller
   12779 	 */
   12780 	REQUIRE(LOCKED_ZONE(zone));
   12781 
   12782 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   12783 		cancel_refresh(zone);
   12784 		return;
   12785 	}
   12786 
   12787 	e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
   12788 			       soa_query, zone, sizeof(isc_event_t));
   12789 	if (e == NULL) {
   12790 		cancel_refresh(zone);
   12791 		return;
   12792 	}
   12793 
   12794 	/*
   12795 	 * Attach so that we won't clean up
   12796 	 * until the event is delivered.
   12797 	 */
   12798 	zone_iattach(zone, &dummy);
   12799 
   12800 	e->ev_arg = zone;
   12801 	e->ev_sender = NULL;
   12802 	result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
   12803 	if (result != ISC_R_SUCCESS) {
   12804 		zone_idetach(&dummy);
   12805 		isc_event_free(&e);
   12806 		cancel_refresh(zone);
   12807 	}
   12808 }
   12809 
   12810 static inline isc_result_t
   12811 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
   12812 	     dns_message_t **messagep)
   12813 {
   12814 	dns_message_t *message = NULL;
   12815 	dns_name_t *qname = NULL;
   12816 	dns_rdataset_t *qrdataset = NULL;
   12817 	isc_result_t result;
   12818 
   12819 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
   12820 				    &message);
   12821 	if (result != ISC_R_SUCCESS)
   12822 		goto cleanup;
   12823 
   12824 	message->opcode = dns_opcode_query;
   12825 	message->rdclass = zone->rdclass;
   12826 
   12827 	result = dns_message_gettempname(message, &qname);
   12828 	if (result != ISC_R_SUCCESS)
   12829 		goto cleanup;
   12830 
   12831 	result = dns_message_gettemprdataset(message, &qrdataset);
   12832 	if (result != ISC_R_SUCCESS)
   12833 		goto cleanup;
   12834 
   12835 	/*
   12836 	 * Make question.
   12837 	 */
   12838 	dns_name_init(qname, NULL);
   12839 	dns_name_clone(&zone->origin, qname);
   12840 	dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
   12841 	ISC_LIST_APPEND(qname->list, qrdataset, link);
   12842 	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
   12843 
   12844 	*messagep = message;
   12845 	return (ISC_R_SUCCESS);
   12846 
   12847  cleanup:
   12848 	if (qname != NULL)
   12849 		dns_message_puttempname(message, &qname);
   12850 	if (qrdataset != NULL)
   12851 		dns_message_puttemprdataset(message, &qrdataset);
   12852 	if (message != NULL)
   12853 		dns_message_destroy(&message);
   12854 	return (result);
   12855 }
   12856 
   12857 static isc_result_t
   12858 add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
   12859 	bool reqexpire)
   12860 {
   12861 	isc_result_t result;
   12862 	dns_rdataset_t *rdataset = NULL;
   12863 	dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
   12864 	int count = 0;
   12865 
   12866 	/* Set EDNS options if applicable */
   12867 	if (reqnsid) {
   12868 		INSIST(count < DNS_EDNSOPTIONS);
   12869 		ednsopts[count].code = DNS_OPT_NSID;
   12870 		ednsopts[count].length = 0;
   12871 		ednsopts[count].value = NULL;
   12872 		count++;
   12873 	}
   12874 	if (reqexpire) {
   12875 		INSIST(count < DNS_EDNSOPTIONS);
   12876 		ednsopts[count].code = DNS_OPT_EXPIRE;
   12877 		ednsopts[count].length = 0;
   12878 		ednsopts[count].value = NULL;
   12879 		count++;
   12880 	}
   12881 	result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
   12882 				      ednsopts, count);
   12883 	if (result != ISC_R_SUCCESS)
   12884 		return (result);
   12885 
   12886 	return (dns_message_setopt(message, rdataset));
   12887 }
   12888 
   12889 static void
   12890 soa_query(isc_task_t *task, isc_event_t *event) {
   12891 	const char me[] = "soa_query";
   12892 	isc_result_t result = ISC_R_FAILURE;
   12893 	dns_message_t *message = NULL;
   12894 	dns_zone_t *zone = event->ev_arg;
   12895 	dns_zone_t *dummy = NULL;
   12896 	isc_netaddr_t masterip;
   12897 	dns_tsigkey_t *key = NULL;
   12898 	uint32_t options;
   12899 	bool cancel = true;
   12900 	int timeout;
   12901 	bool have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
   12902 	uint16_t udpsize = SEND_BUFFER_SIZE;
   12903 	isc_dscp_t dscp = -1;
   12904 
   12905 	REQUIRE(DNS_ZONE_VALID(zone));
   12906 
   12907 	UNUSED(task);
   12908 
   12909 	ENTER;
   12910 
   12911 	LOCK_ZONE(zone);
   12912 	if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
   12913 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
   12914 	    zone->view->requestmgr == NULL) {
   12915 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
   12916 			cancel = false;
   12917 		goto cleanup;
   12918 	}
   12919 
   12920  again:
   12921 	result = create_query(zone, dns_rdatatype_soa, &message);
   12922 	if (result != ISC_R_SUCCESS)
   12923 		goto cleanup;
   12924 
   12925 	INSIST(zone->masterscnt > 0);
   12926 	INSIST(zone->curmaster < zone->masterscnt);
   12927 
   12928 	zone->masteraddr = zone->masters[zone->curmaster];
   12929 
   12930 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
   12931 	/*
   12932 	 * First, look for a tsig key in the master statement, then
   12933 	 * try for a server key.
   12934 	 */
   12935 	if ((zone->masterkeynames != NULL) &&
   12936 	    (zone->masterkeynames[zone->curmaster] != NULL)) {
   12937 		dns_view_t *view = dns_zone_getview(zone);
   12938 		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
   12939 		result = dns_view_gettsig(view, keyname, &key);
   12940 		if (result != ISC_R_SUCCESS) {
   12941 			char namebuf[DNS_NAME_FORMATSIZE];
   12942 			dns_name_format(keyname, namebuf, sizeof(namebuf));
   12943 			dns_zone_log(zone, ISC_LOG_ERROR,
   12944 				     "unable to find key: %s", namebuf);
   12945 			goto skip_master;
   12946 		}
   12947 	}
   12948 	if (key == NULL) {
   12949 		result = dns_view_getpeertsig(zone->view, &masterip, &key);
   12950 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   12951 			char addrbuf[ISC_NETADDR_FORMATSIZE];
   12952 			isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
   12953 			dns_zone_log(zone, ISC_LOG_ERROR,
   12954 				     "unable to find TSIG key for %s", addrbuf);
   12955 			goto skip_master;
   12956 		}
   12957 	}
   12958 
   12959 	options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
   12960 		  DNS_REQUESTOPT_TCP : 0;
   12961 	have_xfrsource = have_xfrdscp = false;
   12962 	reqnsid = zone->view->requestnsid;
   12963 	reqexpire = zone->requestexpire;
   12964 	if (zone->view->peers != NULL) {
   12965 		dns_peer_t *peer = NULL;
   12966 		bool edns, usetcp;
   12967 		result = dns_peerlist_peerbyaddr(zone->view->peers,
   12968 						 &masterip, &peer);
   12969 		if (result == ISC_R_SUCCESS) {
   12970 			result = dns_peer_getsupportedns(peer, &edns);
   12971 			if (result == ISC_R_SUCCESS && !edns)
   12972 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   12973 			result = dns_peer_gettransfersource(peer,
   12974 							    &zone->sourceaddr);
   12975 			if (result == ISC_R_SUCCESS)
   12976 				have_xfrsource = true;
   12977 			(void)dns_peer_gettransferdscp(peer, &dscp);
   12978 			if (dscp != -1)
   12979 				have_xfrdscp = true;
   12980 			if (zone->view->resolver != NULL)
   12981 				udpsize =
   12982 				  dns_resolver_getudpsize(zone->view->resolver);
   12983 			(void)dns_peer_getudpsize(peer, &udpsize);
   12984 			(void)dns_peer_getrequestnsid(peer, &reqnsid);
   12985 			(void)dns_peer_getrequestexpire(peer, &reqexpire);
   12986 			result = dns_peer_getforcetcp(peer, &usetcp);
   12987 			if (result == ISC_R_SUCCESS && usetcp)
   12988 				options |= DNS_REQUESTOPT_TCP;
   12989 		}
   12990 	}
   12991 
   12992 	switch (isc_sockaddr_pf(&zone->masteraddr)) {
   12993 	case PF_INET:
   12994 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   12995 			if (isc_sockaddr_equal(&zone->altxfrsource4,
   12996 					       &zone->xfrsource4))
   12997 				goto skip_master;
   12998 			zone->sourceaddr = zone->altxfrsource4;
   12999 			if (!have_xfrdscp)
   13000 				dscp = zone->altxfrsource4dscp;
   13001 		} else if (!have_xfrsource) {
   13002 			zone->sourceaddr = zone->xfrsource4;
   13003 			if (!have_xfrdscp)
   13004 				dscp = zone->xfrsource4dscp;
   13005 		}
   13006 		break;
   13007 	case PF_INET6:
   13008 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   13009 			if (isc_sockaddr_equal(&zone->altxfrsource6,
   13010 					       &zone->xfrsource6))
   13011 				goto skip_master;
   13012 			zone->sourceaddr = zone->altxfrsource6;
   13013 			if (!have_xfrdscp)
   13014 				dscp = zone->altxfrsource6dscp;
   13015 		} else if (!have_xfrsource) {
   13016 			zone->sourceaddr = zone->xfrsource6;
   13017 			if (!have_xfrdscp)
   13018 				dscp = zone->xfrsource6dscp;
   13019 		}
   13020 		break;
   13021 	default:
   13022 		result = ISC_R_NOTIMPLEMENTED;
   13023 		goto cleanup;
   13024 	}
   13025 
   13026 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   13027 		result = add_opt(message, udpsize, reqnsid, reqexpire);
   13028 		if (result != ISC_R_SUCCESS)
   13029 			zone_debuglog(zone, me, 1,
   13030 				      "unable to add opt record: %s",
   13031 				      dns_result_totext(result));
   13032 	}
   13033 
   13034 	zone_iattach(zone, &dummy);
   13035 	timeout = 15;
   13036 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
   13037 		timeout = 30;
   13038 	result = dns_request_createvia(zone->view->requestmgr, message,
   13039 				       &zone->sourceaddr, &zone->masteraddr,
   13040 				       dscp, options, key, timeout * 3,
   13041 				       timeout, 0, zone->task,
   13042 				       refresh_callback, zone, &zone->request);
   13043 	if (result != ISC_R_SUCCESS) {
   13044 		zone_idetach(&dummy);
   13045 		zone_debuglog(zone, me, 1,
   13046 			      "dns_request_createvia4() failed: %s",
   13047 			      dns_result_totext(result));
   13048 		goto skip_master;
   13049 	} else {
   13050 		if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
   13051 			inc_stats(zone, dns_zonestatscounter_soaoutv4);
   13052 		else
   13053 			inc_stats(zone, dns_zonestatscounter_soaoutv6);
   13054 	}
   13055 	cancel = false;
   13056 
   13057  cleanup:
   13058 	if (key != NULL)
   13059 		dns_tsigkey_detach(&key);
   13060 	if (result != ISC_R_SUCCESS)
   13061 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   13062 	if (message != NULL)
   13063 		dns_message_destroy(&message);
   13064 	if (cancel)
   13065 		cancel_refresh(zone);
   13066 	isc_event_free(&event);
   13067 	UNLOCK_ZONE(zone);
   13068 	dns_zone_idetach(&zone);
   13069 	return;
   13070 
   13071  skip_master:
   13072 	if (key != NULL)
   13073 		dns_tsigkey_detach(&key);
   13074 	dns_message_destroy(&message);
   13075 	/*
   13076 	 * Skip to next failed / untried master.
   13077 	 */
   13078 	do {
   13079 		zone->curmaster++;
   13080 	} while (zone->curmaster < zone->masterscnt &&
   13081 		 zone->mastersok[zone->curmaster]);
   13082 	if (zone->curmaster < zone->masterscnt)
   13083 		goto again;
   13084 	zone->curmaster = 0;
   13085 	goto cleanup;
   13086 }
   13087 
   13088 static void
   13089 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
   13090 	const char me[] = "ns_query";
   13091 	isc_result_t result;
   13092 	dns_message_t *message = NULL;
   13093 	isc_netaddr_t masterip;
   13094 	dns_tsigkey_t *key = NULL;
   13095 	dns_dbnode_t *node = NULL;
   13096 	int timeout;
   13097 	bool have_xfrsource = false, have_xfrdscp = false;
   13098 	bool reqnsid;
   13099 	uint16_t udpsize = SEND_BUFFER_SIZE;
   13100 	isc_dscp_t dscp = -1;
   13101 
   13102 	REQUIRE(DNS_ZONE_VALID(zone));
   13103 	REQUIRE(LOCKED_ZONE(zone));
   13104 	REQUIRE((soardataset != NULL && stub == NULL) ||
   13105 		(soardataset == NULL && stub != NULL));
   13106 	REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
   13107 
   13108 	ENTER;
   13109 
   13110 	if (stub == NULL) {
   13111 		stub = isc_mem_get(zone->mctx, sizeof(*stub));
   13112 		if (stub == NULL)
   13113 			goto cleanup;
   13114 		stub->magic = STUB_MAGIC;
   13115 		stub->mctx = zone->mctx;
   13116 		stub->zone = NULL;
   13117 		stub->db = NULL;
   13118 		stub->version = NULL;
   13119 
   13120 		/*
   13121 		 * Attach so that the zone won't disappear from under us.
   13122 		 */
   13123 		zone_iattach(zone, &stub->zone);
   13124 
   13125 		/*
   13126 		 * If a db exists we will update it, otherwise we create a
   13127 		 * new one and attach it to the zone once we have the NS
   13128 		 * RRset and glue.
   13129 		 */
   13130 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   13131 		if (zone->db != NULL) {
   13132 			dns_db_attach(zone->db, &stub->db);
   13133 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   13134 		} else {
   13135 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   13136 
   13137 			INSIST(zone->db_argc >= 1);
   13138 			result = dns_db_create(zone->mctx, zone->db_argv[0],
   13139 					       &zone->origin, dns_dbtype_stub,
   13140 					       zone->rdclass,
   13141 					       zone->db_argc - 1,
   13142 					       zone->db_argv + 1,
   13143 					       &stub->db);
   13144 			if (result != ISC_R_SUCCESS) {
   13145 				dns_zone_log(zone, ISC_LOG_ERROR,
   13146 					     "refreshing stub: "
   13147 					     "could not create "
   13148 					     "database: %s",
   13149 					     dns_result_totext(result));
   13150 				goto cleanup;
   13151 			}
   13152 			dns_db_settask(stub->db, zone->task);
   13153 		}
   13154 
   13155 		result = dns_db_newversion(stub->db, &stub->version);
   13156 		if (result != ISC_R_SUCCESS) {
   13157 			dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
   13158 				     "dns_db_newversion() failed: %s",
   13159 				     dns_result_totext(result));
   13160 			goto cleanup;
   13161 		}
   13162 
   13163 		/*
   13164 		 * Update SOA record.
   13165 		 */
   13166 		result = dns_db_findnode(stub->db, &zone->origin, true,
   13167 					 &node);
   13168 		if (result != ISC_R_SUCCESS) {
   13169 			dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
   13170 				     "dns_db_findnode() failed: %s",
   13171 				     dns_result_totext(result));
   13172 			goto cleanup;
   13173 		}
   13174 
   13175 		result = dns_db_addrdataset(stub->db, node, stub->version, 0,
   13176 					    soardataset, 0, NULL);
   13177 		dns_db_detachnode(stub->db, &node);
   13178 		if (result != ISC_R_SUCCESS) {
   13179 			dns_zone_log(zone, ISC_LOG_INFO,
   13180 				     "refreshing stub: "
   13181 				     "dns_db_addrdataset() failed: %s",
   13182 				     dns_result_totext(result));
   13183 			goto cleanup;
   13184 		}
   13185 	}
   13186 
   13187 	/*
   13188 	 * XXX Optimisation: Create message when zone is setup and reuse.
   13189 	 */
   13190 	result = create_query(zone, dns_rdatatype_ns, &message);
   13191 	INSIST(result == ISC_R_SUCCESS);
   13192 
   13193 	INSIST(zone->masterscnt > 0);
   13194 	INSIST(zone->curmaster < zone->masterscnt);
   13195 	zone->masteraddr = zone->masters[zone->curmaster];
   13196 
   13197 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
   13198 	/*
   13199 	 * First, look for a tsig key in the master statement, then
   13200 	 * try for a server key.
   13201 	 */
   13202 	if ((zone->masterkeynames != NULL) &&
   13203 	    (zone->masterkeynames[zone->curmaster] != NULL)) {
   13204 		dns_view_t *view = dns_zone_getview(zone);
   13205 		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
   13206 		result = dns_view_gettsig(view, keyname, &key);
   13207 		if (result != ISC_R_SUCCESS) {
   13208 			char namebuf[DNS_NAME_FORMATSIZE];
   13209 			dns_name_format(keyname, namebuf, sizeof(namebuf));
   13210 			dns_zone_log(zone, ISC_LOG_ERROR,
   13211 				     "unable to find key: %s", namebuf);
   13212 		}
   13213 	}
   13214 	if (key == NULL)
   13215 		(void)dns_view_getpeertsig(zone->view, &masterip, &key);
   13216 
   13217 	reqnsid = zone->view->requestnsid;
   13218 	if (zone->view->peers != NULL) {
   13219 		dns_peer_t *peer = NULL;
   13220 		bool edns;
   13221 		result = dns_peerlist_peerbyaddr(zone->view->peers,
   13222 						 &masterip, &peer);
   13223 		if (result == ISC_R_SUCCESS) {
   13224 			result = dns_peer_getsupportedns(peer, &edns);
   13225 			if (result == ISC_R_SUCCESS && !edns)
   13226 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   13227 			result = dns_peer_gettransfersource(peer,
   13228 							    &zone->sourceaddr);
   13229 			if (result == ISC_R_SUCCESS)
   13230 				have_xfrsource = true;
   13231 			result = dns_peer_gettransferdscp(peer, &dscp);
   13232 			if (result == ISC_R_SUCCESS && dscp != -1)
   13233 				have_xfrdscp = true;
   13234 			if (zone->view->resolver != NULL)
   13235 				udpsize =
   13236 				  dns_resolver_getudpsize(zone->view->resolver);
   13237 			(void)dns_peer_getudpsize(peer, &udpsize);
   13238 			(void)dns_peer_getrequestnsid(peer, &reqnsid);
   13239 		}
   13240 
   13241 	}
   13242 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   13243 		result = add_opt(message, udpsize, reqnsid, false);
   13244 		if (result != ISC_R_SUCCESS)
   13245 			zone_debuglog(zone, me, 1,
   13246 				      "unable to add opt record: %s",
   13247 				      dns_result_totext(result));
   13248 	}
   13249 
   13250 	/*
   13251 	 * Always use TCP so that we shouldn't truncate in additional section.
   13252 	 */
   13253 	switch (isc_sockaddr_pf(&zone->masteraddr)) {
   13254 	case PF_INET:
   13255 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   13256 			zone->sourceaddr = zone->altxfrsource4;
   13257 			if (!have_xfrdscp)
   13258 				dscp = zone->altxfrsource4dscp;
   13259 		} else if (!have_xfrsource) {
   13260 			zone->sourceaddr = zone->xfrsource4;
   13261 			if (!have_xfrdscp)
   13262 				dscp = zone->xfrsource4dscp;
   13263 		}
   13264 		break;
   13265 	case PF_INET6:
   13266 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   13267 			zone->sourceaddr = zone->altxfrsource6;
   13268 			if (!have_xfrdscp)
   13269 				dscp = zone->altxfrsource6dscp;
   13270 		} else if (!have_xfrsource) {
   13271 			zone->sourceaddr = zone->xfrsource6;
   13272 			if (!have_xfrdscp)
   13273 				dscp = zone->xfrsource6dscp;
   13274 		}
   13275 		break;
   13276 	default:
   13277 		result = ISC_R_NOTIMPLEMENTED;
   13278 		POST(result);
   13279 		goto cleanup;
   13280 	}
   13281 	timeout = 15;
   13282 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
   13283 		timeout = 30;
   13284 	result = dns_request_createvia(zone->view->requestmgr, message,
   13285 				       &zone->sourceaddr, &zone->masteraddr,
   13286 				       dscp, DNS_REQUESTOPT_TCP, key,
   13287 				       timeout * 3, timeout, 0, zone->task,
   13288 				       stub_callback, stub, &zone->request);
   13289 	if (result != ISC_R_SUCCESS) {
   13290 		zone_debuglog(zone, me, 1,
   13291 			      "dns_request_createvia() failed: %s",
   13292 			      dns_result_totext(result));
   13293 		goto cleanup;
   13294 	}
   13295 	dns_message_destroy(&message);
   13296 	goto unlock;
   13297 
   13298  cleanup:
   13299 	cancel_refresh(zone);
   13300 	if (stub != NULL) {
   13301 		stub->magic = 0;
   13302 		if (stub->version != NULL)
   13303 			dns_db_closeversion(stub->db, &stub->version,
   13304 					    false);
   13305 		if (stub->db != NULL)
   13306 			dns_db_detach(&stub->db);
   13307 		if (stub->zone != NULL)
   13308 			zone_idetach(&stub->zone);
   13309 		isc_mem_put(stub->mctx, stub, sizeof(*stub));
   13310 	}
   13311 	if (message != NULL)
   13312 		dns_message_destroy(&message);
   13313  unlock:
   13314 	if (key != NULL)
   13315 		dns_tsigkey_detach(&key);
   13316 	return;
   13317 }
   13318 
   13319 /*
   13320  * Handle the control event.  Note that although this event causes the zone
   13321  * to shut down, it is not a shutdown event in the sense of the task library.
   13322  */
   13323 static void
   13324 zone_shutdown(isc_task_t *task, isc_event_t *event) {
   13325 	dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
   13326 	bool free_needed, linked = false;
   13327 	dns_zone_t *raw = NULL, *secure = NULL;
   13328 
   13329 	UNUSED(task);
   13330 	REQUIRE(DNS_ZONE_VALID(zone));
   13331 	INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
   13332 	INSIST(isc_refcount_current(&zone->erefs) == 0);
   13333 
   13334 	zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
   13335 
   13336 	/*
   13337 	 * Stop things being restarted after we cancel them below.
   13338 	 */
   13339 	LOCK_ZONE(zone);
   13340 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
   13341 	UNLOCK_ZONE(zone);
   13342 
   13343 	/*
   13344 	 * If we were waiting for xfrin quota, step out of
   13345 	 * the queue.
   13346 	 * If there's no zone manager, we can't be waiting for the
   13347 	 * xfrin quota
   13348 	 */
   13349 	if (zone->zmgr != NULL) {
   13350 		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   13351 		if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
   13352 			ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
   13353 					statelink);
   13354 			linked = true;
   13355 			zone->statelist = NULL;
   13356 		}
   13357 		if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
   13358 			ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
   13359 					statelink);
   13360 			zone->statelist = NULL;
   13361 			zmgr_resume_xfrs(zone->zmgr, false);
   13362 		}
   13363 		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   13364 	}
   13365 
   13366 	/*
   13367 	 * In task context, no locking required.  See zone_xfrdone().
   13368 	 */
   13369 	if (zone->xfr != NULL)
   13370 		dns_xfrin_shutdown(zone->xfr);
   13371 
   13372 	/* Safe to release the zone now */
   13373 	if (zone->zmgr != NULL)
   13374 		dns_zonemgr_releasezone(zone->zmgr, zone);
   13375 
   13376 	LOCK_ZONE(zone);
   13377 	INSIST(zone != zone->raw);
   13378 	if (linked) {
   13379 		INSIST(zone->irefs > 0);
   13380 		zone->irefs--;
   13381 	}
   13382 	if (zone->request != NULL) {
   13383 		dns_request_cancel(zone->request);
   13384 	}
   13385 
   13386 	if (zone->readio != NULL)
   13387 		zonemgr_cancelio(zone->readio);
   13388 
   13389 	if (zone->lctx != NULL)
   13390 		dns_loadctx_cancel(zone->lctx);
   13391 
   13392 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
   13393 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   13394 		if (zone->writeio != NULL)
   13395 			zonemgr_cancelio(zone->writeio);
   13396 
   13397 		if (zone->dctx != NULL)
   13398 			dns_dumpctx_cancel(zone->dctx);
   13399 	}
   13400 
   13401 	notify_cancel(zone);
   13402 
   13403 	forward_cancel(zone);
   13404 
   13405 	if (zone->timer != NULL) {
   13406 		isc_timer_detach(&zone->timer);
   13407 		INSIST(zone->irefs > 0);
   13408 		zone->irefs--;
   13409 	}
   13410 
   13411 	/*
   13412 	 * We have now canceled everything set the flag to allow exit_check()
   13413 	 * to succeed.	We must not unlock between setting this flag and
   13414 	 * calling exit_check().
   13415 	 */
   13416 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
   13417 	free_needed = exit_check(zone);
   13418 	if (inline_secure(zone)) {
   13419 		raw = zone->raw;
   13420 		zone->raw = NULL;
   13421 	}
   13422 	if (inline_raw(zone)) {
   13423 		secure = zone->secure;
   13424 		zone->secure = NULL;
   13425 	}
   13426 	UNLOCK_ZONE(zone);
   13427 	if (raw != NULL)
   13428 		dns_zone_detach(&raw);
   13429 	if (secure != NULL)
   13430 		dns_zone_idetach(&secure);
   13431 	if (free_needed)
   13432 		zone_free(zone);
   13433 }
   13434 
   13435 static void
   13436 zone_timer(isc_task_t *task, isc_event_t *event) {
   13437 	const char me[] = "zone_timer";
   13438 	dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
   13439 
   13440 	UNUSED(task);
   13441 	REQUIRE(DNS_ZONE_VALID(zone));
   13442 
   13443 	ENTER;
   13444 
   13445 	zone_maintenance(zone);
   13446 
   13447 	isc_event_free(&event);
   13448 }
   13449 
   13450 static void
   13451 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
   13452 	const char me[] = "zone_settimer";
   13453 	isc_time_t next;
   13454 	isc_result_t result;
   13455 
   13456 	REQUIRE(DNS_ZONE_VALID(zone));
   13457 	ENTER;
   13458 
   13459 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
   13460 		return;
   13461 
   13462 	isc_time_settoepoch(&next);
   13463 
   13464 	switch (zone->type) {
   13465 	case dns_zone_redirect:
   13466 		if (zone->masters != NULL)
   13467 			goto treat_as_slave;
   13468 		/* FALLTHROUGH */
   13469 
   13470 	case dns_zone_master:
   13471 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   13472 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
   13473 			next = zone->notifytime;
   13474 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   13475 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   13476 			INSIST(!isc_time_isepoch(&zone->dumptime));
   13477 			if (isc_time_isepoch(&next) ||
   13478 			    isc_time_compare(&zone->dumptime, &next) < 0)
   13479 				next = zone->dumptime;
   13480 		}
   13481 		if (zone->type == dns_zone_redirect)
   13482 			break;
   13483 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
   13484 		    !isc_time_isepoch(&zone->refreshkeytime)) {
   13485 			if (isc_time_isepoch(&next) ||
   13486 			    isc_time_compare(&zone->refreshkeytime, &next) < 0)
   13487 				next = zone->refreshkeytime;
   13488 		}
   13489 		if (!isc_time_isepoch(&zone->resigntime)) {
   13490 			if (isc_time_isepoch(&next) ||
   13491 			    isc_time_compare(&zone->resigntime, &next) < 0)
   13492 				next = zone->resigntime;
   13493 		}
   13494 		if (!isc_time_isepoch(&zone->keywarntime)) {
   13495 			if (isc_time_isepoch(&next) ||
   13496 			    isc_time_compare(&zone->keywarntime, &next) < 0)
   13497 				next = zone->keywarntime;
   13498 		}
   13499 		if (!isc_time_isepoch(&zone->signingtime)) {
   13500 			if (isc_time_isepoch(&next) ||
   13501 			    isc_time_compare(&zone->signingtime, &next) < 0)
   13502 				next = zone->signingtime;
   13503 		}
   13504 		if (!isc_time_isepoch(&zone->nsec3chaintime)) {
   13505 			if (isc_time_isepoch(&next) ||
   13506 			    isc_time_compare(&zone->nsec3chaintime, &next) < 0)
   13507 				next = zone->nsec3chaintime;
   13508 		}
   13509 		break;
   13510 
   13511 	case dns_zone_slave:
   13512 	case dns_zone_mirror:
   13513 	treat_as_slave:
   13514 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   13515 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
   13516 			next = zone->notifytime;
   13517 		/* FALLTHROUGH */
   13518 
   13519 	case dns_zone_stub:
   13520 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
   13521 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
   13522 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
   13523 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
   13524 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
   13525 		    !isc_time_isepoch(&zone->refreshtime) &&
   13526 		    (isc_time_isepoch(&next) ||
   13527 		     isc_time_compare(&zone->refreshtime, &next) < 0))
   13528 			next = zone->refreshtime;
   13529 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   13530 		    !isc_time_isepoch(&zone->expiretime)) {
   13531 			if (isc_time_isepoch(&next) ||
   13532 			     isc_time_compare(&zone->expiretime, &next) < 0)
   13533 				next = zone->expiretime;
   13534 		}
   13535 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   13536 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   13537 			INSIST(!isc_time_isepoch(&zone->dumptime));
   13538 			if (isc_time_isepoch(&next) ||
   13539 			    isc_time_compare(&zone->dumptime, &next) < 0)
   13540 				next = zone->dumptime;
   13541 		}
   13542 		break;
   13543 
   13544 	case dns_zone_key:
   13545 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   13546 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   13547 			INSIST(!isc_time_isepoch(&zone->dumptime));
   13548 			if (isc_time_isepoch(&next) ||
   13549 			    isc_time_compare(&zone->dumptime, &next) < 0)
   13550 				next = zone->dumptime;
   13551 		}
   13552 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
   13553 			if (isc_time_isepoch(&next) ||
   13554 			    (!isc_time_isepoch(&zone->refreshkeytime) &&
   13555 			    isc_time_compare(&zone->refreshkeytime, &next) < 0))
   13556 				next = zone->refreshkeytime;
   13557 		}
   13558 		break;
   13559 
   13560 	default:
   13561 		break;
   13562 	}
   13563 
   13564 	if (isc_time_isepoch(&next)) {
   13565 		zone_debuglog(zone, me, 10, "settimer inactive");
   13566 		result = isc_timer_reset(zone->timer, isc_timertype_inactive,
   13567 					  NULL, NULL, true);
   13568 		if (result != ISC_R_SUCCESS)
   13569 			dns_zone_log(zone, ISC_LOG_ERROR,
   13570 				     "could not deactivate zone timer: %s",
   13571 				     isc_result_totext(result));
   13572 	} else {
   13573 		if (isc_time_compare(&next, now) <= 0)
   13574 			next = *now;
   13575 		result = isc_timer_reset(zone->timer, isc_timertype_once,
   13576 					 &next, NULL, true);
   13577 		if (result != ISC_R_SUCCESS)
   13578 			dns_zone_log(zone, ISC_LOG_ERROR,
   13579 				     "could not reset zone timer: %s",
   13580 				     isc_result_totext(result));
   13581 	}
   13582 }
   13583 
   13584 static void
   13585 cancel_refresh(dns_zone_t *zone) {
   13586 	const char me[] = "cancel_refresh";
   13587 	isc_time_t now;
   13588 
   13589 	/*
   13590 	 * 'zone' locked by caller.
   13591 	 */
   13592 
   13593 	REQUIRE(DNS_ZONE_VALID(zone));
   13594 	REQUIRE(LOCKED_ZONE(zone));
   13595 
   13596 	ENTER;
   13597 
   13598 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   13599 	TIME_NOW(&now);
   13600 	zone_settimer(zone, &now);
   13601 }
   13602 
   13603 static isc_result_t
   13604 notify_createmessage(dns_zone_t *zone, unsigned int flags,
   13605 		     dns_message_t **messagep)
   13606 {
   13607 	dns_db_t *zonedb = NULL;
   13608 	dns_dbnode_t *node = NULL;
   13609 	dns_dbversion_t *version = NULL;
   13610 	dns_message_t *message = NULL;
   13611 	dns_rdataset_t rdataset;
   13612 	dns_rdata_t rdata = DNS_RDATA_INIT;
   13613 
   13614 	dns_name_t *tempname = NULL;
   13615 	dns_rdata_t *temprdata = NULL;
   13616 	dns_rdatalist_t *temprdatalist = NULL;
   13617 	dns_rdataset_t *temprdataset = NULL;
   13618 
   13619 	isc_result_t result;
   13620 	isc_region_t r;
   13621 	isc_buffer_t *b = NULL;
   13622 
   13623 	REQUIRE(DNS_ZONE_VALID(zone));
   13624 	REQUIRE(messagep != NULL && *messagep == NULL);
   13625 
   13626 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
   13627 				    &message);
   13628 	if (result != ISC_R_SUCCESS)
   13629 		return (result);
   13630 
   13631 	message->opcode = dns_opcode_notify;
   13632 	message->flags |= DNS_MESSAGEFLAG_AA;
   13633 	message->rdclass = zone->rdclass;
   13634 
   13635 	result = dns_message_gettempname(message, &tempname);
   13636 	if (result != ISC_R_SUCCESS)
   13637 		goto cleanup;
   13638 
   13639 	result = dns_message_gettemprdataset(message, &temprdataset);
   13640 	if (result != ISC_R_SUCCESS)
   13641 		goto cleanup;
   13642 
   13643 	/*
   13644 	 * Make question.
   13645 	 */
   13646 	dns_name_init(tempname, NULL);
   13647 	dns_name_clone(&zone->origin, tempname);
   13648 	dns_rdataset_makequestion(temprdataset, zone->rdclass,
   13649 				  dns_rdatatype_soa);
   13650 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
   13651 	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
   13652 	tempname = NULL;
   13653 	temprdataset = NULL;
   13654 
   13655 	if ((flags & DNS_NOTIFY_NOSOA) != 0)
   13656 		goto done;
   13657 
   13658 	result = dns_message_gettempname(message, &tempname);
   13659 	if (result != ISC_R_SUCCESS)
   13660 		goto soa_cleanup;
   13661 	result = dns_message_gettemprdata(message, &temprdata);
   13662 	if (result != ISC_R_SUCCESS)
   13663 		goto soa_cleanup;
   13664 	result = dns_message_gettemprdataset(message, &temprdataset);
   13665 	if (result != ISC_R_SUCCESS)
   13666 		goto soa_cleanup;
   13667 	result = dns_message_gettemprdatalist(message, &temprdatalist);
   13668 	if (result != ISC_R_SUCCESS)
   13669 		goto soa_cleanup;
   13670 
   13671 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   13672 	INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
   13673 	dns_db_attach(zone->db, &zonedb);
   13674 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   13675 
   13676 	dns_name_init(tempname, NULL);
   13677 	dns_name_clone(&zone->origin, tempname);
   13678 	dns_db_currentversion(zonedb, &version);
   13679 	result = dns_db_findnode(zonedb, tempname, false, &node);
   13680 	if (result != ISC_R_SUCCESS)
   13681 		goto soa_cleanup;
   13682 
   13683 	dns_rdataset_init(&rdataset);
   13684 	result = dns_db_findrdataset(zonedb, node, version,
   13685 				     dns_rdatatype_soa,
   13686 				     dns_rdatatype_none, 0, &rdataset,
   13687 				     NULL);
   13688 	if (result != ISC_R_SUCCESS)
   13689 		goto soa_cleanup;
   13690 	result = dns_rdataset_first(&rdataset);
   13691 	if (result != ISC_R_SUCCESS)
   13692 		goto soa_cleanup;
   13693 	dns_rdataset_current(&rdataset, &rdata);
   13694 	dns_rdata_toregion(&rdata, &r);
   13695 	result = isc_buffer_allocate(zone->mctx, &b, r.length);
   13696 	if (result != ISC_R_SUCCESS)
   13697 		goto soa_cleanup;
   13698 	isc_buffer_putmem(b, r.base, r.length);
   13699 	isc_buffer_usedregion(b, &r);
   13700 	dns_rdata_init(temprdata);
   13701 	dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
   13702 	dns_message_takebuffer(message, &b);
   13703 	result = dns_rdataset_next(&rdataset);
   13704 	dns_rdataset_disassociate(&rdataset);
   13705 	if (result != ISC_R_NOMORE)
   13706 		goto soa_cleanup;
   13707 	temprdatalist->rdclass = rdata.rdclass;
   13708 	temprdatalist->type = rdata.type;
   13709 	temprdatalist->ttl = rdataset.ttl;
   13710 	ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
   13711 
   13712 	result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
   13713 	if (result != ISC_R_SUCCESS)
   13714 		goto soa_cleanup;
   13715 
   13716 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
   13717 	dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
   13718 	temprdatalist = NULL;
   13719 	temprdataset = NULL;
   13720 	temprdata = NULL;
   13721 	tempname = NULL;
   13722 
   13723  soa_cleanup:
   13724 	if (node != NULL)
   13725 		dns_db_detachnode(zonedb, &node);
   13726 	if (version != NULL)
   13727 		dns_db_closeversion(zonedb, &version, false);
   13728 	if (zonedb != NULL)
   13729 		dns_db_detach(&zonedb);
   13730 	if (tempname != NULL)
   13731 		dns_message_puttempname(message, &tempname);
   13732 	if (temprdata != NULL)
   13733 		dns_message_puttemprdata(message, &temprdata);
   13734 	if (temprdataset != NULL)
   13735 		dns_message_puttemprdataset(message, &temprdataset);
   13736 	if (temprdatalist != NULL)
   13737 		dns_message_puttemprdatalist(message, &temprdatalist);
   13738 
   13739  done:
   13740 	*messagep = message;
   13741 	return (ISC_R_SUCCESS);
   13742 
   13743  cleanup:
   13744 	if (tempname != NULL)
   13745 		dns_message_puttempname(message, &tempname);
   13746 	if (temprdataset != NULL)
   13747 		dns_message_puttemprdataset(message, &temprdataset);
   13748 	dns_message_destroy(&message);
   13749 	return (result);
   13750 }
   13751 
   13752 isc_result_t
   13753 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
   13754 		       isc_sockaddr_t *to, dns_message_t *msg)
   13755 {
   13756 	unsigned int i;
   13757 	dns_rdata_soa_t soa;
   13758 	dns_rdataset_t *rdataset = NULL;
   13759 	dns_rdata_t rdata = DNS_RDATA_INIT;
   13760 	isc_result_t result;
   13761 	char fromtext[ISC_SOCKADDR_FORMATSIZE];
   13762 	int match = 0;
   13763 	isc_netaddr_t netaddr;
   13764 	uint32_t serial = 0;
   13765 	bool have_serial = false;
   13766 	dns_tsigkey_t *tsigkey;
   13767 	const dns_name_t *tsig;
   13768 
   13769 	REQUIRE(DNS_ZONE_VALID(zone));
   13770 
   13771 	/*
   13772 	 * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
   13773 	 * ROLLOVER.
   13774 	 *
   13775 	 * SOA:	RFC1996
   13776 	 * Check that 'from' is a valid notify source, (zone->masters).
   13777 	 *	Return DNS_R_REFUSED if not.
   13778 	 *
   13779 	 * If the notify message contains a serial number check it
   13780 	 * against the zones serial and return if <= current serial
   13781 	 *
   13782 	 * If a refresh check is progress, if so just record the
   13783 	 * fact we received a NOTIFY and from where and return.
   13784 	 * We will perform a new refresh check when the current one
   13785 	 * completes. Return ISC_R_SUCCESS.
   13786 	 *
   13787 	 * Otherwise initiate a refresh check using 'from' as the
   13788 	 * first address to check.  Return ISC_R_SUCCESS.
   13789 	 */
   13790 
   13791 	isc_sockaddr_format(from, fromtext, sizeof(fromtext));
   13792 
   13793 	/*
   13794 	 * Notify messages are processed by the raw zone.
   13795 	 */
   13796 	LOCK_ZONE(zone);
   13797 	INSIST(zone != zone->raw);
   13798 	if (inline_secure(zone)) {
   13799 		result = dns_zone_notifyreceive(zone->raw, from, to, msg);
   13800 		UNLOCK_ZONE(zone);
   13801 		return (result);
   13802 	}
   13803 	/*
   13804 	 *  We only handle NOTIFY (SOA) at the present.
   13805 	 */
   13806 	if (isc_sockaddr_pf(from) == PF_INET)
   13807 		inc_stats(zone, dns_zonestatscounter_notifyinv4);
   13808 	else
   13809 		inc_stats(zone, dns_zonestatscounter_notifyinv6);
   13810 	if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
   13811 	    dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
   13812 				 dns_rdatatype_soa, dns_rdatatype_none,
   13813 				 NULL, NULL) != ISC_R_SUCCESS) {
   13814 		UNLOCK_ZONE(zone);
   13815 		if (msg->counts[DNS_SECTION_QUESTION] == 0) {
   13816 			dns_zone_log(zone, ISC_LOG_NOTICE,
   13817 				     "NOTIFY with no "
   13818 				     "question section from: %s", fromtext);
   13819 			return (DNS_R_FORMERR);
   13820 		}
   13821 		dns_zone_log(zone, ISC_LOG_NOTICE,
   13822 			     "NOTIFY zone does not match");
   13823 		return (DNS_R_NOTIMP);
   13824 	}
   13825 
   13826 	/*
   13827 	 * If we are a master zone just succeed.
   13828 	 */
   13829 	if (zone->type == dns_zone_master) {
   13830 		UNLOCK_ZONE(zone);
   13831 		return (ISC_R_SUCCESS);
   13832 	}
   13833 
   13834 	isc_netaddr_fromsockaddr(&netaddr, from);
   13835 	for (i = 0; i < zone->masterscnt; i++) {
   13836 		if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
   13837 			break;
   13838 		if (zone->view->aclenv.match_mapped &&
   13839 		    IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
   13840 		    isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
   13841 			isc_netaddr_t na1, na2;
   13842 			isc_netaddr_fromv4mapped(&na1, &netaddr);
   13843 			isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
   13844 			if (isc_netaddr_equal(&na1, &na2))
   13845 				break;
   13846 		}
   13847 	}
   13848 
   13849 	/*
   13850 	 * Accept notify requests from non masters if they are on
   13851 	 * 'zone->notify_acl'.
   13852 	 */
   13853 	tsigkey = dns_message_gettsigkey(msg);
   13854 	tsig = dns_tsigkey_identity(tsigkey);
   13855 	if (i >= zone->masterscnt && zone->notify_acl != NULL &&
   13856 	    (dns_acl_match(&netaddr, tsig, zone->notify_acl,
   13857 			   &zone->view->aclenv, &match,
   13858 			   NULL) == ISC_R_SUCCESS) &&
   13859 	    match > 0)
   13860 	{
   13861 		/* Accept notify. */
   13862 	} else if (i >= zone->masterscnt) {
   13863 		UNLOCK_ZONE(zone);
   13864 		dns_zone_log(zone, ISC_LOG_INFO,
   13865 			     "refused notify from non-master: %s", fromtext);
   13866 		inc_stats(zone, dns_zonestatscounter_notifyrej);
   13867 		return (DNS_R_REFUSED);
   13868 	}
   13869 
   13870 	/*
   13871 	 * If the zone is loaded and there are answers check the serial
   13872 	 * to see if we need to do a refresh.  Do not worry about this
   13873 	 * check if we are a dialup zone as we use the notify request
   13874 	 * to trigger a refresh check.
   13875 	 */
   13876 	if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
   13877 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   13878 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
   13879 		result = dns_message_findname(msg, DNS_SECTION_ANSWER,
   13880 					      &zone->origin,
   13881 					      dns_rdatatype_soa,
   13882 					      dns_rdatatype_none, NULL,
   13883 					      &rdataset);
   13884 		if (result == ISC_R_SUCCESS)
   13885 			result = dns_rdataset_first(rdataset);
   13886 		if (result == ISC_R_SUCCESS) {
   13887 			uint32_t oldserial;
   13888 			unsigned int soacount;
   13889 
   13890 			dns_rdataset_current(rdataset, &rdata);
   13891 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
   13892 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   13893 			serial = soa.serial;
   13894 			have_serial = true;
   13895 			/*
   13896 			 * The following should safely be performed without DB
   13897 			 * lock and succeed in this context.
   13898 			 */
   13899 			result = zone_get_from_db(zone, zone->db, NULL,
   13900 						  &soacount, &oldserial, NULL,
   13901 						  NULL, NULL, NULL, NULL);
   13902 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   13903 			RUNTIME_CHECK(soacount > 0U);
   13904 			if (isc_serial_le(serial, oldserial)) {
   13905 				dns_zone_log(zone,
   13906 					     ISC_LOG_INFO,
   13907 					     "notify from %s: "
   13908 					     "zone is up to date",
   13909 					     fromtext);
   13910 				UNLOCK_ZONE(zone);
   13911 				return (ISC_R_SUCCESS);
   13912 			}
   13913 		}
   13914 	}
   13915 
   13916 	/*
   13917 	 * If we got this far and there was a refresh in progress just
   13918 	 * let it complete.  Record where we got the notify from so we
   13919 	 * can perform a refresh check when the current one completes
   13920 	 */
   13921 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
   13922 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   13923 		zone->notifyfrom = *from;
   13924 		UNLOCK_ZONE(zone);
   13925 		if (have_serial)
   13926 			dns_zone_log(zone, ISC_LOG_INFO,
   13927 				     "notify from %s: serial %u: refresh in "
   13928 				     "progress, refresh check queued",
   13929 				      fromtext, serial);
   13930 		else
   13931 			dns_zone_log(zone, ISC_LOG_INFO,
   13932 				     "notify from %s: refresh in progress, "
   13933 				     "refresh check queued", fromtext);
   13934 		return (ISC_R_SUCCESS);
   13935 	}
   13936 	if (have_serial)
   13937 		dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
   13938 			     fromtext, serial);
   13939 	else
   13940 		dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
   13941 			     fromtext);
   13942 	zone->notifyfrom = *from;
   13943 	UNLOCK_ZONE(zone);
   13944 
   13945 	if (to != NULL) {
   13946 		dns_zonemgr_unreachabledel(zone->zmgr, from, to);
   13947 	}
   13948 	dns_zone_refresh(zone);
   13949 	return (ISC_R_SUCCESS);
   13950 }
   13951 
   13952 void
   13953 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
   13954 
   13955 	REQUIRE(DNS_ZONE_VALID(zone));
   13956 
   13957 	LOCK_ZONE(zone);
   13958 	if (zone->notify_acl != NULL)
   13959 		dns_acl_detach(&zone->notify_acl);
   13960 	dns_acl_attach(acl, &zone->notify_acl);
   13961 	UNLOCK_ZONE(zone);
   13962 }
   13963 
   13964 void
   13965 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
   13966 
   13967 	REQUIRE(DNS_ZONE_VALID(zone));
   13968 
   13969 	LOCK_ZONE(zone);
   13970 	if (zone->query_acl != NULL)
   13971 		dns_acl_detach(&zone->query_acl);
   13972 	dns_acl_attach(acl, &zone->query_acl);
   13973 	UNLOCK_ZONE(zone);
   13974 }
   13975 
   13976 void
   13977 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
   13978 
   13979 	REQUIRE(DNS_ZONE_VALID(zone));
   13980 
   13981 	LOCK_ZONE(zone);
   13982 	if (zone->queryon_acl != NULL)
   13983 		dns_acl_detach(&zone->queryon_acl);
   13984 	dns_acl_attach(acl, &zone->queryon_acl);
   13985 	UNLOCK_ZONE(zone);
   13986 }
   13987 
   13988 void
   13989 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
   13990 
   13991 	REQUIRE(DNS_ZONE_VALID(zone));
   13992 
   13993 	LOCK_ZONE(zone);
   13994 	if (zone->update_acl != NULL)
   13995 		dns_acl_detach(&zone->update_acl);
   13996 	dns_acl_attach(acl, &zone->update_acl);
   13997 	UNLOCK_ZONE(zone);
   13998 }
   13999 
   14000 void
   14001 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
   14002 
   14003 	REQUIRE(DNS_ZONE_VALID(zone));
   14004 
   14005 	LOCK_ZONE(zone);
   14006 	if (zone->forward_acl != NULL)
   14007 		dns_acl_detach(&zone->forward_acl);
   14008 	dns_acl_attach(acl, &zone->forward_acl);
   14009 	UNLOCK_ZONE(zone);
   14010 }
   14011 
   14012 void
   14013 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
   14014 
   14015 	REQUIRE(DNS_ZONE_VALID(zone));
   14016 
   14017 	LOCK_ZONE(zone);
   14018 	if (zone->xfr_acl != NULL)
   14019 		dns_acl_detach(&zone->xfr_acl);
   14020 	dns_acl_attach(acl, &zone->xfr_acl);
   14021 	UNLOCK_ZONE(zone);
   14022 }
   14023 
   14024 dns_acl_t *
   14025 dns_zone_getnotifyacl(dns_zone_t *zone) {
   14026 
   14027 	REQUIRE(DNS_ZONE_VALID(zone));
   14028 
   14029 	return (zone->notify_acl);
   14030 }
   14031 
   14032 dns_acl_t *
   14033 dns_zone_getqueryacl(dns_zone_t *zone) {
   14034 
   14035 	REQUIRE(DNS_ZONE_VALID(zone));
   14036 
   14037 	return (zone->query_acl);
   14038 }
   14039 
   14040 dns_acl_t *
   14041 dns_zone_getqueryonacl(dns_zone_t *zone) {
   14042 
   14043 	REQUIRE(DNS_ZONE_VALID(zone));
   14044 
   14045 	return (zone->queryon_acl);
   14046 }
   14047 
   14048 dns_acl_t *
   14049 dns_zone_getupdateacl(dns_zone_t *zone) {
   14050 
   14051 	REQUIRE(DNS_ZONE_VALID(zone));
   14052 
   14053 	return (zone->update_acl);
   14054 }
   14055 
   14056 dns_acl_t *
   14057 dns_zone_getforwardacl(dns_zone_t *zone) {
   14058 
   14059 	REQUIRE(DNS_ZONE_VALID(zone));
   14060 
   14061 	return (zone->forward_acl);
   14062 }
   14063 
   14064 dns_acl_t *
   14065 dns_zone_getxfracl(dns_zone_t *zone) {
   14066 
   14067 	REQUIRE(DNS_ZONE_VALID(zone));
   14068 
   14069 	return (zone->xfr_acl);
   14070 }
   14071 
   14072 void
   14073 dns_zone_clearupdateacl(dns_zone_t *zone) {
   14074 
   14075 	REQUIRE(DNS_ZONE_VALID(zone));
   14076 
   14077 	LOCK_ZONE(zone);
   14078 	if (zone->update_acl != NULL)
   14079 		dns_acl_detach(&zone->update_acl);
   14080 	UNLOCK_ZONE(zone);
   14081 }
   14082 
   14083 void
   14084 dns_zone_clearforwardacl(dns_zone_t *zone) {
   14085 
   14086 	REQUIRE(DNS_ZONE_VALID(zone));
   14087 
   14088 	LOCK_ZONE(zone);
   14089 	if (zone->forward_acl != NULL)
   14090 		dns_acl_detach(&zone->forward_acl);
   14091 	UNLOCK_ZONE(zone);
   14092 }
   14093 
   14094 void
   14095 dns_zone_clearnotifyacl(dns_zone_t *zone) {
   14096 
   14097 	REQUIRE(DNS_ZONE_VALID(zone));
   14098 
   14099 	LOCK_ZONE(zone);
   14100 	if (zone->notify_acl != NULL)
   14101 		dns_acl_detach(&zone->notify_acl);
   14102 	UNLOCK_ZONE(zone);
   14103 }
   14104 
   14105 void
   14106 dns_zone_clearqueryacl(dns_zone_t *zone) {
   14107 
   14108 	REQUIRE(DNS_ZONE_VALID(zone));
   14109 
   14110 	LOCK_ZONE(zone);
   14111 	if (zone->query_acl != NULL)
   14112 		dns_acl_detach(&zone->query_acl);
   14113 	UNLOCK_ZONE(zone);
   14114 }
   14115 
   14116 void
   14117 dns_zone_clearqueryonacl(dns_zone_t *zone) {
   14118 
   14119 	REQUIRE(DNS_ZONE_VALID(zone));
   14120 
   14121 	LOCK_ZONE(zone);
   14122 	if (zone->queryon_acl != NULL)
   14123 		dns_acl_detach(&zone->queryon_acl);
   14124 	UNLOCK_ZONE(zone);
   14125 }
   14126 
   14127 void
   14128 dns_zone_clearxfracl(dns_zone_t *zone) {
   14129 
   14130 	REQUIRE(DNS_ZONE_VALID(zone));
   14131 
   14132 	LOCK_ZONE(zone);
   14133 	if (zone->xfr_acl != NULL)
   14134 		dns_acl_detach(&zone->xfr_acl);
   14135 	UNLOCK_ZONE(zone);
   14136 }
   14137 
   14138 bool
   14139 dns_zone_getupdatedisabled(dns_zone_t *zone) {
   14140 	REQUIRE(DNS_ZONE_VALID(zone));
   14141 	return (zone->update_disabled);
   14142 
   14143 }
   14144 
   14145 void
   14146 dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
   14147 	REQUIRE(DNS_ZONE_VALID(zone));
   14148 	zone->update_disabled = state;
   14149 }
   14150 
   14151 bool
   14152 dns_zone_getzeronosoattl(dns_zone_t *zone) {
   14153 	REQUIRE(DNS_ZONE_VALID(zone));
   14154 	return (zone->zero_no_soa_ttl);
   14155 
   14156 }
   14157 
   14158 void
   14159 dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
   14160 	REQUIRE(DNS_ZONE_VALID(zone));
   14161 	zone->zero_no_soa_ttl = state;
   14162 }
   14163 
   14164 void
   14165 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
   14166 	REQUIRE(DNS_ZONE_VALID(zone));
   14167 
   14168 	zone->check_names = severity;
   14169 }
   14170 
   14171 dns_severity_t
   14172 dns_zone_getchecknames(dns_zone_t *zone) {
   14173 	REQUIRE(DNS_ZONE_VALID(zone));
   14174 
   14175 	return (zone->check_names);
   14176 }
   14177 
   14178 void
   14179 dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
   14180 	REQUIRE(DNS_ZONE_VALID(zone));
   14181 
   14182 	zone->journalsize = size;
   14183 }
   14184 
   14185 int32_t
   14186 dns_zone_getjournalsize(dns_zone_t *zone) {
   14187 	REQUIRE(DNS_ZONE_VALID(zone));
   14188 
   14189 	return (zone->journalsize);
   14190 }
   14191 
   14192 static void
   14193 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
   14194 	isc_result_t result = ISC_R_FAILURE;
   14195 	isc_buffer_t buffer;
   14196 
   14197 	REQUIRE(buf != NULL);
   14198 	REQUIRE(length > 1U);
   14199 
   14200 	/*
   14201 	 * Leave space for terminating '\0'.
   14202 	 */
   14203 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   14204 	if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
   14205 		if (dns_name_dynamic(&zone->origin))
   14206 			result = dns_name_totext(&zone->origin, true, &buffer);
   14207 		if (result != ISC_R_SUCCESS &&
   14208 		    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
   14209 			isc_buffer_putstr(&buffer, "<UNKNOWN>");
   14210 
   14211 		if (isc_buffer_availablelength(&buffer) > 0)
   14212 			isc_buffer_putstr(&buffer, "/");
   14213 		(void)dns_rdataclass_totext(zone->rdclass, &buffer);
   14214 	}
   14215 
   14216 	if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
   14217 	    strcmp(zone->view->name, "_default") != 0 &&
   14218 	    strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
   14219 		isc_buffer_putstr(&buffer, "/");
   14220 		isc_buffer_putstr(&buffer, zone->view->name);
   14221 	}
   14222 	if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
   14223 		isc_buffer_putstr(&buffer, " (signed)");
   14224 	if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
   14225 		isc_buffer_putstr(&buffer, " (unsigned)");
   14226 
   14227 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   14228 }
   14229 
   14230 static void
   14231 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
   14232 	isc_result_t result = ISC_R_FAILURE;
   14233 	isc_buffer_t buffer;
   14234 
   14235 	REQUIRE(buf != NULL);
   14236 	REQUIRE(length > 1U);
   14237 
   14238 	/*
   14239 	 * Leave space for terminating '\0'.
   14240 	 */
   14241 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   14242 	if (dns_name_dynamic(&zone->origin))
   14243 		result = dns_name_totext(&zone->origin, true, &buffer);
   14244 	if (result != ISC_R_SUCCESS &&
   14245 	    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
   14246 		isc_buffer_putstr(&buffer, "<UNKNOWN>");
   14247 
   14248 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   14249 }
   14250 
   14251 static void
   14252 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
   14253 	isc_buffer_t buffer;
   14254 
   14255 	REQUIRE(buf != NULL);
   14256 	REQUIRE(length > 1U);
   14257 
   14258 	/*
   14259 	 * Leave space for terminating '\0'.
   14260 	 */
   14261 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   14262 	(void)dns_rdataclass_totext(zone->rdclass, &buffer);
   14263 
   14264 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   14265 }
   14266 
   14267 static void
   14268 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
   14269 	isc_buffer_t buffer;
   14270 
   14271 	REQUIRE(buf != NULL);
   14272 	REQUIRE(length > 1U);
   14273 
   14274 
   14275 	/*
   14276 	 * Leave space for terminating '\0'.
   14277 	 */
   14278 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   14279 
   14280 	if (zone->view == NULL) {
   14281 		isc_buffer_putstr(&buffer, "_none");
   14282 	} else if (strlen(zone->view->name)
   14283 		   < isc_buffer_availablelength(&buffer)) {
   14284 		isc_buffer_putstr(&buffer, zone->view->name);
   14285 	} else {
   14286 		isc_buffer_putstr(&buffer, "_toolong");
   14287 	}
   14288 
   14289 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   14290 }
   14291 
   14292 void
   14293 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
   14294 	REQUIRE(DNS_ZONE_VALID(zone));
   14295 	REQUIRE(buf != NULL);
   14296 	zone_namerd_tostr(zone, buf, length);
   14297 }
   14298 
   14299 void
   14300 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
   14301 	REQUIRE(DNS_ZONE_VALID(zone));
   14302 	REQUIRE(buf != NULL);
   14303 	zone_name_tostr(zone, buf, length);
   14304 }
   14305 
   14306 void
   14307 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
   14308 	      const char *prefix, const char *fmt, va_list ap)
   14309 {
   14310 	char message[4096];
   14311 	const char *zstr;
   14312 
   14313 	if (!isc_log_wouldlog(dns_lctx, level)) {
   14314 		return;
   14315 	}
   14316 
   14317 	vsnprintf(message, sizeof(message), fmt, ap);
   14318 
   14319 	switch (zone->type) {
   14320 	case dns_zone_key:
   14321 		zstr = "managed-keys-zone";
   14322 		break;
   14323 	case dns_zone_redirect:
   14324 		zstr = "redirect-zone";
   14325 		break;
   14326 	default:
   14327 		zstr = "zone ";
   14328 	}
   14329 
   14330 	isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
   14331 		      "%s%s%s%s: %s",
   14332 		      (prefix != NULL ? prefix : ""),
   14333 		      (prefix != NULL ? ": " : ""),
   14334 		      zstr, zone->strnamerd, message);
   14335 }
   14336 
   14337 static void
   14338 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
   14339 	va_list ap;
   14340 
   14341 	va_start(ap, fmt);
   14342 	dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
   14343 	va_end(ap);
   14344 }
   14345 
   14346 void
   14347 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
   14348 	      int level, const char *fmt, ...)
   14349 {
   14350 	va_list ap;
   14351 
   14352 	va_start(ap, fmt);
   14353 	dns_zone_logv(zone, category, level, NULL, fmt, ap);
   14354 	va_end(ap);
   14355 }
   14356 
   14357 void
   14358 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
   14359 	va_list ap;
   14360 
   14361 	va_start(ap, fmt);
   14362 	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
   14363 	va_end(ap);
   14364 }
   14365 
   14366 static void
   14367 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
   14368 	      const char *fmt, ...)
   14369 {
   14370 	int level = ISC_LOG_DEBUG(debuglevel);
   14371 	va_list ap;
   14372 
   14373 	va_start(ap, fmt);
   14374 	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
   14375 	va_end(ap);
   14376 }
   14377 
   14378 static void
   14379 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
   14380 	va_list ap;
   14381 
   14382 	va_start(ap, fmt);
   14383 	dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
   14384 	va_end(ap);
   14385 }
   14386 
   14387 static int
   14388 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
   14389 {
   14390 	isc_result_t result;
   14391 	dns_name_t *name;
   14392 	dns_rdataset_t *curr;
   14393 	int count = 0;
   14394 
   14395 	result = dns_message_firstname(msg, section);
   14396 	while (result == ISC_R_SUCCESS) {
   14397 		name = NULL;
   14398 		dns_message_currentname(msg, section, &name);
   14399 
   14400 		for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
   14401 		     curr = ISC_LIST_PREV(curr, link)) {
   14402 			if (curr->type == type)
   14403 				count++;
   14404 		}
   14405 		result = dns_message_nextname(msg, section);
   14406 	}
   14407 
   14408 	return (count);
   14409 }
   14410 
   14411 void
   14412 dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
   14413 	REQUIRE(DNS_ZONE_VALID(zone));
   14414 
   14415 	zone->maxxfrin = maxxfrin;
   14416 }
   14417 
   14418 uint32_t
   14419 dns_zone_getmaxxfrin(dns_zone_t *zone) {
   14420 	REQUIRE(DNS_ZONE_VALID(zone));
   14421 
   14422 	return (zone->maxxfrin);
   14423 }
   14424 
   14425 void
   14426 dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
   14427 	REQUIRE(DNS_ZONE_VALID(zone));
   14428 	zone->maxxfrout = maxxfrout;
   14429 }
   14430 
   14431 uint32_t
   14432 dns_zone_getmaxxfrout(dns_zone_t *zone) {
   14433 	REQUIRE(DNS_ZONE_VALID(zone));
   14434 
   14435 	return (zone->maxxfrout);
   14436 }
   14437 
   14438 dns_zonetype_t
   14439 dns_zone_gettype(dns_zone_t *zone) {
   14440 	REQUIRE(DNS_ZONE_VALID(zone));
   14441 
   14442 	return (zone->type);
   14443 }
   14444 
   14445 dns_zonetype_t
   14446 dns_zone_getredirecttype(dns_zone_t *zone) {
   14447 	REQUIRE(DNS_ZONE_VALID(zone));
   14448 	REQUIRE(zone->type == dns_zone_redirect);
   14449 
   14450 	return (zone->masters == NULL ? dns_zone_master : dns_zone_slave);
   14451 }
   14452 
   14453 dns_name_t *
   14454 dns_zone_getorigin(dns_zone_t *zone) {
   14455 	REQUIRE(DNS_ZONE_VALID(zone));
   14456 
   14457 	return (&zone->origin);
   14458 }
   14459 
   14460 void
   14461 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
   14462 	REQUIRE(DNS_ZONE_VALID(zone));
   14463 
   14464 	LOCK_ZONE(zone);
   14465 	if (zone->task != NULL)
   14466 		isc_task_detach(&zone->task);
   14467 	isc_task_attach(task, &zone->task);
   14468 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   14469 	if (zone->db != NULL)
   14470 		dns_db_settask(zone->db, zone->task);
   14471 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   14472 	UNLOCK_ZONE(zone);
   14473 }
   14474 
   14475 void
   14476 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
   14477 	REQUIRE(DNS_ZONE_VALID(zone));
   14478 	isc_task_attach(zone->task, target);
   14479 }
   14480 
   14481 void
   14482 dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
   14483 	REQUIRE(DNS_ZONE_VALID(zone));
   14484 
   14485 	if (idlein == 0)
   14486 		idlein = DNS_DEFAULT_IDLEIN;
   14487 	zone->idlein = idlein;
   14488 }
   14489 
   14490 uint32_t
   14491 dns_zone_getidlein(dns_zone_t *zone) {
   14492 	REQUIRE(DNS_ZONE_VALID(zone));
   14493 
   14494 	return (zone->idlein);
   14495 }
   14496 
   14497 void
   14498 dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
   14499 	REQUIRE(DNS_ZONE_VALID(zone));
   14500 
   14501 	zone->idleout = idleout;
   14502 }
   14503 
   14504 uint32_t
   14505 dns_zone_getidleout(dns_zone_t *zone) {
   14506 	REQUIRE(DNS_ZONE_VALID(zone));
   14507 
   14508 	return (zone->idleout);
   14509 }
   14510 
   14511 static void
   14512 notify_done(isc_task_t *task, isc_event_t *event) {
   14513 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
   14514 	dns_notify_t *notify;
   14515 	isc_result_t result;
   14516 	dns_message_t *message = NULL;
   14517 	isc_buffer_t buf;
   14518 	char rcode[128];
   14519 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   14520 
   14521 	UNUSED(task);
   14522 
   14523 	notify = event->ev_arg;
   14524 	REQUIRE(DNS_NOTIFY_VALID(notify));
   14525 	INSIST(task == notify->zone->task);
   14526 
   14527 	isc_buffer_init(&buf, rcode, sizeof(rcode));
   14528 	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
   14529 
   14530 	result = revent->result;
   14531 	if (result == ISC_R_SUCCESS)
   14532 		result = dns_message_create(notify->zone->mctx,
   14533 					    DNS_MESSAGE_INTENTPARSE, &message);
   14534 	if (result == ISC_R_SUCCESS)
   14535 		result = dns_request_getresponse(revent->request, message,
   14536 					DNS_MESSAGEPARSE_PRESERVEORDER);
   14537 	if (result == ISC_R_SUCCESS)
   14538 		result = dns_rcode_totext(message->rcode, &buf);
   14539 	if (result == ISC_R_SUCCESS)
   14540 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
   14541 			   "notify response from %s: %.*s",
   14542 			   addrbuf, (int)buf.used, rcode);
   14543 	else
   14544 		notify_log(notify->zone, ISC_LOG_DEBUG(2),
   14545 			   "notify to %s failed: %s", addrbuf,
   14546 			   dns_result_totext(result));
   14547 
   14548 	/*
   14549 	 * Old bind's return formerr if they see a soa record.	Retry w/o
   14550 	 * the soa if we see a formerr and had sent a SOA.
   14551 	 */
   14552 	isc_event_free(&event);
   14553 	if (message != NULL && message->rcode == dns_rcode_formerr &&
   14554 	    (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
   14555 		bool startup;
   14556 
   14557 		notify->flags |= DNS_NOTIFY_NOSOA;
   14558 		dns_request_destroy(&notify->request);
   14559 		startup = (notify->flags & DNS_NOTIFY_STARTUP);
   14560 		result = notify_send_queue(notify, startup);
   14561 		if (result != ISC_R_SUCCESS)
   14562 			notify_destroy(notify, false);
   14563 	} else {
   14564 		if (result == ISC_R_TIMEDOUT)
   14565 			notify_log(notify->zone, ISC_LOG_DEBUG(1),
   14566 				   "notify to %s: retries exceeded", addrbuf);
   14567 		notify_destroy(notify, false);
   14568 	}
   14569 	if (message != NULL)
   14570 		dns_message_destroy(&message);
   14571 }
   14572 
   14573 struct secure_event {
   14574 	isc_event_t e;
   14575 	dns_db_t *db;
   14576 	uint32_t serial;
   14577 };
   14578 
   14579 static void
   14580 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
   14581 	UNUSED(arg);
   14582 	dns_zone_log(zone, level, "%s", message);
   14583 }
   14584 
   14585 static isc_result_t
   14586 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
   14587 		    uint32_t start, uint32_t end,
   14588 		    dns_difftuple_t **soatuplep, dns_diff_t *diff)
   14589 {
   14590 	isc_result_t result;
   14591 	dns_difftuple_t *tuple = NULL;
   14592 	dns_diffop_t op = DNS_DIFFOP_ADD;
   14593 	int n_soa = 0;
   14594 
   14595 	REQUIRE(soatuplep != NULL);
   14596 
   14597 	if (start == end)
   14598 		return (DNS_R_UNCHANGED);
   14599 
   14600 	CHECK(dns_journal_iter_init(journal, start, end));
   14601 	for (result = dns_journal_first_rr(journal);
   14602 	     result == ISC_R_SUCCESS;
   14603 	     result = dns_journal_next_rr(journal))
   14604 	{
   14605 		dns_name_t *name = NULL;
   14606 		uint32_t ttl;
   14607 		dns_rdata_t *rdata = NULL;
   14608 		dns_journal_current_rr(journal, &name, &ttl, &rdata);
   14609 
   14610 		if (rdata->type == dns_rdatatype_soa) {
   14611 			n_soa++;
   14612 			if (n_soa == 2) {
   14613 				/*
   14614 				 * Save the latest raw SOA record.
   14615 				 */
   14616 				if (*soatuplep != NULL)
   14617 					dns_difftuple_free(soatuplep);
   14618 				CHECK(dns_difftuple_create(diff->mctx,
   14619 							   DNS_DIFFOP_ADD,
   14620 							   name, ttl, rdata,
   14621 							   soatuplep));
   14622 			}
   14623 			if (n_soa == 3)
   14624 				n_soa = 1;
   14625 			continue;
   14626 		}
   14627 
   14628 		/* Sanity. */
   14629 		if (n_soa == 0) {
   14630 			dns_zone_log(raw, ISC_LOG_ERROR,
   14631 				     "corrupt journal file: '%s'\n",
   14632 				     raw->journal);
   14633 			return (ISC_R_FAILURE);
   14634 		}
   14635 
   14636 		if (zone->privatetype != 0 &&
   14637 		    rdata->type == zone->privatetype)
   14638 			continue;
   14639 
   14640 		if (rdata->type == dns_rdatatype_nsec ||
   14641 		    rdata->type == dns_rdatatype_rrsig ||
   14642 		    rdata->type == dns_rdatatype_nsec3 ||
   14643 		    rdata->type == dns_rdatatype_dnskey ||
   14644 		    rdata->type == dns_rdatatype_nsec3param)
   14645 			continue;
   14646 
   14647 		op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
   14648 
   14649 		CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
   14650 					   &tuple));
   14651 		dns_diff_appendminimal(diff, &tuple);
   14652 	}
   14653 	if (result == ISC_R_NOMORE)
   14654 		result = ISC_R_SUCCESS;
   14655 
   14656  failure:
   14657 	return(result);
   14658 }
   14659 
   14660 static isc_result_t
   14661 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
   14662 	       dns_dbversion_t *secver, dns_difftuple_t **soatuple,
   14663 	       dns_diff_t *diff)
   14664 {
   14665 	isc_result_t result;
   14666 	dns_db_t *rawdb = NULL;
   14667 	dns_dbversion_t *rawver = NULL;
   14668 	dns_difftuple_t *tuple = NULL, *next;
   14669 	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
   14670 	dns_rdata_soa_t oldsoa, newsoa;
   14671 
   14672 	REQUIRE(DNS_ZONE_VALID(seczone));
   14673 	REQUIRE(soatuple != NULL && *soatuple == NULL);
   14674 
   14675 	if (!seczone->sourceserialset)
   14676 		return (DNS_R_UNCHANGED);
   14677 
   14678 	dns_db_attach(raw->db, &rawdb);
   14679 	dns_db_currentversion(rawdb, &rawver);
   14680 	result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
   14681 	dns_db_closeversion(rawdb, &rawver, false);
   14682 	dns_db_detach(&rawdb);
   14683 
   14684 	if (result != ISC_R_SUCCESS)
   14685 		return (result);
   14686 
   14687 	for (tuple = ISC_LIST_HEAD(diff->tuples);
   14688 	     tuple != NULL;
   14689 	     tuple = next)
   14690 	{
   14691 		next = ISC_LIST_NEXT(tuple, link);
   14692 		if (tuple->rdata.type == dns_rdatatype_nsec ||
   14693 		    tuple->rdata.type == dns_rdatatype_rrsig ||
   14694 		    tuple->rdata.type == dns_rdatatype_dnskey ||
   14695 		    tuple->rdata.type == dns_rdatatype_nsec3 ||
   14696 		    tuple->rdata.type == dns_rdatatype_nsec3param)
   14697 		{
   14698 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
   14699 			dns_difftuple_free(&tuple);
   14700 			continue;
   14701 		}
   14702 		if (tuple->rdata.type == dns_rdatatype_soa) {
   14703 			if (tuple->op == DNS_DIFFOP_DEL) {
   14704 				INSIST(oldtuple == NULL);
   14705 				oldtuple = tuple;
   14706 			}
   14707 			if (tuple->op == DNS_DIFFOP_ADD) {
   14708 				INSIST(newtuple == NULL);
   14709 				newtuple = tuple;
   14710 			}
   14711 		}
   14712 	}
   14713 
   14714 	if (oldtuple != NULL && newtuple != NULL) {
   14715 
   14716 		result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
   14717 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14718 
   14719 		result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
   14720 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14721 
   14722 		/*
   14723 		 * If the SOA records are the same except for the serial
   14724 		 * remove them from the diff.
   14725 		 */
   14726 		if (oldsoa.refresh == newsoa.refresh &&
   14727 		    oldsoa.retry == newsoa.retry &&
   14728 		    oldsoa.minimum == newsoa.minimum &&
   14729 		    oldsoa.expire == newsoa.expire &&
   14730 		    dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
   14731 		    dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
   14732 			ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
   14733 			dns_difftuple_free(&oldtuple);
   14734 			ISC_LIST_UNLINK(diff->tuples, newtuple, link);
   14735 			dns_difftuple_free(&newtuple);
   14736 		}
   14737 	}
   14738 
   14739 	if (ISC_LIST_EMPTY(diff->tuples))
   14740 		return (DNS_R_UNCHANGED);
   14741 
   14742 	/*
   14743 	 * If there are still SOA records in the diff they can now be removed
   14744 	 * saving the new SOA record.
   14745 	 */
   14746 	if (oldtuple != NULL) {
   14747 		ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
   14748 		dns_difftuple_free(&oldtuple);
   14749 	}
   14750 
   14751 	if (newtuple != NULL) {
   14752 		ISC_LIST_UNLINK(diff->tuples, newtuple, link);
   14753 		*soatuple = newtuple;
   14754 	}
   14755 
   14756 	return (ISC_R_SUCCESS);
   14757 }
   14758 
   14759 static void
   14760 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
   14761 	static char me[] = "receive_secure_serial";
   14762 	isc_result_t result = ISC_R_SUCCESS;
   14763 	dns_journal_t *rjournal = NULL;
   14764 	dns_journal_t *sjournal = NULL;
   14765 	uint32_t start, end;
   14766 	dns_zone_t *zone;
   14767 	dns_difftuple_t *tuple = NULL, *soatuple = NULL;
   14768 	dns_update_log_t log = { update_log_cb, NULL };
   14769 	uint32_t newserial = 0, desired = 0;
   14770 	isc_time_t timenow;
   14771 	int level = ISC_LOG_ERROR;
   14772 
   14773 	UNUSED(task);
   14774 
   14775 	zone = event->ev_arg;
   14776 	end = ((struct secure_event *)event)->serial;
   14777 
   14778 	ENTER;
   14779 
   14780 	LOCK_ZONE(zone);
   14781 
   14782 	/*
   14783 	 * If we are already processing a receive secure serial event
   14784 	 * for the zone, just queue the new one and exit.
   14785 	 */
   14786 	if (zone->rss_event != NULL && zone->rss_event != event) {
   14787 		ISC_LIST_APPEND(zone->rss_events, event, ev_link);
   14788 		UNLOCK_ZONE(zone);
   14789 		return;
   14790 	}
   14791 
   14792  nextevent:
   14793 	if (zone->rss_event != NULL) {
   14794 		INSIST(zone->rss_event == event);
   14795 		UNLOCK_ZONE(zone);
   14796 	} else {
   14797 		zone->rss_event = event;
   14798 		dns_diff_init(zone->mctx, &zone->rss_diff);
   14799 
   14800 		/*
   14801 		 * zone->db may be NULL, if the load from disk failed.
   14802 		 */
   14803 		result = ISC_R_SUCCESS;
   14804 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   14805 		if (zone->db != NULL) {
   14806 			dns_db_attach(zone->db, &zone->rss_db);
   14807 		} else {
   14808 			result = ISC_R_FAILURE;
   14809 		}
   14810 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   14811 
   14812 		if (result == ISC_R_SUCCESS && zone->raw != NULL) {
   14813 			dns_zone_attach(zone->raw, &zone->rss_raw);
   14814 		} else {
   14815 			result = ISC_R_FAILURE;
   14816 		}
   14817 
   14818 		UNLOCK_ZONE(zone);
   14819 
   14820 		CHECK(result);
   14821 
   14822 		/*
   14823 		 * We first attempt to sync the raw zone to the secure zone
   14824 		 * by using the raw zone's journal, applying all the deltas
   14825 		 * from the latest source-serial of the secure zone up to
   14826 		 * the current serial number of the raw zone.
   14827 		 *
   14828 		 * If that fails, then we'll fall back to a direct comparison
   14829 		 * between raw and secure zones.
   14830 		 */
   14831 		CHECK(dns_journal_open(zone->rss_raw->mctx,
   14832 				       zone->rss_raw->journal,
   14833 				       DNS_JOURNAL_WRITE, &rjournal));
   14834 
   14835 		result = dns_journal_open(zone->mctx, zone->journal,
   14836 					  DNS_JOURNAL_READ, &sjournal);
   14837 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   14838 			goto failure;
   14839 		}
   14840 
   14841 		if (!dns_journal_get_sourceserial(rjournal, &start)) {
   14842 			start = dns_journal_first_serial(rjournal);
   14843 			dns_journal_set_sourceserial(rjournal, start);
   14844 		}
   14845 		if (sjournal != NULL) {
   14846 			uint32_t serial;
   14847 			/*
   14848 			 * We read the secure journal first, if that
   14849 			 * exists use its value provided it is greater
   14850 			 * that from the raw journal.
   14851 			 */
   14852 			if (dns_journal_get_sourceserial(sjournal, &serial)) {
   14853 				if (isc_serial_gt(serial, start))
   14854 					start = serial;
   14855 			}
   14856 			dns_journal_destroy(&sjournal);
   14857 		}
   14858 
   14859 		dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
   14860 		CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
   14861 
   14862 		/*
   14863 		 * Try to apply diffs from the raw zone's journal to the secure
   14864 		 * zone.  If that fails, we recover by syncing up the databases
   14865 		 * directly.
   14866 		 */
   14867 		result = sync_secure_journal(zone, zone->rss_raw, rjournal,
   14868 					     start, end, &soatuple,
   14869 					     &zone->rss_diff);
   14870 		if (result == DNS_R_UNCHANGED) {
   14871 			level = ISC_LOG_INFO;
   14872 			goto failure;
   14873 		} else if (result != ISC_R_SUCCESS) {
   14874 			CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
   14875 					     zone->rss_oldver, &soatuple,
   14876 					     &zone->rss_diff));
   14877 		}
   14878 
   14879 		CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
   14880 				     zone->rss_newver));
   14881 
   14882 		if (soatuple != NULL) {
   14883 			uint32_t oldserial;
   14884 
   14885 			CHECK(dns_db_createsoatuple(zone->rss_db,
   14886 						    zone->rss_oldver,
   14887 						    zone->rss_diff.mctx,
   14888 						    DNS_DIFFOP_DEL, &tuple));
   14889 			oldserial = dns_soa_getserial(&tuple->rdata);
   14890 			newserial = desired =
   14891 				    dns_soa_getserial(&soatuple->rdata);
   14892 			if (!isc_serial_gt(newserial, oldserial)) {
   14893 				newserial = oldserial + 1;
   14894 				if (newserial == 0) {
   14895 					newserial++;
   14896 				}
   14897 				dns_soa_setserial(newserial, &soatuple->rdata);
   14898 			}
   14899 			CHECK(do_one_tuple(&tuple, zone->rss_db,
   14900 					   zone->rss_newver, &zone->rss_diff));
   14901 			CHECK(do_one_tuple(&soatuple, zone->rss_db,
   14902 					   zone->rss_newver, &zone->rss_diff));
   14903 		} else {
   14904 			CHECK(update_soa_serial(zone->rss_db, zone->rss_newver,
   14905 						&zone->rss_diff, zone->mctx,
   14906 						zone->updatemethod));
   14907 		}
   14908 
   14909 	}
   14910 	result = dns_update_signaturesinc(&log, zone, zone->rss_db,
   14911 					  zone->rss_oldver, zone->rss_newver,
   14912 					  &zone->rss_diff,
   14913 					  zone->sigvalidityinterval,
   14914 					  &zone->rss_state);
   14915 	if (result == DNS_R_CONTINUE) {
   14916 		if (rjournal != NULL) {
   14917 			dns_journal_destroy(&rjournal);
   14918 		}
   14919 		isc_task_send(task, &event);
   14920 		return;
   14921 	}
   14922 	/*
   14923 	 * If something went wrong while trying to update the secure zone and
   14924 	 * the latter was already signed before, do not apply raw zone deltas
   14925 	 * to it as that would break existing DNSSEC signatures.  However, if
   14926 	 * the secure zone was not yet signed (e.g. because no signing keys
   14927 	 * were created for it), commence applying raw zone deltas to it so
   14928 	 * that contents of the raw zone and the secure zone are kept in sync.
   14929 	 */
   14930 	if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
   14931 		goto failure;
   14932 	}
   14933 
   14934 	if (rjournal == NULL) {
   14935 		CHECK(dns_journal_open(zone->rss_raw->mctx,
   14936 				       zone->rss_raw->journal,
   14937 				       DNS_JOURNAL_WRITE, &rjournal));
   14938 	}
   14939 	CHECK(zone_journal(zone, &zone->rss_diff, &end,
   14940 			   "receive_secure_serial"));
   14941 
   14942 	dns_journal_set_sourceserial(rjournal, end);
   14943 	dns_journal_commit(rjournal);
   14944 
   14945 	LOCK_ZONE(zone);
   14946 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   14947 
   14948 	zone->sourceserial = end;
   14949 	zone->sourceserialset = true;
   14950 	zone_needdump(zone, DNS_DUMP_DELAY);
   14951 
   14952 	TIME_NOW(&timenow);
   14953 	zone_settimer(zone, &timenow);
   14954 	UNLOCK_ZONE(zone);
   14955 
   14956 	dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
   14957 	dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
   14958 
   14959 	if (newserial != 0) {
   14960 		dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
   14961 			     newserial, desired);
   14962 	}
   14963 
   14964  failure:
   14965 	isc_event_free(&zone->rss_event);
   14966 	event = ISC_LIST_HEAD(zone->rss_events);
   14967 
   14968 	if (zone->rss_raw != NULL) {
   14969 		dns_zone_detach(&zone->rss_raw);
   14970 	}
   14971 	if (result != ISC_R_SUCCESS) {
   14972 		dns_zone_log(zone, level, "receive_secure_serial: %s",
   14973 			     dns_result_totext(result));
   14974 	}
   14975 	if (tuple != NULL) {
   14976 		dns_difftuple_free(&tuple);
   14977 	}
   14978 	if (soatuple != NULL) {
   14979 		dns_difftuple_free(&soatuple);
   14980 	}
   14981 	if (zone->rss_db != NULL) {
   14982 		if (zone->rss_oldver != NULL) {
   14983 			dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
   14984 					    false);
   14985 		}
   14986 		if (zone->rss_newver != NULL) {
   14987 			dns_db_closeversion(zone->rss_db, &zone->rss_newver,
   14988 					    false);
   14989 		}
   14990 		dns_db_detach(&zone->rss_db);
   14991 	}
   14992 	INSIST(zone->rss_oldver == NULL);
   14993 	INSIST(zone->rss_newver == NULL);
   14994 	if (rjournal != NULL) {
   14995 		dns_journal_destroy(&rjournal);
   14996 	}
   14997 	dns_diff_clear(&zone->rss_diff);
   14998 
   14999 	if (event != NULL) {
   15000 		LOCK_ZONE(zone);
   15001 		INSIST(zone->irefs > 1);
   15002 		zone->irefs--;
   15003 		ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
   15004 		goto nextevent;
   15005 	}
   15006 
   15007 	event = ISC_LIST_HEAD(zone->rss_post);
   15008 	while (event != NULL) {
   15009 		ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
   15010 		rss_post(zone, event);
   15011 		event = ISC_LIST_HEAD(zone->rss_post);
   15012 	}
   15013 
   15014 	dns_zone_idetach(&zone);
   15015 }
   15016 
   15017 static isc_result_t
   15018 zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
   15019 	isc_event_t *e;
   15020 	dns_zone_t *dummy = NULL;
   15021 
   15022 	e = isc_event_allocate(zone->secure->mctx, zone,
   15023 			       DNS_EVENT_ZONESECURESERIAL,
   15024 			       receive_secure_serial, zone->secure,
   15025 			       sizeof(struct secure_event));
   15026 	if (e == NULL)
   15027 		return (ISC_R_NOMEMORY);
   15028 	((struct secure_event *)e)->serial = serial;
   15029 	INSIST(LOCKED_ZONE(zone->secure));
   15030 	zone_iattach(zone->secure, &dummy);
   15031 	isc_task_send(zone->secure->task, &e);
   15032 
   15033 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
   15034 	return (ISC_R_SUCCESS);
   15035 }
   15036 
   15037 static isc_result_t
   15038 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   15039 	       dns_rdataset_t *rdataset, uint32_t oldserial)
   15040 {
   15041 	dns_rdata_soa_t soa;
   15042 	dns_rdata_t rdata = DNS_RDATA_INIT;
   15043 	dns_rdatalist_t temprdatalist;
   15044 	dns_rdataset_t temprdataset;
   15045 	isc_buffer_t b;
   15046 	isc_result_t result;
   15047 	unsigned char buf[DNS_SOA_BUFFERSIZE];
   15048 	dns_fixedname_t fixed;
   15049 	dns_name_t *name;
   15050 
   15051 	result = dns_rdataset_first(rdataset);
   15052 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   15053 	dns_rdataset_current(rdataset, &rdata);
   15054 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   15055 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   15056 
   15057 	if (isc_serial_gt(soa.serial, oldserial))
   15058 		return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
   15059 					   NULL));
   15060 	/*
   15061 	 * Always bump the serial.
   15062 	 */
   15063 	oldserial++;
   15064 	if (oldserial == 0)
   15065 		oldserial++;
   15066 	soa.serial = oldserial;
   15067 
   15068 	/*
   15069 	 * Construct a replacement rdataset.
   15070 	 */
   15071 	dns_rdata_reset(&rdata);
   15072 	isc_buffer_init(&b, buf, sizeof(buf));
   15073 	result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
   15074 				      dns_rdatatype_soa, &soa, &b);
   15075 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   15076 	dns_rdatalist_init(&temprdatalist);
   15077 	temprdatalist.rdclass = rdata.rdclass;
   15078 	temprdatalist.type = rdata.type;
   15079 	temprdatalist.ttl = rdataset->ttl;
   15080 	ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
   15081 
   15082 	dns_rdataset_init(&temprdataset);
   15083 	result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
   15084 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   15085 
   15086 	name = dns_fixedname_initname(&fixed);
   15087 	result = dns_db_nodefullname(db, node, name);
   15088 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   15089 	dns_rdataset_getownercase(rdataset, name);
   15090 	dns_rdataset_setownercase(&temprdataset, name);
   15091 	return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
   15092 				   0, NULL));
   15093 }
   15094 
   15095 /*
   15096  * This function should populate an nsec3paramlist_t with the
   15097  * nsecparam_t data from a zone.
   15098  */
   15099 static isc_result_t
   15100 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
   15101 	isc_result_t result;
   15102 	dns_dbnode_t *node = NULL;
   15103 	dns_rdataset_t rdataset, prdataset;
   15104 	dns_dbversion_t *version = NULL;
   15105 	nsec3param_t *nsec3param = NULL;
   15106 	nsec3param_t *nsec3p = NULL;
   15107 	nsec3param_t *next;
   15108 	dns_db_t *db = NULL;
   15109 	unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   15110 
   15111 	REQUIRE(DNS_ZONE_VALID(zone));
   15112 	REQUIRE(nsec3list != NULL);
   15113 	REQUIRE(ISC_LIST_EMPTY(*nsec3list));
   15114 
   15115 	dns_rdataset_init(&rdataset);
   15116 	dns_rdataset_init(&prdataset);
   15117 
   15118 	dns_db_attach(zone->db, &db);
   15119 	CHECK(dns_db_getoriginnode(db, &node));
   15120 
   15121 	dns_db_currentversion(db, &version);
   15122 	result = dns_db_findrdataset(db, node, version,
   15123 				     dns_rdatatype_nsec3param,
   15124 				     dns_rdatatype_none, 0, &rdataset, NULL);
   15125 
   15126 	if (result != ISC_R_SUCCESS)
   15127 		goto getprivate;
   15128 
   15129 	/*
   15130 	 * walk nsec3param rdataset making a list of parameters (note that
   15131 	 * multiple simultaneous nsec3 chains are annoyingly legal -- this
   15132 	 * is why we use an nsec3list, even tho we will usually only have
   15133 	 * one)
   15134 	 */
   15135 	for (result = dns_rdataset_first(&rdataset);
   15136 	     result == ISC_R_SUCCESS;
   15137 	     result = dns_rdataset_next(&rdataset))
   15138 	{
   15139 		dns_rdata_t rdata = DNS_RDATA_INIT;
   15140 		dns_rdata_t private = DNS_RDATA_INIT;
   15141 
   15142 		dns_rdataset_current(&rdataset, &rdata);
   15143 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   15144 			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   15145 			      "looping through nsec3param data");
   15146 		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
   15147 		if (nsec3param == NULL)
   15148 			CHECK(ISC_R_NOMEMORY);
   15149 		ISC_LINK_INIT(nsec3param, link);
   15150 
   15151 		/*
   15152 		 * now transfer the data from the rdata to
   15153 		 * the nsec3param
   15154 		 */
   15155 		dns_nsec3param_toprivate(&rdata, &private,
   15156 					 zone->privatetype, nsec3param->data,
   15157 					 sizeof(nsec3param->data));
   15158 		nsec3param->length = private.length;
   15159 		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
   15160 	}
   15161 
   15162  getprivate:
   15163 	result = dns_db_findrdataset(db, node, version, zone->privatetype,
   15164 				     dns_rdatatype_none, 0, &prdataset, NULL);
   15165 	if (result != ISC_R_SUCCESS)
   15166 		goto done;
   15167 
   15168 	/*
   15169 	 * walk private type records, converting them to nsec3 parameters
   15170 	 * using dns_nsec3param_fromprivate(), do the right thing based on
   15171 	 * CREATE and REMOVE flags
   15172 	 */
   15173 	for (result = dns_rdataset_first(&prdataset);
   15174 	     result == ISC_R_SUCCESS;
   15175 	     result = dns_rdataset_next(&prdataset))
   15176 	{
   15177 		dns_rdata_t rdata = DNS_RDATA_INIT;
   15178 		dns_rdata_t private = DNS_RDATA_INIT;
   15179 
   15180 		dns_rdataset_current(&prdataset, &private);
   15181 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   15182 			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   15183 			      "looping through nsec3param private data");
   15184 
   15185 		/*
   15186 		 * Do we have a valid private record?
   15187 		 */
   15188 		if (!dns_nsec3param_fromprivate(&private, &rdata,
   15189 						buf, sizeof(buf)))
   15190 			continue;
   15191 
   15192 		/*
   15193 		 * Remove any NSEC3PARAM records scheduled to be removed.
   15194 		 */
   15195 		if (NSEC3REMOVE(rdata.data[1])) {
   15196 			/*
   15197 			 * Zero out the flags.
   15198 			 */
   15199 			rdata.data[1] = 0;
   15200 
   15201 			for (nsec3p = ISC_LIST_HEAD(*nsec3list);
   15202 			     nsec3p != NULL;
   15203 			     nsec3p = next)
   15204 			{
   15205 				next = ISC_LIST_NEXT(nsec3p, link);
   15206 
   15207 				if (nsec3p->length == rdata.length + 1 &&
   15208 				    memcmp(rdata.data, nsec3p->data + 1,
   15209 					   nsec3p->length - 1) == 0) {
   15210 					ISC_LIST_UNLINK(*nsec3list,
   15211 							nsec3p, link);
   15212 					isc_mem_put(zone->mctx, nsec3p,
   15213 						    sizeof(nsec3param_t));
   15214 				}
   15215 			}
   15216 			continue;
   15217 		}
   15218 
   15219 		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
   15220 		if (nsec3param == NULL)
   15221 			CHECK(ISC_R_NOMEMORY);
   15222 		ISC_LINK_INIT(nsec3param, link);
   15223 
   15224 		/*
   15225 		 * Copy the remaining private records so the nsec/nsec3
   15226 		 * chain gets created.
   15227 		 */
   15228 		INSIST(private.length <= sizeof(nsec3param->data));
   15229 		memmove(nsec3param->data, private.data, private.length);
   15230 		nsec3param->length = private.length;
   15231 		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
   15232 	}
   15233 
   15234  done:
   15235 	if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
   15236 		result = ISC_R_SUCCESS;
   15237 
   15238  failure:
   15239 	if (node != NULL)
   15240 		dns_db_detachnode(db, &node);
   15241 	if (version != NULL)
   15242 		dns_db_closeversion(db, &version, false);
   15243 	if (db != NULL)
   15244 		dns_db_detach(&db);
   15245 	if (dns_rdataset_isassociated(&rdataset))
   15246 		dns_rdataset_disassociate(&rdataset);
   15247 	if (dns_rdataset_isassociated(&prdataset))
   15248 		dns_rdataset_disassociate(&prdataset);
   15249 	return (result);
   15250 }
   15251 
   15252 /*
   15253  * Populate new zone db with private type records found by save_nsec3param().
   15254  */
   15255 static isc_result_t
   15256 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
   15257 		   nsec3paramlist_t *nsec3list)
   15258 {
   15259 	isc_result_t result = ISC_R_SUCCESS;
   15260 	dns_diff_t diff;
   15261 	dns_rdata_t rdata;
   15262 	nsec3param_t *nsec3p = NULL;
   15263 	nsec3param_t *next;
   15264 
   15265 	REQUIRE(DNS_ZONE_VALID(zone));
   15266 	REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
   15267 
   15268 	dns_diff_init(zone->mctx, &diff);
   15269 
   15270 	/*
   15271 	 * Loop through the list of private-type records, set the INITIAL
   15272 	 * and CREATE flags, and the add the record to the apex of the tree
   15273 	 * in db.
   15274 	 */
   15275 	for (nsec3p = ISC_LIST_HEAD(*nsec3list);
   15276 	     nsec3p != NULL;
   15277 	     nsec3p = next)
   15278 	{
   15279 		next = ISC_LIST_NEXT(nsec3p, link);
   15280 		dns_rdata_init(&rdata);
   15281 		nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
   15282 		rdata.length = nsec3p->length;
   15283 		rdata.data = nsec3p->data;
   15284 		rdata.type = zone->privatetype;
   15285 		rdata.rdclass = zone->rdclass;
   15286 		result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
   15287 				       &zone->origin, 0, &rdata);
   15288 		if (result != ISC_R_SUCCESS) {
   15289 			break;
   15290 		}
   15291 	}
   15292 
   15293 	dns_diff_clear(&diff);
   15294 	return (result);
   15295 }
   15296 
   15297 static void
   15298 receive_secure_db(isc_task_t *task, isc_event_t *event) {
   15299 	isc_result_t result;
   15300 	dns_zone_t *zone;
   15301 	dns_db_t *rawdb, *db = NULL;
   15302 	dns_dbnode_t *rawnode = NULL, *node = NULL;
   15303 	dns_fixedname_t fname;
   15304 	dns_name_t *name;
   15305 	dns_dbiterator_t *dbiterator = NULL;
   15306 	dns_rdatasetiter_t *rdsit = NULL;
   15307 	dns_rdataset_t rdataset;
   15308 	dns_dbversion_t *version = NULL;
   15309 	isc_time_t loadtime;
   15310 	unsigned int oldserial = 0;
   15311 	bool have_oldserial = false;
   15312 	nsec3paramlist_t nsec3list;
   15313 	isc_event_t *setnsec3param_event;
   15314 	dns_zone_t *dummy;
   15315 
   15316 	UNUSED(task);
   15317 
   15318 	ISC_LIST_INIT(nsec3list);
   15319 
   15320 	zone = event->ev_arg;
   15321 	rawdb = ((struct secure_event *)event)->db;
   15322 	isc_event_free(&event);
   15323 
   15324 	name = dns_fixedname_initname(&fname);
   15325 	dns_rdataset_init(&rdataset);
   15326 
   15327 	LOCK_ZONE(zone);
   15328 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
   15329 		result = ISC_R_SHUTTINGDOWN;
   15330 		goto failure;
   15331 	}
   15332 
   15333 	TIME_NOW(&loadtime);
   15334 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   15335 	if (zone->db != NULL) {
   15336 		result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
   15337 		if (result == ISC_R_SUCCESS)
   15338 			have_oldserial = true;
   15339 
   15340 		/*
   15341 		 * assemble nsec3parameters from the old zone, and set a flag
   15342 		 * if any are found
   15343 		 */
   15344 		result = save_nsec3param(zone, &nsec3list);
   15345 		if (result != ISC_R_SUCCESS) {
   15346 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   15347 			goto failure;
   15348 		}
   15349 	}
   15350 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   15351 
   15352 	result = dns_db_create(zone->mctx, zone->db_argv[0],
   15353 			       &zone->origin, dns_dbtype_zone, zone->rdclass,
   15354 			       zone->db_argc - 1, zone->db_argv + 1, &db);
   15355 	if (result != ISC_R_SUCCESS)
   15356 		goto failure;
   15357 
   15358 	result = dns_db_setgluecachestats(db, zone->gluecachestats);
   15359 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
   15360 		goto failure;
   15361 	}
   15362 
   15363 	result = dns_db_newversion(db, &version);
   15364 	if (result != ISC_R_SUCCESS)
   15365 		goto failure;
   15366 
   15367 	result = dns_db_createiterator(rawdb, 0, &dbiterator);
   15368 	if (result != ISC_R_SUCCESS)
   15369 		goto failure;
   15370 
   15371 	for (result = dns_dbiterator_first(dbiterator);
   15372 	     result == ISC_R_SUCCESS;
   15373 	     result = dns_dbiterator_next(dbiterator)) {
   15374 		result = dns_dbiterator_current(dbiterator, &rawnode, name);
   15375 		if (result != ISC_R_SUCCESS)
   15376 			continue;
   15377 
   15378 		result = dns_db_findnode(db, name, true, &node);
   15379 		if (result != ISC_R_SUCCESS)
   15380 			goto failure;
   15381 
   15382 		result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
   15383 		if (result != ISC_R_SUCCESS)
   15384 			goto failure;
   15385 
   15386 		for (result = dns_rdatasetiter_first(rdsit);
   15387 		     result == ISC_R_SUCCESS;
   15388 		     result = dns_rdatasetiter_next(rdsit)) {
   15389 			dns_rdatasetiter_current(rdsit, &rdataset);
   15390 			if (rdataset.type == dns_rdatatype_nsec ||
   15391 			    rdataset.type == dns_rdatatype_rrsig ||
   15392 			    rdataset.type == dns_rdatatype_nsec3 ||
   15393 			    rdataset.type == dns_rdatatype_dnskey ||
   15394 			    rdataset.type == dns_rdatatype_nsec3param) {
   15395 				dns_rdataset_disassociate(&rdataset);
   15396 				continue;
   15397 			}
   15398 			if (rdataset.type == dns_rdatatype_soa &&
   15399 			    have_oldserial) {
   15400 				result = checkandaddsoa(db, node, version,
   15401 							&rdataset, oldserial);
   15402 			} else
   15403 				result = dns_db_addrdataset(db, node, version,
   15404 							    0, &rdataset, 0,
   15405 							    NULL);
   15406 			if (result != ISC_R_SUCCESS)
   15407 				goto failure;
   15408 
   15409 			dns_rdataset_disassociate(&rdataset);
   15410 		}
   15411 		dns_rdatasetiter_destroy(&rdsit);
   15412 		dns_db_detachnode(rawdb, &rawnode);
   15413 		dns_db_detachnode(db, &node);
   15414 	}
   15415 
   15416 	/*
   15417 	 * Call restore_nsec3param() to create private-type records from
   15418 	 * the old nsec3 parameters and insert them into db
   15419 	 */
   15420 	if (!ISC_LIST_EMPTY(nsec3list)) {
   15421 		result = restore_nsec3param(zone, db, version, &nsec3list);
   15422 		if (result != ISC_R_SUCCESS) {
   15423 			goto failure;
   15424 		}
   15425 	}
   15426 
   15427 	dns_db_closeversion(db, &version, true);
   15428 
   15429 	/*
   15430 	 * Lock hierarchy: zmgr, zone, raw.
   15431 	 */
   15432 	INSIST(zone != zone->raw);
   15433 	LOCK_ZONE(zone->raw);
   15434 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   15435 	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
   15436 	zone_needdump(zone, 0); /* XXXMPA */
   15437 	UNLOCK_ZONE(zone->raw);
   15438 
   15439 	/*
   15440 	 * Process any queued NSEC3PARAM change requests.
   15441 	 */
   15442 	while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
   15443 		setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
   15444 		ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
   15445 				ev_link);
   15446 		dummy = NULL;
   15447 		zone_iattach(zone, &dummy);
   15448 		isc_task_send(zone->task, &setnsec3param_event);
   15449 	}
   15450 
   15451  failure:
   15452 	UNLOCK_ZONE(zone);
   15453 	if (result != ISC_R_SUCCESS)
   15454 		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
   15455 			     dns_result_totext(result));
   15456 
   15457 	while (!ISC_LIST_EMPTY(nsec3list)) {
   15458 		nsec3param_t *nsec3p;
   15459 		nsec3p = ISC_LIST_HEAD(nsec3list);
   15460 		ISC_LIST_UNLINK(nsec3list, nsec3p, link);
   15461 		isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
   15462 	}
   15463 	if (dns_rdataset_isassociated(&rdataset))
   15464 		dns_rdataset_disassociate(&rdataset);
   15465 	if (db != NULL) {
   15466 		if (node != NULL)
   15467 			dns_db_detachnode(db, &node);
   15468 		if (version != NULL)
   15469 			dns_db_closeversion(db, &version, false);
   15470 		dns_db_detach(&db);
   15471 	}
   15472 	if (rawnode != NULL)
   15473 		dns_db_detachnode(rawdb, &rawnode);
   15474 	dns_db_detach(&rawdb);
   15475 	if (dbiterator != NULL)
   15476 		dns_dbiterator_destroy(&dbiterator);
   15477 	dns_zone_idetach(&zone);
   15478 
   15479 	INSIST(version == NULL);
   15480 }
   15481 
   15482 static isc_result_t
   15483 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
   15484 	isc_event_t *e;
   15485 	dns_db_t *dummy = NULL;
   15486 	dns_zone_t *secure = NULL;
   15487 
   15488 	e = isc_event_allocate(zone->secure->mctx, zone,
   15489 			       DNS_EVENT_ZONESECUREDB,
   15490 			       receive_secure_db, zone->secure,
   15491 			       sizeof(struct secure_event));
   15492 	if (e == NULL)
   15493 		return (ISC_R_NOMEMORY);
   15494 	dns_db_attach(db, &dummy);
   15495 	((struct secure_event *)e)->db = dummy;
   15496 	INSIST(LOCKED_ZONE(zone->secure));
   15497 	zone_iattach(zone->secure, &secure);
   15498 	isc_task_send(zone->secure->task, &e);
   15499 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
   15500 	return (ISC_R_SUCCESS);
   15501 }
   15502 
   15503 isc_result_t
   15504 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
   15505 	isc_result_t result;
   15506 	dns_zone_t *secure = NULL;
   15507 
   15508 	REQUIRE(DNS_ZONE_VALID(zone));
   15509  again:
   15510 	LOCK_ZONE(zone);
   15511 	if (inline_raw(zone)) {
   15512 		secure = zone->secure;
   15513 		INSIST(secure != zone);
   15514 		TRYLOCK_ZONE(result, secure);
   15515 		if (result != ISC_R_SUCCESS) {
   15516 			UNLOCK_ZONE(zone);
   15517 			secure = NULL;
   15518 			isc_thread_yield();
   15519 			goto again;
   15520 		}
   15521 	}
   15522 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   15523 	result = zone_replacedb(zone, db, dump);
   15524 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   15525 	if (secure != NULL)
   15526 		UNLOCK_ZONE(secure);
   15527 	UNLOCK_ZONE(zone);
   15528 	return (result);
   15529 }
   15530 
   15531 static isc_result_t
   15532 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
   15533 	dns_dbversion_t *ver;
   15534 	isc_result_t result;
   15535 	unsigned int soacount = 0;
   15536 	unsigned int nscount = 0;
   15537 
   15538 	/*
   15539 	 * 'zone' and 'zone->db' locked by caller.
   15540 	 */
   15541 	REQUIRE(DNS_ZONE_VALID(zone));
   15542 	REQUIRE(LOCKED_ZONE(zone));
   15543 	if (inline_raw(zone))
   15544 		REQUIRE(LOCKED_ZONE(zone->secure));
   15545 
   15546 	result = zone_get_from_db(zone, db, &nscount, &soacount,
   15547 				  NULL, NULL, NULL, NULL, NULL, NULL);
   15548 	if (result == ISC_R_SUCCESS) {
   15549 		if (soacount != 1) {
   15550 			dns_zone_log(zone, ISC_LOG_ERROR,
   15551 				     "has %d SOA records", soacount);
   15552 			result = DNS_R_BADZONE;
   15553 		}
   15554 		if (nscount == 0 && zone->type != dns_zone_key) {
   15555 			dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
   15556 			result = DNS_R_BADZONE;
   15557 		}
   15558 		if (result != ISC_R_SUCCESS)
   15559 			return (result);
   15560 	} else {
   15561 		dns_zone_log(zone, ISC_LOG_ERROR,
   15562 			    "retrieving SOA and NS records failed: %s",
   15563 			    dns_result_totext(result));
   15564 		return (result);
   15565 	}
   15566 
   15567 	result = check_nsec3param(zone, db);
   15568 	if (result != ISC_R_SUCCESS)
   15569 		return (result);
   15570 
   15571 	ver = NULL;
   15572 	dns_db_currentversion(db, &ver);
   15573 
   15574 	/*
   15575 	 * The initial version of a slave zone is always dumped;
   15576 	 * subsequent versions may be journaled instead if this
   15577 	 * is enabled in the configuration.
   15578 	 */
   15579 	if (zone->db != NULL && zone->journal != NULL &&
   15580 	    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
   15581 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
   15582 	{
   15583 		uint32_t serial, oldserial;
   15584 
   15585 		dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
   15586 
   15587 		result = dns_db_getsoaserial(db, ver, &serial);
   15588 		if (result != ISC_R_SUCCESS) {
   15589 			dns_zone_log(zone, ISC_LOG_ERROR,
   15590 				     "ixfr-from-differences: unable to get "
   15591 				     "new serial");
   15592 			goto fail;
   15593 		}
   15594 
   15595 		/*
   15596 		 * This is checked in zone_postload() for master zones.
   15597 		 */
   15598 		result = zone_get_from_db(zone, zone->db, NULL, &soacount,
   15599 					  &oldserial, NULL, NULL, NULL, NULL,
   15600 					  NULL);
   15601 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   15602 		RUNTIME_CHECK(soacount > 0U);
   15603 		if ((zone->type == dns_zone_slave ||
   15604 		     (zone->type == dns_zone_redirect &&
   15605 		      zone->masters != NULL))
   15606 		    && !isc_serial_gt(serial, oldserial)) {
   15607 			uint32_t serialmin, serialmax;
   15608 			serialmin = (oldserial + 1) & 0xffffffffU;
   15609 			serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
   15610 			dns_zone_log(zone, ISC_LOG_ERROR,
   15611 				     "ixfr-from-differences: failed: "
   15612 				     "new serial (%u) out of range [%u - %u]",
   15613 				     serial, serialmin, serialmax);
   15614 			result = ISC_R_RANGE;
   15615 			goto fail;
   15616 		}
   15617 
   15618 		result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
   15619 				     zone->journal);
   15620 		if (result != ISC_R_SUCCESS) {
   15621 			char strbuf[ISC_STRERRORSIZE];
   15622 			strerror_r(errno, strbuf, sizeof(strbuf));
   15623 			dns_zone_log(zone, ISC_LOG_ERROR,
   15624 				     "ixfr-from-differences: failed: "
   15625 				     "%s", strbuf);
   15626 			goto fallback;
   15627 		}
   15628 		if (dump)
   15629 			zone_needdump(zone, DNS_DUMP_DELAY);
   15630 		else
   15631 			zone_journal_compact(zone, zone->db, serial);
   15632 		if (zone->type == dns_zone_master && inline_raw(zone))
   15633 			zone_send_secureserial(zone, serial);
   15634 	} else {
   15635  fallback:
   15636 		if (dump && zone->masterfile != NULL) {
   15637 			/*
   15638 			 * If DNS_ZONEFLG_FORCEXFER was set we don't want
   15639 			 * to keep the old masterfile.
   15640 			 */
   15641 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
   15642 			    remove(zone->masterfile) < 0 && errno != ENOENT) {
   15643 				char strbuf[ISC_STRERRORSIZE];
   15644 				strerror_r(errno, strbuf, sizeof(strbuf));
   15645 				isc_log_write(dns_lctx,
   15646 					      DNS_LOGCATEGORY_GENERAL,
   15647 					      DNS_LOGMODULE_ZONE,
   15648 					      ISC_LOG_WARNING,
   15649 					      "unable to remove masterfile "
   15650 					      "'%s': '%s'",
   15651 					      zone->masterfile, strbuf);
   15652 			}
   15653 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
   15654 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
   15655 			else
   15656 				zone_needdump(zone, 0);
   15657 		}
   15658 		if (dump && zone->journal != NULL) {
   15659 			/*
   15660 			 * The in-memory database just changed, and
   15661 			 * because 'dump' is set, it didn't change by
   15662 			 * being loaded from disk.  Also, we have not
   15663 			 * journaled diffs for this change.
   15664 			 * Therefore, the on-disk journal is missing
   15665 			 * the deltas for this change.	Since it can
   15666 			 * no longer be used to bring the zone
   15667 			 * up-to-date, it is useless and should be
   15668 			 * removed.
   15669 			 */
   15670 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   15671 				      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   15672 				      "removing journal file");
   15673 			if (remove(zone->journal) < 0 && errno != ENOENT) {
   15674 				char strbuf[ISC_STRERRORSIZE];
   15675 				strerror_r(errno, strbuf, sizeof(strbuf));
   15676 				isc_log_write(dns_lctx,
   15677 					      DNS_LOGCATEGORY_GENERAL,
   15678 					      DNS_LOGMODULE_ZONE,
   15679 					      ISC_LOG_WARNING,
   15680 					      "unable to remove journal "
   15681 					      "'%s': '%s'",
   15682 					      zone->journal, strbuf);
   15683 			}
   15684 		}
   15685 
   15686 		if (inline_raw(zone))
   15687 			zone_send_securedb(zone, db);
   15688 	}
   15689 
   15690 	dns_db_closeversion(db, &ver, false);
   15691 
   15692 	dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
   15693 
   15694 	if (zone->db != NULL)
   15695 		zone_detachdb(zone);
   15696 	zone_attachdb(zone, db);
   15697 	dns_db_settask(zone->db, zone->task);
   15698 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
   15699 	return (ISC_R_SUCCESS);
   15700 
   15701  fail:
   15702 	dns_db_closeversion(db, &ver, false);
   15703 	return (result);
   15704 }
   15705 
   15706 /* The caller must hold the dblock as a writer. */
   15707 static inline void
   15708 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
   15709 	REQUIRE(zone->db == NULL && db != NULL);
   15710 
   15711 	dns_db_attach(db, &zone->db);
   15712 }
   15713 
   15714 /* The caller must hold the dblock as a writer. */
   15715 static inline void
   15716 zone_detachdb(dns_zone_t *zone) {
   15717 	REQUIRE(zone->db != NULL);
   15718 
   15719 	dns_db_detach(&zone->db);
   15720 }
   15721 
   15722 static void
   15723 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
   15724 	isc_time_t now;
   15725 	bool again = false;
   15726 	unsigned int soacount;
   15727 	unsigned int nscount;
   15728 	uint32_t serial, refresh, retry, expire, minimum;
   15729 	isc_result_t xfrresult = result;
   15730 	bool free_needed;
   15731 	dns_zone_t *secure = NULL;
   15732 
   15733 	REQUIRE(DNS_ZONE_VALID(zone));
   15734 
   15735 	dns_zone_log(zone, ISC_LOG_DEBUG(1),
   15736 		     "zone transfer finished: %s", dns_result_totext(result));
   15737 
   15738 	/*
   15739 	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
   15740 	 * could result in a deadlock due to a LOR so we will spin if we
   15741 	 * can't obtain the both locks.
   15742 	 */
   15743  again:
   15744 	LOCK_ZONE(zone);
   15745 	if (inline_raw(zone)) {
   15746 		secure = zone->secure;
   15747 		INSIST(secure != zone);
   15748 		TRYLOCK_ZONE(result, secure);
   15749 		if (result != ISC_R_SUCCESS) {
   15750 			UNLOCK_ZONE(zone);
   15751 			secure = NULL;
   15752 			isc_thread_yield();
   15753 			goto again;
   15754 		}
   15755 	}
   15756 
   15757 	INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
   15758 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   15759 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
   15760 
   15761 	TIME_NOW(&now);
   15762 	switch (xfrresult) {
   15763 	case ISC_R_SUCCESS:
   15764 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   15765 		/* FALLTHROUGH */
   15766 	case DNS_R_UPTODATE:
   15767 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
   15768 		/*
   15769 		 * Has the zone expired underneath us?
   15770 		 */
   15771 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   15772 		if (zone->db == NULL) {
   15773 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   15774 			goto same_master;
   15775 		}
   15776 
   15777 		/*
   15778 		 * Update the zone structure's data from the actual
   15779 		 * SOA received.
   15780 		 */
   15781 		nscount = 0;
   15782 		soacount = 0;
   15783 		INSIST(zone->db != NULL);
   15784 		result = zone_get_from_db(zone, zone->db, &nscount,
   15785 					  &soacount, &serial, &refresh,
   15786 					  &retry, &expire, &minimum, NULL);
   15787 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   15788 		if (result == ISC_R_SUCCESS) {
   15789 			if (soacount != 1)
   15790 				dns_zone_log(zone, ISC_LOG_ERROR,
   15791 					     "transferred zone "
   15792 					     "has %d SOA record%s", soacount,
   15793 					     (soacount != 0) ? "s" : "");
   15794 			if (nscount == 0) {
   15795 				dns_zone_log(zone, ISC_LOG_ERROR,
   15796 					     "transferred zone "
   15797 					     "has no NS records");
   15798 				if (DNS_ZONE_FLAG(zone,
   15799 						  DNS_ZONEFLG_HAVETIMERS)) {
   15800 					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
   15801 					zone->retry = DNS_ZONE_DEFAULTRETRY;
   15802 				}
   15803 				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   15804 				zone_unload(zone);
   15805 				goto next_master;
   15806 			}
   15807 			zone->refresh = RANGE(refresh, zone->minrefresh,
   15808 					      zone->maxrefresh);
   15809 			zone->retry = RANGE(retry, zone->minretry,
   15810 					    zone->maxretry);
   15811 			zone->expire = RANGE(expire,
   15812 					     zone->refresh + zone->retry,
   15813 					     DNS_MAX_EXPIRE);
   15814 			zone->minimum = minimum;
   15815 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   15816 		}
   15817 
   15818 		/*
   15819 		 * Set our next update/expire times.
   15820 		 */
   15821 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
   15822 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   15823 			zone->refreshtime = now;
   15824 			DNS_ZONE_TIME_ADD(&now, zone->expire,
   15825 					  &zone->expiretime);
   15826 		} else {
   15827 			DNS_ZONE_JITTER_ADD(&now, zone->refresh,
   15828 					    &zone->refreshtime);
   15829 			DNS_ZONE_TIME_ADD(&now, zone->expire,
   15830 					  &zone->expiretime);
   15831 		}
   15832 		if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
   15833 			char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
   15834 			if (zone->tsigkey != NULL) {
   15835 				char namebuf[DNS_NAME_FORMATSIZE];
   15836 				dns_name_format(&zone->tsigkey->name, namebuf,
   15837 						sizeof(namebuf));
   15838 				snprintf(buf, sizeof(buf), ": TSIG '%s'",
   15839 					 namebuf);
   15840 			} else
   15841 				buf[0] = '\0';
   15842 			dns_zone_log(zone, ISC_LOG_INFO,
   15843 				     "transferred serial %u%s",
   15844 				     serial, buf);
   15845 			if (inline_raw(zone))
   15846 				zone_send_secureserial(zone, serial);
   15847 		}
   15848 
   15849 		/*
   15850 		 * This is not necessary if we just performed a AXFR
   15851 		 * however it is necessary for an IXFR / UPTODATE and
   15852 		 * won't hurt with an AXFR.
   15853 		 */
   15854 		if (zone->masterfile != NULL || zone->journal != NULL) {
   15855 			unsigned int delay = DNS_DUMP_DELAY;
   15856 
   15857 			result = ISC_R_FAILURE;
   15858 			if (zone->journal != NULL)
   15859 				result = isc_file_settime(zone->journal, &now);
   15860 			if (result != ISC_R_SUCCESS &&
   15861 			    zone->masterfile != NULL)
   15862 				result = isc_file_settime(zone->masterfile,
   15863 							  &now);
   15864 
   15865 			if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
   15866 			    result == ISC_R_FILENOTFOUND)
   15867 				delay = 0;
   15868 
   15869 			if ((result == ISC_R_SUCCESS ||
   15870 			    result == ISC_R_FILENOTFOUND) &&
   15871 			    zone->masterfile != NULL)
   15872 				zone_needdump(zone, delay);
   15873 			else if (result != ISC_R_SUCCESS)
   15874 				dns_zone_log(zone, ISC_LOG_ERROR,
   15875 					     "transfer: could not set file "
   15876 					     "modification time of '%s': %s",
   15877 					     zone->masterfile,
   15878 					     dns_result_totext(result));
   15879 		}
   15880 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
   15881 		inc_stats(zone, dns_zonestatscounter_xfrsuccess);
   15882 		break;
   15883 
   15884 	case DNS_R_BADIXFR:
   15885 		/* Force retry with AXFR. */
   15886 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
   15887 		goto same_master;
   15888 
   15889 	case DNS_R_TOOMANYRECORDS:
   15890 	case DNS_R_VERIFYFAILURE:
   15891 		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
   15892 		inc_stats(zone, dns_zonestatscounter_xfrfail);
   15893 		break;
   15894 
   15895 	default:
   15896 	next_master:
   15897 		/*
   15898 		 * Skip to next failed / untried master.
   15899 		 */
   15900 		do {
   15901 			zone->curmaster++;
   15902 		} while (zone->curmaster < zone->masterscnt &&
   15903 			 zone->mastersok[zone->curmaster]);
   15904 		/* FALLTHROUGH */
   15905 	same_master:
   15906 		if (zone->curmaster >= zone->masterscnt) {
   15907 			zone->curmaster = 0;
   15908 			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
   15909 			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   15910 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
   15911 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
   15912 				while (zone->curmaster < zone->masterscnt &&
   15913 				       zone->mastersok[zone->curmaster])
   15914 					zone->curmaster++;
   15915 				again = true;
   15916 			} else
   15917 				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
   15918 		} else {
   15919 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
   15920 			again = true;
   15921 		}
   15922 		inc_stats(zone, dns_zonestatscounter_xfrfail);
   15923 		break;
   15924 	}
   15925 	zone_settimer(zone, &now);
   15926 
   15927 	/*
   15928 	 * If creating the transfer object failed, zone->xfr is NULL.
   15929 	 * Otherwise, we are called as the done callback of a zone
   15930 	 * transfer object that just entered its shutting-down
   15931 	 * state.  Since we are no longer responsible for shutting
   15932 	 * it down, we can detach our reference.
   15933 	 */
   15934 	if (zone->xfr != NULL)
   15935 		dns_xfrin_detach(&zone->xfr);
   15936 
   15937 	if (zone->tsigkey != NULL)
   15938 		dns_tsigkey_detach(&zone->tsigkey);
   15939 
   15940 	/*
   15941 	 * Handle any deferred journal compaction.
   15942 	 */
   15943 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
   15944 		dns_db_t *db = NULL;
   15945 		if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
   15946 			zone_journal_compact(zone, db, zone->compact_serial);
   15947 			dns_db_detach(&db);
   15948 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
   15949 		}
   15950 	}
   15951 
   15952 	if (secure != NULL)
   15953 		UNLOCK_ZONE(secure);
   15954 	/*
   15955 	 * This transfer finishing freed up a transfer quota slot.
   15956 	 * Let any other zones waiting for quota have it.
   15957 	 */
   15958 	if (zone->zmgr != NULL &&
   15959 	    zone->statelist == &zone->zmgr->xfrin_in_progress) {
   15960 		UNLOCK_ZONE(zone);
   15961 		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   15962 		ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
   15963 		zone->statelist = NULL;
   15964 		zmgr_resume_xfrs(zone->zmgr, false);
   15965 		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   15966 		LOCK_ZONE(zone);
   15967 	}
   15968 
   15969 	/*
   15970 	 * Retry with a different server if necessary.
   15971 	 */
   15972 	if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
   15973 		queue_soa_query(zone);
   15974 
   15975 	INSIST(zone->irefs > 0);
   15976 	zone->irefs--;
   15977 	free_needed = exit_check(zone);
   15978 	UNLOCK_ZONE(zone);
   15979 	if (free_needed)
   15980 		zone_free(zone);
   15981 }
   15982 
   15983 static void
   15984 zone_loaddone(void *arg, isc_result_t result) {
   15985 	static char me[] = "zone_loaddone";
   15986 	dns_load_t *load = arg;
   15987 	dns_zone_t *zone;
   15988 	isc_result_t tresult;
   15989 	dns_zone_t *secure = NULL;
   15990 
   15991 	REQUIRE(DNS_LOAD_VALID(load));
   15992 	zone = load->zone;
   15993 
   15994 	ENTER;
   15995 
   15996 	/*
   15997 	 * If zone loading failed, remove the update db callbacks prior
   15998 	 * to calling the list of callbacks in the zone load structure.
   15999 	 */
   16000 	if (result != ISC_R_SUCCESS) {
   16001 		dns_zone_rpz_disable_db(zone, load->db);
   16002 		dns_zone_catz_disable_db(zone, load->db);
   16003 	}
   16004 
   16005 	tresult = dns_db_endload(load->db, &load->callbacks);
   16006 	if (tresult != ISC_R_SUCCESS &&
   16007 	    (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
   16008 		result = tresult;
   16009 
   16010 	/*
   16011 	 * Lock hierarchy: zmgr, zone, raw.
   16012 	 */
   16013  again:
   16014 	LOCK_ZONE(zone);
   16015 	INSIST(zone != zone->raw);
   16016 	if (inline_secure(zone))
   16017 		LOCK_ZONE(zone->raw);
   16018 	else if (inline_raw(zone)) {
   16019 		secure = zone->secure;
   16020 		TRYLOCK_ZONE(tresult, secure);
   16021 		if (tresult != ISC_R_SUCCESS) {
   16022 			UNLOCK_ZONE(zone);
   16023 			secure = NULL;
   16024 			isc_thread_yield();
   16025 			goto again;
   16026 		}
   16027 	}
   16028 	(void)zone_postload(zone, load->db, load->loadtime, result);
   16029 	zonemgr_putio(&zone->readio);
   16030 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
   16031 	zone_idetach(&load->callbacks.zone);
   16032 	/*
   16033 	 * Leave the zone frozen if the reload fails.
   16034 	 */
   16035 	if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
   16036 	     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
   16037 		zone->update_disabled = false;
   16038 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
   16039 	if (inline_secure(zone))
   16040 		UNLOCK_ZONE(zone->raw);
   16041 	else if (secure != NULL)
   16042 		UNLOCK_ZONE(secure);
   16043 	UNLOCK_ZONE(zone);
   16044 
   16045 	load->magic = 0;
   16046 	dns_db_detach(&load->db);
   16047 	if (load->zone->lctx != NULL)
   16048 		dns_loadctx_detach(&load->zone->lctx);
   16049 	dns_zone_idetach(&load->zone);
   16050 	isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
   16051 }
   16052 
   16053 void
   16054 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
   16055 	REQUIRE(DNS_ZONE_VALID(zone));
   16056 	REQUIRE(table != NULL);
   16057 	REQUIRE(*table == NULL);
   16058 
   16059 	LOCK_ZONE(zone);
   16060 	if (zone->ssutable != NULL)
   16061 		dns_ssutable_attach(zone->ssutable, table);
   16062 	UNLOCK_ZONE(zone);
   16063 }
   16064 
   16065 void
   16066 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
   16067 	REQUIRE(DNS_ZONE_VALID(zone));
   16068 
   16069 	LOCK_ZONE(zone);
   16070 	if (zone->ssutable != NULL)
   16071 		dns_ssutable_detach(&zone->ssutable);
   16072 	if (table != NULL)
   16073 		dns_ssutable_attach(table, &zone->ssutable);
   16074 	UNLOCK_ZONE(zone);
   16075 }
   16076 
   16077 void
   16078 dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
   16079 	REQUIRE(DNS_ZONE_VALID(zone));
   16080 
   16081 	zone->sigvalidityinterval = interval;
   16082 }
   16083 
   16084 uint32_t
   16085 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
   16086 	REQUIRE(DNS_ZONE_VALID(zone));
   16087 
   16088 	return (zone->sigvalidityinterval);
   16089 }
   16090 
   16091 void
   16092 dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
   16093 	REQUIRE(DNS_ZONE_VALID(zone));
   16094 
   16095 	zone->keyvalidityinterval = interval;
   16096 }
   16097 
   16098 uint32_t
   16099 dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
   16100 	REQUIRE(DNS_ZONE_VALID(zone));
   16101 
   16102 	return (zone->keyvalidityinterval);
   16103 }
   16104 
   16105 void
   16106 dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
   16107 	isc_time_t now;
   16108 
   16109 	REQUIRE(DNS_ZONE_VALID(zone));
   16110 
   16111 	LOCK_ZONE(zone);
   16112 	zone->sigresigninginterval = interval;
   16113 	set_resigntime(zone);
   16114 	if (zone->task != NULL) {
   16115 		TIME_NOW(&now);
   16116 		zone_settimer(zone, &now);
   16117 	}
   16118 	UNLOCK_ZONE(zone);
   16119 }
   16120 
   16121 uint32_t
   16122 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
   16123 	REQUIRE(DNS_ZONE_VALID(zone));
   16124 
   16125 	return (zone->sigresigninginterval);
   16126 }
   16127 
   16128 static void
   16129 queue_xfrin(dns_zone_t *zone) {
   16130 	const char me[] = "queue_xfrin";
   16131 	isc_result_t result;
   16132 	dns_zonemgr_t *zmgr = zone->zmgr;
   16133 
   16134 	ENTER;
   16135 
   16136 	INSIST(zone->statelist == NULL);
   16137 
   16138 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16139 	ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
   16140 	LOCK_ZONE(zone);
   16141 	zone->irefs++;
   16142 	UNLOCK_ZONE(zone);
   16143 	zone->statelist = &zmgr->waiting_for_xfrin;
   16144 	result = zmgr_start_xfrin_ifquota(zmgr, zone);
   16145 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16146 
   16147 	if (result == ISC_R_QUOTA) {
   16148 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   16149 			      "zone transfer deferred due to quota");
   16150 	} else if (result != ISC_R_SUCCESS) {
   16151 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
   16152 			      "starting zone transfer: %s",
   16153 			      isc_result_totext(result));
   16154 	}
   16155 }
   16156 
   16157 /*
   16158  * This event callback is called when a zone has received
   16159  * any necessary zone transfer quota.  This is the time
   16160  * to go ahead and start the transfer.
   16161  */
   16162 static void
   16163 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
   16164 	isc_result_t result = ISC_R_SUCCESS;
   16165 	dns_peer_t *peer = NULL;
   16166 	char master[ISC_SOCKADDR_FORMATSIZE];
   16167 	char source[ISC_SOCKADDR_FORMATSIZE];
   16168 	dns_rdatatype_t xfrtype;
   16169 	dns_zone_t *zone = event->ev_arg;
   16170 	isc_netaddr_t masterip;
   16171 	isc_sockaddr_t sourceaddr;
   16172 	isc_sockaddr_t masteraddr;
   16173 	isc_time_t now;
   16174 	const char *soa_before = "";
   16175 	isc_dscp_t dscp = -1;
   16176 	bool loaded;
   16177 
   16178 	UNUSED(task);
   16179 
   16180 	INSIST(task == zone->task);
   16181 
   16182 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   16183 		result = ISC_R_CANCELED;
   16184 		goto cleanup;
   16185 	}
   16186 
   16187 	TIME_NOW(&now);
   16188 
   16189 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
   16190 	if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
   16191 				    &zone->sourceaddr, &now))
   16192 	{
   16193 		isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   16194 		dns_zone_log(zone, ISC_LOG_INFO,
   16195 			     "got_transfer_quota: skipping zone transfer as "
   16196 			     "master %s (source %s) is unreachable (cached)",
   16197 			     master, source);
   16198 		result = ISC_R_CANCELED;
   16199 		goto cleanup;
   16200 	}
   16201 
   16202 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
   16203 	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
   16204 
   16205 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
   16206 		soa_before = "SOA before ";
   16207 	/*
   16208 	 * Decide whether we should request IXFR or AXFR.
   16209 	 */
   16210 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   16211 	loaded = (zone->db != NULL);
   16212 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   16213 
   16214 	if (!loaded) {
   16215 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
   16216 			     "no database exists yet, requesting AXFR of "
   16217 			     "initial version from %s", master);
   16218 		xfrtype = dns_rdatatype_axfr;
   16219 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
   16220 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
   16221 			     "forced reload, requesting AXFR of "
   16222 			     "initial version from %s", master);
   16223 		xfrtype = dns_rdatatype_axfr;
   16224 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
   16225 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
   16226 			     "retrying with AXFR from %s due to "
   16227 			     "previous IXFR failure", master);
   16228 		xfrtype = dns_rdatatype_axfr;
   16229 		LOCK_ZONE(zone);
   16230 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
   16231 		UNLOCK_ZONE(zone);
   16232 	} else {
   16233 		bool use_ixfr = true;
   16234 		if (peer != NULL)
   16235 			result = dns_peer_getrequestixfr(peer, &use_ixfr);
   16236 		if (peer == NULL || result != ISC_R_SUCCESS)
   16237 			use_ixfr = zone->requestixfr;
   16238 		if (use_ixfr == false) {
   16239 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   16240 				     "IXFR disabled, requesting %sAXFR from %s",
   16241 				     soa_before, master);
   16242 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
   16243 				xfrtype = dns_rdatatype_soa;
   16244 			else
   16245 				xfrtype = dns_rdatatype_axfr;
   16246 		} else {
   16247 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   16248 				     "requesting IXFR from %s", master);
   16249 			xfrtype = dns_rdatatype_ixfr;
   16250 		}
   16251 	}
   16252 
   16253 	/*
   16254 	 * Determine if we should attempt to sign the request with TSIG.
   16255 	 */
   16256 	result = ISC_R_NOTFOUND;
   16257 
   16258 	/*
   16259 	 * First, look for a tsig key in the master statement, then
   16260 	 * try for a server key.
   16261 	 */
   16262 	if ((zone->masterkeynames != NULL) &&
   16263 	    (zone->masterkeynames[zone->curmaster] != NULL)) {
   16264 		dns_view_t *view = dns_zone_getview(zone);
   16265 		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
   16266 		result = dns_view_gettsig(view, keyname, &zone->tsigkey);
   16267 	}
   16268 	if (zone->tsigkey == NULL)
   16269 		result = dns_view_getpeertsig(zone->view, &masterip,
   16270 					      &zone->tsigkey);
   16271 
   16272 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   16273 		dns_zone_log(zone, ISC_LOG_ERROR,
   16274 			     "could not get TSIG key for zone transfer: %s",
   16275 			     isc_result_totext(result));
   16276 	}
   16277 
   16278 	if (zone->masterdscps != NULL)
   16279 	    dscp = zone->masterdscps[zone->curmaster];
   16280 
   16281 	LOCK_ZONE(zone);
   16282 	masteraddr = zone->masteraddr;
   16283 	sourceaddr = zone->sourceaddr;
   16284 	switch (isc_sockaddr_pf(&masteraddr)) {
   16285 	case PF_INET:
   16286 		if (dscp == -1)
   16287 			dscp = zone->xfrsource4dscp;
   16288 		break;
   16289 	case PF_INET6:
   16290 		if (dscp == -1)
   16291 			dscp = zone->xfrsource6dscp;
   16292 		break;
   16293 	default:
   16294 		INSIST(0);
   16295 		ISC_UNREACHABLE();
   16296 	}
   16297 	UNLOCK_ZONE(zone);
   16298 	INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
   16299 	result = dns_xfrin_create(zone, xfrtype, &masteraddr, &sourceaddr,
   16300 				  dscp, zone->tsigkey, zone->mctx,
   16301 				  zone->zmgr->timermgr, zone->zmgr->socketmgr,
   16302 				  zone->task, zone_xfrdone, &zone->xfr);
   16303 	if (result == ISC_R_SUCCESS) {
   16304 		LOCK_ZONE(zone);
   16305 		if (xfrtype == dns_rdatatype_axfr) {
   16306 			if (isc_sockaddr_pf(&masteraddr) == PF_INET)
   16307 				inc_stats(zone, dns_zonestatscounter_axfrreqv4);
   16308 			else
   16309 				inc_stats(zone, dns_zonestatscounter_axfrreqv6);
   16310 		} else if (xfrtype == dns_rdatatype_ixfr) {
   16311 			if (isc_sockaddr_pf(&masteraddr) == PF_INET)
   16312 				inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
   16313 			else
   16314 				inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
   16315 		}
   16316 		UNLOCK_ZONE(zone);
   16317 	}
   16318  cleanup:
   16319 	/*
   16320 	 * Any failure in this function is handled like a failed
   16321 	 * zone transfer.  This ensures that we get removed from
   16322 	 * zmgr->xfrin_in_progress.
   16323 	 */
   16324 	if (result != ISC_R_SUCCESS)
   16325 		zone_xfrdone(zone, result);
   16326 
   16327 	isc_event_free(&event);
   16328 }
   16329 
   16330 /*
   16331  * Update forwarding support.
   16332  */
   16333 
   16334 static void
   16335 forward_destroy(dns_forward_t *forward) {
   16336 
   16337 	forward->magic = 0;
   16338 	if (forward->request != NULL)
   16339 		dns_request_destroy(&forward->request);
   16340 	if (forward->msgbuf != NULL)
   16341 		isc_buffer_free(&forward->msgbuf);
   16342 	if (forward->zone != NULL) {
   16343 		LOCK(&forward->zone->lock);
   16344 		if (ISC_LINK_LINKED(forward, link))
   16345 			ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
   16346 		UNLOCK(&forward->zone->lock);
   16347 		dns_zone_idetach(&forward->zone);
   16348 	}
   16349 	isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
   16350 }
   16351 
   16352 static isc_result_t
   16353 sendtomaster(dns_forward_t *forward) {
   16354 	isc_result_t result;
   16355 	isc_sockaddr_t src;
   16356 	isc_dscp_t dscp = -1;
   16357 
   16358 	LOCK_ZONE(forward->zone);
   16359 
   16360 	if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
   16361 		UNLOCK_ZONE(forward->zone);
   16362 		return (ISC_R_CANCELED);
   16363 	}
   16364 
   16365 	if (forward->which >= forward->zone->masterscnt) {
   16366 		UNLOCK_ZONE(forward->zone);
   16367 		return (ISC_R_NOMORE);
   16368 	}
   16369 
   16370 	forward->addr = forward->zone->masters[forward->which];
   16371 	/*
   16372 	 * Always use TCP regardless of whether the original update
   16373 	 * used TCP.
   16374 	 * XXX The timeout may but a bit small if we are far down a
   16375 	 * transfer graph and the master has to try several masters.
   16376 	 */
   16377 	switch (isc_sockaddr_pf(&forward->addr)) {
   16378 	case PF_INET:
   16379 		src = forward->zone->xfrsource4;
   16380 		dscp = forward->zone->xfrsource4dscp;
   16381 		break;
   16382 	case PF_INET6:
   16383 		src = forward->zone->xfrsource6;
   16384 		dscp = forward->zone->xfrsource6dscp;
   16385 		break;
   16386 	default:
   16387 		result = ISC_R_NOTIMPLEMENTED;
   16388 		goto unlock;
   16389 	}
   16390 	result = dns_request_createraw(forward->zone->view->requestmgr,
   16391 				       forward->msgbuf,
   16392 				       &src, &forward->addr, dscp,
   16393 				       forward->options, 15 /* XXX */,
   16394 				       0, 0, forward->zone->task,
   16395 				       forward_callback, forward,
   16396 				       &forward->request);
   16397 	if (result == ISC_R_SUCCESS) {
   16398 		if (!ISC_LINK_LINKED(forward, link))
   16399 			ISC_LIST_APPEND(forward->zone->forwards, forward, link);
   16400 	}
   16401 
   16402  unlock:
   16403 	UNLOCK_ZONE(forward->zone);
   16404 	return (result);
   16405 }
   16406 
   16407 static void
   16408 forward_callback(isc_task_t *task, isc_event_t *event) {
   16409 	const char me[] = "forward_callback";
   16410 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
   16411 	dns_message_t *msg = NULL;
   16412 	char master[ISC_SOCKADDR_FORMATSIZE];
   16413 	isc_result_t result;
   16414 	dns_forward_t *forward;
   16415 	dns_zone_t *zone;
   16416 
   16417 	UNUSED(task);
   16418 
   16419 	forward = revent->ev_arg;
   16420 	INSIST(DNS_FORWARD_VALID(forward));
   16421 	zone = forward->zone;
   16422 	INSIST(DNS_ZONE_VALID(zone));
   16423 
   16424 	ENTER;
   16425 
   16426 	isc_sockaddr_format(&forward->addr, master, sizeof(master));
   16427 
   16428 	if (revent->result != ISC_R_SUCCESS) {
   16429 		dns_zone_log(zone, ISC_LOG_INFO,
   16430 			     "could not forward dynamic update to %s: %s",
   16431 			     master, dns_result_totext(revent->result));
   16432 		goto next_master;
   16433 	}
   16434 
   16435 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
   16436 	if (result != ISC_R_SUCCESS)
   16437 		goto next_master;
   16438 
   16439 	result = dns_request_getresponse(revent->request, msg,
   16440 					 DNS_MESSAGEPARSE_PRESERVEORDER |
   16441 					 DNS_MESSAGEPARSE_CLONEBUFFER);
   16442 	if (result != ISC_R_SUCCESS)
   16443 		goto next_master;
   16444 
   16445 	switch (msg->rcode) {
   16446 	/*
   16447 	 * Pass these rcodes back to client.
   16448 	 */
   16449 	case dns_rcode_noerror:
   16450 	case dns_rcode_yxdomain:
   16451 	case dns_rcode_yxrrset:
   16452 	case dns_rcode_nxrrset:
   16453 	case dns_rcode_refused:
   16454 	case dns_rcode_nxdomain: {
   16455 		char rcode[128];
   16456 		isc_buffer_t rb;
   16457 
   16458 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   16459 		(void)dns_rcode_totext(msg->rcode, &rb);
   16460 		dns_zone_log(zone, ISC_LOG_INFO,
   16461 			     "forwarded dynamic update: "
   16462 			     "master %s returned: %.*s",
   16463 			     master, (int)rb.used, rcode);
   16464 		break;
   16465 	}
   16466 
   16467 	/* These should not occur if the masters/zone are valid. */
   16468 	case dns_rcode_notzone:
   16469 	case dns_rcode_notauth: {
   16470 		char rcode[128];
   16471 		isc_buffer_t rb;
   16472 
   16473 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   16474 		(void)dns_rcode_totext(msg->rcode, &rb);
   16475 		dns_zone_log(zone, ISC_LOG_WARNING,
   16476 			     "forwarding dynamic update: "
   16477 			     "unexpected response: master %s returned: %.*s",
   16478 			     master, (int)rb.used, rcode);
   16479 		goto next_master;
   16480 	}
   16481 
   16482 	/* Try another server for these rcodes. */
   16483 	case dns_rcode_formerr:
   16484 	case dns_rcode_servfail:
   16485 	case dns_rcode_notimp:
   16486 	case dns_rcode_badvers:
   16487 	default:
   16488 		goto next_master;
   16489 	}
   16490 
   16491 	/* call callback */
   16492 	(forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
   16493 	msg = NULL;
   16494 	dns_request_destroy(&forward->request);
   16495 	forward_destroy(forward);
   16496 	isc_event_free(&event);
   16497 	return;
   16498 
   16499  next_master:
   16500 	if (msg != NULL)
   16501 		dns_message_destroy(&msg);
   16502 	isc_event_free(&event);
   16503 	forward->which++;
   16504 	dns_request_destroy(&forward->request);
   16505 	result = sendtomaster(forward);
   16506 	if (result != ISC_R_SUCCESS) {
   16507 		/* call callback */
   16508 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   16509 			     "exhausted dynamic update forwarder list");
   16510 		(forward->callback)(forward->callback_arg, result, NULL);
   16511 		forward_destroy(forward);
   16512 	}
   16513 }
   16514 
   16515 isc_result_t
   16516 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
   16517 		       dns_updatecallback_t callback, void *callback_arg)
   16518 {
   16519 	dns_forward_t *forward;
   16520 	isc_result_t result;
   16521 	isc_region_t *mr;
   16522 
   16523 	REQUIRE(DNS_ZONE_VALID(zone));
   16524 	REQUIRE(msg != NULL);
   16525 	REQUIRE(callback != NULL);
   16526 
   16527 	forward = isc_mem_get(zone->mctx, sizeof(*forward));
   16528 	if (forward == NULL)
   16529 		return (ISC_R_NOMEMORY);
   16530 
   16531 	forward->request = NULL;
   16532 	forward->zone = NULL;
   16533 	forward->msgbuf = NULL;
   16534 	forward->which = 0;
   16535 	forward->mctx = 0;
   16536 	forward->callback = callback;
   16537 	forward->callback_arg = callback_arg;
   16538 	ISC_LINK_INIT(forward, link);
   16539 	forward->magic = FORWARD_MAGIC;
   16540 	forward->options = DNS_REQUESTOPT_TCP;
   16541 	/*
   16542 	 * If we have a SIG(0) signed message we need to preserve the
   16543 	 * query id as that is included in the SIG(0) computation.
   16544 	 */
   16545 	if (msg->sig0 != NULL)
   16546 		forward->options |= DNS_REQUESTOPT_FIXEDID;
   16547 
   16548 	mr = dns_message_getrawmessage(msg);
   16549 	if (mr == NULL) {
   16550 		result = ISC_R_UNEXPECTEDEND;
   16551 		goto cleanup;
   16552 	}
   16553 
   16554 	result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
   16555 	if (result != ISC_R_SUCCESS)
   16556 		goto cleanup;
   16557 	result = isc_buffer_copyregion(forward->msgbuf, mr);
   16558 	if (result != ISC_R_SUCCESS)
   16559 		goto cleanup;
   16560 
   16561 	isc_mem_attach(zone->mctx, &forward->mctx);
   16562 	dns_zone_iattach(zone, &forward->zone);
   16563 	result = sendtomaster(forward);
   16564 
   16565  cleanup:
   16566 	if (result != ISC_R_SUCCESS) {
   16567 		forward_destroy(forward);
   16568 	}
   16569 	return (result);
   16570 }
   16571 
   16572 isc_result_t
   16573 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
   16574 	REQUIRE(DNS_ZONE_VALID(zone));
   16575 	REQUIRE(next != NULL && *next == NULL);
   16576 
   16577 	*next = ISC_LIST_NEXT(zone, link);
   16578 	if (*next == NULL)
   16579 		return (ISC_R_NOMORE);
   16580 	else
   16581 		return (ISC_R_SUCCESS);
   16582 }
   16583 
   16584 isc_result_t
   16585 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
   16586 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16587 	REQUIRE(first != NULL && *first == NULL);
   16588 
   16589 	*first = ISC_LIST_HEAD(zmgr->zones);
   16590 	if (*first == NULL)
   16591 		return (ISC_R_NOMORE);
   16592 	else
   16593 		return (ISC_R_SUCCESS);
   16594 }
   16595 
   16596 /***
   16597  ***	Zone manager.
   16598  ***/
   16599 
   16600 isc_result_t
   16601 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
   16602 		   isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
   16603 		   dns_zonemgr_t **zmgrp)
   16604 {
   16605 	dns_zonemgr_t *zmgr;
   16606 	isc_result_t result;
   16607 
   16608 	zmgr = isc_mem_get(mctx, sizeof(*zmgr));
   16609 	if (zmgr == NULL)
   16610 		return (ISC_R_NOMEMORY);
   16611 	zmgr->mctx = NULL;
   16612 	zmgr->refs = 1;
   16613 	isc_mem_attach(mctx, &zmgr->mctx);
   16614 	zmgr->taskmgr = taskmgr;
   16615 	zmgr->timermgr = timermgr;
   16616 	zmgr->socketmgr = socketmgr;
   16617 	zmgr->zonetasks = NULL;
   16618 	zmgr->loadtasks = NULL;
   16619 	zmgr->mctxpool = NULL;
   16620 	zmgr->task = NULL;
   16621 	zmgr->notifyrl = NULL;
   16622 	zmgr->refreshrl = NULL;
   16623 	zmgr->startupnotifyrl = NULL;
   16624 	zmgr->startuprefreshrl = NULL;
   16625 	ISC_LIST_INIT(zmgr->zones);
   16626 	ISC_LIST_INIT(zmgr->waiting_for_xfrin);
   16627 	ISC_LIST_INIT(zmgr->xfrin_in_progress);
   16628 	memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
   16629 	result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
   16630 	if (result != ISC_R_SUCCESS)
   16631 		goto free_mem;
   16632 
   16633 	zmgr->transfersin = 10;
   16634 	zmgr->transfersperns = 2;
   16635 
   16636 	/* Unreachable lock. */
   16637 	result = isc_rwlock_init(&zmgr->urlock, 0, 0);
   16638 	if (result != ISC_R_SUCCESS)
   16639 		goto free_rwlock;
   16640 
   16641 	/* Create a single task for queueing of SOA queries. */
   16642 	result = isc_task_create(taskmgr, 1, &zmgr->task);
   16643 	if (result != ISC_R_SUCCESS)
   16644 		goto free_urlock;
   16645 
   16646 	isc_task_setname(zmgr->task, "zmgr", zmgr);
   16647 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
   16648 					&zmgr->notifyrl);
   16649 	if (result != ISC_R_SUCCESS)
   16650 		goto free_task;
   16651 
   16652 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
   16653 					&zmgr->refreshrl);
   16654 	if (result != ISC_R_SUCCESS)
   16655 		goto free_notifyrl;
   16656 
   16657 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
   16658 					&zmgr->startupnotifyrl);
   16659 	if (result != ISC_R_SUCCESS)
   16660 		goto free_refreshrl;
   16661 
   16662 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
   16663 					&zmgr->startuprefreshrl);
   16664 	if (result != ISC_R_SUCCESS)
   16665 		goto free_startupnotifyrl;
   16666 
   16667 	/* default to 20 refresh queries / notifies per second. */
   16668 	setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
   16669 	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
   16670 	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
   16671 	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
   16672 	isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
   16673 	isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
   16674 
   16675 	zmgr->iolimit = 1;
   16676 	zmgr->ioactive = 0;
   16677 	ISC_LIST_INIT(zmgr->high);
   16678 	ISC_LIST_INIT(zmgr->low);
   16679 
   16680 	isc_mutex_init(&zmgr->iolock);
   16681 
   16682 	zmgr->magic = ZONEMGR_MAGIC;
   16683 
   16684 	*zmgrp = zmgr;
   16685 	return (ISC_R_SUCCESS);
   16686 
   16687 #if 0
   16688  free_iolock:
   16689 	isc_mutex_destroy(&zmgr->iolock);
   16690 #endif
   16691  free_startupnotifyrl:
   16692 	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
   16693  free_refreshrl:
   16694 	isc_ratelimiter_detach(&zmgr->refreshrl);
   16695  free_notifyrl:
   16696 	isc_ratelimiter_detach(&zmgr->notifyrl);
   16697  free_task:
   16698 	isc_task_detach(&zmgr->task);
   16699  free_urlock:
   16700 	isc_rwlock_destroy(&zmgr->urlock);
   16701  free_rwlock:
   16702 	isc_rwlock_destroy(&zmgr->rwlock);
   16703  free_mem:
   16704 	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
   16705 	isc_mem_detach(&mctx);
   16706 	return (result);
   16707 }
   16708 
   16709 isc_result_t
   16710 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
   16711 	isc_result_t result;
   16712 	isc_mem_t *mctx = NULL;
   16713 	dns_zone_t *zone = NULL;
   16714 	void *item;
   16715 
   16716 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16717 	REQUIRE(zonep != NULL && *zonep == NULL);
   16718 
   16719 	if (zmgr->mctxpool == NULL)
   16720 		return (ISC_R_FAILURE);
   16721 
   16722 	item = isc_pool_get(zmgr->mctxpool);
   16723 	if (item == NULL)
   16724 		return (ISC_R_FAILURE);
   16725 
   16726 	isc_mem_attach((isc_mem_t *) item, &mctx);
   16727 	result = dns_zone_create(&zone, mctx);
   16728 	isc_mem_detach(&mctx);
   16729 
   16730 	if (result == ISC_R_SUCCESS)
   16731 		*zonep = zone;
   16732 
   16733 	return (result);
   16734 }
   16735 
   16736 isc_result_t
   16737 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
   16738 	isc_result_t result;
   16739 
   16740 	REQUIRE(DNS_ZONE_VALID(zone));
   16741 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16742 
   16743 	if (zmgr->zonetasks == NULL)
   16744 		return (ISC_R_FAILURE);
   16745 
   16746 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16747 	LOCK_ZONE(zone);
   16748 	REQUIRE(zone->task == NULL);
   16749 	REQUIRE(zone->timer == NULL);
   16750 	REQUIRE(zone->zmgr == NULL);
   16751 
   16752 	isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
   16753 	isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
   16754 
   16755 	/*
   16756 	 * Set the task name.  The tag will arbitrarily point to one
   16757 	 * of the zones sharing the task (in practice, the one
   16758 	 * to be managed last).
   16759 	 */
   16760 	isc_task_setname(zone->task, "zone", zone);
   16761 	isc_task_setname(zone->loadtask, "loadzone", zone);
   16762 
   16763 	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
   16764 				  NULL, NULL,
   16765 				  zone->task, zone_timer, zone,
   16766 				  &zone->timer);
   16767 
   16768 	if (result != ISC_R_SUCCESS)
   16769 		goto cleanup_tasks;
   16770 
   16771 	/*
   16772 	 * The timer "holds" a iref.
   16773 	 */
   16774 	zone->irefs++;
   16775 	INSIST(zone->irefs != 0);
   16776 
   16777 	ISC_LIST_APPEND(zmgr->zones, zone, link);
   16778 	zone->zmgr = zmgr;
   16779 	zmgr->refs++;
   16780 
   16781 	goto unlock;
   16782 
   16783  cleanup_tasks:
   16784 	isc_task_detach(&zone->loadtask);
   16785 	isc_task_detach(&zone->task);
   16786 
   16787  unlock:
   16788 	UNLOCK_ZONE(zone);
   16789 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16790 	return (result);
   16791 }
   16792 
   16793 void
   16794 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
   16795 	bool free_now = false;
   16796 
   16797 	REQUIRE(DNS_ZONE_VALID(zone));
   16798 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16799 	REQUIRE(zone->zmgr == zmgr);
   16800 
   16801 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16802 	LOCK_ZONE(zone);
   16803 
   16804 	ISC_LIST_UNLINK(zmgr->zones, zone, link);
   16805 	zone->zmgr = NULL;
   16806 	zmgr->refs--;
   16807 	if (zmgr->refs == 0)
   16808 		free_now = true;
   16809 
   16810 	UNLOCK_ZONE(zone);
   16811 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16812 
   16813 	if (free_now)
   16814 		zonemgr_free(zmgr);
   16815 	ENSURE(zone->zmgr == NULL);
   16816 }
   16817 
   16818 void
   16819 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
   16820 	REQUIRE(DNS_ZONEMGR_VALID(source));
   16821 	REQUIRE(target != NULL && *target == NULL);
   16822 
   16823 	RWLOCK(&source->rwlock, isc_rwlocktype_write);
   16824 	REQUIRE(source->refs > 0);
   16825 	source->refs++;
   16826 	INSIST(source->refs > 0);
   16827 	RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
   16828 	*target = source;
   16829 }
   16830 
   16831 void
   16832 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
   16833 	dns_zonemgr_t *zmgr;
   16834 	bool free_now = false;
   16835 
   16836 	REQUIRE(zmgrp != NULL);
   16837 	zmgr = *zmgrp;
   16838 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16839 
   16840 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16841 	zmgr->refs--;
   16842 	if (zmgr->refs == 0)
   16843 		free_now = true;
   16844 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16845 
   16846 	if (free_now)
   16847 		zonemgr_free(zmgr);
   16848 	*zmgrp = NULL;
   16849 }
   16850 
   16851 isc_result_t
   16852 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
   16853 	dns_zone_t *p;
   16854 
   16855 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16856 
   16857 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   16858 	for (p = ISC_LIST_HEAD(zmgr->zones);
   16859 	     p != NULL;
   16860 	     p = ISC_LIST_NEXT(p, link))
   16861 	{
   16862 		dns_zone_maintenance(p);
   16863 	}
   16864 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   16865 
   16866 	/*
   16867 	 * Recent configuration changes may have increased the
   16868 	 * amount of available transfers quota.  Make sure any
   16869 	 * transfers currently blocked on quota get started if
   16870 	 * possible.
   16871 	 */
   16872 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16873 	zmgr_resume_xfrs(zmgr, true);
   16874 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16875 	return (ISC_R_SUCCESS);
   16876 }
   16877 
   16878 void
   16879 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
   16880 
   16881 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16882 
   16883 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16884 	zmgr_resume_xfrs(zmgr, true);
   16885 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16886 }
   16887 
   16888 void
   16889 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
   16890 	dns_zone_t *zone;
   16891 
   16892 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16893 
   16894 	isc_ratelimiter_shutdown(zmgr->notifyrl);
   16895 	isc_ratelimiter_shutdown(zmgr->refreshrl);
   16896 	isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
   16897 	isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
   16898 
   16899 	if (zmgr->task != NULL)
   16900 		isc_task_destroy(&zmgr->task);
   16901 	if (zmgr->zonetasks != NULL)
   16902 		isc_taskpool_destroy(&zmgr->zonetasks);
   16903 	if (zmgr->loadtasks != NULL)
   16904 		isc_taskpool_destroy(&zmgr->loadtasks);
   16905 	if (zmgr->mctxpool != NULL)
   16906 		isc_pool_destroy(&zmgr->mctxpool);
   16907 
   16908 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   16909 	for (zone = ISC_LIST_HEAD(zmgr->zones);
   16910 	     zone != NULL;
   16911 	     zone = ISC_LIST_NEXT(zone, link))
   16912 	{
   16913 		LOCK_ZONE(zone);
   16914 		forward_cancel(zone);
   16915 		UNLOCK_ZONE(zone);
   16916 	}
   16917 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   16918 }
   16919 
   16920 static isc_result_t
   16921 mctxinit(void **target, void *arg) {
   16922 	isc_result_t result;
   16923 	isc_mem_t *mctx = NULL;
   16924 
   16925 	UNUSED(arg);
   16926 
   16927 	REQUIRE(target != NULL && *target == NULL);
   16928 
   16929 	result = isc_mem_create(0, 0, &mctx);
   16930 	if (result != ISC_R_SUCCESS)
   16931 		return (result);
   16932 	isc_mem_setname(mctx, "zonemgr-pool", NULL);
   16933 
   16934 	*target = mctx;
   16935 	return (ISC_R_SUCCESS);
   16936 }
   16937 
   16938 static void
   16939 mctxfree(void **target) {
   16940 	isc_mem_t *mctx = *(isc_mem_t **) target;
   16941 	isc_mem_detach(&mctx);
   16942 	*target = NULL;
   16943 }
   16944 
   16945 #define ZONES_PER_TASK 100
   16946 #define ZONES_PER_MCTX 1000
   16947 
   16948 isc_result_t
   16949 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
   16950 	isc_result_t result;
   16951 	int ntasks = num_zones / ZONES_PER_TASK;
   16952 	int nmctx = num_zones / ZONES_PER_MCTX;
   16953 	isc_taskpool_t *pool = NULL;
   16954 	isc_pool_t *mctxpool = NULL;
   16955 
   16956 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16957 
   16958 	/*
   16959 	 * For anything fewer than 1000 zones we use 10 tasks in
   16960 	 * the task pools.  More than that, and we'll scale at one
   16961 	 * task per 100 zones.  Similarly, for anything smaller than
   16962 	 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
   16963 	 */
   16964 	if (ntasks < 10)
   16965 		ntasks = 10;
   16966 	if (nmctx < 2)
   16967 		nmctx = 2;
   16968 
   16969 	/* Create or resize the zone task pools. */
   16970 	if (zmgr->zonetasks == NULL)
   16971 		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
   16972 					     ntasks, 2, &pool);
   16973 	else
   16974 		result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
   16975 
   16976 	if (result == ISC_R_SUCCESS)
   16977 		zmgr->zonetasks = pool;
   16978 
   16979 	pool = NULL;
   16980 	if (zmgr->loadtasks == NULL)
   16981 		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
   16982 					     ntasks, 2, &pool);
   16983 	else
   16984 		result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
   16985 
   16986 	if (result == ISC_R_SUCCESS)
   16987 		zmgr->loadtasks = pool;
   16988 
   16989 	/*
   16990 	 * We always set all tasks in the zone-load task pool to
   16991 	 * privileged.  This prevents other tasks in the system from
   16992 	 * running while the server task manager is in privileged
   16993 	 * mode.
   16994 	 *
   16995 	 * NOTE: If we start using task privileges for any other
   16996 	 * part of the system than zone tasks, then this will need to be
   16997 	 * revisted.  In that case we'd want to turn on privileges for
   16998 	 * zone tasks only when we were loading, and turn them off the
   16999 	 * rest of the time.  For now, however, it's okay to just
   17000 	 * set it and forget it.
   17001 	 */
   17002 	isc_taskpool_setprivilege(zmgr->loadtasks, true);
   17003 
   17004 	/* Create or resize the zone memory context pool. */
   17005 	if (zmgr->mctxpool == NULL)
   17006 		result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
   17007 					 mctxinit, NULL, &mctxpool);
   17008 	else
   17009 		result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
   17010 
   17011 	if (result == ISC_R_SUCCESS)
   17012 		zmgr->mctxpool = mctxpool;
   17013 
   17014 	return (result);
   17015 }
   17016 
   17017 static void
   17018 zonemgr_free(dns_zonemgr_t *zmgr) {
   17019 	isc_mem_t *mctx;
   17020 
   17021 	INSIST(zmgr->refs == 0);
   17022 	INSIST(ISC_LIST_EMPTY(zmgr->zones));
   17023 
   17024 	zmgr->magic = 0;
   17025 
   17026 	isc_mutex_destroy(&zmgr->iolock);
   17027 	isc_ratelimiter_detach(&zmgr->notifyrl);
   17028 	isc_ratelimiter_detach(&zmgr->refreshrl);
   17029 	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
   17030 	isc_ratelimiter_detach(&zmgr->startuprefreshrl);
   17031 
   17032 	isc_rwlock_destroy(&zmgr->urlock);
   17033 	isc_rwlock_destroy(&zmgr->rwlock);
   17034 	mctx = zmgr->mctx;
   17035 	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
   17036 	isc_mem_detach(&mctx);
   17037 }
   17038 
   17039 void
   17040 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
   17041 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17042 
   17043 	zmgr->transfersin = value;
   17044 }
   17045 
   17046 uint32_t
   17047 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
   17048 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17049 
   17050 	return (zmgr->transfersin);
   17051 }
   17052 
   17053 void
   17054 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
   17055 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17056 
   17057 	zmgr->transfersperns = value;
   17058 }
   17059 
   17060 uint32_t
   17061 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
   17062 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17063 
   17064 	return (zmgr->transfersperns);
   17065 }
   17066 
   17067 /*
   17068  * Try to start a new incoming zone transfer to fill a quota
   17069  * slot that was just vacated.
   17070  *
   17071  * Requires:
   17072  *	The zone manager is locked by the caller.
   17073  */
   17074 static void
   17075 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
   17076 	dns_zone_t *zone;
   17077 	dns_zone_t *next;
   17078 
   17079 	for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
   17080 	     zone != NULL;
   17081 	     zone = next)
   17082 	{
   17083 		isc_result_t result;
   17084 		next = ISC_LIST_NEXT(zone, statelink);
   17085 		result = zmgr_start_xfrin_ifquota(zmgr, zone);
   17086 		if (result == ISC_R_SUCCESS) {
   17087 			if (multi)
   17088 				continue;
   17089 			/*
   17090 			 * We successfully filled the slot.  We're done.
   17091 			 */
   17092 			break;
   17093 		} else if (result == ISC_R_QUOTA) {
   17094 			/*
   17095 			 * Not enough quota.  This is probably the per-server
   17096 			 * quota, because we usually get called when a unit of
   17097 			 * global quota has just been freed.  Try the next
   17098 			 * zone, it may succeed if it uses another master.
   17099 			 */
   17100 			continue;
   17101 		} else {
   17102 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   17103 				     "starting zone transfer: %s",
   17104 				     isc_result_totext(result));
   17105 			break;
   17106 		}
   17107 	}
   17108 }
   17109 
   17110 /*
   17111  * Try to start an incoming zone transfer for 'zone', quota permitting.
   17112  *
   17113  * Requires:
   17114  *	The zone manager is locked by the caller.
   17115  *
   17116  * Returns:
   17117  *	ISC_R_SUCCESS	There was enough quota and we attempted to
   17118  *			start a transfer.  zone_xfrdone() has been or will
   17119  *			be called.
   17120  *	ISC_R_QUOTA	Not enough quota.
   17121  *	Others		Failure.
   17122  */
   17123 static isc_result_t
   17124 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
   17125 	dns_peer_t *peer = NULL;
   17126 	isc_netaddr_t masterip;
   17127 	uint32_t nxfrsin, nxfrsperns;
   17128 	dns_zone_t *x;
   17129 	uint32_t maxtransfersin, maxtransfersperns;
   17130 	isc_event_t *e;
   17131 
   17132 	/*
   17133 	 * If we are exiting just pretend we got quota so the zone will
   17134 	 * be cleaned up in the zone's task context.
   17135 	 */
   17136 	LOCK_ZONE(zone);
   17137 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   17138 		UNLOCK_ZONE(zone);
   17139 		goto gotquota;
   17140 	}
   17141 
   17142 	/*
   17143 	 * Find any configured information about the server we'd
   17144 	 * like to transfer this zone from.
   17145 	 */
   17146 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
   17147 	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
   17148 	UNLOCK_ZONE(zone);
   17149 
   17150 	/*
   17151 	 * Determine the total maximum number of simultaneous
   17152 	 * transfers allowed, and the maximum for this specific
   17153 	 * master.
   17154 	 */
   17155 	maxtransfersin = zmgr->transfersin;
   17156 	maxtransfersperns = zmgr->transfersperns;
   17157 	if (peer != NULL)
   17158 		(void)dns_peer_gettransfers(peer, &maxtransfersperns);
   17159 
   17160 	/*
   17161 	 * Count the total number of transfers that are in progress,
   17162 	 * and the number of transfers in progress from this master.
   17163 	 * We linearly scan a list of all transfers; if this turns
   17164 	 * out to be too slow, we could hash on the master address.
   17165 	 */
   17166 	nxfrsin = nxfrsperns = 0;
   17167 	for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
   17168 	     x != NULL;
   17169 	     x = ISC_LIST_NEXT(x, statelink))
   17170 	{
   17171 		isc_netaddr_t xip;
   17172 
   17173 		LOCK_ZONE(x);
   17174 		isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
   17175 		UNLOCK_ZONE(x);
   17176 
   17177 		nxfrsin++;
   17178 		if (isc_netaddr_equal(&xip, &masterip))
   17179 			nxfrsperns++;
   17180 	}
   17181 
   17182 	/* Enforce quota. */
   17183 	if (nxfrsin >= maxtransfersin)
   17184 		return (ISC_R_QUOTA);
   17185 
   17186 	if (nxfrsperns >= maxtransfersperns)
   17187 		return (ISC_R_QUOTA);
   17188 
   17189  gotquota:
   17190 	/*
   17191 	 * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
   17192 	 * list and send it an event to let it start the actual transfer in the
   17193 	 * context of its own task.
   17194 	 */
   17195 	e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
   17196 			       got_transfer_quota, zone, sizeof(isc_event_t));
   17197 	if (e == NULL)
   17198 		return (ISC_R_NOMEMORY);
   17199 
   17200 	LOCK_ZONE(zone);
   17201 	INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
   17202 	ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
   17203 	ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
   17204 	zone->statelist = &zmgr->xfrin_in_progress;
   17205 	isc_task_send(zone->task, &e);
   17206 	dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
   17207 	UNLOCK_ZONE(zone);
   17208 
   17209 	return (ISC_R_SUCCESS);
   17210 }
   17211 
   17212 void
   17213 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, uint32_t iolimit) {
   17214 
   17215 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17216 	REQUIRE(iolimit > 0);
   17217 
   17218 	zmgr->iolimit = iolimit;
   17219 }
   17220 
   17221 uint32_t
   17222 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
   17223 
   17224 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17225 
   17226 	return (zmgr->iolimit);
   17227 }
   17228 
   17229 /*
   17230  * Get permission to request a file handle from the OS.
   17231  * An event will be sent to action when one is available.
   17232  * There are two queues available (high and low), the high
   17233  * queue will be serviced before the low one.
   17234  *
   17235  * zonemgr_putio() must be called after the event is delivered to
   17236  * 'action'.
   17237  */
   17238 
   17239 static isc_result_t
   17240 zonemgr_getio(dns_zonemgr_t *zmgr, bool high,
   17241 	      isc_task_t *task, isc_taskaction_t action, void *arg,
   17242 	      dns_io_t **iop)
   17243 {
   17244 	dns_io_t *io;
   17245 	bool queue;
   17246 
   17247 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17248 	REQUIRE(iop != NULL && *iop == NULL);
   17249 
   17250 	io = isc_mem_get(zmgr->mctx, sizeof(*io));
   17251 	if (io == NULL)
   17252 		return (ISC_R_NOMEMORY);
   17253 
   17254 	io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
   17255 				       action, arg, sizeof(*io->event));
   17256 	if (io->event == NULL) {
   17257 		isc_mem_put(zmgr->mctx, io, sizeof(*io));
   17258 		return (ISC_R_NOMEMORY);
   17259 	}
   17260 
   17261 	io->zmgr = zmgr;
   17262 	io->high = high;
   17263 	io->task = NULL;
   17264 	isc_task_attach(task, &io->task);
   17265 	ISC_LINK_INIT(io, link);
   17266 	io->magic = IO_MAGIC;
   17267 
   17268 	LOCK(&zmgr->iolock);
   17269 	zmgr->ioactive++;
   17270 	queue = (zmgr->ioactive > zmgr->iolimit);
   17271 	if (queue) {
   17272 		if (io->high)
   17273 			ISC_LIST_APPEND(zmgr->high, io, link);
   17274 		else
   17275 			ISC_LIST_APPEND(zmgr->low, io, link);
   17276 	}
   17277 	UNLOCK(&zmgr->iolock);
   17278 	*iop = io;
   17279 
   17280 	if (!queue)
   17281 		isc_task_send(io->task, &io->event);
   17282 	return (ISC_R_SUCCESS);
   17283 }
   17284 
   17285 static void
   17286 zonemgr_putio(dns_io_t **iop) {
   17287 	dns_io_t *io;
   17288 	dns_io_t *next;
   17289 	dns_zonemgr_t *zmgr;
   17290 
   17291 	REQUIRE(iop != NULL);
   17292 	io = *iop;
   17293 	REQUIRE(DNS_IO_VALID(io));
   17294 
   17295 	*iop = NULL;
   17296 
   17297 	INSIST(!ISC_LINK_LINKED(io, link));
   17298 	INSIST(io->event == NULL);
   17299 
   17300 	zmgr = io->zmgr;
   17301 	isc_task_detach(&io->task);
   17302 	io->magic = 0;
   17303 	isc_mem_put(zmgr->mctx, io, sizeof(*io));
   17304 
   17305 	LOCK(&zmgr->iolock);
   17306 	INSIST(zmgr->ioactive > 0);
   17307 	zmgr->ioactive--;
   17308 	next = HEAD(zmgr->high);
   17309 	if (next == NULL)
   17310 		next = HEAD(zmgr->low);
   17311 	if (next != NULL) {
   17312 		if (next->high)
   17313 			ISC_LIST_UNLINK(zmgr->high, next, link);
   17314 		else
   17315 			ISC_LIST_UNLINK(zmgr->low, next, link);
   17316 		INSIST(next->event != NULL);
   17317 	}
   17318 	UNLOCK(&zmgr->iolock);
   17319 	if (next != NULL)
   17320 		isc_task_send(next->task, &next->event);
   17321 }
   17322 
   17323 static void
   17324 zonemgr_cancelio(dns_io_t *io) {
   17325 	bool send_event = false;
   17326 
   17327 	REQUIRE(DNS_IO_VALID(io));
   17328 
   17329 	/*
   17330 	 * If we are queued to be run then dequeue.
   17331 	 */
   17332 	LOCK(&io->zmgr->iolock);
   17333 	if (ISC_LINK_LINKED(io, link)) {
   17334 		if (io->high)
   17335 			ISC_LIST_UNLINK(io->zmgr->high, io, link);
   17336 		else
   17337 			ISC_LIST_UNLINK(io->zmgr->low, io, link);
   17338 
   17339 		send_event = true;
   17340 		INSIST(io->event != NULL);
   17341 	}
   17342 	UNLOCK(&io->zmgr->iolock);
   17343 	if (send_event) {
   17344 		io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
   17345 		isc_task_send(io->task, &io->event);
   17346 	}
   17347 }
   17348 
   17349 static void
   17350 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
   17351 	char *buf;
   17352 	int buflen;
   17353 	isc_result_t result;
   17354 
   17355 	buflen = strlen(path) + strlen(templat) + 2;
   17356 
   17357 	buf = isc_mem_get(zone->mctx, buflen);
   17358 	if (buf == NULL)
   17359 		return;
   17360 
   17361 	result = isc_file_template(path, templat, buf, buflen);
   17362 	if (result != ISC_R_SUCCESS)
   17363 		goto cleanup;
   17364 
   17365 	result = isc_file_renameunique(path, buf);
   17366 	if (result != ISC_R_SUCCESS)
   17367 		goto cleanup;
   17368 
   17369 	dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
   17370 		     "renaming file to '%s' for failure analysis and "
   17371 		     "retransferring.", path, buf);
   17372 
   17373  cleanup:
   17374 	isc_mem_put(zone->mctx, buf, buflen);
   17375 }
   17376 
   17377 static void
   17378 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
   17379 	isc_interval_t interval;
   17380 	uint32_t s, ns;
   17381 	uint32_t pertic;
   17382 	isc_result_t result;
   17383 
   17384 	if (value == 0)
   17385 		value = 1;
   17386 
   17387 	if (value == 1) {
   17388 		s = 1;
   17389 		ns = 0;
   17390 		pertic = 1;
   17391 	} else if (value <= 10) {
   17392 		s = 0;
   17393 		ns = 1000000000 / value;
   17394 		pertic = 1;
   17395 	} else {
   17396 		s = 0;
   17397 		ns = (1000000000 / value) * 10;
   17398 		pertic = 10;
   17399 	}
   17400 
   17401 	isc_interval_set(&interval, s, ns);
   17402 
   17403 	result = isc_ratelimiter_setinterval(rl, &interval);
   17404 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17405 	isc_ratelimiter_setpertic(rl, pertic);
   17406 
   17407 	*rate = value;
   17408 }
   17409 
   17410 void
   17411 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
   17412 
   17413 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17414 
   17415 	setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
   17416 }
   17417 
   17418 void
   17419 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
   17420 
   17421 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17422 
   17423 	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
   17424 }
   17425 
   17426 void
   17427 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
   17428 
   17429 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17430 
   17431 	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
   17432 	/* XXXMPA seperate out once we have the code to support this. */
   17433 	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
   17434 }
   17435 
   17436 unsigned int
   17437 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
   17438 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17439 
   17440 	return (zmgr->notifyrate);
   17441 }
   17442 
   17443 unsigned int
   17444 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
   17445 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17446 
   17447 	return (zmgr->startupnotifyrate);
   17448 }
   17449 
   17450 unsigned int
   17451 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
   17452 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17453 
   17454 	return (zmgr->serialqueryrate);
   17455 }
   17456 
   17457 bool
   17458 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
   17459 			isc_sockaddr_t *local, isc_time_t *now)
   17460 {
   17461 	unsigned int i;
   17462 	isc_rwlocktype_t locktype;
   17463 	isc_result_t result;
   17464 	uint32_t seconds = isc_time_seconds(now);
   17465 	uint32_t count = 0;
   17466 
   17467 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17468 
   17469 	locktype = isc_rwlocktype_read;
   17470 	RWLOCK(&zmgr->urlock, locktype);
   17471 	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
   17472 		if (zmgr->unreachable[i].expire >= seconds &&
   17473 		    isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
   17474 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
   17475 			result = isc_rwlock_tryupgrade(&zmgr->urlock);
   17476 			if (result == ISC_R_SUCCESS) {
   17477 				locktype = isc_rwlocktype_write;
   17478 				zmgr->unreachable[i].last = seconds;
   17479 				count = zmgr->unreachable[i].count;
   17480 			}
   17481 			break;
   17482 		}
   17483 	}
   17484 	RWUNLOCK(&zmgr->urlock, locktype);
   17485 	return (i < UNREACH_CHACHE_SIZE && count > 1U);
   17486 }
   17487 
   17488 void
   17489 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
   17490 			   isc_sockaddr_t *local)
   17491 {
   17492 	unsigned int i;
   17493 	isc_rwlocktype_t locktype;
   17494 	isc_result_t result;
   17495 
   17496 	char master[ISC_SOCKADDR_FORMATSIZE];
   17497 	char source[ISC_SOCKADDR_FORMATSIZE];
   17498 
   17499 	isc_sockaddr_format(remote, master, sizeof(master));
   17500 	isc_sockaddr_format(local, source, sizeof(source));
   17501 
   17502 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17503 
   17504 	locktype = isc_rwlocktype_read;
   17505 	RWLOCK(&zmgr->urlock, locktype);
   17506 	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
   17507 		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
   17508 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
   17509 			if (zmgr->unreachable[i].expire == 0)
   17510 				break;
   17511 			result = isc_rwlock_tryupgrade(&zmgr->urlock);
   17512 			if (result == ISC_R_SUCCESS) {
   17513 				locktype = isc_rwlocktype_write;
   17514 				zmgr->unreachable[i].expire = 0;
   17515 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   17516 					      DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
   17517 					      "master %s (source %s) deleted "
   17518 					      "from unreachable cache",
   17519 					      master, source);
   17520 			}
   17521 			break;
   17522 		}
   17523 	}
   17524 	RWUNLOCK(&zmgr->urlock, locktype);
   17525 }
   17526 
   17527 void
   17528 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
   17529 			   isc_sockaddr_t *local, isc_time_t *now)
   17530 {
   17531 	uint32_t seconds = isc_time_seconds(now);
   17532 	uint32_t last = seconds;
   17533 	unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
   17534 
   17535 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17536 
   17537 	RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
   17538 	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
   17539 		/* Existing entry? */
   17540 		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
   17541 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
   17542 			break;
   17543 		/* Empty slot? */
   17544 		if (zmgr->unreachable[i].expire < seconds)
   17545 			slot = i;
   17546 		/* Least recently used slot? */
   17547 		if (zmgr->unreachable[i].last < last) {
   17548 			last = zmgr->unreachable[i].last;
   17549 			oldest = i;
   17550 		}
   17551 	}
   17552 	if (i < UNREACH_CHACHE_SIZE) {
   17553 		/*
   17554 		 * Found a existing entry.  Update the expire timer and
   17555 		 * last usage timestamps.
   17556 		 */
   17557 		zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
   17558 		zmgr->unreachable[i].last = seconds;
   17559 		if (zmgr->unreachable[i].expire < seconds)
   17560 			zmgr->unreachable[i].count = 1;
   17561 		else
   17562 			zmgr->unreachable[i].count++;
   17563 	} else if (slot != UNREACH_CHACHE_SIZE) {
   17564 		/*
   17565 		 * Found a empty slot. Add a new entry to the cache.
   17566 		 */
   17567 		zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
   17568 		zmgr->unreachable[slot].last = seconds;
   17569 		zmgr->unreachable[slot].remote = *remote;
   17570 		zmgr->unreachable[slot].local = *local;
   17571 		zmgr->unreachable[slot].count = 1;
   17572 	} else {
   17573 		/*
   17574 		 * Replace the least recently used entry in the cache.
   17575 		 */
   17576 		zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
   17577 		zmgr->unreachable[oldest].last = seconds;
   17578 		zmgr->unreachable[oldest].remote = *remote;
   17579 		zmgr->unreachable[oldest].local = *local;
   17580 		zmgr->unreachable[oldest].count = 1;
   17581 	}
   17582 	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
   17583 }
   17584 
   17585 void
   17586 dns_zone_forcereload(dns_zone_t *zone) {
   17587 	REQUIRE(DNS_ZONE_VALID(zone));
   17588 
   17589 	if (zone->type == dns_zone_master ||
   17590 	    (zone->type == dns_zone_redirect && zone->masters == NULL))
   17591 		return;
   17592 
   17593 	LOCK_ZONE(zone);
   17594 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
   17595 	UNLOCK_ZONE(zone);
   17596 	dns_zone_refresh(zone);
   17597 }
   17598 
   17599 bool
   17600 dns_zone_isforced(dns_zone_t *zone) {
   17601 	REQUIRE(DNS_ZONE_VALID(zone));
   17602 
   17603 	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
   17604 }
   17605 
   17606 isc_result_t
   17607 dns_zone_setstatistics(dns_zone_t *zone, bool on) {
   17608 	/*
   17609 	 * This function is obsoleted.
   17610 	 */
   17611 	UNUSED(zone);
   17612 	UNUSED(on);
   17613 	return (ISC_R_NOTIMPLEMENTED);
   17614 }
   17615 
   17616 uint64_t *
   17617 dns_zone_getstatscounters(dns_zone_t *zone) {
   17618 	/*
   17619 	 * This function is obsoleted.
   17620 	 */
   17621 	UNUSED(zone);
   17622 	return (NULL);
   17623 }
   17624 
   17625 void
   17626 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
   17627 	REQUIRE(DNS_ZONE_VALID(zone));
   17628 	REQUIRE(zone->stats == NULL);
   17629 
   17630 	LOCK_ZONE(zone);
   17631 	zone->stats = NULL;
   17632 	isc_stats_attach(stats, &zone->stats);
   17633 	UNLOCK_ZONE(zone);
   17634 }
   17635 
   17636 void
   17637 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
   17638 
   17639 	REQUIRE(DNS_ZONE_VALID(zone));
   17640 
   17641 	LOCK_ZONE(zone);
   17642 	if (zone->requeststats_on && stats == NULL)
   17643 		zone->requeststats_on = false;
   17644 	else if (!zone->requeststats_on && stats != NULL) {
   17645 		if (zone->requeststats == NULL) {
   17646 			isc_stats_attach(stats, &zone->requeststats);
   17647 			zone->requeststats_on = true;
   17648 		}
   17649 	}
   17650 	UNLOCK_ZONE(zone);
   17651 }
   17652 
   17653 void
   17654 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
   17655 
   17656 	REQUIRE(DNS_ZONE_VALID(zone));
   17657 
   17658 	LOCK_ZONE(zone);
   17659 	if (zone->requeststats_on && stats != NULL) {
   17660 		if (zone->rcvquerystats == NULL) {
   17661 			dns_stats_attach(stats, &zone->rcvquerystats);
   17662 			zone->requeststats_on = true;
   17663 		}
   17664 	}
   17665 	UNLOCK_ZONE(zone);
   17666 }
   17667 
   17668 void
   17669 dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
   17670 	REQUIRE(DNS_ZONE_VALID(zone));
   17671 
   17672 	LOCK_ZONE(zone);
   17673 	if (stats != NULL && zone->dnssecsignstats == NULL) {
   17674 		dns_stats_attach(stats, &zone->dnssecsignstats);
   17675 	}
   17676 	UNLOCK_ZONE(zone);
   17677 }
   17678 
   17679 void
   17680 dns_zone_setdnssecrefreshstats(dns_zone_t *zone, dns_stats_t *stats) {
   17681 	REQUIRE(DNS_ZONE_VALID(zone));
   17682 
   17683 	LOCK_ZONE(zone);
   17684 	if (stats != NULL && zone->dnssecrefreshstats == NULL) {
   17685 		dns_stats_attach(stats, &zone->dnssecrefreshstats);
   17686 	}
   17687 	UNLOCK_ZONE(zone);
   17688 }
   17689 
   17690 dns_stats_t*
   17691 dns_zone_getdnssecsignstats(dns_zone_t *zone) {
   17692 	REQUIRE(DNS_ZONE_VALID(zone));
   17693 
   17694 	return (zone->dnssecsignstats);
   17695 }
   17696 
   17697 dns_stats_t*
   17698 dns_zone_getdnssecrefreshstats(dns_zone_t *zone) {
   17699 	REQUIRE(DNS_ZONE_VALID(zone));
   17700 
   17701 	return (zone->dnssecrefreshstats);
   17702 }
   17703 
   17704 isc_stats_t *
   17705 dns_zone_getrequeststats(dns_zone_t *zone) {
   17706 	/*
   17707 	 * We don't lock zone for efficiency reason.  This is not catastrophic
   17708 	 * because requeststats must always be valid when requeststats_on is
   17709 	 * true.
   17710 	 * Some counters may be incremented while requeststats_on is becoming
   17711 	 * false, or some cannot be incremented just after the statistics are
   17712 	 * installed, but it shouldn't matter much in practice.
   17713 	 */
   17714 	if (zone->requeststats_on)
   17715 		return (zone->requeststats);
   17716 	else
   17717 		return (NULL);
   17718 }
   17719 
   17720 /*
   17721  * Return the received query stats bucket
   17722  * see note from dns_zone_getrequeststats()
   17723  */
   17724 dns_stats_t *
   17725 dns_zone_getrcvquerystats(dns_zone_t *zone) {
   17726 	if (zone->requeststats_on)
   17727 		return (zone->rcvquerystats);
   17728 	else
   17729 		return (NULL);
   17730 }
   17731 
   17732 void
   17733 dns_zone_dialup(dns_zone_t *zone) {
   17734 
   17735 	REQUIRE(DNS_ZONE_VALID(zone));
   17736 
   17737 	zone_debuglog(zone, "dns_zone_dialup", 3,
   17738 		      "notify = %d, refresh = %d",
   17739 		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
   17740 		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
   17741 
   17742 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
   17743 		dns_zone_notify(zone);
   17744 	if (zone->type != dns_zone_master && zone->masters != NULL &&
   17745 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
   17746 		dns_zone_refresh(zone);
   17747 }
   17748 
   17749 void
   17750 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
   17751 	REQUIRE(DNS_ZONE_VALID(zone));
   17752 
   17753 	LOCK_ZONE(zone);
   17754 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
   17755 			 DNS_ZONEFLG_DIALREFRESH |
   17756 			 DNS_ZONEFLG_NOREFRESH);
   17757 	switch (dialup) {
   17758 	case dns_dialuptype_no:
   17759 		break;
   17760 	case dns_dialuptype_yes:
   17761 		DNS_ZONE_SETFLAG(zone,	(DNS_ZONEFLG_DIALNOTIFY |
   17762 				 DNS_ZONEFLG_DIALREFRESH |
   17763 				 DNS_ZONEFLG_NOREFRESH));
   17764 		break;
   17765 	case dns_dialuptype_notify:
   17766 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
   17767 		break;
   17768 	case dns_dialuptype_notifypassive:
   17769 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
   17770 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
   17771 		break;
   17772 	case dns_dialuptype_refresh:
   17773 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
   17774 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
   17775 		break;
   17776 	case dns_dialuptype_passive:
   17777 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
   17778 		break;
   17779 	default:
   17780 		INSIST(0);
   17781 		ISC_UNREACHABLE();
   17782 	}
   17783 	UNLOCK_ZONE(zone);
   17784 }
   17785 
   17786 isc_result_t
   17787 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
   17788 	isc_result_t result = ISC_R_SUCCESS;
   17789 
   17790 	REQUIRE(DNS_ZONE_VALID(zone));
   17791 
   17792 	LOCK_ZONE(zone);
   17793 	result = dns_zone_setstring(zone, &zone->keydirectory, directory);
   17794 	UNLOCK_ZONE(zone);
   17795 
   17796 	return (result);
   17797 }
   17798 
   17799 const char *
   17800 dns_zone_getkeydirectory(dns_zone_t *zone) {
   17801 	REQUIRE(DNS_ZONE_VALID(zone));
   17802 
   17803 	return (zone->keydirectory);
   17804 }
   17805 
   17806 unsigned int
   17807 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
   17808 	dns_zone_t *zone;
   17809 	unsigned int count = 0;
   17810 
   17811 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17812 
   17813 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   17814 	switch (state) {
   17815 	case DNS_ZONESTATE_XFERRUNNING:
   17816 		for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
   17817 		     zone != NULL;
   17818 		     zone = ISC_LIST_NEXT(zone, statelink))
   17819 			count++;
   17820 		break;
   17821 	case DNS_ZONESTATE_XFERDEFERRED:
   17822 		for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
   17823 		     zone != NULL;
   17824 		     zone = ISC_LIST_NEXT(zone, statelink))
   17825 			count++;
   17826 		break;
   17827 	case DNS_ZONESTATE_SOAQUERY:
   17828 		for (zone = ISC_LIST_HEAD(zmgr->zones);
   17829 		     zone != NULL;
   17830 		     zone = ISC_LIST_NEXT(zone, link))
   17831 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
   17832 				count++;
   17833 		break;
   17834 	case DNS_ZONESTATE_ANY:
   17835 		for (zone = ISC_LIST_HEAD(zmgr->zones);
   17836 		     zone != NULL;
   17837 		     zone = ISC_LIST_NEXT(zone, link)) {
   17838 			dns_view_t *view = zone->view;
   17839 			if (view != NULL && strcmp(view->name, "_bind") == 0)
   17840 				continue;
   17841 			count++;
   17842 		}
   17843 		break;
   17844 	case DNS_ZONESTATE_AUTOMATIC:
   17845 		for (zone = ISC_LIST_HEAD(zmgr->zones);
   17846 		     zone != NULL;
   17847 		     zone = ISC_LIST_NEXT(zone, link)) {
   17848 			dns_view_t *view = zone->view;
   17849 			if (view != NULL && strcmp(view->name, "_bind") == 0)
   17850 				continue;
   17851 			if (zone->automatic)
   17852 				count++;
   17853 		}
   17854 		break;
   17855 	default:
   17856 		INSIST(0);
   17857 		ISC_UNREACHABLE();
   17858 	}
   17859 
   17860 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   17861 
   17862 	return (count);
   17863 }
   17864 
   17865 isc_result_t
   17866 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
   17867 		    dns_rdata_t *rdata)
   17868 {
   17869 	bool ok = true;
   17870 	bool fail = false;
   17871 	char namebuf[DNS_NAME_FORMATSIZE];
   17872 	char namebuf2[DNS_NAME_FORMATSIZE];
   17873 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
   17874 	int level = ISC_LOG_WARNING;
   17875 	dns_name_t bad;
   17876 
   17877 	REQUIRE(DNS_ZONE_VALID(zone));
   17878 
   17879 	if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
   17880 	    rdata->type != dns_rdatatype_nsec3)
   17881 		return (ISC_R_SUCCESS);
   17882 
   17883 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
   17884 	    rdata->type == dns_rdatatype_nsec3) {
   17885 		level = ISC_LOG_ERROR;
   17886 		fail = true;
   17887 	}
   17888 
   17889 	ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
   17890 	if (!ok) {
   17891 		dns_name_format(name, namebuf, sizeof(namebuf));
   17892 		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
   17893 		dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
   17894 			     dns_result_totext(DNS_R_BADOWNERNAME));
   17895 		if (fail)
   17896 			return (DNS_R_BADOWNERNAME);
   17897 	}
   17898 
   17899 	dns_name_init(&bad, NULL);
   17900 	ok = dns_rdata_checknames(rdata, name, &bad);
   17901 	if (!ok) {
   17902 		dns_name_format(name, namebuf, sizeof(namebuf));
   17903 		dns_name_format(&bad, namebuf2, sizeof(namebuf2));
   17904 		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
   17905 		dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
   17906 			     namebuf2, dns_result_totext(DNS_R_BADNAME));
   17907 		if (fail)
   17908 			return (DNS_R_BADNAME);
   17909 	}
   17910 
   17911 	return (ISC_R_SUCCESS);
   17912 }
   17913 
   17914 void
   17915 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
   17916 	REQUIRE(DNS_ZONE_VALID(zone));
   17917 	zone->checkmx = checkmx;
   17918 }
   17919 
   17920 void
   17921 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
   17922 	REQUIRE(DNS_ZONE_VALID(zone));
   17923 	zone->checksrv = checksrv;
   17924 }
   17925 
   17926 void
   17927 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
   17928 	REQUIRE(DNS_ZONE_VALID(zone));
   17929 	zone->checkns = checkns;
   17930 }
   17931 
   17932 void
   17933 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
   17934 	REQUIRE(DNS_ZONE_VALID(zone));
   17935 
   17936 	LOCK_ZONE(zone);
   17937 	zone->isself = isself;
   17938 	zone->isselfarg = arg;
   17939 	UNLOCK_ZONE(zone);
   17940 }
   17941 
   17942 void
   17943 dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
   17944 	REQUIRE(DNS_ZONE_VALID(zone));
   17945 
   17946 	LOCK_ZONE(zone);
   17947 	zone->notifydelay = delay;
   17948 	UNLOCK_ZONE(zone);
   17949 }
   17950 
   17951 uint32_t
   17952 dns_zone_getnotifydelay(dns_zone_t *zone) {
   17953 	REQUIRE(DNS_ZONE_VALID(zone));
   17954 
   17955 	return (zone->notifydelay);
   17956 }
   17957 
   17958 isc_result_t
   17959 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
   17960 		     uint16_t keyid, bool deleteit)
   17961 {
   17962 	isc_result_t result;
   17963 	REQUIRE(DNS_ZONE_VALID(zone));
   17964 
   17965 	dnssec_log(zone, ISC_LOG_NOTICE,
   17966 		   "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
   17967 		   algorithm, keyid);
   17968 	LOCK_ZONE(zone);
   17969 	result = zone_signwithkey(zone, algorithm, keyid, deleteit);
   17970 	UNLOCK_ZONE(zone);
   17971 
   17972 	return (result);
   17973 }
   17974 
   17975 /*
   17976  * Called when a dynamic update for an NSEC3PARAM record is received.
   17977  *
   17978  * If set, transform the NSEC3 salt into human-readable form so that it can be
   17979  * logged.  Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
   17980  */
   17981 isc_result_t
   17982 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
   17983 	isc_result_t result;
   17984 	char salt[255*2+1];
   17985 
   17986 	REQUIRE(DNS_ZONE_VALID(zone));
   17987 
   17988 	result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
   17989 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17990 	dnssec_log(zone, ISC_LOG_NOTICE,
   17991 		   "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
   17992 		   nsec3param->hash, nsec3param->iterations, salt);
   17993 	LOCK_ZONE(zone);
   17994 	result = zone_addnsec3chain(zone, nsec3param);
   17995 	UNLOCK_ZONE(zone);
   17996 
   17997 	return (result);
   17998 }
   17999 
   18000 void
   18001 dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
   18002 	REQUIRE(DNS_ZONE_VALID(zone));
   18003 
   18004 	if (nodes == 0)
   18005 		nodes = 1;
   18006 	zone->nodes = nodes;
   18007 }
   18008 
   18009 void
   18010 dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
   18011 	REQUIRE(DNS_ZONE_VALID(zone));
   18012 
   18013 	/*
   18014 	 * We treat signatures as a signed value so explicitly
   18015 	 * limit its range here.
   18016 	 */
   18017 	if (signatures > INT32_MAX)
   18018 		signatures = INT32_MAX;
   18019 	else if (signatures == 0)
   18020 		signatures = 1;
   18021 	zone->signatures = signatures;
   18022 }
   18023 
   18024 uint32_t
   18025 dns_zone_getsignatures(dns_zone_t *zone) {
   18026 	REQUIRE(DNS_ZONE_VALID(zone));
   18027 	return (zone->signatures);
   18028 }
   18029 
   18030 void
   18031 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
   18032 	REQUIRE(DNS_ZONE_VALID(zone));
   18033 	zone->privatetype = type;
   18034 }
   18035 
   18036 dns_rdatatype_t
   18037 dns_zone_getprivatetype(dns_zone_t *zone) {
   18038 	REQUIRE(DNS_ZONE_VALID(zone));
   18039 	return (zone->privatetype);
   18040 }
   18041 
   18042 static isc_result_t
   18043 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
   18044 		 bool deleteit)
   18045 {
   18046 	dns_signing_t *signing;
   18047 	dns_signing_t *current;
   18048 	isc_result_t result = ISC_R_SUCCESS;
   18049 	isc_time_t now;
   18050 	dns_db_t *db = NULL;
   18051 
   18052 	signing = isc_mem_get(zone->mctx, sizeof *signing);
   18053 	if (signing == NULL)
   18054 		return (ISC_R_NOMEMORY);
   18055 
   18056 	signing->magic = 0;
   18057 	signing->db  = NULL;
   18058 	signing->dbiterator = NULL;
   18059 	signing->algorithm = algorithm;
   18060 	signing->keyid = keyid;
   18061 	signing->deleteit = deleteit;
   18062 	signing->done = false;
   18063 
   18064 	TIME_NOW(&now);
   18065 
   18066 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   18067 	if (zone->db != NULL)
   18068 		dns_db_attach(zone->db, &db);
   18069 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   18070 
   18071 	if (db == NULL) {
   18072 		result = ISC_R_NOTFOUND;
   18073 		goto cleanup;
   18074 	}
   18075 
   18076 	dns_db_attach(db, &signing->db);
   18077 
   18078 	for (current = ISC_LIST_HEAD(zone->signing);
   18079 	     current != NULL;
   18080 	     current = ISC_LIST_NEXT(current, link)) {
   18081 		if (current->db == signing->db &&
   18082 		    current->algorithm == signing->algorithm &&
   18083 		    current->keyid == signing->keyid) {
   18084 			if (current->deleteit != signing->deleteit)
   18085 				current->done = true;
   18086 			else
   18087 				goto cleanup;
   18088 		}
   18089 	}
   18090 
   18091 	result = dns_db_createiterator(signing->db, 0,
   18092 				       &signing->dbiterator);
   18093 
   18094 	if (result == ISC_R_SUCCESS)
   18095 		result = dns_dbiterator_first(signing->dbiterator);
   18096 	if (result == ISC_R_SUCCESS) {
   18097 		dns_dbiterator_pause(signing->dbiterator);
   18098 		ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
   18099 		signing = NULL;
   18100 		if (isc_time_isepoch(&zone->signingtime)) {
   18101 			zone->signingtime = now;
   18102 			if (zone->task != NULL)
   18103 				zone_settimer(zone, &now);
   18104 		}
   18105 	}
   18106 
   18107  cleanup:
   18108 	if (signing != NULL) {
   18109 		if (signing->db != NULL)
   18110 			dns_db_detach(&signing->db);
   18111 		if (signing->dbiterator != NULL)
   18112 			dns_dbiterator_destroy(&signing->dbiterator);
   18113 		isc_mem_put(zone->mctx, signing, sizeof *signing);
   18114 	}
   18115 	if (db != NULL)
   18116 		dns_db_detach(&db);
   18117 	return (result);
   18118 }
   18119 
   18120 static void
   18121 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
   18122 	dns_dnsseckey_t *key;
   18123 	while (!ISC_LIST_EMPTY(*list)) {
   18124 		key = ISC_LIST_HEAD(*list);
   18125 		ISC_LIST_UNLINK(*list, key, link);
   18126 		dns_dnsseckey_destroy(mctx, &key);
   18127 	}
   18128 }
   18129 
   18130 /* Called once; *timep should be set to the current time. */
   18131 static isc_result_t
   18132 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
   18133 	isc_result_t result;
   18134 	isc_stdtime_t now, then = 0, event;
   18135 	int i;
   18136 
   18137 	now = *timep;
   18138 
   18139 	for (i = 0; i <= DST_MAX_TIMES; i++) {
   18140 		result = dst_key_gettime(key, i, &event);
   18141 		if (result == ISC_R_SUCCESS && event > now &&
   18142 		    (then == 0 || event < then))
   18143 			then = event;
   18144 	}
   18145 
   18146 	if (then != 0) {
   18147 		*timep = then;
   18148 		return (ISC_R_SUCCESS);
   18149 	}
   18150 
   18151 	return (ISC_R_NOTFOUND);
   18152 }
   18153 
   18154 static isc_result_t
   18155 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
   18156 	  const dns_rdata_t *rdata, bool *flag)
   18157 {
   18158 	dns_rdataset_t rdataset;
   18159 	dns_dbnode_t *node = NULL;
   18160 	isc_result_t result;
   18161 
   18162 	dns_rdataset_init(&rdataset);
   18163 	if (rdata->type == dns_rdatatype_nsec3)
   18164 		CHECK(dns_db_findnsec3node(db, name, false, &node));
   18165 	else
   18166 		CHECK(dns_db_findnode(db, name, false, &node));
   18167 	result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
   18168 				     (isc_stdtime_t) 0, &rdataset, NULL);
   18169 	if (result == ISC_R_NOTFOUND) {
   18170 		*flag = false;
   18171 		result = ISC_R_SUCCESS;
   18172 		goto failure;
   18173 	}
   18174 
   18175 	for (result = dns_rdataset_first(&rdataset);
   18176 	     result == ISC_R_SUCCESS;
   18177 	     result = dns_rdataset_next(&rdataset)) {
   18178 		dns_rdata_t myrdata = DNS_RDATA_INIT;
   18179 		dns_rdataset_current(&rdataset, &myrdata);
   18180 		if (!dns_rdata_compare(&myrdata, rdata))
   18181 			break;
   18182 	}
   18183 	dns_rdataset_disassociate(&rdataset);
   18184 	if (result == ISC_R_SUCCESS) {
   18185 		*flag = true;
   18186 	} else if (result == ISC_R_NOMORE) {
   18187 		*flag = false;
   18188 		result = ISC_R_SUCCESS;
   18189 	}
   18190 
   18191  failure:
   18192 	if (node != NULL)
   18193 		dns_db_detachnode(db, &node);
   18194 	return (result);
   18195 }
   18196 
   18197 /*
   18198  * Add records to signal the state of signing or of key removal.
   18199  */
   18200 static isc_result_t
   18201 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
   18202 		    dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all)
   18203 {
   18204 	dns_difftuple_t *tuple, *newtuple = NULL;
   18205 	dns_rdata_dnskey_t dnskey;
   18206 	dns_rdata_t rdata = DNS_RDATA_INIT;
   18207 	bool flag;
   18208 	isc_region_t r;
   18209 	isc_result_t result = ISC_R_SUCCESS;
   18210 	uint16_t keyid;
   18211 	unsigned char buf[5];
   18212 	dns_name_t *name = dns_db_origin(db);
   18213 
   18214 	for (tuple = ISC_LIST_HEAD(diff->tuples);
   18215 	     tuple != NULL;
   18216 	     tuple = ISC_LIST_NEXT(tuple, link)) {
   18217 		if (tuple->rdata.type != dns_rdatatype_dnskey) {
   18218 			continue;
   18219 		}
   18220 
   18221 		result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
   18222 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   18223 		if ((dnskey.flags &
   18224 		     (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
   18225 			 != DNS_KEYOWNER_ZONE)
   18226 		{
   18227 			continue;
   18228 		}
   18229 
   18230 		dns_rdata_toregion(&tuple->rdata, &r);
   18231 
   18232 		keyid = dst_region_computeid(&r);
   18233 
   18234 		buf[0] = dnskey.algorithm;
   18235 		buf[1] = (keyid & 0xff00) >> 8;
   18236 		buf[2] = (keyid & 0xff);
   18237 		buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
   18238 		buf[4] = 0;
   18239 		rdata.data = buf;
   18240 		rdata.length = sizeof(buf);
   18241 		rdata.type = privatetype;
   18242 		rdata.rdclass = tuple->rdata.rdclass;
   18243 
   18244 		if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
   18245 			CHECK(rr_exists(db, ver, name, &rdata, &flag));
   18246 			if (flag) {
   18247 				continue;
   18248 			}
   18249 
   18250 			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
   18251 						   name, 0, &rdata, &newtuple));
   18252 			CHECK(do_one_tuple(&newtuple, db, ver, diff));
   18253 			INSIST(newtuple == NULL);
   18254 		}
   18255 
   18256 		/*
   18257 		 * Remove any record which says this operation has already
   18258 		 * completed.
   18259 		 */
   18260 		buf[4] = 1;
   18261 		CHECK(rr_exists(db, ver, name, &rdata, &flag));
   18262 		if (flag) {
   18263 			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
   18264 						   name, 0, &rdata, &newtuple));
   18265 			CHECK(do_one_tuple(&newtuple, db, ver, diff));
   18266 			INSIST(newtuple == NULL);
   18267 		}
   18268 	}
   18269  failure:
   18270 	return (result);
   18271 }
   18272 
   18273 static isc_result_t
   18274 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   18275 	  isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff)
   18276 {
   18277 	isc_result_t result;
   18278 	isc_stdtime_t inception, soaexpire, keyexpire;
   18279 	bool check_ksk, keyset_kskonly;
   18280 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   18281 	unsigned int nkeys = 0, i;
   18282 	dns_difftuple_t *tuple;
   18283 
   18284 	result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
   18285 				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
   18286 	if (result != ISC_R_SUCCESS) {
   18287 		dnssec_log(zone, ISC_LOG_ERROR,
   18288 			   "sign_apex:dns__zone_findkeys -> %s",
   18289 			   dns_result_totext(result));
   18290 		return (result);
   18291 	}
   18292 
   18293 	inception = now - 3600;	/* Allow for clock skew. */
   18294 	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
   18295 
   18296 	keyexpire = dns_zone_getkeyvalidityinterval(zone);
   18297 	if (keyexpire == 0) {
   18298 		keyexpire = soaexpire - 1;
   18299 	} else {
   18300 		keyexpire += now;
   18301 	}
   18302 
   18303 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
   18304 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
   18305 
   18306 	/*
   18307 	 * See if dns__zone_updatesigs() will update DNSKEY signature and if
   18308 	 * not cause them to sign so that newly activated keys are used.
   18309 	 */
   18310 	for (tuple = ISC_LIST_HEAD(diff->tuples);
   18311 	     tuple != NULL;
   18312 	     tuple = ISC_LIST_NEXT(tuple, link))
   18313 	{
   18314 		if (tuple->rdata.type == dns_rdatatype_dnskey &&
   18315 		    dns_name_equal(&tuple->name, &zone->origin))
   18316 		{
   18317 			break;
   18318 		}
   18319 	}
   18320 
   18321 	if (tuple == NULL) {
   18322 		result = del_sigs(zone, db, ver, &zone->origin,
   18323 				  dns_rdatatype_dnskey, zonediff,
   18324 				  zone_keys, nkeys, now, false);
   18325 		if (result != ISC_R_SUCCESS) {
   18326 			dnssec_log(zone, ISC_LOG_ERROR,
   18327 				   "sign_apex:del_sigs -> %s",
   18328 				   dns_result_totext(result));
   18329 			goto failure;
   18330 		}
   18331 		result = add_sigs(db, ver, &zone->origin, zone,
   18332 				  dns_rdatatype_dnskey, zonediff->diff,
   18333 				  zone_keys, nkeys, zone->mctx, inception,
   18334 				  keyexpire, check_ksk, keyset_kskonly);
   18335 		if (result != ISC_R_SUCCESS) {
   18336 			dnssec_log(zone, ISC_LOG_ERROR,
   18337 				   "sign_apex:add_sigs -> %s",
   18338 				   dns_result_totext(result));
   18339 			goto failure;
   18340 		}
   18341 	}
   18342 
   18343 	result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
   18344 				      inception, soaexpire, keyexpire, now,
   18345 				      check_ksk, keyset_kskonly, zonediff);
   18346 
   18347 	if (result != ISC_R_SUCCESS) {
   18348 		dnssec_log(zone, ISC_LOG_ERROR,
   18349 			   "sign_apex:dns__zone_updatesigs -> %s",
   18350 			   dns_result_totext(result));
   18351 		goto failure;
   18352 	}
   18353 
   18354  failure:
   18355 	for (i = 0; i < nkeys; i++) {
   18356 		dst_key_free(&zone_keys[i]);
   18357 	}
   18358 	return (result);
   18359 }
   18360 
   18361 /*
   18362  * Prevent the zone entering a inconsistent state where
   18363  * NSEC only DNSKEYs are present with NSEC3 chains.
   18364  * See update.c:check_dnssec()
   18365  */
   18366 static bool
   18367 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   18368 	    dns_diff_t *diff)
   18369 {
   18370 	isc_result_t result;
   18371 	dns_difftuple_t *tuple;
   18372 	bool nseconly = false, nsec3 = false;
   18373 	dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
   18374 
   18375 	/* Scan the tuples for an NSEC-only DNSKEY */
   18376 	for (tuple = ISC_LIST_HEAD(diff->tuples);
   18377 	     tuple != NULL;
   18378 	     tuple = ISC_LIST_NEXT(tuple, link))
   18379 	{
   18380 		uint8_t alg;
   18381 		if (tuple->rdata.type != dns_rdatatype_dnskey ||
   18382 		    tuple->op != DNS_DIFFOP_ADD)
   18383 		{
   18384 			continue;
   18385 		}
   18386 
   18387 		alg = tuple->rdata.data[3];
   18388 		if (alg == DST_ALG_RSASHA1) {
   18389 			nseconly = true;
   18390 			break;
   18391 		}
   18392 	}
   18393 
   18394 	/* Check existing DB for NSEC-only DNSKEY */
   18395 	if (!nseconly) {
   18396 		result = dns_nsec_nseconly(db, ver, &nseconly);
   18397 		if (result == ISC_R_NOTFOUND) {
   18398 			result = ISC_R_SUCCESS;
   18399 		}
   18400 		CHECK(result);
   18401 	}
   18402 
   18403 	/* Check existing DB for NSEC3 */
   18404 	if (!nsec3) {
   18405 		CHECK(dns_nsec3_activex(db, ver, false,
   18406 					privatetype, &nsec3));
   18407 	}
   18408 
   18409 	/* Refuse to allow NSEC3 with NSEC-only keys */
   18410 	if (nseconly && nsec3) {
   18411 		dnssec_log(zone, ISC_LOG_ERROR,
   18412 			   "NSEC only DNSKEYs and NSEC3 chains not allowed");
   18413 		goto failure;
   18414 	}
   18415 
   18416 	return (true);
   18417 
   18418  failure:
   18419 	return (false);
   18420 }
   18421 
   18422 static isc_result_t
   18423 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   18424 		 dns_diff_t *diff)
   18425 {
   18426 	isc_result_t result;
   18427 	dns_dbnode_t *node = NULL;
   18428 	dns_rdataset_t rdataset;
   18429 
   18430 	dns_rdataset_init(&rdataset);
   18431 	CHECK(dns_db_getoriginnode(db, &node));
   18432 
   18433 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
   18434 				     dns_rdatatype_none, 0, &rdataset, NULL);
   18435 	if (dns_rdataset_isassociated(&rdataset))
   18436 		dns_rdataset_disassociate(&rdataset);
   18437 	if (result != ISC_R_NOTFOUND)
   18438 		goto failure;
   18439 
   18440 	result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
   18441 
   18442  failure:
   18443 	if (node != NULL)
   18444 		dns_db_detachnode(db, &node);
   18445 	return (result);
   18446 }
   18447 
   18448 /*
   18449  * Given an RRSIG rdataset and an algorithm, determine whether there
   18450  * are any signatures using that algorithm.
   18451  */
   18452 static bool
   18453 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
   18454 	dns_rdata_t rdata = DNS_RDATA_INIT;
   18455 	dns_rdata_rrsig_t rrsig;
   18456 	isc_result_t result;
   18457 
   18458 	REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
   18459 	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
   18460 		return (false);
   18461 	}
   18462 
   18463 	for (result = dns_rdataset_first(rdataset);
   18464 	     result == ISC_R_SUCCESS;
   18465 	     result = dns_rdataset_next(rdataset))
   18466 	{
   18467 		dns_rdataset_current(rdataset, &rdata);
   18468 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   18469 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   18470 		dns_rdata_reset(&rdata);
   18471 		if (rrsig.algorithm == alg)
   18472 			return (true);
   18473 	}
   18474 
   18475 	return (false);
   18476 }
   18477 
   18478 static isc_result_t
   18479 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   18480 	   dns_diff_t *diff)
   18481 {
   18482 	dns_name_t *origin;
   18483 	bool build_nsec3;
   18484 	isc_result_t result;
   18485 
   18486 	origin = dns_db_origin(db);
   18487 	CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
   18488 				 &build_nsec3));
   18489 	if (build_nsec3)
   18490 		CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
   18491 					   false, zone->privatetype, diff));
   18492 	CHECK(updatesecure(db, ver, origin, zone->minimum, true, diff));
   18493 
   18494  failure:
   18495 	return (result);
   18496 }
   18497 
   18498 static void
   18499 dnssec_report(const char *format, ...) {
   18500 	va_list args;
   18501 	va_start(args, format);
   18502 	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
   18503 		       ISC_LOG_INFO, format, args);
   18504 	va_end(args);
   18505 }
   18506 
   18507 static void
   18508 zone_rekey(dns_zone_t *zone) {
   18509 	isc_result_t result;
   18510 	dns_db_t *db = NULL;
   18511 	dns_dbnode_t *node = NULL;
   18512 	dns_dbversion_t *ver = NULL;
   18513 	dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
   18514 	dns_dnsseckeylist_t dnskeys, keys, rmkeys;
   18515 	dns_dnsseckey_t *key = NULL;
   18516 	dns_diff_t diff, _sig_diff;
   18517 	dns__zonediff_t zonediff;
   18518 	bool commit = false, newactive = false;
   18519 	bool newalg = false;
   18520 	bool fullsign;
   18521 	dns_ttl_t ttl = 3600;
   18522 	const char *dir = NULL;
   18523 	isc_mem_t *mctx = NULL;
   18524 	isc_stdtime_t now;
   18525 	isc_time_t timenow;
   18526 	isc_interval_t ival;
   18527 	char timebuf[80];
   18528 
   18529 	REQUIRE(DNS_ZONE_VALID(zone));
   18530 
   18531 	ISC_LIST_INIT(dnskeys);
   18532 	ISC_LIST_INIT(keys);
   18533 	ISC_LIST_INIT(rmkeys);
   18534 	dns_rdataset_init(&soaset);
   18535 	dns_rdataset_init(&soasigs);
   18536 	dns_rdataset_init(&keyset);
   18537 	dns_rdataset_init(&keysigs);
   18538 	dns_rdataset_init(&cdsset);
   18539 	dns_rdataset_init(&cdnskeyset);
   18540 	dir = dns_zone_getkeydirectory(zone);
   18541 	mctx = zone->mctx;
   18542 	dns_diff_init(mctx, &diff);
   18543 	dns_diff_init(mctx, &_sig_diff);
   18544 	zonediff_init(&zonediff, &_sig_diff);
   18545 
   18546 	CHECK(dns_zone_getdb(zone, &db));
   18547 	CHECK(dns_db_newversion(db, &ver));
   18548 	CHECK(dns_db_getoriginnode(db, &node));
   18549 
   18550 	TIME_NOW(&timenow);
   18551 	now = isc_time_seconds(&timenow);
   18552 
   18553 	dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
   18554 
   18555 	/* Get the SOA record's TTL */
   18556 	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
   18557 				  dns_rdatatype_none, 0, &soaset, &soasigs));
   18558 	ttl = soaset.ttl;
   18559 	dns_rdataset_disassociate(&soaset);
   18560 
   18561 	/* Get the DNSKEY rdataset */
   18562 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
   18563 				     dns_rdatatype_none, 0, &keyset, &keysigs);
   18564 	if (result == ISC_R_SUCCESS) {
   18565 		ttl = keyset.ttl;
   18566 		CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
   18567 						     mctx, &keyset,
   18568 						     &keysigs, &soasigs,
   18569 						     false, false,
   18570 						     &dnskeys));
   18571 	} else if (result != ISC_R_NOTFOUND) {
   18572 		goto failure;
   18573 	}
   18574 
   18575 	/* Get the CDS rdataset */
   18576 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
   18577 				     dns_rdatatype_none, 0, &cdsset, NULL);
   18578 	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset))
   18579 		dns_rdataset_disassociate(&cdsset);
   18580 
   18581 	/* Get the CDNSKEY rdataset */
   18582 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
   18583 				     dns_rdatatype_none, 0, &cdnskeyset, NULL);
   18584 	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset))
   18585 	{
   18586 		dns_rdataset_disassociate(&cdnskeyset);
   18587 	}
   18588 
   18589 	/*
   18590 	 * True when called from "rndc sign".  Indicates the zone should be
   18591 	 * fully signed now.
   18592 	 */
   18593 	fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
   18594 
   18595 	result = dns_dnssec_findmatchingkeys(&zone->origin, dir, now, mctx,
   18596 					     &keys);
   18597 	if (result == ISC_R_SUCCESS) {
   18598 		bool check_ksk;
   18599 		check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
   18600 		result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
   18601 					       &zone->origin, ttl, &diff,
   18602 					       !check_ksk, mctx,
   18603 					       dnssec_report);
   18604 		/*
   18605 		 * Keys couldn't be updated for some reason;
   18606 		 * try again later.
   18607 		 */
   18608 		if (result != ISC_R_SUCCESS) {
   18609 			dnssec_log(zone, ISC_LOG_ERROR,
   18610 				   "zone_rekey:couldn't update zone keys: %s",
   18611 				   isc_result_totext(result));
   18612 			goto failure;
   18613 		}
   18614 
   18615 		/*
   18616 		 * Update CDS / CDNSKEY records.
   18617 		 */
   18618 		result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
   18619 					       &cdnskeyset, now, ttl,
   18620 					       &diff, mctx);
   18621 		if (result != ISC_R_SUCCESS) {
   18622 			dnssec_log(zone, ISC_LOG_ERROR,
   18623 				   "zone_rekey:couldn't update CDS/CDNSKEY: %s",
   18624 				   isc_result_totext(result));
   18625 			goto failure;
   18626 		}
   18627 
   18628 		/*
   18629 		 * See if any pre-existing keys have newly become active;
   18630 		 * also, see if any new key is for a new algorithm, as in that
   18631 		 * event, we need to sign the zone fully.  (If there's a new
   18632 		 * key, but it's for an already-existing algorithm, then
   18633 		 * the zone signing can be handled incrementally.)
   18634 		 */
   18635 		for (key = ISC_LIST_HEAD(dnskeys);
   18636 		     key != NULL;
   18637 		     key = ISC_LIST_NEXT(key, link))
   18638 		{
   18639 			if (!key->first_sign) {
   18640 				continue;
   18641 			}
   18642 
   18643 			newactive = true;
   18644 
   18645 			if (!dns_rdataset_isassociated(&keysigs)) {
   18646 				newalg = true;
   18647 				break;
   18648 			}
   18649 
   18650 			if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
   18651 				/*
   18652 				 * This isn't a new algorithm; clear
   18653 				 * first_sign so we won't sign the
   18654 				 * whole zone with this key later
   18655 				 */
   18656 				key->first_sign = false;
   18657 			} else {
   18658 				newalg = true;
   18659 				break;
   18660 			}
   18661 		}
   18662 
   18663 		if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
   18664 		    dnskey_sane(zone, db, ver, &diff))
   18665 		{
   18666 			CHECK(dns_diff_apply(&diff, db, ver));
   18667 			CHECK(clean_nsec3param(zone, db, ver, &diff));
   18668 			CHECK(add_signing_records(db, zone->privatetype, ver,
   18669 						  &diff, (newalg || fullsign)));
   18670 			CHECK(update_soa_serial(db, ver, &diff, mctx,
   18671 						zone->updatemethod));
   18672 			CHECK(add_chains(zone, db, ver, &diff));
   18673 			CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
   18674 			CHECK(zone_journal(zone, zonediff.diff, NULL,
   18675 					   "zone_rekey"));
   18676 			commit = true;
   18677 		}
   18678 	}
   18679 
   18680 	dns_db_closeversion(db, &ver, true);
   18681 
   18682 	if (commit) {
   18683 		dns_difftuple_t *tuple;
   18684 
   18685 		LOCK_ZONE(zone);
   18686 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   18687 
   18688 		zone_needdump(zone, DNS_DUMP_DELAY);
   18689 
   18690 		zone_settimer(zone, &timenow);
   18691 
   18692 		/* Remove any signatures from removed keys.  */
   18693 		if (!ISC_LIST_EMPTY(rmkeys)) {
   18694 			for (key = ISC_LIST_HEAD(rmkeys);
   18695 			     key != NULL;
   18696 			     key = ISC_LIST_NEXT(key, link))
   18697 			{
   18698 				result = zone_signwithkey(zone,
   18699 							  dst_key_alg(key->key),
   18700 							  dst_key_id(key->key),
   18701 							  true);
   18702 				if (result != ISC_R_SUCCESS) {
   18703 					dnssec_log(zone, ISC_LOG_ERROR,
   18704 					   "zone_signwithkey failed: %s",
   18705 					   dns_result_totext(result));
   18706 				}
   18707 			}
   18708 		}
   18709 
   18710 		if (fullsign) {
   18711 			/*
   18712 			 * "rndc sign" was called, so we now sign the zone
   18713 			 * with all active keys, whether they're new or not.
   18714 			 */
   18715 			for (key = ISC_LIST_HEAD(dnskeys);
   18716 			     key != NULL;
   18717 			     key = ISC_LIST_NEXT(key, link))
   18718 			{
   18719 				if (!key->force_sign && !key->hint_sign) {
   18720 					continue;
   18721 				}
   18722 
   18723 				result = zone_signwithkey(zone,
   18724 							  dst_key_alg(key->key),
   18725 							  dst_key_id(key->key),
   18726 							  false);
   18727 				if (result != ISC_R_SUCCESS) {
   18728 					dnssec_log(zone, ISC_LOG_ERROR,
   18729 					   "zone_signwithkey failed: %s",
   18730 					   dns_result_totext(result));
   18731 				}
   18732 			}
   18733 		} else if (newalg) {
   18734 			/*
   18735 			 * We haven't been told to sign fully, but a new
   18736 			 * algorithm was added to the DNSKEY.  We sign
   18737 			 * the full zone, but only with newly active
   18738 			 * keys.
   18739 			 */
   18740 			for (key = ISC_LIST_HEAD(dnskeys);
   18741 			     key != NULL;
   18742 			     key = ISC_LIST_NEXT(key, link))
   18743 			{
   18744 				if (!key->first_sign) {
   18745 					continue;
   18746 				}
   18747 
   18748 				result = zone_signwithkey(zone,
   18749 							  dst_key_alg(key->key),
   18750 							  dst_key_id(key->key),
   18751 							  false);
   18752 				if (result != ISC_R_SUCCESS) {
   18753 					dnssec_log(zone, ISC_LOG_ERROR,
   18754 					   "zone_signwithkey failed: %s",
   18755 					   dns_result_totext(result));
   18756 				}
   18757 			}
   18758 		}
   18759 
   18760 		/*
   18761 		 * Clear fullsign flag, if it was set, so we don't do
   18762 		 * another full signing next time
   18763 		 */
   18764 		zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
   18765 
   18766 		/*
   18767 		 * Cause the zone to add/delete NSEC3 chains for the
   18768 		 * deferred NSEC3PARAM changes.
   18769 		 */
   18770 		for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
   18771 		     tuple != NULL;
   18772 		     tuple = ISC_LIST_NEXT(tuple, link))
   18773 		{
   18774 			unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   18775 			dns_rdata_t rdata = DNS_RDATA_INIT;
   18776 			dns_rdata_nsec3param_t nsec3param;
   18777 
   18778 			if (tuple->rdata.type != zone->privatetype ||
   18779 			    tuple->op != DNS_DIFFOP_ADD)
   18780 			{
   18781 				continue;
   18782 			}
   18783 
   18784 			if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
   18785 							buf, sizeof(buf)))
   18786 			{
   18787 				continue;
   18788 			}
   18789 
   18790 			result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   18791 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   18792 			if (nsec3param.flags == 0) {
   18793 				continue;
   18794 			}
   18795 
   18796 			result = zone_addnsec3chain(zone, &nsec3param);
   18797 			if (result != ISC_R_SUCCESS) {
   18798 				dnssec_log(zone, ISC_LOG_ERROR,
   18799 					   "zone_addnsec3chain failed: %s",
   18800 					   dns_result_totext(result));
   18801 			}
   18802 		}
   18803 
   18804 		/*
   18805 		 * Activate any NSEC3 chain updates that may have
   18806 		 * been scheduled before this rekey.
   18807 		 */
   18808 		if (fullsign || newalg) {
   18809 			resume_addnsec3chain(zone);
   18810 		}
   18811 
   18812 		/*
   18813 		 * Schedule the next resigning event
   18814 		 */
   18815 		set_resigntime(zone);
   18816 		UNLOCK_ZONE(zone);
   18817 	}
   18818 
   18819 	isc_time_settoepoch(&zone->refreshkeytime);
   18820 
   18821 	/*
   18822 	 * If we're doing key maintenance, set the key refresh timer to
   18823 	 * the next scheduled key event or to 'dnssec-loadkeys-interval'
   18824 	 * seconds in the future, whichever is sooner.
   18825 	 */
   18826 	if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
   18827 		isc_time_t timethen;
   18828 		isc_stdtime_t then;
   18829 
   18830 		LOCK_ZONE(zone);
   18831 		DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
   18832 				  &timethen);
   18833 		zone->refreshkeytime = timethen;
   18834 		UNLOCK_ZONE(zone);
   18835 
   18836 		for (key = ISC_LIST_HEAD(dnskeys);
   18837 		     key != NULL;
   18838 		     key = ISC_LIST_NEXT(key, link))
   18839 		{
   18840 			then = now;
   18841 			result = next_keyevent(key->key, &then);
   18842 			if (result != ISC_R_SUCCESS) {
   18843 				continue;
   18844 			}
   18845 
   18846 			DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
   18847 			LOCK_ZONE(zone);
   18848 			if (isc_time_compare(&timethen,
   18849 					     &zone->refreshkeytime) < 0)
   18850 			{
   18851 				zone->refreshkeytime = timethen;
   18852 			}
   18853 			UNLOCK_ZONE(zone);
   18854 		}
   18855 
   18856 		zone_settimer(zone, &timenow);
   18857 
   18858 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   18859 		dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
   18860 	}
   18861 
   18862 	result = ISC_R_SUCCESS;
   18863 
   18864  failure:
   18865 	if (result != ISC_R_SUCCESS) {
   18866 		/*
   18867 		 * Something went wrong; try again in ten minutes or
   18868 		 * after a key refresh interval, whichever is shorter.
   18869 		 */
   18870 		isc_interval_set(&ival,
   18871 				 ISC_MIN(zone->refreshkeyinterval, 600), 0);
   18872 		isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
   18873 	}
   18874 
   18875 	dns_diff_clear(&diff);
   18876 	dns_diff_clear(&_sig_diff);
   18877 
   18878 	clear_keylist(&dnskeys, mctx);
   18879 	clear_keylist(&keys, mctx);
   18880 	clear_keylist(&rmkeys, mctx);
   18881 
   18882 	if (ver != NULL) {
   18883 		dns_db_closeversion(db, &ver, false);
   18884 	}
   18885 	if (dns_rdataset_isassociated(&cdsset)) {
   18886 		dns_rdataset_disassociate(&cdsset);
   18887 	}
   18888 	if (dns_rdataset_isassociated(&keyset)) {
   18889 		dns_rdataset_disassociate(&keyset);
   18890 	}
   18891 	if (dns_rdataset_isassociated(&keysigs)) {
   18892 		dns_rdataset_disassociate(&keysigs);
   18893 	}
   18894 	if (dns_rdataset_isassociated(&soasigs)) {
   18895 		dns_rdataset_disassociate(&soasigs);
   18896 	}
   18897 	if (dns_rdataset_isassociated(&cdnskeyset)) {
   18898 		dns_rdataset_disassociate(&cdnskeyset);
   18899 	}
   18900 	if (node != NULL) {
   18901 		dns_db_detachnode(db, &node);
   18902 	}
   18903 	if (db != NULL) {
   18904 		dns_db_detach(&db);
   18905 	}
   18906 
   18907 	INSIST(ver == NULL);
   18908 }
   18909 
   18910 void
   18911 dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
   18912 	isc_time_t now;
   18913 
   18914 	if (zone->type == dns_zone_master && zone->task != NULL) {
   18915 		LOCK_ZONE(zone);
   18916 
   18917 		if (fullsign)
   18918 			zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
   18919 
   18920 		TIME_NOW(&now);
   18921 		zone->refreshkeytime = now;
   18922 		zone_settimer(zone, &now);
   18923 
   18924 		UNLOCK_ZONE(zone);
   18925 	}
   18926 }
   18927 
   18928 isc_result_t
   18929 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
   18930 		 unsigned int *errors)
   18931 {
   18932 	isc_result_t result;
   18933 	dns_dbnode_t *node = NULL;
   18934 
   18935 	REQUIRE(DNS_ZONE_VALID(zone));
   18936 	REQUIRE(errors != NULL);
   18937 
   18938 	result = dns_db_getoriginnode(db, &node);
   18939 	if (result != ISC_R_SUCCESS)
   18940 		return (result);
   18941 	result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
   18942 				  false);
   18943 	dns_db_detachnode(db, &node);
   18944 	return (result);
   18945 }
   18946 
   18947 isc_result_t
   18948 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
   18949 	isc_result_t result;
   18950 	dns_dbnode_t *node = NULL;
   18951 	dns_rdataset_t dnskey, cds, cdnskey;
   18952 	unsigned char buffer[DNS_DS_BUFFERSIZE];
   18953 	unsigned char algorithms[256];
   18954 	unsigned int i;
   18955 
   18956 	REQUIRE(DNS_ZONE_VALID(zone));
   18957 
   18958 	result = dns_db_getoriginnode(db, &node);
   18959 	if (result != ISC_R_SUCCESS)
   18960 		return (result);
   18961 
   18962 	dns_rdataset_init(&cds);
   18963 	dns_rdataset_init(&dnskey);
   18964 	dns_rdataset_init(&cdnskey);
   18965 
   18966 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
   18967 				     dns_rdatatype_none, 0, &cds, NULL);
   18968 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
   18969 		goto failure;
   18970 
   18971 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
   18972 				     dns_rdatatype_none, 0, &cdnskey, NULL);
   18973 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
   18974 		goto failure;
   18975 
   18976 	if (!dns_rdataset_isassociated(&cds) &&
   18977 	    !dns_rdataset_isassociated(&cdnskey)) {
   18978 		result = ISC_R_SUCCESS;
   18979 		goto failure;
   18980 	}
   18981 
   18982 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
   18983 				     dns_rdatatype_none, 0, &dnskey, NULL);
   18984 	if (result == ISC_R_NOTFOUND) {
   18985 		if (dns_rdataset_isassociated(&cds))
   18986 			result = DNS_R_BADCDS;
   18987 		else
   18988 			result = DNS_R_BADCDNSKEY;
   18989 		goto failure;
   18990 	}
   18991 	if (result != ISC_R_SUCCESS)
   18992 		goto failure;
   18993 
   18994 	/*
   18995 	 * For each DNSSEC algorithm in the CDS RRset there must be
   18996 	 * a matching DNSKEY record.
   18997 	 */
   18998 	if (dns_rdataset_isassociated(&cds)) {
   18999 		memset(algorithms, 0, sizeof(algorithms));
   19000 		for (result = dns_rdataset_first(&cds);
   19001 		     result == ISC_R_SUCCESS;
   19002 		     result = dns_rdataset_next(&cds)) {
   19003 			dns_rdata_t crdata = DNS_RDATA_INIT;
   19004 			dns_rdata_cds_t structcds;
   19005 
   19006 			dns_rdataset_current(&cds, &crdata);
   19007 			CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
   19008 			if (algorithms[structcds.algorithm] == 0)
   19009 				algorithms[structcds.algorithm] = 1;
   19010 			for (result = dns_rdataset_first(&dnskey);
   19011 			     result == ISC_R_SUCCESS;
   19012 			     result = dns_rdataset_next(&dnskey)) {
   19013 				dns_rdata_t rdata = DNS_RDATA_INIT;
   19014 				dns_rdata_t dsrdata = DNS_RDATA_INIT;
   19015 
   19016 				dns_rdataset_current(&dnskey, &rdata);
   19017 				CHECK(dns_ds_buildrdata(&zone->origin, &rdata,
   19018 							structcds.digest_type,
   19019 							buffer, &dsrdata));
   19020 				if (crdata.length == dsrdata.length &&
   19021 				    memcmp(crdata.data, dsrdata.data,
   19022 					   dsrdata.length) == 0) {
   19023 					algorithms[structcds.algorithm] = 2;
   19024 				}
   19025 			}
   19026 			if (result != ISC_R_NOMORE)
   19027 				goto failure;
   19028 		}
   19029 		for (i = 0; i < sizeof(algorithms); i++) {
   19030 			if (algorithms[i] == 1) {
   19031 				result = DNS_R_BADCDNSKEY;
   19032 				goto failure;
   19033 			}
   19034 		}
   19035 	}
   19036 
   19037 	/*
   19038 	 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
   19039 	 * a matching DNSKEY record.
   19040 	 */
   19041 	if (dns_rdataset_isassociated(&cdnskey)) {
   19042 		memset(algorithms, 0, sizeof(algorithms));
   19043 		for (result = dns_rdataset_first(&cdnskey);
   19044 		     result == ISC_R_SUCCESS;
   19045 		     result = dns_rdataset_next(&cdnskey)) {
   19046 			dns_rdata_t crdata = DNS_RDATA_INIT;
   19047 			dns_rdata_cdnskey_t structcdnskey;
   19048 
   19049 			dns_rdataset_current(&cdnskey, &crdata);
   19050 			CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
   19051 						 NULL));
   19052 			if (algorithms[structcdnskey.algorithm] == 0)
   19053 				algorithms[structcdnskey.algorithm] = 1;
   19054 			for (result = dns_rdataset_first(&dnskey);
   19055 			     result == ISC_R_SUCCESS;
   19056 			     result = dns_rdataset_next(&dnskey)) {
   19057 				dns_rdata_t rdata = DNS_RDATA_INIT;
   19058 
   19059 				dns_rdataset_current(&dnskey, &rdata);
   19060 				if (crdata.length == rdata.length &&
   19061 				    memcmp(crdata.data, rdata.data,
   19062 					   rdata.length) == 0) {
   19063 					algorithms[structcdnskey.algorithm] = 2;
   19064 				}
   19065 			}
   19066 			if (result != ISC_R_NOMORE)
   19067 				goto failure;
   19068 		}
   19069 		for (i = 0; i < sizeof(algorithms); i++) {
   19070 			if (algorithms[i] == 1) {
   19071 				result = DNS_R_BADCDS;
   19072 				goto failure;
   19073 			}
   19074 		}
   19075 	}
   19076 	result = ISC_R_SUCCESS;
   19077 
   19078  failure:
   19079 	if (dns_rdataset_isassociated(&cds))
   19080 		dns_rdataset_disassociate(&cds);
   19081 	if (dns_rdataset_isassociated(&dnskey))
   19082 		dns_rdataset_disassociate(&dnskey);
   19083 	if (dns_rdataset_isassociated(&cdnskey))
   19084 		dns_rdataset_disassociate(&cdnskey);
   19085 	dns_db_detachnode(db, &node);
   19086 	return (result);
   19087 }
   19088 
   19089 void
   19090 dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
   19091 	REQUIRE(DNS_ZONE_VALID(zone));
   19092 
   19093 	LOCK_ZONE(zone);
   19094 	zone->automatic = automatic;
   19095 	UNLOCK_ZONE(zone);
   19096 }
   19097 
   19098 bool
   19099 dns_zone_getautomatic(dns_zone_t *zone) {
   19100 	REQUIRE(DNS_ZONE_VALID(zone));
   19101 	return (zone->automatic);
   19102 }
   19103 
   19104 void
   19105 dns_zone_setadded(dns_zone_t *zone, bool added) {
   19106 	REQUIRE(DNS_ZONE_VALID(zone));
   19107 
   19108 	LOCK_ZONE(zone);
   19109 	zone->added = added;
   19110 	UNLOCK_ZONE(zone);
   19111 }
   19112 
   19113 bool
   19114 dns_zone_getadded(dns_zone_t *zone) {
   19115 	REQUIRE(DNS_ZONE_VALID(zone));
   19116 	return (zone->added);
   19117 }
   19118 
   19119 isc_result_t
   19120 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
   19121 {
   19122 	isc_time_t loadtime;
   19123 	isc_result_t result;
   19124 	dns_zone_t *secure = NULL;
   19125 
   19126 	TIME_NOW(&loadtime);
   19127 
   19128 	/*
   19129 	 * Lock hierarchy: zmgr, zone, raw.
   19130 	 */
   19131  again:
   19132 	LOCK_ZONE(zone);
   19133 	INSIST(zone != zone->raw);
   19134 	if (inline_secure(zone))
   19135 		LOCK_ZONE(zone->raw);
   19136 	else if (inline_raw(zone)) {
   19137 		secure = zone->secure;
   19138 		TRYLOCK_ZONE(result, secure);
   19139 		if (result != ISC_R_SUCCESS) {
   19140 			UNLOCK_ZONE(zone);
   19141 			secure = NULL;
   19142 			isc_thread_yield();
   19143 			goto again;
   19144 		}
   19145 	}
   19146 	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
   19147 	if (inline_secure(zone))
   19148 		UNLOCK_ZONE(zone->raw);
   19149 	else if (secure != NULL)
   19150 		UNLOCK_ZONE(secure);
   19151 	UNLOCK_ZONE(zone);
   19152 	return result;
   19153 }
   19154 
   19155 isc_result_t
   19156 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
   19157 	REQUIRE(DNS_ZONE_VALID(zone));
   19158 	if (interval == 0)
   19159 		return (ISC_R_RANGE);
   19160 	/* Maximum value: 24 hours (3600 minutes) */
   19161 	if (interval > (24 * 60))
   19162 		interval = (24 * 60);
   19163 	/* Multiply by 60 for seconds */
   19164 	zone->refreshkeyinterval = interval * 60;
   19165 	return (ISC_R_SUCCESS);
   19166 }
   19167 
   19168 void
   19169 dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
   19170 	REQUIRE(DNS_ZONE_VALID(zone));
   19171 	zone->requestixfr = flag;
   19172 }
   19173 
   19174 bool
   19175 dns_zone_getrequestixfr(dns_zone_t *zone) {
   19176 	REQUIRE(DNS_ZONE_VALID(zone));
   19177 	return (zone->requestixfr);
   19178 }
   19179 
   19180 void
   19181 dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
   19182 	REQUIRE(DNS_ZONE_VALID(zone));
   19183 	zone->requestexpire = flag;
   19184 }
   19185 
   19186 bool
   19187 dns_zone_getrequestexpire(dns_zone_t *zone) {
   19188 	REQUIRE(DNS_ZONE_VALID(zone));
   19189 	return (zone->requestexpire);
   19190 }
   19191 
   19192 void
   19193 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
   19194 	REQUIRE(DNS_ZONE_VALID(zone));
   19195 	zone->updatemethod = method;
   19196 }
   19197 
   19198 dns_updatemethod_t
   19199 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
   19200 	REQUIRE(DNS_ZONE_VALID(zone));
   19201 	return(zone->updatemethod);
   19202 }
   19203 
   19204 /*
   19205  * Lock hierarchy: zmgr, zone, raw.
   19206  */
   19207 isc_result_t
   19208 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
   19209 	isc_result_t result;
   19210 	dns_zonemgr_t *zmgr;
   19211 
   19212 	REQUIRE(DNS_ZONE_VALID(zone));
   19213 	REQUIRE(zone->zmgr != NULL);
   19214 	REQUIRE(zone->task != NULL);
   19215 	REQUIRE(zone->loadtask != NULL);
   19216 	REQUIRE(zone->raw == NULL);
   19217 
   19218 	REQUIRE(DNS_ZONE_VALID(raw));
   19219 	REQUIRE(raw->zmgr == NULL);
   19220 	REQUIRE(raw->task == NULL);
   19221 	REQUIRE(raw->loadtask == NULL);
   19222 	REQUIRE(raw->secure == NULL);
   19223 
   19224 	REQUIRE(zone != raw);
   19225 
   19226 	/*
   19227 	 * Lock hierarchy: zmgr, zone, raw.
   19228 	 */
   19229 	zmgr = zone->zmgr;
   19230 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19231 	LOCK_ZONE(zone);
   19232 	LOCK_ZONE(raw);
   19233 
   19234 	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
   19235 				  NULL, NULL, zone->task, zone_timer, raw,
   19236 				  &raw->timer);
   19237 	if (result != ISC_R_SUCCESS)
   19238 		goto unlock;
   19239 
   19240 	/*
   19241 	 * The timer "holds" a iref.
   19242 	 */
   19243 	raw->irefs++;
   19244 	INSIST(raw->irefs != 0);
   19245 
   19246 
   19247 	/* dns_zone_attach(raw, &zone->raw); */
   19248 	isc_refcount_increment(&raw->erefs);
   19249 	zone->raw = raw;
   19250 
   19251 	/* dns_zone_iattach(zone,  &raw->secure); */
   19252 	zone_iattach(zone, &raw->secure);
   19253 
   19254 	isc_task_attach(zone->task, &raw->task);
   19255 	isc_task_attach(zone->loadtask, &raw->loadtask);
   19256 
   19257 	ISC_LIST_APPEND(zmgr->zones, raw, link);
   19258 	raw->zmgr = zmgr;
   19259 	zmgr->refs++;
   19260 
   19261  unlock:
   19262 	UNLOCK_ZONE(raw);
   19263 	UNLOCK_ZONE(zone);
   19264 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   19265 	return (result);
   19266 }
   19267 
   19268 void
   19269 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
   19270 	REQUIRE(DNS_ZONE_VALID(zone));
   19271 	REQUIRE(raw != NULL && *raw == NULL);
   19272 
   19273 	LOCK(&zone->lock);
   19274 	INSIST(zone != zone->raw);
   19275 	if (zone->raw != NULL)
   19276 		dns_zone_attach(zone->raw, raw);
   19277 	UNLOCK(&zone->lock);
   19278 }
   19279 
   19280 struct keydone {
   19281 	isc_event_t event;
   19282 	bool all;
   19283 	unsigned char data[5];
   19284 };
   19285 
   19286 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
   19287 
   19288 static void
   19289 keydone(isc_task_t *task, isc_event_t *event) {
   19290 	const char *me = "keydone";
   19291 	bool commit = false;
   19292 	isc_result_t result;
   19293 	dns_rdata_t rdata = DNS_RDATA_INIT;
   19294 	dns_dbversion_t *oldver = NULL, *newver = NULL;
   19295 	dns_zone_t *zone;
   19296 	dns_db_t *db = NULL;
   19297 	dns_dbnode_t *node = NULL;
   19298 	dns_rdataset_t rdataset;
   19299 	dns_diff_t diff;
   19300 	struct keydone *kd = (struct keydone *)event;
   19301 	dns_update_log_t log = { update_log_cb, NULL };
   19302 	bool clear_pending = false;
   19303 
   19304 	UNUSED(task);
   19305 
   19306 	zone = event->ev_arg;
   19307 	INSIST(DNS_ZONE_VALID(zone));
   19308 
   19309 	ENTER;
   19310 
   19311 	dns_rdataset_init(&rdataset);
   19312 	dns_diff_init(zone->mctx, &diff);
   19313 
   19314 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   19315 	if (zone->db != NULL) {
   19316 		dns_db_attach(zone->db, &db);
   19317 	}
   19318 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   19319 	if (db == NULL) {
   19320 		goto failure;
   19321 	}
   19322 
   19323 	dns_db_currentversion(db, &oldver);
   19324 	result = dns_db_newversion(db, &newver);
   19325 	if (result != ISC_R_SUCCESS) {
   19326 		dnssec_log(zone, ISC_LOG_ERROR,
   19327 			   "keydone:dns_db_newversion -> %s",
   19328 			   dns_result_totext(result));
   19329 		goto failure;
   19330 	}
   19331 
   19332 	result = dns_db_getoriginnode(db, &node);
   19333 	if (result != ISC_R_SUCCESS) {
   19334 		goto failure;
   19335 	}
   19336 
   19337 	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
   19338 				     dns_rdatatype_none, 0, &rdataset, NULL);
   19339 	if (result == ISC_R_NOTFOUND) {
   19340 		INSIST(!dns_rdataset_isassociated(&rdataset));
   19341 		goto failure;
   19342 	}
   19343 	if (result != ISC_R_SUCCESS) {
   19344 		INSIST(!dns_rdataset_isassociated(&rdataset));
   19345 		goto failure;
   19346 	}
   19347 
   19348 	for (result = dns_rdataset_first(&rdataset);
   19349 	     result == ISC_R_SUCCESS;
   19350 	     result = dns_rdataset_next(&rdataset))
   19351 	{
   19352 		bool found = false;
   19353 
   19354 		dns_rdataset_current(&rdataset, &rdata);
   19355 
   19356 		if (kd->all) {
   19357 			if (rdata.length == 5 && rdata.data[0] != 0 &&
   19358 			       rdata.data[3] == 0 && rdata.data[4] == 1)
   19359 			{
   19360 				found = true;
   19361 			} else if (rdata.data[0] == 0 &&
   19362 				   (rdata.data[2] & PENDINGFLAGS) != 0)
   19363 			{
   19364 				found = true;
   19365 				clear_pending = true;
   19366 			}
   19367 		} else if (rdata.length == 5 &&
   19368 			   memcmp(rdata.data, kd->data, 5) == 0)
   19369 		{
   19370 			found = true;
   19371 		}
   19372 
   19373 		if (found) {
   19374 			CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
   19375 					    &zone->origin, rdataset.ttl,
   19376 					    &rdata));
   19377 		}
   19378 		dns_rdata_reset(&rdata);
   19379 	}
   19380 
   19381 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   19382 		/* Write changes to journal file. */
   19383 		CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
   19384 					zone->updatemethod));
   19385 
   19386 		result = dns_update_signatures(&log, zone, db,
   19387 					       oldver, newver, &diff,
   19388 					       zone->sigvalidityinterval);
   19389 		if (!clear_pending) {
   19390 			CHECK(result);
   19391 		}
   19392 
   19393 		CHECK(zone_journal(zone, &diff, NULL, "keydone"));
   19394 		commit = true;
   19395 
   19396 		LOCK_ZONE(zone);
   19397 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   19398 		zone_needdump(zone, 30);
   19399 		UNLOCK_ZONE(zone);
   19400 	}
   19401 
   19402  failure:
   19403 	if (dns_rdataset_isassociated(&rdataset)) {
   19404 		dns_rdataset_disassociate(&rdataset);
   19405 	}
   19406 	if (db != NULL) {
   19407 		if (node != NULL) {
   19408 			dns_db_detachnode(db, &node);
   19409 		}
   19410 		if (oldver != NULL) {
   19411 			dns_db_closeversion(db, &oldver, false);
   19412 		}
   19413 		if (newver != NULL) {
   19414 			dns_db_closeversion(db, &newver, commit);
   19415 		}
   19416 		dns_db_detach(&db);
   19417 	}
   19418 	dns_diff_clear(&diff);
   19419 	isc_event_free(&event);
   19420 	dns_zone_idetach(&zone);
   19421 
   19422 	INSIST(oldver == NULL);
   19423 	INSIST(newver == NULL);
   19424 }
   19425 
   19426 isc_result_t
   19427 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
   19428 	isc_result_t result = ISC_R_SUCCESS;
   19429 	isc_event_t *e;
   19430 	isc_buffer_t b;
   19431 	dns_zone_t *dummy = NULL;
   19432 	struct keydone *kd;
   19433 
   19434 	REQUIRE(DNS_ZONE_VALID(zone));
   19435 
   19436 	LOCK_ZONE(zone);
   19437 
   19438 	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
   19439 			       zone, sizeof(struct keydone));
   19440 	if (e == NULL) {
   19441 		result = ISC_R_NOMEMORY;
   19442 		goto failure;
   19443 	}
   19444 
   19445 	kd = (struct keydone *) e;
   19446 	if (strcasecmp(keystr, "all") == 0) {
   19447 		kd->all = true;
   19448 	} else {
   19449 		isc_textregion_t r;
   19450 		const char *algstr;
   19451 		dns_keytag_t keyid;
   19452 		dns_secalg_t alg;
   19453 		size_t n;
   19454 
   19455 		kd->all = false;
   19456 
   19457 		n = sscanf(keystr, "%hu/", &keyid);
   19458 		if (n == 0U) {
   19459 			CHECK(ISC_R_FAILURE);
   19460 		}
   19461 
   19462 		algstr = strchr(keystr, '/');
   19463 		if (algstr != NULL) {
   19464 			algstr++;
   19465 		} else {
   19466 			CHECK(ISC_R_FAILURE);
   19467 		}
   19468 
   19469 		n = sscanf(algstr, "%hhu", &alg);
   19470 		if (n == 0U) {
   19471 			DE_CONST(algstr, r.base);
   19472 			r.length = strlen(algstr);
   19473 			CHECK(dns_secalg_fromtext(&alg, &r));
   19474 		}
   19475 
   19476 		/* construct a private-type rdata */
   19477 		isc_buffer_init(&b, kd->data, sizeof(kd->data));
   19478 		isc_buffer_putuint8(&b, alg);
   19479 		isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
   19480 		isc_buffer_putuint8(&b, (keyid & 0xff));
   19481 		isc_buffer_putuint8(&b, 0);
   19482 		isc_buffer_putuint8(&b, 1);
   19483 	}
   19484 
   19485 	zone_iattach(zone, &dummy);
   19486 	isc_task_send(zone->task, &e);
   19487 
   19488  failure:
   19489 	if (e != NULL) {
   19490 		isc_event_free(&e);
   19491 	}
   19492 	UNLOCK_ZONE(zone);
   19493 	return (result);
   19494 }
   19495 
   19496 /*
   19497  * Called from the zone task's queue after the relevant event is posted by
   19498  * dns_zone_setnsec3param().
   19499  */
   19500 static void
   19501 setnsec3param(isc_task_t *task, isc_event_t *event) {
   19502 	const char *me = "setnsec3param";
   19503 	dns_zone_t *zone = event->ev_arg;
   19504 
   19505 	INSIST(DNS_ZONE_VALID(zone));
   19506 
   19507 	UNUSED(task);
   19508 
   19509 	ENTER;
   19510 
   19511 	/*
   19512 	 * If receive_secure_serial is still processing or we have a
   19513 	 * queued event append rss_post queue.
   19514 	 */
   19515 	if (zone->rss_newver != NULL ||
   19516 	    ISC_LIST_HEAD(zone->rss_post) != NULL)
   19517 	{
   19518 		/*
   19519 		 * Wait for receive_secure_serial() to finish processing.
   19520 		 */
   19521 		ISC_LIST_APPEND(zone->rss_post, event, ev_link);
   19522 	} else {
   19523 		rss_post(zone, event);
   19524 	}
   19525 	dns_zone_idetach(&zone);
   19526 }
   19527 
   19528 /*
   19529  * Check whether NSEC3 chain addition or removal specified by the private-type
   19530  * record passed with the event was already queued (or even fully performed).
   19531  * If not, modify the relevant private-type records at the zone apex and call
   19532  * resume_addnsec3chain().
   19533  */
   19534 static void
   19535 rss_post(dns_zone_t *zone, isc_event_t *event) {
   19536 	const char *me = "rss_post";
   19537 	bool commit = false;
   19538 	isc_result_t result;
   19539 	dns_dbversion_t *oldver = NULL, *newver = NULL;
   19540 	dns_db_t *db = NULL;
   19541 	dns_dbnode_t *node = NULL;
   19542 	dns_rdataset_t prdataset, nrdataset;
   19543 	dns_diff_t diff;
   19544 	struct np3event *npe = (struct np3event *)event;
   19545 	nsec3param_t *np;
   19546 	dns_update_log_t log = { update_log_cb, NULL };
   19547 	dns_rdata_t rdata;
   19548 	bool nseconly;
   19549 	bool exists = false;
   19550 
   19551 	ENTER;
   19552 
   19553 	np = &npe->params;
   19554 
   19555 	dns_rdataset_init(&prdataset);
   19556 	dns_rdataset_init(&nrdataset);
   19557 	dns_diff_init(zone->mctx, &diff);
   19558 
   19559 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   19560 	if (zone->db != NULL) {
   19561 		dns_db_attach(zone->db, &db);
   19562 	}
   19563 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   19564 	if (db == NULL) {
   19565 		goto failure;
   19566 	}
   19567 
   19568 	dns_db_currentversion(db, &oldver);
   19569 	result = dns_db_newversion(db, &newver);
   19570 	if (result != ISC_R_SUCCESS) {
   19571 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   19572 		dnssec_log(zone, ISC_LOG_ERROR,
   19573 			   "setnsec3param:dns_db_newversion -> %s",
   19574 			   dns_result_totext(result));
   19575 		goto failure;
   19576 	}
   19577 
   19578 	CHECK(dns_db_getoriginnode(db, &node));
   19579 
   19580 	/*
   19581 	 * Does a private-type record already exist for this chain?
   19582 	 */
   19583 	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
   19584 				     dns_rdatatype_none, 0, &prdataset, NULL);
   19585 	if (result == ISC_R_SUCCESS) {
   19586 		for (result = dns_rdataset_first(&prdataset);
   19587 		     result == ISC_R_SUCCESS;
   19588 		     result = dns_rdataset_next(&prdataset))
   19589 		{
   19590 			dns_rdata_init(&rdata);
   19591 			dns_rdataset_current(&prdataset, &rdata);
   19592 
   19593 			if (np->length == rdata.length &&
   19594 			    memcmp(rdata.data, np->data, np->length) == 0)
   19595 			{
   19596 				exists = true;
   19597 				break;
   19598 			}
   19599 		}
   19600 	} else if (result != ISC_R_NOTFOUND) {
   19601 		INSIST(!dns_rdataset_isassociated(&prdataset));
   19602 		goto failure;
   19603 	}
   19604 
   19605 	/*
   19606 	 * Does the chain already exist?
   19607 	 */
   19608 	result = dns_db_findrdataset(db, node, newver,
   19609 				     dns_rdatatype_nsec3param,
   19610 				     dns_rdatatype_none, 0, &nrdataset, NULL);
   19611 	if (result == ISC_R_SUCCESS) {
   19612 		for (result = dns_rdataset_first(&nrdataset);
   19613 		     result == ISC_R_SUCCESS;
   19614 		     result = dns_rdataset_next(&nrdataset))
   19615 		{
   19616 			dns_rdata_init(&rdata);
   19617 			dns_rdataset_current(&nrdataset, &rdata);
   19618 
   19619 			if (np->length == (rdata.length + 1) &&
   19620 			    memcmp(rdata.data, np->data + 1,
   19621 				   np->length - 1) == 0)
   19622 			{
   19623 				exists = true;
   19624 				break;
   19625 			}
   19626 		}
   19627 	} else if (result != ISC_R_NOTFOUND) {
   19628 		INSIST(!dns_rdataset_isassociated(&nrdataset));
   19629 		goto failure;
   19630 	}
   19631 
   19632 
   19633 	/*
   19634 	 * We need to remove any existing NSEC3 chains if the supplied NSEC3
   19635 	 * parameters are supposed to replace the current ones or if we are
   19636 	 * switching to NSEC.
   19637 	 */
   19638 	if (!exists && np->replace && (np->length != 0 || np->nsec)) {
   19639 		CHECK(dns_nsec3param_deletechains(db, newver, zone,
   19640 						  !np->nsec, &diff));
   19641 	}
   19642 
   19643 	if (!exists && np->length != 0) {
   19644 		/*
   19645 		 * We're creating an NSEC3 chain.  Add the private-type record
   19646 		 * passed in the event handler's argument to the zone apex.
   19647 		 *
   19648 		 * If the zone is not currently capable of supporting an NSEC3
   19649 		 * chain (due to the DNSKEY RRset at the zone apex not existing
   19650 		 * or containing at least one key using an NSEC-only
   19651 		 * algorithm), add the INITIAL flag, so these parameters can be
   19652 		 * used later when NSEC3 becomes available.
   19653 		 */
   19654 		dns_rdata_init(&rdata);
   19655 
   19656 		np->data[2] |= DNS_NSEC3FLAG_CREATE;
   19657 		result = dns_nsec_nseconly(db, newver, &nseconly);
   19658 		if (result == ISC_R_NOTFOUND || nseconly) {
   19659 			np->data[2] |= DNS_NSEC3FLAG_INITIAL;
   19660 		}
   19661 
   19662 		rdata.length = np->length;
   19663 		rdata.data = np->data;
   19664 		rdata.type = zone->privatetype;
   19665 		rdata.rdclass = zone->rdclass;
   19666 		CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
   19667 				    &zone->origin, 0, &rdata));
   19668 	}
   19669 
   19670 	/*
   19671 	 * If we changed anything in the zone, write changes to journal file
   19672 	 * and set commit to true so that resume_addnsec3chain() will be
   19673 	 * called below in order to kick off adding/removing relevant NSEC3
   19674 	 * records.
   19675 	 */
   19676 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   19677 		CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
   19678 					zone->updatemethod));
   19679 		result = dns_update_signatures(&log, zone, db,
   19680 					       oldver, newver, &diff,
   19681 					       zone->sigvalidityinterval);
   19682 		if (result != ISC_R_NOTFOUND) {
   19683 			CHECK(result);
   19684 		}
   19685 		CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
   19686 		commit = true;
   19687 
   19688 		LOCK_ZONE(zone);
   19689 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   19690 		zone_needdump(zone, 30);
   19691 		UNLOCK_ZONE(zone);
   19692 	}
   19693 
   19694  failure:
   19695 	if (dns_rdataset_isassociated(&prdataset)) {
   19696 		dns_rdataset_disassociate(&prdataset);
   19697 	}
   19698 	if (dns_rdataset_isassociated(&nrdataset)) {
   19699 		dns_rdataset_disassociate(&nrdataset);
   19700 	}
   19701 	if (node != NULL) {
   19702 		dns_db_detachnode(db, &node);
   19703 	}
   19704 	if (oldver != NULL) {
   19705 		dns_db_closeversion(db, &oldver, false);
   19706 	}
   19707 	if (newver != NULL) {
   19708 		dns_db_closeversion(db, &newver, commit);
   19709 	}
   19710 	if (db != NULL) {
   19711 		dns_db_detach(&db);
   19712 	}
   19713 	if (commit) {
   19714 		LOCK_ZONE(zone);
   19715 		resume_addnsec3chain(zone);
   19716 		UNLOCK_ZONE(zone);
   19717 	}
   19718 	dns_diff_clear(&diff);
   19719 	isc_event_free(&event);
   19720 
   19721 	INSIST(oldver == NULL);
   19722 	INSIST(newver == NULL);
   19723 }
   19724 
   19725 /*
   19726  * Called when an "rndc signing -nsec3param ..." command is received.
   19727  *
   19728  * Allocate and prepare an nsec3param_t structure which holds information about
   19729  * the NSEC3 changes requested for the zone:
   19730  *
   19731  *   - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
   19732  *     field of the structure to true and the "replace" field to the value
   19733  *     of the "replace" argument, leaving other fields initialized to zeros, to
   19734  *     signal that the zone should be signed using NSEC instead of NSEC3,
   19735  *
   19736  *   - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
   19737  *     the zone apex, convert it to a private-type record and store the latter
   19738  *     in the "data" field of the nsec3param_t structure.
   19739  *
   19740  * Once the nsec3param_t structure is prepared, post an event to the zone's
   19741  * task which will cause setnsec3param() to be called with the prepared
   19742  * structure passed as an argument.
   19743  */
   19744 isc_result_t
   19745 dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
   19746 		       uint16_t iter, uint8_t saltlen,
   19747 		       unsigned char *salt, bool replace)
   19748 {
   19749 	isc_result_t result = ISC_R_SUCCESS;
   19750 	dns_rdata_nsec3param_t param;
   19751 	dns_rdata_t nrdata = DNS_RDATA_INIT;
   19752 	dns_rdata_t prdata = DNS_RDATA_INIT;
   19753 	unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
   19754 	struct np3event *npe;
   19755 	nsec3param_t *np;
   19756 	dns_zone_t *dummy = NULL;
   19757 	isc_buffer_t b;
   19758 	isc_event_t *e;
   19759 
   19760 	REQUIRE(DNS_ZONE_VALID(zone));
   19761 	REQUIRE(salt != NULL);
   19762 
   19763 	LOCK_ZONE(zone);
   19764 
   19765 	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
   19766 			       setnsec3param, zone, sizeof(struct np3event));
   19767 	if (e == NULL) {
   19768 		result = ISC_R_NOMEMORY;
   19769 		goto failure;
   19770 	}
   19771 
   19772 	npe = (struct np3event *) e;
   19773 	np = &npe->params;
   19774 
   19775 	np->replace = replace;
   19776 	if (hash == 0) {
   19777 		np->length = 0;
   19778 		np->nsec = true;
   19779 	} else {
   19780 		param.common.rdclass = zone->rdclass;
   19781 		param.common.rdtype = dns_rdatatype_nsec3param;
   19782 		ISC_LINK_INIT(&param.common, link);
   19783 		param.mctx = NULL;
   19784 		param.hash = hash;
   19785 		param.flags = flags;
   19786 		param.iterations = iter;
   19787 		param.salt_length = saltlen;
   19788 		param.salt = salt;
   19789 		isc_buffer_init(&b, nbuf, sizeof(nbuf));
   19790 		CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
   19791 					   dns_rdatatype_nsec3param,
   19792 					   &param, &b));
   19793 		dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
   19794 					 np->data, sizeof(np->data));
   19795 		np->length = prdata.length;
   19796 		np->nsec = false;
   19797 	}
   19798 
   19799 	/*
   19800 	 * setnsec3param() will silently return early if the zone does not yet
   19801 	 * have a database.  Prevent that by queueing the event up if zone->db
   19802 	 * is NULL.  All events queued here are subsequently processed by
   19803 	 * receive_secure_db() if it ever gets called or simply freed by
   19804 	 * zone_free() otherwise.
   19805 	 */
   19806 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   19807 	if (zone->db != NULL) {
   19808 		zone_iattach(zone, &dummy);
   19809 		isc_task_send(zone->task, &e);
   19810 	} else {
   19811 		ISC_LIST_APPEND(zone->setnsec3param_queue, e, ev_link);
   19812 		e = NULL;
   19813 	}
   19814 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   19815 
   19816  failure:
   19817 	if (e != NULL) {
   19818 		isc_event_free(&e);
   19819 	}
   19820 	UNLOCK_ZONE(zone);
   19821 	return (result);
   19822 }
   19823 
   19824 isc_result_t
   19825 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
   19826 	REQUIRE(DNS_ZONE_VALID(zone));
   19827 	REQUIRE(loadtime != NULL);
   19828 
   19829 	LOCK_ZONE(zone);
   19830 	*loadtime = zone->loadtime;
   19831 	UNLOCK_ZONE(zone);
   19832 	return (ISC_R_SUCCESS);
   19833 }
   19834 
   19835 isc_result_t
   19836 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
   19837 	REQUIRE(DNS_ZONE_VALID(zone));
   19838 	REQUIRE(expiretime != NULL);
   19839 
   19840 	LOCK_ZONE(zone);
   19841 	*expiretime = zone->expiretime;
   19842 	UNLOCK_ZONE(zone);
   19843 	return (ISC_R_SUCCESS);
   19844 }
   19845 
   19846 isc_result_t
   19847 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
   19848 	REQUIRE(DNS_ZONE_VALID(zone));
   19849 	REQUIRE(refreshtime != NULL);
   19850 
   19851 	LOCK_ZONE(zone);
   19852 	*refreshtime = zone->refreshtime;
   19853 	UNLOCK_ZONE(zone);
   19854 	return (ISC_R_SUCCESS);
   19855 }
   19856 
   19857 isc_result_t
   19858 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
   19859 	REQUIRE(DNS_ZONE_VALID(zone));
   19860 	REQUIRE(refreshkeytime != NULL);
   19861 
   19862 	LOCK_ZONE(zone);
   19863 	*refreshkeytime = zone->refreshkeytime;
   19864 	UNLOCK_ZONE(zone);
   19865 	return (ISC_R_SUCCESS);
   19866 }
   19867 
   19868 unsigned int
   19869 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
   19870 	dns_include_t *include;
   19871 	char **array = NULL;
   19872 	unsigned int n = 0;
   19873 
   19874 	REQUIRE(DNS_ZONE_VALID(zone));
   19875 	REQUIRE(includesp != NULL && *includesp == NULL);
   19876 
   19877 	LOCK_ZONE(zone);
   19878 	if (zone->nincludes == 0)
   19879 		goto done;
   19880 
   19881 	array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
   19882 	if (array == NULL)
   19883 		goto done;
   19884 	for (include = ISC_LIST_HEAD(zone->includes);
   19885 	     include != NULL;
   19886 	     include = ISC_LIST_NEXT(include, link)) {
   19887 		INSIST(n < zone->nincludes);
   19888 		array[n++] = isc_mem_strdup(zone->mctx, include->name);
   19889 	}
   19890 	INSIST(n == zone->nincludes);
   19891 	*includesp = array;
   19892 
   19893  done:
   19894 	UNLOCK_ZONE(zone);
   19895 	return (n);
   19896 }
   19897 
   19898 void
   19899 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
   19900 	REQUIRE(DNS_ZONE_VALID(zone));
   19901 
   19902 	zone->statlevel = level;
   19903 }
   19904 
   19905 dns_zonestat_level_t
   19906 dns_zone_getstatlevel(dns_zone_t *zone) {
   19907 	REQUIRE(DNS_ZONE_VALID(zone));
   19908 
   19909 	return (zone->statlevel);
   19910 }
   19911 
   19912 static void
   19913 setserial(isc_task_t *task, isc_event_t *event) {
   19914 	uint32_t oldserial, desired;
   19915 	const char *me = "setserial";
   19916 	bool commit = false;
   19917 	isc_result_t result;
   19918 	dns_dbversion_t *oldver = NULL, *newver = NULL;
   19919 	dns_zone_t *zone;
   19920 	dns_db_t *db = NULL;
   19921 	dns_diff_t diff;
   19922 	struct ssevent *sse = (struct ssevent *)event;
   19923 	dns_update_log_t log = { update_log_cb, NULL };
   19924 	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
   19925 
   19926 	UNUSED(task);
   19927 
   19928 	zone = event->ev_arg;
   19929 	INSIST(DNS_ZONE_VALID(zone));
   19930 
   19931 	ENTER;
   19932 
   19933 	if (zone->update_disabled)
   19934 		goto failure;
   19935 
   19936 	desired = sse->serial;
   19937 
   19938 	dns_diff_init(zone->mctx, &diff);
   19939 
   19940 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   19941 	if (zone->db != NULL)
   19942 		dns_db_attach(zone->db, &db);
   19943 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   19944 	if (db == NULL)
   19945 		goto failure;
   19946 
   19947 	dns_db_currentversion(db, &oldver);
   19948 	result = dns_db_newversion(db, &newver);
   19949 	if (result != ISC_R_SUCCESS) {
   19950 		dns_zone_log(zone, ISC_LOG_ERROR,
   19951 			     "setserial:dns_db_newversion -> %s",
   19952 			     dns_result_totext(result));
   19953 		goto failure;
   19954 	}
   19955 
   19956 	CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
   19957 				    DNS_DIFFOP_DEL, &oldtuple));
   19958 	CHECK(dns_difftuple_copy(oldtuple, &newtuple));
   19959 	newtuple->op = DNS_DIFFOP_ADD;
   19960 
   19961 	oldserial = dns_soa_getserial(&oldtuple->rdata);
   19962 	if (desired == 0U)
   19963 		desired = 1;
   19964 	if (!isc_serial_gt(desired, oldserial)) {
   19965 		if (desired != oldserial)
   19966 			dns_zone_log(zone, ISC_LOG_INFO,
   19967 				     "setserial: desired serial (%u) "
   19968 				     "out of range (%u-%u)", desired,
   19969 				     oldserial + 1, (oldserial + 0x7fffffff));
   19970 		goto failure;
   19971 	}
   19972 
   19973 	dns_soa_setserial(desired, &newtuple->rdata);
   19974 	CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
   19975 	CHECK(do_one_tuple(&newtuple, db, newver, &diff));
   19976 	result = dns_update_signatures(&log, zone, db,
   19977 				       oldver, newver, &diff,
   19978 				       zone->sigvalidityinterval);
   19979 	if (result != ISC_R_NOTFOUND)
   19980 		CHECK(result);
   19981 
   19982 	/* Write changes to journal file. */
   19983 	CHECK(zone_journal(zone, &diff, NULL, "setserial"));
   19984 	commit = true;
   19985 
   19986 	LOCK_ZONE(zone);
   19987 	zone_needdump(zone, 30);
   19988 	UNLOCK_ZONE(zone);
   19989 
   19990  failure:
   19991 	if (oldtuple != NULL)
   19992 		dns_difftuple_free(&oldtuple);
   19993 	if (newtuple != NULL)
   19994 		dns_difftuple_free(&newtuple);
   19995 	if (oldver != NULL)
   19996 		dns_db_closeversion(db, &oldver, false);
   19997 	if (newver != NULL)
   19998 		dns_db_closeversion(db, &newver, commit);
   19999 	if (db != NULL)
   20000 		dns_db_detach(&db);
   20001 	dns_diff_clear(&diff);
   20002 	isc_event_free(&event);
   20003 	dns_zone_idetach(&zone);
   20004 
   20005 	INSIST(oldver == NULL);
   20006 	INSIST(newver == NULL);
   20007 }
   20008 
   20009 isc_result_t
   20010 dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
   20011 	isc_result_t result = ISC_R_SUCCESS;
   20012 	dns_zone_t *dummy = NULL;
   20013 	isc_event_t *e = NULL;
   20014 	struct ssevent *sse;
   20015 
   20016 	REQUIRE(DNS_ZONE_VALID(zone));
   20017 
   20018 	LOCK_ZONE(zone);
   20019 
   20020 	if (!inline_secure(zone)) {
   20021 		if (!dns_zone_isdynamic(zone, true)) {
   20022 			result = DNS_R_NOTDYNAMIC;
   20023 			goto failure;
   20024 		}
   20025 	}
   20026 
   20027 	if (zone->update_disabled) {
   20028 		result = DNS_R_FROZEN;
   20029 		goto failure;
   20030 	}
   20031 
   20032 	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL,
   20033 			       setserial, zone, sizeof(struct ssevent));
   20034 	if (e == NULL) {
   20035 		result = ISC_R_NOMEMORY;
   20036 		goto failure;
   20037 	}
   20038 
   20039 	sse = (struct ssevent *)e;
   20040 	sse->serial = serial;
   20041 
   20042 	zone_iattach(zone, &dummy);
   20043 	isc_task_send(zone->task, &e);
   20044 
   20045  failure:
   20046 	if (e != NULL)
   20047 		isc_event_free(&e);
   20048 	UNLOCK_ZONE(zone);
   20049 	return (result);
   20050 }
   20051 
   20052 isc_stats_t *
   20053 dns_zone_getgluecachestats(dns_zone_t *zone) {
   20054 	REQUIRE(DNS_ZONE_VALID(zone));
   20055 
   20056 	return (zone->gluecachestats);
   20057 }
   20058 
   20059 bool
   20060 dns_zone_isloaded(const dns_zone_t *zone) {
   20061 	REQUIRE(DNS_ZONE_VALID(zone));
   20062 
   20063 	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED));
   20064 }
   20065 
   20066 isc_result_t
   20067 dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
   20068 	dns_dbversion_t *version = NULL;
   20069 	dns_keytable_t *secroots = NULL;
   20070 	isc_result_t result;
   20071 	dns_name_t *origin;
   20072 
   20073 	const char me[] = "dns_zone_verifydb";
   20074 	ENTER;
   20075 
   20076 	REQUIRE(DNS_ZONE_VALID(zone));
   20077 	REQUIRE(db != NULL);
   20078 
   20079 	if (dns_zone_gettype(zone) != dns_zone_mirror) {
   20080 		return (ISC_R_SUCCESS);
   20081 	}
   20082 
   20083 	if (ver == NULL) {
   20084 		dns_db_currentversion(db, &version);
   20085 	} else {
   20086 		version = ver;
   20087 	}
   20088 
   20089 	if (zone->view != NULL) {
   20090 		result = dns_view_getsecroots(zone->view, &secroots);
   20091 		if (result != ISC_R_SUCCESS) {
   20092 			goto done;
   20093 		}
   20094 	}
   20095 
   20096 	origin = dns_db_origin(db);
   20097 	result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
   20098 				       zone->mctx, true, false);
   20099 
   20100  done:
   20101 	if (secroots != NULL) {
   20102 		dns_keytable_detach(&secroots);
   20103 	}
   20104 
   20105 	if (ver == NULL) {
   20106 		dns_db_closeversion(db, &version, false);
   20107 	}
   20108 
   20109 	if (result != ISC_R_SUCCESS) {
   20110 		dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
   20111 			   isc_result_totext(result));
   20112 		result = DNS_R_VERIFYFAILURE;
   20113 	}
   20114 
   20115 	return (result);
   20116 }
   20117