Home | History | Annotate | Line # | Download | only in dns
zone.c revision 1.2
      1 /*	$NetBSD: zone.c,v 1.2 2018/08/12 13:02:35 christos 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 #include <errno.h>
     18 
     19 #include <isc/file.h>
     20 #include <isc/hex.h>
     21 #include <isc/mutex.h>
     22 #include <isc/pool.h>
     23 #include <isc/print.h>
     24 #include <isc/random.h>
     25 #include <isc/ratelimiter.h>
     26 #include <isc/refcount.h>
     27 #include <isc/rwlock.h>
     28 #include <isc/serial.h>
     29 #include <isc/stats.h>
     30 #include <isc/stdtime.h>
     31 #include <isc/strerror.h>
     32 #include <isc/string.h>
     33 #include <isc/taskpool.h>
     34 #include <isc/thread.h>
     35 #include <isc/timer.h>
     36 #include <isc/util.h>
     37 
     38 #include <dns/acl.h>
     39 #include <dns/adb.h>
     40 #include <dns/callbacks.h>
     41 #include <dns/catz.h>
     42 #include <dns/db.h>
     43 #include <dns/dbiterator.h>
     44 #include <dns/dlz.h>
     45 #include <dns/dnssec.h>
     46 #include <dns/events.h>
     47 #include <dns/journal.h>
     48 #include <dns/keydata.h>
     49 #include <dns/keytable.h>
     50 #include <dns/keyvalues.h>
     51 #include <dns/log.h>
     52 #include <dns/master.h>
     53 #include <dns/masterdump.h>
     54 #include <dns/message.h>
     55 #include <dns/name.h>
     56 #include <dns/nsec.h>
     57 #include <dns/nsec3.h>
     58 #include <dns/peer.h>
     59 #include <dns/private.h>
     60 #include <dns/rcode.h>
     61 #include <dns/rdata.h>
     62 #include <dns/rdataclass.h>
     63 #include <dns/rdatalist.h>
     64 #include <dns/rdataset.h>
     65 #include <dns/rdatasetiter.h>
     66 #include <dns/rdatastruct.h>
     67 #include <dns/rdatatype.h>
     68 #include <dns/request.h>
     69 #include <dns/resolver.h>
     70 #include <dns/result.h>
     71 #include <dns/rriterator.h>
     72 #include <dns/soa.h>
     73 #include <dns/ssu.h>
     74 #include <dns/stats.h>
     75 #include <dns/time.h>
     76 #include <dns/tsig.h>
     77 #include <dns/update.h>
     78 #include <dns/xfrin.h>
     79 #include <dns/zone.h>
     80 #include <dns/zt.h>
     81 
     82 #include <dst/dst.h>
     83 
     84 #include "zone_p.h"
     85 
     86 #define ZONE_MAGIC			ISC_MAGIC('Z', 'O', 'N', 'E')
     87 #define DNS_ZONE_VALID(zone)		ISC_MAGIC_VALID(zone, ZONE_MAGIC)
     88 
     89 #define NOTIFY_MAGIC			ISC_MAGIC('N', 't', 'f', 'y')
     90 #define DNS_NOTIFY_VALID(notify)	ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
     91 
     92 #define STUB_MAGIC			ISC_MAGIC('S', 't', 'u', 'b')
     93 #define DNS_STUB_VALID(stub)		ISC_MAGIC_VALID(stub, STUB_MAGIC)
     94 
     95 #define ZONEMGR_MAGIC			ISC_MAGIC('Z', 'm', 'g', 'r')
     96 #define DNS_ZONEMGR_VALID(stub)		ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
     97 
     98 #define LOAD_MAGIC			ISC_MAGIC('L', 'o', 'a', 'd')
     99 #define DNS_LOAD_VALID(load)		ISC_MAGIC_VALID(load, LOAD_MAGIC)
    100 
    101 #define FORWARD_MAGIC			ISC_MAGIC('F', 'o', 'r', 'w')
    102 #define DNS_FORWARD_VALID(load)		ISC_MAGIC_VALID(load, FORWARD_MAGIC)
    103 
    104 #define IO_MAGIC			ISC_MAGIC('Z', 'm', 'I', 'O')
    105 #define DNS_IO_VALID(load)		ISC_MAGIC_VALID(load, IO_MAGIC)
    106 
    107 /*%
    108  * Ensure 'a' is at least 'min' but not more than 'max'.
    109  */
    110 #define RANGE(a, min, max) \
    111 		(((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
    112 
    113 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
    114 
    115 /*%
    116  * Key flags
    117  */
    118 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
    119 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
    120 #define ALG(x) dst_key_alg(x)
    121 
    122 /*
    123  * Default values.
    124  */
    125 #define DNS_DEFAULT_IDLEIN 3600		/*%< 1 hour */
    126 #define DNS_DEFAULT_IDLEOUT 3600	/*%< 1 hour */
    127 #define MAX_XFER_TIME (2*3600)		/*%< Documented default is 2 hours */
    128 #define RESIGN_DELAY 3600		/*%< 1 hour */
    129 
    130 #ifndef DNS_MAX_EXPIRE
    131 #define DNS_MAX_EXPIRE	14515200	/*%< 24 weeks */
    132 #endif
    133 
    134 #ifndef DNS_DUMP_DELAY
    135 #define DNS_DUMP_DELAY 900		/*%< 15 minutes */
    136 #endif
    137 
    138 typedef struct dns_notify dns_notify_t;
    139 typedef struct dns_stub dns_stub_t;
    140 typedef struct dns_load dns_load_t;
    141 typedef struct dns_forward dns_forward_t;
    142 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
    143 typedef struct dns_io dns_io_t;
    144 typedef ISC_LIST(dns_io_t) dns_iolist_t;
    145 typedef struct dns_signing dns_signing_t;
    146 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
    147 typedef struct dns_nsec3chain dns_nsec3chain_t;
    148 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
    149 typedef struct dns_keyfetch dns_keyfetch_t;
    150 typedef struct dns_asyncload dns_asyncload_t;
    151 typedef struct dns_include dns_include_t;
    152 
    153 #define DNS_ZONE_CHECKLOCK
    154 #ifdef DNS_ZONE_CHECKLOCK
    155 #define LOCK_ZONE(z) \
    156 	 do { LOCK(&(z)->lock); \
    157 	      INSIST((z)->locked == ISC_FALSE); \
    158 	     (z)->locked = ISC_TRUE; \
    159 		} while (/*CONSTCOND*/0)
    160 #define UNLOCK_ZONE(z) \
    161 	do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (/*CONSTCOND*/0)
    162 #define LOCKED_ZONE(z) ((z)->locked)
    163 #define TRYLOCK_ZONE(result, z) \
    164 	do { \
    165 	      result = isc_mutex_trylock(&(z)->lock); \
    166 	      if (result == ISC_R_SUCCESS) {  \
    167 		     INSIST((z)->locked == ISC_FALSE); \
    168 		     (z)->locked = ISC_TRUE; \
    169 	      } \
    170 	} while (/*CONSTCOND*/0)
    171 #else
    172 #define LOCK_ZONE(z) LOCK(&(z)->lock)
    173 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
    174 #define LOCKED_ZONE(z) ISC_TRUE
    175 #define TRYLOCK_ZONE(result, z) \
    176 	do { result = isc_mutex_trylock(&(z)->lock); } while (/*CONSTCOND*/0)
    177 #endif
    178 
    179 #ifdef ISC_RWLOCK_USEATOMIC
    180 #define ZONEDB_INITLOCK(l)	isc_rwlock_init((l), 0, 0)
    181 #define ZONEDB_DESTROYLOCK(l)	isc_rwlock_destroy(l)
    182 #define ZONEDB_LOCK(l, t)	RWLOCK((l), (t))
    183 #define ZONEDB_UNLOCK(l, t)	RWUNLOCK((l), (t))
    184 #else
    185 #define ZONEDB_INITLOCK(l)	isc_mutex_init(l)
    186 #define ZONEDB_DESTROYLOCK(l)	DESTROYLOCK(l)
    187 #define ZONEDB_LOCK(l, t)	LOCK(l)
    188 #define ZONEDB_UNLOCK(l, t)	UNLOCK(l)
    189 #endif
    190 
    191 #ifdef ENABLE_AFL
    192 extern isc_boolean_t dns_fuzzing_resolver;
    193 #endif
    194 
    195 struct dns_zone {
    196 	/* Unlocked */
    197 	unsigned int		magic;
    198 	isc_mutex_t		lock;
    199 #ifdef DNS_ZONE_CHECKLOCK
    200 	isc_boolean_t		locked;
    201 #endif
    202 	isc_mem_t		*mctx;
    203 	isc_refcount_t		erefs;
    204 
    205 #ifdef ISC_RWLOCK_USEATOMIC
    206 	isc_rwlock_t		dblock;
    207 #else
    208 	isc_mutex_t		dblock;
    209 #endif
    210 	dns_db_t		*db;		/* Locked by dblock */
    211 
    212 	/* Locked */
    213 	dns_zonemgr_t		*zmgr;
    214 	ISC_LINK(dns_zone_t)	link;		/* Used by zmgr. */
    215 	isc_timer_t		*timer;
    216 	unsigned int		irefs;
    217 	dns_name_t		origin;
    218 	char			*masterfile;
    219 	ISC_LIST(dns_include_t)	includes;	/* Include files */
    220 	ISC_LIST(dns_include_t)	newincludes;	/* Loading */
    221 	unsigned int		nincludes;
    222 	dns_masterformat_t	masterformat;
    223 	const dns_master_style_t *masterstyle;
    224 	char			*journal;
    225 	isc_int32_t		journalsize;
    226 	dns_rdataclass_t	rdclass;
    227 	dns_zonetype_t		type;
    228 	unsigned int		flags;
    229 	unsigned int		options;
    230 	unsigned int		options2;
    231 	unsigned int		db_argc;
    232 	char			**db_argv;
    233 	isc_time_t		expiretime;
    234 	isc_time_t		refreshtime;
    235 	isc_time_t		dumptime;
    236 	isc_time_t		loadtime;
    237 	isc_time_t		notifytime;
    238 	isc_time_t		resigntime;
    239 	isc_time_t		keywarntime;
    240 	isc_time_t		signingtime;
    241 	isc_time_t		nsec3chaintime;
    242 	isc_time_t		refreshkeytime;
    243 	isc_uint32_t		refreshkeyinterval;
    244 	isc_uint32_t		refreshkeycount;
    245 	isc_uint32_t		refresh;
    246 	isc_uint32_t		retry;
    247 	isc_uint32_t		expire;
    248 	isc_uint32_t		minimum;
    249 	isc_stdtime_t		key_expiry;
    250 	isc_stdtime_t		log_key_expired_timer;
    251 	char			*keydirectory;
    252 
    253 	isc_uint32_t		maxrefresh;
    254 	isc_uint32_t		minrefresh;
    255 	isc_uint32_t		maxretry;
    256 	isc_uint32_t		minretry;
    257 
    258 	isc_uint32_t		maxrecords;
    259 
    260 	isc_sockaddr_t		*masters;
    261 	isc_dscp_t		*masterdscps;
    262 	dns_name_t		**masterkeynames;
    263 	isc_boolean_t		*mastersok;
    264 	unsigned int		masterscnt;
    265 	unsigned int		curmaster;
    266 	isc_sockaddr_t		masteraddr;
    267 	dns_notifytype_t	notifytype;
    268 	isc_sockaddr_t		*notify;
    269 	dns_name_t		**notifykeynames;
    270 	isc_dscp_t		*notifydscp;
    271 	unsigned int		notifycnt;
    272 	isc_sockaddr_t		notifyfrom;
    273 	isc_task_t		*task;
    274 	isc_task_t		*loadtask;
    275 	isc_sockaddr_t		notifysrc4;
    276 	isc_sockaddr_t		notifysrc6;
    277 	isc_sockaddr_t		xfrsource4;
    278 	isc_sockaddr_t		xfrsource6;
    279 	isc_sockaddr_t		altxfrsource4;
    280 	isc_sockaddr_t		altxfrsource6;
    281 	isc_sockaddr_t		sourceaddr;
    282 	isc_dscp_t		notifysrc4dscp;
    283 	isc_dscp_t		notifysrc6dscp;
    284 	isc_dscp_t		xfrsource4dscp;
    285 	isc_dscp_t		xfrsource6dscp;
    286 	isc_dscp_t		altxfrsource4dscp;
    287 	isc_dscp_t		altxfrsource6dscp;
    288 	dns_xfrin_ctx_t		*xfr;		/* task locked */
    289 	dns_tsigkey_t		*tsigkey;	/* key used for xfr */
    290 	/* Access Control Lists */
    291 	dns_acl_t		*update_acl;
    292 	dns_acl_t		*forward_acl;
    293 	dns_acl_t		*notify_acl;
    294 	dns_acl_t		*query_acl;
    295 	dns_acl_t		*queryon_acl;
    296 	dns_acl_t		*xfr_acl;
    297 	isc_boolean_t		update_disabled;
    298 	isc_boolean_t		zero_no_soa_ttl;
    299 	dns_severity_t		check_names;
    300 	ISC_LIST(dns_notify_t)	notifies;
    301 	dns_request_t		*request;
    302 	dns_loadctx_t		*lctx;
    303 	dns_io_t		*readio;
    304 	dns_dumpctx_t		*dctx;
    305 	dns_io_t		*writeio;
    306 	isc_uint32_t		maxxfrin;
    307 	isc_uint32_t		maxxfrout;
    308 	isc_uint32_t		idlein;
    309 	isc_uint32_t		idleout;
    310 	isc_event_t		ctlevent;
    311 	dns_ssutable_t		*ssutable;
    312 	isc_uint32_t		sigvalidityinterval;
    313 	isc_uint32_t		sigresigninginterval;
    314 	dns_view_t		*view;
    315 	dns_view_t		*prev_view;
    316 	dns_checkmxfunc_t	checkmx;
    317 	dns_checksrvfunc_t	checksrv;
    318 	dns_checknsfunc_t	checkns;
    319 	/*%
    320 	 * Zones in certain states such as "waiting for zone transfer"
    321 	 * or "zone transfer in progress" are kept on per-state linked lists
    322 	 * in the zone manager using the 'statelink' field.  The 'statelist'
    323 	 * field points at the list the zone is currently on.  It the zone
    324 	 * is not on any such list, statelist is NULL.
    325 	 */
    326 	ISC_LINK(dns_zone_t)	statelink;
    327 	dns_zonelist_t		*statelist;
    328 	/*%
    329 	 * Statistics counters about zone management.
    330 	 */
    331 	isc_stats_t		*stats;
    332 	/*%
    333 	 * Optional per-zone statistics counters.  Counted outside of this
    334 	 * module.
    335 	 */
    336 	dns_zonestat_level_t	statlevel;
    337 	isc_boolean_t		requeststats_on;
    338 	isc_stats_t		*requeststats;
    339 	dns_stats_t		*rcvquerystats;
    340 	isc_uint32_t		notifydelay;
    341 	dns_isselffunc_t	isself;
    342 	void			*isselfarg;
    343 
    344 	char *			strnamerd;
    345 	char *			strname;
    346 	char *			strrdclass;
    347 	char *			strviewname;
    348 
    349 	/*%
    350 	 * Serial number for deferred journal compaction.
    351 	 */
    352 	isc_uint32_t		compact_serial;
    353 	/*%
    354 	 * Keys that are signing the zone for the first time.
    355 	 */
    356 	dns_signinglist_t	signing;
    357 	dns_nsec3chainlist_t	nsec3chain;
    358 	/*%
    359 	 * Signing / re-signing quantum stopping parameters.
    360 	 */
    361 	isc_uint32_t		signatures;
    362 	isc_uint32_t		nodes;
    363 	dns_rdatatype_t		privatetype;
    364 
    365 	/*%
    366 	 * Autosigning/key-maintenance options
    367 	 */
    368 	isc_uint32_t		keyopts;
    369 
    370 	/*%
    371 	 * True if added by "rndc addzone"
    372 	 */
    373 	isc_boolean_t           added;
    374 
    375 	/*%
    376 	 * True if added by automatically by named.
    377 	 */
    378 	isc_boolean_t           automatic;
    379 
    380 	/*%
    381 	 * response policy data to be relayed to the database
    382 	 */
    383 	dns_rpz_zones_t		*rpzs;
    384 	dns_rpz_num_t		rpz_num;
    385 
    386 	/*%
    387 	 * catalog zone data
    388 	 */
    389 	dns_catz_zones_t	*catzs;
    390 
    391 	/*%
    392 	 * parent catalog zone
    393 	 */
    394 	dns_catz_zone_t		*parentcatz;
    395 
    396 	/*%
    397 	 * Serial number update method.
    398 	 */
    399 	dns_updatemethod_t	updatemethod;
    400 
    401 	/*%
    402 	 * whether ixfr is requested
    403 	 */
    404 	isc_boolean_t		requestixfr;
    405 
    406 	/*%
    407 	 * whether EDNS EXPIRE is requested
    408 	 */
    409 	isc_boolean_t		requestexpire;
    410 
    411 	/*%
    412 	 * Outstanding forwarded UPDATE requests.
    413 	 */
    414 	dns_forwardlist_t	forwards;
    415 
    416 	dns_zone_t		*raw;
    417 	dns_zone_t		*secure;
    418 
    419 	isc_boolean_t		sourceserialset;
    420 	isc_uint32_t		sourceserial;
    421 
    422 	/*%
    423 	 * maximum zone ttl
    424 	 */
    425 	dns_ttl_t		maxttl;
    426 
    427 	/*
    428 	 * Inline zone signing state.
    429 	 */
    430 	dns_diff_t		rss_diff;
    431 	isc_eventlist_t		rss_events;
    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 = ISC_FALSE; \
    447 	} while (/*CONSTCOND*/0)
    448 
    449 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
    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_ZONE_OPTION2(z,o) (((z)->options2 & (o)) != 0)
    505 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
    506 
    507 /* Flags for zone_load() */
    508 #define DNS_ZONELOADFLAG_NOSTAT	0x00000001U	/* Do not stat() master files */
    509 #define DNS_ZONELOADFLAG_THAW	0x00000002U	/* Thaw the zone on successful
    510 						   load. */
    511 
    512 #define UNREACH_CHACHE_SIZE	10U
    513 #define UNREACH_HOLD_TIME	600	/* 10 minutes */
    514 
    515 #define CHECK(op) \
    516 	do { result = (op); \
    517 		if (result != ISC_R_SUCCESS) goto failure; \
    518 	} while (/*CONSTCOND*/0)
    519 
    520 struct dns_unreachable {
    521 	isc_sockaddr_t	remote;
    522 	isc_sockaddr_t	local;
    523 	isc_uint32_t	expire;
    524 	isc_uint32_t	last;
    525 	isc_uint32_t	count;
    526 };
    527 
    528 struct dns_zonemgr {
    529 	unsigned int		magic;
    530 	isc_mem_t *		mctx;
    531 	int			refs;		/* Locked by rwlock */
    532 	isc_taskmgr_t *		taskmgr;
    533 	isc_timermgr_t *	timermgr;
    534 	isc_socketmgr_t *	socketmgr;
    535 	isc_taskpool_t *	zonetasks;
    536 	isc_taskpool_t *	loadtasks;
    537 	isc_task_t *		task;
    538 	isc_pool_t *		mctxpool;
    539 	isc_ratelimiter_t *	notifyrl;
    540 	isc_ratelimiter_t *	refreshrl;
    541 	isc_ratelimiter_t *	startupnotifyrl;
    542 	isc_ratelimiter_t *	startuprefreshrl;
    543 	isc_rwlock_t		rwlock;
    544 	isc_mutex_t		iolock;
    545 	isc_rwlock_t		urlock;
    546 
    547 	/* Locked by rwlock. */
    548 	dns_zonelist_t		zones;
    549 	dns_zonelist_t		waiting_for_xfrin;
    550 	dns_zonelist_t		xfrin_in_progress;
    551 
    552 	/* Configuration data. */
    553 	isc_uint32_t		transfersin;
    554 	isc_uint32_t		transfersperns;
    555 	unsigned int		notifyrate;
    556 	unsigned int		startupnotifyrate;
    557 	unsigned int		serialqueryrate;
    558 	unsigned int		startupserialqueryrate;
    559 
    560 	/* Locked by iolock */
    561 	isc_uint32_t		iolimit;
    562 	isc_uint32_t		ioactive;
    563 	dns_iolist_t		high;
    564 	dns_iolist_t		low;
    565 
    566 	/* Locked by urlock. */
    567 	/* LRU cache */
    568 	struct dns_unreachable	unreachable[UNREACH_CHACHE_SIZE];
    569 };
    570 
    571 /*%
    572  * Hold notify state.
    573  */
    574 struct dns_notify {
    575 	unsigned int		magic;
    576 	unsigned int		flags;
    577 	isc_mem_t		*mctx;
    578 	dns_zone_t		*zone;
    579 	dns_adbfind_t		*find;
    580 	dns_request_t		*request;
    581 	dns_name_t		ns;
    582 	isc_sockaddr_t		dst;
    583 	dns_tsigkey_t		*key;
    584 	isc_dscp_t		dscp;
    585 	ISC_LINK(dns_notify_t)	link;
    586 	isc_event_t		*event;
    587 };
    588 
    589 #define DNS_NOTIFY_NOSOA	0x0001U
    590 #define DNS_NOTIFY_STARTUP	0x0002U
    591 
    592 /*%
    593  *	dns_stub holds state while performing a 'stub' transfer.
    594  *	'db' is the zone's 'db' or a new one if this is the initial
    595  *	transfer.
    596  */
    597 
    598 struct dns_stub {
    599 	unsigned int		magic;
    600 	isc_mem_t		*mctx;
    601 	dns_zone_t		*zone;
    602 	dns_db_t		*db;
    603 	dns_dbversion_t		*version;
    604 };
    605 
    606 /*%
    607  *	Hold load state.
    608  */
    609 struct dns_load {
    610 	unsigned int		magic;
    611 	isc_mem_t		*mctx;
    612 	dns_zone_t		*zone;
    613 	dns_db_t		*db;
    614 	isc_time_t		loadtime;
    615 	dns_rdatacallbacks_t	callbacks;
    616 };
    617 
    618 /*%
    619  *	Hold forward state.
    620  */
    621 struct dns_forward {
    622 	unsigned int		magic;
    623 	isc_mem_t		*mctx;
    624 	dns_zone_t		*zone;
    625 	isc_buffer_t		*msgbuf;
    626 	dns_request_t		*request;
    627 	isc_uint32_t		which;
    628 	isc_sockaddr_t		addr;
    629 	dns_updatecallback_t	callback;
    630 	void			*callback_arg;
    631 	unsigned int		options;
    632 	ISC_LINK(dns_forward_t)	link;
    633 };
    634 
    635 /*%
    636  *	Hold IO request state.
    637  */
    638 struct dns_io {
    639 	unsigned int	magic;
    640 	dns_zonemgr_t	*zmgr;
    641 	isc_boolean_t	high;
    642 	isc_task_t	*task;
    643 	ISC_LINK(dns_io_t) link;
    644 	isc_event_t	*event;
    645 };
    646 
    647 /*%
    648  *	Hold state for when we are signing a zone with a new
    649  *	DNSKEY as result of an update.
    650  */
    651 struct dns_signing {
    652 	unsigned int		magic;
    653 	dns_db_t		*db;
    654 	dns_dbiterator_t	*dbiterator;
    655 	dns_secalg_t		algorithm;
    656 	isc_uint16_t		keyid;
    657 	isc_boolean_t		deleteit;
    658 	isc_boolean_t		done;
    659 	ISC_LINK(dns_signing_t)	link;
    660 };
    661 
    662 struct dns_nsec3chain {
    663 	unsigned int			magic;
    664 	dns_db_t			*db;
    665 	dns_dbiterator_t		*dbiterator;
    666 	dns_rdata_nsec3param_t		nsec3param;
    667 	unsigned char			salt[255];
    668 	isc_boolean_t			done;
    669 	isc_boolean_t			seen_nsec;
    670 	isc_boolean_t			delete_nsec;
    671 	isc_boolean_t			save_delete_nsec;
    672 	ISC_LINK(dns_nsec3chain_t)	link;
    673 };
    674 /*%<
    675  * 'dbiterator' contains a iterator for the database.  If we are creating
    676  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
    677  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
    678  * iterated.
    679  *
    680  * 'nsec3param' contains the parameters of the NSEC3 chain being created
    681  * or removed.
    682  *
    683  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
    684  *
    685  * 'seen_nsec' will be set to true if, while iterating the zone to create a
    686  * NSEC3 chain, a NSEC record is seen.
    687  *
    688  * 'delete_nsec' will be set to true if, at the completion of the creation
    689  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
    690  * are in the process of deleting the NSEC chain.
    691  *
    692  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
    693  * so it can be recovered in the event of a error.
    694  */
    695 
    696 struct dns_keyfetch {
    697 	dns_fixedname_t name;
    698 	dns_rdataset_t keydataset;
    699 	dns_rdataset_t dnskeyset;
    700 	dns_rdataset_t dnskeysigset;
    701 	dns_zone_t *zone;
    702 	dns_db_t *db;
    703 	dns_fetch_t *fetch;
    704 };
    705 
    706 /*%
    707  * Hold state for an asynchronous load
    708  */
    709 struct dns_asyncload {
    710 	dns_zone_t *zone;
    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 queue_xfrin(dns_zone_t *zone);
    745 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
    746 				  dns_diff_t *diff, dns_diffop_t op,
    747 				  dns_name_t *name, dns_ttl_t ttl,
    748 				  dns_rdata_t *rdata);
    749 static void zone_unload(dns_zone_t *zone);
    750 static void zone_expire(dns_zone_t *zone);
    751 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
    752 static void zone_idetach(dns_zone_t **zonep);
    753 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
    754 				   isc_boolean_t dump);
    755 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
    756 static inline void zone_detachdb(dns_zone_t *zone);
    757 static isc_result_t default_journal(dns_zone_t *zone);
    758 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
    759 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
    760 				  isc_time_t loadtime, isc_result_t result);
    761 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
    762 static void zone_shutdown(isc_task_t *, isc_event_t *);
    763 static void zone_loaddone(void *arg, isc_result_t result);
    764 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
    765 				   isc_time_t loadtime);
    766 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
    767 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
    768 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
    769 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
    770 static isc_result_t zone_send_secureserial(dns_zone_t *zone,
    771 					   isc_uint32_t serial);
    772 
    773 #if 0
    774 /* ondestroy example */
    775 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
    776 #endif
    777 
    778 static void refresh_callback(isc_task_t *, isc_event_t *);
    779 static void stub_callback(isc_task_t *, isc_event_t *);
    780 static void queue_soa_query(dns_zone_t *zone);
    781 static void soa_query(isc_task_t *, isc_event_t *);
    782 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
    783 		     dns_stub_t *stub);
    784 static int message_count(dns_message_t *msg, dns_section_t section,
    785 			 dns_rdatatype_t type);
    786 static void notify_cancel(dns_zone_t *zone);
    787 static void notify_find_address(dns_notify_t *notify);
    788 static void notify_send(dns_notify_t *notify);
    789 static isc_result_t notify_createmessage(dns_zone_t *zone,
    790 					 unsigned int flags,
    791 					 dns_message_t **messagep);
    792 static void notify_done(isc_task_t *task, isc_event_t *event);
    793 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
    794 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
    795 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
    796 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
    797 					     dns_zone_t *zone);
    798 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
    799 static void zonemgr_free(dns_zonemgr_t *zmgr);
    800 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
    801 				  isc_task_t *task, isc_taskaction_t action,
    802 				  void *arg, dns_io_t **iop);
    803 static void zonemgr_putio(dns_io_t **iop);
    804 static void zonemgr_cancelio(dns_io_t *io);
    805 
    806 static isc_result_t
    807 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
    808 		 unsigned int *soacount, isc_uint32_t *serial,
    809 		 isc_uint32_t *refresh, isc_uint32_t *retry,
    810 		 isc_uint32_t *expire, isc_uint32_t *minimum,
    811 		 unsigned int *errors);
    812 
    813 static void zone_freedbargs(dns_zone_t *zone);
    814 static void forward_callback(isc_task_t *task, isc_event_t *event);
    815 static void zone_saveunique(dns_zone_t *zone, const char *path,
    816 			    const char *templat);
    817 static void zone_maintenance(dns_zone_t *zone);
    818 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
    819 static void dump_done(void *arg, isc_result_t result);
    820 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
    821 				     isc_uint16_t keyid,
    822 				     isc_boolean_t deleteit);
    823 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
    824 				dns_dbnode_t *node, dns_name_t *name,
    825 				dns_diff_t *diff);
    826 static void zone_rekey(dns_zone_t *zone);
    827 static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
    828 static void setrl(isc_ratelimiter_t *rl, unsigned int *rate,
    829 		  unsigned int value);
    830 
    831 #define ENTER zone_debuglog(zone, me, 1, "enter")
    832 
    833 static const unsigned int dbargc_default = 1;
    834 static const char *dbargv_default[] = { "rbt" };
    835 
    836 #define DNS_ZONE_JITTER_ADD(a, b, c) \
    837 	do { \
    838 		isc_interval_t _i; \
    839 		isc_uint32_t _j; \
    840 		_j = isc_random_jitter((b), (b)/4); \
    841 		isc_interval_set(&_i, _j, 0); \
    842 		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
    843 			dns_zone_log(zone, ISC_LOG_WARNING, \
    844 				     "epoch approaching: upgrade required: " \
    845 				     "now + %s failed", #b); \
    846 			isc_interval_set(&_i, _j/2, 0); \
    847 			(void)isc_time_add((a), &_i, (c)); \
    848 		} \
    849 	} while (/*CONSTCOND*/0)
    850 
    851 #define DNS_ZONE_TIME_ADD(a, b, c) \
    852 	do { \
    853 		isc_interval_t _i; \
    854 		isc_interval_set(&_i, (b), 0); \
    855 		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
    856 			dns_zone_log(zone, ISC_LOG_WARNING, \
    857 				     "epoch approaching: upgrade required: " \
    858 				     "now + %s failed", #b); \
    859 			isc_interval_set(&_i, (b)/2, 0); \
    860 			(void)isc_time_add((a), &_i, (c)); \
    861 		} \
    862 	} while (/*CONSTCOND*/0)
    863 
    864 typedef struct nsec3param nsec3param_t;
    865 struct nsec3param {
    866 	unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
    867 	unsigned int length;
    868 	isc_boolean_t nsec;
    869 	isc_boolean_t replace;
    870 	ISC_LINK(nsec3param_t)	link;
    871 };
    872 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
    873 struct np3event {
    874 	isc_event_t event;
    875 	nsec3param_t params;
    876 };
    877 
    878 struct ssevent {
    879 	isc_event_t event;
    880 	isc_uint32_t serial;
    881 };
    882 
    883 /*%
    884  * Increment resolver-related statistics counters.  Zone must be locked.
    885  */
    886 static inline void
    887 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
    888 	if (zone->stats != NULL)
    889 		isc_stats_increment(zone->stats, counter);
    890 }
    891 
    892 /***
    893  ***	Public functions.
    894  ***/
    895 
    896 isc_result_t
    897 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
    898 	isc_result_t result;
    899 	dns_zone_t *zone;
    900 	isc_time_t now;
    901 
    902 	REQUIRE(zonep != NULL && *zonep == NULL);
    903 	REQUIRE(mctx != NULL);
    904 
    905 	TIME_NOW(&now);
    906 	zone = isc_mem_get(mctx, sizeof(*zone));
    907 	if (zone == NULL) {
    908 		return (ISC_R_NOMEMORY);
    909 	}
    910 
    911 	zone->mctx = NULL;
    912 	isc_mem_attach(mctx, &zone->mctx);
    913 
    914 	result = isc_mutex_init(&zone->lock);
    915 	if (result != ISC_R_SUCCESS) {
    916 		goto free_zone;
    917 	}
    918 
    919 	result = ZONEDB_INITLOCK(&zone->dblock);
    920 	if (result != ISC_R_SUCCESS) {
    921 		goto free_mutex;
    922 	}
    923 
    924 	/* XXX MPA check that all elements are initialised */
    925 #ifdef DNS_ZONE_CHECKLOCK
    926 	zone->locked = ISC_FALSE;
    927 #endif
    928 	zone->db = NULL;
    929 	zone->zmgr = NULL;
    930 	ISC_LINK_INIT(zone, link);
    931 	result = isc_refcount_init(&zone->erefs, 1);	/* Implicit attach. */
    932 	if (result != ISC_R_SUCCESS) {
    933 		goto free_dblock;
    934 	}
    935 	zone->irefs = 0;
    936 	dns_name_init(&zone->origin, NULL);
    937 	zone->strnamerd = NULL;
    938 	zone->strname = NULL;
    939 	zone->strrdclass = NULL;
    940 	zone->strviewname = NULL;
    941 	zone->masterfile = NULL;
    942 	ISC_LIST_INIT(zone->includes);
    943 	ISC_LIST_INIT(zone->newincludes);
    944 	zone->nincludes = 0;
    945 	zone->masterformat = dns_masterformat_none;
    946 	zone->masterstyle = NULL;
    947 	zone->keydirectory = NULL;
    948 	zone->journalsize = -1;
    949 	zone->journal = NULL;
    950 	zone->rdclass = dns_rdataclass_none;
    951 	zone->type = dns_zone_none;
    952 	zone->flags = 0;
    953 	zone->options = 0;
    954 	zone->options2 = 0;
    955 	zone->keyopts = 0;
    956 	zone->db_argc = 0;
    957 	zone->db_argv = NULL;
    958 	isc_time_settoepoch(&zone->expiretime);
    959 	isc_time_settoepoch(&zone->refreshtime);
    960 	isc_time_settoepoch(&zone->dumptime);
    961 	isc_time_settoepoch(&zone->loadtime);
    962 	zone->notifytime = now;
    963 	isc_time_settoepoch(&zone->resigntime);
    964 	isc_time_settoepoch(&zone->keywarntime);
    965 	isc_time_settoepoch(&zone->signingtime);
    966 	isc_time_settoepoch(&zone->nsec3chaintime);
    967 	isc_time_settoepoch(&zone->refreshkeytime);
    968 	zone->refreshkeyinterval = 0;
    969 	zone->refreshkeycount = 0;
    970 	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
    971 	zone->retry = DNS_ZONE_DEFAULTRETRY;
    972 	zone->expire = 0;
    973 	zone->minimum = 0;
    974 	zone->maxrefresh = DNS_ZONE_MAXREFRESH;
    975 	zone->minrefresh = DNS_ZONE_MINREFRESH;
    976 	zone->maxretry = DNS_ZONE_MAXRETRY;
    977 	zone->minretry = DNS_ZONE_MINRETRY;
    978 	zone->masters = NULL;
    979 	zone->masterdscps = NULL;
    980 	zone->masterkeynames = NULL;
    981 	zone->mastersok = NULL;
    982 	zone->masterscnt = 0;
    983 	zone->curmaster = 0;
    984 	zone->maxttl = 0;
    985 	zone->notify = NULL;
    986 	zone->notifykeynames = NULL;
    987 	zone->notifydscp = NULL;
    988 	zone->notifytype = dns_notifytype_yes;
    989 	zone->notifycnt = 0;
    990 	zone->task = NULL;
    991 	zone->loadtask = NULL;
    992 	zone->update_acl = NULL;
    993 	zone->forward_acl = NULL;
    994 	zone->notify_acl = NULL;
    995 	zone->query_acl = NULL;
    996 	zone->queryon_acl = NULL;
    997 	zone->xfr_acl = NULL;
    998 	zone->update_disabled = ISC_FALSE;
    999 	zone->zero_no_soa_ttl = ISC_TRUE;
   1000 	zone->check_names = dns_severity_ignore;
   1001 	zone->request = NULL;
   1002 	zone->lctx = NULL;
   1003 	zone->readio = NULL;
   1004 	zone->dctx = NULL;
   1005 	zone->writeio = NULL;
   1006 	zone->timer = NULL;
   1007 	zone->idlein = DNS_DEFAULT_IDLEIN;
   1008 	zone->idleout = DNS_DEFAULT_IDLEOUT;
   1009 	zone->log_key_expired_timer = 0;
   1010 	ISC_LIST_INIT(zone->notifies);
   1011 	isc_sockaddr_any(&zone->notifysrc4);
   1012 	isc_sockaddr_any6(&zone->notifysrc6);
   1013 	isc_sockaddr_any(&zone->xfrsource4);
   1014 	isc_sockaddr_any6(&zone->xfrsource6);
   1015 	isc_sockaddr_any(&zone->altxfrsource4);
   1016 	isc_sockaddr_any6(&zone->altxfrsource6);
   1017 	zone->notifysrc4dscp = -1;
   1018 	zone->notifysrc6dscp = -1;
   1019 	zone->xfrsource4dscp = -1;
   1020 	zone->xfrsource6dscp = -1;
   1021 	zone->altxfrsource4dscp = -1;
   1022 	zone->altxfrsource6dscp = -1;
   1023 	zone->xfr = NULL;
   1024 	zone->tsigkey = NULL;
   1025 	zone->maxxfrin = MAX_XFER_TIME;
   1026 	zone->maxxfrout = MAX_XFER_TIME;
   1027 	zone->ssutable = NULL;
   1028 	zone->sigvalidityinterval = 30 * 24 * 3600;
   1029 	zone->sigresigninginterval = 7 * 24 * 3600;
   1030 	zone->view = NULL;
   1031 	zone->prev_view = NULL;
   1032 	zone->checkmx = NULL;
   1033 	zone->checksrv = NULL;
   1034 	zone->checkns = NULL;
   1035 	ISC_LINK_INIT(zone, statelink);
   1036 	zone->statelist = NULL;
   1037 	zone->stats = NULL;
   1038 	zone->requeststats_on = ISC_FALSE;
   1039 	zone->statlevel = dns_zonestat_none;
   1040 	zone->requeststats = NULL;
   1041 	zone->rcvquerystats = NULL;
   1042 	zone->notifydelay = 5;
   1043 	zone->isself = NULL;
   1044 	zone->isselfarg = NULL;
   1045 	ISC_LIST_INIT(zone->signing);
   1046 	ISC_LIST_INIT(zone->nsec3chain);
   1047 	zone->signatures = 10;
   1048 	zone->nodes = 100;
   1049 	zone->privatetype = (dns_rdatatype_t)0xffffU;
   1050 	zone->added = ISC_FALSE;
   1051 	zone->automatic = ISC_FALSE;
   1052 	zone->rpzs = NULL;
   1053 	zone->rpz_num = DNS_RPZ_INVALID_NUM;
   1054 
   1055 	zone->catzs = NULL;
   1056 	zone->parentcatz = NULL;
   1057 
   1058 	ISC_LIST_INIT(zone->forwards);
   1059 	zone->raw = NULL;
   1060 	zone->secure = NULL;
   1061 	zone->sourceserial = 0;
   1062 	zone->sourceserialset = ISC_FALSE;
   1063 	zone->requestixfr = ISC_TRUE;
   1064 	zone->requestexpire = ISC_TRUE;
   1065 	ISC_LIST_INIT(zone->rss_events);
   1066 	zone->rss_db = NULL;
   1067 	zone->rss_raw = NULL;
   1068 	zone->rss_newver = NULL;
   1069 	zone->rss_oldver = NULL;
   1070 	zone->rss_event = NULL;
   1071 	zone->rss_state = NULL;
   1072 	zone->updatemethod = dns_updatemethod_increment;
   1073 	zone->maxrecords = 0U;
   1074 
   1075 	zone->magic = ZONE_MAGIC;
   1076 
   1077 	zone->gluecachestats = NULL;
   1078 	result = isc_stats_create(mctx, &zone->gluecachestats,
   1079 				  dns_gluecachestatscounter_max);
   1080 	if (result != ISC_R_SUCCESS) {
   1081 		goto free_erefs;
   1082 	}
   1083 
   1084 	/* Must be after magic is set. */
   1085 	result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
   1086 	if (result != ISC_R_SUCCESS) {
   1087 		goto free_stats;
   1088 	}
   1089 
   1090 	ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
   1091 		       DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
   1092 		       NULL, NULL);
   1093 	*zonep = zone;
   1094 	return (ISC_R_SUCCESS);
   1095 
   1096  free_stats:
   1097 	if (zone->gluecachestats != NULL)
   1098 		isc_stats_detach(&zone->gluecachestats);
   1099 
   1100  free_erefs:
   1101 	isc_refcount_decrement(&zone->erefs, NULL);
   1102 	isc_refcount_destroy(&zone->erefs);
   1103 
   1104  free_dblock:
   1105 	ZONEDB_DESTROYLOCK(&zone->dblock);
   1106 
   1107  free_mutex:
   1108 	DESTROYLOCK(&zone->lock);
   1109 
   1110  free_zone:
   1111 	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
   1112 	return (result);
   1113 }
   1114 
   1115 /*
   1116  * Free a zone.  Because we require that there be no more
   1117  * outstanding events or references, no locking is necessary.
   1118  */
   1119 static void
   1120 zone_free(dns_zone_t *zone) {
   1121 	isc_mem_t *mctx = NULL;
   1122 	dns_signing_t *signing;
   1123 	dns_nsec3chain_t *nsec3chain;
   1124 	dns_include_t *include;
   1125 
   1126 	REQUIRE(DNS_ZONE_VALID(zone));
   1127 	REQUIRE(isc_refcount_current(&zone->erefs) == 0);
   1128 	REQUIRE(zone->irefs == 0);
   1129 	REQUIRE(!LOCKED_ZONE(zone));
   1130 	REQUIRE(zone->timer == NULL);
   1131 	REQUIRE(zone->zmgr == NULL);
   1132 
   1133 	/*
   1134 	 * Managed objects.  Order is important.
   1135 	 */
   1136 	if (zone->request != NULL) {
   1137 		dns_request_destroy(&zone->request); /* XXXMPA */
   1138 	}
   1139 	INSIST(zone->readio == NULL);
   1140 	INSIST(zone->statelist == NULL);
   1141 	INSIST(zone->writeio == NULL);
   1142 
   1143 	if (zone->task != NULL) {
   1144 		isc_task_detach(&zone->task);
   1145 	}
   1146 	if (zone->loadtask != NULL) {
   1147 		isc_task_detach(&zone->loadtask);
   1148 	}
   1149 	if (zone->view != NULL) {
   1150 		dns_view_weakdetach(&zone->view);
   1151 	}
   1152 	if (zone->prev_view != NULL) {
   1153 		dns_view_weakdetach(&zone->prev_view);
   1154 	}
   1155 
   1156 	/* Unmanaged objects */
   1157 	for (signing = ISC_LIST_HEAD(zone->signing);
   1158 	     signing != NULL;
   1159 	     signing = ISC_LIST_HEAD(zone->signing)) {
   1160 		ISC_LIST_UNLINK(zone->signing, signing, link);
   1161 		dns_db_detach(&signing->db);
   1162 		dns_dbiterator_destroy(&signing->dbiterator);
   1163 		isc_mem_put(zone->mctx, signing, sizeof *signing);
   1164 	}
   1165 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   1166 	     nsec3chain != NULL;
   1167 	     nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
   1168 		ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
   1169 		dns_db_detach(&nsec3chain->db);
   1170 		dns_dbiterator_destroy(&nsec3chain->dbiterator);
   1171 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   1172 	}
   1173 	for (include = ISC_LIST_HEAD(zone->includes);
   1174 	     include != NULL;
   1175 	     include = ISC_LIST_HEAD(zone->includes)) {
   1176 		ISC_LIST_UNLINK(zone->includes, include, link);
   1177 		isc_mem_free(zone->mctx, include->name);
   1178 		isc_mem_put(zone->mctx, include, sizeof *include);
   1179 	}
   1180 	for (include = ISC_LIST_HEAD(zone->newincludes);
   1181 	     include != NULL;
   1182 	     include = ISC_LIST_HEAD(zone->newincludes)) {
   1183 		ISC_LIST_UNLINK(zone->newincludes, include, link);
   1184 		isc_mem_free(zone->mctx, include->name);
   1185 		isc_mem_put(zone->mctx, include, sizeof *include);
   1186 	}
   1187 	if (zone->masterfile != NULL) {
   1188 		isc_mem_free(zone->mctx, zone->masterfile);
   1189 	}
   1190 	zone->masterfile = NULL;
   1191 	if (zone->keydirectory != NULL) {
   1192 		isc_mem_free(zone->mctx, zone->keydirectory);
   1193 	}
   1194 	zone->keydirectory = NULL;
   1195 	zone->journalsize = -1;
   1196 	if (zone->journal != NULL) {
   1197 		isc_mem_free(zone->mctx, zone->journal);
   1198 	}
   1199 	zone->journal = NULL;
   1200 	if (zone->stats != NULL) {
   1201 		isc_stats_detach(&zone->stats);
   1202 	}
   1203 	if (zone->requeststats != NULL) {
   1204 		isc_stats_detach(&zone->requeststats);
   1205 	}
   1206 	if (zone->rcvquerystats != NULL){
   1207 		dns_stats_detach(&zone->rcvquerystats);
   1208 	}
   1209 	if (zone->db != NULL) {
   1210 		zone_detachdb(zone);
   1211 	}
   1212 	if (zone->rpzs != NULL) {
   1213 		REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
   1214 		dns_rpz_detach_rpzs(&zone->rpzs);
   1215 		zone->rpz_num = DNS_RPZ_INVALID_NUM;
   1216 	}
   1217 	if (zone->catzs != NULL) {
   1218 		dns_catz_catzs_detach(&zone->catzs);
   1219 	}
   1220 	zone_freedbargs(zone);
   1221 	RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL,
   1222 						  NULL, 0) == ISC_R_SUCCESS);
   1223 	RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0) == ISC_R_SUCCESS);
   1224 	zone->check_names = dns_severity_ignore;
   1225 	if (zone->update_acl != NULL) {
   1226 		dns_acl_detach(&zone->update_acl);
   1227 	}
   1228 	if (zone->forward_acl != NULL) {
   1229 		dns_acl_detach(&zone->forward_acl);
   1230 	}
   1231 	if (zone->notify_acl != NULL) {
   1232 		dns_acl_detach(&zone->notify_acl);
   1233 	}
   1234 	if (zone->query_acl != NULL) {
   1235 		dns_acl_detach(&zone->query_acl);
   1236 	}
   1237 	if (zone->queryon_acl != NULL) {
   1238 		dns_acl_detach(&zone->queryon_acl);
   1239 	}
   1240 	if (zone->xfr_acl != NULL) {
   1241 		dns_acl_detach(&zone->xfr_acl);
   1242 	}
   1243 	if (dns_name_dynamic(&zone->origin)) {
   1244 		dns_name_free(&zone->origin, zone->mctx);
   1245 	}
   1246 	if (zone->strnamerd != NULL) {
   1247 		isc_mem_free(zone->mctx, zone->strnamerd);
   1248 	}
   1249 	if (zone->strname != NULL) {
   1250 		isc_mem_free(zone->mctx, zone->strname);
   1251 	}
   1252 	if (zone->strrdclass != NULL) {
   1253 		isc_mem_free(zone->mctx, zone->strrdclass);
   1254 	}
   1255 	if (zone->strviewname != NULL) {
   1256 		isc_mem_free(zone->mctx, zone->strviewname);
   1257 	}
   1258 	if (zone->ssutable != NULL) {
   1259 		dns_ssutable_detach(&zone->ssutable);
   1260 	}
   1261 	if (zone->gluecachestats != NULL) {
   1262 		isc_stats_detach(&zone->gluecachestats);
   1263 	}
   1264 
   1265 	/* last stuff */
   1266 	ZONEDB_DESTROYLOCK(&zone->dblock);
   1267 	DESTROYLOCK(&zone->lock);
   1268 	isc_refcount_destroy(&zone->erefs);
   1269 	zone->magic = 0;
   1270 	mctx = zone->mctx;
   1271 	isc_mem_put(mctx, zone, sizeof(*zone));
   1272 	isc_mem_detach(&mctx);
   1273 }
   1274 
   1275 /*
   1276  * Returns ISC_TRUE iff this the signed side of an inline-signing zone.
   1277  * Caller should hold zone lock.
   1278  */
   1279 static inline isc_boolean_t
   1280 inline_secure(dns_zone_t *zone) {
   1281 	REQUIRE(DNS_ZONE_VALID(zone));
   1282 	if (zone->raw != NULL)
   1283 		return (ISC_TRUE);
   1284 	return (ISC_FALSE);
   1285 }
   1286 
   1287 /*
   1288  * Returns ISC_TRUE iff this the unsigned side of an inline-signing zone
   1289  * Caller should hold zone lock.
   1290  */
   1291 static inline isc_boolean_t
   1292 inline_raw(dns_zone_t *zone) {
   1293 	REQUIRE(DNS_ZONE_VALID(zone));
   1294 	if (zone->secure != NULL)
   1295 		return (ISC_TRUE);
   1296 	return (ISC_FALSE);
   1297 }
   1298 
   1299 /*
   1300  *	Single shot.
   1301  */
   1302 void
   1303 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
   1304 	char namebuf[1024];
   1305 
   1306 	REQUIRE(DNS_ZONE_VALID(zone));
   1307 	REQUIRE(rdclass != dns_rdataclass_none);
   1308 
   1309 	/*
   1310 	 * Test and set.
   1311 	 */
   1312 	LOCK_ZONE(zone);
   1313 	INSIST(zone != zone->raw);
   1314 	REQUIRE(zone->rdclass == dns_rdataclass_none ||
   1315 		zone->rdclass == rdclass);
   1316 	zone->rdclass = rdclass;
   1317 
   1318 	if (zone->strnamerd != NULL)
   1319 		isc_mem_free(zone->mctx, zone->strnamerd);
   1320 	if (zone->strrdclass != NULL)
   1321 		isc_mem_free(zone->mctx, zone->strrdclass);
   1322 
   1323 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1324 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1325 	zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
   1326 	zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
   1327 
   1328 	if (inline_secure(zone))
   1329 		dns_zone_setclass(zone->raw, rdclass);
   1330 	UNLOCK_ZONE(zone);
   1331 }
   1332 
   1333 dns_rdataclass_t
   1334 dns_zone_getclass(dns_zone_t *zone) {
   1335 	REQUIRE(DNS_ZONE_VALID(zone));
   1336 
   1337 	return (zone->rdclass);
   1338 }
   1339 
   1340 void
   1341 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
   1342 	REQUIRE(DNS_ZONE_VALID(zone));
   1343 
   1344 	LOCK_ZONE(zone);
   1345 	zone->notifytype = notifytype;
   1346 	UNLOCK_ZONE(zone);
   1347 }
   1348 
   1349 isc_result_t
   1350 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
   1351 	isc_result_t result;
   1352 	unsigned int soacount;
   1353 
   1354 	REQUIRE(DNS_ZONE_VALID(zone));
   1355 	REQUIRE(serialp != NULL);
   1356 
   1357 	LOCK_ZONE(zone);
   1358 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   1359 	if (zone->db != NULL) {
   1360 		result = zone_get_from_db(zone, zone->db, NULL, &soacount,
   1361 					  serialp, NULL, NULL, NULL, NULL,
   1362 					  NULL);
   1363 		if (result == ISC_R_SUCCESS && soacount == 0)
   1364 			result = ISC_R_FAILURE;
   1365 	} else
   1366 		result = DNS_R_NOTLOADED;
   1367 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   1368 	UNLOCK_ZONE(zone);
   1369 
   1370 	return (result);
   1371 }
   1372 
   1373 isc_uint32_t
   1374 dns_zone_getserial(dns_zone_t *zone) {
   1375 	isc_result_t result;
   1376 	isc_uint32_t serial;
   1377 
   1378 	result = dns_zone_getserial2(zone, &serial);
   1379 	if (result != ISC_R_SUCCESS)
   1380 		serial = 0; /* XXX: not really correct, but no other choice */
   1381 
   1382 	return (serial);
   1383 }
   1384 
   1385 /*
   1386  *	Single shot.
   1387  */
   1388 void
   1389 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
   1390 	char namebuf[1024];
   1391 
   1392 	REQUIRE(DNS_ZONE_VALID(zone));
   1393 	REQUIRE(type != dns_zone_none);
   1394 
   1395 	/*
   1396 	 * Test and set.
   1397 	 */
   1398 	LOCK_ZONE(zone);
   1399 	REQUIRE(zone->type == dns_zone_none || zone->type == type);
   1400 	zone->type = type;
   1401 
   1402 	if (zone->strnamerd != NULL)
   1403 		isc_mem_free(zone->mctx, zone->strnamerd);
   1404 
   1405 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1406 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1407 	UNLOCK_ZONE(zone);
   1408 }
   1409 
   1410 static void
   1411 zone_freedbargs(dns_zone_t *zone) {
   1412 	unsigned int i;
   1413 
   1414 	/* Free the old database argument list. */
   1415 	if (zone->db_argv != NULL) {
   1416 		for (i = 0; i < zone->db_argc; i++)
   1417 			isc_mem_free(zone->mctx, zone->db_argv[i]);
   1418 		isc_mem_put(zone->mctx, zone->db_argv,
   1419 			    zone->db_argc * sizeof(*zone->db_argv));
   1420 	}
   1421 	zone->db_argc = 0;
   1422 	zone->db_argv = NULL;
   1423 }
   1424 
   1425 isc_result_t
   1426 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
   1427 	size_t size = 0;
   1428 	unsigned int i;
   1429 	isc_result_t result = ISC_R_SUCCESS;
   1430 	void *mem;
   1431 	char **tmp, *tmp2, *base;
   1432 
   1433 	REQUIRE(DNS_ZONE_VALID(zone));
   1434 	REQUIRE(argv != NULL && *argv == NULL);
   1435 
   1436 	LOCK_ZONE(zone);
   1437 	size = (zone->db_argc + 1) * sizeof(char *);
   1438 	for (i = 0; i < zone->db_argc; i++)
   1439 		size += strlen(zone->db_argv[i]) + 1;
   1440 	mem = isc_mem_allocate(mctx, size);
   1441 	if (mem != NULL) {
   1442 		tmp = mem;
   1443 		tmp2 = mem;
   1444 		base = mem;
   1445 		tmp2 += (zone->db_argc + 1) * sizeof(char *);
   1446 		for (i = 0; i < zone->db_argc; i++) {
   1447 			*tmp++ = tmp2;
   1448 			strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
   1449 			tmp2 += strlen(tmp2) + 1;
   1450 		}
   1451 		*tmp = NULL;
   1452 	} else
   1453 		result = ISC_R_NOMEMORY;
   1454 	UNLOCK_ZONE(zone);
   1455 	*argv = mem;
   1456 	return (result);
   1457 }
   1458 
   1459 isc_result_t
   1460 dns_zone_setdbtype(dns_zone_t *zone,
   1461 		   unsigned int dbargc, const char * const *dbargv)
   1462 {
   1463 	isc_result_t result = ISC_R_SUCCESS;
   1464 	char **argv = NULL;
   1465 	unsigned int i;
   1466 
   1467 	REQUIRE(DNS_ZONE_VALID(zone));
   1468 	REQUIRE(dbargc >= 1);
   1469 	REQUIRE(dbargv != NULL);
   1470 
   1471 	LOCK_ZONE(zone);
   1472 
   1473 	/* Set up a new database argument list. */
   1474 	argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
   1475 	if (argv == NULL) {
   1476 		goto nomem;
   1477 	}
   1478 	for (i = 0; i < dbargc; i++) {
   1479 		argv[i] = NULL;
   1480 	}
   1481 	for (i = 0; i < dbargc; i++) {
   1482 		argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
   1483 		if (argv[i] == NULL)
   1484 			goto nomem;
   1485 	}
   1486 
   1487 	/* Free the old list. */
   1488 	zone_freedbargs(zone);
   1489 
   1490 	zone->db_argc = dbargc;
   1491 	zone->db_argv = argv;
   1492 	result = ISC_R_SUCCESS;
   1493 	goto unlock;
   1494 
   1495  nomem:
   1496 	if (argv != NULL) {
   1497 		for (i = 0; i < dbargc; i++) {
   1498 			if (argv[i] != NULL) {
   1499 				isc_mem_free(zone->mctx, argv[i]);
   1500 			}
   1501 		}
   1502 		isc_mem_put(zone->mctx, argv, dbargc * sizeof(*argv));
   1503 	}
   1504 	result = ISC_R_NOMEMORY;
   1505 
   1506  unlock:
   1507 	UNLOCK_ZONE(zone);
   1508 	return (result);
   1509 }
   1510 
   1511 static void
   1512 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
   1513 	char namebuf[1024];
   1514 
   1515 	if (zone->prev_view == NULL && zone->view != NULL) {
   1516 		dns_view_weakattach(zone->view, &zone->prev_view);
   1517 	}
   1518 
   1519 	INSIST(zone != zone->raw);
   1520 	if (zone->view != NULL) {
   1521 		dns_view_weakdetach(&zone->view);
   1522 	}
   1523 	dns_view_weakattach(view, &zone->view);
   1524 
   1525 	if (zone->strviewname != NULL) {
   1526 		isc_mem_free(zone->mctx, zone->strviewname);
   1527 	}
   1528 	if (zone->strnamerd != NULL) {
   1529 		isc_mem_free(zone->mctx, zone->strnamerd);
   1530 	}
   1531 
   1532 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1533 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1534 	zone_viewname_tostr(zone, namebuf, sizeof namebuf);
   1535 	zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
   1536 
   1537 	if (inline_secure(zone)) {
   1538 		dns_zone_setview(zone->raw, view);
   1539 	}
   1540 }
   1541 
   1542 void
   1543 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
   1544 	REQUIRE(DNS_ZONE_VALID(zone));
   1545 
   1546 	LOCK_ZONE(zone);
   1547 	dns_zone_setview_helper(zone, view);
   1548 	UNLOCK_ZONE(zone);
   1549 }
   1550 
   1551 dns_view_t *
   1552 dns_zone_getview(dns_zone_t *zone) {
   1553 	REQUIRE(DNS_ZONE_VALID(zone));
   1554 
   1555 	return (zone->view);
   1556 }
   1557 
   1558 void
   1559 dns_zone_setviewcommit(dns_zone_t *zone) {
   1560 	REQUIRE(DNS_ZONE_VALID(zone));
   1561 
   1562 	LOCK_ZONE(zone);
   1563 	if (zone->prev_view != NULL)
   1564 		dns_view_weakdetach(&zone->prev_view);
   1565 	UNLOCK_ZONE(zone);
   1566 }
   1567 
   1568 void
   1569 dns_zone_setviewrevert(dns_zone_t *zone) {
   1570 	REQUIRE(DNS_ZONE_VALID(zone));
   1571 
   1572 	LOCK_ZONE(zone);
   1573 	if (zone->prev_view != NULL) {
   1574 		dns_zone_setview_helper(zone, zone->prev_view);
   1575 		dns_view_weakdetach(&zone->prev_view);
   1576 	}
   1577 	UNLOCK_ZONE(zone);
   1578 }
   1579 
   1580 isc_result_t
   1581 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
   1582 	isc_result_t result;
   1583 	char namebuf[1024];
   1584 
   1585 	REQUIRE(DNS_ZONE_VALID(zone));
   1586 	REQUIRE(origin != NULL);
   1587 
   1588 	LOCK_ZONE(zone);
   1589 	INSIST(zone != zone->raw);
   1590 	if (dns_name_dynamic(&zone->origin)) {
   1591 		dns_name_free(&zone->origin, zone->mctx);
   1592 		dns_name_init(&zone->origin, NULL);
   1593 	}
   1594 	result = dns_name_dup(origin, zone->mctx, &zone->origin);
   1595 
   1596 	if (zone->strnamerd != NULL)
   1597 		isc_mem_free(zone->mctx, zone->strnamerd);
   1598 	if (zone->strname != NULL)
   1599 		isc_mem_free(zone->mctx, zone->strname);
   1600 
   1601 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
   1602 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
   1603 	zone_name_tostr(zone, namebuf, sizeof namebuf);
   1604 	zone->strname = isc_mem_strdup(zone->mctx, namebuf);
   1605 
   1606 	if (result == ISC_R_SUCCESS && inline_secure(zone))
   1607 		result = dns_zone_setorigin(zone->raw, origin);
   1608 	UNLOCK_ZONE(zone);
   1609 	return (result);
   1610 }
   1611 
   1612 static isc_result_t
   1613 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
   1614 	char *copy;
   1615 
   1616 	if (value != NULL) {
   1617 		copy = isc_mem_strdup(zone->mctx, value);
   1618 		if (copy == NULL)
   1619 			return (ISC_R_NOMEMORY);
   1620 	} else {
   1621 		copy = NULL;
   1622 	}
   1623 
   1624 	if (*field != NULL)
   1625 		isc_mem_free(zone->mctx, *field);
   1626 
   1627 	*field = copy;
   1628 	return (ISC_R_SUCCESS);
   1629 }
   1630 
   1631 isc_result_t
   1632 dns_zone_setfile(dns_zone_t *zone, const char *file) {
   1633 	return (dns_zone_setfile3(zone, file, dns_masterformat_text,
   1634 				  &dns_master_style_default));
   1635 }
   1636 
   1637 isc_result_t
   1638 dns_zone_setfile2(dns_zone_t *zone, const char *file,
   1639 		  dns_masterformat_t format)
   1640 {
   1641 	return (dns_zone_setfile3(zone, file, format,
   1642 				  &dns_master_style_default));
   1643 }
   1644 
   1645 isc_result_t
   1646 dns_zone_setfile3(dns_zone_t *zone, const char *file,
   1647 		  dns_masterformat_t format,
   1648 		  const dns_master_style_t *style)
   1649 {
   1650 	isc_result_t result = ISC_R_SUCCESS;
   1651 
   1652 	REQUIRE(DNS_ZONE_VALID(zone));
   1653 
   1654 	LOCK_ZONE(zone);
   1655 	result = dns_zone_setstring(zone, &zone->masterfile, file);
   1656 	if (result == ISC_R_SUCCESS) {
   1657 		zone->masterformat = format;
   1658 		if (format == dns_masterformat_text)
   1659 			zone->masterstyle = style;
   1660 		result = default_journal(zone);
   1661 	}
   1662 	UNLOCK_ZONE(zone);
   1663 
   1664 	return (result);
   1665 }
   1666 
   1667 const char *
   1668 dns_zone_getfile(dns_zone_t *zone) {
   1669 	REQUIRE(DNS_ZONE_VALID(zone));
   1670 
   1671 	return (zone->masterfile);
   1672 }
   1673 
   1674 dns_ttl_t
   1675 dns_zone_getmaxttl(dns_zone_t *zone) {
   1676 	REQUIRE(DNS_ZONE_VALID(zone));
   1677 
   1678 	return (zone->maxttl);
   1679 }
   1680 
   1681 void
   1682 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
   1683 	REQUIRE(DNS_ZONE_VALID(zone));
   1684 
   1685 	LOCK_ZONE(zone);
   1686 	if (maxttl != 0)
   1687 		zone->options2 |= DNS_ZONEOPT2_CHECKTTL;
   1688 	else
   1689 		zone->options2 &= ~DNS_ZONEOPT2_CHECKTTL;
   1690 	zone->maxttl = maxttl;
   1691 	UNLOCK_ZONE(zone);
   1692 
   1693 	return;
   1694 }
   1695 
   1696 static isc_result_t
   1697 default_journal(dns_zone_t *zone) {
   1698 	isc_result_t result;
   1699 	char *journal;
   1700 
   1701 	REQUIRE(DNS_ZONE_VALID(zone));
   1702 	REQUIRE(LOCKED_ZONE(zone));
   1703 
   1704 	if (zone->masterfile != NULL) {
   1705 		/* Calculate string length including '\0'. */
   1706 		int len = strlen(zone->masterfile) + sizeof(".jnl");
   1707 		journal = isc_mem_allocate(zone->mctx, len);
   1708 		if (journal == NULL)
   1709 			return (ISC_R_NOMEMORY);
   1710 		strlcpy(journal, zone->masterfile, len);
   1711 		strlcat(journal, ".jnl", len);
   1712 	} else {
   1713 		journal = NULL;
   1714 	}
   1715 	result = dns_zone_setstring(zone, &zone->journal, journal);
   1716 	if (journal != NULL)
   1717 		isc_mem_free(zone->mctx, journal);
   1718 	return (result);
   1719 }
   1720 
   1721 isc_result_t
   1722 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
   1723 	isc_result_t result = ISC_R_SUCCESS;
   1724 
   1725 	REQUIRE(DNS_ZONE_VALID(zone));
   1726 
   1727 	LOCK_ZONE(zone);
   1728 	result = dns_zone_setstring(zone, &zone->journal, myjournal);
   1729 	UNLOCK_ZONE(zone);
   1730 
   1731 	return (result);
   1732 }
   1733 
   1734 char *
   1735 dns_zone_getjournal(dns_zone_t *zone) {
   1736 	REQUIRE(DNS_ZONE_VALID(zone));
   1737 
   1738 	return (zone->journal);
   1739 }
   1740 
   1741 /*
   1742  * Return true iff the zone is "dynamic", in the sense that the zone's
   1743  * master file (if any) is written by the server, rather than being
   1744  * updated manually and read by the server.
   1745  *
   1746  * This is true for slave zones, stub zones, key zones, and zones that
   1747  * allow dynamic updates either by having an update policy ("ssutable")
   1748  * or an "allow-update" ACL with a value other than exactly "{ none; }".
   1749  */
   1750 isc_boolean_t
   1751 dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze) {
   1752 	REQUIRE(DNS_ZONE_VALID(zone));
   1753 
   1754 	if (zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
   1755 	    zone->type == dns_zone_key ||
   1756 	    (zone->type == dns_zone_redirect && zone->masters != NULL))
   1757 		return (ISC_TRUE);
   1758 
   1759 	/* If !ignore_freeze, we need check whether updates are disabled.  */
   1760 	if (zone->type == dns_zone_master &&
   1761 	    (!zone->update_disabled || ignore_freeze) &&
   1762 	    ((zone->ssutable != NULL) ||
   1763 	     (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
   1764 		return (ISC_TRUE);
   1765 
   1766 	return (ISC_FALSE);
   1767 
   1768 }
   1769 
   1770 /*
   1771  * Set the response policy index and information for a zone.
   1772  */
   1773 isc_result_t
   1774 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
   1775 		    dns_rpz_num_t rpz_num)
   1776 {
   1777 	/*
   1778 	 * Only RBTDB zones can be used for response policy zones,
   1779 	 * because only they have the code to load the create the summary data.
   1780 	 * Only zones that are loaded instead of mmap()ed create the
   1781 	 * summary data and so can be policy zones.
   1782 	 */
   1783 	if (strcmp(zone->db_argv[0], "rbt") != 0 &&
   1784 	    strcmp(zone->db_argv[0], "rbt64") != 0)
   1785 		return (ISC_R_NOTIMPLEMENTED);
   1786 	if (zone->masterformat == dns_masterformat_map)
   1787 		return (ISC_R_NOTIMPLEMENTED);
   1788 
   1789 	/*
   1790 	 * This must happen only once or be redundant.
   1791 	 */
   1792 	LOCK_ZONE(zone);
   1793 	if (zone->rpzs != NULL) {
   1794 		REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
   1795 	} else {
   1796 		REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
   1797 		dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
   1798 		zone->rpz_num = rpz_num;
   1799 	}
   1800 	rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
   1801 	UNLOCK_ZONE(zone);
   1802 
   1803 	return (ISC_R_SUCCESS);
   1804 }
   1805 
   1806 dns_rpz_num_t
   1807 dns_zone_get_rpz_num(dns_zone_t *zone) {
   1808 	return (zone->rpz_num);
   1809 }
   1810 
   1811 /*
   1812  * If a zone is a response policy zone, mark its new database.
   1813  */
   1814 void
   1815 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
   1816 	isc_result_t result;
   1817 	if (zone->rpz_num == DNS_RPZ_INVALID_NUM)
   1818 		return;
   1819 	REQUIRE(zone->rpzs != NULL);
   1820 	zone->rpzs->zones[zone->rpz_num]->db_registered = ISC_TRUE;
   1821 	result = dns_db_updatenotify_register(db,
   1822 					      dns_rpz_dbupdate_callback,
   1823 					      zone->rpzs->zones[zone->rpz_num]);
   1824 	REQUIRE(result == ISC_R_SUCCESS);
   1825 }
   1826 
   1827 void
   1828 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
   1829 	REQUIRE(DNS_ZONE_VALID(zone));
   1830 	REQUIRE(catzs != NULL);
   1831 
   1832 	LOCK_ZONE(zone);
   1833 	INSIST(zone->catzs == NULL || zone->catzs == catzs);
   1834 	dns_catz_catzs_set_view(catzs, zone->view);
   1835 	if (zone->catzs == NULL)
   1836 		dns_catz_catzs_attach(catzs, &zone->catzs);
   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 /*
   1855  * Set catalog zone ownership of the zone
   1856  */
   1857 void
   1858 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
   1859 	REQUIRE(DNS_ZONE_VALID(zone));
   1860 	REQUIRE(catz != NULL);
   1861 	LOCK_ZONE(zone);
   1862 	INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
   1863 	zone->parentcatz = catz;
   1864 	UNLOCK_ZONE(zone);
   1865 }
   1866 
   1867 dns_catz_zone_t *
   1868 dns_zone_get_parentcatz(const dns_zone_t *zone) {
   1869 	REQUIRE(DNS_ZONE_VALID(zone));
   1870 	return (zone->parentcatz);
   1871 }
   1872 
   1873 
   1874 static isc_boolean_t
   1875 zone_touched(dns_zone_t *zone) {
   1876 	isc_result_t result;
   1877 	isc_time_t modtime;
   1878 	dns_include_t *include;
   1879 
   1880 	REQUIRE(DNS_ZONE_VALID(zone));
   1881 
   1882 	result = isc_file_getmodtime(zone->masterfile, &modtime);
   1883 	if (result != ISC_R_SUCCESS ||
   1884 	    isc_time_compare(&modtime, &zone->loadtime) > 0)
   1885 		return (ISC_TRUE);
   1886 
   1887 	for (include = ISC_LIST_HEAD(zone->includes);
   1888 	     include != NULL;
   1889 	     include = ISC_LIST_NEXT(include, link))
   1890 	{
   1891 		result = isc_file_getmodtime(include->name, &modtime);
   1892 		if (result != ISC_R_SUCCESS ||
   1893 		    isc_time_compare(&modtime, &include->filetime) > 0)
   1894 			return (ISC_TRUE);
   1895 	}
   1896 
   1897 	return (ISC_FALSE);
   1898 }
   1899 
   1900 static isc_result_t
   1901 zone_load(dns_zone_t *zone, unsigned int flags, isc_boolean_t locked) {
   1902 	isc_result_t result;
   1903 	isc_time_t now;
   1904 	isc_time_t loadtime;
   1905 	dns_db_t *db = NULL;
   1906 	isc_boolean_t rbt, hasraw;
   1907 
   1908 	REQUIRE(DNS_ZONE_VALID(zone));
   1909 
   1910 	if (!locked)
   1911 		LOCK_ZONE(zone);
   1912 
   1913 	INSIST(zone != zone->raw);
   1914 	hasraw = inline_secure(zone);
   1915 	if (hasraw) {
   1916 		result = zone_load(zone->raw, flags, ISC_FALSE);
   1917 		if (result != ISC_R_SUCCESS) {
   1918 			if (!locked)
   1919 				UNLOCK_ZONE(zone);
   1920 			return(result);
   1921 		}
   1922 		LOCK_ZONE(zone->raw);
   1923 	}
   1924 
   1925 	TIME_NOW(&now);
   1926 
   1927 	INSIST(zone->type != dns_zone_none);
   1928 
   1929 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
   1930 		if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
   1931 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
   1932 		result = DNS_R_CONTINUE;
   1933 		goto cleanup;
   1934 	}
   1935 
   1936 	INSIST(zone->db_argc >= 1);
   1937 
   1938 	rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
   1939 	      strcmp(zone->db_argv[0], "rbt64") == 0;
   1940 
   1941 	if (zone->db != NULL && zone->masterfile == NULL && rbt) {
   1942 		/*
   1943 		 * The zone has no master file configured.
   1944 		 */
   1945 		result = ISC_R_SUCCESS;
   1946 		goto cleanup;
   1947 	}
   1948 
   1949 	if (zone->db != NULL && dns_zone_isdynamic(zone, ISC_FALSE)) {
   1950 		/*
   1951 		 * This is a slave, stub, or dynamically updated
   1952 		 * zone being reloaded.  Do nothing - the database
   1953 		 * we already have is guaranteed to be up-to-date.
   1954 		 */
   1955 		if (zone->type == dns_zone_master)
   1956 			result = DNS_R_DYNAMIC;
   1957 		else
   1958 			result = ISC_R_SUCCESS;
   1959 		goto cleanup;
   1960 	}
   1961 
   1962 	/*
   1963 	 * Store the current time before the zone is loaded, so that if the
   1964 	 * file changes between the time of the load and the time that
   1965 	 * zone->loadtime is set, then the file will still be reloaded
   1966 	 * the next time dns_zone_load is called.
   1967 	 */
   1968 	TIME_NOW(&loadtime);
   1969 
   1970 	/*
   1971 	 * Don't do the load if the file that stores the zone is older
   1972 	 * than the last time the zone was loaded.  If the zone has not
   1973 	 * been loaded yet, zone->loadtime will be the epoch.
   1974 	 */
   1975 	if (zone->masterfile != NULL) {
   1976 		isc_time_t filetime;
   1977 
   1978 		/*
   1979 		 * The file is already loaded.	If we are just doing a
   1980 		 * "rndc reconfig", we are done.
   1981 		 */
   1982 		if (!isc_time_isepoch(&zone->loadtime) &&
   1983 		    (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
   1984 			result = ISC_R_SUCCESS;
   1985 			goto cleanup;
   1986 		}
   1987 
   1988 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   1989 		    !zone_touched(zone))
   1990 		{
   1991 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   1992 				      ISC_LOG_DEBUG(1),
   1993 				      "skipping load: master file "
   1994 				      "older than last load");
   1995 			result = DNS_R_UPTODATE;
   1996 			goto cleanup;
   1997 		}
   1998 
   1999 
   2000 		/*
   2001 		 * If the file modification time is in the past
   2002 		 * set loadtime to that value.
   2003 		 */
   2004 		result = isc_file_getmodtime(zone->masterfile, &filetime);
   2005 		if (result == ISC_R_SUCCESS &&
   2006 		    isc_time_compare(&loadtime, &filetime) > 0)
   2007 			loadtime = filetime;
   2008 	}
   2009 
   2010 	/*
   2011 	 * Built in zones (with the exception of empty zones) don't need
   2012 	 * to be reloaded.
   2013 	 */
   2014 	if (zone->type == dns_zone_master &&
   2015 	    strcmp(zone->db_argv[0], "_builtin") == 0 &&
   2016 	    (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
   2017 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   2018 		result = ISC_R_SUCCESS;
   2019 		goto cleanup;
   2020 	}
   2021 
   2022 	/*
   2023 	 * Zones associated with a DLZ don't need to be loaded either,
   2024 	 * but we need to associate the database with the zone object.
   2025 	 */
   2026 	if (strcmp(zone->db_argv[0], "dlz") == 0) {
   2027 		dns_dlzdb_t *dlzdb;
   2028 		dns_dlzfindzone_t findzone;
   2029 
   2030 		for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
   2031 		     dlzdb != NULL;
   2032 		     dlzdb = ISC_LIST_NEXT(dlzdb, link))
   2033 		{
   2034 			INSIST(DNS_DLZ_VALID(dlzdb));
   2035 			if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0)
   2036 				break;
   2037 		}
   2038 
   2039 		if (dlzdb == NULL) {
   2040 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2041 				      ISC_LOG_ERROR,
   2042 				      "DLZ %s does not exist or is set "
   2043 				      "to 'search yes;'", zone->db_argv[1]);
   2044 			result = ISC_R_NOTFOUND;
   2045 			goto cleanup;
   2046 		}
   2047 
   2048 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   2049 		/* ask SDLZ driver if the zone is supported */
   2050 		findzone = dlzdb->implementation->methods->findzone;
   2051 		result = (*findzone)(dlzdb->implementation->driverarg,
   2052 				     dlzdb->dbdata, dlzdb->mctx,
   2053 				     zone->view->rdclass, &zone->origin,
   2054 				     NULL, NULL, &db);
   2055 		if (result != ISC_R_NOTFOUND) {
   2056 			if (zone->db != NULL)
   2057 				zone_detachdb(zone);
   2058 			zone_attachdb(zone, db);
   2059 			dns_db_detach(&db);
   2060 			result = ISC_R_SUCCESS;
   2061 		}
   2062 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   2063 
   2064 		if (result == ISC_R_SUCCESS) {
   2065 			if (dlzdb->configure_callback == NULL)
   2066 				goto cleanup;
   2067 
   2068 			result = (*dlzdb->configure_callback)(zone->view,
   2069 							      dlzdb, zone);
   2070 			if (result != ISC_R_SUCCESS)
   2071 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2072 					      ISC_LOG_ERROR,
   2073 					      "DLZ configuration callback: %s",
   2074 					      isc_result_totext(result));
   2075 		}
   2076 		goto cleanup;
   2077 	}
   2078 
   2079 	if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
   2080 	     (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
   2081 	    rbt) {
   2082 		if (zone->masterfile == NULL ||
   2083 		    !isc_file_exists(zone->masterfile)) {
   2084 			if (zone->masterfile != NULL) {
   2085 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2086 					      ISC_LOG_DEBUG(1),
   2087 					     "no master file");
   2088 			}
   2089 			zone->refreshtime = now;
   2090 			if (zone->task != NULL)
   2091 				zone_settimer(zone, &now);
   2092 			result = ISC_R_SUCCESS;
   2093 			goto cleanup;
   2094 		}
   2095 	}
   2096 
   2097 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2098 		      ISC_LOG_DEBUG(1), "starting load");
   2099 
   2100 	result = dns_db_create(zone->mctx, zone->db_argv[0],
   2101 			       &zone->origin, (zone->type == dns_zone_stub) ?
   2102 			       dns_dbtype_stub : dns_dbtype_zone,
   2103 			       zone->rdclass,
   2104 			       zone->db_argc - 1, zone->db_argv + 1,
   2105 			       &db);
   2106 
   2107 	if (result != ISC_R_SUCCESS) {
   2108 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   2109 			     "loading zone: creating database: %s",
   2110 			     isc_result_totext(result));
   2111 		goto cleanup;
   2112 	}
   2113 	dns_db_settask(db, zone->task);
   2114 
   2115 	if (zone->type == dns_zone_master || zone->type == dns_zone_slave) {
   2116 		result = dns_db_setgluecachestats(db, zone->gluecachestats);
   2117 		if (result == ISC_R_NOTIMPLEMENTED) {
   2118 			result = ISC_R_SUCCESS;
   2119 		}
   2120 		if (result != ISC_R_SUCCESS) {
   2121 			goto cleanup;
   2122 		}
   2123 	}
   2124 
   2125 	if (! dns_db_ispersistent(db)) {
   2126 		if (zone->masterfile != NULL) {
   2127 			result = zone_startload(db, zone, loadtime);
   2128 		} else {
   2129 			result = DNS_R_NOMASTERFILE;
   2130 			if (zone->type == dns_zone_master ||
   2131 			    (zone->type == dns_zone_redirect &&
   2132 			     zone->masters == NULL)) {
   2133 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2134 					      ISC_LOG_ERROR,
   2135 					     "loading zone: "
   2136 					     "no master file configured");
   2137 				goto cleanup;
   2138 			}
   2139 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   2140 				      ISC_LOG_INFO, "loading zone: "
   2141 				      "no master file configured: continuing");
   2142 		}
   2143 	}
   2144 
   2145 	if (result == DNS_R_CONTINUE) {
   2146 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
   2147 		if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
   2148 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
   2149 		goto cleanup;
   2150 	}
   2151 
   2152 	result = zone_postload(zone, db, loadtime, result);
   2153 
   2154  cleanup:
   2155 	if (hasraw)
   2156 		UNLOCK_ZONE(zone->raw);
   2157 	if (!locked)
   2158 		UNLOCK_ZONE(zone);
   2159 	if (db != NULL)
   2160 		dns_db_detach(&db);
   2161 	return (result);
   2162 }
   2163 
   2164 isc_result_t
   2165 dns_zone_load(dns_zone_t *zone) {
   2166 	return (zone_load(zone, 0, ISC_FALSE));
   2167 }
   2168 
   2169 isc_result_t
   2170 dns_zone_loadnew(dns_zone_t *zone) {
   2171 	return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT, ISC_FALSE));
   2172 }
   2173 
   2174 static void
   2175 zone_asyncload(isc_task_t *task, isc_event_t *event) {
   2176 	dns_asyncload_t *asl = event->ev_arg;
   2177 	dns_zone_t *zone = asl->zone;
   2178 	isc_result_t result;
   2179 
   2180 	UNUSED(task);
   2181 
   2182 	REQUIRE(DNS_ZONE_VALID(zone));
   2183 
   2184 	isc_event_free(&event);
   2185 
   2186 	LOCK_ZONE(zone);
   2187 	result = zone_load(zone, 0, ISC_TRUE);
   2188 	if (result != DNS_R_CONTINUE) {
   2189 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
   2190 	}
   2191 	UNLOCK_ZONE(zone);
   2192 
   2193 	/* Inform the zone table we've finished loading */
   2194 	if (asl->loaded != NULL)
   2195 		(asl->loaded)(asl->loaded_arg, zone, task);
   2196 
   2197 	isc_mem_put(zone->mctx, asl, sizeof (*asl));
   2198 	dns_zone_idetach(&zone);
   2199 }
   2200 
   2201 isc_result_t
   2202 dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
   2203 	isc_event_t *e;
   2204 	dns_asyncload_t *asl = NULL;
   2205 	isc_result_t result = ISC_R_SUCCESS;
   2206 
   2207 	REQUIRE(DNS_ZONE_VALID(zone));
   2208 
   2209 	if (zone->zmgr == NULL)
   2210 		return (ISC_R_FAILURE);
   2211 
   2212 	/* If we already have a load pending, stop now */
   2213 	LOCK_ZONE(zone);
   2214 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
   2215 		UNLOCK_ZONE(zone);
   2216 		return (ISC_R_ALREADYRUNNING);
   2217 	}
   2218 
   2219 	asl = isc_mem_get(zone->mctx, sizeof (*asl));
   2220 	if (asl == NULL)
   2221 		CHECK(ISC_R_NOMEMORY);
   2222 
   2223 	asl->zone = NULL;
   2224 	asl->loaded = done;
   2225 	asl->loaded_arg = arg;
   2226 
   2227 	e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
   2228 			       DNS_EVENT_ZONELOAD,
   2229 			       zone_asyncload, asl,
   2230 			       sizeof(isc_event_t));
   2231 	if (e == NULL)
   2232 		CHECK(ISC_R_NOMEMORY);
   2233 
   2234 	zone_iattach(zone, &asl->zone);
   2235 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
   2236 	isc_task_send(zone->loadtask, &e);
   2237 	UNLOCK_ZONE(zone);
   2238 
   2239 	return (ISC_R_SUCCESS);
   2240 
   2241   failure:
   2242 	if (asl != NULL)
   2243 		isc_mem_put(zone->mctx, asl, sizeof (*asl));
   2244 	UNLOCK_ZONE(zone);
   2245 	return (result);
   2246 }
   2247 
   2248 isc_boolean_t
   2249 dns__zone_loadpending(dns_zone_t *zone) {
   2250 	REQUIRE(DNS_ZONE_VALID(zone));
   2251 
   2252 	return (ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)));
   2253 }
   2254 
   2255 isc_result_t
   2256 dns_zone_loadandthaw(dns_zone_t *zone) {
   2257 	isc_result_t result;
   2258 
   2259 	if (inline_raw(zone))
   2260 		result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW,
   2261 				   ISC_FALSE);
   2262 	else
   2263 		result = zone_load(zone, DNS_ZONELOADFLAG_THAW, ISC_FALSE);
   2264 
   2265 	switch (result) {
   2266 	case DNS_R_CONTINUE:
   2267 		/* Deferred thaw. */
   2268 		break;
   2269 	case DNS_R_UPTODATE:
   2270 	case ISC_R_SUCCESS:
   2271 	case DNS_R_SEENINCLUDE:
   2272 		zone->update_disabled = ISC_FALSE;
   2273 		break;
   2274 	case DNS_R_NOMASTERFILE:
   2275 		zone->update_disabled = ISC_FALSE;
   2276 		break;
   2277 	default:
   2278 		/* Error, remain in disabled state. */
   2279 		break;
   2280 	}
   2281 	return (result);
   2282 }
   2283 
   2284 static unsigned int
   2285 get_master_options(dns_zone_t *zone) {
   2286 	unsigned int options;
   2287 
   2288 	options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
   2289 	if (zone->type == dns_zone_slave ||
   2290 	    (zone->type == dns_zone_redirect && zone->masters == NULL))
   2291 		options |= DNS_MASTER_SLAVE;
   2292 	if (zone->type == dns_zone_key)
   2293 		options |= DNS_MASTER_KEY;
   2294 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
   2295 		options |= DNS_MASTER_CHECKNS;
   2296 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
   2297 		options |= DNS_MASTER_FATALNS;
   2298 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
   2299 		options |= DNS_MASTER_CHECKNAMES;
   2300 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
   2301 		options |= DNS_MASTER_CHECKNAMESFAIL;
   2302 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
   2303 		options |= DNS_MASTER_CHECKMX;
   2304 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
   2305 		options |= DNS_MASTER_CHECKMXFAIL;
   2306 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
   2307 		options |= DNS_MASTER_CHECKWILDCARD;
   2308 	if (DNS_ZONE_OPTION2(zone, DNS_ZONEOPT2_CHECKTTL))
   2309 		options |= DNS_MASTER_CHECKTTL;
   2310 	return (options);
   2311 }
   2312 
   2313 static void
   2314 zone_registerinclude(const char *filename, void *arg) {
   2315 	isc_result_t result;
   2316 	dns_zone_t *zone = (dns_zone_t *) arg;
   2317 	dns_include_t *inc = NULL;
   2318 
   2319 	REQUIRE(DNS_ZONE_VALID(zone));
   2320 
   2321 	if (filename == NULL)
   2322 		return;
   2323 
   2324 	/*
   2325 	 * Suppress duplicates.
   2326 	 */
   2327 	for (inc = ISC_LIST_HEAD(zone->newincludes);
   2328 	     inc != NULL;
   2329 	     inc = ISC_LIST_NEXT(inc, link))
   2330 		if (strcmp(filename, inc->name) == 0)
   2331 			return;
   2332 
   2333 	inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
   2334 	if (inc == NULL)
   2335 		return;
   2336 	inc->name = isc_mem_strdup(zone->mctx, filename);
   2337 	if (inc->name == NULL) {
   2338 		isc_mem_put(zone->mctx, inc, sizeof(dns_include_t));
   2339 		return;
   2340 	}
   2341 	ISC_LINK_INIT(inc, link);
   2342 
   2343 	result = isc_file_getmodtime(filename, &inc->filetime);
   2344 	if (result != ISC_R_SUCCESS)
   2345 		isc_time_settoepoch(&inc->filetime);
   2346 
   2347 	ISC_LIST_APPEND(zone->newincludes, inc, link);
   2348 }
   2349 
   2350 static void
   2351 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
   2352 	dns_load_t *load = event->ev_arg;
   2353 	isc_result_t result = ISC_R_SUCCESS;
   2354 	unsigned int options;
   2355 
   2356 	REQUIRE(DNS_LOAD_VALID(load));
   2357 
   2358 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
   2359 		result = ISC_R_CANCELED;
   2360 	isc_event_free(&event);
   2361 	if (result == ISC_R_CANCELED)
   2362 		goto fail;
   2363 
   2364 	options = get_master_options(load->zone);
   2365 
   2366 	result = dns_master_loadfileinc5(load->zone->masterfile,
   2367 					 dns_db_origin(load->db),
   2368 					 dns_db_origin(load->db),
   2369 					 load->zone->rdclass, options, 0,
   2370 					 &load->callbacks, task,
   2371 					 zone_loaddone, load,
   2372 					 &load->zone->lctx,
   2373 					 zone_registerinclude,
   2374 					 load->zone, load->zone->mctx,
   2375 					 load->zone->masterformat,
   2376 					 load->zone->maxttl);
   2377 	if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
   2378 	    result != DNS_R_SEENINCLUDE)
   2379 		goto fail;
   2380 	return;
   2381 
   2382  fail:
   2383 	zone_loaddone(load, result);
   2384 }
   2385 
   2386 static void
   2387 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
   2388 	isc_result_t result;
   2389 	unsigned int soacount;
   2390 
   2391 	LOCK(&raw->lock);
   2392 	if (raw->db != NULL) {
   2393 		result = zone_get_from_db(raw, raw->db, NULL, &soacount,
   2394 					  &rawdata->sourceserial,
   2395 					  NULL, NULL, NULL, NULL,
   2396 					  NULL);
   2397 		if (result == ISC_R_SUCCESS && soacount > 0U)
   2398 			rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
   2399 	}
   2400 	UNLOCK(&raw->lock);
   2401 }
   2402 
   2403 static void
   2404 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
   2405 	const char me[] = "zone_gotwritehandle";
   2406 	dns_zone_t *zone = event->ev_arg;
   2407 	isc_result_t result = ISC_R_SUCCESS;
   2408 	dns_dbversion_t *version = NULL;
   2409 	dns_masterrawheader_t rawdata;
   2410 
   2411 	REQUIRE(DNS_ZONE_VALID(zone));
   2412 	INSIST(task == zone->task);
   2413 	ENTER;
   2414 
   2415 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
   2416 		result = ISC_R_CANCELED;
   2417 	isc_event_free(&event);
   2418 	if (result == ISC_R_CANCELED)
   2419 		goto fail;
   2420 
   2421 	LOCK_ZONE(zone);
   2422 	INSIST(zone != zone->raw);
   2423 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   2424 	if (zone->db != NULL) {
   2425 		const dns_master_style_t *output_style;
   2426 
   2427 		dns_db_currentversion(zone->db, &version);
   2428 		dns_master_initrawheader(&rawdata);
   2429 		if (inline_secure(zone))
   2430 			get_raw_serial(zone->raw, &rawdata);
   2431 		if (zone->type == dns_zone_key)
   2432 			output_style = &dns_master_style_keyzone;
   2433 		else if (zone->masterstyle != NULL)
   2434 			output_style = zone->masterstyle;
   2435 		else
   2436 			output_style = &dns_master_style_default;
   2437 		result = dns_master_dumpinc3(zone->mctx, zone->db, version,
   2438 					     output_style, zone->masterfile,
   2439 					     zone->task, dump_done, zone,						     &zone->dctx, zone->masterformat,
   2440 					     &rawdata);
   2441 		dns_db_closeversion(zone->db, &version, ISC_FALSE);
   2442 	} else
   2443 		result = ISC_R_CANCELED;
   2444 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   2445 	UNLOCK_ZONE(zone);
   2446 	if (result != DNS_R_CONTINUE)
   2447 		goto fail;
   2448 	return;
   2449 
   2450  fail:
   2451 	dump_done(zone, result);
   2452 }
   2453 
   2454 /*
   2455  * Save the raw serial number for inline-signing zones.
   2456  * (XXX: Other information from the header will be used
   2457  * for other purposes in the future, but for now this is
   2458  * all we're interested in.)
   2459  */
   2460 static void
   2461 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
   2462 	if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
   2463 		return;
   2464 
   2465 	zone->sourceserial = header->sourceserial;
   2466 	zone->sourceserialset = ISC_TRUE;
   2467 }
   2468 
   2469 void
   2470 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
   2471 	if (zone == NULL)
   2472 		return;
   2473 
   2474 	LOCK_ZONE(zone);
   2475 	zone_setrawdata(zone, header);
   2476 	UNLOCK_ZONE(zone);
   2477 }
   2478 
   2479 static isc_result_t
   2480 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
   2481 	dns_load_t *load;
   2482 	isc_result_t result;
   2483 	isc_result_t tresult;
   2484 	unsigned int options;
   2485 
   2486 	dns_zone_rpz_enable_db(zone, db);
   2487 	dns_zone_catz_enable_db(zone, db);
   2488 	options = get_master_options(zone);
   2489 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
   2490 		options |= DNS_MASTER_MANYERRORS;
   2491 
   2492 	if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
   2493 		load = isc_mem_get(zone->mctx, sizeof(*load));
   2494 		if (load == NULL)
   2495 			return (ISC_R_NOMEMORY);
   2496 
   2497 		load->mctx = NULL;
   2498 		load->zone = NULL;
   2499 		load->db = NULL;
   2500 		load->loadtime = loadtime;
   2501 		load->magic = LOAD_MAGIC;
   2502 
   2503 		isc_mem_attach(zone->mctx, &load->mctx);
   2504 		zone_iattach(zone, &load->zone);
   2505 		dns_db_attach(db, &load->db);
   2506 		dns_rdatacallbacks_init(&load->callbacks);
   2507 		load->callbacks.rawdata = zone_setrawdata;
   2508 		zone_iattach(zone, &load->callbacks.zone);
   2509 		result = dns_db_beginload(db, &load->callbacks);
   2510 		if (result != ISC_R_SUCCESS)
   2511 			goto cleanup;
   2512 		result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->loadtask,
   2513 				       zone_gotreadhandle, load,
   2514 				       &zone->readio);
   2515 		if (result != ISC_R_SUCCESS) {
   2516 			/*
   2517 			 * We can't report multiple errors so ignore
   2518 			 * the result of dns_db_endload().
   2519 			 */
   2520 			(void)dns_db_endload(load->db, &load->callbacks);
   2521 			goto cleanup;
   2522 		} else
   2523 			result = DNS_R_CONTINUE;
   2524 	} else {
   2525 		dns_rdatacallbacks_t callbacks;
   2526 
   2527 		dns_rdatacallbacks_init(&callbacks);
   2528 		callbacks.rawdata = zone_setrawdata;
   2529 		zone_iattach(zone, &callbacks.zone);
   2530 		result = dns_db_beginload(db, &callbacks);
   2531 		if (result != ISC_R_SUCCESS) {
   2532 			zone_idetach(&callbacks.zone);
   2533 			return (result);
   2534 		}
   2535 		result = dns_master_loadfile5(zone->masterfile,
   2536 					      &zone->origin, &zone->origin,
   2537 					      zone->rdclass, options, 0,
   2538 					      &callbacks,
   2539 					      zone_registerinclude,
   2540 					      zone, zone->mctx,
   2541 					      zone->masterformat,
   2542 					      zone->maxttl);
   2543 		tresult = dns_db_endload(db, &callbacks);
   2544 		if (result == ISC_R_SUCCESS)
   2545 			result = tresult;
   2546 		zone_idetach(&callbacks.zone);
   2547 	}
   2548 
   2549 	return (result);
   2550 
   2551  cleanup:
   2552 	load->magic = 0;
   2553 	dns_db_detach(&load->db);
   2554 	zone_idetach(&load->zone);
   2555 	zone_idetach(&load->callbacks.zone);
   2556 	isc_mem_detach(&load->mctx);
   2557 	isc_mem_put(zone->mctx, load, sizeof(*load));
   2558 	return (result);
   2559 }
   2560 
   2561 static isc_boolean_t
   2562 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
   2563 	      dns_name_t *owner)
   2564 {
   2565 	isc_result_t result;
   2566 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2567 	char namebuf[DNS_NAME_FORMATSIZE];
   2568 	char altbuf[DNS_NAME_FORMATSIZE];
   2569 	dns_fixedname_t fixed;
   2570 	dns_name_t *foundname;
   2571 	int level;
   2572 
   2573 	/*
   2574 	 * "." means the services does not exist.
   2575 	 */
   2576 	if (dns_name_equal(name, dns_rootname))
   2577 		return (ISC_TRUE);
   2578 
   2579 	/*
   2580 	 * Outside of zone.
   2581 	 */
   2582 	if (!dns_name_issubdomain(name, &zone->origin)) {
   2583 		if (zone->checkmx != NULL)
   2584 			return ((zone->checkmx)(zone, name, owner));
   2585 		return (ISC_TRUE);
   2586 	}
   2587 
   2588 	if (zone->type == dns_zone_master)
   2589 		level = ISC_LOG_ERROR;
   2590 	else
   2591 		level = ISC_LOG_WARNING;
   2592 
   2593 	foundname = dns_fixedname_initname(&fixed);
   2594 
   2595 	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
   2596 			     0, 0, NULL, foundname, NULL, NULL);
   2597 	if (result == ISC_R_SUCCESS)
   2598 		return (ISC_TRUE);
   2599 
   2600 	if (result == DNS_R_NXRRSET) {
   2601 		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
   2602 				     0, 0, NULL, foundname, NULL, NULL);
   2603 		if (result == ISC_R_SUCCESS)
   2604 			return (ISC_TRUE);
   2605 	}
   2606 
   2607 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
   2608 	dns_name_format(name, namebuf, sizeof namebuf);
   2609 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   2610 	    result == DNS_R_EMPTYNAME) {
   2611 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
   2612 			level = ISC_LOG_WARNING;
   2613 		dns_zone_log(zone, level,
   2614 			     "%s/MX '%s' has no address records (A or AAAA)",
   2615 			     ownerbuf, namebuf);
   2616 		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
   2617 	}
   2618 
   2619 	if (result == DNS_R_CNAME) {
   2620 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
   2621 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
   2622 			level = ISC_LOG_WARNING;
   2623 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
   2624 			dns_zone_log(zone, level,
   2625 				     "%s/MX '%s' is a CNAME (illegal)",
   2626 				     ownerbuf, namebuf);
   2627 		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
   2628 	}
   2629 
   2630 	if (result == DNS_R_DNAME) {
   2631 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
   2632 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
   2633 			level = ISC_LOG_WARNING;
   2634 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
   2635 			dns_name_format(foundname, altbuf, sizeof altbuf);
   2636 			dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
   2637 				     " '%s' (illegal)", ownerbuf, namebuf,
   2638 				     altbuf);
   2639 		}
   2640 		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
   2641 	}
   2642 
   2643 	if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
   2644 		return ((zone->checkmx)(zone, name, owner));
   2645 
   2646 	return (ISC_TRUE);
   2647 }
   2648 
   2649 static isc_boolean_t
   2650 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
   2651 	       dns_name_t *owner)
   2652 {
   2653 	isc_result_t result;
   2654 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2655 	char namebuf[DNS_NAME_FORMATSIZE];
   2656 	char altbuf[DNS_NAME_FORMATSIZE];
   2657 	dns_fixedname_t fixed;
   2658 	dns_name_t *foundname;
   2659 	int level;
   2660 
   2661 	/*
   2662 	 * "." means the services does not exist.
   2663 	 */
   2664 	if (dns_name_equal(name, dns_rootname))
   2665 		return (ISC_TRUE);
   2666 
   2667 	/*
   2668 	 * Outside of zone.
   2669 	 */
   2670 	if (!dns_name_issubdomain(name, &zone->origin)) {
   2671 		if (zone->checksrv != NULL)
   2672 			return ((zone->checksrv)(zone, name, owner));
   2673 		return (ISC_TRUE);
   2674 	}
   2675 
   2676 	if (zone->type == dns_zone_master)
   2677 		level = ISC_LOG_ERROR;
   2678 	else
   2679 		level = ISC_LOG_WARNING;
   2680 
   2681 	foundname = dns_fixedname_initname(&fixed);
   2682 
   2683 	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
   2684 			     0, 0, NULL, foundname, NULL, NULL);
   2685 	if (result == ISC_R_SUCCESS)
   2686 		return (ISC_TRUE);
   2687 
   2688 	if (result == DNS_R_NXRRSET) {
   2689 		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
   2690 				     0, 0, NULL, foundname, NULL, NULL);
   2691 		if (result == ISC_R_SUCCESS)
   2692 			return (ISC_TRUE);
   2693 	}
   2694 
   2695 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
   2696 	dns_name_format(name, namebuf, sizeof namebuf);
   2697 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   2698 	    result == DNS_R_EMPTYNAME) {
   2699 		dns_zone_log(zone, level,
   2700 			     "%s/SRV '%s' has no address records (A or AAAA)",
   2701 			     ownerbuf, namebuf);
   2702 		/* XXX950 make fatal for 9.5.0. */
   2703 		return (ISC_TRUE);
   2704 	}
   2705 
   2706 	if (result == DNS_R_CNAME) {
   2707 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
   2708 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
   2709 			level = ISC_LOG_WARNING;
   2710 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
   2711 			dns_zone_log(zone, level,
   2712 				     "%s/SRV '%s' is a CNAME (illegal)",
   2713 				     ownerbuf, namebuf);
   2714 		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
   2715 	}
   2716 
   2717 	if (result == DNS_R_DNAME) {
   2718 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
   2719 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
   2720 			level = ISC_LOG_WARNING;
   2721 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
   2722 			dns_name_format(foundname, altbuf, sizeof altbuf);
   2723 			dns_zone_log(zone, level, "%s/SRV '%s' is below a "
   2724 				     "DNAME '%s' (illegal)", ownerbuf, namebuf,
   2725 				     altbuf);
   2726 		}
   2727 		return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
   2728 	}
   2729 
   2730 	if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
   2731 		return ((zone->checksrv)(zone, name, owner));
   2732 
   2733 	return (ISC_TRUE);
   2734 }
   2735 
   2736 static isc_boolean_t
   2737 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
   2738 		dns_name_t *owner)
   2739 {
   2740 	isc_boolean_t answer = ISC_TRUE;
   2741 	isc_result_t result, tresult;
   2742 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2743 	char namebuf[DNS_NAME_FORMATSIZE];
   2744 	char altbuf[DNS_NAME_FORMATSIZE];
   2745 	dns_fixedname_t fixed;
   2746 	dns_name_t *foundname;
   2747 	dns_rdataset_t a;
   2748 	dns_rdataset_t aaaa;
   2749 	int level;
   2750 
   2751 	/*
   2752 	 * Outside of zone.
   2753 	 */
   2754 	if (!dns_name_issubdomain(name, &zone->origin)) {
   2755 		if (zone->checkns != NULL)
   2756 			return ((zone->checkns)(zone, name, owner, NULL, NULL));
   2757 		return (ISC_TRUE);
   2758 	}
   2759 
   2760 	if (zone->type == dns_zone_master)
   2761 		level = ISC_LOG_ERROR;
   2762 	else
   2763 		level = ISC_LOG_WARNING;
   2764 
   2765 	foundname = dns_fixedname_initname(&fixed);
   2766 	dns_rdataset_init(&a);
   2767 	dns_rdataset_init(&aaaa);
   2768 
   2769 	/*
   2770 	 * Perform a regular lookup to catch DNAME records then look
   2771 	 * for glue.
   2772 	 */
   2773 	result = dns_db_find(db, name, NULL, dns_rdatatype_a,
   2774 			     0, 0, NULL, foundname, &a, NULL);
   2775 	switch (result) {
   2776 	case ISC_R_SUCCESS:
   2777 	case DNS_R_DNAME:
   2778 	case DNS_R_CNAME:
   2779 		break;
   2780 	default:
   2781 		if (dns_rdataset_isassociated(&a))
   2782 			dns_rdataset_disassociate(&a);
   2783 		result = dns_db_find(db, name, NULL, dns_rdatatype_a,
   2784 				     DNS_DBFIND_GLUEOK, 0, NULL,
   2785 				     foundname, &a, NULL);
   2786 	}
   2787 	if (result == ISC_R_SUCCESS) {
   2788 		dns_rdataset_disassociate(&a);
   2789 		return (ISC_TRUE);
   2790 	} else if (result == DNS_R_DELEGATION)
   2791 		dns_rdataset_disassociate(&a);
   2792 
   2793 	if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
   2794 	    result == DNS_R_GLUE) {
   2795 		tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
   2796 				     DNS_DBFIND_GLUEOK, 0, NULL,
   2797 				     foundname, &aaaa, NULL);
   2798 		if (tresult == ISC_R_SUCCESS) {
   2799 			if (dns_rdataset_isassociated(&a))
   2800 				dns_rdataset_disassociate(&a);
   2801 			dns_rdataset_disassociate(&aaaa);
   2802 			return (ISC_TRUE);
   2803 		}
   2804 		if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME)
   2805 			dns_rdataset_disassociate(&aaaa);
   2806 		if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
   2807 			/*
   2808 			 * Check glue against child zone.
   2809 			 */
   2810 			if (zone->checkns != NULL)
   2811 				answer = (zone->checkns)(zone, name, owner,
   2812 							 &a, &aaaa);
   2813 			if (dns_rdataset_isassociated(&a))
   2814 				dns_rdataset_disassociate(&a);
   2815 			if (dns_rdataset_isassociated(&aaaa))
   2816 				dns_rdataset_disassociate(&aaaa);
   2817 			return (answer);
   2818 		}
   2819 	}
   2820 
   2821 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
   2822 	dns_name_format(name, namebuf, sizeof namebuf);
   2823 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   2824 	    result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
   2825 		const char *what;
   2826 		isc_boolean_t required = ISC_FALSE;
   2827 		if (dns_name_issubdomain(name, owner)) {
   2828 			what = "REQUIRED GLUE ";
   2829 			required = ISC_TRUE;
   2830 		 } else if (result == DNS_R_DELEGATION)
   2831 			what = "SIBLING GLUE ";
   2832 		else
   2833 			what = "";
   2834 
   2835 		if (result != DNS_R_DELEGATION || required ||
   2836 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
   2837 			dns_zone_log(zone, level, "%s/NS '%s' has no %s"
   2838 				     "address records (A or AAAA)",
   2839 				     ownerbuf, namebuf, what);
   2840 			/*
   2841 			 * Log missing address record.
   2842 			 */
   2843 			if (result == DNS_R_DELEGATION && zone->checkns != NULL)
   2844 				(void)(zone->checkns)(zone, name, owner,
   2845 						      &a, &aaaa);
   2846 			/* XXX950 make fatal for 9.5.0. */
   2847 			/* answer = ISC_FALSE; */
   2848 		}
   2849 	} else if (result == DNS_R_CNAME) {
   2850 		dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
   2851 			     ownerbuf, namebuf);
   2852 		/* XXX950 make fatal for 9.5.0. */
   2853 		/* answer = ISC_FALSE; */
   2854 	} else if (result == DNS_R_DNAME) {
   2855 		dns_name_format(foundname, altbuf, sizeof altbuf);
   2856 		dns_zone_log(zone, level,
   2857 			     "%s/NS '%s' is below a DNAME '%s' (illegal)",
   2858 			     ownerbuf, namebuf, altbuf);
   2859 		/* XXX950 make fatal for 9.5.0. */
   2860 		/* answer = ISC_FALSE; */
   2861 	}
   2862 
   2863 	if (dns_rdataset_isassociated(&a))
   2864 		dns_rdataset_disassociate(&a);
   2865 	if (dns_rdataset_isassociated(&aaaa))
   2866 		dns_rdataset_disassociate(&aaaa);
   2867 	return (answer);
   2868 }
   2869 
   2870 static isc_boolean_t
   2871 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
   2872 		     dns_rdataset_t *rdataset)
   2873 {
   2874 	dns_rdataset_t tmprdataset;
   2875 	isc_result_t result;
   2876 	isc_boolean_t answer = ISC_TRUE;
   2877 	isc_boolean_t format = ISC_TRUE;
   2878 	int level = ISC_LOG_WARNING;
   2879 	char ownerbuf[DNS_NAME_FORMATSIZE];
   2880 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
   2881 	unsigned int count1 = 0;
   2882 
   2883 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
   2884 		level = ISC_LOG_ERROR;
   2885 
   2886 	dns_rdataset_init(&tmprdataset);
   2887 	for (result = dns_rdataset_first(rdataset);
   2888 	     result == ISC_R_SUCCESS;
   2889 	     result = dns_rdataset_next(rdataset)) {
   2890 		dns_rdata_t rdata1 = DNS_RDATA_INIT;
   2891 		unsigned int count2 = 0;
   2892 
   2893 		count1++;
   2894 		dns_rdataset_current(rdataset, &rdata1);
   2895 		dns_rdataset_clone(rdataset, &tmprdataset);
   2896 		for (result = dns_rdataset_first(&tmprdataset);
   2897 		     result == ISC_R_SUCCESS;
   2898 		     result = dns_rdataset_next(&tmprdataset)) {
   2899 			dns_rdata_t rdata2 = DNS_RDATA_INIT;
   2900 			count2++;
   2901 			if (count1 >= count2)
   2902 				continue;
   2903 			dns_rdataset_current(&tmprdataset, &rdata2);
   2904 			if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
   2905 				if (format) {
   2906 					dns_name_format(owner, ownerbuf,
   2907 							sizeof ownerbuf);
   2908 					dns_rdatatype_format(rdata1.type,
   2909 							     typebuf,
   2910 							     sizeof(typebuf));
   2911 					format = ISC_FALSE;
   2912 				}
   2913 				dns_zone_log(zone, level, "%s/%s has "
   2914 					     "semantically identical records",
   2915 					     ownerbuf, typebuf);
   2916 				if (level == ISC_LOG_ERROR)
   2917 					answer = ISC_FALSE;
   2918 				break;
   2919 			}
   2920 		}
   2921 		dns_rdataset_disassociate(&tmprdataset);
   2922 		if (!format)
   2923 			break;
   2924 	}
   2925 	return (answer);
   2926 }
   2927 
   2928 static isc_boolean_t
   2929 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
   2930 	dns_dbiterator_t *dbiterator = NULL;
   2931 	dns_dbnode_t *node = NULL;
   2932 	dns_fixedname_t fixed;
   2933 	dns_name_t *name;
   2934 	dns_rdataset_t rdataset;
   2935 	dns_rdatasetiter_t *rdsit = NULL;
   2936 	isc_boolean_t ok = ISC_TRUE;
   2937 	isc_result_t result;
   2938 
   2939 	name = dns_fixedname_initname(&fixed);
   2940 	dns_rdataset_init(&rdataset);
   2941 
   2942 	result = dns_db_createiterator(db, 0, &dbiterator);
   2943 	if (result != ISC_R_SUCCESS)
   2944 		return (ISC_TRUE);
   2945 
   2946 	for (result = dns_dbiterator_first(dbiterator);
   2947 	     result == ISC_R_SUCCESS;
   2948 	     result = dns_dbiterator_next(dbiterator)) {
   2949 		result = dns_dbiterator_current(dbiterator, &node, name);
   2950 		if (result != ISC_R_SUCCESS)
   2951 			continue;
   2952 
   2953 		result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
   2954 		if (result != ISC_R_SUCCESS)
   2955 			continue;
   2956 
   2957 		for (result = dns_rdatasetiter_first(rdsit);
   2958 		     result == ISC_R_SUCCESS;
   2959 		     result = dns_rdatasetiter_next(rdsit)) {
   2960 			dns_rdatasetiter_current(rdsit, &rdataset);
   2961 			if (!zone_rrset_check_dup(zone, name, &rdataset))
   2962 				ok = ISC_FALSE;
   2963 			dns_rdataset_disassociate(&rdataset);
   2964 		}
   2965 		dns_rdatasetiter_destroy(&rdsit);
   2966 		dns_db_detachnode(db, &node);
   2967 	}
   2968 
   2969 	if (node != NULL)
   2970 		dns_db_detachnode(db, &node);
   2971 	dns_dbiterator_destroy(&dbiterator);
   2972 
   2973 	return (ok);
   2974 }
   2975 
   2976 static isc_boolean_t
   2977 isspf(const dns_rdata_t *rdata) {
   2978 	char buf[1024];
   2979 	const unsigned char *data = rdata->data;
   2980 	unsigned int rdl = rdata->length, i = 0, tl, len;
   2981 
   2982 	while (rdl > 0U) {
   2983 		len = tl = *data;
   2984 		++data;
   2985 		--rdl;
   2986 		INSIST(tl <= rdl);
   2987 		if (len > sizeof(buf) - i - 1)
   2988 			len = sizeof(buf) - i - 1;
   2989 		memmove(buf + i, data, len);
   2990 		i += len;
   2991 		data += tl;
   2992 		rdl -= tl;
   2993 	}
   2994 
   2995 	if (i < 6U)
   2996 		return(ISC_FALSE);
   2997 
   2998 	buf[i] = 0;
   2999 	if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
   3000 		return (ISC_TRUE);
   3001 	return (ISC_FALSE);
   3002 }
   3003 
   3004 static isc_boolean_t
   3005 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
   3006 	dns_dbiterator_t *dbiterator = NULL;
   3007 	dns_dbnode_t *node = NULL;
   3008 	dns_rdataset_t rdataset;
   3009 	dns_fixedname_t fixed;
   3010 	dns_fixedname_t fixedbottom;
   3011 	dns_rdata_mx_t mx;
   3012 	dns_rdata_ns_t ns;
   3013 	dns_rdata_in_srv_t srv;
   3014 	dns_rdata_t rdata;
   3015 	dns_name_t *name;
   3016 	dns_name_t *bottom;
   3017 	isc_result_t result;
   3018 	isc_boolean_t ok = ISC_TRUE, have_spf, have_txt;
   3019 
   3020 	name = dns_fixedname_initname(&fixed);
   3021 	bottom = dns_fixedname_initname(&fixedbottom);
   3022 	dns_rdataset_init(&rdataset);
   3023 	dns_rdata_init(&rdata);
   3024 
   3025 	result = dns_db_createiterator(db, 0, &dbiterator);
   3026 	if (result != ISC_R_SUCCESS)
   3027 		return (ISC_TRUE);
   3028 
   3029 	result = dns_dbiterator_first(dbiterator);
   3030 	while (result == ISC_R_SUCCESS) {
   3031 		result = dns_dbiterator_current(dbiterator, &node, name);
   3032 		if (result != ISC_R_SUCCESS)
   3033 			goto cleanup;
   3034 
   3035 		/*
   3036 		 * Is this name visible in the zone?
   3037 		 */
   3038 		if (!dns_name_issubdomain(name, &zone->origin) ||
   3039 		    (dns_name_countlabels(bottom) > 0 &&
   3040 		     dns_name_issubdomain(name, bottom)))
   3041 			goto next;
   3042 
   3043 		/*
   3044 		 * Don't check the NS records at the origin.
   3045 		 */
   3046 		if (dns_name_equal(name, &zone->origin))
   3047 			goto checkfordname;
   3048 
   3049 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
   3050 					     0, 0, &rdataset, NULL);
   3051 		if (result != ISC_R_SUCCESS)
   3052 			goto checkfordname;
   3053 		/*
   3054 		 * Remember bottom of zone due to NS.
   3055 		 */
   3056 		dns_name_copy(name, bottom, NULL);
   3057 
   3058 		result = dns_rdataset_first(&rdataset);
   3059 		while (result == ISC_R_SUCCESS) {
   3060 			dns_rdataset_current(&rdataset, &rdata);
   3061 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
   3062 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3063 			if (!zone_check_glue(zone, db, &ns.name, name))
   3064 				ok = ISC_FALSE;
   3065 			dns_rdata_reset(&rdata);
   3066 			result = dns_rdataset_next(&rdataset);
   3067 		}
   3068 		dns_rdataset_disassociate(&rdataset);
   3069 		goto next;
   3070 
   3071  checkfordname:
   3072 		result = dns_db_findrdataset(db, node, NULL,
   3073 					     dns_rdatatype_dname, 0, 0,
   3074 					     &rdataset, NULL);
   3075 		if (result == ISC_R_SUCCESS) {
   3076 			/*
   3077 			 * Remember bottom of zone due to DNAME.
   3078 			 */
   3079 			dns_name_copy(name, bottom, NULL);
   3080 			dns_rdataset_disassociate(&rdataset);
   3081 		}
   3082 
   3083 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
   3084 					     0, 0, &rdataset, NULL);
   3085 		if (result != ISC_R_SUCCESS)
   3086 			goto checksrv;
   3087 		result = dns_rdataset_first(&rdataset);
   3088 		while (result == ISC_R_SUCCESS) {
   3089 			dns_rdataset_current(&rdataset, &rdata);
   3090 			result = dns_rdata_tostruct(&rdata, &mx, NULL);
   3091 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3092 			if (!zone_check_mx(zone, db, &mx.mx, name))
   3093 				ok = ISC_FALSE;
   3094 			dns_rdata_reset(&rdata);
   3095 			result = dns_rdataset_next(&rdataset);
   3096 		}
   3097 		dns_rdataset_disassociate(&rdataset);
   3098 
   3099  checksrv:
   3100 		if (zone->rdclass != dns_rdataclass_in)
   3101 			goto next;
   3102 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
   3103 					     0, 0, &rdataset, NULL);
   3104 		if (result != ISC_R_SUCCESS)
   3105 			goto checkspf;
   3106 		result = dns_rdataset_first(&rdataset);
   3107 		while (result == ISC_R_SUCCESS) {
   3108 			dns_rdataset_current(&rdataset, &rdata);
   3109 			result = dns_rdata_tostruct(&rdata, &srv, NULL);
   3110 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3111 			if (!zone_check_srv(zone, db, &srv.target, name))
   3112 				ok = ISC_FALSE;
   3113 			dns_rdata_reset(&rdata);
   3114 			result = dns_rdataset_next(&rdataset);
   3115 		}
   3116 		dns_rdataset_disassociate(&rdataset);
   3117 
   3118  checkspf:
   3119 		/*
   3120 		 * Check if there is a type SPF record without an
   3121 		 * SPF-formatted type TXT record also being present.
   3122 		 */
   3123 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
   3124 			goto next;
   3125 		if (zone->rdclass != dns_rdataclass_in)
   3126 			goto next;
   3127 		have_spf = have_txt = ISC_FALSE;
   3128 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
   3129 					     0, 0, &rdataset, NULL);
   3130 		if (result == ISC_R_SUCCESS) {
   3131 			dns_rdataset_disassociate(&rdataset);
   3132 			have_spf = ISC_TRUE;
   3133 		}
   3134 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
   3135 					     0, 0, &rdataset, NULL);
   3136 		if (result != ISC_R_SUCCESS)
   3137 			goto notxt;
   3138 		result = dns_rdataset_first(&rdataset);
   3139 		while (result == ISC_R_SUCCESS) {
   3140 			dns_rdataset_current(&rdataset, &rdata);
   3141 			have_txt = isspf(&rdata);
   3142 			dns_rdata_reset(&rdata);
   3143 			if (have_txt)
   3144 				break;
   3145 			result = dns_rdataset_next(&rdataset);
   3146 		}
   3147 		dns_rdataset_disassociate(&rdataset);
   3148 
   3149  notxt:
   3150 		if (have_spf && !have_txt) {
   3151 			char namebuf[DNS_NAME_FORMATSIZE];
   3152 
   3153 			dns_name_format(name, namebuf, sizeof(namebuf));
   3154 			dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type "
   3155 				     "SPF record but no SPF TXT record found, "
   3156 				     "add matching type TXT record", namebuf);
   3157 		}
   3158 
   3159  next:
   3160 		dns_db_detachnode(db, &node);
   3161 		result = dns_dbiterator_next(dbiterator);
   3162 	}
   3163 
   3164  cleanup:
   3165 	if (node != NULL)
   3166 		dns_db_detachnode(db, &node);
   3167 	dns_dbiterator_destroy(&dbiterator);
   3168 
   3169 	return (ok);
   3170 }
   3171 
   3172 /*
   3173  * OpenSSL verification of RSA keys with exponent 3 is known to be
   3174  * broken prior OpenSSL 0.9.8c/0.9.7k.	Look for such keys and warn
   3175  * if they are in use.
   3176  */
   3177 static void
   3178 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
   3179 	dns_dbnode_t *node = NULL;
   3180 	dns_dbversion_t *version = NULL;
   3181 	dns_rdata_dnskey_t dnskey;
   3182 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3183 	dns_rdataset_t rdataset;
   3184 	isc_result_t result;
   3185 	isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
   3186 	const char *algorithm;
   3187 
   3188 	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
   3189 	if (result != ISC_R_SUCCESS)
   3190 		goto cleanup;
   3191 
   3192 	dns_db_currentversion(db, &version);
   3193 	dns_rdataset_init(&rdataset);
   3194 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
   3195 				     dns_rdatatype_none, 0, &rdataset, NULL);
   3196 	if (result != ISC_R_SUCCESS)
   3197 		goto cleanup;
   3198 
   3199 	for (result = dns_rdataset_first(&rdataset);
   3200 	     result == ISC_R_SUCCESS;
   3201 	     result = dns_rdataset_next(&rdataset))
   3202 	{
   3203 		dns_rdataset_current(&rdataset, &rdata);
   3204 		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
   3205 		INSIST(result == ISC_R_SUCCESS);
   3206 
   3207 		if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
   3208 		     dnskey.algorithm == DST_ALG_RSAMD5) &&
   3209 		     dnskey.datalen > 1 && dnskey.data[0] == 1 &&
   3210 		     dnskey.data[1] == 3)
   3211 		{
   3212 			if (dnskey.algorithm == DST_ALG_RSASHA1) {
   3213 				logit = !foundrsa;
   3214 				foundrsa = ISC_TRUE;
   3215 				algorithm = "RSASHA1";
   3216 			} else {
   3217 				logit = !foundmd5;
   3218 				foundmd5 = ISC_TRUE;
   3219 				algorithm = "RSAMD5";
   3220 			}
   3221 			if (logit)
   3222 				dns_zone_log(zone, ISC_LOG_WARNING,
   3223 					     "weak %s (%u) key found "
   3224 					     "(exponent=3)", algorithm,
   3225 					     dnskey.algorithm);
   3226 			if (foundrsa && foundmd5)
   3227 				break;
   3228 		}
   3229 		dns_rdata_reset(&rdata);
   3230 	}
   3231 	dns_rdataset_disassociate(&rdataset);
   3232 
   3233  cleanup:
   3234 	if (node != NULL)
   3235 		dns_db_detachnode(db, &node);
   3236 	if (version != NULL)
   3237 		dns_db_closeversion(db, &version, ISC_FALSE);
   3238 }
   3239 
   3240 static void
   3241 resume_signingwithkey(dns_zone_t *zone) {
   3242 	dns_dbnode_t *node = NULL;
   3243 	dns_dbversion_t *version = NULL;
   3244 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3245 	dns_rdataset_t rdataset;
   3246 	isc_result_t result;
   3247 	dns_db_t *db = NULL;
   3248 
   3249 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3250 	if (zone->db != NULL)
   3251 		dns_db_attach(zone->db, &db);
   3252 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3253 	if (db == NULL)
   3254 		goto cleanup;
   3255 
   3256 	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
   3257 	if (result != ISC_R_SUCCESS)
   3258 		goto cleanup;
   3259 
   3260 	dns_db_currentversion(db, &version);
   3261 	dns_rdataset_init(&rdataset);
   3262 	result = dns_db_findrdataset(db, node, version,
   3263 				     zone->privatetype,
   3264 				     dns_rdatatype_none, 0,
   3265 				     &rdataset, NULL);
   3266 	if (result != ISC_R_SUCCESS) {
   3267 		INSIST(!dns_rdataset_isassociated(&rdataset));
   3268 		goto cleanup;
   3269 	}
   3270 
   3271 	for (result = dns_rdataset_first(&rdataset);
   3272 	     result == ISC_R_SUCCESS;
   3273 	     result = dns_rdataset_next(&rdataset))
   3274 	{
   3275 		dns_rdataset_current(&rdataset, &rdata);
   3276 		if (rdata.length != 5 ||
   3277 		    rdata.data[0] == 0 || rdata.data[4] != 0) {
   3278 			dns_rdata_reset(&rdata);
   3279 			continue;
   3280 		}
   3281 
   3282 		result = zone_signwithkey(zone, rdata.data[0],
   3283 					  (rdata.data[1] << 8) | rdata.data[2],
   3284 					  ISC_TF(rdata.data[3]));
   3285 		if (result != ISC_R_SUCCESS) {
   3286 			dns_zone_log(zone, ISC_LOG_ERROR,
   3287 				     "zone_signwithkey failed: %s",
   3288 				     dns_result_totext(result));
   3289 		}
   3290 		dns_rdata_reset(&rdata);
   3291 	}
   3292 	dns_rdataset_disassociate(&rdataset);
   3293 
   3294  cleanup:
   3295 	if (db != NULL) {
   3296 		if (node != NULL)
   3297 			dns_db_detachnode(db, &node);
   3298 		if (version != NULL)
   3299 			dns_db_closeversion(db, &version, ISC_FALSE);
   3300 		dns_db_detach(&db);
   3301 	}
   3302 }
   3303 
   3304 /*
   3305  * Initiate adding/removing NSEC3 records belonging to the chain defined by the
   3306  * supplied NSEC3PARAM RDATA.
   3307  *
   3308  * Zone must be locked by caller.
   3309  */
   3310 static isc_result_t
   3311 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
   3312 	dns_nsec3chain_t *nsec3chain, *current;
   3313 	dns_dbversion_t *version = NULL;
   3314 	isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
   3315 	isc_result_t result;
   3316 	isc_time_t now;
   3317 	unsigned int options = 0;
   3318 	char saltbuf[255*2+1];
   3319 	char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
   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 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3326 
   3327 	if (db == NULL) {
   3328 		result = ISC_R_SUCCESS;
   3329 		goto cleanup;
   3330 	}
   3331 
   3332 	/*
   3333 	 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
   3334 	 * chain from it is pointless as it would not be possible for the
   3335 	 * latter to exist in the first place.
   3336 	 */
   3337 	dns_db_currentversion(db, &version);
   3338 	result = dns_nsec_nseconly(db, version, &nseconly);
   3339 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
   3340 	dns_db_closeversion(db, &version, ISC_FALSE);
   3341 	if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
   3342 		result = ISC_R_SUCCESS;
   3343 		goto cleanup;
   3344 	}
   3345 
   3346 	/*
   3347 	 * Allocate and initialize structure preserving state of
   3348 	 * adding/removing records belonging to this NSEC3 chain between
   3349 	 * separate zone_nsec3chain() calls.
   3350 	 */
   3351 	nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
   3352 	if (nsec3chain == NULL) {
   3353 		result = ISC_R_NOMEMORY;
   3354 		goto cleanup;
   3355 	}
   3356 
   3357 	nsec3chain->magic = 0;
   3358 	nsec3chain->done = ISC_FALSE;
   3359 	nsec3chain->db = NULL;
   3360 	nsec3chain->dbiterator = NULL;
   3361 	nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
   3362 	nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
   3363 	nsec3chain->nsec3param.hash = nsec3param->hash;
   3364 	nsec3chain->nsec3param.iterations = nsec3param->iterations;
   3365 	nsec3chain->nsec3param.flags = nsec3param->flags;
   3366 	nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
   3367 	memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
   3368 	nsec3chain->nsec3param.salt = nsec3chain->salt;
   3369 	nsec3chain->seen_nsec = ISC_FALSE;
   3370 	nsec3chain->delete_nsec = ISC_FALSE;
   3371 	nsec3chain->save_delete_nsec = ISC_FALSE;
   3372 
   3373 	/*
   3374 	 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
   3375 	 */
   3376 	if (nsec3param->flags == 0)
   3377 		strlcpy(flags, "NONE", sizeof(flags));
   3378 	else {
   3379 		flags[0] = '\0';
   3380 		if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
   3381 			strlcat(flags, "REMOVE", sizeof(flags));
   3382 		if (nsec3param->flags & DNS_NSEC3FLAG_INITIAL) {
   3383 			if (flags[0] == '\0')
   3384 				strlcpy(flags, "INITIAL", sizeof(flags));
   3385 			else
   3386 				strlcat(flags, "|INITIAL", sizeof(flags));
   3387 		}
   3388 		if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
   3389 			if (flags[0] == '\0')
   3390 				strlcpy(flags, "CREATE", sizeof(flags));
   3391 			else
   3392 				strlcat(flags, "|CREATE", sizeof(flags));
   3393 		}
   3394 		if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
   3395 			if (flags[0] == '\0')
   3396 				strlcpy(flags, "NONSEC", sizeof(flags));
   3397 			else
   3398 				strlcat(flags, "|NONSEC", sizeof(flags));
   3399 		}
   3400 		if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
   3401 			if (flags[0] == '\0')
   3402 				strlcpy(flags, "OPTOUT", sizeof(flags));
   3403 			else
   3404 				strlcat(flags, "|OPTOUT", sizeof(flags));
   3405 		}
   3406 	}
   3407 	result = dns_nsec3param_salttotext(nsec3param, saltbuf,
   3408 					   sizeof(saltbuf));
   3409 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3410 	dns_zone_log(zone, ISC_LOG_INFO,
   3411 		     "zone_addnsec3chain(%u,%s,%u,%s)",
   3412 		      nsec3param->hash, flags, nsec3param->iterations,
   3413 		      saltbuf);
   3414 
   3415 	/*
   3416 	 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
   3417 	 * currently being processed, interrupt its processing to avoid
   3418 	 * simultaneously adding and removing records for the same NSEC3 chain.
   3419 	 */
   3420 	for (current = ISC_LIST_HEAD(zone->nsec3chain);
   3421 	     current != NULL;
   3422 	     current = ISC_LIST_NEXT(current, link)) {
   3423 		if (current->db == db &&
   3424 		    current->nsec3param.hash == nsec3param->hash &&
   3425 		    current->nsec3param.iterations == nsec3param->iterations &&
   3426 		    current->nsec3param.salt_length == nsec3param->salt_length
   3427 		    && !memcmp(current->nsec3param.salt, nsec3param->salt,
   3428 			       nsec3param->salt_length))
   3429 			current->done = ISC_TRUE;
   3430 	}
   3431 
   3432 	/*
   3433 	 * Attach zone database to the structure initialized above and create
   3434 	 * an iterator for it with appropriate options in order to avoid
   3435 	 * creating NSEC3 records for NSEC3 records.
   3436 	 */
   3437 	dns_db_attach(db, &nsec3chain->db);
   3438 	if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
   3439 		options = DNS_DB_NONSEC3;
   3440 	result = dns_db_createiterator(nsec3chain->db, options,
   3441 				       &nsec3chain->dbiterator);
   3442 	if (result == ISC_R_SUCCESS)
   3443 		result = dns_dbiterator_first(nsec3chain->dbiterator);
   3444 	if (result == ISC_R_SUCCESS) {
   3445 		/*
   3446 		 * Database iterator initialization succeeded.  We are now
   3447 		 * ready to kick off adding/removing records belonging to this
   3448 		 * NSEC3 chain.  Append the structure initialized above to the
   3449 		 * "nsec3chain" list for the zone and set the appropriate zone
   3450 		 * timer so that zone_nsec3chain() is called as soon as
   3451 		 * possible.
   3452 		 */
   3453 		dns_dbiterator_pause(nsec3chain->dbiterator);
   3454 		ISC_LIST_INITANDAPPEND(zone->nsec3chain,
   3455 				       nsec3chain, link);
   3456 		nsec3chain = NULL;
   3457 		if (isc_time_isepoch(&zone->nsec3chaintime)) {
   3458 			TIME_NOW(&now);
   3459 			zone->nsec3chaintime = now;
   3460 			if (zone->task != NULL)
   3461 				zone_settimer(zone, &now);
   3462 		}
   3463 	}
   3464 
   3465 	if (nsec3chain != NULL) {
   3466 		if (nsec3chain->db != NULL)
   3467 			dns_db_detach(&nsec3chain->db);
   3468 		if (nsec3chain->dbiterator != NULL)
   3469 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
   3470 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   3471 	}
   3472 
   3473  cleanup:
   3474 	if (db != NULL)
   3475 		dns_db_detach(&db);
   3476 	return (result);
   3477 }
   3478 
   3479 /*
   3480  * Find private-type records at the zone apex which signal that an NSEC3 chain
   3481  * should be added or removed.  For each such record, extract NSEC3PARAM RDATA
   3482  * and pass it to zone_addnsec3chain().
   3483  *
   3484  * Zone must be locked by caller.
   3485  */
   3486 static void
   3487 resume_addnsec3chain(dns_zone_t *zone) {
   3488 	dns_dbnode_t *node = NULL;
   3489 	dns_dbversion_t *version = NULL;
   3490 	dns_rdataset_t rdataset;
   3491 	isc_result_t result;
   3492 	dns_rdata_nsec3param_t nsec3param;
   3493 	isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
   3494 	dns_db_t *db = NULL;
   3495 
   3496 	INSIST(LOCKED_ZONE(zone));
   3497 
   3498 	if (zone->privatetype == 0)
   3499 		return;
   3500 
   3501 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3502 	if (zone->db != NULL)
   3503 		dns_db_attach(zone->db, &db);
   3504 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3505 	if (db == NULL)
   3506 		goto cleanup;
   3507 
   3508 	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
   3509 	if (result != ISC_R_SUCCESS)
   3510 		goto cleanup;
   3511 
   3512 	dns_db_currentversion(db, &version);
   3513 
   3514 	/*
   3515 	 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
   3516 	 * apex to exist and contain no keys using NSEC-only algorithms.
   3517 	 */
   3518 	result = dns_nsec_nseconly(db, version, &nseconly);
   3519 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
   3520 
   3521 	/*
   3522 	 * Get the RRset containing all private-type records at the zone apex.
   3523 	 */
   3524 	dns_rdataset_init(&rdataset);
   3525 	result = dns_db_findrdataset(db, node, version,
   3526 				     zone->privatetype, dns_rdatatype_none,
   3527 				     0, &rdataset, NULL);
   3528 	if (result != ISC_R_SUCCESS) {
   3529 		INSIST(!dns_rdataset_isassociated(&rdataset));
   3530 		goto cleanup;
   3531 	}
   3532 
   3533 	for (result = dns_rdataset_first(&rdataset);
   3534 	     result == ISC_R_SUCCESS;
   3535 	     result = dns_rdataset_next(&rdataset))
   3536 	{
   3537 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   3538 		dns_rdata_t rdata = DNS_RDATA_INIT;
   3539 		dns_rdata_t private = DNS_RDATA_INIT;
   3540 
   3541 		dns_rdataset_current(&rdataset, &private);
   3542 		/*
   3543 		 * Try extracting NSEC3PARAM RDATA from this private-type
   3544 		 * record.  Failure means this private-type record does not
   3545 		 * represent an NSEC3PARAM record, so skip it.
   3546 		 */
   3547 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
   3548 						sizeof(buf)))
   3549 			continue;
   3550 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   3551 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3552 		if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
   3553 		    ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
   3554 		{
   3555 			/*
   3556 			 * Pass the NSEC3PARAM RDATA contained in this
   3557 			 * private-type record to zone_addnsec3chain() so that
   3558 			 * it can kick off adding or removing NSEC3 records.
   3559 			 */
   3560 			result = zone_addnsec3chain(zone, &nsec3param);
   3561 			if (result != ISC_R_SUCCESS) {
   3562 				dns_zone_log(zone, ISC_LOG_ERROR,
   3563 					     "zone_addnsec3chain failed: %s",
   3564 					     dns_result_totext(result));
   3565 			}
   3566 		}
   3567 	}
   3568 	dns_rdataset_disassociate(&rdataset);
   3569  cleanup:
   3570 	if (db != NULL) {
   3571 		if (node != NULL)
   3572 			dns_db_detachnode(db, &node);
   3573 		if (version != NULL)
   3574 			dns_db_closeversion(db, &version, ISC_FALSE);
   3575 		dns_db_detach(&db);
   3576 	}
   3577 }
   3578 
   3579 static void
   3580 set_resigntime(dns_zone_t *zone) {
   3581 	dns_rdataset_t rdataset;
   3582 	dns_fixedname_t fixed;
   3583 	unsigned int resign;
   3584 	isc_result_t result;
   3585 	isc_uint32_t nanosecs;
   3586 	dns_db_t *db = NULL;
   3587 
   3588 	/* We only re-sign zones that can be dynamically updated */
   3589 	if (zone->update_disabled)
   3590 		return;
   3591 
   3592 	if (!inline_secure(zone) && (zone->type != dns_zone_master ||
   3593 	    (zone->ssutable == NULL &&
   3594 	     (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
   3595 		return;
   3596 
   3597 	dns_rdataset_init(&rdataset);
   3598 	dns_fixedname_init(&fixed);
   3599 
   3600 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   3601 	if (zone->db != NULL)
   3602 		dns_db_attach(zone->db, &db);
   3603 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   3604 	if (db == NULL) {
   3605 		isc_time_settoepoch(&zone->resigntime);
   3606 		return;
   3607 	}
   3608 
   3609 	result = dns_db_getsigningtime(db, &rdataset,
   3610 				       dns_fixedname_name(&fixed));
   3611 	if (result != ISC_R_SUCCESS) {
   3612 		isc_time_settoepoch(&zone->resigntime);
   3613 		goto cleanup;
   3614 	}
   3615 
   3616 	resign = rdataset.resign - zone->sigresigninginterval;
   3617 	dns_rdataset_disassociate(&rdataset);
   3618 	isc_random_get(&nanosecs);
   3619 	nanosecs %= 1000000000;
   3620 	isc_time_set(&zone->resigntime, resign, nanosecs);
   3621  cleanup:
   3622 	dns_db_detach(&db);
   3623 	return;
   3624 }
   3625 
   3626 static isc_result_t
   3627 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
   3628 	dns_dbnode_t *node = NULL;
   3629 	dns_rdataset_t rdataset;
   3630 	dns_dbversion_t *version = NULL;
   3631 	dns_rdata_nsec3param_t nsec3param;
   3632 	isc_boolean_t ok = ISC_FALSE;
   3633 	isc_result_t result;
   3634 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3635 	isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
   3636 				dns_zone_isdynamic(zone, ISC_FALSE) : ISC_FALSE;
   3637 
   3638 	dns_rdataset_init(&rdataset);
   3639 	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
   3640 	if (result != ISC_R_SUCCESS) {
   3641 		dns_zone_log(zone, ISC_LOG_ERROR,
   3642 			     "nsec3param lookup failure: %s",
   3643 			     dns_result_totext(result));
   3644 		return (result);
   3645 	}
   3646 	dns_db_currentversion(db, &version);
   3647 
   3648 	result = dns_db_findrdataset(db, node, version,
   3649 				     dns_rdatatype_nsec3param,
   3650 				     dns_rdatatype_none, 0, &rdataset, NULL);
   3651 	if (result == ISC_R_NOTFOUND) {
   3652 		INSIST(!dns_rdataset_isassociated(&rdataset));
   3653 		result = ISC_R_SUCCESS;
   3654 		goto cleanup;
   3655 	}
   3656 	if (result != ISC_R_SUCCESS) {
   3657 		INSIST(!dns_rdataset_isassociated(&rdataset));
   3658 		dns_zone_log(zone, ISC_LOG_ERROR,
   3659 			     "nsec3param lookup failure: %s",
   3660 			     dns_result_totext(result));
   3661 		goto cleanup;
   3662 	}
   3663 
   3664 	/*
   3665 	 * For dynamic zones we must support every algorithm so we can
   3666 	 * regenerate all the NSEC3 chains.
   3667 	 * For non-dynamic zones we only need to find a supported algorithm.
   3668 	 */
   3669 	for (result = dns_rdataset_first(&rdataset);
   3670 	     result == ISC_R_SUCCESS;
   3671 	     result = dns_rdataset_next(&rdataset))
   3672 	{
   3673 		dns_rdataset_current(&rdataset, &rdata);
   3674 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   3675 		dns_rdata_reset(&rdata);
   3676 		INSIST(result == ISC_R_SUCCESS);
   3677 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
   3678 		    nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
   3679 		{
   3680 			dns_zone_log(zone, ISC_LOG_WARNING,
   3681 			     "nsec3 test \"unknown\" hash algorithm found: %u",
   3682 				     nsec3param.hash);
   3683 			ok = ISC_TRUE;
   3684 		} else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
   3685 			if (dynamic) {
   3686 				dns_zone_log(zone, ISC_LOG_ERROR,
   3687 					     "unsupported nsec3 hash algorithm"
   3688 					     " in dynamic zone: %u",
   3689 					     nsec3param.hash);
   3690 				result = DNS_R_BADZONE;
   3691 				/* Stop second error message. */
   3692 				ok = ISC_TRUE;
   3693 				break;
   3694 			} else
   3695 				dns_zone_log(zone, ISC_LOG_WARNING,
   3696 				     "unsupported nsec3 hash algorithm: %u",
   3697 					     nsec3param.hash);
   3698 		} else
   3699 			ok = ISC_TRUE;
   3700 	}
   3701 	if (result == ISC_R_NOMORE)
   3702 		result = ISC_R_SUCCESS;
   3703 
   3704 	if (!ok) {
   3705 		result = DNS_R_BADZONE;
   3706 		dns_zone_log(zone, ISC_LOG_ERROR,
   3707 			     "no supported nsec3 hash algorithm");
   3708 	}
   3709 
   3710  cleanup:
   3711 	if (dns_rdataset_isassociated(&rdataset))
   3712 		dns_rdataset_disassociate(&rdataset);
   3713 	dns_db_closeversion(db, &version, ISC_FALSE);
   3714 	dns_db_detachnode(db, &node);
   3715 	return (result);
   3716 }
   3717 
   3718 /*
   3719  * Set the timer for refreshing the key zone to the soonest future time
   3720  * of the set (current timer, keydata->refresh, keydata->addhd,
   3721  * keydata->removehd).
   3722  */
   3723 static void
   3724 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
   3725 		    isc_stdtime_t now, isc_boolean_t force)
   3726 {
   3727 	const char me[] = "set_refreshkeytimer";
   3728 	isc_stdtime_t then;
   3729 	isc_time_t timenow, timethen;
   3730 	char timebuf[80];
   3731 
   3732 	ENTER;
   3733 	then = key->refresh;
   3734 	if (force)
   3735 		then = now;
   3736 	if (key->addhd > now && key->addhd < then)
   3737 		then = key->addhd;
   3738 	if (key->removehd > now && key->removehd < then)
   3739 		then = key->removehd;
   3740 
   3741 	TIME_NOW(&timenow);
   3742 	if (then > now)
   3743 		DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
   3744 	else
   3745 		timethen = timenow;
   3746 	if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
   3747 	    isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
   3748 		zone->refreshkeytime = timethen;
   3749 
   3750 	isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   3751 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
   3752 	zone_settimer(zone, &timenow);
   3753 }
   3754 
   3755 /*
   3756  * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
   3757  * If the key zone is changed, set '*changed' to ISC_TRUE.
   3758  */
   3759 static isc_result_t
   3760 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   3761 	       dns_diff_t *diff, dns_keytable_t *keytable,
   3762 	       dns_keynode_t **keynodep, isc_boolean_t *changed)
   3763 {
   3764 	const char me[] = "create_keydata";
   3765 	isc_result_t result = ISC_R_SUCCESS;
   3766 	isc_buffer_t keyb, dstb;
   3767 	unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
   3768 	dns_rdata_keydata_t keydata;
   3769 	dns_rdata_dnskey_t dnskey;
   3770 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3771 	dns_keynode_t *keynode;
   3772 	isc_stdtime_t now;
   3773 	isc_region_t r;
   3774 	dst_key_t *key;
   3775 
   3776 	REQUIRE(keynodep != NULL);
   3777 	keynode = *keynodep;
   3778 
   3779 	ENTER;
   3780 	isc_stdtime_get(&now);
   3781 
   3782 	/* Loop in case there's more than one key. */
   3783 	while (result == ISC_R_SUCCESS) {
   3784 		dns_keynode_t *nextnode = NULL;
   3785 
   3786 		key = dns_keynode_key(keynode);
   3787 		if (key == NULL)
   3788 			goto skip;
   3789 
   3790 		isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
   3791 		CHECK(dst_key_todns(key, &dstb));
   3792 
   3793 		/* Convert DST key to DNSKEY. */
   3794 		dns_rdata_reset(&rdata);
   3795 		isc_buffer_usedregion(&dstb, &r);
   3796 		dns_rdata_fromregion(&rdata, dst_key_class(key),
   3797 				     dns_rdatatype_dnskey, &r);
   3798 
   3799 		/* DSTKEY to KEYDATA. */
   3800 		CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
   3801 		CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
   3802 					     NULL));
   3803 
   3804 		/* KEYDATA to rdata. */
   3805 		dns_rdata_reset(&rdata);
   3806 		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   3807 		CHECK(dns_rdata_fromstruct(&rdata,
   3808 					   zone->rdclass, dns_rdatatype_keydata,
   3809 					   &keydata, &keyb));
   3810 
   3811 		/* Add rdata to zone. */
   3812 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
   3813 				    dst_key_name(key), 0, &rdata));
   3814 		*changed = ISC_TRUE;
   3815 
   3816 		/* Refresh new keys from the zone apex as soon as possible. */
   3817 		set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
   3818 
   3819  skip:
   3820 		result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
   3821 		if (result != ISC_R_NOTFOUND) {
   3822 			dns_keytable_detachkeynode(keytable, &keynode);
   3823 			keynode = nextnode;
   3824 		}
   3825 	}
   3826 
   3827 	if (keynode != NULL)
   3828 		dns_keytable_detachkeynode(keytable, &keynode);
   3829 	*keynodep = NULL;
   3830 
   3831 	return (ISC_R_SUCCESS);
   3832 
   3833   failure:
   3834 	return (result);
   3835 }
   3836 
   3837 /*
   3838  * Remove from the key zone all the KEYDATA records found in rdataset.
   3839  */
   3840 static isc_result_t
   3841 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
   3842 	       dns_name_t *name, dns_rdataset_t *rdataset)
   3843 {
   3844 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3845 	isc_result_t result, uresult;
   3846 
   3847 	for (result = dns_rdataset_first(rdataset);
   3848 	     result == ISC_R_SUCCESS;
   3849 	     result = dns_rdataset_next(rdataset)) {
   3850 		dns_rdata_reset(&rdata);
   3851 		dns_rdataset_current(rdataset, &rdata);
   3852 		uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
   3853 					name, 0, &rdata);
   3854 		if (uresult != ISC_R_SUCCESS)
   3855 			return (uresult);
   3856 	}
   3857 	if (result == ISC_R_NOMORE)
   3858 		result = ISC_R_SUCCESS;
   3859 	return (result);
   3860 }
   3861 
   3862 /*
   3863  * Compute the DNSSEC key ID for a DNSKEY record.
   3864  */
   3865 static isc_result_t
   3866 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
   3867 	    dns_keytag_t *tag)
   3868 {
   3869 	isc_result_t result;
   3870 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3871 	unsigned char data[4096];
   3872 	isc_buffer_t buffer;
   3873 	dst_key_t *dstkey = NULL;
   3874 
   3875 	isc_buffer_init(&buffer, data, sizeof(data));
   3876 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
   3877 			     dns_rdatatype_dnskey, dnskey, &buffer);
   3878 
   3879 	result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
   3880 	if (result == ISC_R_SUCCESS)
   3881 		*tag = dst_key_id(dstkey);
   3882 	dst_key_free(&dstkey);
   3883 
   3884 	return (result);
   3885 }
   3886 
   3887 /*
   3888  * Add key to the security roots.
   3889  */
   3890 static void
   3891 trust_key(dns_zone_t *zone, dns_name_t *keyname,
   3892 	  dns_rdata_dnskey_t *dnskey, isc_boolean_t initial,
   3893 	  isc_mem_t *mctx)
   3894 {
   3895 	isc_result_t result;
   3896 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3897 	unsigned char data[4096];
   3898 	isc_buffer_t buffer;
   3899 	dns_keytable_t *sr = NULL;
   3900 	dst_key_t *dstkey = NULL;
   3901 
   3902 	/* Convert dnskey to DST key. */
   3903 	isc_buffer_init(&buffer, data, sizeof(data));
   3904 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
   3905 			     dns_rdatatype_dnskey, dnskey, &buffer);
   3906 
   3907 	result = dns_view_getsecroots(zone->view, &sr);
   3908 	if (result != ISC_R_SUCCESS)
   3909 		goto failure;
   3910 
   3911 	CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
   3912 	CHECK(dns_keytable_add2(sr, ISC_TRUE, initial, &dstkey));
   3913 	dns_keytable_detach(&sr);
   3914 
   3915   failure:
   3916 	if (dstkey != NULL)
   3917 		dst_key_free(&dstkey);
   3918 	if (sr != NULL)
   3919 		dns_keytable_detach(&sr);
   3920 	return;
   3921 }
   3922 
   3923 /*
   3924  * Add a null key to the security roots for so that all queries
   3925  * to the zone will fail.
   3926  */
   3927 static void
   3928 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
   3929 	isc_result_t result;
   3930 	dns_keytable_t *sr = NULL;
   3931 
   3932 	result = dns_view_getsecroots(zone->view, &sr);
   3933 	if (result == ISC_R_SUCCESS) {
   3934 		dns_keytable_marksecure(sr, keyname);
   3935 		dns_keytable_detach(&sr);
   3936 	}
   3937 }
   3938 
   3939 /*
   3940  * Scan a set of KEYDATA records from the key zone.  The ones that are
   3941  * valid (i.e., the add holddown timer has expired) become trusted keys.
   3942  */
   3943 static void
   3944 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
   3945 	isc_result_t result;
   3946 	dns_rdata_t rdata = DNS_RDATA_INIT;
   3947 	dns_rdata_keydata_t keydata;
   3948 	dns_rdata_dnskey_t dnskey;
   3949 	isc_mem_t *mctx = zone->mctx;
   3950 	int trusted = 0, revoked = 0, pending = 0;
   3951 	isc_stdtime_t now;
   3952 	dns_keytable_t *sr = NULL;
   3953 
   3954 	isc_stdtime_get(&now);
   3955 
   3956 	result = dns_view_getsecroots(zone->view, &sr);
   3957 	if (result == ISC_R_SUCCESS) {
   3958 		dns_keytable_delete(sr, name);
   3959 		dns_keytable_detach(&sr);
   3960 	}
   3961 
   3962 	/* Now insert all the accepted trust anchors from this keydata set. */
   3963 	for (result = dns_rdataset_first(rdataset);
   3964 	     result == ISC_R_SUCCESS;
   3965 	     result = dns_rdataset_next(rdataset)) {
   3966 		dns_rdata_reset(&rdata);
   3967 		dns_rdataset_current(rdataset, &rdata);
   3968 
   3969 		/* Convert rdata to keydata. */
   3970 		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
   3971 		if (result == ISC_R_UNEXPECTEDEND)
   3972 			continue;
   3973 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   3974 
   3975 		/* Set the key refresh timer to force a fast refresh. */
   3976 		set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
   3977 
   3978 		/* If the removal timer is nonzero, this key was revoked. */
   3979 		if (keydata.removehd != 0) {
   3980 			revoked++;
   3981 			continue;
   3982 		}
   3983 
   3984 		/*
   3985 		 * If the add timer is still pending, this key is not
   3986 		 * trusted yet.
   3987 		 */
   3988 		if (now < keydata.addhd) {
   3989 			pending++;
   3990 			continue;
   3991 		}
   3992 
   3993 		/* Convert keydata to dnskey. */
   3994 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
   3995 
   3996 		/* Add to keytables. */
   3997 		trusted++;
   3998 		trust_key(zone, name, &dnskey,
   3999 			  ISC_TF(keydata.addhd == 0), mctx);
   4000 	}
   4001 
   4002 	if (trusted == 0 && pending != 0) {
   4003 		char namebuf[DNS_NAME_FORMATSIZE];
   4004 		dns_name_format(name, namebuf, sizeof namebuf);
   4005 		dns_zone_log(zone, ISC_LOG_ERROR,
   4006 			     "No valid trust anchors for '%s'!", namebuf);
   4007 		dns_zone_log(zone, ISC_LOG_ERROR,
   4008 			     "%d key(s) revoked, %d still pending",
   4009 			     revoked, pending);
   4010 		dns_zone_log(zone, ISC_LOG_ERROR,
   4011 			     "All queries to '%s' will fail", namebuf);
   4012 		fail_secure(zone, name);
   4013 	}
   4014 }
   4015 
   4016 static isc_result_t
   4017 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
   4018 	     dns_diff_t *diff)
   4019 {
   4020 	dns_diff_t temp_diff;
   4021 	isc_result_t result;
   4022 
   4023 	/*
   4024 	 * Create a singleton diff.
   4025 	 */
   4026 	dns_diff_init(diff->mctx, &temp_diff);
   4027 	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
   4028 
   4029 	/*
   4030 	 * Apply it to the database.
   4031 	 */
   4032 	result = dns_diff_apply(&temp_diff, db, ver);
   4033 	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
   4034 	if (result != ISC_R_SUCCESS) {
   4035 		dns_difftuple_free(tuple);
   4036 		return (result);
   4037 	}
   4038 
   4039 	/*
   4040 	 * Merge it into the current pending journal entry.
   4041 	 */
   4042 	dns_diff_appendminimal(diff, tuple);
   4043 
   4044 	/*
   4045 	 * Do not clear temp_diff.
   4046 	 */
   4047 	return (ISC_R_SUCCESS);
   4048 }
   4049 
   4050 static isc_result_t
   4051 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
   4052 	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
   4053 	      dns_rdata_t *rdata)
   4054 {
   4055 	dns_difftuple_t *tuple = NULL;
   4056 	isc_result_t result;
   4057 	result = dns_difftuple_create(diff->mctx, op,
   4058 				      name, ttl, rdata, &tuple);
   4059 	if (result != ISC_R_SUCCESS)
   4060 		return (result);
   4061 	return (do_one_tuple(&tuple, db, ver, diff));
   4062 }
   4063 
   4064 static isc_result_t
   4065 update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
   4066 		  isc_mem_t *mctx, dns_updatemethod_t method) {
   4067 	dns_difftuple_t *deltuple = NULL;
   4068 	dns_difftuple_t *addtuple = NULL;
   4069 	isc_uint32_t serial;
   4070 	isc_result_t result;
   4071 
   4072 	INSIST(method != dns_updatemethod_none);
   4073 
   4074 	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
   4075 	CHECK(dns_difftuple_copy(deltuple, &addtuple));
   4076 	addtuple->op = DNS_DIFFOP_ADD;
   4077 
   4078 	serial = dns_soa_getserial(&addtuple->rdata);
   4079 	serial = dns_update_soaserial(serial, method);
   4080 	dns_soa_setserial(serial, &addtuple->rdata);
   4081 	CHECK(do_one_tuple(&deltuple, db, ver, diff));
   4082 	CHECK(do_one_tuple(&addtuple, db, ver, diff));
   4083 	result = ISC_R_SUCCESS;
   4084 
   4085 	failure:
   4086 	if (addtuple != NULL)
   4087 		dns_difftuple_free(&addtuple);
   4088 	if (deltuple != NULL)
   4089 		dns_difftuple_free(&deltuple);
   4090 	return (result);
   4091 }
   4092 
   4093 /*
   4094  * Write all transactions in 'diff' to the zone journal file.
   4095  */
   4096 static isc_result_t
   4097 zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *sourceserial,
   4098 	     const char *caller)
   4099 {
   4100 	const char me[] = "zone_journal";
   4101 	const char *journalfile;
   4102 	isc_result_t result = ISC_R_SUCCESS;
   4103 	dns_journal_t *journal = NULL;
   4104 	unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
   4105 
   4106 	ENTER;
   4107 	journalfile = dns_zone_getjournal(zone);
   4108 	if (journalfile != NULL) {
   4109 		result = dns_journal_open(zone->mctx, journalfile, mode,
   4110 					  &journal);
   4111 		if (result != ISC_R_SUCCESS) {
   4112 			dns_zone_log(zone, ISC_LOG_ERROR,
   4113 				     "%s:dns_journal_open -> %s",
   4114 				     caller, dns_result_totext(result));
   4115 			return (result);
   4116 		}
   4117 
   4118 		if (sourceserial != NULL)
   4119 			dns_journal_set_sourceserial(journal, *sourceserial);
   4120 
   4121 		result = dns_journal_write_transaction(journal, diff);
   4122 		if (result != ISC_R_SUCCESS) {
   4123 			dns_zone_log(zone, ISC_LOG_ERROR,
   4124 				     "%s:dns_journal_write_transaction -> %s",
   4125 				     caller, dns_result_totext(result));
   4126 		}
   4127 		dns_journal_destroy(&journal);
   4128 	}
   4129 
   4130 	return (result);
   4131 }
   4132 
   4133 /*
   4134  * Create an SOA record for a newly-created zone
   4135  */
   4136 static isc_result_t
   4137 add_soa(dns_zone_t *zone, dns_db_t *db) {
   4138 	isc_result_t result;
   4139 	dns_rdata_t rdata = DNS_RDATA_INIT;
   4140 	unsigned char buf[DNS_SOA_BUFFERSIZE];
   4141 	dns_dbversion_t *ver = NULL;
   4142 	dns_diff_t diff;
   4143 
   4144 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
   4145 
   4146 	dns_diff_init(zone->mctx, &diff);
   4147 	result = dns_db_newversion(db, &ver);
   4148 	if (result != ISC_R_SUCCESS) {
   4149 		dns_zone_log(zone, ISC_LOG_ERROR,
   4150 			     "add_soa:dns_db_newversion -> %s",
   4151 			     dns_result_totext(result));
   4152 		goto failure;
   4153 	}
   4154 
   4155 	/* Build SOA record */
   4156 	result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
   4157 				    0, 0, 0, 0, 0, buf, &rdata);
   4158 	if (result != ISC_R_SUCCESS) {
   4159 		dns_zone_log(zone, ISC_LOG_ERROR,
   4160 			     "add_soa:dns_soa_buildrdata -> %s",
   4161 			     dns_result_totext(result));
   4162 		goto failure;
   4163 	}
   4164 
   4165 	result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
   4166 			       &zone->origin, 0, &rdata);
   4167 
   4168 failure:
   4169 	dns_diff_clear(&diff);
   4170 	if (ver != NULL)
   4171 		dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
   4172 
   4173 	INSIST(ver == NULL);
   4174 
   4175 	return (result);
   4176 }
   4177 
   4178 struct addifmissing_arg {
   4179 	dns_db_t *db;
   4180 	dns_dbversion_t *ver;
   4181 	dns_diff_t *diff;
   4182 	dns_zone_t *zone;
   4183 	isc_boolean_t *changed;
   4184 	isc_result_t result;
   4185 };
   4186 
   4187 static void
   4188 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
   4189 	dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
   4190 	dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
   4191 	dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
   4192 	dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
   4193 	isc_boolean_t *changed = ((struct addifmissing_arg *)arg)->changed;
   4194 	isc_result_t result;
   4195 	dns_keynode_t *dummy = NULL;
   4196 
   4197 	if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS)
   4198 		return;
   4199 
   4200 	if (dns_keynode_managed(keynode)) {
   4201 		dns_fixedname_t fname;
   4202 		dns_name_t *keyname;
   4203 		dst_key_t *key;
   4204 
   4205 		key = dns_keynode_key(keynode);
   4206 		if (key == NULL)
   4207 			return;
   4208 		dns_fixedname_init(&fname);
   4209 
   4210 		keyname = dst_key_name(key);
   4211 		result = dns_db_find(db, keyname, ver,
   4212 				     dns_rdatatype_keydata,
   4213 				     DNS_DBFIND_NOWILD, 0, NULL,
   4214 				     dns_fixedname_name(&fname),
   4215 				     NULL, NULL);
   4216 		if (result == ISC_R_SUCCESS)
   4217 			return;
   4218 		dns_keytable_attachkeynode(keytable, keynode, &dummy);
   4219 		result = create_keydata(zone, db, ver, diff, keytable,
   4220 					&dummy, changed);
   4221 		if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
   4222 			((struct addifmissing_arg *)arg)->result = result;
   4223 	}
   4224 };
   4225 
   4226 /*
   4227  * Synchronize the set of initializing keys found in managed-keys {}
   4228  * statements with the set of trust anchors found in the managed-keys.bind
   4229  * zone.  If a domain is no longer named in managed-keys, delete all keys
   4230  * from that domain from the key zone.	If a domain is mentioned in in
   4231  * managed-keys but there are no references to it in the key zone, load
   4232  * the key zone with the initializing key(s) for that domain.
   4233  */
   4234 static isc_result_t
   4235 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
   4236 	isc_result_t result = ISC_R_SUCCESS;
   4237 	isc_boolean_t changed = ISC_FALSE;
   4238 	isc_boolean_t commit = ISC_FALSE;
   4239 	dns_keynode_t *keynode = NULL;
   4240 	dns_view_t *view = zone->view;
   4241 	dns_keytable_t *sr = NULL;
   4242 	dns_dbversion_t *ver = NULL;
   4243 	dns_diff_t diff;
   4244 	dns_rriterator_t rrit;
   4245 	struct addifmissing_arg arg;
   4246 
   4247 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
   4248 
   4249 	dns_diff_init(zone->mctx, &diff);
   4250 
   4251 	CHECK(dns_view_getsecroots(view, &sr));
   4252 
   4253 	result = dns_db_newversion(db, &ver);
   4254 	if (result != ISC_R_SUCCESS) {
   4255 		dns_zone_log(zone, ISC_LOG_ERROR,
   4256 			     "sync_keyzone:dns_db_newversion -> %s",
   4257 			     dns_result_totext(result));
   4258 		goto failure;
   4259 	}
   4260 
   4261 	/*
   4262 	 * Walk the zone DB.  If we find any keys whose names are no longer
   4263 	 * in managed-keys (or *are* in trusted-keys, meaning they are
   4264 	 * permanent and not RFC5011-maintained), delete them from the
   4265 	 * zone.  Otherwise call load_secroots(), which loads keys into
   4266 	 * secroots as appropriate.
   4267 	 */
   4268 	dns_rriterator_init(&rrit, db, ver, 0);
   4269 	for (result = dns_rriterator_first(&rrit);
   4270 	     result == ISC_R_SUCCESS;
   4271 	     result = dns_rriterator_nextrrset(&rrit)) {
   4272 		dns_rdataset_t *rdataset = NULL;
   4273 		dns_name_t *rrname = NULL;
   4274 		isc_uint32_t ttl;
   4275 
   4276 		dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
   4277 		if (!dns_rdataset_isassociated(rdataset)) {
   4278 			dns_rriterator_destroy(&rrit);
   4279 			goto failure;
   4280 		}
   4281 
   4282 		if (rdataset->type != dns_rdatatype_keydata)
   4283 			continue;
   4284 
   4285 		result = dns_keytable_find(sr, rrname, &keynode);
   4286 		if ((result != ISC_R_SUCCESS &&
   4287 		     result != DNS_R_PARTIALMATCH) ||
   4288 		    dns_keynode_managed(keynode) == ISC_FALSE)
   4289 		{
   4290 			CHECK(delete_keydata(db, ver, &diff,
   4291 					     rrname, rdataset));
   4292 			changed = ISC_TRUE;
   4293 		} else {
   4294 			load_secroots(zone, rrname, rdataset);
   4295 		}
   4296 
   4297 		if (keynode != NULL)
   4298 			dns_keytable_detachkeynode(sr, &keynode);
   4299 	}
   4300 	dns_rriterator_destroy(&rrit);
   4301 
   4302 	/*
   4303 	 * Now walk secroots to find any managed keys that aren't
   4304 	 * in the zone.  If we find any, we add them to the zone.
   4305 	 */
   4306 	arg.db = db;
   4307 	arg.ver = ver;
   4308 	arg.result = ISC_R_SUCCESS;
   4309 	arg.diff = &diff;
   4310 	arg.zone = zone;
   4311 	arg.changed = &changed;
   4312 	dns_keytable_forall(sr, addifmissing, &arg);
   4313 	result = arg.result;
   4314 	if (changed) {
   4315 		/* Write changes to journal file. */
   4316 		CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
   4317 					zone->updatemethod));
   4318 		CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
   4319 
   4320 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   4321 		zone_needdump(zone, 30);
   4322 		commit = ISC_TRUE;
   4323 	}
   4324 
   4325  failure:
   4326 	if (result != ISC_R_SUCCESS &&
   4327 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   4328 		dns_zone_log(zone, ISC_LOG_ERROR,
   4329 			     "unable to synchronize managed keys: %s",
   4330 			     dns_result_totext(result));
   4331 		isc_time_settoepoch(&zone->refreshkeytime);
   4332 	}
   4333 	if (keynode != NULL)
   4334 		dns_keytable_detachkeynode(sr, &keynode);
   4335 	if (sr != NULL)
   4336 		dns_keytable_detach(&sr);
   4337 	if (ver != NULL)
   4338 		dns_db_closeversion(db, &ver, commit);
   4339 	dns_diff_clear(&diff);
   4340 
   4341 	INSIST(ver == NULL);
   4342 
   4343 	return (result);
   4344 }
   4345 
   4346 isc_result_t
   4347 dns_zone_synckeyzone(dns_zone_t *zone) {
   4348 	isc_result_t result;
   4349 	dns_db_t *db = NULL;
   4350 
   4351 	if (zone->type != dns_zone_key)
   4352 		return (DNS_R_BADZONE);
   4353 
   4354 	CHECK(dns_zone_getdb(zone, &db));
   4355 
   4356 	LOCK_ZONE(zone);
   4357 	result = sync_keyzone(zone, db);
   4358 	UNLOCK_ZONE(zone);
   4359 
   4360  failure:
   4361 	if (db != NULL)
   4362 		dns_db_detach(&db);
   4363 	return (result);
   4364 }
   4365 
   4366 static void
   4367 maybe_send_secure(dns_zone_t *zone) {
   4368 	isc_result_t result;
   4369 
   4370 	/*
   4371 	 * We've finished loading, or else failed to load, an inline-signing
   4372 	 * 'secure' zone.  We now need information about the status of the
   4373 	 * 'raw' zone.  If we failed to load, then we need it to send a
   4374 	 * copy of its database; if we succeeded, we need it to send its
   4375 	 * serial number so that we can sync with it.  If it has not yet
   4376 	 * loaded, we set a flag so that it will send the necessary
   4377 	 * information when it has finished loading.
   4378 	 */
   4379 	if (zone->raw->db != NULL) {
   4380 		if (zone->db != NULL) {
   4381 			isc_uint32_t serial;
   4382 			unsigned int soacount;
   4383 
   4384 			result = zone_get_from_db(zone->raw, zone->raw->db,
   4385 						  NULL, &soacount, &serial, NULL,
   4386 						  NULL, NULL, NULL, NULL);
   4387 			if (result == ISC_R_SUCCESS && soacount > 0U)
   4388 				zone_send_secureserial(zone->raw, serial);
   4389 		} else
   4390 			zone_send_securedb(zone->raw, zone->raw->db);
   4391 
   4392 	} else
   4393 		DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
   4394 }
   4395 
   4396 static isc_boolean_t
   4397 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
   4398 	isc_result_t result;
   4399 	isc_boolean_t answer = ISC_FALSE;
   4400 	dns_diff_t diff;
   4401 
   4402 	dns_diff_init(mctx, &diff);
   4403 	result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
   4404 	if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
   4405 		answer = ISC_TRUE;
   4406 	dns_diff_clear(&diff);
   4407 	return (answer);
   4408 }
   4409 
   4410 /*
   4411  * The zone is presumed to be locked.
   4412  * If this is a inline_raw zone the secure version is also locked.
   4413  */
   4414 static isc_result_t
   4415 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
   4416 	      isc_result_t result)
   4417 {
   4418 	unsigned int soacount = 0;
   4419 	unsigned int nscount = 0;
   4420 	unsigned int errors = 0;
   4421 	isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
   4422 	isc_time_t now;
   4423 	isc_boolean_t needdump = ISC_FALSE;
   4424 	isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
   4425 	isc_boolean_t nomaster = ISC_FALSE;
   4426 	unsigned int options;
   4427 	dns_include_t *inc;
   4428 
   4429 	INSIST(LOCKED_ZONE(zone));
   4430 	if (inline_raw(zone))
   4431 		INSIST(LOCKED_ZONE(zone->secure));
   4432 
   4433 	TIME_NOW(&now);
   4434 
   4435 	/*
   4436 	 * Initiate zone transfer?  We may need a error code that
   4437 	 * indicates that the "permanent" form does not exist.
   4438 	 * XXX better error feedback to log.
   4439 	 */
   4440 	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
   4441 		if (zone->type == dns_zone_slave ||
   4442 		    zone->type == dns_zone_stub ||
   4443 		    (zone->type == dns_zone_redirect &&
   4444 		     zone->masters == NULL)) {
   4445 			if (result == ISC_R_FILENOTFOUND)
   4446 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4447 					      ISC_LOG_DEBUG(1),
   4448 					     "no master file");
   4449 			else if (result != DNS_R_NOMASTERFILE)
   4450 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4451 					      ISC_LOG_ERROR,
   4452 					     "loading from master file %s "
   4453 					     "failed: %s",
   4454 					     zone->masterfile,
   4455 					     dns_result_totext(result));
   4456 		} else if (zone->type == dns_zone_master &&
   4457 			   inline_secure(zone) && result == ISC_R_FILENOTFOUND)
   4458 		{
   4459 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4460 				      ISC_LOG_DEBUG(1),
   4461 				     "no master file, requesting db");
   4462 			maybe_send_secure(zone);
   4463 		} else {
   4464 			int level = ISC_LOG_ERROR;
   4465 			if (zone->type == dns_zone_key &&
   4466 			    result == ISC_R_FILENOTFOUND)
   4467 				level = ISC_LOG_DEBUG(1);
   4468 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
   4469 				     "loading from master file %s failed: %s",
   4470 				     zone->masterfile,
   4471 				     dns_result_totext(result));
   4472 			nomaster = ISC_TRUE;
   4473 		}
   4474 
   4475 		if (zone->type != dns_zone_key)
   4476 			goto cleanup;
   4477 	}
   4478 
   4479 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
   4480 		     "number of nodes in database: %u",
   4481 		     dns_db_nodecount(db));
   4482 
   4483 	if (result == DNS_R_SEENINCLUDE)
   4484 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
   4485 	else
   4486 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
   4487 
   4488 	/*
   4489 	 * If there's no master file for a key zone, then the zone is new:
   4490 	 * create an SOA record.  (We do this now, instead of later, so that
   4491 	 * if there happens to be a journal file, we can roll forward from
   4492 	 * a sane starting point.)
   4493 	 */
   4494 	if (nomaster && zone->type == dns_zone_key) {
   4495 		result = add_soa(zone, db);
   4496 		if (result != ISC_R_SUCCESS)
   4497 			goto cleanup;
   4498 	}
   4499 
   4500 	/*
   4501 	 * Apply update log, if any, on initial load.
   4502 	 */
   4503 	if (zone->journal != NULL &&
   4504 	    ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
   4505 	    ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   4506 	{
   4507 		if (zone->type == dns_zone_master &&
   4508 		    (zone->update_acl != NULL || zone->ssutable != NULL))
   4509 			options = DNS_JOURNALOPT_RESIGN;
   4510 		else
   4511 			options = 0;
   4512 		result = dns_journal_rollforward(zone->mctx, db, options,
   4513 						 zone->journal);
   4514 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
   4515 		    result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
   4516 		    result != ISC_R_RANGE)
   4517 		{
   4518 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4519 				      ISC_LOG_ERROR,
   4520 				     "journal rollforward failed: %s",
   4521 				     dns_result_totext(result));
   4522 			goto cleanup;
   4523 
   4524 
   4525 		}
   4526 		if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
   4527 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4528 				      ISC_LOG_ERROR,
   4529 				     "journal rollforward failed: "
   4530 				     "journal out of sync with zone");
   4531 			goto cleanup;
   4532 		}
   4533 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
   4534 			     "journal rollforward completed "
   4535 			     "successfully: %s",
   4536 			     dns_result_totext(result));
   4537 		if (result == ISC_R_SUCCESS)
   4538 			needdump = ISC_TRUE;
   4539 	}
   4540 
   4541 	/*
   4542 	 * Obtain ns, soa and cname counts for top of zone.
   4543 	 */
   4544 	INSIST(db != NULL);
   4545 	result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
   4546 				  &refresh, &retry, &expire, &minimum,
   4547 				  &errors);
   4548 	if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
   4549 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
   4550 			     "could not find NS and/or SOA records");
   4551 	}
   4552 
   4553 	/*
   4554 	 * Check to make sure the journal is up to date, and remove the
   4555 	 * journal file if it isn't, as we wouldn't be able to apply
   4556 	 * updates otherwise.
   4557 	 */
   4558 	if (zone->journal != NULL && dns_zone_isdynamic(zone, ISC_TRUE) &&
   4559 	    ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
   4560 		isc_uint32_t jserial;
   4561 		dns_journal_t *journal = NULL;
   4562 		isc_boolean_t empty = ISC_FALSE;
   4563 
   4564 		result = dns_journal_open(zone->mctx, zone->journal,
   4565 					  DNS_JOURNAL_READ, &journal);
   4566 		if (result == ISC_R_SUCCESS) {
   4567 			jserial = dns_journal_last_serial(journal);
   4568 			empty = dns_journal_empty(journal);
   4569 			dns_journal_destroy(&journal);
   4570 		} else {
   4571 			jserial = serial;
   4572 			result = ISC_R_SUCCESS;
   4573 		}
   4574 
   4575 		if (jserial != serial) {
   4576 			if (!empty)
   4577 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4578 					      ISC_LOG_INFO,
   4579 					     "journal file is out of date: "
   4580 					     "removing journal file");
   4581 			if (remove(zone->journal) < 0 && errno != ENOENT) {
   4582 				char strbuf[ISC_STRERRORSIZE];
   4583 				isc__strerror(errno, strbuf, sizeof(strbuf));
   4584 				isc_log_write(dns_lctx,
   4585 					      DNS_LOGCATEGORY_GENERAL,
   4586 					      DNS_LOGMODULE_ZONE,
   4587 					      ISC_LOG_WARNING,
   4588 					      "unable to remove journal "
   4589 					      "'%s': '%s'",
   4590 					      zone->journal, strbuf);
   4591 			}
   4592 		}
   4593 	}
   4594 
   4595 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
   4596 		      "loaded; checking validity");
   4597 
   4598 	/*
   4599 	 * Master / Slave / Stub zones require both NS and SOA records at
   4600 	 * the top of the zone.
   4601 	 */
   4602 
   4603 	switch (zone->type) {
   4604 	case dns_zone_dlz:
   4605 	case dns_zone_master:
   4606 	case dns_zone_slave:
   4607 	case dns_zone_stub:
   4608 	case dns_zone_redirect:
   4609 		if (soacount != 1) {
   4610 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4611 				      ISC_LOG_ERROR,
   4612 				     "has %d SOA records", soacount);
   4613 			result = DNS_R_BADZONE;
   4614 		}
   4615 		if (nscount == 0) {
   4616 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4617 				      ISC_LOG_ERROR,
   4618 				     "has no NS records");
   4619 			result = DNS_R_BADZONE;
   4620 		}
   4621 		if (result != ISC_R_SUCCESS)
   4622 			goto cleanup;
   4623 		if (zone->type == dns_zone_master && errors != 0) {
   4624 			result = DNS_R_BADZONE;
   4625 			goto cleanup;
   4626 		}
   4627 		if (zone->type != dns_zone_stub &&
   4628 		    zone->type != dns_zone_redirect) {
   4629 			result = check_nsec3param(zone, db);
   4630 			if (result != ISC_R_SUCCESS)
   4631 				goto cleanup;
   4632 		}
   4633 		if (zone->type == dns_zone_master &&
   4634 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
   4635 		    !integrity_checks(zone, db)) {
   4636 			result = DNS_R_BADZONE;
   4637 			goto cleanup;
   4638 		}
   4639 		if (zone->type == dns_zone_master &&
   4640 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
   4641 		    !zone_check_dup(zone, db)) {
   4642 			result = DNS_R_BADZONE;
   4643 			goto cleanup;
   4644 		}
   4645 
   4646 		if (zone->db != NULL) {
   4647 			unsigned int oldsoacount;
   4648 
   4649 			/*
   4650 			 * This is checked in zone_replacedb() for slave zones
   4651 			 * as they don't reload from disk.
   4652 			 */
   4653 			result = zone_get_from_db(zone, zone->db, NULL,
   4654 						  &oldsoacount, &oldserial,
   4655 						  NULL, NULL, NULL, NULL,
   4656 						  NULL);
   4657 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   4658 			RUNTIME_CHECK(soacount > 0U);
   4659 			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
   4660 			    !isc_serial_gt(serial, oldserial)) {
   4661 				isc_uint32_t serialmin, serialmax;
   4662 
   4663 				INSIST(zone->type == dns_zone_master);
   4664 
   4665 				if (serial == oldserial &&
   4666 				    zone_unchanged(zone->db, db, zone->mctx)) {
   4667 					dns_zone_logc(zone,
   4668 						      DNS_LOGCATEGORY_ZONELOAD,
   4669 						      ISC_LOG_INFO,
   4670 						     "ixfr-from-differences: "
   4671 						     "unchanged");
   4672 					return(ISC_R_SUCCESS);
   4673 				}
   4674 
   4675 				serialmin = (oldserial + 1) & 0xffffffffU;
   4676 				serialmax = (oldserial + 0x7fffffffU) &
   4677 					     0xffffffffU;
   4678 				dns_zone_logc(zone,
   4679 					      DNS_LOGCATEGORY_ZONELOAD,
   4680 					      ISC_LOG_ERROR,
   4681 					      "ixfr-from-differences: "
   4682 					      "new serial (%u) out of range "
   4683 					      "[%u - %u]", serial, serialmin,
   4684 					      serialmax);
   4685 				result = DNS_R_BADZONE;
   4686 				goto cleanup;
   4687 			} else if (!isc_serial_ge(serial, oldserial))
   4688 				dns_zone_logc(zone,
   4689 					      DNS_LOGCATEGORY_ZONELOAD,
   4690 					      ISC_LOG_ERROR,
   4691 					      "zone serial (%u/%u) has gone "
   4692 					      "backwards", serial, oldserial);
   4693 			else if (serial == oldserial && !hasinclude &&
   4694 				 strcmp(zone->db_argv[0], "_builtin") != 0)
   4695 				dns_zone_logc(zone,
   4696 					      DNS_LOGCATEGORY_ZONELOAD,
   4697 					      ISC_LOG_ERROR,
   4698 					      "zone serial (%u) unchanged. "
   4699 					      "zone may fail to transfer "
   4700 					      "to slaves.", serial);
   4701 		}
   4702 
   4703 		if (zone->type == dns_zone_master &&
   4704 		    (zone->update_acl != NULL || zone->ssutable != NULL) &&
   4705 		    zone->sigresigninginterval < (3 * refresh) &&
   4706 		    dns_db_issecure(db))
   4707 		{
   4708 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4709 				      ISC_LOG_WARNING,
   4710 				      "sig-re-signing-interval less than "
   4711 				      "3 * refresh.");
   4712 		}
   4713 
   4714 		zone->refresh = RANGE(refresh,
   4715 				      zone->minrefresh, zone->maxrefresh);
   4716 		zone->retry = RANGE(retry,
   4717 				    zone->minretry, zone->maxretry);
   4718 		zone->expire = RANGE(expire, zone->refresh + zone->retry,
   4719 				     DNS_MAX_EXPIRE);
   4720 		zone->minimum = minimum;
   4721 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   4722 
   4723 		if (zone->type == dns_zone_slave ||
   4724 		    zone->type == dns_zone_stub ||
   4725 		    (zone->type == dns_zone_redirect &&
   4726 		     zone->masters != NULL)) {
   4727 			isc_time_t t;
   4728 			isc_uint32_t delay;
   4729 
   4730 			result = isc_file_getmodtime(zone->journal, &t);
   4731 			if (result != ISC_R_SUCCESS)
   4732 				result = isc_file_getmodtime(zone->masterfile,
   4733 							     &t);
   4734 			if (result == ISC_R_SUCCESS)
   4735 				DNS_ZONE_TIME_ADD(&t, zone->expire,
   4736 						  &zone->expiretime);
   4737 			else
   4738 				DNS_ZONE_TIME_ADD(&now, zone->retry,
   4739 						  &zone->expiretime);
   4740 
   4741 			delay = isc_random_jitter(zone->retry,
   4742 						  (zone->retry * 3) / 4);
   4743 			DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
   4744 			if (isc_time_compare(&zone->refreshtime,
   4745 					     &zone->expiretime) >= 0)
   4746 				zone->refreshtime = now;
   4747 		}
   4748 
   4749 		break;
   4750 
   4751 	case dns_zone_key:
   4752 		result = sync_keyzone(zone, db);
   4753 		if (result != ISC_R_SUCCESS) {
   4754 			goto cleanup;
   4755 		}
   4756 		break;
   4757 
   4758 	default:
   4759 		UNEXPECTED_ERROR(__FILE__, __LINE__,
   4760 				 "unexpected zone type %d", zone->type);
   4761 		result = ISC_R_UNEXPECTED;
   4762 		goto cleanup;
   4763 	}
   4764 
   4765 	/*
   4766 	 * Check for weak DNSKEY's.
   4767 	 */
   4768 	if (zone->type == dns_zone_master)
   4769 		zone_check_dnskeys(zone, db);
   4770 
   4771 	/*
   4772 	 * Schedule DNSSEC key refresh.
   4773 	 */
   4774 	if (zone->type == dns_zone_master &&
   4775 	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
   4776 		zone->refreshkeytime = now;
   4777 
   4778 #if 0
   4779 	/* destroy notification example. */
   4780 	{
   4781 		isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
   4782 						    DNS_EVENT_DBDESTROYED,
   4783 						    dns_zonemgr_dbdestroyed,
   4784 						    zone,
   4785 						    sizeof(isc_event_t));
   4786 		dns_db_ondestroy(db, zone->task, &e);
   4787 	}
   4788 #endif
   4789 
   4790 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   4791 	if (zone->db != NULL) {
   4792 		result = zone_replacedb(zone, db, ISC_FALSE);
   4793 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   4794 		if (result != ISC_R_SUCCESS)
   4795 			goto cleanup;
   4796 	} else {
   4797 		zone_attachdb(zone, db);
   4798 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   4799 		DNS_ZONE_SETFLAG(zone,
   4800 				 DNS_ZONEFLG_LOADED|
   4801 				 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
   4802 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
   4803 		    inline_raw(zone))
   4804 		{
   4805 			if (zone->secure->db == NULL)
   4806 				zone_send_securedb(zone, db);
   4807 			else
   4808 				zone_send_secureserial(zone, serial);
   4809 		}
   4810 	}
   4811 
   4812 	/*
   4813 	 * Finished loading inline-signing zone; need to get status
   4814 	 * from the raw side now.
   4815 	 */
   4816 	if (zone->type == dns_zone_master && inline_secure(zone))
   4817 		maybe_send_secure(zone);
   4818 
   4819 
   4820 	result = ISC_R_SUCCESS;
   4821 
   4822 	if (needdump) {
   4823 		if (zone->type == dns_zone_key)
   4824 			zone_needdump(zone, 30);
   4825 		else
   4826 			zone_needdump(zone, DNS_DUMP_DELAY);
   4827 	}
   4828 
   4829 	if (zone->task != NULL) {
   4830 		if (zone->type == dns_zone_master) {
   4831 			set_resigntime(zone);
   4832 			resume_signingwithkey(zone);
   4833 			resume_addnsec3chain(zone);
   4834 		}
   4835 
   4836 		if (zone->type == dns_zone_master &&
   4837 		    !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
   4838 		    dns_zone_isdynamic(zone, ISC_FALSE) &&
   4839 		    dns_db_issecure(db)) {
   4840 			dns_name_t *name;
   4841 			dns_fixedname_t fixed;
   4842 			dns_rdataset_t next;
   4843 
   4844 			dns_rdataset_init(&next);
   4845 			name = dns_fixedname_initname(&fixed);
   4846 
   4847 			result = dns_db_getsigningtime(db, &next, name);
   4848 			if (result == ISC_R_SUCCESS) {
   4849 				isc_stdtime_t timenow;
   4850 				char namebuf[DNS_NAME_FORMATSIZE];
   4851 				char typebuf[DNS_RDATATYPE_FORMATSIZE];
   4852 
   4853 				isc_stdtime_get(&timenow);
   4854 				dns_name_format(name, namebuf, sizeof(namebuf));
   4855 				dns_rdatatype_format(next.covers,
   4856 						     typebuf, sizeof(typebuf));
   4857 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4858 					      ISC_LOG_DEBUG(3),
   4859 					      "next resign: %s/%s "
   4860 					      "in %d seconds", namebuf, typebuf,
   4861 					      next.resign - timenow -
   4862 					       zone->sigresigninginterval);
   4863 				dns_rdataset_disassociate(&next);
   4864 			} else
   4865 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4866 					      ISC_LOG_WARNING,
   4867 					      "signed dynamic zone has no "
   4868 					      "resign event scheduled");
   4869 		}
   4870 
   4871 		zone_settimer(zone, &now);
   4872 	}
   4873 
   4874 	/*
   4875 	 * Clear old include list.
   4876 	 */
   4877 	for (inc = ISC_LIST_HEAD(zone->includes);
   4878 	     inc != NULL;
   4879 	     inc = ISC_LIST_HEAD(zone->includes)) {
   4880 		ISC_LIST_UNLINK(zone->includes, inc, link);
   4881 		isc_mem_free(zone->mctx, inc->name);
   4882 		isc_mem_put(zone->mctx, inc, sizeof(*inc));
   4883 	}
   4884 	zone->nincludes = 0;
   4885 
   4886 	/*
   4887 	 * Transfer new include list.
   4888 	 */
   4889 	for (inc = ISC_LIST_HEAD(zone->newincludes);
   4890 	     inc != NULL;
   4891 	     inc = ISC_LIST_HEAD(zone->newincludes)) {
   4892 		ISC_LIST_UNLINK(zone->newincludes, inc, link);
   4893 		ISC_LIST_APPEND(zone->includes, inc, link);
   4894 		zone->nincludes++;
   4895 	}
   4896 
   4897 	if (! dns_db_ispersistent(db)) {
   4898 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4899 			      ISC_LOG_INFO, "loaded serial %u%s", serial,
   4900 			      dns_db_issecure(db) ? " (DNSSEC signed)" : "");
   4901 	}
   4902 
   4903 	zone->loadtime = loadtime;
   4904 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
   4905 	return (result);
   4906 
   4907  cleanup:
   4908 	if (zone->type == dns_zone_key && result != ISC_R_SUCCESS) {
   4909 		dns_zone_log(zone, ISC_LOG_ERROR,
   4910 			     "failed to initialize managed-keys (%s): "
   4911 			     "DNSSEC validation is at risk",
   4912 			     isc_result_totext(result));
   4913 	}
   4914 
   4915 	for (inc = ISC_LIST_HEAD(zone->newincludes);
   4916 	     inc != NULL;
   4917 	     inc = ISC_LIST_HEAD(zone->newincludes))
   4918 	{
   4919 		ISC_LIST_UNLINK(zone->newincludes, inc, link);
   4920 		isc_mem_free(zone->mctx, inc->name);
   4921 		isc_mem_put(zone->mctx, inc, sizeof(*inc));
   4922 	}
   4923 	if (zone->type == dns_zone_slave ||
   4924 	    zone->type == dns_zone_stub ||
   4925 	    zone->type == dns_zone_key ||
   4926 	    (zone->type == dns_zone_redirect && zone->masters != NULL)) {
   4927 		if (result != ISC_R_NOMEMORY) {
   4928 			if (zone->journal != NULL)
   4929 				zone_saveunique(zone, zone->journal,
   4930 						"jn-XXXXXXXX");
   4931 			if (zone->masterfile != NULL)
   4932 				zone_saveunique(zone, zone->masterfile,
   4933 						"db-XXXXXXXX");
   4934 		}
   4935 
   4936 		/* Mark the zone for immediate refresh. */
   4937 		zone->refreshtime = now;
   4938 		if (zone->task != NULL)
   4939 			zone_settimer(zone, &now);
   4940 		result = ISC_R_SUCCESS;
   4941 	} else if (zone->type == dns_zone_master ||
   4942 		   zone->type == dns_zone_redirect) {
   4943 		if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND))
   4944 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
   4945 				      ISC_LOG_ERROR,
   4946 				      "not loaded due to errors.");
   4947 		else if (zone->type == dns_zone_master)
   4948 			result = ISC_R_SUCCESS;
   4949 	}
   4950 
   4951 	return (result);
   4952 }
   4953 
   4954 static isc_boolean_t
   4955 exit_check(dns_zone_t *zone) {
   4956 	REQUIRE(LOCKED_ZONE(zone));
   4957 
   4958 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
   4959 		/*
   4960 		 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
   4961 		 */
   4962 		INSIST(isc_refcount_current(&zone->erefs) == 0);
   4963 		return (ISC_TRUE);
   4964 	}
   4965 	return (ISC_FALSE);
   4966 }
   4967 
   4968 static isc_boolean_t
   4969 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
   4970 	      dns_name_t *name, isc_boolean_t logit)
   4971 {
   4972 	isc_result_t result;
   4973 	char namebuf[DNS_NAME_FORMATSIZE];
   4974 	char altbuf[DNS_NAME_FORMATSIZE];
   4975 	dns_fixedname_t fixed;
   4976 	dns_name_t *foundname;
   4977 	int level;
   4978 
   4979 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
   4980 		return (ISC_TRUE);
   4981 
   4982 	if (zone->type == dns_zone_master)
   4983 		level = ISC_LOG_ERROR;
   4984 	else
   4985 		level = ISC_LOG_WARNING;
   4986 
   4987 	foundname = dns_fixedname_initname(&fixed);
   4988 
   4989 	result = dns_db_find(db, name, version, dns_rdatatype_a,
   4990 			     0, 0, NULL, foundname, NULL, NULL);
   4991 	if (result == ISC_R_SUCCESS)
   4992 		return (ISC_TRUE);
   4993 
   4994 	if (result == DNS_R_NXRRSET) {
   4995 		result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
   4996 				     0, 0, NULL, foundname, NULL, NULL);
   4997 		if (result == ISC_R_SUCCESS)
   4998 			return (ISC_TRUE);
   4999 	}
   5000 
   5001 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
   5002 	    result == DNS_R_EMPTYNAME) {
   5003 		if (logit) {
   5004 			dns_name_format(name, namebuf, sizeof namebuf);
   5005 			dns_zone_log(zone, level, "NS '%s' has no address "
   5006 				     "records (A or AAAA)", namebuf);
   5007 		}
   5008 		return (ISC_FALSE);
   5009 	}
   5010 
   5011 	if (result == DNS_R_CNAME) {
   5012 		if (logit) {
   5013 			dns_name_format(name, namebuf, sizeof namebuf);
   5014 			dns_zone_log(zone, level, "NS '%s' is a CNAME "
   5015 				     "(illegal)", namebuf);
   5016 		}
   5017 		return (ISC_FALSE);
   5018 	}
   5019 
   5020 	if (result == DNS_R_DNAME) {
   5021 		if (logit) {
   5022 			dns_name_format(name, namebuf, sizeof namebuf);
   5023 			dns_name_format(foundname, altbuf, sizeof altbuf);
   5024 			dns_zone_log(zone, level, "NS '%s' is below a DNAME "
   5025 				     "'%s' (illegal)", namebuf, altbuf);
   5026 		}
   5027 		return (ISC_FALSE);
   5028 	}
   5029 
   5030 	return (ISC_TRUE);
   5031 }
   5032 
   5033 static isc_result_t
   5034 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
   5035 		 dns_dbversion_t *version, unsigned int *nscount,
   5036 		 unsigned int *errors, isc_boolean_t logit)
   5037 {
   5038 	isc_result_t result;
   5039 	unsigned int count = 0;
   5040 	unsigned int ecount = 0;
   5041 	dns_rdataset_t rdataset;
   5042 	dns_rdata_t rdata;
   5043 	dns_rdata_ns_t ns;
   5044 
   5045 	dns_rdataset_init(&rdataset);
   5046 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
   5047 				     dns_rdatatype_none, 0, &rdataset, NULL);
   5048 	if (result == ISC_R_NOTFOUND) {
   5049 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5050 		goto success;
   5051 	}
   5052 	if (result != ISC_R_SUCCESS) {
   5053 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5054 		goto invalidate_rdataset;
   5055 	}
   5056 
   5057 	result = dns_rdataset_first(&rdataset);
   5058 	while (result == ISC_R_SUCCESS) {
   5059 		if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
   5060 		    (zone->type == dns_zone_master ||
   5061 		     zone->type == dns_zone_slave)) {
   5062 			dns_rdata_init(&rdata);
   5063 			dns_rdataset_current(&rdataset, &rdata);
   5064 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
   5065 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   5066 			if (dns_name_issubdomain(&ns.name, &zone->origin) &&
   5067 			    !zone_check_ns(zone, db, version, &ns.name, logit))
   5068 				ecount++;
   5069 		}
   5070 		count++;
   5071 		result = dns_rdataset_next(&rdataset);
   5072 	}
   5073 	dns_rdataset_disassociate(&rdataset);
   5074 
   5075  success:
   5076 	if (nscount != NULL)
   5077 		*nscount = count;
   5078 	if (errors != NULL)
   5079 		*errors = ecount;
   5080 
   5081 	result = ISC_R_SUCCESS;
   5082 
   5083  invalidate_rdataset:
   5084 	dns_rdataset_invalidate(&rdataset);
   5085 
   5086 	return (result);
   5087 }
   5088 
   5089 static isc_result_t
   5090 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   5091 		 unsigned int *soacount,
   5092 		 isc_uint32_t *serial, isc_uint32_t *refresh,
   5093 		 isc_uint32_t *retry, isc_uint32_t *expire,
   5094 		 isc_uint32_t *minimum)
   5095 {
   5096 	isc_result_t result;
   5097 	unsigned int count;
   5098 	dns_rdataset_t rdataset;
   5099 	dns_rdata_t rdata = DNS_RDATA_INIT;
   5100 	dns_rdata_soa_t soa;
   5101 
   5102 	dns_rdataset_init(&rdataset);
   5103 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
   5104 				     dns_rdatatype_none, 0, &rdataset, NULL);
   5105 	if (result == ISC_R_NOTFOUND) {
   5106 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5107 		if (soacount != NULL)
   5108 			*soacount = 0;
   5109 		if (serial != NULL)
   5110 			*serial = 0;
   5111 		if (refresh != NULL)
   5112 			*refresh = 0;
   5113 		if (retry != NULL)
   5114 			*retry = 0;
   5115 		if (expire != NULL)
   5116 			*expire = 0;
   5117 		if (minimum != NULL)
   5118 			*minimum = 0;
   5119 		result = ISC_R_SUCCESS;
   5120 		goto invalidate_rdataset;
   5121 	}
   5122 	if (result != ISC_R_SUCCESS) {
   5123 		INSIST(!dns_rdataset_isassociated(&rdataset));
   5124 		goto invalidate_rdataset;
   5125 	}
   5126 
   5127 	count = 0;
   5128 	result = dns_rdataset_first(&rdataset);
   5129 	while (result == ISC_R_SUCCESS) {
   5130 		dns_rdata_init(&rdata);
   5131 		dns_rdataset_current(&rdataset, &rdata);
   5132 		count++;
   5133 		if (count == 1) {
   5134 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
   5135 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   5136 		}
   5137 
   5138 		result = dns_rdataset_next(&rdataset);
   5139 		dns_rdata_reset(&rdata);
   5140 	}
   5141 	dns_rdataset_disassociate(&rdataset);
   5142 
   5143 	if (soacount != NULL)
   5144 		*soacount = count;
   5145 
   5146 	if (count > 0) {
   5147 		if (serial != NULL)
   5148 			*serial = soa.serial;
   5149 		if (refresh != NULL)
   5150 			*refresh = soa.refresh;
   5151 		if (retry != NULL)
   5152 			*retry = soa.retry;
   5153 		if (expire != NULL)
   5154 			*expire = soa.expire;
   5155 		if (minimum != NULL)
   5156 			*minimum = soa.minimum;
   5157 	} else {
   5158 		if (soacount != NULL)
   5159 			*soacount = 0;
   5160 		if (serial != NULL)
   5161 			*serial = 0;
   5162 		if (refresh != NULL)
   5163 			*refresh = 0;
   5164 		if (retry != NULL)
   5165 			*retry = 0;
   5166 		if (expire != NULL)
   5167 			*expire = 0;
   5168 		if (minimum != NULL)
   5169 			*minimum = 0;
   5170 	}
   5171 
   5172 	result = ISC_R_SUCCESS;
   5173 
   5174  invalidate_rdataset:
   5175 	dns_rdataset_invalidate(&rdataset);
   5176 
   5177 	return (result);
   5178 }
   5179 
   5180 /*
   5181  * zone must be locked.
   5182  */
   5183 static isc_result_t
   5184 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
   5185 		 unsigned int *soacount, isc_uint32_t *serial,
   5186 		 isc_uint32_t *refresh, isc_uint32_t *retry,
   5187 		 isc_uint32_t *expire, isc_uint32_t *minimum,
   5188 		 unsigned int *errors)
   5189 {
   5190 	isc_result_t result;
   5191 	isc_result_t answer = ISC_R_SUCCESS;
   5192 	dns_dbversion_t *version = NULL;
   5193 	dns_dbnode_t *node;
   5194 
   5195 	REQUIRE(db != NULL);
   5196 	REQUIRE(zone != NULL);
   5197 
   5198 	dns_db_currentversion(db, &version);
   5199 
   5200 	if (nscount != NULL)
   5201 		*nscount = 0;
   5202 	if (soacount != NULL)
   5203 		*soacount = 0;
   5204 	if (serial != NULL)
   5205 		*serial = 0;
   5206 	if (refresh != NULL)
   5207 		*refresh = 0;
   5208 	if (retry != NULL)
   5209 		*retry = 0;
   5210 	if (expire != NULL)
   5211 		*expire = 0;
   5212 	if (errors != NULL)
   5213 		*errors = 0;
   5214 
   5215 	node = NULL;
   5216 	result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
   5217 	if (result != ISC_R_SUCCESS) {
   5218 		answer = result;
   5219 		goto closeversion;
   5220 	}
   5221 
   5222 	if (nscount != NULL || errors != NULL) {
   5223 		result = zone_count_ns_rr(zone, db, node, version,
   5224 					  nscount, errors, ISC_TRUE);
   5225 		if (result != ISC_R_SUCCESS)
   5226 			answer = result;
   5227 	}
   5228 
   5229 	if (soacount != NULL || serial != NULL || refresh != NULL
   5230 	    || retry != NULL || expire != NULL || minimum != NULL) {
   5231 		result = zone_load_soa_rr(db, node, version, soacount,
   5232 					  serial, refresh, retry, expire,
   5233 					  minimum);
   5234 		if (result != ISC_R_SUCCESS)
   5235 			answer = result;
   5236 	}
   5237 
   5238 	dns_db_detachnode(db, &node);
   5239  closeversion:
   5240 	dns_db_closeversion(db, &version, ISC_FALSE);
   5241 
   5242 	return (answer);
   5243 }
   5244 
   5245 void
   5246 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
   5247 	REQUIRE(DNS_ZONE_VALID(source));
   5248 	REQUIRE(target != NULL && *target == NULL);
   5249 	isc_refcount_increment(&source->erefs, NULL);
   5250 	*target = source;
   5251 }
   5252 
   5253 void
   5254 dns_zone_detach(dns_zone_t **zonep) {
   5255 	dns_zone_t *zone;
   5256 	dns_zone_t *raw = NULL;
   5257 	dns_zone_t *secure = NULL;
   5258 	unsigned int refs;
   5259 	isc_boolean_t free_now = ISC_FALSE;
   5260 
   5261 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
   5262 
   5263 	zone = *zonep;
   5264 
   5265 	isc_refcount_decrement(&zone->erefs, &refs);
   5266 
   5267 	if (refs == 0) {
   5268 		LOCK_ZONE(zone);
   5269 		INSIST(zone != zone->raw);
   5270 		/*
   5271 		 * We just detached the last external reference.
   5272 		 */
   5273 		if (zone->task != NULL) {
   5274 			/*
   5275 			 * This zone is being managed.	Post
   5276 			 * its control event and let it clean
   5277 			 * up synchronously in the context of
   5278 			 * its task.
   5279 			 */
   5280 			isc_event_t *ev = &zone->ctlevent;
   5281 			isc_task_send(zone->task, &ev);
   5282 		} else {
   5283 			/*
   5284 			 * This zone is not being managed; it has
   5285 			 * no task and can have no outstanding
   5286 			 * events.  Free it immediately.
   5287 			 */
   5288 			/*
   5289 			 * Unmanaged zones should not have non-null views;
   5290 			 * we have no way of detaching from the view here
   5291 			 * without causing deadlock because this code is called
   5292 			 * with the view already locked.
   5293 			 */
   5294 			INSIST(zone->view == NULL);
   5295 			free_now = ISC_TRUE;
   5296 			raw = zone->raw;
   5297 			zone->raw = NULL;
   5298 			secure = zone->secure;
   5299 			zone->secure = NULL;
   5300 		}
   5301 		UNLOCK_ZONE(zone);
   5302 	}
   5303 	*zonep = NULL;
   5304 	if (free_now) {
   5305 		if (raw != NULL)
   5306 			dns_zone_detach(&raw);
   5307 		if (secure != NULL)
   5308 			dns_zone_idetach(&secure);
   5309 		zone_free(zone);
   5310 	}
   5311 }
   5312 
   5313 void
   5314 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
   5315 	REQUIRE(DNS_ZONE_VALID(source));
   5316 	REQUIRE(target != NULL && *target == NULL);
   5317 	LOCK_ZONE(source);
   5318 	zone_iattach(source, target);
   5319 	UNLOCK_ZONE(source);
   5320 }
   5321 
   5322 static void
   5323 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
   5324 
   5325 	/*
   5326 	 * 'source' locked by caller.
   5327 	 */
   5328 	REQUIRE(LOCKED_ZONE(source));
   5329 	REQUIRE(DNS_ZONE_VALID(source));
   5330 	REQUIRE(target != NULL && *target == NULL);
   5331 	INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
   5332 	source->irefs++;
   5333 	INSIST(source->irefs != 0);
   5334 	*target = source;
   5335 }
   5336 
   5337 static void
   5338 zone_idetach(dns_zone_t **zonep) {
   5339 	dns_zone_t *zone;
   5340 
   5341 	/*
   5342 	 * 'zone' locked by caller.
   5343 	 */
   5344 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
   5345 	zone = *zonep;
   5346 	REQUIRE(LOCKED_ZONE(*zonep));
   5347 	*zonep = NULL;
   5348 
   5349 	INSIST(zone->irefs > 0);
   5350 	zone->irefs--;
   5351 	INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
   5352 }
   5353 
   5354 void
   5355 dns_zone_idetach(dns_zone_t **zonep) {
   5356 	dns_zone_t *zone;
   5357 	isc_boolean_t free_needed;
   5358 
   5359 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
   5360 	zone = *zonep;
   5361 	*zonep = NULL;
   5362 
   5363 	LOCK_ZONE(zone);
   5364 	INSIST(zone->irefs > 0);
   5365 	zone->irefs--;
   5366 	free_needed = exit_check(zone);
   5367 	UNLOCK_ZONE(zone);
   5368 	if (free_needed)
   5369 		zone_free(zone);
   5370 }
   5371 
   5372 isc_mem_t *
   5373 dns_zone_getmctx(dns_zone_t *zone) {
   5374 	REQUIRE(DNS_ZONE_VALID(zone));
   5375 
   5376 	return (zone->mctx);
   5377 }
   5378 
   5379 dns_zonemgr_t *
   5380 dns_zone_getmgr(dns_zone_t *zone) {
   5381 	REQUIRE(DNS_ZONE_VALID(zone));
   5382 
   5383 	return (zone->zmgr);
   5384 }
   5385 
   5386 void
   5387 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
   5388 	REQUIRE(DNS_ZONE_VALID(zone));
   5389 
   5390 	LOCK_ZONE(zone);
   5391 	if (value)
   5392 		DNS_ZONE_SETFLAG(zone, flags);
   5393 	else
   5394 		DNS_ZONE_CLRFLAG(zone, flags);
   5395 	UNLOCK_ZONE(zone);
   5396 }
   5397 
   5398 void
   5399 dns_zone_setoption(dns_zone_t *zone, unsigned int option,
   5400 		   isc_boolean_t value)
   5401 {
   5402 	REQUIRE(DNS_ZONE_VALID(zone));
   5403 
   5404 	LOCK_ZONE(zone);
   5405 	if (value)
   5406 		zone->options |= option;
   5407 	else
   5408 		zone->options &= ~option;
   5409 	UNLOCK_ZONE(zone);
   5410 }
   5411 
   5412 void
   5413 dns_zone_setoption2(dns_zone_t *zone, unsigned int option,
   5414 		    isc_boolean_t value)
   5415 {
   5416 	REQUIRE(DNS_ZONE_VALID(zone));
   5417 
   5418 	LOCK_ZONE(zone);
   5419 	if (value)
   5420 		zone->options2 |= option;
   5421 	else
   5422 		zone->options2 &= ~option;
   5423 	UNLOCK_ZONE(zone);
   5424 }
   5425 
   5426 unsigned int
   5427 dns_zone_getoptions(dns_zone_t *zone) {
   5428 	REQUIRE(DNS_ZONE_VALID(zone));
   5429 
   5430 	return (zone->options);
   5431 }
   5432 
   5433 unsigned int
   5434 dns_zone_getoptions2(dns_zone_t *zone) {
   5435 	REQUIRE(DNS_ZONE_VALID(zone));
   5436 
   5437 	return (zone->options2);
   5438 }
   5439 
   5440 void
   5441 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
   5442 {
   5443 	REQUIRE(DNS_ZONE_VALID(zone));
   5444 
   5445 	LOCK_ZONE(zone);
   5446 	if (value)
   5447 		zone->keyopts |= keyopt;
   5448 	else
   5449 		zone->keyopts &= ~keyopt;
   5450 	UNLOCK_ZONE(zone);
   5451 }
   5452 
   5453 unsigned int
   5454 dns_zone_getkeyopts(dns_zone_t *zone) {
   5455 
   5456 	REQUIRE(DNS_ZONE_VALID(zone));
   5457 
   5458 	return (zone->keyopts);
   5459 }
   5460 
   5461 isc_result_t
   5462 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
   5463 	REQUIRE(DNS_ZONE_VALID(zone));
   5464 
   5465 	LOCK_ZONE(zone);
   5466 	zone->xfrsource4 = *xfrsource;
   5467 	UNLOCK_ZONE(zone);
   5468 
   5469 	return (ISC_R_SUCCESS);
   5470 }
   5471 
   5472 isc_sockaddr_t *
   5473 dns_zone_getxfrsource4(dns_zone_t *zone) {
   5474 	REQUIRE(DNS_ZONE_VALID(zone));
   5475 	return (&zone->xfrsource4);
   5476 }
   5477 
   5478 isc_result_t
   5479 dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
   5480 	REQUIRE(DNS_ZONE_VALID(zone));
   5481 
   5482 	LOCK_ZONE(zone);
   5483 	zone->xfrsource4dscp = dscp;
   5484 	UNLOCK_ZONE(zone);
   5485 
   5486 	return (ISC_R_SUCCESS);
   5487 }
   5488 
   5489 isc_dscp_t
   5490 dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
   5491 	REQUIRE(DNS_ZONE_VALID(zone));
   5492 	return (zone->xfrsource4dscp);
   5493 }
   5494 
   5495 isc_result_t
   5496 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
   5497 	REQUIRE(DNS_ZONE_VALID(zone));
   5498 
   5499 	LOCK_ZONE(zone);
   5500 	zone->xfrsource6 = *xfrsource;
   5501 	UNLOCK_ZONE(zone);
   5502 
   5503 	return (ISC_R_SUCCESS);
   5504 }
   5505 
   5506 isc_sockaddr_t *
   5507 dns_zone_getxfrsource6(dns_zone_t *zone) {
   5508 	REQUIRE(DNS_ZONE_VALID(zone));
   5509 	return (&zone->xfrsource6);
   5510 }
   5511 
   5512 isc_dscp_t
   5513 dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
   5514 	REQUIRE(DNS_ZONE_VALID(zone));
   5515 	return (zone->xfrsource6dscp);
   5516 }
   5517 
   5518 isc_result_t
   5519 dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
   5520 	REQUIRE(DNS_ZONE_VALID(zone));
   5521 
   5522 	LOCK_ZONE(zone);
   5523 	zone->xfrsource6dscp = dscp;
   5524 	UNLOCK_ZONE(zone);
   5525 
   5526 	return (ISC_R_SUCCESS);
   5527 }
   5528 
   5529 isc_result_t
   5530 dns_zone_setaltxfrsource4(dns_zone_t *zone,
   5531 			  const isc_sockaddr_t *altxfrsource)
   5532 {
   5533 	REQUIRE(DNS_ZONE_VALID(zone));
   5534 
   5535 	LOCK_ZONE(zone);
   5536 	zone->altxfrsource4 = *altxfrsource;
   5537 	UNLOCK_ZONE(zone);
   5538 
   5539 	return (ISC_R_SUCCESS);
   5540 }
   5541 
   5542 isc_sockaddr_t *
   5543 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
   5544 	REQUIRE(DNS_ZONE_VALID(zone));
   5545 	return (&zone->altxfrsource4);
   5546 }
   5547 
   5548 isc_result_t
   5549 dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
   5550 	REQUIRE(DNS_ZONE_VALID(zone));
   5551 
   5552 	LOCK_ZONE(zone);
   5553 	zone->altxfrsource4dscp = dscp;
   5554 	UNLOCK_ZONE(zone);
   5555 
   5556 	return (ISC_R_SUCCESS);
   5557 }
   5558 
   5559 isc_dscp_t
   5560 dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
   5561 	REQUIRE(DNS_ZONE_VALID(zone));
   5562 	return (zone->altxfrsource4dscp);
   5563 }
   5564 
   5565 isc_result_t
   5566 dns_zone_setaltxfrsource6(dns_zone_t *zone,
   5567 			  const isc_sockaddr_t *altxfrsource)
   5568 {
   5569 	REQUIRE(DNS_ZONE_VALID(zone));
   5570 
   5571 	LOCK_ZONE(zone);
   5572 	zone->altxfrsource6 = *altxfrsource;
   5573 	UNLOCK_ZONE(zone);
   5574 
   5575 	return (ISC_R_SUCCESS);
   5576 }
   5577 
   5578 isc_sockaddr_t *
   5579 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
   5580 	REQUIRE(DNS_ZONE_VALID(zone));
   5581 	return (&zone->altxfrsource6);
   5582 }
   5583 
   5584 isc_result_t
   5585 dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
   5586 	REQUIRE(DNS_ZONE_VALID(zone));
   5587 
   5588 	LOCK_ZONE(zone);
   5589 	zone->altxfrsource6dscp = dscp;
   5590 	UNLOCK_ZONE(zone);
   5591 
   5592 	return (ISC_R_SUCCESS);
   5593 }
   5594 
   5595 isc_dscp_t
   5596 dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
   5597 	REQUIRE(DNS_ZONE_VALID(zone));
   5598 	return (zone->altxfrsource6dscp);
   5599 }
   5600 
   5601 isc_result_t
   5602 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
   5603 	REQUIRE(DNS_ZONE_VALID(zone));
   5604 
   5605 	LOCK_ZONE(zone);
   5606 	zone->notifysrc4 = *notifysrc;
   5607 	UNLOCK_ZONE(zone);
   5608 
   5609 	return (ISC_R_SUCCESS);
   5610 }
   5611 
   5612 isc_sockaddr_t *
   5613 dns_zone_getnotifysrc4(dns_zone_t *zone) {
   5614 	REQUIRE(DNS_ZONE_VALID(zone));
   5615 	return (&zone->notifysrc4);
   5616 }
   5617 
   5618 isc_result_t
   5619 dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
   5620 	REQUIRE(DNS_ZONE_VALID(zone));
   5621 
   5622 	LOCK_ZONE(zone);
   5623 	zone->notifysrc4dscp = dscp;
   5624 	UNLOCK_ZONE(zone);
   5625 
   5626 	return (ISC_R_SUCCESS);
   5627 }
   5628 
   5629 isc_dscp_t
   5630 dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
   5631 	REQUIRE(DNS_ZONE_VALID(zone));
   5632 	return (zone->notifysrc4dscp);
   5633 }
   5634 
   5635 isc_result_t
   5636 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
   5637 	REQUIRE(DNS_ZONE_VALID(zone));
   5638 
   5639 	LOCK_ZONE(zone);
   5640 	zone->notifysrc6 = *notifysrc;
   5641 	UNLOCK_ZONE(zone);
   5642 
   5643 	return (ISC_R_SUCCESS);
   5644 }
   5645 
   5646 isc_sockaddr_t *
   5647 dns_zone_getnotifysrc6(dns_zone_t *zone) {
   5648 	REQUIRE(DNS_ZONE_VALID(zone));
   5649 	return (&zone->notifysrc6);
   5650 }
   5651 
   5652 static isc_boolean_t
   5653 same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
   5654 	   isc_uint32_t count)
   5655 {
   5656 	unsigned int i;
   5657 
   5658 	for (i = 0; i < count; i++)
   5659 		if (!isc_sockaddr_equal(&oldlist[i], &newlist[i]))
   5660 			return (ISC_FALSE);
   5661 	return (ISC_TRUE);
   5662 }
   5663 
   5664 static isc_boolean_t
   5665 same_keynames(dns_name_t * const *oldlist, dns_name_t * const *newlist,
   5666 	      isc_uint32_t count)
   5667 {
   5668 	unsigned int i;
   5669 
   5670 	if (oldlist == NULL && newlist == NULL)
   5671 		return (ISC_TRUE);
   5672 	if (oldlist == NULL || newlist == NULL)
   5673 		return (ISC_FALSE);
   5674 
   5675 	for (i = 0; i < count; i++) {
   5676 		if (oldlist[i] == NULL && newlist[i] == NULL)
   5677 			continue;
   5678 		if (oldlist[i] == NULL || newlist[i] == NULL ||
   5679 		    !dns_name_equal(oldlist[i], newlist[i]))
   5680 			return (ISC_FALSE);
   5681 	}
   5682 	return (ISC_TRUE);
   5683 }
   5684 
   5685 static void
   5686 clear_addresskeylist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
   5687 		     dns_name_t ***keynamesp, unsigned int *countp,
   5688 		     isc_mem_t *mctx)
   5689 {
   5690 	unsigned int count;
   5691 	isc_sockaddr_t *addrs;
   5692 	isc_dscp_t *dscps;
   5693 	dns_name_t **keynames;
   5694 
   5695 	REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
   5696 		keynamesp != NULL);
   5697 
   5698 	count = *countp;
   5699 	*countp = 0;
   5700 	addrs = *addrsp;
   5701 	*addrsp = NULL;
   5702 	dscps = *dscpsp;
   5703 	*dscpsp = NULL;
   5704 	keynames = *keynamesp;
   5705 	*keynamesp = NULL;
   5706 
   5707 	if (addrs != NULL)
   5708 		isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
   5709 
   5710 	if (dscps != NULL)
   5711 		isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
   5712 
   5713 	if (keynames != NULL) {
   5714 		unsigned int i;
   5715 		for (i = 0; i < count; i++) {
   5716 			if (keynames[i] != NULL) {
   5717 				dns_name_free(keynames[i], mctx);
   5718 				isc_mem_put(mctx, keynames[i],
   5719 					    sizeof(dns_name_t));
   5720 				keynames[i] = NULL;
   5721 			}
   5722 		}
   5723 		isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
   5724 	}
   5725 }
   5726 
   5727 static isc_result_t
   5728 set_addrkeylist(unsigned int count,
   5729 		const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
   5730 		const isc_dscp_t *dscp, isc_dscp_t **newdscpp,
   5731 		dns_name_t **names, dns_name_t ***newnamesp,
   5732 		isc_mem_t *mctx)
   5733 {
   5734 	isc_result_t result;
   5735 	isc_sockaddr_t *newaddrs = NULL;
   5736 	isc_dscp_t *newdscp = NULL;
   5737 	dns_name_t **newnames = NULL;
   5738 	unsigned int i;
   5739 
   5740 	REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
   5741 	REQUIRE(newdscpp != NULL && *newdscpp == NULL);
   5742 	REQUIRE(newnamesp != NULL && *newnamesp == NULL);
   5743 
   5744 	newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
   5745 	if (newaddrs == NULL)
   5746 		return (ISC_R_NOMEMORY);
   5747 	memmove(newaddrs, addrs, count * sizeof(*newaddrs));
   5748 
   5749 	if (dscp != NULL) {
   5750 		newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
   5751 		if (newdscp == NULL) {
   5752 			isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
   5753 			return (ISC_R_NOMEMORY);
   5754 		}
   5755 		memmove(newdscp, dscp, count * sizeof(*newdscp));
   5756 	} else
   5757 		newdscp = NULL;
   5758 
   5759 	if (names != NULL) {
   5760 		newnames = isc_mem_get(mctx, count * sizeof(*newnames));
   5761 		if (newnames == NULL) {
   5762 			if (newdscp != NULL)
   5763 				isc_mem_put(mctx, newdscp,
   5764 					    count * sizeof(*newdscp));
   5765 			isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
   5766 			return (ISC_R_NOMEMORY);
   5767 		}
   5768 		for (i = 0; i < count; i++)
   5769 			newnames[i] = NULL;
   5770 		for (i = 0; i < count; i++) {
   5771 			if (names[i] != NULL) {
   5772 				newnames[i] = isc_mem_get(mctx,
   5773 							 sizeof(dns_name_t));
   5774 				if (newnames[i] == NULL)
   5775 					goto allocfail;
   5776 				dns_name_init(newnames[i], NULL);
   5777 				result = dns_name_dup(names[i], mctx,
   5778 						      newnames[i]);
   5779 				if (result != ISC_R_SUCCESS) {
   5780 				allocfail:
   5781 					for (i = 0; i < count; i++)
   5782 						if (newnames[i] != NULL)
   5783 							dns_name_free(
   5784 							       newnames[i],
   5785 							       mctx);
   5786 					isc_mem_put(mctx, newaddrs,
   5787 						    count * sizeof(*newaddrs));
   5788 					isc_mem_put(mctx, newdscp,
   5789 						    count * sizeof(*newdscp));
   5790 					isc_mem_put(mctx, newnames,
   5791 						    count * sizeof(*newnames));
   5792 					return (ISC_R_NOMEMORY);
   5793 				}
   5794 			}
   5795 		}
   5796 	} else
   5797 		newnames = NULL;
   5798 
   5799 	*newdscpp = newdscp;
   5800 	*newaddrsp = newaddrs;
   5801 	*newnamesp = newnames;
   5802 	return (ISC_R_SUCCESS);
   5803 }
   5804 
   5805 isc_result_t
   5806 dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
   5807 	REQUIRE(DNS_ZONE_VALID(zone));
   5808 
   5809 	LOCK_ZONE(zone);
   5810 	zone->notifysrc6dscp = dscp;
   5811 	UNLOCK_ZONE(zone);
   5812 
   5813 	return (ISC_R_SUCCESS);
   5814 }
   5815 
   5816 isc_dscp_t
   5817 dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
   5818 	REQUIRE(DNS_ZONE_VALID(zone));
   5819 	return (zone->notifysrc6dscp);
   5820 }
   5821 
   5822 isc_result_t
   5823 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
   5824 		       isc_uint32_t count)
   5825 {
   5826 	return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
   5827 					       count));
   5828 }
   5829 
   5830 isc_result_t
   5831 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
   5832 			       dns_name_t **keynames, isc_uint32_t count)
   5833 {
   5834 	return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
   5835 					       count));
   5836 }
   5837 
   5838 isc_result_t
   5839 dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
   5840 			       const isc_dscp_t *dscps, dns_name_t **keynames,
   5841 			       isc_uint32_t count)
   5842 {
   5843 	isc_result_t result;
   5844 	isc_sockaddr_t *newaddrs = NULL;
   5845 	isc_dscp_t *newdscps = NULL;
   5846 	dns_name_t **newnames = NULL;
   5847 
   5848 	REQUIRE(DNS_ZONE_VALID(zone));
   5849 	REQUIRE(count == 0 || notify != NULL);
   5850 	if (keynames != NULL)
   5851 		REQUIRE(count != 0);
   5852 
   5853 	LOCK_ZONE(zone);
   5854 
   5855 	if (count == zone->notifycnt &&
   5856 	    same_addrs(zone->notify, notify, count) &&
   5857 	    same_keynames(zone->notifykeynames, keynames, count))
   5858 		goto unlock;
   5859 
   5860 	clear_addresskeylist(&zone->notify, &zone->notifydscp,
   5861 			     &zone->notifykeynames, &zone->notifycnt,
   5862 			     zone->mctx);
   5863 
   5864 	if (count == 0)
   5865 		goto unlock;
   5866 
   5867 	/*
   5868 	 * Set up the notify and notifykey lists
   5869 	 */
   5870 	result = set_addrkeylist(count, notify, &newaddrs, dscps, &newdscps,
   5871 				 keynames, &newnames, zone->mctx);
   5872 	if (result != ISC_R_SUCCESS)
   5873 		goto unlock;
   5874 
   5875 	/*
   5876 	 * Everything is ok so attach to the zone.
   5877 	 */
   5878 	zone->notify = newaddrs;
   5879 	zone->notifydscp = newdscps;
   5880 	zone->notifykeynames = newnames;
   5881 	zone->notifycnt = count;
   5882  unlock:
   5883 	UNLOCK_ZONE(zone);
   5884 	return (ISC_R_SUCCESS);
   5885 }
   5886 
   5887 isc_result_t
   5888 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
   5889 		    isc_uint32_t count)
   5890 {
   5891 	isc_result_t result;
   5892 
   5893 	result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
   5894 	return (result);
   5895 }
   5896 
   5897 isc_result_t
   5898 dns_zone_setmasterswithkeys(dns_zone_t *zone,
   5899 			    const isc_sockaddr_t *masters,
   5900 			    dns_name_t **keynames,
   5901 			    isc_uint32_t count)
   5902 {
   5903 	isc_result_t result = ISC_R_SUCCESS;
   5904 	isc_sockaddr_t *newaddrs = NULL;
   5905 	isc_dscp_t *newdscps = NULL;
   5906 	dns_name_t **newnames = NULL;
   5907 	isc_boolean_t *newok;
   5908 	unsigned int i;
   5909 
   5910 	REQUIRE(DNS_ZONE_VALID(zone));
   5911 	REQUIRE(count == 0 || masters != NULL);
   5912 	if (keynames != NULL) {
   5913 		REQUIRE(count != 0);
   5914 	}
   5915 
   5916 	LOCK_ZONE(zone);
   5917 	/*
   5918 	 * The refresh code assumes that 'masters' wouldn't change under it.
   5919 	 * If it will change then kill off any current refresh in progress
   5920 	 * and update the masters info.  If it won't change then we can just
   5921 	 * unlock and exit.
   5922 	 */
   5923 	if (count != zone->masterscnt ||
   5924 	    !same_addrs(zone->masters, masters, count) ||
   5925 	    !same_keynames(zone->masterkeynames, keynames, count)) {
   5926 		if (zone->request != NULL)
   5927 			dns_request_cancel(zone->request);
   5928 	} else
   5929 		goto unlock;
   5930 
   5931 	/*
   5932 	 * This needs to happen before clear_addresskeylist() sets
   5933 	 * zone->masterscnt to 0:
   5934 	 */
   5935 	if (zone->mastersok != NULL) {
   5936 		isc_mem_put(zone->mctx, zone->mastersok,
   5937 			    zone->masterscnt * sizeof(isc_boolean_t));
   5938 		zone->mastersok = NULL;
   5939 	}
   5940 	clear_addresskeylist(&zone->masters, &zone->masterdscps,
   5941 			     &zone->masterkeynames, &zone->masterscnt,
   5942 			     zone->mctx);
   5943 	/*
   5944 	 * If count == 0, don't allocate any space for masters, mastersok or
   5945 	 * keynames so internally, those pointers are NULL if count == 0
   5946 	 */
   5947 	if (count == 0)
   5948 		goto unlock;
   5949 
   5950 	/*
   5951 	 * mastersok must contain count elements
   5952 	 */
   5953 	newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
   5954 	if (newok == NULL) {
   5955 		result = ISC_R_NOMEMORY;
   5956 		isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
   5957 		goto unlock;
   5958 	};
   5959 	for (i = 0; i < count; i++)
   5960 		newok[i] = ISC_FALSE;
   5961 
   5962 	/*
   5963 	 * Now set up the masters and masterkey lists
   5964 	 */
   5965 	result = set_addrkeylist(count, masters, &newaddrs, NULL, &newdscps,
   5966 				 keynames, &newnames, zone->mctx);
   5967 	INSIST(newdscps == NULL);
   5968 	if (result != ISC_R_SUCCESS) {
   5969 		isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
   5970 		goto unlock;
   5971 	}
   5972 
   5973 	/*
   5974 	 * Everything is ok so attach to the zone.
   5975 	 */
   5976 	zone->curmaster = 0;
   5977 	zone->mastersok = newok;
   5978 	zone->masters = newaddrs;
   5979 	zone->masterdscps = newdscps;
   5980 	zone->masterkeynames = newnames;
   5981 	zone->masterscnt = count;
   5982 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
   5983 
   5984  unlock:
   5985 	UNLOCK_ZONE(zone);
   5986 	return (result);
   5987 }
   5988 
   5989 isc_result_t
   5990 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
   5991 	isc_result_t result = ISC_R_SUCCESS;
   5992 
   5993 	REQUIRE(DNS_ZONE_VALID(zone));
   5994 
   5995 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   5996 	if (zone->db == NULL)
   5997 		result = DNS_R_NOTLOADED;
   5998 	else
   5999 		dns_db_attach(zone->db, dpb);
   6000 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   6001 
   6002 	return (result);
   6003 }
   6004 
   6005 void
   6006 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
   6007 	REQUIRE(DNS_ZONE_VALID(zone));
   6008 	REQUIRE(zone->type == dns_zone_staticstub);
   6009 
   6010 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   6011 	REQUIRE(zone->db == NULL);
   6012 	dns_db_attach(db, &zone->db);
   6013 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   6014 }
   6015 
   6016 /*
   6017  * Co-ordinates the starting of routine jobs.
   6018  */
   6019 void
   6020 dns_zone_maintenance(dns_zone_t *zone) {
   6021 	const char me[] = "dns_zone_maintenance";
   6022 	isc_time_t now;
   6023 
   6024 	REQUIRE(DNS_ZONE_VALID(zone));
   6025 	ENTER;
   6026 
   6027 	LOCK_ZONE(zone);
   6028 	TIME_NOW(&now);
   6029 	zone_settimer(zone, &now);
   6030 	UNLOCK_ZONE(zone);
   6031 }
   6032 
   6033 static inline isc_boolean_t
   6034 was_dumping(dns_zone_t *zone) {
   6035 	isc_boolean_t dumping;
   6036 
   6037 	REQUIRE(LOCKED_ZONE(zone));
   6038 
   6039 	dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
   6040 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
   6041 	if (!dumping) {
   6042 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   6043 		isc_time_settoepoch(&zone->dumptime);
   6044 	}
   6045 	return (dumping);
   6046 }
   6047 
   6048 /*%
   6049  * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
   6050  * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
   6051  * Only load the public part of a given key if it is not active at timestamp
   6052  * 'now'.  Store the number of keys found in 'nkeys'.
   6053  */
   6054 isc_result_t
   6055 dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   6056 		   isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
   6057 		   dst_key_t **keys, unsigned int *nkeys)
   6058 {
   6059 	isc_result_t result;
   6060 	dns_dbnode_t *node = NULL;
   6061 	const char *directory = dns_zone_getkeydirectory(zone);
   6062 
   6063 	CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
   6064 	memset(keys, 0, sizeof(*keys) * maxkeys);
   6065 	result = dns_dnssec_findzonekeys3(db, ver, node, dns_db_origin(db),
   6066 					  directory, now, mctx, maxkeys, keys,
   6067 					  nkeys);
   6068 	if (result == ISC_R_NOTFOUND)
   6069 		result = ISC_R_SUCCESS;
   6070  failure:
   6071 	if (node != NULL)
   6072 		dns_db_detachnode(db, &node);
   6073 	return (result);
   6074 }
   6075 
   6076 static isc_result_t
   6077 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
   6078 	dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
   6079 {
   6080 	isc_result_t result;
   6081 
   6082 	if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
   6083 		return (ISC_R_SUCCESS);
   6084 	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
   6085 			       name, ttl, rdata);
   6086 	if (result != ISC_R_SUCCESS)
   6087 		return (result);
   6088 	rdata->flags |= DNS_RDATA_OFFLINE;
   6089 	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
   6090 			       name, ttl, rdata);
   6091 	zonediff->offline = ISC_TRUE;
   6092 	return (result);
   6093 }
   6094 
   6095 static void
   6096 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
   6097 {
   6098 	unsigned int delta;
   6099 	char timebuf[80];
   6100 
   6101 	zone->key_expiry = when;
   6102 	if (when <= now) {
   6103 		dns_zone_log(zone, ISC_LOG_ERROR,
   6104 			     "DNSKEY RRSIG(s) have expired");
   6105 		isc_time_settoepoch(&zone->keywarntime);
   6106 	} else if (when < now + 7 * 24 * 3600) {
   6107 		isc_time_t t;
   6108 		isc_time_set(&t, when, 0);
   6109 		isc_time_formattimestamp(&t, timebuf, 80);
   6110 		dns_zone_log(zone, ISC_LOG_WARNING,
   6111 			     "DNSKEY RRSIG(s) will expire within 7 days: %s",
   6112 			     timebuf);
   6113 		delta = when - now;
   6114 		delta--;		/* loop prevention */
   6115 		delta /= 24 * 3600;	/* to whole days */
   6116 		delta *= 24 * 3600;	/* to seconds */
   6117 		isc_time_set(&zone->keywarntime, when - delta, 0);
   6118 	}  else {
   6119 		isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
   6120 		isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
   6121 		dns_zone_log(zone, ISC_LOG_NOTICE,
   6122 			     "setting keywarntime to %s", timebuf);
   6123 	}
   6124 }
   6125 
   6126 /*
   6127  * Helper function to del_sigs(). We don't want to delete RRSIGs that
   6128  * have no new key.
   6129  */
   6130 static isc_boolean_t
   6131 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
   6132 	  isc_boolean_t *warn)
   6133 {
   6134 	unsigned int i = 0;
   6135 	isc_boolean_t have_ksk = ISC_FALSE, have_zsk = ISC_FALSE;
   6136 	isc_boolean_t have_pksk = ISC_FALSE, have_pzsk = ISC_FALSE;
   6137 
   6138 	for (i = 0; i < nkeys; i++) {
   6139 		if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
   6140 			continue;
   6141 		if (dst_key_isprivate(keys[i])) {
   6142 			if (KSK(keys[i]))
   6143 				have_ksk = have_pksk = ISC_TRUE;
   6144 			else
   6145 				have_zsk = have_pzsk = ISC_TRUE;
   6146 		} else {
   6147 			if (KSK(keys[i]))
   6148 				have_ksk = ISC_TRUE;
   6149 			else
   6150 				have_zsk = ISC_TRUE;
   6151 		}
   6152 	}
   6153 
   6154 	if (have_zsk && have_ksk && !have_pzsk)
   6155 		*warn = ISC_TRUE;
   6156 
   6157 	/*
   6158 	 * It's okay to delete a signature if there is an active key
   6159 	 * with the same algorithm to replace it.
   6160 	 */
   6161 	if (have_pksk || have_pzsk)
   6162 		return (ISC_TRUE);
   6163 
   6164 	/*
   6165 	 * Failing that, it is *not* okay to delete a signature
   6166 	 * if the associated public key is still in the DNSKEY RRset
   6167 	 */
   6168 	for (i = 0; i < nkeys; i++) {
   6169 		if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
   6170 		    (rrsig_ptr->keyid == dst_key_id(keys[i])))
   6171 			return (ISC_FALSE);
   6172 	}
   6173 
   6174 	/*
   6175 	 * But if the key is gone, then go ahead.
   6176 	 */
   6177 	return (ISC_TRUE);
   6178 }
   6179 
   6180 /*
   6181  * Delete expired RRsigs and any RRsigs we are about to re-sign.
   6182  * See also update.c:del_keysigs().
   6183  */
   6184 static isc_result_t
   6185 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
   6186 	 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
   6187 	 unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
   6188 {
   6189 	isc_result_t result;
   6190 	dns_dbnode_t *node = NULL;
   6191 	dns_rdataset_t rdataset;
   6192 	unsigned int i;
   6193 	dns_rdata_rrsig_t rrsig;
   6194 	isc_boolean_t found;
   6195 	isc_int64_t timewarn = 0, timemaybe = 0;
   6196 
   6197 	dns_rdataset_init(&rdataset);
   6198 
   6199 	if (type == dns_rdatatype_nsec3)
   6200 		result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
   6201 	else
   6202 		result = dns_db_findnode(db, name, ISC_FALSE, &node);
   6203 	if (result == ISC_R_NOTFOUND)
   6204 		return (ISC_R_SUCCESS);
   6205 	if (result != ISC_R_SUCCESS)
   6206 		goto failure;
   6207 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
   6208 				     (isc_stdtime_t) 0, &rdataset, NULL);
   6209 	dns_db_detachnode(db, &node);
   6210 
   6211 	if (result == ISC_R_NOTFOUND) {
   6212 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6213 		return (ISC_R_SUCCESS);
   6214 	}
   6215 	if (result != ISC_R_SUCCESS) {
   6216 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6217 		goto failure;
   6218 	}
   6219 
   6220 	for (result = dns_rdataset_first(&rdataset);
   6221 	     result == ISC_R_SUCCESS;
   6222 	     result = dns_rdataset_next(&rdataset)) {
   6223 		dns_rdata_t rdata = DNS_RDATA_INIT;
   6224 
   6225 		dns_rdataset_current(&rdataset, &rdata);
   6226 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   6227 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   6228 
   6229 		if (type != dns_rdatatype_dnskey) {
   6230 			isc_boolean_t warn = ISC_FALSE, deleted = ISC_FALSE;
   6231 			if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
   6232 				result = update_one_rr(db, ver, zonediff->diff,
   6233 					       DNS_DIFFOP_DELRESIGN, name,
   6234 					       rdataset.ttl, &rdata);
   6235 				if (result != ISC_R_SUCCESS)
   6236 					break;
   6237 				deleted = ISC_TRUE;
   6238 			}
   6239 			if (warn) {
   6240 				/*
   6241 				 * At this point, we've got an RRSIG,
   6242 				 * which is signed by an inactive key.
   6243 				 * An administrator needs to provide a new
   6244 				 * key/alg, but until that time, we want to
   6245 				 * keep the old RRSIG.  Marking the key as
   6246 				 * offline will prevent us spinning waiting
   6247 				 * for the private part.
   6248 				 */
   6249 				if (incremental && !deleted) {
   6250 					result = offline(db, ver, zonediff,
   6251 							 name, rdataset.ttl,
   6252 							 &rdata);
   6253 					if (result != ISC_R_SUCCESS)
   6254 						break;
   6255 				}
   6256 
   6257 				/*
   6258 				 * Log the key id and algorithm of
   6259 				 * the inactive key with no replacement
   6260 				 */
   6261 				if (zone->log_key_expired_timer <= now) {
   6262 					char origin[DNS_NAME_FORMATSIZE];
   6263 					char algbuf[DNS_NAME_FORMATSIZE];
   6264 					dns_name_format(&zone->origin, origin,
   6265 							sizeof(origin));
   6266 					dns_secalg_format(rrsig.algorithm,
   6267 							  algbuf,
   6268 							  sizeof(algbuf));
   6269 					dns_zone_log(zone, ISC_LOG_WARNING,
   6270 						     "Key %s/%s/%d "
   6271 						     "missing or inactive "
   6272 						     "and has no replacement: "
   6273 						     "retaining signatures.",
   6274 						     origin, algbuf,
   6275 						     rrsig.keyid);
   6276 					zone->log_key_expired_timer = now +
   6277 									3600;
   6278 				}
   6279 			}
   6280 			continue;
   6281 		}
   6282 
   6283 		/*
   6284 		 * RRSIG(DNSKEY) requires special processing.
   6285 		 */
   6286 		found = ISC_FALSE;
   6287 		for (i = 0; i < nkeys; i++) {
   6288 			if (rrsig.algorithm == dst_key_alg(keys[i]) &&
   6289 			    rrsig.keyid == dst_key_id(keys[i])) {
   6290 				found = ISC_TRUE;
   6291 				/*
   6292 				 * Mark offline RRSIG(DNSKEY).
   6293 				 * We want the earliest offline expire time
   6294 				 * iff there is a new offline signature.
   6295 				 */
   6296 				if (!dst_key_inactive(keys[i]) &&
   6297 				    !dst_key_isprivate(keys[i]))
   6298 				{
   6299 					isc_int64_t timeexpire =
   6300 					   dns_time64_from32(rrsig.timeexpire);
   6301 					if (timewarn != 0 &&
   6302 					    timewarn > timeexpire)
   6303 						timewarn = timeexpire;
   6304 					if (rdata.flags & DNS_RDATA_OFFLINE) {
   6305 						if (timemaybe == 0 ||
   6306 						    timemaybe > timeexpire)
   6307 							timemaybe = timeexpire;
   6308 						break;
   6309 					}
   6310 					if (timewarn == 0)
   6311 						timewarn = timemaybe;
   6312 					if (timewarn == 0 ||
   6313 					    timewarn > timeexpire)
   6314 						timewarn = timeexpire;
   6315 					result = offline(db, ver, zonediff,
   6316 							 name, rdataset.ttl,
   6317 							 &rdata);
   6318 					break;
   6319 				}
   6320 				result = update_one_rr(db, ver, zonediff->diff,
   6321 						       DNS_DIFFOP_DELRESIGN,
   6322 						       name, rdataset.ttl,
   6323 						       &rdata);
   6324 				break;
   6325 			}
   6326 		}
   6327 
   6328 		/*
   6329 		 * If there is not a matching DNSKEY then
   6330 		 * delete the RRSIG.
   6331 		 */
   6332 		if (!found)
   6333 			result = update_one_rr(db, ver, zonediff->diff,
   6334 					       DNS_DIFFOP_DELRESIGN, name,
   6335 					       rdataset.ttl, &rdata);
   6336 		if (result != ISC_R_SUCCESS)
   6337 			break;
   6338 	}
   6339 
   6340 	dns_rdataset_disassociate(&rdataset);
   6341 	if (result == ISC_R_NOMORE)
   6342 		result = ISC_R_SUCCESS;
   6343 	if (timewarn > 0) {
   6344 #if defined(STDTIME_ON_32BITS)
   6345 		isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
   6346 		if (timewarn == stdwarn)
   6347 #endif
   6348 			set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
   6349 					       now);
   6350 #if defined(STDTIME_ON_32BITS)
   6351 		else
   6352 			dns_zone_log(zone, ISC_LOG_ERROR,
   6353 				     "key expiry warning time out of range");
   6354 #endif
   6355 	}
   6356  failure:
   6357 	if (node != NULL)
   6358 		dns_db_detachnode(db, &node);
   6359 	return (result);
   6360 }
   6361 
   6362 static isc_result_t
   6363 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
   6364 	 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
   6365 	 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
   6366 	 isc_stdtime_t expire, isc_boolean_t check_ksk,
   6367 	 isc_boolean_t keyset_kskonly)
   6368 {
   6369 	isc_result_t result;
   6370 	dns_dbnode_t *node = NULL;
   6371 	dns_rdataset_t rdataset;
   6372 	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
   6373 	unsigned char data[1024]; /* XXX */
   6374 	isc_buffer_t buffer;
   6375 	unsigned int i, j;
   6376 
   6377 	dns_rdataset_init(&rdataset);
   6378 	isc_buffer_init(&buffer, data, sizeof(data));
   6379 
   6380 	if (type == dns_rdatatype_nsec3)
   6381 		result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
   6382 	else
   6383 		result = dns_db_findnode(db, name, ISC_FALSE, &node);
   6384 	if (result == ISC_R_NOTFOUND)
   6385 		return (ISC_R_SUCCESS);
   6386 	if (result != ISC_R_SUCCESS)
   6387 		goto failure;
   6388 	result = dns_db_findrdataset(db, node, ver, type, 0,
   6389 				     (isc_stdtime_t) 0, &rdataset, NULL);
   6390 	dns_db_detachnode(db, &node);
   6391 	if (result == ISC_R_NOTFOUND) {
   6392 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6393 		return (ISC_R_SUCCESS);
   6394 	}
   6395 	if (result != ISC_R_SUCCESS) {
   6396 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6397 		goto failure;
   6398 	}
   6399 
   6400 	for (i = 0; i < nkeys; i++) {
   6401 		isc_boolean_t both = ISC_FALSE;
   6402 
   6403 		if (!dst_key_isprivate(keys[i]))
   6404 			continue;
   6405 		if (dst_key_inactive(keys[i]))	/* Should be redundant. */
   6406 			continue;
   6407 
   6408 		if (check_ksk && !REVOKE(keys[i])) {
   6409 			isc_boolean_t have_ksk, have_nonksk;
   6410 			if (KSK(keys[i])) {
   6411 				have_ksk = ISC_TRUE;
   6412 				have_nonksk = ISC_FALSE;
   6413 			} else {
   6414 				have_ksk = ISC_FALSE;
   6415 				have_nonksk = ISC_TRUE;
   6416 			}
   6417 			for (j = 0; j < nkeys; j++) {
   6418 				if (j == i || ALG(keys[i]) != ALG(keys[j]))
   6419 					continue;
   6420 				if (!dst_key_isprivate(keys[j]))
   6421 					continue;
   6422 				if (dst_key_inactive(keys[j]))	/* SBR */
   6423 					continue;
   6424 				if (REVOKE(keys[j]))
   6425 					continue;
   6426 				if (KSK(keys[j]))
   6427 					have_ksk = ISC_TRUE;
   6428 				else
   6429 					have_nonksk = ISC_TRUE;
   6430 				both = have_ksk && have_nonksk;
   6431 				if (both)
   6432 					break;
   6433 			}
   6434 		}
   6435 		if (both) {
   6436 			/*
   6437 			 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
   6438 			 */
   6439 			if (type == dns_rdatatype_dnskey ||
   6440 			    type == dns_rdatatype_cdnskey ||
   6441 			    type == dns_rdatatype_cds)
   6442 			{
   6443 				if (!KSK(keys[i]) && keyset_kskonly)
   6444 					continue;
   6445 			} else if (KSK(keys[i])) {
   6446 				continue;
   6447 			}
   6448 		} else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
   6449 			continue;
   6450 		}
   6451 
   6452 		/* Calculate the signature, creating a RRSIG RDATA. */
   6453 		isc_buffer_clear(&buffer);
   6454 		CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
   6455 				      &inception, &expire,
   6456 				      mctx, &buffer, &sig_rdata));
   6457 		/* Update the database and journal with the RRSIG. */
   6458 		/* XXX inefficient - will cause dataset merging */
   6459 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
   6460 				    name, rdataset.ttl, &sig_rdata));
   6461 		dns_rdata_reset(&sig_rdata);
   6462 		isc_buffer_init(&buffer, data, sizeof(data));
   6463 	}
   6464 
   6465  failure:
   6466 	if (dns_rdataset_isassociated(&rdataset))
   6467 		dns_rdataset_disassociate(&rdataset);
   6468 	if (node != NULL)
   6469 		dns_db_detachnode(db, &node);
   6470 	return (result);
   6471 }
   6472 
   6473 static void
   6474 zone_resigninc(dns_zone_t *zone) {
   6475 	const char *me = "zone_resigninc";
   6476 	dns_db_t *db = NULL;
   6477 	dns_dbversion_t *version = NULL;
   6478 	dns_diff_t _sig_diff;
   6479 	dns__zonediff_t zonediff;
   6480 	dns_fixedname_t fixed;
   6481 	dns_name_t *name;
   6482 	dns_rdataset_t rdataset;
   6483 	dns_rdatatype_t covers;
   6484 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   6485 	isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
   6486 	isc_result_t result;
   6487 	isc_stdtime_t now, inception, soaexpire, expire, stop;
   6488 	isc_uint32_t jitter, sigvalidityinterval;
   6489 	unsigned int i;
   6490 	unsigned int nkeys = 0;
   6491 	unsigned int resign;
   6492 
   6493 	ENTER;
   6494 
   6495 	dns_rdataset_init(&rdataset);
   6496 	dns_diff_init(zone->mctx, &_sig_diff);
   6497 	zonediff_init(&zonediff, &_sig_diff);
   6498 
   6499 	/*
   6500 	 * Zone is frozen or automatic resigning is disabled.
   6501 	 * Pause for 5 minutes.
   6502 	 */
   6503 	if (zone->update_disabled ||
   6504 	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
   6505 	{
   6506 		result = ISC_R_FAILURE;
   6507 		goto failure;
   6508 	}
   6509 
   6510 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   6511 	dns_db_attach(zone->db, &db);
   6512 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   6513 
   6514 	result = dns_db_newversion(db, &version);
   6515 	if (result != ISC_R_SUCCESS) {
   6516 		dns_zone_log(zone, ISC_LOG_ERROR,
   6517 			     "zone_resigninc:dns_db_newversion -> %s",
   6518 			     dns_result_totext(result));
   6519 		goto failure;
   6520 	}
   6521 
   6522 	isc_stdtime_get(&now);
   6523 
   6524 	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
   6525 				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
   6526 	if (result != ISC_R_SUCCESS) {
   6527 		dns_zone_log(zone, ISC_LOG_ERROR,
   6528 			     "zone_resigninc:dns__zone_findkeys -> %s",
   6529 			     dns_result_totext(result));
   6530 		goto failure;
   6531 	}
   6532 
   6533 	sigvalidityinterval = zone->sigvalidityinterval;
   6534 	inception = now - 3600;	/* Allow for clock skew. */
   6535 	soaexpire = now + sigvalidityinterval;
   6536 	/*
   6537 	 * Spread out signatures over time if they happen to be
   6538 	 * clumped.  We don't do this for each add_sigs() call as
   6539 	 * we still want some clustering to occur.
   6540 	 */
   6541 	if (sigvalidityinterval >= 3600U) {
   6542 		isc_random_get(&jitter);
   6543 		if (sigvalidityinterval > 7200U) {
   6544 			jitter %= 3600;
   6545 		} else {
   6546 			jitter %= 1200;
   6547 		}
   6548 		expire = soaexpire - jitter - 1;
   6549 	} else {
   6550 		expire = soaexpire - 1;
   6551 	}
   6552 	stop = now + 5;
   6553 
   6554 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
   6555 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
   6556 
   6557 	name = dns_fixedname_initname(&fixed);
   6558 	result = dns_db_getsigningtime(db, &rdataset, name);
   6559 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   6560 		dns_zone_log(zone, ISC_LOG_ERROR,
   6561 			     "zone_resigninc:dns_db_getsigningtime -> %s",
   6562 			     dns_result_totext(result));
   6563 	}
   6564 
   6565 	i = 0;
   6566 	while (result == ISC_R_SUCCESS) {
   6567 		resign = rdataset.resign - zone->sigresigninginterval;
   6568 		covers = rdataset.covers;
   6569 		dns_rdataset_disassociate(&rdataset);
   6570 
   6571 		/*
   6572 		 * Stop if we hit the SOA as that means we have walked the
   6573 		 * entire zone.  The SOA record should always be the most
   6574 		 * recent signature.
   6575 		 */
   6576 		/* XXXMPA increase number of RRsets signed pre call */
   6577 		if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
   6578 		    resign > stop)
   6579 			break;
   6580 
   6581 		result = del_sigs(zone, db, version, name, covers, &zonediff,
   6582 				  zone_keys, nkeys, now, ISC_TRUE);
   6583 		if (result != ISC_R_SUCCESS) {
   6584 			dns_zone_log(zone, ISC_LOG_ERROR,
   6585 				     "zone_resigninc:del_sigs -> %s",
   6586 				     dns_result_totext(result));
   6587 			break;
   6588 		}
   6589 
   6590 		result = add_sigs(db, version, name, covers, zonediff.diff,
   6591 				  zone_keys, nkeys, zone->mctx, inception,
   6592 				  expire, check_ksk, keyset_kskonly);
   6593 		if (result != ISC_R_SUCCESS) {
   6594 			dns_zone_log(zone, ISC_LOG_ERROR,
   6595 				     "zone_resigninc:add_sigs -> %s",
   6596 				     dns_result_totext(result));
   6597 			break;
   6598 		}
   6599 		result	= dns_db_getsigningtime(db, &rdataset, name);
   6600 		if (nkeys == 0 && result == ISC_R_NOTFOUND) {
   6601 			result = ISC_R_SUCCESS;
   6602 			break;
   6603 		}
   6604 		if (result != ISC_R_SUCCESS)
   6605 			dns_zone_log(zone, ISC_LOG_ERROR,
   6606 			     "zone_resigninc:dns_db_getsigningtime -> %s",
   6607 				     dns_result_totext(result));
   6608 	}
   6609 
   6610 	if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
   6611 		goto failure;
   6612 
   6613 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
   6614 			  &zonediff, zone_keys, nkeys, now, ISC_TRUE);
   6615 	if (result != ISC_R_SUCCESS) {
   6616 		dns_zone_log(zone, ISC_LOG_ERROR,
   6617 			     "zone_resigninc:del_sigs -> %s",
   6618 			     dns_result_totext(result));
   6619 		goto failure;
   6620 	}
   6621 
   6622 	/*
   6623 	 * Did we change anything in the zone?
   6624 	 */
   6625 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
   6626 		/*
   6627 		 * Commit the changes if any key has been marked as offline.
   6628 		 */
   6629 		if (zonediff.offline)
   6630 			dns_db_closeversion(db, &version, ISC_TRUE);
   6631 		goto failure;
   6632 	}
   6633 
   6634 	/* Increment SOA serial if we have made changes */
   6635 	result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
   6636 				   zone->updatemethod);
   6637 	if (result != ISC_R_SUCCESS) {
   6638 		dns_zone_log(zone, ISC_LOG_ERROR,
   6639 			     "zone_resigninc:update_soa_serial -> %s",
   6640 			     dns_result_totext(result));
   6641 		goto failure;
   6642 	}
   6643 
   6644 	/*
   6645 	 * Generate maximum life time signatures so that the above loop
   6646 	 * termination is sensible.
   6647 	 */
   6648 	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
   6649 			  zonediff.diff, zone_keys, nkeys, zone->mctx,
   6650 			  inception, soaexpire, check_ksk, keyset_kskonly);
   6651 	if (result != ISC_R_SUCCESS) {
   6652 		dns_zone_log(zone, ISC_LOG_ERROR,
   6653 			     "zone_resigninc:add_sigs -> %s",
   6654 			     dns_result_totext(result));
   6655 		goto failure;
   6656 	}
   6657 
   6658 	/* Write changes to journal file. */
   6659 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
   6660 
   6661 	/* Everything has succeeded. Commit the changes. */
   6662 	dns_db_closeversion(db, &version, ISC_TRUE);
   6663 
   6664  failure:
   6665 	dns_diff_clear(&_sig_diff);
   6666 	for (i = 0; i < nkeys; i++)
   6667 		dst_key_free(&zone_keys[i]);
   6668 	if (version != NULL) {
   6669 		dns_db_closeversion(db, &version, ISC_FALSE);
   6670 		dns_db_detach(&db);
   6671 	} else if (db != NULL)
   6672 		dns_db_detach(&db);
   6673 	if (result == ISC_R_SUCCESS) {
   6674 		set_resigntime(zone);
   6675 		LOCK_ZONE(zone);
   6676 		zone_needdump(zone, DNS_DUMP_DELAY);
   6677 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   6678 		UNLOCK_ZONE(zone);
   6679 	} else {
   6680 		/*
   6681 		 * Something failed.  Retry in 5 minutes.
   6682 		 */
   6683 		isc_interval_t ival;
   6684 		isc_interval_set(&ival, 300, 0);
   6685 		isc_time_nowplusinterval(&zone->resigntime, &ival);
   6686 	}
   6687 
   6688 	INSIST(version == NULL);
   6689 }
   6690 
   6691 static isc_result_t
   6692 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
   6693 	    dns_name_t *newname, isc_boolean_t bottom)
   6694 {
   6695 	isc_result_t result;
   6696 	dns_dbiterator_t *dbit = NULL;
   6697 	dns_rdatasetiter_t *rdsit = NULL;
   6698 	dns_dbnode_t *node = NULL;
   6699 
   6700 	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
   6701 	CHECK(dns_dbiterator_seek(dbit, oldname));
   6702 	do {
   6703 		result = dns_dbiterator_next(dbit);
   6704 		if (result == ISC_R_NOMORE)
   6705 			CHECK(dns_dbiterator_first(dbit));
   6706 		CHECK(dns_dbiterator_current(dbit, &node, newname));
   6707 		if (bottom && dns_name_issubdomain(newname, oldname) &&
   6708 		    !dns_name_equal(newname, oldname)) {
   6709 			dns_db_detachnode(db, &node);
   6710 			continue;
   6711 		}
   6712 		/*
   6713 		 * Is this node empty?
   6714 		 */
   6715 		CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
   6716 		result = dns_rdatasetiter_first(rdsit);
   6717 		dns_db_detachnode(db, &node);
   6718 		dns_rdatasetiter_destroy(&rdsit);
   6719 		if (result != ISC_R_NOMORE)
   6720 			break;
   6721 	} while (1);
   6722  failure:
   6723 	if (node != NULL)
   6724 		dns_db_detachnode(db, &node);
   6725 	if (dbit != NULL)
   6726 		dns_dbiterator_destroy(&dbit);
   6727 	return (result);
   6728 }
   6729 
   6730 static isc_boolean_t
   6731 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   6732 		dns_rdatatype_t type, dst_key_t *key)
   6733 {
   6734 	isc_result_t result;
   6735 	dns_rdataset_t rdataset;
   6736 	dns_rdata_t rdata = DNS_RDATA_INIT;
   6737 	dns_rdata_rrsig_t rrsig;
   6738 
   6739 	dns_rdataset_init(&rdataset);
   6740 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
   6741 				     type, 0, &rdataset, NULL);
   6742 	if (result != ISC_R_SUCCESS) {
   6743 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6744 		return (ISC_FALSE);
   6745 	}
   6746 	for (result = dns_rdataset_first(&rdataset);
   6747 	     result == ISC_R_SUCCESS;
   6748 	     result = dns_rdataset_next(&rdataset)) {
   6749 		dns_rdataset_current(&rdataset, &rdata);
   6750 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   6751 		INSIST(result == ISC_R_SUCCESS);
   6752 		if (rrsig.algorithm == dst_key_alg(key) &&
   6753 		    rrsig.keyid == dst_key_id(key)) {
   6754 			dns_rdataset_disassociate(&rdataset);
   6755 			return (ISC_TRUE);
   6756 		}
   6757 		dns_rdata_reset(&rdata);
   6758 	}
   6759 	dns_rdataset_disassociate(&rdataset);
   6760 	return (ISC_FALSE);
   6761 }
   6762 
   6763 static isc_result_t
   6764 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
   6765 	 dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
   6766 	 dns_diff_t *diff)
   6767 {
   6768 	dns_fixedname_t fixed;
   6769 	dns_name_t *next;
   6770 	dns_rdata_t rdata = DNS_RDATA_INIT;
   6771 	isc_result_t result;
   6772 	unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
   6773 
   6774 	next = dns_fixedname_initname(&fixed);
   6775 
   6776 	CHECK(next_active(db, version, name, next, bottom));
   6777 	CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
   6778 				  &rdata));
   6779 	CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
   6780 			    &rdata));
   6781  failure:
   6782 	return (result);
   6783 }
   6784 
   6785 static isc_result_t
   6786 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
   6787 	    dns_dbversion_t *version, isc_boolean_t build_nsec3,
   6788 	    isc_boolean_t build_nsec, dst_key_t *key,
   6789 	    isc_stdtime_t inception, isc_stdtime_t expire,
   6790 	    unsigned int minimum, isc_boolean_t is_ksk,
   6791 	    isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
   6792 	    dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
   6793 {
   6794 	isc_result_t result;
   6795 	dns_rdatasetiter_t *iterator = NULL;
   6796 	dns_rdataset_t rdataset;
   6797 	dns_rdata_t rdata = DNS_RDATA_INIT;
   6798 	isc_buffer_t buffer;
   6799 	unsigned char data[1024];
   6800 	isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
   6801 		      seen_nsec3, seen_ds;
   6802 	isc_boolean_t bottom;
   6803 
   6804 	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
   6805 	if (result != ISC_R_SUCCESS) {
   6806 		if (result == ISC_R_NOTFOUND)
   6807 			result = ISC_R_SUCCESS;
   6808 		return (result);
   6809 	}
   6810 
   6811 	dns_rdataset_init(&rdataset);
   6812 	isc_buffer_init(&buffer, data, sizeof(data));
   6813 	seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
   6814 	seen_nsec3 = seen_ds = ISC_FALSE;
   6815 	for (result = dns_rdatasetiter_first(iterator);
   6816 	     result == ISC_R_SUCCESS;
   6817 	     result = dns_rdatasetiter_next(iterator)) {
   6818 		dns_rdatasetiter_current(iterator, &rdataset);
   6819 		if (rdataset.type == dns_rdatatype_soa)
   6820 			seen_soa = ISC_TRUE;
   6821 		else if (rdataset.type == dns_rdatatype_ns)
   6822 			seen_ns = ISC_TRUE;
   6823 		else if (rdataset.type == dns_rdatatype_ds)
   6824 			seen_ds = ISC_TRUE;
   6825 		else if (rdataset.type == dns_rdatatype_dname)
   6826 			seen_dname = ISC_TRUE;
   6827 		else if (rdataset.type == dns_rdatatype_nsec)
   6828 			seen_nsec = ISC_TRUE;
   6829 		else if (rdataset.type == dns_rdatatype_nsec3)
   6830 			seen_nsec3 = ISC_TRUE;
   6831 		if (rdataset.type != dns_rdatatype_rrsig)
   6832 			seen_rr = ISC_TRUE;
   6833 		dns_rdataset_disassociate(&rdataset);
   6834 	}
   6835 	if (result != ISC_R_NOMORE)
   6836 		goto failure;
   6837 	if (seen_ns && !seen_soa)
   6838 		*delegation = ISC_TRUE;
   6839 	/*
   6840 	 * Going from insecure to NSEC3.
   6841 	 * Don't generate NSEC3 records for NSEC3 records.
   6842 	 */
   6843 	if (build_nsec3 && !seen_nsec3 && seen_rr) {
   6844 		isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
   6845 		CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
   6846 					  unsecure, diff));
   6847 		(*signatures)--;
   6848 	}
   6849 	/*
   6850 	 * Going from insecure to NSEC.
   6851 	 * Don't generate NSEC records for NSEC3 records.
   6852 	 */
   6853 	if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
   6854 		/* Build and add NSEC. */
   6855 		bottom = (seen_ns && !seen_soa) || seen_dname;
   6856 		/*
   6857 		 * Build a NSEC record except at the origin.
   6858 		 */
   6859 		if (!dns_name_equal(name, dns_db_origin(db))) {
   6860 			CHECK(add_nsec(db, version, name, node, minimum,
   6861 				       bottom, diff));
   6862 			/* Count a NSEC generation as a signature generation. */
   6863 			(*signatures)--;
   6864 		}
   6865 	}
   6866 	result = dns_rdatasetiter_first(iterator);
   6867 	while (result == ISC_R_SUCCESS) {
   6868 		dns_rdatasetiter_current(iterator, &rdataset);
   6869 		if (rdataset.type == dns_rdatatype_soa ||
   6870 		    rdataset.type == dns_rdatatype_rrsig)
   6871 		{
   6872 			goto next_rdataset;
   6873 		}
   6874 		if (rdataset.type == dns_rdatatype_dnskey ||
   6875 		    rdataset.type == dns_rdatatype_cdnskey ||
   6876 		    rdataset.type == dns_rdatatype_cds)
   6877 		{
   6878 			/*
   6879 			 * CDS and CDNSKEY are signed with KSK like DNSKEY.
   6880 			 * (RFC 7344, section 4.1 specifies that they must
   6881 			 * be signed with a key in the current DS RRset,
   6882 			 * which would only include KSK's.)
   6883 			 */
   6884 			if (!is_ksk && keyset_kskonly) {
   6885 				goto next_rdataset;
   6886 			}
   6887 		} else if (is_ksk) {
   6888 			goto next_rdataset;
   6889 		}
   6890 		if (*delegation &&
   6891 		    rdataset.type != dns_rdatatype_ds &&
   6892 		    rdataset.type != dns_rdatatype_nsec)
   6893 		{
   6894 			goto next_rdataset;
   6895 		}
   6896 		if (signed_with_key(db, node, version, rdataset.type, key)) {
   6897 			goto next_rdataset;
   6898 		}
   6899 		/* Calculate the signature, creating a RRSIG RDATA. */
   6900 		isc_buffer_clear(&buffer);
   6901 		CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
   6902 				      &expire, mctx, &buffer, &rdata));
   6903 		/* Update the database and journal with the RRSIG. */
   6904 		/* XXX inefficient - will cause dataset merging */
   6905 		CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
   6906 				    name, rdataset.ttl, &rdata));
   6907 		dns_rdata_reset(&rdata);
   6908 		(*signatures)--;
   6909  next_rdataset:
   6910 		dns_rdataset_disassociate(&rdataset);
   6911 		result = dns_rdatasetiter_next(iterator);
   6912 	}
   6913 	if (result == ISC_R_NOMORE)
   6914 		result = ISC_R_SUCCESS;
   6915 	if (seen_dname)
   6916 		*delegation = ISC_TRUE;
   6917  failure:
   6918 	if (dns_rdataset_isassociated(&rdataset))
   6919 		dns_rdataset_disassociate(&rdataset);
   6920 	if (iterator != NULL)
   6921 		dns_rdatasetiter_destroy(&iterator);
   6922 	return (result);
   6923 }
   6924 
   6925 /*
   6926  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
   6927  */
   6928 static isc_result_t
   6929 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
   6930 	     dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
   6931 {
   6932 	isc_result_t result;
   6933 	dns_rdataset_t rdataset;
   6934 	dns_dbnode_t *node = NULL;
   6935 
   6936 	CHECK(dns_db_getoriginnode(db, &node));
   6937 	if (update_only) {
   6938 		dns_rdataset_init(&rdataset);
   6939 		result = dns_db_findrdataset(db, node, version,
   6940 					     dns_rdatatype_nsec,
   6941 					     dns_rdatatype_none,
   6942 					     0, &rdataset, NULL);
   6943 		if (dns_rdataset_isassociated(&rdataset))
   6944 			dns_rdataset_disassociate(&rdataset);
   6945 		if (result == ISC_R_NOTFOUND)
   6946 			goto success;
   6947 		if (result != ISC_R_SUCCESS)
   6948 			goto failure;
   6949 	}
   6950 	CHECK(delete_nsec(db, version, node, name, diff));
   6951 	CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
   6952  success:
   6953 	result = ISC_R_SUCCESS;
   6954  failure:
   6955 	if (node != NULL)
   6956 		dns_db_detachnode(db, &node);
   6957 	return (result);
   6958 }
   6959 
   6960 static isc_result_t
   6961 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
   6962 		  dns_dbversion_t *version, isc_boolean_t build_nsec3,
   6963 		  dns_ttl_t minimum, dns_diff_t *diff)
   6964 {
   6965 	isc_result_t result;
   6966 	dns_dbnode_t *node = NULL;
   6967 	dns_rdataset_t rdataset;
   6968 	dns_rdata_t rdata = DNS_RDATA_INIT;
   6969 	unsigned char data[5];
   6970 	isc_boolean_t seen_done = ISC_FALSE;
   6971 	isc_boolean_t have_rr = ISC_FALSE;
   6972 
   6973 	dns_rdataset_init(&rdataset);
   6974 	result = dns_db_getoriginnode(signing->db, &node);
   6975 	if (result != ISC_R_SUCCESS)
   6976 		goto failure;
   6977 
   6978 	result = dns_db_findrdataset(signing->db, node, version,
   6979 				     zone->privatetype, dns_rdatatype_none,
   6980 				     0, &rdataset, NULL);
   6981 	if (result == ISC_R_NOTFOUND) {
   6982 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6983 		result = ISC_R_SUCCESS;
   6984 		goto failure;
   6985 	}
   6986 	if (result != ISC_R_SUCCESS) {
   6987 		INSIST(!dns_rdataset_isassociated(&rdataset));
   6988 		goto failure;
   6989 	}
   6990 	for (result = dns_rdataset_first(&rdataset);
   6991 	     result == ISC_R_SUCCESS;
   6992 	     result = dns_rdataset_next(&rdataset)) {
   6993 		dns_rdataset_current(&rdataset, &rdata);
   6994 		/*
   6995 		 * If we don't match the algorithm or keyid skip the record.
   6996 		 */
   6997 		if (rdata.length != 5 ||
   6998 		    rdata.data[0] != signing->algorithm ||
   6999 		    rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
   7000 		    rdata.data[2] != (signing->keyid & 0xff)) {
   7001 			have_rr = ISC_TRUE;
   7002 			dns_rdata_reset(&rdata);
   7003 			continue;
   7004 		}
   7005 		/*
   7006 		 * We have a match.  If we were signing (!signing->deleteit)
   7007 		 * and we already have a record indicating that we have
   7008 		 * finished signing (rdata.data[4] != 0) then keep it.
   7009 		 * Otherwise it needs to be deleted as we have removed all
   7010 		 * the signatures (signing->deleteit), so any record indicating
   7011 		 * completion is now out of date, or we have finished signing
   7012 		 * with the new record so we no longer need to remember that
   7013 		 * we need to sign the zone with the matching key across a
   7014 		 * nameserver re-start.
   7015 		 */
   7016 		if (!signing->deleteit && rdata.data[4] != 0) {
   7017 			seen_done = ISC_TRUE;
   7018 			have_rr = ISC_TRUE;
   7019 		} else
   7020 			CHECK(update_one_rr(signing->db, version, diff,
   7021 					    DNS_DIFFOP_DEL, &zone->origin,
   7022 					    rdataset.ttl, &rdata));
   7023 		dns_rdata_reset(&rdata);
   7024 	}
   7025 	if (result == ISC_R_NOMORE)
   7026 		result = ISC_R_SUCCESS;
   7027 	if (!signing->deleteit && !seen_done) {
   7028 		/*
   7029 		 * If we were signing then we need to indicate that we have
   7030 		 * finished signing the zone with this key.  If it is already
   7031 		 * there we don't need to add it a second time.
   7032 		 */
   7033 		data[0] = signing->algorithm;
   7034 		data[1] = (signing->keyid >> 8) & 0xff;
   7035 		data[2] = signing->keyid & 0xff;
   7036 		data[3] = 0;
   7037 		data[4] = 1;
   7038 		rdata.length = sizeof(data);
   7039 		rdata.data = data;
   7040 		rdata.type = zone->privatetype;
   7041 		rdata.rdclass = dns_db_class(signing->db);
   7042 		CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
   7043 				    &zone->origin, rdataset.ttl, &rdata));
   7044 	} else if (!have_rr) {
   7045 		dns_name_t *origin = dns_db_origin(signing->db);
   7046 		/*
   7047 		 * Rebuild the NSEC/NSEC3 record for the origin as we no
   7048 		 * longer have any private records.
   7049 		 */
   7050 		if (build_nsec3)
   7051 			CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
   7052 						  minimum, ISC_FALSE, diff));
   7053 		CHECK(updatesecure(signing->db, version, origin, minimum,
   7054 				   ISC_TRUE, diff));
   7055 	}
   7056 
   7057  failure:
   7058 	if (dns_rdataset_isassociated(&rdataset))
   7059 		dns_rdataset_disassociate(&rdataset);
   7060 	if (node != NULL)
   7061 		dns_db_detachnode(signing->db, &node);
   7062 	return (result);
   7063 }
   7064 
   7065 /*
   7066  * Called from zone_nsec3chain() in order to update zone records indicating
   7067  * processing status of given NSEC3 chain:
   7068  *
   7069  *   - If the supplied dns_nsec3chain_t structure has been fully processed
   7070  *     (which is indicated by "active" being set to ISC_FALSE):
   7071  *
   7072  *       - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
   7073  *
   7074  *       - remove all private-type records containing NSEC3PARAM RDATA matching
   7075  *         the relevant NSEC3 chain.
   7076  *
   7077  *   - If the supplied dns_nsec3chain_t structure has not been fully processed
   7078  *     (which is indicated by "active" being set to ISC_TRUE), only remove the
   7079  *     NSEC3PARAM record which matches the relevant NSEC3 chain and has the
   7080  *     "flags" field set to 0.
   7081  *
   7082  *   - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
   7083  *     in the relevant private-type record, but with the "flags" field set to
   7084  *     0, indicating that this NSEC3 chain is now complete for this zone.
   7085  *
   7086  * Note that this function is called at different processing stages for NSEC3
   7087  * chain additions vs. removals and needs to handle all cases properly.
   7088  */
   7089 static isc_result_t
   7090 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
   7091 		 isc_boolean_t active, dns_rdatatype_t privatetype,
   7092 		 dns_diff_t *diff)
   7093 {
   7094 	dns_dbnode_t *node = NULL;
   7095 	dns_name_t *name = dns_db_origin(db);
   7096 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7097 	dns_rdataset_t rdataset;
   7098 	dns_rdata_nsec3param_t nsec3param;
   7099 	isc_result_t result;
   7100 	isc_buffer_t buffer;
   7101 	unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
   7102 	dns_ttl_t ttl = 0;
   7103 	isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
   7104 
   7105 	dns_rdataset_init(&rdataset);
   7106 
   7107 	result = dns_db_getoriginnode(db, &node);
   7108 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   7109 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
   7110 				     0, 0, &rdataset, NULL);
   7111 	if (result == ISC_R_NOTFOUND)
   7112 		goto try_private;
   7113 	if (result != ISC_R_SUCCESS)
   7114 		goto failure;
   7115 
   7116 	/*
   7117 	 * Preserve the existing ttl.
   7118 	 */
   7119 	ttl = rdataset.ttl;
   7120 
   7121 	/*
   7122 	 * Delete all NSEC3PARAM records which match that in nsec3chain.
   7123 	 */
   7124 	for (result = dns_rdataset_first(&rdataset);
   7125 	     result == ISC_R_SUCCESS;
   7126 	     result = dns_rdataset_next(&rdataset)) {
   7127 
   7128 		dns_rdataset_current(&rdataset, &rdata);
   7129 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
   7130 
   7131 		if (nsec3param.hash != chain->nsec3param.hash ||
   7132 		    (active && nsec3param.flags != 0) ||
   7133 		    nsec3param.iterations != chain->nsec3param.iterations ||
   7134 		    nsec3param.salt_length != chain->nsec3param.salt_length ||
   7135 		    memcmp(nsec3param.salt, chain->nsec3param.salt,
   7136 			   nsec3param.salt_length)) {
   7137 			dns_rdata_reset(&rdata);
   7138 			continue;
   7139 		}
   7140 
   7141 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
   7142 				    name, rdataset.ttl, &rdata));
   7143 		dns_rdata_reset(&rdata);
   7144 	}
   7145 	if (result != ISC_R_NOMORE)
   7146 		goto failure;
   7147 
   7148 	dns_rdataset_disassociate(&rdataset);
   7149 
   7150  try_private:
   7151 
   7152 	if (active)
   7153 		goto add;
   7154 
   7155 	result = dns_nsec_nseconly(db, ver, &nseconly);
   7156 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
   7157 
   7158 	/*
   7159 	 * Delete all private records which match that in nsec3chain.
   7160 	 */
   7161 	result = dns_db_findrdataset(db, node, ver, privatetype,
   7162 				     0, 0, &rdataset, NULL);
   7163 	if (result == ISC_R_NOTFOUND)
   7164 		goto add;
   7165 	if (result != ISC_R_SUCCESS)
   7166 		goto failure;
   7167 
   7168 	for (result = dns_rdataset_first(&rdataset);
   7169 	     result == ISC_R_SUCCESS;
   7170 	     result = dns_rdataset_next(&rdataset)) {
   7171 		dns_rdata_t private = DNS_RDATA_INIT;
   7172 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   7173 
   7174 		dns_rdataset_current(&rdataset, &private);
   7175 		if (!dns_nsec3param_fromprivate(&private, &rdata,
   7176 						buf, sizeof(buf)))
   7177 			continue;
   7178 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
   7179 
   7180 		if ((!nsec3ok &&
   7181 		     (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
   7182 		    nsec3param.hash != chain->nsec3param.hash ||
   7183 		    nsec3param.iterations != chain->nsec3param.iterations ||
   7184 		    nsec3param.salt_length != chain->nsec3param.salt_length ||
   7185 		    memcmp(nsec3param.salt, chain->nsec3param.salt,
   7186 			   nsec3param.salt_length)) {
   7187 			dns_rdata_reset(&rdata);
   7188 			continue;
   7189 		}
   7190 
   7191 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
   7192 				    name, rdataset.ttl, &private));
   7193 		dns_rdata_reset(&rdata);
   7194 	}
   7195 	if (result != ISC_R_NOMORE)
   7196 		goto failure;
   7197 
   7198   add:
   7199 	if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
   7200 		result = ISC_R_SUCCESS;
   7201 		goto failure;
   7202 	}
   7203 
   7204 	/*
   7205 	 * Add a NSEC3PARAM record which matches that in nsec3chain but
   7206 	 * with all flags bits cleared.
   7207 	 *
   7208 	 * Note: we do not clear chain->nsec3param.flags as this change
   7209 	 * may be reversed.
   7210 	 */
   7211 	isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
   7212 	CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
   7213 				   dns_rdatatype_nsec3param,
   7214 				   &chain->nsec3param, &buffer));
   7215 	rdata.data[1] = 0;	/* Clear flag bits. */
   7216 	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
   7217 
   7218   failure:
   7219 	dns_db_detachnode(db, &node);
   7220 	if (dns_rdataset_isassociated(&rdataset))
   7221 		dns_rdataset_disassociate(&rdataset);
   7222 	return (result);
   7223 }
   7224 
   7225 static isc_result_t
   7226 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
   7227 	    dns_name_t *name, dns_diff_t *diff)
   7228 {
   7229 	dns_rdataset_t rdataset;
   7230 	isc_result_t result;
   7231 
   7232 	dns_rdataset_init(&rdataset);
   7233 
   7234 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
   7235 				     0, 0, &rdataset, NULL);
   7236 	if (result == ISC_R_NOTFOUND)
   7237 		return (ISC_R_SUCCESS);
   7238 	if (result != ISC_R_SUCCESS)
   7239 		return (result);
   7240 	for (result = dns_rdataset_first(&rdataset);
   7241 	     result == ISC_R_SUCCESS;
   7242 	     result = dns_rdataset_next(&rdataset)) {
   7243 		dns_rdata_t rdata = DNS_RDATA_INIT;
   7244 
   7245 		dns_rdataset_current(&rdataset, &rdata);
   7246 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
   7247 				    rdataset.ttl, &rdata));
   7248 	}
   7249 	if (result == ISC_R_NOMORE)
   7250 		result = ISC_R_SUCCESS;
   7251  failure:
   7252 	dns_rdataset_disassociate(&rdataset);
   7253 	return (result);
   7254 }
   7255 
   7256 static isc_result_t
   7257 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
   7258 		    dns_name_t *name, const dns_rdata_nsec3param_t *param,
   7259 		    dns_diff_t *diff)
   7260 {
   7261 	dns_rdataset_t rdataset;
   7262 	dns_rdata_nsec3_t nsec3;
   7263 	isc_result_t result;
   7264 
   7265 	dns_rdataset_init(&rdataset);
   7266 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
   7267 				     0, 0, &rdataset, NULL);
   7268 	if (result == ISC_R_NOTFOUND)
   7269 		return (ISC_R_SUCCESS);
   7270 	if (result != ISC_R_SUCCESS)
   7271 		return (result);
   7272 
   7273 	for (result = dns_rdataset_first(&rdataset);
   7274 	     result == ISC_R_SUCCESS;
   7275 	     result = dns_rdataset_next(&rdataset)) {
   7276 		dns_rdata_t rdata = DNS_RDATA_INIT;
   7277 
   7278 		dns_rdataset_current(&rdataset, &rdata);
   7279 		CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
   7280 		if (nsec3.hash != param->hash ||
   7281 		    nsec3.iterations != param->iterations ||
   7282 		    nsec3.salt_length != param->salt_length ||
   7283 		    memcmp(nsec3.salt, param->salt, nsec3.salt_length))
   7284 			continue;
   7285 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
   7286 				    rdataset.ttl, &rdata));
   7287 	}
   7288 	if (result == ISC_R_NOMORE)
   7289 		result = ISC_R_SUCCESS;
   7290  failure:
   7291 	dns_rdataset_disassociate(&rdataset);
   7292 	return (result);
   7293 }
   7294 
   7295 static isc_result_t
   7296 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
   7297 		const dns_rdata_nsec3param_t *param,
   7298 		isc_boolean_t *answer)
   7299 {
   7300 	dns_dbnode_t *node = NULL;
   7301 	dns_rdata_t rdata = DNS_RDATA_INIT;
   7302 	dns_rdata_nsec3param_t myparam;
   7303 	dns_rdataset_t rdataset;
   7304 	isc_result_t result;
   7305 
   7306 	*answer = ISC_FALSE;
   7307 
   7308 	result = dns_db_getoriginnode(db, &node);
   7309 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   7310 
   7311 	dns_rdataset_init(&rdataset);
   7312 
   7313 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
   7314 				     0, 0, &rdataset, NULL);
   7315 	if (result == ISC_R_SUCCESS) {
   7316 		dns_rdataset_disassociate(&rdataset);
   7317 		dns_db_detachnode(db, &node);
   7318 		return (result);
   7319 	}
   7320 	if (result != ISC_R_NOTFOUND) {
   7321 		dns_db_detachnode(db, &node);
   7322 		return (result);
   7323 	}
   7324 
   7325 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
   7326 				     0, 0, &rdataset, NULL);
   7327 	if (result == ISC_R_NOTFOUND) {
   7328 		*answer = ISC_TRUE;
   7329 		dns_db_detachnode(db, &node);
   7330 		return (ISC_R_SUCCESS);
   7331 	}
   7332 	if (result != ISC_R_SUCCESS) {
   7333 		dns_db_detachnode(db, &node);
   7334 		return (result);
   7335 	}
   7336 
   7337 	for (result = dns_rdataset_first(&rdataset);
   7338 	     result == ISC_R_SUCCESS;
   7339 	     result = dns_rdataset_next(&rdataset)) {
   7340 		dns_rdataset_current(&rdataset, &rdata);
   7341 		CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
   7342 		dns_rdata_reset(&rdata);
   7343 		/*
   7344 		 * Ignore any NSEC3PARAM removals.
   7345 		 */
   7346 		if (NSEC3REMOVE(myparam.flags))
   7347 			continue;
   7348 		/*
   7349 		 * Ignore the chain that we are in the process of deleting.
   7350 		 */
   7351 		if (myparam.hash == param->hash &&
   7352 		    myparam.iterations == param->iterations &&
   7353 		    myparam.salt_length == param->salt_length &&
   7354 		    !memcmp(myparam.salt, param->salt, myparam.salt_length))
   7355 			continue;
   7356 		/*
   7357 		 * Found an active NSEC3 chain.
   7358 		 */
   7359 		break;
   7360 	}
   7361 	if (result == ISC_R_NOMORE) {
   7362 		*answer = ISC_TRUE;
   7363 		result = ISC_R_SUCCESS;
   7364 	}
   7365 
   7366  failure:
   7367 	if (dns_rdataset_isassociated(&rdataset))
   7368 		dns_rdataset_disassociate(&rdataset);
   7369 	dns_db_detachnode(db, &node);
   7370 	return (result);
   7371 }
   7372 
   7373 /*%
   7374  * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
   7375  * 'diff'.  Gradually remove tuples from 'diff' and append them to 'zonediff'
   7376  * along with tuples representing relevant signature changes.
   7377  */
   7378 isc_result_t
   7379 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
   7380 		     dst_key_t *zone_keys[], unsigned int nkeys,
   7381 		     dns_zone_t *zone, isc_stdtime_t inception,
   7382 		     isc_stdtime_t expire, isc_stdtime_t now,
   7383 		     isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
   7384 		     dns__zonediff_t *zonediff)
   7385 {
   7386 	dns_difftuple_t *tuple;
   7387 	isc_result_t result;
   7388 
   7389 	for (tuple = ISC_LIST_HEAD(diff->tuples);
   7390 	     tuple != NULL;
   7391 	     tuple = ISC_LIST_HEAD(diff->tuples)) {
   7392 		result = del_sigs(zone, db, version, &tuple->name,
   7393 				  tuple->rdata.type, zonediff,
   7394 				  zone_keys, nkeys, now, ISC_FALSE);
   7395 		if (result != ISC_R_SUCCESS) {
   7396 			dns_zone_log(zone, ISC_LOG_ERROR,
   7397 				     "dns__zone_updatesigs:del_sigs -> %s",
   7398 				     dns_result_totext(result));
   7399 			return (result);
   7400 		}
   7401 		result = add_sigs(db, version, &tuple->name,
   7402 				  tuple->rdata.type, zonediff->diff,
   7403 				  zone_keys, nkeys, zone->mctx, inception,
   7404 				  expire, check_ksk, keyset_kskonly);
   7405 		if (result != ISC_R_SUCCESS) {
   7406 			dns_zone_log(zone, ISC_LOG_ERROR,
   7407 				     "dns__zone_updatesigs:add_sigs -> %s",
   7408 				     dns_result_totext(result));
   7409 			return (result);
   7410 		}
   7411 
   7412 		do {
   7413 			dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
   7414 			while (next != NULL &&
   7415 			       (tuple->rdata.type != next->rdata.type ||
   7416 				!dns_name_equal(&tuple->name, &next->name)))
   7417 				next = ISC_LIST_NEXT(next, link);
   7418 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
   7419 			dns_diff_appendminimal(zonediff->diff, &tuple);
   7420 			INSIST(tuple == NULL);
   7421 			tuple = next;
   7422 		} while (tuple != NULL);
   7423 	}
   7424 	return (ISC_R_SUCCESS);
   7425 }
   7426 
   7427 /*
   7428  * Incrementally build and sign a new NSEC3 chain using the parameters
   7429  * requested.
   7430  */
   7431 static void
   7432 zone_nsec3chain(dns_zone_t *zone) {
   7433 	const char *me = "zone_nsec3chain";
   7434 	dns_db_t *db = NULL;
   7435 	dns_dbnode_t *node = NULL;
   7436 	dns_dbversion_t *version = NULL;
   7437 	dns_diff_t _sig_diff;
   7438 	dns_diff_t nsec_diff;
   7439 	dns_diff_t nsec3_diff;
   7440 	dns_diff_t param_diff;
   7441 	dns__zonediff_t zonediff;
   7442 	dns_fixedname_t fixed;
   7443 	dns_fixedname_t nextfixed;
   7444 	dns_name_t *name, *nextname;
   7445 	dns_rdataset_t rdataset;
   7446 	dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
   7447 	dns_nsec3chainlist_t cleanup;
   7448 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   7449 	isc_int32_t signatures;
   7450 	isc_boolean_t check_ksk, keyset_kskonly;
   7451 	isc_boolean_t delegation;
   7452 	isc_boolean_t first;
   7453 	isc_result_t result;
   7454 	isc_stdtime_t now, inception, soaexpire, expire;
   7455 	isc_uint32_t jitter, sigvalidityinterval;
   7456 	unsigned int i;
   7457 	unsigned int nkeys = 0;
   7458 	isc_uint32_t nodes;
   7459 	isc_boolean_t unsecure = ISC_FALSE;
   7460 	isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
   7461 	isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
   7462 	dns_rdatasetiter_t *iterator = NULL;
   7463 	isc_boolean_t buildnsecchain;
   7464 	isc_boolean_t updatensec = ISC_FALSE;
   7465 	dns_rdatatype_t privatetype = zone->privatetype;
   7466 
   7467 	ENTER;
   7468 
   7469 	dns_rdataset_init(&rdataset);
   7470 	name = dns_fixedname_initname(&fixed);
   7471 	nextname = dns_fixedname_initname(&nextfixed);
   7472 	dns_diff_init(zone->mctx, &param_diff);
   7473 	dns_diff_init(zone->mctx, &nsec3_diff);
   7474 	dns_diff_init(zone->mctx, &nsec_diff);
   7475 	dns_diff_init(zone->mctx, &_sig_diff);
   7476 	zonediff_init(&zonediff, &_sig_diff);
   7477 	ISC_LIST_INIT(cleanup);
   7478 
   7479 	/*
   7480 	 * Updates are disabled.  Pause for 5 minutes.
   7481 	 */
   7482 	if (zone->update_disabled) {
   7483 		result = ISC_R_FAILURE;
   7484 		goto failure;
   7485 	}
   7486 
   7487 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   7488 	/*
   7489 	 * This function is called when zone timer fires, after the latter gets
   7490 	 * set by zone_addnsec3chain().  If the action triggering the call to
   7491 	 * zone_addnsec3chain() is closely followed by a zone deletion request,
   7492 	 * it might turn out that the timer thread will not be woken up until
   7493 	 * after the zone is deleted by rmzone(), which calls dns_db_detach()
   7494 	 * for zone->db, causing the latter to become NULL.  Return immediately
   7495 	 * if that happens.
   7496 	 */
   7497 	if (zone->db != NULL) {
   7498 		dns_db_attach(zone->db, &db);
   7499 	}
   7500 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   7501 	if (db == NULL) {
   7502 		return;
   7503 	}
   7504 
   7505 	result = dns_db_newversion(db, &version);
   7506 	if (result != ISC_R_SUCCESS) {
   7507 		dns_zone_log(zone, ISC_LOG_ERROR,
   7508 			     "zone_nsec3chain:dns_db_newversion -> %s",
   7509 			     dns_result_totext(result));
   7510 		goto failure;
   7511 	}
   7512 
   7513 	isc_stdtime_get(&now);
   7514 
   7515 	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
   7516 				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
   7517 	if (result != ISC_R_SUCCESS) {
   7518 		dns_zone_log(zone, ISC_LOG_ERROR,
   7519 			     "zone_nsec3chain:dns__zone_findkeys -> %s",
   7520 			     dns_result_totext(result));
   7521 		goto failure;
   7522 	}
   7523 
   7524 	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
   7525 	inception = now - 3600;	/* Allow for clock skew. */
   7526 	soaexpire = now + sigvalidityinterval;
   7527 
   7528 	/*
   7529 	 * Spread out signatures over time if they happen to be
   7530 	 * clumped.  We don't do this for each add_sigs() call as
   7531 	 * we still want some clustering to occur.
   7532 	 */
   7533 	if (sigvalidityinterval >= 3600U) {
   7534 		isc_random_get(&jitter);
   7535 		if (sigvalidityinterval > 7200U) {
   7536 			jitter %= 3600;
   7537 		} else {
   7538 			jitter %= 1200;
   7539 		}
   7540 		expire = soaexpire - jitter - 1;
   7541 	} else {
   7542 		expire = soaexpire - 1;
   7543 	}
   7544 
   7545 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
   7546 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
   7547 
   7548 	/*
   7549 	 * We keep pulling nodes off each iterator in turn until
   7550 	 * we have no more nodes to pull off or we reach the limits
   7551 	 * for this quantum.
   7552 	 */
   7553 	nodes = zone->nodes;
   7554 	signatures = zone->signatures;
   7555 	LOCK_ZONE(zone);
   7556 	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   7557 	UNLOCK_ZONE(zone);
   7558 	first = ISC_TRUE;
   7559 
   7560 	if (nsec3chain != NULL)
   7561 		nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
   7562 	/*
   7563 	 * Generate new NSEC3 chains first.
   7564 	 *
   7565 	 * The following while loop iterates over nodes in the zone database,
   7566 	 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
   7567 	 * them.  Once all nodes are processed, the "delete_nsec" field is
   7568 	 * consulted to check whether we are supposed to remove NSEC records
   7569 	 * from the zone database; if so, the database iterator is reset to
   7570 	 * point to the first node and the loop traverses all of them again,
   7571 	 * this time removing NSEC records.  If we hit a node which is obscured
   7572 	 * by a delegation or a DNAME, nodes are skipped over until we find one
   7573 	 * that is not obscured by the same obscuring name and then normal
   7574 	 * processing is resumed.
   7575 	 *
   7576 	 * The above is repeated until all requested NSEC3 chain changes are
   7577 	 * applied or when we reach the limits for this quantum, whichever
   7578 	 * happens first.
   7579 	 *
   7580 	 * Note that the "signatures" variable is only used here to limit the
   7581 	 * amount of work performed.  Actual DNSSEC signatures are only
   7582 	 * generated by dns__zone_updatesigs() calls later in this function.
   7583 	 */
   7584 	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
   7585 		LOCK_ZONE(zone);
   7586 		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
   7587 
   7588 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   7589 		if (nsec3chain->done || nsec3chain->db != zone->db) {
   7590 			ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
   7591 			ISC_LIST_APPEND(cleanup, nsec3chain, link);
   7592 		}
   7593 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   7594 		UNLOCK_ZONE(zone);
   7595 		if (ISC_LIST_TAIL(cleanup) == nsec3chain)
   7596 			goto next_addchain;
   7597 
   7598 		/*
   7599 		 * Possible future db.
   7600 		 */
   7601 		if (nsec3chain->db != db) {
   7602 			goto next_addchain;
   7603 		}
   7604 
   7605 		if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
   7606 			goto next_addchain;
   7607 
   7608 		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
   7609 
   7610 		if (nsec3chain->delete_nsec) {
   7611 			delegation = ISC_FALSE;
   7612 			dns_dbiterator_pause(nsec3chain->dbiterator);
   7613 			CHECK(delete_nsec(db, version, node, name, &nsec_diff));
   7614 			goto next_addnode;
   7615 		}
   7616 		/*
   7617 		 * On the first pass we need to check if the current node
   7618 		 * has not been obscured.
   7619 		 */
   7620 		delegation = ISC_FALSE;
   7621 		unsecure = ISC_FALSE;
   7622 		if (first) {
   7623 			dns_fixedname_t ffound;
   7624 			dns_name_t *found;
   7625 			found = dns_fixedname_initname(&ffound);
   7626 			result = dns_db_find(db, name, version,
   7627 					     dns_rdatatype_soa,
   7628 					     DNS_DBFIND_NOWILD, 0, NULL, found,
   7629 					     NULL, NULL);
   7630 			if ((result == DNS_R_DELEGATION ||
   7631 			    result == DNS_R_DNAME) &&
   7632 			    !dns_name_equal(name, found)) {
   7633 				/*
   7634 				 * Remember the obscuring name so that
   7635 				 * we skip all obscured names.
   7636 				 */
   7637 				dns_name_copy(found, name, NULL);
   7638 				delegation = ISC_TRUE;
   7639 				goto next_addnode;
   7640 			}
   7641 		}
   7642 
   7643 		/*
   7644 		 * Check to see if this is a bottom of zone node.
   7645 		 */
   7646 		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
   7647 		if (result == ISC_R_NOTFOUND)	/* Empty node? */
   7648 			goto next_addnode;
   7649 		if (result != ISC_R_SUCCESS)
   7650 			goto failure;
   7651 
   7652 		seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
   7653 			ISC_FALSE;
   7654 		for (result = dns_rdatasetiter_first(iterator);
   7655 		     result == ISC_R_SUCCESS;
   7656 		     result = dns_rdatasetiter_next(iterator)) {
   7657 			dns_rdatasetiter_current(iterator, &rdataset);
   7658 			INSIST(rdataset.type != dns_rdatatype_nsec3);
   7659 			if (rdataset.type == dns_rdatatype_soa)
   7660 				seen_soa = ISC_TRUE;
   7661 			else if (rdataset.type == dns_rdatatype_ns)
   7662 				seen_ns = ISC_TRUE;
   7663 			else if (rdataset.type == dns_rdatatype_dname)
   7664 				seen_dname = ISC_TRUE;
   7665 			else if (rdataset.type == dns_rdatatype_ds)
   7666 				seen_ds = ISC_TRUE;
   7667 			else if (rdataset.type == dns_rdatatype_nsec)
   7668 				seen_nsec = ISC_TRUE;
   7669 			dns_rdataset_disassociate(&rdataset);
   7670 		}
   7671 		dns_rdatasetiter_destroy(&iterator);
   7672 		/*
   7673 		 * Is there a NSEC chain than needs to be cleaned up?
   7674 		 */
   7675 		if (seen_nsec)
   7676 			nsec3chain->seen_nsec = ISC_TRUE;
   7677 		if (seen_ns && !seen_soa && !seen_ds)
   7678 			unsecure = ISC_TRUE;
   7679 		if ((seen_ns && !seen_soa) || seen_dname)
   7680 			delegation = ISC_TRUE;
   7681 
   7682 		/*
   7683 		 * Process one node.
   7684 		 */
   7685 		dns_dbiterator_pause(nsec3chain->dbiterator);
   7686 		result = dns_nsec3_addnsec3(db, version, name,
   7687 					    &nsec3chain->nsec3param,
   7688 					    zone->minimum, unsecure,
   7689 					    &nsec3_diff);
   7690 		if (result != ISC_R_SUCCESS) {
   7691 			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
   7692 				     "dns_nsec3_addnsec3 -> %s",
   7693 				     dns_result_totext(result));
   7694 			goto failure;
   7695 		}
   7696 
   7697 		/*
   7698 		 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
   7699 		 * two signatures.  Additionally there will, in general, be
   7700 		 * two signature generated below.
   7701 		 *
   7702 		 * If we are only changing the optout flag the cost is half
   7703 		 * that of the cost of generating a completely new chain.
   7704 		 */
   7705 		signatures -= 4;
   7706 
   7707 		/*
   7708 		 * Go onto next node.
   7709 		 */
   7710  next_addnode:
   7711 		first = ISC_FALSE;
   7712 		dns_db_detachnode(db, &node);
   7713 		do {
   7714 			result = dns_dbiterator_next(nsec3chain->dbiterator);
   7715 
   7716 			if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
   7717 				dns_dbiterator_pause(nsec3chain->dbiterator);
   7718 				CHECK(fixup_nsec3param(db, version, nsec3chain,
   7719 						       ISC_FALSE, privatetype,
   7720 						       &param_diff));
   7721 				LOCK_ZONE(zone);
   7722 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
   7723 						link);
   7724 				UNLOCK_ZONE(zone);
   7725 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
   7726 				goto next_addchain;
   7727 			}
   7728 			if (result == ISC_R_NOMORE) {
   7729 				dns_dbiterator_pause(nsec3chain->dbiterator);
   7730 				if (nsec3chain->seen_nsec) {
   7731 					CHECK(fixup_nsec3param(db, version,
   7732 							       nsec3chain,
   7733 							       ISC_TRUE,
   7734 							       privatetype,
   7735 							       &param_diff));
   7736 					nsec3chain->delete_nsec = ISC_TRUE;
   7737 					goto same_addchain;
   7738 				}
   7739 				CHECK(fixup_nsec3param(db, version, nsec3chain,
   7740 						       ISC_FALSE, privatetype,
   7741 						       &param_diff));
   7742 				LOCK_ZONE(zone);
   7743 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
   7744 						link);
   7745 				UNLOCK_ZONE(zone);
   7746 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
   7747 				goto next_addchain;
   7748 			} else if (result != ISC_R_SUCCESS) {
   7749 				dns_zone_log(zone, ISC_LOG_ERROR,
   7750 					     "zone_nsec3chain:"
   7751 					     "dns_dbiterator_next -> %s",
   7752 					     dns_result_totext(result));
   7753 				goto failure;
   7754 			} else if (delegation) {
   7755 				dns_dbiterator_current(nsec3chain->dbiterator,
   7756 						       &node, nextname);
   7757 				dns_db_detachnode(db, &node);
   7758 				if (!dns_name_issubdomain(nextname, name))
   7759 					break;
   7760 			} else
   7761 				break;
   7762 		} while (1);
   7763 		continue;
   7764 
   7765  same_addchain:
   7766 		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
   7767 		first = ISC_TRUE;
   7768 		continue;
   7769 
   7770  next_addchain:
   7771 		dns_dbiterator_pause(nsec3chain->dbiterator);
   7772 		nsec3chain = nextnsec3chain;
   7773 		first = ISC_TRUE;
   7774 		if (nsec3chain != NULL)
   7775 			nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
   7776 	}
   7777 
   7778 	if (nsec3chain != NULL)
   7779 		goto skip_removals;
   7780 
   7781 	/*
   7782 	 * Process removals.
   7783 	 *
   7784 	 * This is a counterpart of the above while loop which takes care of
   7785 	 * removing an NSEC3 chain.  It starts with determining whether the
   7786 	 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
   7787 	 * NSEC chain by iterating over all nodes in the zone database and only
   7788 	 * then goes on to remove NSEC3 records be iterating over all nodes
   7789 	 * again and calling deletematchingnsec3() for each of them; otherwise,
   7790 	 * it starts removing NSEC3 records immediately.  Rules for processing
   7791 	 * obscured nodes and interrupting work are the same as for the while
   7792 	 * loop above.
   7793 	 */
   7794 	LOCK_ZONE(zone);
   7795 	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   7796 	UNLOCK_ZONE(zone);
   7797 	first = ISC_TRUE;
   7798 	buildnsecchain = ISC_FALSE;
   7799 	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
   7800 		LOCK_ZONE(zone);
   7801 		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
   7802 		UNLOCK_ZONE(zone);
   7803 
   7804 		if (nsec3chain->db != db)
   7805 			goto next_removechain;
   7806 
   7807 		if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
   7808 			goto next_removechain;
   7809 
   7810 		/*
   7811 		 * Work out if we need to build a NSEC chain as a consequence
   7812 		 * of removing this NSEC3 chain.
   7813 		 */
   7814 		if (first && !updatensec &&
   7815 		    (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
   7816 		{
   7817 			result = need_nsec_chain(db, version,
   7818 						 &nsec3chain->nsec3param,
   7819 						 &buildnsecchain);
   7820 			if (result != ISC_R_SUCCESS) {
   7821 				dns_zone_log(zone, ISC_LOG_ERROR,
   7822 					     "zone_nsec3chain:"
   7823 					     "need_nsec_chain -> %s",
   7824 					     dns_result_totext(result));
   7825 				goto failure;
   7826 			}
   7827 		}
   7828 
   7829 		if (first)
   7830 			dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
   7831 				     "buildnsecchain = %u\n", buildnsecchain);
   7832 
   7833 		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
   7834 		delegation = ISC_FALSE;
   7835 
   7836 		if (!buildnsecchain) {
   7837 			/*
   7838 			 * Delete the NSEC3PARAM record matching this chain.
   7839 			 */
   7840 			if (first) {
   7841 				result = fixup_nsec3param(db, version,
   7842 							  nsec3chain,
   7843 							  ISC_TRUE, privatetype,
   7844 							  &param_diff);
   7845 				if (result != ISC_R_SUCCESS) {
   7846 					dns_zone_log(zone, ISC_LOG_ERROR,
   7847 						     "zone_nsec3chain:"
   7848 						     "fixup_nsec3param -> %s",
   7849 						     dns_result_totext(result));
   7850 					goto failure;
   7851 				}
   7852 			}
   7853 
   7854 			/*
   7855 			 * Delete the NSEC3 records.
   7856 			 */
   7857 			result = deletematchingnsec3(db, version, node, name,
   7858 						     &nsec3chain->nsec3param,
   7859 						     &nsec3_diff);
   7860 			if (result != ISC_R_SUCCESS) {
   7861 				dns_zone_log(zone, ISC_LOG_ERROR,
   7862 					     "zone_nsec3chain:"
   7863 					     "deletematchingnsec3 -> %s",
   7864 					     dns_result_totext(result));
   7865 				goto failure;
   7866 			}
   7867 			goto next_removenode;
   7868 		}
   7869 
   7870 		if (first) {
   7871 			dns_fixedname_t ffound;
   7872 			dns_name_t *found;
   7873 			found = dns_fixedname_initname(&ffound);
   7874 			result = dns_db_find(db, name, version,
   7875 					     dns_rdatatype_soa,
   7876 					     DNS_DBFIND_NOWILD, 0, NULL, found,
   7877 					     NULL, NULL);
   7878 			if ((result == DNS_R_DELEGATION ||
   7879 			     result == DNS_R_DNAME) &&
   7880 			    !dns_name_equal(name, found)) {
   7881 				/*
   7882 				 * Remember the obscuring name so that
   7883 				 * we skip all obscured names.
   7884 				 */
   7885 				dns_name_copy(found, name, NULL);
   7886 				delegation = ISC_TRUE;
   7887 				goto next_removenode;
   7888 			}
   7889 		}
   7890 
   7891 		/*
   7892 		 * Check to see if this is a bottom of zone node.
   7893 		 */
   7894 		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
   7895 		if (result == ISC_R_NOTFOUND)	/* Empty node? */
   7896 			goto next_removenode;
   7897 		if (result != ISC_R_SUCCESS)
   7898 			goto failure;
   7899 
   7900 		seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
   7901 			seen_rr = ISC_FALSE;
   7902 		for (result = dns_rdatasetiter_first(iterator);
   7903 		     result == ISC_R_SUCCESS;
   7904 		     result = dns_rdatasetiter_next(iterator)) {
   7905 			dns_rdatasetiter_current(iterator, &rdataset);
   7906 			if (rdataset.type == dns_rdatatype_soa)
   7907 				seen_soa = ISC_TRUE;
   7908 			else if (rdataset.type == dns_rdatatype_ns)
   7909 				seen_ns = ISC_TRUE;
   7910 			else if (rdataset.type == dns_rdatatype_dname)
   7911 				seen_dname = ISC_TRUE;
   7912 			else if (rdataset.type == dns_rdatatype_nsec)
   7913 				seen_nsec = ISC_TRUE;
   7914 			else if (rdataset.type == dns_rdatatype_nsec3)
   7915 				seen_nsec3 = ISC_TRUE;
   7916 			if (rdataset.type != dns_rdatatype_rrsig)
   7917 				seen_rr = ISC_TRUE;
   7918 			dns_rdataset_disassociate(&rdataset);
   7919 		}
   7920 		dns_rdatasetiter_destroy(&iterator);
   7921 
   7922 		if (!seen_rr || seen_nsec3 || seen_nsec)
   7923 			goto next_removenode;
   7924 		if ((seen_ns && !seen_soa) || seen_dname)
   7925 			delegation = ISC_TRUE;
   7926 
   7927 		/*
   7928 		 * Add a NSEC record except at the origin.
   7929 		 */
   7930 		if (!dns_name_equal(name, dns_db_origin(db))) {
   7931 			dns_dbiterator_pause(nsec3chain->dbiterator);
   7932 			CHECK(add_nsec(db, version, name, node, zone->minimum,
   7933 				       delegation, &nsec_diff));
   7934 			signatures--;
   7935 		}
   7936 
   7937  next_removenode:
   7938 		first = ISC_FALSE;
   7939 		dns_db_detachnode(db, &node);
   7940 		do {
   7941 			result = dns_dbiterator_next(nsec3chain->dbiterator);
   7942 			if (result == ISC_R_NOMORE && buildnsecchain) {
   7943 				/*
   7944 				 * The NSEC chain should now be built.
   7945 				 * We can now remove the NSEC3 chain.
   7946 				 */
   7947 				updatensec = ISC_TRUE;
   7948 				goto same_removechain;
   7949 			}
   7950 			if (result == ISC_R_NOMORE) {
   7951 				LOCK_ZONE(zone);
   7952 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
   7953 						link);
   7954 				UNLOCK_ZONE(zone);
   7955 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
   7956 				dns_dbiterator_pause(nsec3chain->dbiterator);
   7957 				result = fixup_nsec3param(db, version,
   7958 							  nsec3chain, ISC_FALSE,
   7959 							  privatetype,
   7960 							  &param_diff);
   7961 				if (result != ISC_R_SUCCESS) {
   7962 					dns_zone_log(zone, ISC_LOG_ERROR,
   7963 						     "zone_nsec3chain:"
   7964 						     "fixup_nsec3param -> %s",
   7965 						     dns_result_totext(result));
   7966 					goto failure;
   7967 				}
   7968 				goto next_removechain;
   7969 			} else if (result != ISC_R_SUCCESS) {
   7970 				dns_zone_log(zone, ISC_LOG_ERROR,
   7971 					     "zone_nsec3chain:"
   7972 					     "dns_dbiterator_next -> %s",
   7973 					     dns_result_totext(result));
   7974 				goto failure;
   7975 			} else if (delegation) {
   7976 				dns_dbiterator_current(nsec3chain->dbiterator,
   7977 						       &node, nextname);
   7978 				dns_db_detachnode(db, &node);
   7979 				if (!dns_name_issubdomain(nextname, name))
   7980 					break;
   7981 			} else
   7982 				break;
   7983 		} while (1);
   7984 		continue;
   7985 
   7986  same_removechain:
   7987 		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
   7988 		buildnsecchain = ISC_FALSE;
   7989 		first = ISC_TRUE;
   7990 		continue;
   7991 
   7992  next_removechain:
   7993 		dns_dbiterator_pause(nsec3chain->dbiterator);
   7994 		nsec3chain = nextnsec3chain;
   7995 		first = ISC_TRUE;
   7996 	}
   7997 
   7998  skip_removals:
   7999 	/*
   8000 	 * We may need to update the NSEC/NSEC3 records for the zone apex.
   8001 	 */
   8002 	if (!ISC_LIST_EMPTY(param_diff.tuples)) {
   8003 		isc_boolean_t rebuild_nsec = ISC_FALSE,
   8004 			      rebuild_nsec3 = ISC_FALSE;
   8005 		result = dns_db_getoriginnode(db, &node);
   8006 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8007 		result = dns_db_allrdatasets(db, node, version, 0, &iterator);
   8008 		if (result != ISC_R_SUCCESS) {
   8009 			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
   8010 				     "dns_db_allrdatasets -> %s",
   8011 				     dns_result_totext(result));
   8012 			goto failure;
   8013 		}
   8014 		for (result = dns_rdatasetiter_first(iterator);
   8015 		     result == ISC_R_SUCCESS;
   8016 		     result = dns_rdatasetiter_next(iterator)) {
   8017 			dns_rdatasetiter_current(iterator, &rdataset);
   8018 			if (rdataset.type == dns_rdatatype_nsec)
   8019 				rebuild_nsec = ISC_TRUE;
   8020 			if (rdataset.type == dns_rdatatype_nsec3param)
   8021 				rebuild_nsec3 = ISC_TRUE;
   8022 			dns_rdataset_disassociate(&rdataset);
   8023 		}
   8024 		dns_rdatasetiter_destroy(&iterator);
   8025 		dns_db_detachnode(db, &node);
   8026 
   8027 		if (rebuild_nsec) {
   8028 			if (nsec3chain != NULL)
   8029 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8030 
   8031 			result = updatesecure(db, version, &zone->origin,
   8032 					      zone->minimum, ISC_TRUE,
   8033 					      &nsec_diff);
   8034 			if (result != ISC_R_SUCCESS) {
   8035 				dns_zone_log(zone, ISC_LOG_ERROR,
   8036 					     "zone_nsec3chain:"
   8037 					     "updatesecure -> %s",
   8038 					     dns_result_totext(result));
   8039 				goto failure;
   8040 			}
   8041 		}
   8042 
   8043 		if (rebuild_nsec3) {
   8044 			if (nsec3chain != NULL)
   8045 				dns_dbiterator_pause(nsec3chain->dbiterator);
   8046 
   8047 			result = dns_nsec3_addnsec3s(db, version,
   8048 						     dns_db_origin(db),
   8049 						     zone->minimum, ISC_FALSE,
   8050 						     &nsec3_diff);
   8051 			if (result != ISC_R_SUCCESS) {
   8052 				dns_zone_log(zone, ISC_LOG_ERROR,
   8053 					     "zone_nsec3chain:"
   8054 					     "dns_nsec3_addnsec3s -> %s",
   8055 					     dns_result_totext(result));
   8056 				goto failure;
   8057 			}
   8058 		}
   8059 	}
   8060 
   8061 	/*
   8062 	 * Add / update signatures for the NSEC3 records.
   8063 	 */
   8064 	if (nsec3chain != NULL)
   8065 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8066 	result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
   8067 				      nkeys, zone, inception, expire, now,
   8068 				      check_ksk, keyset_kskonly, &zonediff);
   8069 	if (result != ISC_R_SUCCESS) {
   8070 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
   8071 			     "dns__zone_updatesigs -> %s",
   8072 			     dns_result_totext(result));
   8073 		goto failure;
   8074 	}
   8075 
   8076 	/*
   8077 	 * We have changed the NSEC3PARAM or private RRsets
   8078 	 * above so we need to update the signatures.
   8079 	 */
   8080 	result = dns__zone_updatesigs(&param_diff, db, version, zone_keys,
   8081 				      nkeys, zone, inception, expire, now,
   8082 				      check_ksk, keyset_kskonly, &zonediff);
   8083 	if (result != ISC_R_SUCCESS) {
   8084 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
   8085 			     "dns__zone_updatesigs -> %s",
   8086 			     dns_result_totext(result));
   8087 		goto failure;
   8088 	}
   8089 
   8090 	if (updatensec) {
   8091 		result = updatesecure(db, version, &zone->origin,
   8092 				      zone->minimum, ISC_FALSE, &nsec_diff);
   8093 		if (result != ISC_R_SUCCESS) {
   8094 			dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
   8095 				     "updatesecure -> %s",
   8096 				     dns_result_totext(result));
   8097 			goto failure;
   8098 		}
   8099 	}
   8100 
   8101 	result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys,
   8102 				      nkeys, zone, inception, expire, now,
   8103 				      check_ksk, keyset_kskonly, &zonediff);
   8104 	if (result != ISC_R_SUCCESS) {
   8105 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
   8106 			     "dns__zone_updatesigs -> %s",
   8107 			     dns_result_totext(result));
   8108 		goto failure;
   8109 	}
   8110 
   8111 	/*
   8112 	 * If we made no effective changes to the zone then we can just
   8113 	 * cleanup otherwise we need to increment the serial.
   8114 	 */
   8115 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
   8116 		/*
   8117 		 * No need to call dns_db_closeversion() here as it is
   8118 		 * called with commit = ISC_TRUE below.
   8119 		 */
   8120 		goto done;
   8121 	}
   8122 
   8123 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
   8124 			  &zonediff, zone_keys, nkeys, now, ISC_FALSE);
   8125 	if (result != ISC_R_SUCCESS) {
   8126 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
   8127 			     "del_sigs -> %s", dns_result_totext(result));
   8128 		goto failure;
   8129 	}
   8130 
   8131 	result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
   8132 				   zone->updatemethod);
   8133 	if (result != ISC_R_SUCCESS) {
   8134 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
   8135 			     "update_soa_serial -> %s",
   8136 			     dns_result_totext(result));
   8137 		goto failure;
   8138 	}
   8139 
   8140 	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
   8141 			  zonediff.diff, zone_keys, nkeys, zone->mctx,
   8142 			  inception, soaexpire, check_ksk, keyset_kskonly);
   8143 	if (result != ISC_R_SUCCESS) {
   8144 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
   8145 			     "add_sigs -> %s", dns_result_totext(result));
   8146 		goto failure;
   8147 	}
   8148 
   8149 	/* Write changes to journal file. */
   8150 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
   8151 
   8152 	LOCK_ZONE(zone);
   8153 	zone_needdump(zone, DNS_DUMP_DELAY);
   8154 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   8155 	UNLOCK_ZONE(zone);
   8156 
   8157  done:
   8158 	/*
   8159 	 * Pause all iterators so that dns_db_closeversion() can succeed.
   8160 	 */
   8161 	LOCK_ZONE(zone);
   8162 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   8163 	     nsec3chain != NULL;
   8164 	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
   8165 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8166 	UNLOCK_ZONE(zone);
   8167 
   8168 	/*
   8169 	 * Everything has succeeded. Commit the changes.
   8170 	 * Unconditionally commit as zonediff.offline not checked above.
   8171 	 */
   8172 	dns_db_closeversion(db, &version, ISC_TRUE);
   8173 
   8174 	/*
   8175 	 * Everything succeeded so we can clean these up now.
   8176 	 */
   8177 	nsec3chain = ISC_LIST_HEAD(cleanup);
   8178 	while (nsec3chain != NULL) {
   8179 		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
   8180 		dns_db_detach(&nsec3chain->db);
   8181 		dns_dbiterator_destroy(&nsec3chain->dbiterator);
   8182 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   8183 		nsec3chain = ISC_LIST_HEAD(cleanup);
   8184 	}
   8185 
   8186 	set_resigntime(zone);
   8187 
   8188  failure:
   8189 	if (result != ISC_R_SUCCESS)
   8190 		dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
   8191 			     dns_result_totext(result));
   8192 	/*
   8193 	 * On error roll back the current nsec3chain.
   8194 	 */
   8195 	if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
   8196 		if (nsec3chain->done) {
   8197 			dns_db_detach(&nsec3chain->db);
   8198 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
   8199 			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   8200 		} else {
   8201 			result = dns_dbiterator_first(nsec3chain->dbiterator);
   8202 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8203 			dns_dbiterator_pause(nsec3chain->dbiterator);
   8204 			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
   8205 		}
   8206 	}
   8207 
   8208 	/*
   8209 	 * Rollback the cleanup list.
   8210 	 */
   8211 	nsec3chain = ISC_LIST_TAIL(cleanup);
   8212 	while (nsec3chain != NULL) {
   8213 		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
   8214 		if (nsec3chain->done) {
   8215 			dns_db_detach(&nsec3chain->db);
   8216 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
   8217 			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
   8218 		} else {
   8219 			LOCK_ZONE(zone);
   8220 			ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
   8221 			UNLOCK_ZONE(zone);
   8222 			result = dns_dbiterator_first(nsec3chain->dbiterator);
   8223 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8224 			dns_dbiterator_pause(nsec3chain->dbiterator);
   8225 			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
   8226 		}
   8227 		nsec3chain = ISC_LIST_TAIL(cleanup);
   8228 	}
   8229 
   8230 	LOCK_ZONE(zone);
   8231 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
   8232 	     nsec3chain != NULL;
   8233 	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
   8234 		dns_dbiterator_pause(nsec3chain->dbiterator);
   8235 	UNLOCK_ZONE(zone);
   8236 
   8237 	dns_diff_clear(&param_diff);
   8238 	dns_diff_clear(&nsec3_diff);
   8239 	dns_diff_clear(&nsec_diff);
   8240 	dns_diff_clear(&_sig_diff);
   8241 
   8242 	if (iterator != NULL)
   8243 		dns_rdatasetiter_destroy(&iterator);
   8244 
   8245 	for (i = 0; i < nkeys; i++)
   8246 		dst_key_free(&zone_keys[i]);
   8247 
   8248 	if (node != NULL)
   8249 		dns_db_detachnode(db, &node);
   8250 	if (version != NULL) {
   8251 		dns_db_closeversion(db, &version, ISC_FALSE);
   8252 		dns_db_detach(&db);
   8253 	} else if (db != NULL)
   8254 		dns_db_detach(&db);
   8255 
   8256 	LOCK_ZONE(zone);
   8257 	if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
   8258 		isc_interval_t interval;
   8259 		if (zone->update_disabled || result != ISC_R_SUCCESS)
   8260 			isc_interval_set(&interval, 60, 0);	  /* 1 minute */
   8261 		else
   8262 			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
   8263 		isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
   8264 	} else
   8265 		isc_time_settoepoch(&zone->nsec3chaintime);
   8266 	UNLOCK_ZONE(zone);
   8267 
   8268 	INSIST(version == NULL);
   8269 }
   8270 
   8271 /*%
   8272  * Delete all RRSIG records with the given algorithm and keyid.
   8273  * Remove the NSEC record and RRSIGs if nkeys is zero.
   8274  * If all remaining RRsets are signed with the given algorithm
   8275  * set *has_algp to ISC_TRUE.
   8276  */
   8277 static isc_result_t
   8278 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
   8279 	dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
   8280 	isc_uint16_t keyid, isc_boolean_t *has_algp, dns_diff_t *diff)
   8281 {
   8282 	dns_rdata_rrsig_t rrsig;
   8283 	dns_rdataset_t rdataset;
   8284 	dns_rdatasetiter_t *iterator = NULL;
   8285 	isc_result_t result;
   8286 	isc_boolean_t alg_missed = ISC_FALSE;
   8287 	isc_boolean_t alg_found = ISC_FALSE;
   8288 
   8289 	char namebuf[DNS_NAME_FORMATSIZE];
   8290 	dns_name_format(name, namebuf, sizeof(namebuf));
   8291 
   8292 	result = dns_db_allrdatasets(db, node, version, 0, &iterator);
   8293 	if (result != ISC_R_SUCCESS) {
   8294 		if (result == ISC_R_NOTFOUND)
   8295 			result = ISC_R_SUCCESS;
   8296 		return (result);
   8297 	}
   8298 
   8299 	dns_rdataset_init(&rdataset);
   8300 	for (result = dns_rdatasetiter_first(iterator);
   8301 	     result == ISC_R_SUCCESS;
   8302 	     result = dns_rdatasetiter_next(iterator)) {
   8303 		isc_boolean_t has_alg = ISC_FALSE;
   8304 		dns_rdatasetiter_current(iterator, &rdataset);
   8305 		if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
   8306 			for (result = dns_rdataset_first(&rdataset);
   8307 			     result == ISC_R_SUCCESS;
   8308 			     result = dns_rdataset_next(&rdataset)) {
   8309 				dns_rdata_t rdata = DNS_RDATA_INIT;
   8310 				dns_rdataset_current(&rdataset, &rdata);
   8311 				CHECK(update_one_rr(db, version, diff,
   8312 						    DNS_DIFFOP_DEL, name,
   8313 						    rdataset.ttl, &rdata));
   8314 			}
   8315 			if (result != ISC_R_NOMORE)
   8316 				goto failure;
   8317 			dns_rdataset_disassociate(&rdataset);
   8318 			continue;
   8319 		}
   8320 		if (rdataset.type != dns_rdatatype_rrsig) {
   8321 			dns_rdataset_disassociate(&rdataset);
   8322 			continue;
   8323 		}
   8324 		for (result = dns_rdataset_first(&rdataset);
   8325 		     result == ISC_R_SUCCESS;
   8326 		     result = dns_rdataset_next(&rdataset))
   8327 		{
   8328 			dns_rdata_t rdata = DNS_RDATA_INIT;
   8329 			dns_rdataset_current(&rdataset, &rdata);
   8330 			CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
   8331 			if (nkeys != 0 &&
   8332 			    (rrsig.algorithm != algorithm ||
   8333 			     rrsig.keyid != keyid))
   8334 			{
   8335 				if (rrsig.algorithm == algorithm) {
   8336 					has_alg = ISC_TRUE;
   8337 				}
   8338 				continue;
   8339 			}
   8340 			CHECK(update_one_rr(db, version, diff,
   8341 					    DNS_DIFFOP_DELRESIGN, name,
   8342 					    rdataset.ttl, &rdata));
   8343 		}
   8344 		dns_rdataset_disassociate(&rdataset);
   8345 		if (result != ISC_R_NOMORE)
   8346 			break;
   8347 
   8348 		/*
   8349 		 * After deleting, if there's still a signature for
   8350 		 * 'algorithm', set alg_found; if not, set alg_missed.
   8351 		 */
   8352 		if (has_alg) {
   8353 			alg_found = ISC_TRUE;
   8354 		} else {
   8355 			alg_missed = ISC_TRUE;
   8356 		}
   8357 	}
   8358 	if (result == ISC_R_NOMORE)
   8359 		result = ISC_R_SUCCESS;
   8360 
   8361 	/*
   8362 	 * Set `has_algp` if the algorithm was found in every RRset:
   8363 	 * i.e., found in at least one, and not missing from any.
   8364 	 */
   8365 	*has_algp = ISC_TF(alg_found && !alg_missed);
   8366  failure:
   8367 	if (dns_rdataset_isassociated(&rdataset))
   8368 		dns_rdataset_disassociate(&rdataset);
   8369 	dns_rdatasetiter_destroy(&iterator);
   8370 	return (result);
   8371 }
   8372 
   8373 /*
   8374  * Incrementally sign the zone using the keys requested.
   8375  * Builds the NSEC chain if required.
   8376  */
   8377 static void
   8378 zone_sign(dns_zone_t *zone) {
   8379 	const char *me = "zone_sign";
   8380 	dns_db_t *db = NULL;
   8381 	dns_dbnode_t *node = NULL;
   8382 	dns_dbversion_t *version = NULL;
   8383 	dns_diff_t _sig_diff;
   8384 	dns_diff_t post_diff;
   8385 	dns__zonediff_t zonediff;
   8386 	dns_fixedname_t fixed;
   8387 	dns_fixedname_t nextfixed;
   8388 	dns_name_t *name, *nextname;
   8389 	dns_rdataset_t rdataset;
   8390 	dns_signing_t *signing, *nextsigning;
   8391 	dns_signinglist_t cleanup;
   8392 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   8393 	isc_int32_t signatures;
   8394 	isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
   8395 	isc_boolean_t with_ksk, with_zsk;
   8396 	isc_boolean_t commit = ISC_FALSE;
   8397 	isc_boolean_t delegation;
   8398 	isc_boolean_t build_nsec = ISC_FALSE;
   8399 	isc_boolean_t build_nsec3 = ISC_FALSE;
   8400 	isc_boolean_t first;
   8401 	isc_result_t result;
   8402 	isc_stdtime_t now, inception, soaexpire, expire;
   8403 	isc_uint32_t jitter, sigvalidityinterval;
   8404 	unsigned int i, j;
   8405 	unsigned int nkeys = 0;
   8406 	isc_uint32_t nodes;
   8407 
   8408 	ENTER;
   8409 
   8410 	dns_rdataset_init(&rdataset);
   8411 	name = dns_fixedname_initname(&fixed);
   8412 	nextname = dns_fixedname_initname(&nextfixed);
   8413 	dns_diff_init(zone->mctx, &_sig_diff);
   8414 	dns_diff_init(zone->mctx, &post_diff);
   8415 	zonediff_init(&zonediff, &_sig_diff);
   8416 	ISC_LIST_INIT(cleanup);
   8417 
   8418 	/*
   8419 	 * Updates are disabled.  Pause for 5 minutes.
   8420 	 */
   8421 	if (zone->update_disabled) {
   8422 		result = ISC_R_FAILURE;
   8423 		goto failure;
   8424 	}
   8425 
   8426 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   8427 	if (zone->db != NULL)
   8428 		dns_db_attach(zone->db, &db);
   8429 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   8430 	if (db == NULL) {
   8431 		result = ISC_R_FAILURE;
   8432 		goto failure;
   8433 	}
   8434 
   8435 	result = dns_db_newversion(db, &version);
   8436 	if (result != ISC_R_SUCCESS) {
   8437 		dns_zone_log(zone, ISC_LOG_ERROR,
   8438 			     "zone_sign:dns_db_newversion -> %s",
   8439 			     dns_result_totext(result));
   8440 		goto failure;
   8441 	}
   8442 
   8443 	isc_stdtime_get(&now);
   8444 
   8445 	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
   8446 				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
   8447 	if (result != ISC_R_SUCCESS) {
   8448 		dns_zone_log(zone, ISC_LOG_ERROR,
   8449 			     "zone_sign:dns__zone_findkeys -> %s",
   8450 			     dns_result_totext(result));
   8451 		goto failure;
   8452 	}
   8453 
   8454 	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
   8455 	inception = now - 3600;	/* Allow for clock skew. */
   8456 	soaexpire = now + sigvalidityinterval;
   8457 
   8458 	/*
   8459 	 * Spread out signatures over time if they happen to be
   8460 	 * clumped.  We don't do this for each add_sigs() call as
   8461 	 * we still want some clustering to occur.
   8462 	 */
   8463 	if (sigvalidityinterval >= 3600U) {
   8464 		isc_random_get(&jitter);
   8465 		if (sigvalidityinterval > 7200U) {
   8466 			jitter %= 3600;
   8467 		} else {
   8468 			jitter %= 1200;
   8469 		}
   8470 		expire = soaexpire - jitter - 1;
   8471 	} else {
   8472 		expire = soaexpire - 1;
   8473 	}
   8474 
   8475 	/*
   8476 	 * We keep pulling nodes off each iterator in turn until
   8477 	 * we have no more nodes to pull off or we reach the limits
   8478 	 * for this quantum.
   8479 	 */
   8480 	nodes = zone->nodes;
   8481 	signatures = zone->signatures;
   8482 	signing = ISC_LIST_HEAD(zone->signing);
   8483 	first = ISC_TRUE;
   8484 
   8485 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
   8486 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
   8487 
   8488 	/* Determine which type of chain to build */
   8489 	CHECK(dns_private_chains(db, version, zone->privatetype,
   8490 				 &build_nsec, &build_nsec3));
   8491 
   8492 	/* If neither chain is found, default to NSEC */
   8493 	if (!build_nsec && !build_nsec3)
   8494 		build_nsec = ISC_TRUE;
   8495 
   8496 	while (signing != NULL && nodes-- > 0 && signatures > 0) {
   8497 		isc_boolean_t has_alg = ISC_FALSE;
   8498 		nextsigning = ISC_LIST_NEXT(signing, link);
   8499 
   8500 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   8501 		if (signing->done || signing->db != zone->db) {
   8502 			/*
   8503 			 * The zone has been reloaded.	We will have
   8504 			 * created new signings as part of the reload
   8505 			 * process so we can destroy this one.
   8506 			 */
   8507 			ISC_LIST_UNLINK(zone->signing, signing, link);
   8508 			ISC_LIST_APPEND(cleanup, signing, link);
   8509 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   8510 			goto next_signing;
   8511 		}
   8512 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   8513 
   8514 		if (signing->db != db)
   8515 			goto next_signing;
   8516 
   8517 		delegation = ISC_FALSE;
   8518 
   8519 		if (first && signing->deleteit) {
   8520 			/*
   8521 			 * Remove the key we are deleting from consideration.
   8522 			 */
   8523 			for (i = 0, j = 0; i < nkeys; i++) {
   8524 				/*
   8525 				 * Find the key we want to remove.
   8526 				 */
   8527 				if (ALG(zone_keys[i]) == signing->algorithm &&
   8528 				    dst_key_id(zone_keys[i]) == signing->keyid)
   8529 				{
   8530 					if (KSK(zone_keys[i]))
   8531 						dst_key_free(&zone_keys[i]);
   8532 					continue;
   8533 				}
   8534 				zone_keys[j] = zone_keys[i];
   8535 				j++;
   8536 			}
   8537 			for (i = j; i < nkeys; i++) {
   8538 				zone_keys[i] = NULL;
   8539 			}
   8540 			nkeys = j;
   8541 		}
   8542 
   8543 		dns_dbiterator_current(signing->dbiterator, &node, name);
   8544 
   8545 		if (signing->deleteit) {
   8546 			dns_dbiterator_pause(signing->dbiterator);
   8547 			CHECK(del_sig(db, version, name, node, nkeys,
   8548 				      signing->algorithm, signing->keyid,
   8549 				      &has_alg, zonediff.diff));
   8550 		}
   8551 
   8552 		/*
   8553 		 * On the first pass we need to check if the current node
   8554 		 * has not been obscured.
   8555 		 */
   8556 		if (first) {
   8557 			dns_fixedname_t ffound;
   8558 			dns_name_t *found;
   8559 			found = dns_fixedname_initname(&ffound);
   8560 			result = dns_db_find(db, name, version,
   8561 					     dns_rdatatype_soa,
   8562 					     DNS_DBFIND_NOWILD, 0, NULL, found,
   8563 					     NULL, NULL);
   8564 			if ((result == DNS_R_DELEGATION ||
   8565 			     result == DNS_R_DNAME) &&
   8566 			    !dns_name_equal(name, found)) {
   8567 				/*
   8568 				 * Remember the obscuring name so that
   8569 				 * we skip all obscured names.
   8570 				 */
   8571 				dns_name_copy(found, name, NULL);
   8572 				delegation = ISC_TRUE;
   8573 				goto next_node;
   8574 			}
   8575 		}
   8576 
   8577 		/*
   8578 		 * Process one node.
   8579 		 */
   8580 		with_ksk = ISC_FALSE;
   8581 		with_zsk = ISC_FALSE;
   8582 		dns_dbiterator_pause(signing->dbiterator);
   8583 		for (i = 0; !has_alg && i < nkeys; i++) {
   8584 			isc_boolean_t both = ISC_FALSE;
   8585 
   8586 			/*
   8587 			 * Find the keys we want to sign with.
   8588 			 */
   8589 			if (!dst_key_isprivate(zone_keys[i]))
   8590 				continue;
   8591 			/*
   8592 			 * Should be redundant.
   8593 			 */
   8594 			if (dst_key_inactive(zone_keys[i]))
   8595 				continue;
   8596 
   8597 			/*
   8598 			 * When adding look for the specific key.
   8599 			 */
   8600 			if (!signing->deleteit &&
   8601 			    (dst_key_alg(zone_keys[i]) != signing->algorithm ||
   8602 			     dst_key_id(zone_keys[i]) != signing->keyid))
   8603 				continue;
   8604 
   8605 			/*
   8606 			 * When deleting make sure we are properly signed
   8607 			 * with the algorithm that was being removed.
   8608 			 */
   8609 			if (signing->deleteit &&
   8610 			    ALG(zone_keys[i]) != signing->algorithm)
   8611 				continue;
   8612 
   8613 			/*
   8614 			 * Do we do KSK processing?
   8615 			 */
   8616 			if (check_ksk && !REVOKE(zone_keys[i])) {
   8617 				isc_boolean_t have_ksk, have_nonksk;
   8618 				if (KSK(zone_keys[i])) {
   8619 					have_ksk = ISC_TRUE;
   8620 					have_nonksk = ISC_FALSE;
   8621 				} else {
   8622 					have_ksk = ISC_FALSE;
   8623 					have_nonksk = ISC_TRUE;
   8624 				}
   8625 				for (j = 0; j < nkeys; j++) {
   8626 					if (j == i ||
   8627 					    ALG(zone_keys[i]) !=
   8628 					    ALG(zone_keys[j]))
   8629 						continue;
   8630 					if (!dst_key_isprivate(zone_keys[j]))
   8631 						continue;
   8632 					/*
   8633 					 * Should be redundant.
   8634 					 */
   8635 					if (dst_key_inactive(zone_keys[j]))
   8636 						continue;
   8637 					if (REVOKE(zone_keys[j]))
   8638 						continue;
   8639 					if (KSK(zone_keys[j]))
   8640 						have_ksk = ISC_TRUE;
   8641 					else
   8642 						have_nonksk = ISC_TRUE;
   8643 					both = have_ksk && have_nonksk;
   8644 					if (both)
   8645 						break;
   8646 				}
   8647 			}
   8648 			if (both || REVOKE(zone_keys[i]))
   8649 				is_ksk = KSK(zone_keys[i]);
   8650 			else
   8651 				is_ksk = ISC_FALSE;
   8652 
   8653 			/*
   8654 			 * If deleting signatures, we need to ensure that
   8655 			 * the RRset is still signed at least once by a
   8656 			 * KSK and a ZSK.
   8657 			 */
   8658 			if (signing->deleteit && !is_ksk && with_zsk) {
   8659 				continue;
   8660 			}
   8661 
   8662 			if (signing->deleteit && is_ksk && with_ksk) {
   8663 				continue;
   8664 			}
   8665 
   8666 			CHECK(sign_a_node(db, name, node, version, build_nsec3,
   8667 					  build_nsec, zone_keys[i], inception,
   8668 					  expire, zone->minimum, is_ksk,
   8669 					  ISC_TF(both && keyset_kskonly),
   8670 					  &delegation, zonediff.diff,
   8671 					  &signatures, zone->mctx));
   8672 			/*
   8673 			 * If we are adding we are done.  Look for other keys
   8674 			 * of the same algorithm if deleting.
   8675 			 */
   8676 			if (!signing->deleteit) {
   8677 				break;
   8678 			}
   8679 			if (!is_ksk) {
   8680 				with_zsk = ISC_TRUE;
   8681 			}
   8682 			if (KSK(zone_keys[i])) {
   8683 				with_ksk = ISC_TRUE;
   8684 			}
   8685 		}
   8686 
   8687 		/*
   8688 		 * Go onto next node.
   8689 		 */
   8690  next_node:
   8691 		first = ISC_FALSE;
   8692 		dns_db_detachnode(db, &node);
   8693 		do {
   8694 			result = dns_dbiterator_next(signing->dbiterator);
   8695 			if (result == ISC_R_NOMORE) {
   8696 				ISC_LIST_UNLINK(zone->signing, signing, link);
   8697 				ISC_LIST_APPEND(cleanup, signing, link);
   8698 				dns_dbiterator_pause(signing->dbiterator);
   8699 				if (nkeys != 0 && build_nsec) {
   8700 					/*
   8701 					 * We have finished regenerating the
   8702 					 * zone with a zone signing key.
   8703 					 * The NSEC chain is now complete and
   8704 					 * there is a full set of signatures
   8705 					 * for the zone.  We can now clear the
   8706 					 * OPT bit from the NSEC record.
   8707 					 */
   8708 					result = updatesecure(db, version,
   8709 							      &zone->origin,
   8710 							      zone->minimum,
   8711 							      ISC_FALSE,
   8712 							      &post_diff);
   8713 					if (result != ISC_R_SUCCESS) {
   8714 						dns_zone_log(zone,
   8715 							     ISC_LOG_ERROR,
   8716 						    "updatesecure -> %s",
   8717 						    dns_result_totext(result));
   8718 						goto failure;
   8719 					}
   8720 				}
   8721 				result = updatesignwithkey(zone, signing,
   8722 							   version,
   8723 							   build_nsec3,
   8724 							   zone->minimum,
   8725 							   &post_diff);
   8726 				if (result != ISC_R_SUCCESS) {
   8727 					dns_zone_log(zone, ISC_LOG_ERROR,
   8728 						     "updatesignwithkey -> %s",
   8729 						     dns_result_totext(result));
   8730 					goto failure;
   8731 				}
   8732 				build_nsec = ISC_FALSE;
   8733 				goto next_signing;
   8734 			} else if (result != ISC_R_SUCCESS) {
   8735 				dns_zone_log(zone, ISC_LOG_ERROR,
   8736 					"zone_sign:dns_dbiterator_next -> %s",
   8737 					     dns_result_totext(result));
   8738 				goto failure;
   8739 			} else if (delegation) {
   8740 				dns_dbiterator_current(signing->dbiterator,
   8741 						       &node, nextname);
   8742 				dns_db_detachnode(db, &node);
   8743 				if (!dns_name_issubdomain(nextname, name))
   8744 					break;
   8745 			} else
   8746 				break;
   8747 		} while (1);
   8748 		continue;
   8749 
   8750  next_signing:
   8751 		dns_dbiterator_pause(signing->dbiterator);
   8752 		signing = nextsigning;
   8753 		first = ISC_TRUE;
   8754 	}
   8755 
   8756 	if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
   8757 		result = dns__zone_updatesigs(&post_diff, db, version,
   8758 					      zone_keys, nkeys, zone,
   8759 					      inception, expire, now,
   8760 					      check_ksk, keyset_kskonly,
   8761 					      &zonediff);
   8762 		if (result != ISC_R_SUCCESS) {
   8763 			dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
   8764 				     "dns__zone_updatesigs -> %s",
   8765 				     dns_result_totext(result));
   8766 			goto failure;
   8767 		}
   8768 	}
   8769 
   8770 	/*
   8771 	 * Have we changed anything?
   8772 	 */
   8773 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
   8774 		if (zonediff.offline)
   8775 			commit = ISC_TRUE;
   8776 		result = ISC_R_SUCCESS;
   8777 		goto pauseall;
   8778 	}
   8779 
   8780 	commit = ISC_TRUE;
   8781 
   8782 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
   8783 			  &zonediff, zone_keys, nkeys, now, ISC_FALSE);
   8784 	if (result != ISC_R_SUCCESS) {
   8785 		dns_zone_log(zone, ISC_LOG_ERROR,
   8786 			     "zone_sign:del_sigs -> %s",
   8787 			     dns_result_totext(result));
   8788 		goto failure;
   8789 	}
   8790 
   8791 	result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
   8792 				   zone->updatemethod);
   8793 	if (result != ISC_R_SUCCESS) {
   8794 		dns_zone_log(zone, ISC_LOG_ERROR,
   8795 			     "zone_sign:update_soa_serial -> %s",
   8796 			     dns_result_totext(result));
   8797 		goto failure;
   8798 	}
   8799 
   8800 	/*
   8801 	 * Generate maximum life time signatures so that the above loop
   8802 	 * termination is sensible.
   8803 	 */
   8804 	result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
   8805 			  zonediff.diff, zone_keys, nkeys, zone->mctx,
   8806 			  inception, soaexpire, check_ksk, keyset_kskonly);
   8807 	if (result != ISC_R_SUCCESS) {
   8808 		dns_zone_log(zone, ISC_LOG_ERROR,
   8809 			     "zone_sign:add_sigs -> %s",
   8810 			     dns_result_totext(result));
   8811 		goto failure;
   8812 	}
   8813 
   8814 	/*
   8815 	 * Write changes to journal file.
   8816 	 */
   8817 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
   8818 
   8819  pauseall:
   8820 	/*
   8821 	 * Pause all iterators so that dns_db_closeversion() can succeed.
   8822 	 */
   8823 	for (signing = ISC_LIST_HEAD(zone->signing);
   8824 	     signing != NULL;
   8825 	     signing = ISC_LIST_NEXT(signing, link))
   8826 		dns_dbiterator_pause(signing->dbiterator);
   8827 
   8828 	for (signing = ISC_LIST_HEAD(cleanup);
   8829 	     signing != NULL;
   8830 	     signing = ISC_LIST_NEXT(signing, link))
   8831 		dns_dbiterator_pause(signing->dbiterator);
   8832 
   8833 	/*
   8834 	 * Everything has succeeded. Commit the changes.
   8835 	 */
   8836 	dns_db_closeversion(db, &version, commit);
   8837 
   8838 	/*
   8839 	 * Everything succeeded so we can clean these up now.
   8840 	 */
   8841 	signing = ISC_LIST_HEAD(cleanup);
   8842 	while (signing != NULL) {
   8843 		ISC_LIST_UNLINK(cleanup, signing, link);
   8844 		dns_db_detach(&signing->db);
   8845 		dns_dbiterator_destroy(&signing->dbiterator);
   8846 		isc_mem_put(zone->mctx, signing, sizeof *signing);
   8847 		signing = ISC_LIST_HEAD(cleanup);
   8848 	}
   8849 
   8850 	set_resigntime(zone);
   8851 
   8852 	if (commit) {
   8853 		LOCK_ZONE(zone);
   8854 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   8855 		zone_needdump(zone, DNS_DUMP_DELAY);
   8856 		UNLOCK_ZONE(zone);
   8857 	}
   8858 
   8859  failure:
   8860 	/*
   8861 	 * Pause all dbiterators.
   8862 	 */
   8863 	for (signing = ISC_LIST_HEAD(zone->signing);
   8864 	     signing != NULL;
   8865 	     signing = ISC_LIST_NEXT(signing, link))
   8866 		dns_dbiterator_pause(signing->dbiterator);
   8867 
   8868 	/*
   8869 	 * Rollback the cleanup list.
   8870 	 */
   8871 	signing = ISC_LIST_HEAD(cleanup);
   8872 	while (signing != NULL) {
   8873 		ISC_LIST_UNLINK(cleanup, signing, link);
   8874 		ISC_LIST_PREPEND(zone->signing, signing, link);
   8875 		dns_dbiterator_first(signing->dbiterator);
   8876 		dns_dbiterator_pause(signing->dbiterator);
   8877 		signing = ISC_LIST_HEAD(cleanup);
   8878 	}
   8879 
   8880 	dns_diff_clear(&_sig_diff);
   8881 
   8882 	for (i = 0; i < nkeys; i++)
   8883 		dst_key_free(&zone_keys[i]);
   8884 
   8885 	if (node != NULL)
   8886 		dns_db_detachnode(db, &node);
   8887 
   8888 	if (version != NULL) {
   8889 		dns_db_closeversion(db, &version, ISC_FALSE);
   8890 		dns_db_detach(&db);
   8891 	} else if (db != NULL)
   8892 		dns_db_detach(&db);
   8893 
   8894 	if (ISC_LIST_HEAD(zone->signing) != NULL) {
   8895 		isc_interval_t interval;
   8896 		if (zone->update_disabled || result != ISC_R_SUCCESS)
   8897 			isc_interval_set(&interval, 60, 0);	  /* 1 minute */
   8898 		else
   8899 			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
   8900 		isc_time_nowplusinterval(&zone->signingtime, &interval);
   8901 	} else
   8902 		isc_time_settoepoch(&zone->signingtime);
   8903 
   8904 	INSIST(version == NULL);
   8905 }
   8906 
   8907 static isc_result_t
   8908 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
   8909 	      unsigned char *data, int size)
   8910 {
   8911 	dns_rdata_dnskey_t dnskey;
   8912 	dns_rdata_keydata_t keydata;
   8913 	isc_buffer_t buf;
   8914 	isc_result_t result;
   8915 
   8916 	dns_rdata_reset(target);
   8917 	isc_buffer_init(&buf, data, size);
   8918 
   8919 	switch (rr->type) {
   8920 	    case dns_rdatatype_dnskey:
   8921 		result = dns_rdata_tostruct(rr, &dnskey, NULL);
   8922 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8923 		dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
   8924 		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
   8925 				     &dnskey, &buf);
   8926 		break;
   8927 	    case dns_rdatatype_keydata:
   8928 		result = dns_rdata_tostruct(rr, &keydata, NULL);
   8929 		if (result == ISC_R_UNEXPECTEDEND)
   8930 			return (result);
   8931 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   8932 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
   8933 		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
   8934 				     &dnskey, &buf);
   8935 		break;
   8936 	    default:
   8937 		INSIST(0);
   8938 	}
   8939 	return (ISC_R_SUCCESS);
   8940 }
   8941 
   8942 /*
   8943  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
   8944  * a KEYDATA rdataset from the key zone.
   8945  *
   8946  * 'rr' contains either a DNSKEY record, or a KEYDATA record
   8947  *
   8948  * After normalizing keys to the same format (DNSKEY, with revoke bit
   8949  * cleared), return ISC_TRUE if a key that matches 'rr' is found in
   8950  * 'rdset', or ISC_FALSE if not.
   8951  */
   8952 
   8953 static isc_boolean_t
   8954 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
   8955 	unsigned char data1[4096], data2[4096];
   8956 	dns_rdata_t rdata, rdata1, rdata2;
   8957 	isc_result_t result;
   8958 
   8959 	dns_rdata_init(&rdata);
   8960 	dns_rdata_init(&rdata1);
   8961 	dns_rdata_init(&rdata2);
   8962 
   8963 	result = normalize_key(rr, &rdata1, data1, sizeof(data1));
   8964 	if (result != ISC_R_SUCCESS)
   8965 		return (ISC_FALSE);
   8966 
   8967 	for (result = dns_rdataset_first(rdset);
   8968 	     result == ISC_R_SUCCESS;
   8969 	     result = dns_rdataset_next(rdset)) {
   8970 		dns_rdata_reset(&rdata);
   8971 		dns_rdataset_current(rdset, &rdata);
   8972 		result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
   8973 		if (result != ISC_R_SUCCESS)
   8974 			continue;
   8975 		if (dns_rdata_compare(&rdata1, &rdata2) == 0)
   8976 			return (ISC_TRUE);
   8977 	}
   8978 
   8979 	return (ISC_FALSE);
   8980 }
   8981 
   8982 /*
   8983  * Calculate the refresh interval for a keydata zone, per
   8984  * RFC5011: MAX(1 hr,
   8985  *		MIN(15 days,
   8986  *		    1/2 * OrigTTL,
   8987  *		    1/2 * RRSigExpirationInterval))
   8988  * or for retries: MAX(1 hr,
   8989  *		       MIN(1 day,
   8990  *			   1/10 * OrigTTL,
   8991  *			   1/10 * RRSigExpirationInterval))
   8992  */
   8993 static inline isc_stdtime_t
   8994 refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
   8995 	isc_result_t result;
   8996 	isc_uint32_t t;
   8997 	dns_rdataset_t *rdset;
   8998 	dns_rdata_t sigrr = DNS_RDATA_INIT;
   8999 	dns_rdata_sig_t sig;
   9000 	isc_stdtime_t now;
   9001 
   9002 	isc_stdtime_get(&now);
   9003 
   9004 	if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
   9005 		rdset = &kfetch->dnskeysigset;
   9006 	else
   9007 		return (now + dns_zone_mkey_hour);
   9008 
   9009 	result = dns_rdataset_first(rdset);
   9010 	if (result != ISC_R_SUCCESS)
   9011 		return (now + dns_zone_mkey_hour);
   9012 
   9013 	dns_rdataset_current(rdset, &sigrr);
   9014 	result = dns_rdata_tostruct(&sigrr, &sig, NULL);
   9015 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9016 
   9017 	if (!retry) {
   9018 		t = sig.originalttl / 2;
   9019 
   9020 		if (isc_serial_gt(sig.timeexpire, now)) {
   9021 			isc_uint32_t exp = (sig.timeexpire - now) / 2;
   9022 			if (t > exp)
   9023 				t = exp;
   9024 		}
   9025 
   9026 		if (t > (15 * dns_zone_mkey_day))
   9027 			t = (15 * dns_zone_mkey_day);
   9028 
   9029 		if (t < dns_zone_mkey_hour)
   9030 			t = dns_zone_mkey_hour;
   9031 	} else {
   9032 		t = sig.originalttl / 10;
   9033 
   9034 		if (isc_serial_gt(sig.timeexpire, now)) {
   9035 			isc_uint32_t exp = (sig.timeexpire - now) / 10;
   9036 			if (t > exp)
   9037 				t = exp;
   9038 		}
   9039 
   9040 		if (t > dns_zone_mkey_day)
   9041 			t = dns_zone_mkey_day;
   9042 
   9043 		if (t < dns_zone_mkey_hour)
   9044 			t = dns_zone_mkey_hour;
   9045 	}
   9046 
   9047 	return (now + t);
   9048 }
   9049 
   9050 /*
   9051  * This routine is called when no changes are needed in a KEYDATA
   9052  * record except to simply update the refresh timer.  Caller should
   9053  * hold zone lock.
   9054  */
   9055 static isc_result_t
   9056 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
   9057 {
   9058 	isc_result_t result;
   9059 	isc_buffer_t keyb;
   9060 	unsigned char key_buf[4096];
   9061 	dns_rdata_t rdata = DNS_RDATA_INIT;
   9062 	dns_rdata_keydata_t keydata;
   9063 	dns_name_t *name;
   9064 	dns_zone_t *zone = kfetch->zone;
   9065 	isc_stdtime_t now;
   9066 
   9067 	name = dns_fixedname_name(&kfetch->name);
   9068 	isc_stdtime_get(&now);
   9069 
   9070 	for (result = dns_rdataset_first(&kfetch->keydataset);
   9071 	     result == ISC_R_SUCCESS;
   9072 	     result = dns_rdataset_next(&kfetch->keydataset)) {
   9073 		dns_rdata_reset(&rdata);
   9074 		dns_rdataset_current(&kfetch->keydataset, &rdata);
   9075 
   9076 		/* Delete old version */
   9077 		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
   9078 				    name, 0, &rdata));
   9079 
   9080 		/* Update refresh timer */
   9081 		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
   9082 		if (result == ISC_R_UNEXPECTEDEND)
   9083 			continue;
   9084 		if (result != ISC_R_SUCCESS)
   9085 			goto failure;
   9086 		keydata.refresh = refresh_time(kfetch, ISC_TRUE);
   9087 		set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
   9088 
   9089 		dns_rdata_reset(&rdata);
   9090 		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   9091 		CHECK(dns_rdata_fromstruct(&rdata,
   9092 					   zone->rdclass, dns_rdatatype_keydata,
   9093 					   &keydata, &keyb));
   9094 
   9095 		/* Insert updated version */
   9096 		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
   9097 				    name, 0, &rdata));
   9098 	}
   9099 	result = ISC_R_SUCCESS;
   9100   failure:
   9101 	return (result);
   9102 }
   9103 
   9104 /*
   9105  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
   9106  */
   9107 static isc_boolean_t
   9108 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
   9109 	isc_result_t result;
   9110 	dns_name_t *keyname;
   9111 	isc_mem_t *mctx;
   9112 	dns_rdata_t sigrr = DNS_RDATA_INIT;
   9113 	dns_rdata_t rr = DNS_RDATA_INIT;
   9114 	dns_rdata_rrsig_t sig;
   9115 	dns_rdata_dnskey_t dnskey;
   9116 	dst_key_t *dstkey = NULL;
   9117 	unsigned char key_buf[4096];
   9118 	isc_buffer_t keyb;
   9119 	isc_boolean_t answer = ISC_FALSE;
   9120 
   9121 	REQUIRE(kfetch != NULL && keydata != NULL);
   9122 	REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
   9123 
   9124 	keyname = dns_fixedname_name(&kfetch->name);
   9125 	mctx = kfetch->zone->view->mctx;
   9126 
   9127 	/* Generate a key from keydata */
   9128 	isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   9129 	dns_keydata_todnskey(keydata, &dnskey, NULL);
   9130 	dns_rdata_fromstruct(&rr, keydata->common.rdclass,
   9131 			     dns_rdatatype_dnskey, &dnskey, &keyb);
   9132 	result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
   9133 	if (result != ISC_R_SUCCESS)
   9134 		return (ISC_FALSE);
   9135 
   9136 	/* See if that key generated any of the signatures */
   9137 	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
   9138 	     result == ISC_R_SUCCESS;
   9139 	     result = dns_rdataset_next(&kfetch->dnskeysigset))
   9140 	{
   9141 		dns_fixedname_t fixed;
   9142 		dns_fixedname_init(&fixed);
   9143 
   9144 		dns_rdata_reset(&sigrr);
   9145 		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
   9146 		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
   9147 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9148 
   9149 		if (dst_key_alg(dstkey) == sig.algorithm &&
   9150 		    dst_key_rid(dstkey) == sig.keyid)
   9151 		{
   9152 			result = dns_dnssec_verify2(keyname,
   9153 					    &kfetch->dnskeyset,
   9154 					    dstkey, ISC_FALSE, mctx, &sigrr,
   9155 					    dns_fixedname_name(&fixed));
   9156 
   9157 			dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
   9158 				     "Confirm revoked DNSKEY is self-signed: "
   9159 				     "%s", dns_result_totext(result));
   9160 
   9161 			if (result == ISC_R_SUCCESS) {
   9162 				answer = ISC_TRUE;
   9163 				break;
   9164 			}
   9165 		}
   9166 	}
   9167 
   9168 	dst_key_free(&dstkey);
   9169 	return (answer);
   9170 }
   9171 
   9172 /*
   9173  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
   9174  * anchors are being managed; scan the keyset, and update the key zone and the
   9175  * local trust anchors according to RFC5011.
   9176  */
   9177 static void
   9178 keyfetch_done(isc_task_t *task, isc_event_t *event) {
   9179 	isc_result_t result, eresult;
   9180 	dns_fetchevent_t *devent;
   9181 	dns_keyfetch_t *kfetch;
   9182 	dns_zone_t *zone;
   9183 	isc_mem_t *mctx = NULL;
   9184 	dns_keytable_t *secroots = NULL;
   9185 	dns_dbversion_t *ver = NULL;
   9186 	dns_diff_t diff;
   9187 	isc_boolean_t alldone = ISC_FALSE;
   9188 	isc_boolean_t commit = ISC_FALSE;
   9189 	dns_name_t *keyname;
   9190 	dns_rdata_t sigrr = DNS_RDATA_INIT;
   9191 	dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
   9192 	dns_rdata_t keydatarr = DNS_RDATA_INIT;
   9193 	dns_rdata_rrsig_t sig;
   9194 	dns_rdata_dnskey_t dnskey;
   9195 	dns_rdata_keydata_t keydata;
   9196 	isc_boolean_t initializing;
   9197 	char namebuf[DNS_NAME_FORMATSIZE];
   9198 	unsigned char key_buf[4096];
   9199 	isc_buffer_t keyb;
   9200 	dst_key_t *dstkey;
   9201 	isc_stdtime_t now;
   9202 	int pending = 0;
   9203 	isc_boolean_t secure = ISC_FALSE, initial = ISC_FALSE;
   9204 	isc_boolean_t free_needed;
   9205 
   9206 	UNUSED(task);
   9207 	INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
   9208 	INSIST(event->ev_arg != NULL);
   9209 
   9210 	kfetch = event->ev_arg;
   9211 	zone = kfetch->zone;
   9212 	isc_mem_attach(zone->mctx, &mctx);
   9213 	keyname = dns_fixedname_name(&kfetch->name);
   9214 
   9215 	devent = (dns_fetchevent_t *) event;
   9216 	eresult = devent->result;
   9217 
   9218 	/* Free resources which are not of interest */
   9219 	if (devent->node != NULL)
   9220 		dns_db_detachnode(devent->db, &devent->node);
   9221 	if (devent->db != NULL)
   9222 		dns_db_detach(&devent->db);
   9223 	isc_event_free(&event);
   9224 	dns_resolver_destroyfetch(&kfetch->fetch);
   9225 
   9226 	LOCK_ZONE(zone);
   9227 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
   9228 		goto cleanup;
   9229 
   9230 	isc_stdtime_get(&now);
   9231 	dns_name_format(keyname, namebuf, sizeof(namebuf));
   9232 
   9233 	result = dns_view_getsecroots(zone->view, &secroots);
   9234 	INSIST(result == ISC_R_SUCCESS);
   9235 
   9236 	dns_diff_init(mctx, &diff);
   9237 
   9238 	CHECK(dns_db_newversion(kfetch->db, &ver));
   9239 
   9240 	zone->refreshkeycount--;
   9241 	alldone = ISC_TF(zone->refreshkeycount == 0);
   9242 
   9243 	if (alldone)
   9244 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
   9245 
   9246 	dns_zone_log(zone, ISC_LOG_DEBUG(3),
   9247 		     "Returned from key fetch in keyfetch_done() for "
   9248 		     "'%s': %s", namebuf, dns_result_totext(eresult));
   9249 
   9250 	/* Fetch failed */
   9251 	if (eresult != ISC_R_SUCCESS ||
   9252 	    !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
   9253 		dns_zone_log(zone, ISC_LOG_WARNING,
   9254 			     "Unable to fetch DNSKEY set "
   9255 			     "'%s': %s", namebuf, dns_result_totext(eresult));
   9256 		CHECK(minimal_update(kfetch, ver, &diff));
   9257 		goto done;
   9258 	}
   9259 
   9260 	/* No RRSIGs found */
   9261 	if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
   9262 		dns_zone_log(zone, ISC_LOG_WARNING,
   9263 			     "No DNSKEY RRSIGs found for "
   9264 			     "'%s': %s", namebuf, dns_result_totext(eresult));
   9265 		CHECK(minimal_update(kfetch, ver, &diff));
   9266 		goto done;
   9267 	}
   9268 
   9269 	/*
   9270 	 * Clear any cached trust level, as we need to run validation
   9271 	 * over again; trusted keys might have changed.
   9272 	 */
   9273 	kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none;
   9274 
   9275 	/*
   9276 	 * Validate the dnskeyset against the current trusted keys.
   9277 	 */
   9278 	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
   9279 	     result == ISC_R_SUCCESS;
   9280 	     result = dns_rdataset_next(&kfetch->dnskeysigset))
   9281 	{
   9282 		dns_keynode_t *keynode = NULL;
   9283 
   9284 		dns_rdata_reset(&sigrr);
   9285 		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
   9286 		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
   9287 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9288 
   9289 		result = dns_keytable_find(secroots, keyname, &keynode);
   9290 		while (result == ISC_R_SUCCESS) {
   9291 			dns_keynode_t *nextnode = NULL;
   9292 			dns_fixedname_t fixed;
   9293 			dns_fixedname_init(&fixed);
   9294 
   9295 			dstkey = dns_keynode_key(keynode);
   9296 			if (dstkey == NULL) /* fail_secure() was called */
   9297 				break;
   9298 
   9299 			if (dst_key_alg(dstkey) == sig.algorithm &&
   9300 			    dst_key_id(dstkey) == sig.keyid)
   9301 			{
   9302 				result = dns_dnssec_verify2(keyname,
   9303 						    &kfetch->dnskeyset,
   9304 						    dstkey, ISC_FALSE,
   9305 						    zone->view->mctx, &sigrr,
   9306 						    dns_fixedname_name(&fixed));
   9307 
   9308 				dns_zone_log(zone, ISC_LOG_DEBUG(3),
   9309 					     "Verifying DNSKEY set for zone "
   9310 					     "'%s' using key %d/%d: %s",
   9311 					     namebuf, sig.keyid, sig.algorithm,
   9312 					     dns_result_totext(result));
   9313 
   9314 				if (result == ISC_R_SUCCESS) {
   9315 					kfetch->dnskeyset.trust =
   9316 						dns_trust_secure;
   9317 					kfetch->dnskeysigset.trust =
   9318 						dns_trust_secure;
   9319 					secure = ISC_TRUE;
   9320 					initial = dns_keynode_initial(keynode);
   9321 					dns_keynode_trust(keynode);
   9322 					break;
   9323 				}
   9324 			}
   9325 
   9326 			result = dns_keytable_nextkeynode(secroots,
   9327 							  keynode, &nextnode);
   9328 			dns_keytable_detachkeynode(secroots, &keynode);
   9329 			keynode = nextnode;
   9330 		}
   9331 
   9332 		if (keynode != NULL) {
   9333 			dns_keytable_detachkeynode(secroots, &keynode);
   9334 		}
   9335 
   9336 		if (secure) {
   9337 			break;
   9338 		}
   9339 	}
   9340 
   9341 	/*
   9342 	 * If we were not able to verify the answer using the current
   9343 	 * trusted keys then all we can do is look at any revoked keys.
   9344 	 */
   9345 	if (!secure) {
   9346 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   9347 			     "DNSKEY set for zone '%s' could not be verified "
   9348 			     "with current keys", namebuf);
   9349 	}
   9350 
   9351 	/*
   9352 	 * First scan keydataset to find keys that are not in dnskeyset
   9353 	 *   - Missing keys which are not scheduled for removal,
   9354 	 *     log a warning
   9355 	 *   - Missing keys which are scheduled for removal and
   9356 	 *     the remove hold-down timer has completed should
   9357 	 *     be removed from the key zone
   9358 	 *   - Missing keys whose acceptance timers have not yet
   9359 	 *     completed, log a warning and reset the acceptance
   9360 	 *     timer to 30 days in the future
   9361 	 *   - All keys not being removed have their refresh timers
   9362 	 *     updated
   9363 	 */
   9364 	initializing = ISC_TRUE;
   9365 	for (result = dns_rdataset_first(&kfetch->keydataset);
   9366 	     result == ISC_R_SUCCESS;
   9367 	     result = dns_rdataset_next(&kfetch->keydataset))
   9368 	{
   9369 		dns_keytag_t keytag;
   9370 
   9371 		dns_rdata_reset(&keydatarr);
   9372 		dns_rdataset_current(&kfetch->keydataset, &keydatarr);
   9373 		result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
   9374 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9375 
   9376 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
   9377 		result = compute_tag(keyname, &dnskey, mctx, &keytag);
   9378 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9379 
   9380 		/*
   9381 		 * If any keydata record has a nonzero add holddown, then
   9382 		 * there was a pre-existing trust anchor for this domain;
   9383 		 * that means we are *not* initializing it and shouldn't
   9384 		 * automatically trust all the keys we find at the zone apex.
   9385 		 */
   9386 		initializing = initializing && ISC_TF(keydata.addhd == 0);
   9387 
   9388 		if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
   9389 			isc_boolean_t deletekey = ISC_FALSE;
   9390 
   9391 			if (!secure) {
   9392 				if (keydata.removehd != 0 &&
   9393 				    keydata.removehd <= now) {
   9394 					deletekey = ISC_TRUE;
   9395 				}
   9396 			} else if (keydata.addhd == 0) {
   9397 				deletekey = ISC_TRUE;
   9398 			} else if (keydata.addhd > now) {
   9399 				dns_zone_log(zone, ISC_LOG_DEBUG(3),
   9400 					     "Pending key %d for zone %s "
   9401 					     "unexpectedly missing "
   9402 					     "restarting 30-day acceptance "
   9403 					     "timer", keytag, namebuf);
   9404 				if (keydata.addhd < now + dns_zone_mkey_month)
   9405 					keydata.addhd =
   9406 						now + dns_zone_mkey_month;
   9407 				keydata.refresh = refresh_time(kfetch,
   9408 							       ISC_FALSE);
   9409 			} else if (keydata.removehd == 0) {
   9410 				dns_zone_log(zone, ISC_LOG_DEBUG(3),
   9411 					     "Active key %d for zone %s "
   9412 					     "unexpectedly missing",
   9413 					     keytag, namebuf);
   9414 				keydata.refresh = now + dns_zone_mkey_hour;
   9415 			} else if (keydata.removehd <= now) {
   9416 				deletekey = ISC_TRUE;
   9417 				dns_zone_log(zone, ISC_LOG_DEBUG(3),
   9418 					     "Revoked key %d for zone %s "
   9419 					     "missing: deleting from "
   9420 					     "managed keys database",
   9421 					     keytag, namebuf);
   9422 			} else {
   9423 				keydata.refresh = refresh_time(kfetch,
   9424 							       ISC_FALSE);
   9425 			}
   9426 
   9427 			if (secure || deletekey) {
   9428 				/* Delete old version */
   9429 				CHECK(update_one_rr(kfetch->db, ver, &diff,
   9430 						    DNS_DIFFOP_DEL, keyname, 0,
   9431 						    &keydatarr));
   9432 			}
   9433 
   9434 			if (!secure || deletekey)
   9435 				continue;
   9436 
   9437 			dns_rdata_reset(&keydatarr);
   9438 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   9439 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
   9440 					     dns_rdatatype_keydata,
   9441 					     &keydata, &keyb);
   9442 
   9443 			/* Insert updated version */
   9444 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   9445 					    DNS_DIFFOP_ADD, keyname, 0,
   9446 					    &keydatarr));
   9447 
   9448 			set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
   9449 		}
   9450 	}
   9451 
   9452 	/*
   9453 	 * Next scan dnskeyset:
   9454 	 *   - If new keys are found (i.e., lacking a match in keydataset)
   9455 	 *     add them to the key zone and set the acceptance timer
   9456 	 *     to 30 days in the future (or to immediately if we've
   9457 	 *     determined that we're initializing the zone for the
   9458 	 *     first time)
   9459 	 *   - Previously-known keys that have been revoked
   9460 	 *     must be scheduled for removal from the key zone (or,
   9461 	 *     if they hadn't been accepted as trust anchors yet
   9462 	 *     anyway, removed at once)
   9463 	 *   - Previously-known unrevoked keys whose acceptance timers
   9464 	 *     have completed are promoted to trust anchors
   9465 	 *   - All keys not being removed have their refresh
   9466 	 *     timers updated
   9467 	 */
   9468 	for (result = dns_rdataset_first(&kfetch->dnskeyset);
   9469 	     result == ISC_R_SUCCESS;
   9470 	     result = dns_rdataset_next(&kfetch->dnskeyset))
   9471 	{
   9472 		isc_boolean_t revoked = ISC_FALSE;
   9473 		isc_boolean_t newkey = ISC_FALSE;
   9474 		isc_boolean_t updatekey = ISC_FALSE;
   9475 		isc_boolean_t deletekey = ISC_FALSE;
   9476 		isc_boolean_t trustkey = ISC_FALSE;
   9477 		dns_keytag_t keytag;
   9478 
   9479 		dns_rdata_reset(&dnskeyrr);
   9480 		dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
   9481 		result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
   9482 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9483 
   9484 		/* Skip ZSK's */
   9485 		if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
   9486 			continue;
   9487 
   9488 		result = compute_tag(keyname, &dnskey, mctx, &keytag);
   9489 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9490 
   9491 		revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
   9492 
   9493 		if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
   9494 			dns_rdata_reset(&keydatarr);
   9495 			dns_rdataset_current(&kfetch->keydataset, &keydatarr);
   9496 			result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
   9497 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9498 
   9499 			if (revoked && revocable(kfetch, &keydata)) {
   9500 				if (keydata.addhd > now) {
   9501 					/*
   9502 					 * Key wasn't trusted yet, and now
   9503 					 * it's been revoked?  Just remove it
   9504 					 */
   9505 					deletekey = ISC_TRUE;
   9506 					dns_zone_log(zone, ISC_LOG_DEBUG(3),
   9507 						     "Pending key %d "
   9508 						     "for zone %s is now "
   9509 						     "revoked: "
   9510 						     "deleting from the "
   9511 						     "managed keys database",
   9512 						     keytag, namebuf);
   9513 				} else if (keydata.removehd == 0) {
   9514 					/*
   9515 					 * Remove key from secroots.
   9516 					 */
   9517 					dns_view_untrust(zone->view, keyname,
   9518 							 &dnskey, mctx);
   9519 
   9520 					/* If initializing, delete now */
   9521 					if (keydata.addhd == 0)
   9522 						deletekey = ISC_TRUE;
   9523 					else {
   9524 						keydata.removehd = now +
   9525 							dns_zone_mkey_month;
   9526 						keydata.flags |=
   9527 							DNS_KEYFLAG_REVOKE;
   9528 					}
   9529 
   9530 					dns_zone_log(zone, ISC_LOG_INFO,
   9531 						     "Trusted key %d "
   9532 						     "for zone %s is now "
   9533 						     "revoked",
   9534 						     keytag, namebuf);
   9535 				} else if (keydata.removehd < now) {
   9536 					/* Scheduled for removal */
   9537 					deletekey = ISC_TRUE;
   9538 
   9539 					dns_zone_log(zone, ISC_LOG_INFO,
   9540 						     "Revoked key %d "
   9541 						     "for zone %s removal "
   9542 						     "timer complete: "
   9543 						     "deleting from the "
   9544 						     "managed keys database",
   9545 						     keytag, namebuf);
   9546 				}
   9547 			} else if (revoked && keydata.removehd == 0) {
   9548 				dns_zone_log(zone, ISC_LOG_WARNING,
   9549 					     "Active key %d for zone "
   9550 					     "%s is revoked but "
   9551 					     "did not self-sign; "
   9552 					     "ignoring", keytag, namebuf);
   9553 					continue;
   9554 			} else if (secure) {
   9555 				if (keydata.removehd != 0) {
   9556 					/*
   9557 					 * Key isn't revoked--but it
   9558 					 * seems it used to be.
   9559 					 * Remove it now and add it
   9560 					 * back as if it were a fresh key,
   9561 					 * with a 30-day acceptance timer.
   9562 					 */
   9563 					deletekey = ISC_TRUE;
   9564 					newkey = ISC_TRUE;
   9565 					keydata.removehd = 0;
   9566 					keydata.addhd =
   9567 						now + dns_zone_mkey_month;
   9568 
   9569 					dns_zone_log(zone, ISC_LOG_DEBUG(3),
   9570 						     "Revoked key %d "
   9571 						     "for zone %s "
   9572 						     "has returned: starting "
   9573 						     "30-day acceptance timer",
   9574 						     keytag, namebuf);
   9575 				} else if (keydata.addhd > now)
   9576 					pending++;
   9577 				else if (keydata.addhd == 0)
   9578 					keydata.addhd = now;
   9579 
   9580 				if (keydata.addhd <= now) {
   9581 					trustkey = ISC_TRUE;
   9582 					dns_zone_log(zone, ISC_LOG_INFO,
   9583 						     "Key %d for zone %s "
   9584 						     "is now trusted (%s)",
   9585 						     keytag, namebuf,
   9586 						     initial
   9587 						      ? "initializing key "
   9588 							"verified"
   9589 						      : "acceptance timer "
   9590 							"complete");
   9591 				}
   9592 			} else if (keydata.addhd > now) {
   9593 				/*
   9594 				 * Not secure, and key is pending:
   9595 				 * reset the acceptance timer
   9596 				 */
   9597 				pending++;
   9598 				keydata.addhd = now + dns_zone_mkey_month;
   9599 				dns_zone_log(zone, ISC_LOG_DEBUG(3),
   9600 					     "Pending key %d "
   9601 					     "for zone %s was "
   9602 					     "not validated: restarting "
   9603 					     "30-day acceptance timer",
   9604 					     keytag, namebuf);
   9605 			}
   9606 
   9607 			if (!deletekey && !newkey)
   9608 				updatekey = ISC_TRUE;
   9609 		} else if (secure) {
   9610 			/*
   9611 			 * Key wasn't in the key zone but it's
   9612 			 * revoked now anyway, so just skip it
   9613 			 */
   9614 			if (revoked)
   9615 				continue;
   9616 
   9617 			/* Key wasn't in the key zone: add it */
   9618 			newkey = ISC_TRUE;
   9619 
   9620 			if (initializing) {
   9621 				dns_zone_log(zone, ISC_LOG_WARNING,
   9622 					     "Initializing automatic trust "
   9623 					     "anchor management for zone '%s'; "
   9624 					     "DNSKEY ID %d is now trusted, "
   9625 					     "waiving the normal 30-day "
   9626 					     "waiting period.",
   9627 					     namebuf, keytag);
   9628 				trustkey = ISC_TRUE;
   9629 			} else {
   9630 				dns_zone_log(zone, ISC_LOG_INFO,
   9631 					     "New key %d observed "
   9632 					     "for zone '%s': "
   9633 					     "starting 30-day "
   9634 					     "acceptance timer",
   9635 					     keytag, namebuf);
   9636 			}
   9637 		} else {
   9638 			/*
   9639 			 * No previously known key, and the key is not
   9640 			 * secure, so skip it.
   9641 			 */
   9642 			continue;
   9643 		}
   9644 
   9645 		/* Delete old version */
   9646 		if (deletekey || !newkey)
   9647 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   9648 					    DNS_DIFFOP_DEL, keyname, 0,
   9649 					    &keydatarr));
   9650 
   9651 		if (updatekey) {
   9652 			/* Set refresh timer */
   9653 			keydata.refresh = refresh_time(kfetch, ISC_FALSE);
   9654 			dns_rdata_reset(&keydatarr);
   9655 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   9656 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
   9657 					     dns_rdatatype_keydata,
   9658 					     &keydata, &keyb);
   9659 
   9660 			/* Insert updated version */
   9661 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   9662 					    DNS_DIFFOP_ADD, keyname, 0,
   9663 					    &keydatarr));
   9664 		} else if (newkey) {
   9665 			/* Convert DNSKEY to KEYDATA */
   9666 			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
   9667 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9668 			dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
   9669 					       NULL);
   9670 			keydata.addhd = initializing
   9671 					 ? now : now + dns_zone_mkey_month;
   9672 			keydata.refresh = refresh_time(kfetch, ISC_FALSE);
   9673 			dns_rdata_reset(&keydatarr);
   9674 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
   9675 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
   9676 					     dns_rdatatype_keydata,
   9677 					     &keydata, &keyb);
   9678 
   9679 			/* Insert into key zone */
   9680 			CHECK(update_one_rr(kfetch->db, ver, &diff,
   9681 					    DNS_DIFFOP_ADD, keyname, 0,
   9682 					    &keydatarr));
   9683 		}
   9684 
   9685 		if (trustkey) {
   9686 			/* Trust this key. */
   9687 			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
   9688 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9689 			trust_key(zone, keyname, &dnskey, ISC_FALSE, mctx);
   9690 		}
   9691 
   9692 		if (secure && !deletekey) {
   9693 			INSIST(newkey || updatekey);
   9694 			set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
   9695 		}
   9696 	}
   9697 
   9698 	/*
   9699 	 * RFC5011 says, "A trust point that has all of its trust anchors
   9700 	 * revoked is considered deleted and is treated as if the trust
   9701 	 * point was never configured."  But if someone revoked their
   9702 	 * active key before the standby was trusted, that would mean the
   9703 	 * zone would suddenly be nonsecured.  We avoid this by checking to
   9704 	 * see if there's pending keydata.  If so, we put a null key in
   9705 	 * the security roots; then all queries to the zone will fail.
   9706 	 */
   9707 	if (pending != 0)
   9708 		fail_secure(zone, keyname);
   9709 
   9710  done:
   9711 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   9712 		/* Write changes to journal file. */
   9713 		CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
   9714 					zone->updatemethod));
   9715 		CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
   9716 		commit = ISC_TRUE;
   9717 
   9718 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   9719 		zone_needdump(zone, 30);
   9720 	} else if (result == ISC_R_NOMORE) {
   9721 		/*
   9722 		 * If "updatekey" was true for all keys found in the DNSKEY
   9723 		 * response and the previous update of those keys happened
   9724 		 * during the same second (only possible if a key refresh was
   9725 		 * externally triggered), it may happen that all relevant
   9726 		 * update_one_rr() calls will return ISC_R_SUCCESS, but
   9727 		 * diff.tuples will remain empty.  Reset result to
   9728 		 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
   9729 		 */
   9730 		result = ISC_R_SUCCESS;
   9731 	}
   9732 
   9733  failure:
   9734 	if (result != ISC_R_SUCCESS) {
   9735 		dns_zone_log(zone, ISC_LOG_ERROR,
   9736 			     "error during managed-keys processing (%s): "
   9737 			     "DNSSEC validation may be at risk",
   9738 			     isc_result_totext(result));
   9739 	}
   9740 	dns_diff_clear(&diff);
   9741 	if (ver != NULL)
   9742 		dns_db_closeversion(kfetch->db, &ver, commit);
   9743 
   9744  cleanup:
   9745 	dns_db_detach(&kfetch->db);
   9746 
   9747 	INSIST(zone->irefs > 0);
   9748 	zone->irefs--;
   9749 	kfetch->zone = NULL;
   9750 
   9751 	if (dns_rdataset_isassociated(&kfetch->keydataset))
   9752 		dns_rdataset_disassociate(&kfetch->keydataset);
   9753 	if (dns_rdataset_isassociated(&kfetch->dnskeyset))
   9754 		dns_rdataset_disassociate(&kfetch->dnskeyset);
   9755 	if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
   9756 		dns_rdataset_disassociate(&kfetch->dnskeysigset);
   9757 
   9758 	dns_name_free(keyname, mctx);
   9759 	isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
   9760 	isc_mem_detach(&mctx);
   9761 
   9762 	if (secroots != NULL)
   9763 		dns_keytable_detach(&secroots);
   9764 
   9765 	free_needed = exit_check(zone);
   9766 	UNLOCK_ZONE(zone);
   9767 	if (free_needed)
   9768 		zone_free(zone);
   9769 
   9770 	INSIST(ver == NULL);
   9771 }
   9772 
   9773 /*
   9774  * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
   9775  * records from the zone apex.
   9776  */
   9777 static void
   9778 zone_refreshkeys(dns_zone_t *zone) {
   9779 	const char me[] = "zone_refreshkeys";
   9780 	isc_result_t result;
   9781 	dns_rriterator_t rrit;
   9782 	dns_db_t *db = NULL;
   9783 	dns_dbversion_t *ver = NULL;
   9784 	dns_diff_t diff;
   9785 	dns_rdata_t rdata = DNS_RDATA_INIT;
   9786 	dns_rdata_keydata_t kd;
   9787 	isc_stdtime_t now;
   9788 	isc_boolean_t commit = ISC_FALSE;
   9789 	isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
   9790 
   9791 	ENTER;
   9792 	REQUIRE(zone->db != NULL);
   9793 
   9794 	isc_stdtime_get(&now);
   9795 
   9796 	LOCK_ZONE(zone);
   9797 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   9798 		isc_time_settoepoch(&zone->refreshkeytime);
   9799 		UNLOCK_ZONE(zone);
   9800 		return;
   9801 	}
   9802 
   9803 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   9804 	dns_db_attach(zone->db, &db);
   9805 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   9806 
   9807 	dns_diff_init(zone->mctx, &diff);
   9808 
   9809 	CHECK(dns_db_newversion(db, &ver));
   9810 
   9811 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
   9812 
   9813 	dns_rriterator_init(&rrit, db, ver, 0);
   9814 	for (result = dns_rriterator_first(&rrit);
   9815 	     result == ISC_R_SUCCESS;
   9816 	     result = dns_rriterator_nextrrset(&rrit)) {
   9817 		isc_stdtime_t timer = 0xffffffff;
   9818 		dns_name_t *name = NULL, *kname = NULL;
   9819 		dns_rdataset_t *kdset = NULL;
   9820 		dns_keyfetch_t *kfetch;
   9821 		isc_uint32_t ttl;
   9822 
   9823 		dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
   9824 		if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
   9825 		    !dns_rdataset_isassociated(kdset))
   9826 			continue;
   9827 
   9828 		/*
   9829 		 * Scan the stored keys looking for ones that need
   9830 		 * removal or refreshing
   9831 		 */
   9832 		for (result = dns_rdataset_first(kdset);
   9833 		     result == ISC_R_SUCCESS;
   9834 		     result = dns_rdataset_next(kdset)) {
   9835 			dns_rdata_reset(&rdata);
   9836 			dns_rdataset_current(kdset, &rdata);
   9837 			result = dns_rdata_tostruct(&rdata, &kd, NULL);
   9838 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   9839 
   9840 			/* Removal timer expired? */
   9841 			if (kd.removehd != 0 && kd.removehd < now) {
   9842 				CHECK(update_one_rr(db, ver, &diff,
   9843 						    DNS_DIFFOP_DEL, name, ttl,
   9844 						    &rdata));
   9845 				continue;
   9846 			}
   9847 
   9848 			/* Acceptance timer expired? */
   9849 			if (kd.addhd <= now)
   9850 				timer = kd.addhd;
   9851 
   9852 			/* Or do we just need to refresh the keyset? */
   9853 			if (timer > kd.refresh)
   9854 				timer = kd.refresh;
   9855 		}
   9856 
   9857 		if (timer > now)
   9858 			continue;
   9859 
   9860 		kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
   9861 		if (kfetch == NULL) {
   9862 			fetch_err = ISC_TRUE;
   9863 			goto failure;
   9864 		}
   9865 
   9866 		zone->refreshkeycount++;
   9867 		kfetch->zone = zone;
   9868 		zone->irefs++;
   9869 		INSIST(zone->irefs != 0);
   9870 		kname = dns_fixedname_initname(&kfetch->name);
   9871 		dns_name_dup(name, zone->mctx, kname);
   9872 		dns_rdataset_init(&kfetch->dnskeyset);
   9873 		dns_rdataset_init(&kfetch->dnskeysigset);
   9874 		dns_rdataset_init(&kfetch->keydataset);
   9875 		dns_rdataset_clone(kdset, &kfetch->keydataset);
   9876 		kfetch->db = NULL;
   9877 		dns_db_attach(db, &kfetch->db);
   9878 		kfetch->fetch = NULL;
   9879 
   9880 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
   9881 			char namebuf[DNS_NAME_FORMATSIZE];
   9882 			dns_name_format(kname, namebuf,
   9883 					sizeof(namebuf));
   9884 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
   9885 				     "Creating key fetch in "
   9886 				     "zone_refreshkeys() for '%s'",
   9887 				     namebuf);
   9888 		}
   9889 
   9890 		/*
   9891 		 * Use of DNS_FETCHOPT_NOCACHED is essential here.  If it is
   9892 		 * not set and the cache still holds a non-expired, validated
   9893 		 * version of the RRset being queried for by the time the
   9894 		 * response is received, the cached RRset will be passed to
   9895 		 * keyfetch_done() instead of the one received in the response
   9896 		 * as the latter will have a lower trust level due to not being
   9897 		 * validated until keyfetch_done() is called.
   9898 		 */
   9899 
   9900 #ifdef ENABLE_AFL
   9901 		if (dns_fuzzing_resolver == ISC_FALSE) {
   9902 #endif
   9903 		result = dns_resolver_createfetch(zone->view->resolver,
   9904 						  kname, dns_rdatatype_dnskey,
   9905 						  NULL, NULL, NULL,
   9906 						  DNS_FETCHOPT_NOVALIDATE|
   9907 						  DNS_FETCHOPT_UNSHARED|
   9908 						  DNS_FETCHOPT_NOCACHED,
   9909 						  zone->task,
   9910 						  keyfetch_done, kfetch,
   9911 						  &kfetch->dnskeyset,
   9912 						  &kfetch->dnskeysigset,
   9913 						  &kfetch->fetch);
   9914 #ifdef ENABLE_AFL
   9915 		} else {
   9916 			result = ISC_R_FAILURE;
   9917 		}
   9918 #endif
   9919 		if (result == ISC_R_SUCCESS)
   9920 			fetching = ISC_TRUE;
   9921 		else {
   9922 			zone->refreshkeycount--;
   9923 			zone->irefs--;
   9924 			dns_db_detach(&kfetch->db);
   9925 			dns_rdataset_disassociate(&kfetch->keydataset);
   9926 			dns_name_free(kname, zone->mctx);
   9927 			isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
   9928 			dns_zone_log(zone, ISC_LOG_WARNING,
   9929 				     "Failed to create fetch for "
   9930 				     "DNSKEY update");
   9931 			fetch_err = ISC_TRUE;
   9932 		}
   9933 	}
   9934 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   9935 		CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
   9936 					zone->updatemethod));
   9937 		CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
   9938 		commit = ISC_TRUE;
   9939 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   9940 		zone_needdump(zone, 30);
   9941 	}
   9942 
   9943   failure:
   9944 	if (fetch_err) {
   9945 		/*
   9946 		 * Error during a key fetch; retry in an hour.
   9947 		 */
   9948 		isc_time_t timenow, timethen;
   9949 		char timebuf[80];
   9950 
   9951 		TIME_NOW(&timenow);
   9952 		DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
   9953 		zone->refreshkeytime = timethen;
   9954 		zone_settimer(zone, &timenow);
   9955 
   9956 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   9957 		dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
   9958 			     timebuf);
   9959 	}
   9960 
   9961 	if (!fetching)
   9962 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
   9963 
   9964 	dns_diff_clear(&diff);
   9965 	if (ver != NULL) {
   9966 		dns_rriterator_destroy(&rrit);
   9967 		dns_db_closeversion(db, &ver, commit);
   9968 	}
   9969 	dns_db_detach(&db);
   9970 
   9971 	UNLOCK_ZONE(zone);
   9972 
   9973 	INSIST(ver == NULL);
   9974 }
   9975 
   9976 static void
   9977 zone_maintenance(dns_zone_t *zone) {
   9978 	const char me[] = "zone_maintenance";
   9979 	isc_time_t now;
   9980 	isc_result_t result;
   9981 	isc_boolean_t dumping;
   9982 
   9983 	REQUIRE(DNS_ZONE_VALID(zone));
   9984 	ENTER;
   9985 
   9986 	/*
   9987 	 * Are we pending load/reload?
   9988 	 */
   9989 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
   9990 		return;
   9991 
   9992 	/*
   9993 	 * Configuring the view of this zone may have
   9994 	 * failed, for example because the config file
   9995 	 * had a syntax error.	In that case, the view
   9996 	 * adb or resolver will be NULL, and we had better not try
   9997 	 * to do further maintenance on it.
   9998 	 */
   9999 	if (zone->view == NULL || zone->view->adb == NULL)
   10000 		return;
   10001 
   10002 	TIME_NOW(&now);
   10003 
   10004 	/*
   10005 	 * Expire check.
   10006 	 */
   10007 	switch (zone->type) {
   10008 	case dns_zone_redirect:
   10009 		if (zone->masters == NULL)
   10010 			break;
   10011 		/* FALLTHROUGH */
   10012 	case dns_zone_slave:
   10013 	case dns_zone_stub:
   10014 		LOCK_ZONE(zone);
   10015 		if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
   10016 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   10017 			zone_expire(zone);
   10018 			zone->refreshtime = now;
   10019 		}
   10020 		UNLOCK_ZONE(zone);
   10021 		break;
   10022 	default:
   10023 		break;
   10024 	}
   10025 
   10026 	/*
   10027 	 * Up to date check.
   10028 	 */
   10029 	switch (zone->type) {
   10030 	case dns_zone_redirect:
   10031 		if (zone->masters == NULL)
   10032 			break;
   10033 		/* FALLTHROUGH */
   10034 	case dns_zone_slave:
   10035 	case dns_zone_stub:
   10036 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
   10037 		    isc_time_compare(&now, &zone->refreshtime) >= 0)
   10038 			dns_zone_refresh(zone);
   10039 		break;
   10040 	default:
   10041 		break;
   10042 	}
   10043 
   10044 	/*
   10045 	 * Slaves send notifies before backing up to disk, masters after.
   10046 	 */
   10047 	if (zone->type == dns_zone_slave &&
   10048 	    (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   10049 	     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
   10050 	    isc_time_compare(&now, &zone->notifytime) >= 0)
   10051 		zone_notify(zone, &now);
   10052 
   10053 	/*
   10054 	 * Do we need to consolidate the backing store?
   10055 	 */
   10056 	switch (zone->type) {
   10057 	case dns_zone_master:
   10058 	case dns_zone_slave:
   10059 	case dns_zone_key:
   10060 	case dns_zone_redirect:
   10061 	case dns_zone_stub:
   10062 		LOCK_ZONE(zone);
   10063 		if (zone->masterfile != NULL &&
   10064 		    isc_time_compare(&now, &zone->dumptime) >= 0 &&
   10065 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   10066 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
   10067 			dumping = was_dumping(zone);
   10068 		} else
   10069 			dumping = ISC_TRUE;
   10070 		UNLOCK_ZONE(zone);
   10071 		if (!dumping) {
   10072 			result = zone_dump(zone, ISC_TRUE); /* task locked */
   10073 			if (result != ISC_R_SUCCESS)
   10074 				dns_zone_log(zone, ISC_LOG_WARNING,
   10075 					     "dump failed: %s",
   10076 					     dns_result_totext(result));
   10077 		}
   10078 		break;
   10079 	default:
   10080 		break;
   10081 	}
   10082 
   10083 	/*
   10084 	 * Master/redirect zones send notifies now, if needed
   10085 	 */
   10086 	switch (zone->type) {
   10087 	case dns_zone_master:
   10088 	case dns_zone_redirect:
   10089 		if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   10090 		     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))&&
   10091 		    isc_time_compare(&now, &zone->notifytime) >= 0)
   10092 			zone_notify(zone, &now);
   10093 	default:
   10094 		break;
   10095 	}
   10096 
   10097 	/*
   10098 	 * Do we need to refresh keys?
   10099 	 */
   10100 	switch (zone->type) {
   10101 	case dns_zone_key:
   10102 		if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
   10103 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   10104 			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
   10105 				zone_refreshkeys(zone);
   10106 			}
   10107 		}
   10108 		break;
   10109 	case dns_zone_master:
   10110 		if (!isc_time_isepoch(&zone->refreshkeytime) &&
   10111 		    isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
   10112 		    zone->rss_event == NULL)
   10113 			zone_rekey(zone);
   10114 	default:
   10115 		break;
   10116 	}
   10117 
   10118 	switch (zone->type) {
   10119 	case dns_zone_master:
   10120 	case dns_zone_redirect:
   10121 	case dns_zone_slave:
   10122 		/*
   10123 		 * Do we need to sign/resign some RRsets?
   10124 		 */
   10125 		if (zone->rss_event != NULL)
   10126 			break;
   10127 		if (!isc_time_isepoch(&zone->signingtime) &&
   10128 		    isc_time_compare(&now, &zone->signingtime) >= 0)
   10129 			zone_sign(zone);
   10130 		else if (!isc_time_isepoch(&zone->resigntime) &&
   10131 		    isc_time_compare(&now, &zone->resigntime) >= 0)
   10132 			zone_resigninc(zone);
   10133 		else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
   10134 			isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
   10135 			zone_nsec3chain(zone);
   10136 		/*
   10137 		 * Do we need to issue a key expiry warning?
   10138 		 */
   10139 		if (!isc_time_isepoch(&zone->keywarntime) &&
   10140 		    isc_time_compare(&now, &zone->keywarntime) >= 0)
   10141 			set_key_expiry_warning(zone, zone->key_expiry,
   10142 					       isc_time_seconds(&now));
   10143 		break;
   10144 
   10145 	default:
   10146 		break;
   10147 	}
   10148 	zone_settimer(zone, &now);
   10149 }
   10150 
   10151 void
   10152 dns_zone_markdirty(dns_zone_t *zone) {
   10153 	isc_uint32_t serial;
   10154 	isc_result_t result = ISC_R_SUCCESS;
   10155 	dns_zone_t *secure = NULL;
   10156 
   10157 	/*
   10158 	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
   10159 	 * could result in a deadlock due to a LOR so we will spin if we
   10160 	 * can't obtain the both locks.
   10161 	 */
   10162  again:
   10163 	LOCK_ZONE(zone);
   10164 	if (zone->type == dns_zone_master) {
   10165 		if (inline_raw(zone)) {
   10166 			unsigned int soacount;
   10167 			secure = zone->secure;
   10168 			INSIST(secure != zone);
   10169 			TRYLOCK_ZONE(result, secure);
   10170 			if (result != ISC_R_SUCCESS) {
   10171 				UNLOCK_ZONE(zone);
   10172 				secure = NULL;
   10173 #ifdef ISC_PLATFORM_USETHREADS
   10174 				isc_thread_yield();
   10175 #endif
   10176 				goto again;
   10177 			}
   10178 
   10179 			ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   10180 			if (zone->db != NULL) {
   10181 				result = zone_get_from_db(zone, zone->db, NULL,
   10182 							  &soacount, &serial,
   10183 							  NULL, NULL, NULL,
   10184 							  NULL, NULL);
   10185 			} else
   10186 				result = DNS_R_NOTLOADED;
   10187 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   10188 			if (result == ISC_R_SUCCESS && soacount > 0U)
   10189 				zone_send_secureserial(zone, serial);
   10190 		}
   10191 
   10192 		/* XXXMPA make separate call back */
   10193 		if (result == ISC_R_SUCCESS)
   10194 			set_resigntime(zone);
   10195 	}
   10196 	if (secure != NULL)
   10197 		UNLOCK_ZONE(secure);
   10198 	zone_needdump(zone, DNS_DUMP_DELAY);
   10199 	UNLOCK_ZONE(zone);
   10200 }
   10201 
   10202 void
   10203 dns_zone_expire(dns_zone_t *zone) {
   10204 	REQUIRE(DNS_ZONE_VALID(zone));
   10205 
   10206 	LOCK_ZONE(zone);
   10207 	zone_expire(zone);
   10208 	UNLOCK_ZONE(zone);
   10209 }
   10210 
   10211 static void
   10212 zone_expire(dns_zone_t *zone) {
   10213 	/*
   10214 	 * 'zone' locked by caller.
   10215 	 */
   10216 
   10217 	REQUIRE(LOCKED_ZONE(zone));
   10218 
   10219 	dns_zone_log(zone, ISC_LOG_WARNING, "expired");
   10220 
   10221 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
   10222 	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
   10223 	zone->retry = DNS_ZONE_DEFAULTRETRY;
   10224 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   10225 	zone_unload(zone);
   10226 }
   10227 
   10228 void
   10229 dns_zone_refresh(dns_zone_t *zone) {
   10230 	isc_interval_t i;
   10231 	isc_uint32_t oldflags;
   10232 	unsigned int j;
   10233 	isc_result_t result;
   10234 
   10235 	REQUIRE(DNS_ZONE_VALID(zone));
   10236 
   10237 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
   10238 		return;
   10239 
   10240 	/*
   10241 	 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
   10242 	 * in progress at a time.
   10243 	 */
   10244 
   10245 	LOCK_ZONE(zone);
   10246 	oldflags = zone->flags;
   10247 	if (zone->masterscnt == 0) {
   10248 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
   10249 		if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
   10250 			dns_zone_log(zone, ISC_LOG_ERROR,
   10251 				     "cannot refresh: no masters");
   10252 		goto unlock;
   10253 	}
   10254 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
   10255 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
   10256 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
   10257 	if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
   10258 		goto unlock;
   10259 
   10260 	/*
   10261 	 * Set the next refresh time as if refresh check has failed.
   10262 	 * Setting this to the retry time will do that.  XXXMLG
   10263 	 * If we are successful it will be reset using zone->refresh.
   10264 	 */
   10265 	isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
   10266 			 0);
   10267 	result = isc_time_nowplusinterval(&zone->refreshtime, &i);
   10268 	if (result != ISC_R_SUCCESS)
   10269 		dns_zone_log(zone, ISC_LOG_WARNING,
   10270 			     "isc_time_nowplusinterval() failed: %s",
   10271 			     dns_result_totext(result));
   10272 
   10273 	/*
   10274 	 * When lacking user-specified timer values from the SOA,
   10275 	 * do exponential backoff of the retry time up to a
   10276 	 * maximum of six hours.
   10277 	 */
   10278 	if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
   10279 		zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
   10280 
   10281 	zone->curmaster = 0;
   10282 	for (j = 0; j < zone->masterscnt; j++)
   10283 		zone->mastersok[j] = ISC_FALSE;
   10284 	/* initiate soa query */
   10285 	queue_soa_query(zone);
   10286  unlock:
   10287 	UNLOCK_ZONE(zone);
   10288 }
   10289 
   10290 static void
   10291 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, isc_uint32_t serial) {
   10292 	isc_result_t result;
   10293 	isc_int32_t journalsize;
   10294 	dns_dbversion_t *ver = NULL;
   10295 	isc_uint64_t dbsize;
   10296 
   10297 	INSIST(LOCKED_ZONE(zone));
   10298 	if (inline_raw(zone))
   10299 		INSIST(LOCKED_ZONE(zone->secure));
   10300 
   10301 	journalsize = zone->journalsize;
   10302 	if (journalsize == -1) {
   10303 		journalsize = DNS_JOURNAL_SIZE_MAX;
   10304 		dns_db_currentversion(db, &ver);
   10305 		result = dns_db_getsize(db, ver, NULL, &dbsize);
   10306 		dns_db_closeversion(db, &ver, ISC_FALSE);
   10307 		if (result != ISC_R_SUCCESS) {
   10308 			dns_zone_log(zone, ISC_LOG_ERROR,
   10309 				     "zone_journal_compact: "
   10310 				     "could not get zone size: %s",
   10311 				     isc_result_totext(result));
   10312 		} else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
   10313 			journalsize = (isc_int32_t)dbsize * 2;
   10314 		}
   10315 	}
   10316 	zone_debuglog(zone, "zone_journal_compact", 1,
   10317 		      "target journal size %d", journalsize);
   10318 	result = dns_journal_compact(zone->mctx, zone->journal,
   10319 				     serial, journalsize);
   10320 	switch (result) {
   10321 	case ISC_R_SUCCESS:
   10322 	case ISC_R_NOSPACE:
   10323 	case ISC_R_NOTFOUND:
   10324 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   10325 			     "dns_journal_compact: %s",
   10326 			     dns_result_totext(result));
   10327 		break;
   10328 	default:
   10329 		dns_zone_log(zone, ISC_LOG_ERROR,
   10330 			     "dns_journal_compact failed: %s",
   10331 			     dns_result_totext(result));
   10332 		break;
   10333 	}
   10334 }
   10335 
   10336 isc_result_t
   10337 dns_zone_flush(dns_zone_t *zone) {
   10338 	isc_result_t result = ISC_R_SUCCESS;
   10339 	isc_boolean_t dumping;
   10340 
   10341 	REQUIRE(DNS_ZONE_VALID(zone));
   10342 
   10343 	LOCK_ZONE(zone);
   10344 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
   10345 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   10346 	    zone->masterfile != NULL) {
   10347 		result = ISC_R_ALREADYRUNNING;
   10348 		dumping = was_dumping(zone);
   10349 	} else
   10350 		dumping = ISC_TRUE;
   10351 	UNLOCK_ZONE(zone);
   10352 	if (!dumping)
   10353 		result = zone_dump(zone, ISC_TRUE);	/* Unknown task. */
   10354 	return (result);
   10355 }
   10356 
   10357 isc_result_t
   10358 dns_zone_dump(dns_zone_t *zone) {
   10359 	isc_result_t result = ISC_R_ALREADYRUNNING;
   10360 	isc_boolean_t dumping;
   10361 
   10362 	REQUIRE(DNS_ZONE_VALID(zone));
   10363 
   10364 	LOCK_ZONE(zone);
   10365 	dumping = was_dumping(zone);
   10366 	UNLOCK_ZONE(zone);
   10367 	if (!dumping)
   10368 		result = zone_dump(zone, ISC_FALSE);	/* Unknown task. */
   10369 	return (result);
   10370 }
   10371 
   10372 static void
   10373 zone_needdump(dns_zone_t *zone, unsigned int delay) {
   10374 	const char me[] = "zone_needdump";
   10375 	isc_time_t dumptime;
   10376 	isc_time_t now;
   10377 
   10378 	/*
   10379 	 * 'zone' locked by caller
   10380 	 */
   10381 
   10382 	REQUIRE(DNS_ZONE_VALID(zone));
   10383 	REQUIRE(LOCKED_ZONE(zone));
   10384 	ENTER;
   10385 
   10386 	/*
   10387 	 * Do we have a place to dump to and are we loaded?
   10388 	 */
   10389 	if (zone->masterfile == NULL ||
   10390 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
   10391 		return;
   10392 
   10393 	TIME_NOW(&now);
   10394 	/* add some noise */
   10395 	DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
   10396 
   10397 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   10398 	if (isc_time_isepoch(&zone->dumptime) ||
   10399 	    isc_time_compare(&zone->dumptime, &dumptime) > 0)
   10400 		zone->dumptime = dumptime;
   10401 	if (zone->task != NULL)
   10402 		zone_settimer(zone, &now);
   10403 }
   10404 
   10405 static void
   10406 dump_done(void *arg, isc_result_t result) {
   10407 	const char me[] = "dump_done";
   10408 	dns_zone_t *zone = arg;
   10409 	dns_zone_t *secure = NULL;
   10410 	dns_db_t *db;
   10411 	dns_dbversion_t *version;
   10412 	isc_boolean_t again = ISC_FALSE;
   10413 	isc_boolean_t compact = ISC_FALSE;
   10414 	isc_uint32_t serial;
   10415 	isc_result_t tresult;
   10416 
   10417 	REQUIRE(DNS_ZONE_VALID(zone));
   10418 
   10419 	ENTER;
   10420 
   10421 	if (result == ISC_R_SUCCESS && zone->journal != NULL) {
   10422 		/*
   10423 		 * We don't own these, zone->dctx must stay valid.
   10424 		 */
   10425 		db = dns_dumpctx_db(zone->dctx);
   10426 		version = dns_dumpctx_version(zone->dctx);
   10427 		tresult = dns_db_getsoaserial(db, version, &serial);
   10428 
   10429 		/*
   10430 		 * Handle lock order inversion.
   10431 		 */
   10432  again:
   10433 		LOCK_ZONE(zone);
   10434 		if (inline_raw(zone)) {
   10435 			secure = zone->secure;
   10436 			INSIST(secure != zone);
   10437 			TRYLOCK_ZONE(result, secure);
   10438 			if (result != ISC_R_SUCCESS) {
   10439 				UNLOCK_ZONE(zone);
   10440 				secure = NULL;
   10441 #if ISC_PLATFORM_USETHREADS
   10442 				isc_thread_yield();
   10443 #endif
   10444 				goto again;
   10445 			}
   10446 		}
   10447 
   10448 		/*
   10449 		 * If there is a secure version of this zone
   10450 		 * use its serial if it is less than ours.
   10451 		 */
   10452 		if (tresult == ISC_R_SUCCESS && secure != NULL) {
   10453 			isc_uint32_t sserial;
   10454 			isc_result_t mresult;
   10455 
   10456 			ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
   10457 			if (secure->db != NULL) {
   10458 				mresult = dns_db_getsoaserial(zone->secure->db,
   10459 							      NULL, &sserial);
   10460 				if (mresult == ISC_R_SUCCESS &&
   10461 				    isc_serial_lt(sserial, serial))
   10462 					serial = sserial;
   10463 			}
   10464 			ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
   10465 		}
   10466 		if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
   10467 			dns_db_t *zdb = NULL;
   10468 			if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
   10469 				zone_journal_compact(zone, zdb, serial);
   10470 				dns_db_detach(&zdb);
   10471 			}
   10472 		} else if (tresult == ISC_R_SUCCESS) {
   10473 			compact = ISC_TRUE;
   10474 			zone->compact_serial = serial;
   10475 		}
   10476 		if (secure != NULL)
   10477 			UNLOCK_ZONE(secure);
   10478 		UNLOCK_ZONE(zone);
   10479 	}
   10480 
   10481 	LOCK_ZONE(zone);
   10482 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
   10483 	if (compact)
   10484 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
   10485 	if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
   10486 		/*
   10487 		 * Try again in a short while.
   10488 		 */
   10489 		zone_needdump(zone, DNS_DUMP_DELAY);
   10490 	} else if (result == ISC_R_SUCCESS &&
   10491 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
   10492 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   10493 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   10494 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   10495 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
   10496 		isc_time_settoepoch(&zone->dumptime);
   10497 		again = ISC_TRUE;
   10498 	} else if (result == ISC_R_SUCCESS)
   10499 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
   10500 
   10501 	if (zone->dctx != NULL)
   10502 		dns_dumpctx_detach(&zone->dctx);
   10503 	zonemgr_putio(&zone->writeio);
   10504 	UNLOCK_ZONE(zone);
   10505 	if (again)
   10506 		(void)zone_dump(zone, ISC_FALSE);
   10507 	dns_zone_idetach(&zone);
   10508 }
   10509 
   10510 static isc_result_t
   10511 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
   10512 	const char me[] = "zone_dump";
   10513 	isc_result_t result;
   10514 	dns_dbversion_t *version = NULL;
   10515 	isc_boolean_t again;
   10516 	dns_db_t *db = NULL;
   10517 	char *masterfile = NULL;
   10518 	dns_masterformat_t masterformat = dns_masterformat_none;
   10519 
   10520 /*
   10521  * 'compact' MUST only be set if we are task locked.
   10522  */
   10523 
   10524 	REQUIRE(DNS_ZONE_VALID(zone));
   10525 	ENTER;
   10526 
   10527  redo:
   10528 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   10529 	if (zone->db != NULL)
   10530 		dns_db_attach(zone->db, &db);
   10531 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   10532 	LOCK_ZONE(zone);
   10533 	if (zone->masterfile != NULL) {
   10534 		masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
   10535 		masterformat = zone->masterformat;
   10536 	}
   10537 	UNLOCK_ZONE(zone);
   10538 	if (db == NULL) {
   10539 		result = DNS_R_NOTLOADED;
   10540 		goto fail;
   10541 	}
   10542 	if (masterfile == NULL) {
   10543 		result = DNS_R_NOMASTERFILE;
   10544 		goto fail;
   10545 	}
   10546 
   10547 	if (compact && zone->type != dns_zone_stub) {
   10548 		dns_zone_t *dummy = NULL;
   10549 		LOCK_ZONE(zone);
   10550 		zone_iattach(zone, &dummy);
   10551 		result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
   10552 				       zone_gotwritehandle, zone,
   10553 				       &zone->writeio);
   10554 		if (result != ISC_R_SUCCESS)
   10555 			zone_idetach(&dummy);
   10556 		else
   10557 			result = DNS_R_CONTINUE;
   10558 		UNLOCK_ZONE(zone);
   10559 	} else {
   10560 		const dns_master_style_t *output_style;
   10561 
   10562 		dns_masterrawheader_t rawdata;
   10563 		dns_db_currentversion(db, &version);
   10564 		dns_master_initrawheader(&rawdata);
   10565 		if (inline_secure(zone))
   10566 			get_raw_serial(zone->raw, &rawdata);
   10567 		if (zone->type == dns_zone_key)
   10568 			output_style = &dns_master_style_keyzone;
   10569 		else
   10570 			output_style = &dns_master_style_default;
   10571 		result = dns_master_dump3(zone->mctx, db, version,
   10572 					  output_style, masterfile,
   10573 					  masterformat, &rawdata);
   10574 		dns_db_closeversion(db, &version, ISC_FALSE);
   10575 	}
   10576  fail:
   10577 	if (db != NULL)
   10578 		dns_db_detach(&db);
   10579 	if (masterfile != NULL)
   10580 		isc_mem_free(zone->mctx, masterfile);
   10581 	masterfile = NULL;
   10582 
   10583 	if (result == DNS_R_CONTINUE)
   10584 		return (ISC_R_SUCCESS); /* XXXMPA */
   10585 
   10586 	again = ISC_FALSE;
   10587 	LOCK_ZONE(zone);
   10588 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
   10589 	if (result != ISC_R_SUCCESS) {
   10590 		/*
   10591 		 * Try again in a short while.
   10592 		 */
   10593 		zone_needdump(zone, DNS_DUMP_DELAY);
   10594 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
   10595 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   10596 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   10597 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   10598 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
   10599 		isc_time_settoepoch(&zone->dumptime);
   10600 		again = ISC_TRUE;
   10601 	} else
   10602 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
   10603 	UNLOCK_ZONE(zone);
   10604 	if (again)
   10605 		goto redo;
   10606 
   10607 	return (result);
   10608 }
   10609 
   10610 static isc_result_t
   10611 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
   10612 	     dns_masterformat_t format, const isc_uint32_t rawversion)
   10613 {
   10614 	isc_result_t result;
   10615 	dns_dbversion_t *version = NULL;
   10616 	dns_db_t *db = NULL;
   10617 	dns_masterrawheader_t rawdata;
   10618 
   10619 	REQUIRE(DNS_ZONE_VALID(zone));
   10620 
   10621 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   10622 	if (zone->db != NULL)
   10623 		dns_db_attach(zone->db, &db);
   10624 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   10625 	if (db == NULL)
   10626 		return (DNS_R_NOTLOADED);
   10627 
   10628 	dns_db_currentversion(db, &version);
   10629 	dns_master_initrawheader(&rawdata);
   10630 	if (rawversion == 0)
   10631 		rawdata.flags |= DNS_MASTERRAW_COMPAT;
   10632 	else if (inline_secure(zone))
   10633 		get_raw_serial(zone->raw, &rawdata);
   10634 	else if (zone->sourceserialset) {
   10635 		rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
   10636 		rawdata.sourceserial = zone->sourceserial;
   10637 	}
   10638 	result = dns_master_dumptostream3(zone->mctx, db, version, style,
   10639 					  format, &rawdata, fd);
   10640 	dns_db_closeversion(db, &version, ISC_FALSE);
   10641 	dns_db_detach(&db);
   10642 	return (result);
   10643 }
   10644 
   10645 isc_result_t
   10646 dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
   10647 		       const dns_master_style_t *style,
   10648 		       const isc_uint32_t rawversion)
   10649 {
   10650 	return (dumptostream(zone, fd, style, format, rawversion));
   10651 }
   10652 
   10653 isc_result_t
   10654 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
   10655 		       const dns_master_style_t *style) {
   10656 	return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION));
   10657 }
   10658 
   10659 isc_result_t
   10660 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
   10661 	return (dumptostream(zone, fd, &dns_master_style_default,
   10662 			     dns_masterformat_text, 0));
   10663 }
   10664 
   10665 isc_result_t
   10666 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
   10667 	return (dumptostream(zone, fd, &dns_master_style_full,
   10668 			     dns_masterformat_text, 0));
   10669 }
   10670 
   10671 void
   10672 dns_zone_unload(dns_zone_t *zone) {
   10673 	REQUIRE(DNS_ZONE_VALID(zone));
   10674 
   10675 	LOCK_ZONE(zone);
   10676 	zone_unload(zone);
   10677 	UNLOCK_ZONE(zone);
   10678 }
   10679 
   10680 static void
   10681 notify_cancel(dns_zone_t *zone) {
   10682 	dns_notify_t *notify;
   10683 
   10684 	/*
   10685 	 * 'zone' locked by caller.
   10686 	 */
   10687 
   10688 	REQUIRE(LOCKED_ZONE(zone));
   10689 
   10690 	for (notify = ISC_LIST_HEAD(zone->notifies);
   10691 	     notify != NULL;
   10692 	     notify = ISC_LIST_NEXT(notify, link)) {
   10693 		if (notify->find != NULL)
   10694 			dns_adb_cancelfind(notify->find);
   10695 		if (notify->request != NULL)
   10696 			dns_request_cancel(notify->request);
   10697 	}
   10698 }
   10699 
   10700 static void
   10701 forward_cancel(dns_zone_t *zone) {
   10702 	dns_forward_t *forward;
   10703 
   10704 	/*
   10705 	 * 'zone' locked by caller.
   10706 	 */
   10707 
   10708 	REQUIRE(LOCKED_ZONE(zone));
   10709 
   10710 	for (forward = ISC_LIST_HEAD(zone->forwards);
   10711 	     forward != NULL;
   10712 	     forward = ISC_LIST_NEXT(forward, link)) {
   10713 		if (forward->request != NULL)
   10714 			dns_request_cancel(forward->request);
   10715 	}
   10716 }
   10717 
   10718 static void
   10719 zone_unload(dns_zone_t *zone) {
   10720 	/*
   10721 	 * 'zone' locked by caller.
   10722 	 */
   10723 
   10724 	REQUIRE(LOCKED_ZONE(zone));
   10725 
   10726 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
   10727 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   10728 		if (zone->writeio != NULL)
   10729 			zonemgr_cancelio(zone->writeio);
   10730 
   10731 		if (zone->dctx != NULL)
   10732 			dns_dumpctx_cancel(zone->dctx);
   10733 	}
   10734 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   10735 	zone_detachdb(zone);
   10736 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   10737 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
   10738 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
   10739 }
   10740 
   10741 void
   10742 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
   10743 	REQUIRE(DNS_ZONE_VALID(zone));
   10744 	REQUIRE(val > 0);
   10745 
   10746 	zone->minrefresh = val;
   10747 }
   10748 
   10749 void
   10750 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
   10751 	REQUIRE(DNS_ZONE_VALID(zone));
   10752 	REQUIRE(val > 0);
   10753 
   10754 	zone->maxrefresh = val;
   10755 }
   10756 
   10757 void
   10758 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
   10759 	REQUIRE(DNS_ZONE_VALID(zone));
   10760 	REQUIRE(val > 0);
   10761 
   10762 	zone->minretry = val;
   10763 }
   10764 
   10765 void
   10766 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
   10767 	REQUIRE(DNS_ZONE_VALID(zone));
   10768 	REQUIRE(val > 0);
   10769 
   10770 	zone->maxretry = val;
   10771 }
   10772 
   10773 isc_uint32_t
   10774 dns_zone_getmaxrecords(dns_zone_t *zone) {
   10775 	REQUIRE(DNS_ZONE_VALID(zone));
   10776 
   10777 	return (zone->maxrecords);
   10778 }
   10779 
   10780 void
   10781 dns_zone_setmaxrecords(dns_zone_t *zone, isc_uint32_t val) {
   10782 	REQUIRE(DNS_ZONE_VALID(zone));
   10783 
   10784 	zone->maxrecords = val;
   10785 }
   10786 
   10787 static isc_boolean_t
   10788 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
   10789 		isc_sockaddr_t *addr, dns_tsigkey_t *key)
   10790 {
   10791 	dns_notify_t *notify;
   10792 	dns_zonemgr_t *zmgr;
   10793 	isc_result_t result;
   10794 
   10795 	for (notify = ISC_LIST_HEAD(zone->notifies);
   10796 	     notify != NULL;
   10797 	     notify = ISC_LIST_NEXT(notify, link)) {
   10798 		if (notify->request != NULL)
   10799 			continue;
   10800 		if (name != NULL && dns_name_dynamic(&notify->ns) &&
   10801 		    dns_name_equal(name, &notify->ns))
   10802 			goto requeue;
   10803 		if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst) &&
   10804 		    notify->key == key)
   10805 			goto requeue;
   10806 	}
   10807 	return (ISC_FALSE);
   10808 
   10809 requeue:
   10810 	/*
   10811 	 * If we are enqueued on the startup ratelimiter and this is
   10812 	 * not a startup notify, re-enqueue on the normal notify
   10813 	 * ratelimiter.
   10814 	 */
   10815 	if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
   10816 	    (notify->flags & DNS_NOTIFY_STARTUP) != 0) {
   10817 		zmgr = notify->zone->zmgr;
   10818 		result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
   10819 						 notify->event);
   10820 		if (result != ISC_R_SUCCESS)
   10821 			return (ISC_TRUE);
   10822 
   10823 		notify->flags &= ~DNS_NOTIFY_STARTUP;
   10824 		result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
   10825 						 notify->zone->task,
   10826 						 &notify->event);
   10827 		if (result != ISC_R_SUCCESS) {
   10828 			isc_event_free(&notify->event);
   10829 			return (ISC_FALSE);
   10830 		}
   10831 	}
   10832 
   10833 	return (ISC_TRUE);
   10834 }
   10835 
   10836 static isc_boolean_t
   10837 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
   10838 	dns_tsigkey_t *key = NULL;
   10839 	isc_sockaddr_t src;
   10840 	isc_sockaddr_t any;
   10841 	isc_boolean_t isself;
   10842 	isc_netaddr_t dstaddr;
   10843 	isc_result_t result;
   10844 
   10845 	if (zone->view == NULL || zone->isself == NULL)
   10846 		return (ISC_FALSE);
   10847 
   10848 	switch (isc_sockaddr_pf(dst)) {
   10849 	case PF_INET:
   10850 		src = zone->notifysrc4;
   10851 		isc_sockaddr_any(&any);
   10852 		break;
   10853 	case PF_INET6:
   10854 		src = zone->notifysrc6;
   10855 		isc_sockaddr_any6(&any);
   10856 		break;
   10857 	default:
   10858 		return (ISC_FALSE);
   10859 	}
   10860 
   10861 	/*
   10862 	 * When sending from any the kernel will assign a source address
   10863 	 * that matches the destination address.
   10864 	 */
   10865 	if (isc_sockaddr_eqaddr(&any, &src))
   10866 		src = *dst;
   10867 
   10868 	isc_netaddr_fromsockaddr(&dstaddr, dst);
   10869 	result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
   10870 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
   10871 		return (ISC_FALSE);
   10872 	isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
   10873 				zone->isselfarg);
   10874 	if (key != NULL)
   10875 		dns_tsigkey_detach(&key);
   10876 	return (isself);
   10877 }
   10878 
   10879 static void
   10880 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
   10881 	isc_mem_t *mctx;
   10882 
   10883 	REQUIRE(DNS_NOTIFY_VALID(notify));
   10884 
   10885 	if (notify->zone != NULL) {
   10886 		if (!locked)
   10887 			LOCK_ZONE(notify->zone);
   10888 		REQUIRE(LOCKED_ZONE(notify->zone));
   10889 		if (ISC_LINK_LINKED(notify, link))
   10890 			ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
   10891 		if (!locked)
   10892 			UNLOCK_ZONE(notify->zone);
   10893 		if (locked)
   10894 			zone_idetach(&notify->zone);
   10895 		else
   10896 			dns_zone_idetach(&notify->zone);
   10897 	}
   10898 	if (notify->find != NULL)
   10899 		dns_adb_destroyfind(&notify->find);
   10900 	if (notify->request != NULL)
   10901 		dns_request_destroy(&notify->request);
   10902 	if (dns_name_dynamic(&notify->ns))
   10903 		dns_name_free(&notify->ns, notify->mctx);
   10904 	if (notify->key != NULL)
   10905 		dns_tsigkey_detach(&notify->key);
   10906 	mctx = notify->mctx;
   10907 	isc_mem_put(notify->mctx, notify, sizeof(*notify));
   10908 	isc_mem_detach(&mctx);
   10909 }
   10910 
   10911 static isc_result_t
   10912 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
   10913 	dns_notify_t *notify;
   10914 
   10915 	REQUIRE(notifyp != NULL && *notifyp == NULL);
   10916 
   10917 	notify = isc_mem_get(mctx, sizeof(*notify));
   10918 	if (notify == NULL)
   10919 		return (ISC_R_NOMEMORY);
   10920 
   10921 	notify->mctx = NULL;
   10922 	isc_mem_attach(mctx, &notify->mctx);
   10923 	notify->flags = flags;
   10924 	notify->zone = NULL;
   10925 	notify->find = NULL;
   10926 	notify->request = NULL;
   10927 	notify->key = NULL;
   10928 	notify->event = NULL;
   10929 	isc_sockaddr_any(&notify->dst);
   10930 	dns_name_init(&notify->ns, NULL);
   10931 	ISC_LINK_INIT(notify, link);
   10932 	notify->magic = NOTIFY_MAGIC;
   10933 	*notifyp = notify;
   10934 	return (ISC_R_SUCCESS);
   10935 }
   10936 
   10937 /*
   10938  * XXXAG should check for DNS_ZONEFLG_EXITING
   10939  */
   10940 static void
   10941 process_adb_event(isc_task_t *task, isc_event_t *ev) {
   10942 	dns_notify_t *notify;
   10943 	isc_eventtype_t result;
   10944 
   10945 	UNUSED(task);
   10946 
   10947 	notify = ev->ev_arg;
   10948 	REQUIRE(DNS_NOTIFY_VALID(notify));
   10949 	INSIST(task == notify->zone->task);
   10950 	result = ev->ev_type;
   10951 	isc_event_free(&ev);
   10952 	if (result == DNS_EVENT_ADBMOREADDRESSES) {
   10953 		dns_adb_destroyfind(&notify->find);
   10954 		notify_find_address(notify);
   10955 		return;
   10956 	}
   10957 	if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
   10958 		LOCK_ZONE(notify->zone);
   10959 		notify_send(notify);
   10960 		UNLOCK_ZONE(notify->zone);
   10961 	}
   10962 	notify_destroy(notify, ISC_FALSE);
   10963 }
   10964 
   10965 static void
   10966 notify_find_address(dns_notify_t *notify) {
   10967 	isc_result_t result;
   10968 	unsigned int options;
   10969 
   10970 	REQUIRE(DNS_NOTIFY_VALID(notify));
   10971 	options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
   10972 		  DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
   10973 
   10974 	if (notify->zone->view->adb == NULL)
   10975 		goto destroy;
   10976 
   10977 	result = dns_adb_createfind(notify->zone->view->adb,
   10978 				    notify->zone->task,
   10979 				    process_adb_event, notify,
   10980 				    &notify->ns, dns_rootname, 0,
   10981 				    options, 0, NULL,
   10982 				    notify->zone->view->dstport,
   10983 				    &notify->find);
   10984 
   10985 	/* Something failed? */
   10986 	if (result != ISC_R_SUCCESS)
   10987 		goto destroy;
   10988 
   10989 	/* More addresses pending? */
   10990 	if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
   10991 		return;
   10992 
   10993 	/* We have as many addresses as we can get. */
   10994 	LOCK_ZONE(notify->zone);
   10995 	notify_send(notify);
   10996 	UNLOCK_ZONE(notify->zone);
   10997 
   10998  destroy:
   10999 	notify_destroy(notify, ISC_FALSE);
   11000 }
   11001 
   11002 
   11003 static isc_result_t
   11004 notify_send_queue(dns_notify_t *notify, isc_boolean_t startup) {
   11005 	isc_event_t *e;
   11006 	isc_result_t result;
   11007 
   11008 	INSIST(notify->event == NULL);
   11009 	e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
   11010 			       notify_send_toaddr, notify, sizeof(isc_event_t));
   11011 	if (e == NULL)
   11012 		return (ISC_R_NOMEMORY);
   11013 	if (startup)
   11014 		notify->event = e;
   11015 	e->ev_arg = notify;
   11016 	e->ev_sender = NULL;
   11017 	result = isc_ratelimiter_enqueue(startup
   11018 					  ? notify->zone->zmgr->startupnotifyrl
   11019 					  : notify->zone->zmgr->notifyrl,
   11020 					 notify->zone->task, &e);
   11021 	if (result != ISC_R_SUCCESS) {
   11022 		isc_event_free(&e);
   11023 		notify->event = NULL;
   11024 	}
   11025 	return (result);
   11026 }
   11027 
   11028 static void
   11029 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
   11030 	dns_notify_t *notify;
   11031 	isc_result_t result;
   11032 	dns_message_t *message = NULL;
   11033 	isc_netaddr_t dstip;
   11034 	dns_tsigkey_t *key = NULL;
   11035 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   11036 	isc_sockaddr_t src;
   11037 	unsigned int options, timeout;
   11038 	isc_boolean_t have_notifysource = ISC_FALSE;
   11039 	isc_boolean_t have_notifydscp = ISC_FALSE;
   11040 	isc_dscp_t dscp = -1;
   11041 
   11042 	notify = event->ev_arg;
   11043 	REQUIRE(DNS_NOTIFY_VALID(notify));
   11044 
   11045 	UNUSED(task);
   11046 
   11047 	LOCK_ZONE(notify->zone);
   11048 
   11049 	notify->event = NULL;
   11050 
   11051 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
   11052 		result = ISC_R_CANCELED;
   11053 		goto cleanup;
   11054 	}
   11055 
   11056 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
   11057 	    DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
   11058 	    notify->zone->view->requestmgr == NULL ||
   11059 	    notify->zone->db == NULL) {
   11060 		result = ISC_R_CANCELED;
   11061 		goto cleanup;
   11062 	}
   11063 
   11064 	/*
   11065 	 * The raw IPv4 address should also exist.  Don't send to the
   11066 	 * mapped form.
   11067 	 */
   11068 	if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
   11069 	    IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
   11070 		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
   11071 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
   11072 			   "notify: ignoring IPv6 mapped IPV4 address: %s",
   11073 			   addrbuf);
   11074 		result = ISC_R_CANCELED;
   11075 		goto cleanup;
   11076 	}
   11077 
   11078 	result = notify_createmessage(notify->zone, notify->flags, &message);
   11079 	if (result != ISC_R_SUCCESS)
   11080 		goto cleanup;
   11081 
   11082 	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
   11083 	if (notify->key != NULL) {
   11084 		/* Transfer ownership of key */
   11085 		key = notify->key;
   11086 		notify->key = NULL;
   11087 	} else {
   11088 		isc_netaddr_fromsockaddr(&dstip, &notify->dst);
   11089 		result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
   11090 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   11091 			notify_log(notify->zone, ISC_LOG_ERROR,
   11092 				   "NOTIFY to %s not sent. "
   11093 				   "Peer TSIG key lookup failure.", addrbuf);
   11094 			goto cleanup_message;
   11095 		}
   11096 	}
   11097 
   11098 	/* XXX: should we log the tsig key too? */
   11099 	notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
   11100 		   addrbuf);
   11101 	options = 0;
   11102 	if (notify->zone->view->peers != NULL) {
   11103 		dns_peer_t *peer = NULL;
   11104 		isc_boolean_t usetcp = ISC_FALSE;
   11105 		result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
   11106 						 &dstip, &peer);
   11107 		if (result == ISC_R_SUCCESS) {
   11108 			result = dns_peer_getnotifysource(peer, &src);
   11109 			if (result == ISC_R_SUCCESS)
   11110 				have_notifysource = ISC_TRUE;
   11111 			dns_peer_getnotifydscp(peer, &dscp);
   11112 			if (dscp != -1)
   11113 				have_notifydscp = ISC_TRUE;
   11114 			result = dns_peer_getforcetcp(peer, &usetcp);
   11115 			if (result == ISC_R_SUCCESS && usetcp)
   11116 				options |= DNS_FETCHOPT_TCP;
   11117 		}
   11118 	}
   11119 	switch (isc_sockaddr_pf(&notify->dst)) {
   11120 	case PF_INET:
   11121 		if (!have_notifysource)
   11122 			src = notify->zone->notifysrc4;
   11123 		if (!have_notifydscp)
   11124 			dscp = notify->zone->notifysrc4dscp;
   11125 		break;
   11126 	case PF_INET6:
   11127 		if (!have_notifysource)
   11128 			src = notify->zone->notifysrc6;
   11129 		if (!have_notifydscp)
   11130 			dscp = notify->zone->notifysrc6dscp;
   11131 		break;
   11132 	default:
   11133 		result = ISC_R_NOTIMPLEMENTED;
   11134 		goto cleanup_key;
   11135 	}
   11136 	timeout = 15;
   11137 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
   11138 		timeout = 30;
   11139 	result = dns_request_createvia4(notify->zone->view->requestmgr,
   11140 					message, &src, &notify->dst, dscp,
   11141 					options, key, timeout * 3, timeout,
   11142 					0, notify->zone->task, notify_done,
   11143 					notify, &notify->request);
   11144 	if (result == ISC_R_SUCCESS) {
   11145 		if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
   11146 			inc_stats(notify->zone,
   11147 				  dns_zonestatscounter_notifyoutv4);
   11148 		} else {
   11149 			inc_stats(notify->zone,
   11150 				  dns_zonestatscounter_notifyoutv6);
   11151 		}
   11152 	}
   11153 
   11154  cleanup_key:
   11155 	if (key != NULL)
   11156 		dns_tsigkey_detach(&key);
   11157  cleanup_message:
   11158 	dns_message_destroy(&message);
   11159  cleanup:
   11160 	UNLOCK_ZONE(notify->zone);
   11161 	isc_event_free(&event);
   11162 	if (result != ISC_R_SUCCESS)
   11163 		notify_destroy(notify, ISC_FALSE);
   11164 }
   11165 
   11166 static void
   11167 notify_send(dns_notify_t *notify) {
   11168 	dns_adbaddrinfo_t *ai;
   11169 	isc_sockaddr_t dst;
   11170 	isc_result_t result;
   11171 	dns_notify_t *newnotify = NULL;
   11172 	unsigned int flags;
   11173 	isc_boolean_t startup;
   11174 
   11175 	/*
   11176 	 * Zone lock held by caller.
   11177 	 */
   11178 	REQUIRE(DNS_NOTIFY_VALID(notify));
   11179 	REQUIRE(LOCKED_ZONE(notify->zone));
   11180 
   11181 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING))
   11182 		return;
   11183 
   11184 	for (ai = ISC_LIST_HEAD(notify->find->list);
   11185 	     ai != NULL;
   11186 	     ai = ISC_LIST_NEXT(ai, publink)) {
   11187 		dst = ai->sockaddr;
   11188 		if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
   11189 				    NULL))
   11190 			continue;
   11191 		if (notify_isself(notify->zone, &dst))
   11192 			continue;
   11193 		newnotify = NULL;
   11194 		flags = notify->flags & DNS_NOTIFY_NOSOA;
   11195 		result = notify_create(notify->mctx, flags, &newnotify);
   11196 		if (result != ISC_R_SUCCESS)
   11197 			goto cleanup;
   11198 		zone_iattach(notify->zone, &newnotify->zone);
   11199 		ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
   11200 		newnotify->dst = dst;
   11201 		startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0);
   11202 		result = notify_send_queue(newnotify, startup);
   11203 		if (result != ISC_R_SUCCESS)
   11204 			goto cleanup;
   11205 		newnotify = NULL;
   11206 	}
   11207 
   11208  cleanup:
   11209 	if (newnotify != NULL)
   11210 		notify_destroy(newnotify, ISC_TRUE);
   11211 }
   11212 
   11213 void
   11214 dns_zone_notify(dns_zone_t *zone) {
   11215 	isc_time_t now;
   11216 
   11217 	REQUIRE(DNS_ZONE_VALID(zone));
   11218 
   11219 	LOCK_ZONE(zone);
   11220 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   11221 
   11222 	TIME_NOW(&now);
   11223 	zone_settimer(zone, &now);
   11224 	UNLOCK_ZONE(zone);
   11225 }
   11226 
   11227 static void
   11228 zone_notify(dns_zone_t *zone, isc_time_t *now) {
   11229 	dns_dbnode_t *node = NULL;
   11230 	dns_db_t *zonedb = NULL;
   11231 	dns_dbversion_t *version = NULL;
   11232 	dns_name_t *origin = NULL;
   11233 	dns_name_t master;
   11234 	dns_rdata_ns_t ns;
   11235 	dns_rdata_soa_t soa;
   11236 	isc_uint32_t serial;
   11237 	dns_rdata_t rdata = DNS_RDATA_INIT;
   11238 	dns_rdataset_t nsrdset;
   11239 	dns_rdataset_t soardset;
   11240 	isc_result_t result;
   11241 	unsigned int i;
   11242 	isc_sockaddr_t dst;
   11243 	isc_boolean_t isqueued;
   11244 	dns_notifytype_t notifytype;
   11245 	unsigned int flags = 0;
   11246 	isc_boolean_t loggednotify = ISC_FALSE;
   11247 	isc_boolean_t startup;
   11248 
   11249 	REQUIRE(DNS_ZONE_VALID(zone));
   11250 
   11251 	LOCK_ZONE(zone);
   11252 	startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   11253 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   11254 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
   11255 	notifytype = zone->notifytype;
   11256 	DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
   11257 	UNLOCK_ZONE(zone);
   11258 
   11259 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
   11260 	    ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
   11261 		return;
   11262 
   11263 	if (notifytype == dns_notifytype_no)
   11264 		return;
   11265 
   11266 	if (notifytype == dns_notifytype_masteronly &&
   11267 	    zone->type != dns_zone_master)
   11268 		return;
   11269 
   11270 	origin = &zone->origin;
   11271 
   11272 	/*
   11273 	 * If the zone is dialup we are done as we don't want to send
   11274 	 * the current soa so as to force a refresh query.
   11275 	 */
   11276 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
   11277 		flags |= DNS_NOTIFY_NOSOA;
   11278 
   11279 	/*
   11280 	 * Record that this was a notify due to starting up.
   11281 	 */
   11282 	if (startup)
   11283 		flags |= DNS_NOTIFY_STARTUP;
   11284 
   11285 	/*
   11286 	 * Get SOA RRset.
   11287 	 */
   11288 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   11289 	if (zone->db != NULL)
   11290 		dns_db_attach(zone->db, &zonedb);
   11291 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   11292 	if (zonedb == NULL)
   11293 		return;
   11294 	dns_db_currentversion(zonedb, &version);
   11295 	result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
   11296 	if (result != ISC_R_SUCCESS)
   11297 		goto cleanup1;
   11298 
   11299 	dns_rdataset_init(&soardset);
   11300 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
   11301 				     dns_rdatatype_none, 0, &soardset, NULL);
   11302 	if (result != ISC_R_SUCCESS)
   11303 		goto cleanup2;
   11304 
   11305 	/*
   11306 	 * Find serial and master server's name.
   11307 	 */
   11308 	dns_name_init(&master, NULL);
   11309 	result = dns_rdataset_first(&soardset);
   11310 	if (result != ISC_R_SUCCESS)
   11311 		goto cleanup3;
   11312 	dns_rdataset_current(&soardset, &rdata);
   11313 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   11314 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   11315 	dns_rdata_reset(&rdata);
   11316 	result = dns_name_dup(&soa.origin, zone->mctx, &master);
   11317 	serial = soa.serial;
   11318 	dns_rdataset_disassociate(&soardset);
   11319 	if (result != ISC_R_SUCCESS)
   11320 		goto cleanup3;
   11321 
   11322 	/*
   11323 	 * Enqueue notify requests for 'also-notify' servers.
   11324 	 */
   11325 	LOCK_ZONE(zone);
   11326 	for (i = 0; i < zone->notifycnt; i++) {
   11327 		dns_tsigkey_t *key = NULL;
   11328 		dns_notify_t *notify = NULL;
   11329 
   11330 		if ((zone->notifykeynames != NULL) &&
   11331 		    (zone->notifykeynames[i] != NULL)) {
   11332 			dns_view_t *view = dns_zone_getview(zone);
   11333 			dns_name_t *keyname = zone->notifykeynames[i];
   11334 			(void)dns_view_gettsig(view, keyname, &key);
   11335 		}
   11336 
   11337 		dst = zone->notify[i];
   11338 		if (notify_isqueued(zone, flags, NULL, &dst, key)) {
   11339 			if (key != NULL)
   11340 				dns_tsigkey_detach(&key);
   11341 			continue;
   11342 		}
   11343 
   11344 		result = notify_create(zone->mctx, flags, &notify);
   11345 		if (result != ISC_R_SUCCESS) {
   11346 			if (key != NULL)
   11347 				dns_tsigkey_detach(&key);
   11348 			continue;
   11349 		}
   11350 
   11351 		zone_iattach(zone, &notify->zone);
   11352 		notify->dst = dst;
   11353 
   11354 		INSIST(notify->key == NULL);
   11355 
   11356 		if (key != NULL) {
   11357 			notify->key = key;
   11358 			key = NULL;
   11359 		}
   11360 
   11361 		ISC_LIST_APPEND(zone->notifies, notify, link);
   11362 		result = notify_send_queue(notify, startup);
   11363 		if (result != ISC_R_SUCCESS)
   11364 			notify_destroy(notify, ISC_TRUE);
   11365 		if (!loggednotify) {
   11366 			notify_log(zone, ISC_LOG_INFO,
   11367 				   "sending notifies (serial %u)",
   11368 				   serial);
   11369 			loggednotify = ISC_TRUE;
   11370 		}
   11371 	}
   11372 	UNLOCK_ZONE(zone);
   11373 
   11374 	if (notifytype == dns_notifytype_explicit)
   11375 		goto cleanup3;
   11376 
   11377 	/*
   11378 	 * Process NS RRset to generate notifies.
   11379 	 */
   11380 
   11381 	dns_rdataset_init(&nsrdset);
   11382 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
   11383 				     dns_rdatatype_none, 0, &nsrdset, NULL);
   11384 	if (result != ISC_R_SUCCESS)
   11385 		goto cleanup3;
   11386 
   11387 	result = dns_rdataset_first(&nsrdset);
   11388 	while (result == ISC_R_SUCCESS) {
   11389 		dns_notify_t *notify = NULL;
   11390 
   11391 		dns_rdataset_current(&nsrdset, &rdata);
   11392 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
   11393 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   11394 		dns_rdata_reset(&rdata);
   11395 		/*
   11396 		 * Don't notify the master server unless explicitly
   11397 		 * configured to do so.
   11398 		 */
   11399 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
   11400 		    dns_name_compare(&master, &ns.name) == 0) {
   11401 			result = dns_rdataset_next(&nsrdset);
   11402 			continue;
   11403 		}
   11404 
   11405 		if (!loggednotify) {
   11406 			notify_log(zone, ISC_LOG_INFO,
   11407 				   "sending notifies (serial %u)",
   11408 				   serial);
   11409 			loggednotify = ISC_TRUE;
   11410 		}
   11411 
   11412 		LOCK_ZONE(zone);
   11413 		isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
   11414 		UNLOCK_ZONE(zone);
   11415 		if (isqueued) {
   11416 			result = dns_rdataset_next(&nsrdset);
   11417 			continue;
   11418 		}
   11419 		result = notify_create(zone->mctx, flags, &notify);
   11420 		if (result != ISC_R_SUCCESS)
   11421 			continue;
   11422 		dns_zone_iattach(zone, &notify->zone);
   11423 		result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
   11424 		if (result != ISC_R_SUCCESS) {
   11425 			LOCK_ZONE(zone);
   11426 			notify_destroy(notify, ISC_TRUE);
   11427 			UNLOCK_ZONE(zone);
   11428 			continue;
   11429 		}
   11430 		LOCK_ZONE(zone);
   11431 		ISC_LIST_APPEND(zone->notifies, notify, link);
   11432 		UNLOCK_ZONE(zone);
   11433 		notify_find_address(notify);
   11434 		result = dns_rdataset_next(&nsrdset);
   11435 	}
   11436 	dns_rdataset_disassociate(&nsrdset);
   11437 
   11438  cleanup3:
   11439 	if (dns_name_dynamic(&master))
   11440 		dns_name_free(&master, zone->mctx);
   11441  cleanup2:
   11442 	dns_db_detachnode(zonedb, &node);
   11443  cleanup1:
   11444 	dns_db_closeversion(zonedb, &version, ISC_FALSE);
   11445 	dns_db_detach(&zonedb);
   11446 }
   11447 
   11448 /***
   11449  *** Private
   11450  ***/
   11451 
   11452 static inline isc_result_t
   11453 save_nsrrset(dns_message_t *message, dns_name_t *name,
   11454 	     dns_db_t *db, dns_dbversion_t *version)
   11455 {
   11456 	dns_rdataset_t *nsrdataset = NULL;
   11457 	dns_rdataset_t *rdataset = NULL;
   11458 	dns_dbnode_t *node = NULL;
   11459 	dns_rdata_ns_t ns;
   11460 	isc_result_t result;
   11461 	dns_rdata_t rdata = DNS_RDATA_INIT;
   11462 
   11463 	/*
   11464 	 * Extract NS RRset from message.
   11465 	 */
   11466 	result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
   11467 				      dns_rdatatype_ns, dns_rdatatype_none,
   11468 				      NULL, &nsrdataset);
   11469 	if (result != ISC_R_SUCCESS)
   11470 		goto fail;
   11471 
   11472 	/*
   11473 	 * Add NS rdataset.
   11474 	 */
   11475 	result = dns_db_findnode(db, name, ISC_TRUE, &node);
   11476 	if (result != ISC_R_SUCCESS)
   11477 		goto fail;
   11478 	result = dns_db_addrdataset(db, node, version, 0,
   11479 				    nsrdataset, 0, NULL);
   11480 	dns_db_detachnode(db, &node);
   11481 	if (result != ISC_R_SUCCESS)
   11482 		goto fail;
   11483 	/*
   11484 	 * Add glue rdatasets.
   11485 	 */
   11486 	for (result = dns_rdataset_first(nsrdataset);
   11487 	     result == ISC_R_SUCCESS;
   11488 	     result = dns_rdataset_next(nsrdataset)) {
   11489 		dns_rdataset_current(nsrdataset, &rdata);
   11490 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
   11491 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   11492 		dns_rdata_reset(&rdata);
   11493 		if (!dns_name_issubdomain(&ns.name, name))
   11494 			continue;
   11495 		rdataset = NULL;
   11496 		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
   11497 					      &ns.name, dns_rdatatype_aaaa,
   11498 					      dns_rdatatype_none, NULL,
   11499 					      &rdataset);
   11500 		if (result == ISC_R_SUCCESS) {
   11501 			result = dns_db_findnode(db, &ns.name,
   11502 						 ISC_TRUE, &node);
   11503 			if (result != ISC_R_SUCCESS)
   11504 				goto fail;
   11505 			result = dns_db_addrdataset(db, node, version, 0,
   11506 						    rdataset, 0, NULL);
   11507 			dns_db_detachnode(db, &node);
   11508 			if (result != ISC_R_SUCCESS)
   11509 				goto fail;
   11510 		}
   11511 		rdataset = NULL;
   11512 		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
   11513 					      &ns.name, dns_rdatatype_a,
   11514 					      dns_rdatatype_none, NULL,
   11515 					      &rdataset);
   11516 		if (result == ISC_R_SUCCESS) {
   11517 			result = dns_db_findnode(db, &ns.name,
   11518 						 ISC_TRUE, &node);
   11519 			if (result != ISC_R_SUCCESS)
   11520 				goto fail;
   11521 			result = dns_db_addrdataset(db, node, version, 0,
   11522 						    rdataset, 0, NULL);
   11523 			dns_db_detachnode(db, &node);
   11524 			if (result != ISC_R_SUCCESS)
   11525 				goto fail;
   11526 		}
   11527 	}
   11528 	if (result != ISC_R_NOMORE)
   11529 		goto fail;
   11530 
   11531 	return (ISC_R_SUCCESS);
   11532 
   11533 fail:
   11534 	return (result);
   11535 }
   11536 
   11537 static void
   11538 stub_callback(isc_task_t *task, isc_event_t *event) {
   11539 	const char me[] = "stub_callback";
   11540 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
   11541 	dns_stub_t *stub = NULL;
   11542 	dns_message_t *msg = NULL;
   11543 	dns_zone_t *zone = NULL;
   11544 	char master[ISC_SOCKADDR_FORMATSIZE];
   11545 	char source[ISC_SOCKADDR_FORMATSIZE];
   11546 	isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
   11547 	isc_result_t result;
   11548 	isc_time_t now;
   11549 	isc_boolean_t exiting = ISC_FALSE;
   11550 	isc_interval_t i;
   11551 	unsigned int j, soacount;
   11552 
   11553 	stub = revent->ev_arg;
   11554 	INSIST(DNS_STUB_VALID(stub));
   11555 
   11556 	UNUSED(task);
   11557 
   11558 	zone = stub->zone;
   11559 
   11560 	ENTER;
   11561 
   11562 	TIME_NOW(&now);
   11563 
   11564 	LOCK_ZONE(zone);
   11565 
   11566 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   11567 		zone_debuglog(zone, me, 1, "exiting");
   11568 		exiting = ISC_TRUE;
   11569 		goto next_master;
   11570 	}
   11571 
   11572 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
   11573 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   11574 
   11575 	if (revent->result != ISC_R_SUCCESS) {
   11576 		if (revent->result == ISC_R_TIMEDOUT &&
   11577 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   11578 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   11579 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   11580 				     "refreshing stub: timeout retrying "
   11581 				     " without EDNS master %s (source %s)",
   11582 				     master, source);
   11583 			goto same_master;
   11584 		}
   11585 		dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
   11586 					   &zone->sourceaddr, &now);
   11587 		dns_zone_log(zone, ISC_LOG_INFO,
   11588 			     "could not refresh stub from master %s"
   11589 			     " (source %s): %s", master, source,
   11590 			     dns_result_totext(revent->result));
   11591 		goto next_master;
   11592 	}
   11593 
   11594 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
   11595 	if (result != ISC_R_SUCCESS)
   11596 		goto next_master;
   11597 
   11598 	result = dns_request_getresponse(revent->request, msg, 0);
   11599 	if (result != ISC_R_SUCCESS)
   11600 		goto next_master;
   11601 
   11602 	/*
   11603 	 * Unexpected rcode.
   11604 	 */
   11605 	if (msg->rcode != dns_rcode_noerror) {
   11606 		char rcode[128];
   11607 		isc_buffer_t rb;
   11608 
   11609 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   11610 		(void)dns_rcode_totext(msg->rcode, &rb);
   11611 
   11612 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
   11613 		    (msg->rcode == dns_rcode_servfail ||
   11614 		     msg->rcode == dns_rcode_notimp ||
   11615 		     msg->rcode == dns_rcode_formerr)) {
   11616 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   11617 				     "refreshing stub: rcode (%.*s) retrying "
   11618 				     "without EDNS master %s (source %s)",
   11619 				     (int)rb.used, rcode, master, source);
   11620 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   11621 			goto same_master;
   11622 		}
   11623 
   11624 		dns_zone_log(zone, ISC_LOG_INFO,
   11625 			     "refreshing stub: "
   11626 			     "unexpected rcode (%.*s) from %s (source %s)",
   11627 			     (int)rb.used, rcode, master, source);
   11628 		goto next_master;
   11629 	}
   11630 
   11631 	/*
   11632 	 * We need complete messages.
   11633 	 */
   11634 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
   11635 		if (dns_request_usedtcp(revent->request)) {
   11636 			dns_zone_log(zone, ISC_LOG_INFO,
   11637 				     "refreshing stub: truncated TCP "
   11638 				     "response from master %s (source %s)",
   11639 				     master, source);
   11640 			goto next_master;
   11641 		}
   11642 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
   11643 		goto same_master;
   11644 	}
   11645 
   11646 	/*
   11647 	 * If non-auth log and next master.
   11648 	 */
   11649 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
   11650 		dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
   11651 			     "non-authoritative answer from "
   11652 			     "master %s (source %s)", master, source);
   11653 		goto next_master;
   11654 	}
   11655 
   11656 	/*
   11657 	 * Sanity checks.
   11658 	 */
   11659 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
   11660 	nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
   11661 
   11662 	if (cnamecnt != 0) {
   11663 		dns_zone_log(zone, ISC_LOG_INFO,
   11664 			     "refreshing stub: unexpected CNAME response "
   11665 			     "from master %s (source %s)", master, source);
   11666 		goto next_master;
   11667 	}
   11668 
   11669 	if (nscnt == 0) {
   11670 		dns_zone_log(zone, ISC_LOG_INFO,
   11671 			     "refreshing stub: no NS records in response "
   11672 			     "from master %s (source %s)", master, source);
   11673 		goto next_master;
   11674 	}
   11675 
   11676 	/*
   11677 	 * Save answer.
   11678 	 */
   11679 	result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
   11680 	if (result != ISC_R_SUCCESS) {
   11681 		dns_zone_log(zone, ISC_LOG_INFO,
   11682 			     "refreshing stub: unable to save NS records "
   11683 			     "from master %s (source %s)", master, source);
   11684 		goto next_master;
   11685 	}
   11686 
   11687 	/*
   11688 	 * Tidy up.
   11689 	 */
   11690 	dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
   11691 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   11692 	if (zone->db == NULL)
   11693 		zone_attachdb(zone, stub->db);
   11694 	result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
   11695 				  &refresh, &retry, &expire, NULL, NULL);
   11696 	if (result == ISC_R_SUCCESS && soacount > 0U) {
   11697 		zone->refresh = RANGE(refresh, zone->minrefresh,
   11698 				      zone->maxrefresh);
   11699 		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
   11700 		zone->expire = RANGE(expire, zone->refresh + zone->retry,
   11701 				     DNS_MAX_EXPIRE);
   11702 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   11703 	}
   11704 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   11705 	dns_db_detach(&stub->db);
   11706 
   11707 	dns_message_destroy(&msg);
   11708 	isc_event_free(&event);
   11709 	dns_request_destroy(&zone->request);
   11710 
   11711 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   11712 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   11713 	DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
   11714 	isc_interval_set(&i, zone->expire, 0);
   11715 	DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
   11716 
   11717 	if (zone->masterfile != NULL)
   11718 		zone_needdump(zone, 0);
   11719 
   11720 	zone_settimer(zone, &now);
   11721 	goto free_stub;
   11722 
   11723  next_master:
   11724 	if (stub->version != NULL)
   11725 		dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
   11726 	if (stub->db != NULL)
   11727 		dns_db_detach(&stub->db);
   11728 	if (msg != NULL)
   11729 		dns_message_destroy(&msg);
   11730 	isc_event_free(&event);
   11731 	dns_request_destroy(&zone->request);
   11732 	/*
   11733 	 * Skip to next failed / untried master.
   11734 	 */
   11735 	do {
   11736 		zone->curmaster++;
   11737 	} while (zone->curmaster < zone->masterscnt &&
   11738 		 zone->mastersok[zone->curmaster]);
   11739 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
   11740 	if (exiting || zone->curmaster >= zone->masterscnt) {
   11741 		isc_boolean_t done = ISC_TRUE;
   11742 		if (!exiting &&
   11743 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
   11744 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   11745 			/*
   11746 			 * Did we get a good answer from all the masters?
   11747 			 */
   11748 			for (j = 0; j < zone->masterscnt; j++)
   11749 				if (zone->mastersok[j] == ISC_FALSE) {
   11750 					done = ISC_FALSE;
   11751 					break;
   11752 				}
   11753 		} else
   11754 			done = ISC_TRUE;
   11755 		if (!done) {
   11756 			zone->curmaster = 0;
   11757 			/*
   11758 			 * Find the next failed master.
   11759 			 */
   11760 			while (zone->curmaster < zone->masterscnt &&
   11761 			       zone->mastersok[zone->curmaster])
   11762 				zone->curmaster++;
   11763 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
   11764 		} else {
   11765 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   11766 
   11767 			zone_settimer(zone, &now);
   11768 			goto free_stub;
   11769 		}
   11770 	}
   11771 	queue_soa_query(zone);
   11772 	goto free_stub;
   11773 
   11774  same_master:
   11775 	if (msg != NULL)
   11776 		dns_message_destroy(&msg);
   11777 	isc_event_free(&event);
   11778 	dns_request_destroy(&zone->request);
   11779 	ns_query(zone, NULL, stub);
   11780 	UNLOCK_ZONE(zone);
   11781 	goto done;
   11782 
   11783  free_stub:
   11784 	UNLOCK_ZONE(zone);
   11785 	stub->magic = 0;
   11786 	dns_zone_idetach(&stub->zone);
   11787 	INSIST(stub->db == NULL);
   11788 	INSIST(stub->version == NULL);
   11789 	isc_mem_put(stub->mctx, stub, sizeof(*stub));
   11790 
   11791  done:
   11792 	INSIST(event == NULL);
   11793 	return;
   11794 }
   11795 
   11796 /*
   11797  * Get the EDNS EXPIRE option from the response and if it exists trim
   11798  * expire to be not more than it.
   11799  */
   11800 static void
   11801 get_edns_expire(dns_zone_t * zone, dns_message_t *message,
   11802 		isc_uint32_t *expirep)
   11803 {
   11804 	isc_result_t result;
   11805 	isc_uint32_t expire;
   11806 	dns_rdata_t rdata = DNS_RDATA_INIT;
   11807 	isc_buffer_t optbuf;
   11808 	isc_uint16_t optcode;
   11809 	isc_uint16_t optlen;
   11810 
   11811 	REQUIRE(expirep != NULL);
   11812 	REQUIRE(message != NULL);
   11813 
   11814 	if (message->opt == NULL)
   11815 		return;
   11816 
   11817 	result = dns_rdataset_first(message->opt);
   11818 	if (result == ISC_R_SUCCESS) {
   11819 		dns_rdataset_current(message->opt, &rdata);
   11820 		isc_buffer_init(&optbuf, rdata.data, rdata.length);
   11821 		isc_buffer_add(&optbuf, rdata.length);
   11822 		while (isc_buffer_remaininglength(&optbuf) >= 4) {
   11823 			optcode = isc_buffer_getuint16(&optbuf);
   11824 			optlen = isc_buffer_getuint16(&optbuf);
   11825 			/*
   11826 			 * A EDNS EXPIRE response has a length of 4.
   11827 			 */
   11828 			if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
   11829 				isc_buffer_forward(&optbuf, optlen);
   11830 				continue;
   11831 			}
   11832 			expire = isc_buffer_getuint32(&optbuf);
   11833 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   11834 				     "got EDNS EXPIRE of %u", expire);
   11835 			/*
   11836 			 * Trim *expirep?
   11837 			 */
   11838 			if (expire < *expirep)
   11839 				*expirep = expire;
   11840 			break;
   11841 		}
   11842 	}
   11843 }
   11844 
   11845 /*
   11846  * Set the file modification time zone->expire seconds before expiretime.
   11847  */
   11848 static void
   11849 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
   11850 	isc_result_t result;
   11851 	isc_time_t when;
   11852 	isc_interval_t i;
   11853 
   11854 	isc_interval_set(&i, zone->expire, 0);
   11855 	result = isc_time_subtract(expiretime, &i, &when);
   11856 	if (result != ISC_R_SUCCESS)
   11857 		return;
   11858 
   11859 	result = ISC_R_FAILURE;
   11860 	if (zone->journal != NULL)
   11861 		result = isc_file_settime(zone->journal, &when);
   11862 	if (result == ISC_R_SUCCESS &&
   11863 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   11864 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
   11865 		result = isc_file_settime(zone->masterfile, &when);
   11866 	else if (result != ISC_R_SUCCESS)
   11867 		result = isc_file_settime(zone->masterfile, &when);
   11868 
   11869 	/*
   11870 	 * Someone removed the file from underneath us!
   11871 	 */
   11872 	if (result == ISC_R_FILENOTFOUND) {
   11873 		zone_needdump(zone, DNS_DUMP_DELAY);
   11874 	} else if (result != ISC_R_SUCCESS)
   11875 		dns_zone_log(zone, ISC_LOG_ERROR, "refresh: could not set "
   11876 			     "file modification time of '%s': %s",
   11877 			     zone->masterfile, dns_result_totext(result));
   11878 }
   11879 
   11880 /*
   11881  * An SOA query has finished (successfully or not).
   11882  */
   11883 static void
   11884 refresh_callback(isc_task_t *task, isc_event_t *event) {
   11885 	const char me[] = "refresh_callback";
   11886 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
   11887 	dns_zone_t *zone;
   11888 	dns_message_t *msg = NULL;
   11889 	isc_uint32_t soacnt, cnamecnt, soacount, nscount;
   11890 	isc_time_t now;
   11891 	char master[ISC_SOCKADDR_FORMATSIZE];
   11892 	char source[ISC_SOCKADDR_FORMATSIZE];
   11893 	dns_rdataset_t *rdataset = NULL;
   11894 	dns_rdata_t rdata = DNS_RDATA_INIT;
   11895 	dns_rdata_soa_t soa;
   11896 	isc_result_t result;
   11897 	isc_uint32_t serial, oldserial = 0;
   11898 	unsigned int j;
   11899 	isc_boolean_t do_queue_xfrin = ISC_FALSE;
   11900 
   11901 	zone = revent->ev_arg;
   11902 	INSIST(DNS_ZONE_VALID(zone));
   11903 
   11904 	UNUSED(task);
   11905 
   11906 	ENTER;
   11907 
   11908 	TIME_NOW(&now);
   11909 
   11910 	LOCK_ZONE(zone);
   11911 
   11912 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   11913 		isc_event_free(&event);
   11914 		dns_request_destroy(&zone->request);
   11915 		goto detach;
   11916 	}
   11917 
   11918 	/*
   11919 	 * if timeout log and next master;
   11920 	 */
   11921 
   11922 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
   11923 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   11924 
   11925 	if (revent->result != ISC_R_SUCCESS) {
   11926 		if (revent->result == ISC_R_TIMEDOUT &&
   11927 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   11928 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   11929 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   11930 				     "refresh: timeout retrying without EDNS "
   11931 				     "master %s (source %s)", master, source);
   11932 			goto same_master;
   11933 		}
   11934 		if (revent->result == ISC_R_TIMEDOUT &&
   11935 		    !dns_request_usedtcp(revent->request)) {
   11936 			dns_zone_log(zone, ISC_LOG_INFO,
   11937 				     "refresh: retry limit for "
   11938 				     "master %s exceeded (source %s)",
   11939 				     master, source);
   11940 			/* Try with slave with TCP. */
   11941 			if ((zone->type == dns_zone_slave ||
   11942 			     zone->type == dns_zone_redirect) &&
   11943 			    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
   11944 				if (!dns_zonemgr_unreachable(zone->zmgr,
   11945 							     &zone->masteraddr,
   11946 							     &zone->sourceaddr,
   11947 							     &now))
   11948 				{
   11949 					DNS_ZONE_SETFLAG(zone,
   11950 						     DNS_ZONEFLG_SOABEFOREAXFR);
   11951 					goto tcp_transfer;
   11952 				}
   11953 				dns_zone_log(zone, ISC_LOG_DEBUG(1),
   11954 					     "refresh: skipped tcp fallback "
   11955 					     "as master %s (source %s) is "
   11956 					     "unreachable (cached)",
   11957 					      master, source);
   11958 			}
   11959 		} else
   11960 			dns_zone_log(zone, ISC_LOG_INFO,
   11961 				     "refresh: failure trying master "
   11962 				     "%s (source %s): %s", master, source,
   11963 				     dns_result_totext(revent->result));
   11964 		goto next_master;
   11965 	}
   11966 
   11967 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
   11968 	if (result != ISC_R_SUCCESS)
   11969 		goto next_master;
   11970 	result = dns_request_getresponse(revent->request, msg, 0);
   11971 	if (result != ISC_R_SUCCESS) {
   11972 		dns_zone_log(zone, ISC_LOG_INFO,
   11973 			     "refresh: failure trying master "
   11974 			     "%s (source %s): %s", master, source,
   11975 			     dns_result_totext(result));
   11976 		goto next_master;
   11977 	}
   11978 
   11979 	/*
   11980 	 * Unexpected rcode.
   11981 	 */
   11982 	if (msg->rcode != dns_rcode_noerror) {
   11983 		char rcode[128];
   11984 		isc_buffer_t rb;
   11985 
   11986 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   11987 		(void)dns_rcode_totext(msg->rcode, &rb);
   11988 
   11989 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
   11990 		    (msg->rcode == dns_rcode_servfail ||
   11991 		     msg->rcode == dns_rcode_notimp ||
   11992 		     msg->rcode == dns_rcode_formerr)) {
   11993 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   11994 				     "refresh: rcode (%.*s) retrying without "
   11995 				     "EDNS master %s (source %s)",
   11996 				     (int)rb.used, rcode, master, source);
   11997 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   11998 			goto same_master;
   11999 		}
   12000 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
   12001 		    msg->rcode == dns_rcode_badvers) {
   12002 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   12003 				     "refresh: rcode (%.*s) retrying without "
   12004 				     "EDNS EXPIRE OPTION master %s (source %s)",
   12005 				     (int)rb.used, rcode, master, source);
   12006 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   12007 			goto same_master;
   12008 		}
   12009 		dns_zone_log(zone, ISC_LOG_INFO,
   12010 			     "refresh: unexpected rcode (%.*s) from "
   12011 			     "master %s (source %s)", (int)rb.used, rcode,
   12012 			     master, source);
   12013 		/*
   12014 		 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
   12015 		 */
   12016 		if (msg->rcode == dns_rcode_refused &&
   12017 		    (zone->type == dns_zone_slave ||
   12018 		     zone->type == dns_zone_redirect))
   12019 			goto tcp_transfer;
   12020 		goto next_master;
   12021 	}
   12022 
   12023 	/*
   12024 	 * If truncated punt to zone transfer which will query again.
   12025 	 */
   12026 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
   12027 		if (zone->type == dns_zone_slave ||
   12028 		    zone->type == dns_zone_redirect) {
   12029 			dns_zone_log(zone, ISC_LOG_INFO,
   12030 				     "refresh: truncated UDP answer, "
   12031 				     "initiating TCP zone xfer "
   12032 				     "for master %s (source %s)",
   12033 				     master, source);
   12034 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
   12035 			goto tcp_transfer;
   12036 		} else {
   12037 			INSIST(zone->type == dns_zone_stub);
   12038 			if (dns_request_usedtcp(revent->request)) {
   12039 				dns_zone_log(zone, ISC_LOG_INFO,
   12040 					     "refresh: truncated TCP response "
   12041 					     "from master %s (source %s)",
   12042 					     master, source);
   12043 				goto next_master;
   12044 			}
   12045 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
   12046 			goto same_master;
   12047 		}
   12048 	}
   12049 
   12050 	/*
   12051 	 * if non-auth log and next master;
   12052 	 */
   12053 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
   12054 		dns_zone_log(zone, ISC_LOG_INFO,
   12055 			     "refresh: non-authoritative answer from "
   12056 			     "master %s (source %s)", master, source);
   12057 		goto next_master;
   12058 	}
   12059 
   12060 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
   12061 	soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
   12062 	nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
   12063 	soacount = message_count(msg, DNS_SECTION_AUTHORITY,
   12064 				 dns_rdatatype_soa);
   12065 
   12066 	/*
   12067 	 * There should not be a CNAME record at top of zone.
   12068 	 */
   12069 	if (cnamecnt != 0) {
   12070 		dns_zone_log(zone, ISC_LOG_INFO,
   12071 			     "refresh: CNAME at top of zone "
   12072 			     "in master %s (source %s)", master, source);
   12073 		goto next_master;
   12074 	}
   12075 
   12076 	/*
   12077 	 * if referral log and next master;
   12078 	 */
   12079 	if (soacnt == 0 && soacount == 0 && nscount != 0) {
   12080 		dns_zone_log(zone, ISC_LOG_INFO,
   12081 			     "refresh: referral response "
   12082 			     "from master %s (source %s)", master, source);
   12083 		goto next_master;
   12084 	}
   12085 
   12086 	/*
   12087 	 * if nodata log and next master;
   12088 	 */
   12089 	if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
   12090 		dns_zone_log(zone, ISC_LOG_INFO,
   12091 			     "refresh: NODATA response "
   12092 			     "from master %s (source %s)", master, source);
   12093 		goto next_master;
   12094 	}
   12095 
   12096 	/*
   12097 	 * Only one soa at top of zone.
   12098 	 */
   12099 	if (soacnt != 1) {
   12100 		dns_zone_log(zone, ISC_LOG_INFO,
   12101 			     "refresh: answer SOA count (%d) != 1 "
   12102 			     "from master %s (source %s)",
   12103 			     soacnt, master, source);
   12104 		goto next_master;
   12105 	}
   12106 
   12107 	/*
   12108 	 * Extract serial
   12109 	 */
   12110 	rdataset = NULL;
   12111 	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
   12112 				      dns_rdatatype_soa, dns_rdatatype_none,
   12113 				      NULL, &rdataset);
   12114 	if (result != ISC_R_SUCCESS) {
   12115 		dns_zone_log(zone, ISC_LOG_INFO,
   12116 			     "refresh: unable to get SOA record "
   12117 			     "from master %s (source %s)", master, source);
   12118 		goto next_master;
   12119 	}
   12120 
   12121 	result = dns_rdataset_first(rdataset);
   12122 	if (result != ISC_R_SUCCESS) {
   12123 		dns_zone_log(zone, ISC_LOG_INFO,
   12124 			     "refresh: dns_rdataset_first() failed");
   12125 		goto next_master;
   12126 	}
   12127 
   12128 	dns_rdataset_current(rdataset, &rdata);
   12129 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   12130 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   12131 
   12132 	serial = soa.serial;
   12133 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
   12134 		unsigned int dbsoacount;
   12135 		result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
   12136 					  &oldserial, NULL, NULL, NULL, NULL,
   12137 					  NULL);
   12138 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   12139 		RUNTIME_CHECK(dbsoacount > 0U);
   12140 		zone_debuglog(zone, me, 1, "serial: new %u, old %u",
   12141 			      serial, oldserial);
   12142 	} else
   12143 		zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
   12144 			      serial);
   12145 
   12146 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
   12147 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
   12148 	    isc_serial_gt(serial, oldserial)) {
   12149 		if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
   12150 					    &zone->sourceaddr, &now))
   12151 		{
   12152 			dns_zone_log(zone, ISC_LOG_INFO,
   12153 				     "refresh: skipping %s as master %s "
   12154 				     "(source %s) is unreachable (cached)",
   12155 				     (zone->type == dns_zone_slave ||
   12156 				      zone->type == dns_zone_redirect) ?
   12157 				     "zone transfer" : "NS query",
   12158 				     master, source);
   12159 			goto next_master;
   12160 		}
   12161  tcp_transfer:
   12162 		isc_event_free(&event);
   12163 		dns_request_destroy(&zone->request);
   12164 		if (zone->type == dns_zone_slave ||
   12165 		    zone->type == dns_zone_redirect) {
   12166 			do_queue_xfrin = ISC_TRUE;
   12167 		} else {
   12168 			INSIST(zone->type == dns_zone_stub);
   12169 			ns_query(zone, rdataset, NULL);
   12170 		}
   12171 		if (msg != NULL)
   12172 			dns_message_destroy(&msg);
   12173 	} else if (isc_serial_eq(soa.serial, oldserial)) {
   12174 		isc_time_t expiretime;
   12175 		isc_uint32_t expire;
   12176 
   12177 		/*
   12178 		 * Compute the new expire time based on this response.
   12179 		 */
   12180 		expire = zone->expire;
   12181 		get_edns_expire(zone, msg, &expire);
   12182 		DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
   12183 
   12184 		/*
   12185 		 * Has the expire time improved?
   12186 		 */
   12187 		if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
   12188 			zone->expiretime = expiretime;
   12189 			if (zone->masterfile != NULL)
   12190 				setmodtime(zone, &expiretime);
   12191 		}
   12192 
   12193 		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
   12194 		zone->mastersok[zone->curmaster] = ISC_TRUE;
   12195 		goto next_master;
   12196 	} else {
   12197 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
   12198 			dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
   12199 				     "received from master %s < ours (%u)",
   12200 				     soa.serial, master, oldserial);
   12201 		else
   12202 			zone_debuglog(zone, me, 1, "ahead");
   12203 		zone->mastersok[zone->curmaster] = ISC_TRUE;
   12204 		goto next_master;
   12205 	}
   12206 	if (msg != NULL)
   12207 		dns_message_destroy(&msg);
   12208 	goto detach;
   12209 
   12210  next_master:
   12211 	if (msg != NULL)
   12212 		dns_message_destroy(&msg);
   12213 	isc_event_free(&event);
   12214 	dns_request_destroy(&zone->request);
   12215 	/*
   12216 	 * Skip to next failed / untried master.
   12217 	 */
   12218 	do {
   12219 		zone->curmaster++;
   12220 	} while (zone->curmaster < zone->masterscnt &&
   12221 		 zone->mastersok[zone->curmaster]);
   12222 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
   12223 	if (zone->curmaster >= zone->masterscnt) {
   12224 		isc_boolean_t done = ISC_TRUE;
   12225 		if (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] == ISC_FALSE) {
   12232 					done = ISC_FALSE;
   12233 					break;
   12234 				}
   12235 		} else
   12236 			done = ISC_TRUE;
   12237 		if (!done) {
   12238 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
   12239 			zone->curmaster = 0;
   12240 			/*
   12241 			 * Find the next failed master.
   12242 			 */
   12243 			while (zone->curmaster < zone->masterscnt &&
   12244 			       zone->mastersok[zone->curmaster])
   12245 				zone->curmaster++;
   12246 			goto requeue;
   12247 		}
   12248 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   12249 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
   12250 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   12251 			zone->refreshtime = now;
   12252 		}
   12253 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
   12254 		zone_settimer(zone, &now);
   12255 		goto detach;
   12256 	}
   12257 
   12258  requeue:
   12259 	queue_soa_query(zone);
   12260 	goto detach;
   12261 
   12262  same_master:
   12263 	if (msg != NULL)
   12264 		dns_message_destroy(&msg);
   12265 	isc_event_free(&event);
   12266 	dns_request_destroy(&zone->request);
   12267 	queue_soa_query(zone);
   12268 
   12269  detach:
   12270 	UNLOCK_ZONE(zone);
   12271 	if (do_queue_xfrin)
   12272 		queue_xfrin(zone);
   12273 	dns_zone_idetach(&zone);
   12274 	return;
   12275 }
   12276 
   12277 static void
   12278 queue_soa_query(dns_zone_t *zone) {
   12279 	const char me[] = "queue_soa_query";
   12280 	isc_event_t *e;
   12281 	dns_zone_t *dummy = NULL;
   12282 	isc_result_t result;
   12283 
   12284 	ENTER;
   12285 	/*
   12286 	 * Locked by caller
   12287 	 */
   12288 	REQUIRE(LOCKED_ZONE(zone));
   12289 
   12290 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   12291 		cancel_refresh(zone);
   12292 		return;
   12293 	}
   12294 
   12295 	e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
   12296 			       soa_query, zone, sizeof(isc_event_t));
   12297 	if (e == NULL) {
   12298 		cancel_refresh(zone);
   12299 		return;
   12300 	}
   12301 
   12302 	/*
   12303 	 * Attach so that we won't clean up
   12304 	 * until the event is delivered.
   12305 	 */
   12306 	zone_iattach(zone, &dummy);
   12307 
   12308 	e->ev_arg = zone;
   12309 	e->ev_sender = NULL;
   12310 	result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
   12311 	if (result != ISC_R_SUCCESS) {
   12312 		zone_idetach(&dummy);
   12313 		isc_event_free(&e);
   12314 		cancel_refresh(zone);
   12315 	}
   12316 }
   12317 
   12318 static inline isc_result_t
   12319 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
   12320 	     dns_message_t **messagep)
   12321 {
   12322 	dns_message_t *message = NULL;
   12323 	dns_name_t *qname = NULL;
   12324 	dns_rdataset_t *qrdataset = NULL;
   12325 	isc_result_t result;
   12326 
   12327 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
   12328 				    &message);
   12329 	if (result != ISC_R_SUCCESS)
   12330 		goto cleanup;
   12331 
   12332 	message->opcode = dns_opcode_query;
   12333 	message->rdclass = zone->rdclass;
   12334 
   12335 	result = dns_message_gettempname(message, &qname);
   12336 	if (result != ISC_R_SUCCESS)
   12337 		goto cleanup;
   12338 
   12339 	result = dns_message_gettemprdataset(message, &qrdataset);
   12340 	if (result != ISC_R_SUCCESS)
   12341 		goto cleanup;
   12342 
   12343 	/*
   12344 	 * Make question.
   12345 	 */
   12346 	dns_name_init(qname, NULL);
   12347 	dns_name_clone(&zone->origin, qname);
   12348 	dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
   12349 	ISC_LIST_APPEND(qname->list, qrdataset, link);
   12350 	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
   12351 
   12352 	*messagep = message;
   12353 	return (ISC_R_SUCCESS);
   12354 
   12355  cleanup:
   12356 	if (qname != NULL)
   12357 		dns_message_puttempname(message, &qname);
   12358 	if (qrdataset != NULL)
   12359 		dns_message_puttemprdataset(message, &qrdataset);
   12360 	if (message != NULL)
   12361 		dns_message_destroy(&message);
   12362 	return (result);
   12363 }
   12364 
   12365 static isc_result_t
   12366 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid,
   12367 	isc_boolean_t reqexpire)
   12368 {
   12369 	isc_result_t result;
   12370 	dns_rdataset_t *rdataset = NULL;
   12371 	dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
   12372 	int count = 0;
   12373 
   12374 	/* Set EDNS options if applicable */
   12375 	if (reqnsid) {
   12376 		INSIST(count < DNS_EDNSOPTIONS);
   12377 		ednsopts[count].code = DNS_OPT_NSID;
   12378 		ednsopts[count].length = 0;
   12379 		ednsopts[count].value = NULL;
   12380 		count++;
   12381 	}
   12382 	if (reqexpire) {
   12383 		INSIST(count < DNS_EDNSOPTIONS);
   12384 		ednsopts[count].code = DNS_OPT_EXPIRE;
   12385 		ednsopts[count].length = 0;
   12386 		ednsopts[count].value = NULL;
   12387 		count++;
   12388 	}
   12389 	result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
   12390 				      ednsopts, count);
   12391 	if (result != ISC_R_SUCCESS)
   12392 		return (result);
   12393 
   12394 	return (dns_message_setopt(message, rdataset));
   12395 }
   12396 
   12397 static void
   12398 soa_query(isc_task_t *task, isc_event_t *event) {
   12399 	const char me[] = "soa_query";
   12400 	isc_result_t result = ISC_R_FAILURE;
   12401 	dns_message_t *message = NULL;
   12402 	dns_zone_t *zone = event->ev_arg;
   12403 	dns_zone_t *dummy = NULL;
   12404 	isc_netaddr_t masterip;
   12405 	dns_tsigkey_t *key = NULL;
   12406 	isc_uint32_t options;
   12407 	isc_boolean_t cancel = ISC_TRUE;
   12408 	int timeout;
   12409 	isc_boolean_t have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
   12410 	isc_uint16_t udpsize = SEND_BUFFER_SIZE;
   12411 	isc_dscp_t dscp = -1;
   12412 
   12413 	REQUIRE(DNS_ZONE_VALID(zone));
   12414 
   12415 	UNUSED(task);
   12416 
   12417 	ENTER;
   12418 
   12419 	LOCK_ZONE(zone);
   12420 	if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
   12421 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
   12422 	    zone->view->requestmgr == NULL) {
   12423 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
   12424 			cancel = ISC_FALSE;
   12425 		goto cleanup;
   12426 	}
   12427 
   12428  again:
   12429 	result = create_query(zone, dns_rdatatype_soa, &message);
   12430 	if (result != ISC_R_SUCCESS)
   12431 		goto cleanup;
   12432 
   12433 	INSIST(zone->masterscnt > 0);
   12434 	INSIST(zone->curmaster < zone->masterscnt);
   12435 
   12436 	zone->masteraddr = zone->masters[zone->curmaster];
   12437 
   12438 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
   12439 	/*
   12440 	 * First, look for a tsig key in the master statement, then
   12441 	 * try for a server key.
   12442 	 */
   12443 	if ((zone->masterkeynames != NULL) &&
   12444 	    (zone->masterkeynames[zone->curmaster] != NULL)) {
   12445 		dns_view_t *view = dns_zone_getview(zone);
   12446 		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
   12447 		result = dns_view_gettsig(view, keyname, &key);
   12448 		if (result != ISC_R_SUCCESS) {
   12449 			char namebuf[DNS_NAME_FORMATSIZE];
   12450 			dns_name_format(keyname, namebuf, sizeof(namebuf));
   12451 			dns_zone_log(zone, ISC_LOG_ERROR,
   12452 				     "unable to find key: %s", namebuf);
   12453 			goto skip_master;
   12454 		}
   12455 	}
   12456 	if (key == NULL) {
   12457 		result = dns_view_getpeertsig(zone->view, &masterip, &key);
   12458 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   12459 			char addrbuf[ISC_NETADDR_FORMATSIZE];
   12460 			isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
   12461 			dns_zone_log(zone, ISC_LOG_ERROR,
   12462 				     "unable to find TSIG key for %s", addrbuf);
   12463 			goto skip_master;
   12464 		}
   12465 	}
   12466 
   12467 	options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
   12468 		  DNS_REQUESTOPT_TCP : 0;
   12469 	have_xfrsource = have_xfrdscp = ISC_FALSE;
   12470 	reqnsid = zone->view->requestnsid;
   12471 	reqexpire = zone->requestexpire;
   12472 	if (zone->view->peers != NULL) {
   12473 		dns_peer_t *peer = NULL;
   12474 		isc_boolean_t edns, usetcp;
   12475 		result = dns_peerlist_peerbyaddr(zone->view->peers,
   12476 						 &masterip, &peer);
   12477 		if (result == ISC_R_SUCCESS) {
   12478 			result = dns_peer_getsupportedns(peer, &edns);
   12479 			if (result == ISC_R_SUCCESS && !edns)
   12480 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   12481 			result = dns_peer_gettransfersource(peer,
   12482 							    &zone->sourceaddr);
   12483 			if (result == ISC_R_SUCCESS)
   12484 				have_xfrsource = ISC_TRUE;
   12485 			(void)dns_peer_gettransferdscp(peer, &dscp);
   12486 			if (dscp != -1)
   12487 				have_xfrdscp = ISC_TRUE;
   12488 			if (zone->view->resolver != NULL)
   12489 				udpsize =
   12490 				  dns_resolver_getudpsize(zone->view->resolver);
   12491 			(void)dns_peer_getudpsize(peer, &udpsize);
   12492 			(void)dns_peer_getrequestnsid(peer, &reqnsid);
   12493 			(void)dns_peer_getrequestexpire(peer, &reqexpire);
   12494 			result = dns_peer_getforcetcp(peer, &usetcp);
   12495 			if (result == ISC_R_SUCCESS && usetcp)
   12496 				options |= DNS_REQUESTOPT_TCP;
   12497 		}
   12498 	}
   12499 
   12500 	switch (isc_sockaddr_pf(&zone->masteraddr)) {
   12501 	case PF_INET:
   12502 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   12503 			if (isc_sockaddr_equal(&zone->altxfrsource4,
   12504 					       &zone->xfrsource4))
   12505 				goto skip_master;
   12506 			zone->sourceaddr = zone->altxfrsource4;
   12507 			if (!have_xfrdscp)
   12508 				dscp = zone->altxfrsource4dscp;
   12509 		} else if (!have_xfrsource) {
   12510 			zone->sourceaddr = zone->xfrsource4;
   12511 			if (!have_xfrdscp)
   12512 				dscp = zone->xfrsource4dscp;
   12513 		}
   12514 		break;
   12515 	case PF_INET6:
   12516 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   12517 			if (isc_sockaddr_equal(&zone->altxfrsource6,
   12518 					       &zone->xfrsource6))
   12519 				goto skip_master;
   12520 			zone->sourceaddr = zone->altxfrsource6;
   12521 			if (!have_xfrdscp)
   12522 				dscp = zone->altxfrsource6dscp;
   12523 		} else if (!have_xfrsource) {
   12524 			zone->sourceaddr = zone->xfrsource6;
   12525 			if (!have_xfrdscp)
   12526 				dscp = zone->xfrsource6dscp;
   12527 		}
   12528 		break;
   12529 	default:
   12530 		result = ISC_R_NOTIMPLEMENTED;
   12531 		goto cleanup;
   12532 	}
   12533 
   12534 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   12535 		result = add_opt(message, udpsize, reqnsid, reqexpire);
   12536 		if (result != ISC_R_SUCCESS)
   12537 			zone_debuglog(zone, me, 1,
   12538 				      "unable to add opt record: %s",
   12539 				      dns_result_totext(result));
   12540 	}
   12541 
   12542 	zone_iattach(zone, &dummy);
   12543 	timeout = 15;
   12544 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
   12545 		timeout = 30;
   12546 	result = dns_request_createvia4(zone->view->requestmgr, message,
   12547 					&zone->sourceaddr, &zone->masteraddr,
   12548 					dscp, options, key, timeout * 3,
   12549 					timeout, 0, zone->task,
   12550 					refresh_callback, zone, &zone->request);
   12551 	if (result != ISC_R_SUCCESS) {
   12552 		zone_idetach(&dummy);
   12553 		zone_debuglog(zone, me, 1,
   12554 			      "dns_request_createvia4() failed: %s",
   12555 			      dns_result_totext(result));
   12556 		goto skip_master;
   12557 	} else {
   12558 		if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
   12559 			inc_stats(zone, dns_zonestatscounter_soaoutv4);
   12560 		else
   12561 			inc_stats(zone, dns_zonestatscounter_soaoutv6);
   12562 	}
   12563 	cancel = ISC_FALSE;
   12564 
   12565  cleanup:
   12566 	if (key != NULL)
   12567 		dns_tsigkey_detach(&key);
   12568 	if (result != ISC_R_SUCCESS)
   12569 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   12570 	if (message != NULL)
   12571 		dns_message_destroy(&message);
   12572 	if (cancel)
   12573 		cancel_refresh(zone);
   12574 	isc_event_free(&event);
   12575 	UNLOCK_ZONE(zone);
   12576 	dns_zone_idetach(&zone);
   12577 	return;
   12578 
   12579  skip_master:
   12580 	if (key != NULL)
   12581 		dns_tsigkey_detach(&key);
   12582 	dns_message_destroy(&message);
   12583 	/*
   12584 	 * Skip to next failed / untried master.
   12585 	 */
   12586 	do {
   12587 		zone->curmaster++;
   12588 	} while (zone->curmaster < zone->masterscnt &&
   12589 		 zone->mastersok[zone->curmaster]);
   12590 	if (zone->curmaster < zone->masterscnt)
   12591 		goto again;
   12592 	zone->curmaster = 0;
   12593 	goto cleanup;
   12594 }
   12595 
   12596 static void
   12597 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
   12598 	const char me[] = "ns_query";
   12599 	isc_result_t result;
   12600 	dns_message_t *message = NULL;
   12601 	isc_netaddr_t masterip;
   12602 	dns_tsigkey_t *key = NULL;
   12603 	dns_dbnode_t *node = NULL;
   12604 	int timeout;
   12605 	isc_boolean_t have_xfrsource = ISC_FALSE, have_xfrdscp = ISC_FALSE;
   12606 	isc_boolean_t reqnsid;
   12607 	isc_uint16_t udpsize = SEND_BUFFER_SIZE;
   12608 	isc_dscp_t dscp = -1;
   12609 
   12610 	REQUIRE(DNS_ZONE_VALID(zone));
   12611 	REQUIRE(LOCKED_ZONE(zone));
   12612 	REQUIRE((soardataset != NULL && stub == NULL) ||
   12613 		(soardataset == NULL && stub != NULL));
   12614 	REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
   12615 
   12616 	ENTER;
   12617 
   12618 	if (stub == NULL) {
   12619 		stub = isc_mem_get(zone->mctx, sizeof(*stub));
   12620 		if (stub == NULL)
   12621 			goto cleanup;
   12622 		stub->magic = STUB_MAGIC;
   12623 		stub->mctx = zone->mctx;
   12624 		stub->zone = NULL;
   12625 		stub->db = NULL;
   12626 		stub->version = NULL;
   12627 
   12628 		/*
   12629 		 * Attach so that the zone won't disappear from under us.
   12630 		 */
   12631 		zone_iattach(zone, &stub->zone);
   12632 
   12633 		/*
   12634 		 * If a db exists we will update it, otherwise we create a
   12635 		 * new one and attach it to the zone once we have the NS
   12636 		 * RRset and glue.
   12637 		 */
   12638 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   12639 		if (zone->db != NULL) {
   12640 			dns_db_attach(zone->db, &stub->db);
   12641 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   12642 		} else {
   12643 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   12644 
   12645 			INSIST(zone->db_argc >= 1);
   12646 			result = dns_db_create(zone->mctx, zone->db_argv[0],
   12647 					       &zone->origin, dns_dbtype_stub,
   12648 					       zone->rdclass,
   12649 					       zone->db_argc - 1,
   12650 					       zone->db_argv + 1,
   12651 					       &stub->db);
   12652 			if (result != ISC_R_SUCCESS) {
   12653 				dns_zone_log(zone, ISC_LOG_ERROR,
   12654 					     "refreshing stub: "
   12655 					     "could not create "
   12656 					     "database: %s",
   12657 					     dns_result_totext(result));
   12658 				goto cleanup;
   12659 			}
   12660 			dns_db_settask(stub->db, zone->task);
   12661 		}
   12662 
   12663 		result = dns_db_newversion(stub->db, &stub->version);
   12664 		if (result != ISC_R_SUCCESS) {
   12665 			dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
   12666 				     "dns_db_newversion() failed: %s",
   12667 				     dns_result_totext(result));
   12668 			goto cleanup;
   12669 		}
   12670 
   12671 		/*
   12672 		 * Update SOA record.
   12673 		 */
   12674 		result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
   12675 					 &node);
   12676 		if (result != ISC_R_SUCCESS) {
   12677 			dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
   12678 				     "dns_db_findnode() failed: %s",
   12679 				     dns_result_totext(result));
   12680 			goto cleanup;
   12681 		}
   12682 
   12683 		result = dns_db_addrdataset(stub->db, node, stub->version, 0,
   12684 					    soardataset, 0, NULL);
   12685 		dns_db_detachnode(stub->db, &node);
   12686 		if (result != ISC_R_SUCCESS) {
   12687 			dns_zone_log(zone, ISC_LOG_INFO,
   12688 				     "refreshing stub: "
   12689 				     "dns_db_addrdataset() failed: %s",
   12690 				     dns_result_totext(result));
   12691 			goto cleanup;
   12692 		}
   12693 	}
   12694 
   12695 	/*
   12696 	 * XXX Optimisation: Create message when zone is setup and reuse.
   12697 	 */
   12698 	result = create_query(zone, dns_rdatatype_ns, &message);
   12699 	INSIST(result == ISC_R_SUCCESS);
   12700 
   12701 	INSIST(zone->masterscnt > 0);
   12702 	INSIST(zone->curmaster < zone->masterscnt);
   12703 	zone->masteraddr = zone->masters[zone->curmaster];
   12704 
   12705 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
   12706 	/*
   12707 	 * First, look for a tsig key in the master statement, then
   12708 	 * try for a server key.
   12709 	 */
   12710 	if ((zone->masterkeynames != NULL) &&
   12711 	    (zone->masterkeynames[zone->curmaster] != NULL)) {
   12712 		dns_view_t *view = dns_zone_getview(zone);
   12713 		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
   12714 		result = dns_view_gettsig(view, keyname, &key);
   12715 		if (result != ISC_R_SUCCESS) {
   12716 			char namebuf[DNS_NAME_FORMATSIZE];
   12717 			dns_name_format(keyname, namebuf, sizeof(namebuf));
   12718 			dns_zone_log(zone, ISC_LOG_ERROR,
   12719 				     "unable to find key: %s", namebuf);
   12720 		}
   12721 	}
   12722 	if (key == NULL)
   12723 		(void)dns_view_getpeertsig(zone->view, &masterip, &key);
   12724 
   12725 	reqnsid = zone->view->requestnsid;
   12726 	if (zone->view->peers != NULL) {
   12727 		dns_peer_t *peer = NULL;
   12728 		isc_boolean_t edns;
   12729 		result = dns_peerlist_peerbyaddr(zone->view->peers,
   12730 						 &masterip, &peer);
   12731 		if (result == ISC_R_SUCCESS) {
   12732 			result = dns_peer_getsupportedns(peer, &edns);
   12733 			if (result == ISC_R_SUCCESS && !edns)
   12734 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
   12735 			result = dns_peer_gettransfersource(peer,
   12736 							    &zone->sourceaddr);
   12737 			if (result == ISC_R_SUCCESS)
   12738 				have_xfrsource = ISC_TRUE;
   12739 			result = dns_peer_gettransferdscp(peer, &dscp);
   12740 			if (result == ISC_R_SUCCESS && dscp != -1)
   12741 				have_xfrdscp = ISC_TRUE;
   12742 			if (zone->view->resolver != NULL)
   12743 				udpsize =
   12744 				  dns_resolver_getudpsize(zone->view->resolver);
   12745 			(void)dns_peer_getudpsize(peer, &udpsize);
   12746 			(void)dns_peer_getrequestnsid(peer, &reqnsid);
   12747 		}
   12748 
   12749 	}
   12750 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
   12751 		result = add_opt(message, udpsize, reqnsid, ISC_FALSE);
   12752 		if (result != ISC_R_SUCCESS)
   12753 			zone_debuglog(zone, me, 1,
   12754 				      "unable to add opt record: %s",
   12755 				      dns_result_totext(result));
   12756 	}
   12757 
   12758 	/*
   12759 	 * Always use TCP so that we shouldn't truncate in additional section.
   12760 	 */
   12761 	switch (isc_sockaddr_pf(&zone->masteraddr)) {
   12762 	case PF_INET:
   12763 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   12764 			zone->sourceaddr = zone->altxfrsource4;
   12765 			if (!have_xfrdscp)
   12766 				dscp = zone->altxfrsource4dscp;
   12767 		} else if (!have_xfrsource) {
   12768 			zone->sourceaddr = zone->xfrsource4;
   12769 			if (!have_xfrdscp)
   12770 				dscp = zone->xfrsource4dscp;
   12771 		}
   12772 		break;
   12773 	case PF_INET6:
   12774 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   12775 			zone->sourceaddr = zone->altxfrsource6;
   12776 			if (!have_xfrdscp)
   12777 				dscp = zone->altxfrsource6dscp;
   12778 		} else if (!have_xfrsource) {
   12779 			zone->sourceaddr = zone->xfrsource6;
   12780 			if (!have_xfrdscp)
   12781 				dscp = zone->xfrsource6dscp;
   12782 		}
   12783 		break;
   12784 	default:
   12785 		result = ISC_R_NOTIMPLEMENTED;
   12786 		POST(result);
   12787 		goto cleanup;
   12788 	}
   12789 	timeout = 15;
   12790 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
   12791 		timeout = 30;
   12792 	result = dns_request_createvia4(zone->view->requestmgr, message,
   12793 					&zone->sourceaddr, &zone->masteraddr,
   12794 					dscp, DNS_REQUESTOPT_TCP, key,
   12795 					timeout * 3, timeout, 0, zone->task,
   12796 					stub_callback, stub, &zone->request);
   12797 	if (result != ISC_R_SUCCESS) {
   12798 		zone_debuglog(zone, me, 1,
   12799 			      "dns_request_createvia() failed: %s",
   12800 			      dns_result_totext(result));
   12801 		goto cleanup;
   12802 	}
   12803 	dns_message_destroy(&message);
   12804 	goto unlock;
   12805 
   12806  cleanup:
   12807 	cancel_refresh(zone);
   12808 	if (stub != NULL) {
   12809 		stub->magic = 0;
   12810 		if (stub->version != NULL)
   12811 			dns_db_closeversion(stub->db, &stub->version,
   12812 					    ISC_FALSE);
   12813 		if (stub->db != NULL)
   12814 			dns_db_detach(&stub->db);
   12815 		if (stub->zone != NULL)
   12816 			zone_idetach(&stub->zone);
   12817 		isc_mem_put(stub->mctx, stub, sizeof(*stub));
   12818 	}
   12819 	if (message != NULL)
   12820 		dns_message_destroy(&message);
   12821  unlock:
   12822 	if (key != NULL)
   12823 		dns_tsigkey_detach(&key);
   12824 	return;
   12825 }
   12826 
   12827 /*
   12828  * Handle the control event.  Note that although this event causes the zone
   12829  * to shut down, it is not a shutdown event in the sense of the task library.
   12830  */
   12831 static void
   12832 zone_shutdown(isc_task_t *task, isc_event_t *event) {
   12833 	dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
   12834 	isc_boolean_t free_needed, linked = ISC_FALSE;
   12835 	dns_zone_t *raw = NULL, *secure = NULL;
   12836 
   12837 	UNUSED(task);
   12838 	REQUIRE(DNS_ZONE_VALID(zone));
   12839 	INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
   12840 	INSIST(isc_refcount_current(&zone->erefs) == 0);
   12841 
   12842 	zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
   12843 
   12844 	/*
   12845 	 * Stop things being restarted after we cancel them below.
   12846 	 */
   12847 	LOCK_ZONE(zone);
   12848 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
   12849 	UNLOCK_ZONE(zone);
   12850 
   12851 	/*
   12852 	 * If we were waiting for xfrin quota, step out of
   12853 	 * the queue.
   12854 	 * If there's no zone manager, we can't be waiting for the
   12855 	 * xfrin quota
   12856 	 */
   12857 	if (zone->zmgr != NULL) {
   12858 		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   12859 		if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
   12860 			ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
   12861 					statelink);
   12862 			linked = ISC_TRUE;
   12863 			zone->statelist = NULL;
   12864 		}
   12865 		if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
   12866 			ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
   12867 					statelink);
   12868 			zone->statelist = NULL;
   12869 			zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
   12870 		}
   12871 		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   12872 	}
   12873 
   12874 	/*
   12875 	 * In task context, no locking required.  See zone_xfrdone().
   12876 	 */
   12877 	if (zone->xfr != NULL)
   12878 		dns_xfrin_shutdown(zone->xfr);
   12879 
   12880 	/* Safe to release the zone now */
   12881 	if (zone->zmgr != NULL)
   12882 		dns_zonemgr_releasezone(zone->zmgr, zone);
   12883 
   12884 	LOCK_ZONE(zone);
   12885 	INSIST(zone != zone->raw);
   12886 	if (linked) {
   12887 		INSIST(zone->irefs > 0);
   12888 		zone->irefs--;
   12889 	}
   12890 	if (zone->request != NULL) {
   12891 		dns_request_cancel(zone->request);
   12892 	}
   12893 
   12894 	if (zone->readio != NULL)
   12895 		zonemgr_cancelio(zone->readio);
   12896 
   12897 	if (zone->lctx != NULL)
   12898 		dns_loadctx_cancel(zone->lctx);
   12899 
   12900 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
   12901 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   12902 		if (zone->writeio != NULL)
   12903 			zonemgr_cancelio(zone->writeio);
   12904 
   12905 		if (zone->dctx != NULL)
   12906 			dns_dumpctx_cancel(zone->dctx);
   12907 	}
   12908 
   12909 	notify_cancel(zone);
   12910 
   12911 	forward_cancel(zone);
   12912 
   12913 	if (zone->timer != NULL) {
   12914 		isc_timer_detach(&zone->timer);
   12915 		INSIST(zone->irefs > 0);
   12916 		zone->irefs--;
   12917 	}
   12918 
   12919 	/*
   12920 	 * We have now canceled everything set the flag to allow exit_check()
   12921 	 * to succeed.	We must not unlock between setting this flag and
   12922 	 * calling exit_check().
   12923 	 */
   12924 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
   12925 	free_needed = exit_check(zone);
   12926 	if (inline_secure(zone)) {
   12927 		raw = zone->raw;
   12928 		zone->raw = NULL;
   12929 	}
   12930 	if (inline_raw(zone)) {
   12931 		secure = zone->secure;
   12932 		zone->secure = NULL;
   12933 	}
   12934 	UNLOCK_ZONE(zone);
   12935 	if (raw != NULL)
   12936 		dns_zone_detach(&raw);
   12937 	if (secure != NULL)
   12938 		dns_zone_idetach(&secure);
   12939 	if (free_needed)
   12940 		zone_free(zone);
   12941 }
   12942 
   12943 static void
   12944 zone_timer(isc_task_t *task, isc_event_t *event) {
   12945 	const char me[] = "zone_timer";
   12946 	dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
   12947 
   12948 	UNUSED(task);
   12949 	REQUIRE(DNS_ZONE_VALID(zone));
   12950 
   12951 	ENTER;
   12952 
   12953 	zone_maintenance(zone);
   12954 
   12955 	isc_event_free(&event);
   12956 }
   12957 
   12958 static void
   12959 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
   12960 	const char me[] = "zone_settimer";
   12961 	isc_time_t next;
   12962 	isc_result_t result;
   12963 
   12964 	REQUIRE(DNS_ZONE_VALID(zone));
   12965 	ENTER;
   12966 
   12967 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
   12968 		return;
   12969 
   12970 	isc_time_settoepoch(&next);
   12971 
   12972 	switch (zone->type) {
   12973 	case dns_zone_redirect:
   12974 		if (zone->masters != NULL)
   12975 			goto treat_as_slave;
   12976 		/* FALLTHROUGH */
   12977 
   12978 	case dns_zone_master:
   12979 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   12980 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
   12981 			next = zone->notifytime;
   12982 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   12983 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   12984 			INSIST(!isc_time_isepoch(&zone->dumptime));
   12985 			if (isc_time_isepoch(&next) ||
   12986 			    isc_time_compare(&zone->dumptime, &next) < 0)
   12987 				next = zone->dumptime;
   12988 		}
   12989 		if (zone->type == dns_zone_redirect)
   12990 			break;
   12991 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
   12992 		    !isc_time_isepoch(&zone->refreshkeytime)) {
   12993 			if (isc_time_isepoch(&next) ||
   12994 			    isc_time_compare(&zone->refreshkeytime, &next) < 0)
   12995 				next = zone->refreshkeytime;
   12996 		}
   12997 		if (!isc_time_isepoch(&zone->resigntime)) {
   12998 			if (isc_time_isepoch(&next) ||
   12999 			    isc_time_compare(&zone->resigntime, &next) < 0)
   13000 				next = zone->resigntime;
   13001 		}
   13002 		if (!isc_time_isepoch(&zone->keywarntime)) {
   13003 			if (isc_time_isepoch(&next) ||
   13004 			    isc_time_compare(&zone->keywarntime, &next) < 0)
   13005 				next = zone->keywarntime;
   13006 		}
   13007 		if (!isc_time_isepoch(&zone->signingtime)) {
   13008 			if (isc_time_isepoch(&next) ||
   13009 			    isc_time_compare(&zone->signingtime, &next) < 0)
   13010 				next = zone->signingtime;
   13011 		}
   13012 		if (!isc_time_isepoch(&zone->nsec3chaintime)) {
   13013 			if (isc_time_isepoch(&next) ||
   13014 			    isc_time_compare(&zone->nsec3chaintime, &next) < 0)
   13015 				next = zone->nsec3chaintime;
   13016 		}
   13017 		break;
   13018 
   13019 	case dns_zone_slave:
   13020 	treat_as_slave:
   13021 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
   13022 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
   13023 			next = zone->notifytime;
   13024 		/* FALLTHROUGH */
   13025 
   13026 	case dns_zone_stub:
   13027 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
   13028 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
   13029 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
   13030 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
   13031 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
   13032 		    !isc_time_isepoch(&zone->refreshtime) &&
   13033 		    (isc_time_isepoch(&next) ||
   13034 		     isc_time_compare(&zone->refreshtime, &next) < 0))
   13035 			next = zone->refreshtime;
   13036 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   13037 		    !isc_time_isepoch(&zone->expiretime)) {
   13038 			if (isc_time_isepoch(&next) ||
   13039 			     isc_time_compare(&zone->expiretime, &next) < 0)
   13040 				next = zone->expiretime;
   13041 		}
   13042 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   13043 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   13044 			INSIST(!isc_time_isepoch(&zone->dumptime));
   13045 			if (isc_time_isepoch(&next) ||
   13046 			    isc_time_compare(&zone->dumptime, &next) < 0)
   13047 				next = zone->dumptime;
   13048 		}
   13049 		break;
   13050 
   13051 	case dns_zone_key:
   13052 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
   13053 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
   13054 			INSIST(!isc_time_isepoch(&zone->dumptime));
   13055 			if (isc_time_isepoch(&next) ||
   13056 			    isc_time_compare(&zone->dumptime, &next) < 0)
   13057 				next = zone->dumptime;
   13058 		}
   13059 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
   13060 			if (isc_time_isepoch(&next) ||
   13061 			    (!isc_time_isepoch(&zone->refreshkeytime) &&
   13062 			    isc_time_compare(&zone->refreshkeytime, &next) < 0))
   13063 				next = zone->refreshkeytime;
   13064 		}
   13065 		break;
   13066 
   13067 	default:
   13068 		break;
   13069 	}
   13070 
   13071 	if (isc_time_isepoch(&next)) {
   13072 		zone_debuglog(zone, me, 10, "settimer inactive");
   13073 		result = isc_timer_reset(zone->timer, isc_timertype_inactive,
   13074 					  NULL, NULL, ISC_TRUE);
   13075 		if (result != ISC_R_SUCCESS)
   13076 			dns_zone_log(zone, ISC_LOG_ERROR,
   13077 				     "could not deactivate zone timer: %s",
   13078 				     isc_result_totext(result));
   13079 	} else {
   13080 		if (isc_time_compare(&next, now) <= 0)
   13081 			next = *now;
   13082 		result = isc_timer_reset(zone->timer, isc_timertype_once,
   13083 					 &next, NULL, ISC_TRUE);
   13084 		if (result != ISC_R_SUCCESS)
   13085 			dns_zone_log(zone, ISC_LOG_ERROR,
   13086 				     "could not reset zone timer: %s",
   13087 				     isc_result_totext(result));
   13088 	}
   13089 }
   13090 
   13091 static void
   13092 cancel_refresh(dns_zone_t *zone) {
   13093 	const char me[] = "cancel_refresh";
   13094 	isc_time_t now;
   13095 
   13096 	/*
   13097 	 * 'zone' locked by caller.
   13098 	 */
   13099 
   13100 	REQUIRE(DNS_ZONE_VALID(zone));
   13101 	REQUIRE(LOCKED_ZONE(zone));
   13102 
   13103 	ENTER;
   13104 
   13105 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   13106 	TIME_NOW(&now);
   13107 	zone_settimer(zone, &now);
   13108 }
   13109 
   13110 static isc_result_t
   13111 notify_createmessage(dns_zone_t *zone, unsigned int flags,
   13112 		     dns_message_t **messagep)
   13113 {
   13114 	dns_db_t *zonedb = NULL;
   13115 	dns_dbnode_t *node = NULL;
   13116 	dns_dbversion_t *version = NULL;
   13117 	dns_message_t *message = NULL;
   13118 	dns_rdataset_t rdataset;
   13119 	dns_rdata_t rdata = DNS_RDATA_INIT;
   13120 
   13121 	dns_name_t *tempname = NULL;
   13122 	dns_rdata_t *temprdata = NULL;
   13123 	dns_rdatalist_t *temprdatalist = NULL;
   13124 	dns_rdataset_t *temprdataset = NULL;
   13125 
   13126 	isc_result_t result;
   13127 	isc_region_t r;
   13128 	isc_buffer_t *b = NULL;
   13129 
   13130 	REQUIRE(DNS_ZONE_VALID(zone));
   13131 	REQUIRE(messagep != NULL && *messagep == NULL);
   13132 
   13133 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
   13134 				    &message);
   13135 	if (result != ISC_R_SUCCESS)
   13136 		return (result);
   13137 
   13138 	message->opcode = dns_opcode_notify;
   13139 	message->flags |= DNS_MESSAGEFLAG_AA;
   13140 	message->rdclass = zone->rdclass;
   13141 
   13142 	result = dns_message_gettempname(message, &tempname);
   13143 	if (result != ISC_R_SUCCESS)
   13144 		goto cleanup;
   13145 
   13146 	result = dns_message_gettemprdataset(message, &temprdataset);
   13147 	if (result != ISC_R_SUCCESS)
   13148 		goto cleanup;
   13149 
   13150 	/*
   13151 	 * Make question.
   13152 	 */
   13153 	dns_name_init(tempname, NULL);
   13154 	dns_name_clone(&zone->origin, tempname);
   13155 	dns_rdataset_makequestion(temprdataset, zone->rdclass,
   13156 				  dns_rdatatype_soa);
   13157 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
   13158 	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
   13159 	tempname = NULL;
   13160 	temprdataset = NULL;
   13161 
   13162 	if ((flags & DNS_NOTIFY_NOSOA) != 0)
   13163 		goto done;
   13164 
   13165 	result = dns_message_gettempname(message, &tempname);
   13166 	if (result != ISC_R_SUCCESS)
   13167 		goto soa_cleanup;
   13168 	result = dns_message_gettemprdata(message, &temprdata);
   13169 	if (result != ISC_R_SUCCESS)
   13170 		goto soa_cleanup;
   13171 	result = dns_message_gettemprdataset(message, &temprdataset);
   13172 	if (result != ISC_R_SUCCESS)
   13173 		goto soa_cleanup;
   13174 	result = dns_message_gettemprdatalist(message, &temprdatalist);
   13175 	if (result != ISC_R_SUCCESS)
   13176 		goto soa_cleanup;
   13177 
   13178 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   13179 	INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
   13180 	dns_db_attach(zone->db, &zonedb);
   13181 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   13182 
   13183 	dns_name_init(tempname, NULL);
   13184 	dns_name_clone(&zone->origin, tempname);
   13185 	dns_db_currentversion(zonedb, &version);
   13186 	result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
   13187 	if (result != ISC_R_SUCCESS)
   13188 		goto soa_cleanup;
   13189 
   13190 	dns_rdataset_init(&rdataset);
   13191 	result = dns_db_findrdataset(zonedb, node, version,
   13192 				     dns_rdatatype_soa,
   13193 				     dns_rdatatype_none, 0, &rdataset,
   13194 				     NULL);
   13195 	if (result != ISC_R_SUCCESS)
   13196 		goto soa_cleanup;
   13197 	result = dns_rdataset_first(&rdataset);
   13198 	if (result != ISC_R_SUCCESS)
   13199 		goto soa_cleanup;
   13200 	dns_rdataset_current(&rdataset, &rdata);
   13201 	dns_rdata_toregion(&rdata, &r);
   13202 	result = isc_buffer_allocate(zone->mctx, &b, r.length);
   13203 	if (result != ISC_R_SUCCESS)
   13204 		goto soa_cleanup;
   13205 	isc_buffer_putmem(b, r.base, r.length);
   13206 	isc_buffer_usedregion(b, &r);
   13207 	dns_rdata_init(temprdata);
   13208 	dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
   13209 	dns_message_takebuffer(message, &b);
   13210 	result = dns_rdataset_next(&rdataset);
   13211 	dns_rdataset_disassociate(&rdataset);
   13212 	if (result != ISC_R_NOMORE)
   13213 		goto soa_cleanup;
   13214 	temprdatalist->rdclass = rdata.rdclass;
   13215 	temprdatalist->type = rdata.type;
   13216 	temprdatalist->ttl = rdataset.ttl;
   13217 	ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
   13218 
   13219 	result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
   13220 	if (result != ISC_R_SUCCESS)
   13221 		goto soa_cleanup;
   13222 
   13223 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
   13224 	dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
   13225 	temprdatalist = NULL;
   13226 	temprdataset = NULL;
   13227 	temprdata = NULL;
   13228 	tempname = NULL;
   13229 
   13230  soa_cleanup:
   13231 	if (node != NULL)
   13232 		dns_db_detachnode(zonedb, &node);
   13233 	if (version != NULL)
   13234 		dns_db_closeversion(zonedb, &version, ISC_FALSE);
   13235 	if (zonedb != NULL)
   13236 		dns_db_detach(&zonedb);
   13237 	if (tempname != NULL)
   13238 		dns_message_puttempname(message, &tempname);
   13239 	if (temprdata != NULL)
   13240 		dns_message_puttemprdata(message, &temprdata);
   13241 	if (temprdataset != NULL)
   13242 		dns_message_puttemprdataset(message, &temprdataset);
   13243 	if (temprdatalist != NULL)
   13244 		dns_message_puttemprdatalist(message, &temprdatalist);
   13245 
   13246  done:
   13247 	*messagep = message;
   13248 	return (ISC_R_SUCCESS);
   13249 
   13250  cleanup:
   13251 	if (tempname != NULL)
   13252 		dns_message_puttempname(message, &tempname);
   13253 	if (temprdataset != NULL)
   13254 		dns_message_puttemprdataset(message, &temprdataset);
   13255 	dns_message_destroy(&message);
   13256 	return (result);
   13257 }
   13258 
   13259 isc_result_t
   13260 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
   13261 		       dns_message_t *msg)
   13262 {
   13263 	return (dns_zone_notifyreceive2(zone, from, NULL, msg));
   13264 }
   13265 
   13266 isc_result_t
   13267 dns_zone_notifyreceive2(dns_zone_t *zone, isc_sockaddr_t *from,
   13268 			isc_sockaddr_t *to, dns_message_t *msg)
   13269 {
   13270 	unsigned int i;
   13271 	dns_rdata_soa_t soa;
   13272 	dns_rdataset_t *rdataset = NULL;
   13273 	dns_rdata_t rdata = DNS_RDATA_INIT;
   13274 	isc_result_t result;
   13275 	char fromtext[ISC_SOCKADDR_FORMATSIZE];
   13276 	int match = 0;
   13277 	isc_netaddr_t netaddr;
   13278 	isc_uint32_t serial = 0;
   13279 	isc_boolean_t have_serial = ISC_FALSE;
   13280 	dns_tsigkey_t *tsigkey;
   13281 	dns_name_t *tsig;
   13282 
   13283 	REQUIRE(DNS_ZONE_VALID(zone));
   13284 
   13285 	/*
   13286 	 * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
   13287 	 * ROLLOVER.
   13288 	 *
   13289 	 * SOA:	RFC1996
   13290 	 * Check that 'from' is a valid notify source, (zone->masters).
   13291 	 *	Return DNS_R_REFUSED if not.
   13292 	 *
   13293 	 * If the notify message contains a serial number check it
   13294 	 * against the zones serial and return if <= current serial
   13295 	 *
   13296 	 * If a refresh check is progress, if so just record the
   13297 	 * fact we received a NOTIFY and from where and return.
   13298 	 * We will perform a new refresh check when the current one
   13299 	 * completes. Return ISC_R_SUCCESS.
   13300 	 *
   13301 	 * Otherwise initiate a refresh check using 'from' as the
   13302 	 * first address to check.  Return ISC_R_SUCCESS.
   13303 	 */
   13304 
   13305 	isc_sockaddr_format(from, fromtext, sizeof(fromtext));
   13306 
   13307 	/*
   13308 	 * Notify messages are processed by the raw zone.
   13309 	 */
   13310 	LOCK_ZONE(zone);
   13311 	INSIST(zone != zone->raw);
   13312 	if (inline_secure(zone)) {
   13313 		result = dns_zone_notifyreceive2(zone->raw, from, to, msg);
   13314 		UNLOCK_ZONE(zone);
   13315 		return (result);
   13316 	}
   13317 	/*
   13318 	 *  We only handle NOTIFY (SOA) at the present.
   13319 	 */
   13320 	if (isc_sockaddr_pf(from) == PF_INET)
   13321 		inc_stats(zone, dns_zonestatscounter_notifyinv4);
   13322 	else
   13323 		inc_stats(zone, dns_zonestatscounter_notifyinv6);
   13324 	if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
   13325 	    dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
   13326 				 dns_rdatatype_soa, dns_rdatatype_none,
   13327 				 NULL, NULL) != ISC_R_SUCCESS) {
   13328 		UNLOCK_ZONE(zone);
   13329 		if (msg->counts[DNS_SECTION_QUESTION] == 0) {
   13330 			dns_zone_log(zone, ISC_LOG_NOTICE,
   13331 				     "NOTIFY with no "
   13332 				     "question section from: %s", fromtext);
   13333 			return (DNS_R_FORMERR);
   13334 		}
   13335 		dns_zone_log(zone, ISC_LOG_NOTICE,
   13336 			     "NOTIFY zone does not match");
   13337 		return (DNS_R_NOTIMP);
   13338 	}
   13339 
   13340 	/*
   13341 	 * If we are a master zone just succeed.
   13342 	 */
   13343 	if (zone->type == dns_zone_master) {
   13344 		UNLOCK_ZONE(zone);
   13345 		return (ISC_R_SUCCESS);
   13346 	}
   13347 
   13348 	isc_netaddr_fromsockaddr(&netaddr, from);
   13349 	for (i = 0; i < zone->masterscnt; i++) {
   13350 		if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
   13351 			break;
   13352 		if (zone->view->aclenv.match_mapped &&
   13353 		    IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
   13354 		    isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
   13355 			isc_netaddr_t na1, na2;
   13356 			isc_netaddr_fromv4mapped(&na1, &netaddr);
   13357 			isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
   13358 			if (isc_netaddr_equal(&na1, &na2))
   13359 				break;
   13360 		}
   13361 	}
   13362 
   13363 	/*
   13364 	 * Accept notify requests from non masters if they are on
   13365 	 * 'zone->notify_acl'.
   13366 	 */
   13367 	tsigkey = dns_message_gettsigkey(msg);
   13368 	tsig = dns_tsigkey_identity(tsigkey);
   13369 	if (i >= zone->masterscnt && zone->notify_acl != NULL &&
   13370 	    dns_acl_match(&netaddr, tsig, zone->notify_acl,
   13371 			  &zone->view->aclenv,
   13372 			  &match, NULL) == ISC_R_SUCCESS &&
   13373 	    match > 0)
   13374 	{
   13375 		/* Accept notify. */
   13376 	} else if (i >= zone->masterscnt) {
   13377 		UNLOCK_ZONE(zone);
   13378 		dns_zone_log(zone, ISC_LOG_INFO,
   13379 			     "refused notify from non-master: %s", fromtext);
   13380 		inc_stats(zone, dns_zonestatscounter_notifyrej);
   13381 		return (DNS_R_REFUSED);
   13382 	}
   13383 
   13384 	/*
   13385 	 * If the zone is loaded and there are answers check the serial
   13386 	 * to see if we need to do a refresh.  Do not worry about this
   13387 	 * check if we are a dialup zone as we use the notify request
   13388 	 * to trigger a refresh check.
   13389 	 */
   13390 	if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
   13391 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
   13392 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
   13393 		result = dns_message_findname(msg, DNS_SECTION_ANSWER,
   13394 					      &zone->origin,
   13395 					      dns_rdatatype_soa,
   13396 					      dns_rdatatype_none, NULL,
   13397 					      &rdataset);
   13398 		if (result == ISC_R_SUCCESS)
   13399 			result = dns_rdataset_first(rdataset);
   13400 		if (result == ISC_R_SUCCESS) {
   13401 			isc_uint32_t oldserial;
   13402 			unsigned int soacount;
   13403 
   13404 			dns_rdataset_current(rdataset, &rdata);
   13405 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
   13406 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   13407 			serial = soa.serial;
   13408 			have_serial = ISC_TRUE;
   13409 			/*
   13410 			 * The following should safely be performed without DB
   13411 			 * lock and succeed in this context.
   13412 			 */
   13413 			result = zone_get_from_db(zone, zone->db, NULL,
   13414 						  &soacount, &oldserial, NULL,
   13415 						  NULL, NULL, NULL, NULL);
   13416 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   13417 			RUNTIME_CHECK(soacount > 0U);
   13418 			if (isc_serial_le(serial, oldserial)) {
   13419 				dns_zone_log(zone,
   13420 					     ISC_LOG_INFO,
   13421 					     "notify from %s: "
   13422 					     "zone is up to date",
   13423 					     fromtext);
   13424 				UNLOCK_ZONE(zone);
   13425 				return (ISC_R_SUCCESS);
   13426 			}
   13427 		}
   13428 	}
   13429 
   13430 	/*
   13431 	 * If we got this far and there was a refresh in progress just
   13432 	 * let it complete.  Record where we got the notify from so we
   13433 	 * can perform a refresh check when the current one completes
   13434 	 */
   13435 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
   13436 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   13437 		zone->notifyfrom = *from;
   13438 		UNLOCK_ZONE(zone);
   13439 		if (have_serial)
   13440 			dns_zone_log(zone, ISC_LOG_INFO,
   13441 				     "notify from %s: serial %u: refresh in "
   13442 				     "progress, refresh check queued",
   13443 				      fromtext, serial);
   13444 		else
   13445 			dns_zone_log(zone, ISC_LOG_INFO,
   13446 				     "notify from %s: refresh in progress, "
   13447 				     "refresh check queued", fromtext);
   13448 		return (ISC_R_SUCCESS);
   13449 	}
   13450 	if (have_serial)
   13451 		dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
   13452 			     fromtext, serial);
   13453 	else
   13454 		dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
   13455 			     fromtext);
   13456 	zone->notifyfrom = *from;
   13457 	UNLOCK_ZONE(zone);
   13458 
   13459 	if (to != NULL) {
   13460 		dns_zonemgr_unreachabledel(zone->zmgr, from, to);
   13461 	}
   13462 	dns_zone_refresh(zone);
   13463 	return (ISC_R_SUCCESS);
   13464 }
   13465 
   13466 void
   13467 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
   13468 
   13469 	REQUIRE(DNS_ZONE_VALID(zone));
   13470 
   13471 	LOCK_ZONE(zone);
   13472 	if (zone->notify_acl != NULL)
   13473 		dns_acl_detach(&zone->notify_acl);
   13474 	dns_acl_attach(acl, &zone->notify_acl);
   13475 	UNLOCK_ZONE(zone);
   13476 }
   13477 
   13478 void
   13479 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
   13480 
   13481 	REQUIRE(DNS_ZONE_VALID(zone));
   13482 
   13483 	LOCK_ZONE(zone);
   13484 	if (zone->query_acl != NULL)
   13485 		dns_acl_detach(&zone->query_acl);
   13486 	dns_acl_attach(acl, &zone->query_acl);
   13487 	UNLOCK_ZONE(zone);
   13488 }
   13489 
   13490 void
   13491 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
   13492 
   13493 	REQUIRE(DNS_ZONE_VALID(zone));
   13494 
   13495 	LOCK_ZONE(zone);
   13496 	if (zone->queryon_acl != NULL)
   13497 		dns_acl_detach(&zone->queryon_acl);
   13498 	dns_acl_attach(acl, &zone->queryon_acl);
   13499 	UNLOCK_ZONE(zone);
   13500 }
   13501 
   13502 void
   13503 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
   13504 
   13505 	REQUIRE(DNS_ZONE_VALID(zone));
   13506 
   13507 	LOCK_ZONE(zone);
   13508 	if (zone->update_acl != NULL)
   13509 		dns_acl_detach(&zone->update_acl);
   13510 	dns_acl_attach(acl, &zone->update_acl);
   13511 	UNLOCK_ZONE(zone);
   13512 }
   13513 
   13514 void
   13515 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
   13516 
   13517 	REQUIRE(DNS_ZONE_VALID(zone));
   13518 
   13519 	LOCK_ZONE(zone);
   13520 	if (zone->forward_acl != NULL)
   13521 		dns_acl_detach(&zone->forward_acl);
   13522 	dns_acl_attach(acl, &zone->forward_acl);
   13523 	UNLOCK_ZONE(zone);
   13524 }
   13525 
   13526 void
   13527 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
   13528 
   13529 	REQUIRE(DNS_ZONE_VALID(zone));
   13530 
   13531 	LOCK_ZONE(zone);
   13532 	if (zone->xfr_acl != NULL)
   13533 		dns_acl_detach(&zone->xfr_acl);
   13534 	dns_acl_attach(acl, &zone->xfr_acl);
   13535 	UNLOCK_ZONE(zone);
   13536 }
   13537 
   13538 dns_acl_t *
   13539 dns_zone_getnotifyacl(dns_zone_t *zone) {
   13540 
   13541 	REQUIRE(DNS_ZONE_VALID(zone));
   13542 
   13543 	return (zone->notify_acl);
   13544 }
   13545 
   13546 dns_acl_t *
   13547 dns_zone_getqueryacl(dns_zone_t *zone) {
   13548 
   13549 	REQUIRE(DNS_ZONE_VALID(zone));
   13550 
   13551 	return (zone->query_acl);
   13552 }
   13553 
   13554 dns_acl_t *
   13555 dns_zone_getqueryonacl(dns_zone_t *zone) {
   13556 
   13557 	REQUIRE(DNS_ZONE_VALID(zone));
   13558 
   13559 	return (zone->queryon_acl);
   13560 }
   13561 
   13562 dns_acl_t *
   13563 dns_zone_getupdateacl(dns_zone_t *zone) {
   13564 
   13565 	REQUIRE(DNS_ZONE_VALID(zone));
   13566 
   13567 	return (zone->update_acl);
   13568 }
   13569 
   13570 dns_acl_t *
   13571 dns_zone_getforwardacl(dns_zone_t *zone) {
   13572 
   13573 	REQUIRE(DNS_ZONE_VALID(zone));
   13574 
   13575 	return (zone->forward_acl);
   13576 }
   13577 
   13578 dns_acl_t *
   13579 dns_zone_getxfracl(dns_zone_t *zone) {
   13580 
   13581 	REQUIRE(DNS_ZONE_VALID(zone));
   13582 
   13583 	return (zone->xfr_acl);
   13584 }
   13585 
   13586 void
   13587 dns_zone_clearupdateacl(dns_zone_t *zone) {
   13588 
   13589 	REQUIRE(DNS_ZONE_VALID(zone));
   13590 
   13591 	LOCK_ZONE(zone);
   13592 	if (zone->update_acl != NULL)
   13593 		dns_acl_detach(&zone->update_acl);
   13594 	UNLOCK_ZONE(zone);
   13595 }
   13596 
   13597 void
   13598 dns_zone_clearforwardacl(dns_zone_t *zone) {
   13599 
   13600 	REQUIRE(DNS_ZONE_VALID(zone));
   13601 
   13602 	LOCK_ZONE(zone);
   13603 	if (zone->forward_acl != NULL)
   13604 		dns_acl_detach(&zone->forward_acl);
   13605 	UNLOCK_ZONE(zone);
   13606 }
   13607 
   13608 void
   13609 dns_zone_clearnotifyacl(dns_zone_t *zone) {
   13610 
   13611 	REQUIRE(DNS_ZONE_VALID(zone));
   13612 
   13613 	LOCK_ZONE(zone);
   13614 	if (zone->notify_acl != NULL)
   13615 		dns_acl_detach(&zone->notify_acl);
   13616 	UNLOCK_ZONE(zone);
   13617 }
   13618 
   13619 void
   13620 dns_zone_clearqueryacl(dns_zone_t *zone) {
   13621 
   13622 	REQUIRE(DNS_ZONE_VALID(zone));
   13623 
   13624 	LOCK_ZONE(zone);
   13625 	if (zone->query_acl != NULL)
   13626 		dns_acl_detach(&zone->query_acl);
   13627 	UNLOCK_ZONE(zone);
   13628 }
   13629 
   13630 void
   13631 dns_zone_clearqueryonacl(dns_zone_t *zone) {
   13632 
   13633 	REQUIRE(DNS_ZONE_VALID(zone));
   13634 
   13635 	LOCK_ZONE(zone);
   13636 	if (zone->queryon_acl != NULL)
   13637 		dns_acl_detach(&zone->queryon_acl);
   13638 	UNLOCK_ZONE(zone);
   13639 }
   13640 
   13641 void
   13642 dns_zone_clearxfracl(dns_zone_t *zone) {
   13643 
   13644 	REQUIRE(DNS_ZONE_VALID(zone));
   13645 
   13646 	LOCK_ZONE(zone);
   13647 	if (zone->xfr_acl != NULL)
   13648 		dns_acl_detach(&zone->xfr_acl);
   13649 	UNLOCK_ZONE(zone);
   13650 }
   13651 
   13652 isc_boolean_t
   13653 dns_zone_getupdatedisabled(dns_zone_t *zone) {
   13654 	REQUIRE(DNS_ZONE_VALID(zone));
   13655 	return (zone->update_disabled);
   13656 
   13657 }
   13658 
   13659 void
   13660 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
   13661 	REQUIRE(DNS_ZONE_VALID(zone));
   13662 	zone->update_disabled = state;
   13663 }
   13664 
   13665 isc_boolean_t
   13666 dns_zone_getzeronosoattl(dns_zone_t *zone) {
   13667 	REQUIRE(DNS_ZONE_VALID(zone));
   13668 	return (zone->zero_no_soa_ttl);
   13669 
   13670 }
   13671 
   13672 void
   13673 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
   13674 	REQUIRE(DNS_ZONE_VALID(zone));
   13675 	zone->zero_no_soa_ttl = state;
   13676 }
   13677 
   13678 void
   13679 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
   13680 	REQUIRE(DNS_ZONE_VALID(zone));
   13681 
   13682 	zone->check_names = severity;
   13683 }
   13684 
   13685 dns_severity_t
   13686 dns_zone_getchecknames(dns_zone_t *zone) {
   13687 	REQUIRE(DNS_ZONE_VALID(zone));
   13688 
   13689 	return (zone->check_names);
   13690 }
   13691 
   13692 void
   13693 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
   13694 	REQUIRE(DNS_ZONE_VALID(zone));
   13695 
   13696 	zone->journalsize = size;
   13697 }
   13698 
   13699 isc_int32_t
   13700 dns_zone_getjournalsize(dns_zone_t *zone) {
   13701 	REQUIRE(DNS_ZONE_VALID(zone));
   13702 
   13703 	return (zone->journalsize);
   13704 }
   13705 
   13706 static void
   13707 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
   13708 	isc_result_t result = ISC_R_FAILURE;
   13709 	isc_buffer_t buffer;
   13710 
   13711 	REQUIRE(buf != NULL);
   13712 	REQUIRE(length > 1U);
   13713 
   13714 	/*
   13715 	 * Leave space for terminating '\0'.
   13716 	 */
   13717 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   13718 	if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
   13719 		if (dns_name_dynamic(&zone->origin))
   13720 			result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
   13721 		if (result != ISC_R_SUCCESS &&
   13722 		    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
   13723 			isc_buffer_putstr(&buffer, "<UNKNOWN>");
   13724 
   13725 		if (isc_buffer_availablelength(&buffer) > 0)
   13726 			isc_buffer_putstr(&buffer, "/");
   13727 		(void)dns_rdataclass_totext(zone->rdclass, &buffer);
   13728 	}
   13729 
   13730 	if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
   13731 	    strcmp(zone->view->name, "_default") != 0 &&
   13732 	    strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
   13733 		isc_buffer_putstr(&buffer, "/");
   13734 		isc_buffer_putstr(&buffer, zone->view->name);
   13735 	}
   13736 	if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
   13737 		isc_buffer_putstr(&buffer, " (signed)");
   13738 	if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
   13739 		isc_buffer_putstr(&buffer, " (unsigned)");
   13740 
   13741 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   13742 }
   13743 
   13744 static void
   13745 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
   13746 	isc_result_t result = ISC_R_FAILURE;
   13747 	isc_buffer_t buffer;
   13748 
   13749 	REQUIRE(buf != NULL);
   13750 	REQUIRE(length > 1U);
   13751 
   13752 	/*
   13753 	 * Leave space for terminating '\0'.
   13754 	 */
   13755 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   13756 	if (dns_name_dynamic(&zone->origin))
   13757 		result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
   13758 	if (result != ISC_R_SUCCESS &&
   13759 	    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
   13760 		isc_buffer_putstr(&buffer, "<UNKNOWN>");
   13761 
   13762 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   13763 }
   13764 
   13765 static void
   13766 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
   13767 	isc_buffer_t buffer;
   13768 
   13769 	REQUIRE(buf != NULL);
   13770 	REQUIRE(length > 1U);
   13771 
   13772 	/*
   13773 	 * Leave space for terminating '\0'.
   13774 	 */
   13775 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   13776 	(void)dns_rdataclass_totext(zone->rdclass, &buffer);
   13777 
   13778 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   13779 }
   13780 
   13781 static void
   13782 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
   13783 	isc_buffer_t buffer;
   13784 
   13785 	REQUIRE(buf != NULL);
   13786 	REQUIRE(length > 1U);
   13787 
   13788 
   13789 	/*
   13790 	 * Leave space for terminating '\0'.
   13791 	 */
   13792 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
   13793 
   13794 	if (zone->view == NULL) {
   13795 		isc_buffer_putstr(&buffer, "_none");
   13796 	} else if (strlen(zone->view->name)
   13797 		   < isc_buffer_availablelength(&buffer)) {
   13798 		isc_buffer_putstr(&buffer, zone->view->name);
   13799 	} else {
   13800 		isc_buffer_putstr(&buffer, "_toolong");
   13801 	}
   13802 
   13803 	buf[isc_buffer_usedlength(&buffer)] = '\0';
   13804 }
   13805 
   13806 void
   13807 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
   13808 	REQUIRE(DNS_ZONE_VALID(zone));
   13809 	REQUIRE(buf != NULL);
   13810 	zone_namerd_tostr(zone, buf, length);
   13811 }
   13812 
   13813 void
   13814 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
   13815 	REQUIRE(DNS_ZONE_VALID(zone));
   13816 	REQUIRE(buf != NULL);
   13817 	zone_name_tostr(zone, buf, length);
   13818 }
   13819 
   13820 void
   13821 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
   13822 	      const char *prefix, const char *fmt, va_list ap)
   13823 {
   13824 	char message[4096];
   13825 	const char *zstr;
   13826 
   13827 	if (!isc_log_wouldlog(dns_lctx, level)) {
   13828 		return;
   13829 	}
   13830 
   13831 	vsnprintf(message, sizeof(message), fmt, ap);
   13832 
   13833 	switch (zone->type) {
   13834 	case dns_zone_key:
   13835 		zstr = "managed-keys-zone";
   13836 		break;
   13837 	case dns_zone_redirect:
   13838 		zstr = "redirect-zone";
   13839 		break;
   13840 	default:
   13841 		zstr = "zone ";
   13842 	}
   13843 
   13844 	isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
   13845 		      "%s%s%s%s: %s",
   13846 		      (prefix != NULL ? prefix : ""),
   13847 		      (prefix != NULL ? ": " : ""),
   13848 		      zstr, zone->strnamerd, message);
   13849 }
   13850 
   13851 static void
   13852 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
   13853 	va_list ap;
   13854 
   13855 	va_start(ap, fmt);
   13856 	dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
   13857 	va_end(ap);
   13858 }
   13859 
   13860 void
   13861 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
   13862 	      int level, const char *fmt, ...)
   13863 {
   13864 	va_list ap;
   13865 
   13866 	va_start(ap, fmt);
   13867 	dns_zone_logv(zone, category, level, NULL, fmt, ap);
   13868 	va_end(ap);
   13869 }
   13870 
   13871 void
   13872 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
   13873 	va_list ap;
   13874 
   13875 	va_start(ap, fmt);
   13876 	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
   13877 	va_end(ap);
   13878 }
   13879 
   13880 static void
   13881 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
   13882 	      const char *fmt, ...)
   13883 {
   13884 	int level = ISC_LOG_DEBUG(debuglevel);
   13885 	va_list ap;
   13886 
   13887 	va_start(ap, fmt);
   13888 	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
   13889 	va_end(ap);
   13890 }
   13891 
   13892 static int
   13893 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
   13894 {
   13895 	isc_result_t result;
   13896 	dns_name_t *name;
   13897 	dns_rdataset_t *curr;
   13898 	int count = 0;
   13899 
   13900 	result = dns_message_firstname(msg, section);
   13901 	while (result == ISC_R_SUCCESS) {
   13902 		name = NULL;
   13903 		dns_message_currentname(msg, section, &name);
   13904 
   13905 		for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
   13906 		     curr = ISC_LIST_PREV(curr, link)) {
   13907 			if (curr->type == type)
   13908 				count++;
   13909 		}
   13910 		result = dns_message_nextname(msg, section);
   13911 	}
   13912 
   13913 	return (count);
   13914 }
   13915 
   13916 void
   13917 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
   13918 	REQUIRE(DNS_ZONE_VALID(zone));
   13919 
   13920 	zone->maxxfrin = maxxfrin;
   13921 }
   13922 
   13923 isc_uint32_t
   13924 dns_zone_getmaxxfrin(dns_zone_t *zone) {
   13925 	REQUIRE(DNS_ZONE_VALID(zone));
   13926 
   13927 	return (zone->maxxfrin);
   13928 }
   13929 
   13930 void
   13931 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
   13932 	REQUIRE(DNS_ZONE_VALID(zone));
   13933 	zone->maxxfrout = maxxfrout;
   13934 }
   13935 
   13936 isc_uint32_t
   13937 dns_zone_getmaxxfrout(dns_zone_t *zone) {
   13938 	REQUIRE(DNS_ZONE_VALID(zone));
   13939 
   13940 	return (zone->maxxfrout);
   13941 }
   13942 
   13943 dns_zonetype_t
   13944 dns_zone_gettype(dns_zone_t *zone) {
   13945 	REQUIRE(DNS_ZONE_VALID(zone));
   13946 
   13947 	return (zone->type);
   13948 }
   13949 
   13950 dns_zonetype_t
   13951 dns_zone_getredirecttype(dns_zone_t *zone) {
   13952 	REQUIRE(DNS_ZONE_VALID(zone));
   13953 	REQUIRE(zone->type == dns_zone_redirect);
   13954 
   13955 	return (zone->masters == NULL ? dns_zone_master : dns_zone_slave);
   13956 }
   13957 
   13958 dns_name_t *
   13959 dns_zone_getorigin(dns_zone_t *zone) {
   13960 	REQUIRE(DNS_ZONE_VALID(zone));
   13961 
   13962 	return (&zone->origin);
   13963 }
   13964 
   13965 void
   13966 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
   13967 	REQUIRE(DNS_ZONE_VALID(zone));
   13968 
   13969 	LOCK_ZONE(zone);
   13970 	if (zone->task != NULL)
   13971 		isc_task_detach(&zone->task);
   13972 	isc_task_attach(task, &zone->task);
   13973 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   13974 	if (zone->db != NULL)
   13975 		dns_db_settask(zone->db, zone->task);
   13976 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   13977 	UNLOCK_ZONE(zone);
   13978 }
   13979 
   13980 void
   13981 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
   13982 	REQUIRE(DNS_ZONE_VALID(zone));
   13983 	isc_task_attach(zone->task, target);
   13984 }
   13985 
   13986 void
   13987 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
   13988 	REQUIRE(DNS_ZONE_VALID(zone));
   13989 
   13990 	if (idlein == 0)
   13991 		idlein = DNS_DEFAULT_IDLEIN;
   13992 	zone->idlein = idlein;
   13993 }
   13994 
   13995 isc_uint32_t
   13996 dns_zone_getidlein(dns_zone_t *zone) {
   13997 	REQUIRE(DNS_ZONE_VALID(zone));
   13998 
   13999 	return (zone->idlein);
   14000 }
   14001 
   14002 void
   14003 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
   14004 	REQUIRE(DNS_ZONE_VALID(zone));
   14005 
   14006 	zone->idleout = idleout;
   14007 }
   14008 
   14009 isc_uint32_t
   14010 dns_zone_getidleout(dns_zone_t *zone) {
   14011 	REQUIRE(DNS_ZONE_VALID(zone));
   14012 
   14013 	return (zone->idleout);
   14014 }
   14015 
   14016 static void
   14017 notify_done(isc_task_t *task, isc_event_t *event) {
   14018 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
   14019 	dns_notify_t *notify;
   14020 	isc_result_t result;
   14021 	dns_message_t *message = NULL;
   14022 	isc_buffer_t buf;
   14023 	char rcode[128];
   14024 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
   14025 
   14026 	UNUSED(task);
   14027 
   14028 	notify = event->ev_arg;
   14029 	REQUIRE(DNS_NOTIFY_VALID(notify));
   14030 	INSIST(task == notify->zone->task);
   14031 
   14032 	isc_buffer_init(&buf, rcode, sizeof(rcode));
   14033 	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
   14034 
   14035 	result = revent->result;
   14036 	if (result == ISC_R_SUCCESS)
   14037 		result = dns_message_create(notify->zone->mctx,
   14038 					    DNS_MESSAGE_INTENTPARSE, &message);
   14039 	if (result == ISC_R_SUCCESS)
   14040 		result = dns_request_getresponse(revent->request, message,
   14041 					DNS_MESSAGEPARSE_PRESERVEORDER);
   14042 	if (result == ISC_R_SUCCESS)
   14043 		result = dns_rcode_totext(message->rcode, &buf);
   14044 	if (result == ISC_R_SUCCESS)
   14045 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
   14046 			   "notify response from %s: %.*s",
   14047 			   addrbuf, (int)buf.used, rcode);
   14048 	else
   14049 		notify_log(notify->zone, ISC_LOG_DEBUG(2),
   14050 			   "notify to %s failed: %s", addrbuf,
   14051 			   dns_result_totext(result));
   14052 
   14053 	/*
   14054 	 * Old bind's return formerr if they see a soa record.	Retry w/o
   14055 	 * the soa if we see a formerr and had sent a SOA.
   14056 	 */
   14057 	isc_event_free(&event);
   14058 	if (message != NULL && message->rcode == dns_rcode_formerr &&
   14059 	    (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
   14060 		isc_boolean_t startup;
   14061 
   14062 		notify->flags |= DNS_NOTIFY_NOSOA;
   14063 		dns_request_destroy(&notify->request);
   14064 		startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0);
   14065 		result = notify_send_queue(notify, startup);
   14066 		if (result != ISC_R_SUCCESS)
   14067 			notify_destroy(notify, ISC_FALSE);
   14068 	} else {
   14069 		if (result == ISC_R_TIMEDOUT)
   14070 			notify_log(notify->zone, ISC_LOG_DEBUG(1),
   14071 				   "notify to %s: retries exceeded", addrbuf);
   14072 		notify_destroy(notify, ISC_FALSE);
   14073 	}
   14074 	if (message != NULL)
   14075 		dns_message_destroy(&message);
   14076 }
   14077 
   14078 struct secure_event {
   14079 	isc_event_t e;
   14080 	dns_db_t *db;
   14081 	isc_uint32_t serial;
   14082 };
   14083 
   14084 static void
   14085 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
   14086 	UNUSED(arg);
   14087 	dns_zone_log(zone, level, "%s", message);
   14088 }
   14089 
   14090 static isc_result_t
   14091 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
   14092 		    isc_uint32_t start, isc_uint32_t end,
   14093 		    dns_difftuple_t **soatuplep, dns_diff_t *diff)
   14094 {
   14095 	isc_result_t result;
   14096 	dns_difftuple_t *tuple = NULL;
   14097 	dns_diffop_t op = DNS_DIFFOP_ADD;
   14098 	int n_soa = 0;
   14099 
   14100 	REQUIRE(soatuplep != NULL);
   14101 
   14102 	if (start == end)
   14103 		return (DNS_R_UNCHANGED);
   14104 
   14105 	CHECK(dns_journal_iter_init(journal, start, end));
   14106 	for (result = dns_journal_first_rr(journal);
   14107 	     result == ISC_R_SUCCESS;
   14108 	     result = dns_journal_next_rr(journal))
   14109 	{
   14110 		dns_name_t *name = NULL;
   14111 		isc_uint32_t ttl;
   14112 		dns_rdata_t *rdata = NULL;
   14113 		dns_journal_current_rr(journal, &name, &ttl, &rdata);
   14114 
   14115 		if (rdata->type == dns_rdatatype_soa) {
   14116 			n_soa++;
   14117 			if (n_soa == 2) {
   14118 				/*
   14119 				 * Save the latest raw SOA record.
   14120 				 */
   14121 				if (*soatuplep != NULL)
   14122 					dns_difftuple_free(soatuplep);
   14123 				CHECK(dns_difftuple_create(diff->mctx,
   14124 							   DNS_DIFFOP_ADD,
   14125 							   name, ttl, rdata,
   14126 							   soatuplep));
   14127 			}
   14128 			if (n_soa == 3)
   14129 				n_soa = 1;
   14130 			continue;
   14131 		}
   14132 
   14133 		/* Sanity. */
   14134 		if (n_soa == 0) {
   14135 			dns_zone_log(raw, ISC_LOG_ERROR,
   14136 				     "corrupt journal file: '%s'\n",
   14137 				     raw->journal);
   14138 			return (ISC_R_FAILURE);
   14139 		}
   14140 
   14141 		if (zone->privatetype != 0 &&
   14142 		    rdata->type == zone->privatetype)
   14143 			continue;
   14144 
   14145 		if (rdata->type == dns_rdatatype_nsec ||
   14146 		    rdata->type == dns_rdatatype_rrsig ||
   14147 		    rdata->type == dns_rdatatype_nsec3 ||
   14148 		    rdata->type == dns_rdatatype_dnskey ||
   14149 		    rdata->type == dns_rdatatype_nsec3param)
   14150 			continue;
   14151 
   14152 		op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
   14153 
   14154 		CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
   14155 					   &tuple));
   14156 		dns_diff_appendminimal(diff, &tuple);
   14157 	}
   14158 	if (result == ISC_R_NOMORE)
   14159 		result = ISC_R_SUCCESS;
   14160 
   14161  failure:
   14162 	return(result);
   14163 }
   14164 
   14165 static isc_result_t
   14166 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
   14167 	       dns_dbversion_t *secver, dns_difftuple_t **soatuple,
   14168 	       dns_diff_t *diff)
   14169 {
   14170 	isc_result_t result;
   14171 	dns_db_t *rawdb = NULL;
   14172 	dns_dbversion_t *rawver = NULL;
   14173 	dns_difftuple_t *tuple = NULL, *next;
   14174 	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
   14175 	dns_rdata_soa_t oldsoa, newsoa;
   14176 
   14177 	REQUIRE(DNS_ZONE_VALID(seczone));
   14178 	REQUIRE(soatuple != NULL && *soatuple == NULL);
   14179 
   14180 	if (!seczone->sourceserialset)
   14181 		return (DNS_R_UNCHANGED);
   14182 
   14183 	dns_db_attach(raw->db, &rawdb);
   14184 	dns_db_currentversion(rawdb, &rawver);
   14185 	result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
   14186 	dns_db_closeversion(rawdb, &rawver, ISC_FALSE);
   14187 	dns_db_detach(&rawdb);
   14188 
   14189 	if (result != ISC_R_SUCCESS)
   14190 		return (result);
   14191 
   14192 	for (tuple = ISC_LIST_HEAD(diff->tuples);
   14193 	     tuple != NULL;
   14194 	     tuple = next)
   14195 	{
   14196 		next = ISC_LIST_NEXT(tuple, link);
   14197 		if (tuple->rdata.type == dns_rdatatype_nsec ||
   14198 		    tuple->rdata.type == dns_rdatatype_rrsig ||
   14199 		    tuple->rdata.type == dns_rdatatype_dnskey ||
   14200 		    tuple->rdata.type == dns_rdatatype_nsec3 ||
   14201 		    tuple->rdata.type == dns_rdatatype_nsec3param)
   14202 		{
   14203 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
   14204 			dns_difftuple_free(&tuple);
   14205 			continue;
   14206 		}
   14207 		if (tuple->rdata.type == dns_rdatatype_soa) {
   14208 			if (tuple->op == DNS_DIFFOP_DEL) {
   14209 				INSIST(oldtuple == NULL);
   14210 				oldtuple = tuple;
   14211 			}
   14212 			if (tuple->op == DNS_DIFFOP_ADD) {
   14213 				INSIST(newtuple == NULL);
   14214 				newtuple = tuple;
   14215 			}
   14216 		}
   14217 	}
   14218 
   14219 	if (oldtuple != NULL && newtuple != NULL) {
   14220 
   14221 		result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
   14222 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14223 
   14224 		result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
   14225 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14226 
   14227 		/*
   14228 		 * If the SOA records are the same except for the serial
   14229 		 * remove them from the diff.
   14230 		 */
   14231 		if (oldsoa.refresh == newsoa.refresh &&
   14232 		    oldsoa.retry == newsoa.retry &&
   14233 		    oldsoa.minimum == newsoa.minimum &&
   14234 		    oldsoa.expire == newsoa.expire &&
   14235 		    dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
   14236 		    dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
   14237 			ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
   14238 			dns_difftuple_free(&oldtuple);
   14239 			ISC_LIST_UNLINK(diff->tuples, newtuple, link);
   14240 			dns_difftuple_free(&newtuple);
   14241 		}
   14242 	}
   14243 
   14244 	if (ISC_LIST_EMPTY(diff->tuples))
   14245 		return (DNS_R_UNCHANGED);
   14246 
   14247 	/*
   14248 	 * If there are still SOA records in the diff they can now be removed
   14249 	 * saving the new SOA record.
   14250 	 */
   14251 	if (oldtuple != NULL) {
   14252 		ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
   14253 		dns_difftuple_free(&oldtuple);
   14254 	}
   14255 
   14256 	if (newtuple != NULL) {
   14257 		ISC_LIST_UNLINK(diff->tuples, newtuple, link);
   14258 		*soatuple = newtuple;
   14259 	}
   14260 
   14261 	return (ISC_R_SUCCESS);
   14262 }
   14263 
   14264 static void
   14265 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
   14266 	static char me[] = "receive_secure_serial";
   14267 	isc_result_t result = ISC_R_SUCCESS;
   14268 	dns_journal_t *rjournal = NULL;
   14269 	dns_journal_t *sjournal = NULL;
   14270 	isc_uint32_t start, end;
   14271 	dns_zone_t *zone;
   14272 	dns_difftuple_t *tuple = NULL, *soatuple = NULL;
   14273 	dns_update_log_t log = { update_log_cb, NULL };
   14274 	isc_uint32_t newserial = 0, desired = 0;
   14275 	isc_time_t timenow;
   14276 
   14277 	UNUSED(task);
   14278 
   14279 	zone = event->ev_arg;
   14280 	end = ((struct secure_event *)event)->serial;
   14281 
   14282 	ENTER;
   14283 
   14284 	LOCK_ZONE(zone);
   14285 
   14286 	/*
   14287 	 * If we are already processing a receive secure serial event
   14288 	 * for the zone, just queue the new one and exit.
   14289 	 */
   14290 	if (zone->rss_event != NULL && zone->rss_event != event) {
   14291 		ISC_LIST_APPEND(zone->rss_events, event, ev_link);
   14292 		UNLOCK_ZONE(zone);
   14293 		return;
   14294 	}
   14295 
   14296  nextevent:
   14297 	if (zone->rss_event != NULL) {
   14298 		INSIST(zone->rss_event == event);
   14299 		UNLOCK_ZONE(zone);
   14300 	} else {
   14301 		zone->rss_event = event;
   14302 		dns_diff_init(zone->mctx, &zone->rss_diff);
   14303 
   14304 		/*
   14305 		 * zone->db may be NULL, if the load from disk failed.
   14306 		 */
   14307 		result = ISC_R_SUCCESS;
   14308 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   14309 		if (zone->db != NULL)
   14310 			dns_db_attach(zone->db, &zone->rss_db);
   14311 		else
   14312 			result = ISC_R_FAILURE;
   14313 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   14314 
   14315 		if (result == ISC_R_SUCCESS && zone->raw != NULL)
   14316 			dns_zone_attach(zone->raw, &zone->rss_raw);
   14317 		else
   14318 			result = ISC_R_FAILURE;
   14319 
   14320 		UNLOCK_ZONE(zone);
   14321 
   14322 		CHECK(result);
   14323 
   14324 		/*
   14325 		 * We first attempt to sync the raw zone to the secure zone
   14326 		 * by using the raw zone's journal, applying all the deltas
   14327 		 * from the latest source-serial of the secure zone up to
   14328 		 * the current serial number of the raw zone.
   14329 		 *
   14330 		 * If that fails, then we'll fall back to a direct comparison
   14331 		 * between raw and secure zones.
   14332 		 */
   14333 		CHECK(dns_journal_open(zone->rss_raw->mctx,
   14334 				       zone->rss_raw->journal,
   14335 				       DNS_JOURNAL_WRITE, &rjournal));
   14336 
   14337 		result = dns_journal_open(zone->mctx, zone->journal,
   14338 					  DNS_JOURNAL_READ, &sjournal);
   14339 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
   14340 			goto failure;
   14341 
   14342 		if (!dns_journal_get_sourceserial(rjournal, &start)) {
   14343 			start = dns_journal_first_serial(rjournal);
   14344 			dns_journal_set_sourceserial(rjournal, start);
   14345 		}
   14346 		if (sjournal != NULL) {
   14347 			isc_uint32_t serial;
   14348 			/*
   14349 			 * We read the secure journal first, if that
   14350 			 * exists use its value provided it is greater
   14351 			 * that from the raw journal.
   14352 			 */
   14353 			if (dns_journal_get_sourceserial(sjournal, &serial)) {
   14354 				if (isc_serial_gt(serial, start))
   14355 					start = serial;
   14356 			}
   14357 			dns_journal_destroy(&sjournal);
   14358 		}
   14359 
   14360 		dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
   14361 		CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
   14362 
   14363 		/*
   14364 		 * Try to apply diffs from the raw zone's journal to the secure
   14365 		 * zone.  If that fails, we recover by syncing up the databases
   14366 		 * directly.
   14367 		 */
   14368 		result = sync_secure_journal(zone, zone->rss_raw, rjournal,
   14369 					     start, end, &soatuple,
   14370 					     &zone->rss_diff);
   14371 		if (result == DNS_R_UNCHANGED)
   14372 			goto failure;
   14373 		else if (result != ISC_R_SUCCESS)
   14374 			CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
   14375 					     zone->rss_oldver, &soatuple,
   14376 					     &zone->rss_diff));
   14377 
   14378 		CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
   14379 				     zone->rss_newver));
   14380 
   14381 		if (soatuple != NULL) {
   14382 			isc_uint32_t oldserial;
   14383 
   14384 			CHECK(dns_db_createsoatuple(zone->rss_db,
   14385 						    zone->rss_oldver,
   14386 						    zone->rss_diff.mctx,
   14387 						    DNS_DIFFOP_DEL, &tuple));
   14388 			oldserial = dns_soa_getserial(&tuple->rdata);
   14389 			newserial = desired =
   14390 				    dns_soa_getserial(&soatuple->rdata);
   14391 			if (!isc_serial_gt(newserial, oldserial)) {
   14392 				newserial = oldserial + 1;
   14393 				if (newserial == 0)
   14394 					newserial++;
   14395 				dns_soa_setserial(newserial, &soatuple->rdata);
   14396 			}
   14397 			CHECK(do_one_tuple(&tuple, zone->rss_db,
   14398 					   zone->rss_newver, &zone->rss_diff));
   14399 			CHECK(do_one_tuple(&soatuple, zone->rss_db,
   14400 					   zone->rss_newver, &zone->rss_diff));
   14401 		} else
   14402 			CHECK(update_soa_serial(zone->rss_db, zone->rss_newver,
   14403 						&zone->rss_diff, zone->mctx,
   14404 						zone->updatemethod));
   14405 
   14406 	}
   14407 	result = dns_update_signaturesinc(&log, zone, zone->rss_db,
   14408 					  zone->rss_oldver, zone->rss_newver,
   14409 					  &zone->rss_diff,
   14410 					  zone->sigvalidityinterval,
   14411 					  &zone->rss_state);
   14412 	if (result == DNS_R_CONTINUE) {
   14413 		if (rjournal != NULL)
   14414 			dns_journal_destroy(&rjournal);
   14415 		isc_task_send(task, &event);
   14416 		fprintf(stderr, "looping on dns_update_signaturesinc\n");
   14417 		return;
   14418 	}
   14419 	/*
   14420 	 * If something went wrong while trying to update the secure zone and
   14421 	 * the latter was already signed before, do not apply raw zone deltas
   14422 	 * to it as that would break existing DNSSEC signatures.  However, if
   14423 	 * the secure zone was not yet signed (e.g. because no signing keys
   14424 	 * were created for it), commence applying raw zone deltas to it so
   14425 	 * that contents of the raw zone and the secure zone are kept in sync.
   14426 	 */
   14427 	if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
   14428 		goto failure;
   14429 	}
   14430 
   14431 	if (rjournal == NULL)
   14432 		CHECK(dns_journal_open(zone->rss_raw->mctx,
   14433 				       zone->rss_raw->journal,
   14434 				       DNS_JOURNAL_WRITE, &rjournal));
   14435 	CHECK(zone_journal(zone, &zone->rss_diff, &end,
   14436 			   "receive_secure_serial"));
   14437 
   14438 	dns_journal_set_sourceserial(rjournal, end);
   14439 	dns_journal_commit(rjournal);
   14440 
   14441 	LOCK_ZONE(zone);
   14442 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   14443 
   14444 	zone->sourceserial = end;
   14445 	zone->sourceserialset = ISC_TRUE;
   14446 	zone_needdump(zone, DNS_DUMP_DELAY);
   14447 
   14448 	TIME_NOW(&timenow);
   14449 	zone_settimer(zone, &timenow);
   14450 	UNLOCK_ZONE(zone);
   14451 
   14452 	dns_db_closeversion(zone->rss_db, &zone->rss_oldver, ISC_FALSE);
   14453 	dns_db_closeversion(zone->rss_db, &zone->rss_newver, ISC_TRUE);
   14454 
   14455 	if (newserial != 0) {
   14456 		dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
   14457 			     newserial, desired);
   14458 	}
   14459 
   14460  failure:
   14461 	isc_event_free(&zone->rss_event);
   14462 	event = ISC_LIST_HEAD(zone->rss_events);
   14463 
   14464 	if (zone->rss_raw != NULL)
   14465 		dns_zone_detach(&zone->rss_raw);
   14466 	if (result != ISC_R_SUCCESS)
   14467 		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
   14468 			     dns_result_totext(result));
   14469 	if (tuple != NULL)
   14470 		dns_difftuple_free(&tuple);
   14471 	if (soatuple != NULL)
   14472 		dns_difftuple_free(&soatuple);
   14473 	if (zone->rss_db != NULL) {
   14474 		if (zone->rss_oldver != NULL)
   14475 			dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
   14476 					    ISC_FALSE);
   14477 		if (zone->rss_newver != NULL)
   14478 			dns_db_closeversion(zone->rss_db, &zone->rss_newver,
   14479 					    ISC_FALSE);
   14480 		dns_db_detach(&zone->rss_db);
   14481 	}
   14482 	INSIST(zone->rss_oldver == NULL);
   14483 	INSIST(zone->rss_newver == NULL);
   14484 	if (rjournal != NULL)
   14485 		dns_journal_destroy(&rjournal);
   14486 	dns_diff_clear(&zone->rss_diff);
   14487 
   14488 	if (event != NULL) {
   14489 		LOCK_ZONE(zone);
   14490 		INSIST(zone->irefs > 1);
   14491 		zone->irefs--;
   14492 		ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
   14493 		goto nextevent;
   14494 	}
   14495 	dns_zone_idetach(&zone);
   14496 }
   14497 
   14498 static isc_result_t
   14499 zone_send_secureserial(dns_zone_t *zone, isc_uint32_t serial) {
   14500 	isc_event_t *e;
   14501 	dns_zone_t *dummy = NULL;
   14502 
   14503 	e = isc_event_allocate(zone->secure->mctx, zone,
   14504 			       DNS_EVENT_ZONESECURESERIAL,
   14505 			       receive_secure_serial, zone->secure,
   14506 			       sizeof(struct secure_event));
   14507 	if (e == NULL)
   14508 		return (ISC_R_NOMEMORY);
   14509 	((struct secure_event *)e)->serial = serial;
   14510 	INSIST(LOCKED_ZONE(zone->secure));
   14511 	zone_iattach(zone->secure, &dummy);
   14512 	isc_task_send(zone->secure->task, &e);
   14513 
   14514 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
   14515 	return (ISC_R_SUCCESS);
   14516 }
   14517 
   14518 static isc_result_t
   14519 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
   14520 	       dns_rdataset_t *rdataset, isc_uint32_t oldserial)
   14521 {
   14522 	dns_rdata_soa_t soa;
   14523 	dns_rdata_t rdata = DNS_RDATA_INIT;
   14524 	dns_rdatalist_t temprdatalist;
   14525 	dns_rdataset_t temprdataset;
   14526 	isc_buffer_t b;
   14527 	isc_result_t result;
   14528 	unsigned char buf[DNS_SOA_BUFFERSIZE];
   14529 	dns_fixedname_t fixed;
   14530 	dns_name_t *name;
   14531 
   14532 	result = dns_rdataset_first(rdataset);
   14533 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14534 	dns_rdataset_current(rdataset, &rdata);
   14535 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
   14536 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14537 
   14538 	if (isc_serial_gt(soa.serial, oldserial))
   14539 		return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
   14540 					   NULL));
   14541 	/*
   14542 	 * Always bump the serial.
   14543 	 */
   14544 	oldserial++;
   14545 	if (oldserial == 0)
   14546 		oldserial++;
   14547 	soa.serial = oldserial;
   14548 
   14549 	/*
   14550 	 * Construct a replacement rdataset.
   14551 	 */
   14552 	dns_rdata_reset(&rdata);
   14553 	isc_buffer_init(&b, buf, sizeof(buf));
   14554 	result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
   14555 				      dns_rdatatype_soa, &soa, &b);
   14556 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14557 	dns_rdatalist_init(&temprdatalist);
   14558 	temprdatalist.rdclass = rdata.rdclass;
   14559 	temprdatalist.type = rdata.type;
   14560 	temprdatalist.ttl = rdataset->ttl;
   14561 	ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
   14562 
   14563 	dns_rdataset_init(&temprdataset);
   14564 	result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
   14565 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14566 
   14567 	name = dns_fixedname_initname(&fixed);
   14568 	result = dns_db_nodefullname(db, node, name);
   14569 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   14570 	dns_rdataset_getownercase(rdataset, name);
   14571 	dns_rdataset_setownercase(&temprdataset, name);
   14572 	return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
   14573 				   0, NULL));
   14574 }
   14575 
   14576 /*
   14577  * This function should populate an nsec3paramlist_t with the
   14578  * nsecparam_t data from a zone.
   14579  */
   14580 static isc_result_t
   14581 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
   14582 	isc_result_t result;
   14583 	dns_dbnode_t *node = NULL;
   14584 	dns_rdataset_t rdataset, prdataset;
   14585 	dns_dbversion_t *version = NULL;
   14586 	nsec3param_t *nsec3param = NULL;
   14587 	nsec3param_t *nsec3p = NULL;
   14588 	nsec3param_t *next;
   14589 	dns_db_t *db = NULL;
   14590 	unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   14591 
   14592 	REQUIRE(DNS_ZONE_VALID(zone));
   14593 	REQUIRE(nsec3list != NULL);
   14594 	REQUIRE(ISC_LIST_EMPTY(*nsec3list));
   14595 
   14596 	dns_rdataset_init(&rdataset);
   14597 	dns_rdataset_init(&prdataset);
   14598 
   14599 	dns_db_attach(zone->db, &db);
   14600 	CHECK(dns_db_getoriginnode(db, &node));
   14601 
   14602 	dns_db_currentversion(db, &version);
   14603 	result = dns_db_findrdataset(db, node, version,
   14604 				     dns_rdatatype_nsec3param,
   14605 				     dns_rdatatype_none, 0, &rdataset, NULL);
   14606 
   14607 	if (result != ISC_R_SUCCESS)
   14608 		goto getprivate;
   14609 
   14610 	/*
   14611 	 * walk nsec3param rdataset making a list of parameters (note that
   14612 	 * multiple simultaneous nsec3 chains are annoyingly legal -- this
   14613 	 * is why we use an nsec3list, even tho we will usually only have
   14614 	 * one)
   14615 	 */
   14616 	for (result = dns_rdataset_first(&rdataset);
   14617 	     result == ISC_R_SUCCESS;
   14618 	     result = dns_rdataset_next(&rdataset))
   14619 	{
   14620 		dns_rdata_t rdata = DNS_RDATA_INIT;
   14621 		dns_rdata_t private = DNS_RDATA_INIT;
   14622 
   14623 		dns_rdataset_current(&rdataset, &rdata);
   14624 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   14625 			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   14626 			      "looping through nsec3param data");
   14627 		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
   14628 		if (nsec3param == NULL)
   14629 			CHECK(ISC_R_NOMEMORY);
   14630 		ISC_LINK_INIT(nsec3param, link);
   14631 
   14632 		/*
   14633 		 * now transfer the data from the rdata to
   14634 		 * the nsec3param
   14635 		 */
   14636 		dns_nsec3param_toprivate(&rdata, &private,
   14637 					 zone->privatetype, nsec3param->data,
   14638 					 sizeof(nsec3param->data));
   14639 		nsec3param->length = private.length;
   14640 		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
   14641 	}
   14642 
   14643  getprivate:
   14644 	result = dns_db_findrdataset(db, node, version, zone->privatetype,
   14645 				     dns_rdatatype_none, 0, &prdataset, NULL);
   14646 	if (result != ISC_R_SUCCESS)
   14647 		goto done;
   14648 
   14649 	/*
   14650 	 * walk private type records, converting them to nsec3 parameters
   14651 	 * using dns_nsec3param_fromprivate(), do the right thing based on
   14652 	 * CREATE and REMOVE flags
   14653 	 */
   14654 	for (result = dns_rdataset_first(&prdataset);
   14655 	     result == ISC_R_SUCCESS;
   14656 	     result = dns_rdataset_next(&prdataset))
   14657 	{
   14658 		dns_rdata_t rdata = DNS_RDATA_INIT;
   14659 		dns_rdata_t private = DNS_RDATA_INIT;
   14660 
   14661 		dns_rdataset_current(&prdataset, &private);
   14662 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   14663 			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   14664 			      "looping through nsec3param private data");
   14665 
   14666 		/*
   14667 		 * Do we have a valid private record?
   14668 		 */
   14669 		if (!dns_nsec3param_fromprivate(&private, &rdata,
   14670 						buf, sizeof(buf)))
   14671 			continue;
   14672 
   14673 		/*
   14674 		 * Remove any NSEC3PARAM records scheduled to be removed.
   14675 		 */
   14676 		if (NSEC3REMOVE(rdata.data[1])) {
   14677 			/*
   14678 			 * Zero out the flags.
   14679 			 */
   14680 			rdata.data[1] = 0;
   14681 
   14682 			for (nsec3p = ISC_LIST_HEAD(*nsec3list);
   14683 			     nsec3p != NULL;
   14684 			     nsec3p = next)
   14685 			{
   14686 				next = ISC_LIST_NEXT(nsec3p, link);
   14687 
   14688 				if (nsec3p->length == rdata.length + 1 &&
   14689 				    memcmp(rdata.data, nsec3p->data + 1,
   14690 					   nsec3p->length - 1) == 0) {
   14691 					ISC_LIST_UNLINK(*nsec3list,
   14692 							nsec3p, link);
   14693 					isc_mem_put(zone->mctx, nsec3p,
   14694 						    sizeof(nsec3param_t));
   14695 				}
   14696 			}
   14697 			continue;
   14698 		}
   14699 
   14700 		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
   14701 		if (nsec3param == NULL)
   14702 			CHECK(ISC_R_NOMEMORY);
   14703 		ISC_LINK_INIT(nsec3param, link);
   14704 
   14705 		/*
   14706 		 * Copy the remaining private records so the nsec/nsec3
   14707 		 * chain gets created.
   14708 		 */
   14709 		INSIST(private.length <= sizeof(nsec3param->data));
   14710 		memmove(nsec3param->data, private.data, private.length);
   14711 		nsec3param->length = private.length;
   14712 		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
   14713 	}
   14714 
   14715  done:
   14716 	if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
   14717 		result = ISC_R_SUCCESS;
   14718 
   14719  failure:
   14720 	if (node != NULL)
   14721 		dns_db_detachnode(db, &node);
   14722 	if (version != NULL)
   14723 		dns_db_closeversion(db, &version, ISC_FALSE);
   14724 	if (db != NULL)
   14725 		dns_db_detach(&db);
   14726 	if (dns_rdataset_isassociated(&rdataset))
   14727 		dns_rdataset_disassociate(&rdataset);
   14728 	if (dns_rdataset_isassociated(&prdataset))
   14729 		dns_rdataset_disassociate(&prdataset);
   14730 	return (result);
   14731 }
   14732 
   14733 /*
   14734  * Populate new zone db with private type records found by save_nsec3param().
   14735  */
   14736 static isc_result_t
   14737 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
   14738 		   nsec3paramlist_t *nsec3list)
   14739 {
   14740 	isc_result_t result;
   14741 	dns_diff_t diff;
   14742 	dns_rdata_t rdata;
   14743 	nsec3param_t *nsec3p = NULL;
   14744 	nsec3param_t *next;
   14745 
   14746 	REQUIRE(DNS_ZONE_VALID(zone));
   14747 	REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
   14748 
   14749 	dns_diff_init(zone->mctx, &diff);
   14750 
   14751 	/*
   14752 	 * Loop through the list of private-type records, set the INITIAL
   14753 	 * and CREATE flags, and the add the record to the apex of the tree
   14754 	 * in db.
   14755 	 */
   14756 	for (nsec3p = ISC_LIST_HEAD(*nsec3list);
   14757 	     nsec3p != NULL;
   14758 	     nsec3p = next)
   14759 	{
   14760 		next = ISC_LIST_NEXT(nsec3p, link);
   14761 		dns_rdata_init(&rdata);
   14762 		nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
   14763 		rdata.length = nsec3p->length;
   14764 		rdata.data = nsec3p->data;
   14765 		rdata.type = zone->privatetype;
   14766 		rdata.rdclass = zone->rdclass;
   14767 		result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
   14768 				       &zone->origin, 0, &rdata);
   14769 		if (result != ISC_R_SUCCESS) {
   14770 			break;
   14771 		}
   14772 	}
   14773 
   14774 	dns_diff_clear(&diff);
   14775 	return (result);
   14776 }
   14777 
   14778 static void
   14779 receive_secure_db(isc_task_t *task, isc_event_t *event) {
   14780 	isc_result_t result;
   14781 	dns_zone_t *zone;
   14782 	dns_db_t *rawdb, *db = NULL;
   14783 	dns_dbnode_t *rawnode = NULL, *node = NULL;
   14784 	dns_fixedname_t fname;
   14785 	dns_name_t *name;
   14786 	dns_dbiterator_t *dbiterator = NULL;
   14787 	dns_rdatasetiter_t *rdsit = NULL;
   14788 	dns_rdataset_t rdataset;
   14789 	dns_dbversion_t *version = NULL;
   14790 	isc_time_t loadtime;
   14791 	unsigned int oldserial = 0;
   14792 	isc_boolean_t have_oldserial = ISC_FALSE;
   14793 	nsec3paramlist_t nsec3list;
   14794 
   14795 	UNUSED(task);
   14796 
   14797 	ISC_LIST_INIT(nsec3list);
   14798 
   14799 	zone = event->ev_arg;
   14800 	rawdb = ((struct secure_event *)event)->db;
   14801 	isc_event_free(&event);
   14802 
   14803 	name = dns_fixedname_initname(&fname);
   14804 	dns_rdataset_init(&rdataset);
   14805 
   14806 	LOCK_ZONE(zone);
   14807 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
   14808 		result = ISC_R_SHUTTINGDOWN;
   14809 		goto failure;
   14810 	}
   14811 
   14812 	TIME_NOW(&loadtime);
   14813 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   14814 	if (zone->db != NULL) {
   14815 		result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
   14816 		if (result == ISC_R_SUCCESS)
   14817 			have_oldserial = ISC_TRUE;
   14818 
   14819 		/*
   14820 		 * assemble nsec3parameters from the old zone, and set a flag
   14821 		 * if any are found
   14822 		 */
   14823 		result = save_nsec3param(zone, &nsec3list);
   14824 		if (result != ISC_R_SUCCESS) {
   14825 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   14826 			goto failure;
   14827 		}
   14828 	}
   14829 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   14830 
   14831 	result = dns_db_create(zone->mctx, zone->db_argv[0],
   14832 			       &zone->origin, dns_dbtype_zone, zone->rdclass,
   14833 			       zone->db_argc - 1, zone->db_argv + 1, &db);
   14834 	if (result != ISC_R_SUCCESS)
   14835 		goto failure;
   14836 
   14837 	result = dns_db_setgluecachestats(db, zone->gluecachestats);
   14838 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
   14839 		goto failure;
   14840 	}
   14841 
   14842 	result = dns_db_newversion(db, &version);
   14843 	if (result != ISC_R_SUCCESS)
   14844 		goto failure;
   14845 
   14846 	result = dns_db_createiterator(rawdb, 0, &dbiterator);
   14847 	if (result != ISC_R_SUCCESS)
   14848 		goto failure;
   14849 
   14850 	for (result = dns_dbiterator_first(dbiterator);
   14851 	     result == ISC_R_SUCCESS;
   14852 	     result = dns_dbiterator_next(dbiterator)) {
   14853 		result = dns_dbiterator_current(dbiterator, &rawnode, name);
   14854 		if (result != ISC_R_SUCCESS)
   14855 			continue;
   14856 
   14857 		result = dns_db_findnode(db, name, ISC_TRUE, &node);
   14858 		if (result != ISC_R_SUCCESS)
   14859 			goto failure;
   14860 
   14861 		result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
   14862 		if (result != ISC_R_SUCCESS)
   14863 			goto failure;
   14864 
   14865 		for (result = dns_rdatasetiter_first(rdsit);
   14866 		     result == ISC_R_SUCCESS;
   14867 		     result = dns_rdatasetiter_next(rdsit)) {
   14868 			dns_rdatasetiter_current(rdsit, &rdataset);
   14869 			if (rdataset.type == dns_rdatatype_nsec ||
   14870 			    rdataset.type == dns_rdatatype_rrsig ||
   14871 			    rdataset.type == dns_rdatatype_nsec3 ||
   14872 			    rdataset.type == dns_rdatatype_dnskey ||
   14873 			    rdataset.type == dns_rdatatype_nsec3param) {
   14874 				dns_rdataset_disassociate(&rdataset);
   14875 				continue;
   14876 			}
   14877 			if (rdataset.type == dns_rdatatype_soa &&
   14878 			    have_oldserial) {
   14879 				result = checkandaddsoa(db, node, version,
   14880 							&rdataset, oldserial);
   14881 			} else
   14882 				result = dns_db_addrdataset(db, node, version,
   14883 							    0, &rdataset, 0,
   14884 							    NULL);
   14885 			if (result != ISC_R_SUCCESS)
   14886 				goto failure;
   14887 
   14888 			dns_rdataset_disassociate(&rdataset);
   14889 		}
   14890 		dns_rdatasetiter_destroy(&rdsit);
   14891 		dns_db_detachnode(rawdb, &rawnode);
   14892 		dns_db_detachnode(db, &node);
   14893 	}
   14894 
   14895 	/*
   14896 	 * Call restore_nsec3param() to create private-type records from
   14897 	 * the old nsec3 parameters and insert them into db
   14898 	 */
   14899 	if (!ISC_LIST_EMPTY(nsec3list)) {
   14900 		result = restore_nsec3param(zone, db, version, &nsec3list);
   14901 		if (result != ISC_R_SUCCESS) {
   14902 			goto failure;
   14903 		}
   14904 	}
   14905 
   14906 	dns_db_closeversion(db, &version, ISC_TRUE);
   14907 
   14908 	/*
   14909 	 * Lock hierarchy: zmgr, zone, raw.
   14910 	 */
   14911 	INSIST(zone != zone->raw);
   14912 	LOCK_ZONE(zone->raw);
   14913 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   14914 	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
   14915 	zone_needdump(zone, 0); /* XXXMPA */
   14916 	UNLOCK_ZONE(zone->raw);
   14917 
   14918  failure:
   14919 	UNLOCK_ZONE(zone);
   14920 	if (result != ISC_R_SUCCESS)
   14921 		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
   14922 			     dns_result_totext(result));
   14923 
   14924 	while (!ISC_LIST_EMPTY(nsec3list)) {
   14925 		nsec3param_t *nsec3p;
   14926 		nsec3p = ISC_LIST_HEAD(nsec3list);
   14927 		ISC_LIST_UNLINK(nsec3list, nsec3p, link);
   14928 		isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
   14929 	}
   14930 	if (dns_rdataset_isassociated(&rdataset))
   14931 		dns_rdataset_disassociate(&rdataset);
   14932 	if (db != NULL) {
   14933 		if (node != NULL)
   14934 			dns_db_detachnode(db, &node);
   14935 		if (version != NULL)
   14936 			dns_db_closeversion(db, &version, ISC_FALSE);
   14937 		dns_db_detach(&db);
   14938 	}
   14939 	if (rawnode != NULL)
   14940 		dns_db_detachnode(rawdb, &rawnode);
   14941 	dns_db_detach(&rawdb);
   14942 	if (dbiterator != NULL)
   14943 		dns_dbiterator_destroy(&dbiterator);
   14944 	dns_zone_idetach(&zone);
   14945 
   14946 	INSIST(version == NULL);
   14947 }
   14948 
   14949 static isc_result_t
   14950 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
   14951 	isc_event_t *e;
   14952 	dns_db_t *dummy = NULL;
   14953 	dns_zone_t *secure = NULL;
   14954 
   14955 	e = isc_event_allocate(zone->secure->mctx, zone,
   14956 			       DNS_EVENT_ZONESECUREDB,
   14957 			       receive_secure_db, zone->secure,
   14958 			       sizeof(struct secure_event));
   14959 	if (e == NULL)
   14960 		return (ISC_R_NOMEMORY);
   14961 	dns_db_attach(db, &dummy);
   14962 	((struct secure_event *)e)->db = dummy;
   14963 	INSIST(LOCKED_ZONE(zone->secure));
   14964 	zone_iattach(zone->secure, &secure);
   14965 	isc_task_send(zone->secure->task, &e);
   14966 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
   14967 	return (ISC_R_SUCCESS);
   14968 }
   14969 
   14970 isc_result_t
   14971 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
   14972 	isc_result_t result;
   14973 	dns_zone_t *secure = NULL;
   14974 
   14975 	REQUIRE(DNS_ZONE_VALID(zone));
   14976  again:
   14977 	LOCK_ZONE(zone);
   14978 	if (inline_raw(zone)) {
   14979 		secure = zone->secure;
   14980 		INSIST(secure != zone);
   14981 		TRYLOCK_ZONE(result, secure);
   14982 		if (result != ISC_R_SUCCESS) {
   14983 			UNLOCK_ZONE(zone);
   14984 			secure = NULL;
   14985 #if ISC_PLATFORM_USETHREADS
   14986 			isc_thread_yield();
   14987 #endif
   14988 			goto again;
   14989 		}
   14990 	}
   14991 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
   14992 	result = zone_replacedb(zone, db, dump);
   14993 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
   14994 	if (secure != NULL)
   14995 		UNLOCK_ZONE(secure);
   14996 	UNLOCK_ZONE(zone);
   14997 	return (result);
   14998 }
   14999 
   15000 static isc_result_t
   15001 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
   15002 	dns_dbversion_t *ver;
   15003 	isc_result_t result;
   15004 	unsigned int soacount = 0;
   15005 	unsigned int nscount = 0;
   15006 
   15007 	/*
   15008 	 * 'zone' and 'zone->db' locked by caller.
   15009 	 */
   15010 	REQUIRE(DNS_ZONE_VALID(zone));
   15011 	REQUIRE(LOCKED_ZONE(zone));
   15012 	if (inline_raw(zone))
   15013 		REQUIRE(LOCKED_ZONE(zone->secure));
   15014 
   15015 	result = zone_get_from_db(zone, db, &nscount, &soacount,
   15016 				  NULL, NULL, NULL, NULL, NULL, NULL);
   15017 	if (result == ISC_R_SUCCESS) {
   15018 		if (soacount != 1) {
   15019 			dns_zone_log(zone, ISC_LOG_ERROR,
   15020 				     "has %d SOA records", soacount);
   15021 			result = DNS_R_BADZONE;
   15022 		}
   15023 		if (nscount == 0 && zone->type != dns_zone_key) {
   15024 			dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
   15025 			result = DNS_R_BADZONE;
   15026 		}
   15027 		if (result != ISC_R_SUCCESS)
   15028 			return (result);
   15029 	} else {
   15030 		dns_zone_log(zone, ISC_LOG_ERROR,
   15031 			    "retrieving SOA and NS records failed: %s",
   15032 			    dns_result_totext(result));
   15033 		return (result);
   15034 	}
   15035 
   15036 	result = check_nsec3param(zone, db);
   15037 	if (result != ISC_R_SUCCESS)
   15038 		return (result);
   15039 
   15040 	ver = NULL;
   15041 	dns_db_currentversion(db, &ver);
   15042 
   15043 	/*
   15044 	 * The initial version of a slave zone is always dumped;
   15045 	 * subsequent versions may be journaled instead if this
   15046 	 * is enabled in the configuration.
   15047 	 */
   15048 	if (zone->db != NULL && zone->journal != NULL &&
   15049 	    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
   15050 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
   15051 	{
   15052 		isc_uint32_t serial, oldserial;
   15053 
   15054 		dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
   15055 
   15056 		result = dns_db_getsoaserial(db, ver, &serial);
   15057 		if (result != ISC_R_SUCCESS) {
   15058 			dns_zone_log(zone, ISC_LOG_ERROR,
   15059 				     "ixfr-from-differences: unable to get "
   15060 				     "new serial");
   15061 			goto fail;
   15062 		}
   15063 
   15064 		/*
   15065 		 * This is checked in zone_postload() for master zones.
   15066 		 */
   15067 		result = zone_get_from_db(zone, zone->db, NULL, &soacount,
   15068 					  &oldserial, NULL, NULL, NULL, NULL,
   15069 					  NULL);
   15070 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   15071 		RUNTIME_CHECK(soacount > 0U);
   15072 		if ((zone->type == dns_zone_slave ||
   15073 		     (zone->type == dns_zone_redirect &&
   15074 		      zone->masters != NULL))
   15075 		    && !isc_serial_gt(serial, oldserial)) {
   15076 			isc_uint32_t serialmin, serialmax;
   15077 			serialmin = (oldserial + 1) & 0xffffffffU;
   15078 			serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
   15079 			dns_zone_log(zone, ISC_LOG_ERROR,
   15080 				     "ixfr-from-differences: failed: "
   15081 				     "new serial (%u) out of range [%u - %u]",
   15082 				     serial, serialmin, serialmax);
   15083 			result = ISC_R_RANGE;
   15084 			goto fail;
   15085 		}
   15086 
   15087 		result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
   15088 				     zone->journal);
   15089 		if (result != ISC_R_SUCCESS) {
   15090 			char strbuf[ISC_STRERRORSIZE];
   15091 			isc__strerror(errno, strbuf, sizeof(strbuf));
   15092 			dns_zone_log(zone, ISC_LOG_ERROR,
   15093 				     "ixfr-from-differences: failed: "
   15094 				     "%s", strbuf);
   15095 			goto fallback;
   15096 		}
   15097 		if (dump)
   15098 			zone_needdump(zone, DNS_DUMP_DELAY);
   15099 		else
   15100 			zone_journal_compact(zone, zone->db, serial);
   15101 		if (zone->type == dns_zone_master && inline_raw(zone))
   15102 			zone_send_secureserial(zone, serial);
   15103 	} else {
   15104  fallback:
   15105 		if (dump && zone->masterfile != NULL) {
   15106 			/*
   15107 			 * If DNS_ZONEFLG_FORCEXFER was set we don't want
   15108 			 * to keep the old masterfile.
   15109 			 */
   15110 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
   15111 			    remove(zone->masterfile) < 0 && errno != ENOENT) {
   15112 				char strbuf[ISC_STRERRORSIZE];
   15113 				isc__strerror(errno, strbuf, sizeof(strbuf));
   15114 				isc_log_write(dns_lctx,
   15115 					      DNS_LOGCATEGORY_GENERAL,
   15116 					      DNS_LOGMODULE_ZONE,
   15117 					      ISC_LOG_WARNING,
   15118 					      "unable to remove masterfile "
   15119 					      "'%s': '%s'",
   15120 					      zone->masterfile, strbuf);
   15121 			}
   15122 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
   15123 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
   15124 			else
   15125 				zone_needdump(zone, 0);
   15126 		}
   15127 		if (dump && zone->journal != NULL) {
   15128 			/*
   15129 			 * The in-memory database just changed, and
   15130 			 * because 'dump' is set, it didn't change by
   15131 			 * being loaded from disk.  Also, we have not
   15132 			 * journaled diffs for this change.
   15133 			 * Therefore, the on-disk journal is missing
   15134 			 * the deltas for this change.	Since it can
   15135 			 * no longer be used to bring the zone
   15136 			 * up-to-date, it is useless and should be
   15137 			 * removed.
   15138 			 */
   15139 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   15140 				      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   15141 				      "removing journal file");
   15142 			if (remove(zone->journal) < 0 && errno != ENOENT) {
   15143 				char strbuf[ISC_STRERRORSIZE];
   15144 				isc__strerror(errno, strbuf, sizeof(strbuf));
   15145 				isc_log_write(dns_lctx,
   15146 					      DNS_LOGCATEGORY_GENERAL,
   15147 					      DNS_LOGMODULE_ZONE,
   15148 					      ISC_LOG_WARNING,
   15149 					      "unable to remove journal "
   15150 					      "'%s': '%s'",
   15151 					      zone->journal, strbuf);
   15152 			}
   15153 		}
   15154 
   15155 		if (inline_raw(zone))
   15156 			zone_send_securedb(zone, db);
   15157 	}
   15158 
   15159 	dns_db_closeversion(db, &ver, ISC_FALSE);
   15160 
   15161 	dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
   15162 
   15163 	if (zone->db != NULL)
   15164 		zone_detachdb(zone);
   15165 	zone_attachdb(zone, db);
   15166 	dns_db_settask(zone->db, zone->task);
   15167 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
   15168 	return (ISC_R_SUCCESS);
   15169 
   15170  fail:
   15171 	dns_db_closeversion(db, &ver, ISC_FALSE);
   15172 	return (result);
   15173 }
   15174 
   15175 /* The caller must hold the dblock as a writer. */
   15176 static inline void
   15177 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
   15178 	REQUIRE(zone->db == NULL && db != NULL);
   15179 
   15180 	dns_db_attach(db, &zone->db);
   15181 }
   15182 
   15183 /* The caller must hold the dblock as a writer. */
   15184 static inline void
   15185 zone_detachdb(dns_zone_t *zone) {
   15186 	REQUIRE(zone->db != NULL);
   15187 
   15188 	dns_db_detach(&zone->db);
   15189 }
   15190 
   15191 static void
   15192 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
   15193 	isc_time_t now;
   15194 	isc_boolean_t again = ISC_FALSE;
   15195 	unsigned int soacount;
   15196 	unsigned int nscount;
   15197 	isc_uint32_t serial, refresh, retry, expire, minimum;
   15198 	isc_result_t xfrresult = result;
   15199 	isc_boolean_t free_needed;
   15200 	dns_zone_t *secure = NULL;
   15201 
   15202 	REQUIRE(DNS_ZONE_VALID(zone));
   15203 
   15204 	dns_zone_log(zone, ISC_LOG_DEBUG(1),
   15205 		     "zone transfer finished: %s", dns_result_totext(result));
   15206 
   15207 	/*
   15208 	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
   15209 	 * could result in a deadlock due to a LOR so we will spin if we
   15210 	 * can't obtain the both locks.
   15211 	 */
   15212  again:
   15213 	LOCK_ZONE(zone);
   15214 	if (inline_raw(zone)) {
   15215 		secure = zone->secure;
   15216 		INSIST(secure != zone);
   15217 		TRYLOCK_ZONE(result, secure);
   15218 		if (result != ISC_R_SUCCESS) {
   15219 			UNLOCK_ZONE(zone);
   15220 			secure = NULL;
   15221 #if ISC_PLATFORM_USETHREADS
   15222 			isc_thread_yield();
   15223 #endif
   15224 			goto again;
   15225 		}
   15226 	}
   15227 
   15228 	INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
   15229 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
   15230 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
   15231 
   15232 	TIME_NOW(&now);
   15233 	switch (xfrresult) {
   15234 	case ISC_R_SUCCESS:
   15235 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   15236 		/* FALLTHROUGH */
   15237 	case DNS_R_UPTODATE:
   15238 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
   15239 		/*
   15240 		 * Has the zone expired underneath us?
   15241 		 */
   15242 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   15243 		if (zone->db == NULL) {
   15244 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   15245 			goto same_master;
   15246 		}
   15247 
   15248 		/*
   15249 		 * Update the zone structure's data from the actual
   15250 		 * SOA received.
   15251 		 */
   15252 		nscount = 0;
   15253 		soacount = 0;
   15254 		INSIST(zone->db != NULL);
   15255 		result = zone_get_from_db(zone, zone->db, &nscount,
   15256 					  &soacount, &serial, &refresh,
   15257 					  &retry, &expire, &minimum, NULL);
   15258 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   15259 		if (result == ISC_R_SUCCESS) {
   15260 			if (soacount != 1)
   15261 				dns_zone_log(zone, ISC_LOG_ERROR,
   15262 					     "transferred zone "
   15263 					     "has %d SOA record%s", soacount,
   15264 					     (soacount != 0) ? "s" : "");
   15265 			if (nscount == 0) {
   15266 				dns_zone_log(zone, ISC_LOG_ERROR,
   15267 					     "transferred zone "
   15268 					     "has no NS records");
   15269 				if (DNS_ZONE_FLAG(zone,
   15270 						  DNS_ZONEFLG_HAVETIMERS)) {
   15271 					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
   15272 					zone->retry = DNS_ZONE_DEFAULTRETRY;
   15273 				}
   15274 				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   15275 				zone_unload(zone);
   15276 				goto next_master;
   15277 			}
   15278 			zone->refresh = RANGE(refresh, zone->minrefresh,
   15279 					      zone->maxrefresh);
   15280 			zone->retry = RANGE(retry, zone->minretry,
   15281 					    zone->maxretry);
   15282 			zone->expire = RANGE(expire,
   15283 					     zone->refresh + zone->retry,
   15284 					     DNS_MAX_EXPIRE);
   15285 			zone->minimum = minimum;
   15286 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
   15287 		}
   15288 
   15289 		/*
   15290 		 * Set our next update/expire times.
   15291 		 */
   15292 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
   15293 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
   15294 			zone->refreshtime = now;
   15295 			DNS_ZONE_TIME_ADD(&now, zone->expire,
   15296 					  &zone->expiretime);
   15297 		} else {
   15298 			DNS_ZONE_JITTER_ADD(&now, zone->refresh,
   15299 					    &zone->refreshtime);
   15300 			DNS_ZONE_TIME_ADD(&now, zone->expire,
   15301 					  &zone->expiretime);
   15302 		}
   15303 		if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
   15304 			char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
   15305 			if (zone->tsigkey != NULL) {
   15306 				char namebuf[DNS_NAME_FORMATSIZE];
   15307 				dns_name_format(&zone->tsigkey->name, namebuf,
   15308 						sizeof(namebuf));
   15309 				snprintf(buf, sizeof(buf), ": TSIG '%s'",
   15310 					 namebuf);
   15311 			} else
   15312 				buf[0] = '\0';
   15313 			dns_zone_log(zone, ISC_LOG_INFO,
   15314 				     "transferred serial %u%s",
   15315 				     serial, buf);
   15316 			if (inline_raw(zone))
   15317 				zone_send_secureserial(zone, serial);
   15318 		}
   15319 
   15320 		/*
   15321 		 * This is not necessary if we just performed a AXFR
   15322 		 * however it is necessary for an IXFR / UPTODATE and
   15323 		 * won't hurt with an AXFR.
   15324 		 */
   15325 		if (zone->masterfile != NULL || zone->journal != NULL) {
   15326 			unsigned int delay = DNS_DUMP_DELAY;
   15327 
   15328 			result = ISC_R_FAILURE;
   15329 			if (zone->journal != NULL)
   15330 				result = isc_file_settime(zone->journal, &now);
   15331 			if (result != ISC_R_SUCCESS &&
   15332 			    zone->masterfile != NULL)
   15333 				result = isc_file_settime(zone->masterfile,
   15334 							  &now);
   15335 
   15336 			if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
   15337 			    result == ISC_R_FILENOTFOUND)
   15338 				delay = 0;
   15339 
   15340 			if ((result == ISC_R_SUCCESS ||
   15341 			    result == ISC_R_FILENOTFOUND) &&
   15342 			    zone->masterfile != NULL)
   15343 				zone_needdump(zone, delay);
   15344 			else if (result != ISC_R_SUCCESS)
   15345 				dns_zone_log(zone, ISC_LOG_ERROR,
   15346 					     "transfer: could not set file "
   15347 					     "modification time of '%s': %s",
   15348 					     zone->masterfile,
   15349 					     dns_result_totext(result));
   15350 		}
   15351 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
   15352 		inc_stats(zone, dns_zonestatscounter_xfrsuccess);
   15353 		break;
   15354 
   15355 	case DNS_R_BADIXFR:
   15356 		/* Force retry with AXFR. */
   15357 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
   15358 		goto same_master;
   15359 
   15360 	case DNS_R_TOOMANYRECORDS:
   15361 		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
   15362 		inc_stats(zone, dns_zonestatscounter_xfrfail);
   15363 		break;
   15364 
   15365 	default:
   15366 	next_master:
   15367 		/*
   15368 		 * Skip to next failed / untried master.
   15369 		 */
   15370 		do {
   15371 			zone->curmaster++;
   15372 		} while (zone->curmaster < zone->masterscnt &&
   15373 			 zone->mastersok[zone->curmaster]);
   15374 		/* FALLTHROUGH */
   15375 	same_master:
   15376 		if (zone->curmaster >= zone->masterscnt) {
   15377 			zone->curmaster = 0;
   15378 			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
   15379 			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
   15380 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
   15381 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
   15382 				while (zone->curmaster < zone->masterscnt &&
   15383 				       zone->mastersok[zone->curmaster])
   15384 					zone->curmaster++;
   15385 				again = ISC_TRUE;
   15386 			} else
   15387 				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
   15388 		} else {
   15389 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
   15390 			again = ISC_TRUE;
   15391 		}
   15392 		inc_stats(zone, dns_zonestatscounter_xfrfail);
   15393 		break;
   15394 	}
   15395 	zone_settimer(zone, &now);
   15396 
   15397 	/*
   15398 	 * If creating the transfer object failed, zone->xfr is NULL.
   15399 	 * Otherwise, we are called as the done callback of a zone
   15400 	 * transfer object that just entered its shutting-down
   15401 	 * state.  Since we are no longer responsible for shutting
   15402 	 * it down, we can detach our reference.
   15403 	 */
   15404 	if (zone->xfr != NULL)
   15405 		dns_xfrin_detach(&zone->xfr);
   15406 
   15407 	if (zone->tsigkey != NULL)
   15408 		dns_tsigkey_detach(&zone->tsigkey);
   15409 
   15410 	/*
   15411 	 * Handle any deferred journal compaction.
   15412 	 */
   15413 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
   15414 		dns_db_t *db = NULL;
   15415 		if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
   15416 			zone_journal_compact(zone, db, zone->compact_serial);
   15417 			dns_db_detach(&db);
   15418 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
   15419 		}
   15420 	}
   15421 
   15422 	if (secure != NULL)
   15423 		UNLOCK_ZONE(secure);
   15424 	/*
   15425 	 * This transfer finishing freed up a transfer quota slot.
   15426 	 * Let any other zones waiting for quota have it.
   15427 	 */
   15428 	if (zone->zmgr != NULL &&
   15429 	    zone->statelist == &zone->zmgr->xfrin_in_progress) {
   15430 		UNLOCK_ZONE(zone);
   15431 		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   15432 		ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
   15433 		zone->statelist = NULL;
   15434 		zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
   15435 		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
   15436 		LOCK_ZONE(zone);
   15437 	}
   15438 
   15439 	/*
   15440 	 * Retry with a different server if necessary.
   15441 	 */
   15442 	if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
   15443 		queue_soa_query(zone);
   15444 
   15445 	INSIST(zone->irefs > 0);
   15446 	zone->irefs--;
   15447 	free_needed = exit_check(zone);
   15448 	UNLOCK_ZONE(zone);
   15449 	if (free_needed)
   15450 		zone_free(zone);
   15451 }
   15452 
   15453 static void
   15454 zone_loaddone(void *arg, isc_result_t result) {
   15455 	static char me[] = "zone_loaddone";
   15456 	dns_load_t *load = arg;
   15457 	dns_zone_t *zone;
   15458 	isc_result_t tresult;
   15459 	dns_zone_t *secure = NULL;
   15460 
   15461 	REQUIRE(DNS_LOAD_VALID(load));
   15462 	zone = load->zone;
   15463 
   15464 	ENTER;
   15465 
   15466 	tresult = dns_db_endload(load->db, &load->callbacks);
   15467 	if (tresult != ISC_R_SUCCESS &&
   15468 	    (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
   15469 		result = tresult;
   15470 
   15471 	/*
   15472 	 * Lock hierarchy: zmgr, zone, raw.
   15473 	 */
   15474  again:
   15475 	LOCK_ZONE(zone);
   15476 	INSIST(zone != zone->raw);
   15477 	if (inline_secure(zone))
   15478 		LOCK_ZONE(zone->raw);
   15479 	else if (inline_raw(zone)) {
   15480 		secure = zone->secure;
   15481 		TRYLOCK_ZONE(result, secure);
   15482 		if (result != ISC_R_SUCCESS) {
   15483 			UNLOCK_ZONE(zone);
   15484 			secure = NULL;
   15485 #if ISC_PLATFORM_USETHREADS
   15486 			isc_thread_yield();
   15487 #endif
   15488 			goto again;
   15489 		}
   15490 	}
   15491 	(void)zone_postload(zone, load->db, load->loadtime, result);
   15492 	zonemgr_putio(&zone->readio);
   15493 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
   15494 	zone_idetach(&load->callbacks.zone);
   15495 	/*
   15496 	 * Leave the zone frozen if the reload fails.
   15497 	 */
   15498 	if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
   15499 	     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
   15500 		zone->update_disabled = ISC_FALSE;
   15501 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
   15502 	if (inline_secure(zone))
   15503 		UNLOCK_ZONE(zone->raw);
   15504 	else if (secure != NULL)
   15505 		UNLOCK_ZONE(secure);
   15506 	UNLOCK_ZONE(zone);
   15507 
   15508 	load->magic = 0;
   15509 	dns_db_detach(&load->db);
   15510 	if (load->zone->lctx != NULL)
   15511 		dns_loadctx_detach(&load->zone->lctx);
   15512 	dns_zone_idetach(&load->zone);
   15513 	isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
   15514 }
   15515 
   15516 void
   15517 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
   15518 	REQUIRE(DNS_ZONE_VALID(zone));
   15519 	REQUIRE(table != NULL);
   15520 	REQUIRE(*table == NULL);
   15521 
   15522 	LOCK_ZONE(zone);
   15523 	if (zone->ssutable != NULL)
   15524 		dns_ssutable_attach(zone->ssutable, table);
   15525 	UNLOCK_ZONE(zone);
   15526 }
   15527 
   15528 void
   15529 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
   15530 	REQUIRE(DNS_ZONE_VALID(zone));
   15531 
   15532 	LOCK_ZONE(zone);
   15533 	if (zone->ssutable != NULL)
   15534 		dns_ssutable_detach(&zone->ssutable);
   15535 	if (table != NULL)
   15536 		dns_ssutable_attach(table, &zone->ssutable);
   15537 	UNLOCK_ZONE(zone);
   15538 }
   15539 
   15540 void
   15541 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
   15542 	REQUIRE(DNS_ZONE_VALID(zone));
   15543 
   15544 	zone->sigvalidityinterval = interval;
   15545 }
   15546 
   15547 isc_uint32_t
   15548 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
   15549 	REQUIRE(DNS_ZONE_VALID(zone));
   15550 
   15551 	return (zone->sigvalidityinterval);
   15552 }
   15553 
   15554 void
   15555 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
   15556 	isc_time_t now;
   15557 
   15558 	REQUIRE(DNS_ZONE_VALID(zone));
   15559 
   15560 	LOCK_ZONE(zone);
   15561 	zone->sigresigninginterval = interval;
   15562 	set_resigntime(zone);
   15563 	if (zone->task != NULL) {
   15564 		TIME_NOW(&now);
   15565 		zone_settimer(zone, &now);
   15566 	}
   15567 	UNLOCK_ZONE(zone);
   15568 }
   15569 
   15570 isc_uint32_t
   15571 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
   15572 	REQUIRE(DNS_ZONE_VALID(zone));
   15573 
   15574 	return (zone->sigresigninginterval);
   15575 }
   15576 
   15577 static void
   15578 queue_xfrin(dns_zone_t *zone) {
   15579 	const char me[] = "queue_xfrin";
   15580 	isc_result_t result;
   15581 	dns_zonemgr_t *zmgr = zone->zmgr;
   15582 
   15583 	ENTER;
   15584 
   15585 	INSIST(zone->statelist == NULL);
   15586 
   15587 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   15588 	ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
   15589 	LOCK_ZONE(zone);
   15590 	zone->irefs++;
   15591 	UNLOCK_ZONE(zone);
   15592 	zone->statelist = &zmgr->waiting_for_xfrin;
   15593 	result = zmgr_start_xfrin_ifquota(zmgr, zone);
   15594 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   15595 
   15596 	if (result == ISC_R_QUOTA) {
   15597 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
   15598 			      "zone transfer deferred due to quota");
   15599 	} else if (result != ISC_R_SUCCESS) {
   15600 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
   15601 			      "starting zone transfer: %s",
   15602 			      isc_result_totext(result));
   15603 	}
   15604 }
   15605 
   15606 /*
   15607  * This event callback is called when a zone has received
   15608  * any necessary zone transfer quota.  This is the time
   15609  * to go ahead and start the transfer.
   15610  */
   15611 static void
   15612 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
   15613 	isc_result_t result = ISC_R_SUCCESS;
   15614 	dns_peer_t *peer = NULL;
   15615 	char master[ISC_SOCKADDR_FORMATSIZE];
   15616 	char source[ISC_SOCKADDR_FORMATSIZE];
   15617 	dns_rdatatype_t xfrtype;
   15618 	dns_zone_t *zone = event->ev_arg;
   15619 	isc_netaddr_t masterip;
   15620 	isc_sockaddr_t sourceaddr;
   15621 	isc_sockaddr_t masteraddr;
   15622 	isc_time_t now;
   15623 	const char *soa_before = "";
   15624 	isc_dscp_t dscp = -1;
   15625 	isc_boolean_t loaded;
   15626 
   15627 	UNUSED(task);
   15628 
   15629 	INSIST(task == zone->task);
   15630 
   15631 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   15632 		result = ISC_R_CANCELED;
   15633 		goto cleanup;
   15634 	}
   15635 
   15636 	TIME_NOW(&now);
   15637 
   15638 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
   15639 	if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
   15640 				    &zone->sourceaddr, &now))
   15641 	{
   15642 		isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
   15643 		dns_zone_log(zone, ISC_LOG_INFO,
   15644 			     "got_transfer_quota: skipping zone transfer as "
   15645 			     "master %s (source %s) is unreachable (cached)",
   15646 			     master, source);
   15647 		result = ISC_R_CANCELED;
   15648 		goto cleanup;
   15649 	}
   15650 
   15651 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
   15652 	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
   15653 
   15654 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
   15655 		soa_before = "SOA before ";
   15656 	/*
   15657 	 * Decide whether we should request IXFR or AXFR.
   15658 	 */
   15659 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   15660 	loaded = ISC_TF(zone->db != NULL);
   15661 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   15662 
   15663 	if (!loaded) {
   15664 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
   15665 			     "no database exists yet, requesting AXFR of "
   15666 			     "initial version from %s", master);
   15667 		xfrtype = dns_rdatatype_axfr;
   15668 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
   15669 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
   15670 			     "forced reload, requesting AXFR of "
   15671 			     "initial version from %s", master);
   15672 		xfrtype = dns_rdatatype_axfr;
   15673 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
   15674 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
   15675 			     "retrying with AXFR from %s due to "
   15676 			     "previous IXFR failure", master);
   15677 		xfrtype = dns_rdatatype_axfr;
   15678 		LOCK_ZONE(zone);
   15679 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
   15680 		UNLOCK_ZONE(zone);
   15681 	} else {
   15682 		isc_boolean_t use_ixfr = ISC_TRUE;
   15683 		if (peer != NULL)
   15684 			result = dns_peer_getrequestixfr(peer, &use_ixfr);
   15685 		if (peer == NULL || result != ISC_R_SUCCESS)
   15686 			use_ixfr = zone->requestixfr;
   15687 		if (use_ixfr == ISC_FALSE) {
   15688 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   15689 				     "IXFR disabled, requesting %sAXFR from %s",
   15690 				     soa_before, master);
   15691 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
   15692 				xfrtype = dns_rdatatype_soa;
   15693 			else
   15694 				xfrtype = dns_rdatatype_axfr;
   15695 		} else {
   15696 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   15697 				     "requesting IXFR from %s", master);
   15698 			xfrtype = dns_rdatatype_ixfr;
   15699 		}
   15700 	}
   15701 
   15702 	/*
   15703 	 * Determine if we should attempt to sign the request with TSIG.
   15704 	 */
   15705 	result = ISC_R_NOTFOUND;
   15706 
   15707 	/*
   15708 	 * First, look for a tsig key in the master statement, then
   15709 	 * try for a server key.
   15710 	 */
   15711 	if ((zone->masterkeynames != NULL) &&
   15712 	    (zone->masterkeynames[zone->curmaster] != NULL)) {
   15713 		dns_view_t *view = dns_zone_getview(zone);
   15714 		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
   15715 		result = dns_view_gettsig(view, keyname, &zone->tsigkey);
   15716 	}
   15717 	if (zone->tsigkey == NULL)
   15718 		result = dns_view_getpeertsig(zone->view, &masterip,
   15719 					      &zone->tsigkey);
   15720 
   15721 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
   15722 		dns_zone_log(zone, ISC_LOG_ERROR,
   15723 			     "could not get TSIG key for zone transfer: %s",
   15724 			     isc_result_totext(result));
   15725 	}
   15726 
   15727 	if (zone->masterdscps != NULL)
   15728 	    dscp = zone->masterdscps[zone->curmaster];
   15729 
   15730 	LOCK_ZONE(zone);
   15731 	masteraddr = zone->masteraddr;
   15732 	sourceaddr = zone->sourceaddr;
   15733 	switch (isc_sockaddr_pf(&masteraddr)) {
   15734 	case PF_INET:
   15735 		if (dscp == -1)
   15736 			dscp = zone->xfrsource4dscp;
   15737 		break;
   15738 	case PF_INET6:
   15739 		if (dscp == -1)
   15740 			dscp = zone->xfrsource6dscp;
   15741 		break;
   15742 	default:
   15743 		INSIST(0);
   15744 	};
   15745 	UNLOCK_ZONE(zone);
   15746 	INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
   15747 	result = dns_xfrin_create3(zone, xfrtype, &masteraddr, &sourceaddr,
   15748 				   dscp, zone->tsigkey, zone->mctx,
   15749 				   zone->zmgr->timermgr, zone->zmgr->socketmgr,
   15750 				   zone->task, zone_xfrdone, &zone->xfr);
   15751 	if (result == ISC_R_SUCCESS) {
   15752 		LOCK_ZONE(zone);
   15753 		if (xfrtype == dns_rdatatype_axfr) {
   15754 			if (isc_sockaddr_pf(&masteraddr) == PF_INET)
   15755 				inc_stats(zone, dns_zonestatscounter_axfrreqv4);
   15756 			else
   15757 				inc_stats(zone, dns_zonestatscounter_axfrreqv6);
   15758 		} else if (xfrtype == dns_rdatatype_ixfr) {
   15759 			if (isc_sockaddr_pf(&masteraddr) == PF_INET)
   15760 				inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
   15761 			else
   15762 				inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
   15763 		}
   15764 		UNLOCK_ZONE(zone);
   15765 	}
   15766  cleanup:
   15767 	/*
   15768 	 * Any failure in this function is handled like a failed
   15769 	 * zone transfer.  This ensures that we get removed from
   15770 	 * zmgr->xfrin_in_progress.
   15771 	 */
   15772 	if (result != ISC_R_SUCCESS)
   15773 		zone_xfrdone(zone, result);
   15774 
   15775 	isc_event_free(&event);
   15776 }
   15777 
   15778 /*
   15779  * Update forwarding support.
   15780  */
   15781 
   15782 static void
   15783 forward_destroy(dns_forward_t *forward) {
   15784 
   15785 	forward->magic = 0;
   15786 	if (forward->request != NULL)
   15787 		dns_request_destroy(&forward->request);
   15788 	if (forward->msgbuf != NULL)
   15789 		isc_buffer_free(&forward->msgbuf);
   15790 	if (forward->zone != NULL) {
   15791 		LOCK(&forward->zone->lock);
   15792 		if (ISC_LINK_LINKED(forward, link))
   15793 			ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
   15794 		UNLOCK(&forward->zone->lock);
   15795 		dns_zone_idetach(&forward->zone);
   15796 	}
   15797 	isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
   15798 }
   15799 
   15800 static isc_result_t
   15801 sendtomaster(dns_forward_t *forward) {
   15802 	isc_result_t result;
   15803 	isc_sockaddr_t src;
   15804 	isc_dscp_t dscp = -1;
   15805 
   15806 	LOCK_ZONE(forward->zone);
   15807 
   15808 	if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
   15809 		UNLOCK_ZONE(forward->zone);
   15810 		return (ISC_R_CANCELED);
   15811 	}
   15812 
   15813 	if (forward->which >= forward->zone->masterscnt) {
   15814 		UNLOCK_ZONE(forward->zone);
   15815 		return (ISC_R_NOMORE);
   15816 	}
   15817 
   15818 	forward->addr = forward->zone->masters[forward->which];
   15819 	/*
   15820 	 * Always use TCP regardless of whether the original update
   15821 	 * used TCP.
   15822 	 * XXX The timeout may but a bit small if we are far down a
   15823 	 * transfer graph and the master has to try several masters.
   15824 	 */
   15825 	switch (isc_sockaddr_pf(&forward->addr)) {
   15826 	case PF_INET:
   15827 		src = forward->zone->xfrsource4;
   15828 		dscp = forward->zone->xfrsource4dscp;
   15829 		break;
   15830 	case PF_INET6:
   15831 		src = forward->zone->xfrsource6;
   15832 		dscp = forward->zone->xfrsource6dscp;
   15833 		break;
   15834 	default:
   15835 		result = ISC_R_NOTIMPLEMENTED;
   15836 		goto unlock;
   15837 	}
   15838 	result = dns_request_createraw4(forward->zone->view->requestmgr,
   15839 					forward->msgbuf,
   15840 					&src, &forward->addr, dscp,
   15841 					forward->options, 15 /* XXX */,
   15842 					0, 0, forward->zone->task,
   15843 					forward_callback, forward,
   15844 					&forward->request);
   15845 	if (result == ISC_R_SUCCESS) {
   15846 		if (!ISC_LINK_LINKED(forward, link))
   15847 			ISC_LIST_APPEND(forward->zone->forwards, forward, link);
   15848 	}
   15849 
   15850  unlock:
   15851 	UNLOCK_ZONE(forward->zone);
   15852 	return (result);
   15853 }
   15854 
   15855 static void
   15856 forward_callback(isc_task_t *task, isc_event_t *event) {
   15857 	const char me[] = "forward_callback";
   15858 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
   15859 	dns_message_t *msg = NULL;
   15860 	char master[ISC_SOCKADDR_FORMATSIZE];
   15861 	isc_result_t result;
   15862 	dns_forward_t *forward;
   15863 	dns_zone_t *zone;
   15864 
   15865 	UNUSED(task);
   15866 
   15867 	forward = revent->ev_arg;
   15868 	INSIST(DNS_FORWARD_VALID(forward));
   15869 	zone = forward->zone;
   15870 	INSIST(DNS_ZONE_VALID(zone));
   15871 
   15872 	ENTER;
   15873 
   15874 	isc_sockaddr_format(&forward->addr, master, sizeof(master));
   15875 
   15876 	if (revent->result != ISC_R_SUCCESS) {
   15877 		dns_zone_log(zone, ISC_LOG_INFO,
   15878 			     "could not forward dynamic update to %s: %s",
   15879 			     master, dns_result_totext(revent->result));
   15880 		goto next_master;
   15881 	}
   15882 
   15883 	result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
   15884 	if (result != ISC_R_SUCCESS)
   15885 		goto next_master;
   15886 
   15887 	result = dns_request_getresponse(revent->request, msg,
   15888 					 DNS_MESSAGEPARSE_PRESERVEORDER |
   15889 					 DNS_MESSAGEPARSE_CLONEBUFFER);
   15890 	if (result != ISC_R_SUCCESS)
   15891 		goto next_master;
   15892 
   15893 	switch (msg->rcode) {
   15894 	/*
   15895 	 * Pass these rcodes back to client.
   15896 	 */
   15897 	case dns_rcode_noerror:
   15898 	case dns_rcode_yxdomain:
   15899 	case dns_rcode_yxrrset:
   15900 	case dns_rcode_nxrrset:
   15901 	case dns_rcode_refused:
   15902 	case dns_rcode_nxdomain: {
   15903 		char rcode[128];
   15904 		isc_buffer_t rb;
   15905 
   15906 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   15907 		(void)dns_rcode_totext(msg->rcode, &rb);
   15908 		dns_zone_log(zone, ISC_LOG_INFO,
   15909 			     "forwarded dynamic update: "
   15910 			     "master %s returned: %.*s",
   15911 			     master, (int)rb.used, rcode);
   15912 		break;
   15913 	}
   15914 
   15915 	/* These should not occur if the masters/zone are valid. */
   15916 	case dns_rcode_notzone:
   15917 	case dns_rcode_notauth: {
   15918 		char rcode[128];
   15919 		isc_buffer_t rb;
   15920 
   15921 		isc_buffer_init(&rb, rcode, sizeof(rcode));
   15922 		(void)dns_rcode_totext(msg->rcode, &rb);
   15923 		dns_zone_log(zone, ISC_LOG_WARNING,
   15924 			     "forwarding dynamic update: "
   15925 			     "unexpected response: master %s returned: %.*s",
   15926 			     master, (int)rb.used, rcode);
   15927 		goto next_master;
   15928 	}
   15929 
   15930 	/* Try another server for these rcodes. */
   15931 	case dns_rcode_formerr:
   15932 	case dns_rcode_servfail:
   15933 	case dns_rcode_notimp:
   15934 	case dns_rcode_badvers:
   15935 	default:
   15936 		goto next_master;
   15937 	}
   15938 
   15939 	/* call callback */
   15940 	(forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
   15941 	msg = NULL;
   15942 	dns_request_destroy(&forward->request);
   15943 	forward_destroy(forward);
   15944 	isc_event_free(&event);
   15945 	return;
   15946 
   15947  next_master:
   15948 	if (msg != NULL)
   15949 		dns_message_destroy(&msg);
   15950 	isc_event_free(&event);
   15951 	forward->which++;
   15952 	dns_request_destroy(&forward->request);
   15953 	result = sendtomaster(forward);
   15954 	if (result != ISC_R_SUCCESS) {
   15955 		/* call callback */
   15956 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
   15957 			     "exhausted dynamic update forwarder list");
   15958 		(forward->callback)(forward->callback_arg, result, NULL);
   15959 		forward_destroy(forward);
   15960 	}
   15961 }
   15962 
   15963 isc_result_t
   15964 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
   15965 		       dns_updatecallback_t callback, void *callback_arg)
   15966 {
   15967 	dns_forward_t *forward;
   15968 	isc_result_t result;
   15969 	isc_region_t *mr;
   15970 
   15971 	REQUIRE(DNS_ZONE_VALID(zone));
   15972 	REQUIRE(msg != NULL);
   15973 	REQUIRE(callback != NULL);
   15974 
   15975 	forward = isc_mem_get(zone->mctx, sizeof(*forward));
   15976 	if (forward == NULL)
   15977 		return (ISC_R_NOMEMORY);
   15978 
   15979 	forward->request = NULL;
   15980 	forward->zone = NULL;
   15981 	forward->msgbuf = NULL;
   15982 	forward->which = 0;
   15983 	forward->mctx = 0;
   15984 	forward->callback = callback;
   15985 	forward->callback_arg = callback_arg;
   15986 	ISC_LINK_INIT(forward, link);
   15987 	forward->magic = FORWARD_MAGIC;
   15988 	forward->options = DNS_REQUESTOPT_TCP;
   15989 	/*
   15990 	 * If we have a SIG(0) signed message we need to preserve the
   15991 	 * query id as that is included in the SIG(0) computation.
   15992 	 */
   15993 	if (msg->sig0 != NULL)
   15994 		forward->options |= DNS_REQUESTOPT_FIXEDID;
   15995 
   15996 	mr = dns_message_getrawmessage(msg);
   15997 	if (mr == NULL) {
   15998 		result = ISC_R_UNEXPECTEDEND;
   15999 		goto cleanup;
   16000 	}
   16001 
   16002 	result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
   16003 	if (result != ISC_R_SUCCESS)
   16004 		goto cleanup;
   16005 	result = isc_buffer_copyregion(forward->msgbuf, mr);
   16006 	if (result != ISC_R_SUCCESS)
   16007 		goto cleanup;
   16008 
   16009 	isc_mem_attach(zone->mctx, &forward->mctx);
   16010 	dns_zone_iattach(zone, &forward->zone);
   16011 	result = sendtomaster(forward);
   16012 
   16013  cleanup:
   16014 	if (result != ISC_R_SUCCESS) {
   16015 		forward_destroy(forward);
   16016 	}
   16017 	return (result);
   16018 }
   16019 
   16020 isc_result_t
   16021 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
   16022 	REQUIRE(DNS_ZONE_VALID(zone));
   16023 	REQUIRE(next != NULL && *next == NULL);
   16024 
   16025 	*next = ISC_LIST_NEXT(zone, link);
   16026 	if (*next == NULL)
   16027 		return (ISC_R_NOMORE);
   16028 	else
   16029 		return (ISC_R_SUCCESS);
   16030 }
   16031 
   16032 isc_result_t
   16033 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
   16034 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16035 	REQUIRE(first != NULL && *first == NULL);
   16036 
   16037 	*first = ISC_LIST_HEAD(zmgr->zones);
   16038 	if (*first == NULL)
   16039 		return (ISC_R_NOMORE);
   16040 	else
   16041 		return (ISC_R_SUCCESS);
   16042 }
   16043 
   16044 /***
   16045  ***	Zone manager.
   16046  ***/
   16047 
   16048 isc_result_t
   16049 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
   16050 		   isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
   16051 		   dns_zonemgr_t **zmgrp)
   16052 {
   16053 	dns_zonemgr_t *zmgr;
   16054 	isc_result_t result;
   16055 
   16056 	zmgr = isc_mem_get(mctx, sizeof(*zmgr));
   16057 	if (zmgr == NULL)
   16058 		return (ISC_R_NOMEMORY);
   16059 	zmgr->mctx = NULL;
   16060 	zmgr->refs = 1;
   16061 	isc_mem_attach(mctx, &zmgr->mctx);
   16062 	zmgr->taskmgr = taskmgr;
   16063 	zmgr->timermgr = timermgr;
   16064 	zmgr->socketmgr = socketmgr;
   16065 	zmgr->zonetasks = NULL;
   16066 	zmgr->loadtasks = NULL;
   16067 	zmgr->mctxpool = NULL;
   16068 	zmgr->task = NULL;
   16069 	zmgr->notifyrl = NULL;
   16070 	zmgr->refreshrl = NULL;
   16071 	zmgr->startupnotifyrl = NULL;
   16072 	zmgr->startuprefreshrl = NULL;
   16073 	ISC_LIST_INIT(zmgr->zones);
   16074 	ISC_LIST_INIT(zmgr->waiting_for_xfrin);
   16075 	ISC_LIST_INIT(zmgr->xfrin_in_progress);
   16076 	memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
   16077 	result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
   16078 	if (result != ISC_R_SUCCESS)
   16079 		goto free_mem;
   16080 
   16081 	zmgr->transfersin = 10;
   16082 	zmgr->transfersperns = 2;
   16083 
   16084 	/* Unreachable lock. */
   16085 	result = isc_rwlock_init(&zmgr->urlock, 0, 0);
   16086 	if (result != ISC_R_SUCCESS)
   16087 		goto free_rwlock;
   16088 
   16089 	/* Create a single task for queueing of SOA queries. */
   16090 	result = isc_task_create(taskmgr, 1, &zmgr->task);
   16091 	if (result != ISC_R_SUCCESS)
   16092 		goto free_urlock;
   16093 
   16094 	isc_task_setname(zmgr->task, "zmgr", zmgr);
   16095 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
   16096 					&zmgr->notifyrl);
   16097 	if (result != ISC_R_SUCCESS)
   16098 		goto free_task;
   16099 
   16100 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
   16101 					&zmgr->refreshrl);
   16102 	if (result != ISC_R_SUCCESS)
   16103 		goto free_notifyrl;
   16104 
   16105 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
   16106 					&zmgr->startupnotifyrl);
   16107 	if (result != ISC_R_SUCCESS)
   16108 		goto free_refreshrl;
   16109 
   16110 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
   16111 					&zmgr->startuprefreshrl);
   16112 	if (result != ISC_R_SUCCESS)
   16113 		goto free_startupnotifyrl;
   16114 
   16115 	/* default to 20 refresh queries / notifies per second. */
   16116 	setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
   16117 	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
   16118 	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
   16119 	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
   16120 	isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, ISC_TRUE);
   16121 	isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, ISC_TRUE);
   16122 
   16123 	zmgr->iolimit = 1;
   16124 	zmgr->ioactive = 0;
   16125 	ISC_LIST_INIT(zmgr->high);
   16126 	ISC_LIST_INIT(zmgr->low);
   16127 
   16128 	result = isc_mutex_init(&zmgr->iolock);
   16129 	if (result != ISC_R_SUCCESS)
   16130 		goto free_startuprefreshrl;
   16131 
   16132 	zmgr->magic = ZONEMGR_MAGIC;
   16133 
   16134 	*zmgrp = zmgr;
   16135 	return (ISC_R_SUCCESS);
   16136 
   16137 #if 0
   16138  free_iolock:
   16139 	DESTROYLOCK(&zmgr->iolock);
   16140 #endif
   16141  free_startuprefreshrl:
   16142 	isc_ratelimiter_detach(&zmgr->startuprefreshrl);
   16143  free_startupnotifyrl:
   16144 	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
   16145  free_refreshrl:
   16146 	isc_ratelimiter_detach(&zmgr->refreshrl);
   16147  free_notifyrl:
   16148 	isc_ratelimiter_detach(&zmgr->notifyrl);
   16149  free_task:
   16150 	isc_task_detach(&zmgr->task);
   16151  free_urlock:
   16152 	isc_rwlock_destroy(&zmgr->urlock);
   16153  free_rwlock:
   16154 	isc_rwlock_destroy(&zmgr->rwlock);
   16155  free_mem:
   16156 	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
   16157 	isc_mem_detach(&mctx);
   16158 	return (result);
   16159 }
   16160 
   16161 isc_result_t
   16162 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
   16163 	isc_result_t result;
   16164 	isc_mem_t *mctx = NULL;
   16165 	dns_zone_t *zone = NULL;
   16166 	void *item;
   16167 
   16168 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16169 	REQUIRE(zonep != NULL && *zonep == NULL);
   16170 
   16171 	if (zmgr->mctxpool == NULL)
   16172 		return (ISC_R_FAILURE);
   16173 
   16174 	item = isc_pool_get(zmgr->mctxpool);
   16175 	if (item == NULL)
   16176 		return (ISC_R_FAILURE);
   16177 
   16178 	isc_mem_attach((isc_mem_t *) item, &mctx);
   16179 	result = dns_zone_create(&zone, mctx);
   16180 	isc_mem_detach(&mctx);
   16181 
   16182 	if (result == ISC_R_SUCCESS)
   16183 		*zonep = zone;
   16184 
   16185 	return (result);
   16186 }
   16187 
   16188 isc_result_t
   16189 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
   16190 	isc_result_t result;
   16191 
   16192 	REQUIRE(DNS_ZONE_VALID(zone));
   16193 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16194 
   16195 	if (zmgr->zonetasks == NULL)
   16196 		return (ISC_R_FAILURE);
   16197 
   16198 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16199 	LOCK_ZONE(zone);
   16200 	REQUIRE(zone->task == NULL);
   16201 	REQUIRE(zone->timer == NULL);
   16202 	REQUIRE(zone->zmgr == NULL);
   16203 
   16204 	isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
   16205 	isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
   16206 
   16207 	/*
   16208 	 * Set the task name.  The tag will arbitrarily point to one
   16209 	 * of the zones sharing the task (in practice, the one
   16210 	 * to be managed last).
   16211 	 */
   16212 	isc_task_setname(zone->task, "zone", zone);
   16213 	isc_task_setname(zone->loadtask, "loadzone", zone);
   16214 
   16215 	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
   16216 				  NULL, NULL,
   16217 				  zone->task, zone_timer, zone,
   16218 				  &zone->timer);
   16219 
   16220 	if (result != ISC_R_SUCCESS)
   16221 		goto cleanup_tasks;
   16222 
   16223 	/*
   16224 	 * The timer "holds" a iref.
   16225 	 */
   16226 	zone->irefs++;
   16227 	INSIST(zone->irefs != 0);
   16228 
   16229 	ISC_LIST_APPEND(zmgr->zones, zone, link);
   16230 	zone->zmgr = zmgr;
   16231 	zmgr->refs++;
   16232 
   16233 	goto unlock;
   16234 
   16235  cleanup_tasks:
   16236 	isc_task_detach(&zone->loadtask);
   16237 	isc_task_detach(&zone->task);
   16238 
   16239  unlock:
   16240 	UNLOCK_ZONE(zone);
   16241 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16242 	return (result);
   16243 }
   16244 
   16245 void
   16246 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
   16247 	isc_boolean_t free_now = ISC_FALSE;
   16248 
   16249 	REQUIRE(DNS_ZONE_VALID(zone));
   16250 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16251 	REQUIRE(zone->zmgr == zmgr);
   16252 
   16253 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16254 	LOCK_ZONE(zone);
   16255 
   16256 	ISC_LIST_UNLINK(zmgr->zones, zone, link);
   16257 	zone->zmgr = NULL;
   16258 	zmgr->refs--;
   16259 	if (zmgr->refs == 0)
   16260 		free_now = ISC_TRUE;
   16261 
   16262 	UNLOCK_ZONE(zone);
   16263 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16264 
   16265 	if (free_now)
   16266 		zonemgr_free(zmgr);
   16267 	ENSURE(zone->zmgr == NULL);
   16268 }
   16269 
   16270 void
   16271 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
   16272 	REQUIRE(DNS_ZONEMGR_VALID(source));
   16273 	REQUIRE(target != NULL && *target == NULL);
   16274 
   16275 	RWLOCK(&source->rwlock, isc_rwlocktype_write);
   16276 	REQUIRE(source->refs > 0);
   16277 	source->refs++;
   16278 	INSIST(source->refs > 0);
   16279 	RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
   16280 	*target = source;
   16281 }
   16282 
   16283 void
   16284 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
   16285 	dns_zonemgr_t *zmgr;
   16286 	isc_boolean_t free_now = ISC_FALSE;
   16287 
   16288 	REQUIRE(zmgrp != NULL);
   16289 	zmgr = *zmgrp;
   16290 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16291 
   16292 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16293 	zmgr->refs--;
   16294 	if (zmgr->refs == 0)
   16295 		free_now = ISC_TRUE;
   16296 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16297 
   16298 	if (free_now)
   16299 		zonemgr_free(zmgr);
   16300 	*zmgrp = NULL;
   16301 }
   16302 
   16303 isc_result_t
   16304 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
   16305 	dns_zone_t *p;
   16306 
   16307 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16308 
   16309 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   16310 	for (p = ISC_LIST_HEAD(zmgr->zones);
   16311 	     p != NULL;
   16312 	     p = ISC_LIST_NEXT(p, link))
   16313 	{
   16314 		dns_zone_maintenance(p);
   16315 	}
   16316 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   16317 
   16318 	/*
   16319 	 * Recent configuration changes may have increased the
   16320 	 * amount of available transfers quota.  Make sure any
   16321 	 * transfers currently blocked on quota get started if
   16322 	 * possible.
   16323 	 */
   16324 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16325 	zmgr_resume_xfrs(zmgr, ISC_TRUE);
   16326 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16327 	return (ISC_R_SUCCESS);
   16328 }
   16329 
   16330 void
   16331 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
   16332 
   16333 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16334 
   16335 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16336 	zmgr_resume_xfrs(zmgr, ISC_TRUE);
   16337 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   16338 }
   16339 
   16340 void
   16341 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
   16342 	dns_zone_t *zone;
   16343 
   16344 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16345 
   16346 	isc_ratelimiter_shutdown(zmgr->notifyrl);
   16347 	isc_ratelimiter_shutdown(zmgr->refreshrl);
   16348 	isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
   16349 	isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
   16350 
   16351 	if (zmgr->task != NULL)
   16352 		isc_task_destroy(&zmgr->task);
   16353 	if (zmgr->zonetasks != NULL)
   16354 		isc_taskpool_destroy(&zmgr->zonetasks);
   16355 	if (zmgr->loadtasks != NULL)
   16356 		isc_taskpool_destroy(&zmgr->loadtasks);
   16357 	if (zmgr->mctxpool != NULL)
   16358 		isc_pool_destroy(&zmgr->mctxpool);
   16359 
   16360 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   16361 	for (zone = ISC_LIST_HEAD(zmgr->zones);
   16362 	     zone != NULL;
   16363 	     zone = ISC_LIST_NEXT(zone, link))
   16364 	{
   16365 		LOCK_ZONE(zone);
   16366 		forward_cancel(zone);
   16367 		UNLOCK_ZONE(zone);
   16368 	}
   16369 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   16370 }
   16371 
   16372 static isc_result_t
   16373 mctxinit(void **target, void *arg) {
   16374 	isc_result_t result;
   16375 	isc_mem_t *mctx = NULL;
   16376 
   16377 	UNUSED(arg);
   16378 
   16379 	REQUIRE(target != NULL && *target == NULL);
   16380 
   16381 	result = isc_mem_create(0, 0, &mctx);
   16382 	if (result != ISC_R_SUCCESS)
   16383 		return (result);
   16384 	isc_mem_setname(mctx, "zonemgr-pool", NULL);
   16385 
   16386 	*target = mctx;
   16387 	return (ISC_R_SUCCESS);
   16388 }
   16389 
   16390 static void
   16391 mctxfree(void **target) {
   16392 	isc_mem_t *mctx = *(isc_mem_t **) target;
   16393 	isc_mem_detach(&mctx);
   16394 	*target = NULL;
   16395 }
   16396 
   16397 #define ZONES_PER_TASK 100
   16398 #define ZONES_PER_MCTX 1000
   16399 
   16400 isc_result_t
   16401 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
   16402 	isc_result_t result;
   16403 	int ntasks = num_zones / ZONES_PER_TASK;
   16404 	int nmctx = num_zones / ZONES_PER_MCTX;
   16405 	isc_taskpool_t *pool = NULL;
   16406 	isc_pool_t *mctxpool = NULL;
   16407 
   16408 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16409 
   16410 	/*
   16411 	 * For anything fewer than 1000 zones we use 10 tasks in
   16412 	 * the task pools.  More than that, and we'll scale at one
   16413 	 * task per 100 zones.  Similarly, for anything smaller than
   16414 	 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
   16415 	 */
   16416 	if (ntasks < 10)
   16417 		ntasks = 10;
   16418 	if (nmctx < 2)
   16419 		nmctx = 2;
   16420 
   16421 	/* Create or resize the zone task pools. */
   16422 	if (zmgr->zonetasks == NULL)
   16423 		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
   16424 					     ntasks, 2, &pool);
   16425 	else
   16426 		result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
   16427 
   16428 	if (result == ISC_R_SUCCESS)
   16429 		zmgr->zonetasks = pool;
   16430 
   16431 	pool = NULL;
   16432 	if (zmgr->loadtasks == NULL)
   16433 		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
   16434 					     ntasks, 2, &pool);
   16435 	else
   16436 		result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
   16437 
   16438 	if (result == ISC_R_SUCCESS)
   16439 		zmgr->loadtasks = pool;
   16440 
   16441 	/*
   16442 	 * We always set all tasks in the zone-load task pool to
   16443 	 * privileged.  This prevents other tasks in the system from
   16444 	 * running while the server task manager is in privileged
   16445 	 * mode.
   16446 	 *
   16447 	 * NOTE: If we start using task privileges for any other
   16448 	 * part of the system than zone tasks, then this will need to be
   16449 	 * revisted.  In that case we'd want to turn on privileges for
   16450 	 * zone tasks only when we were loading, and turn them off the
   16451 	 * rest of the time.  For now, however, it's okay to just
   16452 	 * set it and forget it.
   16453 	 */
   16454 	isc_taskpool_setprivilege(zmgr->loadtasks, ISC_TRUE);
   16455 
   16456 	/* Create or resize the zone memory context pool. */
   16457 	if (zmgr->mctxpool == NULL)
   16458 		result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
   16459 					 mctxinit, NULL, &mctxpool);
   16460 	else
   16461 		result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
   16462 
   16463 	if (result == ISC_R_SUCCESS)
   16464 		zmgr->mctxpool = mctxpool;
   16465 
   16466 	return (result);
   16467 }
   16468 
   16469 static void
   16470 zonemgr_free(dns_zonemgr_t *zmgr) {
   16471 	isc_mem_t *mctx;
   16472 
   16473 	INSIST(zmgr->refs == 0);
   16474 	INSIST(ISC_LIST_EMPTY(zmgr->zones));
   16475 
   16476 	zmgr->magic = 0;
   16477 
   16478 	DESTROYLOCK(&zmgr->iolock);
   16479 	isc_ratelimiter_detach(&zmgr->notifyrl);
   16480 	isc_ratelimiter_detach(&zmgr->refreshrl);
   16481 	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
   16482 	isc_ratelimiter_detach(&zmgr->startuprefreshrl);
   16483 
   16484 	isc_rwlock_destroy(&zmgr->urlock);
   16485 	isc_rwlock_destroy(&zmgr->rwlock);
   16486 	mctx = zmgr->mctx;
   16487 	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
   16488 	isc_mem_detach(&mctx);
   16489 }
   16490 
   16491 void
   16492 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
   16493 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16494 
   16495 	zmgr->transfersin = value;
   16496 }
   16497 
   16498 isc_uint32_t
   16499 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
   16500 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16501 
   16502 	return (zmgr->transfersin);
   16503 }
   16504 
   16505 void
   16506 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
   16507 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16508 
   16509 	zmgr->transfersperns = value;
   16510 }
   16511 
   16512 isc_uint32_t
   16513 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
   16514 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16515 
   16516 	return (zmgr->transfersperns);
   16517 }
   16518 
   16519 /*
   16520  * Try to start a new incoming zone transfer to fill a quota
   16521  * slot that was just vacated.
   16522  *
   16523  * Requires:
   16524  *	The zone manager is locked by the caller.
   16525  */
   16526 static void
   16527 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
   16528 	dns_zone_t *zone;
   16529 	dns_zone_t *next;
   16530 
   16531 	for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
   16532 	     zone != NULL;
   16533 	     zone = next)
   16534 	{
   16535 		isc_result_t result;
   16536 		next = ISC_LIST_NEXT(zone, statelink);
   16537 		result = zmgr_start_xfrin_ifquota(zmgr, zone);
   16538 		if (result == ISC_R_SUCCESS) {
   16539 			if (multi)
   16540 				continue;
   16541 			/*
   16542 			 * We successfully filled the slot.  We're done.
   16543 			 */
   16544 			break;
   16545 		} else if (result == ISC_R_QUOTA) {
   16546 			/*
   16547 			 * Not enough quota.  This is probably the per-server
   16548 			 * quota, because we usually get called when a unit of
   16549 			 * global quota has just been freed.  Try the next
   16550 			 * zone, it may succeed if it uses another master.
   16551 			 */
   16552 			continue;
   16553 		} else {
   16554 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
   16555 				     "starting zone transfer: %s",
   16556 				     isc_result_totext(result));
   16557 			break;
   16558 		}
   16559 	}
   16560 }
   16561 
   16562 /*
   16563  * Try to start an incoming zone transfer for 'zone', quota permitting.
   16564  *
   16565  * Requires:
   16566  *	The zone manager is locked by the caller.
   16567  *
   16568  * Returns:
   16569  *	ISC_R_SUCCESS	There was enough quota and we attempted to
   16570  *			start a transfer.  zone_xfrdone() has been or will
   16571  *			be called.
   16572  *	ISC_R_QUOTA	Not enough quota.
   16573  *	Others		Failure.
   16574  */
   16575 static isc_result_t
   16576 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
   16577 	dns_peer_t *peer = NULL;
   16578 	isc_netaddr_t masterip;
   16579 	isc_uint32_t nxfrsin, nxfrsperns;
   16580 	dns_zone_t *x;
   16581 	isc_uint32_t maxtransfersin, maxtransfersperns;
   16582 	isc_event_t *e;
   16583 
   16584 	/*
   16585 	 * If we are exiting just pretend we got quota so the zone will
   16586 	 * be cleaned up in the zone's task context.
   16587 	 */
   16588 	LOCK_ZONE(zone);
   16589 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
   16590 		UNLOCK_ZONE(zone);
   16591 		goto gotquota;
   16592 	}
   16593 
   16594 	/*
   16595 	 * Find any configured information about the server we'd
   16596 	 * like to transfer this zone from.
   16597 	 */
   16598 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
   16599 	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
   16600 	UNLOCK_ZONE(zone);
   16601 
   16602 	/*
   16603 	 * Determine the total maximum number of simultaneous
   16604 	 * transfers allowed, and the maximum for this specific
   16605 	 * master.
   16606 	 */
   16607 	maxtransfersin = zmgr->transfersin;
   16608 	maxtransfersperns = zmgr->transfersperns;
   16609 	if (peer != NULL)
   16610 		(void)dns_peer_gettransfers(peer, &maxtransfersperns);
   16611 
   16612 	/*
   16613 	 * Count the total number of transfers that are in progress,
   16614 	 * and the number of transfers in progress from this master.
   16615 	 * We linearly scan a list of all transfers; if this turns
   16616 	 * out to be too slow, we could hash on the master address.
   16617 	 */
   16618 	nxfrsin = nxfrsperns = 0;
   16619 	for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
   16620 	     x != NULL;
   16621 	     x = ISC_LIST_NEXT(x, statelink))
   16622 	{
   16623 		isc_netaddr_t xip;
   16624 
   16625 		LOCK_ZONE(x);
   16626 		isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
   16627 		UNLOCK_ZONE(x);
   16628 
   16629 		nxfrsin++;
   16630 		if (isc_netaddr_equal(&xip, &masterip))
   16631 			nxfrsperns++;
   16632 	}
   16633 
   16634 	/* Enforce quota. */
   16635 	if (nxfrsin >= maxtransfersin)
   16636 		return (ISC_R_QUOTA);
   16637 
   16638 	if (nxfrsperns >= maxtransfersperns)
   16639 		return (ISC_R_QUOTA);
   16640 
   16641  gotquota:
   16642 	/*
   16643 	 * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
   16644 	 * list and send it an event to let it start the actual transfer in the
   16645 	 * context of its own task.
   16646 	 */
   16647 	e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
   16648 			       got_transfer_quota, zone, sizeof(isc_event_t));
   16649 	if (e == NULL)
   16650 		return (ISC_R_NOMEMORY);
   16651 
   16652 	LOCK_ZONE(zone);
   16653 	INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
   16654 	ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
   16655 	ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
   16656 	zone->statelist = &zmgr->xfrin_in_progress;
   16657 	isc_task_send(zone->task, &e);
   16658 	dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
   16659 	UNLOCK_ZONE(zone);
   16660 
   16661 	return (ISC_R_SUCCESS);
   16662 }
   16663 
   16664 void
   16665 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
   16666 
   16667 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16668 	REQUIRE(iolimit > 0);
   16669 
   16670 	zmgr->iolimit = iolimit;
   16671 }
   16672 
   16673 isc_uint32_t
   16674 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
   16675 
   16676 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16677 
   16678 	return (zmgr->iolimit);
   16679 }
   16680 
   16681 /*
   16682  * Get permission to request a file handle from the OS.
   16683  * An event will be sent to action when one is available.
   16684  * There are two queues available (high and low), the high
   16685  * queue will be serviced before the low one.
   16686  *
   16687  * zonemgr_putio() must be called after the event is delivered to
   16688  * 'action'.
   16689  */
   16690 
   16691 static isc_result_t
   16692 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
   16693 	      isc_task_t *task, isc_taskaction_t action, void *arg,
   16694 	      dns_io_t **iop)
   16695 {
   16696 	dns_io_t *io;
   16697 	isc_boolean_t queue;
   16698 
   16699 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16700 	REQUIRE(iop != NULL && *iop == NULL);
   16701 
   16702 	io = isc_mem_get(zmgr->mctx, sizeof(*io));
   16703 	if (io == NULL)
   16704 		return (ISC_R_NOMEMORY);
   16705 
   16706 	io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
   16707 				       action, arg, sizeof(*io->event));
   16708 	if (io->event == NULL) {
   16709 		isc_mem_put(zmgr->mctx, io, sizeof(*io));
   16710 		return (ISC_R_NOMEMORY);
   16711 	}
   16712 
   16713 	io->zmgr = zmgr;
   16714 	io->high = high;
   16715 	io->task = NULL;
   16716 	isc_task_attach(task, &io->task);
   16717 	ISC_LINK_INIT(io, link);
   16718 	io->magic = IO_MAGIC;
   16719 
   16720 	LOCK(&zmgr->iolock);
   16721 	zmgr->ioactive++;
   16722 	queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
   16723 	if (queue) {
   16724 		if (io->high)
   16725 			ISC_LIST_APPEND(zmgr->high, io, link);
   16726 		else
   16727 			ISC_LIST_APPEND(zmgr->low, io, link);
   16728 	}
   16729 	UNLOCK(&zmgr->iolock);
   16730 	*iop = io;
   16731 
   16732 	if (!queue)
   16733 		isc_task_send(io->task, &io->event);
   16734 	return (ISC_R_SUCCESS);
   16735 }
   16736 
   16737 static void
   16738 zonemgr_putio(dns_io_t **iop) {
   16739 	dns_io_t *io;
   16740 	dns_io_t *next;
   16741 	dns_zonemgr_t *zmgr;
   16742 
   16743 	REQUIRE(iop != NULL);
   16744 	io = *iop;
   16745 	REQUIRE(DNS_IO_VALID(io));
   16746 
   16747 	*iop = NULL;
   16748 
   16749 	INSIST(!ISC_LINK_LINKED(io, link));
   16750 	INSIST(io->event == NULL);
   16751 
   16752 	zmgr = io->zmgr;
   16753 	isc_task_detach(&io->task);
   16754 	io->magic = 0;
   16755 	isc_mem_put(zmgr->mctx, io, sizeof(*io));
   16756 
   16757 	LOCK(&zmgr->iolock);
   16758 	INSIST(zmgr->ioactive > 0);
   16759 	zmgr->ioactive--;
   16760 	next = HEAD(zmgr->high);
   16761 	if (next == NULL)
   16762 		next = HEAD(zmgr->low);
   16763 	if (next != NULL) {
   16764 		if (next->high)
   16765 			ISC_LIST_UNLINK(zmgr->high, next, link);
   16766 		else
   16767 			ISC_LIST_UNLINK(zmgr->low, next, link);
   16768 		INSIST(next->event != NULL);
   16769 	}
   16770 	UNLOCK(&zmgr->iolock);
   16771 	if (next != NULL)
   16772 		isc_task_send(next->task, &next->event);
   16773 }
   16774 
   16775 static void
   16776 zonemgr_cancelio(dns_io_t *io) {
   16777 	isc_boolean_t send_event = ISC_FALSE;
   16778 
   16779 	REQUIRE(DNS_IO_VALID(io));
   16780 
   16781 	/*
   16782 	 * If we are queued to be run then dequeue.
   16783 	 */
   16784 	LOCK(&io->zmgr->iolock);
   16785 	if (ISC_LINK_LINKED(io, link)) {
   16786 		if (io->high)
   16787 			ISC_LIST_UNLINK(io->zmgr->high, io, link);
   16788 		else
   16789 			ISC_LIST_UNLINK(io->zmgr->low, io, link);
   16790 
   16791 		send_event = ISC_TRUE;
   16792 		INSIST(io->event != NULL);
   16793 	}
   16794 	UNLOCK(&io->zmgr->iolock);
   16795 	if (send_event) {
   16796 		io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
   16797 		isc_task_send(io->task, &io->event);
   16798 	}
   16799 }
   16800 
   16801 static void
   16802 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
   16803 	char *buf;
   16804 	int buflen;
   16805 	isc_result_t result;
   16806 
   16807 	buflen = strlen(path) + strlen(templat) + 2;
   16808 
   16809 	buf = isc_mem_get(zone->mctx, buflen);
   16810 	if (buf == NULL)
   16811 		return;
   16812 
   16813 	result = isc_file_template(path, templat, buf, buflen);
   16814 	if (result != ISC_R_SUCCESS)
   16815 		goto cleanup;
   16816 
   16817 	result = isc_file_renameunique(path, buf);
   16818 	if (result != ISC_R_SUCCESS)
   16819 		goto cleanup;
   16820 
   16821 	dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
   16822 		     "renaming file to '%s' for failure analysis and "
   16823 		     "retransferring.", path, buf);
   16824 
   16825  cleanup:
   16826 	isc_mem_put(zone->mctx, buf, buflen);
   16827 }
   16828 
   16829 #if 0
   16830 /* Hook for ondestroy notification from a database. */
   16831 
   16832 static void
   16833 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
   16834 	dns_db_t *db = event->sender;
   16835 	UNUSED(task);
   16836 
   16837 	isc_event_free(&event);
   16838 
   16839 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   16840 		      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
   16841 		      "database (%p) destroyed", (void*) db);
   16842 }
   16843 #endif
   16844 
   16845 static void
   16846 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
   16847 	isc_interval_t interval;
   16848 	isc_uint32_t s, ns;
   16849 	isc_uint32_t pertic;
   16850 	isc_result_t result;
   16851 
   16852 	if (value == 0)
   16853 		value = 1;
   16854 
   16855 	if (value == 1) {
   16856 		s = 1;
   16857 		ns = 0;
   16858 		pertic = 1;
   16859 	} else if (value <= 10) {
   16860 		s = 0;
   16861 		ns = 1000000000 / value;
   16862 		pertic = 1;
   16863 	} else {
   16864 		s = 0;
   16865 		ns = (1000000000 / value) * 10;
   16866 		pertic = 10;
   16867 	}
   16868 
   16869 	isc_interval_set(&interval, s, ns);
   16870 
   16871 	result = isc_ratelimiter_setinterval(rl, &interval);
   16872 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   16873 	isc_ratelimiter_setpertic(rl, pertic);
   16874 
   16875 	*rate = value;
   16876 }
   16877 
   16878 void
   16879 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
   16880 
   16881 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16882 
   16883 	setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
   16884 }
   16885 
   16886 void
   16887 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
   16888 
   16889 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16890 
   16891 	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
   16892 }
   16893 
   16894 void
   16895 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
   16896 
   16897 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16898 
   16899 	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
   16900 	/* XXXMPA seperate out once we have the code to support this. */
   16901 	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
   16902 }
   16903 
   16904 unsigned int
   16905 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
   16906 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16907 
   16908 	return (zmgr->notifyrate);
   16909 }
   16910 
   16911 unsigned int
   16912 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
   16913 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16914 
   16915 	return (zmgr->startupnotifyrate);
   16916 }
   16917 
   16918 unsigned int
   16919 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
   16920 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16921 
   16922 	return (zmgr->serialqueryrate);
   16923 }
   16924 
   16925 isc_boolean_t
   16926 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
   16927 			isc_sockaddr_t *local, isc_time_t *now)
   16928 {
   16929 	unsigned int i;
   16930 	isc_rwlocktype_t locktype;
   16931 	isc_result_t result;
   16932 	isc_uint32_t seconds = isc_time_seconds(now);
   16933 	isc_uint32_t count = 0;
   16934 
   16935 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16936 
   16937 	locktype = isc_rwlocktype_read;
   16938 	RWLOCK(&zmgr->urlock, locktype);
   16939 	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
   16940 		if (zmgr->unreachable[i].expire >= seconds &&
   16941 		    isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
   16942 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
   16943 			result = isc_rwlock_tryupgrade(&zmgr->urlock);
   16944 			if (result == ISC_R_SUCCESS) {
   16945 				locktype = isc_rwlocktype_write;
   16946 				zmgr->unreachable[i].last = seconds;
   16947 				count = zmgr->unreachable[i].count;
   16948 			}
   16949 			break;
   16950 		}
   16951 	}
   16952 	RWUNLOCK(&zmgr->urlock, locktype);
   16953 	return (ISC_TF(i < UNREACH_CHACHE_SIZE && count > 1U));
   16954 }
   16955 
   16956 void
   16957 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
   16958 			   isc_sockaddr_t *local)
   16959 {
   16960 	unsigned int i;
   16961 	isc_rwlocktype_t locktype;
   16962 	isc_result_t result;
   16963 
   16964 	char master[ISC_SOCKADDR_FORMATSIZE];
   16965 	char source[ISC_SOCKADDR_FORMATSIZE];
   16966 
   16967 	isc_sockaddr_format(remote, master, sizeof(master));
   16968 	isc_sockaddr_format(local, source, sizeof(source));
   16969 
   16970 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   16971 
   16972 	locktype = isc_rwlocktype_read;
   16973 	RWLOCK(&zmgr->urlock, locktype);
   16974 	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
   16975 		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
   16976 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
   16977 			if (zmgr->unreachable[i].expire == 0)
   16978 				break;
   16979 			result = isc_rwlock_tryupgrade(&zmgr->urlock);
   16980 			if (result == ISC_R_SUCCESS) {
   16981 				locktype = isc_rwlocktype_write;
   16982 				zmgr->unreachable[i].expire = 0;
   16983 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   16984 					      DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
   16985 					      "master %s (source %s) deleted "
   16986 					      "from unreachable cache",
   16987 					      master, source);
   16988 			}
   16989 			break;
   16990 		}
   16991 	}
   16992 	RWUNLOCK(&zmgr->urlock, locktype);
   16993 }
   16994 
   16995 void
   16996 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
   16997 			   isc_sockaddr_t *local, isc_time_t *now)
   16998 {
   16999 	isc_uint32_t seconds = isc_time_seconds(now);
   17000 	isc_uint32_t last = seconds;
   17001 	unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
   17002 
   17003 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17004 
   17005 	RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
   17006 	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
   17007 		/* Existing entry? */
   17008 		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
   17009 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
   17010 			break;
   17011 		/* Empty slot? */
   17012 		if (zmgr->unreachable[i].expire < seconds)
   17013 			slot = i;
   17014 		/* Least recently used slot? */
   17015 		if (zmgr->unreachable[i].last < last) {
   17016 			last = zmgr->unreachable[i].last;
   17017 			oldest = i;
   17018 		}
   17019 	}
   17020 	if (i < UNREACH_CHACHE_SIZE) {
   17021 		/*
   17022 		 * Found a existing entry.  Update the expire timer and
   17023 		 * last usage timestamps.
   17024 		 */
   17025 		zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
   17026 		zmgr->unreachable[i].last = seconds;
   17027 		if (zmgr->unreachable[i].expire < seconds)
   17028 			zmgr->unreachable[i].count = 1;
   17029 		else
   17030 			zmgr->unreachable[i].count++;
   17031 	} else if (slot != UNREACH_CHACHE_SIZE) {
   17032 		/*
   17033 		 * Found a empty slot. Add a new entry to the cache.
   17034 		 */
   17035 		zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
   17036 		zmgr->unreachable[slot].last = seconds;
   17037 		zmgr->unreachable[slot].remote = *remote;
   17038 		zmgr->unreachable[slot].local = *local;
   17039 		zmgr->unreachable[slot].count = 1;
   17040 	} else {
   17041 		/*
   17042 		 * Replace the least recently used entry in the cache.
   17043 		 */
   17044 		zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
   17045 		zmgr->unreachable[oldest].last = seconds;
   17046 		zmgr->unreachable[oldest].remote = *remote;
   17047 		zmgr->unreachable[oldest].local = *local;
   17048 		zmgr->unreachable[oldest].count = 1;
   17049 	}
   17050 	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
   17051 }
   17052 
   17053 void
   17054 dns_zone_forcereload(dns_zone_t *zone) {
   17055 	REQUIRE(DNS_ZONE_VALID(zone));
   17056 
   17057 	if (zone->type == dns_zone_master ||
   17058 	    (zone->type == dns_zone_redirect && zone->masters == NULL))
   17059 		return;
   17060 
   17061 	LOCK_ZONE(zone);
   17062 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
   17063 	UNLOCK_ZONE(zone);
   17064 	dns_zone_refresh(zone);
   17065 }
   17066 
   17067 isc_boolean_t
   17068 dns_zone_isforced(dns_zone_t *zone) {
   17069 	REQUIRE(DNS_ZONE_VALID(zone));
   17070 
   17071 	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
   17072 }
   17073 
   17074 isc_result_t
   17075 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
   17076 	/*
   17077 	 * This function is obsoleted.
   17078 	 */
   17079 	UNUSED(zone);
   17080 	UNUSED(on);
   17081 	return (ISC_R_NOTIMPLEMENTED);
   17082 }
   17083 
   17084 isc_uint64_t *
   17085 dns_zone_getstatscounters(dns_zone_t *zone) {
   17086 	/*
   17087 	 * This function is obsoleted.
   17088 	 */
   17089 	UNUSED(zone);
   17090 	return (NULL);
   17091 }
   17092 
   17093 void
   17094 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
   17095 	REQUIRE(DNS_ZONE_VALID(zone));
   17096 	REQUIRE(zone->stats == NULL);
   17097 
   17098 	LOCK_ZONE(zone);
   17099 	zone->stats = NULL;
   17100 	isc_stats_attach(stats, &zone->stats);
   17101 	UNLOCK_ZONE(zone);
   17102 }
   17103 
   17104 void
   17105 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
   17106 
   17107 	REQUIRE(DNS_ZONE_VALID(zone));
   17108 
   17109 	LOCK_ZONE(zone);
   17110 	if (zone->requeststats_on && stats == NULL)
   17111 		zone->requeststats_on = ISC_FALSE;
   17112 	else if (!zone->requeststats_on && stats != NULL) {
   17113 		if (zone->requeststats == NULL) {
   17114 			isc_stats_attach(stats, &zone->requeststats);
   17115 			zone->requeststats_on = ISC_TRUE;
   17116 		}
   17117 	}
   17118 	UNLOCK_ZONE(zone);
   17119 }
   17120 
   17121 void
   17122 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
   17123 
   17124 	REQUIRE(DNS_ZONE_VALID(zone));
   17125 
   17126 	LOCK_ZONE(zone);
   17127 	if (zone->requeststats_on && stats != NULL) {
   17128 		if (zone->rcvquerystats == NULL) {
   17129 			dns_stats_attach(stats, &zone->rcvquerystats);
   17130 			zone->requeststats_on = ISC_TRUE;
   17131 		}
   17132 	}
   17133 	UNLOCK_ZONE(zone);
   17134 }
   17135 
   17136 isc_stats_t *
   17137 dns_zone_getrequeststats(dns_zone_t *zone) {
   17138 	/*
   17139 	 * We don't lock zone for efficiency reason.  This is not catastrophic
   17140 	 * because requeststats must always be valid when requeststats_on is
   17141 	 * true.
   17142 	 * Some counters may be incremented while requeststats_on is becoming
   17143 	 * false, or some cannot be incremented just after the statistics are
   17144 	 * installed, but it shouldn't matter much in practice.
   17145 	 */
   17146 	if (zone->requeststats_on)
   17147 		return (zone->requeststats);
   17148 	else
   17149 		return (NULL);
   17150 }
   17151 
   17152 /*
   17153  * Return the received query stats bucket
   17154  * see note from dns_zone_getrequeststats()
   17155  */
   17156 dns_stats_t *
   17157 dns_zone_getrcvquerystats(dns_zone_t *zone) {
   17158 	if (zone->requeststats_on)
   17159 		return (zone->rcvquerystats);
   17160 	else
   17161 		return (NULL);
   17162 }
   17163 
   17164 void
   17165 dns_zone_dialup(dns_zone_t *zone) {
   17166 
   17167 	REQUIRE(DNS_ZONE_VALID(zone));
   17168 
   17169 	zone_debuglog(zone, "dns_zone_dialup", 3,
   17170 		      "notify = %d, refresh = %d",
   17171 		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
   17172 		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
   17173 
   17174 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
   17175 		dns_zone_notify(zone);
   17176 	if (zone->type != dns_zone_master && zone->masters != NULL &&
   17177 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
   17178 		dns_zone_refresh(zone);
   17179 }
   17180 
   17181 void
   17182 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
   17183 	REQUIRE(DNS_ZONE_VALID(zone));
   17184 
   17185 	LOCK_ZONE(zone);
   17186 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
   17187 			 DNS_ZONEFLG_DIALREFRESH |
   17188 			 DNS_ZONEFLG_NOREFRESH);
   17189 	switch (dialup) {
   17190 	case dns_dialuptype_no:
   17191 		break;
   17192 	case dns_dialuptype_yes:
   17193 		DNS_ZONE_SETFLAG(zone,	(DNS_ZONEFLG_DIALNOTIFY |
   17194 				 DNS_ZONEFLG_DIALREFRESH |
   17195 				 DNS_ZONEFLG_NOREFRESH));
   17196 		break;
   17197 	case dns_dialuptype_notify:
   17198 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
   17199 		break;
   17200 	case dns_dialuptype_notifypassive:
   17201 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
   17202 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
   17203 		break;
   17204 	case dns_dialuptype_refresh:
   17205 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
   17206 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
   17207 		break;
   17208 	case dns_dialuptype_passive:
   17209 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
   17210 		break;
   17211 	default:
   17212 		INSIST(0);
   17213 	}
   17214 	UNLOCK_ZONE(zone);
   17215 }
   17216 
   17217 isc_result_t
   17218 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
   17219 	isc_result_t result = ISC_R_SUCCESS;
   17220 
   17221 	REQUIRE(DNS_ZONE_VALID(zone));
   17222 
   17223 	LOCK_ZONE(zone);
   17224 	result = dns_zone_setstring(zone, &zone->keydirectory, directory);
   17225 	UNLOCK_ZONE(zone);
   17226 
   17227 	return (result);
   17228 }
   17229 
   17230 const char *
   17231 dns_zone_getkeydirectory(dns_zone_t *zone) {
   17232 	REQUIRE(DNS_ZONE_VALID(zone));
   17233 
   17234 	return (zone->keydirectory);
   17235 }
   17236 
   17237 unsigned int
   17238 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
   17239 	dns_zone_t *zone;
   17240 	unsigned int count = 0;
   17241 
   17242 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
   17243 
   17244 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   17245 	switch (state) {
   17246 	case DNS_ZONESTATE_XFERRUNNING:
   17247 		for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
   17248 		     zone != NULL;
   17249 		     zone = ISC_LIST_NEXT(zone, statelink))
   17250 			count++;
   17251 		break;
   17252 	case DNS_ZONESTATE_XFERDEFERRED:
   17253 		for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
   17254 		     zone != NULL;
   17255 		     zone = ISC_LIST_NEXT(zone, statelink))
   17256 			count++;
   17257 		break;
   17258 	case DNS_ZONESTATE_SOAQUERY:
   17259 		for (zone = ISC_LIST_HEAD(zmgr->zones);
   17260 		     zone != NULL;
   17261 		     zone = ISC_LIST_NEXT(zone, link))
   17262 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
   17263 				count++;
   17264 		break;
   17265 	case DNS_ZONESTATE_ANY:
   17266 		for (zone = ISC_LIST_HEAD(zmgr->zones);
   17267 		     zone != NULL;
   17268 		     zone = ISC_LIST_NEXT(zone, link)) {
   17269 			dns_view_t *view = zone->view;
   17270 			if (view != NULL && strcmp(view->name, "_bind") == 0)
   17271 				continue;
   17272 			count++;
   17273 		}
   17274 		break;
   17275 	case DNS_ZONESTATE_AUTOMATIC:
   17276 		for (zone = ISC_LIST_HEAD(zmgr->zones);
   17277 		     zone != NULL;
   17278 		     zone = ISC_LIST_NEXT(zone, link)) {
   17279 			dns_view_t *view = zone->view;
   17280 			if (view != NULL && strcmp(view->name, "_bind") == 0)
   17281 				continue;
   17282 			if (zone->automatic)
   17283 				count++;
   17284 		}
   17285 		break;
   17286 	default:
   17287 		INSIST(0);
   17288 	}
   17289 
   17290 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
   17291 
   17292 	return (count);
   17293 }
   17294 
   17295 isc_result_t
   17296 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
   17297 		    dns_rdata_t *rdata)
   17298 {
   17299 	isc_boolean_t ok = ISC_TRUE;
   17300 	isc_boolean_t fail = ISC_FALSE;
   17301 	char namebuf[DNS_NAME_FORMATSIZE];
   17302 	char namebuf2[DNS_NAME_FORMATSIZE];
   17303 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
   17304 	int level = ISC_LOG_WARNING;
   17305 	dns_name_t bad;
   17306 
   17307 	REQUIRE(DNS_ZONE_VALID(zone));
   17308 
   17309 	if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
   17310 	    rdata->type != dns_rdatatype_nsec3)
   17311 		return (ISC_R_SUCCESS);
   17312 
   17313 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
   17314 	    rdata->type == dns_rdatatype_nsec3) {
   17315 		level = ISC_LOG_ERROR;
   17316 		fail = ISC_TRUE;
   17317 	}
   17318 
   17319 	ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
   17320 	if (!ok) {
   17321 		dns_name_format(name, namebuf, sizeof(namebuf));
   17322 		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
   17323 		dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
   17324 			     dns_result_totext(DNS_R_BADOWNERNAME));
   17325 		if (fail)
   17326 			return (DNS_R_BADOWNERNAME);
   17327 	}
   17328 
   17329 	dns_name_init(&bad, NULL);
   17330 	ok = dns_rdata_checknames(rdata, name, &bad);
   17331 	if (!ok) {
   17332 		dns_name_format(name, namebuf, sizeof(namebuf));
   17333 		dns_name_format(&bad, namebuf2, sizeof(namebuf2));
   17334 		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
   17335 		dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
   17336 			     namebuf2, dns_result_totext(DNS_R_BADNAME));
   17337 		if (fail)
   17338 			return (DNS_R_BADNAME);
   17339 	}
   17340 
   17341 	return (ISC_R_SUCCESS);
   17342 }
   17343 
   17344 void
   17345 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
   17346 	REQUIRE(DNS_ZONE_VALID(zone));
   17347 	zone->checkmx = checkmx;
   17348 }
   17349 
   17350 void
   17351 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
   17352 	REQUIRE(DNS_ZONE_VALID(zone));
   17353 	zone->checksrv = checksrv;
   17354 }
   17355 
   17356 void
   17357 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
   17358 	REQUIRE(DNS_ZONE_VALID(zone));
   17359 	zone->checkns = checkns;
   17360 }
   17361 
   17362 void
   17363 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
   17364 	REQUIRE(DNS_ZONE_VALID(zone));
   17365 
   17366 	LOCK_ZONE(zone);
   17367 	zone->isself = isself;
   17368 	zone->isselfarg = arg;
   17369 	UNLOCK_ZONE(zone);
   17370 }
   17371 
   17372 void
   17373 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
   17374 	REQUIRE(DNS_ZONE_VALID(zone));
   17375 
   17376 	LOCK_ZONE(zone);
   17377 	zone->notifydelay = delay;
   17378 	UNLOCK_ZONE(zone);
   17379 }
   17380 
   17381 isc_uint32_t
   17382 dns_zone_getnotifydelay(dns_zone_t *zone) {
   17383 	REQUIRE(DNS_ZONE_VALID(zone));
   17384 
   17385 	return (zone->notifydelay);
   17386 }
   17387 
   17388 isc_result_t
   17389 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
   17390 		     isc_uint16_t keyid, isc_boolean_t deleteit)
   17391 {
   17392 	isc_result_t result;
   17393 	REQUIRE(DNS_ZONE_VALID(zone));
   17394 
   17395 	dns_zone_log(zone, ISC_LOG_NOTICE,
   17396 		     "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
   17397 		     algorithm, keyid);
   17398 	LOCK_ZONE(zone);
   17399 	result = zone_signwithkey(zone, algorithm, keyid, deleteit);
   17400 	UNLOCK_ZONE(zone);
   17401 
   17402 	return (result);
   17403 }
   17404 
   17405 /*
   17406  * Called when a dynamic update for an NSEC3PARAM record is received.
   17407  *
   17408  * If set, transform the NSEC3 salt into human-readable form so that it can be
   17409  * logged.  Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
   17410  */
   17411 isc_result_t
   17412 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
   17413 	isc_result_t result;
   17414 	char salt[255*2+1];
   17415 
   17416 	REQUIRE(DNS_ZONE_VALID(zone));
   17417 
   17418 	result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
   17419 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17420 	dns_zone_log(zone, ISC_LOG_NOTICE,
   17421 		     "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
   17422 		     nsec3param->hash, nsec3param->iterations,
   17423 		     salt);
   17424 	LOCK_ZONE(zone);
   17425 	result = zone_addnsec3chain(zone, nsec3param);
   17426 	UNLOCK_ZONE(zone);
   17427 
   17428 	return (result);
   17429 }
   17430 
   17431 void
   17432 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
   17433 	REQUIRE(DNS_ZONE_VALID(zone));
   17434 
   17435 	if (nodes == 0)
   17436 		nodes = 1;
   17437 	zone->nodes = nodes;
   17438 }
   17439 
   17440 void
   17441 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
   17442 	REQUIRE(DNS_ZONE_VALID(zone));
   17443 
   17444 	/*
   17445 	 * We treat signatures as a signed value so explicitly
   17446 	 * limit its range here.
   17447 	 */
   17448 	if (signatures > ISC_INT32_MAX)
   17449 		signatures = ISC_INT32_MAX;
   17450 	else if (signatures == 0)
   17451 		signatures = 1;
   17452 	zone->signatures = signatures;
   17453 }
   17454 
   17455 isc_uint32_t
   17456 dns_zone_getsignatures(dns_zone_t *zone) {
   17457 	REQUIRE(DNS_ZONE_VALID(zone));
   17458 	return (zone->signatures);
   17459 }
   17460 
   17461 void
   17462 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
   17463 	REQUIRE(DNS_ZONE_VALID(zone));
   17464 	zone->privatetype = type;
   17465 }
   17466 
   17467 dns_rdatatype_t
   17468 dns_zone_getprivatetype(dns_zone_t *zone) {
   17469 	REQUIRE(DNS_ZONE_VALID(zone));
   17470 	return (zone->privatetype);
   17471 }
   17472 
   17473 static isc_result_t
   17474 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
   17475 		 isc_boolean_t deleteit)
   17476 {
   17477 	dns_signing_t *signing;
   17478 	dns_signing_t *current;
   17479 	isc_result_t result = ISC_R_SUCCESS;
   17480 	isc_time_t now;
   17481 	dns_db_t *db = NULL;
   17482 
   17483 	signing = isc_mem_get(zone->mctx, sizeof *signing);
   17484 	if (signing == NULL)
   17485 		return (ISC_R_NOMEMORY);
   17486 
   17487 	signing->magic = 0;
   17488 	signing->db  = NULL;
   17489 	signing->dbiterator = NULL;
   17490 	signing->algorithm = algorithm;
   17491 	signing->keyid = keyid;
   17492 	signing->deleteit = deleteit;
   17493 	signing->done = ISC_FALSE;
   17494 
   17495 	TIME_NOW(&now);
   17496 
   17497 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   17498 	if (zone->db != NULL)
   17499 		dns_db_attach(zone->db, &db);
   17500 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   17501 
   17502 	if (db == NULL) {
   17503 		result = ISC_R_NOTFOUND;
   17504 		goto cleanup;
   17505 	}
   17506 
   17507 	dns_db_attach(db, &signing->db);
   17508 
   17509 	for (current = ISC_LIST_HEAD(zone->signing);
   17510 	     current != NULL;
   17511 	     current = ISC_LIST_NEXT(current, link)) {
   17512 		if (current->db == signing->db &&
   17513 		    current->algorithm == signing->algorithm &&
   17514 		    current->keyid == signing->keyid) {
   17515 			if (current->deleteit != signing->deleteit)
   17516 				current->done = ISC_TRUE;
   17517 			else
   17518 				goto cleanup;
   17519 		}
   17520 	}
   17521 
   17522 	result = dns_db_createiterator(signing->db, 0,
   17523 				       &signing->dbiterator);
   17524 
   17525 	if (result == ISC_R_SUCCESS)
   17526 		result = dns_dbiterator_first(signing->dbiterator);
   17527 	if (result == ISC_R_SUCCESS) {
   17528 		dns_dbiterator_pause(signing->dbiterator);
   17529 		ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
   17530 		signing = NULL;
   17531 		if (isc_time_isepoch(&zone->signingtime)) {
   17532 			zone->signingtime = now;
   17533 			if (zone->task != NULL)
   17534 				zone_settimer(zone, &now);
   17535 		}
   17536 	}
   17537 
   17538  cleanup:
   17539 	if (signing != NULL) {
   17540 		if (signing->db != NULL)
   17541 			dns_db_detach(&signing->db);
   17542 		if (signing->dbiterator != NULL)
   17543 			dns_dbiterator_destroy(&signing->dbiterator);
   17544 		isc_mem_put(zone->mctx, signing, sizeof *signing);
   17545 	}
   17546 	if (db != NULL)
   17547 		dns_db_detach(&db);
   17548 	return (result);
   17549 }
   17550 
   17551 static void
   17552 logmsg(const char *format, ...) {
   17553 	va_list args;
   17554 	va_start(args, format);
   17555 	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
   17556 		       ISC_LOG_DEBUG(1), format, args);
   17557 	va_end(args);
   17558 }
   17559 
   17560 static void
   17561 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
   17562 	dns_dnsseckey_t *key;
   17563 	while (!ISC_LIST_EMPTY(*list)) {
   17564 		key = ISC_LIST_HEAD(*list);
   17565 		ISC_LIST_UNLINK(*list, key, link);
   17566 		dns_dnsseckey_destroy(mctx, &key);
   17567 	}
   17568 }
   17569 
   17570 /* Called once; *timep should be set to the current time. */
   17571 static isc_result_t
   17572 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
   17573 	isc_result_t result;
   17574 	isc_stdtime_t now, then = 0, event;
   17575 	int i;
   17576 
   17577 	now = *timep;
   17578 
   17579 	for (i = 0; i <= DST_MAX_TIMES; i++) {
   17580 		result = dst_key_gettime(key, i, &event);
   17581 		if (result == ISC_R_SUCCESS && event > now &&
   17582 		    (then == 0 || event < then))
   17583 			then = event;
   17584 	}
   17585 
   17586 	if (then != 0) {
   17587 		*timep = then;
   17588 		return (ISC_R_SUCCESS);
   17589 	}
   17590 
   17591 	return (ISC_R_NOTFOUND);
   17592 }
   17593 
   17594 static isc_result_t
   17595 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
   17596 	  const dns_rdata_t *rdata, isc_boolean_t *flag)
   17597 {
   17598 	dns_rdataset_t rdataset;
   17599 	dns_dbnode_t *node = NULL;
   17600 	isc_result_t result;
   17601 
   17602 	dns_rdataset_init(&rdataset);
   17603 	if (rdata->type == dns_rdatatype_nsec3)
   17604 		CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
   17605 	else
   17606 		CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
   17607 	result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
   17608 				     (isc_stdtime_t) 0, &rdataset, NULL);
   17609 	if (result == ISC_R_NOTFOUND) {
   17610 		*flag = ISC_FALSE;
   17611 		result = ISC_R_SUCCESS;
   17612 		goto failure;
   17613 	}
   17614 
   17615 	for (result = dns_rdataset_first(&rdataset);
   17616 	     result == ISC_R_SUCCESS;
   17617 	     result = dns_rdataset_next(&rdataset)) {
   17618 		dns_rdata_t myrdata = DNS_RDATA_INIT;
   17619 		dns_rdataset_current(&rdataset, &myrdata);
   17620 		if (!dns_rdata_compare(&myrdata, rdata))
   17621 			break;
   17622 	}
   17623 	dns_rdataset_disassociate(&rdataset);
   17624 	if (result == ISC_R_SUCCESS) {
   17625 		*flag = ISC_TRUE;
   17626 	} else if (result == ISC_R_NOMORE) {
   17627 		*flag = ISC_FALSE;
   17628 		result = ISC_R_SUCCESS;
   17629 	}
   17630 
   17631  failure:
   17632 	if (node != NULL)
   17633 		dns_db_detachnode(db, &node);
   17634 	return (result);
   17635 }
   17636 
   17637 /*
   17638  * Add records to signal the state of signing or of key removal.
   17639  */
   17640 static isc_result_t
   17641 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
   17642 		    dns_dbversion_t *ver, dns_diff_t *diff,
   17643 		    isc_boolean_t sign_all)
   17644 {
   17645 	dns_difftuple_t *tuple, *newtuple = NULL;
   17646 	dns_rdata_dnskey_t dnskey;
   17647 	dns_rdata_t rdata = DNS_RDATA_INIT;
   17648 	isc_boolean_t flag;
   17649 	isc_region_t r;
   17650 	isc_result_t result = ISC_R_SUCCESS;
   17651 	isc_uint16_t keyid;
   17652 	unsigned char buf[5];
   17653 	dns_name_t *name = dns_db_origin(db);
   17654 
   17655 	for (tuple = ISC_LIST_HEAD(diff->tuples);
   17656 	     tuple != NULL;
   17657 	     tuple = ISC_LIST_NEXT(tuple, link)) {
   17658 		if (tuple->rdata.type != dns_rdatatype_dnskey)
   17659 			continue;
   17660 
   17661 		result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
   17662 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17663 		if ((dnskey.flags &
   17664 		     (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
   17665 			 != DNS_KEYOWNER_ZONE)
   17666 			continue;
   17667 
   17668 		dns_rdata_toregion(&tuple->rdata, &r);
   17669 
   17670 		keyid = dst_region_computeid(&r, dnskey.algorithm);
   17671 
   17672 		buf[0] = dnskey.algorithm;
   17673 		buf[1] = (keyid & 0xff00) >> 8;
   17674 		buf[2] = (keyid & 0xff);
   17675 		buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
   17676 		buf[4] = 0;
   17677 		rdata.data = buf;
   17678 		rdata.length = sizeof(buf);
   17679 		rdata.type = privatetype;
   17680 		rdata.rdclass = tuple->rdata.rdclass;
   17681 
   17682 		if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
   17683 			CHECK(rr_exists(db, ver, name, &rdata, &flag));
   17684 			if (flag)
   17685 				continue;
   17686 			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
   17687 						   name, 0, &rdata, &newtuple));
   17688 			CHECK(do_one_tuple(&newtuple, db, ver, diff));
   17689 			INSIST(newtuple == NULL);
   17690 		}
   17691 
   17692 		/*
   17693 		 * Remove any record which says this operation has already
   17694 		 * completed.
   17695 		 */
   17696 		buf[4] = 1;
   17697 		CHECK(rr_exists(db, ver, name, &rdata, &flag));
   17698 		if (flag) {
   17699 			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
   17700 						   name, 0, &rdata, &newtuple));
   17701 			CHECK(do_one_tuple(&newtuple, db, ver, diff));
   17702 			INSIST(newtuple == NULL);
   17703 		}
   17704 	}
   17705  failure:
   17706 	return (result);
   17707 }
   17708 
   17709 static isc_result_t
   17710 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   17711 	  isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff)
   17712 {
   17713 	isc_result_t result;
   17714 	isc_stdtime_t inception, soaexpire;
   17715 	isc_boolean_t check_ksk, keyset_kskonly;
   17716 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
   17717 	unsigned int nkeys = 0, i;
   17718 	dns_difftuple_t *tuple;
   17719 
   17720 	result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
   17721 				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
   17722 	if (result != ISC_R_SUCCESS) {
   17723 		dns_zone_log(zone, ISC_LOG_ERROR,
   17724 			     "sign_apex:dns__zone_findkeys -> %s",
   17725 			     dns_result_totext(result));
   17726 		return (result);
   17727 	}
   17728 
   17729 	inception = now - 3600;	/* Allow for clock skew. */
   17730 	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
   17731 
   17732 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
   17733 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
   17734 
   17735 	/*
   17736 	 * See if dns__zone_updatesigs() will update DNSKEY signature and if
   17737 	 * not cause them to sign so that newly activated keys are used.
   17738 	 */
   17739 	for (tuple = ISC_LIST_HEAD(diff->tuples);
   17740 	     tuple != NULL;
   17741 	     tuple = ISC_LIST_NEXT(tuple, link)) {
   17742 		if (tuple->rdata.type == dns_rdatatype_dnskey &&
   17743 		    dns_name_equal(&tuple->name, &zone->origin))
   17744 			break;
   17745 	}
   17746 
   17747 	if (tuple == NULL) {
   17748 		result = del_sigs(zone, db, ver, &zone->origin,
   17749 				  dns_rdatatype_dnskey, zonediff,
   17750 				  zone_keys, nkeys, now, ISC_FALSE);
   17751 		if (result != ISC_R_SUCCESS) {
   17752 			dns_zone_log(zone, ISC_LOG_ERROR,
   17753 				     "sign_apex:del_sigs -> %s",
   17754 				     dns_result_totext(result));
   17755 			goto failure;
   17756 		}
   17757 		result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
   17758 				  zonediff->diff, zone_keys, nkeys, zone->mctx,
   17759 				  inception, soaexpire, check_ksk,
   17760 				  keyset_kskonly);
   17761 		if (result != ISC_R_SUCCESS) {
   17762 			dns_zone_log(zone, ISC_LOG_ERROR,
   17763 				     "sign_apex:add_sigs -> %s",
   17764 				     dns_result_totext(result));
   17765 			goto failure;
   17766 		}
   17767 	}
   17768 
   17769 	result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
   17770 				      inception, soaexpire, now, check_ksk,
   17771 				      keyset_kskonly, zonediff);
   17772 	if (result != ISC_R_SUCCESS) {
   17773 		dns_zone_log(zone, ISC_LOG_ERROR,
   17774 			     "sign_apex:dns__zone_updatesigs -> %s",
   17775 			     dns_result_totext(result));
   17776 		goto failure;
   17777 	}
   17778 
   17779  failure:
   17780 	for (i = 0; i < nkeys; i++)
   17781 		dst_key_free(&zone_keys[i]);
   17782 	return (result);
   17783 }
   17784 
   17785 /*
   17786  * Prevent the zone entering a inconsistent state where
   17787  * NSEC only DNSKEYs are present with NSEC3 chains.
   17788  * See update.c:check_dnssec()
   17789  */
   17790 static isc_boolean_t
   17791 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   17792 	    dns_diff_t *diff)
   17793 {
   17794 	isc_result_t result;
   17795 	dns_difftuple_t *tuple;
   17796 	isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
   17797 	dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
   17798 
   17799 	/* Scan the tuples for an NSEC-only DNSKEY */
   17800 	for (tuple = ISC_LIST_HEAD(diff->tuples);
   17801 	     tuple != NULL;
   17802 	     tuple = ISC_LIST_NEXT(tuple, link)) {
   17803 		isc_uint8_t alg;
   17804 		if (tuple->rdata.type != dns_rdatatype_dnskey ||
   17805 		    tuple->op != DNS_DIFFOP_ADD)
   17806 			continue;
   17807 
   17808 		alg = tuple->rdata.data[3];
   17809 		if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
   17810 		    alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
   17811 			nseconly = ISC_TRUE;
   17812 			break;
   17813 		}
   17814 	}
   17815 
   17816 	/* Check existing DB for NSEC-only DNSKEY */
   17817 	if (!nseconly) {
   17818 		result = dns_nsec_nseconly(db, ver, &nseconly);
   17819 		if (result == ISC_R_NOTFOUND)
   17820 			result = ISC_R_SUCCESS;
   17821 		CHECK(result);
   17822 	}
   17823 
   17824 	/* Check existing DB for NSEC3 */
   17825 	if (!nsec3)
   17826 		CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
   17827 					privatetype, &nsec3));
   17828 
   17829 	/* Refuse to allow NSEC3 with NSEC-only keys */
   17830 	if (nseconly && nsec3) {
   17831 		dns_zone_log(zone, ISC_LOG_ERROR,
   17832 			   "NSEC only DNSKEYs and NSEC3 chains not allowed");
   17833 		goto failure;
   17834 	}
   17835 
   17836 	return (ISC_TRUE);
   17837 
   17838  failure:
   17839 	return (ISC_FALSE);
   17840 }
   17841 
   17842 static isc_result_t
   17843 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   17844 		 dns_diff_t *diff)
   17845 {
   17846 	isc_result_t result;
   17847 	dns_dbnode_t *node = NULL;
   17848 	dns_rdataset_t rdataset;
   17849 
   17850 	dns_rdataset_init(&rdataset);
   17851 	CHECK(dns_db_getoriginnode(db, &node));
   17852 
   17853 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
   17854 				     dns_rdatatype_none, 0, &rdataset, NULL);
   17855 	if (dns_rdataset_isassociated(&rdataset))
   17856 		dns_rdataset_disassociate(&rdataset);
   17857 	if (result != ISC_R_NOTFOUND)
   17858 		goto failure;
   17859 
   17860 	result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff);
   17861 
   17862  failure:
   17863 	if (node != NULL)
   17864 		dns_db_detachnode(db, &node);
   17865 	return (result);
   17866 }
   17867 
   17868 /*
   17869  * Given an RRSIG rdataset and an algorithm, determine whether there
   17870  * are any signatures using that algorithm.
   17871  */
   17872 static isc_boolean_t
   17873 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
   17874 	dns_rdata_t rdata = DNS_RDATA_INIT;
   17875 	dns_rdata_rrsig_t rrsig;
   17876 	isc_result_t result;
   17877 
   17878 	REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
   17879 	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
   17880 		return (ISC_FALSE);
   17881 	}
   17882 
   17883 	for (result = dns_rdataset_first(rdataset);
   17884 	     result == ISC_R_SUCCESS;
   17885 	     result = dns_rdataset_next(rdataset))
   17886 	{
   17887 		dns_rdataset_current(rdataset, &rdata);
   17888 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
   17889 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
   17890 		dns_rdata_reset(&rdata);
   17891 		if (rrsig.algorithm == alg)
   17892 			return (ISC_TRUE);
   17893 	}
   17894 
   17895 	return (ISC_FALSE);
   17896 }
   17897 
   17898 static isc_result_t
   17899 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
   17900 	   dns_diff_t *diff)
   17901 {
   17902 	dns_name_t *origin;
   17903 	isc_boolean_t build_nsec3;
   17904 	isc_result_t result;
   17905 
   17906 	origin = dns_db_origin(db);
   17907 	CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
   17908 				 &build_nsec3));
   17909 	if (build_nsec3)
   17910 		CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
   17911 					   ISC_FALSE, zone->privatetype, diff));
   17912 	CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
   17913 
   17914  failure:
   17915 	return (result);
   17916 }
   17917 
   17918 static void
   17919 zone_rekey(dns_zone_t *zone) {
   17920 	isc_result_t result;
   17921 	dns_db_t *db = NULL;
   17922 	dns_dbnode_t *node = NULL;
   17923 	dns_dbversion_t *ver = NULL;
   17924 	dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
   17925 	dns_dnsseckeylist_t dnskeys, keys, rmkeys;
   17926 	dns_dnsseckey_t *key;
   17927 	dns_diff_t diff, _sig_diff;
   17928 	dns__zonediff_t zonediff;
   17929 	isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
   17930 	isc_boolean_t newalg = ISC_FALSE;
   17931 	isc_boolean_t fullsign;
   17932 	dns_ttl_t ttl = 3600;
   17933 	const char *dir;
   17934 	isc_mem_t *mctx;
   17935 	isc_stdtime_t now;
   17936 	isc_time_t timenow;
   17937 	isc_interval_t ival;
   17938 	char timebuf[80];
   17939 
   17940 	REQUIRE(DNS_ZONE_VALID(zone));
   17941 
   17942 	ISC_LIST_INIT(dnskeys);
   17943 	ISC_LIST_INIT(keys);
   17944 	ISC_LIST_INIT(rmkeys);
   17945 	dns_rdataset_init(&soaset);
   17946 	dns_rdataset_init(&soasigs);
   17947 	dns_rdataset_init(&keyset);
   17948 	dns_rdataset_init(&keysigs);
   17949 	dns_rdataset_init(&cdsset);
   17950 	dns_rdataset_init(&cdnskeyset);
   17951 	dir = dns_zone_getkeydirectory(zone);
   17952 	mctx = zone->mctx;
   17953 	dns_diff_init(mctx, &diff);
   17954 	dns_diff_init(mctx, &_sig_diff);
   17955 	zonediff_init(&zonediff, &_sig_diff);
   17956 
   17957 	CHECK(dns_zone_getdb(zone, &db));
   17958 	CHECK(dns_db_newversion(db, &ver));
   17959 	CHECK(dns_db_getoriginnode(db, &node));
   17960 
   17961 	TIME_NOW(&timenow);
   17962 	now = isc_time_seconds(&timenow);
   17963 
   17964 	dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
   17965 
   17966 	/* Get the SOA record's TTL */
   17967 	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
   17968 				  dns_rdatatype_none, 0, &soaset, &soasigs));
   17969 	ttl = soaset.ttl;
   17970 	dns_rdataset_disassociate(&soaset);
   17971 
   17972 	/* Get the DNSKEY rdataset */
   17973 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
   17974 				     dns_rdatatype_none, 0, &keyset, &keysigs);
   17975 	if (result == ISC_R_SUCCESS) {
   17976 		ttl = keyset.ttl;
   17977 		CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
   17978 						     mctx, &keyset,
   17979 						     &keysigs, &soasigs,
   17980 						     ISC_FALSE, ISC_FALSE,
   17981 						     &dnskeys));
   17982 	} else if (result != ISC_R_NOTFOUND)
   17983 		goto failure;
   17984 
   17985 
   17986 	/* Get the CDS rdataset */
   17987 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
   17988 				     dns_rdatatype_none, 0, &cdsset, NULL);
   17989 	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset))
   17990 		dns_rdataset_disassociate(&cdsset);
   17991 
   17992 	/* Get the CDNSKEY rdataset */
   17993 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
   17994 				     dns_rdatatype_none, 0, &cdnskeyset, NULL);
   17995 	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset))
   17996 		dns_rdataset_disassociate(&cdnskeyset);
   17997 
   17998 	/*
   17999 	 * True when called from "rndc sign".  Indicates the zone should be
   18000 	 * fully signed now.
   18001 	 */
   18002 	fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
   18003 
   18004 	result = dns_dnssec_findmatchingkeys2(&zone->origin, dir, now, mctx,
   18005 					      &keys);
   18006 	if (result == ISC_R_SUCCESS) {
   18007 		isc_boolean_t check_ksk;
   18008 		check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
   18009 
   18010 		result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
   18011 					       &zone->origin, ttl, &diff,
   18012 					       ISC_TF(!check_ksk),
   18013 					       mctx, logmsg);
   18014 		/*
   18015 		 * Keys couldn't be updated for some reason;
   18016 		 * try again later.
   18017 		 */
   18018 		if (result != ISC_R_SUCCESS) {
   18019 			dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
   18020 				     "couldn't update zone keys: %s",
   18021 				     isc_result_totext(result));
   18022 			goto failure;
   18023 		}
   18024 
   18025 		/*
   18026 		 * Update CDS / CDNSKEY records.
   18027 		 */
   18028 		result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
   18029 					       &cdnskeyset, now, ttl,
   18030 					       &diff, mctx);
   18031 		if (result != ISC_R_SUCCESS) {
   18032 			dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
   18033 				     "couldn't update CDS/CDNSKEY: %s",
   18034 				     isc_result_totext(result));
   18035 			goto failure;
   18036 		}
   18037 
   18038 		/*
   18039 		 * See if any pre-existing keys have newly become active;
   18040 		 * also, see if any new key is for a new algorithm, as in that
   18041 		 * event, we need to sign the zone fully.  (If there's a new
   18042 		 * key, but it's for an already-existing algorithm, then
   18043 		 * the zone signing can be handled incrementally.)
   18044 		 */
   18045 		for (key = ISC_LIST_HEAD(dnskeys);
   18046 		     key != NULL;
   18047 		     key = ISC_LIST_NEXT(key, link)) {
   18048 			if (!key->first_sign)
   18049 				continue;
   18050 
   18051 			newactive = ISC_TRUE;
   18052 
   18053 			if (!dns_rdataset_isassociated(&keysigs)) {
   18054 				newalg = ISC_TRUE;
   18055 				break;
   18056 			}
   18057 
   18058 			if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
   18059 				/*
   18060 				 * This isn't a new algorithm; clear
   18061 				 * first_sign so we won't sign the
   18062 				 * whole zone with this key later
   18063 				 */
   18064 				key->first_sign = ISC_FALSE;
   18065 			} else {
   18066 				newalg = ISC_TRUE;
   18067 				break;
   18068 			}
   18069 		}
   18070 
   18071 		if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
   18072 		    dnskey_sane(zone, db, ver, &diff)) {
   18073 			CHECK(dns_diff_apply(&diff, db, ver));
   18074 			CHECK(clean_nsec3param(zone, db, ver, &diff));
   18075 			CHECK(add_signing_records(db, zone->privatetype,
   18076 						  ver, &diff,
   18077 						  ISC_TF(newalg || fullsign)));
   18078 			CHECK(update_soa_serial(db, ver, &diff, mctx,
   18079 						zone->updatemethod));
   18080 			CHECK(add_chains(zone, db, ver, &diff));
   18081 			CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
   18082 			CHECK(zone_journal(zone, zonediff.diff, NULL,
   18083 					   "zone_rekey"));
   18084 			commit = ISC_TRUE;
   18085 		}
   18086 	}
   18087 
   18088 	dns_db_closeversion(db, &ver, ISC_TRUE);
   18089 
   18090 	if (commit) {
   18091 		dns_difftuple_t *tuple;
   18092 
   18093 		LOCK_ZONE(zone);
   18094 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
   18095 
   18096 		zone_needdump(zone, DNS_DUMP_DELAY);
   18097 
   18098 		zone_settimer(zone, &timenow);
   18099 
   18100 		/* Remove any signatures from removed keys.  */
   18101 		if (!ISC_LIST_EMPTY(rmkeys)) {
   18102 			for (key = ISC_LIST_HEAD(rmkeys);
   18103 			     key != NULL;
   18104 			     key = ISC_LIST_NEXT(key, link)) {
   18105 				result = zone_signwithkey(zone,
   18106 							  dst_key_alg(key->key),
   18107 							  dst_key_id(key->key),
   18108 							  ISC_TRUE);
   18109 				if (result != ISC_R_SUCCESS) {
   18110 					dns_zone_log(zone, ISC_LOG_ERROR,
   18111 					     "zone_signwithkey failed: %s",
   18112 					     dns_result_totext(result));
   18113 				}
   18114 			}
   18115 		}
   18116 
   18117 		if (fullsign) {
   18118 			/*
   18119 			 * "rndc sign" was called, so we now sign the zone
   18120 			 * with all active keys, whether they're new or not.
   18121 			 */
   18122 			for (key = ISC_LIST_HEAD(dnskeys);
   18123 			     key != NULL;
   18124 			     key = ISC_LIST_NEXT(key, link)) {
   18125 				if (!key->force_sign && !key->hint_sign)
   18126 					continue;
   18127 
   18128 				result = zone_signwithkey(zone,
   18129 							  dst_key_alg(key->key),
   18130 							  dst_key_id(key->key),
   18131 							  ISC_FALSE);
   18132 				if (result != ISC_R_SUCCESS) {
   18133 					dns_zone_log(zone, ISC_LOG_ERROR,
   18134 					     "zone_signwithkey failed: %s",
   18135 					     dns_result_totext(result));
   18136 				}
   18137 			}
   18138 		} else if (newalg) {
   18139 			/*
   18140 			 * We haven't been told to sign fully, but a new
   18141 			 * algorithm was added to the DNSKEY.  We sign
   18142 			 * the full zone, but only with newly active
   18143 			 * keys.
   18144 			 */
   18145 			for (key = ISC_LIST_HEAD(dnskeys);
   18146 			     key != NULL;
   18147 			     key = ISC_LIST_NEXT(key, link)) {
   18148 				if (!key->first_sign)
   18149 					continue;
   18150 
   18151 				result = zone_signwithkey(zone,
   18152 							  dst_key_alg(key->key),
   18153 							  dst_key_id(key->key),
   18154 							  ISC_FALSE);
   18155 				if (result != ISC_R_SUCCESS) {
   18156 					dns_zone_log(zone, ISC_LOG_ERROR,
   18157 					     "zone_signwithkey failed: %s",
   18158 					     dns_result_totext(result));
   18159 				}
   18160 			}
   18161 		}
   18162 
   18163 		/*
   18164 		 * Clear fullsign flag, if it was set, so we don't do
   18165 		 * another full signing next time
   18166 		 */
   18167 		zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
   18168 
   18169 		/*
   18170 		 * Cause the zone to add/delete NSEC3 chains for the
   18171 		 * deferred NSEC3PARAM changes.
   18172 		 */
   18173 		for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
   18174 		     tuple != NULL;
   18175 		     tuple = ISC_LIST_NEXT(tuple, link)) {
   18176 			unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
   18177 			dns_rdata_t rdata = DNS_RDATA_INIT;
   18178 			dns_rdata_nsec3param_t nsec3param;
   18179 
   18180 			if (tuple->rdata.type != zone->privatetype ||
   18181 			    tuple->op != DNS_DIFFOP_ADD)
   18182 				continue;
   18183 
   18184 			if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
   18185 							buf, sizeof(buf)))
   18186 				continue;
   18187 			result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
   18188 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
   18189 			if (nsec3param.flags == 0)
   18190 				continue;
   18191 
   18192 			result = zone_addnsec3chain(zone, &nsec3param);
   18193 			if (result != ISC_R_SUCCESS) {
   18194 				dns_zone_log(zone, ISC_LOG_ERROR,
   18195 					     "zone_addnsec3chain failed: %s",
   18196 					     dns_result_totext(result));
   18197 			}
   18198 		}
   18199 
   18200 		/*
   18201 		 * Activate any NSEC3 chain updates that may have
   18202 		 * been scheduled before this rekey.
   18203 		 */
   18204 		if (fullsign || newalg)
   18205 			resume_addnsec3chain(zone);
   18206 
   18207 		/*
   18208 		 * Schedule the next resigning event
   18209 		 */
   18210 		set_resigntime(zone);
   18211 		UNLOCK_ZONE(zone);
   18212 	}
   18213 
   18214 	isc_time_settoepoch(&zone->refreshkeytime);
   18215 
   18216 	/*
   18217 	 * If we're doing key maintenance, set the key refresh timer to
   18218 	 * the next scheduled key event or to 'dnssec-loadkeys-interval'
   18219 	 * seconds in the future, whichever is sooner.
   18220 	 */
   18221 	if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
   18222 		isc_time_t timethen;
   18223 		isc_stdtime_t then;
   18224 
   18225 		LOCK_ZONE(zone);
   18226 		DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
   18227 				  &timethen);
   18228 		zone->refreshkeytime = timethen;
   18229 		UNLOCK_ZONE(zone);
   18230 
   18231 		for (key = ISC_LIST_HEAD(dnskeys);
   18232 		     key != NULL;
   18233 		     key = ISC_LIST_NEXT(key, link)) {
   18234 			then = now;
   18235 			result = next_keyevent(key->key, &then);
   18236 			if (result != ISC_R_SUCCESS)
   18237 				continue;
   18238 
   18239 			DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
   18240 			LOCK_ZONE(zone);
   18241 			if (isc_time_compare(&timethen,
   18242 					     &zone->refreshkeytime) < 0) {
   18243 				zone->refreshkeytime = timethen;
   18244 			}
   18245 			UNLOCK_ZONE(zone);
   18246 		}
   18247 
   18248 		zone_settimer(zone, &timenow);
   18249 
   18250 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
   18251 		dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
   18252 	}
   18253 
   18254  done:
   18255 	dns_diff_clear(&diff);
   18256 	dns_diff_clear(&_sig_diff);
   18257 
   18258 	clear_keylist(&dnskeys, mctx);
   18259 	clear_keylist(&keys, mctx);
   18260 	clear_keylist(&rmkeys, mctx);
   18261 
   18262 	if (ver != NULL)
   18263 		dns_db_closeversion(db, &ver, ISC_FALSE);
   18264 	if (dns_rdataset_isassociated(&cdsset))
   18265 		dns_rdataset_disassociate(&cdsset);
   18266 	if (dns_rdataset_isassociated(&keyset))
   18267 		dns_rdataset_disassociate(&keyset);
   18268 	if (dns_rdataset_isassociated(&keysigs))
   18269 		dns_rdataset_disassociate(&keysigs);
   18270 	if (dns_rdataset_isassociated(&soasigs))
   18271 		dns_rdataset_disassociate(&soasigs);
   18272 	if (dns_rdataset_isassociated(&cdnskeyset))
   18273 		dns_rdataset_disassociate(&cdnskeyset);
   18274 	if (node != NULL)
   18275 		dns_db_detachnode(db, &node);
   18276 	if (db != NULL)
   18277 		dns_db_detach(&db);
   18278 
   18279 	INSIST(ver == NULL);
   18280 	return;
   18281 
   18282  failure:
   18283 	/*
   18284 	 * Something went wrong; try again in ten minutes or
   18285 	 * after a key refresh interval, whichever is shorter.
   18286 	 */
   18287 	isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0);
   18288 	isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
   18289 	goto done;
   18290 }
   18291 
   18292 void
   18293 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
   18294 	isc_time_t now;
   18295 
   18296 	if (zone->type == dns_zone_master && zone->task != NULL) {
   18297 		LOCK_ZONE(zone);
   18298 
   18299 		if (fullsign)
   18300 			zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
   18301 
   18302 		TIME_NOW(&now);
   18303 		zone->refreshkeytime = now;
   18304 		zone_settimer(zone, &now);
   18305 
   18306 		UNLOCK_ZONE(zone);
   18307 	}
   18308 }
   18309 
   18310 isc_result_t
   18311 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
   18312 		 unsigned int *errors)
   18313 {
   18314 	isc_result_t result;
   18315 	dns_dbnode_t *node = NULL;
   18316 
   18317 	REQUIRE(DNS_ZONE_VALID(zone));
   18318 	REQUIRE(errors != NULL);
   18319 
   18320 	result = dns_db_getoriginnode(db, &node);
   18321 	if (result != ISC_R_SUCCESS)
   18322 		return (result);
   18323 	result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
   18324 				  ISC_FALSE);
   18325 	dns_db_detachnode(db, &node);
   18326 	return (result);
   18327 }
   18328 
   18329 isc_result_t
   18330 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
   18331 	isc_result_t result;
   18332 	dns_dbnode_t *node = NULL;
   18333 	dns_rdataset_t dnskey, cds, cdnskey;
   18334 	unsigned char buffer[DNS_DS_BUFFERSIZE];
   18335 	unsigned char algorithms[256];
   18336 	unsigned int i;
   18337 
   18338 	REQUIRE(DNS_ZONE_VALID(zone));
   18339 
   18340 	result = dns_db_getoriginnode(db, &node);
   18341 	if (result != ISC_R_SUCCESS)
   18342 		return (result);
   18343 
   18344 	dns_rdataset_init(&cds);
   18345 	dns_rdataset_init(&dnskey);
   18346 	dns_rdataset_init(&cdnskey);
   18347 
   18348 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
   18349 				     dns_rdatatype_none, 0, &cds, NULL);
   18350 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
   18351 		goto failure;
   18352 
   18353 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
   18354 				     dns_rdatatype_none, 0, &cdnskey, NULL);
   18355 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
   18356 		goto failure;
   18357 
   18358 	if (!dns_rdataset_isassociated(&cds) &&
   18359 	    !dns_rdataset_isassociated(&cdnskey)) {
   18360 		result = ISC_R_SUCCESS;
   18361 		goto failure;
   18362 	}
   18363 
   18364 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
   18365 				     dns_rdatatype_none, 0, &dnskey, NULL);
   18366 	if (result == ISC_R_NOTFOUND) {
   18367 		if (dns_rdataset_isassociated(&cds))
   18368 			result = DNS_R_BADCDS;
   18369 		else
   18370 			result = DNS_R_BADCDNSKEY;
   18371 		goto failure;
   18372 	}
   18373 	if (result != ISC_R_SUCCESS)
   18374 		goto failure;
   18375 
   18376 	/*
   18377 	 * For each DNSSEC algorithm in the CDS RRset there must be
   18378 	 * a matching DNSKEY record.
   18379 	 */
   18380 	if (dns_rdataset_isassociated(&cds)) {
   18381 		memset(algorithms, 0, sizeof(algorithms));
   18382 		for (result = dns_rdataset_first(&cds);
   18383 		     result == ISC_R_SUCCESS;
   18384 		     result = dns_rdataset_next(&cds)) {
   18385 			dns_rdata_t crdata = DNS_RDATA_INIT;
   18386 			dns_rdata_cds_t structcds;
   18387 
   18388 			dns_rdataset_current(&cds, &crdata);
   18389 			CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
   18390 			if (algorithms[structcds.algorithm] == 0)
   18391 				algorithms[structcds.algorithm] = 1;
   18392 			for (result = dns_rdataset_first(&dnskey);
   18393 			     result == ISC_R_SUCCESS;
   18394 			     result = dns_rdataset_next(&dnskey)) {
   18395 				dns_rdata_t rdata = DNS_RDATA_INIT;
   18396 				dns_rdata_t dsrdata = DNS_RDATA_INIT;
   18397 
   18398 				dns_rdataset_current(&dnskey, &rdata);
   18399 				CHECK(dns_ds_buildrdata(&zone->origin, &rdata,
   18400 							structcds.digest_type,
   18401 							buffer, &dsrdata));
   18402 				if (crdata.length == dsrdata.length &&
   18403 				    memcmp(crdata.data, dsrdata.data,
   18404 					   dsrdata.length) == 0) {
   18405 					algorithms[structcds.algorithm] = 2;
   18406 				}
   18407 			}
   18408 			if (result != ISC_R_NOMORE)
   18409 				goto failure;
   18410 		}
   18411 		for (i = 0; i < sizeof(algorithms); i++) {
   18412 			if (algorithms[i] == 1) {
   18413 				result = DNS_R_BADCDNSKEY;
   18414 				goto failure;
   18415 			}
   18416 		}
   18417 	}
   18418 
   18419 	/*
   18420 	 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
   18421 	 * a matching DNSKEY record.
   18422 	 */
   18423 	if (dns_rdataset_isassociated(&cdnskey)) {
   18424 		memset(algorithms, 0, sizeof(algorithms));
   18425 		for (result = dns_rdataset_first(&cdnskey);
   18426 		     result == ISC_R_SUCCESS;
   18427 		     result = dns_rdataset_next(&cdnskey)) {
   18428 			dns_rdata_t crdata = DNS_RDATA_INIT;
   18429 			dns_rdata_cdnskey_t structcdnskey;
   18430 
   18431 			dns_rdataset_current(&cdnskey, &crdata);
   18432 			CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
   18433 						 NULL));
   18434 			if (algorithms[structcdnskey.algorithm] == 0)
   18435 				algorithms[structcdnskey.algorithm] = 1;
   18436 			for (result = dns_rdataset_first(&dnskey);
   18437 			     result == ISC_R_SUCCESS;
   18438 			     result = dns_rdataset_next(&dnskey)) {
   18439 				dns_rdata_t rdata = DNS_RDATA_INIT;
   18440 
   18441 				dns_rdataset_current(&dnskey, &rdata);
   18442 				if (crdata.length == rdata.length &&
   18443 				    memcmp(crdata.data, rdata.data,
   18444 					   rdata.length) == 0) {
   18445 					algorithms[structcdnskey.algorithm] = 2;
   18446 				}
   18447 			}
   18448 			if (result != ISC_R_NOMORE)
   18449 				goto failure;
   18450 		}
   18451 		for (i = 0; i < sizeof(algorithms); i++) {
   18452 			if (algorithms[i] == 1) {
   18453 				result = DNS_R_BADCDS;
   18454 				goto failure;
   18455 			}
   18456 		}
   18457 	}
   18458 	result = ISC_R_SUCCESS;
   18459 
   18460  failure:
   18461 	if (dns_rdataset_isassociated(&cds))
   18462 		dns_rdataset_disassociate(&cds);
   18463 	if (dns_rdataset_isassociated(&dnskey))
   18464 		dns_rdataset_disassociate(&dnskey);
   18465 	if (dns_rdataset_isassociated(&cdnskey))
   18466 		dns_rdataset_disassociate(&cdnskey);
   18467 	dns_db_detachnode(db, &node);
   18468 	return (result);
   18469 }
   18470 
   18471 void
   18472 dns_zone_setautomatic(dns_zone_t *zone, isc_boolean_t automatic) {
   18473 	REQUIRE(DNS_ZONE_VALID(zone));
   18474 
   18475 	LOCK_ZONE(zone);
   18476 	zone->automatic = automatic;
   18477 	UNLOCK_ZONE(zone);
   18478 }
   18479 
   18480 isc_boolean_t
   18481 dns_zone_getautomatic(dns_zone_t *zone) {
   18482 	REQUIRE(DNS_ZONE_VALID(zone));
   18483 	return (zone->automatic);
   18484 }
   18485 
   18486 void
   18487 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
   18488 	REQUIRE(DNS_ZONE_VALID(zone));
   18489 
   18490 	LOCK_ZONE(zone);
   18491 	zone->added = added;
   18492 	UNLOCK_ZONE(zone);
   18493 }
   18494 
   18495 isc_boolean_t
   18496 dns_zone_getadded(dns_zone_t *zone) {
   18497 	REQUIRE(DNS_ZONE_VALID(zone));
   18498 	return (zone->added);
   18499 }
   18500 
   18501 isc_result_t
   18502 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
   18503 {
   18504 	isc_time_t loadtime;
   18505 	isc_result_t result;
   18506 	dns_zone_t *secure = NULL;
   18507 
   18508 	TIME_NOW(&loadtime);
   18509 
   18510 	/*
   18511 	 * Lock hierarchy: zmgr, zone, raw.
   18512 	 */
   18513  again:
   18514 	LOCK_ZONE(zone);
   18515 	INSIST(zone != zone->raw);
   18516 	if (inline_secure(zone))
   18517 		LOCK_ZONE(zone->raw);
   18518 	else if (inline_raw(zone)) {
   18519 		secure = zone->secure;
   18520 		TRYLOCK_ZONE(result, secure);
   18521 		if (result != ISC_R_SUCCESS) {
   18522 			UNLOCK_ZONE(zone);
   18523 			secure = NULL;
   18524 #if ISC_PLATFORM_USETHREADS
   18525 			isc_thread_yield();
   18526 #endif
   18527 			goto again;
   18528 		}
   18529 	}
   18530 	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
   18531 	if (inline_secure(zone))
   18532 		UNLOCK_ZONE(zone->raw);
   18533 	else if (secure != NULL)
   18534 		UNLOCK_ZONE(secure);
   18535 	UNLOCK_ZONE(zone);
   18536 	return result;
   18537 }
   18538 
   18539 isc_result_t
   18540 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) {
   18541 	REQUIRE(DNS_ZONE_VALID(zone));
   18542 	if (interval == 0)
   18543 		return (ISC_R_RANGE);
   18544 	/* Maximum value: 24 hours (3600 minutes) */
   18545 	if (interval > (24 * 60))
   18546 		interval = (24 * 60);
   18547 	/* Multiply by 60 for seconds */
   18548 	zone->refreshkeyinterval = interval * 60;
   18549 	return (ISC_R_SUCCESS);
   18550 }
   18551 
   18552 void
   18553 dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t flag) {
   18554 	REQUIRE(DNS_ZONE_VALID(zone));
   18555 	zone->requestixfr = flag;
   18556 }
   18557 
   18558 isc_boolean_t
   18559 dns_zone_getrequestixfr(dns_zone_t *zone) {
   18560 	REQUIRE(DNS_ZONE_VALID(zone));
   18561 	return (zone->requestixfr);
   18562 }
   18563 
   18564 void
   18565 dns_zone_setrequestexpire(dns_zone_t *zone, isc_boolean_t flag) {
   18566 	REQUIRE(DNS_ZONE_VALID(zone));
   18567 	zone->requestexpire = flag;
   18568 }
   18569 
   18570 isc_boolean_t
   18571 dns_zone_getrequestexpire(dns_zone_t *zone) {
   18572 	REQUIRE(DNS_ZONE_VALID(zone));
   18573 	return (zone->requestexpire);
   18574 }
   18575 
   18576 void
   18577 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
   18578 	REQUIRE(DNS_ZONE_VALID(zone));
   18579 	zone->updatemethod = method;
   18580 }
   18581 
   18582 dns_updatemethod_t
   18583 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
   18584 	REQUIRE(DNS_ZONE_VALID(zone));
   18585 	return(zone->updatemethod);
   18586 }
   18587 
   18588 /*
   18589  * Lock hierarchy: zmgr, zone, raw.
   18590  */
   18591 isc_result_t
   18592 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
   18593 	isc_result_t result;
   18594 	dns_zonemgr_t *zmgr;
   18595 
   18596 	REQUIRE(DNS_ZONE_VALID(zone));
   18597 	REQUIRE(zone->zmgr != NULL);
   18598 	REQUIRE(zone->task != NULL);
   18599 	REQUIRE(zone->loadtask != NULL);
   18600 	REQUIRE(zone->raw == NULL);
   18601 
   18602 	REQUIRE(DNS_ZONE_VALID(raw));
   18603 	REQUIRE(raw->zmgr == NULL);
   18604 	REQUIRE(raw->task == NULL);
   18605 	REQUIRE(raw->loadtask == NULL);
   18606 	REQUIRE(raw->secure == NULL);
   18607 
   18608 	REQUIRE(zone != raw);
   18609 
   18610 	/*
   18611 	 * Lock hierarchy: zmgr, zone, raw.
   18612 	 */
   18613 	zmgr = zone->zmgr;
   18614 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   18615 	LOCK_ZONE(zone);
   18616 	LOCK_ZONE(raw);
   18617 
   18618 	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
   18619 				  NULL, NULL, zone->task, zone_timer, raw,
   18620 				  &raw->timer);
   18621 	if (result != ISC_R_SUCCESS)
   18622 		goto unlock;
   18623 
   18624 	/*
   18625 	 * The timer "holds" a iref.
   18626 	 */
   18627 	raw->irefs++;
   18628 	INSIST(raw->irefs != 0);
   18629 
   18630 
   18631 	/* dns_zone_attach(raw, &zone->raw); */
   18632 	isc_refcount_increment(&raw->erefs, NULL);
   18633 	zone->raw = raw;
   18634 
   18635 	/* dns_zone_iattach(zone,  &raw->secure); */
   18636 	zone_iattach(zone, &raw->secure);
   18637 
   18638 	isc_task_attach(zone->task, &raw->task);
   18639 	isc_task_attach(zone->loadtask, &raw->loadtask);
   18640 
   18641 	ISC_LIST_APPEND(zmgr->zones, raw, link);
   18642 	raw->zmgr = zmgr;
   18643 	zmgr->refs++;
   18644 
   18645  unlock:
   18646 	UNLOCK_ZONE(raw);
   18647 	UNLOCK_ZONE(zone);
   18648 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
   18649 	return (result);
   18650 }
   18651 
   18652 void
   18653 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
   18654 	REQUIRE(DNS_ZONE_VALID(zone));
   18655 	REQUIRE(raw != NULL && *raw == NULL);
   18656 
   18657 	LOCK(&zone->lock);
   18658 	INSIST(zone != zone->raw);
   18659 	if (zone->raw != NULL)
   18660 		dns_zone_attach(zone->raw, raw);
   18661 	UNLOCK(&zone->lock);
   18662 }
   18663 
   18664 struct keydone {
   18665 	isc_event_t event;
   18666 	isc_boolean_t all;
   18667 	unsigned char data[5];
   18668 };
   18669 
   18670 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
   18671 
   18672 static void
   18673 keydone(isc_task_t *task, isc_event_t *event) {
   18674 	const char *me = "keydone";
   18675 	isc_boolean_t commit = ISC_FALSE;
   18676 	isc_result_t result;
   18677 	dns_rdata_t rdata = DNS_RDATA_INIT;
   18678 	dns_dbversion_t *oldver = NULL, *newver = NULL;
   18679 	dns_zone_t *zone;
   18680 	dns_db_t *db = NULL;
   18681 	dns_dbnode_t *node = NULL;
   18682 	dns_rdataset_t rdataset;
   18683 	dns_diff_t diff;
   18684 	struct keydone *kd = (struct keydone *)event;
   18685 	dns_update_log_t log = { update_log_cb, NULL };
   18686 	isc_boolean_t clear_pending = ISC_FALSE;
   18687 
   18688 	UNUSED(task);
   18689 
   18690 	zone = event->ev_arg;
   18691 	INSIST(DNS_ZONE_VALID(zone));
   18692 
   18693 	ENTER;
   18694 
   18695 	dns_rdataset_init(&rdataset);
   18696 	dns_diff_init(zone->mctx, &diff);
   18697 
   18698 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   18699 	if (zone->db != NULL)
   18700 		dns_db_attach(zone->db, &db);
   18701 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   18702 	if (db == NULL)
   18703 		goto failure;
   18704 
   18705 	dns_db_currentversion(db, &oldver);
   18706 	result = dns_db_newversion(db, &newver);
   18707 	if (result != ISC_R_SUCCESS) {
   18708 		dns_zone_log(zone, ISC_LOG_ERROR,
   18709 			     "keydone:dns_db_newversion -> %s",
   18710 			     dns_result_totext(result));
   18711 		goto failure;
   18712 	}
   18713 
   18714 	result = dns_db_getoriginnode(db, &node);
   18715 	if (result != ISC_R_SUCCESS)
   18716 		goto failure;
   18717 
   18718 	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
   18719 				     dns_rdatatype_none, 0, &rdataset, NULL);
   18720 	if (result == ISC_R_NOTFOUND) {
   18721 		INSIST(!dns_rdataset_isassociated(&rdataset));
   18722 		goto failure;
   18723 	}
   18724 	if (result != ISC_R_SUCCESS) {
   18725 		INSIST(!dns_rdataset_isassociated(&rdataset));
   18726 		goto failure;
   18727 	}
   18728 
   18729 	for (result = dns_rdataset_first(&rdataset);
   18730 	     result == ISC_R_SUCCESS;
   18731 	     result = dns_rdataset_next(&rdataset)) {
   18732 		isc_boolean_t found = ISC_FALSE;
   18733 
   18734 		dns_rdataset_current(&rdataset, &rdata);
   18735 
   18736 		if (kd->all) {
   18737 			if (rdata.length == 5 && rdata.data[0] != 0 &&
   18738 			       rdata.data[3] == 0 && rdata.data[4] == 1)
   18739 				found = ISC_TRUE;
   18740 			else if (rdata.data[0] == 0 &&
   18741 				 (rdata.data[2] & PENDINGFLAGS) != 0) {
   18742 				found = ISC_TRUE;
   18743 				clear_pending = ISC_TRUE;
   18744 			}
   18745 		} else if (rdata.length == 5 &&
   18746 			   memcmp(rdata.data, kd->data, 5) == 0)
   18747 			found = ISC_TRUE;
   18748 
   18749 		if (found)
   18750 			CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
   18751 					    &zone->origin, rdataset.ttl,
   18752 					    &rdata));
   18753 		dns_rdata_reset(&rdata);
   18754 	}
   18755 
   18756 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   18757 		/* Write changes to journal file. */
   18758 		CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
   18759 					zone->updatemethod));
   18760 
   18761 		result = dns_update_signatures(&log, zone, db,
   18762 					       oldver, newver, &diff,
   18763 					       zone->sigvalidityinterval);
   18764 		if (!clear_pending)
   18765 			CHECK(result);
   18766 
   18767 		CHECK(zone_journal(zone, &diff, NULL, "keydone"));
   18768 		commit = ISC_TRUE;
   18769 
   18770 		LOCK_ZONE(zone);
   18771 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   18772 		zone_needdump(zone, 30);
   18773 		UNLOCK_ZONE(zone);
   18774 	}
   18775 
   18776  failure:
   18777 	if (dns_rdataset_isassociated(&rdataset))
   18778 		dns_rdataset_disassociate(&rdataset);
   18779 	if (db != NULL) {
   18780 		if (node != NULL)
   18781 			dns_db_detachnode(db, &node);
   18782 		if (oldver != NULL)
   18783 			dns_db_closeversion(db, &oldver, ISC_FALSE);
   18784 		if (newver != NULL)
   18785 			dns_db_closeversion(db, &newver, commit);
   18786 		dns_db_detach(&db);
   18787 	}
   18788 	dns_diff_clear(&diff);
   18789 	isc_event_free(&event);
   18790 	dns_zone_idetach(&zone);
   18791 
   18792 	INSIST(oldver == NULL);
   18793 	INSIST(newver == NULL);
   18794 }
   18795 
   18796 isc_result_t
   18797 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
   18798 	isc_result_t result = ISC_R_SUCCESS;
   18799 	isc_event_t *e;
   18800 	isc_buffer_t b;
   18801 	dns_zone_t *dummy = NULL;
   18802 	struct keydone *kd;
   18803 
   18804 	REQUIRE(DNS_ZONE_VALID(zone));
   18805 
   18806 	LOCK_ZONE(zone);
   18807 
   18808 	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
   18809 			       zone, sizeof(struct keydone));
   18810 	if (e == NULL) {
   18811 		result = ISC_R_NOMEMORY;
   18812 		goto failure;
   18813 	}
   18814 
   18815 	kd = (struct keydone *) e;
   18816 	if (strcasecmp(keystr, "all") == 0)
   18817 		kd->all = ISC_TRUE;
   18818 	else {
   18819 		isc_textregion_t r;
   18820 		const char *algstr;
   18821 		dns_keytag_t keyid;
   18822 		dns_secalg_t alg;
   18823 		size_t n;
   18824 
   18825 		kd->all = ISC_FALSE;
   18826 
   18827 		n = sscanf(keystr, "%hu/", &keyid);
   18828 		if (n == 0U)
   18829 			CHECK(ISC_R_FAILURE);
   18830 
   18831 		algstr = strchr(keystr, '/');
   18832 		if (algstr != NULL)
   18833 			algstr++;
   18834 		else
   18835 			CHECK(ISC_R_FAILURE);
   18836 
   18837 		n = sscanf(algstr, "%hhu", &alg);
   18838 		if (n == 0U) {
   18839 			DE_CONST(algstr, r.base);
   18840 			r.length = strlen(algstr);
   18841 			CHECK(dns_secalg_fromtext(&alg, &r));
   18842 		}
   18843 
   18844 		/* construct a private-type rdata */
   18845 		isc_buffer_init(&b, kd->data, sizeof(kd->data));
   18846 		isc_buffer_putuint8(&b, alg);
   18847 		isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
   18848 		isc_buffer_putuint8(&b, (keyid & 0xff));
   18849 		isc_buffer_putuint8(&b, 0);
   18850 		isc_buffer_putuint8(&b, 1);
   18851 	}
   18852 
   18853 	zone_iattach(zone, &dummy);
   18854 	isc_task_send(zone->task, &e);
   18855 
   18856  failure:
   18857 	if (e != NULL)
   18858 		isc_event_free(&e);
   18859 	UNLOCK_ZONE(zone);
   18860 	return (result);
   18861 }
   18862 
   18863 /*
   18864  * Called from the zone task's queue after the relevant event is posted by
   18865  * dns_zone_setnsec3param().
   18866  *
   18867  * Check whether NSEC3 chain addition or removal specified by the private-type
   18868  * record passed with the event was already queued (or even fully performed).
   18869  * If not, modify the relevant private-type records at the zone apex and call
   18870  * resume_addnsec3chain().
   18871  */
   18872 static void
   18873 setnsec3param(isc_task_t *task, isc_event_t *event) {
   18874 	const char *me = "setnsec3param";
   18875 	isc_boolean_t commit = ISC_FALSE;
   18876 	isc_result_t result;
   18877 	dns_dbversion_t *oldver = NULL, *newver = NULL;
   18878 	dns_zone_t *zone;
   18879 	dns_db_t *db = NULL;
   18880 	dns_dbnode_t *node = NULL;
   18881 	dns_rdataset_t prdataset, nrdataset;
   18882 	dns_diff_t diff;
   18883 	struct np3event *npe = (struct np3event *)event;
   18884 	nsec3param_t *np;
   18885 	dns_update_log_t log = { update_log_cb, NULL };
   18886 	dns_rdata_t rdata;
   18887 	isc_boolean_t nseconly;
   18888 	isc_boolean_t exists = ISC_FALSE;
   18889 
   18890 	UNUSED(task);
   18891 
   18892 	zone = event->ev_arg;
   18893 	INSIST(DNS_ZONE_VALID(zone));
   18894 
   18895 	ENTER;
   18896 
   18897 	np = &npe->params;
   18898 
   18899 	dns_rdataset_init(&prdataset);
   18900 	dns_rdataset_init(&nrdataset);
   18901 	dns_diff_init(zone->mctx, &diff);
   18902 
   18903 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   18904 	if (zone->db != NULL)
   18905 		dns_db_attach(zone->db, &db);
   18906 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   18907 	if (db == NULL)
   18908 		goto failure;
   18909 
   18910 	dns_db_currentversion(db, &oldver);
   18911 	result = dns_db_newversion(db, &newver);
   18912 	if (result != ISC_R_SUCCESS) {
   18913 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   18914 		dns_zone_log(zone, ISC_LOG_ERROR,
   18915 			     "setnsec3param:dns_db_newversion -> %s",
   18916 			     dns_result_totext(result));
   18917 		goto failure;
   18918 	}
   18919 
   18920 	CHECK(dns_db_getoriginnode(db, &node));
   18921 
   18922 	/*
   18923 	 * Does a private-type record already exist for this chain?
   18924 	 */
   18925 	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
   18926 				     dns_rdatatype_none, 0, &prdataset, NULL);
   18927 	if (result == ISC_R_SUCCESS) {
   18928 		for (result = dns_rdataset_first(&prdataset);
   18929 		     result == ISC_R_SUCCESS;
   18930 		     result = dns_rdataset_next(&prdataset)) {
   18931 			dns_rdata_init(&rdata);
   18932 			dns_rdataset_current(&prdataset, &rdata);
   18933 
   18934 			if (np->length == rdata.length &&
   18935 			    memcmp(rdata.data, np->data, np->length) == 0) {
   18936 				exists = ISC_TRUE;
   18937 				break;
   18938 			}
   18939 		}
   18940 	} else if (result != ISC_R_NOTFOUND) {
   18941 		INSIST(!dns_rdataset_isassociated(&prdataset));
   18942 		goto failure;
   18943 	}
   18944 
   18945 	/*
   18946 	 * Does the chain already exist?
   18947 	 */
   18948 	result = dns_db_findrdataset(db, node, newver,
   18949 				     dns_rdatatype_nsec3param,
   18950 				     dns_rdatatype_none, 0, &nrdataset, NULL);
   18951 	if (result == ISC_R_SUCCESS) {
   18952 		for (result = dns_rdataset_first(&nrdataset);
   18953 		     result == ISC_R_SUCCESS;
   18954 		     result = dns_rdataset_next(&nrdataset)) {
   18955 			dns_rdata_init(&rdata);
   18956 			dns_rdataset_current(&nrdataset, &rdata);
   18957 
   18958 			if (np->length == (rdata.length + 1) &&
   18959 			    memcmp(rdata.data, np->data + 1,
   18960 				   np->length - 1) == 0)
   18961 			{
   18962 				exists = ISC_TRUE;
   18963 				break;
   18964 			}
   18965 		}
   18966 	} else if (result != ISC_R_NOTFOUND) {
   18967 		INSIST(!dns_rdataset_isassociated(&nrdataset));
   18968 		goto failure;
   18969 	}
   18970 
   18971 
   18972 	/*
   18973 	 * We need to remove any existing NSEC3 chains if the supplied NSEC3
   18974 	 * parameters are supposed to replace the current ones or if we are
   18975 	 * switching to NSEC.
   18976 	 */
   18977 	if (!exists && np->replace && (np->length != 0 || np->nsec))
   18978 		CHECK(dns_nsec3param_deletechains(db, newver, zone,
   18979 						  !np->nsec, &diff));
   18980 
   18981 	if (!exists && np->length != 0) {
   18982 		/*
   18983 		 * We're creating an NSEC3 chain.  Add the private-type record
   18984 		 * passed in the event handler's argument to the zone apex.
   18985 		 *
   18986 		 * If the zone is not currently capable of supporting an NSEC3
   18987 		 * chain (due to the DNSKEY RRset at the zone apex not existing
   18988 		 * or containing at least one key using an NSEC-only
   18989 		 * algorithm), add the INITIAL flag, so these parameters can be
   18990 		 * used later when NSEC3 becomes available.
   18991 		 */
   18992 		dns_rdata_init(&rdata);
   18993 
   18994 		np->data[2] |= DNS_NSEC3FLAG_CREATE;
   18995 		result = dns_nsec_nseconly(db, newver, &nseconly);
   18996 		if (result == ISC_R_NOTFOUND || nseconly)
   18997 			np->data[2] |= DNS_NSEC3FLAG_INITIAL;
   18998 
   18999 		rdata.length = np->length;
   19000 		rdata.data = np->data;
   19001 		rdata.type = zone->privatetype;
   19002 		rdata.rdclass = zone->rdclass;
   19003 		CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
   19004 				    &zone->origin, 0, &rdata));
   19005 	}
   19006 
   19007 	/*
   19008 	 * If we changed anything in the zone, write changes to journal file
   19009 	 * and set commit to ISC_TRUE so that resume_addnsec3chain() will be
   19010 	 * called below in order to kick off adding/removing relevant NSEC3
   19011 	 * records.
   19012 	 */
   19013 	if (!ISC_LIST_EMPTY(diff.tuples)) {
   19014 		CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
   19015 					zone->updatemethod));
   19016 		result = dns_update_signatures(&log, zone, db,
   19017 					       oldver, newver, &diff,
   19018 					       zone->sigvalidityinterval);
   19019 		if (result != ISC_R_NOTFOUND)
   19020 			CHECK(result);
   19021 		CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
   19022 		commit = ISC_TRUE;
   19023 
   19024 		LOCK_ZONE(zone);
   19025 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
   19026 		zone_needdump(zone, 30);
   19027 		UNLOCK_ZONE(zone);
   19028 	}
   19029 
   19030  failure:
   19031 	if (dns_rdataset_isassociated(&prdataset))
   19032 		dns_rdataset_disassociate(&prdataset);
   19033 	if (dns_rdataset_isassociated(&nrdataset))
   19034 		dns_rdataset_disassociate(&nrdataset);
   19035 	if (node != NULL)
   19036 		dns_db_detachnode(db, &node);
   19037 	if (oldver != NULL)
   19038 		dns_db_closeversion(db, &oldver, ISC_FALSE);
   19039 	if (newver != NULL)
   19040 		dns_db_closeversion(db, &newver, commit);
   19041 	if (db != NULL)
   19042 		dns_db_detach(&db);
   19043 	if (commit) {
   19044 		LOCK_ZONE(zone);
   19045 		resume_addnsec3chain(zone);
   19046 		UNLOCK_ZONE(zone);
   19047 	}
   19048 	dns_diff_clear(&diff);
   19049 	isc_event_free(&event);
   19050 	dns_zone_idetach(&zone);
   19051 
   19052 	INSIST(oldver == NULL);
   19053 	INSIST(newver == NULL);
   19054 }
   19055 
   19056 /*
   19057  * Called when an "rndc signing -nsec3param ..." command is received.
   19058  *
   19059  * Allocate and prepare an nsec3param_t structure which holds information about
   19060  * the NSEC3 changes requested for the zone:
   19061  *
   19062  *   - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
   19063  *     field of the structure to ISC_TRUE and the "replace" field to the value
   19064  *     of the "replace" argument, leaving other fields initialized to zeros, to
   19065  *     signal that the zone should be signed using NSEC instead of NSEC3,
   19066  *
   19067  *   - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
   19068  *     the zone apex, convert it to a private-type record and store the latter
   19069  *     in the "data" field of the nsec3param_t structure.
   19070  *
   19071  * Once the nsec3param_t structure is prepared, post an event to the zone's
   19072  * task which will cause setnsec3param() to be called with the prepared
   19073  * structure passed as an argument.
   19074  */
   19075 isc_result_t
   19076 dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
   19077 		       isc_uint16_t iter, isc_uint8_t saltlen,
   19078 		       unsigned char *salt, isc_boolean_t replace)
   19079 {
   19080 	isc_result_t result = ISC_R_SUCCESS;
   19081 	dns_rdata_nsec3param_t param;
   19082 	dns_rdata_t nrdata = DNS_RDATA_INIT;
   19083 	dns_rdata_t prdata = DNS_RDATA_INIT;
   19084 	unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
   19085 	struct np3event *npe;
   19086 	nsec3param_t *np;
   19087 	dns_zone_t *dummy = NULL;
   19088 	isc_buffer_t b;
   19089 	isc_event_t *e;
   19090 
   19091 	REQUIRE(DNS_ZONE_VALID(zone));
   19092 	REQUIRE(salt != NULL);
   19093 
   19094 	LOCK_ZONE(zone);
   19095 
   19096 	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
   19097 			       setnsec3param, zone, sizeof(struct np3event));
   19098 	if (e == NULL) {
   19099 		result = ISC_R_NOMEMORY;
   19100 		goto failure;
   19101 	}
   19102 
   19103 	npe = (struct np3event *) e;
   19104 	np = &npe->params;
   19105 
   19106 	np->replace = replace;
   19107 	if (hash == 0) {
   19108 		np->length = 0;
   19109 		np->nsec = ISC_TRUE;
   19110 	} else {
   19111 		param.common.rdclass = zone->rdclass;
   19112 		param.common.rdtype = dns_rdatatype_nsec3param;
   19113 		ISC_LINK_INIT(&param.common, link);
   19114 		param.mctx = NULL;
   19115 		param.hash = hash;
   19116 		param.flags = flags;
   19117 		param.iterations = iter;
   19118 		param.salt_length = saltlen;
   19119 		param.salt = salt;
   19120 		isc_buffer_init(&b, nbuf, sizeof(nbuf));
   19121 		CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
   19122 					   dns_rdatatype_nsec3param,
   19123 					   &param, &b));
   19124 		dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
   19125 					 np->data, sizeof(np->data));
   19126 		np->length = prdata.length;
   19127 		np->nsec = ISC_FALSE;
   19128 	}
   19129 
   19130 	zone_iattach(zone, &dummy);
   19131 	isc_task_send(zone->task, &e);
   19132 
   19133  failure:
   19134 	if (e != NULL)
   19135 		isc_event_free(&e);
   19136 	UNLOCK_ZONE(zone);
   19137 	return (result);
   19138 }
   19139 
   19140 isc_result_t
   19141 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
   19142 	REQUIRE(DNS_ZONE_VALID(zone));
   19143 	REQUIRE(loadtime != NULL);
   19144 
   19145 	LOCK_ZONE(zone);
   19146 	*loadtime = zone->loadtime;
   19147 	UNLOCK_ZONE(zone);
   19148 	return (ISC_R_SUCCESS);
   19149 }
   19150 
   19151 isc_result_t
   19152 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
   19153 	REQUIRE(DNS_ZONE_VALID(zone));
   19154 	REQUIRE(expiretime != NULL);
   19155 
   19156 	LOCK_ZONE(zone);
   19157 	*expiretime = zone->expiretime;
   19158 	UNLOCK_ZONE(zone);
   19159 	return (ISC_R_SUCCESS);
   19160 }
   19161 
   19162 isc_result_t
   19163 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
   19164 	REQUIRE(DNS_ZONE_VALID(zone));
   19165 	REQUIRE(refreshtime != NULL);
   19166 
   19167 	LOCK_ZONE(zone);
   19168 	*refreshtime = zone->refreshtime;
   19169 	UNLOCK_ZONE(zone);
   19170 	return (ISC_R_SUCCESS);
   19171 }
   19172 
   19173 isc_result_t
   19174 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
   19175 	REQUIRE(DNS_ZONE_VALID(zone));
   19176 	REQUIRE(refreshkeytime != NULL);
   19177 
   19178 	LOCK_ZONE(zone);
   19179 	*refreshkeytime = zone->refreshkeytime;
   19180 	UNLOCK_ZONE(zone);
   19181 	return (ISC_R_SUCCESS);
   19182 }
   19183 
   19184 unsigned int
   19185 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
   19186 	dns_include_t *include;
   19187 	char **array = NULL;
   19188 	unsigned int n = 0;
   19189 
   19190 	REQUIRE(DNS_ZONE_VALID(zone));
   19191 	REQUIRE(includesp != NULL && *includesp == NULL);
   19192 
   19193 	LOCK_ZONE(zone);
   19194 	if (zone->nincludes == 0)
   19195 		goto done;
   19196 
   19197 	array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
   19198 	if (array == NULL)
   19199 		goto done;
   19200 	for (include = ISC_LIST_HEAD(zone->includes);
   19201 	     include != NULL;
   19202 	     include = ISC_LIST_NEXT(include, link)) {
   19203 		INSIST(n < zone->nincludes);
   19204 		array[n++] = isc_mem_strdup(zone->mctx, include->name);
   19205 	}
   19206 	INSIST(n == zone->nincludes);
   19207 	*includesp = array;
   19208 
   19209  done:
   19210 	UNLOCK_ZONE(zone);
   19211 	return (n);
   19212 }
   19213 
   19214 void
   19215 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
   19216 	REQUIRE(DNS_ZONE_VALID(zone));
   19217 
   19218 	zone->statlevel = level;
   19219 }
   19220 
   19221 dns_zonestat_level_t
   19222 dns_zone_getstatlevel(dns_zone_t *zone) {
   19223 	REQUIRE(DNS_ZONE_VALID(zone));
   19224 
   19225 	return (zone->statlevel);
   19226 }
   19227 
   19228 static void
   19229 setserial(isc_task_t *task, isc_event_t *event) {
   19230 	isc_uint32_t oldserial, desired;
   19231 	const char *me = "setserial";
   19232 	isc_boolean_t commit = ISC_FALSE;
   19233 	isc_result_t result;
   19234 	dns_dbversion_t *oldver = NULL, *newver = NULL;
   19235 	dns_zone_t *zone;
   19236 	dns_db_t *db = NULL;
   19237 	dns_diff_t diff;
   19238 	struct ssevent *sse = (struct ssevent *)event;
   19239 	dns_update_log_t log = { update_log_cb, NULL };
   19240 	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
   19241 
   19242 	UNUSED(task);
   19243 
   19244 	zone = event->ev_arg;
   19245 	INSIST(DNS_ZONE_VALID(zone));
   19246 
   19247 	ENTER;
   19248 
   19249 	if (zone->update_disabled)
   19250 		goto failure;
   19251 
   19252 	desired = sse->serial;
   19253 
   19254 	dns_diff_init(zone->mctx, &diff);
   19255 
   19256 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
   19257 	if (zone->db != NULL)
   19258 		dns_db_attach(zone->db, &db);
   19259 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
   19260 	if (db == NULL)
   19261 		goto failure;
   19262 
   19263 	dns_db_currentversion(db, &oldver);
   19264 	result = dns_db_newversion(db, &newver);
   19265 	if (result != ISC_R_SUCCESS) {
   19266 		dns_zone_log(zone, ISC_LOG_ERROR,
   19267 			     "setserial:dns_db_newversion -> %s",
   19268 			     dns_result_totext(result));
   19269 		goto failure;
   19270 	}
   19271 
   19272 	CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
   19273 				    DNS_DIFFOP_DEL, &oldtuple));
   19274 	CHECK(dns_difftuple_copy(oldtuple, &newtuple));
   19275 	newtuple->op = DNS_DIFFOP_ADD;
   19276 
   19277 	oldserial = dns_soa_getserial(&oldtuple->rdata);
   19278 	if (desired == 0U)
   19279 		desired = 1;
   19280 	if (!isc_serial_gt(desired, oldserial)) {
   19281 		if (desired != oldserial)
   19282 			dns_zone_log(zone, ISC_LOG_INFO,
   19283 				     "setserial: desired serial (%u) "
   19284 				     "out of range (%u-%u)", desired,
   19285 				     oldserial + 1, (oldserial + 0x7fffffff));
   19286 		goto failure;
   19287 	}
   19288 
   19289 	dns_soa_setserial(desired, &newtuple->rdata);
   19290 	CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
   19291 	CHECK(do_one_tuple(&newtuple, db, newver, &diff));
   19292 	result = dns_update_signatures(&log, zone, db,
   19293 				       oldver, newver, &diff,
   19294 				       zone->sigvalidityinterval);
   19295 	if (result != ISC_R_NOTFOUND)
   19296 		CHECK(result);
   19297 
   19298 	/* Write changes to journal file. */
   19299 	CHECK(zone_journal(zone, &diff, NULL, "setserial"));
   19300 	commit = ISC_TRUE;
   19301 
   19302 	LOCK_ZONE(zone);
   19303 	zone_needdump(zone, 30);
   19304 	UNLOCK_ZONE(zone);
   19305 
   19306  failure:
   19307 	if (oldtuple != NULL)
   19308 		dns_difftuple_free(&oldtuple);
   19309 	if (newtuple != NULL)
   19310 		dns_difftuple_free(&newtuple);
   19311 	if (oldver != NULL)
   19312 		dns_db_closeversion(db, &oldver, ISC_FALSE);
   19313 	if (newver != NULL)
   19314 		dns_db_closeversion(db, &newver, commit);
   19315 	if (db != NULL)
   19316 		dns_db_detach(&db);
   19317 	dns_diff_clear(&diff);
   19318 	isc_event_free(&event);
   19319 	dns_zone_idetach(&zone);
   19320 
   19321 	INSIST(oldver == NULL);
   19322 	INSIST(newver == NULL);
   19323 }
   19324 
   19325 isc_result_t
   19326 dns_zone_setserial(dns_zone_t *zone, isc_uint32_t serial) {
   19327 	isc_result_t result = ISC_R_SUCCESS;
   19328 	dns_zone_t *dummy = NULL;
   19329 	isc_event_t *e = NULL;
   19330 	struct ssevent *sse;
   19331 
   19332 	REQUIRE(DNS_ZONE_VALID(zone));
   19333 
   19334 	LOCK_ZONE(zone);
   19335 
   19336 	if (!inline_secure(zone)) {
   19337 		if (!dns_zone_isdynamic(zone, ISC_TRUE)) {
   19338 			result = DNS_R_NOTDYNAMIC;
   19339 			goto failure;
   19340 		}
   19341 	}
   19342 
   19343 	if (zone->update_disabled) {
   19344 		result = DNS_R_FROZEN;
   19345 		goto failure;
   19346 	}
   19347 
   19348 	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL,
   19349 			       setserial, zone, sizeof(struct ssevent));
   19350 	if (e == NULL) {
   19351 		result = ISC_R_NOMEMORY;
   19352 		goto failure;
   19353 	}
   19354 
   19355 	sse = (struct ssevent *)e;
   19356 	sse->serial = serial;
   19357 
   19358 	zone_iattach(zone, &dummy);
   19359 	isc_task_send(zone->task, &e);
   19360 
   19361  failure:
   19362 	if (e != NULL)
   19363 		isc_event_free(&e);
   19364 	UNLOCK_ZONE(zone);
   19365 	return (result);
   19366 }
   19367 
   19368 isc_stats_t *
   19369 dns_zone_getgluecachestats(dns_zone_t *zone) {
   19370 	REQUIRE(DNS_ZONE_VALID(zone));
   19371 
   19372 	return (zone->gluecachestats);
   19373 }
   19374